diff --git a/[refs] b/[refs] index a3037f70a4f2..1c1048a273e7 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 220b07e90e3b7b3adc60b8a72c79ad4465312072 +refs/heads/master: 8431a27ad5af8e52b4cd2d9e15c2a23670845b18 diff --git a/trunk/Documentation/cgroups/memory.txt b/trunk/Documentation/cgroups/memory.txt index 6922b6cb58e3..cc0ebc5241b3 100644 --- a/trunk/Documentation/cgroups/memory.txt +++ b/trunk/Documentation/cgroups/memory.txt @@ -44,9 +44,8 @@ Features: - oom-killer disable knob and oom-notifier - Root cgroup has no limit controls. - Hugepages is not under control yet. We just manage pages on LRU. To add more - controls, we have to take care of performance. Kernel memory support is work - in progress, and the current version provides basically functionality. + Kernel memory and Hugepages are not under control yet. We just manage + pages on LRU. To add more controls, we have to take care of performance. Brief summary of control files. @@ -57,11 +56,8 @@ Brief summary of control files. (See 5.5 for details) memory.memsw.usage_in_bytes # show current res_counter usage for memory+Swap (See 5.5 for details) - memory.kmem.usage_in_bytes # show current res_counter usage for kmem only. - (See 2.7 for details) memory.limit_in_bytes # set/show limit of memory usage memory.memsw.limit_in_bytes # set/show limit of memory+Swap usage - memory.kmem.limit_in_bytes # if allowed, set/show limit of kernel memory memory.failcnt # show the number of memory usage hits limits memory.memsw.failcnt # show the number of memory+Swap hits limits memory.max_usage_in_bytes # show max memory usage recorded @@ -76,11 +72,6 @@ Brief summary of control files. memory.oom_control # set/show oom controls. memory.numa_stat # show the number of memory usage per numa node - memory.independent_kmem_limit # select whether or not kernel memory limits are - independent of user limits - memory.kmem.tcp.limit_in_bytes # set/show hard limit for tcp buf memory - memory.kmem.tcp.usage_in_bytes # show current tcp buf memory allocation - 1. History The memory controller has a long history. A request for comments for the memory @@ -264,39 +255,6 @@ When oom event notifier is registered, event will be delivered. per-zone-per-cgroup LRU (cgroup's private LRU) is just guarded by zone->lru_lock, it has no lock of its own. -2.7 Kernel Memory Extension (CONFIG_CGROUP_MEM_RES_CTLR_KMEM) - -With the Kernel memory extension, the Memory Controller is able to limit -the amount of kernel memory used by the system. Kernel memory is fundamentally -different than user memory, since it can't be swapped out, which makes it -possible to DoS the system by consuming too much of this precious resource. - -Some kernel memory resources may be accounted and limited separately from the -main "kmem" resource. For instance, a slab cache that is considered important -enough to be limited separately may have its own knobs. - -Kernel memory limits are not imposed for the root cgroup. Usage for the root -cgroup may or may not be accounted. - -Memory limits as specified by the standard Memory Controller may or may not -take kernel memory into consideration. This is achieved through the file -memory.independent_kmem_limit. A Value different than 0 will allow for kernel -memory to be controlled separately. - -When kernel memory limits are not independent, the limit values set in -memory.kmem files are ignored. - -Currently no soft limit is implemented for kernel memory. It is future work -to trigger slab reclaim when those limits are reached. - -2.7.1 Current Kernel Memory resources accounted - -* sockets memory pressure: some sockets protocols have memory pressure -thresholds. The Memory Controller allows them to be controlled individually -per cgroup, instead of globally. - -* tcp memory pressure: sockets memory pressure for the tcp protocol. - 3. User Interface 0. Configuration diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 33f7327d0451..3d849122b5b1 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -263,7 +263,8 @@ Who: Ravikiran Thirumalai What: Code that is now under CONFIG_WIRELESS_EXT_SYSFS (in net/core/net-sysfs.c) -When: 3.5 +When: After the only user (hal) has seen a release with the patches + for enough time, probably some time in 2010. Why: Over 1K .text/.data size reduction, data is available in other ways (ioctls) Who: Johannes Berg diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 5e22c3f1f8bd..a0c5c5f4fce6 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -315,8 +315,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. CPU-intensive style benchmark, and it can vary highly in a microbenchmark depending on workload and compiler. - 32: only for 32-bit processes - 64: only for 64-bit processes + 1: only for 32-bit processes + 2: only for 64-bit processes on: enable for both 32- and 64-bit processes off: disable for both 32- and 64-bit processes diff --git a/trunk/Documentation/networking/batman-adv.txt b/trunk/Documentation/networking/batman-adv.txt index 221ad0cdf11f..c86d03f18a5b 100644 --- a/trunk/Documentation/networking/batman-adv.txt +++ b/trunk/Documentation/networking/batman-adv.txt @@ -200,16 +200,15 @@ abled during run time. Following log_levels are defined: 0 - All debug output disabled 1 - Enable messages related to routing / flooding / broadcasting -2 - Enable messages related to route added / changed / deleted -4 - Enable messages related to translation table operations -7 - Enable all messages +2 - Enable route or tt entry added / changed / deleted +3 - Enable all messages The debug output can be changed at runtime using the file /sys/class/net/bat0/mesh/log_level. e.g. # echo 2 > /sys/class/net/bat0/mesh/log_level -will enable debug messages for when routes change. +will enable debug messages for when routes or TTs change. BATCTL diff --git a/trunk/Documentation/networking/ip-sysctl.txt b/trunk/Documentation/networking/ip-sysctl.txt index ad3e80e17b4f..cb2b1c6a2ce1 100644 --- a/trunk/Documentation/networking/ip-sysctl.txt +++ b/trunk/Documentation/networking/ip-sysctl.txt @@ -295,11 +295,11 @@ tcp_max_ssthresh - INTEGER Default: 0 (off) tcp_max_syn_backlog - INTEGER - Maximal number of remembered connection requests, which have not - received an acknowledgment from connecting client. - The minimal value is 128 for low memory machines, and it will - increase in proportion to the memory of machine. - If server suffers from overload, try increasing this number. + Maximal number of remembered connection requests, which are + still did not receive an acknowledgment from connecting client. + Default value is 1024 for systems with more than 128Mb of memory, + and 128 for low memory machines. If server suffers of overload, + try to increase this number. tcp_max_tw_buckets - INTEGER Maximal number of timewait sockets held by system simultaneously. diff --git a/trunk/Documentation/usb/linux-cdc-acm.inf b/trunk/Documentation/usb/linux-cdc-acm.inf index f0ffc27d4c0a..37a02ce54841 100644 --- a/trunk/Documentation/usb/linux-cdc-acm.inf +++ b/trunk/Documentation/usb/linux-cdc-acm.inf @@ -90,10 +90,10 @@ ServiceBinary=%12%\USBSER.sys [SourceDisksFiles] [SourceDisksNames] [DeviceList] -%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00 +%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02 [DeviceList.NTamd64] -%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02, USB\VID_1D6B&PID_0106&MI_00 +%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02 ;------------------------------------------------------------------------------ diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 209ad0695ba2..860a4ce18045 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -5910,7 +5910,6 @@ F: drivers/net/ethernet/emulex/benet/ SFC NETWORK DRIVER M: Solarflare linux maintainers -M: Steve Hodgson M: Ben Hutchings L: netdev@vger.kernel.org S: Supported diff --git a/trunk/arch/arm/kernel/perf_event.c b/trunk/arch/arm/kernel/perf_event.c index 8e9c98edc068..c475379199b1 100644 --- a/trunk/arch/arm/kernel/perf_event.c +++ b/trunk/arch/arm/kernel/perf_event.c @@ -353,15 +353,15 @@ validate_group(struct perf_event *event) fake_pmu.used_mask = fake_used_mask; if (!validate_event(&fake_pmu, leader)) - return -EINVAL; + return -ENOSPC; list_for_each_entry(sibling, &leader->sibling_list, group_entry) { if (!validate_event(&fake_pmu, sibling)) - return -EINVAL; + return -ENOSPC; } if (!validate_event(&fake_pmu, event)) - return -EINVAL; + return -ENOSPC; return 0; } diff --git a/trunk/arch/mips/kernel/perf_event_mipsxx.c b/trunk/arch/mips/kernel/perf_event_mipsxx.c index 315fc0b250f8..4f2971bcf8e5 100644 --- a/trunk/arch/mips/kernel/perf_event_mipsxx.c +++ b/trunk/arch/mips/kernel/perf_event_mipsxx.c @@ -623,7 +623,7 @@ static int mipspmu_event_init(struct perf_event *event) if (!atomic_inc_not_zero(&active_events)) { if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) { atomic_dec(&active_events); - return -EINVAL; + return -ENOSPC; } mutex_lock(&pmu_reserve_mutex); @@ -732,15 +732,15 @@ static int validate_group(struct perf_event *event) memset(&fake_cpuc, 0, sizeof(fake_cpuc)); if (!validate_event(&fake_cpuc, leader)) - return -EINVAL; + return -ENOSPC; list_for_each_entry(sibling, &leader->sibling_list, group_entry) { if (!validate_event(&fake_cpuc, sibling)) - return -EINVAL; + return -ENOSPC; } if (!validate_event(&fake_cpuc, event)) - return -EINVAL; + return -ENOSPC; return 0; } diff --git a/trunk/arch/s390/include/asm/pgtable.h b/trunk/arch/s390/include/asm/pgtable.h index 4f289ff0b7fe..524d23b8610c 100644 --- a/trunk/arch/s390/include/asm/pgtable.h +++ b/trunk/arch/s390/include/asm/pgtable.h @@ -599,10 +599,10 @@ static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste) skey = page_get_storage_key(address); bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED); /* Clear page changed & referenced bit in the storage key */ - if (bits & _PAGE_CHANGED) - page_set_storage_key(address, skey ^ bits, 1); - else if (bits) - page_reset_referenced(address); + if (bits) { + skey ^= bits; + page_set_storage_key(address, skey, 1); + } /* Transfer page changed & referenced bit to guest bits in pgste */ pgste_val(pgste) |= bits << 48; /* RCP_GR_BIT & RCP_GC_BIT */ /* Get host changed & referenced bits from pgste */ diff --git a/trunk/arch/s390/kernel/ptrace.c b/trunk/arch/s390/kernel/ptrace.c index 573bc29551ef..450931a45b68 100644 --- a/trunk/arch/s390/kernel/ptrace.c +++ b/trunk/arch/s390/kernel/ptrace.c @@ -296,6 +296,13 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) ((data & PSW_MASK_EA) && !(data & PSW_MASK_BA)))) /* Invalid psw mask. */ return -EINVAL; + if (addr == (addr_t) &dummy->regs.psw.addr) + /* + * The debugger changed the instruction address, + * reset system call restart, see signal.c:do_signal + */ + task_thread_info(child)->system_call = 0; + *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data; } else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) { @@ -607,6 +614,11 @@ static int __poke_user_compat(struct task_struct *child, /* Transfer 31 bit amode bit to psw mask. */ regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) | (__u64)(tmp & PSW32_ADDR_AMODE); + /* + * The debugger changed the instruction address, + * reset system call restart, see signal.c:do_signal + */ + task_thread_info(child)->system_call = 0; } else { /* gpr 0-15 */ *(__u32*)((addr_t) ®s->psw + addr*2 + 4) = tmp; @@ -893,14 +905,6 @@ static int s390_last_break_get(struct task_struct *target, return 0; } -static int s390_last_break_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - return 0; -} - #endif static int s390_system_call_get(struct task_struct *target, @@ -947,7 +951,6 @@ static const struct user_regset s390_regsets[] = { .size = sizeof(long), .align = sizeof(long), .get = s390_last_break_get, - .set = s390_last_break_set, }, #endif [REGSET_SYSTEM_CALL] = { @@ -1113,14 +1116,6 @@ static int s390_compat_last_break_get(struct task_struct *target, return 0; } -static int s390_compat_last_break_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - return 0; -} - static const struct user_regset s390_compat_regsets[] = { [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, @@ -1144,7 +1139,6 @@ static const struct user_regset s390_compat_regsets[] = { .size = sizeof(long), .align = sizeof(long), .get = s390_compat_last_break_get, - .set = s390_compat_last_break_set, }, [REGSET_SYSTEM_CALL] = { .core_note_type = NT_S390_SYSTEM_CALL, diff --git a/trunk/arch/s390/kernel/setup.c b/trunk/arch/s390/kernel/setup.c index e54c4ff8abaa..e58a462949b1 100644 --- a/trunk/arch/s390/kernel/setup.c +++ b/trunk/arch/s390/kernel/setup.c @@ -579,7 +579,7 @@ static unsigned long __init find_crash_base(unsigned long crash_size, *msg = "first memory chunk must be at least crashkernel size"; return 0; } - if (OLDMEM_BASE && crash_size == OLDMEM_SIZE) + if (is_kdump_kernel() && (crash_size == OLDMEM_SIZE)) return OLDMEM_BASE; for (i = MEMORY_CHUNKS - 1; i >= 0; i--) { diff --git a/trunk/arch/s390/kernel/signal.c b/trunk/arch/s390/kernel/signal.c index 7f6f9f354545..05a85bc14c98 100644 --- a/trunk/arch/s390/kernel/signal.c +++ b/trunk/arch/s390/kernel/signal.c @@ -460,9 +460,9 @@ void do_signal(struct pt_regs *regs) regs->svc_code >> 16); break; } + /* No longer in a system call */ + clear_thread_flag(TIF_SYSCALL); } - /* No longer in a system call */ - clear_thread_flag(TIF_SYSCALL); if ((is_compat_task() ? handle_signal32(signr, &ka, &info, oldset, regs) : @@ -486,7 +486,6 @@ void do_signal(struct pt_regs *regs) } /* No handlers present - check for system call restart */ - clear_thread_flag(TIF_SYSCALL); if (current_thread_info()->system_call) { regs->svc_code = current_thread_info()->system_call; switch (regs->gprs[2]) { @@ -501,6 +500,9 @@ void do_signal(struct pt_regs *regs) regs->gprs[2] = regs->orig_gpr2; set_thread_flag(TIF_SYSCALL); break; + default: + clear_thread_flag(TIF_SYSCALL); + break; } } diff --git a/trunk/arch/x86/include/asm/intel_scu_ipc.h b/trunk/arch/x86/include/asm/intel_scu_ipc.h index 925b605eb5c6..4420993acc47 100644 --- a/trunk/arch/x86/include/asm/intel_scu_ipc.h +++ b/trunk/arch/x86/include/asm/intel_scu_ipc.h @@ -3,15 +3,11 @@ #include -#define IPCMSG_WARM_RESET 0xF0 -#define IPCMSG_COLD_RESET 0xF1 -#define IPCMSG_SOFT_RESET 0xF2 -#define IPCMSG_COLD_BOOT 0xF3 - -#define IPCMSG_VRTC 0xFA /* Set vRTC device */ - /* Command id associated with message IPCMSG_VRTC */ - #define IPC_CMD_VRTC_SETTIME 1 /* Set time */ - #define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */ +#define IPCMSG_VRTC 0xFA /* Set vRTC device */ + +/* Command id associated with message IPCMSG_VRTC */ +#define IPC_CMD_VRTC_SETTIME 1 /* Set time */ +#define IPC_CMD_VRTC_SETALARM 2 /* Set alarm */ /* Read single register */ int intel_scu_ipc_ioread8(u16 addr, u8 *data); diff --git a/trunk/arch/x86/include/asm/mrst.h b/trunk/arch/x86/include/asm/mrst.h index 93f79094c224..e6283129c821 100644 --- a/trunk/arch/x86/include/asm/mrst.h +++ b/trunk/arch/x86/include/asm/mrst.h @@ -31,20 +31,11 @@ enum mrst_cpu_type { }; extern enum mrst_cpu_type __mrst_cpu_chip; - -#ifdef CONFIG_X86_INTEL_MID - static inline enum mrst_cpu_type mrst_identify_cpu(void) { return __mrst_cpu_chip; } -#else /* !CONFIG_X86_INTEL_MID */ - -#define mrst_identify_cpu() (0) - -#endif /* !CONFIG_X86_INTEL_MID */ - enum mrst_timer_options { MRST_TIMER_DEFAULT, MRST_TIMER_APBT_ONLY, diff --git a/trunk/arch/x86/include/asm/msr.h b/trunk/arch/x86/include/asm/msr.h index 95203d40ffdd..084ef95274cd 100644 --- a/trunk/arch/x86/include/asm/msr.h +++ b/trunk/arch/x86/include/asm/msr.h @@ -169,14 +169,7 @@ static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high) return native_write_msr_safe(msr, low, high); } -/* - * rdmsr with exception handling. - * - * Please note that the exception handling works only after we've - * switched to the "smart" #GP handler in trap_init() which knows about - * exception tables - using this macro earlier than that causes machine - * hangs on boxes which do not implement the @msr in the first argument. - */ +/* rdmsr with exception handling */ #define rdmsr_safe(msr, p1, p2) \ ({ \ int __err; \ diff --git a/trunk/arch/x86/include/asm/system.h b/trunk/arch/x86/include/asm/system.h index 2d2f01ce6dcb..c2ff2a1d845e 100644 --- a/trunk/arch/x86/include/asm/system.h +++ b/trunk/arch/x86/include/asm/system.h @@ -401,7 +401,6 @@ extern unsigned long arch_align_stack(unsigned long sp); extern void free_init_pages(char *what, unsigned long begin, unsigned long end); void default_idle(void); -bool set_pm_idle_to_default(void); void stop_this_cpu(void *dummy); diff --git a/trunk/arch/x86/include/asm/timer.h b/trunk/arch/x86/include/asm/timer.h index 431793e5d484..fa7b9176b76c 100644 --- a/trunk/arch/x86/include/asm/timer.h +++ b/trunk/arch/x86/include/asm/timer.h @@ -32,22 +32,6 @@ extern int no_timer_check; * (mathieu.desnoyers@polymtl.ca) * * -johnstul@us.ibm.com "math is hard, lets go shopping!" - * - * In: - * - * ns = cycles * cyc2ns_scale / SC - * - * Although we may still have enough bits to store the value of ns, - * in some cases, we may not have enough bits to store cycles * cyc2ns_scale, - * leading to an incorrect result. - * - * To avoid this, we can decompose 'cycles' into quotient and remainder - * of division by SC. Then, - * - * ns = (quot * SC + rem) * cyc2ns_scale / SC - * = quot * cyc2ns_scale + (rem * cyc2ns_scale) / SC - * - * - sqazi@google.com */ DECLARE_PER_CPU(unsigned long, cyc2ns); @@ -57,14 +41,9 @@ DECLARE_PER_CPU(unsigned long long, cyc2ns_offset); static inline unsigned long long __cycles_2_ns(unsigned long long cyc) { - unsigned long long quot; - unsigned long long rem; int cpu = smp_processor_id(); unsigned long long ns = per_cpu(cyc2ns_offset, cpu); - quot = (cyc >> CYC2NS_SCALE_FACTOR); - rem = cyc & ((1ULL << CYC2NS_SCALE_FACTOR) - 1); - ns += quot * per_cpu(cyc2ns, cpu) + - ((rem * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR); + ns += cyc * per_cpu(cyc2ns, cpu) >> CYC2NS_SCALE_FACTOR; return ns; } diff --git a/trunk/arch/x86/include/asm/uv/uv_mmrs.h b/trunk/arch/x86/include/asm/uv/uv_mmrs.h index cf1d73643f60..10474fb1185d 100644 --- a/trunk/arch/x86/include/asm/uv/uv_mmrs.h +++ b/trunk/arch/x86/include/asm/uv/uv_mmrs.h @@ -57,7 +57,6 @@ #define UV1_HUB_PART_NUMBER 0x88a5 #define UV2_HUB_PART_NUMBER 0x8eb8 -#define UV2_HUB_PART_NUMBER_X 0x1111 /* Compat: if this #define is present, UV headers support UV2 */ #define UV2_HUB_IS_SUPPORTED 1 diff --git a/trunk/arch/x86/kernel/apic/x2apic_uv_x.c b/trunk/arch/x86/kernel/apic/x2apic_uv_x.c index 9d59bbacd4e3..62ae3001ae02 100644 --- a/trunk/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/trunk/arch/x86/kernel/apic/x2apic_uv_x.c @@ -93,8 +93,6 @@ static int __init early_get_pnodeid(void) if (node_id.s.part_number == UV2_HUB_PART_NUMBER) uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1; - if (node_id.s.part_number == UV2_HUB_PART_NUMBER_X) - uv_min_hub_revision_id += UV2_HUB_REVISION_BASE - 1; uv_hub_info->hub_revision = uv_min_hub_revision_id; pnode = (node_id.s.node_id >> 1) & ((1 << m_n_config.s.n_skt) - 1); diff --git a/trunk/arch/x86/kernel/cpu/amd.c b/trunk/arch/x86/kernel/cpu/amd.c index 0bab2b18bb20..c7e46cb35327 100644 --- a/trunk/arch/x86/kernel/cpu/amd.c +++ b/trunk/arch/x86/kernel/cpu/amd.c @@ -442,6 +442,8 @@ static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c) static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) { + u32 dummy; + early_init_amd_mc(c); /* @@ -471,12 +473,12 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_EXTD_APICID); } #endif + + rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); } static void __cpuinit init_amd(struct cpuinfo_x86 *c) { - u32 dummy; - #ifdef CONFIG_SMP unsigned long long value; @@ -655,8 +657,6 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) checking_wrmsrl(MSR_AMD64_MCx_MASK(4), mask); } } - - rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy); } #ifdef CONFIG_X86_32 diff --git a/trunk/arch/x86/kernel/cpu/mtrr/generic.c b/trunk/arch/x86/kernel/cpu/mtrr/generic.c index 97b26356e9ee..a71efcdbb092 100644 --- a/trunk/arch/x86/kernel/cpu/mtrr/generic.c +++ b/trunk/arch/x86/kernel/cpu/mtrr/generic.c @@ -547,7 +547,6 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, if (tmp != mask_lo) { printk(KERN_WARNING "mtrr: your BIOS has configured an incorrect mask, fixing it.\n"); - add_taint(TAINT_FIRMWARE_WORKAROUND); mask_lo = tmp; } } @@ -694,7 +693,6 @@ static void prepare_set(void) __acquires(set_atomicity_lock) /* Disable MTRRs, and set the default type to uncached */ mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi); - wbinvd(); } static void post_set(void) __releases(set_atomicity_lock) diff --git a/trunk/arch/x86/kernel/cpu/perf_event.c b/trunk/arch/x86/kernel/cpu/perf_event.c index 2bda212a0010..640891014b2a 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event.c +++ b/trunk/arch/x86/kernel/cpu/perf_event.c @@ -312,8 +312,12 @@ int x86_setup_perfctr(struct perf_event *event) return -EOPNOTSUPP; } + /* + * Do not allow config1 (extended registers) to propagate, + * there's no sane user-space generalization yet: + */ if (attr->type == PERF_TYPE_RAW) - return x86_pmu_extra_regs(event->attr.config, event); + return 0; if (attr->type == PERF_TYPE_HW_CACHE) return set_ext_hw_attr(hwc, event); @@ -584,7 +588,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) x86_pmu.put_event_constraints(cpuc, cpuc->event_list[i]); } } - return num ? -EINVAL : 0; + return num ? -ENOSPC : 0; } /* @@ -603,7 +607,7 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader, if (is_x86_event(leader)) { if (n >= max_count) - return -EINVAL; + return -ENOSPC; cpuc->event_list[n] = leader; n++; } @@ -616,7 +620,7 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader, continue; if (n >= max_count) - return -EINVAL; + return -ENOSPC; cpuc->event_list[n] = event; n++; @@ -1312,7 +1316,7 @@ static int validate_event(struct perf_event *event) c = x86_pmu.get_event_constraints(fake_cpuc, event); if (!c || !c->weight) - ret = -EINVAL; + ret = -ENOSPC; if (x86_pmu.put_event_constraints) x86_pmu.put_event_constraints(fake_cpuc, event); @@ -1337,7 +1341,7 @@ static int validate_group(struct perf_event *event) { struct perf_event *leader = event->group_leader; struct cpu_hw_events *fake_cpuc; - int ret = -EINVAL, n; + int ret = -ENOSPC, n; fake_cpuc = allocate_fake_cpuc(); if (IS_ERR(fake_cpuc)) diff --git a/trunk/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/trunk/arch/x86/kernel/cpu/perf_event_amd_ibs.c index 3b8a2d30d14e..ab6343d21825 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -199,7 +199,8 @@ static int force_ibs_eilvt_setup(void) goto out; } - pr_info("IBS: LVT offset %d assigned\n", offset); + pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset); + pr_err(FW_BUG "workaround enabled for IBS LVT offset\n"); return 0; out: @@ -264,23 +265,19 @@ perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *h static __init int amd_ibs_init(void) { u32 caps; - int ret = -EINVAL; + int ret; caps = __get_ibs_caps(); if (!caps) return -ENODEV; /* ibs not supported by the cpu */ - /* - * Force LVT offset assignment for family 10h: The offsets are - * not assigned by the BIOS for this family, so the OS is - * responsible for doing it. If the OS assignment fails, fall - * back to BIOS settings and try to setup this. - */ - if (boot_cpu_data.x86 == 0x10) - force_ibs_eilvt_setup(); - - if (!ibs_eilvt_valid()) - goto out; + if (!ibs_eilvt_valid()) { + ret = force_ibs_eilvt_setup(); + if (ret) { + pr_err("Failed to setup IBS, %d\n", ret); + return ret; + } + } get_online_cpus(); ibs_caps = caps; @@ -290,11 +287,7 @@ static __init int amd_ibs_init(void) smp_call_function(setup_APIC_ibs, NULL, 1); put_online_cpus(); - ret = perf_event_ibs_init(); -out: - if (ret) - pr_err("Failed to setup IBS, %d\n", ret); - return ret; + return perf_event_ibs_init(); } /* Since we need the pci subsystem to init ibs we can't do this earlier: */ diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel.c b/trunk/arch/x86/kernel/cpu/perf_event_intel.c index 8d601b18bf9f..2be5ebe99872 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel.c @@ -1545,13 +1545,6 @@ static void intel_clovertown_quirks(void) x86_pmu.pebs_constraints = NULL; } -static void intel_sandybridge_quirks(void) -{ - printk(KERN_WARNING "PEBS disabled due to CPU errata.\n"); - x86_pmu.pebs = 0; - x86_pmu.pebs_constraints = NULL; -} - __init int intel_pmu_init(void) { union cpuid10_edx edx; @@ -1701,7 +1694,6 @@ __init int intel_pmu_init(void) break; case 42: /* SandyBridge */ - x86_pmu.quirks = intel_sandybridge_quirks; case 45: /* SandyBridge, "Romely-EP" */ memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, sizeof(hw_cache_event_ids)); diff --git a/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c b/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c index 73da6b64f5b7..c0d238f49db8 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -493,7 +493,6 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) unsigned long from = cpuc->lbr_entries[0].from; unsigned long old_to, to = cpuc->lbr_entries[0].to; unsigned long ip = regs->ip; - int is_64bit = 0; /* * We don't need to fixup if the PEBS assist is fault like @@ -545,10 +544,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) } else kaddr = (void *)to; -#ifdef CONFIG_X86_64 - is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32); -#endif - insn_init(&insn, kaddr, is_64bit); + kernel_insn_init(&insn, kaddr); insn_get_length(&insn); to += insn.length; } while (to < ip); diff --git a/trunk/arch/x86/kernel/cpu/perf_event_p4.c b/trunk/arch/x86/kernel/cpu/perf_event_p4.c index ef484d9d0a25..492bf1358a7c 100644 --- a/trunk/arch/x86/kernel/cpu/perf_event_p4.c +++ b/trunk/arch/x86/kernel/cpu/perf_event_p4.c @@ -1268,7 +1268,7 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign } done: - return num ? -EINVAL : 0; + return num ? -ENOSPC : 0; } static __initconst const struct x86_pmu p4_pmu = { diff --git a/trunk/arch/x86/kernel/irq_64.c b/trunk/arch/x86/kernel/irq_64.c index 69bca468c47a..acf8fbf8fbda 100644 --- a/trunk/arch/x86/kernel/irq_64.c +++ b/trunk/arch/x86/kernel/irq_64.c @@ -38,9 +38,6 @@ static inline void stack_overflow_check(struct pt_regs *regs) #ifdef CONFIG_DEBUG_STACKOVERFLOW u64 curbase = (u64)task_stack_page(current); - if (user_mode_vm(regs)) - return; - WARN_ONCE(regs->sp >= curbase && regs->sp <= curbase + THREAD_SIZE && regs->sp < curbase + sizeof(struct thread_info) + diff --git a/trunk/arch/x86/kernel/microcode_core.c b/trunk/arch/x86/kernel/microcode_core.c index 9d46f5e43b51..f2d2a664e797 100644 --- a/trunk/arch/x86/kernel/microcode_core.c +++ b/trunk/arch/x86/kernel/microcode_core.c @@ -256,7 +256,7 @@ static int __init microcode_dev_init(void) return 0; } -static void __exit microcode_dev_exit(void) +static void microcode_dev_exit(void) { misc_deregister(µcode_dev); } @@ -519,8 +519,10 @@ static int __init microcode_init(void) microcode_pdev = platform_device_register_simple("microcode", -1, NULL, 0); - if (IS_ERR(microcode_pdev)) + if (IS_ERR(microcode_pdev)) { + microcode_dev_exit(); return PTR_ERR(microcode_pdev); + } get_online_cpus(); mutex_lock(µcode_mutex); @@ -530,12 +532,14 @@ static int __init microcode_init(void) mutex_unlock(µcode_mutex); put_online_cpus(); - if (error) - goto out_pdev; + if (error) { + platform_device_unregister(microcode_pdev); + return error; + } error = microcode_dev_init(); if (error) - goto out_sysdev_driver; + return error; register_syscore_ops(&mc_syscore_ops); register_hotcpu_notifier(&mc_cpu_notifier); @@ -544,20 +548,6 @@ static int __init microcode_init(void) " , Peter Oruba\n"); return 0; - -out_sysdev_driver: - get_online_cpus(); - mutex_lock(µcode_mutex); - - sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver); - - mutex_unlock(µcode_mutex); - put_online_cpus(); - -out_pdev: - platform_device_unregister(microcode_pdev); - return error; - } module_init(microcode_init); diff --git a/trunk/arch/x86/kernel/mpparse.c b/trunk/arch/x86/kernel/mpparse.c index 0741b062a304..9103b89c145a 100644 --- a/trunk/arch/x86/kernel/mpparse.c +++ b/trunk/arch/x86/kernel/mpparse.c @@ -95,8 +95,8 @@ static void __init MP_bus_info(struct mpc_bus *m) } #endif - set_bit(m->busid, mp_bus_not_pci); if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA) - 1) == 0) { + set_bit(m->busid, mp_bus_not_pci); #if defined(CONFIG_EISA) || defined(CONFIG_MCA) mp_bus_id_to_type[m->busid] = MP_BUS_ISA; #endif diff --git a/trunk/arch/x86/kernel/process.c b/trunk/arch/x86/kernel/process.c index ee5d4fbd53b4..b9b3b1a51643 100644 --- a/trunk/arch/x86/kernel/process.c +++ b/trunk/arch/x86/kernel/process.c @@ -403,14 +403,6 @@ void default_idle(void) EXPORT_SYMBOL(default_idle); #endif -bool set_pm_idle_to_default(void) -{ - bool ret = !!pm_idle; - - pm_idle = default_idle; - - return ret; -} void stop_this_cpu(void *dummy) { local_irq_disable(); diff --git a/trunk/arch/x86/kernel/quirks.c b/trunk/arch/x86/kernel/quirks.c index 03920a15a632..b78643d0f9a5 100644 --- a/trunk/arch/x86/kernel/quirks.c +++ b/trunk/arch/x86/kernel/quirks.c @@ -553,17 +553,4 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC, quirk_amd_nb_node); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_LINK, quirk_amd_nb_node); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F0, - quirk_amd_nb_node); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F1, - quirk_amd_nb_node); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F2, - quirk_amd_nb_node); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3, - quirk_amd_nb_node); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4, - quirk_amd_nb_node); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F5, - quirk_amd_nb_node); - #endif diff --git a/trunk/arch/x86/kernel/reboot.c b/trunk/arch/x86/kernel/reboot.c index 37a458b521a6..e334be1182b9 100644 --- a/trunk/arch/x86/kernel/reboot.c +++ b/trunk/arch/x86/kernel/reboot.c @@ -124,7 +124,7 @@ __setup("reboot=", reboot_setup); */ /* - * Some machines require the "reboot=b" or "reboot=k" commandline options, + * Some machines require the "reboot=b" commandline option, * this quirk makes that automatic. */ static int __init set_bios_reboot(const struct dmi_system_id *d) @@ -136,15 +136,6 @@ static int __init set_bios_reboot(const struct dmi_system_id *d) return 0; } -static int __init set_kbd_reboot(const struct dmi_system_id *d) -{ - if (reboot_type != BOOT_KBD) { - reboot_type = BOOT_KBD; - printk(KERN_INFO "%s series board detected. Selecting KBD-method for reboot.\n", d->ident); - } - return 0; -} - static struct dmi_system_id __initdata reboot_dmi_table[] = { { /* Handle problems with rebooting on Dell E520's */ .callback = set_bios_reboot, @@ -304,7 +295,7 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { }, }, { /* Handle reboot issue on Acer Aspire one */ - .callback = set_kbd_reboot, + .callback = set_bios_reboot, .ident = "Acer Aspire One A110", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), @@ -452,14 +443,6 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6420"), }, }, - { /* Handle problems with rebooting on the OptiPlex 990. */ - .callback = set_pci_reboot, - .ident = "Dell OptiPlex 990", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"), - }, - }, { } }; diff --git a/trunk/arch/x86/kernel/rtc.c b/trunk/arch/x86/kernel/rtc.c index af6db6ec5b2a..348ce016a835 100644 --- a/trunk/arch/x86/kernel/rtc.c +++ b/trunk/arch/x86/kernel/rtc.c @@ -12,7 +12,6 @@ #include #include #include -#include #ifdef CONFIG_X86_32 /* @@ -243,10 +242,6 @@ static __init int add_rtc_cmos(void) if (of_have_populated_dt()) return 0; - /* Intel MID platforms don't have ioport rtc */ - if (mrst_identify_cpu()) - return -ENODEV; - platform_device_register(&rtc_device); dev_info(&rtc_device.dev, "registered platform RTC device (no PNP device found)\n"); diff --git a/trunk/arch/x86/mm/highmem_32.c b/trunk/arch/x86/mm/highmem_32.c index f4f29b19fac5..b49962662101 100644 --- a/trunk/arch/x86/mm/highmem_32.c +++ b/trunk/arch/x86/mm/highmem_32.c @@ -45,7 +45,6 @@ void *kmap_atomic_prot(struct page *page, pgprot_t prot) vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); BUG_ON(!pte_none(*(kmap_pte-idx))); set_pte(kmap_pte-idx, mk_pte(page, prot)); - arch_flush_lazy_mmu_mode(); return (void *)vaddr; } @@ -89,7 +88,6 @@ void __kunmap_atomic(void *kvaddr) */ kpte_clear_flush(kmap_pte-idx, vaddr); kmap_atomic_idx_pop(); - arch_flush_lazy_mmu_mode(); } #ifdef CONFIG_DEBUG_HIGHMEM else { diff --git a/trunk/arch/x86/oprofile/init.c b/trunk/arch/x86/oprofile/init.c index f148cf652678..cdfe4c54deca 100644 --- a/trunk/arch/x86/oprofile/init.c +++ b/trunk/arch/x86/oprofile/init.c @@ -21,7 +21,6 @@ extern int op_nmi_timer_init(struct oprofile_operations *ops); extern void op_nmi_exit(void); extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth); -static int nmi_timer; int __init oprofile_arch_init(struct oprofile_operations *ops) { @@ -32,9 +31,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) #ifdef CONFIG_X86_LOCAL_APIC ret = op_nmi_init(ops); #endif - nmi_timer = (ret != 0); #ifdef CONFIG_X86_IO_APIC - if (nmi_timer) + if (ret < 0) ret = op_nmi_timer_init(ops); #endif ops->backtrace = x86_backtrace; @@ -46,7 +44,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) void oprofile_arch_exit(void) { #ifdef CONFIG_X86_LOCAL_APIC - if (!nmi_timer) - op_nmi_exit(); + op_nmi_exit(); #endif } diff --git a/trunk/arch/x86/platform/mrst/mrst.c b/trunk/arch/x86/platform/mrst/mrst.c index ad4ec1cb097e..b1489a06a49d 100644 --- a/trunk/arch/x86/platform/mrst/mrst.c +++ b/trunk/arch/x86/platform/mrst/mrst.c @@ -76,20 +76,6 @@ struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX]; EXPORT_SYMBOL_GPL(sfi_mrtc_array); int sfi_mrtc_num; -static void mrst_power_off(void) -{ - if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) - intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 1); -} - -static void mrst_reboot(void) -{ - if (__mrst_cpu_chip == MRST_CPU_CHIP_LINCROFT) - intel_scu_ipc_simple_command(IPCMSG_COLD_RESET, 0); - else - intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0); -} - /* parse all the mtimer info to a static mtimer array */ static int __init sfi_parse_mtmr(struct sfi_table_header *table) { @@ -279,6 +265,17 @@ static int mrst_i8042_detect(void) return 0; } +/* Reboot and power off are handled by the SCU on a MID device */ +static void mrst_power_off(void) +{ + intel_scu_ipc_simple_command(0xf1, 1); +} + +static void mrst_reboot(void) +{ + intel_scu_ipc_simple_command(0xf1, 0); +} + /* * Moorestown does not have external NMI source nor port 0x61 to report * NMI status. The possible NMI sources are from pmu as a result of NMI @@ -487,46 +484,6 @@ static void __init *max7315_platform_data(void *info) return max7315; } -static void *tca6416_platform_data(void *info) -{ - static struct pca953x_platform_data tca6416; - struct i2c_board_info *i2c_info = info; - int gpio_base, intr; - char base_pin_name[SFI_NAME_LEN + 1]; - char intr_pin_name[SFI_NAME_LEN + 1]; - - strcpy(i2c_info->type, "tca6416"); - strcpy(base_pin_name, "tca6416_base"); - strcpy(intr_pin_name, "tca6416_int"); - - gpio_base = get_gpio_by_name(base_pin_name); - intr = get_gpio_by_name(intr_pin_name); - - if (gpio_base == -1) - return NULL; - tca6416.gpio_base = gpio_base; - if (intr != -1) { - i2c_info->irq = intr + MRST_IRQ_OFFSET; - tca6416.irq_base = gpio_base + MRST_IRQ_OFFSET; - } else { - i2c_info->irq = -1; - tca6416.irq_base = -1; - } - return &tca6416; -} - -static void *mpu3050_platform_data(void *info) -{ - struct i2c_board_info *i2c_info = info; - int intr = get_gpio_by_name("mpu3050_int"); - - if (intr == -1) - return NULL; - - i2c_info->irq = intr + MRST_IRQ_OFFSET; - return NULL; -} - static void __init *emc1403_platform_data(void *info) { static short intr2nd_pdata; @@ -689,15 +646,12 @@ static void *msic_ocd_platform_data(void *info) static const struct devs_id __initconst device_ids[] = { {"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data}, {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, - {"pmic_gpio", SFI_DEV_TYPE_IPC, 1, &pmic_gpio_platform_data}, {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data}, {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, {"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, - {"tca6416", SFI_DEV_TYPE_I2C, 1, &tca6416_platform_data}, {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data}, {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data}, {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, - {"mpu3050", SFI_DEV_TYPE_I2C, 1, &mpu3050_platform_data}, /* MSIC subdevices */ {"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data}, diff --git a/trunk/arch/x86/xen/setup.c b/trunk/arch/x86/xen/setup.c index 1093f80c162d..38d0af4fefec 100644 --- a/trunk/arch/x86/xen/setup.c +++ b/trunk/arch/x86/xen/setup.c @@ -410,6 +410,6 @@ void __init xen_arch_setup(void) #endif disable_cpuidle(); boot_option_idle_override = IDLE_HALT; - WARN_ON(set_pm_idle_to_default()); + fiddle_vdso(); } diff --git a/trunk/drivers/bcma/host_pci.c b/trunk/drivers/bcma/host_pci.c index b0994c0e05dc..1b51d8b7ac80 100644 --- a/trunk/drivers/bcma/host_pci.c +++ b/trunk/drivers/bcma/host_pci.c @@ -21,58 +21,48 @@ static void bcma_host_pci_switch_core(struct bcma_device *core) pr_debug("Switched to core: 0x%X\n", core->id.id); } -/* Provides access to the requested core. Returns base offset that has to be - * used. It makes use of fixed windows when possible. */ -static u16 bcma_host_pci_provide_access_to_core(struct bcma_device *core) +static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) { - switch (core->id.id) { - case BCMA_CORE_CHIPCOMMON: - return 3 * BCMA_CORE_SIZE; - case BCMA_CORE_PCIE: - return 2 * BCMA_CORE_SIZE; - } - if (core->bus->mapped_core != core) bcma_host_pci_switch_core(core); - return 0; -} - -static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) -{ - offset += bcma_host_pci_provide_access_to_core(core); return ioread8(core->bus->mmio + offset); } static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset) { - offset += bcma_host_pci_provide_access_to_core(core); + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); return ioread16(core->bus->mmio + offset); } static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset) { - offset += bcma_host_pci_provide_access_to_core(core); + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); return ioread32(core->bus->mmio + offset); } static void bcma_host_pci_write8(struct bcma_device *core, u16 offset, u8 value) { - offset += bcma_host_pci_provide_access_to_core(core); + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); iowrite8(value, core->bus->mmio + offset); } static void bcma_host_pci_write16(struct bcma_device *core, u16 offset, u16 value) { - offset += bcma_host_pci_provide_access_to_core(core); + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); iowrite16(value, core->bus->mmio + offset); } static void bcma_host_pci_write32(struct bcma_device *core, u16 offset, u32 value) { - offset += bcma_host_pci_provide_access_to_core(core); + if (core->bus->mapped_core != core) + bcma_host_pci_switch_core(core); iowrite32(value, core->bus->mmio + offset); } diff --git a/trunk/drivers/bluetooth/Kconfig b/trunk/drivers/bluetooth/Kconfig index 5ccf142ef0b8..11b41fd40c27 100644 --- a/trunk/drivers/bluetooth/Kconfig +++ b/trunk/drivers/bluetooth/Kconfig @@ -188,7 +188,7 @@ config BT_MRVL The core driver to support Marvell Bluetooth devices. This driver is required if you want to support - Marvell Bluetooth devices, such as 8688/8787/8797. + Marvell Bluetooth devices, such as 8688/8787. Say Y here to compile Marvell Bluetooth driver into the kernel or say M to compile it as module. @@ -201,8 +201,8 @@ config BT_MRVL_SDIO The driver for Marvell Bluetooth chipsets with SDIO interface. This driver is required if you want to use Marvell Bluetooth - devices with SDIO interface. Currently SD8688/SD8787/SD8797 - chipsets are supported. + devices with SDIO interface. Currently SD8688/SD8787 chipsets are + supported. Say Y here to compile support for Marvell BT-over-SDIO driver into the kernel or say M to compile it as module. diff --git a/trunk/drivers/bluetooth/btmrvl_sdio.c b/trunk/drivers/bluetooth/btmrvl_sdio.c index 27b74b0d547b..9ef48167e2cf 100644 --- a/trunk/drivers/bluetooth/btmrvl_sdio.c +++ b/trunk/drivers/bluetooth/btmrvl_sdio.c @@ -65,7 +65,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8688 = { .io_port_1 = 0x01, .io_port_2 = 0x02, }; -static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = { +static const struct btmrvl_sdio_card_reg btmrvl_reg_8787 = { .cfg = 0x00, .host_int_mask = 0x02, .host_intstatus = 0x03, @@ -92,14 +92,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { .helper = NULL, .firmware = "mrvl/sd8787_uapsta.bin", - .reg = &btmrvl_reg_87xx, - .sd_blksz_fw_dl = 256, -}; - -static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { - .helper = NULL, - .firmware = "mrvl/sd8797_uapsta.bin", - .reg = &btmrvl_reg_87xx, + .reg = &btmrvl_reg_8787, .sd_blksz_fw_dl = 256, }; @@ -110,9 +103,6 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = { /* Marvell SD8787 Bluetooth device */ { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x911A), .driver_data = (unsigned long) &btmrvl_sdio_sd8787 }, - /* Marvell SD8797 Bluetooth device */ - { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), - .driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, { } /* Terminating entry */ }; @@ -1086,4 +1076,3 @@ MODULE_LICENSE("GPL v2"); MODULE_FIRMWARE("sd8688_helper.bin"); MODULE_FIRMWARE("sd8688.bin"); MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); -MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); diff --git a/trunk/drivers/bluetooth/btusb.c b/trunk/drivers/bluetooth/btusb.c index ea5ad1cbbd3d..2bd87d45f1c2 100644 --- a/trunk/drivers/bluetooth/btusb.c +++ b/trunk/drivers/bluetooth/btusb.c @@ -785,8 +785,9 @@ static int btusb_send_frame(struct sk_buff *skb) usb_mark_last_busy(data->udev); } -done: usb_free_urb(urb); + +done: return err; } diff --git a/trunk/drivers/bluetooth/hci_vhci.c b/trunk/drivers/bluetooth/hci_vhci.c index 2ed6ab1c6e1b..2e302a11ab55 100644 --- a/trunk/drivers/bluetooth/hci_vhci.c +++ b/trunk/drivers/bluetooth/hci_vhci.c @@ -41,8 +41,6 @@ #define VERSION "1.3" -static bool amp; - struct vhci_data { struct hci_dev *hdev; @@ -241,9 +239,6 @@ static int vhci_open(struct inode *inode, struct file *file) hdev->bus = HCI_VIRTUAL; hdev->driver_data = data; - if (amp) - hdev->dev_type = HCI_AMP; - hdev->open = vhci_open_dev; hdev->close = vhci_close_dev; hdev->flush = vhci_flush; @@ -308,9 +303,6 @@ static void __exit vhci_exit(void) module_init(vhci_init); module_exit(vhci_exit); -module_param(amp, bool, 0644); -MODULE_PARM_DESC(amp, "Create AMP controller device"); - MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); MODULE_VERSION(VERSION); diff --git a/trunk/drivers/firmware/sigma.c b/trunk/drivers/firmware/sigma.c index 1eedb6f7fdab..f10fc521951b 100644 --- a/trunk/drivers/firmware/sigma.c +++ b/trunk/drivers/firmware/sigma.c @@ -14,34 +14,13 @@ #include #include -static size_t sigma_action_size(struct sigma_action *sa) -{ - size_t payload = 0; - - switch (sa->instr) { - case SIGMA_ACTION_WRITEXBYTES: - case SIGMA_ACTION_WRITESINGLE: - case SIGMA_ACTION_WRITESAFELOAD: - payload = sigma_action_len(sa); - break; - default: - break; - } - - payload = ALIGN(payload, 2); - - return payload + sizeof(struct sigma_action); -} - -/* - * Returns a negative error value in case of an error, 0 if processing of - * the firmware should be stopped after this action, 1 otherwise. - */ +/* Return: 0==OK, <0==error, =1 ==no more actions */ static int -process_sigma_action(struct i2c_client *client, struct sigma_action *sa) +process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw) { + struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos); size_t len = sigma_action_len(sa); - int ret; + int ret = 0; pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__, sa->instr, sa->addr, len); @@ -50,50 +29,44 @@ process_sigma_action(struct i2c_client *client, struct sigma_action *sa) case SIGMA_ACTION_WRITEXBYTES: case SIGMA_ACTION_WRITESINGLE: case SIGMA_ACTION_WRITESAFELOAD: + if (ssfw->fw->size < ssfw->pos + len) + return -EINVAL; ret = i2c_master_send(client, (void *)&sa->addr, len); if (ret < 0) return -EINVAL; break; + case SIGMA_ACTION_DELAY: + ret = 0; udelay(len); len = 0; break; + case SIGMA_ACTION_END: - return 0; + return 1; + default: return -EINVAL; } - return 1; + /* when arrive here ret=0 or sent data */ + ssfw->pos += sigma_action_size(sa, len); + return ssfw->pos == ssfw->fw->size; } static int process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw) { - struct sigma_action *sa; - size_t size; - int ret; - - while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) { - sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos); - - size = sigma_action_size(sa); - ssfw->pos += size; - if (ssfw->pos > ssfw->fw->size || size == 0) - break; - - ret = process_sigma_action(client, sa); + pr_debug("%s: processing %p\n", __func__, ssfw); + while (1) { + int ret = process_sigma_action(client, ssfw); pr_debug("%s: action returned %i\n", __func__, ret); - - if (ret <= 0) + if (ret == 1) + return 0; + else if (ret) return ret; } - - if (ssfw->pos != ssfw->fw->size) - return -EINVAL; - - return 0; } int process_sigma_firmware(struct i2c_client *client, const char *name) @@ -116,24 +89,16 @@ int process_sigma_firmware(struct i2c_client *client, const char *name) /* then verify the header */ ret = -EINVAL; - - /* - * Reject too small or unreasonable large files. The upper limit has been - * chosen a bit arbitrarily, but it should be enough for all practical - * purposes and having the limit makes it easier to avoid integer - * overflows later in the loading process. - */ - if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) + if (fw->size < sizeof(*ssfw_head)) goto done; ssfw_head = (void *)fw->data; if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) goto done; - crc = crc32(0, fw->data + sizeof(*ssfw_head), - fw->size - sizeof(*ssfw_head)); + crc = crc32(0, fw->data, fw->size); pr_debug("%s: crc=%x\n", __func__, crc); - if (crc != le32_to_cpu(ssfw_head->crc)) + if (crc != ssfw_head->crc) goto done; ssfw.pos = sizeof(*ssfw_head); diff --git a/trunk/drivers/gpio/Makefile b/trunk/drivers/gpio/Makefile index 4e018d6a7639..dbcb0bcfd8da 100644 --- a/trunk/drivers/gpio/Makefile +++ b/trunk/drivers/gpio/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o -obj-$(CONFIG_ARCH_KS8695) += gpio-ks8695.o +obj-$(CONFIG_MACH_KS8695) += gpio-ks8695.o obj-$(CONFIG_GPIO_LANGWELL) += gpio-langwell.o obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o diff --git a/trunk/drivers/gpu/drm/drm_crtc_helper.c b/trunk/drivers/gpu/drm/drm_crtc_helper.c index d2619d72cece..3969f7553fe7 100644 --- a/trunk/drivers/gpu/drm/drm_crtc_helper.c +++ b/trunk/drivers/gpu/drm/drm_crtc_helper.c @@ -456,30 +456,6 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, EXPORT_SYMBOL(drm_crtc_helper_set_mode); -static int -drm_crtc_helper_disable(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct drm_connector *connector; - struct drm_encoder *encoder; - - /* Decouple all encoders and their attached connectors from this crtc */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - if (encoder->crtc != crtc) - continue; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder != encoder) - continue; - - connector->encoder = NULL; - } - } - - drm_helper_disable_unused_functions(dev); - return 0; -} - /** * drm_crtc_helper_set_config - set a new config from userspace * @crtc: CRTC to setup @@ -534,7 +510,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) (int)set->num_connectors, set->x, set->y); } else { DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); - return drm_crtc_helper_disable(set->crtc); + set->mode = NULL; + set->num_connectors = 0; } dev = set->crtc->dev; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_display.c b/trunk/drivers/gpu/drm/nouveau/nouveau_display.c index b12fd2c80812..ddbabefb4273 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_display.c @@ -369,48 +369,3 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, spin_unlock_irqrestore(&dev->event_lock, flags); return 0; } - -int -nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, - struct drm_mode_create_dumb *args) -{ - struct nouveau_bo *bo; - int ret; - - args->pitch = roundup(args->width * (args->bpp / 8), 256); - args->size = args->pitch * args->height; - args->size = roundup(args->size, PAGE_SIZE); - - ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo); - if (ret) - return ret; - - ret = drm_gem_handle_create(file_priv, bo->gem, &args->handle); - drm_gem_object_unreference_unlocked(bo->gem); - return ret; -} - -int -nouveau_display_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev, - uint32_t handle) -{ - return drm_gem_handle_delete(file_priv, handle); -} - -int -nouveau_display_dumb_map_offset(struct drm_file *file_priv, - struct drm_device *dev, - uint32_t handle, uint64_t *poffset) -{ - struct drm_gem_object *gem; - - gem = drm_gem_object_lookup(dev, file_priv, handle); - if (gem) { - struct nouveau_bo *bo = gem->driver_private; - *poffset = bo->bo.addr_space_offset; - drm_gem_object_unreference_unlocked(gem); - return 0; - } - - return -ENOENT; -} diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.c b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.c index 9791d13c9e3b..9f7bb1295262 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -433,10 +433,6 @@ static struct drm_driver driver = { .gem_open_object = nouveau_gem_object_open, .gem_close_object = nouveau_gem_object_close, - .dumb_create = nouveau_display_dumb_create, - .dumb_map_offset = nouveau_display_dumb_map_offset, - .dumb_destroy = nouveau_display_dumb_destroy, - .name = DRIVER_NAME, .desc = DRIVER_DESC, #ifdef GIT_REVISION diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h index 4c0be3a4ed88..29837da1098b 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1418,12 +1418,6 @@ int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event); int nouveau_finish_page_flip(struct nouveau_channel *, struct nouveau_page_flip_state *); -int nouveau_display_dumb_create(struct drm_file *, struct drm_device *, - struct drm_mode_create_dumb *args); -int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *, - uint32_t handle, uint64_t *offset); -int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, - uint32_t handle); /* nv10_gpio.c */ int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_object.c b/trunk/drivers/gpu/drm/nouveau/nouveau_object.c index 960c0ae0c0c3..02222c540aee 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_object.c @@ -680,7 +680,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan) return ret; } - ret = drm_mm_init(&chan->ramin_heap, base, size - base); + ret = drm_mm_init(&chan->ramin_heap, base, size); if (ret) { NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret); nouveau_gpuobj_ref(NULL, &chan->ramin); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/trunk/drivers/gpu/drm/nouveau/nouveau_sgdma.c index c8a463b76c89..b75258a9fe44 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -67,10 +67,7 @@ nouveau_sgdma_clear(struct ttm_backend *be) pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages], PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); } - nvbe->unmap_pages = false; } - - nvbe->pages = NULL; } static void diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_display.c b/trunk/drivers/gpu/drm/nouveau/nv50_display.c index 06de250fe617..d23ca00e7d62 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_display.c @@ -616,7 +616,7 @@ 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 = 0, type = OUTPUT_ANY; + int i, crtc, or, type = OUTPUT_ANY; NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); disp->irq.dcb = NULL; @@ -708,7 +708,7 @@ nv50_display_unk20_handler(struct drm_device *dev) 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 = 0, type = OUTPUT_ANY; + int i, crtc, or, type = OUTPUT_ANY; NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); dcb = disp->irq.dcb; diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_graph.c b/trunk/drivers/gpu/drm/nouveau/nvc0_graph.c index ecfafd70cf0e..a74e501afd25 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_graph.c +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_graph.c @@ -381,8 +381,6 @@ nvc0_graph_init_gpc_0(struct drm_device *dev) u8 tpnr[GPC_MAX]; int i, gpc, tpc; - nv_wr32(dev, TP_UNIT(0, 0, 0x5c), 1); /* affects TFB offset queries */ - /* * TP ROP UNKVAL(magic_not_rop_nr) * 450: 4/0/0/0 2 3 diff --git a/trunk/drivers/gpu/drm/nouveau/nvd0_display.c b/trunk/drivers/gpu/drm/nouveau/nvd0_display.c index cb006a718e70..23d63b4b3d77 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nvd0_display.c @@ -780,7 +780,7 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) continue; if (nv_partner != nv_encoder && - nv_partner->dcb->or == nv_encoder->dcb->or) { + nv_partner->dcb->or == nv_encoder->or) { if (nv_partner->last_dpms == DRM_MODE_DPMS_ON) return; break; diff --git a/trunk/drivers/gpu/drm/radeon/atombios_crtc.c b/trunk/drivers/gpu/drm/radeon/atombios_crtc.c index 2b97262e3ab1..87631fede1f8 100644 --- a/trunk/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/trunk/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1107,40 +1107,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, return -EINVAL; } - if (tiling_flags & RADEON_TILING_MACRO) { - if (rdev->family >= CHIP_CAYMAN) - tmp = rdev->config.cayman.tile_config; - else - tmp = rdev->config.evergreen.tile_config; - - switch ((tmp & 0xf0) >> 4) { - case 0: /* 4 banks */ - fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_4_BANK); - break; - case 1: /* 8 banks */ - default: - fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_8_BANK); - break; - case 2: /* 16 banks */ - fb_format |= EVERGREEN_GRPH_NUM_BANKS(EVERGREEN_ADDR_SURF_16_BANK); - break; - } - - switch ((tmp & 0xf000) >> 12) { - case 0: /* 1KB rows */ - default: - fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB); - break; - case 1: /* 2KB rows */ - fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB); - break; - case 2: /* 4KB rows */ - fb_format |= EVERGREEN_GRPH_TILE_SPLIT(EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB); - break; - } - + if (tiling_flags & RADEON_TILING_MACRO) fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1); - } else if (tiling_flags & RADEON_TILING_MICRO) + else if (tiling_flags & RADEON_TILING_MICRO) fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1); switch (radeon_crtc->crtc_id) { diff --git a/trunk/drivers/gpu/drm/radeon/evergreen.c b/trunk/drivers/gpu/drm/radeon/evergreen.c index 5e00d1670aa9..1d603a3335db 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen.c @@ -82,7 +82,6 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); - int i; /* Lock the graphics update lock */ tmp |= EVERGREEN_GRPH_UPDATE_LOCK; @@ -100,11 +99,7 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) (u32)crtc_base); /* Wait for update_pending to go high. */ - for (i = 0; i < rdev->usec_timeout; i++) { - if (RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) - break; - udelay(1); - } + while (!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)); DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); /* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/trunk/drivers/gpu/drm/radeon/evergreen_cs.c b/trunk/drivers/gpu/drm/radeon/evergreen_cs.c index cd4590aae154..38e1bda73d33 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen_cs.c @@ -38,7 +38,6 @@ struct evergreen_cs_track { u32 group_size; u32 nbanks; u32 npipes; - u32 row_size; /* value we track */ u32 nsamples; u32 cb_color_base_last[12]; @@ -78,44 +77,6 @@ struct evergreen_cs_track { struct radeon_bo *db_s_write_bo; }; -static u32 evergreen_cs_get_aray_mode(u32 tiling_flags) -{ - if (tiling_flags & RADEON_TILING_MACRO) - return ARRAY_2D_TILED_THIN1; - else if (tiling_flags & RADEON_TILING_MICRO) - return ARRAY_1D_TILED_THIN1; - else - return ARRAY_LINEAR_GENERAL; -} - -static u32 evergreen_cs_get_num_banks(u32 nbanks) -{ - switch (nbanks) { - case 2: - return ADDR_SURF_2_BANK; - case 4: - return ADDR_SURF_4_BANK; - case 8: - default: - return ADDR_SURF_8_BANK; - case 16: - return ADDR_SURF_16_BANK; - } -} - -static u32 evergreen_cs_get_tile_split(u32 row_size) -{ - switch (row_size) { - case 1: - default: - return ADDR_SURF_TILE_SPLIT_1KB; - case 2: - return ADDR_SURF_TILE_SPLIT_2KB; - case 4: - return ADDR_SURF_TILE_SPLIT_4KB; - } -} - static void evergreen_cs_track_init(struct evergreen_cs_track *track) { int i; @@ -529,11 +490,12 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) } ib[idx] &= ~Z_ARRAY_MODE(0xf); track->db_z_info &= ~Z_ARRAY_MODE(0xf); - ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); - track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { - ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); - ib[idx] |= DB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size)); + ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + } else { + ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1); } } break; @@ -656,8 +618,13 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) "0x%04X\n", reg); return -EINVAL; } - ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); - track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { + ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + } } break; case CB_COLOR8_INFO: @@ -673,8 +640,13 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) "0x%04X\n", reg); return -EINVAL; } - ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); - track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { + ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { + ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1); + } } break; case CB_COLOR0_PITCH: @@ -729,16 +701,6 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case CB_COLOR9_ATTRIB: case CB_COLOR10_ATTRIB: case CB_COLOR11_ATTRIB: - r = evergreen_cs_packet_next_reloc(p, &reloc); - if (r) { - dev_warn(p->dev, "bad SET_CONTEXT_REG " - "0x%04X\n", reg); - return -EINVAL; - } - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { - ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); - ib[idx] |= CB_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size)); - } break; case CB_COLOR0_DIM: case CB_COLOR1_DIM: @@ -1356,14 +1318,10 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, } ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); if (!p->keep_tiling_flags) { - ib[idx+1+(i*8)+1] |= - TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->lobj.tiling_flags)); - if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) { - ib[idx+1+(i*8)+6] |= - TEX_TILE_SPLIT(evergreen_cs_get_tile_split(track->row_size)); - ib[idx+1+(i*8)+7] |= - TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); - } + if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) + ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1); + else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) + ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1); } texture = reloc->robj; /* tex mip base */ @@ -1464,7 +1422,6 @@ int evergreen_cs_parse(struct radeon_cs_parser *p) { struct radeon_cs_packet pkt; struct evergreen_cs_track *track; - u32 tmp; int r; if (p->track == NULL) { @@ -1473,63 +1430,9 @@ int evergreen_cs_parse(struct radeon_cs_parser *p) if (track == NULL) return -ENOMEM; evergreen_cs_track_init(track); - if (p->rdev->family >= CHIP_CAYMAN) - tmp = p->rdev->config.cayman.tile_config; - else - tmp = p->rdev->config.evergreen.tile_config; - - switch (tmp & 0xf) { - case 0: - track->npipes = 1; - break; - case 1: - default: - track->npipes = 2; - break; - case 2: - track->npipes = 4; - break; - case 3: - track->npipes = 8; - break; - } - - switch ((tmp & 0xf0) >> 4) { - case 0: - track->nbanks = 4; - break; - case 1: - default: - track->nbanks = 8; - break; - case 2: - track->nbanks = 16; - break; - } - - switch ((tmp & 0xf00) >> 8) { - case 0: - track->group_size = 256; - break; - case 1: - default: - track->group_size = 512; - break; - } - - switch ((tmp & 0xf000) >> 12) { - case 0: - track->row_size = 1; - break; - case 1: - default: - track->row_size = 2; - break; - case 2: - track->row_size = 4; - break; - } - + track->npipes = p->rdev->config.evergreen.tiling_npipes; + track->nbanks = p->rdev->config.evergreen.tiling_nbanks; + track->group_size = p->rdev->config.evergreen.tiling_group_size; p->track = track; } do { diff --git a/trunk/drivers/gpu/drm/radeon/evergreen_reg.h b/trunk/drivers/gpu/drm/radeon/evergreen_reg.h index 7d7f2155e34c..c781c92c3451 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/trunk/drivers/gpu/drm/radeon/evergreen_reg.h @@ -42,17 +42,6 @@ # define EVERGREEN_GRPH_DEPTH_8BPP 0 # define EVERGREEN_GRPH_DEPTH_16BPP 1 # define EVERGREEN_GRPH_DEPTH_32BPP 2 -# define EVERGREEN_GRPH_NUM_BANKS(x) (((x) & 0x3) << 2) -# define EVERGREEN_ADDR_SURF_2_BANK 0 -# define EVERGREEN_ADDR_SURF_4_BANK 1 -# define EVERGREEN_ADDR_SURF_8_BANK 2 -# define EVERGREEN_ADDR_SURF_16_BANK 3 -# define EVERGREEN_GRPH_Z(x) (((x) & 0x3) << 4) -# define EVERGREEN_GRPH_BANK_WIDTH(x) (((x) & 0x3) << 6) -# define EVERGREEN_ADDR_SURF_BANK_WIDTH_1 0 -# define EVERGREEN_ADDR_SURF_BANK_WIDTH_2 1 -# define EVERGREEN_ADDR_SURF_BANK_WIDTH_4 2 -# define EVERGREEN_ADDR_SURF_BANK_WIDTH_8 3 # define EVERGREEN_GRPH_FORMAT(x) (((x) & 0x7) << 8) /* 8 BPP */ # define EVERGREEN_GRPH_FORMAT_INDEXED 0 @@ -72,24 +61,6 @@ # define EVERGREEN_GRPH_FORMAT_8B_BGRA1010102 5 # define EVERGREEN_GRPH_FORMAT_RGB111110 6 # define EVERGREEN_GRPH_FORMAT_BGR101111 7 -# define EVERGREEN_GRPH_BANK_HEIGHT(x) (((x) & 0x3) << 11) -# define EVERGREEN_ADDR_SURF_BANK_HEIGHT_1 0 -# define EVERGREEN_ADDR_SURF_BANK_HEIGHT_2 1 -# define EVERGREEN_ADDR_SURF_BANK_HEIGHT_4 2 -# define EVERGREEN_ADDR_SURF_BANK_HEIGHT_8 3 -# define EVERGREEN_GRPH_TILE_SPLIT(x) (((x) & 0x7) << 13) -# define EVERGREEN_ADDR_SURF_TILE_SPLIT_64B 0 -# define EVERGREEN_ADDR_SURF_TILE_SPLIT_128B 1 -# define EVERGREEN_ADDR_SURF_TILE_SPLIT_256B 2 -# define EVERGREEN_ADDR_SURF_TILE_SPLIT_512B 3 -# define EVERGREEN_ADDR_SURF_TILE_SPLIT_1KB 4 -# define EVERGREEN_ADDR_SURF_TILE_SPLIT_2KB 5 -# define EVERGREEN_ADDR_SURF_TILE_SPLIT_4KB 6 -# define EVERGREEN_GRPH_MACRO_TILE_ASPECT(x) (((x) & 0x3) << 18) -# define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1 0 -# define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2 1 -# define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4 2 -# define EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8 3 # define EVERGREEN_GRPH_ARRAY_MODE(x) (((x) & 0x7) << 20) # define EVERGREEN_GRPH_ARRAY_LINEAR_GENERAL 0 # define EVERGREEN_GRPH_ARRAY_LINEAR_ALIGNED 1 diff --git a/trunk/drivers/gpu/drm/radeon/evergreend.h b/trunk/drivers/gpu/drm/radeon/evergreend.h index e00039e59a75..b937c49054d9 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreend.h +++ b/trunk/drivers/gpu/drm/radeon/evergreend.h @@ -899,10 +899,6 @@ #define DB_HTILE_DATA_BASE 0x28014 #define DB_Z_INFO 0x28040 # define Z_ARRAY_MODE(x) ((x) << 4) -# define DB_TILE_SPLIT(x) (((x) & 0x7) << 8) -# define DB_NUM_BANKS(x) (((x) & 0x3) << 12) -# define DB_BANK_WIDTH(x) (((x) & 0x3) << 16) -# define DB_BANK_HEIGHT(x) (((x) & 0x3) << 20) #define DB_STENCIL_INFO 0x28044 #define DB_Z_READ_BASE 0x28048 #define DB_STENCIL_READ_BASE 0x2804c @@ -955,29 +951,6 @@ # define CB_SF_EXPORT_FULL 0 # define CB_SF_EXPORT_NORM 1 #define CB_COLOR0_ATTRIB 0x28c74 -# define CB_TILE_SPLIT(x) (((x) & 0x7) << 5) -# define ADDR_SURF_TILE_SPLIT_64B 0 -# define ADDR_SURF_TILE_SPLIT_128B 1 -# define ADDR_SURF_TILE_SPLIT_256B 2 -# define ADDR_SURF_TILE_SPLIT_512B 3 -# define ADDR_SURF_TILE_SPLIT_1KB 4 -# define ADDR_SURF_TILE_SPLIT_2KB 5 -# define ADDR_SURF_TILE_SPLIT_4KB 6 -# define CB_NUM_BANKS(x) (((x) & 0x3) << 10) -# define ADDR_SURF_2_BANK 0 -# define ADDR_SURF_4_BANK 1 -# define ADDR_SURF_8_BANK 2 -# define ADDR_SURF_16_BANK 3 -# define CB_BANK_WIDTH(x) (((x) & 0x3) << 13) -# define ADDR_SURF_BANK_WIDTH_1 0 -# define ADDR_SURF_BANK_WIDTH_2 1 -# define ADDR_SURF_BANK_WIDTH_4 2 -# define ADDR_SURF_BANK_WIDTH_8 3 -# define CB_BANK_HEIGHT(x) (((x) & 0x3) << 16) -# define ADDR_SURF_BANK_HEIGHT_1 0 -# define ADDR_SURF_BANK_HEIGHT_2 1 -# define ADDR_SURF_BANK_HEIGHT_4 2 -# define ADDR_SURF_BANK_HEIGHT_8 3 #define CB_COLOR0_DIM 0x28c78 /* only CB0-7 blocks have these regs */ #define CB_COLOR0_CMASK 0x28c7c @@ -1164,11 +1137,7 @@ # define SQ_SEL_1 5 #define SQ_TEX_RESOURCE_WORD5_0 0x30014 #define SQ_TEX_RESOURCE_WORD6_0 0x30018 -# define TEX_TILE_SPLIT(x) (((x) & 0x7) << 29) #define SQ_TEX_RESOURCE_WORD7_0 0x3001c -# define TEX_BANK_WIDTH(x) (((x) & 0x3) << 8) -# define TEX_BANK_HEIGHT(x) (((x) & 0x3) << 10) -# define TEX_NUM_BANKS(x) (((x) & 0x3) << 16) #define SQ_VTX_CONSTANT_WORD0_0 0x30000 #define SQ_VTX_CONSTANT_WORD1_0 0x30004 diff --git a/trunk/drivers/gpu/drm/radeon/r100.c b/trunk/drivers/gpu/drm/radeon/r100.c index bfc08f6320f8..ad158ea49901 100644 --- a/trunk/drivers/gpu/drm/radeon/r100.c +++ b/trunk/drivers/gpu/drm/radeon/r100.c @@ -187,18 +187,13 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; - int i; /* Lock the graphics update lock */ /* update the scanout addresses */ WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); /* Wait for update_pending to go high. */ - for (i = 0; i < rdev->usec_timeout; i++) { - if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET) - break; - udelay(1); - } + while (!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)); DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); /* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/trunk/drivers/gpu/drm/radeon/radeon_acpi.c b/trunk/drivers/gpu/drm/radeon/radeon_acpi.c index 3516a6081dcf..3f6636bb2d7f 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_acpi.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_acpi.c @@ -35,8 +35,7 @@ static int radeon_atif_call(acpi_handle handle) /* Fail only if calling the method fails and ATIF is supported */ if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n", - acpi_format_exception(status)); + printk(KERN_DEBUG "failed to evaluate ATIF got %s\n", acpi_format_exception(status)); kfree(buffer.pointer); return 1; } @@ -51,13 +50,13 @@ int radeon_acpi_init(struct radeon_device *rdev) acpi_handle handle; int ret; - /* Get the device handle */ - handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev); - /* No need to proceed if we're sure that ATIF is not supported */ - if (!ASIC_IS_AVIVO(rdev) || !rdev->bios || !handle) + if (!ASIC_IS_AVIVO(rdev) || !rdev->bios) return 0; + /* Get the device handle */ + handle = DEVICE_ACPI_HANDLE(&rdev->pdev->dev); + /* Call the ATIF method */ ret = radeon_atif_call(handle); if (ret) diff --git a/trunk/drivers/gpu/drm/radeon/rs600.c b/trunk/drivers/gpu/drm/radeon/rs600.c index b1053d640423..481b99e89f65 100644 --- a/trunk/drivers/gpu/drm/radeon/rs600.c +++ b/trunk/drivers/gpu/drm/radeon/rs600.c @@ -62,7 +62,6 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); - int i; /* Lock the graphics update lock */ tmp |= AVIVO_D1GRPH_UPDATE_LOCK; @@ -75,11 +74,7 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) (u32)crtc_base); /* Wait for update_pending to go high. */ - for (i = 0; i < rdev->usec_timeout; i++) { - if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) - break; - udelay(1); - } + while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); /* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/trunk/drivers/gpu/drm/radeon/rv770.c b/trunk/drivers/gpu/drm/radeon/rv770.c index 23ae1c60ab3d..a983f410ab89 100644 --- a/trunk/drivers/gpu/drm/radeon/rv770.c +++ b/trunk/drivers/gpu/drm/radeon/rv770.c @@ -47,7 +47,6 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); - int i; /* Lock the graphics update lock */ tmp |= AVIVO_D1GRPH_UPDATE_LOCK; @@ -67,11 +66,7 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) (u32)crtc_base); /* Wait for update_pending to go high. */ - for (i = 0; i < rdev->usec_timeout; i++) { - if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) - break; - udelay(1); - } + while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); /* Unlock the lock, so double-buffering can take place inside vblank */ diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 37d40545ed77..880e285d7578 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1809,8 +1809,7 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, } rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect); - rects = kcalloc(arg->num_outputs, sizeof(struct drm_vmw_rect), - GFP_KERNEL); + rects = kzalloc(rects_size, GFP_KERNEL); if (unlikely(!rects)) { ret = -ENOMEM; goto out_unlock; @@ -1825,10 +1824,10 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, } for (i = 0; i < arg->num_outputs; ++i) { - if (rects[i].x < 0 || - rects[i].y < 0 || - rects[i].x + rects[i].w > mode_config->max_width || - rects[i].y + rects[i].h > mode_config->max_height) { + if (rects->x < 0 || + rects->y < 0 || + rects->x + rects->w > mode_config->max_width || + rects->y + rects->h > mode_config->max_height) { DRM_ERROR("Invalid GUI layout.\n"); ret = -EINVAL; goto out_free; diff --git a/trunk/drivers/hid/hid-core.c b/trunk/drivers/hid/hid-core.c index af353842f75f..848a56c0279c 100644 --- a/trunk/drivers/hid/hid-core.c +++ b/trunk/drivers/hid/hid-core.c @@ -1771,8 +1771,8 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) }, { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) }, { HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, + { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0003) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) }, { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) }, diff --git a/trunk/drivers/hid/hid-ids.h b/trunk/drivers/hid/hid-ids.h index 4a441a6f9967..06ce996b8b65 100644 --- a/trunk/drivers/hid/hid-ids.h +++ b/trunk/drivers/hid/hid-ids.h @@ -266,7 +266,7 @@ #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 #define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc -#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003 +#define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0001 #define USB_VENDOR_ID_GLAB 0x06c2 #define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 diff --git a/trunk/drivers/infiniband/hw/mlx4/mad.c b/trunk/drivers/infiniband/hw/mlx4/mad.c index 95c94d8f0254..f36da994a85a 100644 --- a/trunk/drivers/infiniband/hw/mlx4/mad.c +++ b/trunk/drivers/infiniband/hw/mlx4/mad.c @@ -109,8 +109,7 @@ int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey, err = mlx4_cmd_box(dev->dev, inmailbox->dma, outmailbox->dma, in_modifier, op_modifier, - MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, - MLX4_CMD_NATIVE); + MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C); if (!err) memcpy(response_mad, outmailbox->buf, 256); @@ -331,8 +330,7 @@ static int iboe_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, return IB_MAD_RESULT_FAILURE; err = mlx4_cmd_box(dev->dev, 0, mailbox->dma, inmod, 0, - MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C, - MLX4_CMD_WRAPPED); + MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C); if (err) err = IB_MAD_RESULT_FAILURE; else { diff --git a/trunk/drivers/infiniband/hw/mlx4/main.c b/trunk/drivers/infiniband/hw/mlx4/main.c index b8279deb614d..77f3dbc0aaa1 100644 --- a/trunk/drivers/infiniband/hw/mlx4/main.c +++ b/trunk/drivers/infiniband/hw/mlx4/main.c @@ -177,7 +177,7 @@ mlx4_ib_port_link_layer(struct ib_device *device, u8 port_num) { struct mlx4_dev *dev = to_mdev(device)->dev; - return dev->caps.port_mask[port_num] == MLX4_PORT_TYPE_IB ? + return dev->caps.port_mask & (1 << (port_num - 1)) ? IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET; } @@ -434,7 +434,7 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask, memset(mailbox->buf, 0, 256); memcpy(mailbox->buf, props->node_desc, 64); mlx4_cmd(to_mdev(ibdev)->dev, mailbox->dma, 1, 0, - MLX4_CMD_SET_NODE, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); + MLX4_CMD_SET_NODE, MLX4_CMD_TIME_CLASS_A); mlx4_free_cmd_mailbox(to_mdev(ibdev)->dev, mailbox); @@ -463,7 +463,7 @@ static int mlx4_SET_PORT(struct mlx4_ib_dev *dev, u8 port, int reset_qkey_viols, } err = mlx4_cmd(dev->dev, mailbox->dma, port, is_eth, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_B); mlx4_free_cmd_mailbox(dev->dev, mailbox); return err; @@ -899,8 +899,7 @@ static void update_gids_task(struct work_struct *work) memcpy(gids, gw->gids, sizeof gw->gids); err = mlx4_cmd(dev, mailbox->dma, MLX4_SET_PORT_GID_TABLE << 8 | gw->port, - 1, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_NATIVE); + 1, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B); if (err) printk(KERN_WARNING "set port command failed\n"); else { @@ -1075,11 +1074,6 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) printk_once(KERN_INFO "%s", mlx4_ib_version); - if (mlx4_is_mfunc(dev)) { - printk(KERN_WARNING "IB not yet supported in SRIOV\n"); - return NULL; - } - mlx4_foreach_ib_transport_port(i, dev) num_ports++; diff --git a/trunk/drivers/iommu/intel-iommu.c b/trunk/drivers/iommu/intel-iommu.c index a004c3945c67..c0c7820d4c46 100644 --- a/trunk/drivers/iommu/intel-iommu.c +++ b/trunk/drivers/iommu/intel-iommu.c @@ -3524,7 +3524,7 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev) return 0; } -int __init dmar_parse_rmrr_atsr_dev(void) +int dmar_parse_rmrr_atsr_dev(void) { struct dmar_rmrr_unit *rmrr, *rmrr_n; struct dmar_atsr_unit *atsr, *atsr_n; diff --git a/trunk/drivers/iommu/intr_remapping.c b/trunk/drivers/iommu/intr_remapping.c index 6777ca049471..07c9f189f314 100644 --- a/trunk/drivers/iommu/intr_remapping.c +++ b/trunk/drivers/iommu/intr_remapping.c @@ -773,7 +773,7 @@ int __init parse_ioapics_under_ir(void) return ir_supported; } -int __init ir_dev_scope_init(void) +int ir_dev_scope_init(void) { if (!intr_remapping_enabled) return 0; diff --git a/trunk/drivers/net/bonding/bond_main.c b/trunk/drivers/net/bonding/bond_main.c index 0c0dacba1f51..3216c514fdc8 100644 --- a/trunk/drivers/net/bonding/bond_main.c +++ b/trunk/drivers/net/bonding/bond_main.c @@ -428,34 +428,27 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, * @bond_dev: bonding net device that got called * @vid: vlan id being added */ -static int bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid) +static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid) { struct bonding *bond = netdev_priv(bond_dev); - struct slave *slave, *stop_at; + struct slave *slave; int i, res; bond_for_each_slave(bond, slave, i) { - res = vlan_vid_add(slave->dev, vid); - if (res) - goto unwind; + struct net_device *slave_dev = slave->dev; + const struct net_device_ops *slave_ops = slave_dev->netdev_ops; + + if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) && + slave_ops->ndo_vlan_rx_add_vid) { + slave_ops->ndo_vlan_rx_add_vid(slave_dev, vid); + } } res = bond_add_vlan(bond, vid); if (res) { pr_err("%s: Error: Failed to add vlan id %d\n", bond_dev->name, vid); - return res; } - - return 0; - -unwind: - /* unwind from head to the slave that failed */ - stop_at = slave; - bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) - vlan_vid_del(slave->dev, vid); - - return res; } /** @@ -463,48 +456,56 @@ static int bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid) * @bond_dev: bonding net device that got called * @vid: vlan id being removed */ -static int bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) +static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) { struct bonding *bond = netdev_priv(bond_dev); struct slave *slave; int i, res; - bond_for_each_slave(bond, slave, i) - vlan_vid_del(slave->dev, vid); + bond_for_each_slave(bond, slave, i) { + struct net_device *slave_dev = slave->dev; + const struct net_device_ops *slave_ops = slave_dev->netdev_ops; + + if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) && + slave_ops->ndo_vlan_rx_kill_vid) { + slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vid); + } + } res = bond_del_vlan(bond, vid); if (res) { pr_err("%s: Error: Failed to remove vlan id %d\n", bond_dev->name, vid); - return res; } - - return 0; } static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev) { struct vlan_entry *vlan; - int res; + const struct net_device_ops *slave_ops = slave_dev->netdev_ops; - list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { - res = vlan_vid_add(slave_dev, vlan->vlan_id); - if (res) - pr_warning("%s: Failed to add vlan id %d to device %s\n", - bond->dev->name, vlan->vlan_id, - slave_dev->name); - } + if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || + !(slave_ops->ndo_vlan_rx_add_vid)) + return; + + list_for_each_entry(vlan, &bond->vlan_list, vlan_list) + slave_ops->ndo_vlan_rx_add_vid(slave_dev, vlan->vlan_id); } static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *slave_dev) { + const struct net_device_ops *slave_ops = slave_dev->netdev_ops; struct vlan_entry *vlan; + if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || + !(slave_ops->ndo_vlan_rx_kill_vid)) + return; + list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { if (!vlan->vlan_id) continue; - vlan_vid_del(slave_dev, vlan->vlan_id); + slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vlan->vlan_id); } } diff --git a/trunk/drivers/net/caif/caif_hsi.c b/trunk/drivers/net/caif/caif_hsi.c index 0a4fc62a381d..073352517adc 100644 --- a/trunk/drivers/net/caif/caif_hsi.c +++ b/trunk/drivers/net/caif/caif_hsi.c @@ -117,6 +117,15 @@ static int cfhsi_flush_fifo(struct cfhsi *cfhsi) dev_dbg(&cfhsi->ndev->dev, "%s.\n", __func__); + + ret = cfhsi->dev->cfhsi_wake_up(cfhsi->dev); + if (ret) { + dev_warn(&cfhsi->ndev->dev, + "%s: can't wake up HSI interface: %d.\n", + __func__, ret); + return ret; + } + do { ret = cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev, &fifo_occupancy); @@ -159,6 +168,8 @@ static int cfhsi_flush_fifo(struct cfhsi *cfhsi) } } while (1); + cfhsi->dev->cfhsi_wake_down(cfhsi->dev); + return ret; } @@ -933,7 +944,7 @@ static int cfhsi_xmit(struct sk_buff *skb, struct net_device *dev) /* Create HSI frame. */ len = cfhsi_tx_frm(desc, cfhsi); - WARN_ON(!len); + BUG_ON(!len); /* Set up new transfer. */ res = cfhsi->dev->cfhsi_tx(cfhsi->tx_buf, len, cfhsi->dev); diff --git a/trunk/drivers/net/caif/caif_serial.c b/trunk/drivers/net/caif/caif_serial.c index 9341a2d6efee..23406e62c0b0 100644 --- a/trunk/drivers/net/caif/caif_serial.c +++ b/trunk/drivers/net/caif/caif_serial.c @@ -261,7 +261,7 @@ static int handle_tx(struct ser_device *ser) skb_pull(skb, tty_wr); if (skb->len == 0) { struct sk_buff *tmp = skb_dequeue(&ser->head); - WARN_ON(tmp != skb); + BUG_ON(tmp != skb); if (in_interrupt()) dev_kfree_skb_irq(skb); else @@ -305,7 +305,7 @@ static void ldisc_tx_wakeup(struct tty_struct *tty) ser = tty->disc_data; BUG_ON(ser == NULL); - WARN_ON(ser->tty != tty); + BUG_ON(ser->tty != tty); handle_tx(ser); } diff --git a/trunk/drivers/net/caif/caif_shmcore.c b/trunk/drivers/net/caif/caif_shmcore.c index 5b2041319a32..d4b26fb24ed9 100644 --- a/trunk/drivers/net/caif/caif_shmcore.c +++ b/trunk/drivers/net/caif/caif_shmcore.c @@ -238,11 +238,11 @@ int caif_shmdrv_rx_cb(u32 mbx_msg, void *priv) if ((avail_emptybuff > HIGH_WATERMARK) && (!pshm_drv->tx_empty_available)) { pshm_drv->tx_empty_available = 1; - spin_unlock_irqrestore(&pshm_drv->lock, flags); pshm_drv->cfdev.flowctrl (pshm_drv->pshm_dev->pshm_netdev, CAIF_FLOW_ON); + spin_unlock_irqrestore(&pshm_drv->lock, flags); /* Schedule the work queue. if required */ if (!work_pending(&pshm_drv->shm_tx_work)) @@ -285,7 +285,6 @@ static void shm_rx_work_func(struct work_struct *rx_work) list_entry(pshm_drv->rx_full_list.next, struct buf_list, list); list_del_init(&pbuf->list); - spin_unlock_irqrestore(&pshm_drv->lock, flags); /* Retrieve pointer to start of the packet descriptor area. */ pck_desc = (struct shm_pck_desc *) pbuf->desc_vptr; @@ -337,11 +336,7 @@ static void shm_rx_work_func(struct work_struct *rx_work) /* Get a suitable CAIF packet and copy in data. */ skb = netdev_alloc_skb(pshm_drv->pshm_dev->pshm_netdev, frm_pck_len + 1); - - if (skb == NULL) { - pr_info("OOM: Try next frame in descriptor\n"); - break; - } + BUG_ON(skb == NULL); p = skb_put(skb, frm_pck_len); memcpy(p, pbuf->desc_vptr + frm_pck_ofs, frm_pck_len); @@ -365,7 +360,6 @@ static void shm_rx_work_func(struct work_struct *rx_work) pck_desc++; } - spin_lock_irqsave(&pshm_drv->lock, flags); list_add_tail(&pbuf->list, &pshm_drv->rx_pend_list); spin_unlock_irqrestore(&pshm_drv->lock, flags); @@ -418,6 +412,7 @@ static void shm_tx_work_func(struct work_struct *tx_work) if (skb == NULL) goto send_msg; + /* Check the available no. of buffers in the empty list */ list_for_each(pos, &pshm_drv->tx_empty_list) avail_emptybuff++; @@ -426,11 +421,9 @@ static void shm_tx_work_func(struct work_struct *tx_work) pshm_drv->tx_empty_available) { /* Update blocking condition. */ pshm_drv->tx_empty_available = 0; - spin_unlock_irqrestore(&pshm_drv->lock, flags); pshm_drv->cfdev.flowctrl (pshm_drv->pshm_dev->pshm_netdev, CAIF_FLOW_OFF); - spin_lock_irqsave(&pshm_drv->lock, flags); } /* * We simply return back to the caller if we do not have space @@ -476,8 +469,6 @@ static void shm_tx_work_func(struct work_struct *tx_work) } skb = skb_dequeue(&pshm_drv->sk_qhead); - if (skb == NULL) - break; /* Copy in CAIF frame. */ skb_copy_bits(skb, 0, pbuf->desc_vptr + pbuf->frm_ofs + SHM_HDR_LEN + @@ -486,7 +477,7 @@ static void shm_tx_work_func(struct work_struct *tx_work) pshm_drv->pshm_dev->pshm_netdev->stats.tx_packets++; pshm_drv->pshm_dev->pshm_netdev->stats.tx_bytes += frmlen; - dev_kfree_skb_irq(skb); + dev_kfree_skb(skb); /* Fill in the shared memory packet descriptor area. */ pck_desc = (struct shm_pck_desc *) (pbuf->desc_vptr); @@ -521,11 +512,16 @@ static void shm_tx_work_func(struct work_struct *tx_work) static int shm_netdev_tx(struct sk_buff *skb, struct net_device *shm_netdev) { struct shmdrv_layer *pshm_drv; + unsigned long flags = 0; pshm_drv = netdev_priv(shm_netdev); + spin_lock_irqsave(&pshm_drv->lock, flags); + skb_queue_tail(&pshm_drv->sk_qhead, skb); + spin_unlock_irqrestore(&pshm_drv->lock, flags); + /* Schedule Tx work queue. for deferred processing of skbs*/ if (!work_pending(&pshm_drv->shm_tx_work)) queue_work(pshm_drv->pshm_tx_workqueue, &pshm_drv->shm_tx_work); @@ -610,7 +606,6 @@ int caif_shmcore_probe(struct shmdev_layer *pshm_dev) pshm_drv->shm_rx_addr = pshm_dev->shm_base_addr + (NR_TX_BUF * TX_BUF_SZ); - spin_lock_init(&pshm_drv->lock); INIT_LIST_HEAD(&pshm_drv->tx_empty_list); INIT_LIST_HEAD(&pshm_drv->tx_pend_list); INIT_LIST_HEAD(&pshm_drv->tx_full_list); @@ -645,7 +640,7 @@ int caif_shmcore_probe(struct shmdev_layer *pshm_dev) tx_buf->frm_ofs = SHM_CAIF_FRM_OFS; if (pshm_dev->shm_loopback) - tx_buf->desc_vptr = (unsigned char *)tx_buf->phy_addr; + tx_buf->desc_vptr = (char *)tx_buf->phy_addr; else tx_buf->desc_vptr = ioremap(tx_buf->phy_addr, TX_BUF_SZ); @@ -669,7 +664,7 @@ int caif_shmcore_probe(struct shmdev_layer *pshm_dev) rx_buf->len = RX_BUF_SZ; if (pshm_dev->shm_loopback) - rx_buf->desc_vptr = (unsigned char *)rx_buf->phy_addr; + rx_buf->desc_vptr = (char *)rx_buf->phy_addr; else rx_buf->desc_vptr = ioremap(rx_buf->phy_addr, RX_BUF_SZ); diff --git a/trunk/drivers/net/caif/caif_spi.c b/trunk/drivers/net/caif/caif_spi.c index 761057b6f267..05e791f46aef 100644 --- a/trunk/drivers/net/caif/caif_spi.c +++ b/trunk/drivers/net/caif/caif_spi.c @@ -226,7 +226,7 @@ static ssize_t dbgfs_frame(struct file *file, char __user *user_buf, "Tx data (Len: %d):\n", cfspi->tx_cpck_len); len += print_frame((buf + len), (DEBUGFS_BUF_SIZE - len), - cfspi->xfer.va_tx[0], + cfspi->xfer.va_tx, (cfspi->tx_cpck_len + SPI_CMD_SZ), 100); len += snprintf((buf + len), (DEBUGFS_BUF_SIZE - len), @@ -599,11 +599,48 @@ static int cfspi_close(struct net_device *dev) netif_stop_queue(dev); return 0; } +static const struct net_device_ops cfspi_ops = { + .ndo_open = cfspi_open, + .ndo_stop = cfspi_close, + .ndo_start_xmit = cfspi_xmit +}; -static int cfspi_init(struct net_device *dev) +static void cfspi_setup(struct net_device *dev) { - int res = 0; struct cfspi *cfspi = netdev_priv(dev); + dev->features = 0; + dev->netdev_ops = &cfspi_ops; + dev->type = ARPHRD_CAIF; + dev->flags = IFF_NOARP | IFF_POINTOPOINT; + dev->tx_queue_len = 0; + dev->mtu = SPI_MAX_PAYLOAD_SIZE; + dev->destructor = free_netdev; + skb_queue_head_init(&cfspi->qhead); + skb_queue_head_init(&cfspi->chead); + cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW; + cfspi->cfdev.use_frag = false; + cfspi->cfdev.use_stx = false; + cfspi->cfdev.use_fcs = false; + cfspi->ndev = dev; +} + +int cfspi_spi_probe(struct platform_device *pdev) +{ + struct cfspi *cfspi = NULL; + struct net_device *ndev; + struct cfspi_dev *dev; + int res; + dev = (struct cfspi_dev *)pdev->dev.platform_data; + + ndev = alloc_netdev(sizeof(struct cfspi), + "cfspi%d", cfspi_setup); + if (!ndev) + return -ENOMEM; + + cfspi = netdev_priv(ndev); + netif_stop_queue(ndev); + cfspi->ndev = ndev; + cfspi->pdev = pdev; /* Set flow info. */ cfspi->flow_off_sent = 0; @@ -619,11 +656,16 @@ static int cfspi_init(struct net_device *dev) cfspi->slave_talked = false; } + /* Assign the SPI device. */ + cfspi->dev = dev; + /* Assign the device ifc to this SPI interface. */ + dev->ifc = &cfspi->ifc; + /* Allocate DMA buffers. */ - cfspi->xfer.va_tx[0] = dma_alloc(&cfspi->xfer.pa_tx[0]); - if (!cfspi->xfer.va_tx[0]) { + cfspi->xfer.va_tx = dma_alloc(&cfspi->xfer.pa_tx); + if (!cfspi->xfer.va_tx) { res = -ENODEV; - goto err_dma_alloc_tx_0; + goto err_dma_alloc_tx; } cfspi->xfer.va_rx = dma_alloc(&cfspi->xfer.pa_rx); @@ -672,87 +714,6 @@ static int cfspi_init(struct net_device *dev) /* Schedule the work queue. */ queue_work(cfspi->wq, &cfspi->work); - return 0; - - err_create_wq: - dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx); - err_dma_alloc_rx: - dma_free(cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]); - err_dma_alloc_tx_0: - return res; -} - -static void cfspi_uninit(struct net_device *dev) -{ - struct cfspi *cfspi = netdev_priv(dev); - - /* Remove from list. */ - spin_lock(&cfspi_list_lock); - list_del(&cfspi->list); - spin_unlock(&cfspi_list_lock); - - cfspi->ndev = NULL; - /* Free DMA buffers. */ - dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx); - dma_free(cfspi->xfer.va_tx[0], cfspi->xfer.pa_tx[0]); - set_bit(SPI_TERMINATE, &cfspi->state); - wake_up_interruptible(&cfspi->wait); - destroy_workqueue(cfspi->wq); - /* Destroy debugfs directory and files. */ - dev_debugfs_rem(cfspi); - return; -} - -static const struct net_device_ops cfspi_ops = { - .ndo_open = cfspi_open, - .ndo_stop = cfspi_close, - .ndo_init = cfspi_init, - .ndo_uninit = cfspi_uninit, - .ndo_start_xmit = cfspi_xmit -}; - -static void cfspi_setup(struct net_device *dev) -{ - struct cfspi *cfspi = netdev_priv(dev); - dev->features = 0; - dev->netdev_ops = &cfspi_ops; - dev->type = ARPHRD_CAIF; - dev->flags = IFF_NOARP | IFF_POINTOPOINT; - dev->tx_queue_len = 0; - dev->mtu = SPI_MAX_PAYLOAD_SIZE; - dev->destructor = free_netdev; - skb_queue_head_init(&cfspi->qhead); - skb_queue_head_init(&cfspi->chead); - cfspi->cfdev.link_select = CAIF_LINK_HIGH_BANDW; - cfspi->cfdev.use_frag = false; - cfspi->cfdev.use_stx = false; - cfspi->cfdev.use_fcs = false; - cfspi->ndev = dev; -} - -int cfspi_spi_probe(struct platform_device *pdev) -{ - struct cfspi *cfspi = NULL; - struct net_device *ndev; - struct cfspi_dev *dev; - int res; - dev = (struct cfspi_dev *)pdev->dev.platform_data; - - ndev = alloc_netdev(sizeof(struct cfspi), - "cfspi%d", cfspi_setup); - if (!dev) - return -ENODEV; - - cfspi = netdev_priv(ndev); - netif_stop_queue(ndev); - cfspi->ndev = ndev; - cfspi->pdev = pdev; - - /* Assign the SPI device. */ - cfspi->dev = dev; - /* Assign the device ifc to this SPI interface. */ - dev->ifc = &cfspi->ifc; - /* Register network device. */ res = register_netdev(ndev); if (res) { @@ -762,6 +723,15 @@ int cfspi_spi_probe(struct platform_device *pdev) return res; err_net_reg: + dev_debugfs_rem(cfspi); + set_bit(SPI_TERMINATE, &cfspi->state); + wake_up_interruptible(&cfspi->wait); + destroy_workqueue(cfspi->wq); + err_create_wq: + dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx); + err_dma_alloc_rx: + dma_free(cfspi->xfer.va_tx, cfspi->xfer.pa_tx); + err_dma_alloc_tx: free_netdev(ndev); return res; @@ -769,8 +739,34 @@ int cfspi_spi_probe(struct platform_device *pdev) int cfspi_spi_remove(struct platform_device *pdev) { - /* Everything is done in cfspi_uninit(). */ - return 0; + struct list_head *list_node; + struct list_head *n; + struct cfspi *cfspi = NULL; + struct cfspi_dev *dev; + + dev = (struct cfspi_dev *)pdev->dev.platform_data; + spin_lock(&cfspi_list_lock); + list_for_each_safe(list_node, n, &cfspi_list) { + cfspi = list_entry(list_node, struct cfspi, list); + /* Find the corresponding device. */ + if (cfspi->dev == dev) { + /* Remove from list. */ + list_del(list_node); + /* Free DMA buffers. */ + dma_free(cfspi->xfer.va_rx, cfspi->xfer.pa_rx); + dma_free(cfspi->xfer.va_tx, cfspi->xfer.pa_tx); + set_bit(SPI_TERMINATE, &cfspi->state); + wake_up_interruptible(&cfspi->wait); + destroy_workqueue(cfspi->wq); + /* Destroy debugfs directory and files. */ + dev_debugfs_rem(cfspi); + unregister_netdev(cfspi->ndev); + spin_unlock(&cfspi_list_lock); + return 0; + } + } + spin_unlock(&cfspi_list_lock); + return -ENODEV; } static void __exit cfspi_exit_module(void) @@ -781,7 +777,7 @@ static void __exit cfspi_exit_module(void) list_for_each_safe(list_node, n, &cfspi_list) { cfspi = list_entry(list_node, struct cfspi, list); - unregister_netdev(cfspi->ndev); + platform_device_unregister(cfspi->pdev); } /* Destroy sysfs files. */ diff --git a/trunk/drivers/net/ethernet/adaptec/starfire.c b/trunk/drivers/net/ethernet/adaptec/starfire.c index cb4f38a17f20..a446e251908b 100644 --- a/trunk/drivers/net/ethernet/adaptec/starfire.c +++ b/trunk/drivers/net/ethernet/adaptec/starfire.c @@ -607,7 +607,7 @@ static const struct ethtool_ops ethtool_ops; #ifdef VLAN_SUPPORT -static int netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) +static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { struct netdev_private *np = netdev_priv(dev); @@ -617,11 +617,9 @@ static int netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) set_bit(vid, np->active_vlans); set_rx_mode(dev); spin_unlock(&np->lock); - - return 0; } -static int netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct netdev_private *np = netdev_priv(dev); @@ -631,8 +629,6 @@ static int netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) clear_bit(vid, np->active_vlans); set_rx_mode(dev); spin_unlock(&np->lock); - - return 0; } #endif /* VLAN_SUPPORT */ diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 8c73d34b2ff1..6c7bd638d6ed 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -887,8 +887,6 @@ struct bnx2x_common { #define CHIP_PORT_MODE_NONE 0x2 #define CHIP_MODE(bp) (bp->common.chip_port_mode) #define CHIP_MODE_IS_4_PORT(bp) (CHIP_MODE(bp) == CHIP_4_PORT_MODE) - - u32 boot_mode; }; /* IGU MSIX STATISTICS on 57712: 64 for VFs; 4 for PFs; 4 for Attentions */ @@ -1050,8 +1048,6 @@ struct bnx2x_slowpath { u32 wb_comp; u32 wb_data[4]; - - union drv_info_to_mcp drv_info_to_mcp; }; #define bnx2x_sp(bp, var) (&bp->slowpath->var) @@ -1132,21 +1128,18 @@ enum { enum { BNX2X_PORT_QUERY_IDX, BNX2X_PF_QUERY_IDX, - BNX2X_FCOE_QUERY_IDX, BNX2X_FIRST_QUEUE_QUERY_IDX, }; struct bnx2x_fw_stats_req { struct stats_query_header hdr; - struct stats_query_entry query[FP_SB_MAX_E1x+ - BNX2X_FIRST_QUEUE_QUERY_IDX]; + struct stats_query_entry query[STATS_QUERY_CMD_COUNT]; }; struct bnx2x_fw_stats_data { struct stats_counter storm_counters; struct per_port_stats port; struct per_pf_stats pf; - struct fcoe_statistics_params fcoe; struct per_queue_stats queue_stats[1]; }; @@ -1273,7 +1266,6 @@ struct bnx2x { #define NO_ISCSI_OOO_FLAG (1 << 13) #define NO_ISCSI_FLAG (1 << 14) #define NO_FCOE_FLAG (1 << 15) -#define BC_SUPPORTS_PFC_STATS (1 << 17) #define NO_ISCSI(bp) ((bp)->flags & NO_ISCSI_FLAG) #define NO_ISCSI_OOO(bp) ((bp)->flags & NO_ISCSI_OOO_FLAG) diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 2b731b253598..477bc9713a66 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -731,22 +731,22 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) bnx2x_reuse_rx_data(fp, bd_cons, bd_prod); goto next_rx; } - } - skb_put(skb, len); - skb->protocol = eth_type_trans(skb, bp->dev); + skb_put(skb, len); + skb->protocol = eth_type_trans(skb, bp->dev); - /* Set Toeplitz hash for a none-LRO skb */ - skb->rxhash = bnx2x_get_rxhash(bp, cqe_fp); + /* Set Toeplitz hash for a none-LRO skb */ + skb->rxhash = bnx2x_get_rxhash(bp, cqe_fp); - skb_checksum_none_assert(skb); + skb_checksum_none_assert(skb); - if (bp->dev->features & NETIF_F_RXCSUM) { + if (bp->dev->features & NETIF_F_RXCSUM) { - if (likely(BNX2X_RX_CSUM_OK(cqe))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - fp->eth_q_stats.hw_csum_err++; + if (likely(BNX2X_RX_CSUM_OK(cqe))) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + fp->eth_q_stats.hw_csum_err++; + } } skb_record_rx_queue(skb, fp->rx_queue); @@ -1545,8 +1545,7 @@ static inline int bnx2x_init_rss_pf(struct bnx2x *bp) if (bp->multi_mode != ETH_RSS_MODE_DISABLED) { for (i = 0; i < sizeof(ind_table); i++) ind_table[i] = - bp->fp->cl_id + - ethtool_rxfh_indir_default(i, num_eth_queues); + bp->fp->cl_id + (i % num_eth_queues); } /* diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index bf27c54ff2e0..2891cdcabdc8 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h @@ -1491,6 +1491,7 @@ static inline u16 bnx2x_extract_max_cfg(struct bnx2x *bp, u32 mf_cfg) return max_cfg; } +#ifdef BCM_CNIC /** * bnx2x_get_iscsi_info - update iSCSI params according to licensing info. * @@ -1498,6 +1499,7 @@ static inline u16 bnx2x_extract_max_cfg(struct bnx2x *bp, u32 mf_cfg) * */ void bnx2x_get_iscsi_info(struct bnx2x *bp); +#endif /* returns func by VN for current port */ static inline int func_by_vn(struct bnx2x *bp, int vn) diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index a688b9d975a2..c679ed9d3035 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -107,10 +107,6 @@ static const struct { 4, STATS_FLAGS_PORT, "rx_filtered_packets" }, { STATS_OFFSET32(mf_tag_discard), 4, STATS_FLAGS_PORT, "rx_mf_tag_discard" }, - { STATS_OFFSET32(pfc_frames_received_hi), - 8, STATS_FLAGS_PORT, "pfc_frames_received" }, - { STATS_OFFSET32(pfc_frames_sent_hi), - 8, STATS_FLAGS_PORT, "pfc_frames_sent" }, { STATS_OFFSET32(brb_drop_hi), 8, STATS_FLAGS_PORT, "rx_brb_discard" }, { STATS_OFFSET32(brb_truncate_hi), @@ -1745,7 +1741,6 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) u16 len; int rc = -ENODEV; u8 *data; - struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txdata->txq_index); /* check the loopback mode */ switch (loopback_mode) { @@ -1800,8 +1795,6 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) tx_start_idx = le16_to_cpu(*txdata->tx_cons_sb); rx_start_idx = le16_to_cpu(*fp_rx->rx_cons_sb); - netdev_tx_sent_queue(txq, skb->len); - pkt_prod = txdata->tx_pkt_prod++; tx_buf = &txdata->tx_buf_ring[TX_BD(pkt_prod)]; tx_buf->first_bd = txdata->tx_bd_prod; @@ -2302,20 +2295,18 @@ static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, } } -static u32 bnx2x_get_rxfh_indir_size(struct net_device *dev) -{ - struct bnx2x *bp = netdev_priv(dev); - - return (bp->multi_mode == ETH_RSS_MODE_DISABLED ? - 0 : T_ETH_INDIRECTION_TABLE_SIZE); -} - -static int bnx2x_get_rxfh_indir(struct net_device *dev, u32 *indir) +static int bnx2x_get_rxfh_indir(struct net_device *dev, + struct ethtool_rxfh_indir *indir) { struct bnx2x *bp = netdev_priv(dev); + size_t copy_size = + min_t(size_t, indir->size, T_ETH_INDIRECTION_TABLE_SIZE); u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0}; size_t i; + if (bp->multi_mode == ETH_RSS_MODE_DISABLED) + return -EOPNOTSUPP; + /* Get the current configuration of the RSS indirection table */ bnx2x_get_rss_ind_table(&bp->rss_conf_obj, ind_table); @@ -2328,19 +2319,33 @@ static int bnx2x_get_rxfh_indir(struct net_device *dev, u32 *indir) * align the returned table to the Client ID of the leading RSS * queue. */ - for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) - indir[i] = ind_table[i] - bp->fp->cl_id; + for (i = 0; i < copy_size; i++) + indir->ring_index[i] = ind_table[i] - bp->fp->cl_id; + + indir->size = T_ETH_INDIRECTION_TABLE_SIZE; return 0; } -static int bnx2x_set_rxfh_indir(struct net_device *dev, const u32 *indir) +static int bnx2x_set_rxfh_indir(struct net_device *dev, + const struct ethtool_rxfh_indir *indir) { struct bnx2x *bp = netdev_priv(dev); size_t i; u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0}; + u32 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp); + + if (bp->multi_mode == ETH_RSS_MODE_DISABLED) + return -EOPNOTSUPP; + + /* validate the size */ + if (indir->size != T_ETH_INDIRECTION_TABLE_SIZE) + return -EINVAL; for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) { + /* validate the indices */ + if (indir->ring_index[i] >= num_eth_queues) + return -EINVAL; /* * The same as in bnx2x_get_rxfh_indir: we can't use a memcpy() * as an internal storage of an indirection table is a u8 array @@ -2350,7 +2355,7 @@ static int bnx2x_set_rxfh_indir(struct net_device *dev, const u32 *indir) * align the received table to the Client ID of the leading RSS * queue */ - ind_table[i] = indir[i] + bp->fp->cl_id; + ind_table[i] = indir->ring_index[i] + bp->fp->cl_id; } return bnx2x_config_rss_pf(bp, ind_table, false); @@ -2383,7 +2388,6 @@ static const struct ethtool_ops bnx2x_ethtool_ops = { .set_phys_id = bnx2x_set_phys_id, .get_ethtool_stats = bnx2x_get_ethtool_stats, .get_rxnfc = bnx2x_get_rxnfc, - .get_rxfh_indir_size = bnx2x_get_rxfh_indir_size, .get_rxfh_indir = bnx2x_get_rxfh_indir, .set_rxfh_indir = bnx2x_set_rxfh_indir, }; diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h index 3e30c8642c26..fc754cb6cc0f 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h @@ -1247,14 +1247,11 @@ struct drv_func_mb { #define DRV_MSG_CODE_VRFY_SPECIFIC_PHY_OPT_MDL 0xa1000000 #define REQ_BC_VER_4_VRFY_SPECIFIC_PHY_OPT_MDL 0x00050234 #define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED 0x00070014 - #define REQ_BC_VER_4_PFC_STATS_SUPPORTED 0x00070201 #define DRV_MSG_CODE_DCBX_ADMIN_PMF_MSG 0xb0000000 #define DRV_MSG_CODE_DCBX_PMF_DRV_OK 0xb2000000 #define DRV_MSG_CODE_VF_DISABLED_DONE 0xc0000000 - #define DRV_MSG_CODE_DRV_INFO_ACK 0xd8000000 - #define DRV_MSG_CODE_DRV_INFO_NACK 0xd9000000 #define DRV_MSG_CODE_SET_MF_BW 0xe0000000 #define REQ_BC_VER_4_SET_MF_BW 0x00060202 @@ -1307,8 +1304,6 @@ struct drv_func_mb { #define FW_MSG_CODE_VRFY_OPT_MDL_INVLD_IMG 0xa0200000 #define FW_MSG_CODE_VRFY_OPT_MDL_UNAPPROVED 0xa0300000 #define FW_MSG_CODE_VF_DISABLED_DONE 0xb0000000 - #define FW_MSG_CODE_DRV_INFO_ACK 0xd8100000 - #define FW_MSG_CODE_DRV_INFO_NACK 0xd9100000 #define FW_MSG_CODE_SET_MF_BW_SENT 0xe0000000 #define FW_MSG_CODE_SET_MF_BW_DONE 0xe1000000 @@ -1365,7 +1360,6 @@ struct drv_func_mb { #define DRV_STATUS_DCBX_EVENT_MASK 0x000f0000 #define DRV_STATUS_DCBX_NEGOTIATION_RESULTS 0x00010000 - #define DRV_STATUS_DRV_INFO_REQ 0x04000000 u32 virt_mac_upper; #define VIRT_MAC_SIGN_MASK 0xffff0000 @@ -1970,38 +1964,9 @@ struct shmem2_region { u32 extended_dev_info_shared_addr; u32 ncsi_oem_data_addr; - u32 ocsd_host_addr; /* initialized by option ROM */ - u32 ocbb_host_addr; /* initialized by option ROM */ - u32 ocsd_req_update_interval; /* initialized by option ROM */ - u32 temperature_in_half_celsius; - u32 glob_struct_in_host; - - u32 dcbx_neg_res_ext_offset; -#define SHMEM_DCBX_NEG_RES_EXT_NONE 0x00000000 - - u32 drv_capabilities_flag[E2_FUNC_MAX]; -#define DRV_FLAGS_CAPABILITIES_LOADED_SUPPORTED 0x00000001 -#define DRV_FLAGS_CAPABILITIES_LOADED_L2 0x00000002 -#define DRV_FLAGS_CAPABILITIES_LOADED_FCOE 0x00000004 -#define DRV_FLAGS_CAPABILITIES_LOADED_ISCSI 0x00000008 - - u32 extended_dev_info_shared_cfg_size; - - u32 dcbx_en[PORT_MAX]; - - /* The offset points to the multi threaded meta structure */ - u32 multi_thread_data_offset; - - /* address of DMAable host address holding values from the drivers */ - u32 drv_info_host_addr_lo; - u32 drv_info_host_addr_hi; - - /* general values written by the MFW (such as current version) */ - u32 drv_info_control; -#define DRV_INFO_CONTROL_VER_MASK 0x000000ff -#define DRV_INFO_CONTROL_VER_SHIFT 0 -#define DRV_INFO_CONTROL_OP_CODE_MASK 0x0000ff00 -#define DRV_INFO_CONTROL_OP_CODE_SHIFT 8 + u32 ocsd_host_addr; + u32 ocbb_host_addr; + u32 ocsd_req_update_interval; }; @@ -2536,18 +2501,14 @@ struct mac_stx { #define MAC_STX_IDX_MAX 2 struct host_port_stats { - u32 host_port_stats_counter; + u32 host_port_stats_start; struct mac_stx mac_stx[MAC_STX_IDX_MAX]; u32 brb_drop_hi; u32 brb_drop_lo; - u32 not_used; /* obsolete */ - u32 pfc_frames_tx_hi; - u32 pfc_frames_tx_lo; - u32 pfc_frames_rx_hi; - u32 pfc_frames_rx_lo; + u32 host_port_stats_end; }; @@ -2587,118 +2548,6 @@ struct host_func_stats { /* VIC definitions */ #define VICSTATST_UIF_INDEX 2 -/* current drv_info version */ -#define DRV_INFO_CUR_VER 1 - -/* drv_info op codes supported */ -enum drv_info_opcode { - ETH_STATS_OPCODE, - FCOE_STATS_OPCODE, - ISCSI_STATS_OPCODE -}; - -#define ETH_STAT_INFO_VERSION_LEN 12 -/* Per PCI Function Ethernet Statistics required from the driver */ -struct eth_stats_info { - /* Function's Driver Version. padded to 12 */ - u8 version[ETH_STAT_INFO_VERSION_LEN]; - /* Locally Admin Addr. BigEndian EIU48. Actual size is 6 bytes */ - u8 mac_local[8]; - u8 mac_add1[8]; /* Additional Programmed MAC Addr 1. */ - u8 mac_add2[8]; /* Additional Programmed MAC Addr 2. */ - u32 mtu_size; /* MTU Size. Note : Negotiated MTU */ - u32 feature_flags; /* Feature_Flags. */ -#define FEATURE_ETH_CHKSUM_OFFLOAD_MASK 0x01 -#define FEATURE_ETH_LSO_MASK 0x02 -#define FEATURE_ETH_BOOTMODE_MASK 0x1C -#define FEATURE_ETH_BOOTMODE_SHIFT 2 -#define FEATURE_ETH_BOOTMODE_NONE (0x0 << 2) -#define FEATURE_ETH_BOOTMODE_PXE (0x1 << 2) -#define FEATURE_ETH_BOOTMODE_ISCSI (0x2 << 2) -#define FEATURE_ETH_BOOTMODE_FCOE (0x3 << 2) -#define FEATURE_ETH_TOE_MASK 0x20 - u32 lso_max_size; /* LSO MaxOffloadSize. */ - u32 lso_min_seg_cnt; /* LSO MinSegmentCount. */ - /* Num Offloaded Connections TCP_IPv4. */ - u32 ipv4_ofld_cnt; - /* Num Offloaded Connections TCP_IPv6. */ - u32 ipv6_ofld_cnt; - u32 promiscuous_mode; /* Promiscuous Mode. non-zero true */ - u32 txq_size; /* TX Descriptors Queue Size */ - u32 rxq_size; /* RX Descriptors Queue Size */ - /* TX Descriptor Queue Avg Depth. % Avg Queue Depth since last poll */ - u32 txq_avg_depth; - /* RX Descriptors Queue Avg Depth. % Avg Queue Depth since last poll */ - u32 rxq_avg_depth; - /* IOV_Offload. 0=none; 1=MultiQueue, 2=VEB 3= VEPA*/ - u32 iov_offload; - /* Number of NetQueue/VMQ Config'd. */ - u32 netq_cnt; - u32 vf_cnt; /* Num VF assigned to this PF. */ -}; - -/* Per PCI Function FCOE Statistics required from the driver */ -struct fcoe_stats_info { - u8 version[12]; /* Function's Driver Version. */ - u8 mac_local[8]; /* Locally Admin Addr. */ - u8 mac_add1[8]; /* Additional Programmed MAC Addr 1. */ - u8 mac_add2[8]; /* Additional Programmed MAC Addr 2. */ - /* QoS Priority (per 802.1p). 0-7255 */ - u32 qos_priority; - u32 txq_size; /* FCoE TX Descriptors Queue Size. */ - u32 rxq_size; /* FCoE RX Descriptors Queue Size. */ - /* FCoE TX Descriptor Queue Avg Depth. */ - u32 txq_avg_depth; - /* FCoE RX Descriptors Queue Avg Depth. */ - u32 rxq_avg_depth; - u32 rx_frames_lo; /* FCoE RX Frames received. */ - u32 rx_frames_hi; /* FCoE RX Frames received. */ - u32 rx_bytes_lo; /* FCoE RX Bytes received. */ - u32 rx_bytes_hi; /* FCoE RX Bytes received. */ - u32 tx_frames_lo; /* FCoE TX Frames sent. */ - u32 tx_frames_hi; /* FCoE TX Frames sent. */ - u32 tx_bytes_lo; /* FCoE TX Bytes sent. */ - u32 tx_bytes_hi; /* FCoE TX Bytes sent. */ -}; - -/* Per PCI Function iSCSI Statistics required from the driver*/ -struct iscsi_stats_info { - u8 version[12]; /* Function's Driver Version. */ - u8 mac_local[8]; /* Locally Admin iSCSI MAC Addr. */ - u8 mac_add1[8]; /* Additional Programmed MAC Addr 1. */ - /* QoS Priority (per 802.1p). 0-7255 */ - u32 qos_priority; - u8 initiator_name[64]; /* iSCSI Boot Initiator Node name. */ - u8 ww_port_name[64]; /* iSCSI World wide port name */ - u8 boot_target_name[64];/* iSCSI Boot Target Name. */ - u8 boot_target_ip[16]; /* iSCSI Boot Target IP. */ - u32 boot_target_portal; /* iSCSI Boot Target Portal. */ - u8 boot_init_ip[16]; /* iSCSI Boot Initiator IP Address. */ - u32 max_frame_size; /* Max Frame Size. bytes */ - u32 txq_size; /* PDU TX Descriptors Queue Size. */ - u32 rxq_size; /* PDU RX Descriptors Queue Size. */ - u32 txq_avg_depth; /* PDU TX Descriptor Queue Avg Depth. */ - u32 rxq_avg_depth; /* PDU RX Descriptors Queue Avg Depth. */ - u32 rx_pdus_lo; /* iSCSI PDUs received. */ - u32 rx_pdus_hi; /* iSCSI PDUs received. */ - u32 rx_bytes_lo; /* iSCSI RX Bytes received. */ - u32 rx_bytes_hi; /* iSCSI RX Bytes received. */ - u32 tx_pdus_lo; /* iSCSI PDUs sent. */ - u32 tx_pdus_hi; /* iSCSI PDUs sent. */ - u32 tx_bytes_lo; /* iSCSI PDU TX Bytes sent. */ - u32 tx_bytes_hi; /* iSCSI PDU TX Bytes sent. */ - u32 pcp_prior_map_tbl; /* C-PCP to S-PCP Priority MapTable. - * 9 nibbles, the position of each nibble - * represents the C-PCP value, the value - * of the nibble = S-PCP value. - */ -}; - -union drv_info_to_mcp { - struct eth_stats_info ether_stat; - struct fcoe_stats_info fcoe_stat; - struct iscsi_stats_info iscsi_stat; -}; #define BCM_5710_FW_MAJOR_VERSION 7 #define BCM_5710_FW_MINOR_VERSION 0 #define BCM_5710_FW_REVISION_VERSION 29 @@ -4311,63 +4160,9 @@ struct ustorm_eth_rx_producers { }; -/* - * FCoE RX statistics parameters section#0 - */ -struct fcoe_rx_stat_params_section0 { - __le32 fcoe_rx_pkt_cnt; - __le32 fcoe_rx_byte_cnt; -}; - - -/* - * FCoE RX statistics parameters section#1 - */ -struct fcoe_rx_stat_params_section1 { - __le32 fcoe_ver_cnt; - __le32 fcoe_rx_drop_pkt_cnt; -}; - - -/* - * FCoE RX statistics parameters section#2 - */ -struct fcoe_rx_stat_params_section2 { - __le32 fc_crc_cnt; - __le32 eofa_del_cnt; - __le32 miss_frame_cnt; - __le32 seq_timeout_cnt; - __le32 drop_seq_cnt; - __le32 fcoe_rx_drop_pkt_cnt; - __le32 fcp_rx_pkt_cnt; - __le32 reserved0; -}; - - -/* - * FCoE TX statistics parameters - */ -struct fcoe_tx_stat_params { - __le32 fcoe_tx_pkt_cnt; - __le32 fcoe_tx_byte_cnt; - __le32 fcp_tx_pkt_cnt; - __le32 reserved0; -}; - -/* - * FCoE statistics parameters - */ -struct fcoe_statistics_params { - struct fcoe_tx_stat_params tx_stat; - struct fcoe_rx_stat_params_section0 rx_stat0; - struct fcoe_rx_stat_params_section1 rx_stat1; - struct fcoe_rx_stat_params_section2 rx_stat2; -}; - - /* * cfc delete event data -*/ + */ struct cfc_del_event_data { u32 cid; u32 reserved0; diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index ffeaaa95ed96..2213e0be5e63 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -2624,6 +2624,15 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param) return rc; } +static u8 stat_counter_valid(struct bnx2x *bp, struct bnx2x_fastpath *fp) +{ +#ifdef BCM_CNIC + /* Statistics are not supported for CNIC Clients at the moment */ + if (IS_FCOE_FP(fp)) + return false; +#endif + return true; +} void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p) { @@ -2667,11 +2676,11 @@ static inline unsigned long bnx2x_get_common_flags(struct bnx2x *bp, * parent connection). The statistics are zeroed when the parent * connection is initialized. */ - - __set_bit(BNX2X_Q_FLG_STATS, &flags); - if (zero_stats) - __set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags); - + if (stat_counter_valid(bp, fp)) { + __set_bit(BNX2X_Q_FLG_STATS, &flags); + if (zero_stats) + __set_bit(BNX2X_Q_FLG_ZERO_STATS, &flags); + } return flags; } @@ -2912,143 +2921,6 @@ static void bnx2x_e1h_enable(struct bnx2x *bp) */ } -#define DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED 3 - -static void bnx2x_drv_info_ether_stat(struct bnx2x *bp) -{ - struct eth_stats_info *ether_stat = - &bp->slowpath->drv_info_to_mcp.ether_stat; - - /* leave last char as NULL */ - memcpy(ether_stat->version, DRV_MODULE_VERSION, - ETH_STAT_INFO_VERSION_LEN - 1); - - bp->fp[0].mac_obj.get_n_elements(bp, &bp->fp[0].mac_obj, - DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED, - ether_stat->mac_local); - - ether_stat->mtu_size = bp->dev->mtu; - - if (bp->dev->features & NETIF_F_RXCSUM) - ether_stat->feature_flags |= FEATURE_ETH_CHKSUM_OFFLOAD_MASK; - if (bp->dev->features & NETIF_F_TSO) - ether_stat->feature_flags |= FEATURE_ETH_LSO_MASK; - ether_stat->feature_flags |= bp->common.boot_mode; - - ether_stat->promiscuous_mode = (bp->dev->flags & IFF_PROMISC) ? 1 : 0; - - ether_stat->txq_size = bp->tx_ring_size; - ether_stat->rxq_size = bp->rx_ring_size; -} - -static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp) -{ -#ifdef BCM_CNIC - struct bnx2x_dcbx_app_params *app = &bp->dcbx_port_params.app; - struct fcoe_stats_info *fcoe_stat = - &bp->slowpath->drv_info_to_mcp.fcoe_stat; - - memcpy(fcoe_stat->mac_local, bp->fip_mac, ETH_ALEN); - - fcoe_stat->qos_priority = - app->traffic_type_priority[LLFC_TRAFFIC_TYPE_FCOE]; - - /* insert FCoE stats from ramrod response */ - if (!NO_FCOE(bp)) { - struct tstorm_per_queue_stats *fcoe_q_tstorm_stats = - &bp->fw_stats_data->queue_stats[FCOE_IDX]. - tstorm_queue_statistics; - - struct xstorm_per_queue_stats *fcoe_q_xstorm_stats = - &bp->fw_stats_data->queue_stats[FCOE_IDX]. - xstorm_queue_statistics; - - struct fcoe_statistics_params *fw_fcoe_stat = - &bp->fw_stats_data->fcoe; - - ADD_64(fcoe_stat->rx_bytes_hi, 0, fcoe_stat->rx_bytes_lo, - fw_fcoe_stat->rx_stat0.fcoe_rx_byte_cnt); - - ADD_64(fcoe_stat->rx_bytes_hi, - fcoe_q_tstorm_stats->rcv_ucast_bytes.hi, - fcoe_stat->rx_bytes_lo, - fcoe_q_tstorm_stats->rcv_ucast_bytes.lo); - - ADD_64(fcoe_stat->rx_bytes_hi, - fcoe_q_tstorm_stats->rcv_bcast_bytes.hi, - fcoe_stat->rx_bytes_lo, - fcoe_q_tstorm_stats->rcv_bcast_bytes.lo); - - ADD_64(fcoe_stat->rx_bytes_hi, - fcoe_q_tstorm_stats->rcv_mcast_bytes.hi, - fcoe_stat->rx_bytes_lo, - fcoe_q_tstorm_stats->rcv_mcast_bytes.lo); - - ADD_64(fcoe_stat->rx_frames_hi, 0, fcoe_stat->rx_frames_lo, - fw_fcoe_stat->rx_stat0.fcoe_rx_pkt_cnt); - - ADD_64(fcoe_stat->rx_frames_hi, 0, fcoe_stat->rx_frames_lo, - fcoe_q_tstorm_stats->rcv_ucast_pkts); - - ADD_64(fcoe_stat->rx_frames_hi, 0, fcoe_stat->rx_frames_lo, - fcoe_q_tstorm_stats->rcv_bcast_pkts); - - ADD_64(fcoe_stat->rx_frames_hi, 0, fcoe_stat->rx_frames_lo, - fcoe_q_tstorm_stats->rcv_mcast_pkts); - - ADD_64(fcoe_stat->tx_bytes_hi, 0, fcoe_stat->tx_bytes_lo, - fw_fcoe_stat->tx_stat.fcoe_tx_byte_cnt); - - ADD_64(fcoe_stat->tx_bytes_hi, - fcoe_q_xstorm_stats->ucast_bytes_sent.hi, - fcoe_stat->tx_bytes_lo, - fcoe_q_xstorm_stats->ucast_bytes_sent.lo); - - ADD_64(fcoe_stat->tx_bytes_hi, - fcoe_q_xstorm_stats->bcast_bytes_sent.hi, - fcoe_stat->tx_bytes_lo, - fcoe_q_xstorm_stats->bcast_bytes_sent.lo); - - ADD_64(fcoe_stat->tx_bytes_hi, - fcoe_q_xstorm_stats->mcast_bytes_sent.hi, - fcoe_stat->tx_bytes_lo, - fcoe_q_xstorm_stats->mcast_bytes_sent.lo); - - ADD_64(fcoe_stat->tx_frames_hi, 0, fcoe_stat->tx_frames_lo, - fw_fcoe_stat->tx_stat.fcoe_tx_pkt_cnt); - - ADD_64(fcoe_stat->tx_frames_hi, 0, fcoe_stat->tx_frames_lo, - fcoe_q_xstorm_stats->ucast_pkts_sent); - - ADD_64(fcoe_stat->tx_frames_hi, 0, fcoe_stat->tx_frames_lo, - fcoe_q_xstorm_stats->bcast_pkts_sent); - - ADD_64(fcoe_stat->tx_frames_hi, 0, fcoe_stat->tx_frames_lo, - fcoe_q_xstorm_stats->mcast_pkts_sent); - } - - /* ask L5 driver to add data to the struct */ - bnx2x_cnic_notify(bp, CNIC_CTL_FCOE_STATS_GET_CMD); -#endif -} - -static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp) -{ -#ifdef BCM_CNIC - struct bnx2x_dcbx_app_params *app = &bp->dcbx_port_params.app; - struct iscsi_stats_info *iscsi_stat = - &bp->slowpath->drv_info_to_mcp.iscsi_stat; - - memcpy(iscsi_stat->mac_local, bp->cnic_eth_dev.iscsi_mac, ETH_ALEN); - - iscsi_stat->qos_priority = - app->traffic_type_priority[LLFC_TRAFFIC_TYPE_ISCSI]; - - /* ask L5 driver to add data to the struct */ - bnx2x_cnic_notify(bp, CNIC_CTL_ISCSI_STATS_GET_CMD); -#endif -} - /* called due to MCP event (on pmf): * reread new bandwidth configuration * configure FW @@ -3069,50 +2941,6 @@ static inline void bnx2x_set_mf_bw(struct bnx2x *bp) bnx2x_fw_command(bp, DRV_MSG_CODE_SET_MF_BW_ACK, 0); } -static void bnx2x_handle_drv_info_req(struct bnx2x *bp) -{ - enum drv_info_opcode op_code; - u32 drv_info_ctl = SHMEM2_RD(bp, drv_info_control); - - /* if drv_info version supported by MFW doesn't match - send NACK */ - if ((drv_info_ctl & DRV_INFO_CONTROL_VER_MASK) != DRV_INFO_CUR_VER) { - bnx2x_fw_command(bp, DRV_MSG_CODE_DRV_INFO_NACK, 0); - return; - } - - op_code = (drv_info_ctl & DRV_INFO_CONTROL_OP_CODE_MASK) >> - DRV_INFO_CONTROL_OP_CODE_SHIFT; - - memset(&bp->slowpath->drv_info_to_mcp, 0, - sizeof(union drv_info_to_mcp)); - - switch (op_code) { - case ETH_STATS_OPCODE: - bnx2x_drv_info_ether_stat(bp); - break; - case FCOE_STATS_OPCODE: - bnx2x_drv_info_fcoe_stat(bp); - break; - case ISCSI_STATS_OPCODE: - bnx2x_drv_info_iscsi_stat(bp); - break; - default: - /* if op code isn't supported - send NACK */ - bnx2x_fw_command(bp, DRV_MSG_CODE_DRV_INFO_NACK, 0); - return; - } - - /* if we got drv_info attn from MFW then these fields are defined in - * shmem2 for sure - */ - SHMEM2_WR(bp, drv_info_host_addr_lo, - U64_LO(bnx2x_sp_mapping(bp, drv_info_to_mcp))); - SHMEM2_WR(bp, drv_info_host_addr_hi, - U64_HI(bnx2x_sp_mapping(bp, drv_info_to_mcp))); - - bnx2x_fw_command(bp, DRV_MSG_CODE_DRV_INFO_ACK, 0); -} - static void bnx2x_dcc_event(struct bnx2x *bp, u32 dcc_event) { DP(BNX2X_MSG_MCP, "dcc_event 0x%x\n", dcc_event); @@ -3620,8 +3448,6 @@ static inline void bnx2x_attn_int_deasserted3(struct bnx2x *bp, u32 attn) if (val & DRV_STATUS_SET_MF_BW) bnx2x_set_mf_bw(bp); - if (val & DRV_STATUS_DRV_INFO_REQ) - bnx2x_handle_drv_info_req(bp); if ((bp->port.pmf == 0) && (val & DRV_STATUS_PMF)) bnx2x_pmf_update(bp); @@ -7022,16 +6848,13 @@ void bnx2x_free_mem(struct bnx2x *bp) static inline int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp) { int num_groups; - int is_fcoe_stats = NO_FCOE(bp) ? 0 : 1; - /* number of queues for statistics is number of eth queues + FCoE */ - u8 num_queue_stats = BNX2X_NUM_ETH_QUEUES(bp) + is_fcoe_stats; + /* number of eth_queues */ + u8 num_queue_stats = BNX2X_NUM_ETH_QUEUES(bp); /* Total number of FW statistics requests = - * 1 for port stats + 1 for PF stats + potential 1 for FCoE stats + - * num of queues - */ - bp->fw_stats_num = 2 + is_fcoe_stats + num_queue_stats; + * 1 for port stats + 1 for PF stats + num_eth_queues */ + bp->fw_stats_num = 2 + num_queue_stats; /* Request is built from stats_query_header and an array of @@ -7039,8 +6862,8 @@ static inline int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp) * STATS_QUERY_CMD_COUNT rules. The real number or requests is * configured in the stats_query_header. */ - num_groups = ((bp->fw_stats_num) / STATS_QUERY_CMD_COUNT) + - (((bp->fw_stats_num) % STATS_QUERY_CMD_COUNT) ? 1 : 0); + num_groups = (2 + num_queue_stats) / STATS_QUERY_CMD_COUNT + + (((2 + num_queue_stats) % STATS_QUERY_CMD_COUNT) ? 1 : 0); bp->fw_stats_req_sz = sizeof(struct stats_query_header) + num_groups * sizeof(struct stats_query_cmd_group); @@ -7049,13 +6872,9 @@ static inline int bnx2x_alloc_fw_stats_mem(struct bnx2x *bp) * * stats_counter holds per-STORM counters that are incremented * when STORM has finished with the current request. - * - * memory for FCoE offloaded statistics are counted anyway, - * even if they will not be sent. */ bp->fw_stats_data_sz = sizeof(struct per_port_stats) + sizeof(struct per_pf_stats) + - sizeof(struct fcoe_statistics_params) + sizeof(struct per_queue_stats) * num_queue_stats + sizeof(struct stats_counter); @@ -8899,7 +8718,7 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) { - u32 val, val2, val3, val4, id, boot_mode; + u32 val, val2, val3, val4, id; u16 pmc; /* Get the chip revision id and number. */ @@ -9008,26 +8827,6 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp) bp->link_params.feature_config_flags |= (val >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED) ? FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED : 0; - bp->flags |= (val >= REQ_BC_VER_4_PFC_STATS_SUPPORTED) ? - BC_SUPPORTS_PFC_STATS : 0; - - boot_mode = SHMEM_RD(bp, - dev_info.port_feature_config[BP_PORT(bp)].mba_config) & - PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK; - switch (boot_mode) { - case PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE: - bp->common.boot_mode = FEATURE_ETH_BOOTMODE_PXE; - break; - case PORT_FEATURE_MBA_BOOT_AGENT_TYPE_ISCSIB: - bp->common.boot_mode = FEATURE_ETH_BOOTMODE_ISCSI; - break; - case PORT_FEATURE_MBA_BOOT_AGENT_TYPE_FCOE_BOOT: - bp->common.boot_mode = FEATURE_ETH_BOOTMODE_FCOE; - break; - case PORT_FEATURE_MBA_BOOT_AGENT_TYPE_NONE: - bp->common.boot_mode = FEATURE_ETH_BOOTMODE_NONE; - break; - } pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_PMC, &pmc); bp->flags |= (pmc & PCI_PM_CAP_PME_D3cold) ? 0 : NO_WOL_FLAG; @@ -9478,9 +9277,9 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) bp->common.shmem2_base); } +#ifdef BCM_CNIC void bnx2x_get_iscsi_info(struct bnx2x *bp) { -#ifdef BCM_CNIC int port = BP_PORT(bp); u32 max_iscsi_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp, @@ -9500,14 +9299,10 @@ void bnx2x_get_iscsi_info(struct bnx2x *bp) */ if (!bp->cnic_eth_dev.max_iscsi_conn) bp->flags |= NO_ISCSI_FLAG; -#else - bp->flags |= NO_ISCSI_FLAG; -#endif } static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp) { -#ifdef BCM_CNIC int port = BP_PORT(bp); int func = BP_ABS_FUNC(bp); @@ -9574,9 +9369,6 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp) */ if (!bp->cnic_eth_dev.max_fcoe_conn) bp->flags |= NO_FCOE_FLAG; -#else - bp->flags |= NO_FCOE_FLAG; -#endif } static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp) @@ -9589,6 +9381,7 @@ static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp) bnx2x_get_iscsi_info(bp); bnx2x_get_fcoe_info(bp); } +#endif static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp) { @@ -9913,7 +9706,9 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) /* Get MAC addresses */ bnx2x_get_mac_hwinfo(bp); +#ifdef BCM_CNIC bnx2x_get_cnic_info(bp); +#endif /* Get current FW pulse sequence */ if (!BP_NOMCP(bp)) { @@ -9931,49 +9726,30 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp) static void __devinit bnx2x_read_fwinfo(struct bnx2x *bp) { int cnt, i, block_end, rodi; - char vpd_start[BNX2X_VPD_LEN+1]; + char vpd_data[BNX2X_VPD_LEN+1]; char str_id_reg[VENDOR_ID_LEN+1]; char str_id_cap[VENDOR_ID_LEN+1]; - char *vpd_data; - char *vpd_extended_data = NULL; u8 len; - cnt = pci_read_vpd(bp->pdev, 0, BNX2X_VPD_LEN, vpd_start); + cnt = pci_read_vpd(bp->pdev, 0, BNX2X_VPD_LEN, vpd_data); memset(bp->fw_ver, 0, sizeof(bp->fw_ver)); if (cnt < BNX2X_VPD_LEN) goto out_not_found; - /* VPD RO tag should be first tag after identifier string, hence - * we should be able to find it in first BNX2X_VPD_LEN chars - */ - i = pci_vpd_find_tag(vpd_start, 0, BNX2X_VPD_LEN, + i = pci_vpd_find_tag(vpd_data, 0, BNX2X_VPD_LEN, PCI_VPD_LRDT_RO_DATA); if (i < 0) goto out_not_found; + block_end = i + PCI_VPD_LRDT_TAG_SIZE + - pci_vpd_lrdt_size(&vpd_start[i]); + pci_vpd_lrdt_size(&vpd_data[i]); i += PCI_VPD_LRDT_TAG_SIZE; - if (block_end > BNX2X_VPD_LEN) { - vpd_extended_data = kmalloc(block_end, GFP_KERNEL); - if (vpd_extended_data == NULL) - goto out_not_found; - - /* read rest of vpd image into vpd_extended_data */ - memcpy(vpd_extended_data, vpd_start, BNX2X_VPD_LEN); - cnt = pci_read_vpd(bp->pdev, BNX2X_VPD_LEN, - block_end - BNX2X_VPD_LEN, - vpd_extended_data + BNX2X_VPD_LEN); - if (cnt < (block_end - BNX2X_VPD_LEN)) - goto out_not_found; - vpd_data = vpd_extended_data; - } else - vpd_data = vpd_start; - - /* now vpd_data holds full vpd content in both cases */ + if (block_end > BNX2X_VPD_LEN) + goto out_not_found; rodi = pci_vpd_find_info_keyword(vpd_data, i, block_end, PCI_VPD_RO_KEYWORD_MFR_ID); @@ -10005,11 +9781,9 @@ static void __devinit bnx2x_read_fwinfo(struct bnx2x *bp) bp->fw_ver[len] = ' '; } } - kfree(vpd_extended_data); return; } out_not_found: - kfree(vpd_extended_data); return; } @@ -11776,38 +11550,6 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl) smp_mb__after_atomic_inc(); break; } - case DRV_CTL_ULP_REGISTER_CMD: { - int ulp_type = ctl->data.ulp_type; - - if (CHIP_IS_E3(bp)) { - int idx = BP_FW_MB_IDX(bp); - u32 cap; - - cap = SHMEM2_RD(bp, drv_capabilities_flag[idx]); - if (ulp_type == CNIC_ULP_ISCSI) - cap |= DRV_FLAGS_CAPABILITIES_LOADED_ISCSI; - else if (ulp_type == CNIC_ULP_FCOE) - cap |= DRV_FLAGS_CAPABILITIES_LOADED_FCOE; - SHMEM2_WR(bp, drv_capabilities_flag[idx], cap); - } - break; - } - case DRV_CTL_ULP_UNREGISTER_CMD: { - int ulp_type = ctl->data.ulp_type; - - if (CHIP_IS_E3(bp)) { - int idx = BP_FW_MB_IDX(bp); - u32 cap; - - cap = SHMEM2_RD(bp, drv_capabilities_flag[idx]); - if (ulp_type == CNIC_ULP_ISCSI) - cap &= ~DRV_FLAGS_CAPABILITIES_LOADED_ISCSI; - else if (ulp_type == CNIC_ULP_FCOE) - cap &= ~DRV_FLAGS_CAPABILITIES_LOADED_FCOE; - SHMEM2_WR(bp, drv_capabilities_flag[idx], cap); - } - break; - } default: BNX2X_ERR("unknown command %x\n", ctl->cmd); diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 5ac616093f9f..a34362e9fd9c 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -30,8 +30,6 @@ #define BNX2X_MAX_EMUL_MULTI 16 -#define MAC_LEADING_ZERO_CNT (ALIGN(ETH_ALEN, sizeof(u32)) - ETH_ALEN) - /**** Exe Queue interfaces ****/ /** @@ -443,36 +441,6 @@ static bool bnx2x_put_credit_vlan_mac(struct bnx2x_vlan_mac_obj *o) return true; } -static int bnx2x_get_n_elements(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o, - int n, u8 *buf) -{ - struct bnx2x_vlan_mac_registry_elem *pos; - u8 *next = buf; - int counter = 0; - - /* traverse list */ - list_for_each_entry(pos, &o->head, link) { - if (counter < n) { - /* place leading zeroes in buffer */ - memset(next, 0, MAC_LEADING_ZERO_CNT); - - /* place mac after leading zeroes*/ - memcpy(next + MAC_LEADING_ZERO_CNT, pos->u.mac.mac, - ETH_ALEN); - - /* calculate address of next element and - * advance counter - */ - counter++; - next = buf + counter * ALIGN(ETH_ALEN, sizeof(u32)); - - DP(BNX2X_MSG_SP, "copied element number %d to address %p element was %pM\n", - counter, next, pos->u.mac.mac); - } - } - return counter * ETH_ALEN; -} - /* check_add() callbacks */ static int bnx2x_check_mac_add(struct bnx2x_vlan_mac_obj *o, union bnx2x_classification_ramrod_data *data) @@ -1918,7 +1886,6 @@ void bnx2x_init_mac_obj(struct bnx2x *bp, mac_obj->check_move = bnx2x_check_move; mac_obj->ramrod_cmd = RAMROD_CMD_ID_ETH_CLASSIFICATION_RULES; - mac_obj->get_n_elements = bnx2x_get_n_elements; /* Exe Queue */ bnx2x_exe_queue_init(bp, diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h index 992308ff82e8..9a517c2e9f1b 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h @@ -285,19 +285,6 @@ struct bnx2x_vlan_mac_obj { /* RAMROD command to be used */ int ramrod_cmd; - /* copy first n elements onto preallocated buffer - * - * @param n number of elements to get - * @param buf buffer preallocated by caller into which elements - * will be copied. Note elements are 4-byte aligned - * so buffer size must be able to accomodate the - * aligned elements. - * - * @return number of copied bytes - */ - int (*get_n_elements)(struct bnx2x *bp, struct bnx2x_vlan_mac_obj *o, - int n, u8 *buf); - /** * Checks if ADD-ramrod with the given params may be performed. * diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c index bc0121ac291e..3034f0e31938 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c @@ -39,17 +39,6 @@ static inline long bnx2x_hilo(u32 *hiref) #endif } -static u16 bnx2x_get_port_stats_dma_len(struct bnx2x *bp) -{ - u16 res = sizeof(struct host_port_stats) >> 2; - - /* if PFC stats are not supported by the MFW, don't DMA them */ - if (!(bp->flags & BC_SUPPORTS_PFC_STATS)) - res -= (sizeof(u32)*4) >> 2; - - return res; -} - /* * Init service functions */ @@ -189,8 +178,7 @@ static void bnx2x_stats_pmf_update(struct bnx2x *bp) DMAE_LEN32_RD_MAX * 4); dmae->dst_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats) + DMAE_LEN32_RD_MAX * 4); - dmae->len = bnx2x_get_port_stats_dma_len(bp) - DMAE_LEN32_RD_MAX; - + dmae->len = (sizeof(struct host_port_stats) >> 2) - DMAE_LEN32_RD_MAX; dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); dmae->comp_val = DMAE_COMP_VAL; @@ -229,7 +217,7 @@ static void bnx2x_port_stats_init(struct bnx2x *bp) dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats)); dmae->dst_addr_lo = bp->port.port_stx >> 2; dmae->dst_addr_hi = 0; - dmae->len = bnx2x_get_port_stats_dma_len(bp); + dmae->len = sizeof(struct host_port_stats) >> 2; dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; dmae->comp_addr_hi = 0; dmae->comp_val = 1; @@ -552,25 +540,6 @@ static void bnx2x_bmac_stats_update(struct bnx2x *bp) UPDATE_STAT64(tx_stat_gterr, tx_stat_dot3statsinternalmactransmiterrors); UPDATE_STAT64(tx_stat_gtufl, tx_stat_mac_ufl); - - /* collect PFC stats */ - DIFF_64(diff.hi, new->tx_stat_gtpp_hi, - pstats->pfc_frames_tx_hi, - diff.lo, new->tx_stat_gtpp_lo, - pstats->pfc_frames_tx_lo); - pstats->pfc_frames_tx_hi = new->tx_stat_gtpp_hi; - pstats->pfc_frames_tx_lo = new->tx_stat_gtpp_lo; - ADD_64(pstats->pfc_frames_tx_hi, diff.hi, - pstats->pfc_frames_tx_lo, diff.lo); - - DIFF_64(diff.hi, new->rx_stat_grpp_hi, - pstats->pfc_frames_rx_hi, - diff.lo, new->rx_stat_grpp_lo, - pstats->pfc_frames_rx_lo); - pstats->pfc_frames_rx_hi = new->rx_stat_grpp_hi; - pstats->pfc_frames_rx_lo = new->rx_stat_grpp_lo; - ADD_64(pstats->pfc_frames_rx_hi, diff.hi, - pstats->pfc_frames_rx_lo, diff.lo); } estats->pause_frames_received_hi = @@ -582,15 +551,6 @@ static void bnx2x_bmac_stats_update(struct bnx2x *bp) pstats->mac_stx[1].tx_stat_outxoffsent_hi; estats->pause_frames_sent_lo = pstats->mac_stx[1].tx_stat_outxoffsent_lo; - - estats->pfc_frames_received_hi = - pstats->pfc_frames_rx_hi; - estats->pfc_frames_received_lo = - pstats->pfc_frames_rx_lo; - estats->pfc_frames_sent_hi = - pstats->pfc_frames_tx_hi; - estats->pfc_frames_sent_lo = - pstats->pfc_frames_tx_lo; } static void bnx2x_mstat_stats_update(struct bnx2x *bp) @@ -611,11 +571,6 @@ static void bnx2x_mstat_stats_update(struct bnx2x *bp) ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_outxoffsent); ADD_STAT64(stats_tx.tx_gtxpf, tx_stat_flowcontroldone); - /* collect pfc stats */ - ADD_64(pstats->pfc_frames_tx_hi, new->stats_tx.tx_gtxpp_hi, - pstats->pfc_frames_tx_lo, new->stats_tx.tx_gtxpp_lo); - ADD_64(pstats->pfc_frames_rx_hi, new->stats_rx.rx_grxpp_hi, - pstats->pfc_frames_rx_lo, new->stats_rx.rx_grxpp_lo); ADD_STAT64(stats_tx.tx_gt64, tx_stat_etherstatspkts64octets); ADD_STAT64(stats_tx.tx_gt127, @@ -673,15 +628,6 @@ static void bnx2x_mstat_stats_update(struct bnx2x *bp) pstats->mac_stx[1].tx_stat_outxoffsent_hi; estats->pause_frames_sent_lo = pstats->mac_stx[1].tx_stat_outxoffsent_lo; - - estats->pfc_frames_received_hi = - pstats->pfc_frames_rx_hi; - estats->pfc_frames_received_lo = - pstats->pfc_frames_rx_lo; - estats->pfc_frames_sent_hi = - pstats->pfc_frames_tx_hi; - estats->pfc_frames_sent_lo = - pstats->pfc_frames_tx_lo; } static void bnx2x_emac_stats_update(struct bnx2x *bp) @@ -794,7 +740,7 @@ static int bnx2x_hw_stats_update(struct bnx2x *bp) estats->brb_drop_hi = pstats->brb_drop_hi; estats->brb_drop_lo = pstats->brb_drop_lo; - pstats->host_port_stats_counter++; + pstats->host_port_stats_start = ++pstats->host_port_stats_end; if (!BP_NOMCP(bp)) { u32 nig_timer_max = @@ -1319,7 +1265,7 @@ static void bnx2x_port_stats_stop(struct bnx2x *bp) dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats)); dmae->dst_addr_lo = bp->port.port_stx >> 2; dmae->dst_addr_hi = 0; - dmae->len = bnx2x_get_port_stats_dma_len(bp); + dmae->len = sizeof(struct host_port_stats) >> 2; if (bp->func_stx) { dmae->comp_addr_lo = dmae_reg_go_c[loader_idx] >> 2; dmae->comp_addr_hi = 0; @@ -1436,7 +1382,7 @@ static void bnx2x_port_stats_base_init(struct bnx2x *bp) dmae->src_addr_hi = U64_HI(bnx2x_sp_mapping(bp, port_stats)); dmae->dst_addr_lo = bp->port.port_stx >> 2; dmae->dst_addr_hi = 0; - dmae->len = bnx2x_get_port_stats_dma_len(bp); + dmae->len = sizeof(struct host_port_stats) >> 2; dmae->comp_addr_lo = U64_LO(bnx2x_sp_mapping(bp, stats_comp)); dmae->comp_addr_hi = U64_HI(bnx2x_sp_mapping(bp, stats_comp)); dmae->comp_val = DMAE_COMP_VAL; @@ -1513,7 +1459,6 @@ static void bnx2x_func_stats_base_update(struct bnx2x *bp) static inline void bnx2x_prep_fw_stats_req(struct bnx2x *bp) { int i; - int first_queue_query_index; struct stats_query_header *stats_hdr = &bp->fw_stats_req->hdr; dma_addr_t cur_data_offset; @@ -1569,40 +1514,14 @@ static inline void bnx2x_prep_fw_stats_req(struct bnx2x *bp) cur_query_entry->address.hi = cpu_to_le32(U64_HI(cur_data_offset)); cur_query_entry->address.lo = cpu_to_le32(U64_LO(cur_data_offset)); - /**** FCoE FW statistics data ****/ - if (!NO_FCOE(bp)) { - cur_data_offset = bp->fw_stats_data_mapping + - offsetof(struct bnx2x_fw_stats_data, fcoe); - - cur_query_entry = - &bp->fw_stats_req->query[BNX2X_FCOE_QUERY_IDX]; - - cur_query_entry->kind = STATS_TYPE_FCOE; - /* For FCoE query index is a DONT CARE */ - cur_query_entry->index = BP_PORT(bp); - cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp)); - cur_query_entry->address.hi = - cpu_to_le32(U64_HI(cur_data_offset)); - cur_query_entry->address.lo = - cpu_to_le32(U64_LO(cur_data_offset)); - } - /**** Clients' queries ****/ cur_data_offset = bp->fw_stats_data_mapping + offsetof(struct bnx2x_fw_stats_data, queue_stats); - /* first queue query index depends whether FCoE offloaded request will - * be included in the ramrod - */ - if (!NO_FCOE(bp)) - first_queue_query_index = BNX2X_FIRST_QUEUE_QUERY_IDX; - else - first_queue_query_index = BNX2X_FIRST_QUEUE_QUERY_IDX - 1; - for_each_eth_queue(bp, i) { cur_query_entry = &bp->fw_stats_req-> - query[first_queue_query_index + i]; + query[BNX2X_FIRST_QUEUE_QUERY_IDX + i]; cur_query_entry->kind = STATS_TYPE_QUEUE; cur_query_entry->index = bnx2x_stats_id(&bp->fp[i]); @@ -1614,21 +1533,6 @@ static inline void bnx2x_prep_fw_stats_req(struct bnx2x *bp) cur_data_offset += sizeof(struct per_queue_stats); } - - /* add FCoE queue query if needed */ - if (!NO_FCOE(bp)) { - cur_query_entry = - &bp->fw_stats_req-> - query[first_queue_query_index + i]; - - cur_query_entry->kind = STATS_TYPE_QUEUE; - cur_query_entry->index = bnx2x_stats_id(&bp->fp[FCOE_IDX]); - cur_query_entry->funcID = cpu_to_le16(BP_FUNC(bp)); - cur_query_entry->address.hi = - cpu_to_le32(U64_HI(cur_data_offset)); - cur_query_entry->address.lo = - cpu_to_le32(U64_LO(cur_data_offset)); - } } void bnx2x_stats_init(struct bnx2x *bp) diff --git a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h index 683deb053109..5d8ce2f6afef 100644 --- a/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h +++ b/trunk/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h @@ -193,12 +193,6 @@ struct bnx2x_eth_stats { u32 total_tpa_aggregated_frames_lo; u32 total_tpa_bytes_hi; u32 total_tpa_bytes_lo; - - /* PFC */ - u32 pfc_frames_received_hi; - u32 pfc_frames_received_lo; - u32 pfc_frames_sent_hi; - u32 pfc_frames_sent_lo; }; diff --git a/trunk/drivers/net/ethernet/broadcom/cnic.c b/trunk/drivers/net/ethernet/broadcom/cnic.c index 4bcb67eedf1e..b336e55e0d80 100644 --- a/trunk/drivers/net/ethernet/broadcom/cnic.c +++ b/trunk/drivers/net/ethernet/broadcom/cnic.c @@ -250,21 +250,6 @@ static u32 cnic_reg_rd_ind(struct cnic_dev *dev, u32 off) return io->data; } -static void cnic_ulp_ctl(struct cnic_dev *dev, int ulp_type, bool reg) -{ - struct cnic_local *cp = dev->cnic_priv; - struct cnic_eth_dev *ethdev = cp->ethdev; - struct drv_ctl_info info; - - if (reg) - info.cmd = DRV_CTL_ULP_REGISTER_CMD; - else - info.cmd = DRV_CTL_ULP_UNREGISTER_CMD; - - info.data.ulp_type = ulp_type; - ethdev->drv_ctl(dev->netdev, &info); -} - static int cnic_in_use(struct cnic_sock *csk) { return test_bit(SK_F_INUSE, &csk->flags); @@ -578,8 +563,6 @@ static int cnic_register_device(struct cnic_dev *dev, int ulp_type, mutex_unlock(&cnic_lock); - cnic_ulp_ctl(dev, ulp_type, true); - return 0; } @@ -619,8 +602,6 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type) if (test_bit(ULP_F_CALL_PENDING, &cp->ulp_flags[ulp_type])) netdev_warn(dev->netdev, "Failed waiting for ULP up call to complete\n"); - cnic_ulp_ctl(dev, ulp_type, false); - return 0; } EXPORT_SYMBOL(cnic_unregister_driver); @@ -3071,26 +3052,9 @@ static void cnic_ulp_start(struct cnic_dev *dev) } } -static int cnic_copy_ulp_stats(struct cnic_dev *dev, int ulp_type) -{ - struct cnic_local *cp = dev->cnic_priv; - struct cnic_ulp_ops *ulp_ops; - int rc; - - mutex_lock(&cnic_lock); - ulp_ops = cnic_ulp_tbl_prot(ulp_type); - if (ulp_ops && ulp_ops->cnic_get_stats) - rc = ulp_ops->cnic_get_stats(cp->ulp_handle[ulp_type]); - else - rc = -ENODEV; - mutex_unlock(&cnic_lock); - return rc; -} - static int cnic_ctl(void *data, struct cnic_ctl_info *info) { struct cnic_dev *dev = data; - int ulp_type = CNIC_ULP_ISCSI; switch (info->cmd) { case CNIC_CTL_STOP_CMD: @@ -3136,15 +3100,6 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info) } break; } - case CNIC_CTL_FCOE_STATS_GET_CMD: - ulp_type = CNIC_ULP_FCOE; - /* fall through */ - case CNIC_CTL_ISCSI_STATS_GET_CMD: - cnic_hold(dev); - cnic_copy_ulp_stats(dev, ulp_type); - cnic_put(dev); - break; - default: return -EINVAL; } @@ -5333,8 +5288,6 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev) cdev->pcidev = pdev; cp->chip_id = ethdev->chip_id; - cdev->stats_addr = ethdev->addr_drv_info_to_mcp; - if (!(ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI)) cdev->max_iscsi_conn = ethdev->max_iscsi_conn; if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id) && diff --git a/trunk/drivers/net/ethernet/broadcom/cnic_if.h b/trunk/drivers/net/ethernet/broadcom/cnic_if.h index d1f6456d22bb..79443e0dbf96 100644 --- a/trunk/drivers/net/ethernet/broadcom/cnic_if.h +++ b/trunk/drivers/net/ethernet/broadcom/cnic_if.h @@ -86,8 +86,6 @@ struct kcqe { #define CNIC_CTL_START_CMD 2 #define CNIC_CTL_COMPLETION_CMD 3 #define CNIC_CTL_STOP_ISCSI_CMD 4 -#define CNIC_CTL_FCOE_STATS_GET_CMD 5 -#define CNIC_CTL_ISCSI_STATS_GET_CMD 6 #define DRV_CTL_IO_WR_CMD 0x101 #define DRV_CTL_IO_RD_CMD 0x102 @@ -98,8 +96,6 @@ struct kcqe { #define DRV_CTL_STOP_L2_CMD 0x107 #define DRV_CTL_RET_L2_SPQ_CREDIT_CMD 0x10c #define DRV_CTL_ISCSI_STOPPED_CMD 0x10d -#define DRV_CTL_ULP_REGISTER_CMD 0x10e -#define DRV_CTL_ULP_UNREGISTER_CMD 0x10f struct cnic_ctl_completion { u32 cid; @@ -137,7 +133,6 @@ struct drv_ctl_info { struct drv_ctl_spq_credit credit; struct drv_ctl_io io; struct drv_ctl_l2_ring ring; - int ulp_type; char bytes[MAX_DRV_CTL_DATA]; } data; }; @@ -206,7 +201,6 @@ struct cnic_eth_dev { struct kwqe_16 *[], u32); int (*drv_ctl)(struct net_device *, struct drv_ctl_info *); unsigned long reserved1[2]; - union drv_info_to_mcp *addr_drv_info_to_mcp; }; struct cnic_sockaddr { @@ -303,8 +297,6 @@ struct cnic_dev { int max_fcoe_conn; int max_rdma_conn; - union drv_info_to_mcp *stats_addr; - void *cnic_priv; }; @@ -334,7 +326,6 @@ struct cnic_ulp_ops { void (*cm_remote_abort)(struct cnic_sock *); int (*iscsi_nl_send_msg)(void *ulp_ctx, u32 msg_type, char *data, u16 data_size); - int (*cnic_get_stats)(void *ulp_ctx); struct module *owner; atomic_t ref_count; }; diff --git a/trunk/drivers/net/ethernet/broadcom/tg3.c b/trunk/drivers/net/ethernet/broadcom/tg3.c index 8bf11ca30efe..cf36312ac5ac 100644 --- a/trunk/drivers/net/ethernet/broadcom/tg3.c +++ b/trunk/drivers/net/ethernet/broadcom/tg3.c @@ -89,10 +89,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) #define DRV_MODULE_NAME "tg3" #define TG3_MAJ_NUM 3 -#define TG3_MIN_NUM 122 +#define TG3_MIN_NUM 121 #define DRV_MODULE_VERSION \ __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM) -#define DRV_MODULE_RELDATE "December 7, 2011" +#define DRV_MODULE_RELDATE "November 2, 2011" #define RESET_KIND_SHUTDOWN 0 #define RESET_KIND_INIT 1 @@ -135,6 +135,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) (tg3_flag(tp, LRG_PROD_RING_CAP) ? \ TG3_RX_JMB_MAX_SIZE_5717 : TG3_RX_JMB_MAX_SIZE_5700) #define TG3_DEF_RX_JUMBO_RING_PENDING 100 +#define TG3_RSS_INDIR_TBL_SIZE 128 /* Do not place this n-ring entries value into the tp struct itself, * we really want to expose these constants to GCC so that modulo et @@ -198,8 +199,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits) /* minimum number of free TX descriptors required to wake up TX process */ #define TG3_TX_WAKEUP_THRESH(tnapi) ((tnapi)->tx_pending / 4) -#define TG3_TX_BD_DMA_MAX_2K 2048 -#define TG3_TX_BD_DMA_MAX_4K 4096 +#define TG3_TX_BD_DMA_MAX 4096 #define TG3_RAW_IP_ALIGN 2 @@ -1670,6 +1670,22 @@ static void tg3_link_report(struct tg3 *tp) } } +static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl) +{ + u16 miireg; + + if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX)) + miireg = ADVERTISE_PAUSE_CAP; + else if (flow_ctrl & FLOW_CTRL_TX) + miireg = ADVERTISE_PAUSE_ASYM; + else if (flow_ctrl & FLOW_CTRL_RX) + miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + else + miireg = 0; + + return miireg; +} + static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl) { u16 miireg; @@ -1770,7 +1786,7 @@ static void tg3_adjust_link(struct net_device *dev) if (phydev->duplex == DUPLEX_HALF) mac_mode |= MAC_MODE_HALF_DUPLEX; else { - lcl_adv = mii_advertise_flowctrl( + lcl_adv = tg3_advert_flowctrl_1000T( tp->link_config.flowctrl); if (phydev->pause) @@ -2138,7 +2154,7 @@ static void tg3_phy_eee_enable(struct tg3 *tp) if (tp->link_config.active_speed == SPEED_1000 && (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - tg3_flag(tp, 57765_CLASS)) && + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) && !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { val = MII_TG3_DSP_TAP26_ALNOKO | MII_TG3_DSP_TAP26_RMRXSTO; @@ -2657,7 +2673,8 @@ static void tg3_frob_aux_power(struct tg3 *tp, bool include_wol) bool need_vaux = false; /* The GPIOs do something completely different on 57765. */ - if (!tg3_flag(tp, IS_NIC) || tg3_flag(tp, 57765_CLASS)) + if (!tg3_flag(tp, IS_NIC) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) return; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || @@ -3572,23 +3589,24 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) new_adv = ADVERTISE_CSMA; new_adv |= ethtool_adv_to_mii_adv_t(advertise) & ADVERTISE_ALL; - new_adv |= mii_advertise_flowctrl(flowctrl); + new_adv |= tg3_advert_flowctrl_1000T(flowctrl); err = tg3_writephy(tp, MII_ADVERTISE, new_adv); if (err) goto done; - if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) { - new_adv = ethtool_adv_to_mii_ctrl1000_t(advertise); + if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY) + goto done; - if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) - new_adv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER; + new_adv = ethtool_adv_to_mii_ctrl1000_t(advertise); - err = tg3_writephy(tp, MII_CTRL1000, new_adv); - if (err) - goto done; - } + if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 || + tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) + new_adv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER; + + err = tg3_writephy(tp, MII_CTRL1000, new_adv); + if (err) + goto done; if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) goto done; @@ -3614,7 +3632,6 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) switch (GET_ASIC_REV(tp->pci_chip_rev_id)) { case ASIC_REV_5717: case ASIC_REV_57765: - case ASIC_REV_57766: case ASIC_REV_5719: /* If we advertised any eee advertisements above... */ if (val) @@ -3751,61 +3768,65 @@ static int tg3_init_5401phy_dsp(struct tg3 *tp) return err; } -static bool tg3_phy_copper_an_config_ok(struct tg3 *tp, u32 *lcladv) +static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask) { - u32 advmsk, tgtadv, advertising; - - advertising = tp->link_config.advertising; - tgtadv = ethtool_adv_to_mii_adv_t(advertising) & ADVERTISE_ALL; + u32 adv_reg, all_mask = 0; - advmsk = ADVERTISE_ALL; - if (tp->link_config.active_duplex == DUPLEX_FULL) { - tgtadv |= mii_advertise_flowctrl(tp->link_config.flowctrl); - advmsk |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - } + all_mask = ethtool_adv_to_mii_adv_t(mask) & ADVERTISE_ALL; - if (tg3_readphy(tp, MII_ADVERTISE, lcladv)) - return false; + if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg)) + return 0; - if ((*lcladv & advmsk) != tgtadv) - return false; + if ((adv_reg & ADVERTISE_ALL) != all_mask) + return 0; if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) { u32 tg3_ctrl; - tgtadv = ethtool_adv_to_mii_ctrl1000_t(advertising); + all_mask = ethtool_adv_to_mii_ctrl1000_t(mask); if (tg3_readphy(tp, MII_CTRL1000, &tg3_ctrl)) - return false; + return 0; tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL); - if (tg3_ctrl != tgtadv) - return false; + if (tg3_ctrl != all_mask) + return 0; } - return true; + return 1; } -static bool tg3_phy_copper_fetch_rmtadv(struct tg3 *tp, u32 *rmtadv) +static int tg3_adv_1000T_flowctrl_ok(struct tg3 *tp, u32 *lcladv, u32 *rmtadv) { - u32 lpeth = 0; - - if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) { - u32 val; + u32 curadv, reqadv; - if (tg3_readphy(tp, MII_STAT1000, &val)) - return false; + if (tg3_readphy(tp, MII_ADVERTISE, lcladv)) + return 1; - lpeth = mii_stat1000_to_ethtool_lpa_t(val); - } + curadv = *lcladv & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); + reqadv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl); - if (tg3_readphy(tp, MII_LPA, rmtadv)) - return false; + if (tp->link_config.active_duplex == DUPLEX_FULL) { + if (curadv != reqadv) + return 0; - lpeth |= mii_lpa_to_ethtool_lpa_t(*rmtadv); - tp->link_config.rmt_adv = lpeth; + if (tg3_flag(tp, PAUSE_AUTONEG)) + tg3_readphy(tp, MII_LPA, rmtadv); + } else { + /* Reprogram the advertisement register, even if it + * does not affect the current link. If the link + * gets renegotiated in the future, we can save an + * additional renegotiation cycle by advertising + * it correctly in the first place. + */ + if (curadv != reqadv) { + *lcladv &= ~(ADVERTISE_PAUSE_CAP | + ADVERTISE_PAUSE_ASYM); + tg3_writephy(tp, MII_ADVERTISE, *lcladv | reqadv); + } + } - return true; + return 1; } static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) @@ -3912,7 +3933,6 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) current_speed = SPEED_INVALID; current_duplex = DUPLEX_INVALID; tp->phy_flags &= ~TG3_PHYFLG_MDIX_STATE; - tp->link_config.rmt_adv = 0; if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) { err = tg3_phy_auxctl_read(tp, @@ -3968,9 +3988,12 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) if (tp->link_config.autoneg == AUTONEG_ENABLE) { if ((bmcr & BMCR_ANENABLE) && - tg3_phy_copper_an_config_ok(tp, &lcl_adv) && - tg3_phy_copper_fetch_rmtadv(tp, &rmt_adv)) - current_link_up = 1; + tg3_copper_is_advertising_all(tp, + tp->link_config.advertising)) { + if (tg3_adv_1000T_flowctrl_ok(tp, &lcl_adv, + &rmt_adv)) + current_link_up = 1; + } } else { if (!(bmcr & BMCR_ANENABLE) && tp->link_config.speed == current_speed && @@ -4606,9 +4629,6 @@ static int tg3_setup_fiber_hw_autoneg(struct tg3 *tp, u32 mac_status) if (sg_dig_status & SG_DIG_PARTNER_ASYM_PAUSE) remote_adv |= LPA_1000XPAUSE_ASYM; - tp->link_config.rmt_adv = - mii_adv_to_ethtool_adv_x(remote_adv); - tg3_setup_flow_control(tp, local_adv, remote_adv); current_link_up = 1; tp->serdes_counter = 0; @@ -4680,9 +4700,6 @@ static int tg3_setup_fiber_by_hand(struct tg3 *tp, u32 mac_status) if (rxflags & MR_LP_ADV_ASYM_PAUSE) remote_adv |= LPA_1000XPAUSE_ASYM; - tp->link_config.rmt_adv = - mii_adv_to_ethtool_adv_x(remote_adv); - tg3_setup_flow_control(tp, local_adv, remote_adv); current_link_up = 1; @@ -4765,7 +4782,6 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) udelay(40); current_link_up = 0; - tp->link_config.rmt_adv = 0; mac_status = tr32(MAC_STATUS); if (tg3_flag(tp, HW_AUTONEG)) @@ -4857,7 +4873,6 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) current_link_up = 0; current_speed = SPEED_INVALID; current_duplex = DUPLEX_INVALID; - tp->link_config.rmt_adv = 0; err |= tg3_readphy(tp, MII_BMSR, &bmsr); err |= tg3_readphy(tp, MII_BMSR, &bmsr); @@ -4964,9 +4979,6 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) current_duplex = DUPLEX_FULL; else current_duplex = DUPLEX_HALF; - - tp->link_config.rmt_adv = - mii_adv_to_ethtool_adv_x(remote_adv); } else if (!tg3_flag(tp, 5780_CLASS)) { /* Link is up via parallel detect */ } else { @@ -6433,17 +6445,17 @@ static bool tg3_tx_frag_set(struct tg3_napi *tnapi, u32 *entry, u32 *budget, if (tg3_40bit_overflow_test(tp, map, len)) hwbug = 1; - if (tp->dma_limit) { + if (tg3_flag(tp, 4K_FIFO_LIMIT)) { u32 prvidx = *entry; u32 tmp_flag = flags & ~TXD_FLAG_END; - while (len > tp->dma_limit && *budget) { - u32 frag_len = tp->dma_limit; - len -= tp->dma_limit; + while (len > TG3_TX_BD_DMA_MAX && *budget) { + u32 frag_len = TG3_TX_BD_DMA_MAX; + len -= TG3_TX_BD_DMA_MAX; /* Avoid the 8byte DMA problem */ if (len <= 8) { - len += tp->dma_limit / 2; - frag_len = tp->dma_limit / 2; + len += TG3_TX_BD_DMA_MAX / 2; + frag_len = TG3_TX_BD_DMA_MAX / 2; } tnapi->tx_buffers[*entry].fragmented = true; @@ -7576,6 +7588,8 @@ static int tg3_abort_hw(struct tg3 *tp, int silent) if (tnapi->hw_status) memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE); } + if (tp->hw_stats) + memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats)); return err; } @@ -7891,11 +7905,6 @@ static int tg3_chip_reset(struct tg3 *tp) return 0; } -static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *, - struct rtnl_link_stats64 *); -static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *, - struct tg3_ethtool_stats *); - /* tp->lock is held. */ static int tg3_halt(struct tg3 *tp, int kind, int silent) { @@ -7913,15 +7922,6 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent) tg3_write_sig_legacy(tp, kind); tg3_write_sig_post_reset(tp, kind); - if (tp->hw_stats) { - /* Save the stats across chip resets... */ - tg3_get_stats64(tp->dev, &tp->net_stats_prev), - tg3_get_estats(tp, &tp->estats_prev); - - /* And make sure the next sample is new data */ - memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats)); - } - if (err) return err; @@ -8065,7 +8065,7 @@ static void tg3_rings_reset(struct tg3 *tp) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16; else if (tg3_flag(tp, 5717_PLUS)) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 4; - else if (tg3_flag(tp, 57765_CLASS)) + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 2; else limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE; @@ -8082,7 +8082,7 @@ static void tg3_rings_reset(struct tg3 *tp) else if (!tg3_flag(tp, 5705_PLUS)) limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16; else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || - tg3_flag(tp, 57765_CLASS)) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 4; else limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE; @@ -8220,37 +8220,6 @@ static void tg3_setup_rxbd_thresholds(struct tg3 *tp) tw32(JMB_REPLENISH_LWM, bdcache_maxcnt); } -void tg3_rss_init_indir_tbl(struct tg3 *tp) -{ - int i; - - if (!tg3_flag(tp, SUPPORT_MSIX)) - return; - - if (tp->irq_cnt <= 2) - memset(&tp->rss_ind_tbl[0], 0, sizeof(tp->rss_ind_tbl)); - else - for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) - tp->rss_ind_tbl[i] = i % (tp->irq_cnt - 1); -} - -void tg3_rss_write_indir_tbl(struct tg3 *tp) -{ - int i = 0; - u32 reg = MAC_RSS_INDIR_TBL_0; - - while (i < TG3_RSS_INDIR_TBL_SIZE) { - u32 val = tp->rss_ind_tbl[i]; - i++; - for (; i % 8; i++) { - val <<= 4; - val |= tp->rss_ind_tbl[i]; - } - tw32(reg, val); - reg += 4; - } -} - /* tp->lock is held. */ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) { @@ -8357,7 +8326,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(GRC_MODE, grc_mode); } - if (tg3_flag(tp, 57765_CLASS)) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) { if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) { u32 grc_mode = tr32(GRC_MODE); @@ -8445,7 +8414,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) ~DMA_RWCTRL_DIS_CACHE_ALIGNMENT; if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) val &= ~DMA_RWCTRL_CRDRDR_RDMA_MRRS_MSK; - if (!tg3_flag(tp, 57765_CLASS) && + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) val |= DMA_RWCTRL_TAGGED_STAT_WA; tw32(TG3PCI_DMA_RW_CTRL, val | tp->dma_rwctrl); @@ -8592,7 +8561,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_MAXLEN_FLAGS, val | BDINFO_FLAGS_USE_EXT_RECV); if (!tg3_flag(tp, USE_JUMBO_BDFLAG) || - tg3_flag(tp, 57765_CLASS)) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tw32(RCVDBDI_JUMBO_BD + TG3_BDINFO_NIC_ADDR, NIC_SRAM_RX_JUMBO_BUFFER_DESC); } else { @@ -8678,9 +8647,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) if (tg3_flag(tp, PCI_EXPRESS)) rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) - rdmac_mode |= RDMAC_MODE_JMB_2K_MMRR; - if (tg3_flag(tp, HW_TSO_1) || tg3_flag(tp, HW_TSO_2) || tg3_flag(tp, HW_TSO_3)) @@ -8944,7 +8910,28 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(100); if (tg3_flag(tp, ENABLE_RSS)) { - tg3_rss_write_indir_tbl(tp); + int i = 0; + u32 reg = MAC_RSS_INDIR_TBL_0; + + if (tp->irq_cnt == 2) { + for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i += 8) { + tw32(reg, 0x0); + reg += 4; + } + } else { + u32 val; + + while (i < TG3_RSS_INDIR_TBL_SIZE) { + val = i % (tp->irq_cnt - 1); + i++; + for (; i % 8; i++) { + val <<= 4; + val |= (i % (tp->irq_cnt - 1)); + } + tw32(reg, val); + reg += 4; + } + } /* Setup the "secret" hash key. */ tw32(MAC_RSS_HASH_KEY_0, 0x5f865437); @@ -9001,7 +8988,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) /* Prevent chip from dropping frames when flow control * is enabled. */ - if (tg3_flag(tp, 57765_CLASS)) + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) val = 1; else val = 2; @@ -9216,7 +9203,7 @@ static void tg3_timer(unsigned long __opaque) spin_lock(&tp->lock); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || - tg3_flag(tp, 57765_CLASS)) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tg3_chk_missed_msi(tp); if (!tg3_flag(tp, TAGGED_STATUS)) { @@ -9668,8 +9655,6 @@ static int tg3_open(struct net_device *dev) */ tg3_ints_init(tp); - tg3_rss_init_indir_tbl(tp); - /* The placement of this call is tied * to the setup and use of Host TX descriptors. */ @@ -9701,8 +9686,8 @@ static int tg3_open(struct net_device *dev) tg3_free_rings(tp); } else { if (tg3_flag(tp, TAGGED_STATUS) && - GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && - !tg3_flag(tp, 57765_CLASS)) + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 && + GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57765) tp->timer_offset = HZ; else tp->timer_offset = HZ / 10; @@ -9783,6 +9768,10 @@ static int tg3_open(struct net_device *dev) return err; } +static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *, + struct rtnl_link_stats64 *); +static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *); + static int tg3_close(struct net_device *dev) { int i; @@ -9814,9 +9803,10 @@ static int tg3_close(struct net_device *dev) tg3_ints_fini(tp); - /* Clear stats across close / open calls */ - memset(&tp->net_stats_prev, 0, sizeof(tp->net_stats_prev)); - memset(&tp->estats_prev, 0, sizeof(tp->estats_prev)); + tg3_get_stats64(tp->dev, &tp->net_stats_prev); + + memcpy(&tp->estats_prev, tg3_get_estats(tp), + sizeof(tp->estats_prev)); tg3_napi_fini(tp); @@ -9864,9 +9854,9 @@ static u64 calc_crc_errors(struct tg3 *tp) estats->member = old_estats->member + \ get_stat64(&hw_stats->member) -static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp, - struct tg3_ethtool_stats *estats) +static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp) { + struct tg3_ethtool_stats *estats = &tp->estats; struct tg3_ethtool_stats *old_estats = &tp->estats_prev; struct tg3_hw_stats *hw_stats = tp->hw_stats; @@ -10314,10 +10304,9 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->advertising |= ADVERTISED_Asym_Pause; } } - if (netif_running(dev) && netif_carrier_ok(dev)) { + if (netif_running(dev)) { ethtool_cmd_speed_set(cmd, tp->link_config.active_speed); cmd->duplex = tp->link_config.active_duplex; - cmd->lp_advertising = tp->link_config.rmt_adv; if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) { if (tp->phy_flags & TG3_PHYFLG_MDIX_STATE) cmd->eth_tp_mdix = ETH_TP_MDI_X; @@ -10594,12 +10583,12 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam epause->autoneg = !!tg3_flag(tp, PAUSE_AUTONEG); - if (tp->link_config.flowctrl & FLOW_CTRL_RX) + if (tp->link_config.active_flowctrl & FLOW_CTRL_RX) epause->rx_pause = 1; else epause->rx_pause = 0; - if (tp->link_config.flowctrl & FLOW_CTRL_TX) + if (tp->link_config.active_flowctrl & FLOW_CTRL_TX) epause->tx_pause = 1; else epause->tx_pause = 0; @@ -10773,8 +10762,7 @@ static void tg3_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *estats, u64 *tmp_stats) { struct tg3 *tp = netdev_priv(dev); - - tg3_get_estats(tp, (struct tg3_ethtool_stats *)tmp_stats); + memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats)); } static __be32 *tg3_vpd_readblock(struct tg3 *tp, u32 *vpdlen) @@ -11357,7 +11345,7 @@ static int tg3_test_memory(struct tg3 *tp) if (tg3_flag(tp, 5717_PLUS)) mem_tbl = mem_tbl_5717; - else if (tg3_flag(tp, 57765_CLASS)) + else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) mem_tbl = mem_tbl_57765; else if (tg3_flag(tp, 5755_PLUS)) mem_tbl = mem_tbl_5755; @@ -12618,7 +12606,7 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tg3_get_5906_nvram_info(tp); else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || - tg3_flag(tp, 57765_CLASS)) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tg3_get_57780_nvram_info(tp); else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) @@ -13327,7 +13315,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) && !tg3_flag(tp, ENABLE_APE) && !tg3_flag(tp, ENABLE_ASF)) { - u32 bmsr, dummy; + u32 bmsr, mask; tg3_readphy(tp, MII_BMSR, &bmsr); if (!tg3_readphy(tp, MII_BMSR, &bmsr) && @@ -13340,7 +13328,10 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) tg3_phy_set_wirespeed(tp); - if (!tg3_phy_copper_an_config_ok(tp, &dummy)) { + mask = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full); + if (!tg3_copper_is_advertising_all(tp, mask)) { tg3_phy_autoneg_cfg(tp, tp->link_config.advertising, tp->link_config.flowctrl); @@ -13462,17 +13453,6 @@ static void __devinit tg3_read_vpd(struct tg3 *tp) strcpy(tp->board_part_number, "BCM57795"); else goto nomatch; - } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) { - if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57762) - strcpy(tp->board_part_number, "BCM57762"); - else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57766) - strcpy(tp->board_part_number, "BCM57766"); - else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57782) - strcpy(tp->board_part_number, "BCM57782"); - else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57786) - strcpy(tp->board_part_number, "BCM57786"); - else - goto nomatch; } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { strcpy(tp->board_part_number, "BCM95906"); } else { @@ -13811,11 +13791,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57762 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57766 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57782 || - tp->pdev->device == TG3PCI_DEVICE_TIGON3_57786) + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795) pci_read_config_dword(tp->pdev, TG3PCI_GEN15_PRODID_ASICREV, &prod_id_asic_rev); @@ -13962,10 +13938,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tg3_flag_set(tp, 5717_PLUS); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) - tg3_flag_set(tp, 57765_CLASS); - - if (tg3_flag(tp, 57765_CLASS) || tg3_flag(tp, 5717_PLUS)) + tg3_flag(tp, 5717_PLUS)) tg3_flag_set(tp, 57765_PLUS); /* Intentionally exclude ASIC_REV_5906 */ @@ -14058,9 +14031,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tg3_flag_set(tp, SHORT_DMA_BUG); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) - tp->dma_limit = TG3_TX_BD_DMA_MAX_4K; - else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766) - tp->dma_limit = TG3_TX_BD_DMA_MAX_2K; + tg3_flag_set(tp, 4K_FIFO_LIMIT); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || @@ -14344,7 +14315,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || - tg3_flag(tp, 57765_CLASS)) + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 || diff --git a/trunk/drivers/net/ethernet/broadcom/tg3.h b/trunk/drivers/net/ethernet/broadcom/tg3.h index aea8f72c24fa..9cc10a868dcd 100644 --- a/trunk/drivers/net/ethernet/broadcom/tg3.h +++ b/trunk/drivers/net/ethernet/broadcom/tg3.h @@ -31,8 +31,6 @@ #define TG3_RX_RET_MAX_SIZE_5705 512 #define TG3_RX_RET_MAX_SIZE_5717 4096 -#define TG3_RSS_INDIR_TBL_SIZE 128 - /* First 256 bytes are a mirror of PCI config space. */ #define TG3PCI_VENDOR 0x00000000 #define TG3PCI_VENDOR_BROADCOM 0x14e4 @@ -59,10 +57,6 @@ #define TG3PCI_DEVICE_TIGON3_57795 0x16b6 #define TG3PCI_DEVICE_TIGON3_5719 0x1657 #define TG3PCI_DEVICE_TIGON3_5720 0x165f -#define TG3PCI_DEVICE_TIGON3_57762 0x1682 -#define TG3PCI_DEVICE_TIGON3_57766 0x1686 -#define TG3PCI_DEVICE_TIGON3_57786 0x16b3 -#define TG3PCI_DEVICE_TIGON3_57782 0x16b7 /* 0x04 --> 0x2c unused */ #define TG3PCI_SUBVENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM #define TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6 0x1644 @@ -174,7 +168,6 @@ #define ASIC_REV_57765 0x57785 #define ASIC_REV_5719 0x5719 #define ASIC_REV_5720 0x5720 -#define ASIC_REV_57766 0x57766 #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define CHIPREV_5700_AX 0x70 #define CHIPREV_5700_BX 0x71 @@ -1347,7 +1340,6 @@ #define RDMAC_MODE_MBUF_SBD_CRPT_ENAB 0x00002000 #define RDMAC_MODE_FIFO_SIZE_128 0x00020000 #define RDMAC_MODE_FIFO_LONG_BURST 0x00030000 -#define RDMAC_MODE_JMB_2K_MMRR 0x00800000 #define RDMAC_MODE_MULT_DMA_RD_DIS 0x01000000 #define RDMAC_MODE_IPV4_LSO_EN 0x08000000 #define RDMAC_MODE_IPV6_LSO_EN 0x10000000 @@ -2706,7 +2698,6 @@ struct tg3_link_config { #define DUPLEX_INVALID 0xff #define AUTONEG_INVALID 0xff u16 active_speed; - u32 rmt_adv; /* When we go in and out of low power mode we need * to swap with this state. @@ -2882,8 +2873,6 @@ enum TG3_FLAGS { TG3_FLAG_NVRAM_BUFFERED, TG3_FLAG_SUPPORT_MSI, TG3_FLAG_SUPPORT_MSIX, - TG3_FLAG_USING_MSI, - TG3_FLAG_USING_MSIX, TG3_FLAG_PCIX_MODE, TG3_FLAG_PCI_HIGH_SPEED, TG3_FLAG_PCI_32BIT, @@ -2899,6 +2888,7 @@ enum TG3_FLAGS { TG3_FLAG_CHIP_RESETTING, TG3_FLAG_INIT_COMPLETE, TG3_FLAG_TSO_BUG, + TG3_FLAG_IS_5788, TG3_FLAG_MAX_RXPEND_64, TG3_FLAG_TSO_CAPABLE, TG3_FLAG_PCI_EXPRESS, /* BCM5785 + pci_is_pcie() */ @@ -2907,9 +2897,14 @@ enum TG3_FLAGS { TG3_FLAG_IS_NIC, TG3_FLAG_FLASH, TG3_FLAG_HW_TSO_1, - TG3_FLAG_HW_TSO_2, + TG3_FLAG_5705_PLUS, + TG3_FLAG_5750_PLUS, TG3_FLAG_HW_TSO_3, + TG3_FLAG_USING_MSI, + TG3_FLAG_USING_MSIX, TG3_FLAG_ICH_WORKAROUND, + TG3_FLAG_5780_CLASS, + TG3_FLAG_HW_TSO_2, TG3_FLAG_1SHOT_MSI, TG3_FLAG_NO_FWARE_REPORTED, TG3_FLAG_NO_NVRAM_ADDR_TRANS, @@ -2923,23 +2918,18 @@ enum TG3_FLAGS { TG3_FLAG_RGMII_EXT_IBND_RX_EN, TG3_FLAG_RGMII_EXT_IBND_TX_EN, TG3_FLAG_CLKREQ_BUG, + TG3_FLAG_5755_PLUS, TG3_FLAG_NO_NVRAM, TG3_FLAG_ENABLE_RSS, TG3_FLAG_ENABLE_TSS, TG3_FLAG_SHORT_DMA_BUG, TG3_FLAG_USE_JUMBO_BDFLAG, TG3_FLAG_L1PLLPD_EN, + TG3_FLAG_57765_PLUS, TG3_FLAG_APE_HAS_NCSI, + TG3_FLAG_5717_PLUS, TG3_FLAG_4K_FIFO_LIMIT, TG3_FLAG_RESET_TASK_PENDING, - TG3_FLAG_5705_PLUS, - TG3_FLAG_IS_5788, - TG3_FLAG_5750_PLUS, - TG3_FLAG_5780_CLASS, - TG3_FLAG_5755_PLUS, - TG3_FLAG_57765_PLUS, - TG3_FLAG_57765_CLASS, - TG3_FLAG_5717_PLUS, /* Add new flags before this comment and TG3_FLAG_NUMBER_OF_FLAGS */ TG3_FLAG_NUMBER_OF_FLAGS, /* Last entry in enum TG3_FLAGS */ @@ -3003,7 +2993,6 @@ struct tg3 { /* begin "tx thread" cacheline section */ void (*write32_tx_mbox) (struct tg3 *, u32, u32); - u32 dma_limit; /* begin "rx thread" cacheline section */ struct tg3_napi napi[TG3_IRQ_MAX_VECS]; @@ -3024,6 +3013,7 @@ struct tg3 { unsigned long rx_dropped; unsigned long tx_dropped; struct rtnl_link_stats64 net_stats_prev; + struct tg3_ethtool_stats estats; struct tg3_ethtool_stats estats_prev; DECLARE_BITMAP(tg3_flags, TG3_FLAG_NUMBER_OF_FLAGS); @@ -3154,7 +3144,6 @@ struct tg3 { u32 led_ctrl; u32 phy_otp; u32 setlpicnt; - u8 rss_ind_tbl[TG3_RSS_INDIR_TBL_SIZE]; #define TG3_BPN_SIZE 24 char board_part_number[TG3_BPN_SIZE]; diff --git a/trunk/drivers/net/ethernet/brocade/bna/bnad.c b/trunk/drivers/net/ethernet/brocade/bna/bnad.c index aac3a3b710a0..7f3091e7eb42 100644 --- a/trunk/drivers/net/ethernet/brocade/bna/bnad.c +++ b/trunk/drivers/net/ethernet/brocade/bna/bnad.c @@ -2968,7 +2968,7 @@ bnad_change_mtu(struct net_device *netdev, int new_mtu) return err; } -static int +static void bnad_vlan_rx_add_vid(struct net_device *netdev, unsigned short vid) { @@ -2976,7 +2976,7 @@ bnad_vlan_rx_add_vid(struct net_device *netdev, unsigned long flags; if (!bnad->rx_info[0].rx) - return 0; + return; mutex_lock(&bnad->conf_mutex); @@ -2986,11 +2986,9 @@ bnad_vlan_rx_add_vid(struct net_device *netdev, spin_unlock_irqrestore(&bnad->bna_lock, flags); mutex_unlock(&bnad->conf_mutex); - - return 0; } -static int +static void bnad_vlan_rx_kill_vid(struct net_device *netdev, unsigned short vid) { @@ -2998,7 +2996,7 @@ bnad_vlan_rx_kill_vid(struct net_device *netdev, unsigned long flags; if (!bnad->rx_info[0].rx) - return 0; + return; mutex_lock(&bnad->conf_mutex); @@ -3008,8 +3006,6 @@ bnad_vlan_rx_kill_vid(struct net_device *netdev, spin_unlock_irqrestore(&bnad->bna_lock, flags); mutex_unlock(&bnad->conf_mutex); - - return 0; } #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index fccbe490c7f0..a34e7ce7e214 100644 --- a/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/trunk/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -1871,30 +1871,30 @@ static int cxgb_set_features(struct net_device *dev, netdev_features_t features) return err; } -static u32 get_rss_table_size(struct net_device *dev) +static int get_rss_table(struct net_device *dev, struct ethtool_rxfh_indir *p) { const struct port_info *pi = netdev_priv(dev); + unsigned int n = min_t(unsigned int, p->size, pi->rss_size); - return pi->rss_size; -} - -static int get_rss_table(struct net_device *dev, u32 *p) -{ - const struct port_info *pi = netdev_priv(dev); - unsigned int n = pi->rss_size; - + p->size = pi->rss_size; while (n--) - p[n] = pi->rss[n]; + p->ring_index[n] = pi->rss[n]; return 0; } -static int set_rss_table(struct net_device *dev, const u32 *p) +static int set_rss_table(struct net_device *dev, + const struct ethtool_rxfh_indir *p) { unsigned int i; struct port_info *pi = netdev_priv(dev); - for (i = 0; i < pi->rss_size; i++) - pi->rss[i] = p[i]; + if (p->size != pi->rss_size) + return -EINVAL; + for (i = 0; i < p->size; i++) + if (p->ring_index[i] >= pi->nqsets) + return -EINVAL; + for (i = 0; i < p->size; i++) + pi->rss[i] = p->ring_index[i]; if (pi->adapter->flags & FULL_INIT_DONE) return write_rss(pi, pi->rss); return 0; @@ -1989,7 +1989,6 @@ static struct ethtool_ops cxgb_ethtool_ops = { .get_wol = get_wol, .set_wol = set_wol, .get_rxnfc = get_rxnfc, - .get_rxfh_indir_size = get_rss_table_size, .get_rxfh_indir = get_rss_table, .set_rxfh_indir = set_rss_table, .flash_device = set_flash, @@ -3449,7 +3448,7 @@ static int __devinit init_rss(struct adapter *adap) if (!pi->rss) return -ENOMEM; for (j = 0; j < pi->rss_size; j++) - pi->rss[j] = ethtool_rxfh_indir_default(j, pi->nqsets); + pi->rss[j] = j % pi->nqsets; } return 0; } diff --git a/trunk/drivers/net/ethernet/cisco/enic/enic_dev.c b/trunk/drivers/net/ethernet/cisco/enic/enic_dev.c index bf0fc56dba19..fd6247b3c0ee 100644 --- a/trunk/drivers/net/ethernet/cisco/enic/enic_dev.c +++ b/trunk/drivers/net/ethernet/cisco/enic/enic_dev.c @@ -212,29 +212,23 @@ int enic_dev_deinit_done(struct enic *enic, int *status) } /* rtnl lock is held */ -int enic_vlan_rx_add_vid(struct net_device *netdev, u16 vid) +void enic_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct enic *enic = netdev_priv(netdev); - int err; spin_lock(&enic->devcmd_lock); - err = enic_add_vlan(enic, vid); + enic_add_vlan(enic, vid); spin_unlock(&enic->devcmd_lock); - - return err; } /* rtnl lock is held */ -int enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +void enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct enic *enic = netdev_priv(netdev); - int err; spin_lock(&enic->devcmd_lock); - err = enic_del_vlan(enic, vid); + enic_del_vlan(enic, vid); spin_unlock(&enic->devcmd_lock); - - return err; } int enic_dev_enable2(struct enic *enic, int active) diff --git a/trunk/drivers/net/ethernet/cisco/enic/enic_dev.h b/trunk/drivers/net/ethernet/cisco/enic/enic_dev.h index da1cba3c410e..1f83a4747ba0 100644 --- a/trunk/drivers/net/ethernet/cisco/enic/enic_dev.h +++ b/trunk/drivers/net/ethernet/cisco/enic/enic_dev.h @@ -46,8 +46,8 @@ int enic_dev_packet_filter(struct enic *enic, int directed, int multicast, int broadcast, int promisc, int allmulti); int enic_dev_add_addr(struct enic *enic, u8 *addr); int enic_dev_del_addr(struct enic *enic, u8 *addr); -int enic_vlan_rx_add_vid(struct net_device *netdev, u16 vid); -int enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); +void enic_vlan_rx_add_vid(struct net_device *netdev, u16 vid); +void enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); int enic_dev_notify_unset(struct enic *enic); int enic_dev_hang_notify(struct enic *enic); int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic); diff --git a/trunk/drivers/net/ethernet/emulex/benet/be.h b/trunk/drivers/net/ethernet/emulex/benet/be.h index a3588fb8d6a9..34f162db9f2e 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be.h +++ b/trunk/drivers/net/ethernet/emulex/benet/be.h @@ -288,11 +288,11 @@ struct be_drv_stats { }; struct be_vf_cfg { - unsigned char mac_addr[ETH_ALEN]; - int if_handle; - int pmac_id; - u16 vlan_tag; - u32 tx_rate; + unsigned char vf_mac_addr[ETH_ALEN]; + int vf_if_handle; + int vf_pmac_id; + u16 vf_vlan_tag; + u32 vf_tx_rate; }; struct be_adapter { @@ -368,20 +368,16 @@ struct be_adapter { u32 flash_status; struct completion flash_compl; - u32 num_vfs; - u8 is_virtfn; - struct be_vf_cfg *vf_cfg; bool be3_native; + bool sriov_enabled; + struct be_vf_cfg *vf_cfg; + u8 is_virtfn; u32 sli_family; u8 hba_port_num; u16 pvid; }; #define be_physfn(adapter) (!adapter->is_virtfn) -#define sriov_enabled(adapter) (adapter->num_vfs > 0) -#define for_all_vfs(adapter, vf_cfg, i) \ - for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \ - i++, vf_cfg++) /* BladeEngine Generation numbers */ #define BE_GEN2 2 diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_ethtool.c b/trunk/drivers/net/ethernet/emulex/benet/be_ethtool.c index 6ba2dc6bdf7b..575c78306313 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -520,13 +520,16 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) return 0; } -static void be_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) +static void +be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) { struct be_adapter *adapter = netdev_priv(netdev); - ring->rx_max_pending = ring->rx_pending = adapter->rx_obj[0].q.len; - ring->tx_max_pending = ring->tx_pending = adapter->tx_obj[0].q.len; + ring->rx_max_pending = adapter->rx_obj[0].q.len; + ring->tx_max_pending = adapter->tx_obj[0].q.len; + + ring->rx_pending = atomic_read(&adapter->rx_obj[0].q.used); + ring->tx_pending = atomic_read(&adapter->tx_obj[0].q.used); } static void diff --git a/trunk/drivers/net/ethernet/emulex/benet/be_main.c b/trunk/drivers/net/ethernet/emulex/benet/be_main.c index 9b5304a653f3..7236280c1af0 100644 --- a/trunk/drivers/net/ethernet/emulex/benet/be_main.c +++ b/trunk/drivers/net/ethernet/emulex/benet/be_main.c @@ -27,13 +27,12 @@ MODULE_DESCRIPTION(DRV_DESC " " DRV_VER); MODULE_AUTHOR("ServerEngines Corporation"); MODULE_LICENSE("GPL"); -static unsigned int num_vfs; -module_param(num_vfs, uint, S_IRUGO); -MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize"); - static ushort rx_frag_size = 2048; +static unsigned int num_vfs; module_param(rx_frag_size, ushort, S_IRUGO); +module_param(num_vfs, uint, S_IRUGO); MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data."); +MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize"); static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, @@ -317,8 +316,6 @@ static void populate_be3_stats(struct be_adapter *adapter) struct be_drv_stats *drvs = &adapter->drv_stats; be_dws_le_to_cpu(hw_stats, sizeof(*hw_stats)); - drvs->pmem_fifo_overflow_drop = port_stats->pmem_fifo_overflow_drop; - drvs->rx_priority_pause_frames = port_stats->rx_priority_pause_frames; drvs->rx_pause_frames = port_stats->rx_pause_frames; drvs->rx_crc_errors = port_stats->rx_crc_errors; drvs->rx_control_frames = port_stats->rx_control_frames; @@ -553,26 +550,11 @@ static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len) wrb->frag_len = len & ETH_WRB_FRAG_LEN_MASK; } -static inline u16 be_get_tx_vlan_tag(struct be_adapter *adapter, - struct sk_buff *skb) -{ - u8 vlan_prio; - u16 vlan_tag; - - vlan_tag = vlan_tx_tag_get(skb); - vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; - /* If vlan priority provided by OS is NOT in available bmap */ - if (!(adapter->vlan_prio_bmap & (1 << vlan_prio))) - vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) | - adapter->recommended_prio; - - return vlan_tag; -} - static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, struct sk_buff *skb, u32 wrb_cnt, u32 len) { - u16 vlan_tag; + u8 vlan_prio = 0; + u16 vlan_tag = 0; memset(hdr, 0, sizeof(*hdr)); @@ -603,7 +585,12 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, if (vlan_tx_tag_present(skb)) { AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1); - vlan_tag = be_get_tx_vlan_tag(adapter, skb); + vlan_tag = vlan_tx_tag_get(skb); + vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; + /* If vlan priority provided by OS is NOT in available bmap */ + if (!(adapter->vlan_prio_bmap & (1 << vlan_prio))) + vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) | + adapter->recommended_prio; AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, hdr, vlan_tag); } @@ -706,25 +693,6 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, u32 start = txq->head; bool dummy_wrb, stopped = false; - /* For vlan tagged pkts, BE - * 1) calculates checksum even when CSO is not requested - * 2) calculates checksum wrongly for padded pkt less than - * 60 bytes long. - * As a workaround disable TX vlan offloading in such cases. - */ - if (unlikely(vlan_tx_tag_present(skb) && - (skb->ip_summed != CHECKSUM_PARTIAL || skb->len <= 60))) { - skb = skb_share_check(skb, GFP_ATOMIC); - if (unlikely(!skb)) - goto tx_drop; - - skb = __vlan_put_tag(skb, be_get_tx_vlan_tag(adapter, skb)); - if (unlikely(!skb)) - goto tx_drop; - - skb->vlan_tci = 0; - } - wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb); @@ -752,7 +720,6 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, txq->head = start; dev_kfree_skb_any(skb); } -tx_drop: return NETDEV_TX_OK; } @@ -780,15 +747,15 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) */ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) { - struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf_num]; u16 vtag[BE_NUM_VLANS_SUPPORTED]; u16 ntags = 0, i; int status = 0; + u32 if_handle; if (vf) { - vtag[0] = cpu_to_le16(vf_cfg->vlan_tag); - status = be_cmd_vlan_config(adapter, vf_cfg->if_handle, vtag, - 1, 1, 0); + if_handle = adapter->vf_cfg[vf_num].vf_if_handle; + vtag[0] = cpu_to_le16(adapter->vf_cfg[vf_num].vf_vlan_tag); + status = be_cmd_vlan_config(adapter, if_handle, vtag, 1, 1, 0); } /* No need to further configure vids if in promiscuous mode */ @@ -813,35 +780,31 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) return status; } -static int be_vlan_add_vid(struct net_device *netdev, u16 vid) +static void be_vlan_add_vid(struct net_device *netdev, u16 vid) { struct be_adapter *adapter = netdev_priv(netdev); adapter->vlans_added++; if (!be_physfn(adapter)) - return 0; + return; adapter->vlan_tag[vid] = 1; if (adapter->vlans_added <= (adapter->max_vlans + 1)) be_vid_config(adapter, false, 0); - - return 0; } -static int be_vlan_rem_vid(struct net_device *netdev, u16 vid) +static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) { struct be_adapter *adapter = netdev_priv(netdev); adapter->vlans_added--; if (!be_physfn(adapter)) - return 0; + return; adapter->vlan_tag[vid] = 0; if (adapter->vlans_added <= adapter->max_vlans) be_vid_config(adapter, false, 0); - - return 0; } static void be_set_rx_mode(struct net_device *netdev) @@ -878,30 +841,31 @@ static void be_set_rx_mode(struct net_device *netdev) static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) { struct be_adapter *adapter = netdev_priv(netdev); - struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; int status; - if (!sriov_enabled(adapter)) + if (!adapter->sriov_enabled) return -EPERM; - if (!is_valid_ether_addr(mac) || vf >= adapter->num_vfs) + if (!is_valid_ether_addr(mac) || (vf >= num_vfs)) return -EINVAL; if (lancer_chip(adapter)) { status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1); } else { - status = be_cmd_pmac_del(adapter, vf_cfg->if_handle, - vf_cfg->pmac_id, vf + 1); + status = be_cmd_pmac_del(adapter, + adapter->vf_cfg[vf].vf_if_handle, + adapter->vf_cfg[vf].vf_pmac_id, vf + 1); - status = be_cmd_pmac_add(adapter, mac, vf_cfg->if_handle, - &vf_cfg->pmac_id, vf + 1); + status = be_cmd_pmac_add(adapter, mac, + adapter->vf_cfg[vf].vf_if_handle, + &adapter->vf_cfg[vf].vf_pmac_id, vf + 1); } if (status) dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n", mac, vf); else - memcpy(vf_cfg->mac_addr, mac, ETH_ALEN); + memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN); return status; } @@ -910,19 +874,18 @@ static int be_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *vi) { struct be_adapter *adapter = netdev_priv(netdev); - struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; - if (!sriov_enabled(adapter)) + if (!adapter->sriov_enabled) return -EPERM; - if (vf >= adapter->num_vfs) + if (vf >= num_vfs) return -EINVAL; vi->vf = vf; - vi->tx_rate = vf_cfg->tx_rate; - vi->vlan = vf_cfg->vlan_tag; + vi->tx_rate = adapter->vf_cfg[vf].vf_tx_rate; + vi->vlan = adapter->vf_cfg[vf].vf_vlan_tag; vi->qos = 0; - memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN); + memcpy(&vi->mac, adapter->vf_cfg[vf].vf_mac_addr, ETH_ALEN); return 0; } @@ -933,17 +896,17 @@ static int be_set_vf_vlan(struct net_device *netdev, struct be_adapter *adapter = netdev_priv(netdev); int status = 0; - if (!sriov_enabled(adapter)) + if (!adapter->sriov_enabled) return -EPERM; - if (vf >= adapter->num_vfs || vlan > 4095) + if ((vf >= num_vfs) || (vlan > 4095)) return -EINVAL; if (vlan) { - adapter->vf_cfg[vf].vlan_tag = vlan; + adapter->vf_cfg[vf].vf_vlan_tag = vlan; adapter->vlans_added++; } else { - adapter->vf_cfg[vf].vlan_tag = 0; + adapter->vf_cfg[vf].vf_vlan_tag = 0; adapter->vlans_added--; } @@ -961,16 +924,16 @@ static int be_set_vf_tx_rate(struct net_device *netdev, struct be_adapter *adapter = netdev_priv(netdev); int status = 0; - if (!sriov_enabled(adapter)) + if (!adapter->sriov_enabled) return -EPERM; - if (vf >= adapter->num_vfs || rate < 0) + if ((vf >= num_vfs) || (rate < 0)) return -EINVAL; if (rate > 10000) rate = 10000; - adapter->vf_cfg[vf].tx_rate = rate; + adapter->vf_cfg[vf].vf_tx_rate = rate; status = be_cmd_set_qos(adapter, rate / 10, vf + 1); if (status) @@ -1686,7 +1649,8 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) static int be_num_txqs_want(struct be_adapter *adapter) { - if (sriov_enabled(adapter) || be_is_mc(adapter) || + if ((num_vfs && adapter->sriov_enabled) || + be_is_mc(adapter) || lancer_chip(adapter) || !be_physfn(adapter) || adapter->generation == BE_GEN2) return 1; @@ -1768,8 +1732,8 @@ static void be_rx_queues_destroy(struct be_adapter *adapter) static u32 be_num_rxqs_want(struct be_adapter *adapter) { if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && - !sriov_enabled(adapter) && be_physfn(adapter) && - !be_is_mc(adapter)) { + !adapter->sriov_enabled && be_physfn(adapter) && + !be_is_mc(adapter)) { return 1 + MAX_RSS_QS; /* one default non-RSS queue */ } else { dev_warn(&adapter->pdev->dev, @@ -2116,28 +2080,27 @@ static void be_msix_enable(struct be_adapter *adapter) static int be_sriov_enable(struct be_adapter *adapter) { be_check_sriov_fn_type(adapter); - #ifdef CONFIG_PCI_IOV if (be_physfn(adapter) && num_vfs) { int status, pos; - u16 dev_vfs; + u16 nvfs; pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV); pci_read_config_word(adapter->pdev, - pos + PCI_SRIOV_TOTAL_VF, &dev_vfs); + pos + PCI_SRIOV_TOTAL_VF, &nvfs); - adapter->num_vfs = min_t(u16, num_vfs, dev_vfs); - if (adapter->num_vfs != num_vfs) + if (num_vfs > nvfs) { dev_info(&adapter->pdev->dev, - "Device supports %d VFs and not %d\n", - adapter->num_vfs, num_vfs); + "Device supports %d VFs and not %d\n", + nvfs, num_vfs); + num_vfs = nvfs; + } - status = pci_enable_sriov(adapter->pdev, adapter->num_vfs); - if (status) - adapter->num_vfs = 0; + status = pci_enable_sriov(adapter->pdev, num_vfs); + adapter->sriov_enabled = status ? false : true; - if (adapter->num_vfs) { + if (adapter->sriov_enabled) { adapter->vf_cfg = kcalloc(num_vfs, sizeof(struct be_vf_cfg), GFP_KERNEL); @@ -2152,10 +2115,10 @@ static int be_sriov_enable(struct be_adapter *adapter) static void be_sriov_disable(struct be_adapter *adapter) { #ifdef CONFIG_PCI_IOV - if (sriov_enabled(adapter)) { + if (adapter->sriov_enabled) { pci_disable_sriov(adapter->pdev); kfree(adapter->vf_cfg); - adapter->num_vfs = 0; + adapter->sriov_enabled = false; } #endif } @@ -2467,24 +2430,24 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter) u32 vf; int status = 0; u8 mac[ETH_ALEN]; - struct be_vf_cfg *vf_cfg; be_vf_eth_addr_generate(adapter, mac); - for_all_vfs(adapter, vf_cfg, vf) { + for (vf = 0; vf < num_vfs; vf++) { if (lancer_chip(adapter)) { status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1); } else { status = be_cmd_pmac_add(adapter, mac, - vf_cfg->if_handle, - &vf_cfg->pmac_id, vf + 1); + adapter->vf_cfg[vf].vf_if_handle, + &adapter->vf_cfg[vf].vf_pmac_id, + vf + 1); } if (status) dev_err(&adapter->pdev->dev, "Mac address assignment failed for VF %d\n", vf); else - memcpy(vf_cfg->mac_addr, mac, ETH_ALEN); + memcpy(adapter->vf_cfg[vf].vf_mac_addr, mac, ETH_ALEN); mac[5] += 1; } @@ -2493,23 +2456,25 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter) static void be_vf_clear(struct be_adapter *adapter) { - struct be_vf_cfg *vf_cfg; u32 vf; - for_all_vfs(adapter, vf_cfg, vf) { + for (vf = 0; vf < num_vfs; vf++) { if (lancer_chip(adapter)) be_cmd_set_mac_list(adapter, NULL, 0, vf + 1); else - be_cmd_pmac_del(adapter, vf_cfg->if_handle, - vf_cfg->pmac_id, vf + 1); - - be_cmd_if_destroy(adapter, vf_cfg->if_handle, vf + 1); + be_cmd_pmac_del(adapter, + adapter->vf_cfg[vf].vf_if_handle, + adapter->vf_cfg[vf].vf_pmac_id, vf + 1); } + + for (vf = 0; vf < num_vfs; vf++) + be_cmd_if_destroy(adapter, adapter->vf_cfg[vf].vf_if_handle, + vf + 1); } static int be_clear(struct be_adapter *adapter) { - if (sriov_enabled(adapter)) + if (be_physfn(adapter) && adapter->sriov_enabled) be_vf_clear(adapter); be_cmd_if_destroy(adapter, adapter->if_handle, 0); @@ -2525,18 +2490,16 @@ static int be_clear(struct be_adapter *adapter) static void be_vf_setup_init(struct be_adapter *adapter) { - struct be_vf_cfg *vf_cfg; int vf; - for_all_vfs(adapter, vf_cfg, vf) { - vf_cfg->if_handle = -1; - vf_cfg->pmac_id = -1; + for (vf = 0; vf < num_vfs; vf++) { + adapter->vf_cfg[vf].vf_if_handle = -1; + adapter->vf_cfg[vf].vf_pmac_id = -1; } } static int be_vf_setup(struct be_adapter *adapter) { - struct be_vf_cfg *vf_cfg; u32 cap_flags, en_flags, vf; u16 lnk_speed; int status; @@ -2545,9 +2508,11 @@ static int be_vf_setup(struct be_adapter *adapter) cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_MULTICAST; - for_all_vfs(adapter, vf_cfg, vf) { + + for (vf = 0; vf < num_vfs; vf++) { status = be_cmd_if_create(adapter, cap_flags, en_flags, NULL, - &vf_cfg->if_handle, NULL, vf + 1); + &adapter->vf_cfg[vf].vf_if_handle, + NULL, vf+1); if (status) goto err; } @@ -2556,12 +2521,12 @@ static int be_vf_setup(struct be_adapter *adapter) if (status) goto err; - for_all_vfs(adapter, vf_cfg, vf) { + for (vf = 0; vf < num_vfs; vf++) { status = be_cmd_link_status_query(adapter, NULL, &lnk_speed, - vf + 1); + vf + 1); if (status) goto err; - vf_cfg->tx_rate = lnk_speed * 10; + adapter->vf_cfg[vf].vf_tx_rate = lnk_speed * 10; } return 0; err: @@ -2689,7 +2654,7 @@ static int be_setup(struct be_adapter *adapter) pcie_set_readrq(adapter->pdev, 4096); - if (sriov_enabled(adapter)) { + if (be_physfn(adapter) && adapter->sriov_enabled) { status = be_vf_setup(adapter); if (status) goto err; @@ -2701,19 +2666,6 @@ static int be_setup(struct be_adapter *adapter) return status; } -#ifdef CONFIG_NET_POLL_CONTROLLER -static void be_netpoll(struct net_device *netdev) -{ - struct be_adapter *adapter = netdev_priv(netdev); - struct be_rx_obj *rxo; - int i; - - event_handle(adapter, &adapter->tx_eq, false); - for_all_rx_queues(adapter, rxo, i) - event_handle(adapter, &rxo->rx_eq, true); -} -#endif - #define FW_FILE_HDR_SIGN "ServerEngines Corp. " static bool be_flash_redboot(struct be_adapter *adapter, const u8 *p, u32 img_start, int image_size, @@ -3062,10 +3014,7 @@ static struct net_device_ops be_netdev_ops = { .ndo_set_vf_mac = be_set_vf_mac, .ndo_set_vf_vlan = be_set_vf_vlan, .ndo_set_vf_tx_rate = be_set_vf_tx_rate, - .ndo_get_vf_config = be_get_vf_config, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = be_netpoll, -#endif + .ndo_get_vf_config = be_get_vf_config }; static void be_netdev_init(struct net_device *netdev) diff --git a/trunk/drivers/net/ethernet/freescale/Kconfig b/trunk/drivers/net/ethernet/freescale/Kconfig index 820de8b9ff08..5272f9d4dda9 100644 --- a/trunk/drivers/net/ethernet/freescale/Kconfig +++ b/trunk/drivers/net/ethernet/freescale/Kconfig @@ -21,7 +21,7 @@ config NET_VENDOR_FREESCALE if NET_VENDOR_FREESCALE config FEC - tristate "FEC ethernet controller (of ColdFire and some i.MX CPUs)" + bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)" depends on (M523x || M527x || M5272 || M528x || M520x || M532x || \ ARCH_MXC || ARCH_MXS) default ARCH_MXC || ARCH_MXS if ARM diff --git a/trunk/drivers/net/ethernet/freescale/fec.c b/trunk/drivers/net/ethernet/freescale/fec.c index 4ea2bdc852f8..1124ce0a1594 100644 --- a/trunk/drivers/net/ethernet/freescale/fec.c +++ b/trunk/drivers/net/ethernet/freescale/fec.c @@ -99,7 +99,7 @@ static struct platform_device_id fec_devtype[] = { MODULE_DEVICE_TABLE(platform, fec_devtype); enum imx_fec_type { - IMX25_FEC = 1, /* runs on i.mx25/50/53 */ + IMX25_FEC = 1, /* runs on i.mx25/50/53 */ IMX27_FEC, /* runs on i.mx27/35/51 */ IMX28_FEC, IMX6Q_FEC, @@ -132,7 +132,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); #elif defined (CONFIG_M5272C3) #define FEC_FLASHMAC (0xffe04000 + 4) #elif defined(CONFIG_MOD5272) -#define FEC_FLASHMAC 0xffc0406b +#define FEC_FLASHMAC 0xffc0406b #else #define FEC_FLASHMAC 0 #endif @@ -232,7 +232,6 @@ struct fec_enet_private { struct platform_device *pdev; int opened; - int dev_id; /* Phylib and MDIO interface */ struct mii_bus *mii_bus; @@ -260,8 +259,6 @@ struct fec_enet_private { /* Transmitter timeout */ #define TX_TIMEOUT (2 * HZ) -static int mii_cnt; - static void *swap_buffer(void *bufaddr, int len) { int i; @@ -518,7 +515,6 @@ fec_stop(struct net_device *ndev) struct fec_enet_private *fep = netdev_priv(ndev); const struct platform_device_id *id_entry = platform_get_device_id(fep->pdev); - u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8); /* We cannot expect a graceful transmit stop without link !!! */ if (fep->link) { @@ -535,10 +531,8 @@ fec_stop(struct net_device *ndev) writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); /* We have to keep ENET enabled to have MII interrupt stay working */ - if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) { + if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) writel(2, fep->hwp + FEC_ECNTRL); - writel(rmii_mode, fep->hwp + FEC_R_CNTRL); - } } @@ -824,7 +818,7 @@ static void __inline__ fec_get_mac(struct net_device *ndev) iap = (unsigned char *)FEC_FLASHMAC; #else if (pdata) - iap = (unsigned char *)&pdata->mac; + memcpy(iap, pdata->mac, ETH_ALEN); #endif } @@ -843,7 +837,7 @@ static void __inline__ fec_get_mac(struct net_device *ndev) /* Adjust MAC if using macaddr */ if (iap == macaddr) - ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->dev_id; + ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id; } /* ------------------------------------------------------------------------- */ @@ -871,8 +865,6 @@ static void fec_enet_adjust_link(struct net_device *ndev) if (phy_dev->link) { if (fep->full_duplex != phy_dev->duplex) { fec_restart(ndev, phy_dev->duplex); - /* prevent unnecessary second fec_restart() below */ - fep->link = phy_dev->link; status_change = 1; } } @@ -961,7 +953,7 @@ static int fec_enet_mii_probe(struct net_device *ndev) char mdio_bus_id[MII_BUS_ID_SIZE]; char phy_name[MII_BUS_ID_SIZE + 3]; int phy_id; - int dev_id = fep->dev_id; + int dev_id = fep->pdev->id; fep->phy_dev = NULL; @@ -980,9 +972,8 @@ static int fec_enet_mii_probe(struct net_device *ndev) } if (phy_id >= PHY_MAX_ADDR) { - printk(KERN_INFO - "%s: no PHY, assuming direct connection to switch\n", - ndev->name); + printk(KERN_INFO "%s: no PHY, assuming direct connection " + "to switch\n", ndev->name); strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); phy_id = 0; } @@ -1007,9 +998,8 @@ static int fec_enet_mii_probe(struct net_device *ndev) fep->link = 0; fep->full_duplex = 0; - printk(KERN_INFO - "%s: Freescale FEC PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", - ndev->name, + printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] " + "(mii_bus:phy_addr=%s, irq=%d)\n", ndev->name, fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev), fep->phy_dev->irq); @@ -1041,14 +1031,10 @@ static int fec_enet_mii_init(struct platform_device *pdev) * mdio interface in board design, and need to be configured by * fec0 mii_bus. */ - if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && fep->dev_id > 0) { + if ((id_entry->driver_data & FEC_QUIRK_ENET_MAC) && pdev->id > 0) { /* fec1 uses fec0 mii_bus */ - if (mii_cnt && fec0_mii_bus) { - fep->mii_bus = fec0_mii_bus; - mii_cnt++; - return 0; - } - return -ENOENT; + fep->mii_bus = fec0_mii_bus; + return 0; } fep->mii_timeout = 0; @@ -1077,7 +1063,7 @@ static int fec_enet_mii_init(struct platform_device *pdev) fep->mii_bus->read = fec_enet_mdio_read; fep->mii_bus->write = fec_enet_mdio_write; fep->mii_bus->reset = fec_enet_mdio_reset; - snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", fep->dev_id + 1); + snprintf(fep->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id + 1); fep->mii_bus->priv = fep; fep->mii_bus->parent = &pdev->dev; @@ -1093,8 +1079,6 @@ static int fec_enet_mii_init(struct platform_device *pdev) if (mdiobus_register(fep->mii_bus)) goto err_out_free_mdio_irq; - mii_cnt++; - /* save fec0 mii_bus */ if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) fec0_mii_bus = fep->mii_bus; @@ -1111,11 +1095,11 @@ static int fec_enet_mii_init(struct platform_device *pdev) static void fec_enet_mii_remove(struct fec_enet_private *fep) { - if (--mii_cnt == 0) { - mdiobus_unregister(fep->mii_bus); - kfree(fep->mii_bus->irq); - mdiobus_free(fep->mii_bus); - } + if (fep->phy_dev) + phy_disconnect(fep->phy_dev); + mdiobus_unregister(fep->mii_bus); + kfree(fep->mii_bus->irq); + mdiobus_free(fep->mii_bus); } static int fec_enet_get_settings(struct net_device *ndev, @@ -1537,7 +1521,6 @@ fec_probe(struct platform_device *pdev) int i, irq, ret = 0; struct resource *r; const struct of_device_id *of_id; - static int dev_id; of_id = of_match_device(fec_dt_ids, &pdev->dev); if (of_id) @@ -1565,7 +1548,6 @@ fec_probe(struct platform_device *pdev) fep->hwp = ioremap(r->start, resource_size(r)); fep->pdev = pdev; - fep->dev_id = dev_id++; if (!fep->hwp) { ret = -ENOMEM; @@ -1589,12 +1571,8 @@ fec_probe(struct platform_device *pdev) for (i = 0; i < FEC_IRQ_NUM; i++) { irq = platform_get_irq(pdev, i); - if (irq < 0) { - if (i) - break; - ret = irq; - goto failed_irq; - } + if (i && irq < 0) + break; ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev); if (ret) { while (--i >= 0) { @@ -1605,7 +1583,7 @@ fec_probe(struct platform_device *pdev) } } - fep->clk = clk_get(&pdev->dev, NULL); + fep->clk = clk_get(&pdev->dev, "fec_clk"); if (IS_ERR(fep->clk)) { ret = PTR_ERR(fep->clk); goto failed_clk; @@ -1657,18 +1635,13 @@ fec_drv_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct fec_enet_private *fep = netdev_priv(ndev); struct resource *r; - int i; - unregister_netdev(ndev); + fec_stop(ndev); fec_enet_mii_remove(fep); - for (i = 0; i < FEC_IRQ_NUM; i++) { - int irq = platform_get_irq(pdev, i); - if (irq > 0) - free_irq(irq, ndev); - } clk_disable(fep->clk); clk_put(fep->clk); iounmap(fep->hwp); + unregister_netdev(ndev); free_netdev(ndev); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/trunk/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/trunk/drivers/net/ethernet/freescale/fsl_pq_mdio.c index 9eb815941df5..f1096027b186 100644 --- a/trunk/drivers/net/ethernet/freescale/fsl_pq_mdio.c +++ b/trunk/drivers/net/ethernet/freescale/fsl_pq_mdio.c @@ -356,13 +356,14 @@ static int fsl_pq_mdio_probe(struct platform_device *ofdev) if (prop) tbiaddr = *prop; - } - if (tbiaddr == -1) { - err = -EBUSY; - goto err_free_irqs; - } else { - out_be32(tbipa, tbiaddr); + if (tbiaddr == -1) { + err = -EBUSY; + + goto err_free_irqs; + } else { + out_be32(tbipa, tbiaddr); + } } err = of_mdiobus_register(new_bus, np); diff --git a/trunk/drivers/net/ethernet/ibm/ehea/ehea_main.c b/trunk/drivers/net/ethernet/ibm/ehea/ehea_main.c index 3554414eb5e2..bfeccbfde236 100644 --- a/trunk/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/trunk/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -2114,19 +2114,17 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static int ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) +static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { struct ehea_port *port = netdev_priv(dev); struct ehea_adapter *adapter = port->adapter; struct hcp_ehea_port_cb1 *cb1; int index; u64 hret; - int err = 0; cb1 = (void *)get_zeroed_page(GFP_KERNEL); if (!cb1) { pr_err("no mem for cb1\n"); - err = -ENOMEM; goto out; } @@ -2134,7 +2132,6 @@ static int ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) H_PORT_CB1, H_PORT_CB1_ALL, cb1); if (hret != H_SUCCESS) { pr_err("query_ehea_port failed\n"); - err = -EINVAL; goto out; } @@ -2143,28 +2140,24 @@ static int ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id, H_PORT_CB1, H_PORT_CB1_ALL, cb1); - if (hret != H_SUCCESS) { + if (hret != H_SUCCESS) pr_err("modify_ehea_port failed\n"); - err = -EINVAL; - } out: free_page((unsigned long)cb1); - return err; + return; } -static int ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct ehea_port *port = netdev_priv(dev); struct ehea_adapter *adapter = port->adapter; struct hcp_ehea_port_cb1 *cb1; int index; u64 hret; - int err = 0; cb1 = (void *)get_zeroed_page(GFP_KERNEL); if (!cb1) { pr_err("no mem for cb1\n"); - err = -ENOMEM; goto out; } @@ -2172,7 +2165,6 @@ static int ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) H_PORT_CB1, H_PORT_CB1_ALL, cb1); if (hret != H_SUCCESS) { pr_err("query_ehea_port failed\n"); - err = -EINVAL; goto out; } @@ -2181,13 +2173,10 @@ static int ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id, H_PORT_CB1, H_PORT_CB1_ALL, cb1); - if (hret != H_SUCCESS) { + if (hret != H_SUCCESS) pr_err("modify_ehea_port failed\n"); - err = -EINVAL; - } out: free_page((unsigned long)cb1); - return err; } int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp) diff --git a/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c b/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c index 053f01289eff..82f4ef142259 100644 --- a/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/trunk/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -169,8 +169,8 @@ static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, static bool e1000_vlan_used(struct e1000_adapter *adapter); static void e1000_vlan_mode(struct net_device *netdev, netdev_features_t features); -static int e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid); -static int e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); +static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid); +static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); static void e1000_restore_vlan(struct e1000_adapter *adapter); #ifdef CONFIG_PM @@ -4604,7 +4604,7 @@ static void e1000_vlan_mode(struct net_device *netdev, e1000_irq_enable(adapter); } -static int e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid) +static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; @@ -4613,7 +4613,7 @@ static int e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid) if ((hw->mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && (vid == adapter->mng_vlan_id)) - return 0; + return; if (!e1000_vlan_used(adapter)) e1000_vlan_filter_on_off(adapter, true); @@ -4625,11 +4625,9 @@ static int e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid) e1000_write_vfta(hw, index, vfta); set_bit(vid, adapter->active_vlans); - - return 0; } -static int e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; @@ -4650,8 +4648,6 @@ static int e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) if (!e1000_vlan_used(adapter)) e1000_vlan_filter_on_off(adapter, false); - - return 0; } static void e1000_restore_vlan(struct e1000_adapter *adapter) diff --git a/trunk/drivers/net/ethernet/intel/e1000e/netdev.c b/trunk/drivers/net/ethernet/intel/e1000e/netdev.c index 90953b4d6bfa..93ae0c26d434 100644 --- a/trunk/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/trunk/drivers/net/ethernet/intel/e1000e/netdev.c @@ -2522,7 +2522,7 @@ static int e1000_clean(struct napi_struct *napi, int budget) return work_done; } -static int e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid) +static void e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; @@ -2532,7 +2532,7 @@ static int e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid) if ((adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && (vid == adapter->mng_vlan_id)) - return 0; + return; /* add VID to filter table */ if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { @@ -2543,11 +2543,9 @@ static int e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid) } set_bit(vid, adapter->active_vlans); - - return 0; } -static int e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct e1000_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; @@ -2558,7 +2556,7 @@ static int e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) (vid == adapter->mng_vlan_id)) { /* release control to f/w */ e1000e_release_hw_control(adapter); - return 0; + return; } /* remove VID from filter table */ @@ -2570,8 +2568,6 @@ static int e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) } clear_bit(vid, adapter->active_vlans); - - return 0; } /** diff --git a/trunk/drivers/net/ethernet/intel/igb/igb_main.c b/trunk/drivers/net/ethernet/intel/igb/igb_main.c index 89d576ce5776..143cfebe3182 100644 --- a/trunk/drivers/net/ethernet/intel/igb/igb_main.c +++ b/trunk/drivers/net/ethernet/intel/igb/igb_main.c @@ -148,8 +148,8 @@ static int igb_ioctl(struct net_device *, struct ifreq *, int cmd); static void igb_tx_timeout(struct net_device *); static void igb_reset_task(struct work_struct *); static void igb_vlan_mode(struct net_device *netdev, netdev_features_t features); -static int igb_vlan_rx_add_vid(struct net_device *, u16); -static int igb_vlan_rx_kill_vid(struct net_device *, u16); +static void igb_vlan_rx_add_vid(struct net_device *, u16); +static void igb_vlan_rx_kill_vid(struct net_device *, u16); static void igb_restore_vlan(struct igb_adapter *); static void igb_rar_set_qsel(struct igb_adapter *, u8 *, u32 , u8); static void igb_ping_all_vfs(struct igb_adapter *); @@ -6491,7 +6491,7 @@ static void igb_vlan_mode(struct net_device *netdev, netdev_features_t features) igb_rlpml_set(adapter); } -static int igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) +static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; @@ -6504,11 +6504,9 @@ static int igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) igb_vfta_set(hw, vid, true); set_bit(vid, adapter->active_vlans); - - return 0; } -static int igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +static void igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; @@ -6523,8 +6521,6 @@ static int igb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) igb_vfta_set(hw, vid, false); clear_bit(vid, adapter->active_vlans); - - return 0; } static void igb_restore_vlan(struct igb_adapter *adapter) diff --git a/trunk/drivers/net/ethernet/intel/igbvf/netdev.c b/trunk/drivers/net/ethernet/intel/igbvf/netdev.c index fd3da3076c2f..c358973ce414 100644 --- a/trunk/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/trunk/drivers/net/ethernet/intel/igbvf/netdev.c @@ -1176,20 +1176,18 @@ static void igbvf_set_rlpml(struct igbvf_adapter *adapter) e1000_rlpml_set_vf(hw, max_frame_size); } -static int igbvf_vlan_rx_add_vid(struct net_device *netdev, u16 vid) +static void igbvf_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct igbvf_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - if (hw->mac.ops.set_vfta(hw, vid, true)) { + if (hw->mac.ops.set_vfta(hw, vid, true)) dev_err(&adapter->pdev->dev, "Failed to add vlan id %d\n", vid); - return -EINVAL; - } - set_bit(vid, adapter->active_vlans); - return 0; + else + set_bit(vid, adapter->active_vlans); } -static int igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +static void igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct igbvf_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; @@ -1199,13 +1197,11 @@ static int igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) if (!test_bit(__IGBVF_DOWN, &adapter->state)) igbvf_irq_enable(adapter); - if (hw->mac.ops.set_vfta(hw, vid, false)) { + if (hw->mac.ops.set_vfta(hw, vid, false)) dev_err(&adapter->pdev->dev, "Failed to remove vlan id %d\n", vid); - return -EINVAL; - } - clear_bit(vid, adapter->active_vlans); - return 0; + else + clear_bit(vid, adapter->active_vlans); } static void igbvf_restore_vlan(struct igbvf_adapter *adapter) diff --git a/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c index c573655f3307..247cf9219e03 100644 --- a/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgb/ixgb_main.c @@ -101,8 +101,8 @@ static void ixgb_tx_timeout_task(struct work_struct *work); static void ixgb_vlan_strip_enable(struct ixgb_adapter *adapter); static void ixgb_vlan_strip_disable(struct ixgb_adapter *adapter); -static int ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid); -static int ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); +static void ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid); +static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); static void ixgb_restore_vlan(struct ixgb_adapter *adapter); #ifdef CONFIG_NET_POLL_CONTROLLER @@ -2217,7 +2217,7 @@ ixgb_vlan_strip_disable(struct ixgb_adapter *adapter) IXGB_WRITE_REG(&adapter->hw, CTRL0, ctrl); } -static int +static void ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct ixgb_adapter *adapter = netdev_priv(netdev); @@ -2230,11 +2230,9 @@ ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) vfta |= (1 << (vid & 0x1F)); ixgb_write_vfta(&adapter->hw, index, vfta); set_bit(vid, adapter->active_vlans); - - return 0; } -static int +static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct ixgb_adapter *adapter = netdev_priv(netdev); @@ -2247,8 +2245,6 @@ ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) vfta &= ~(1 << (vid & 0x1F)); ixgb_write_vfta(&adapter->hw, index, vfta); clear_bit(vid, adapter->active_vlans); - - return 0; } static void diff --git a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 5d94ce1c0fc3..1b28ed9d8cc1 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3044,7 +3044,7 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter) hw->mac.ops.enable_rx_dma(hw, rxctrl); } -static int ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) +static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -3053,11 +3053,9 @@ static int ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) /* add VID to filter table */ hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, true); set_bit(vid, adapter->active_vlans); - - return 0; } -static int ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -3066,8 +3064,6 @@ static int ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) /* remove VID from filter table */ hw->mac.ops.set_vfta(&adapter->hw, vid, pool_ndx, false); clear_bit(vid, adapter->active_vlans); - - return 0; } /** diff --git a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 891162d1610c..5d1a64398169 100644 --- a/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/trunk/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -1403,7 +1403,7 @@ static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter) } } -static int ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid) +static void ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -1412,11 +1412,9 @@ static int ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid) if (hw->mac.ops.set_vfta) hw->mac.ops.set_vfta(hw, vid, 0, true); set_bit(vid, adapter->active_vlans); - - return 0; } -static int ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +static void ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -1425,8 +1423,6 @@ static int ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) if (hw->mac.ops.set_vfta) hw->mac.ops.set_vfta(hw, vid, 0, false); clear_bit(vid, adapter->active_vlans); - - return 0; } static void ixgbevf_restore_vlan(struct ixgbevf_adapter *adapter) diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/Makefile b/trunk/drivers/net/ethernet/mellanox/mlx4/Makefile index 4a40ab967eeb..d1aa45a15854 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/Makefile +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/Makefile @@ -1,7 +1,7 @@ obj-$(CONFIG_MLX4_CORE) += mlx4_core.o mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \ - mr.o pd.o port.o profile.o qp.o reset.o sense.o srq.o resource_tracker.o + mr.o pd.o port.o profile.o qp.o reset.o sense.o srq.o obj-$(CONFIG_MLX4_EN) += mlx4_en.o diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/catas.c b/trunk/drivers/net/ethernet/mellanox/mlx4/catas.c index 915e947b422d..45aea9c3ae2c 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/catas.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/catas.c @@ -48,8 +48,7 @@ static struct work_struct catas_work; static int internal_err_reset = 1; module_param(internal_err_reset, int, 0644); MODULE_PARM_DESC(internal_err_reset, - "Reset device on internal errors if non-zero" - " (default 1, in SRIOV mode default is 0)"); + "Reset device on internal errors if non-zero (default 1)"); static void dump_err_buf(struct mlx4_dev *dev) { @@ -117,10 +116,6 @@ void mlx4_start_catas_poll(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); phys_addr_t addr; - /*If we are in SRIOV the default of the module param must be 0*/ - if (mlx4_is_mfunc(dev)) - internal_err_reset = 0; - INIT_LIST_HEAD(&priv->catas_err.list); init_timer(&priv->catas_err.timer); priv->catas_err.map = NULL; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/cmd.c b/trunk/drivers/net/ethernet/mellanox/mlx4/cmd.c index c4fef839168c..78f5a1a0b8c8 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -39,18 +39,12 @@ #include #include -#include #include #include "mlx4.h" -#include "fw.h" #define CMD_POLL_TOKEN 0xffff -#define INBOX_MASK 0xffffffffffffff00ULL - -#define CMD_CHAN_VER 1 -#define CMD_CHAN_IF_REV 1 enum { /* command completed successfully: */ @@ -116,12 +110,8 @@ struct mlx4_cmd_context { int next; u64 out_param; u16 token; - u8 fw_status; }; -static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr_cmd *in_vhcr); - static int mlx4_status_to_errno(u8 status) { static const int trans_table[] = { @@ -152,119 +142,6 @@ static int mlx4_status_to_errno(u8 status) return trans_table[status]; } -static int comm_pending(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - u32 status = readl(&priv->mfunc.comm->slave_read); - - return (swab32(status) >> 31) != priv->cmd.comm_toggle; -} - -static void mlx4_comm_cmd_post(struct mlx4_dev *dev, u8 cmd, u16 param) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - u32 val; - - priv->cmd.comm_toggle ^= 1; - val = param | (cmd << 16) | (priv->cmd.comm_toggle << 31); - __raw_writel((__force u32) cpu_to_be32(val), - &priv->mfunc.comm->slave_write); - mmiowb(); -} - -static int mlx4_comm_cmd_poll(struct mlx4_dev *dev, u8 cmd, u16 param, - unsigned long timeout) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - unsigned long end; - int err = 0; - int ret_from_pending = 0; - - /* First, verify that the master reports correct status */ - if (comm_pending(dev)) { - mlx4_warn(dev, "Communication channel is not idle." - "my toggle is %d (cmd:0x%x)\n", - priv->cmd.comm_toggle, cmd); - return -EAGAIN; - } - - /* Write command */ - down(&priv->cmd.poll_sem); - mlx4_comm_cmd_post(dev, cmd, param); - - end = msecs_to_jiffies(timeout) + jiffies; - while (comm_pending(dev) && time_before(jiffies, end)) - cond_resched(); - ret_from_pending = comm_pending(dev); - if (ret_from_pending) { - /* check if the slave is trying to boot in the middle of - * FLR process. The only non-zero result in the RESET command - * is MLX4_DELAY_RESET_SLAVE*/ - if ((MLX4_COMM_CMD_RESET == cmd)) { - mlx4_warn(dev, "Got slave FLRed from Communication" - " channel (ret:0x%x)\n", ret_from_pending); - err = MLX4_DELAY_RESET_SLAVE; - } else { - mlx4_warn(dev, "Communication channel timed out\n"); - err = -ETIMEDOUT; - } - } - - up(&priv->cmd.poll_sem); - return err; -} - -static int mlx4_comm_cmd_wait(struct mlx4_dev *dev, u8 op, - u16 param, unsigned long timeout) -{ - struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd; - struct mlx4_cmd_context *context; - int err = 0; - - down(&cmd->event_sem); - - spin_lock(&cmd->context_lock); - BUG_ON(cmd->free_head < 0); - context = &cmd->context[cmd->free_head]; - context->token += cmd->token_mask + 1; - cmd->free_head = context->next; - spin_unlock(&cmd->context_lock); - - init_completion(&context->done); - - mlx4_comm_cmd_post(dev, op, param); - - if (!wait_for_completion_timeout(&context->done, - msecs_to_jiffies(timeout))) { - err = -EBUSY; - goto out; - } - - err = context->result; - if (err && context->fw_status != CMD_STAT_MULTI_FUNC_REQ) { - mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n", - op, context->fw_status); - goto out; - } - -out: - spin_lock(&cmd->context_lock); - context->next = cmd->free_head; - cmd->free_head = context - cmd->context; - spin_unlock(&cmd->context_lock); - - up(&cmd->event_sem); - return err; -} - -int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param, - unsigned long timeout) -{ - if (mlx4_priv(dev)->cmd.use_events) - return mlx4_comm_cmd_wait(dev, cmd, param, timeout); - return mlx4_comm_cmd_poll(dev, cmd, param, timeout); -} - static int cmd_pending(struct mlx4_dev *dev) { u32 status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET); @@ -290,10 +167,8 @@ static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param, end += msecs_to_jiffies(GO_BIT_TIMEOUT_MSECS); while (cmd_pending(dev)) { - if (time_after_eq(jiffies, end)) { - mlx4_err(dev, "%s:cmd_pending failed\n", __func__); + if (time_after_eq(jiffies, end)) goto out; - } cond_resched(); } @@ -317,7 +192,7 @@ static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param, (cmd->toggle << HCR_T_BIT) | (event ? (1 << HCR_E_BIT) : 0) | (op_modifier << HCR_OPMOD_SHIFT) | - op), hcr + 6); + op), hcr + 6); /* * Make sure that our HCR writes don't get mixed in with @@ -334,62 +209,6 @@ static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param, return ret; } -static int mlx4_slave_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, - int out_is_imm, u32 in_modifier, u8 op_modifier, - u16 op, unsigned long timeout) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_vhcr_cmd *vhcr = priv->mfunc.vhcr; - int ret; - - down(&priv->cmd.slave_sem); - vhcr->in_param = cpu_to_be64(in_param); - vhcr->out_param = out_param ? cpu_to_be64(*out_param) : 0; - vhcr->in_modifier = cpu_to_be32(in_modifier); - vhcr->opcode = cpu_to_be16((((u16) op_modifier) << 12) | (op & 0xfff)); - vhcr->token = cpu_to_be16(CMD_POLL_TOKEN); - vhcr->status = 0; - vhcr->flags = !!(priv->cmd.use_events) << 6; - if (mlx4_is_master(dev)) { - ret = mlx4_master_process_vhcr(dev, dev->caps.function, vhcr); - if (!ret) { - if (out_is_imm) { - if (out_param) - *out_param = - be64_to_cpu(vhcr->out_param); - else { - mlx4_err(dev, "response expected while" - "output mailbox is NULL for " - "command 0x%x\n", op); - vhcr->status = -EINVAL; - } - } - ret = vhcr->status; - } - } else { - ret = mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR_POST, 0, - MLX4_COMM_TIME + timeout); - if (!ret) { - if (out_is_imm) { - if (out_param) - *out_param = - be64_to_cpu(vhcr->out_param); - else { - mlx4_err(dev, "response expected while" - "output mailbox is NULL for " - "command 0x%x\n", op); - vhcr->status = -EINVAL; - } - } - ret = vhcr->status; - } else - mlx4_err(dev, "failed execution of VHCR_POST command" - "opcode 0x%x\n", op); - } - up(&priv->cmd.slave_sem); - return ret; -} - static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param, int out_is_imm, u32 in_modifier, u8 op_modifier, u16 op, unsigned long timeout) @@ -398,7 +217,6 @@ static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param, void __iomem *hcr = priv->cmd.hcr; int err = 0; unsigned long end; - u32 stat; down(&priv->cmd.poll_sem); @@ -422,12 +240,9 @@ static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param, __raw_readl(hcr + HCR_OUT_PARAM_OFFSET)) << 32 | (u64) be32_to_cpu((__force __be32) __raw_readl(hcr + HCR_OUT_PARAM_OFFSET + 4)); - stat = be32_to_cpu((__force __be32) - __raw_readl(hcr + HCR_STATUS_OFFSET)) >> 24; - err = mlx4_status_to_errno(stat); - if (err) - mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n", - op, stat); + + err = mlx4_status_to_errno(be32_to_cpu((__force __be32) + __raw_readl(hcr + HCR_STATUS_OFFSET)) >> 24); out: up(&priv->cmd.poll_sem); @@ -444,7 +259,6 @@ void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param) if (token != context->token) return; - context->fw_status = status; context->result = mlx4_status_to_errno(status); context->out_param = out_param; @@ -473,18 +287,14 @@ static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param, mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0, in_modifier, op_modifier, op, context->token, 1); - if (!wait_for_completion_timeout(&context->done, - msecs_to_jiffies(timeout))) { + if (!wait_for_completion_timeout(&context->done, msecs_to_jiffies(timeout))) { err = -EBUSY; goto out; } err = context->result; - if (err) { - mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n", - op, context->fw_status); + if (err) goto out; - } if (out_is_imm) *out_param = context->out_param; @@ -501,1041 +311,16 @@ static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param, int __mlx4_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, int out_is_imm, u32 in_modifier, u8 op_modifier, - u16 op, unsigned long timeout, int native) -{ - if (!mlx4_is_mfunc(dev) || (native && mlx4_is_master(dev))) { - if (mlx4_priv(dev)->cmd.use_events) - return mlx4_cmd_wait(dev, in_param, out_param, - out_is_imm, in_modifier, - op_modifier, op, timeout); - else - return mlx4_cmd_poll(dev, in_param, out_param, - out_is_imm, in_modifier, - op_modifier, op, timeout); - } - return mlx4_slave_cmd(dev, in_param, out_param, out_is_imm, - in_modifier, op_modifier, op, timeout); -} -EXPORT_SYMBOL_GPL(__mlx4_cmd); - - -static int mlx4_ARM_COMM_CHANNEL(struct mlx4_dev *dev) -{ - return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_ARM_COMM_CHANNEL, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); -} - -static int mlx4_ACCESS_MEM(struct mlx4_dev *dev, u64 master_addr, - int slave, u64 slave_addr, - int size, int is_read) -{ - u64 in_param; - u64 out_param; - - if ((slave_addr & 0xfff) | (master_addr & 0xfff) | - (slave & ~0x7f) | (size & 0xff)) { - mlx4_err(dev, "Bad access mem params - slave_addr:0x%llx " - "master_addr:0x%llx slave_id:%d size:%d\n", - slave_addr, master_addr, slave, size); - return -EINVAL; - } - - if (is_read) { - in_param = (u64) slave | slave_addr; - out_param = (u64) dev->caps.function | master_addr; - } else { - in_param = (u64) dev->caps.function | master_addr; - out_param = (u64) slave | slave_addr; - } - - return mlx4_cmd_imm(dev, in_param, &out_param, size, 0, - MLX4_CMD_ACCESS_MEM, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); -} - -int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) + u16 op, unsigned long timeout) { - u64 in_param; - u64 out_param; - int err; - - in_param = cmd->has_inbox ? (u64) inbox->dma : vhcr->in_param; - out_param = cmd->has_outbox ? (u64) outbox->dma : vhcr->out_param; - if (cmd->encode_slave_id) { - in_param &= 0xffffffffffffff00ll; - in_param |= slave; - } - - err = __mlx4_cmd(dev, in_param, &out_param, cmd->out_is_imm, - vhcr->in_modifier, vhcr->op_modifier, vhcr->op, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); - - if (cmd->out_is_imm) - vhcr->out_param = out_param; - - return err; -} - -static struct mlx4_cmd_info cmd_info[] = { - { - .opcode = MLX4_CMD_QUERY_FW, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = NULL - }, - { - .opcode = MLX4_CMD_QUERY_HCA, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = NULL - }, - { - .opcode = MLX4_CMD_QUERY_DEV_CAP, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = NULL - }, - { - .opcode = MLX4_CMD_QUERY_FUNC_CAP, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_QUERY_FUNC_CAP_wrapper - }, - { - .opcode = MLX4_CMD_QUERY_ADAPTER, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = NULL - }, - { - .opcode = MLX4_CMD_INIT_PORT, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_INIT_PORT_wrapper - }, - { - .opcode = MLX4_CMD_CLOSE_PORT, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_CLOSE_PORT_wrapper - }, - { - .opcode = MLX4_CMD_QUERY_PORT, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_QUERY_PORT_wrapper - }, - { - .opcode = MLX4_CMD_SET_PORT, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_SET_PORT_wrapper - }, - { - .opcode = MLX4_CMD_MAP_EQ, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_MAP_EQ_wrapper - }, - { - .opcode = MLX4_CMD_SW2HW_EQ, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = true, - .verify = NULL, - .wrapper = mlx4_SW2HW_EQ_wrapper - }, - { - .opcode = MLX4_CMD_HW_HEALTH_CHECK, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = NULL - }, - { - .opcode = MLX4_CMD_NOP, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = NULL - }, - { - .opcode = MLX4_CMD_ALLOC_RES, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = true, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_ALLOC_RES_wrapper - }, - { - .opcode = MLX4_CMD_FREE_RES, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_FREE_RES_wrapper - }, - { - .opcode = MLX4_CMD_SW2HW_MPT, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = true, - .verify = NULL, - .wrapper = mlx4_SW2HW_MPT_wrapper - }, - { - .opcode = MLX4_CMD_QUERY_MPT, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_QUERY_MPT_wrapper - }, - { - .opcode = MLX4_CMD_HW2SW_MPT, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_HW2SW_MPT_wrapper - }, - { - .opcode = MLX4_CMD_READ_MTT, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = NULL - }, - { - .opcode = MLX4_CMD_WRITE_MTT, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_WRITE_MTT_wrapper - }, - { - .opcode = MLX4_CMD_SYNC_TPT, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = NULL - }, - { - .opcode = MLX4_CMD_HW2SW_EQ, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = true, - .verify = NULL, - .wrapper = mlx4_HW2SW_EQ_wrapper - }, - { - .opcode = MLX4_CMD_QUERY_EQ, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = true, - .verify = NULL, - .wrapper = mlx4_QUERY_EQ_wrapper - }, - { - .opcode = MLX4_CMD_SW2HW_CQ, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = true, - .verify = NULL, - .wrapper = mlx4_SW2HW_CQ_wrapper - }, - { - .opcode = MLX4_CMD_HW2SW_CQ, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_HW2SW_CQ_wrapper - }, - { - .opcode = MLX4_CMD_QUERY_CQ, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_QUERY_CQ_wrapper - }, - { - .opcode = MLX4_CMD_MODIFY_CQ, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = true, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_MODIFY_CQ_wrapper - }, - { - .opcode = MLX4_CMD_SW2HW_SRQ, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = true, - .verify = NULL, - .wrapper = mlx4_SW2HW_SRQ_wrapper - }, - { - .opcode = MLX4_CMD_HW2SW_SRQ, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_HW2SW_SRQ_wrapper - }, - { - .opcode = MLX4_CMD_QUERY_SRQ, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_QUERY_SRQ_wrapper - }, - { - .opcode = MLX4_CMD_ARM_SRQ, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_ARM_SRQ_wrapper - }, - { - .opcode = MLX4_CMD_RST2INIT_QP, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = true, - .verify = NULL, - .wrapper = mlx4_RST2INIT_QP_wrapper - }, - { - .opcode = MLX4_CMD_INIT2INIT_QP, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_GEN_QP_wrapper - }, - { - .opcode = MLX4_CMD_INIT2RTR_QP, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_INIT2RTR_QP_wrapper - }, - { - .opcode = MLX4_CMD_RTR2RTS_QP, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_GEN_QP_wrapper - }, - { - .opcode = MLX4_CMD_RTS2RTS_QP, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_GEN_QP_wrapper - }, - { - .opcode = MLX4_CMD_SQERR2RTS_QP, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_GEN_QP_wrapper - }, - { - .opcode = MLX4_CMD_2ERR_QP, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_GEN_QP_wrapper - }, - { - .opcode = MLX4_CMD_RTS2SQD_QP, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_GEN_QP_wrapper - }, - { - .opcode = MLX4_CMD_SQD2SQD_QP, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_GEN_QP_wrapper - }, - { - .opcode = MLX4_CMD_SQD2RTS_QP, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_GEN_QP_wrapper - }, - { - .opcode = MLX4_CMD_2RST_QP, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_2RST_QP_wrapper - }, - { - .opcode = MLX4_CMD_QUERY_QP, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_GEN_QP_wrapper - }, - { - .opcode = MLX4_CMD_SUSPEND_QP, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_GEN_QP_wrapper - }, - { - .opcode = MLX4_CMD_UNSUSPEND_QP, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_GEN_QP_wrapper - }, - { - .opcode = MLX4_CMD_QUERY_IF_STAT, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_QUERY_IF_STAT_wrapper - }, - /* Native multicast commands are not available for guests */ - { - .opcode = MLX4_CMD_QP_ATTACH, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_QP_ATTACH_wrapper - }, - { - .opcode = MLX4_CMD_PROMISC, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_PROMISC_wrapper - }, - /* Ethernet specific commands */ - { - .opcode = MLX4_CMD_SET_VLAN_FLTR, - .has_inbox = true, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_SET_VLAN_FLTR_wrapper - }, - { - .opcode = MLX4_CMD_SET_MCAST_FLTR, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_SET_MCAST_FLTR_wrapper - }, - { - .opcode = MLX4_CMD_DUMP_ETH_STATS, - .has_inbox = false, - .has_outbox = true, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = mlx4_DUMP_ETH_STATS_wrapper - }, - { - .opcode = MLX4_CMD_INFORM_FLR_DONE, - .has_inbox = false, - .has_outbox = false, - .out_is_imm = false, - .encode_slave_id = false, - .verify = NULL, - .wrapper = NULL - }, -}; - -static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr_cmd *in_vhcr) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cmd_info *cmd = NULL; - struct mlx4_vhcr_cmd *vhcr_cmd = in_vhcr ? in_vhcr : priv->mfunc.vhcr; - struct mlx4_vhcr *vhcr; - struct mlx4_cmd_mailbox *inbox = NULL; - struct mlx4_cmd_mailbox *outbox = NULL; - u64 in_param; - u64 out_param; - int ret = 0; - int i; - - /* Create sw representation of Virtual HCR */ - vhcr = kzalloc(sizeof(struct mlx4_vhcr), GFP_KERNEL); - if (!vhcr) - return -ENOMEM; - - /* DMA in the vHCR */ - if (!in_vhcr) { - ret = mlx4_ACCESS_MEM(dev, priv->mfunc.vhcr_dma, slave, - priv->mfunc.master.slave_state[slave].vhcr_dma, - ALIGN(sizeof(struct mlx4_vhcr_cmd), - MLX4_ACCESS_MEM_ALIGN), 1); - if (ret) { - mlx4_err(dev, "%s:Failed reading vhcr" - "ret: 0x%x\n", __func__, ret); - kfree(vhcr); - return ret; - } - } - - /* Fill SW VHCR fields */ - vhcr->in_param = be64_to_cpu(vhcr_cmd->in_param); - vhcr->out_param = be64_to_cpu(vhcr_cmd->out_param); - vhcr->in_modifier = be32_to_cpu(vhcr_cmd->in_modifier); - vhcr->token = be16_to_cpu(vhcr_cmd->token); - vhcr->op = be16_to_cpu(vhcr_cmd->opcode) & 0xfff; - vhcr->op_modifier = (u8) (be16_to_cpu(vhcr_cmd->opcode) >> 12); - vhcr->e_bit = vhcr_cmd->flags & (1 << 6); - - /* Lookup command */ - for (i = 0; i < ARRAY_SIZE(cmd_info); ++i) { - if (vhcr->op == cmd_info[i].opcode) { - cmd = &cmd_info[i]; - break; - } - } - if (!cmd) { - mlx4_err(dev, "Unknown command:0x%x accepted from slave:%d\n", - vhcr->op, slave); - vhcr_cmd->status = -EINVAL; - goto out_status; - } - - /* Read inbox */ - if (cmd->has_inbox) { - vhcr->in_param &= INBOX_MASK; - inbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(inbox)) { - ret = PTR_ERR(inbox); - inbox = NULL; - goto out; - } - - ret = mlx4_ACCESS_MEM(dev, inbox->dma, slave, - vhcr->in_param, - MLX4_MAILBOX_SIZE, 1); - if (ret) { - mlx4_err(dev, "%s: Failed reading inbox (cmd:0x%x)\n", - __func__, cmd->opcode); - goto out; - } - } - - /* Apply permission and bound checks if applicable */ - if (cmd->verify && cmd->verify(dev, slave, vhcr, inbox)) { - mlx4_warn(dev, "Command:0x%x from slave: %d failed protection " - "checks for resource_id:%d\n", vhcr->op, slave, - vhcr->in_modifier); - vhcr_cmd->status = -EPERM; - goto out_status; - } - - /* Allocate outbox */ - if (cmd->has_outbox) { - outbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(outbox)) { - ret = PTR_ERR(outbox); - outbox = NULL; - goto out; - } - } - - /* Execute the command! */ - if (cmd->wrapper) { - vhcr_cmd->status = cmd->wrapper(dev, slave, vhcr, inbox, outbox, - cmd); - if (cmd->out_is_imm) - vhcr_cmd->out_param = cpu_to_be64(vhcr->out_param); - } else { - in_param = cmd->has_inbox ? (u64) inbox->dma : - vhcr->in_param; - out_param = cmd->has_outbox ? (u64) outbox->dma : - vhcr->out_param; - vhcr_cmd->status = __mlx4_cmd(dev, in_param, &out_param, - cmd->out_is_imm, vhcr->in_modifier, - vhcr->op_modifier, vhcr->op, - MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); - - if (vhcr_cmd->status) { - mlx4_warn(dev, "vhcr command:0x%x slave:%d failed with" - " error:%d, status %d\n", - vhcr->op, slave, vhcr->errno, - vhcr_cmd->status); - ret = vhcr_cmd->status; - goto out; - } - - if (cmd->out_is_imm) { - vhcr->out_param = out_param; - vhcr_cmd->out_param = cpu_to_be64(vhcr->out_param); - } - } - - /* Write outbox if command completed successfully */ - if (cmd->has_outbox && !vhcr->errno) { - ret = mlx4_ACCESS_MEM(dev, outbox->dma, slave, - vhcr->out_param, - MLX4_MAILBOX_SIZE, MLX4_CMD_WRAPPED); - if (ret) { - mlx4_err(dev, "%s:Failed writing outbox\n", __func__); - goto out; - } - } - -out_status: - /* DMA back vhcr result */ - if (!in_vhcr) { - ret = mlx4_ACCESS_MEM(dev, priv->mfunc.vhcr_dma, slave, - priv->mfunc.master.slave_state[slave].vhcr_dma, - ALIGN(sizeof(struct mlx4_vhcr), - MLX4_ACCESS_MEM_ALIGN), - MLX4_CMD_WRAPPED); - if (ret) - mlx4_err(dev, "%s:Failed writing vhcr result\n", - __func__); - else if (vhcr->e_bit && - mlx4_GEN_EQE(dev, slave, &priv->mfunc.master.cmd_eqe)) - mlx4_warn(dev, "Failed to generate command completion " - "eqe for slave %d\n", slave); - } - -out: - kfree(vhcr); - mlx4_free_cmd_mailbox(dev, inbox); - mlx4_free_cmd_mailbox(dev, outbox); - return ret; -} - -static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd, - u16 param, u8 toggle) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; - u32 reply; - u32 slave_status = 0; - u8 is_going_down = 0; - - slave_state[slave].comm_toggle ^= 1; - reply = (u32) slave_state[slave].comm_toggle << 31; - if (toggle != slave_state[slave].comm_toggle) { - mlx4_warn(dev, "Incorrect toggle %d from slave %d. *** MASTER" - "STATE COMPROMISIED ***\n", toggle, slave); - goto reset_slave; - } - if (cmd == MLX4_COMM_CMD_RESET) { - mlx4_warn(dev, "Received reset from slave:%d\n", slave); - slave_state[slave].active = false; - /*check if we are in the middle of FLR process, - if so return "retry" status to the slave*/ - if (MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) { - slave_status = MLX4_DELAY_RESET_SLAVE; - goto inform_slave_state; - } - - /* write the version in the event field */ - reply |= mlx4_comm_get_version(); - - goto reset_slave; - } - /*command from slave in the middle of FLR*/ - if (cmd != MLX4_COMM_CMD_RESET && - MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) { - mlx4_warn(dev, "slave:%d is Trying to run cmd(0x%x) " - "in the middle of FLR\n", slave, cmd); - return; - } - - switch (cmd) { - case MLX4_COMM_CMD_VHCR0: - if (slave_state[slave].last_cmd != MLX4_COMM_CMD_RESET) - goto reset_slave; - slave_state[slave].vhcr_dma = ((u64) param) << 48; - priv->mfunc.master.slave_state[slave].cookie = 0; - mutex_init(&priv->mfunc.master.gen_eqe_mutex[slave]); - break; - case MLX4_COMM_CMD_VHCR1: - if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR0) - goto reset_slave; - slave_state[slave].vhcr_dma |= ((u64) param) << 32; - break; - case MLX4_COMM_CMD_VHCR2: - if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR1) - goto reset_slave; - slave_state[slave].vhcr_dma |= ((u64) param) << 16; - break; - case MLX4_COMM_CMD_VHCR_EN: - if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR2) - goto reset_slave; - slave_state[slave].vhcr_dma |= param; - slave_state[slave].active = true; - break; - case MLX4_COMM_CMD_VHCR_POST: - if ((slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_EN) && - (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR_POST)) - goto reset_slave; - down(&priv->cmd.slave_sem); - if (mlx4_master_process_vhcr(dev, slave, NULL)) { - mlx4_err(dev, "Failed processing vhcr for slave:%d," - " reseting slave.\n", slave); - up(&priv->cmd.slave_sem); - goto reset_slave; - } - up(&priv->cmd.slave_sem); - break; - default: - mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave); - goto reset_slave; - } - spin_lock(&priv->mfunc.master.slave_state_lock); - if (!slave_state[slave].is_slave_going_down) - slave_state[slave].last_cmd = cmd; - else - is_going_down = 1; - spin_unlock(&priv->mfunc.master.slave_state_lock); - if (is_going_down) { - mlx4_warn(dev, "Slave is going down aborting command(%d)" - " executing from slave:%d\n", - cmd, slave); - return; - } - __raw_writel((__force u32) cpu_to_be32(reply), - &priv->mfunc.comm[slave].slave_read); - mmiowb(); - - return; - -reset_slave: - /* cleanup any slave resources */ - mlx4_delete_all_resources_for_slave(dev, slave); - spin_lock(&priv->mfunc.master.slave_state_lock); - if (!slave_state[slave].is_slave_going_down) - slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET; - spin_unlock(&priv->mfunc.master.slave_state_lock); - /*with slave in the middle of flr, no need to clean resources again.*/ -inform_slave_state: - memset(&slave_state[slave].event_eq, 0, - sizeof(struct mlx4_slave_event_eq_info)); - __raw_writel((__force u32) cpu_to_be32(reply), - &priv->mfunc.comm[slave].slave_read); - wmb(); -} - -/* master command processing */ -void mlx4_master_comm_channel(struct work_struct *work) -{ - struct mlx4_mfunc_master_ctx *master = - container_of(work, - struct mlx4_mfunc_master_ctx, - comm_work); - struct mlx4_mfunc *mfunc = - container_of(master, struct mlx4_mfunc, master); - struct mlx4_priv *priv = - container_of(mfunc, struct mlx4_priv, mfunc); - struct mlx4_dev *dev = &priv->dev; - __be32 *bit_vec; - u32 comm_cmd; - u32 vec; - int i, j, slave; - int toggle; - int served = 0; - int reported = 0; - u32 slt; - - bit_vec = master->comm_arm_bit_vector; - for (i = 0; i < COMM_CHANNEL_BIT_ARRAY_SIZE; i++) { - vec = be32_to_cpu(bit_vec[i]); - for (j = 0; j < 32; j++) { - if (!(vec & (1 << j))) - continue; - ++reported; - slave = (i * 32) + j; - comm_cmd = swab32(readl( - &mfunc->comm[slave].slave_write)); - slt = swab32(readl(&mfunc->comm[slave].slave_read)) - >> 31; - toggle = comm_cmd >> 31; - if (toggle != slt) { - if (master->slave_state[slave].comm_toggle - != slt) { - printk(KERN_INFO "slave %d out of sync." - " read toggle %d, state toggle %d. " - "Resynching.\n", slave, slt, - master->slave_state[slave].comm_toggle); - master->slave_state[slave].comm_toggle = - slt; - } - mlx4_master_do_cmd(dev, slave, - comm_cmd >> 16 & 0xff, - comm_cmd & 0xffff, toggle); - ++served; - } - } - } - - if (reported && reported != served) - mlx4_warn(dev, "Got command event with bitmask from %d slaves" - " but %d were served\n", - reported, served); - - if (mlx4_ARM_COMM_CHANNEL(dev)) - mlx4_warn(dev, "Failed to arm comm channel events\n"); -} - -static int sync_toggles(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int wr_toggle; - int rd_toggle; - unsigned long end; - - wr_toggle = swab32(readl(&priv->mfunc.comm->slave_write)) >> 31; - end = jiffies + msecs_to_jiffies(5000); - - while (time_before(jiffies, end)) { - rd_toggle = swab32(readl(&priv->mfunc.comm->slave_read)) >> 31; - if (rd_toggle == wr_toggle) { - priv->cmd.comm_toggle = rd_toggle; - return 0; - } - - cond_resched(); - } - - /* - * we could reach here if for example the previous VM using this - * function misbehaved and left the channel with unsynced state. We - * should fix this here and give this VM a chance to use a properly - * synced channel - */ - mlx4_warn(dev, "recovering from previously mis-behaved VM\n"); - __raw_writel((__force u32) 0, &priv->mfunc.comm->slave_read); - __raw_writel((__force u32) 0, &priv->mfunc.comm->slave_write); - priv->cmd.comm_toggle = 0; - - return 0; -} - -int mlx4_multi_func_init(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_slave_state *s_state; - int i, err, port; - - priv->mfunc.vhcr = dma_alloc_coherent(&(dev->pdev->dev), PAGE_SIZE, - &priv->mfunc.vhcr_dma, - GFP_KERNEL); - if (!priv->mfunc.vhcr) { - mlx4_err(dev, "Couldn't allocate vhcr.\n"); - return -ENOMEM; - } - - if (mlx4_is_master(dev)) - priv->mfunc.comm = - ioremap(pci_resource_start(dev->pdev, priv->fw.comm_bar) + - priv->fw.comm_base, MLX4_COMM_PAGESIZE); + if (mlx4_priv(dev)->cmd.use_events) + return mlx4_cmd_wait(dev, in_param, out_param, out_is_imm, + in_modifier, op_modifier, op, timeout); else - priv->mfunc.comm = - ioremap(pci_resource_start(dev->pdev, 2) + - MLX4_SLAVE_COMM_BASE, MLX4_COMM_PAGESIZE); - if (!priv->mfunc.comm) { - mlx4_err(dev, "Couldn't map communication vector.\n"); - goto err_vhcr; - } - - if (mlx4_is_master(dev)) { - priv->mfunc.master.slave_state = - kzalloc(dev->num_slaves * - sizeof(struct mlx4_slave_state), GFP_KERNEL); - if (!priv->mfunc.master.slave_state) - goto err_comm; - - for (i = 0; i < dev->num_slaves; ++i) { - s_state = &priv->mfunc.master.slave_state[i]; - s_state->last_cmd = MLX4_COMM_CMD_RESET; - __raw_writel((__force u32) 0, - &priv->mfunc.comm[i].slave_write); - __raw_writel((__force u32) 0, - &priv->mfunc.comm[i].slave_read); - mmiowb(); - for (port = 1; port <= MLX4_MAX_PORTS; port++) { - s_state->vlan_filter[port] = - kzalloc(sizeof(struct mlx4_vlan_fltr), - GFP_KERNEL); - if (!s_state->vlan_filter[port]) { - if (--port) - kfree(s_state->vlan_filter[port]); - goto err_slaves; - } - INIT_LIST_HEAD(&s_state->mcast_filters[port]); - } - spin_lock_init(&s_state->lock); - } - - memset(&priv->mfunc.master.cmd_eqe, 0, sizeof(struct mlx4_eqe)); - priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD; - INIT_WORK(&priv->mfunc.master.comm_work, - mlx4_master_comm_channel); - INIT_WORK(&priv->mfunc.master.slave_event_work, - mlx4_gen_slave_eqe); - INIT_WORK(&priv->mfunc.master.slave_flr_event_work, - mlx4_master_handle_slave_flr); - spin_lock_init(&priv->mfunc.master.slave_state_lock); - priv->mfunc.master.comm_wq = - create_singlethread_workqueue("mlx4_comm"); - if (!priv->mfunc.master.comm_wq) - goto err_slaves; - - if (mlx4_init_resource_tracker(dev)) - goto err_thread; - - sema_init(&priv->cmd.slave_sem, 1); - err = mlx4_ARM_COMM_CHANNEL(dev); - if (err) { - mlx4_err(dev, " Failed to arm comm channel eq: %x\n", - err); - goto err_resource; - } - - } else { - err = sync_toggles(dev); - if (err) { - mlx4_err(dev, "Couldn't sync toggles\n"); - goto err_comm; - } - - sema_init(&priv->cmd.slave_sem, 1); - } - return 0; - -err_resource: - mlx4_free_resource_tracker(dev); -err_thread: - flush_workqueue(priv->mfunc.master.comm_wq); - destroy_workqueue(priv->mfunc.master.comm_wq); -err_slaves: - while (--i) { - for (port = 1; port <= MLX4_MAX_PORTS; port++) - kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]); - } - kfree(priv->mfunc.master.slave_state); -err_comm: - iounmap(priv->mfunc.comm); -err_vhcr: - dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE, - priv->mfunc.vhcr, - priv->mfunc.vhcr_dma); - priv->mfunc.vhcr = NULL; - return -ENOMEM; + return mlx4_cmd_poll(dev, in_param, out_param, out_is_imm, + in_modifier, op_modifier, op, timeout); } +EXPORT_SYMBOL_GPL(__mlx4_cmd); int mlx4_cmd_init(struct mlx4_dev *dev) { @@ -1546,51 +331,22 @@ int mlx4_cmd_init(struct mlx4_dev *dev) priv->cmd.use_events = 0; priv->cmd.toggle = 1; - priv->cmd.hcr = NULL; - priv->mfunc.vhcr = NULL; - - if (!mlx4_is_slave(dev)) { - priv->cmd.hcr = ioremap(pci_resource_start(dev->pdev, 0) + - MLX4_HCR_BASE, MLX4_HCR_SIZE); - if (!priv->cmd.hcr) { - mlx4_err(dev, "Couldn't map command register.\n"); - return -ENOMEM; - } + priv->cmd.hcr = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_HCR_BASE, + MLX4_HCR_SIZE); + if (!priv->cmd.hcr) { + mlx4_err(dev, "Couldn't map command register."); + return -ENOMEM; } priv->cmd.pool = pci_pool_create("mlx4_cmd", dev->pdev, MLX4_MAILBOX_SIZE, MLX4_MAILBOX_SIZE, 0); - if (!priv->cmd.pool) - goto err_hcr; - - return 0; - -err_hcr: - if (!mlx4_is_slave(dev)) + if (!priv->cmd.pool) { iounmap(priv->cmd.hcr); - return -ENOMEM; -} - -void mlx4_multi_func_cleanup(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int i, port; - - if (mlx4_is_master(dev)) { - flush_workqueue(priv->mfunc.master.comm_wq); - destroy_workqueue(priv->mfunc.master.comm_wq); - for (i = 0; i < dev->num_slaves; i++) { - for (port = 1; port <= MLX4_MAX_PORTS; port++) - kfree(priv->mfunc.master.slave_state[i].vlan_filter[port]); - } - kfree(priv->mfunc.master.slave_state); - iounmap(priv->mfunc.comm); - dma_free_coherent(&(dev->pdev->dev), PAGE_SIZE, - priv->mfunc.vhcr, - priv->mfunc.vhcr_dma); - priv->mfunc.vhcr = NULL; + return -ENOMEM; } + + return 0; } void mlx4_cmd_cleanup(struct mlx4_dev *dev) @@ -1598,9 +354,7 @@ void mlx4_cmd_cleanup(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); pci_pool_destroy(priv->cmd.pool); - - if (!mlx4_is_slave(dev)) - iounmap(priv->cmd.hcr); + iounmap(priv->cmd.hcr); } /* @@ -1611,7 +365,6 @@ int mlx4_cmd_use_events(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); int i; - int err = 0; priv->cmd.context = kmalloc(priv->cmd.max_cmds * sizeof (struct mlx4_cmd_context), @@ -1636,10 +389,11 @@ int mlx4_cmd_use_events(struct mlx4_dev *dev) ; /* nothing */ --priv->cmd.token_mask; - down(&priv->cmd.poll_sem); priv->cmd.use_events = 1; - return err; + down(&priv->cmd.poll_sem); + + return 0; } /* @@ -1679,8 +433,7 @@ struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev) } EXPORT_SYMBOL_GPL(mlx4_alloc_cmd_mailbox); -void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, - struct mlx4_cmd_mailbox *mailbox) +void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox) { if (!mailbox) return; @@ -1689,8 +442,3 @@ void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, kfree(mailbox); } EXPORT_SYMBOL_GPL(mlx4_free_cmd_mailbox); - -u32 mlx4_comm_get_version(void) -{ - return ((u32) CMD_CHAN_IF_REV << 8) | (u32) CMD_CHAN_VER; -} diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/cq.c b/trunk/drivers/net/ethernet/mellanox/mlx4/cq.c index 475f9d6af955..499a5168892a 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/cq.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/cq.c @@ -34,9 +34,9 @@ * SOFTWARE. */ -#include #include #include +#include #include #include @@ -44,6 +44,27 @@ #include "mlx4.h" #include "icm.h" +struct mlx4_cq_context { + __be32 flags; + u16 reserved1[3]; + __be16 page_offset; + __be32 logsize_usrpage; + __be16 cq_period; + __be16 cq_max_count; + u8 reserved2[3]; + u8 comp_eqn; + u8 log_page_size; + u8 reserved3[2]; + u8 mtt_base_addr_h; + __be32 mtt_base_addr_l; + __be32 last_notified_index; + __be32 solicit_producer_index; + __be32 consumer_index; + __be32 producer_index; + u32 reserved4[2]; + __be64 db_rec_addr; +}; + #define MLX4_CQ_STATUS_OK ( 0 << 28) #define MLX4_CQ_STATUS_OVERFLOW ( 9 << 28) #define MLX4_CQ_STATUS_WRITE_FAIL (10 << 28) @@ -60,7 +81,7 @@ void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn) cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree, cqn & (dev->caps.num_cqs - 1)); if (!cq) { - mlx4_dbg(dev, "Completion event for bogus CQ %08x\n", cqn); + mlx4_warn(dev, "Completion event for bogus CQ %08x\n", cqn); return; } @@ -96,24 +117,23 @@ void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type) static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int cq_num) { - return mlx4_cmd(dev, mailbox->dma | dev->caps.function, cq_num, 0, - MLX4_CMD_SW2HW_CQ, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED); + return mlx4_cmd(dev, mailbox->dma, cq_num, 0, MLX4_CMD_SW2HW_CQ, + MLX4_CMD_TIME_CLASS_A); } static int mlx4_MODIFY_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int cq_num, u32 opmod) { return mlx4_cmd(dev, mailbox->dma, cq_num, opmod, MLX4_CMD_MODIFY_CQ, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); + MLX4_CMD_TIME_CLASS_A); } static int mlx4_HW2SW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int cq_num) { - return mlx4_cmd_box(dev, dev->caps.function, mailbox ? mailbox->dma : 0, - cq_num, mailbox ? 0 : 1, MLX4_CMD_HW2SW_CQ, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); + return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, cq_num, + mailbox ? 0 : 1, MLX4_CMD_HW2SW_CQ, + MLX4_CMD_TIME_CLASS_A); } int mlx4_cq_modify(struct mlx4_dev *dev, struct mlx4_cq *cq, @@ -168,78 +188,6 @@ int mlx4_cq_resize(struct mlx4_dev *dev, struct mlx4_cq *cq, } EXPORT_SYMBOL_GPL(mlx4_cq_resize); -int __mlx4_cq_alloc_icm(struct mlx4_dev *dev, int *cqn) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cq_table *cq_table = &priv->cq_table; - int err; - - *cqn = mlx4_bitmap_alloc(&cq_table->bitmap); - if (*cqn == -1) - return -ENOMEM; - - err = mlx4_table_get(dev, &cq_table->table, *cqn); - if (err) - goto err_out; - - err = mlx4_table_get(dev, &cq_table->cmpt_table, *cqn); - if (err) - goto err_put; - return 0; - -err_put: - mlx4_table_put(dev, &cq_table->table, *cqn); - -err_out: - mlx4_bitmap_free(&cq_table->bitmap, *cqn); - return err; -} - -static int mlx4_cq_alloc_icm(struct mlx4_dev *dev, int *cqn) -{ - u64 out_param; - int err; - - if (mlx4_is_mfunc(dev)) { - err = mlx4_cmd_imm(dev, 0, &out_param, RES_CQ, - RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); - if (err) - return err; - else { - *cqn = get_param_l(&out_param); - return 0; - } - } - return __mlx4_cq_alloc_icm(dev, cqn); -} - -void __mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_cq_table *cq_table = &priv->cq_table; - - mlx4_table_put(dev, &cq_table->cmpt_table, cqn); - mlx4_table_put(dev, &cq_table->table, cqn); - mlx4_bitmap_free(&cq_table->bitmap, cqn); -} - -static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn) -{ - u64 in_param; - int err; - - if (mlx4_is_mfunc(dev)) { - set_param_l(&in_param, cqn); - err = mlx4_cmd(dev, in_param, RES_CQ, RES_OP_RESERVE_AND_MAP, - MLX4_CMD_FREE_RES, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); - if (err) - mlx4_warn(dev, "Failed freeing cq:%d\n", cqn); - } else - __mlx4_cq_free_icm(dev, cqn); -} - int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt, struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq, unsigned vector, int collapsed) @@ -256,15 +204,23 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt, cq->vector = vector; - err = mlx4_cq_alloc_icm(dev, &cq->cqn); + cq->cqn = mlx4_bitmap_alloc(&cq_table->bitmap); + if (cq->cqn == -1) + return -ENOMEM; + + err = mlx4_table_get(dev, &cq_table->table, cq->cqn); if (err) - return err; + goto err_out; + + err = mlx4_table_get(dev, &cq_table->cmpt_table, cq->cqn); + if (err) + goto err_put; spin_lock_irq(&cq_table->lock); err = radix_tree_insert(&cq_table->tree, cq->cqn, cq); spin_unlock_irq(&cq_table->lock); if (err) - goto err_icm; + goto err_cmpt_put; mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) { @@ -303,8 +259,14 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt, radix_tree_delete(&cq_table->tree, cq->cqn); spin_unlock_irq(&cq_table->lock); -err_icm: - mlx4_cq_free_icm(dev, cq->cqn); +err_cmpt_put: + mlx4_table_put(dev, &cq_table->cmpt_table, cq->cqn); + +err_put: + mlx4_table_put(dev, &cq_table->table, cq->cqn); + +err_out: + mlx4_bitmap_free(&cq_table->bitmap, cq->cqn); return err; } @@ -330,7 +292,8 @@ void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq) complete(&cq->free); wait_for_completion(&cq->free); - mlx4_cq_free_icm(dev, cq->cqn); + mlx4_table_put(dev, &cq_table->table, cq->cqn); + mlx4_bitmap_free(&cq_table->bitmap, cq->cqn); } EXPORT_SYMBOL_GPL(mlx4_cq_free); @@ -341,8 +304,6 @@ int mlx4_init_cq_table(struct mlx4_dev *dev) spin_lock_init(&cq_table->lock); INIT_RADIX_TREE(&cq_table->tree, GFP_ATOMIC); - if (mlx4_is_slave(dev)) - return 0; err = mlx4_bitmap_init(&cq_table->bitmap, dev->caps.num_cqs, dev->caps.num_cqs - 1, dev->caps.reserved_cqs, 0); @@ -354,8 +315,6 @@ int mlx4_init_cq_table(struct mlx4_dev *dev) void mlx4_cleanup_cq_table(struct mlx4_dev *dev) { - if (mlx4_is_slave(dev)) - return; /* Nothing to do to clean up radix_tree */ mlx4_bitmap_cleanup(&mlx4_priv(dev)->cq_table.bitmap); } diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 1db6fea495bf..4c5bbb3aad31 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -45,7 +45,7 @@ #include "mlx4_en.h" #include "en_port.h" -static int mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) +static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; @@ -67,10 +67,9 @@ static int mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) en_err(priv, "failed adding vlan %d\n", vid); mutex_unlock(&mdev->state_lock); - return 0; } -static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_dev *mdev = priv->mdev; @@ -94,8 +93,6 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) en_err(priv, "Failed configuring VLAN filter\n"); } mutex_unlock(&mdev->state_lock); - - return 0; } u64 mlx4_en_mac_to_u64(u8 *addr) @@ -136,7 +133,7 @@ static void mlx4_en_do_set_mac(struct work_struct *work) if (priv->port_up) { /* Remove old MAC and insert the new one */ err = mlx4_replace_mac(mdev->dev, priv->port, - priv->base_qpn, priv->mac); + priv->base_qpn, priv->mac, 0); if (err) en_err(priv, "Failed changing HW MAC address\n"); } else @@ -207,16 +204,6 @@ static void mlx4_en_do_set_multicast(struct work_struct *work) goto out; } - if (!netif_carrier_ok(dev)) { - if (!mlx4_en_QUERY_PORT(mdev, priv->port)) { - if (priv->port_state.link_state) { - priv->last_link_state = MLX4_DEV_EVENT_PORT_UP; - netif_carrier_on(dev); - en_dbg(LINK, priv, "Link Up\n"); - } - } - } - /* * Promsicuous mode: disable all filters */ @@ -612,12 +599,12 @@ int mlx4_en_start_port(struct net_device *dev) ++rx_index; } - /* Set qp number */ - en_dbg(DRV, priv, "Getting qp number for port %d\n", priv->port); - err = mlx4_get_eth_qp(mdev->dev, priv->port, - priv->mac, &priv->base_qpn); + /* Set port mac number */ + en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port); + err = mlx4_register_mac(mdev->dev, priv->port, + priv->mac, &priv->base_qpn, 0); if (err) { - en_err(priv, "Failed getting eth qp\n"); + en_err(priv, "Failed setting port mac\n"); goto cq_err; } mdev->mac_removed[priv->port] = 0; @@ -712,7 +699,7 @@ int mlx4_en_start_port(struct net_device *dev) mlx4_en_release_rss_steer(priv); mac_err: - mlx4_put_eth_qp(mdev->dev, priv->port, priv->mac, priv->base_qpn); + mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn); cq_err: while (rx_index--) mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]); @@ -758,6 +745,10 @@ void mlx4_en_stop_port(struct net_device *dev) /* Flush multicast filter */ mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG); + /* Unregister Mac address for the port */ + mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn); + mdev->mac_removed[priv->port] = 1; + /* Free TX Rings */ for (i = 0; i < priv->tx_ring_num; i++) { mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[i]); @@ -771,10 +762,6 @@ void mlx4_en_stop_port(struct net_device *dev) /* Free RSS qps */ mlx4_en_release_rss_steer(priv); - /* Unregister Mac address for the port */ - mlx4_put_eth_qp(mdev->dev, priv->port, priv->mac, priv->base_qpn); - mdev->mac_removed[priv->port] = 1; - /* Free RX Rings */ for (i = 0; i < priv->rx_ring_num; i++) { mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_port.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_port.c index 331791467a22..03c84cd78cde 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_port.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_port.c @@ -41,6 +41,13 @@ #include "mlx4_en.h" +int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, + u64 mac, u64 clear, u8 mode) +{ + return mlx4_cmd(dev, (mac | (clear << 63)), port, mode, + MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B); +} + int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv) { struct mlx4_cmd_mailbox *mailbox; @@ -65,7 +72,76 @@ int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv) filter->entry[i] = cpu_to_be32(entry); } err = mlx4_cmd(dev, mailbox->dma, priv->port, 0, MLX4_CMD_SET_VLAN_FLTR, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); + MLX4_CMD_TIME_CLASS_B); + mlx4_free_cmd_mailbox(dev, mailbox); + return err; +} + + +int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, + u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx) +{ + struct mlx4_cmd_mailbox *mailbox; + struct mlx4_set_port_general_context *context; + int err; + u32 in_mod; + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + context = mailbox->buf; + memset(context, 0, sizeof *context); + + context->flags = SET_PORT_GEN_ALL_VALID; + context->mtu = cpu_to_be16(mtu); + context->pptx = (pptx * (!pfctx)) << 7; + context->pfctx = pfctx; + context->pprx = (pprx * (!pfcrx)) << 7; + context->pfcrx = pfcrx; + + in_mod = MLX4_SET_PORT_GENERAL << 8 | port; + err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, + MLX4_CMD_TIME_CLASS_B); + + mlx4_free_cmd_mailbox(dev, mailbox); + return err; +} + +int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, + u8 promisc) +{ + struct mlx4_cmd_mailbox *mailbox; + struct mlx4_set_port_rqp_calc_context *context; + int err; + u32 in_mod; + u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ? + MCAST_DIRECT : MCAST_DEFAULT; + + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER && + dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) + return 0; + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + context = mailbox->buf; + memset(context, 0, sizeof *context); + + context->base_qpn = cpu_to_be32(base_qpn); + context->n_mac = dev->caps.log_num_macs; + context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | + base_qpn); + context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT | + base_qpn); + context->intra_no_vlan = 0; + context->no_vlan = MLX4_NO_VLAN_IDX; + context->intra_vlan_miss = 0; + context->vlan_miss = MLX4_VLAN_MISS_IDX; + + in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port; + err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, + MLX4_CMD_TIME_CLASS_B); + mlx4_free_cmd_mailbox(dev, mailbox); return err; } @@ -83,8 +159,7 @@ int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port) return PTR_ERR(mailbox); memset(mailbox->buf, 0, sizeof(*qport_context)); err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0, - MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_WRAPPED); + MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B); if (err) goto out; qport_context = mailbox->buf; @@ -129,8 +204,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset) return PTR_ERR(mailbox); memset(mailbox->buf, 0, sizeof(*mlx4_en_stats)); err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, in_mod, 0, - MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_WRAPPED); + MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B); if (err) goto out; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_port.h b/trunk/drivers/net/ethernet/mellanox/mlx4/en_port.h index 6934fd7e66ed..19eb244f5165 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_port.h +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_port.h @@ -39,6 +39,49 @@ #define SET_PORT_PROMISC_SHIFT 31 #define SET_PORT_MC_PROMISC_SHIFT 30 +enum { + MLX4_CMD_SET_VLAN_FLTR = 0x47, + MLX4_CMD_SET_MCAST_FLTR = 0x48, + MLX4_CMD_DUMP_ETH_STATS = 0x49, +}; + +enum { + MCAST_DIRECT_ONLY = 0, + MCAST_DIRECT = 1, + MCAST_DEFAULT = 2 +}; + +struct mlx4_set_port_general_context { + u8 reserved[3]; + u8 flags; + u16 reserved2; + __be16 mtu; + u8 pptx; + u8 pfctx; + u16 reserved3; + u8 pprx; + u8 pfcrx; + u16 reserved4; +}; + +struct mlx4_set_port_rqp_calc_context { + __be32 base_qpn; + u8 rererved; + u8 n_mac; + u8 n_vlan; + u8 n_prio; + u8 reserved2[3]; + u8 mac_miss; + u8 intra_no_vlan; + u8 no_vlan; + u8 intra_vlan_miss; + u8 vlan_miss; + u8 reserved3[3]; + u8 no_vlan_prio; + __be32 promisc; + __be32 mcast; +}; + #define VLAN_FLTR_SIZE 128 struct mlx4_set_vlan_fltr_mbox { __be32 entry[VLAN_FLTR_SIZE]; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 630a7c113ab7..ce1bc573d114 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_rx.c @@ -541,8 +541,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud unsigned int length; int polled = 0; int ip_summed; - struct ethhdr *ethh; - u64 s_mac; if (!priv->port_up) return 0; @@ -579,19 +577,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud goto next; } - /* Get pointer to first fragment since we haven't skb yet and - * cast it to ethhdr struct */ - ethh = (struct ethhdr *)(page_address(skb_frags[0].page) + - skb_frags[0].offset); - s_mac = mlx4_en_mac_to_u64(ethh->h_source); - - /* If source MAC is equal to our own MAC and not performing - * the selftest or flb disabled - drop the packet */ - if (s_mac == priv->mac && - (!(dev->features & NETIF_F_LOOPBACK) || - !priv->validate_loopback)) - goto next; - /* * Packet is OK - process it. */ diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_selftest.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_selftest.c index bf2e5d3f177c..9fdbcecd499d 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_selftest.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_selftest.c @@ -43,7 +43,7 @@ static int mlx4_en_test_registers(struct mlx4_en_priv *priv) { return mlx4_cmd(priv->mdev->dev, 0, 0, 0, MLX4_CMD_HW_HEALTH_CHECK, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); + MLX4_CMD_TIME_CLASS_A); } static int mlx4_en_test_loopback_xmit(struct mlx4_en_priv *priv) diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 9ef9038d0629..7e76862de355 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -688,15 +688,17 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ring->tx_csum++; } - /* Copy dst mac address to wqe */ - skb_reset_mac_header(skb); - ethh = eth_hdr(skb); - if (ethh && ethh->h_dest) { - mac = mlx4_en_mac_to_u64(ethh->h_dest); - mac_h = (u32) ((mac & 0xffff00000000ULL) >> 16); - mac_l = (u32) (mac & 0xffffffff); - tx_desc->ctrl.srcrb_flags |= cpu_to_be32(mac_h); - tx_desc->ctrl.imm = cpu_to_be32(mac_l); + if (unlikely(priv->validate_loopback)) { + /* Copy dst mac address to wqe */ + skb_reset_mac_header(skb); + ethh = eth_hdr(skb); + if (ethh && ethh->h_dest) { + mac = mlx4_en_mac_to_u64(ethh->h_dest); + mac_h = (u32) ((mac & 0xffff00000000ULL) >> 16); + mac_l = (u32) (mac & 0xffffffff); + tx_desc->ctrl.srcrb_flags |= cpu_to_be32(mac_h); + tx_desc->ctrl.imm = cpu_to_be32(mac_l); + } } /* Handle LSO (TSO) packets */ diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/eq.c b/trunk/drivers/net/ethernet/mellanox/mlx4/eq.c index 1e9b55eb7217..24ee96775996 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -31,7 +31,6 @@ * SOFTWARE. */ -#include #include #include #include @@ -53,6 +52,30 @@ enum { MLX4_EQ_ENTRY_SIZE = 0x20 }; +/* + * Must be packed because start is 64 bits but only aligned to 32 bits. + */ +struct mlx4_eq_context { + __be32 flags; + u16 reserved1[3]; + __be16 page_offset; + u8 log_eq_size; + u8 reserved2[4]; + u8 eq_period; + u8 reserved3; + u8 eq_max_count; + u8 reserved4[3]; + u8 intr; + u8 log_page_size; + u8 reserved5[2]; + u8 mtt_base_addr_h; + __be32 mtt_base_addr_l; + u32 reserved6[2]; + __be32 consumer_index; + __be32 producer_index; + u32 reserved7[4]; +}; + #define MLX4_EQ_STATUS_OK ( 0 << 28) #define MLX4_EQ_STATUS_WRITE_FAIL (10 << 28) #define MLX4_EQ_OWNER_SW ( 0 << 24) @@ -77,9 +100,46 @@ enum { (1ull << MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) | \ (1ull << MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE) | \ (1ull << MLX4_EVENT_TYPE_SRQ_LIMIT) | \ - (1ull << MLX4_EVENT_TYPE_CMD) | \ - (1ull << MLX4_EVENT_TYPE_COMM_CHANNEL) | \ - (1ull << MLX4_EVENT_TYPE_FLR_EVENT)) + (1ull << MLX4_EVENT_TYPE_CMD)) + +struct mlx4_eqe { + u8 reserved1; + u8 type; + u8 reserved2; + u8 subtype; + union { + u32 raw[6]; + struct { + __be32 cqn; + } __packed comp; + struct { + u16 reserved1; + __be16 token; + u32 reserved2; + u8 reserved3[3]; + u8 status; + __be64 out_param; + } __packed cmd; + struct { + __be32 qpn; + } __packed qp; + struct { + __be32 srqn; + } __packed srq; + struct { + __be32 cqn; + u32 reserved1; + u8 reserved2[3]; + u8 syndrome; + } __packed cq_err; + struct { + u32 reserved1[2]; + __be32 port; + } __packed port_change; + } event; + u8 reserved3[3]; + u8 owner; +} __packed; static void eq_set_ci(struct mlx4_eq *eq, int req_not) { @@ -102,144 +162,13 @@ static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq) return !!(eqe->owner & 0x80) ^ !!(eq->cons_index & eq->nent) ? NULL : eqe; } -static struct mlx4_eqe *next_slave_event_eqe(struct mlx4_slave_event_eq *slave_eq) -{ - struct mlx4_eqe *eqe = - &slave_eq->event_eqe[slave_eq->cons & (SLAVE_EVENT_EQ_SIZE - 1)]; - return (!!(eqe->owner & 0x80) ^ - !!(slave_eq->cons & SLAVE_EVENT_EQ_SIZE)) ? - eqe : NULL; -} - -void mlx4_gen_slave_eqe(struct work_struct *work) -{ - struct mlx4_mfunc_master_ctx *master = - container_of(work, struct mlx4_mfunc_master_ctx, - slave_event_work); - struct mlx4_mfunc *mfunc = - container_of(master, struct mlx4_mfunc, master); - struct mlx4_priv *priv = container_of(mfunc, struct mlx4_priv, mfunc); - struct mlx4_dev *dev = &priv->dev; - struct mlx4_slave_event_eq *slave_eq = &mfunc->master.slave_eq; - struct mlx4_eqe *eqe; - u8 slave; - int i; - - for (eqe = next_slave_event_eqe(slave_eq); eqe; - eqe = next_slave_event_eqe(slave_eq)) { - slave = eqe->slave_id; - - /* All active slaves need to receive the event */ - if (slave == ALL_SLAVES) { - for (i = 0; i < dev->num_slaves; i++) { - if (i != dev->caps.function && - master->slave_state[i].active) - if (mlx4_GEN_EQE(dev, i, eqe)) - mlx4_warn(dev, "Failed to " - " generate event " - "for slave %d\n", i); - } - } else { - if (mlx4_GEN_EQE(dev, slave, eqe)) - mlx4_warn(dev, "Failed to generate event " - "for slave %d\n", slave); - } - ++slave_eq->cons; - } -} - - -static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_slave_event_eq *slave_eq = &priv->mfunc.master.slave_eq; - struct mlx4_eqe *s_eqe = - &slave_eq->event_eqe[slave_eq->prod & (SLAVE_EVENT_EQ_SIZE - 1)]; - - if ((!!(s_eqe->owner & 0x80)) ^ - (!!(slave_eq->prod & SLAVE_EVENT_EQ_SIZE))) { - mlx4_warn(dev, "Master failed to generate an EQE for slave: %d. " - "No free EQE on slave events queue\n", slave); - return; - } - - memcpy(s_eqe, eqe, sizeof(struct mlx4_eqe) - 1); - s_eqe->slave_id = slave; - /* ensure all information is written before setting the ownersip bit */ - wmb(); - s_eqe->owner = !!(slave_eq->prod & SLAVE_EVENT_EQ_SIZE) ? 0x0 : 0x80; - ++slave_eq->prod; - - queue_work(priv->mfunc.master.comm_wq, - &priv->mfunc.master.slave_event_work); -} - -static void mlx4_slave_event(struct mlx4_dev *dev, int slave, - struct mlx4_eqe *eqe) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_slave_state *s_slave = - &priv->mfunc.master.slave_state[slave]; - - if (!s_slave->active) { - /*mlx4_warn(dev, "Trying to pass event to inactive slave\n");*/ - return; - } - - slave_event(dev, slave, eqe); -} - -void mlx4_master_handle_slave_flr(struct work_struct *work) -{ - struct mlx4_mfunc_master_ctx *master = - container_of(work, struct mlx4_mfunc_master_ctx, - slave_flr_event_work); - struct mlx4_mfunc *mfunc = - container_of(master, struct mlx4_mfunc, master); - struct mlx4_priv *priv = - container_of(mfunc, struct mlx4_priv, mfunc); - struct mlx4_dev *dev = &priv->dev; - struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; - int i; - int err; - - mlx4_dbg(dev, "mlx4_handle_slave_flr\n"); - - for (i = 0 ; i < dev->num_slaves; i++) { - - if (MLX4_COMM_CMD_FLR == slave_state[i].last_cmd) { - mlx4_dbg(dev, "mlx4_handle_slave_flr: " - "clean slave: %d\n", i); - - mlx4_delete_all_resources_for_slave(dev, i); - /*return the slave to running mode*/ - spin_lock(&priv->mfunc.master.slave_state_lock); - slave_state[i].last_cmd = MLX4_COMM_CMD_RESET; - slave_state[i].is_slave_going_down = 0; - spin_unlock(&priv->mfunc.master.slave_state_lock); - /*notify the FW:*/ - err = mlx4_cmd(dev, 0, i, 0, MLX4_CMD_INFORM_FLR_DONE, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); - if (err) - mlx4_warn(dev, "Failed to notify FW on " - "FLR done (slave:%d)\n", i); - } - } -} - static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) { - struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_eqe *eqe; int cqn; int eqes_found = 0; int set_ci = 0; int port; - int slave = 0; - int ret; - u32 flr_slave; - u8 update_slave_state; - int i; while ((eqe = next_eqe_sw(eq))) { /* @@ -262,68 +191,14 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) case MLX4_EVENT_TYPE_PATH_MIG_FAILED: case MLX4_EVENT_TYPE_WQ_INVAL_REQ_ERROR: case MLX4_EVENT_TYPE_WQ_ACCESS_ERROR: - mlx4_dbg(dev, "event %d arrived\n", eqe->type); - if (mlx4_is_master(dev)) { - /* forward only to slave owning the QP */ - ret = mlx4_get_slave_from_resource_id(dev, - RES_QP, - be32_to_cpu(eqe->event.qp.qpn) - & 0xffffff, &slave); - if (ret && ret != -ENOENT) { - mlx4_dbg(dev, "QP event %02x(%02x) on " - "EQ %d at index %u: could " - "not get slave id (%d)\n", - eqe->type, eqe->subtype, - eq->eqn, eq->cons_index, ret); - break; - } - - if (!ret && slave != dev->caps.function) { - mlx4_slave_event(dev, slave, eqe); - break; - } - - } - mlx4_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & - 0xffffff, eqe->type); + mlx4_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff, + eqe->type); break; case MLX4_EVENT_TYPE_SRQ_LIMIT: - mlx4_warn(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT\n", - __func__); case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR: - if (mlx4_is_master(dev)) { - /* forward only to slave owning the SRQ */ - ret = mlx4_get_slave_from_resource_id(dev, - RES_SRQ, - be32_to_cpu(eqe->event.srq.srqn) - & 0xffffff, - &slave); - if (ret && ret != -ENOENT) { - mlx4_warn(dev, "SRQ event %02x(%02x) " - "on EQ %d at index %u: could" - " not get slave id (%d)\n", - eqe->type, eqe->subtype, - eq->eqn, eq->cons_index, ret); - break; - } - mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x," - " event: %02x(%02x)\n", __func__, - slave, - be32_to_cpu(eqe->event.srq.srqn), - eqe->type, eqe->subtype); - - if (!ret && slave != dev->caps.function) { - mlx4_warn(dev, "%s: sending event " - "%02x(%02x) to slave:%d\n", - __func__, eqe->type, - eqe->subtype, slave); - mlx4_slave_event(dev, slave, eqe); - break; - } - } - mlx4_srq_event(dev, be32_to_cpu(eqe->event.srq.srqn) & - 0xffffff, eqe->type); + mlx4_srq_event(dev, be32_to_cpu(eqe->event.srq.srqn) & 0xffffff, + eqe->type); break; case MLX4_EVENT_TYPE_CMD: @@ -336,35 +211,13 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) case MLX4_EVENT_TYPE_PORT_CHANGE: port = be32_to_cpu(eqe->event.port_change.port) >> 28; if (eqe->subtype == MLX4_PORT_CHANGE_SUBTYPE_DOWN) { - mlx4_dispatch_event(dev, - MLX4_DEV_EVENT_PORT_DOWN, + mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_DOWN, port); mlx4_priv(dev)->sense.do_sense_port[port] = 1; - if (mlx4_is_master(dev)) - /*change the state of all slave's port - * to down:*/ - for (i = 0; i < dev->num_slaves; i++) { - mlx4_dbg(dev, "%s: Sending " - "MLX4_PORT_CHANGE_SUBTYPE_DOWN" - " to slave: %d, port:%d\n", - __func__, i, port); - if (i == dev->caps.function) - continue; - mlx4_slave_event(dev, i, eqe); - } } else { - mlx4_dispatch_event(dev, - MLX4_DEV_EVENT_PORT_UP, + mlx4_dispatch_event(dev, MLX4_DEV_EVENT_PORT_UP, port); mlx4_priv(dev)->sense.do_sense_port[port] = 0; - - if (mlx4_is_master(dev)) { - for (i = 0; i < dev->num_slaves; i++) { - if (i == dev->caps.function) - continue; - mlx4_slave_event(dev, i, eqe); - } - } } break; @@ -373,28 +226,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) eqe->event.cq_err.syndrome == 1 ? "overrun" : "access violation", be32_to_cpu(eqe->event.cq_err.cqn) & 0xffffff); - if (mlx4_is_master(dev)) { - ret = mlx4_get_slave_from_resource_id(dev, - RES_CQ, - be32_to_cpu(eqe->event.cq_err.cqn) - & 0xffffff, &slave); - if (ret && ret != -ENOENT) { - mlx4_dbg(dev, "CQ event %02x(%02x) on " - "EQ %d at index %u: could " - "not get slave id (%d)\n", - eqe->type, eqe->subtype, - eq->eqn, eq->cons_index, ret); - break; - } - - if (!ret && slave != dev->caps.function) { - mlx4_slave_event(dev, slave, eqe); - break; - } - } - mlx4_cq_event(dev, - be32_to_cpu(eqe->event.cq_err.cqn) - & 0xffffff, + mlx4_cq_event(dev, be32_to_cpu(eqe->event.cq_err.cqn), eqe->type); break; @@ -402,60 +234,13 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) mlx4_warn(dev, "EQ overrun on EQN %d\n", eq->eqn); break; - case MLX4_EVENT_TYPE_COMM_CHANNEL: - if (!mlx4_is_master(dev)) { - mlx4_warn(dev, "Received comm channel event " - "for non master device\n"); - break; - } - memcpy(&priv->mfunc.master.comm_arm_bit_vector, - eqe->event.comm_channel_arm.bit_vec, - sizeof eqe->event.comm_channel_arm.bit_vec); - queue_work(priv->mfunc.master.comm_wq, - &priv->mfunc.master.comm_work); - break; - - case MLX4_EVENT_TYPE_FLR_EVENT: - flr_slave = be32_to_cpu(eqe->event.flr_event.slave_id); - if (!mlx4_is_master(dev)) { - mlx4_warn(dev, "Non-master function received" - "FLR event\n"); - break; - } - - mlx4_dbg(dev, "FLR event for slave: %d\n", flr_slave); - - if (flr_slave > dev->num_slaves) { - mlx4_warn(dev, - "Got FLR for unknown function: %d\n", - flr_slave); - update_slave_state = 0; - } else - update_slave_state = 1; - - spin_lock(&priv->mfunc.master.slave_state_lock); - if (update_slave_state) { - priv->mfunc.master.slave_state[flr_slave].active = false; - priv->mfunc.master.slave_state[flr_slave].last_cmd = MLX4_COMM_CMD_FLR; - priv->mfunc.master.slave_state[flr_slave].is_slave_going_down = 1; - } - spin_unlock(&priv->mfunc.master.slave_state_lock); - queue_work(priv->mfunc.master.comm_wq, - &priv->mfunc.master.slave_flr_event_work); - break; case MLX4_EVENT_TYPE_EEC_CATAS_ERROR: case MLX4_EVENT_TYPE_ECC_DETECT: default: - mlx4_warn(dev, "Unhandled event %02x(%02x) on EQ %d at " - "index %u. owner=%x, nent=0x%x, slave=%x, " - "ownership=%s\n", - eqe->type, eqe->subtype, eq->eqn, - eq->cons_index, eqe->owner, eq->nent, - eqe->slave_id, - !!(eqe->owner & 0x80) ^ - !!(eq->cons_index & eq->nent) ? "HW" : "SW"); + mlx4_warn(dev, "Unhandled event %02x(%02x) on EQ %d at index %u\n", + eqe->type, eqe->subtype, eq->eqn, eq->cons_index); break; - }; + } ++eq->cons_index; eqes_found = 1; @@ -505,58 +290,25 @@ static irqreturn_t mlx4_msi_x_interrupt(int irq, void *eq_ptr) return IRQ_HANDLED; } -int mlx4_MAP_EQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_slave_event_eq_info *event_eq = - &priv->mfunc.master.slave_state[slave].event_eq; - u32 in_modifier = vhcr->in_modifier; - u32 eqn = in_modifier & 0x1FF; - u64 in_param = vhcr->in_param; - int err = 0; - - if (slave == dev->caps.function) - err = mlx4_cmd(dev, in_param, (in_modifier & 0x80000000) | eqn, - 0, MLX4_CMD_MAP_EQ, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_NATIVE); - if (!err) { - if (in_modifier >> 31) { - /* unmap */ - event_eq->event_type &= ~in_param; - } else { - event_eq->eqn = eqn; - event_eq->event_type = in_param; - } - } - return err; -} - static int mlx4_MAP_EQ(struct mlx4_dev *dev, u64 event_mask, int unmap, int eq_num) { return mlx4_cmd(dev, event_mask, (unmap << 31) | eq_num, - 0, MLX4_CMD_MAP_EQ, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_WRAPPED); + 0, MLX4_CMD_MAP_EQ, MLX4_CMD_TIME_CLASS_B); } static int mlx4_SW2HW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int eq_num) { - return mlx4_cmd(dev, mailbox->dma | dev->caps.function, eq_num, 0, - MLX4_CMD_SW2HW_EQ, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED); + return mlx4_cmd(dev, mailbox->dma, eq_num, 0, MLX4_CMD_SW2HW_EQ, + MLX4_CMD_TIME_CLASS_A); } static int mlx4_HW2SW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int eq_num) { - return mlx4_cmd_box(dev, dev->caps.function, mailbox->dma, eq_num, - 0, MLX4_CMD_HW2SW_EQ, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED); + return mlx4_cmd_box(dev, 0, mailbox->dma, eq_num, 0, MLX4_CMD_HW2SW_EQ, + MLX4_CMD_TIME_CLASS_A); } static int mlx4_num_eq_uar(struct mlx4_dev *dev) @@ -833,16 +585,14 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) for (i = 0; i < mlx4_num_eq_uar(dev); ++i) priv->eq_table.uar_map[i] = NULL; - if (!mlx4_is_slave(dev)) { - err = mlx4_map_clr_int(dev); - if (err) - goto err_out_bitmap; + err = mlx4_map_clr_int(dev); + if (err) + goto err_out_bitmap; - priv->eq_table.clr_mask = - swab32(1 << (priv->eq_table.inta_pin & 31)); - priv->eq_table.clr_int = priv->clr_base + - (priv->eq_table.inta_pin < 32 ? 4 : 0); - } + priv->eq_table.clr_mask = + swab32(1 << (priv->eq_table.inta_pin & 31)); + priv->eq_table.clr_int = priv->clr_base + + (priv->eq_table.inta_pin < 32 ? 4 : 0); priv->eq_table.irq_names = kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1 + @@ -950,8 +700,7 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) mlx4_free_eq(dev, &priv->eq_table.eq[i]); --i; } - if (!mlx4_is_slave(dev)) - mlx4_unmap_clr_int(dev); + mlx4_unmap_clr_int(dev); mlx4_free_irqs(dev); err_out_bitmap: @@ -976,8 +725,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev) for (i = 0; i < dev->caps.num_comp_vectors + dev->caps.comp_pool + 1; ++i) mlx4_free_eq(dev, &priv->eq_table.eq[i]); - if (!mlx4_is_slave(dev)) - mlx4_unmap_clr_int(dev); + mlx4_unmap_clr_int(dev); for (i = 0; i < mlx4_num_eq_uar(dev); ++i) if (priv->eq_table.uar_map[i]) @@ -1000,7 +748,7 @@ int mlx4_test_interrupts(struct mlx4_dev *dev) err = mlx4_NOP(dev); /* When not in MSI_X, there is only one irq to check */ - if (!(dev->flags & MLX4_FLAG_MSI_X) || mlx4_is_slave(dev)) + if (!(dev->flags & MLX4_FLAG_MSI_X)) return err; /* A loop over all completion vectors, for each vector we will check diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/fw.c b/trunk/drivers/net/ethernet/mellanox/mlx4/fw.c index f03b54e0aa53..435ca6e49734 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -32,7 +32,6 @@ * SOFTWARE. */ -#include #include #include #include @@ -140,185 +139,12 @@ int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg) MLX4_PUT(inbox, cfg->log_pg_sz_m, MOD_STAT_CFG_PG_SZ_M_OFFSET); err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_MOD_STAT_CFG, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_A); mlx4_free_cmd_mailbox(dev, mailbox); return err; } -int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - u8 field; - u32 size; - int err = 0; - -#define QUERY_FUNC_CAP_FLAGS_OFFSET 0x0 -#define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1 -#define QUERY_FUNC_CAP_FUNCTION_OFFSET 0x3 -#define QUERY_FUNC_CAP_PF_BHVR_OFFSET 0x4 -#define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x10 -#define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x14 -#define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET 0x18 -#define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET 0x20 -#define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET 0x24 -#define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET 0x28 -#define QUERY_FUNC_CAP_MAX_EQ_OFFSET 0x2c -#define QUERY_FUNC_CAP_RESERVED_EQ_OFFSET 0X30 - -#define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3 -#define QUERY_FUNC_CAP_ETH_PROPS_OFFSET 0xc - - if (vhcr->op_modifier == 1) { - field = vhcr->in_modifier; - MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_PHYS_PORT_OFFSET); - - field = 0; /* ensure fvl bit is not set */ - MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_ETH_PROPS_OFFSET); - } else if (vhcr->op_modifier == 0) { - field = 1 << 7; /* enable only ethernet interface */ - MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET); - - field = slave; - MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FUNCTION_OFFSET); - - field = dev->caps.num_ports; - MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); - - size = 0; /* no PF behavious is set for now */ - MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_PF_BHVR_OFFSET); - - size = dev->caps.num_qps; - MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); - - size = dev->caps.num_srqs; - MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET); - - size = dev->caps.num_cqs; - MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET); - - size = dev->caps.num_eqs; - MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET); - - size = dev->caps.reserved_eqs; - MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); - - size = dev->caps.num_mpts; - MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET); - - size = dev->caps.num_mtts; - MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET); - - size = dev->caps.num_mgms + dev->caps.num_amgms; - MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); - - } else - err = -EINVAL; - - return err; -} - -int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, struct mlx4_func_cap *func_cap) -{ - struct mlx4_cmd_mailbox *mailbox; - u32 *outbox; - u8 field; - u32 size; - int i; - int err = 0; - - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_FUNC_CAP, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); - if (err) - goto out; - - outbox = mailbox->buf; - - MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS_OFFSET); - if (!(field & (1 << 7))) { - mlx4_err(dev, "The host doesn't support eth interface\n"); - err = -EPROTONOSUPPORT; - goto out; - } - - MLX4_GET(field, outbox, QUERY_FUNC_CAP_FUNCTION_OFFSET); - func_cap->function = field; - - MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET); - func_cap->num_ports = field; - - MLX4_GET(size, outbox, QUERY_FUNC_CAP_PF_BHVR_OFFSET); - func_cap->pf_context_behaviour = size; - - MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET); - func_cap->qp_quota = size & 0xFFFFFF; - - MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET); - func_cap->srq_quota = size & 0xFFFFFF; - - MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET); - func_cap->cq_quota = size & 0xFFFFFF; - - MLX4_GET(size, outbox, QUERY_FUNC_CAP_MAX_EQ_OFFSET); - func_cap->max_eq = size & 0xFFFFFF; - - MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET); - func_cap->reserved_eq = size & 0xFFFFFF; - - MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET); - func_cap->mpt_quota = size & 0xFFFFFF; - - MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET); - func_cap->mtt_quota = size & 0xFFFFFF; - - MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET); - func_cap->mcg_quota = size & 0xFFFFFF; - - for (i = 1; i <= func_cap->num_ports; ++i) { - err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 1, - MLX4_CMD_QUERY_FUNC_CAP, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); - if (err) - goto out; - - MLX4_GET(field, outbox, QUERY_FUNC_CAP_ETH_PROPS_OFFSET); - if (field & (1 << 7)) { - mlx4_err(dev, "VLAN is enforced on this port\n"); - err = -EPROTONOSUPPORT; - goto out; - } - - if (field & (1 << 6)) { - mlx4_err(dev, "Force mac is enabled on this port\n"); - err = -EPROTONOSUPPORT; - goto out; - } - - MLX4_GET(field, outbox, QUERY_FUNC_CAP_PHYS_PORT_OFFSET); - func_cap->physical_port[i] = field; - } - - /* All other resources are allocated by the master, but we still report - * 'num' and 'reserved' capabilities as follows: - * - num remains the maximum resource index - * - 'num - reserved' is the total available objects of a resource, but - * resource indices may be less than 'reserved' - * TODO: set per-resource quotas */ - -out: - mlx4_free_cmd_mailbox(dev, mailbox); - - return err; -} - int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) { struct mlx4_cmd_mailbox *mailbox; @@ -403,7 +229,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) outbox = mailbox->buf; err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP, - MLX4_CMD_TIME_CLASS_A, !mlx4_is_slave(dev)); + MLX4_CMD_TIME_CLASS_A); if (err) goto out; @@ -570,8 +396,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) for (i = 1; i <= dev_cap->num_ports; ++i) { err = mlx4_cmd_box(dev, 0, mailbox->dma, i, 0, MLX4_CMD_QUERY_PORT, - MLX4_CMD_TIME_CLASS_B, - !mlx4_is_slave(dev)); + MLX4_CMD_TIME_CLASS_B); if (err) goto out; @@ -645,54 +470,6 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) return err; } -int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - u64 def_mac; - u8 port_type; - int err; - - err = mlx4_cmd_box(dev, 0, outbox->dma, vhcr->in_modifier, 0, - MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_NATIVE); - - if (!err && dev->caps.function != slave) { - /* set slave default_mac address */ - MLX4_GET(def_mac, outbox->buf, QUERY_PORT_MAC_OFFSET); - def_mac += slave << 8; - MLX4_PUT(outbox->buf, def_mac, QUERY_PORT_MAC_OFFSET); - - /* get port type - currently only eth is enabled */ - MLX4_GET(port_type, outbox->buf, - QUERY_PORT_SUPPORTED_TYPE_OFFSET); - - /* disable ib */ - port_type &= 0xFE; - - /* check eth is enabled for this port */ - if (!(port_type & 2)) - mlx4_dbg(dev, "QUERY PORT: eth not supported by host"); - - MLX4_PUT(outbox->buf, port_type, - QUERY_PORT_SUPPORTED_TYPE_OFFSET); - } - - return err; -} - -static int mlx4_QUERY_PORT(struct mlx4_dev *dev, void *ptr, u8 port) -{ - struct mlx4_cmd_mailbox *outbox = ptr; - - return mlx4_cmd_box(dev, 0, outbox->dma, port, 0, - MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_WRAPPED); -} -EXPORT_SYMBOL_GPL(mlx4_QUERY_PORT); - int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt) { struct mlx4_cmd_mailbox *mailbox; @@ -742,8 +519,7 @@ int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt) if (++nent == MLX4_MAILBOX_SIZE / 16) { err = mlx4_cmd(dev, mailbox->dma, nent, 0, op, - MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_B); if (err) goto out; nent = 0; @@ -752,8 +528,7 @@ int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt) } if (nent) - err = mlx4_cmd(dev, mailbox->dma, nent, 0, op, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); + err = mlx4_cmd(dev, mailbox->dma, nent, 0, op, MLX4_CMD_TIME_CLASS_B); if (err) goto out; @@ -782,15 +557,13 @@ int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm) int mlx4_UNMAP_FA(struct mlx4_dev *dev) { - return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_FA, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); + return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_FA, MLX4_CMD_TIME_CLASS_B); } int mlx4_RUN_FW(struct mlx4_dev *dev) { - return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_RUN_FW, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); + return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_RUN_FW, MLX4_CMD_TIME_CLASS_A); } int mlx4_QUERY_FW(struct mlx4_dev *dev) @@ -806,7 +579,6 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) #define QUERY_FW_OUT_SIZE 0x100 #define QUERY_FW_VER_OFFSET 0x00 -#define QUERY_FW_PPF_ID 0x09 #define QUERY_FW_CMD_IF_REV_OFFSET 0x0a #define QUERY_FW_MAX_CMD_OFFSET 0x0f #define QUERY_FW_ERR_START_OFFSET 0x30 @@ -817,16 +589,13 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) #define QUERY_FW_CLR_INT_BASE_OFFSET 0x20 #define QUERY_FW_CLR_INT_BAR_OFFSET 0x28 -#define QUERY_FW_COMM_BASE_OFFSET 0x40 -#define QUERY_FW_COMM_BAR_OFFSET 0x48 - mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) return PTR_ERR(mailbox); outbox = mailbox->buf; err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_FW, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_A); if (err) goto out; @@ -839,9 +608,6 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) ((fw_ver & 0xffff0000ull) >> 16) | ((fw_ver & 0x0000ffffull) << 16); - MLX4_GET(lg, outbox, QUERY_FW_PPF_ID); - dev->caps.function = lg; - MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET); if (cmd_if_rev < MLX4_COMMAND_INTERFACE_MIN_REV || cmd_if_rev > MLX4_COMMAND_INTERFACE_MAX_REV) { @@ -883,11 +649,6 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) MLX4_GET(fw->clr_int_bar, outbox, QUERY_FW_CLR_INT_BAR_OFFSET); fw->clr_int_bar = (fw->clr_int_bar >> 6) * 2; - MLX4_GET(fw->comm_base, outbox, QUERY_FW_COMM_BASE_OFFSET); - MLX4_GET(fw->comm_bar, outbox, QUERY_FW_COMM_BAR_OFFSET); - fw->comm_bar = (fw->comm_bar >> 6) * 2; - mlx4_dbg(dev, "Communication vector bar:%d offset:0x%llx\n", - fw->comm_bar, fw->comm_base); mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2); /* @@ -950,7 +711,7 @@ int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter) outbox = mailbox->buf; err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, MLX4_CMD_QUERY_ADAPTER, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_A); if (err) goto out; @@ -982,7 +743,6 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) #define INIT_HCA_LOG_SRQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x2f) #define INIT_HCA_CQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x30) #define INIT_HCA_LOG_CQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x37) -#define INIT_HCA_EQE_CQE_OFFSETS (INIT_HCA_QPC_OFFSET + 0x38) #define INIT_HCA_ALTC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x40) #define INIT_HCA_AUXC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x50) #define INIT_HCA_EQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x60) @@ -1071,11 +831,10 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) /* UAR attributes */ - MLX4_PUT(inbox, param->uar_page_sz, INIT_HCA_UAR_PAGE_SZ_OFFSET); + MLX4_PUT(inbox, (u8) (PAGE_SHIFT - 12), INIT_HCA_UAR_PAGE_SZ_OFFSET); MLX4_PUT(inbox, param->log_uar_sz, INIT_HCA_LOG_UAR_SZ_OFFSET); - err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA, 10000, - MLX4_CMD_NATIVE); + err = mlx4_cmd(dev, mailbox->dma, 0, 0, MLX4_CMD_INIT_HCA, 10000); if (err) mlx4_err(dev, "INIT_HCA returns %d\n", err); @@ -1084,101 +843,6 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) return err; } -int mlx4_QUERY_HCA(struct mlx4_dev *dev, - struct mlx4_init_hca_param *param) -{ - struct mlx4_cmd_mailbox *mailbox; - __be32 *outbox; - int err; - -#define QUERY_HCA_GLOBAL_CAPS_OFFSET 0x04 - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - outbox = mailbox->buf; - - err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0, - MLX4_CMD_QUERY_HCA, - MLX4_CMD_TIME_CLASS_B, - !mlx4_is_slave(dev)); - if (err) - goto out; - - MLX4_GET(param->global_caps, outbox, QUERY_HCA_GLOBAL_CAPS_OFFSET); - - /* QPC/EEC/CQC/EQC/RDMARC attributes */ - - MLX4_GET(param->qpc_base, outbox, INIT_HCA_QPC_BASE_OFFSET); - MLX4_GET(param->log_num_qps, outbox, INIT_HCA_LOG_QP_OFFSET); - MLX4_GET(param->srqc_base, outbox, INIT_HCA_SRQC_BASE_OFFSET); - MLX4_GET(param->log_num_srqs, outbox, INIT_HCA_LOG_SRQ_OFFSET); - MLX4_GET(param->cqc_base, outbox, INIT_HCA_CQC_BASE_OFFSET); - MLX4_GET(param->log_num_cqs, outbox, INIT_HCA_LOG_CQ_OFFSET); - MLX4_GET(param->altc_base, outbox, INIT_HCA_ALTC_BASE_OFFSET); - MLX4_GET(param->auxc_base, outbox, INIT_HCA_AUXC_BASE_OFFSET); - MLX4_GET(param->eqc_base, outbox, INIT_HCA_EQC_BASE_OFFSET); - MLX4_GET(param->log_num_eqs, outbox, INIT_HCA_LOG_EQ_OFFSET); - MLX4_GET(param->rdmarc_base, outbox, INIT_HCA_RDMARC_BASE_OFFSET); - MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET); - - /* multicast attributes */ - - MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET); - MLX4_GET(param->log_mc_entry_sz, outbox, - INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET); - MLX4_GET(param->log_mc_hash_sz, outbox, - INIT_HCA_LOG_MC_HASH_SZ_OFFSET); - MLX4_GET(param->log_mc_table_sz, outbox, - INIT_HCA_LOG_MC_TABLE_SZ_OFFSET); - - /* TPT attributes */ - - MLX4_GET(param->dmpt_base, outbox, INIT_HCA_DMPT_BASE_OFFSET); - MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET); - MLX4_GET(param->mtt_base, outbox, INIT_HCA_MTT_BASE_OFFSET); - MLX4_GET(param->cmpt_base, outbox, INIT_HCA_CMPT_BASE_OFFSET); - - /* UAR attributes */ - - MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET); - MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET); - -out: - mlx4_free_cmd_mailbox(dev, mailbox); - - return err; -} - -int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int port = vhcr->in_modifier; - int err; - - if (priv->mfunc.master.slave_state[slave].init_port_mask & (1 << port)) - return 0; - - if (dev->caps.port_mask[port] == MLX4_PORT_TYPE_IB) - return -ENODEV; - - /* Enable port only if it was previously disabled */ - if (!priv->mfunc.master.init_port_ref[port]) { - err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); - if (err) - return err; - priv->mfunc.master.slave_state[slave].init_port_mask |= - (1 << port); - } - ++priv->mfunc.master.init_port_ref[port]; - return 0; -} - int mlx4_INIT_PORT(struct mlx4_dev *dev, int port) { struct mlx4_cmd_mailbox *mailbox; @@ -1222,62 +886,33 @@ int mlx4_INIT_PORT(struct mlx4_dev *dev, int port) MLX4_PUT(inbox, field, INIT_PORT_MAX_PKEY_OFFSET); err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_INIT_PORT, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_A); mlx4_free_cmd_mailbox(dev, mailbox); } else err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_INIT_PORT, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); + MLX4_CMD_TIME_CLASS_A); return err; } EXPORT_SYMBOL_GPL(mlx4_INIT_PORT); -int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int port = vhcr->in_modifier; - int err; - - if (!(priv->mfunc.master.slave_state[slave].init_port_mask & - (1 << port))) - return 0; - - if (dev->caps.port_mask[port] == MLX4_PORT_TYPE_IB) - return -ENODEV; - if (priv->mfunc.master.init_port_ref[port] == 1) { - err = mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000, - MLX4_CMD_NATIVE); - if (err) - return err; - } - priv->mfunc.master.slave_state[slave].init_port_mask &= ~(1 << port); - --priv->mfunc.master.init_port_ref[port]; - return 0; -} - int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port) { - return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000, - MLX4_CMD_WRAPPED); + return mlx4_cmd(dev, 0, port, 0, MLX4_CMD_CLOSE_PORT, 1000); } EXPORT_SYMBOL_GPL(mlx4_CLOSE_PORT); int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic) { - return mlx4_cmd(dev, 0, 0, panic, MLX4_CMD_CLOSE_HCA, 1000, - MLX4_CMD_NATIVE); + return mlx4_cmd(dev, 0, 0, panic, MLX4_CMD_CLOSE_HCA, 1000); } int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages) { int ret = mlx4_cmd_imm(dev, icm_size, aux_pages, 0, 0, MLX4_CMD_SET_ICM_SIZE, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_A); if (ret) return ret; @@ -1294,7 +929,7 @@ int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages) int mlx4_NOP(struct mlx4_dev *dev) { /* Input modifier of 0x1f means "finish as soon as possible." */ - return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100, MLX4_CMD_NATIVE); + return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100); } #define MLX4_WOL_SETUP_MODE (5 << 28) @@ -1303,8 +938,7 @@ int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port) u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8; return mlx4_cmd_imm(dev, 0, config, in_mod, 0x3, - MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); + MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A); } EXPORT_SYMBOL_GPL(mlx4_wol_read); @@ -1313,6 +947,6 @@ int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port) u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8; return mlx4_cmd(dev, config, in_mod, 0x1, MLX4_CMD_MOD_STAT_CFG, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_A); } EXPORT_SYMBOL_GPL(mlx4_wol_write); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/fw.h b/trunk/drivers/net/ethernet/mellanox/mlx4/fw.h index 3368363a8ec5..bf5ec2286528 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/fw.h @@ -116,23 +116,6 @@ struct mlx4_dev_cap { u32 max_counters; }; -struct mlx4_func_cap { - u8 function; - u8 num_ports; - u8 flags; - u32 pf_context_behaviour; - int qp_quota; - int cq_quota; - int srq_quota; - int mpt_quota; - int mtt_quota; - int max_eq; - int reserved_eq; - int mcg_quota; - u8 physical_port[MLX4_MAX_PORTS + 1]; - u8 port_flags[MLX4_MAX_PORTS + 1]; -}; - struct mlx4_adapter { char board_id[MLX4_BOARD_ID_LEN]; u8 inta_pin; @@ -150,7 +133,6 @@ struct mlx4_init_hca_param { u64 dmpt_base; u64 cmpt_base; u64 mtt_base; - u64 global_caps; u16 log_mc_entry_sz; u16 log_mc_hash_sz; u8 log_num_qps; @@ -161,7 +143,6 @@ struct mlx4_init_hca_param { u8 log_mc_table_sz; u8 log_mpt_sz; u8 log_uar_sz; - u8 uar_page_sz; /* log pg sz in 4k chunks */ }; struct mlx4_init_ib_param { @@ -186,19 +167,12 @@ struct mlx4_set_ib_param { }; int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap); -int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, struct mlx4_func_cap *func_cap); -int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); int mlx4_MAP_FA(struct mlx4_dev *dev, struct mlx4_icm *icm); int mlx4_UNMAP_FA(struct mlx4_dev *dev); int mlx4_RUN_FW(struct mlx4_dev *dev); int mlx4_QUERY_FW(struct mlx4_dev *dev); int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter); int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param); -int mlx4_QUERY_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param); int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic); int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt); int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/icm.c b/trunk/drivers/net/ethernet/mellanox/mlx4/icm.c index a9ade1c3cad5..02393fdf44c1 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/icm.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/icm.c @@ -213,7 +213,7 @@ static int mlx4_MAP_ICM(struct mlx4_dev *dev, struct mlx4_icm *icm, u64 virt) static int mlx4_UNMAP_ICM(struct mlx4_dev *dev, u64 virt, u32 page_count) { return mlx4_cmd(dev, virt, page_count, 0, MLX4_CMD_UNMAP_ICM, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_B); } int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm) @@ -223,8 +223,7 @@ int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm) int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev) { - return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_ICM_AUX, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); + return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_UNMAP_ICM_AUX, MLX4_CMD_TIME_CLASS_B); } int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj) diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/intf.c b/trunk/drivers/net/ethernet/mellanox/mlx4/intf.c index b4e9f6f5cc04..ca6feb55bd94 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/intf.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/intf.c @@ -142,8 +142,7 @@ int mlx4_register_device(struct mlx4_dev *dev) mlx4_add_device(intf, priv); mutex_unlock(&intf_mutex); - if (!mlx4_is_slave(dev)) - mlx4_start_catas_poll(dev); + mlx4_start_catas_poll(dev); return 0; } @@ -153,8 +152,7 @@ void mlx4_unregister_device(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_interface *intf; - if (!mlx4_is_slave(dev)) - mlx4_stop_catas_poll(dev); + mlx4_stop_catas_poll(dev); mutex_lock(&intf_mutex); list_for_each_entry(intf, &intf_list, list) diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/main.c b/trunk/drivers/net/ethernet/mellanox/mlx4/main.c index b969bfb569e3..94bbc85a532d 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/main.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include @@ -76,42 +75,21 @@ MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero"); #endif /* CONFIG_PCI_MSI */ -static int num_vfs; -module_param(num_vfs, int, 0444); -MODULE_PARM_DESC(num_vfs, "enable #num_vfs functions if num_vfs > 0"); - -static int probe_vf; -module_param(probe_vf, int, 0644); -MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)"); - -int mlx4_log_num_mgm_entry_size = 10; -module_param_named(log_num_mgm_entry_size, - mlx4_log_num_mgm_entry_size, int, 0444); -MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num" - " of qp per mcg, for example:" - " 10 gives 248.range: 9<=" - " log_num_mgm_entry_size <= 12"); - -#define MLX4_VF (1 << 0) - -#define HCA_GLOBAL_CAP_MASK 0 -#define PF_CONTEXT_BEHAVIOUR_MASK 0 - static char mlx4_version[] __devinitdata = DRV_NAME ": Mellanox ConnectX core driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; static struct mlx4_profile default_profile = { - .num_qp = 1 << 18, + .num_qp = 1 << 17, .num_srq = 1 << 16, .rdmarc_per_qp = 1 << 4, .num_cq = 1 << 16, .num_mcg = 1 << 13, - .num_mpt = 1 << 19, + .num_mpt = 1 << 17, .num_mtt = 1 << 20, }; -static int log_num_mac = 7; +static int log_num_mac = 2; module_param_named(log_num_mac, log_num_mac, int, 0444); MODULE_PARM_DESC(log_num_mac, "Log2 max number of MACs per ETH port (1-7)"); @@ -126,27 +104,10 @@ module_param_named(use_prio, use_prio, bool, 0444); MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports " "(0/1, default 0)"); -int log_mtts_per_seg = ilog2(MLX4_MTT_ENTRY_PER_SEG); +static int log_mtts_per_seg = ilog2(MLX4_MTT_ENTRY_PER_SEG); module_param_named(log_mtts_per_seg, log_mtts_per_seg, int, 0444); MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment (1-7)"); -static int port_type_array[2] = {1, 1}; -static int arr_argc = 2; -module_param_array(port_type_array, int, &arr_argc, 0444); -MODULE_PARM_DESC(port_type_array, "Array of port types: IB by default"); - -struct mlx4_port_config { - struct list_head list; - enum mlx4_port_type port_type[MLX4_MAX_PORTS + 1]; - struct pci_dev *pdev; -}; - -static inline int mlx4_master_get_num_eqs(struct mlx4_dev *dev) -{ - return dev->caps.reserved_eqs + - MLX4_MFUNC_EQ_NUM * (dev->num_slaves + 1); -} - int mlx4_check_port_params(struct mlx4_dev *dev, enum mlx4_port_type *port_type) { @@ -179,8 +140,10 @@ static void mlx4_set_port_mask(struct mlx4_dev *dev) { int i; + dev->caps.port_mask = 0; for (i = 1; i <= dev->caps.num_ports; ++i) - dev->caps.port_mask[i] = dev->caps.port_type[i]; + if (dev->caps.port_type[i] == MLX4_PORT_TYPE_IB) + dev->caps.port_mask |= 1 << (i - 1); } static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) @@ -231,7 +194,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.trans_code[i] = dev_cap->trans_code[i]; } - dev->caps.uar_page_size = PAGE_SIZE; dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE; dev->caps.local_ca_ack_delay = dev_cap->local_ca_ack_delay; dev->caps.bf_reg_size = dev_cap->bf_reg_size; @@ -245,7 +207,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.reserved_srqs = dev_cap->reserved_srqs; dev->caps.max_sq_desc_sz = dev_cap->max_sq_desc_sz; dev->caps.max_rq_desc_sz = dev_cap->max_rq_desc_sz; - dev->caps.num_qp_per_mgm = mlx4_get_qp_per_mgm(dev); + dev->caps.num_qp_per_mgm = MLX4_QP_PER_MGM; /* * Subtract 1 from the limit because we need to allocate a * spare CQE so the HCA HW can tell the difference between an @@ -254,18 +216,17 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.max_cqes = dev_cap->max_cq_sz - 1; dev->caps.reserved_cqs = dev_cap->reserved_cqs; dev->caps.reserved_eqs = dev_cap->reserved_eqs; - dev->caps.reserved_mtts = dev_cap->reserved_mtts; + dev->caps.mtts_per_seg = 1 << log_mtts_per_seg; + dev->caps.reserved_mtts = DIV_ROUND_UP(dev_cap->reserved_mtts, + dev->caps.mtts_per_seg); dev->caps.reserved_mrws = dev_cap->reserved_mrws; - - /* The first 128 UARs are used for EQ doorbells */ - dev->caps.reserved_uars = max_t(int, 128, dev_cap->reserved_uars); + dev->caps.reserved_uars = dev_cap->reserved_uars; dev->caps.reserved_pds = dev_cap->reserved_pds; dev->caps.reserved_xrcds = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ? dev_cap->reserved_xrcds : 0; dev->caps.max_xrcds = (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) ? dev_cap->max_xrcds : 0; - dev->caps.mtt_entry_sz = dev_cap->mtt_entry_sz; - + dev->caps.mtt_entry_sz = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz; dev->caps.max_msg_sz = dev_cap->max_msg_sz; dev->caps.page_size_cap = ~(u32) (dev_cap->min_page_sz - 1); dev->caps.flags = dev_cap->flags; @@ -279,36 +240,10 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) dev->caps.log_num_prios = use_prio ? 3 : 0; for (i = 1; i <= dev->caps.num_ports; ++i) { - dev->caps.port_type[i] = MLX4_PORT_TYPE_NONE; - if (dev->caps.supported_type[i]) { - /* if only ETH is supported - assign ETH */ - if (dev->caps.supported_type[i] == MLX4_PORT_TYPE_ETH) - dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH; - /* if only IB is supported, - * assign IB only if SRIOV is off*/ - else if (dev->caps.supported_type[i] == - MLX4_PORT_TYPE_IB) { - if (dev->flags & MLX4_FLAG_SRIOV) - dev->caps.port_type[i] = - MLX4_PORT_TYPE_NONE; - else - dev->caps.port_type[i] = - MLX4_PORT_TYPE_IB; - /* if IB and ETH are supported, - * first of all check if SRIOV is on */ - } else if (dev->flags & MLX4_FLAG_SRIOV) - dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH; - /* if IB and ETH are supported and SRIOV is off - * use module parameters */ - else { - if (port_type_array[i-1]) - dev->caps.port_type[i] = - MLX4_PORT_TYPE_IB; - else - dev->caps.port_type[i] = - MLX4_PORT_TYPE_ETH; - } - } + if (dev->caps.supported_type[i] != MLX4_PORT_TYPE_ETH) + dev->caps.port_type[i] = MLX4_PORT_TYPE_IB; + else + dev->caps.port_type[i] = MLX4_PORT_TYPE_ETH; dev->caps.possible_type[i] = dev->caps.port_type[i]; mlx4_priv(dev)->sense.sense_allowed[i] = dev->caps.supported_type[i] == MLX4_PORT_TYPE_AUTO; @@ -327,6 +262,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) } } + mlx4_set_port_mask(dev); + dev->caps.max_counters = 1 << ilog2(dev_cap->max_counters); dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FW] = dev_cap->reserved_qps; @@ -345,149 +282,6 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) return 0; } -/*The function checks if there are live vf, return the num of them*/ -static int mlx4_how_many_lives_vf(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_slave_state *s_state; - int i; - int ret = 0; - - for (i = 1/*the ppf is 0*/; i < dev->num_slaves; ++i) { - s_state = &priv->mfunc.master.slave_state[i]; - if (s_state->active && s_state->last_cmd != - MLX4_COMM_CMD_RESET) { - mlx4_warn(dev, "%s: slave: %d is still active\n", - __func__, i); - ret++; - } - } - return ret; -} - -static int mlx4_is_slave_active(struct mlx4_dev *dev, int slave) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_slave_state *s_slave; - - if (!mlx4_is_master(dev)) - return 0; - - s_slave = &priv->mfunc.master.slave_state[slave]; - return !!s_slave->active; -} -EXPORT_SYMBOL(mlx4_is_slave_active); - -static int mlx4_slave_cap(struct mlx4_dev *dev) -{ - int err; - u32 page_size; - struct mlx4_dev_cap dev_cap; - struct mlx4_func_cap func_cap; - struct mlx4_init_hca_param hca_param; - int i; - - memset(&hca_param, 0, sizeof(hca_param)); - err = mlx4_QUERY_HCA(dev, &hca_param); - if (err) { - mlx4_err(dev, "QUERY_HCA command failed, aborting.\n"); - return err; - } - - /*fail if the hca has an unknown capability */ - if ((hca_param.global_caps | HCA_GLOBAL_CAP_MASK) != - HCA_GLOBAL_CAP_MASK) { - mlx4_err(dev, "Unknown hca global capabilities\n"); - return -ENOSYS; - } - - mlx4_log_num_mgm_entry_size = hca_param.log_mc_entry_sz; - - memset(&dev_cap, 0, sizeof(dev_cap)); - err = mlx4_dev_cap(dev, &dev_cap); - if (err) { - mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n"); - return err; - } - - page_size = ~dev->caps.page_size_cap + 1; - mlx4_warn(dev, "HCA minimum page size:%d\n", page_size); - if (page_size > PAGE_SIZE) { - mlx4_err(dev, "HCA minimum page size of %d bigger than " - "kernel PAGE_SIZE of %ld, aborting.\n", - page_size, PAGE_SIZE); - return -ENODEV; - } - - /* slave gets uar page size from QUERY_HCA fw command */ - dev->caps.uar_page_size = 1 << (hca_param.uar_page_sz + 12); - - /* TODO: relax this assumption */ - if (dev->caps.uar_page_size != PAGE_SIZE) { - mlx4_err(dev, "UAR size:%d != kernel PAGE_SIZE of %ld\n", - dev->caps.uar_page_size, PAGE_SIZE); - return -ENODEV; - } - - memset(&func_cap, 0, sizeof(func_cap)); - err = mlx4_QUERY_FUNC_CAP(dev, &func_cap); - if (err) { - mlx4_err(dev, "QUERY_FUNC_CAP command failed, aborting.\n"); - return err; - } - - if ((func_cap.pf_context_behaviour | PF_CONTEXT_BEHAVIOUR_MASK) != - PF_CONTEXT_BEHAVIOUR_MASK) { - mlx4_err(dev, "Unknown pf context behaviour\n"); - return -ENOSYS; - } - - dev->caps.function = func_cap.function; - dev->caps.num_ports = func_cap.num_ports; - dev->caps.num_qps = func_cap.qp_quota; - dev->caps.num_srqs = func_cap.srq_quota; - dev->caps.num_cqs = func_cap.cq_quota; - dev->caps.num_eqs = func_cap.max_eq; - dev->caps.reserved_eqs = func_cap.reserved_eq; - dev->caps.num_mpts = func_cap.mpt_quota; - dev->caps.num_mtts = func_cap.mtt_quota; - dev->caps.num_pds = MLX4_NUM_PDS; - dev->caps.num_mgms = 0; - dev->caps.num_amgms = 0; - - for (i = 1; i <= dev->caps.num_ports; ++i) - dev->caps.port_mask[i] = dev->caps.port_type[i]; - - if (dev->caps.num_ports > MLX4_MAX_PORTS) { - mlx4_err(dev, "HCA has %d ports, but we only support %d, " - "aborting.\n", dev->caps.num_ports, MLX4_MAX_PORTS); - return -ENODEV; - } - - if (dev->caps.uar_page_size * (dev->caps.num_uars - - dev->caps.reserved_uars) > - pci_resource_len(dev->pdev, 2)) { - mlx4_err(dev, "HCA reported UAR region size of 0x%x bigger than " - "PCI resource 2 size of 0x%llx, aborting.\n", - dev->caps.uar_page_size * dev->caps.num_uars, - (unsigned long long) pci_resource_len(dev->pdev, 2)); - return -ENODEV; - } - -#if 0 - mlx4_warn(dev, "sqp_demux:%d\n", dev->caps.sqp_demux); - mlx4_warn(dev, "num_uars:%d reserved_uars:%d uar region:0x%x bar2:0x%llx\n", - dev->caps.num_uars, dev->caps.reserved_uars, - dev->caps.uar_page_size * dev->caps.num_uars, - pci_resource_len(dev->pdev, 2)); - mlx4_warn(dev, "num_eqs:%d reserved_eqs:%d\n", dev->caps.num_eqs, - dev->caps.reserved_eqs); - mlx4_warn(dev, "num_pds:%d reserved_pds:%d slave_pd_shift:%d pd_base:%d\n", - dev->caps.num_pds, dev->caps.reserved_pds, - dev->caps.slave_pd_shift, dev->caps.pd_base); -#endif - return 0; -} /* * Change the port configuration of the device. @@ -657,7 +451,6 @@ static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base, { struct mlx4_priv *priv = mlx4_priv(dev); int err; - int num_eqs; err = mlx4_init_icm_table(dev, &priv->qp_table.cmpt_table, cmpt_base + @@ -687,14 +480,12 @@ static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base, if (err) goto err_srq; - num_eqs = (mlx4_is_master(dev)) ? - roundup_pow_of_two(mlx4_master_get_num_eqs(dev)) : - dev->caps.num_eqs; err = mlx4_init_icm_table(dev, &priv->eq_table.cmpt_table, cmpt_base + ((u64) (MLX4_CMPT_TYPE_EQ * cmpt_entry_sz) << MLX4_CMPT_SHIFT), - cmpt_entry_sz, num_eqs, num_eqs, 0, 0); + cmpt_entry_sz, + dev->caps.num_eqs, dev->caps.num_eqs, 0, 0); if (err) goto err_cq; @@ -718,7 +509,6 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, { struct mlx4_priv *priv = mlx4_priv(dev); u64 aux_pages; - int num_eqs; int err; err = mlx4_SET_ICM_SIZE(dev, icm_size, &aux_pages); @@ -750,13 +540,10 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, goto err_unmap_aux; } - - num_eqs = (mlx4_is_master(dev)) ? - roundup_pow_of_two(mlx4_master_get_num_eqs(dev)) : - dev->caps.num_eqs; err = mlx4_init_icm_table(dev, &priv->eq_table.table, init_hca->eqc_base, dev_cap->eqc_entry_sz, - num_eqs, num_eqs, 0, 0); + dev->caps.num_eqs, dev->caps.num_eqs, + 0, 0); if (err) { mlx4_err(dev, "Failed to map EQ context memory, aborting.\n"); goto err_unmap_cmpt; @@ -776,7 +563,7 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, err = mlx4_init_icm_table(dev, &priv->mr_table.mtt_table, init_hca->mtt_base, dev->caps.mtt_entry_sz, - dev->caps.num_mtts, + dev->caps.num_mtt_segs, dev->caps.reserved_mtts, 1, 0); if (err) { mlx4_err(dev, "Failed to map MTT context memory, aborting.\n"); @@ -863,8 +650,7 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap, * and it's a lot easier than trying to track ref counts. */ err = mlx4_init_icm_table(dev, &priv->mcg_table.table, - init_hca->mc_base, - mlx4_get_mgm_entry_size(dev), + init_hca->mc_base, MLX4_MGM_ENTRY_SIZE, dev->caps.num_mgms + dev->caps.num_amgms, dev->caps.num_mgms + dev->caps.num_amgms, 0, 0); @@ -940,16 +726,6 @@ static void mlx4_free_icms(struct mlx4_dev *dev) mlx4_free_icm(dev, priv->fw.aux_icm, 0); } -static void mlx4_slave_exit(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - down(&priv->cmd.slave_sem); - if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0, MLX4_COMM_TIME)) - mlx4_warn(dev, "Failed to close slave function.\n"); - up(&priv->cmd.slave_sem); -} - static int map_bf_area(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); @@ -957,10 +733,8 @@ static int map_bf_area(struct mlx4_dev *dev) resource_size_t bf_len; int err = 0; - bf_start = pci_resource_start(dev->pdev, 2) + - (dev->caps.num_uars << PAGE_SHIFT); - bf_len = pci_resource_len(dev->pdev, 2) - - (dev->caps.num_uars << PAGE_SHIFT); + bf_start = pci_resource_start(dev->pdev, 2) + (dev->caps.num_uars << PAGE_SHIFT); + bf_len = pci_resource_len(dev->pdev, 2) - (dev->caps.num_uars << PAGE_SHIFT); priv->bf_mapping = io_mapping_create_wc(bf_start, bf_len); if (!priv->bf_mapping) err = -ENOMEM; @@ -977,81 +751,10 @@ static void unmap_bf_area(struct mlx4_dev *dev) static void mlx4_close_hca(struct mlx4_dev *dev) { unmap_bf_area(dev); - if (mlx4_is_slave(dev)) - mlx4_slave_exit(dev); - else { - mlx4_CLOSE_HCA(dev, 0); - mlx4_free_icms(dev); - mlx4_UNMAP_FA(dev); - mlx4_free_icm(dev, mlx4_priv(dev)->fw.fw_icm, 0); - } -} - -static int mlx4_init_slave(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - u64 dma = (u64) priv->mfunc.vhcr_dma; - int num_of_reset_retries = NUM_OF_RESET_RETRIES; - int ret_from_reset = 0; - u32 slave_read; - u32 cmd_channel_ver; - - down(&priv->cmd.slave_sem); - priv->cmd.max_cmds = 1; - mlx4_warn(dev, "Sending reset\n"); - ret_from_reset = mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0, - MLX4_COMM_TIME); - /* if we are in the middle of flr the slave will try - * NUM_OF_RESET_RETRIES times before leaving.*/ - if (ret_from_reset) { - if (MLX4_DELAY_RESET_SLAVE == ret_from_reset) { - msleep(SLEEP_TIME_IN_RESET); - while (ret_from_reset && num_of_reset_retries) { - mlx4_warn(dev, "slave is currently in the" - "middle of FLR. retrying..." - "(try num:%d)\n", - (NUM_OF_RESET_RETRIES - - num_of_reset_retries + 1)); - ret_from_reset = - mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, - 0, MLX4_COMM_TIME); - num_of_reset_retries = num_of_reset_retries - 1; - } - } else - goto err; - } - - /* check the driver version - the slave I/F revision - * must match the master's */ - slave_read = swab32(readl(&priv->mfunc.comm->slave_read)); - cmd_channel_ver = mlx4_comm_get_version(); - - if (MLX4_COMM_GET_IF_REV(cmd_channel_ver) != - MLX4_COMM_GET_IF_REV(slave_read)) { - mlx4_err(dev, "slave driver version is not supported" - " by the master\n"); - goto err; - } - - mlx4_warn(dev, "Sending vhcr0\n"); - if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR0, dma >> 48, - MLX4_COMM_TIME)) - goto err; - if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR1, dma >> 32, - MLX4_COMM_TIME)) - goto err; - if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR2, dma >> 16, - MLX4_COMM_TIME)) - goto err; - if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR_EN, dma, MLX4_COMM_TIME)) - goto err; - up(&priv->cmd.slave_sem); - return 0; - -err: - mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0, 0); - up(&priv->cmd.slave_sem); - return -EIO; + mlx4_CLOSE_HCA(dev, 0); + mlx4_free_icms(dev); + mlx4_UNMAP_FA(dev); + mlx4_free_icm(dev, mlx4_priv(dev)->fw.fw_icm, 0); } static int mlx4_init_hca(struct mlx4_dev *dev) @@ -1065,75 +768,55 @@ static int mlx4_init_hca(struct mlx4_dev *dev) u64 icm_size; int err; - if (!mlx4_is_slave(dev)) { - err = mlx4_QUERY_FW(dev); - if (err) { - if (err == -EACCES) - mlx4_info(dev, "non-primary physical function, skipping.\n"); - else - mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); - goto unmap_bf; - } - - err = mlx4_load_fw(dev); - if (err) { - mlx4_err(dev, "Failed to start FW, aborting.\n"); - goto unmap_bf; - } - - mlx4_cfg.log_pg_sz_m = 1; - mlx4_cfg.log_pg_sz = 0; - err = mlx4_MOD_STAT_CFG(dev, &mlx4_cfg); - if (err) - mlx4_warn(dev, "Failed to override log_pg_sz parameter\n"); - - err = mlx4_dev_cap(dev, &dev_cap); - if (err) { - mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n"); - goto err_stop_fw; - } - - profile = default_profile; + err = mlx4_QUERY_FW(dev); + if (err) { + if (err == -EACCES) + mlx4_info(dev, "non-primary physical function, skipping.\n"); + else + mlx4_err(dev, "QUERY_FW command failed, aborting.\n"); + return err; + } - icm_size = mlx4_make_profile(dev, &profile, &dev_cap, - &init_hca); - if ((long long) icm_size < 0) { - err = icm_size; - goto err_stop_fw; - } + err = mlx4_load_fw(dev); + if (err) { + mlx4_err(dev, "Failed to start FW, aborting.\n"); + return err; + } - init_hca.log_uar_sz = ilog2(dev->caps.num_uars); - init_hca.uar_page_sz = PAGE_SHIFT - 12; + mlx4_cfg.log_pg_sz_m = 1; + mlx4_cfg.log_pg_sz = 0; + err = mlx4_MOD_STAT_CFG(dev, &mlx4_cfg); + if (err) + mlx4_warn(dev, "Failed to override log_pg_sz parameter\n"); - err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size); - if (err) - goto err_stop_fw; + err = mlx4_dev_cap(dev, &dev_cap); + if (err) { + mlx4_err(dev, "QUERY_DEV_CAP command failed, aborting.\n"); + goto err_stop_fw; + } - err = mlx4_INIT_HCA(dev, &init_hca); - if (err) { - mlx4_err(dev, "INIT_HCA command failed, aborting.\n"); - goto err_free_icm; - } - } else { - err = mlx4_init_slave(dev); - if (err) { - mlx4_err(dev, "Failed to initialize slave\n"); - goto unmap_bf; - } + profile = default_profile; - err = mlx4_slave_cap(dev); - if (err) { - mlx4_err(dev, "Failed to obtain slave caps\n"); - goto err_close; - } + icm_size = mlx4_make_profile(dev, &profile, &dev_cap, &init_hca); + if ((long long) icm_size < 0) { + err = icm_size; + goto err_stop_fw; } if (map_bf_area(dev)) mlx4_dbg(dev, "Failed to map blue flame area\n"); - /*Only the master set the ports, all the rest got it from it.*/ - if (!mlx4_is_slave(dev)) - mlx4_set_port_mask(dev); + init_hca.log_uar_sz = ilog2(dev->caps.num_uars); + + err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size); + if (err) + goto err_stop_fw; + + err = mlx4_INIT_HCA(dev, &init_hca); + if (err) { + mlx4_err(dev, "INIT_HCA command failed, aborting.\n"); + goto err_free_icm; + } err = mlx4_QUERY_ADAPTER(dev, &adapter); if (err) { @@ -1147,19 +830,16 @@ static int mlx4_init_hca(struct mlx4_dev *dev) return 0; err_close: - mlx4_close_hca(dev); + mlx4_CLOSE_HCA(dev, 0); err_free_icm: - if (!mlx4_is_slave(dev)) - mlx4_free_icms(dev); + mlx4_free_icms(dev); err_stop_fw: - if (!mlx4_is_slave(dev)) { - mlx4_UNMAP_FA(dev); - mlx4_free_icm(dev, priv->fw.fw_icm, 0); - } -unmap_bf: unmap_bf_area(dev); + mlx4_UNMAP_FA(dev); + mlx4_free_icm(dev, priv->fw.fw_icm, 0); + return err; } @@ -1306,62 +986,55 @@ static int mlx4_setup_hca(struct mlx4_dev *dev) goto err_srq_table_free; } - if (!mlx4_is_slave(dev)) { - err = mlx4_init_mcg_table(dev); - if (err) { - mlx4_err(dev, "Failed to initialize " - "multicast group table, aborting.\n"); - goto err_qp_table_free; - } + err = mlx4_init_mcg_table(dev); + if (err) { + mlx4_err(dev, "Failed to initialize " + "multicast group table, aborting.\n"); + goto err_qp_table_free; } err = mlx4_init_counters_table(dev); if (err && err != -ENOENT) { mlx4_err(dev, "Failed to initialize counters table, aborting.\n"); - goto err_mcg_table_free; + goto err_counters_table_free; } - if (!mlx4_is_slave(dev)) { - for (port = 1; port <= dev->caps.num_ports; port++) { - if (!mlx4_is_mfunc(dev)) { - enum mlx4_port_type port_type = 0; - mlx4_SENSE_PORT(dev, port, &port_type); - if (port_type) - dev->caps.port_type[port] = port_type; - } - ib_port_default_caps = 0; - err = mlx4_get_port_ib_caps(dev, port, - &ib_port_default_caps); - if (err) - mlx4_warn(dev, "failed to get port %d default " - "ib capabilities (%d). Continuing " - "with caps = 0\n", port, err); - dev->caps.ib_port_def_cap[port] = ib_port_default_caps; - - err = mlx4_check_ext_port_caps(dev, port); - if (err) - mlx4_warn(dev, "failed to get port %d extended " - "port capabilities support info (%d)." - " Assuming not supported\n", - port, err); + for (port = 1; port <= dev->caps.num_ports; port++) { + enum mlx4_port_type port_type = 0; + mlx4_SENSE_PORT(dev, port, &port_type); + if (port_type) + dev->caps.port_type[port] = port_type; + ib_port_default_caps = 0; + err = mlx4_get_port_ib_caps(dev, port, &ib_port_default_caps); + if (err) + mlx4_warn(dev, "failed to get port %d default " + "ib capabilities (%d). Continuing with " + "caps = 0\n", port, err); + dev->caps.ib_port_def_cap[port] = ib_port_default_caps; - err = mlx4_SET_PORT(dev, port); - if (err) { - mlx4_err(dev, "Failed to set port %d, aborting\n", - port); - goto err_counters_table_free; - } + err = mlx4_check_ext_port_caps(dev, port); + if (err) + mlx4_warn(dev, "failed to get port %d extended " + "port capabilities support info (%d)." + " Assuming not supported\n", port, err); + + err = mlx4_SET_PORT(dev, port); + if (err) { + mlx4_err(dev, "Failed to set port %d, aborting\n", + port); + goto err_mcg_table_free; } } + mlx4_set_port_mask(dev); return 0; -err_counters_table_free: - mlx4_cleanup_counters_table(dev); - err_mcg_table_free: mlx4_cleanup_mcg_table(dev); +err_counters_table_free: + mlx4_cleanup_counters_table(dev); + err_qp_table_free: mlx4_cleanup_qp_table(dev); @@ -1408,16 +1081,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) int i; if (msi_x) { - /* In multifunction mode each function gets 2 msi-X vectors - * one for data path completions anf the other for asynch events - * or command completions */ - if (mlx4_is_mfunc(dev)) { - nreq = 2; - } else { - nreq = min_t(int, dev->caps.num_eqs - - dev->caps.reserved_eqs, nreq); - } - + nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, + nreq); entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); if (!entries) goto no_msi; @@ -1473,24 +1138,16 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port) info->dev = dev; info->port = port; - if (!mlx4_is_slave(dev)) { - INIT_RADIX_TREE(&info->mac_tree, GFP_KERNEL); - mlx4_init_mac_table(dev, &info->mac_table); - mlx4_init_vlan_table(dev, &info->vlan_table); - info->base_qpn = - dev->caps.reserved_qps_base[MLX4_QP_REGION_ETH_ADDR] + + mlx4_init_mac_table(dev, &info->mac_table); + mlx4_init_vlan_table(dev, &info->vlan_table); + info->base_qpn = dev->caps.reserved_qps_base[MLX4_QP_REGION_ETH_ADDR] + (port - 1) * (1 << log_num_mac); - } sprintf(info->dev_name, "mlx4_port%d", port); info->port_attr.attr.name = info->dev_name; - if (mlx4_is_mfunc(dev)) - info->port_attr.attr.mode = S_IRUGO; - else { - info->port_attr.attr.mode = S_IRUGO | S_IWUSR; - info->port_attr.store = set_port_type; - } + info->port_attr.attr.mode = S_IRUGO | S_IWUSR; info->port_attr.show = show_port_type; + info->port_attr.store = set_port_type; sysfs_attr_init(&info->port_attr.attr); err = device_create_file(&dev->pdev->dev, &info->port_attr); @@ -1563,46 +1220,6 @@ static void mlx4_clear_steering(struct mlx4_dev *dev) kfree(priv->steer); } -static int extended_func_num(struct pci_dev *pdev) -{ - return PCI_SLOT(pdev->devfn) * 8 + PCI_FUNC(pdev->devfn); -} - -#define MLX4_OWNER_BASE 0x8069c -#define MLX4_OWNER_SIZE 4 - -static int mlx4_get_ownership(struct mlx4_dev *dev) -{ - void __iomem *owner; - u32 ret; - - owner = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_OWNER_BASE, - MLX4_OWNER_SIZE); - if (!owner) { - mlx4_err(dev, "Failed to obtain ownership bit\n"); - return -ENOMEM; - } - - ret = readl(owner); - iounmap(owner); - return (int) !!ret; -} - -static void mlx4_free_ownership(struct mlx4_dev *dev) -{ - void __iomem *owner; - - owner = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_OWNER_BASE, - MLX4_OWNER_SIZE); - if (!owner) { - mlx4_err(dev, "Failed to obtain ownership bit\n"); - return; - } - writel(0, owner); - msleep(1000); - iounmap(owner); -} - static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { struct mlx4_priv *priv; @@ -1618,20 +1235,13 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) "aborting.\n"); return err; } - if (num_vfs > MLX4_MAX_NUM_VF) { - printk(KERN_ERR "There are more VF's (%d) than allowed(%d)\n", - num_vfs, MLX4_MAX_NUM_VF); - return -EINVAL; - } + /* - * Check for BARs. + * Check for BARs. We expect 0: 1MB */ - if (((id == NULL) || !(id->driver_data & MLX4_VF)) && - !(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - dev_err(&pdev->dev, "Missing DCS, aborting." - "(id == 0X%p, id->driver_data: 0x%lx," - " pci_resource_flags(pdev, 0):0x%lx)\n", id, - id ? id->driver_data : 0, pci_resource_flags(pdev, 0)); + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) || + pci_resource_len(pdev, 0) != 1 << 20) { + dev_err(&pdev->dev, "Missing DCS, aborting.\n"); err = -ENODEV; goto err_disable_pdev; } @@ -1695,132 +1305,42 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) mutex_init(&priv->bf_mutex); dev->rev_id = pdev->revision; - /* Detect if this device is a virtual function */ - if (id && id->driver_data & MLX4_VF) { - /* When acting as pf, we normally skip vfs unless explicitly - * requested to probe them. */ - if (num_vfs && extended_func_num(pdev) > probe_vf) { - mlx4_warn(dev, "Skipping virtual function:%d\n", - extended_func_num(pdev)); - err = -ENODEV; - goto err_free_dev; - } - mlx4_warn(dev, "Detected virtual function - running in slave mode\n"); - dev->flags |= MLX4_FLAG_SLAVE; - } else { - /* We reset the device and enable SRIOV only for physical - * devices. Try to claim ownership on the device; - * if already taken, skip -- do not allow multiple PFs */ - err = mlx4_get_ownership(dev); - if (err) { - if (err < 0) - goto err_free_dev; - else { - mlx4_warn(dev, "Multiple PFs not yet supported." - " Skipping PF.\n"); - err = -EINVAL; - goto err_free_dev; - } - } - if (num_vfs) { - mlx4_warn(dev, "Enabling sriov with:%d vfs\n", num_vfs); - err = pci_enable_sriov(pdev, num_vfs); - if (err) { - mlx4_err(dev, "Failed to enable sriov," - "continuing without sriov enabled" - " (err = %d).\n", err); - num_vfs = 0; - err = 0; - } else { - mlx4_warn(dev, "Running in master mode\n"); - dev->flags |= MLX4_FLAG_SRIOV | - MLX4_FLAG_MASTER; - dev->num_vfs = num_vfs; - } - } - - /* - * Now reset the HCA before we touch the PCI capabilities or - * attempt a firmware command, since a boot ROM may have left - * the HCA in an undefined state. - */ - err = mlx4_reset(dev); - if (err) { - mlx4_err(dev, "Failed to reset HCA, aborting.\n"); - goto err_rel_own; - } + /* + * Now reset the HCA before we touch the PCI capabilities or + * attempt a firmware command, since a boot ROM may have left + * the HCA in an undefined state. + */ + err = mlx4_reset(dev); + if (err) { + mlx4_err(dev, "Failed to reset HCA, aborting.\n"); + goto err_free_dev; } -slave_start: if (mlx4_cmd_init(dev)) { mlx4_err(dev, "Failed to init command interface, aborting.\n"); - goto err_sriov; - } - - /* In slave functions, the communication channel must be initialized - * before posting commands. Also, init num_slaves before calling - * mlx4_init_hca */ - if (mlx4_is_mfunc(dev)) { - if (mlx4_is_master(dev)) - dev->num_slaves = MLX4_MAX_NUM_SLAVES; - else { - dev->num_slaves = 0; - if (mlx4_multi_func_init(dev)) { - mlx4_err(dev, "Failed to init slave mfunc" - " interface, aborting.\n"); - goto err_cmd; - } - } + goto err_free_dev; } err = mlx4_init_hca(dev); - if (err) { - if (err == -EACCES) { - /* Not primary Physical function - * Running in slave mode */ - mlx4_cmd_cleanup(dev); - dev->flags |= MLX4_FLAG_SLAVE; - dev->flags &= ~MLX4_FLAG_MASTER; - goto slave_start; - } else - goto err_mfunc; - } - - /* In master functions, the communication channel must be initialized - * after obtaining its address from fw */ - if (mlx4_is_master(dev)) { - if (mlx4_multi_func_init(dev)) { - mlx4_err(dev, "Failed to init master mfunc" - "interface, aborting.\n"); - goto err_close; - } - } + if (err) + goto err_cmd; err = mlx4_alloc_eq_table(dev); if (err) - goto err_master_mfunc; + goto err_close; priv->msix_ctl.pool_bm = 0; spin_lock_init(&priv->msix_ctl.pool_lock); mlx4_enable_msi_x(dev); - if ((mlx4_is_mfunc(dev)) && - !(dev->flags & MLX4_FLAG_MSI_X)) { - mlx4_err(dev, "INTx is not supported in multi-function mode." - " aborting.\n"); - goto err_free_eq; - } - if (!mlx4_is_slave(dev)) { - err = mlx4_init_steering(dev); - if (err) - goto err_free_eq; - } + err = mlx4_init_steering(dev); + if (err) + goto err_free_eq; err = mlx4_setup_hca(dev); - if (err == -EBUSY && (dev->flags & MLX4_FLAG_MSI_X) && - !mlx4_is_mfunc(dev)) { + if (err == -EBUSY && (dev->flags & MLX4_FLAG_MSI_X)) { dev->flags &= ~MLX4_FLAG_MSI_X; pci_disable_msix(pdev); err = mlx4_setup_hca(dev); @@ -1863,37 +1383,20 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) mlx4_cleanup_uar_table(dev); err_steer: - if (!mlx4_is_slave(dev)) - mlx4_clear_steering(dev); + mlx4_clear_steering(dev); err_free_eq: mlx4_free_eq_table(dev); -err_master_mfunc: - if (mlx4_is_master(dev)) - mlx4_multi_func_cleanup(dev); - err_close: if (dev->flags & MLX4_FLAG_MSI_X) pci_disable_msix(pdev); mlx4_close_hca(dev); -err_mfunc: - if (mlx4_is_slave(dev)) - mlx4_multi_func_cleanup(dev); - err_cmd: mlx4_cmd_cleanup(dev); -err_sriov: - if (num_vfs && (dev->flags & MLX4_FLAG_SRIOV)) - pci_disable_sriov(pdev); - -err_rel_own: - if (!mlx4_is_slave(dev)) - mlx4_free_ownership(dev); - err_free_dev: kfree(priv); @@ -1921,12 +1424,6 @@ static void mlx4_remove_one(struct pci_dev *pdev) int p; if (dev) { - /* in SRIOV it is not allowed to unload the pf's - * driver while there are alive vf's */ - if (mlx4_is_master(dev)) { - if (mlx4_how_many_lives_vf(dev)) - printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n"); - } mlx4_stop_sense(dev); mlx4_unregister_device(dev); @@ -1946,31 +1443,17 @@ static void mlx4_remove_one(struct pci_dev *pdev) mlx4_cleanup_xrcd_table(dev); mlx4_cleanup_pd_table(dev); - if (mlx4_is_master(dev)) - mlx4_free_resource_tracker(dev); - iounmap(priv->kar); mlx4_uar_free(dev, &priv->driver_uar); mlx4_cleanup_uar_table(dev); - if (!mlx4_is_slave(dev)) - mlx4_clear_steering(dev); + mlx4_clear_steering(dev); mlx4_free_eq_table(dev); - if (mlx4_is_master(dev)) - mlx4_multi_func_cleanup(dev); mlx4_close_hca(dev); - if (mlx4_is_slave(dev)) - mlx4_multi_func_cleanup(dev); mlx4_cmd_cleanup(dev); if (dev->flags & MLX4_FLAG_MSI_X) pci_disable_msix(pdev); - if (num_vfs && (dev->flags & MLX4_FLAG_SRIOV)) { - mlx4_warn(dev, "Disabling sriov\n"); - pci_disable_sriov(pdev); - } - if (!mlx4_is_slave(dev)) - mlx4_free_ownership(dev); kfree(priv); pci_release_regions(pdev); pci_disable_device(pdev); @@ -1985,48 +1468,33 @@ int mlx4_restart_one(struct pci_dev *pdev) } static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_table) = { - /* MT25408 "Hermon" SDR */ - { PCI_VDEVICE(MELLANOX, 0x6340), 0 }, - /* MT25408 "Hermon" DDR */ - { PCI_VDEVICE(MELLANOX, 0x634a), 0 }, - /* MT25408 "Hermon" QDR */ - { PCI_VDEVICE(MELLANOX, 0x6354), 0 }, - /* MT25408 "Hermon" DDR PCIe gen2 */ - { PCI_VDEVICE(MELLANOX, 0x6732), 0 }, - /* MT25408 "Hermon" QDR PCIe gen2 */ - { PCI_VDEVICE(MELLANOX, 0x673c), 0 }, - /* MT25408 "Hermon" EN 10GigE */ - { PCI_VDEVICE(MELLANOX, 0x6368), 0 }, - /* MT25408 "Hermon" EN 10GigE PCIe gen2 */ - { PCI_VDEVICE(MELLANOX, 0x6750), 0 }, - /* MT25458 ConnectX EN 10GBASE-T 10GigE */ - { PCI_VDEVICE(MELLANOX, 0x6372), 0 }, - /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */ - { PCI_VDEVICE(MELLANOX, 0x675a), 0 }, - /* MT26468 ConnectX EN 10GigE PCIe gen2*/ - { PCI_VDEVICE(MELLANOX, 0x6764), 0 }, - /* MT26438 ConnectX EN 40GigE PCIe gen2 5GT/s */ - { PCI_VDEVICE(MELLANOX, 0x6746), 0 }, - /* MT26478 ConnectX2 40GigE PCIe gen2 */ - { PCI_VDEVICE(MELLANOX, 0x676e), 0 }, - /* MT25400 Family [ConnectX-2 Virtual Function] */ - { PCI_VDEVICE(MELLANOX, 0x1002), MLX4_VF }, - /* MT27500 Family [ConnectX-3] */ - { PCI_VDEVICE(MELLANOX, 0x1003), 0 }, - /* MT27500 Family [ConnectX-3 Virtual Function] */ - { PCI_VDEVICE(MELLANOX, 0x1004), MLX4_VF }, - { PCI_VDEVICE(MELLANOX, 0x1005), 0 }, /* MT27510 Family */ - { PCI_VDEVICE(MELLANOX, 0x1006), 0 }, /* MT27511 Family */ - { PCI_VDEVICE(MELLANOX, 0x1007), 0 }, /* MT27520 Family */ - { PCI_VDEVICE(MELLANOX, 0x1008), 0 }, /* MT27521 Family */ - { PCI_VDEVICE(MELLANOX, 0x1009), 0 }, /* MT27530 Family */ - { PCI_VDEVICE(MELLANOX, 0x100a), 0 }, /* MT27531 Family */ - { PCI_VDEVICE(MELLANOX, 0x100b), 0 }, /* MT27540 Family */ - { PCI_VDEVICE(MELLANOX, 0x100c), 0 }, /* MT27541 Family */ - { PCI_VDEVICE(MELLANOX, 0x100d), 0 }, /* MT27550 Family */ - { PCI_VDEVICE(MELLANOX, 0x100e), 0 }, /* MT27551 Family */ - { PCI_VDEVICE(MELLANOX, 0x100f), 0 }, /* MT27560 Family */ - { PCI_VDEVICE(MELLANOX, 0x1010), 0 }, /* MT27561 Family */ + { PCI_VDEVICE(MELLANOX, 0x6340) }, /* MT25408 "Hermon" SDR */ + { PCI_VDEVICE(MELLANOX, 0x634a) }, /* MT25408 "Hermon" DDR */ + { PCI_VDEVICE(MELLANOX, 0x6354) }, /* MT25408 "Hermon" QDR */ + { PCI_VDEVICE(MELLANOX, 0x6732) }, /* MT25408 "Hermon" DDR PCIe gen2 */ + { PCI_VDEVICE(MELLANOX, 0x673c) }, /* MT25408 "Hermon" QDR PCIe gen2 */ + { PCI_VDEVICE(MELLANOX, 0x6368) }, /* MT25408 "Hermon" EN 10GigE */ + { PCI_VDEVICE(MELLANOX, 0x6750) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */ + { PCI_VDEVICE(MELLANOX, 0x6372) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */ + { PCI_VDEVICE(MELLANOX, 0x675a) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */ + { PCI_VDEVICE(MELLANOX, 0x6764) }, /* MT26468 ConnectX EN 10GigE PCIe gen2*/ + { PCI_VDEVICE(MELLANOX, 0x6746) }, /* MT26438 ConnectX EN 40GigE PCIe gen2 5GT/s */ + { PCI_VDEVICE(MELLANOX, 0x676e) }, /* MT26478 ConnectX2 40GigE PCIe gen2 */ + { PCI_VDEVICE(MELLANOX, 0x1002) }, /* MT25400 Family [ConnectX-2 Virtual Function] */ + { PCI_VDEVICE(MELLANOX, 0x1003) }, /* MT27500 Family [ConnectX-3] */ + { PCI_VDEVICE(MELLANOX, 0x1004) }, /* MT27500 Family [ConnectX-3 Virtual Function] */ + { PCI_VDEVICE(MELLANOX, 0x1005) }, /* MT27510 Family */ + { PCI_VDEVICE(MELLANOX, 0x1006) }, /* MT27511 Family */ + { PCI_VDEVICE(MELLANOX, 0x1007) }, /* MT27520 Family */ + { PCI_VDEVICE(MELLANOX, 0x1008) }, /* MT27521 Family */ + { PCI_VDEVICE(MELLANOX, 0x1009) }, /* MT27530 Family */ + { PCI_VDEVICE(MELLANOX, 0x100a) }, /* MT27531 Family */ + { PCI_VDEVICE(MELLANOX, 0x100b) }, /* MT27540 Family */ + { PCI_VDEVICE(MELLANOX, 0x100c) }, /* MT27541 Family */ + { PCI_VDEVICE(MELLANOX, 0x100d) }, /* MT27550 Family */ + { PCI_VDEVICE(MELLANOX, 0x100e) }, /* MT27551 Family */ + { PCI_VDEVICE(MELLANOX, 0x100f) }, /* MT27560 Family */ + { PCI_VDEVICE(MELLANOX, 0x1010) }, /* MT27561 Family */ { 0, } }; @@ -2055,12 +1523,6 @@ static int __init mlx4_verify_params(void) return -1; } - /* Check if module param for ports type has legal combination */ - if (port_type_array[0] == false && port_type_array[1] == true) { - printk(KERN_WARNING "Module parameter configuration ETH/IB is not supported. Switching to default configuration IB/IB\n"); - port_type_array[0] = true; - } - return 0; } diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/mcg.c b/trunk/drivers/net/ethernet/mellanox/mlx4/mcg.c index 0785d9b2a265..978688c31046 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/mcg.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/mcg.c @@ -44,47 +44,28 @@ static const u8 zero_gid[16]; /* automatically initialized to 0 */ -struct mlx4_mgm { - __be32 next_gid_index; - __be32 members_count; - u32 reserved[2]; - u8 gid[16]; - __be32 qp[MLX4_MAX_QP_PER_MGM]; -}; - -int mlx4_get_mgm_entry_size(struct mlx4_dev *dev) -{ - return min((1 << mlx4_log_num_mgm_entry_size), MLX4_MAX_MGM_ENTRY_SIZE); -} - -int mlx4_get_qp_per_mgm(struct mlx4_dev *dev) -{ - return 4 * (mlx4_get_mgm_entry_size(dev) / 16 - 2); -} - static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index, struct mlx4_cmd_mailbox *mailbox) { return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_A); } static int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index, struct mlx4_cmd_mailbox *mailbox) { return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_A); } -static int mlx4_WRITE_PROMISC(struct mlx4_dev *dev, u8 port, u8 steer, +static int mlx4_WRITE_PROMISC(struct mlx4_dev *dev, u8 vep_num, u8 port, u8 steer, struct mlx4_cmd_mailbox *mailbox) { u32 in_mod; - in_mod = (u32) port << 16 | steer << 1; + in_mod = (u32) vep_num << 24 | (u32) port << 16 | steer << 1; return mlx4_cmd(dev, mailbox->dma, in_mod, 0x1, - MLX4_CMD_WRITE_MCG, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); + MLX4_CMD_WRITE_MCG, MLX4_CMD_TIME_CLASS_A); } static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, @@ -94,8 +75,7 @@ static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int err; err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, op_mod, - MLX4_CMD_MGID_HASH, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); + MLX4_CMD_MGID_HASH, MLX4_CMD_TIME_CLASS_A); if (!err) *hash = imm; @@ -122,7 +102,7 @@ static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num, * Add new entry to steering data structure. * All promisc QPs should be added as well */ -static int new_steering_entry(struct mlx4_dev *dev, u8 port, +static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, enum mlx4_steer_type steer, unsigned int index, u32 qpn) { @@ -135,8 +115,10 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port, struct mlx4_promisc_qp *dqp = NULL; u32 prot; int err; + u8 pf_num; - s_steer = &mlx4_priv(dev)->steer[0]; + pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); + s_steer = &mlx4_priv(dev)->steer[pf_num]; new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL); if (!new_entry) return -ENOMEM; @@ -148,7 +130,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port, /* If the given qpn is also a promisc qp, * it should be inserted to duplicates list */ - pqp = get_promisc_qp(dev, 0, steer, qpn); + pqp = get_promisc_qp(dev, pf_num, steer, qpn); if (pqp) { dqp = kmalloc(sizeof *dqp, GFP_KERNEL); if (!dqp) { @@ -183,7 +165,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port, /* don't add already existing qpn */ if (pqp->qpn == qpn) continue; - if (members_count == dev->caps.num_qp_per_mgm) { + if (members_count == MLX4_QP_PER_MGM) { /* out of space */ err = -ENOMEM; goto out_mailbox; @@ -211,7 +193,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port, } /* update the data structures with existing steering entry */ -static int existing_steering_entry(struct mlx4_dev *dev, u8 port, +static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, enum mlx4_steer_type steer, unsigned int index, u32 qpn) { @@ -219,10 +201,12 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port, struct mlx4_steer_index *tmp_entry, *entry = NULL; struct mlx4_promisc_qp *pqp; struct mlx4_promisc_qp *dqp; + u8 pf_num; - s_steer = &mlx4_priv(dev)->steer[0]; + pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); + s_steer = &mlx4_priv(dev)->steer[pf_num]; - pqp = get_promisc_qp(dev, 0, steer, qpn); + pqp = get_promisc_qp(dev, pf_num, steer, qpn); if (!pqp) return 0; /* nothing to do */ @@ -241,7 +225,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port, * we need to add it as a duplicate to this entry * for future references */ list_for_each_entry(dqp, &entry->duplicates, list) { - if (qpn == pqp->qpn) + if (qpn == dqp->qpn) return 0; /* qp is already duplicated */ } @@ -257,18 +241,20 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port, /* Check whether a qpn is a duplicate on steering entry * If so, it should not be removed from mgm */ -static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port, +static bool check_duplicate_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, enum mlx4_steer_type steer, unsigned int index, u32 qpn) { struct mlx4_steer *s_steer; struct mlx4_steer_index *tmp_entry, *entry = NULL; struct mlx4_promisc_qp *dqp, *tmp_dqp; + u8 pf_num; - s_steer = &mlx4_priv(dev)->steer[0]; + pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); + s_steer = &mlx4_priv(dev)->steer[pf_num]; /* if qp is not promisc, it cannot be duplicated */ - if (!get_promisc_qp(dev, 0, steer, qpn)) + if (!get_promisc_qp(dev, pf_num, steer, qpn)) return false; /* The qp is promisc qp so it is a duplicate on this index @@ -293,7 +279,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port, } /* I a steering entry contains only promisc QPs, it can be removed. */ -static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, +static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, enum mlx4_steer_type steer, unsigned int index, u32 tqpn) { @@ -305,8 +291,10 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, u32 members_count; bool ret = false; int i; + u8 pf_num; - s_steer = &mlx4_priv(dev)->steer[0]; + pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); + s_steer = &mlx4_priv(dev)->steer[pf_num]; mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) @@ -318,7 +306,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, members_count = be32_to_cpu(mgm->members_count) & 0xffffff; for (i = 0; i < members_count; i++) { qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK; - if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) { + if (!get_promisc_qp(dev, pf_num, steer, qpn) && qpn != tqpn) { /* the qp is not promisc, the entry can't be removed */ goto out; } @@ -344,7 +332,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port, return ret; } -static int add_promisc_qp(struct mlx4_dev *dev, u8 port, +static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, enum mlx4_steer_type steer, u32 qpn) { struct mlx4_steer *s_steer; @@ -359,13 +347,14 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port, bool found; int last_index; int err; + u8 pf_num; struct mlx4_priv *priv = mlx4_priv(dev); - - s_steer = &mlx4_priv(dev)->steer[0]; + pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); + s_steer = &mlx4_priv(dev)->steer[pf_num]; mutex_lock(&priv->mcg_table.mutex); - if (get_promisc_qp(dev, 0, steer, qpn)) { + if (get_promisc_qp(dev, pf_num, steer, qpn)) { err = 0; /* Noting to do, already exists */ goto out_mutex; } @@ -408,7 +397,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port, } if (!found) { /* Need to add the qpn to mgm */ - if (members_count == dev->caps.num_qp_per_mgm) { + if (members_count == MLX4_QP_PER_MGM) { /* entry is full */ err = -ENOMEM; goto out_mailbox; @@ -431,7 +420,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port, mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK); mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30); - err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox); + err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox); if (err) goto out_list; @@ -450,7 +439,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port, return err; } -static int remove_promisc_qp(struct mlx4_dev *dev, u8 port, +static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, enum mlx4_steer_type steer, u32 qpn) { struct mlx4_priv *priv = mlx4_priv(dev); @@ -465,11 +454,13 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port, bool back_to_list = false; int loc, i; int err; + u8 pf_num; - s_steer = &mlx4_priv(dev)->steer[0]; + pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1); + s_steer = &mlx4_priv(dev)->steer[pf_num]; mutex_lock(&priv->mcg_table.mutex); - pqp = get_promisc_qp(dev, 0, steer, qpn); + pqp = get_promisc_qp(dev, pf_num, steer, qpn); if (unlikely(!pqp)) { mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn); /* nothing to do */ @@ -488,13 +479,12 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port, goto out_list; } mgm = mailbox->buf; - memset(mgm, 0, sizeof *mgm); members_count = 0; list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list) mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK); mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30); - err = mlx4_WRITE_PROMISC(dev, port, steer, mailbox); + err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox); if (err) goto out_mailbox; @@ -659,13 +649,12 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], } index += dev->caps.num_mgms; - new_entry = 1; memset(mgm, 0, sizeof *mgm); memcpy(mgm->gid, gid, 16); } members_count = be32_to_cpu(mgm->members_count) & 0xffffff; - if (members_count == dev->caps.num_qp_per_mgm) { + if (members_count == MLX4_QP_PER_MGM) { mlx4_err(dev, "MGM at index %x is full.\n", index); err = -ENOMEM; goto out; @@ -707,9 +696,9 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], if (prot == MLX4_PROT_ETH) { /* manage the steering entry for promisc mode */ if (new_entry) - new_steering_entry(dev, port, steer, index, qp->qpn); + new_steering_entry(dev, 0, port, steer, index, qp->qpn); else - existing_steering_entry(dev, port, steer, + existing_steering_entry(dev, 0, port, steer, index, qp->qpn); } if (err && link && index != -1) { @@ -760,7 +749,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], /* if this pq is also a promisc qp, it shouldn't be removed */ if (prot == MLX4_PROT_ETH && - check_duplicate_entry(dev, port, steer, index, qp->qpn)) + check_duplicate_entry(dev, 0, port, steer, index, qp->qpn)) goto out; members_count = be32_to_cpu(mgm->members_count) & 0xffffff; @@ -780,8 +769,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], mgm->qp[i - 1] = 0; if (prot == MLX4_PROT_ETH) - removed_entry = can_remove_steering_entry(dev, port, steer, - index, qp->qpn); + removed_entry = can_remove_steering_entry(dev, 0, port, steer, index, qp->qpn); if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) { err = mlx4_WRITE_ENTRY(dev, index, mailbox); goto out; @@ -840,34 +828,6 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], return err; } -static int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp, - u8 gid[16], u8 attach, u8 block_loopback, - enum mlx4_protocol prot) -{ - struct mlx4_cmd_mailbox *mailbox; - int err = 0; - int qpn; - - if (!mlx4_is_mfunc(dev)) - return -EBADF; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - memcpy(mailbox->buf, gid, 16); - qpn = qp->qpn; - qpn |= (prot << 28); - if (attach && block_loopback) - qpn |= (1 << 31); - - err = mlx4_cmd(dev, mailbox->dma, qpn, attach, - MLX4_CMD_QP_ATTACH, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], int block_mcast_loopback, enum mlx4_protocol prot) @@ -883,12 +843,9 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], if (prot == MLX4_PROT_ETH) gid[7] |= (steer << 1); - if (mlx4_is_mfunc(dev)) - return mlx4_QP_ATTACH(dev, qp, gid, 1, - block_mcast_loopback, prot); - - return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback, - prot, steer); + return mlx4_qp_attach_common(dev, qp, gid, + block_mcast_loopback, prot, + steer); } EXPORT_SYMBOL_GPL(mlx4_multicast_attach); @@ -903,90 +860,22 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) return 0; - if (prot == MLX4_PROT_ETH) + if (prot == MLX4_PROT_ETH) { gid[7] |= (steer << 1); - - if (mlx4_is_mfunc(dev)) - return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot); + } return mlx4_qp_detach_common(dev, qp, gid, prot, steer); } EXPORT_SYMBOL_GPL(mlx4_multicast_detach); -int mlx4_unicast_attach(struct mlx4_dev *dev, - struct mlx4_qp *qp, u8 gid[16], - int block_mcast_loopback, enum mlx4_protocol prot) -{ - if (prot == MLX4_PROT_ETH && - !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) - return 0; - - if (prot == MLX4_PROT_ETH) - gid[7] |= (MLX4_UC_STEER << 1); - - if (mlx4_is_mfunc(dev)) - return mlx4_QP_ATTACH(dev, qp, gid, 1, - block_mcast_loopback, prot); - - return mlx4_qp_attach_common(dev, qp, gid, block_mcast_loopback, - prot, MLX4_UC_STEER); -} -EXPORT_SYMBOL_GPL(mlx4_unicast_attach); - -int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, - u8 gid[16], enum mlx4_protocol prot) -{ - if (prot == MLX4_PROT_ETH && - !(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) - return 0; - - if (prot == MLX4_PROT_ETH) - gid[7] |= (MLX4_UC_STEER << 1); - - if (mlx4_is_mfunc(dev)) - return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot); - - return mlx4_qp_detach_common(dev, qp, gid, prot, MLX4_UC_STEER); -} -EXPORT_SYMBOL_GPL(mlx4_unicast_detach); - -int mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - u32 qpn = (u32) vhcr->in_param & 0xffffffff; - u8 port = vhcr->in_param >> 62; - enum mlx4_steer_type steer = vhcr->in_modifier; - - /* Promiscuous unicast is not allowed in mfunc */ - if (mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER) - return 0; - - if (vhcr->op_modifier) - return add_promisc_qp(dev, port, steer, qpn); - else - return remove_promisc_qp(dev, port, steer, qpn); -} - -static int mlx4_PROMISC(struct mlx4_dev *dev, u32 qpn, - enum mlx4_steer_type steer, u8 add, u8 port) -{ - return mlx4_cmd(dev, (u64) qpn | (u64) port << 62, (u32) steer, add, - MLX4_CMD_PROMISC, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED); -} int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) { if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) return 0; - if (mlx4_is_mfunc(dev)) - return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 1, port); - return add_promisc_qp(dev, port, MLX4_MC_STEER, qpn); + return add_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn); } EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add); @@ -995,10 +884,8 @@ int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) return 0; - if (mlx4_is_mfunc(dev)) - return mlx4_PROMISC(dev, qpn, MLX4_MC_STEER, 0, port); - return remove_promisc_qp(dev, port, MLX4_MC_STEER, qpn); + return remove_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn); } EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove); @@ -1007,10 +894,8 @@ int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port) if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) return 0; - if (mlx4_is_mfunc(dev)) - return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 1, port); - return add_promisc_qp(dev, port, MLX4_UC_STEER, qpn); + return add_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn); } EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add); @@ -1019,10 +904,7 @@ int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port) if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)) return 0; - if (mlx4_is_mfunc(dev)) - return mlx4_PROMISC(dev, qpn, MLX4_UC_STEER, 0, port); - - return remove_promisc_qp(dev, port, MLX4_UC_STEER, qpn); + return remove_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn); } EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h index a80121a2b519..5dfa68ffc11c 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -46,25 +46,21 @@ #include #include #include -#include #define DRV_NAME "mlx4_core" -#define PFX DRV_NAME ": " -#define DRV_VERSION "1.1" -#define DRV_RELDATE "Dec, 2011" +#define DRV_VERSION "1.0" +#define DRV_RELDATE "July 14, 2011" enum { MLX4_HCR_BASE = 0x80680, MLX4_HCR_SIZE = 0x0001c, - MLX4_CLR_INT_SIZE = 0x00008, - MLX4_SLAVE_COMM_BASE = 0x0, - MLX4_COMM_PAGESIZE = 0x1000 + MLX4_CLR_INT_SIZE = 0x00008 }; enum { - MLX4_MAX_MGM_ENTRY_SIZE = 0x1000, - MLX4_MAX_QP_PER_MGM = 4 * (MLX4_MAX_MGM_ENTRY_SIZE / 16 - 2), - MLX4_MTT_ENTRY_PER_SEG = 8, + MLX4_MGM_ENTRY_SIZE = 0x100, + MLX4_QP_PER_MGM = 4 * (MLX4_MGM_ENTRY_SIZE / 16 - 2), + MLX4_MTT_ENTRY_PER_SEG = 8 }; enum { @@ -84,94 +80,6 @@ enum { MLX4_NUM_CMPTS = MLX4_CMPT_NUM_TYPE << MLX4_CMPT_SHIFT }; -enum mlx4_mr_state { - MLX4_MR_DISABLED = 0, - MLX4_MR_EN_HW, - MLX4_MR_EN_SW -}; - -#define MLX4_COMM_TIME 10000 -enum { - MLX4_COMM_CMD_RESET, - MLX4_COMM_CMD_VHCR0, - MLX4_COMM_CMD_VHCR1, - MLX4_COMM_CMD_VHCR2, - MLX4_COMM_CMD_VHCR_EN, - MLX4_COMM_CMD_VHCR_POST, - MLX4_COMM_CMD_FLR = 254 -}; - -/*The flag indicates that the slave should delay the RESET cmd*/ -#define MLX4_DELAY_RESET_SLAVE 0xbbbbbbb -/*indicates how many retries will be done if we are in the middle of FLR*/ -#define NUM_OF_RESET_RETRIES 10 -#define SLEEP_TIME_IN_RESET (2 * 1000) -enum mlx4_resource { - RES_QP, - RES_CQ, - RES_SRQ, - RES_XRCD, - RES_MPT, - RES_MTT, - RES_MAC, - RES_VLAN, - RES_EQ, - RES_COUNTER, - MLX4_NUM_OF_RESOURCE_TYPE -}; - -enum mlx4_alloc_mode { - RES_OP_RESERVE, - RES_OP_RESERVE_AND_MAP, - RES_OP_MAP_ICM, -}; - - -/* - *Virtual HCR structures. - * mlx4_vhcr is the sw representation, in machine endianess - * - * mlx4_vhcr_cmd is the formalized structure, the one that is passed - * to FW to go through communication channel. - * It is big endian, and has the same structure as the physical HCR - * used by command interface - */ -struct mlx4_vhcr { - u64 in_param; - u64 out_param; - u32 in_modifier; - u32 errno; - u16 op; - u16 token; - u8 op_modifier; - u8 e_bit; -}; - -struct mlx4_vhcr_cmd { - __be64 in_param; - __be32 in_modifier; - __be64 out_param; - __be16 token; - u16 reserved; - u8 status; - u8 flags; - __be16 opcode; -}; - -struct mlx4_cmd_info { - u16 opcode; - bool has_inbox; - bool has_outbox; - bool out_is_imm; - bool encode_slave_id; - int (*verify)(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox); - int (*wrapper)(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -}; - #ifdef CONFIG_MLX4_DEBUG extern int mlx4_debug_level; #else /* CONFIG_MLX4_DEBUG */ @@ -191,12 +99,6 @@ do { \ #define mlx4_warn(mdev, format, arg...) \ dev_warn(&mdev->pdev->dev, format, ##arg) -extern int mlx4_log_num_mgm_entry_size; -extern int log_mtts_per_seg; - -#define MLX4_MAX_NUM_SLAVES (MLX4_MAX_NUM_PF + MLX4_MAX_NUM_VF) -#define ALL_SLAVES 0xff - struct mlx4_bitmap { u32 last; u32 top; @@ -228,147 +130,6 @@ struct mlx4_icm_table { struct mlx4_icm **icm; }; -/* - * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits. - */ -struct mlx4_mpt_entry { - __be32 flags; - __be32 qpn; - __be32 key; - __be32 pd_flags; - __be64 start; - __be64 length; - __be32 lkey; - __be32 win_cnt; - u8 reserved1[3]; - u8 mtt_rep; - __be64 mtt_addr; - __be32 mtt_sz; - __be32 entity_size; - __be32 first_byte_offset; -} __packed; - -/* - * Must be packed because start is 64 bits but only aligned to 32 bits. - */ -struct mlx4_eq_context { - __be32 flags; - u16 reserved1[3]; - __be16 page_offset; - u8 log_eq_size; - u8 reserved2[4]; - u8 eq_period; - u8 reserved3; - u8 eq_max_count; - u8 reserved4[3]; - u8 intr; - u8 log_page_size; - u8 reserved5[2]; - u8 mtt_base_addr_h; - __be32 mtt_base_addr_l; - u32 reserved6[2]; - __be32 consumer_index; - __be32 producer_index; - u32 reserved7[4]; -}; - -struct mlx4_cq_context { - __be32 flags; - u16 reserved1[3]; - __be16 page_offset; - __be32 logsize_usrpage; - __be16 cq_period; - __be16 cq_max_count; - u8 reserved2[3]; - u8 comp_eqn; - u8 log_page_size; - u8 reserved3[2]; - u8 mtt_base_addr_h; - __be32 mtt_base_addr_l; - __be32 last_notified_index; - __be32 solicit_producer_index; - __be32 consumer_index; - __be32 producer_index; - u32 reserved4[2]; - __be64 db_rec_addr; -}; - -struct mlx4_srq_context { - __be32 state_logsize_srqn; - u8 logstride; - u8 reserved1; - __be16 xrcd; - __be32 pg_offset_cqn; - u32 reserved2; - u8 log_page_size; - u8 reserved3[2]; - u8 mtt_base_addr_h; - __be32 mtt_base_addr_l; - __be32 pd; - __be16 limit_watermark; - __be16 wqe_cnt; - u16 reserved4; - __be16 wqe_counter; - u32 reserved5; - __be64 db_rec_addr; -}; - -struct mlx4_eqe { - u8 reserved1; - u8 type; - u8 reserved2; - u8 subtype; - union { - u32 raw[6]; - struct { - __be32 cqn; - } __packed comp; - struct { - u16 reserved1; - __be16 token; - u32 reserved2; - u8 reserved3[3]; - u8 status; - __be64 out_param; - } __packed cmd; - struct { - __be32 qpn; - } __packed qp; - struct { - __be32 srqn; - } __packed srq; - struct { - __be32 cqn; - u32 reserved1; - u8 reserved2[3]; - u8 syndrome; - } __packed cq_err; - struct { - u32 reserved1[2]; - __be32 port; - } __packed port_change; - struct { - #define COMM_CHANNEL_BIT_ARRAY_SIZE 4 - u32 reserved; - u32 bit_vec[COMM_CHANNEL_BIT_ARRAY_SIZE]; - } __packed comm_channel_arm; - struct { - u8 port; - u8 reserved[3]; - __be64 mac; - } __packed mac_update; - struct { - u8 port; - } __packed sw_event; - struct { - __be32 slave_id; - } __packed flr_event; - } event; - u8 slave_id; - u8 reserved3[2]; - u8 owner; -} __packed; - struct mlx4_eq { struct mlx4_dev *dev; void __iomem *doorbell; @@ -381,18 +142,6 @@ struct mlx4_eq { struct mlx4_mtt mtt; }; -struct mlx4_slave_eqe { - u8 type; - u8 port; - u32 param; -}; - -struct mlx4_slave_event_eq_info { - u32 eqn; - u16 token; - u64 event_type; -}; - struct mlx4_profile { int num_qp; int rdmarc_per_qp; @@ -406,37 +155,16 @@ struct mlx4_profile { struct mlx4_fw { u64 clr_int_base; u64 catas_offset; - u64 comm_base; struct mlx4_icm *fw_icm; struct mlx4_icm *aux_icm; u32 catas_size; u16 fw_pages; u8 clr_int_bar; u8 catas_bar; - u8 comm_bar; }; -struct mlx4_comm { - u32 slave_write; - u32 slave_read; -}; - -enum { - MLX4_MCAST_CONFIG = 0, - MLX4_MCAST_DISABLE = 1, - MLX4_MCAST_ENABLE = 2, -}; - -#define VLAN_FLTR_SIZE 128 - -struct mlx4_vlan_fltr { - __be32 entry[VLAN_FLTR_SIZE]; -}; - -struct mlx4_mcast_entry { - struct list_head list; - u64 addr; -}; +#define MGM_QPN_MASK 0x00FFFFFF +#define MGM_BLCK_LB_BIT 30 struct mlx4_promisc_qp { struct list_head list; @@ -449,87 +177,19 @@ struct mlx4_steer_index { struct list_head duplicates; }; -struct mlx4_slave_state { - u8 comm_toggle; - u8 last_cmd; - u8 init_port_mask; - bool active; - u8 function; - dma_addr_t vhcr_dma; - u16 mtu[MLX4_MAX_PORTS + 1]; - __be32 ib_cap_mask[MLX4_MAX_PORTS + 1]; - struct mlx4_slave_eqe eq[MLX4_MFUNC_MAX_EQES]; - struct list_head mcast_filters[MLX4_MAX_PORTS + 1]; - struct mlx4_vlan_fltr *vlan_filter[MLX4_MAX_PORTS + 1]; - struct mlx4_slave_event_eq_info event_eq; - u16 eq_pi; - u16 eq_ci; - spinlock_t lock; - /*initialized via the kzalloc*/ - u8 is_slave_going_down; - u32 cookie; -}; - -struct slave_list { - struct mutex mutex; - struct list_head res_list[MLX4_NUM_OF_RESOURCE_TYPE]; -}; - -struct mlx4_resource_tracker { - spinlock_t lock; - /* tree for each resources */ - struct radix_tree_root res_tree[MLX4_NUM_OF_RESOURCE_TYPE]; - /* num_of_slave's lists, one per slave */ - struct slave_list *slave_list; -}; - -#define SLAVE_EVENT_EQ_SIZE 128 -struct mlx4_slave_event_eq { - u32 eqn; - u32 cons; - u32 prod; - struct mlx4_eqe event_eqe[SLAVE_EVENT_EQ_SIZE]; -}; - -struct mlx4_master_qp0_state { - int proxy_qp0_active; - int qp0_active; - int port_active; -}; - -struct mlx4_mfunc_master_ctx { - struct mlx4_slave_state *slave_state; - struct mlx4_master_qp0_state qp0_state[MLX4_MAX_PORTS + 1]; - int init_port_ref[MLX4_MAX_PORTS + 1]; - u16 max_mtu[MLX4_MAX_PORTS + 1]; - int disable_mcast_ref[MLX4_MAX_PORTS + 1]; - struct mlx4_resource_tracker res_tracker; - struct workqueue_struct *comm_wq; - struct work_struct comm_work; - struct work_struct slave_event_work; - struct work_struct slave_flr_event_work; - spinlock_t slave_state_lock; - __be32 comm_arm_bit_vector[4]; - struct mlx4_eqe cmd_eqe; - struct mlx4_slave_event_eq slave_eq; - struct mutex gen_eqe_mutex[MLX4_MFUNC_MAX]; -}; - -struct mlx4_mfunc { - struct mlx4_comm __iomem *comm; - struct mlx4_vhcr_cmd *vhcr; - dma_addr_t vhcr_dma; - - struct mlx4_mfunc_master_ctx master; +struct mlx4_mgm { + __be32 next_gid_index; + __be32 members_count; + u32 reserved[2]; + u8 gid[16]; + __be32 qp[MLX4_QP_PER_MGM]; }; - struct mlx4_cmd { struct pci_pool *pool; void __iomem *hcr; struct mutex hcr_mutex; struct semaphore poll_sem; struct semaphore event_sem; - struct semaphore slave_sem; int max_cmds; spinlock_t context_lock; int free_head; @@ -537,7 +197,6 @@ struct mlx4_cmd { u16 token_mask; u8 use_events; u8 toggle; - u8 comm_toggle; }; struct mlx4_uar_table { @@ -628,48 +287,6 @@ struct mlx4_vlan_table { int max; }; -#define SET_PORT_GEN_ALL_VALID 0x7 -#define SET_PORT_PROMISC_SHIFT 31 -#define SET_PORT_MC_PROMISC_SHIFT 30 - -enum { - MCAST_DIRECT_ONLY = 0, - MCAST_DIRECT = 1, - MCAST_DEFAULT = 2 -}; - - -struct mlx4_set_port_general_context { - u8 reserved[3]; - u8 flags; - u16 reserved2; - __be16 mtu; - u8 pptx; - u8 pfctx; - u16 reserved3; - u8 pprx; - u8 pfcrx; - u16 reserved4; -}; - -struct mlx4_set_port_rqp_calc_context { - __be32 base_qpn; - u8 rererved; - u8 n_mac; - u8 n_vlan; - u8 n_prio; - u8 reserved2[3]; - u8 mac_miss; - u8 intra_no_vlan; - u8 no_vlan; - u8 intra_vlan_miss; - u8 vlan_miss; - u8 reserved3[3]; - u8 no_vlan_prio; - __be32 promisc; - __be32 mcast; -}; - struct mlx4_mac_entry { u64 mac; }; @@ -716,7 +333,6 @@ struct mlx4_priv { struct mlx4_fw fw; struct mlx4_cmd cmd; - struct mlx4_mfunc mfunc; struct mlx4_bitmap pd_bitmap; struct mlx4_bitmap xrcd_bitmap; @@ -743,7 +359,6 @@ struct mlx4_priv { struct list_head bf_list; struct mutex bf_mutex; struct io_mapping *bf_mapping; - int reserved_mtts; }; static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev) @@ -788,62 +403,6 @@ void mlx4_cleanup_cq_table(struct mlx4_dev *dev); void mlx4_cleanup_qp_table(struct mlx4_dev *dev); void mlx4_cleanup_srq_table(struct mlx4_dev *dev); void mlx4_cleanup_mcg_table(struct mlx4_dev *dev); -int __mlx4_qp_alloc_icm(struct mlx4_dev *dev, int qpn); -void __mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn); -int __mlx4_cq_alloc_icm(struct mlx4_dev *dev, int *cqn); -void __mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn); -int __mlx4_srq_alloc_icm(struct mlx4_dev *dev, int *srqn); -void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn); -int __mlx4_mr_reserve(struct mlx4_dev *dev); -void __mlx4_mr_release(struct mlx4_dev *dev, u32 index); -int __mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index); -void __mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index); -u32 __mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order); -void __mlx4_free_mtt_range(struct mlx4_dev *dev, u32 first_seg, int order); - -int mlx4_WRITE_MTT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_SYNC_TPT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_HW2SW_MPT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_QUERY_MPT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_SW2HW_EQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, - int *base); -void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt); -int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac); -void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac); -int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac); -int __mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, - int start_index, int npages, u64 *page_list); void mlx4_start_catas_poll(struct mlx4_dev *dev); void mlx4_stop_catas_poll(struct mlx4_dev *dev); @@ -860,113 +419,13 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, struct mlx4_profile *request, struct mlx4_dev_cap *dev_cap, struct mlx4_init_hca_param *init_hca); -void mlx4_master_comm_channel(struct work_struct *work); -void mlx4_gen_slave_eqe(struct work_struct *work); -void mlx4_master_handle_slave_flr(struct work_struct *work); - -int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_MAP_EQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_COMM_INT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_HW2SW_EQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_QUERY_EQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_SW2HW_CQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_HW2SW_CQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_QUERY_CQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_MODIFY_CQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_SW2HW_SRQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_HW2SW_SRQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_QUERY_SRQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_ARM_SRQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_GEN_QP_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_2RST_QP_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); - -int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe); int mlx4_cmd_init(struct mlx4_dev *dev); void mlx4_cmd_cleanup(struct mlx4_dev *dev); -int mlx4_multi_func_init(struct mlx4_dev *dev); -void mlx4_multi_func_cleanup(struct mlx4_dev *dev); void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param); int mlx4_cmd_use_events(struct mlx4_dev *dev); void mlx4_cmd_use_polling(struct mlx4_dev *dev); -int mlx4_comm_cmd(struct mlx4_dev *dev, u8 cmd, u16 param, - unsigned long timeout); - void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn); void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type); @@ -993,113 +452,12 @@ void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table); void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table); int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port); -/* resource tracker functions*/ -int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev, - enum mlx4_resource resource_type, - int resource_id, int *slave); -void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave_id); -int mlx4_init_resource_tracker(struct mlx4_dev *dev); - -void mlx4_free_resource_tracker(struct mlx4_dev *dev); - -int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_INIT_PORT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_CLOSE_PORT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps); int mlx4_check_ext_port_caps(struct mlx4_dev *dev, u8 port); - -int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); - -int mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], enum mlx4_protocol prot, enum mlx4_steer_type steer); int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], int block_mcast_loopback, enum mlx4_protocol prot, enum mlx4_steer_type steer); -int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_common_set_vlan_fltr(struct mlx4_dev *dev, int function, - int port, void *buf); -int mlx4_common_dump_eth_stats(struct mlx4_dev *dev, int slave, u32 in_mod, - struct mlx4_cmd_mailbox *outbox); -int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_PKEY_TABLE_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); -int mlx4_QUERY_IF_STAT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd); - -int mlx4_get_mgm_entry_size(struct mlx4_dev *dev); -int mlx4_get_qp_per_mgm(struct mlx4_dev *dev); - -static inline void set_param_l(u64 *arg, u32 val) -{ - *((u32 *)arg) = val; -} - -static inline void set_param_h(u64 *arg, u32 val) -{ - *arg = (*arg & 0xffffffff) | ((u64) val << 32); -} - -static inline u32 get_param_l(u64 *arg) -{ - return (u32) (*arg & 0xffffffff); -} - -static inline u32 get_param_h(u64 *arg) -{ - return (u32)(*arg >> 32); -} - -static inline spinlock_t *mlx4_tlock(struct mlx4_dev *dev) -{ - return &mlx4_priv(dev)->mfunc.master.res_tracker.lock; -} - -#define NOT_MASKED_PD_BITS 17 - #endif /* MLX4_H */ diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index f2a8e65f5f88..ea2ba6899e9a 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -51,8 +51,8 @@ #include "en_port.h" #define DRV_NAME "mlx4_en" -#define DRV_VERSION "2.0" -#define DRV_RELDATE "Dec 2011" +#define DRV_VERSION "1.5.4.2" +#define DRV_RELDATE "October 2011" #define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN) diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/mr.c b/trunk/drivers/net/ethernet/mellanox/mlx4/mr.c index f7243b26bdf5..efa3e77355e4 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -32,17 +32,35 @@ * SOFTWARE. */ -#include #include #include #include -#include #include #include "mlx4.h" #include "icm.h" +/* + * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits. + */ +struct mlx4_mpt_entry { + __be32 flags; + __be32 qpn; + __be32 key; + __be32 pd_flags; + __be64 start; + __be64 length; + __be32 lkey; + __be32 win_cnt; + u8 reserved1[3]; + u8 mtt_rep; + __be64 mtt_seg; + __be32 mtt_sz; + __be32 entity_size; + __be32 first_byte_offset; +} __packed; + #define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28) #define MLX4_MPT_FLAG_FREE (0x3UL << 28) #define MLX4_MPT_FLAG_MIO (1 << 17) @@ -162,48 +180,22 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy) kfree(buddy->num_free); } -u32 __mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order) +static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order) { struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; u32 seg; - int seg_order; - u32 offset; - seg_order = max_t(int, order - log_mtts_per_seg, 0); - - seg = mlx4_buddy_alloc(&mr_table->mtt_buddy, seg_order); + seg = mlx4_buddy_alloc(&mr_table->mtt_buddy, order); if (seg == -1) return -1; - offset = seg * (1 << log_mtts_per_seg); - - if (mlx4_table_get_range(dev, &mr_table->mtt_table, offset, - offset + (1 << order) - 1)) { - mlx4_buddy_free(&mr_table->mtt_buddy, seg, seg_order); + if (mlx4_table_get_range(dev, &mr_table->mtt_table, seg, + seg + (1 << order) - 1)) { + mlx4_buddy_free(&mr_table->mtt_buddy, seg, order); return -1; } - return offset; -} - -static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order) -{ - u64 in_param; - u64 out_param; - int err; - - if (mlx4_is_mfunc(dev)) { - set_param_l(&in_param, order); - err = mlx4_cmd_imm(dev, in_param, &out_param, RES_MTT, - RES_OP_RESERVE_AND_MAP, - MLX4_CMD_ALLOC_RES, - MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED); - if (err) - return -1; - return get_param_l(&out_param); - } - return __mlx4_alloc_mtt_range(dev, order); + return seg; } int mlx4_mtt_init(struct mlx4_dev *dev, int npages, int page_shift, @@ -218,63 +210,33 @@ int mlx4_mtt_init(struct mlx4_dev *dev, int npages, int page_shift, } else mtt->page_shift = page_shift; - for (mtt->order = 0, i = 1; i < npages; i <<= 1) + for (mtt->order = 0, i = dev->caps.mtts_per_seg; i < npages; i <<= 1) ++mtt->order; - mtt->offset = mlx4_alloc_mtt_range(dev, mtt->order); - if (mtt->offset == -1) + mtt->first_seg = mlx4_alloc_mtt_range(dev, mtt->order); + if (mtt->first_seg == -1) return -ENOMEM; return 0; } EXPORT_SYMBOL_GPL(mlx4_mtt_init); -void __mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order) +void mlx4_mtt_cleanup(struct mlx4_dev *dev, struct mlx4_mtt *mtt) { - u32 first_seg; - int seg_order; struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - seg_order = max_t(int, order - log_mtts_per_seg, 0); - first_seg = offset / (1 << log_mtts_per_seg); - - mlx4_buddy_free(&mr_table->mtt_buddy, first_seg, seg_order); - mlx4_table_put_range(dev, &mr_table->mtt_table, first_seg, - first_seg + (1 << seg_order) - 1); -} - -static void mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order) -{ - u64 in_param; - int err; - - if (mlx4_is_mfunc(dev)) { - set_param_l(&in_param, offset); - set_param_h(&in_param, order); - err = mlx4_cmd(dev, in_param, RES_MTT, RES_OP_RESERVE_AND_MAP, - MLX4_CMD_FREE_RES, - MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED); - if (err) - mlx4_warn(dev, "Failed to free mtt range at:" - "%d order:%d\n", offset, order); - return; - } - __mlx4_free_mtt_range(dev, offset, order); -} - -void mlx4_mtt_cleanup(struct mlx4_dev *dev, struct mlx4_mtt *mtt) -{ if (mtt->order < 0) return; - mlx4_free_mtt_range(dev, mtt->offset, mtt->order); + mlx4_buddy_free(&mr_table->mtt_buddy, mtt->first_seg, mtt->order); + mlx4_table_put_range(dev, &mr_table->mtt_table, mtt->first_seg, + mtt->first_seg + (1 << mtt->order) - 1); } EXPORT_SYMBOL_GPL(mlx4_mtt_cleanup); u64 mlx4_mtt_addr(struct mlx4_dev *dev, struct mlx4_mtt *mtt) { - return (u64) mtt->offset * dev->caps.mtt_entry_sz; + return (u64) mtt->first_seg * dev->caps.mtt_entry_sz; } EXPORT_SYMBOL_GPL(mlx4_mtt_addr); @@ -291,205 +253,69 @@ static u32 key_to_hw_index(u32 key) static int mlx4_SW2HW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int mpt_index) { - return mlx4_cmd(dev, mailbox->dma | dev->caps.function , mpt_index, - 0, MLX4_CMD_SW2HW_MPT, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_WRAPPED); + return mlx4_cmd(dev, mailbox->dma, mpt_index, 0, MLX4_CMD_SW2HW_MPT, + MLX4_CMD_TIME_CLASS_B); } static int mlx4_HW2SW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int mpt_index) { return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, mpt_index, - !mailbox, MLX4_CMD_HW2SW_MPT, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); + !mailbox, MLX4_CMD_HW2SW_MPT, MLX4_CMD_TIME_CLASS_B); } -static int mlx4_mr_reserve_range(struct mlx4_dev *dev, int cnt, int align, - u32 *base_mridx) +int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access, + int npages, int page_shift, struct mlx4_mr *mr) { struct mlx4_priv *priv = mlx4_priv(dev); - u32 mridx; + u32 index; + int err; - mridx = mlx4_bitmap_alloc_range(&priv->mr_table.mpt_bitmap, cnt, align); - if (mridx == -1) + index = mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap); + if (index == -1) return -ENOMEM; - *base_mridx = mridx; - return 0; - -} -EXPORT_SYMBOL_GPL(mlx4_mr_reserve_range); - -static void mlx4_mr_release_range(struct mlx4_dev *dev, u32 base_mridx, int cnt) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - mlx4_bitmap_free_range(&priv->mr_table.mpt_bitmap, base_mridx, cnt); -} -EXPORT_SYMBOL_GPL(mlx4_mr_release_range); - -static int mlx4_mr_alloc_reserved(struct mlx4_dev *dev, u32 mridx, u32 pd, - u64 iova, u64 size, u32 access, int npages, - int page_shift, struct mlx4_mr *mr) -{ mr->iova = iova; mr->size = size; mr->pd = pd; mr->access = access; - mr->enabled = MLX4_MR_DISABLED; - mr->key = hw_index_to_key(mridx); - - return mlx4_mtt_init(dev, npages, page_shift, &mr->mtt); -} -EXPORT_SYMBOL_GPL(mlx4_mr_alloc_reserved); - -static int mlx4_WRITE_MTT(struct mlx4_dev *dev, - struct mlx4_cmd_mailbox *mailbox, - int num_entries) -{ - return mlx4_cmd(dev, mailbox->dma, num_entries, 0, MLX4_CMD_WRITE_MTT, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); -} + mr->enabled = 0; + mr->key = hw_index_to_key(index); -int __mlx4_mr_reserve(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - return mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap); -} - -static int mlx4_mr_reserve(struct mlx4_dev *dev) -{ - u64 out_param; - - if (mlx4_is_mfunc(dev)) { - if (mlx4_cmd_imm(dev, 0, &out_param, RES_MPT, RES_OP_RESERVE, - MLX4_CMD_ALLOC_RES, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED)) - return -1; - return get_param_l(&out_param); - } - return __mlx4_mr_reserve(dev); -} - -void __mlx4_mr_release(struct mlx4_dev *dev, u32 index) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index); -} - -static void mlx4_mr_release(struct mlx4_dev *dev, u32 index) -{ - u64 in_param; - - if (mlx4_is_mfunc(dev)) { - set_param_l(&in_param, index); - if (mlx4_cmd(dev, in_param, RES_MPT, RES_OP_RESERVE, - MLX4_CMD_FREE_RES, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED)) - mlx4_warn(dev, "Failed to release mr index:%d\n", - index); - return; - } - __mlx4_mr_release(dev, index); -} - -int __mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index) -{ - struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - - return mlx4_table_get(dev, &mr_table->dmpt_table, index); -} - -static int mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index) -{ - u64 param; - - if (mlx4_is_mfunc(dev)) { - set_param_l(¶m, index); - return mlx4_cmd_imm(dev, param, ¶m, RES_MPT, RES_OP_MAP_ICM, - MLX4_CMD_ALLOC_RES, - MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED); - } - return __mlx4_mr_alloc_icm(dev, index); -} - -void __mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index) -{ - struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - - mlx4_table_put(dev, &mr_table->dmpt_table, index); -} - -static void mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index) -{ - u64 in_param; - - if (mlx4_is_mfunc(dev)) { - set_param_l(&in_param, index); - if (mlx4_cmd(dev, in_param, RES_MPT, RES_OP_MAP_ICM, - MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED)) - mlx4_warn(dev, "Failed to free icm of mr index:%d\n", - index); - return; - } - return __mlx4_mr_free_icm(dev, index); -} - -int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access, - int npages, int page_shift, struct mlx4_mr *mr) -{ - u32 index; - int err; - - index = mlx4_mr_reserve(dev); - if (index == -1) - return -ENOMEM; - - err = mlx4_mr_alloc_reserved(dev, index, pd, iova, size, - access, npages, page_shift, mr); + err = mlx4_mtt_init(dev, npages, page_shift, &mr->mtt); if (err) - mlx4_mr_release(dev, index); + mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index); return err; } EXPORT_SYMBOL_GPL(mlx4_mr_alloc); -static void mlx4_mr_free_reserved(struct mlx4_dev *dev, struct mlx4_mr *mr) +void mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr) { + struct mlx4_priv *priv = mlx4_priv(dev); int err; - if (mr->enabled == MLX4_MR_EN_HW) { + if (mr->enabled) { err = mlx4_HW2SW_MPT(dev, NULL, key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1)); if (err) - mlx4_warn(dev, "xxx HW2SW_MPT failed (%d)\n", err); - - mr->enabled = MLX4_MR_EN_SW; + mlx4_warn(dev, "HW2SW_MPT failed (%d)\n", err); } - mlx4_mtt_cleanup(dev, &mr->mtt); -} -EXPORT_SYMBOL_GPL(mlx4_mr_free_reserved); -void mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr) -{ - mlx4_mr_free_reserved(dev, mr); - if (mr->enabled) - mlx4_mr_free_icm(dev, key_to_hw_index(mr->key)); - mlx4_mr_release(dev, key_to_hw_index(mr->key)); + mlx4_mtt_cleanup(dev, &mr->mtt); + mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, key_to_hw_index(mr->key)); } EXPORT_SYMBOL_GPL(mlx4_mr_free); int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) { + struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; struct mlx4_cmd_mailbox *mailbox; struct mlx4_mpt_entry *mpt_entry; int err; - err = mlx4_mr_alloc_icm(dev, key_to_hw_index(mr->key)); + err = mlx4_table_get(dev, &mr_table->dmpt_table, key_to_hw_index(mr->key)); if (err) return err; @@ -514,10 +340,9 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) if (mr->mtt.order < 0) { mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL); - mpt_entry->mtt_addr = 0; + mpt_entry->mtt_seg = 0; } else { - mpt_entry->mtt_addr = cpu_to_be64(mlx4_mtt_addr(dev, - &mr->mtt)); + mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt)); } if (mr->mtt.order >= 0 && mr->mtt.page_shift == 0) { @@ -525,7 +350,8 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_FREE); mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG | MLX4_MPT_PD_FLAG_RAE); - mpt_entry->mtt_sz = cpu_to_be32(1 << mr->mtt.order); + mpt_entry->mtt_sz = cpu_to_be32((1 << mr->mtt.order) * + dev->caps.mtts_per_seg); } else { mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS); } @@ -536,7 +362,8 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err); goto err_cmd; } - mr->enabled = MLX4_MR_EN_HW; + + mr->enabled = 1; mlx4_free_cmd_mailbox(dev, mailbox); @@ -546,7 +373,7 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) mlx4_free_cmd_mailbox(dev, mailbox); err_table: - mlx4_mr_free_icm(dev, key_to_hw_index(mr->key)); + mlx4_table_put(dev, &mr_table->dmpt_table, key_to_hw_index(mr->key)); return err; } EXPORT_SYMBOL_GPL(mlx4_mr_enable); @@ -558,10 +385,18 @@ static int mlx4_write_mtt_chunk(struct mlx4_dev *dev, struct mlx4_mtt *mtt, __be64 *mtts; dma_addr_t dma_handle; int i; + int s = start_index * sizeof (u64); - mtts = mlx4_table_find(&priv->mr_table.mtt_table, mtt->offset + - start_index, &dma_handle); + /* All MTTs must fit in the same page */ + if (start_index / (PAGE_SIZE / sizeof (u64)) != + (start_index + npages - 1) / (PAGE_SIZE / sizeof (u64))) + return -EINVAL; + + if (start_index & (dev->caps.mtts_per_seg - 1)) + return -EINVAL; + mtts = mlx4_table_find(&priv->mr_table.mtt_table, mtt->first_seg + + s / dev->caps.mtt_entry_sz, &dma_handle); if (!mtts) return -ENOMEM; @@ -577,75 +412,27 @@ static int mlx4_write_mtt_chunk(struct mlx4_dev *dev, struct mlx4_mtt *mtt, return 0; } -int __mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, - int start_index, int npages, u64 *page_list) +int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, + int start_index, int npages, u64 *page_list) { - int err = 0; int chunk; - int mtts_per_page; - int max_mtts_first_page; - - /* compute how may mtts fit in the first page */ - mtts_per_page = PAGE_SIZE / sizeof(u64); - max_mtts_first_page = mtts_per_page - (mtt->offset + start_index) - % mtts_per_page; + int err; - chunk = min_t(int, max_mtts_first_page, npages); + if (mtt->order < 0) + return -EINVAL; while (npages > 0) { + chunk = min_t(int, PAGE_SIZE / sizeof(u64), npages); err = mlx4_write_mtt_chunk(dev, mtt, start_index, chunk, page_list); if (err) return err; + npages -= chunk; start_index += chunk; page_list += chunk; - - chunk = min_t(int, mtts_per_page, npages); } - return err; -} -int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt, - int start_index, int npages, u64 *page_list) -{ - struct mlx4_cmd_mailbox *mailbox = NULL; - __be64 *inbox = NULL; - int chunk; - int err = 0; - int i; - - if (mtt->order < 0) - return -EINVAL; - - if (mlx4_is_mfunc(dev)) { - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - inbox = mailbox->buf; - - while (npages > 0) { - chunk = min_t(int, MLX4_MAILBOX_SIZE / sizeof(u64) - 2, - npages); - inbox[0] = cpu_to_be64(mtt->offset + start_index); - inbox[1] = 0; - for (i = 0; i < chunk; ++i) - inbox[i + 2] = cpu_to_be64(page_list[i] | - MLX4_MTT_FLAG_PRESENT); - err = mlx4_WRITE_MTT(dev, mailbox, chunk); - if (err) { - mlx4_free_cmd_mailbox(dev, mailbox); - return err; - } - - npages -= chunk; - start_index += chunk; - page_list += chunk; - } - mlx4_free_cmd_mailbox(dev, mailbox); - return err; - } - - return __mlx4_write_mtt(dev, mtt, start_index, npages, page_list); + return 0; } EXPORT_SYMBOL_GPL(mlx4_write_mtt); @@ -675,34 +462,21 @@ EXPORT_SYMBOL_GPL(mlx4_buf_write_mtt); int mlx4_init_mr_table(struct mlx4_dev *dev) { - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_mr_table *mr_table = &priv->mr_table; + struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; int err; - if (!is_power_of_2(dev->caps.num_mpts)) - return -EINVAL; - - /* Nothing to do for slaves - all MR handling is forwarded - * to the master */ - if (mlx4_is_slave(dev)) - return 0; - err = mlx4_bitmap_init(&mr_table->mpt_bitmap, dev->caps.num_mpts, ~0, dev->caps.reserved_mrws, 0); if (err) return err; err = mlx4_buddy_init(&mr_table->mtt_buddy, - ilog2(dev->caps.num_mtts / - (1 << log_mtts_per_seg))); + ilog2(dev->caps.num_mtt_segs)); if (err) goto err_buddy; if (dev->caps.reserved_mtts) { - priv->reserved_mtts = - mlx4_alloc_mtt_range(dev, - fls(dev->caps.reserved_mtts - 1)); - if (priv->reserved_mtts < 0) { + if (mlx4_alloc_mtt_range(dev, fls(dev->caps.reserved_mtts - 1)) == -1) { mlx4_warn(dev, "MTT table of order %d is too small.\n", mr_table->mtt_buddy.max_order); err = -ENOMEM; @@ -723,14 +497,8 @@ int mlx4_init_mr_table(struct mlx4_dev *dev) void mlx4_cleanup_mr_table(struct mlx4_dev *dev) { - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_mr_table *mr_table = &priv->mr_table; + struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table; - if (mlx4_is_slave(dev)) - return; - if (priv->reserved_mtts >= 0) - mlx4_free_mtt_range(dev, priv->reserved_mtts, - fls(dev->caps.reserved_mtts - 1)); mlx4_buddy_cleanup(&mr_table->mtt_buddy); mlx4_bitmap_cleanup(&mr_table->mpt_bitmap); } @@ -813,7 +581,7 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages, int max_maps, u8 page_shift, struct mlx4_fmr *fmr) { struct mlx4_priv *priv = mlx4_priv(dev); - u64 mtt_offset; + u64 mtt_seg; int err = -ENOMEM; if (page_shift < (ffs(dev->caps.page_size_cap) - 1) || page_shift >= 32) @@ -833,12 +601,11 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages, if (err) return err; - mtt_offset = fmr->mr.mtt.offset * dev->caps.mtt_entry_sz; + mtt_seg = fmr->mr.mtt.first_seg * dev->caps.mtt_entry_sz; fmr->mtts = mlx4_table_find(&priv->mr_table.mtt_table, - fmr->mr.mtt.offset, + fmr->mr.mtt.first_seg, &fmr->dma_handle); - if (!fmr->mtts) { err = -ENOMEM; goto err_free; @@ -852,46 +619,6 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages, } EXPORT_SYMBOL_GPL(mlx4_fmr_alloc); -static int mlx4_fmr_alloc_reserved(struct mlx4_dev *dev, u32 mridx, - u32 pd, u32 access, int max_pages, - int max_maps, u8 page_shift, struct mlx4_fmr *fmr) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int err = -ENOMEM; - - if (page_shift < (ffs(dev->caps.page_size_cap) - 1) || page_shift >= 32) - return -EINVAL; - - /* All MTTs must fit in the same page */ - if (max_pages * sizeof *fmr->mtts > PAGE_SIZE) - return -EINVAL; - - fmr->page_shift = page_shift; - fmr->max_pages = max_pages; - fmr->max_maps = max_maps; - fmr->maps = 0; - - err = mlx4_mr_alloc_reserved(dev, mridx, pd, 0, 0, access, max_pages, - page_shift, &fmr->mr); - if (err) - return err; - - fmr->mtts = mlx4_table_find(&priv->mr_table.mtt_table, - fmr->mr.mtt.offset, - &fmr->dma_handle); - if (!fmr->mtts) { - err = -ENOMEM; - goto err_free; - } - - return 0; - -err_free: - mlx4_mr_free_reserved(dev, &fmr->mr); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_fmr_alloc_reserved); - int mlx4_fmr_enable(struct mlx4_dev *dev, struct mlx4_fmr *fmr) { struct mlx4_priv *priv = mlx4_priv(dev); @@ -913,32 +640,12 @@ EXPORT_SYMBOL_GPL(mlx4_fmr_enable); void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr, u32 *lkey, u32 *rkey) { - struct mlx4_cmd_mailbox *mailbox; - int err; - if (!fmr->maps) return; fmr->maps = 0; - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) { - err = PTR_ERR(mailbox); - printk(KERN_WARNING "mlx4_ib: mlx4_alloc_cmd_mailbox" - " failed (%d)\n", err); - return; - } - - err = mlx4_HW2SW_MPT(dev, NULL, - key_to_hw_index(fmr->mr.key) & - (dev->caps.num_mpts - 1)); - mlx4_free_cmd_mailbox(dev, mailbox); - if (err) { - printk(KERN_WARNING "mlx4_ib: mlx4_HW2SW_MPT failed (%d)\n", - err); - return; - } - fmr->mr.enabled = MLX4_MR_EN_SW; + *(u8 *) fmr->mpt = MLX4_MPT_STATUS_SW; } EXPORT_SYMBOL_GPL(mlx4_fmr_unmap); @@ -947,28 +654,15 @@ int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr) if (fmr->maps) return -EBUSY; + fmr->mr.enabled = 0; mlx4_mr_free(dev, &fmr->mr); - fmr->mr.enabled = MLX4_MR_DISABLED; return 0; } EXPORT_SYMBOL_GPL(mlx4_fmr_free); -static int mlx4_fmr_free_reserved(struct mlx4_dev *dev, struct mlx4_fmr *fmr) -{ - if (fmr->maps) - return -EBUSY; - - mlx4_mr_free_reserved(dev, &fmr->mr); - fmr->mr.enabled = MLX4_MR_DISABLED; - - return 0; -} -EXPORT_SYMBOL_GPL(mlx4_fmr_free_reserved); - int mlx4_SYNC_TPT(struct mlx4_dev *dev) { - return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_SYNC_TPT, 1000, - MLX4_CMD_WRAPPED); + return mlx4_cmd(dev, 0, 0, 0, MLX4_CMD_SYNC_TPT, 1000); } EXPORT_SYMBOL_GPL(mlx4_SYNC_TPT); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/pd.c b/trunk/drivers/net/ethernet/mellanox/mlx4/pd.c index 5c9a54df17ab..260ed259ce9b 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/pd.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/pd.c @@ -31,7 +31,6 @@ * SOFTWARE. */ -#include #include #include #include @@ -52,8 +51,7 @@ int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn) *pdn = mlx4_bitmap_alloc(&priv->pd_bitmap); if (*pdn == -1) return -ENOMEM; - if (mlx4_is_mfunc(dev)) - *pdn |= (dev->caps.function + 1) << NOT_MASKED_PD_BITS; + return 0; } EXPORT_SYMBOL_GPL(mlx4_pd_alloc); @@ -87,8 +85,7 @@ int mlx4_init_pd_table(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); return mlx4_bitmap_init(&priv->pd_bitmap, dev->caps.num_pds, - (1 << NOT_MASKED_PD_BITS) - 1, - dev->caps.reserved_pds, 0); + (1 << 24) - 1, dev->caps.reserved_pds, 0); } void mlx4_cleanup_pd_table(struct mlx4_dev *dev) @@ -111,19 +108,13 @@ void mlx4_cleanup_xrcd_table(struct mlx4_dev *dev) int mlx4_uar_alloc(struct mlx4_dev *dev, struct mlx4_uar *uar) { - int offset; - uar->index = mlx4_bitmap_alloc(&mlx4_priv(dev)->uar_table.bitmap); if (uar->index == -1) return -ENOMEM; - if (mlx4_is_slave(dev)) - offset = uar->index % ((int) pci_resource_len(dev->pdev, 2) / - dev->caps.uar_page_size); - else - offset = uar->index; - uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + offset; + uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + uar->index; uar->map = NULL; + return 0; } EXPORT_SYMBOL_GPL(mlx4_uar_alloc); @@ -241,7 +232,7 @@ int mlx4_init_uar_table(struct mlx4_dev *dev) return mlx4_bitmap_init(&mlx4_priv(dev)->uar_table.bitmap, dev->caps.num_uars, dev->caps.num_uars - 1, - dev->caps.reserved_uars, 0); + max(128, dev->caps.reserved_uars), 0); } void mlx4_cleanup_uar_table(struct mlx4_dev *dev) diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/port.c b/trunk/drivers/net/ethernet/mellanox/mlx4/port.c index 00a9547773c1..d942aea4927b 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/port.c @@ -70,12 +70,41 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table) table->total = 0; } -static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) +static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port, + __be64 *entries) +{ + struct mlx4_cmd_mailbox *mailbox; + u32 in_mod; + int err; + + mailbox = mlx4_alloc_cmd_mailbox(dev); + if (IS_ERR(mailbox)) + return PTR_ERR(mailbox); + + memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE); + + in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port; + err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, + MLX4_CMD_TIME_CLASS_B); + + mlx4_free_cmd_mailbox(dev, mailbox); + return err; +} + +static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, + u64 mac, int *qpn, u8 reserve) { struct mlx4_qp qp; u8 gid[16] = {0}; int err; + if (reserve) { + err = mlx4_qp_reserve_range(dev, 1, 1, qpn); + if (err) { + mlx4_err(dev, "Failed to reserve qp for mac registration\n"); + return err; + } + } qp.qpn = *qpn; mac &= 0xffffffffffffULL; @@ -84,15 +113,16 @@ static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) gid[5] = port; gid[7] = MLX4_UC_STEER << 1; - err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH); - if (err) - mlx4_warn(dev, "Failed Attaching Unicast\n"); + err = mlx4_qp_attach_common(dev, &qp, gid, 0, + MLX4_PROT_ETH, MLX4_UC_STEER); + if (err && reserve) + mlx4_qp_release_range(dev, *qpn, 1); return err; } static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port, - u64 mac, int qpn) + u64 mac, int qpn, u8 free) { struct mlx4_qp qp; u8 gid[16] = {0}; @@ -104,164 +134,60 @@ static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port, gid[5] = port; gid[7] = MLX4_UC_STEER << 1; - mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH); -} - -static int validate_index(struct mlx4_dev *dev, - struct mlx4_mac_table *table, int index) -{ - int err = 0; - - if (index < 0 || index >= table->max || !table->entries[index]) { - mlx4_warn(dev, "No valid Mac entry for the given index\n"); - err = -EINVAL; - } - return err; -} - -static int find_index(struct mlx4_dev *dev, - struct mlx4_mac_table *table, u64 mac) -{ - int i; - - for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { - if ((mac & MLX4_MAC_MASK) == - (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) - return i; - } - /* Mac not found */ - return -EINVAL; + mlx4_qp_detach_common(dev, &qp, gid, MLX4_PROT_ETH, MLX4_UC_STEER); + if (free) + mlx4_qp_release_range(dev, qpn, 1); } -int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn) +int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap) { struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; + struct mlx4_mac_table *table = &info->mac_table; struct mlx4_mac_entry *entry; - int index = 0; - int err = 0; - - mlx4_dbg(dev, "Registering MAC: 0x%llx for adding\n", - (unsigned long long) mac); - index = mlx4_register_mac(dev, port, mac); - if (index < 0) { - err = index; - mlx4_err(dev, "Failed adding MAC: 0x%llx\n", - (unsigned long long) mac); - return err; - } - - if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) { - *qpn = info->base_qpn + index; - return 0; - } - - err = mlx4_qp_reserve_range(dev, 1, 1, qpn); - mlx4_dbg(dev, "Reserved qp %d\n", *qpn); - if (err) { - mlx4_err(dev, "Failed to reserve qp for mac registration\n"); - goto qp_err; - } - - err = mlx4_uc_steer_add(dev, port, mac, qpn); - if (err) - goto steer_err; - - entry = kmalloc(sizeof *entry, GFP_KERNEL); - if (!entry) { - err = -ENOMEM; - goto alloc_err; - } - entry->mac = mac; - err = radix_tree_insert(&info->mac_tree, *qpn, entry); - if (err) - goto insert_err; - return 0; - -insert_err: - kfree(entry); - -alloc_err: - mlx4_uc_steer_release(dev, port, mac, *qpn); - -steer_err: - mlx4_qp_release_range(dev, *qpn, 1); - -qp_err: - mlx4_unregister_mac(dev, port, mac); - return err; -} -EXPORT_SYMBOL_GPL(mlx4_get_eth_qp); + int i, err = 0; + int free = -1; -void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn) -{ - struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; - struct mlx4_mac_entry *entry; + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { + err = mlx4_uc_steer_add(dev, port, mac, qpn, 1); + if (err) + return err; - mlx4_dbg(dev, "Registering MAC: 0x%llx for deleting\n", - (unsigned long long) mac); - mlx4_unregister_mac(dev, port, mac); + entry = kmalloc(sizeof *entry, GFP_KERNEL); + if (!entry) { + mlx4_uc_steer_release(dev, port, mac, *qpn, 1); + return -ENOMEM; + } - if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { - entry = radix_tree_lookup(&info->mac_tree, qpn); - if (entry) { - mlx4_dbg(dev, "Releasing qp: port %d, mac 0x%llx," - " qpn %d\n", port, - (unsigned long long) mac, qpn); - mlx4_uc_steer_release(dev, port, entry->mac, qpn); - mlx4_qp_release_range(dev, qpn, 1); - radix_tree_delete(&info->mac_tree, qpn); + entry->mac = mac; + err = radix_tree_insert(&info->mac_tree, *qpn, entry); + if (err) { kfree(entry); + mlx4_uc_steer_release(dev, port, mac, *qpn, 1); + return err; } } -} -EXPORT_SYMBOL_GPL(mlx4_put_eth_qp); - -static int mlx4_set_port_mac_table(struct mlx4_dev *dev, u8 port, - __be64 *entries) -{ - struct mlx4_cmd_mailbox *mailbox; - u32 in_mod; - int err; - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - - memcpy(mailbox->buf, entries, MLX4_MAC_TABLE_SIZE); - - in_mod = MLX4_SET_PORT_MAC_TABLE << 8 | port; - - err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} - -int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) -{ - struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; - struct mlx4_mac_table *table = &info->mac_table; - int i, err = 0; - int free = -1; - - mlx4_dbg(dev, "Registering MAC: 0x%llx for port %d\n", - (unsigned long long) mac, port); + mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac); mutex_lock(&table->mutex); - for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { - if (free < 0 && !table->entries[i]) { + for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) { + if (free < 0 && !table->refs[i]) { free = i; continue; } if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { - /* MAC already registered, Must not have duplicates */ - err = -EEXIST; + /* MAC already registered, increase references count */ + ++table->refs[i]; goto out; } } + if (free < 0) { + err = -ENOMEM; + goto out; + } + mlx4_dbg(dev, "Free MAC index is %d\n", free); if (table->total == table->max) { @@ -271,103 +197,103 @@ int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) } /* Register new MAC */ + table->refs[free] = 1; table->entries[free] = cpu_to_be64(mac | MLX4_MAC_VALID); err = mlx4_set_port_mac_table(dev, port, table->entries); if (unlikely(err)) { - mlx4_err(dev, "Failed adding MAC: 0x%llx\n", - (unsigned long long) mac); + mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) mac); + table->refs[free] = 0; table->entries[free] = 0; goto out; } - err = free; + if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER)) + *qpn = info->base_qpn + free; ++table->total; out: mutex_unlock(&table->mutex); return err; } -EXPORT_SYMBOL_GPL(__mlx4_register_mac); +EXPORT_SYMBOL_GPL(mlx4_register_mac); -int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) +static int validate_index(struct mlx4_dev *dev, + struct mlx4_mac_table *table, int index) { - u64 out_param; - int err; - - if (mlx4_is_mfunc(dev)) { - set_param_l(&out_param, port); - err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, - RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); - if (err) - return err; + int err = 0; - return get_param_l(&out_param); + if (index < 0 || index >= table->max || !table->entries[index]) { + mlx4_warn(dev, "No valid Mac entry for the given index\n"); + err = -EINVAL; } - return __mlx4_register_mac(dev, port, mac); + return err; } -EXPORT_SYMBOL_GPL(mlx4_register_mac); +static int find_index(struct mlx4_dev *dev, + struct mlx4_mac_table *table, u64 mac) +{ + int i; + for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { + if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) + return i; + } + /* Mac not found */ + return -EINVAL; +} -void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) +void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn) { struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; struct mlx4_mac_table *table = &info->mac_table; - int index; + int index = qpn - info->base_qpn; + struct mlx4_mac_entry *entry; - index = find_index(dev, table, mac); + if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { + entry = radix_tree_lookup(&info->mac_tree, qpn); + if (entry) { + mlx4_uc_steer_release(dev, port, entry->mac, qpn, 1); + radix_tree_delete(&info->mac_tree, qpn); + index = find_index(dev, table, entry->mac); + kfree(entry); + } + } mutex_lock(&table->mutex); if (validate_index(dev, table, index)) goto out; - table->entries[index] = 0; - mlx4_set_port_mac_table(dev, port, table->entries); - --table->total; + /* Check whether this address has reference count */ + if (!(--table->refs[index])) { + table->entries[index] = 0; + mlx4_set_port_mac_table(dev, port, table->entries); + --table->total; + } out: mutex_unlock(&table->mutex); } -EXPORT_SYMBOL_GPL(__mlx4_unregister_mac); - -void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) -{ - u64 out_param; - int err; - - if (mlx4_is_mfunc(dev)) { - set_param_l(&out_param, port); - err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC, - RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); - return; - } - __mlx4_unregister_mac(dev, port, mac); - return; -} EXPORT_SYMBOL_GPL(mlx4_unregister_mac); -int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac) +int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wrap) { struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; struct mlx4_mac_table *table = &info->mac_table; - struct mlx4_mac_entry *entry; int index = qpn - info->base_qpn; - int err = 0; + struct mlx4_mac_entry *entry; + int err; if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) { entry = radix_tree_lookup(&info->mac_tree, qpn); if (!entry) return -EINVAL; - mlx4_uc_steer_release(dev, port, entry->mac, qpn); - mlx4_unregister_mac(dev, port, entry->mac); + index = find_index(dev, table, entry->mac); + mlx4_uc_steer_release(dev, port, entry->mac, qpn, 0); entry->mac = new_mac; - mlx4_register_mac(dev, port, new_mac); - err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn); - return err; + err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn, 0); + if (err || index < 0) + return err; } - /* CX1 doesn't support multi-functions */ mutex_lock(&table->mutex); err = validate_index(dev, table, index); @@ -378,8 +304,7 @@ int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac) err = mlx4_set_port_mac_table(dev, port, table->entries); if (unlikely(err)) { - mlx4_err(dev, "Failed adding MAC: 0x%llx\n", - (unsigned long long) new_mac); + mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) new_mac); table->entries[index] = 0; } out: @@ -387,7 +312,6 @@ int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac) return err; } EXPORT_SYMBOL_GPL(mlx4_replace_mac); - static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, __be32 *entries) { @@ -402,7 +326,7 @@ static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port, memcpy(mailbox->buf, entries, MLX4_VLAN_TABLE_SIZE); in_mod = MLX4_SET_PORT_VLAN_TABLE << 8 | port; err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); + MLX4_CMD_TIME_CLASS_B); mlx4_free_cmd_mailbox(dev, mailbox); @@ -428,8 +352,7 @@ int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx) } EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan); -static int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, - int *index) +int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) { struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; int i, err = 0; @@ -464,7 +387,7 @@ static int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, goto out; } - /* Register new VLAN */ + /* Register new MAC */ table->refs[free] = 1; table->entries[free] = cpu_to_be32(vlan | MLX4_VLAN_VALID); @@ -482,27 +405,9 @@ static int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, mutex_unlock(&table->mutex); return err; } - -int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) -{ - u64 out_param; - int err; - - if (mlx4_is_mfunc(dev)) { - set_param_l(&out_param, port); - err = mlx4_cmd_imm(dev, vlan, &out_param, RES_VLAN, - RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); - if (!err) - *index = get_param_l(&out_param); - - return err; - } - return __mlx4_register_vlan(dev, port, vlan, index); -} EXPORT_SYMBOL_GPL(mlx4_register_vlan); -static void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) +void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) { struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table; @@ -527,25 +432,6 @@ static void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) out: mutex_unlock(&table->mutex); } - -void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) -{ - u64 in_param; - int err; - - if (mlx4_is_mfunc(dev)) { - set_param_l(&in_param, port); - err = mlx4_cmd(dev, in_param, RES_VLAN, RES_OP_RESERVE_AND_MAP, - MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED); - if (!err) - mlx4_warn(dev, "Failed freeing vlan at index:%d\n", - index); - - return; - } - __mlx4_unregister_vlan(dev, port, index); -} EXPORT_SYMBOL_GPL(mlx4_unregister_vlan); int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps) @@ -576,8 +462,7 @@ int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps) *(__be32 *) (&inbuf[20]) = cpu_to_be32(port); err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3, - MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, - MLX4_CMD_NATIVE); + MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C); if (!err) *caps = *(__be32 *) (outbuf + 84); mlx4_free_cmd_mailbox(dev, inmailbox); @@ -614,8 +499,7 @@ int mlx4_check_ext_port_caps(struct mlx4_dev *dev, u8 port) *(__be32 *) (&inbuf[20]) = cpu_to_be32(port); err = mlx4_cmd_box(dev, inmailbox->dma, outmailbox->dma, port, 3, - MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C, - MLX4_CMD_NATIVE); + MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C); packet_error = be16_to_cpu(*(__be16 *) (outbuf + 4)); @@ -628,139 +512,6 @@ int mlx4_check_ext_port_caps(struct mlx4_dev *dev, u8 port) return err; } -static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, - u8 op_mod, struct mlx4_cmd_mailbox *inbox) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_port_info *port_info; - struct mlx4_mfunc_master_ctx *master = &priv->mfunc.master; - struct mlx4_slave_state *slave_st = &master->slave_state[slave]; - struct mlx4_set_port_rqp_calc_context *qpn_context; - struct mlx4_set_port_general_context *gen_context; - int reset_qkey_viols; - int port; - int is_eth; - u32 in_modifier; - u32 promisc; - u16 mtu, prev_mtu; - int err; - int i; - __be32 agg_cap_mask; - __be32 slave_cap_mask; - __be32 new_cap_mask; - - port = in_mod & 0xff; - in_modifier = in_mod >> 8; - is_eth = op_mod; - port_info = &priv->port[port]; - - /* Slaves cannot perform SET_PORT operations except changing MTU */ - if (is_eth) { - if (slave != dev->caps.function && - in_modifier != MLX4_SET_PORT_GENERAL) { - mlx4_warn(dev, "denying SET_PORT for slave:%d\n", - slave); - return -EINVAL; - } - switch (in_modifier) { - case MLX4_SET_PORT_RQP_CALC: - qpn_context = inbox->buf; - qpn_context->base_qpn = - cpu_to_be32(port_info->base_qpn); - qpn_context->n_mac = 0x7; - promisc = be32_to_cpu(qpn_context->promisc) >> - SET_PORT_PROMISC_SHIFT; - qpn_context->promisc = cpu_to_be32( - promisc << SET_PORT_PROMISC_SHIFT | - port_info->base_qpn); - promisc = be32_to_cpu(qpn_context->mcast) >> - SET_PORT_MC_PROMISC_SHIFT; - qpn_context->mcast = cpu_to_be32( - promisc << SET_PORT_MC_PROMISC_SHIFT | - port_info->base_qpn); - break; - case MLX4_SET_PORT_GENERAL: - gen_context = inbox->buf; - /* Mtu is configured as the max MTU among all the - * the functions on the port. */ - mtu = be16_to_cpu(gen_context->mtu); - mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port]); - prev_mtu = slave_st->mtu[port]; - slave_st->mtu[port] = mtu; - if (mtu > master->max_mtu[port]) - master->max_mtu[port] = mtu; - if (mtu < prev_mtu && prev_mtu == - master->max_mtu[port]) { - slave_st->mtu[port] = mtu; - master->max_mtu[port] = mtu; - for (i = 0; i < dev->num_slaves; i++) { - master->max_mtu[port] = - max(master->max_mtu[port], - master->slave_state[i].mtu[port]); - } - } - - gen_context->mtu = cpu_to_be16(master->max_mtu[port]); - break; - } - return mlx4_cmd(dev, inbox->dma, in_mod, op_mod, - MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_NATIVE); - } - - /* For IB, we only consider: - * - The capability mask, which is set to the aggregate of all - * slave function capabilities - * - The QKey violatin counter - reset according to each request. - */ - - if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { - reset_qkey_viols = (*(u8 *) inbox->buf) & 0x40; - new_cap_mask = ((__be32 *) inbox->buf)[2]; - } else { - reset_qkey_viols = ((u8 *) inbox->buf)[3] & 0x1; - new_cap_mask = ((__be32 *) inbox->buf)[1]; - } - - agg_cap_mask = 0; - slave_cap_mask = - priv->mfunc.master.slave_state[slave].ib_cap_mask[port]; - priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = new_cap_mask; - for (i = 0; i < dev->num_slaves; i++) - agg_cap_mask |= - priv->mfunc.master.slave_state[i].ib_cap_mask[port]; - - /* only clear mailbox for guests. Master may be setting - * MTU or PKEY table size - */ - if (slave != dev->caps.function) - memset(inbox->buf, 0, 256); - if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { - *(u8 *) inbox->buf = !!reset_qkey_viols << 6; - ((__be32 *) inbox->buf)[2] = agg_cap_mask; - } else { - ((u8 *) inbox->buf)[3] = !!reset_qkey_viols; - ((__be32 *) inbox->buf)[1] = agg_cap_mask; - } - - err = mlx4_cmd(dev, inbox->dma, port, is_eth, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); - if (err) - priv->mfunc.master.slave_state[slave].ib_cap_mask[port] = - slave_cap_mask; - return err; -} - -int mlx4_SET_PORT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - return mlx4_common_set_port(dev, slave, vhcr->in_modifier, - vhcr->op_modifier, inbox); -} - int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) { struct mlx4_cmd_mailbox *mailbox; @@ -777,127 +528,8 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port) ((__be32 *) mailbox->buf)[1] = dev->caps.ib_port_def_cap[port]; err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); + MLX4_CMD_TIME_CLASS_B); mlx4_free_cmd_mailbox(dev, mailbox); return err; } - -static int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu, - u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx) -{ - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_set_port_general_context *context; - int err; - u32 in_mod; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - context = mailbox->buf; - memset(context, 0, sizeof *context); - - context->flags = SET_PORT_GEN_ALL_VALID; - context->mtu = cpu_to_be16(mtu); - context->pptx = (pptx * (!pfctx)) << 7; - context->pfctx = pfctx; - context->pprx = (pprx * (!pfcrx)) << 7; - context->pfcrx = pfcrx; - - in_mod = MLX4_SET_PORT_GENERAL << 8 | port; - err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} -EXPORT_SYMBOL(mlx4_SET_PORT_general); - -static int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn, - u8 promisc) -{ - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_set_port_rqp_calc_context *context; - int err; - u32 in_mod; - u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ? - MCAST_DIRECT : MCAST_DEFAULT; - - if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER && - dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER) - return 0; - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) - return PTR_ERR(mailbox); - context = mailbox->buf; - memset(context, 0, sizeof *context); - - context->base_qpn = cpu_to_be32(base_qpn); - context->n_mac = dev->caps.log_num_macs; - context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | - base_qpn); - context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT | - base_qpn); - context->intra_no_vlan = 0; - context->no_vlan = MLX4_NO_VLAN_IDX; - context->intra_vlan_miss = 0; - context->vlan_miss = MLX4_VLAN_MISS_IDX; - - in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port; - err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); - - mlx4_free_cmd_mailbox(dev, mailbox); - return err; -} -EXPORT_SYMBOL(mlx4_SET_PORT_qpn_calc); - -int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err = 0; - - return err; -} - -int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, - u64 mac, u64 clear, u8 mode) -{ - return mlx4_cmd(dev, (mac | (clear << 63)), port, mode, - MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_WRAPPED); -} -EXPORT_SYMBOL(mlx4_SET_MCAST_FLTR); - -int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err = 0; - - return err; -} - -int mlx4_common_dump_eth_stats(struct mlx4_dev *dev, int slave, - u32 in_mod, struct mlx4_cmd_mailbox *outbox) -{ - return mlx4_cmd_box(dev, 0, outbox->dma, in_mod, 0, - MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_NATIVE); -} - -int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - return mlx4_common_dump_eth_stats(dev, slave, - vhcr->in_modifier, outbox); -} diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c b/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c index 66f91ca7a7c6..b967647d0c76 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/profile.c @@ -98,8 +98,8 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, profile[MLX4_RES_EQ].size = dev_cap->eqc_entry_sz; profile[MLX4_RES_DMPT].size = dev_cap->dmpt_entry_sz; profile[MLX4_RES_CMPT].size = dev_cap->cmpt_entry_sz; - profile[MLX4_RES_MTT].size = dev_cap->mtt_entry_sz; - profile[MLX4_RES_MCG].size = mlx4_get_mgm_entry_size(dev); + profile[MLX4_RES_MTT].size = dev->caps.mtts_per_seg * dev_cap->mtt_entry_sz; + profile[MLX4_RES_MCG].size = MLX4_MGM_ENTRY_SIZE; profile[MLX4_RES_QP].num = request->num_qp; profile[MLX4_RES_RDMARC].num = request->num_qp * request->rdmarc_per_qp; @@ -210,7 +210,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, init_hca->cmpt_base = profile[i].start; break; case MLX4_RES_MTT: - dev->caps.num_mtts = profile[i].num; + dev->caps.num_mtt_segs = profile[i].num; priv->mr_table.mtt_base = profile[i].start; init_hca->mtt_base = profile[i].start; break; @@ -218,8 +218,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev, dev->caps.num_mgms = profile[i].num >> 1; dev->caps.num_amgms = profile[i].num >> 1; init_hca->mc_base = profile[i].start; - init_hca->log_mc_entry_sz = - ilog2(mlx4_get_mgm_entry_size(dev)); + init_hca->log_mc_entry_sz = ilog2(MLX4_MGM_ENTRY_SIZE); init_hca->log_mc_table_sz = profile[i].log_num; init_hca->log_mc_hash_sz = profile[i].log_num - 1; break; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/qp.c b/trunk/drivers/net/ethernet/mellanox/mlx4/qp.c index 6b03ac8b9002..15f870cb2590 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -35,8 +35,6 @@ #include #include -#include - #include #include @@ -57,7 +55,7 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type) spin_unlock(&qp_table->lock); if (!qp) { - mlx4_dbg(dev, "Async event for none existent QP %08x\n", qpn); + mlx4_warn(dev, "Async event for bogus QP %08x\n", qpn); return; } @@ -67,17 +65,10 @@ void mlx4_qp_event(struct mlx4_dev *dev, u32 qpn, int event_type) complete(&qp->free); } -static int is_qp0(struct mlx4_dev *dev, struct mlx4_qp *qp) -{ - return qp->qpn >= dev->caps.sqp_start && - qp->qpn <= dev->caps.sqp_start + 1; -} - -static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, - enum mlx4_qp_state cur_state, enum mlx4_qp_state new_state, - struct mlx4_qp_context *context, - enum mlx4_qp_optpar optpar, - int sqd_event, struct mlx4_qp *qp, int native) +int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, + enum mlx4_qp_state cur_state, enum mlx4_qp_state new_state, + struct mlx4_qp_context *context, enum mlx4_qp_optpar optpar, + int sqd_event, struct mlx4_qp *qp) { static const u16 op[MLX4_QP_NUM_STATE][MLX4_QP_NUM_STATE] = { [MLX4_QP_STATE_RST] = { @@ -119,26 +110,16 @@ static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, } }; - struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_cmd_mailbox *mailbox; int ret = 0; - u8 port; if (cur_state >= MLX4_QP_NUM_STATE || new_state >= MLX4_QP_NUM_STATE || !op[cur_state][new_state]) return -EINVAL; - if (op[cur_state][new_state] == MLX4_CMD_2RST_QP) { - ret = mlx4_cmd(dev, 0, qp->qpn, 2, - MLX4_CMD_2RST_QP, MLX4_CMD_TIME_CLASS_A, native); - if (mlx4_is_master(dev) && cur_state != MLX4_QP_STATE_ERR && - cur_state != MLX4_QP_STATE_RST && - is_qp0(dev, qp)) { - port = (qp->qpn & 1) + 1; - priv->mfunc.master.qp0_state[port].qp0_active = 0; - } - return ret; - } + if (op[cur_state][new_state] == MLX4_CMD_2RST_QP) + return mlx4_cmd(dev, 0, qp->qpn, 2, + MLX4_CMD_2RST_QP, MLX4_CMD_TIME_CLASS_A); mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) @@ -151,218 +132,107 @@ static int __mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT; } - port = ((context->pri_path.sched_queue >> 6) & 1) + 1; - if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH) - context->pri_path.sched_queue = (context->pri_path.sched_queue & - 0xc3); - *(__be32 *) mailbox->buf = cpu_to_be32(optpar); memcpy(mailbox->buf + 8, context, sizeof *context); ((struct mlx4_qp_context *) (mailbox->buf + 8))->local_qpn = cpu_to_be32(qp->qpn); - ret = mlx4_cmd(dev, mailbox->dma | dev->caps.function, - qp->qpn | (!!sqd_event << 31), + ret = mlx4_cmd(dev, mailbox->dma, qp->qpn | (!!sqd_event << 31), new_state == MLX4_QP_STATE_RST ? 2 : 0, - op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C, native); + op[cur_state][new_state], MLX4_CMD_TIME_CLASS_C); mlx4_free_cmd_mailbox(dev, mailbox); return ret; } - -int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, - enum mlx4_qp_state cur_state, enum mlx4_qp_state new_state, - struct mlx4_qp_context *context, - enum mlx4_qp_optpar optpar, - int sqd_event, struct mlx4_qp *qp) -{ - return __mlx4_qp_modify(dev, mtt, cur_state, new_state, context, - optpar, sqd_event, qp, 0); -} EXPORT_SYMBOL_GPL(mlx4_qp_modify); -int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, - int *base) +int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_qp_table *qp_table = &priv->qp_table; + int qpn; - *base = mlx4_bitmap_alloc_range(&qp_table->bitmap, cnt, align); - if (*base == -1) + qpn = mlx4_bitmap_alloc_range(&qp_table->bitmap, cnt, align); + if (qpn == -1) return -ENOMEM; + *base = qpn; return 0; } - -int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base) -{ - u64 in_param; - u64 out_param; - int err; - - if (mlx4_is_mfunc(dev)) { - set_param_l(&in_param, cnt); - set_param_h(&in_param, align); - err = mlx4_cmd_imm(dev, in_param, &out_param, - RES_QP, RES_OP_RESERVE, - MLX4_CMD_ALLOC_RES, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); - if (err) - return err; - - *base = get_param_l(&out_param); - return 0; - } - return __mlx4_qp_reserve_range(dev, cnt, align, base); -} EXPORT_SYMBOL_GPL(mlx4_qp_reserve_range); -void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) +void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_qp_table *qp_table = &priv->qp_table; - - if (mlx4_is_qp_reserved(dev, (u32) base_qpn)) + if (base_qpn < dev->caps.sqp_start + 8) return; - mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt); -} - -void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) -{ - u64 in_param; - int err; - if (mlx4_is_mfunc(dev)) { - set_param_l(&in_param, base_qpn); - set_param_h(&in_param, cnt); - err = mlx4_cmd(dev, in_param, RES_QP, RES_OP_RESERVE, - MLX4_CMD_FREE_RES, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); - if (err) { - mlx4_warn(dev, "Failed to release qp range" - " base:%d cnt:%d\n", base_qpn, cnt); - } - } else - __mlx4_qp_release_range(dev, base_qpn, cnt); + mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt); } EXPORT_SYMBOL_GPL(mlx4_qp_release_range); -int __mlx4_qp_alloc_icm(struct mlx4_dev *dev, int qpn) +int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_qp_table *qp_table = &priv->qp_table; int err; - err = mlx4_table_get(dev, &qp_table->qp_table, qpn); + if (!qpn) + return -EINVAL; + + qp->qpn = qpn; + + err = mlx4_table_get(dev, &qp_table->qp_table, qp->qpn); if (err) goto err_out; - err = mlx4_table_get(dev, &qp_table->auxc_table, qpn); + err = mlx4_table_get(dev, &qp_table->auxc_table, qp->qpn); if (err) goto err_put_qp; - err = mlx4_table_get(dev, &qp_table->altc_table, qpn); + err = mlx4_table_get(dev, &qp_table->altc_table, qp->qpn); if (err) goto err_put_auxc; - err = mlx4_table_get(dev, &qp_table->rdmarc_table, qpn); + err = mlx4_table_get(dev, &qp_table->rdmarc_table, qp->qpn); if (err) goto err_put_altc; - err = mlx4_table_get(dev, &qp_table->cmpt_table, qpn); + err = mlx4_table_get(dev, &qp_table->cmpt_table, qp->qpn); if (err) goto err_put_rdmarc; + spin_lock_irq(&qp_table->lock); + err = radix_tree_insert(&dev->qp_table_tree, qp->qpn & (dev->caps.num_qps - 1), qp); + spin_unlock_irq(&qp_table->lock); + if (err) + goto err_put_cmpt; + + atomic_set(&qp->refcount, 1); + init_completion(&qp->free); + return 0; +err_put_cmpt: + mlx4_table_put(dev, &qp_table->cmpt_table, qp->qpn); + err_put_rdmarc: - mlx4_table_put(dev, &qp_table->rdmarc_table, qpn); + mlx4_table_put(dev, &qp_table->rdmarc_table, qp->qpn); err_put_altc: - mlx4_table_put(dev, &qp_table->altc_table, qpn); + mlx4_table_put(dev, &qp_table->altc_table, qp->qpn); err_put_auxc: - mlx4_table_put(dev, &qp_table->auxc_table, qpn); + mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn); err_put_qp: - mlx4_table_put(dev, &qp_table->qp_table, qpn); + mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); err_out: return err; } - -static int mlx4_qp_alloc_icm(struct mlx4_dev *dev, int qpn) -{ - u64 param; - - if (mlx4_is_mfunc(dev)) { - set_param_l(¶m, qpn); - return mlx4_cmd_imm(dev, param, ¶m, RES_QP, RES_OP_MAP_ICM, - MLX4_CMD_ALLOC_RES, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED); - } - return __mlx4_qp_alloc_icm(dev, qpn); -} - -void __mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_qp_table *qp_table = &priv->qp_table; - - mlx4_table_put(dev, &qp_table->cmpt_table, qpn); - mlx4_table_put(dev, &qp_table->rdmarc_table, qpn); - mlx4_table_put(dev, &qp_table->altc_table, qpn); - mlx4_table_put(dev, &qp_table->auxc_table, qpn); - mlx4_table_put(dev, &qp_table->qp_table, qpn); -} - -static void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn) -{ - u64 in_param; - - if (mlx4_is_mfunc(dev)) { - set_param_l(&in_param, qpn); - if (mlx4_cmd(dev, in_param, RES_QP, RES_OP_MAP_ICM, - MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED)) - mlx4_warn(dev, "Failed to free icm of qp:%d\n", qpn); - } else - __mlx4_qp_free_icm(dev, qpn); -} - -int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_qp_table *qp_table = &priv->qp_table; - int err; - - if (!qpn) - return -EINVAL; - - qp->qpn = qpn; - - err = mlx4_qp_alloc_icm(dev, qpn); - if (err) - return err; - - spin_lock_irq(&qp_table->lock); - err = radix_tree_insert(&dev->qp_table_tree, qp->qpn & - (dev->caps.num_qps - 1), qp); - spin_unlock_irq(&qp_table->lock); - if (err) - goto err_icm; - - atomic_set(&qp->refcount, 1); - init_completion(&qp->free); - - return 0; - -err_icm: - mlx4_qp_free_icm(dev, qpn); - return err; -} - EXPORT_SYMBOL_GPL(mlx4_qp_alloc); void mlx4_qp_remove(struct mlx4_dev *dev, struct mlx4_qp *qp) @@ -378,18 +248,24 @@ EXPORT_SYMBOL_GPL(mlx4_qp_remove); void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp) { + struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; + if (atomic_dec_and_test(&qp->refcount)) complete(&qp->free); wait_for_completion(&qp->free); - mlx4_qp_free_icm(dev, qp->qpn); + mlx4_table_put(dev, &qp_table->cmpt_table, qp->qpn); + mlx4_table_put(dev, &qp_table->rdmarc_table, qp->qpn); + mlx4_table_put(dev, &qp_table->altc_table, qp->qpn); + mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn); + mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); } EXPORT_SYMBOL_GPL(mlx4_qp_free); static int mlx4_CONF_SPECIAL_QP(struct mlx4_dev *dev, u32 base_qpn) { return mlx4_cmd(dev, 0, base_qpn, 0, MLX4_CMD_CONF_SPECIAL_QP, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE); + MLX4_CMD_TIME_CLASS_B); } int mlx4_init_qp_table(struct mlx4_dev *dev) @@ -400,8 +276,6 @@ int mlx4_init_qp_table(struct mlx4_dev *dev) spin_lock_init(&qp_table->lock); INIT_RADIX_TREE(&dev->qp_table_tree, GFP_ATOMIC); - if (mlx4_is_slave(dev)) - return 0; /* * We reserve 2 extra QPs per port for the special QPs. The @@ -453,9 +327,6 @@ int mlx4_init_qp_table(struct mlx4_dev *dev) void mlx4_cleanup_qp_table(struct mlx4_dev *dev) { - if (mlx4_is_slave(dev)) - return; - mlx4_CONF_SPECIAL_QP(dev, 0); mlx4_bitmap_cleanup(&mlx4_priv(dev)->qp_table.bitmap); } @@ -471,8 +342,7 @@ int mlx4_qp_query(struct mlx4_dev *dev, struct mlx4_qp *qp, return PTR_ERR(mailbox); err = mlx4_cmd_box(dev, 0, mailbox->dma, qp->qpn, 0, - MLX4_CMD_QUERY_QP, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED); + MLX4_CMD_QUERY_QP, MLX4_CMD_TIME_CLASS_A); if (!err) memcpy(context, mailbox->buf + 8, sizeof *context); diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c deleted file mode 100644 index bdd61c35d044..000000000000 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ /dev/null @@ -1,3103 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. - * All rights reserved. - * Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * 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 AUTHORS OR COPYRIGHT HOLDERS - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "mlx4.h" -#include "fw.h" - -#define MLX4_MAC_VALID (1ull << 63) -#define MLX4_MAC_MASK 0x7fffffffffffffffULL -#define ETH_ALEN 6 - -struct mac_res { - struct list_head list; - u64 mac; - u8 port; -}; - -struct res_common { - struct list_head list; - u32 res_id; - int owner; - int state; - int from_state; - int to_state; - int removing; -}; - -enum { - RES_ANY_BUSY = 1 -}; - -struct res_gid { - struct list_head list; - u8 gid[16]; - enum mlx4_protocol prot; -}; - -enum res_qp_states { - RES_QP_BUSY = RES_ANY_BUSY, - - /* QP number was allocated */ - RES_QP_RESERVED, - - /* ICM memory for QP context was mapped */ - RES_QP_MAPPED, - - /* QP is in hw ownership */ - RES_QP_HW -}; - -static inline const char *qp_states_str(enum res_qp_states state) -{ - switch (state) { - case RES_QP_BUSY: return "RES_QP_BUSY"; - case RES_QP_RESERVED: return "RES_QP_RESERVED"; - case RES_QP_MAPPED: return "RES_QP_MAPPED"; - case RES_QP_HW: return "RES_QP_HW"; - default: return "Unknown"; - } -} - -struct res_qp { - struct res_common com; - struct res_mtt *mtt; - struct res_cq *rcq; - struct res_cq *scq; - struct res_srq *srq; - struct list_head mcg_list; - spinlock_t mcg_spl; - int local_qpn; -}; - -enum res_mtt_states { - RES_MTT_BUSY = RES_ANY_BUSY, - RES_MTT_ALLOCATED, -}; - -static inline const char *mtt_states_str(enum res_mtt_states state) -{ - switch (state) { - case RES_MTT_BUSY: return "RES_MTT_BUSY"; - case RES_MTT_ALLOCATED: return "RES_MTT_ALLOCATED"; - default: return "Unknown"; - } -} - -struct res_mtt { - struct res_common com; - int order; - atomic_t ref_count; -}; - -enum res_mpt_states { - RES_MPT_BUSY = RES_ANY_BUSY, - RES_MPT_RESERVED, - RES_MPT_MAPPED, - RES_MPT_HW, -}; - -struct res_mpt { - struct res_common com; - struct res_mtt *mtt; - int key; -}; - -enum res_eq_states { - RES_EQ_BUSY = RES_ANY_BUSY, - RES_EQ_RESERVED, - RES_EQ_HW, -}; - -struct res_eq { - struct res_common com; - struct res_mtt *mtt; -}; - -enum res_cq_states { - RES_CQ_BUSY = RES_ANY_BUSY, - RES_CQ_ALLOCATED, - RES_CQ_HW, -}; - -struct res_cq { - struct res_common com; - struct res_mtt *mtt; - atomic_t ref_count; -}; - -enum res_srq_states { - RES_SRQ_BUSY = RES_ANY_BUSY, - RES_SRQ_ALLOCATED, - RES_SRQ_HW, -}; - -static inline const char *srq_states_str(enum res_srq_states state) -{ - switch (state) { - case RES_SRQ_BUSY: return "RES_SRQ_BUSY"; - case RES_SRQ_ALLOCATED: return "RES_SRQ_ALLOCATED"; - case RES_SRQ_HW: return "RES_SRQ_HW"; - default: return "Unknown"; - } -} - -struct res_srq { - struct res_common com; - struct res_mtt *mtt; - struct res_cq *cq; - atomic_t ref_count; -}; - -enum res_counter_states { - RES_COUNTER_BUSY = RES_ANY_BUSY, - RES_COUNTER_ALLOCATED, -}; - -static inline const char *counter_states_str(enum res_counter_states state) -{ - switch (state) { - case RES_COUNTER_BUSY: return "RES_COUNTER_BUSY"; - case RES_COUNTER_ALLOCATED: return "RES_COUNTER_ALLOCATED"; - default: return "Unknown"; - } -} - -struct res_counter { - struct res_common com; - int port; -}; - -/* For Debug uses */ -static const char *ResourceType(enum mlx4_resource rt) -{ - switch (rt) { - case RES_QP: return "RES_QP"; - case RES_CQ: return "RES_CQ"; - case RES_SRQ: return "RES_SRQ"; - case RES_MPT: return "RES_MPT"; - case RES_MTT: return "RES_MTT"; - case RES_MAC: return "RES_MAC"; - case RES_EQ: return "RES_EQ"; - case RES_COUNTER: return "RES_COUNTER"; - default: return "Unknown resource type !!!"; - }; -} - -int mlx4_init_resource_tracker(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int i; - int t; - - priv->mfunc.master.res_tracker.slave_list = - kzalloc(dev->num_slaves * sizeof(struct slave_list), - GFP_KERNEL); - if (!priv->mfunc.master.res_tracker.slave_list) - return -ENOMEM; - - for (i = 0 ; i < dev->num_slaves; i++) { - for (t = 0; t < MLX4_NUM_OF_RESOURCE_TYPE; ++t) - INIT_LIST_HEAD(&priv->mfunc.master.res_tracker. - slave_list[i].res_list[t]); - mutex_init(&priv->mfunc.master.res_tracker.slave_list[i].mutex); - } - - mlx4_dbg(dev, "Started init_resource_tracker: %ld slaves\n", - dev->num_slaves); - for (i = 0 ; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) - INIT_RADIX_TREE(&priv->mfunc.master.res_tracker.res_tree[i], - GFP_ATOMIC|__GFP_NOWARN); - - spin_lock_init(&priv->mfunc.master.res_tracker.lock); - return 0 ; -} - -void mlx4_free_resource_tracker(struct mlx4_dev *dev) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - int i; - - if (priv->mfunc.master.res_tracker.slave_list) { - for (i = 0 ; i < dev->num_slaves; i++) - mlx4_delete_all_resources_for_slave(dev, i); - - kfree(priv->mfunc.master.res_tracker.slave_list); - } -} - -static void update_ud_gid(struct mlx4_dev *dev, - struct mlx4_qp_context *qp_ctx, u8 slave) -{ - u32 ts = (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff; - - if (MLX4_QP_ST_UD == ts) - qp_ctx->pri_path.mgid_index = 0x80 | slave; - - mlx4_dbg(dev, "slave %d, new gid index: 0x%x ", - slave, qp_ctx->pri_path.mgid_index); -} - -static int mpt_mask(struct mlx4_dev *dev) -{ - return dev->caps.num_mpts - 1; -} - -static void *find_res(struct mlx4_dev *dev, int res_id, - enum mlx4_resource type) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - return radix_tree_lookup(&priv->mfunc.master.res_tracker.res_tree[type], - res_id); -} - -static int get_res(struct mlx4_dev *dev, int slave, int res_id, - enum mlx4_resource type, - void *res) -{ - struct res_common *r; - int err = 0; - - spin_lock_irq(mlx4_tlock(dev)); - r = find_res(dev, res_id, type); - if (!r) { - err = -ENONET; - goto exit; - } - - if (r->state == RES_ANY_BUSY) { - err = -EBUSY; - goto exit; - } - - if (r->owner != slave) { - err = -EPERM; - goto exit; - } - - r->from_state = r->state; - r->state = RES_ANY_BUSY; - mlx4_dbg(dev, "res %s id 0x%x to busy\n", - ResourceType(type), r->res_id); - - if (res) - *((struct res_common **)res) = r; - -exit: - spin_unlock_irq(mlx4_tlock(dev)); - return err; -} - -int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev, - enum mlx4_resource type, - int res_id, int *slave) -{ - - struct res_common *r; - int err = -ENOENT; - int id = res_id; - - if (type == RES_QP) - id &= 0x7fffff; - spin_lock_irq(mlx4_tlock(dev)); - - r = find_res(dev, id, type); - if (r) { - *slave = r->owner; - err = 0; - } - spin_unlock_irq(mlx4_tlock(dev)); - - return err; -} - -static void put_res(struct mlx4_dev *dev, int slave, int res_id, - enum mlx4_resource type) -{ - struct res_common *r; - - spin_lock_irq(mlx4_tlock(dev)); - r = find_res(dev, res_id, type); - if (r) - r->state = r->from_state; - spin_unlock_irq(mlx4_tlock(dev)); -} - -static struct res_common *alloc_qp_tr(int id) -{ - struct res_qp *ret; - - ret = kzalloc(sizeof *ret, GFP_KERNEL); - if (!ret) - return NULL; - - ret->com.res_id = id; - ret->com.state = RES_QP_RESERVED; - INIT_LIST_HEAD(&ret->mcg_list); - spin_lock_init(&ret->mcg_spl); - - return &ret->com; -} - -static struct res_common *alloc_mtt_tr(int id, int order) -{ - struct res_mtt *ret; - - ret = kzalloc(sizeof *ret, GFP_KERNEL); - if (!ret) - return NULL; - - ret->com.res_id = id; - ret->order = order; - ret->com.state = RES_MTT_ALLOCATED; - atomic_set(&ret->ref_count, 0); - - return &ret->com; -} - -static struct res_common *alloc_mpt_tr(int id, int key) -{ - struct res_mpt *ret; - - ret = kzalloc(sizeof *ret, GFP_KERNEL); - if (!ret) - return NULL; - - ret->com.res_id = id; - ret->com.state = RES_MPT_RESERVED; - ret->key = key; - - return &ret->com; -} - -static struct res_common *alloc_eq_tr(int id) -{ - struct res_eq *ret; - - ret = kzalloc(sizeof *ret, GFP_KERNEL); - if (!ret) - return NULL; - - ret->com.res_id = id; - ret->com.state = RES_EQ_RESERVED; - - return &ret->com; -} - -static struct res_common *alloc_cq_tr(int id) -{ - struct res_cq *ret; - - ret = kzalloc(sizeof *ret, GFP_KERNEL); - if (!ret) - return NULL; - - ret->com.res_id = id; - ret->com.state = RES_CQ_ALLOCATED; - atomic_set(&ret->ref_count, 0); - - return &ret->com; -} - -static struct res_common *alloc_srq_tr(int id) -{ - struct res_srq *ret; - - ret = kzalloc(sizeof *ret, GFP_KERNEL); - if (!ret) - return NULL; - - ret->com.res_id = id; - ret->com.state = RES_SRQ_ALLOCATED; - atomic_set(&ret->ref_count, 0); - - return &ret->com; -} - -static struct res_common *alloc_counter_tr(int id) -{ - struct res_counter *ret; - - ret = kzalloc(sizeof *ret, GFP_KERNEL); - if (!ret) - return NULL; - - ret->com.res_id = id; - ret->com.state = RES_COUNTER_ALLOCATED; - - return &ret->com; -} - -static struct res_common *alloc_tr(int id, enum mlx4_resource type, int slave, - int extra) -{ - struct res_common *ret; - - switch (type) { - case RES_QP: - ret = alloc_qp_tr(id); - break; - case RES_MPT: - ret = alloc_mpt_tr(id, extra); - break; - case RES_MTT: - ret = alloc_mtt_tr(id, extra); - break; - case RES_EQ: - ret = alloc_eq_tr(id); - break; - case RES_CQ: - ret = alloc_cq_tr(id); - break; - case RES_SRQ: - ret = alloc_srq_tr(id); - break; - case RES_MAC: - printk(KERN_ERR "implementation missing\n"); - return NULL; - case RES_COUNTER: - ret = alloc_counter_tr(id); - break; - - default: - return NULL; - } - if (ret) - ret->owner = slave; - - return ret; -} - -static int add_res_range(struct mlx4_dev *dev, int slave, int base, int count, - enum mlx4_resource type, int extra) -{ - int i; - int err; - struct mlx4_priv *priv = mlx4_priv(dev); - struct res_common **res_arr; - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct radix_tree_root *root = &tracker->res_tree[type]; - - res_arr = kzalloc(count * sizeof *res_arr, GFP_KERNEL); - if (!res_arr) - return -ENOMEM; - - for (i = 0; i < count; ++i) { - res_arr[i] = alloc_tr(base + i, type, slave, extra); - if (!res_arr[i]) { - for (--i; i >= 0; --i) - kfree(res_arr[i]); - - kfree(res_arr); - return -ENOMEM; - } - } - - spin_lock_irq(mlx4_tlock(dev)); - for (i = 0; i < count; ++i) { - if (find_res(dev, base + i, type)) { - err = -EEXIST; - goto undo; - } - err = radix_tree_insert(root, base + i, res_arr[i]); - if (err) - goto undo; - list_add_tail(&res_arr[i]->list, - &tracker->slave_list[slave].res_list[type]); - } - spin_unlock_irq(mlx4_tlock(dev)); - kfree(res_arr); - - return 0; - -undo: - for (--i; i >= base; --i) - radix_tree_delete(&tracker->res_tree[type], i); - - spin_unlock_irq(mlx4_tlock(dev)); - - for (i = 0; i < count; ++i) - kfree(res_arr[i]); - - kfree(res_arr); - - return err; -} - -static int remove_qp_ok(struct res_qp *res) -{ - if (res->com.state == RES_QP_BUSY) - return -EBUSY; - else if (res->com.state != RES_QP_RESERVED) - return -EPERM; - - return 0; -} - -static int remove_mtt_ok(struct res_mtt *res, int order) -{ - if (res->com.state == RES_MTT_BUSY || - atomic_read(&res->ref_count)) { - printk(KERN_DEBUG "%s-%d: state %s, ref_count %d\n", - __func__, __LINE__, - mtt_states_str(res->com.state), - atomic_read(&res->ref_count)); - return -EBUSY; - } else if (res->com.state != RES_MTT_ALLOCATED) - return -EPERM; - else if (res->order != order) - return -EINVAL; - - return 0; -} - -static int remove_mpt_ok(struct res_mpt *res) -{ - if (res->com.state == RES_MPT_BUSY) - return -EBUSY; - else if (res->com.state != RES_MPT_RESERVED) - return -EPERM; - - return 0; -} - -static int remove_eq_ok(struct res_eq *res) -{ - if (res->com.state == RES_MPT_BUSY) - return -EBUSY; - else if (res->com.state != RES_MPT_RESERVED) - return -EPERM; - - return 0; -} - -static int remove_counter_ok(struct res_counter *res) -{ - if (res->com.state == RES_COUNTER_BUSY) - return -EBUSY; - else if (res->com.state != RES_COUNTER_ALLOCATED) - return -EPERM; - - return 0; -} - -static int remove_cq_ok(struct res_cq *res) -{ - if (res->com.state == RES_CQ_BUSY) - return -EBUSY; - else if (res->com.state != RES_CQ_ALLOCATED) - return -EPERM; - - return 0; -} - -static int remove_srq_ok(struct res_srq *res) -{ - if (res->com.state == RES_SRQ_BUSY) - return -EBUSY; - else if (res->com.state != RES_SRQ_ALLOCATED) - return -EPERM; - - return 0; -} - -static int remove_ok(struct res_common *res, enum mlx4_resource type, int extra) -{ - switch (type) { - case RES_QP: - return remove_qp_ok((struct res_qp *)res); - case RES_CQ: - return remove_cq_ok((struct res_cq *)res); - case RES_SRQ: - return remove_srq_ok((struct res_srq *)res); - case RES_MPT: - return remove_mpt_ok((struct res_mpt *)res); - case RES_MTT: - return remove_mtt_ok((struct res_mtt *)res, extra); - case RES_MAC: - return -ENOSYS; - case RES_EQ: - return remove_eq_ok((struct res_eq *)res); - case RES_COUNTER: - return remove_counter_ok((struct res_counter *)res); - default: - return -EINVAL; - } -} - -static int rem_res_range(struct mlx4_dev *dev, int slave, int base, int count, - enum mlx4_resource type, int extra) -{ - int i; - int err; - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct res_common *r; - - spin_lock_irq(mlx4_tlock(dev)); - for (i = base; i < base + count; ++i) { - r = radix_tree_lookup(&tracker->res_tree[type], i); - if (!r) { - err = -ENOENT; - goto out; - } - if (r->owner != slave) { - err = -EPERM; - goto out; - } - err = remove_ok(r, type, extra); - if (err) - goto out; - } - - for (i = base; i < base + count; ++i) { - r = radix_tree_lookup(&tracker->res_tree[type], i); - radix_tree_delete(&tracker->res_tree[type], i); - list_del(&r->list); - kfree(r); - } - err = 0; - -out: - spin_unlock_irq(mlx4_tlock(dev)); - - return err; -} - -static int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn, - enum res_qp_states state, struct res_qp **qp, - int alloc) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct res_qp *r; - int err = 0; - - spin_lock_irq(mlx4_tlock(dev)); - r = radix_tree_lookup(&tracker->res_tree[RES_QP], qpn); - if (!r) - err = -ENOENT; - else if (r->com.owner != slave) - err = -EPERM; - else { - switch (state) { - case RES_QP_BUSY: - mlx4_dbg(dev, "%s: failed RES_QP, 0x%x\n", - __func__, r->com.res_id); - err = -EBUSY; - break; - - case RES_QP_RESERVED: - if (r->com.state == RES_QP_MAPPED && !alloc) - break; - - mlx4_dbg(dev, "failed RES_QP, 0x%x\n", r->com.res_id); - err = -EINVAL; - break; - - case RES_QP_MAPPED: - if ((r->com.state == RES_QP_RESERVED && alloc) || - r->com.state == RES_QP_HW) - break; - else { - mlx4_dbg(dev, "failed RES_QP, 0x%x\n", - r->com.res_id); - err = -EINVAL; - } - - break; - - case RES_QP_HW: - if (r->com.state != RES_QP_MAPPED) - err = -EINVAL; - break; - default: - err = -EINVAL; - } - - if (!err) { - r->com.from_state = r->com.state; - r->com.to_state = state; - r->com.state = RES_QP_BUSY; - if (qp) - *qp = (struct res_qp *)r; - } - } - - spin_unlock_irq(mlx4_tlock(dev)); - - return err; -} - -static int mr_res_start_move_to(struct mlx4_dev *dev, int slave, int index, - enum res_mpt_states state, struct res_mpt **mpt) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct res_mpt *r; - int err = 0; - - spin_lock_irq(mlx4_tlock(dev)); - r = radix_tree_lookup(&tracker->res_tree[RES_MPT], index); - if (!r) - err = -ENOENT; - else if (r->com.owner != slave) - err = -EPERM; - else { - switch (state) { - case RES_MPT_BUSY: - err = -EINVAL; - break; - - case RES_MPT_RESERVED: - if (r->com.state != RES_MPT_MAPPED) - err = -EINVAL; - break; - - case RES_MPT_MAPPED: - if (r->com.state != RES_MPT_RESERVED && - r->com.state != RES_MPT_HW) - err = -EINVAL; - break; - - case RES_MPT_HW: - if (r->com.state != RES_MPT_MAPPED) - err = -EINVAL; - break; - default: - err = -EINVAL; - } - - if (!err) { - r->com.from_state = r->com.state; - r->com.to_state = state; - r->com.state = RES_MPT_BUSY; - if (mpt) - *mpt = (struct res_mpt *)r; - } - } - - spin_unlock_irq(mlx4_tlock(dev)); - - return err; -} - -static int eq_res_start_move_to(struct mlx4_dev *dev, int slave, int index, - enum res_eq_states state, struct res_eq **eq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct res_eq *r; - int err = 0; - - spin_lock_irq(mlx4_tlock(dev)); - r = radix_tree_lookup(&tracker->res_tree[RES_EQ], index); - if (!r) - err = -ENOENT; - else if (r->com.owner != slave) - err = -EPERM; - else { - switch (state) { - case RES_EQ_BUSY: - err = -EINVAL; - break; - - case RES_EQ_RESERVED: - if (r->com.state != RES_EQ_HW) - err = -EINVAL; - break; - - case RES_EQ_HW: - if (r->com.state != RES_EQ_RESERVED) - err = -EINVAL; - break; - - default: - err = -EINVAL; - } - - if (!err) { - r->com.from_state = r->com.state; - r->com.to_state = state; - r->com.state = RES_EQ_BUSY; - if (eq) - *eq = r; - } - } - - spin_unlock_irq(mlx4_tlock(dev)); - - return err; -} - -static int cq_res_start_move_to(struct mlx4_dev *dev, int slave, int cqn, - enum res_cq_states state, struct res_cq **cq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct res_cq *r; - int err; - - spin_lock_irq(mlx4_tlock(dev)); - r = radix_tree_lookup(&tracker->res_tree[RES_CQ], cqn); - if (!r) - err = -ENOENT; - else if (r->com.owner != slave) - err = -EPERM; - else { - switch (state) { - case RES_CQ_BUSY: - err = -EBUSY; - break; - - case RES_CQ_ALLOCATED: - if (r->com.state != RES_CQ_HW) - err = -EINVAL; - else if (atomic_read(&r->ref_count)) - err = -EBUSY; - else - err = 0; - break; - - case RES_CQ_HW: - if (r->com.state != RES_CQ_ALLOCATED) - err = -EINVAL; - else - err = 0; - break; - - default: - err = -EINVAL; - } - - if (!err) { - r->com.from_state = r->com.state; - r->com.to_state = state; - r->com.state = RES_CQ_BUSY; - if (cq) - *cq = r; - } - } - - spin_unlock_irq(mlx4_tlock(dev)); - - return err; -} - -static int srq_res_start_move_to(struct mlx4_dev *dev, int slave, int index, - enum res_cq_states state, struct res_srq **srq) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct res_srq *r; - int err = 0; - - spin_lock_irq(mlx4_tlock(dev)); - r = radix_tree_lookup(&tracker->res_tree[RES_SRQ], index); - if (!r) - err = -ENOENT; - else if (r->com.owner != slave) - err = -EPERM; - else { - switch (state) { - case RES_SRQ_BUSY: - err = -EINVAL; - break; - - case RES_SRQ_ALLOCATED: - if (r->com.state != RES_SRQ_HW) - err = -EINVAL; - else if (atomic_read(&r->ref_count)) - err = -EBUSY; - break; - - case RES_SRQ_HW: - if (r->com.state != RES_SRQ_ALLOCATED) - err = -EINVAL; - break; - - default: - err = -EINVAL; - } - - if (!err) { - r->com.from_state = r->com.state; - r->com.to_state = state; - r->com.state = RES_SRQ_BUSY; - if (srq) - *srq = r; - } - } - - spin_unlock_irq(mlx4_tlock(dev)); - - return err; -} - -static void res_abort_move(struct mlx4_dev *dev, int slave, - enum mlx4_resource type, int id) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct res_common *r; - - spin_lock_irq(mlx4_tlock(dev)); - r = radix_tree_lookup(&tracker->res_tree[type], id); - if (r && (r->owner == slave)) - r->state = r->from_state; - spin_unlock_irq(mlx4_tlock(dev)); -} - -static void res_end_move(struct mlx4_dev *dev, int slave, - enum mlx4_resource type, int id) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct res_common *r; - - spin_lock_irq(mlx4_tlock(dev)); - r = radix_tree_lookup(&tracker->res_tree[type], id); - if (r && (r->owner == slave)) - r->state = r->to_state; - spin_unlock_irq(mlx4_tlock(dev)); -} - -static int valid_reserved(struct mlx4_dev *dev, int slave, int qpn) -{ - return mlx4_is_qp_reserved(dev, qpn); -} - -static int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param, u64 *out_param) -{ - int err; - int count; - int align; - int base; - int qpn; - - switch (op) { - case RES_OP_RESERVE: - count = get_param_l(&in_param); - align = get_param_h(&in_param); - err = __mlx4_qp_reserve_range(dev, count, align, &base); - if (err) - return err; - - err = add_res_range(dev, slave, base, count, RES_QP, 0); - if (err) { - __mlx4_qp_release_range(dev, base, count); - return err; - } - set_param_l(out_param, base); - break; - case RES_OP_MAP_ICM: - qpn = get_param_l(&in_param) & 0x7fffff; - if (valid_reserved(dev, slave, qpn)) { - err = add_res_range(dev, slave, qpn, 1, RES_QP, 0); - if (err) - return err; - } - - err = qp_res_start_move_to(dev, slave, qpn, RES_QP_MAPPED, - NULL, 1); - if (err) - return err; - - if (!valid_reserved(dev, slave, qpn)) { - err = __mlx4_qp_alloc_icm(dev, qpn); - if (err) { - res_abort_move(dev, slave, RES_QP, qpn); - return err; - } - } - - res_end_move(dev, slave, RES_QP, qpn); - break; - - default: - err = -EINVAL; - break; - } - return err; -} - -static int mtt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param, u64 *out_param) -{ - int err = -EINVAL; - int base; - int order; - - if (op != RES_OP_RESERVE_AND_MAP) - return err; - - order = get_param_l(&in_param); - base = __mlx4_alloc_mtt_range(dev, order); - if (base == -1) - return -ENOMEM; - - err = add_res_range(dev, slave, base, 1, RES_MTT, order); - if (err) - __mlx4_free_mtt_range(dev, base, order); - else - set_param_l(out_param, base); - - return err; -} - -static int mpt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param, u64 *out_param) -{ - int err = -EINVAL; - int index; - int id; - struct res_mpt *mpt; - - switch (op) { - case RES_OP_RESERVE: - index = __mlx4_mr_reserve(dev); - if (index == -1) - break; - id = index & mpt_mask(dev); - - err = add_res_range(dev, slave, id, 1, RES_MPT, index); - if (err) { - __mlx4_mr_release(dev, index); - break; - } - set_param_l(out_param, index); - break; - case RES_OP_MAP_ICM: - index = get_param_l(&in_param); - id = index & mpt_mask(dev); - err = mr_res_start_move_to(dev, slave, id, - RES_MPT_MAPPED, &mpt); - if (err) - return err; - - err = __mlx4_mr_alloc_icm(dev, mpt->key); - if (err) { - res_abort_move(dev, slave, RES_MPT, id); - return err; - } - - res_end_move(dev, slave, RES_MPT, id); - break; - } - return err; -} - -static int cq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param, u64 *out_param) -{ - int cqn; - int err; - - switch (op) { - case RES_OP_RESERVE_AND_MAP: - err = __mlx4_cq_alloc_icm(dev, &cqn); - if (err) - break; - - err = add_res_range(dev, slave, cqn, 1, RES_CQ, 0); - if (err) { - __mlx4_cq_free_icm(dev, cqn); - break; - } - - set_param_l(out_param, cqn); - break; - - default: - err = -EINVAL; - } - - return err; -} - -static int srq_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param, u64 *out_param) -{ - int srqn; - int err; - - switch (op) { - case RES_OP_RESERVE_AND_MAP: - err = __mlx4_srq_alloc_icm(dev, &srqn); - if (err) - break; - - err = add_res_range(dev, slave, srqn, 1, RES_SRQ, 0); - if (err) { - __mlx4_srq_free_icm(dev, srqn); - break; - } - - set_param_l(out_param, srqn); - break; - - default: - err = -EINVAL; - } - - return err; -} - -static int mac_add_to_slave(struct mlx4_dev *dev, int slave, u64 mac, int port) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct mac_res *res; - - res = kzalloc(sizeof *res, GFP_KERNEL); - if (!res) - return -ENOMEM; - res->mac = mac; - res->port = (u8) port; - list_add_tail(&res->list, - &tracker->slave_list[slave].res_list[RES_MAC]); - return 0; -} - -static void mac_del_from_slave(struct mlx4_dev *dev, int slave, u64 mac, - int port) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct list_head *mac_list = - &tracker->slave_list[slave].res_list[RES_MAC]; - struct mac_res *res, *tmp; - - list_for_each_entry_safe(res, tmp, mac_list, list) { - if (res->mac == mac && res->port == (u8) port) { - list_del(&res->list); - kfree(res); - break; - } - } -} - -static void rem_slave_macs(struct mlx4_dev *dev, int slave) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct list_head *mac_list = - &tracker->slave_list[slave].res_list[RES_MAC]; - struct mac_res *res, *tmp; - - list_for_each_entry_safe(res, tmp, mac_list, list) { - list_del(&res->list); - __mlx4_unregister_mac(dev, res->port, res->mac); - kfree(res); - } -} - -static int mac_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param, u64 *out_param) -{ - int err = -EINVAL; - int port; - u64 mac; - - if (op != RES_OP_RESERVE_AND_MAP) - return err; - - port = get_param_l(out_param); - mac = in_param; - - err = __mlx4_register_mac(dev, port, mac); - if (err >= 0) { - set_param_l(out_param, err); - err = 0; - } - - if (!err) { - err = mac_add_to_slave(dev, slave, mac, port); - if (err) - __mlx4_unregister_mac(dev, port, mac); - } - return err; -} - -static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param, u64 *out_param) -{ - return 0; -} - -int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int alop = vhcr->op_modifier; - - switch (vhcr->in_modifier) { - case RES_QP: - err = qp_alloc_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param, &vhcr->out_param); - break; - - case RES_MTT: - err = mtt_alloc_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param, &vhcr->out_param); - break; - - case RES_MPT: - err = mpt_alloc_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param, &vhcr->out_param); - break; - - case RES_CQ: - err = cq_alloc_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param, &vhcr->out_param); - break; - - case RES_SRQ: - err = srq_alloc_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param, &vhcr->out_param); - break; - - case RES_MAC: - err = mac_alloc_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param, &vhcr->out_param); - break; - - case RES_VLAN: - err = vlan_alloc_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param, &vhcr->out_param); - break; - - default: - err = -EINVAL; - break; - } - - return err; -} - -static int qp_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param) -{ - int err; - int count; - int base; - int qpn; - - switch (op) { - case RES_OP_RESERVE: - base = get_param_l(&in_param) & 0x7fffff; - count = get_param_h(&in_param); - err = rem_res_range(dev, slave, base, count, RES_QP, 0); - if (err) - break; - __mlx4_qp_release_range(dev, base, count); - break; - case RES_OP_MAP_ICM: - qpn = get_param_l(&in_param) & 0x7fffff; - err = qp_res_start_move_to(dev, slave, qpn, RES_QP_RESERVED, - NULL, 0); - if (err) - return err; - - if (!valid_reserved(dev, slave, qpn)) - __mlx4_qp_free_icm(dev, qpn); - - res_end_move(dev, slave, RES_QP, qpn); - - if (valid_reserved(dev, slave, qpn)) - err = rem_res_range(dev, slave, qpn, 1, RES_QP, 0); - break; - default: - err = -EINVAL; - break; - } - return err; -} - -static int mtt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param, u64 *out_param) -{ - int err = -EINVAL; - int base; - int order; - - if (op != RES_OP_RESERVE_AND_MAP) - return err; - - base = get_param_l(&in_param); - order = get_param_h(&in_param); - err = rem_res_range(dev, slave, base, 1, RES_MTT, order); - if (!err) - __mlx4_free_mtt_range(dev, base, order); - return err; -} - -static int mpt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param) -{ - int err = -EINVAL; - int index; - int id; - struct res_mpt *mpt; - - switch (op) { - case RES_OP_RESERVE: - index = get_param_l(&in_param); - id = index & mpt_mask(dev); - err = get_res(dev, slave, id, RES_MPT, &mpt); - if (err) - break; - index = mpt->key; - put_res(dev, slave, id, RES_MPT); - - err = rem_res_range(dev, slave, id, 1, RES_MPT, 0); - if (err) - break; - __mlx4_mr_release(dev, index); - break; - case RES_OP_MAP_ICM: - index = get_param_l(&in_param); - id = index & mpt_mask(dev); - err = mr_res_start_move_to(dev, slave, id, - RES_MPT_RESERVED, &mpt); - if (err) - return err; - - __mlx4_mr_free_icm(dev, mpt->key); - res_end_move(dev, slave, RES_MPT, id); - return err; - break; - default: - err = -EINVAL; - break; - } - return err; -} - -static int cq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param, u64 *out_param) -{ - int cqn; - int err; - - switch (op) { - case RES_OP_RESERVE_AND_MAP: - cqn = get_param_l(&in_param); - err = rem_res_range(dev, slave, cqn, 1, RES_CQ, 0); - if (err) - break; - - __mlx4_cq_free_icm(dev, cqn); - break; - - default: - err = -EINVAL; - break; - } - - return err; -} - -static int srq_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param, u64 *out_param) -{ - int srqn; - int err; - - switch (op) { - case RES_OP_RESERVE_AND_MAP: - srqn = get_param_l(&in_param); - err = rem_res_range(dev, slave, srqn, 1, RES_SRQ, 0); - if (err) - break; - - __mlx4_srq_free_icm(dev, srqn); - break; - - default: - err = -EINVAL; - break; - } - - return err; -} - -static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param, u64 *out_param) -{ - int port; - int err = 0; - - switch (op) { - case RES_OP_RESERVE_AND_MAP: - port = get_param_l(out_param); - mac_del_from_slave(dev, slave, in_param, port); - __mlx4_unregister_mac(dev, port, in_param); - break; - default: - err = -EINVAL; - break; - } - - return err; - -} - -static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd, - u64 in_param, u64 *out_param) -{ - return 0; -} - -int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err = -EINVAL; - int alop = vhcr->op_modifier; - - switch (vhcr->in_modifier) { - case RES_QP: - err = qp_free_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param); - break; - - case RES_MTT: - err = mtt_free_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param, &vhcr->out_param); - break; - - case RES_MPT: - err = mpt_free_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param); - break; - - case RES_CQ: - err = cq_free_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param, &vhcr->out_param); - break; - - case RES_SRQ: - err = srq_free_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param, &vhcr->out_param); - break; - - case RES_MAC: - err = mac_free_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param, &vhcr->out_param); - break; - - case RES_VLAN: - err = vlan_free_res(dev, slave, vhcr->op_modifier, alop, - vhcr->in_param, &vhcr->out_param); - break; - - default: - break; - } - return err; -} - -/* ugly but other choices are uglier */ -static int mr_phys_mpt(struct mlx4_mpt_entry *mpt) -{ - return (be32_to_cpu(mpt->flags) >> 9) & 1; -} - -static int mr_get_mtt_addr(struct mlx4_mpt_entry *mpt) -{ - return (int)be64_to_cpu(mpt->mtt_addr) & 0xfffffff8; -} - -static int mr_get_mtt_size(struct mlx4_mpt_entry *mpt) -{ - return be32_to_cpu(mpt->mtt_sz); -} - -static int mr_get_pdn(struct mlx4_mpt_entry *mpt) -{ - return be32_to_cpu(mpt->pd_flags) & 0xffffff; -} - -static int qp_get_mtt_addr(struct mlx4_qp_context *qpc) -{ - return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8; -} - -static int srq_get_mtt_addr(struct mlx4_srq_context *srqc) -{ - return be32_to_cpu(srqc->mtt_base_addr_l) & 0xfffffff8; -} - -static int qp_get_mtt_size(struct mlx4_qp_context *qpc) -{ - int page_shift = (qpc->log_page_size & 0x3f) + 12; - int log_sq_size = (qpc->sq_size_stride >> 3) & 0xf; - int log_sq_sride = qpc->sq_size_stride & 7; - int log_rq_size = (qpc->rq_size_stride >> 3) & 0xf; - int log_rq_stride = qpc->rq_size_stride & 7; - int srq = (be32_to_cpu(qpc->srqn) >> 24) & 1; - int rss = (be32_to_cpu(qpc->flags) >> 13) & 1; - int xrc = (be32_to_cpu(qpc->local_qpn) >> 23) & 1; - int sq_size; - int rq_size; - int total_pages; - int total_mem; - int page_offset = (be32_to_cpu(qpc->params2) >> 6) & 0x3f; - - sq_size = 1 << (log_sq_size + log_sq_sride + 4); - rq_size = (srq|rss|xrc) ? 0 : (1 << (log_rq_size + log_rq_stride + 4)); - total_mem = sq_size + rq_size; - total_pages = - roundup_pow_of_two((total_mem + (page_offset << 6)) >> - page_shift); - - return total_pages; -} - -static int qp_get_pdn(struct mlx4_qp_context *qpc) -{ - return be32_to_cpu(qpc->pd) & 0xffffff; -} - -static int pdn2slave(int pdn) -{ - return (pdn >> NOT_MASKED_PD_BITS) - 1; -} - -static int check_mtt_range(struct mlx4_dev *dev, int slave, int start, - int size, struct res_mtt *mtt) -{ - int res_start = mtt->com.res_id; - int res_size = (1 << mtt->order); - - if (start < res_start || start + size > res_start + res_size) - return -EPERM; - return 0; -} - -int mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int index = vhcr->in_modifier; - struct res_mtt *mtt; - struct res_mpt *mpt; - int mtt_base = mr_get_mtt_addr(inbox->buf) / dev->caps.mtt_entry_sz; - int phys; - int id; - - id = index & mpt_mask(dev); - err = mr_res_start_move_to(dev, slave, id, RES_MPT_HW, &mpt); - if (err) - return err; - - phys = mr_phys_mpt(inbox->buf); - if (!phys) { - err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); - if (err) - goto ex_abort; - - err = check_mtt_range(dev, slave, mtt_base, - mr_get_mtt_size(inbox->buf), mtt); - if (err) - goto ex_put; - - mpt->mtt = mtt; - } - - if (pdn2slave(mr_get_pdn(inbox->buf)) != slave) { - err = -EPERM; - goto ex_put; - } - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - if (err) - goto ex_put; - - if (!phys) { - atomic_inc(&mtt->ref_count); - put_res(dev, slave, mtt->com.res_id, RES_MTT); - } - - res_end_move(dev, slave, RES_MPT, id); - return 0; - -ex_put: - if (!phys) - put_res(dev, slave, mtt->com.res_id, RES_MTT); -ex_abort: - res_abort_move(dev, slave, RES_MPT, id); - - return err; -} - -int mlx4_HW2SW_MPT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int index = vhcr->in_modifier; - struct res_mpt *mpt; - int id; - - id = index & mpt_mask(dev); - err = mr_res_start_move_to(dev, slave, id, RES_MPT_MAPPED, &mpt); - if (err) - return err; - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - if (err) - goto ex_abort; - - if (mpt->mtt) - atomic_dec(&mpt->mtt->ref_count); - - res_end_move(dev, slave, RES_MPT, id); - return 0; - -ex_abort: - res_abort_move(dev, slave, RES_MPT, id); - - return err; -} - -int mlx4_QUERY_MPT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int index = vhcr->in_modifier; - struct res_mpt *mpt; - int id; - - id = index & mpt_mask(dev); - err = get_res(dev, slave, id, RES_MPT, &mpt); - if (err) - return err; - - if (mpt->com.from_state != RES_MPT_HW) { - err = -EBUSY; - goto out; - } - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - -out: - put_res(dev, slave, id, RES_MPT); - return err; -} - -static int qp_get_rcqn(struct mlx4_qp_context *qpc) -{ - return be32_to_cpu(qpc->cqn_recv) & 0xffffff; -} - -static int qp_get_scqn(struct mlx4_qp_context *qpc) -{ - return be32_to_cpu(qpc->cqn_send) & 0xffffff; -} - -static u32 qp_get_srqn(struct mlx4_qp_context *qpc) -{ - return be32_to_cpu(qpc->srqn) & 0x1ffffff; -} - -int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int qpn = vhcr->in_modifier & 0x7fffff; - struct res_mtt *mtt; - struct res_qp *qp; - struct mlx4_qp_context *qpc = inbox->buf + 8; - int mtt_base = qp_get_mtt_addr(qpc) / dev->caps.mtt_entry_sz; - int mtt_size = qp_get_mtt_size(qpc); - struct res_cq *rcq; - struct res_cq *scq; - int rcqn = qp_get_rcqn(qpc); - int scqn = qp_get_scqn(qpc); - u32 srqn = qp_get_srqn(qpc) & 0xffffff; - int use_srq = (qp_get_srqn(qpc) >> 24) & 1; - struct res_srq *srq; - int local_qpn = be32_to_cpu(qpc->local_qpn) & 0xffffff; - - err = qp_res_start_move_to(dev, slave, qpn, RES_QP_HW, &qp, 0); - if (err) - return err; - qp->local_qpn = local_qpn; - - err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); - if (err) - goto ex_abort; - - err = check_mtt_range(dev, slave, mtt_base, mtt_size, mtt); - if (err) - goto ex_put_mtt; - - if (pdn2slave(qp_get_pdn(qpc)) != slave) { - err = -EPERM; - goto ex_put_mtt; - } - - err = get_res(dev, slave, rcqn, RES_CQ, &rcq); - if (err) - goto ex_put_mtt; - - if (scqn != rcqn) { - err = get_res(dev, slave, scqn, RES_CQ, &scq); - if (err) - goto ex_put_rcq; - } else - scq = rcq; - - if (use_srq) { - err = get_res(dev, slave, srqn, RES_SRQ, &srq); - if (err) - goto ex_put_scq; - } - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - if (err) - goto ex_put_srq; - atomic_inc(&mtt->ref_count); - qp->mtt = mtt; - atomic_inc(&rcq->ref_count); - qp->rcq = rcq; - atomic_inc(&scq->ref_count); - qp->scq = scq; - - if (scqn != rcqn) - put_res(dev, slave, scqn, RES_CQ); - - if (use_srq) { - atomic_inc(&srq->ref_count); - put_res(dev, slave, srqn, RES_SRQ); - qp->srq = srq; - } - put_res(dev, slave, rcqn, RES_CQ); - put_res(dev, slave, mtt_base, RES_MTT); - res_end_move(dev, slave, RES_QP, qpn); - - return 0; - -ex_put_srq: - if (use_srq) - put_res(dev, slave, srqn, RES_SRQ); -ex_put_scq: - if (scqn != rcqn) - put_res(dev, slave, scqn, RES_CQ); -ex_put_rcq: - put_res(dev, slave, rcqn, RES_CQ); -ex_put_mtt: - put_res(dev, slave, mtt_base, RES_MTT); -ex_abort: - res_abort_move(dev, slave, RES_QP, qpn); - - return err; -} - -static int eq_get_mtt_addr(struct mlx4_eq_context *eqc) -{ - return be32_to_cpu(eqc->mtt_base_addr_l) & 0xfffffff8; -} - -static int eq_get_mtt_size(struct mlx4_eq_context *eqc) -{ - int log_eq_size = eqc->log_eq_size & 0x1f; - int page_shift = (eqc->log_page_size & 0x3f) + 12; - - if (log_eq_size + 5 < page_shift) - return 1; - - return 1 << (log_eq_size + 5 - page_shift); -} - -static int cq_get_mtt_addr(struct mlx4_cq_context *cqc) -{ - return be32_to_cpu(cqc->mtt_base_addr_l) & 0xfffffff8; -} - -static int cq_get_mtt_size(struct mlx4_cq_context *cqc) -{ - int log_cq_size = (be32_to_cpu(cqc->logsize_usrpage) >> 24) & 0x1f; - int page_shift = (cqc->log_page_size & 0x3f) + 12; - - if (log_cq_size + 5 < page_shift) - return 1; - - return 1 << (log_cq_size + 5 - page_shift); -} - -int mlx4_SW2HW_EQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int eqn = vhcr->in_modifier; - int res_id = (slave << 8) | eqn; - struct mlx4_eq_context *eqc = inbox->buf; - int mtt_base = eq_get_mtt_addr(eqc) / dev->caps.mtt_entry_sz; - int mtt_size = eq_get_mtt_size(eqc); - struct res_eq *eq; - struct res_mtt *mtt; - - err = add_res_range(dev, slave, res_id, 1, RES_EQ, 0); - if (err) - return err; - err = eq_res_start_move_to(dev, slave, res_id, RES_EQ_HW, &eq); - if (err) - goto out_add; - - err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); - if (err) - goto out_move; - - err = check_mtt_range(dev, slave, mtt_base, mtt_size, mtt); - if (err) - goto out_put; - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - if (err) - goto out_put; - - atomic_inc(&mtt->ref_count); - eq->mtt = mtt; - put_res(dev, slave, mtt->com.res_id, RES_MTT); - res_end_move(dev, slave, RES_EQ, res_id); - return 0; - -out_put: - put_res(dev, slave, mtt->com.res_id, RES_MTT); -out_move: - res_abort_move(dev, slave, RES_EQ, res_id); -out_add: - rem_res_range(dev, slave, res_id, 1, RES_EQ, 0); - return err; -} - -static int get_containing_mtt(struct mlx4_dev *dev, int slave, int start, - int len, struct res_mtt **res) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct res_mtt *mtt; - int err = -EINVAL; - - spin_lock_irq(mlx4_tlock(dev)); - list_for_each_entry(mtt, &tracker->slave_list[slave].res_list[RES_MTT], - com.list) { - if (!check_mtt_range(dev, slave, start, len, mtt)) { - *res = mtt; - mtt->com.from_state = mtt->com.state; - mtt->com.state = RES_MTT_BUSY; - err = 0; - break; - } - } - spin_unlock_irq(mlx4_tlock(dev)); - - return err; -} - -int mlx4_WRITE_MTT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - struct mlx4_mtt mtt; - __be64 *page_list = inbox->buf; - u64 *pg_list = (u64 *)page_list; - int i; - struct res_mtt *rmtt = NULL; - int start = be64_to_cpu(page_list[0]); - int npages = vhcr->in_modifier; - int err; - - err = get_containing_mtt(dev, slave, start, npages, &rmtt); - if (err) - return err; - - /* Call the SW implementation of write_mtt: - * - Prepare a dummy mtt struct - * - Translate inbox contents to simple addresses in host endianess */ - mtt.offset = 0; /* TBD this is broken but I don't handle it since - we don't really use it */ - mtt.order = 0; - mtt.page_shift = 0; - for (i = 0; i < npages; ++i) - pg_list[i + 2] = (be64_to_cpu(page_list[i + 2]) & ~1ULL); - - err = __mlx4_write_mtt(dev, &mtt, be64_to_cpu(page_list[0]), npages, - ((u64 *)page_list + 2)); - - if (rmtt) - put_res(dev, slave, rmtt->com.res_id, RES_MTT); - - return err; -} - -int mlx4_HW2SW_EQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int eqn = vhcr->in_modifier; - int res_id = eqn | (slave << 8); - struct res_eq *eq; - int err; - - err = eq_res_start_move_to(dev, slave, res_id, RES_EQ_RESERVED, &eq); - if (err) - return err; - - err = get_res(dev, slave, eq->mtt->com.res_id, RES_MTT, NULL); - if (err) - goto ex_abort; - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - if (err) - goto ex_put; - - atomic_dec(&eq->mtt->ref_count); - put_res(dev, slave, eq->mtt->com.res_id, RES_MTT); - res_end_move(dev, slave, RES_EQ, res_id); - rem_res_range(dev, slave, res_id, 1, RES_EQ, 0); - - return 0; - -ex_put: - put_res(dev, slave, eq->mtt->com.res_id, RES_MTT); -ex_abort: - res_abort_move(dev, slave, RES_EQ, res_id); - - return err; -} - -int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_slave_event_eq_info *event_eq; - struct mlx4_cmd_mailbox *mailbox; - u32 in_modifier = 0; - int err; - int res_id; - struct res_eq *req; - - if (!priv->mfunc.master.slave_state) - return -EINVAL; - - event_eq = &priv->mfunc.master.slave_state[slave].event_eq; - - /* Create the event only if the slave is registered */ - if ((event_eq->event_type & (1 << eqe->type)) == 0) - return 0; - - mutex_lock(&priv->mfunc.master.gen_eqe_mutex[slave]); - res_id = (slave << 8) | event_eq->eqn; - err = get_res(dev, slave, res_id, RES_EQ, &req); - if (err) - goto unlock; - - if (req->com.from_state != RES_EQ_HW) { - err = -EINVAL; - goto put; - } - - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) { - err = PTR_ERR(mailbox); - goto put; - } - - if (eqe->type == MLX4_EVENT_TYPE_CMD) { - ++event_eq->token; - eqe->event.cmd.token = cpu_to_be16(event_eq->token); - } - - memcpy(mailbox->buf, (u8 *) eqe, 28); - - in_modifier = (slave & 0xff) | ((event_eq->eqn & 0xff) << 16); - - err = mlx4_cmd(dev, mailbox->dma, in_modifier, 0, - MLX4_CMD_GEN_EQE, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_NATIVE); - - put_res(dev, slave, res_id, RES_EQ); - mutex_unlock(&priv->mfunc.master.gen_eqe_mutex[slave]); - mlx4_free_cmd_mailbox(dev, mailbox); - return err; - -put: - put_res(dev, slave, res_id, RES_EQ); - -unlock: - mutex_unlock(&priv->mfunc.master.gen_eqe_mutex[slave]); - return err; -} - -int mlx4_QUERY_EQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int eqn = vhcr->in_modifier; - int res_id = eqn | (slave << 8); - struct res_eq *eq; - int err; - - err = get_res(dev, slave, res_id, RES_EQ, &eq); - if (err) - return err; - - if (eq->com.from_state != RES_EQ_HW) { - err = -EINVAL; - goto ex_put; - } - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - -ex_put: - put_res(dev, slave, res_id, RES_EQ); - return err; -} - -int mlx4_SW2HW_CQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int cqn = vhcr->in_modifier; - struct mlx4_cq_context *cqc = inbox->buf; - int mtt_base = cq_get_mtt_addr(cqc) / dev->caps.mtt_entry_sz; - struct res_cq *cq; - struct res_mtt *mtt; - - err = cq_res_start_move_to(dev, slave, cqn, RES_CQ_HW, &cq); - if (err) - return err; - err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); - if (err) - goto out_move; - err = check_mtt_range(dev, slave, mtt_base, cq_get_mtt_size(cqc), mtt); - if (err) - goto out_put; - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - if (err) - goto out_put; - atomic_inc(&mtt->ref_count); - cq->mtt = mtt; - put_res(dev, slave, mtt->com.res_id, RES_MTT); - res_end_move(dev, slave, RES_CQ, cqn); - return 0; - -out_put: - put_res(dev, slave, mtt->com.res_id, RES_MTT); -out_move: - res_abort_move(dev, slave, RES_CQ, cqn); - return err; -} - -int mlx4_HW2SW_CQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int cqn = vhcr->in_modifier; - struct res_cq *cq; - - err = cq_res_start_move_to(dev, slave, cqn, RES_CQ_ALLOCATED, &cq); - if (err) - return err; - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - if (err) - goto out_move; - atomic_dec(&cq->mtt->ref_count); - res_end_move(dev, slave, RES_CQ, cqn); - return 0; - -out_move: - res_abort_move(dev, slave, RES_CQ, cqn); - return err; -} - -int mlx4_QUERY_CQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int cqn = vhcr->in_modifier; - struct res_cq *cq; - int err; - - err = get_res(dev, slave, cqn, RES_CQ, &cq); - if (err) - return err; - - if (cq->com.from_state != RES_CQ_HW) - goto ex_put; - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); -ex_put: - put_res(dev, slave, cqn, RES_CQ); - - return err; -} - -static int handle_resize(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd, - struct res_cq *cq) -{ - int err; - struct res_mtt *orig_mtt; - struct res_mtt *mtt; - struct mlx4_cq_context *cqc = inbox->buf; - int mtt_base = cq_get_mtt_addr(cqc) / dev->caps.mtt_entry_sz; - - err = get_res(dev, slave, cq->mtt->com.res_id, RES_MTT, &orig_mtt); - if (err) - return err; - - if (orig_mtt != cq->mtt) { - err = -EINVAL; - goto ex_put; - } - - err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); - if (err) - goto ex_put; - - err = check_mtt_range(dev, slave, mtt_base, cq_get_mtt_size(cqc), mtt); - if (err) - goto ex_put1; - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - if (err) - goto ex_put1; - atomic_dec(&orig_mtt->ref_count); - put_res(dev, slave, orig_mtt->com.res_id, RES_MTT); - atomic_inc(&mtt->ref_count); - cq->mtt = mtt; - put_res(dev, slave, mtt->com.res_id, RES_MTT); - return 0; - -ex_put1: - put_res(dev, slave, mtt->com.res_id, RES_MTT); -ex_put: - put_res(dev, slave, orig_mtt->com.res_id, RES_MTT); - - return err; - -} - -int mlx4_MODIFY_CQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int cqn = vhcr->in_modifier; - struct res_cq *cq; - int err; - - err = get_res(dev, slave, cqn, RES_CQ, &cq); - if (err) - return err; - - if (cq->com.from_state != RES_CQ_HW) - goto ex_put; - - if (vhcr->op_modifier == 0) { - err = handle_resize(dev, slave, vhcr, inbox, outbox, cmd, cq); - if (err) - goto ex_put; - } - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); -ex_put: - put_res(dev, slave, cqn, RES_CQ); - - return err; -} - -static int srq_get_pdn(struct mlx4_srq_context *srqc) -{ - return be32_to_cpu(srqc->pd) & 0xffffff; -} - -static int srq_get_mtt_size(struct mlx4_srq_context *srqc) -{ - int log_srq_size = (be32_to_cpu(srqc->state_logsize_srqn) >> 24) & 0xf; - int log_rq_stride = srqc->logstride & 7; - int page_shift = (srqc->log_page_size & 0x3f) + 12; - - if (log_srq_size + log_rq_stride + 4 < page_shift) - return 1; - - return 1 << (log_srq_size + log_rq_stride + 4 - page_shift); -} - -int mlx4_SW2HW_SRQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int srqn = vhcr->in_modifier; - struct res_mtt *mtt; - struct res_srq *srq; - struct mlx4_srq_context *srqc = inbox->buf; - int mtt_base = srq_get_mtt_addr(srqc) / dev->caps.mtt_entry_sz; - - if (srqn != (be32_to_cpu(srqc->state_logsize_srqn) & 0xffffff)) - return -EINVAL; - - err = srq_res_start_move_to(dev, slave, srqn, RES_SRQ_HW, &srq); - if (err) - return err; - err = get_res(dev, slave, mtt_base, RES_MTT, &mtt); - if (err) - goto ex_abort; - err = check_mtt_range(dev, slave, mtt_base, srq_get_mtt_size(srqc), - mtt); - if (err) - goto ex_put_mtt; - - if (pdn2slave(srq_get_pdn(srqc)) != slave) { - err = -EPERM; - goto ex_put_mtt; - } - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - if (err) - goto ex_put_mtt; - - atomic_inc(&mtt->ref_count); - srq->mtt = mtt; - put_res(dev, slave, mtt->com.res_id, RES_MTT); - res_end_move(dev, slave, RES_SRQ, srqn); - return 0; - -ex_put_mtt: - put_res(dev, slave, mtt->com.res_id, RES_MTT); -ex_abort: - res_abort_move(dev, slave, RES_SRQ, srqn); - - return err; -} - -int mlx4_HW2SW_SRQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int srqn = vhcr->in_modifier; - struct res_srq *srq; - - err = srq_res_start_move_to(dev, slave, srqn, RES_SRQ_ALLOCATED, &srq); - if (err) - return err; - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - if (err) - goto ex_abort; - atomic_dec(&srq->mtt->ref_count); - if (srq->cq) - atomic_dec(&srq->cq->ref_count); - res_end_move(dev, slave, RES_SRQ, srqn); - - return 0; - -ex_abort: - res_abort_move(dev, slave, RES_SRQ, srqn); - - return err; -} - -int mlx4_QUERY_SRQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int srqn = vhcr->in_modifier; - struct res_srq *srq; - - err = get_res(dev, slave, srqn, RES_SRQ, &srq); - if (err) - return err; - if (srq->com.from_state != RES_SRQ_HW) { - err = -EBUSY; - goto out; - } - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); -out: - put_res(dev, slave, srqn, RES_SRQ); - return err; -} - -int mlx4_ARM_SRQ_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int srqn = vhcr->in_modifier; - struct res_srq *srq; - - err = get_res(dev, slave, srqn, RES_SRQ, &srq); - if (err) - return err; - - if (srq->com.from_state != RES_SRQ_HW) { - err = -EBUSY; - goto out; - } - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); -out: - put_res(dev, slave, srqn, RES_SRQ); - return err; -} - -int mlx4_GEN_QP_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int qpn = vhcr->in_modifier & 0x7fffff; - struct res_qp *qp; - - err = get_res(dev, slave, qpn, RES_QP, &qp); - if (err) - return err; - if (qp->com.from_state != RES_QP_HW) { - err = -EBUSY; - goto out; - } - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); -out: - put_res(dev, slave, qpn, RES_QP); - return err; -} - -int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - struct mlx4_qp_context *qpc = inbox->buf + 8; - - update_ud_gid(dev, qpc, (u8)slave); - - return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd); -} - -int mlx4_2RST_QP_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int qpn = vhcr->in_modifier & 0x7fffff; - struct res_qp *qp; - - err = qp_res_start_move_to(dev, slave, qpn, RES_QP_MAPPED, &qp, 0); - if (err) - return err; - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - if (err) - goto ex_abort; - - atomic_dec(&qp->mtt->ref_count); - atomic_dec(&qp->rcq->ref_count); - atomic_dec(&qp->scq->ref_count); - if (qp->srq) - atomic_dec(&qp->srq->ref_count); - res_end_move(dev, slave, RES_QP, qpn); - return 0; - -ex_abort: - res_abort_move(dev, slave, RES_QP, qpn); - - return err; -} - -static struct res_gid *find_gid(struct mlx4_dev *dev, int slave, - struct res_qp *rqp, u8 *gid) -{ - struct res_gid *res; - - list_for_each_entry(res, &rqp->mcg_list, list) { - if (!memcmp(res->gid, gid, 16)) - return res; - } - return NULL; -} - -static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp, - u8 *gid, enum mlx4_protocol prot) -{ - struct res_gid *res; - int err; - - res = kzalloc(sizeof *res, GFP_KERNEL); - if (!res) - return -ENOMEM; - - spin_lock_irq(&rqp->mcg_spl); - if (find_gid(dev, slave, rqp, gid)) { - kfree(res); - err = -EEXIST; - } else { - memcpy(res->gid, gid, 16); - res->prot = prot; - list_add_tail(&res->list, &rqp->mcg_list); - err = 0; - } - spin_unlock_irq(&rqp->mcg_spl); - - return err; -} - -static int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp, - u8 *gid, enum mlx4_protocol prot) -{ - struct res_gid *res; - int err; - - spin_lock_irq(&rqp->mcg_spl); - res = find_gid(dev, slave, rqp, gid); - if (!res || res->prot != prot) - err = -EINVAL; - else { - list_del(&res->list); - kfree(res); - err = 0; - } - spin_unlock_irq(&rqp->mcg_spl); - - return err; -} - -int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - struct mlx4_qp qp; /* dummy for calling attach/detach */ - u8 *gid = inbox->buf; - enum mlx4_protocol prot = (vhcr->in_modifier >> 28) & 0x7; - int err, err1; - int qpn; - struct res_qp *rqp; - int attach = vhcr->op_modifier; - int block_loopback = vhcr->in_modifier >> 31; - u8 steer_type_mask = 2; - enum mlx4_steer_type type = gid[7] & steer_type_mask; - - qpn = vhcr->in_modifier & 0xffffff; - err = get_res(dev, slave, qpn, RES_QP, &rqp); - if (err) - return err; - - qp.qpn = qpn; - if (attach) { - err = add_mcg_res(dev, slave, rqp, gid, prot); - if (err) - goto ex_put; - - err = mlx4_qp_attach_common(dev, &qp, gid, - block_loopback, prot, type); - if (err) - goto ex_rem; - } else { - err = rem_mcg_res(dev, slave, rqp, gid, prot); - if (err) - goto ex_put; - err = mlx4_qp_detach_common(dev, &qp, gid, prot, type); - } - - put_res(dev, slave, qpn, RES_QP); - return 0; - -ex_rem: - /* ignore error return below, already in error */ - err1 = rem_mcg_res(dev, slave, rqp, gid, prot); -ex_put: - put_res(dev, slave, qpn, RES_QP); - - return err; -} - -enum { - BUSY_MAX_RETRIES = 10 -}; - -int mlx4_QUERY_IF_STAT_wrapper(struct mlx4_dev *dev, int slave, - struct mlx4_vhcr *vhcr, - struct mlx4_cmd_mailbox *inbox, - struct mlx4_cmd_mailbox *outbox, - struct mlx4_cmd_info *cmd) -{ - int err; - int index = vhcr->in_modifier & 0xffff; - - err = get_res(dev, slave, index, RES_COUNTER, NULL); - if (err) - return err; - - err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd); - put_res(dev, slave, index, RES_COUNTER); - return err; -} - -static void detach_qp(struct mlx4_dev *dev, int slave, struct res_qp *rqp) -{ - struct res_gid *rgid; - struct res_gid *tmp; - int err; - struct mlx4_qp qp; /* dummy for calling attach/detach */ - - list_for_each_entry_safe(rgid, tmp, &rqp->mcg_list, list) { - qp.qpn = rqp->local_qpn; - err = mlx4_qp_detach_common(dev, &qp, rgid->gid, rgid->prot, - MLX4_MC_STEER); - list_del(&rgid->list); - kfree(rgid); - } -} - -static int _move_all_busy(struct mlx4_dev *dev, int slave, - enum mlx4_resource type, int print) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = - &priv->mfunc.master.res_tracker; - struct list_head *rlist = &tracker->slave_list[slave].res_list[type]; - struct res_common *r; - struct res_common *tmp; - int busy; - - busy = 0; - spin_lock_irq(mlx4_tlock(dev)); - list_for_each_entry_safe(r, tmp, rlist, list) { - if (r->owner == slave) { - if (!r->removing) { - if (r->state == RES_ANY_BUSY) { - if (print) - mlx4_dbg(dev, - "%s id 0x%x is busy\n", - ResourceType(type), - r->res_id); - ++busy; - } else { - r->from_state = r->state; - r->state = RES_ANY_BUSY; - r->removing = 1; - } - } - } - } - spin_unlock_irq(mlx4_tlock(dev)); - - return busy; -} - -static int move_all_busy(struct mlx4_dev *dev, int slave, - enum mlx4_resource type) -{ - unsigned long begin; - int busy; - - begin = jiffies; - do { - busy = _move_all_busy(dev, slave, type, 0); - if (time_after(jiffies, begin + 5 * HZ)) - break; - if (busy) - cond_resched(); - } while (busy); - - if (busy) - busy = _move_all_busy(dev, slave, type, 1); - - return busy; -} -static void rem_slave_qps(struct mlx4_dev *dev, int slave) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct list_head *qp_list = - &tracker->slave_list[slave].res_list[RES_QP]; - struct res_qp *qp; - struct res_qp *tmp; - int state; - u64 in_param; - int qpn; - int err; - - err = move_all_busy(dev, slave, RES_QP); - if (err) - mlx4_warn(dev, "rem_slave_qps: Could not move all qps to busy" - "for slave %d\n", slave); - - spin_lock_irq(mlx4_tlock(dev)); - list_for_each_entry_safe(qp, tmp, qp_list, com.list) { - spin_unlock_irq(mlx4_tlock(dev)); - if (qp->com.owner == slave) { - qpn = qp->com.res_id; - detach_qp(dev, slave, qp); - state = qp->com.from_state; - while (state != 0) { - switch (state) { - case RES_QP_RESERVED: - spin_lock_irq(mlx4_tlock(dev)); - radix_tree_delete(&tracker->res_tree[RES_QP], - qp->com.res_id); - list_del(&qp->com.list); - spin_unlock_irq(mlx4_tlock(dev)); - kfree(qp); - state = 0; - break; - case RES_QP_MAPPED: - if (!valid_reserved(dev, slave, qpn)) - __mlx4_qp_free_icm(dev, qpn); - state = RES_QP_RESERVED; - break; - case RES_QP_HW: - in_param = slave; - err = mlx4_cmd(dev, in_param, - qp->local_qpn, 2, - MLX4_CMD_2RST_QP, - MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); - if (err) - mlx4_dbg(dev, "rem_slave_qps: failed" - " to move slave %d qpn %d to" - " reset\n", slave, - qp->local_qpn); - atomic_dec(&qp->rcq->ref_count); - atomic_dec(&qp->scq->ref_count); - atomic_dec(&qp->mtt->ref_count); - if (qp->srq) - atomic_dec(&qp->srq->ref_count); - state = RES_QP_MAPPED; - break; - default: - state = 0; - } - } - } - spin_lock_irq(mlx4_tlock(dev)); - } - spin_unlock_irq(mlx4_tlock(dev)); -} - -static void rem_slave_srqs(struct mlx4_dev *dev, int slave) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct list_head *srq_list = - &tracker->slave_list[slave].res_list[RES_SRQ]; - struct res_srq *srq; - struct res_srq *tmp; - int state; - u64 in_param; - LIST_HEAD(tlist); - int srqn; - int err; - - err = move_all_busy(dev, slave, RES_SRQ); - if (err) - mlx4_warn(dev, "rem_slave_srqs: Could not move all srqs to " - "busy for slave %d\n", slave); - - spin_lock_irq(mlx4_tlock(dev)); - list_for_each_entry_safe(srq, tmp, srq_list, com.list) { - spin_unlock_irq(mlx4_tlock(dev)); - if (srq->com.owner == slave) { - srqn = srq->com.res_id; - state = srq->com.from_state; - while (state != 0) { - switch (state) { - case RES_SRQ_ALLOCATED: - __mlx4_srq_free_icm(dev, srqn); - spin_lock_irq(mlx4_tlock(dev)); - radix_tree_delete(&tracker->res_tree[RES_SRQ], - srqn); - list_del(&srq->com.list); - spin_unlock_irq(mlx4_tlock(dev)); - kfree(srq); - state = 0; - break; - - case RES_SRQ_HW: - in_param = slave; - err = mlx4_cmd(dev, in_param, srqn, 1, - MLX4_CMD_HW2SW_SRQ, - MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); - if (err) - mlx4_dbg(dev, "rem_slave_srqs: failed" - " to move slave %d srq %d to" - " SW ownership\n", - slave, srqn); - - atomic_dec(&srq->mtt->ref_count); - if (srq->cq) - atomic_dec(&srq->cq->ref_count); - state = RES_SRQ_ALLOCATED; - break; - - default: - state = 0; - } - } - } - spin_lock_irq(mlx4_tlock(dev)); - } - spin_unlock_irq(mlx4_tlock(dev)); -} - -static void rem_slave_cqs(struct mlx4_dev *dev, int slave) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct list_head *cq_list = - &tracker->slave_list[slave].res_list[RES_CQ]; - struct res_cq *cq; - struct res_cq *tmp; - int state; - u64 in_param; - LIST_HEAD(tlist); - int cqn; - int err; - - err = move_all_busy(dev, slave, RES_CQ); - if (err) - mlx4_warn(dev, "rem_slave_cqs: Could not move all cqs to " - "busy for slave %d\n", slave); - - spin_lock_irq(mlx4_tlock(dev)); - list_for_each_entry_safe(cq, tmp, cq_list, com.list) { - spin_unlock_irq(mlx4_tlock(dev)); - if (cq->com.owner == slave && !atomic_read(&cq->ref_count)) { - cqn = cq->com.res_id; - state = cq->com.from_state; - while (state != 0) { - switch (state) { - case RES_CQ_ALLOCATED: - __mlx4_cq_free_icm(dev, cqn); - spin_lock_irq(mlx4_tlock(dev)); - radix_tree_delete(&tracker->res_tree[RES_CQ], - cqn); - list_del(&cq->com.list); - spin_unlock_irq(mlx4_tlock(dev)); - kfree(cq); - state = 0; - break; - - case RES_CQ_HW: - in_param = slave; - err = mlx4_cmd(dev, in_param, cqn, 1, - MLX4_CMD_HW2SW_CQ, - MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); - if (err) - mlx4_dbg(dev, "rem_slave_cqs: failed" - " to move slave %d cq %d to" - " SW ownership\n", - slave, cqn); - atomic_dec(&cq->mtt->ref_count); - state = RES_CQ_ALLOCATED; - break; - - default: - state = 0; - } - } - } - spin_lock_irq(mlx4_tlock(dev)); - } - spin_unlock_irq(mlx4_tlock(dev)); -} - -static void rem_slave_mrs(struct mlx4_dev *dev, int slave) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct list_head *mpt_list = - &tracker->slave_list[slave].res_list[RES_MPT]; - struct res_mpt *mpt; - struct res_mpt *tmp; - int state; - u64 in_param; - LIST_HEAD(tlist); - int mptn; - int err; - - err = move_all_busy(dev, slave, RES_MPT); - if (err) - mlx4_warn(dev, "rem_slave_mrs: Could not move all mpts to " - "busy for slave %d\n", slave); - - spin_lock_irq(mlx4_tlock(dev)); - list_for_each_entry_safe(mpt, tmp, mpt_list, com.list) { - spin_unlock_irq(mlx4_tlock(dev)); - if (mpt->com.owner == slave) { - mptn = mpt->com.res_id; - state = mpt->com.from_state; - while (state != 0) { - switch (state) { - case RES_MPT_RESERVED: - __mlx4_mr_release(dev, mpt->key); - spin_lock_irq(mlx4_tlock(dev)); - radix_tree_delete(&tracker->res_tree[RES_MPT], - mptn); - list_del(&mpt->com.list); - spin_unlock_irq(mlx4_tlock(dev)); - kfree(mpt); - state = 0; - break; - - case RES_MPT_MAPPED: - __mlx4_mr_free_icm(dev, mpt->key); - state = RES_MPT_RESERVED; - break; - - case RES_MPT_HW: - in_param = slave; - err = mlx4_cmd(dev, in_param, mptn, 0, - MLX4_CMD_HW2SW_MPT, - MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); - if (err) - mlx4_dbg(dev, "rem_slave_mrs: failed" - " to move slave %d mpt %d to" - " SW ownership\n", - slave, mptn); - if (mpt->mtt) - atomic_dec(&mpt->mtt->ref_count); - state = RES_MPT_MAPPED; - break; - default: - state = 0; - } - } - } - spin_lock_irq(mlx4_tlock(dev)); - } - spin_unlock_irq(mlx4_tlock(dev)); -} - -static void rem_slave_mtts(struct mlx4_dev *dev, int slave) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = - &priv->mfunc.master.res_tracker; - struct list_head *mtt_list = - &tracker->slave_list[slave].res_list[RES_MTT]; - struct res_mtt *mtt; - struct res_mtt *tmp; - int state; - LIST_HEAD(tlist); - int base; - int err; - - err = move_all_busy(dev, slave, RES_MTT); - if (err) - mlx4_warn(dev, "rem_slave_mtts: Could not move all mtts to " - "busy for slave %d\n", slave); - - spin_lock_irq(mlx4_tlock(dev)); - list_for_each_entry_safe(mtt, tmp, mtt_list, com.list) { - spin_unlock_irq(mlx4_tlock(dev)); - if (mtt->com.owner == slave) { - base = mtt->com.res_id; - state = mtt->com.from_state; - while (state != 0) { - switch (state) { - case RES_MTT_ALLOCATED: - __mlx4_free_mtt_range(dev, base, - mtt->order); - spin_lock_irq(mlx4_tlock(dev)); - radix_tree_delete(&tracker->res_tree[RES_MTT], - base); - list_del(&mtt->com.list); - spin_unlock_irq(mlx4_tlock(dev)); - kfree(mtt); - state = 0; - break; - - default: - state = 0; - } - } - } - spin_lock_irq(mlx4_tlock(dev)); - } - spin_unlock_irq(mlx4_tlock(dev)); -} - -static void rem_slave_eqs(struct mlx4_dev *dev, int slave) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker; - struct list_head *eq_list = - &tracker->slave_list[slave].res_list[RES_EQ]; - struct res_eq *eq; - struct res_eq *tmp; - int err; - int state; - LIST_HEAD(tlist); - int eqn; - struct mlx4_cmd_mailbox *mailbox; - - err = move_all_busy(dev, slave, RES_EQ); - if (err) - mlx4_warn(dev, "rem_slave_eqs: Could not move all eqs to " - "busy for slave %d\n", slave); - - spin_lock_irq(mlx4_tlock(dev)); - list_for_each_entry_safe(eq, tmp, eq_list, com.list) { - spin_unlock_irq(mlx4_tlock(dev)); - if (eq->com.owner == slave) { - eqn = eq->com.res_id; - state = eq->com.from_state; - while (state != 0) { - switch (state) { - case RES_EQ_RESERVED: - spin_lock_irq(mlx4_tlock(dev)); - radix_tree_delete(&tracker->res_tree[RES_EQ], - eqn); - list_del(&eq->com.list); - spin_unlock_irq(mlx4_tlock(dev)); - kfree(eq); - state = 0; - break; - - case RES_EQ_HW: - mailbox = mlx4_alloc_cmd_mailbox(dev); - if (IS_ERR(mailbox)) { - cond_resched(); - continue; - } - err = mlx4_cmd_box(dev, slave, 0, - eqn & 0xff, 0, - MLX4_CMD_HW2SW_EQ, - MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_NATIVE); - mlx4_dbg(dev, "rem_slave_eqs: failed" - " to move slave %d eqs %d to" - " SW ownership\n", slave, eqn); - mlx4_free_cmd_mailbox(dev, mailbox); - if (!err) { - atomic_dec(&eq->mtt->ref_count); - state = RES_EQ_RESERVED; - } - break; - - default: - state = 0; - } - } - } - spin_lock_irq(mlx4_tlock(dev)); - } - spin_unlock_irq(mlx4_tlock(dev)); -} - -void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) -{ - struct mlx4_priv *priv = mlx4_priv(dev); - - mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); - /*VLAN*/ - rem_slave_macs(dev, slave); - rem_slave_qps(dev, slave); - rem_slave_srqs(dev, slave); - rem_slave_cqs(dev, slave); - rem_slave_mrs(dev, slave); - rem_slave_eqs(dev, slave); - rem_slave_mtts(dev, slave); - mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); -} diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/sense.c b/trunk/drivers/net/ethernet/mellanox/mlx4/sense.c index 802498293528..e2337a7411d9 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/sense.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/sense.c @@ -45,8 +45,7 @@ int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port, int err = 0; err = mlx4_cmd_imm(dev, 0, &out_param, port, 0, - MLX4_CMD_SENSE_PORT, MLX4_CMD_TIME_CLASS_B, - MLX4_CMD_WRAPPED); + MLX4_CMD_SENSE_PORT, MLX4_CMD_TIME_CLASS_B); if (err) { mlx4_err(dev, "Sense command failed for port: %d\n", port); return err; diff --git a/trunk/drivers/net/ethernet/mellanox/mlx4/srq.c b/trunk/drivers/net/ethernet/mellanox/mlx4/srq.c index 2823fffc6383..9cbf3fce0145 100644 --- a/trunk/drivers/net/ethernet/mellanox/mlx4/srq.c +++ b/trunk/drivers/net/ethernet/mellanox/mlx4/srq.c @@ -31,8 +31,6 @@ * SOFTWARE. */ -#include - #include #include #include @@ -40,6 +38,26 @@ #include "mlx4.h" #include "icm.h" +struct mlx4_srq_context { + __be32 state_logsize_srqn; + u8 logstride; + u8 reserved1; + __be16 xrcd; + __be32 pg_offset_cqn; + u32 reserved2; + u8 log_page_size; + u8 reserved3[2]; + u8 mtt_base_addr_h; + __be32 mtt_base_addr_l; + __be32 pd; + __be16 limit_watermark; + __be16 wqe_cnt; + u16 reserved4; + __be16 wqe_counter; + u32 reserved5; + __be64 db_rec_addr; +}; + void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type) { struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; @@ -67,9 +85,8 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type) static int mlx4_SW2HW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int srq_num) { - return mlx4_cmd(dev, mailbox->dma | dev->caps.function, srq_num, 0, - MLX4_CMD_SW2HW_SRQ, MLX4_CMD_TIME_CLASS_A, - MLX4_CMD_WRAPPED); + return mlx4_cmd(dev, mailbox->dma, srq_num, 0, MLX4_CMD_SW2HW_SRQ, + MLX4_CMD_TIME_CLASS_A); } static int mlx4_HW2SW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, @@ -77,109 +94,48 @@ static int mlx4_HW2SW_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox { return mlx4_cmd_box(dev, 0, mailbox ? mailbox->dma : 0, srq_num, mailbox ? 0 : 1, MLX4_CMD_HW2SW_SRQ, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); + MLX4_CMD_TIME_CLASS_A); } static int mlx4_ARM_SRQ(struct mlx4_dev *dev, int srq_num, int limit_watermark) { return mlx4_cmd(dev, limit_watermark, srq_num, 0, MLX4_CMD_ARM_SRQ, - MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); + MLX4_CMD_TIME_CLASS_B); } static int mlx4_QUERY_SRQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox, int srq_num) { return mlx4_cmd_box(dev, 0, mailbox->dma, srq_num, 0, MLX4_CMD_QUERY_SRQ, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); + MLX4_CMD_TIME_CLASS_A); } -int __mlx4_srq_alloc_icm(struct mlx4_dev *dev, int *srqn) +int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd, + struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq) { struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; + struct mlx4_cmd_mailbox *mailbox; + struct mlx4_srq_context *srq_context; + u64 mtt_addr; int err; - - *srqn = mlx4_bitmap_alloc(&srq_table->bitmap); - if (*srqn == -1) + srq->srqn = mlx4_bitmap_alloc(&srq_table->bitmap); + if (srq->srqn == -1) return -ENOMEM; - err = mlx4_table_get(dev, &srq_table->table, *srqn); + err = mlx4_table_get(dev, &srq_table->table, srq->srqn); if (err) goto err_out; - err = mlx4_table_get(dev, &srq_table->cmpt_table, *srqn); + err = mlx4_table_get(dev, &srq_table->cmpt_table, srq->srqn); if (err) goto err_put; - return 0; - -err_put: - mlx4_table_put(dev, &srq_table->table, *srqn); - -err_out: - mlx4_bitmap_free(&srq_table->bitmap, *srqn); - return err; -} - -static int mlx4_srq_alloc_icm(struct mlx4_dev *dev, int *srqn) -{ - u64 out_param; - int err; - - if (mlx4_is_mfunc(dev)) { - err = mlx4_cmd_imm(dev, 0, &out_param, RES_SRQ, - RES_OP_RESERVE_AND_MAP, - MLX4_CMD_ALLOC_RES, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); - if (!err) - *srqn = get_param_l(&out_param); - - return err; - } - return __mlx4_srq_alloc_icm(dev, srqn); -} - -void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn) -{ - struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; - - mlx4_table_put(dev, &srq_table->cmpt_table, srqn); - mlx4_table_put(dev, &srq_table->table, srqn); - mlx4_bitmap_free(&srq_table->bitmap, srqn); -} - -static void mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn) -{ - u64 in_param; - - if (mlx4_is_mfunc(dev)) { - set_param_l(&in_param, srqn); - if (mlx4_cmd(dev, in_param, RES_SRQ, RES_OP_RESERVE_AND_MAP, - MLX4_CMD_FREE_RES, - MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED)) - mlx4_warn(dev, "Failed freeing cq:%d\n", srqn); - return; - } - __mlx4_srq_free_icm(dev, srqn); -} - -int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd, - struct mlx4_mtt *mtt, u64 db_rec, struct mlx4_srq *srq) -{ - struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table; - struct mlx4_cmd_mailbox *mailbox; - struct mlx4_srq_context *srq_context; - u64 mtt_addr; - int err; - - err = mlx4_srq_alloc_icm(dev, &srq->srqn); - if (err) - return err; spin_lock_irq(&srq_table->lock); err = radix_tree_insert(&srq_table->tree, srq->srqn, srq); spin_unlock_irq(&srq_table->lock); if (err) - goto err_icm; + goto err_cmpt_put; mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) { @@ -218,8 +174,15 @@ int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, u32 cqn, u16 xrcd, radix_tree_delete(&srq_table->tree, srq->srqn); spin_unlock_irq(&srq_table->lock); -err_icm: - mlx4_srq_free_icm(dev, srq->srqn); +err_cmpt_put: + mlx4_table_put(dev, &srq_table->cmpt_table, srq->srqn); + +err_put: + mlx4_table_put(dev, &srq_table->table, srq->srqn); + +err_out: + mlx4_bitmap_free(&srq_table->bitmap, srq->srqn); + return err; } EXPORT_SYMBOL_GPL(mlx4_srq_alloc); @@ -241,7 +204,8 @@ void mlx4_srq_free(struct mlx4_dev *dev, struct mlx4_srq *srq) complete(&srq->free); wait_for_completion(&srq->free); - mlx4_srq_free_icm(dev, srq->srqn); + mlx4_table_put(dev, &srq_table->table, srq->srqn); + mlx4_bitmap_free(&srq_table->bitmap, srq->srqn); } EXPORT_SYMBOL_GPL(mlx4_srq_free); @@ -281,8 +245,6 @@ int mlx4_init_srq_table(struct mlx4_dev *dev) spin_lock_init(&srq_table->lock); INIT_RADIX_TREE(&srq_table->tree, GFP_ATOMIC); - if (mlx4_is_slave(dev)) - return 0; err = mlx4_bitmap_init(&srq_table->bitmap, dev->caps.num_srqs, dev->caps.num_srqs - 1, dev->caps.reserved_srqs, 0); @@ -294,7 +256,5 @@ int mlx4_init_srq_table(struct mlx4_dev *dev) void mlx4_cleanup_srq_table(struct mlx4_dev *dev) { - if (mlx4_is_slave(dev)) - return; mlx4_bitmap_cleanup(&mlx4_priv(dev)->srq_table.bitmap); } diff --git a/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.c b/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.c index ef76725454d2..16d4d8e913c3 100644 --- a/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/trunk/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -3305,7 +3305,7 @@ static void vxge_tx_watchdog(struct net_device *dev) * * Add the vlan id to the devices vlan id table */ -static int +static void vxge_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { struct vxgedev *vdev = netdev_priv(dev); @@ -3320,7 +3320,6 @@ vxge_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) vxge_hw_vpath_vid_add(vpath->handle, vid); } set_bit(vid, vdev->active_vlans); - return 0; } /** @@ -3330,7 +3329,7 @@ vxge_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) * * Remove the vlan id from the device's vlan id table */ -static int +static void vxge_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct vxgedev *vdev = netdev_priv(dev); @@ -3349,7 +3348,6 @@ vxge_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) vxge_debug_entryexit(VXGE_TRACE, "%s:%d Exiting...", __func__, __LINE__); clear_bit(vid, vdev->active_vlans); - return 0; } static const struct net_device_ops vxge_netdev_ops = { diff --git a/trunk/drivers/net/ethernet/pasemi/Makefile b/trunk/drivers/net/ethernet/pasemi/Makefile index 90497ffb1ac3..05db5434bafc 100644 --- a/trunk/drivers/net/ethernet/pasemi/Makefile +++ b/trunk/drivers/net/ethernet/pasemi/Makefile @@ -2,5 +2,4 @@ # Makefile for the A Semi network device drivers. # -obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o -pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o +obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o pasemi_mac_ethtool.o diff --git a/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 69b8e4ef14d9..823f845ddc04 100644 --- a/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/trunk/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -97,8 +97,8 @@ static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); static int qlcnicvf_start_firmware(struct qlcnic_adapter *); static void qlcnic_set_netdev_features(struct qlcnic_adapter *, struct qlcnic_esw_func_cfg *); -static int qlcnic_vlan_rx_add(struct net_device *, u16); -static int qlcnic_vlan_rx_del(struct net_device *, u16); +static void qlcnic_vlan_rx_add(struct net_device *, u16); +static void qlcnic_vlan_rx_del(struct net_device *, u16); /* PCI Device ID Table */ #define ENTRY(device) \ @@ -735,22 +735,20 @@ qlcnic_set_vlan_config(struct qlcnic_adapter *adapter, adapter->pvid = 0; } -static int +static void qlcnic_vlan_rx_add(struct net_device *netdev, u16 vid) { struct qlcnic_adapter *adapter = netdev_priv(netdev); set_bit(vid, adapter->vlans); - return 0; } -static int +static void qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid) { struct qlcnic_adapter *adapter = netdev_priv(netdev); qlcnic_restore_indev_addr(netdev, NETDEV_DOWN); clear_bit(vid, adapter->vlans); - return 0; } static void diff --git a/trunk/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/trunk/drivers/net/ethernet/qlogic/qlge/qlge_main.c index b54898737284..1ce4e08037b8 100644 --- a/trunk/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/trunk/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -2349,66 +2349,56 @@ static int qlge_set_features(struct net_device *ndev, return 0; } -static int __qlge_vlan_rx_add_vid(struct ql_adapter *qdev, u16 vid) +static void __qlge_vlan_rx_add_vid(struct ql_adapter *qdev, u16 vid) { u32 enable_bit = MAC_ADDR_E; - int err; - err = ql_set_mac_addr_reg(qdev, (u8 *) &enable_bit, - MAC_ADDR_TYPE_VLAN, vid); - if (err) + if (ql_set_mac_addr_reg + (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) { netif_err(qdev, ifup, qdev->ndev, "Failed to init vlan address.\n"); - return err; + } } -static int qlge_vlan_rx_add_vid(struct net_device *ndev, u16 vid) +static void qlge_vlan_rx_add_vid(struct net_device *ndev, u16 vid) { struct ql_adapter *qdev = netdev_priv(ndev); int status; - int err; status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); if (status) - return status; + return; - err = __qlge_vlan_rx_add_vid(qdev, vid); + __qlge_vlan_rx_add_vid(qdev, vid); set_bit(vid, qdev->active_vlans); ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); - - return err; } -static int __qlge_vlan_rx_kill_vid(struct ql_adapter *qdev, u16 vid) +static void __qlge_vlan_rx_kill_vid(struct ql_adapter *qdev, u16 vid) { u32 enable_bit = 0; - int err; - err = ql_set_mac_addr_reg(qdev, (u8 *) &enable_bit, - MAC_ADDR_TYPE_VLAN, vid); - if (err) + if (ql_set_mac_addr_reg + (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) { netif_err(qdev, ifup, qdev->ndev, "Failed to clear vlan address.\n"); - return err; + } } -static int qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid) +static void qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid) { struct ql_adapter *qdev = netdev_priv(ndev); int status; - int err; status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); if (status) - return status; + return; - err = __qlge_vlan_rx_kill_vid(qdev, vid); + __qlge_vlan_rx_kill_vid(qdev, vid); clear_bit(vid, qdev->active_vlans); ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); - - return err; } static void qlge_restore_vlan(struct ql_adapter *qdev) diff --git a/trunk/drivers/net/ethernet/realtek/r8169.c b/trunk/drivers/net/ethernet/realtek/r8169.c index 36b2a4b1c35f..e5a6d8e70502 100644 --- a/trunk/drivers/net/ethernet/realtek/r8169.c +++ b/trunk/drivers/net/ethernet/realtek/r8169.c @@ -1180,13 +1180,11 @@ static u8 rtl8168d_efuse_read(void __iomem *ioaddr, int reg_addr) return value; } -static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp) +static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) { - void __iomem *ioaddr = tp->mmio_addr; - RTL_W16(IntrMask, 0x0000); - RTL_W16(IntrStatus, tp->intr_event); - RTL_R8(ChipCmd); + + RTL_W16(IntrStatus, 0xffff); } static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp) @@ -3935,6 +3933,8 @@ static void rtl_hw_reset(struct rtl8169_private *tp) break; udelay(100); } + + rtl8169_init_ring_indexes(tp); } static int __devinit @@ -4339,7 +4339,7 @@ static void rtl8169_hw_reset(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; /* Disable interrupts */ - rtl8169_irq_mask_and_ack(tp); + rtl8169_irq_mask_and_ack(ioaddr); rtl_rx_close(tp); @@ -4885,7 +4885,8 @@ static void rtl_hw_start_8168(struct net_device *dev) RTL_W16(IntrMitigate, 0x5151); /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { + if (tp->mac_version == RTL_GIGA_MAC_VER_11 || + tp->mac_version == RTL_GIGA_MAC_VER_22) { tp->intr_event |= RxFIFOOver | PCSTimeout; tp->intr_event &= ~RxOverflow; } @@ -5075,11 +5076,6 @@ static void rtl_hw_start_8101(struct net_device *dev) void __iomem *ioaddr = tp->mmio_addr; struct pci_dev *pdev = tp->pci_dev; - if (tp->mac_version >= RTL_GIGA_MAC_VER_30) { - tp->intr_event &= ~RxFIFOOver; - tp->napi_event &= ~RxFIFOOver; - } - if (tp->mac_version == RTL_GIGA_MAC_VER_13 || tp->mac_version == RTL_GIGA_MAC_VER_16) { int cap = pci_pcie_cap(pdev); @@ -5346,7 +5342,7 @@ static void rtl8169_wait_for_quiescence(struct net_device *dev) /* Wait for any pending NAPI task to complete */ napi_disable(&tp->napi); - rtl8169_irq_mask_and_ack(tp); + rtl8169_irq_mask_and_ack(ioaddr); tp->intr_mask = 0xffff; RTL_W16(IntrMask, tp->intr_event); @@ -5393,16 +5389,14 @@ static void rtl8169_reset_task(struct work_struct *work) if (!netif_running(dev)) goto out_unlock; - rtl8169_hw_reset(tp); - rtl8169_wait_for_quiescence(dev); for (i = 0; i < NUM_RX_DESC; i++) rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz); rtl8169_tx_clear(tp); - rtl8169_init_ring_indexes(tp); + rtl8169_hw_reset(tp); rtl_hw_start(dev); netif_wake_queue(dev); rtl8169_check_link_status(dev, tp, tp->mmio_addr); @@ -5413,6 +5407,11 @@ static void rtl8169_reset_task(struct work_struct *work) static void rtl8169_tx_timeout(struct net_device *dev) { + struct rtl8169_private *tp = netdev_priv(dev); + + rtl8169_hw_reset(tp); + + /* Let's wait a bit while any (async) irq lands on */ rtl8169_schedule_work(dev, rtl8169_reset_task); } @@ -5805,10 +5804,6 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) */ status = RTL_R16(IntrStatus); while (status && status != 0xffff) { - status &= tp->intr_event; - if (!status) - break; - handled = 1; /* Handle all of the error cases first. These will reset @@ -5823,9 +5818,27 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) switch (tp->mac_version) { /* Work around for rx fifo overflow */ case RTL_GIGA_MAC_VER_11: + case RTL_GIGA_MAC_VER_22: + case RTL_GIGA_MAC_VER_26: netif_stop_queue(dev); rtl8169_tx_timeout(dev); goto done; + /* Testers needed. */ + case RTL_GIGA_MAC_VER_17: + case RTL_GIGA_MAC_VER_19: + case RTL_GIGA_MAC_VER_20: + case RTL_GIGA_MAC_VER_21: + case RTL_GIGA_MAC_VER_23: + case RTL_GIGA_MAC_VER_24: + case RTL_GIGA_MAC_VER_27: + case RTL_GIGA_MAC_VER_28: + case RTL_GIGA_MAC_VER_31: + /* Experimental science. Pktgen proof. */ + case RTL_GIGA_MAC_VER_12: + case RTL_GIGA_MAC_VER_25: + if (status == RxFIFOOver) + goto done; + break; default: break; } diff --git a/trunk/drivers/net/ethernet/sfc/efx.c b/trunk/drivers/net/ethernet/sfc/efx.c index 44a82c6c60a7..14e134d3b4d7 100644 --- a/trunk/drivers/net/ethernet/sfc/efx.c +++ b/trunk/drivers/net/ethernet/sfc/efx.c @@ -1336,8 +1336,7 @@ static int efx_probe_nic(struct efx_nic *efx) if (efx->n_channels > 1) get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key)); for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++) - efx->rx_indir_table[i] = - ethtool_rxfh_indir_default(i, efx->n_rx_channels); + efx->rx_indir_table[i] = i % efx->n_rx_channels; efx_set_channels(efx); netif_set_real_num_tx_queues(efx->net_dev, efx->n_tx_channels); diff --git a/trunk/drivers/net/ethernet/sfc/ethtool.c b/trunk/drivers/net/ethernet/sfc/ethtool.c index 1be51b2bfa42..f3cd96dfa398 100644 --- a/trunk/drivers/net/ethernet/sfc/ethtool.c +++ b/trunk/drivers/net/ethernet/sfc/ethtool.c @@ -956,28 +956,40 @@ static int efx_ethtool_set_rx_ntuple(struct net_device *net_dev, return rc < 0 ? rc : 0; } -static u32 efx_ethtool_get_rxfh_indir_size(struct net_device *net_dev) +static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev, + struct ethtool_rxfh_indir *indir) { struct efx_nic *efx = netdev_priv(net_dev); + size_t copy_size = + min_t(size_t, indir->size, ARRAY_SIZE(efx->rx_indir_table)); - return (efx_nic_rev(efx) < EFX_REV_FALCON_B0 ? - 0 : ARRAY_SIZE(efx->rx_indir_table)); -} - -static int efx_ethtool_get_rxfh_indir(struct net_device *net_dev, u32 *indir) -{ - struct efx_nic *efx = netdev_priv(net_dev); + if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) + return -EOPNOTSUPP; - memcpy(indir, efx->rx_indir_table, sizeof(efx->rx_indir_table)); + indir->size = ARRAY_SIZE(efx->rx_indir_table); + memcpy(indir->ring_index, efx->rx_indir_table, + copy_size * sizeof(indir->ring_index[0])); return 0; } static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev, - const u32 *indir) + const struct ethtool_rxfh_indir *indir) { struct efx_nic *efx = netdev_priv(net_dev); + size_t i; + + if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) + return -EOPNOTSUPP; + + /* Validate size and indices */ + if (indir->size != ARRAY_SIZE(efx->rx_indir_table)) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(efx->rx_indir_table); i++) + if (indir->ring_index[i] >= efx->n_rx_channels) + return -EINVAL; - memcpy(efx->rx_indir_table, indir, sizeof(efx->rx_indir_table)); + memcpy(efx->rx_indir_table, indir->ring_index, + sizeof(efx->rx_indir_table)); efx_nic_push_rx_indir_table(efx); return 0; } @@ -1008,7 +1020,6 @@ const struct ethtool_ops efx_ethtool_ops = { .reset = efx_ethtool_reset, .get_rxnfc = efx_ethtool_get_rxnfc, .set_rx_ntuple = efx_ethtool_set_rx_ntuple, - .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, .get_rxfh_indir = efx_ethtool_get_rxfh_indir, .set_rxfh_indir = efx_ethtool_set_rxfh_indir, }; diff --git a/trunk/drivers/net/ethernet/tehuti/tehuti.c b/trunk/drivers/net/ethernet/tehuti/tehuti.c index 4b19e9b0606b..3a90af6d111c 100644 --- a/trunk/drivers/net/ethernet/tehuti/tehuti.c +++ b/trunk/drivers/net/ethernet/tehuti/tehuti.c @@ -727,10 +727,9 @@ static void __bdx_vlan_rx_vid(struct net_device *ndev, uint16_t vid, int enable) * @ndev network device * @vid VLAN vid to add */ -static int bdx_vlan_rx_add_vid(struct net_device *ndev, uint16_t vid) +static void bdx_vlan_rx_add_vid(struct net_device *ndev, uint16_t vid) { __bdx_vlan_rx_vid(ndev, vid, 1); - return 0; } /* @@ -738,10 +737,9 @@ static int bdx_vlan_rx_add_vid(struct net_device *ndev, uint16_t vid) * @ndev network device * @vid VLAN vid to kill */ -static int bdx_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid) +static void bdx_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid) { __bdx_vlan_rx_vid(ndev, vid, 0); - return 0; } /** diff --git a/trunk/drivers/net/ethernet/via/via-rhine.c b/trunk/drivers/net/ethernet/via/via-rhine.c index bcdbdc72b558..5587ecdf32e3 100644 --- a/trunk/drivers/net/ethernet/via/via-rhine.c +++ b/trunk/drivers/net/ethernet/via/via-rhine.c @@ -488,8 +488,8 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static const struct ethtool_ops netdev_ethtool_ops; static int rhine_close(struct net_device *dev); static void rhine_shutdown (struct pci_dev *pdev); -static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid); -static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid); +static void rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid); +static void rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid); static void rhine_set_cam(void __iomem *ioaddr, int idx, u8 *addr); static void rhine_set_vlan_cam(void __iomem *ioaddr, int idx, u8 *addr); static void rhine_set_cam_mask(void __iomem *ioaddr, u32 mask); @@ -1261,7 +1261,7 @@ static void rhine_update_vcam(struct net_device *dev) rhine_set_vlan_cam_mask(ioaddr, vCAMmask); } -static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) +static void rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { struct rhine_private *rp = netdev_priv(dev); @@ -1269,10 +1269,9 @@ static int rhine_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) set_bit(vid, rp->active_vlans); rhine_update_vcam(dev); spin_unlock_irq(&rp->lock); - return 0; } -static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +static void rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct rhine_private *rp = netdev_priv(dev); @@ -1280,7 +1279,6 @@ static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) clear_bit(vid, rp->active_vlans); rhine_update_vcam(dev); spin_unlock_irq(&rp->lock); - return 0; } static void init_registers(struct net_device *dev) diff --git a/trunk/drivers/net/ethernet/via/via-velocity.c b/trunk/drivers/net/ethernet/via/via-velocity.c index 4128d6b8cc28..59bb5fd56afe 100644 --- a/trunk/drivers/net/ethernet/via/via-velocity.c +++ b/trunk/drivers/net/ethernet/via/via-velocity.c @@ -522,7 +522,7 @@ static void velocity_init_cam_filter(struct velocity_info *vptr) mac_set_vlan_cam_mask(regs, vptr->vCAMmask); } -static int velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) +static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { struct velocity_info *vptr = netdev_priv(dev); @@ -530,10 +530,9 @@ static int velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) set_bit(vid, vptr->active_vlans); velocity_init_cam_filter(vptr); spin_unlock_irq(&vptr->lock); - return 0; } -static int velocity_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +static void velocity_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct velocity_info *vptr = netdev_priv(dev); @@ -541,7 +540,6 @@ static int velocity_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) clear_bit(vid, vptr->active_vlans); velocity_init_cam_filter(vptr); spin_unlock_irq(&vptr->lock); - return 0; } static void velocity_init_rx_ring_indexes(struct velocity_info *vptr) diff --git a/trunk/drivers/net/macvlan.c b/trunk/drivers/net/macvlan.c index f2f820c4b40a..74134970b709 100644 --- a/trunk/drivers/net/macvlan.c +++ b/trunk/drivers/net/macvlan.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -521,23 +520,26 @@ static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev, return stats; } -static int macvlan_vlan_rx_add_vid(struct net_device *dev, +static void macvlan_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { struct macvlan_dev *vlan = netdev_priv(dev); struct net_device *lowerdev = vlan->lowerdev; + const struct net_device_ops *ops = lowerdev->netdev_ops; - return vlan_vid_add(lowerdev, vid); + if (ops->ndo_vlan_rx_add_vid) + ops->ndo_vlan_rx_add_vid(lowerdev, vid); } -static int macvlan_vlan_rx_kill_vid(struct net_device *dev, +static void macvlan_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct macvlan_dev *vlan = netdev_priv(dev); struct net_device *lowerdev = vlan->lowerdev; + const struct net_device_ops *ops = lowerdev->netdev_ops; - vlan_vid_del(lowerdev, vid); - return 0; + if (ops->ndo_vlan_rx_kill_vid) + ops->ndo_vlan_rx_kill_vid(lowerdev, vid); } static void macvlan_ethtool_get_drvinfo(struct net_device *dev, diff --git a/trunk/drivers/net/ppp/pptp.c b/trunk/drivers/net/ppp/pptp.c index c1c9293c2bbf..ede899ca0ee6 100644 --- a/trunk/drivers/net/ppp/pptp.c +++ b/trunk/drivers/net/ppp/pptp.c @@ -423,8 +423,10 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr, lock_sock(sk); opt->src_addr = sp->sa_addr.pptp; - if (add_chan(po)) + if (add_chan(po)) { + release_sock(sk); error = -EBUSY; + } release_sock(sk); return error; diff --git a/trunk/drivers/net/team/team.c b/trunk/drivers/net/team/team.c index ed2a862b835d..064155d56bce 100644 --- a/trunk/drivers/net/team/team.c +++ b/trunk/drivers/net/team/team.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -588,13 +587,6 @@ static int team_port_add(struct team *team, struct net_device *port_dev) goto err_dev_open; } - err = vlan_vids_add_by_dev(port_dev, dev); - if (err) { - netdev_err(dev, "Failed to add vlan ids to device %s\n", - portname); - goto err_vids_add; - } - err = netdev_set_master(port_dev, dev); if (err) { netdev_err(dev, "Device %s failed to set master\n", portname); @@ -622,9 +614,6 @@ static int team_port_add(struct team *team, struct net_device *port_dev) netdev_set_master(port_dev, NULL); err_set_master: - vlan_vids_del_by_dev(port_dev, dev); - -err_vids_add: dev_close(port_dev); err_dev_open: @@ -658,7 +647,6 @@ static int team_port_del(struct team *team, struct net_device *port_dev) team_adjust_ops(team); netdev_rx_handler_unregister(port_dev); netdev_set_master(port_dev, NULL); - vlan_vids_del_by_dev(port_dev, dev); dev_close(port_dev); team_port_leave(team, port); team_port_set_orig_mac(port); @@ -914,45 +902,34 @@ team_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) return stats; } -static int team_vlan_rx_add_vid(struct net_device *dev, uint16_t vid) +static void team_vlan_rx_add_vid(struct net_device *dev, uint16_t vid) { struct team *team = netdev_priv(dev); struct team_port *port; - int err; - - /* - * Alhough this is reader, it's guarded by team lock. It's not possible - * to traverse list in reverse under rcu_read_lock - */ - mutex_lock(&team->lock); - list_for_each_entry(port, &team->port_list, list) { - err = vlan_vid_add(port->dev, vid); - if (err) - goto unwind; - } - mutex_unlock(&team->lock); - return 0; - -unwind: - list_for_each_entry_continue_reverse(port, &team->port_list, list) - vlan_vid_del(port->dev, vid); - mutex_unlock(&team->lock); + rcu_read_lock(); + list_for_each_entry_rcu(port, &team->port_list, list) { + const struct net_device_ops *ops = port->dev->netdev_ops; - return err; + if (ops->ndo_vlan_rx_add_vid) + ops->ndo_vlan_rx_add_vid(port->dev, vid); + } + rcu_read_unlock(); } -static int team_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) +static void team_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) { struct team *team = netdev_priv(dev); struct team_port *port; rcu_read_lock(); - list_for_each_entry_rcu(port, &team->port_list, list) - vlan_vid_del(port->dev, vid); - rcu_read_unlock(); + list_for_each_entry_rcu(port, &team->port_list, list) { + const struct net_device_ops *ops = port->dev->netdev_ops; - return 0; + if (ops->ndo_vlan_rx_kill_vid) + ops->ndo_vlan_rx_kill_vid(port->dev, vid); + } + rcu_read_unlock(); } static int team_add_slave(struct net_device *dev, struct net_device *port_dev) diff --git a/trunk/drivers/net/virtio_net.c b/trunk/drivers/net/virtio_net.c index 609c51f90e6c..5a961720f64c 100644 --- a/trunk/drivers/net/virtio_net.c +++ b/trunk/drivers/net/virtio_net.c @@ -855,7 +855,7 @@ static void virtnet_set_rx_mode(struct net_device *dev) kfree(buf); } -static int virtnet_vlan_rx_add_vid(struct net_device *dev, u16 vid) +static void virtnet_vlan_rx_add_vid(struct net_device *dev, u16 vid) { struct virtnet_info *vi = netdev_priv(dev); struct scatterlist sg; @@ -865,10 +865,9 @@ static int virtnet_vlan_rx_add_vid(struct net_device *dev, u16 vid) if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, VIRTIO_NET_CTRL_VLAN_ADD, &sg, 1, 0)) dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid); - return 0; } -static int virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) +static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) { struct virtnet_info *vi = netdev_priv(dev); struct scatterlist sg; @@ -878,7 +877,6 @@ static int virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, VIRTIO_NET_CTRL_VLAN_DEL, &sg, 1, 0)) dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid); - return 0; } static void virtnet_get_ringparam(struct net_device *dev, diff --git a/trunk/drivers/net/vmxnet3/vmxnet3_drv.c b/trunk/drivers/net/vmxnet3/vmxnet3_drv.c index de7fc345148a..d96bfb1ac20b 100644 --- a/trunk/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/trunk/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1926,7 +1926,7 @@ vmxnet3_restore_vlan(struct vmxnet3_adapter *adapter) } -static int +static void vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid) { struct vmxnet3_adapter *adapter = netdev_priv(netdev); @@ -1943,12 +1943,10 @@ vmxnet3_vlan_rx_add_vid(struct net_device *netdev, u16 vid) } set_bit(vid, adapter->active_vlans); - - return 0; } -static int +static void vmxnet3_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) { struct vmxnet3_adapter *adapter = netdev_priv(netdev); @@ -1965,8 +1963,6 @@ vmxnet3_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) } clear_bit(vid, adapter->active_vlans); - - return 0; } @@ -2167,8 +2163,7 @@ vmxnet3_setup_driver_shared(struct vmxnet3_adapter *adapter) rssConf->indTableSize = VMXNET3_RSS_IND_TABLE_SIZE; get_random_bytes(&rssConf->hashKey[0], rssConf->hashKeySize); for (i = 0; i < rssConf->indTableSize; i++) - rssConf->indTable[i] = ethtool_rxfh_indir_default( - i, adapter->num_rx_queues); + rssConf->indTable[i] = i % adapter->num_rx_queues; devRead->rssConfDesc.confVer = 1; devRead->rssConfDesc.confLen = sizeof(*rssConf); diff --git a/trunk/drivers/net/vmxnet3/vmxnet3_ethtool.c b/trunk/drivers/net/vmxnet3/vmxnet3_ethtool.c index a3eb75a62ea9..b492ee1e5f17 100644 --- a/trunk/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/trunk/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -565,38 +565,44 @@ vmxnet3_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *info, } #ifdef VMXNET3_RSS -static u32 -vmxnet3_get_rss_indir_size(struct net_device *netdev) -{ - struct vmxnet3_adapter *adapter = netdev_priv(netdev); - struct UPT1_RSSConf *rssConf = adapter->rss_conf; - - return rssConf->indTableSize; -} - static int -vmxnet3_get_rss_indir(struct net_device *netdev, u32 *p) +vmxnet3_get_rss_indir(struct net_device *netdev, + struct ethtool_rxfh_indir *p) { struct vmxnet3_adapter *adapter = netdev_priv(netdev); struct UPT1_RSSConf *rssConf = adapter->rss_conf; - unsigned int n = rssConf->indTableSize; + unsigned int n = min_t(unsigned int, p->size, rssConf->indTableSize); + p->size = rssConf->indTableSize; while (n--) - p[n] = rssConf->indTable[n]; + p->ring_index[n] = rssConf->indTable[n]; return 0; } static int -vmxnet3_set_rss_indir(struct net_device *netdev, const u32 *p) +vmxnet3_set_rss_indir(struct net_device *netdev, + const struct ethtool_rxfh_indir *p) { unsigned int i; unsigned long flags; struct vmxnet3_adapter *adapter = netdev_priv(netdev); struct UPT1_RSSConf *rssConf = adapter->rss_conf; + if (p->size != rssConf->indTableSize) + return -EINVAL; + for (i = 0; i < rssConf->indTableSize; i++) { + /* + * Return with error code if any of the queue indices + * is out of range + */ + if (p->ring_index[i] < 0 || + p->ring_index[i] >= adapter->num_rx_queues) + return -EINVAL; + } + for (i = 0; i < rssConf->indTableSize; i++) - rssConf->indTable[i] = p[i]; + rssConf->indTable[i] = p->ring_index[i]; spin_lock_irqsave(&adapter->cmd_lock, flags); VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD, @@ -623,7 +629,6 @@ static struct ethtool_ops vmxnet3_ethtool_ops = { .set_ringparam = vmxnet3_set_ringparam, .get_rxnfc = vmxnet3_get_rxnfc, #ifdef VMXNET3_RSS - .get_rxfh_indir_size = vmxnet3_get_rss_indir_size, .get_rxfh_indir = vmxnet3_get_rss_indir, .set_rxfh_indir = vmxnet3_set_rss_indir, #endif diff --git a/trunk/drivers/net/wireless/ath/ath5k/ahb.c b/trunk/drivers/net/wireless/ath/ath5k/ahb.c index ee7ea572b065..e5be7e701816 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/ahb.c +++ b/trunk/drivers/net/wireless/ath/ath5k/ahb.c @@ -166,9 +166,7 @@ static int ath_ahb_probe(struct platform_device *pdev) if (to_platform_device(ah->dev)->id == 0 && (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) == (BD_WLAN1 | BD_WLAN0)) - ah->ah_capabilities.cap_needs_2GHz_ovr = true; - else - ah->ah_capabilities.cap_needs_2GHz_ovr = false; + __set_bit(ATH_STAT_2G_DISABLED, ah->status); } ret = ath5k_init_ah(ah, &ath_ahb_bus_ops); diff --git a/trunk/drivers/net/wireless/ath/ath5k/ani.c b/trunk/drivers/net/wireless/ath/ath5k/ani.c index bf674161a217..bea90e6be70e 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/ani.c +++ b/trunk/drivers/net/wireless/ath/ath5k/ani.c @@ -27,21 +27,15 @@ * or reducing sensitivity as necessary. * * The parameters are: - * * - "noise immunity" - * * - "spur immunity" - * * - "firstep level" - * * - "OFDM weak signal detection" - * * - "CCK weak signal detection" * * Basically we look at the amount of ODFM and CCK timing errors we get and then * raise or lower immunity accordingly by setting one or more of these * parameters. - * * Newer chipsets have PHY error counters in hardware which will generate a MIB * interrupt when they overflow. Older hardware has too enable PHY error frames * by setting a RX flag and then count every single PHY error. When a specified @@ -51,13 +45,11 @@ */ -/***********************\ -* ANI parameter control * -\***********************/ +/*** ANI parameter control ***/ /** * ath5k_ani_set_noise_immunity_level() - Set noise immunity level - * @ah: The &struct ath5k_hw + * * @level: level between 0 and @ATH5K_ANI_MAX_NOISE_IMM_LVL */ void @@ -99,11 +91,12 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); } + /** * ath5k_ani_set_spur_immunity_level() - Set spur immunity level - * @ah: The &struct ath5k_hw + * * @level: level between 0 and @max_spur_level (the maximum level is dependent - * on the chip revision). + * on the chip revision). */ void ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) @@ -124,9 +117,10 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); } + /** * ath5k_ani_set_firstep_level() - Set "firstep" level - * @ah: The &struct ath5k_hw + * * @level: level between 0 and @ATH5K_ANI_MAX_FIRSTEP_LVL */ void @@ -146,9 +140,11 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); } + /** - * ath5k_ani_set_ofdm_weak_signal_detection() - Set OFDM weak signal detection - * @ah: The &struct ath5k_hw + * ath5k_ani_set_ofdm_weak_signal_detection() - Control OFDM weak signal + * detection + * * @on: turn on or off */ void @@ -186,9 +182,10 @@ ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) on ? "on" : "off"); } + /** - * ath5k_ani_set_cck_weak_signal_detection() - Set CCK weak signal detection - * @ah: The &struct ath5k_hw + * ath5k_ani_set_cck_weak_signal_detection() - control CCK weak signal detection + * * @on: turn on or off */ void @@ -203,16 +200,13 @@ ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on) } -/***************\ -* ANI algorithm * -\***************/ +/*** ANI algorithm ***/ /** * ath5k_ani_raise_immunity() - Increase noise immunity - * @ah: The &struct ath5k_hw - * @as: The &struct ath5k_ani_state + * * @ofdm_trigger: If this is true we are called because of too many OFDM errors, - * the algorithm will tune more parameters then. + * the algorithm will tune more parameters then. * * Try to raise noise immunity (=decrease sensitivity) in several steps * depending on the average RSSI of the beacons we received. @@ -296,10 +290,9 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, */ } + /** * ath5k_ani_lower_immunity() - Decrease noise immunity - * @ah: The &struct ath5k_hw - * @as: The &struct ath5k_ani_state * * Try to lower noise immunity (=increase sensitivity) in several steps * depending on the average RSSI of the beacons we received. @@ -359,10 +352,9 @@ ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) } } + /** * ath5k_hw_ani_get_listen_time() - Update counters and return listening time - * @ah: The &struct ath5k_hw - * @as: The &struct ath5k_ani_state * * Return an approximation of the time spent "listening" in milliseconds (ms) * since the last call of this function. @@ -387,10 +379,9 @@ ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as) return listen; } + /** * ath5k_ani_save_and_clear_phy_errors() - Clear and save PHY error counters - * @ah: The &struct ath5k_hw - * @as: The &struct ath5k_ani_state * * Clear the PHY error counters as soon as possible, since this might be called * from a MIB interrupt and we want to make sure we don't get interrupted again. @@ -438,14 +429,14 @@ ath5k_ani_save_and_clear_phy_errors(struct ath5k_hw *ah, return 1; } + /** * ath5k_ani_period_restart() - Restart ANI period - * @as: The &struct ath5k_ani_state * * Just reset counters, so they are clear for the next "ani period". */ static void -ath5k_ani_period_restart(struct ath5k_ani_state *as) +ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as) { /* keep last values for debugging */ as->last_ofdm_errors = as->ofdm_errors; @@ -457,9 +448,9 @@ ath5k_ani_period_restart(struct ath5k_ani_state *as) as->listen_time = 0; } + /** * ath5k_ani_calibration() - The main ANI calibration function - * @ah: The &struct ath5k_hw * * We count OFDM and CCK errors relative to the time where we did not send or * receive ("listen" time) and raise or lower immunity accordingly. @@ -501,7 +492,7 @@ ath5k_ani_calibration(struct ath5k_hw *ah) /* too many PHY errors - we have to raise immunity */ bool ofdm_flag = as->ofdm_errors > ofdm_high ? true : false; ath5k_ani_raise_immunity(ah, as, ofdm_flag); - ath5k_ani_period_restart(as); + ath5k_ani_period_restart(ah, as); } else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) { /* If more than 5 (TODO: why 5?) periods have passed and we got @@ -513,18 +504,15 @@ ath5k_ani_calibration(struct ath5k_hw *ah) if (as->ofdm_errors <= ofdm_low && as->cck_errors <= cck_low) ath5k_ani_lower_immunity(ah, as); - ath5k_ani_period_restart(as); + ath5k_ani_period_restart(ah, as); } } -/*******************\ -* Interrupt handler * -\*******************/ +/*** INTERRUPT HANDLER ***/ /** * ath5k_ani_mib_intr() - Interrupt handler for ANI MIB counters - * @ah: The &struct ath5k_hw * * Just read & reset the registers quickly, so they don't generate more * interrupts, save the counters and schedule the tasklet to decide whether @@ -561,11 +549,9 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah) tasklet_schedule(&ah->ani_tasklet); } + /** - * ath5k_ani_phy_error_report - Used by older HW to report PHY errors - * - * @ah: The &struct ath5k_hw - * @phyerr: One of enum ath5k_phy_error_code + * ath5k_ani_phy_error_report() - Used by older HW to report PHY errors * * This is used by hardware without PHY error counters to report PHY errors * on a frame-by-frame basis, instead of the interrupt. @@ -588,13 +574,10 @@ ath5k_ani_phy_error_report(struct ath5k_hw *ah, } -/****************\ -* Initialization * -\****************/ +/*** INIT ***/ /** * ath5k_enable_phy_err_counters() - Enable PHY error counters - * @ah: The &struct ath5k_hw * * Enable PHY error counters for OFDM and CCK timing errors. */ @@ -613,9 +596,9 @@ ath5k_enable_phy_err_counters(struct ath5k_hw *ah) ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); } + /** * ath5k_disable_phy_err_counters() - Disable PHY error counters - * @ah: The &struct ath5k_hw * * Disable PHY error counters for OFDM and CCK timing errors. */ @@ -632,10 +615,10 @@ ath5k_disable_phy_err_counters(struct ath5k_hw *ah) ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); } + /** * ath5k_ani_init() - Initialize ANI - * @ah: The &struct ath5k_hw - * @mode: One of enum ath5k_ani_mode + * @mode: Which mode to use (auto, manual high, manual low, off) * * Initialize ANI according to mode. */ @@ -712,18 +695,10 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode) } -/**************\ -* Debug output * -\**************/ +/*** DEBUG ***/ #ifdef CONFIG_ATH5K_DEBUG -/** - * ath5k_ani_print_counters() - Print ANI counters - * @ah: The &struct ath5k_hw - * - * Used for debugging ANI - */ void ath5k_ani_print_counters(struct ath5k_hw *ah) { diff --git a/trunk/drivers/net/wireless/ath/ath5k/ani.h b/trunk/drivers/net/wireless/ath/ath5k/ani.h index 21aa355460bb..7358b6c83c6c 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/ani.h +++ b/trunk/drivers/net/wireless/ath/ath5k/ani.h @@ -40,13 +40,13 @@ enum ath5k_phy_error_code; * enum ath5k_ani_mode - mode for ANI / noise sensitivity * * @ATH5K_ANI_MODE_OFF: Turn ANI off. This can be useful to just stop the ANI - * algorithm after it has been on auto mode. - * @ATH5K_ANI_MODE_MANUAL_LOW: Manually set all immunity parameters to low, - * maximizing sensitivity. ANI will not run. - * @ATH5K_ANI_MODE_MANUAL_HIGH: Manually set all immunity parameters to high, - * minimizing sensitivity. ANI will not run. - * @ATH5K_ANI_MODE_AUTO: Automatically control immunity parameters based on the - * amount of OFDM and CCK frame errors (default). + * algorithm after it has been on auto mode. + * ATH5K_ANI_MODE_MANUAL_LOW: Manually set all immunity parameters to low, + * maximizing sensitivity. ANI will not run. + * ATH5K_ANI_MODE_MANUAL_HIGH: Manually set all immunity parameters to high, + * minimizing sensitivity. ANI will not run. + * ATH5K_ANI_MODE_AUTO: Automatically control immunity parameters based on the + * amount of OFDM and CCK frame errors (default). */ enum ath5k_ani_mode { ATH5K_ANI_MODE_OFF = 0, @@ -58,22 +58,8 @@ enum ath5k_ani_mode { /** * struct ath5k_ani_state - ANI state and associated counters - * @ani_mode: One of enum ath5k_ani_mode - * @noise_imm_level: Noise immunity level - * @spur_level: Spur immunity level - * @firstep_level: FIRstep level - * @ofdm_weak_sig: OFDM weak signal detection state (on/off) - * @cck_weak_sig: CCK weak signal detection state (on/off) - * @max_spur_level: Max spur immunity level (chip specific) - * @listen_time: Listen time - * @ofdm_errors: OFDM timing error count - * @cck_errors: CCK timing error count - * @last_cc: The &struct ath_cycle_counters (for stats) - * @last_listen: Listen time from previous run (for stats) - * @last_ofdm_errors: OFDM timing error count from previous run (for tats) - * @last_cck_errors: CCK timing error count from previous run (for stats) - * @sum_ofdm_errors: Sum of OFDM timing errors (for stats) - * @sum_cck_errors: Sum of all CCK timing errors (for stats) + * + * @max_spur_level: the maximum spur level is chip dependent */ struct ath5k_ani_state { enum ath5k_ani_mode ani_mode; diff --git a/trunk/drivers/net/wireless/ath/ath5k/ath5k.h b/trunk/drivers/net/wireless/ath/ath5k/ath5k.h index e564e585b221..fecbcd9a4259 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/trunk/drivers/net/wireless/ath/ath5k/ath5k.h @@ -187,9 +187,10 @@ #define AR5K_TUNE_MAX_TXPOWER 63 #define AR5K_TUNE_DEFAULT_TXPOWER 25 #define AR5K_TUNE_TPC_TXPOWER false -#define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 60000 /* 60 sec */ -#define ATH5K_TUNE_CALIBRATION_INTERVAL_SHORT 10000 /* 10 sec */ +#define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 10000 /* 10 sec */ #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ +#define ATH5K_TUNE_CALIBRATION_INTERVAL_NF 60000 /* 60 sec */ + #define ATH5K_TX_COMPLETE_POLL_INT 3000 /* 3 sec */ #define AR5K_INIT_CARR_SENSE_EN 1 @@ -261,34 +262,16 @@ #define AR5K_AGC_SETTLING_TURBO 37 +/* GENERIC CHIPSET DEFINITIONS */ -/*****************************\ -* GENERIC CHIPSET DEFINITIONS * -\*****************************/ - -/** - * enum ath5k_version - MAC Chips - * @AR5K_AR5210: AR5210 (Crete) - * @AR5K_AR5211: AR5211 (Oahu/Maui) - * @AR5K_AR5212: AR5212 (Venice) and newer - */ +/* MAC Chips */ enum ath5k_version { AR5K_AR5210 = 0, AR5K_AR5211 = 1, AR5K_AR5212 = 2, }; -/** - * enum ath5k_radio - PHY Chips - * @AR5K_RF5110: RF5110 (Fez) - * @AR5K_RF5111: RF5111 (Sombrero) - * @AR5K_RF5112: RF2112/5112(A) (Derby/Derby2) - * @AR5K_RF2413: RF2413/2414 (Griffin/Griffin-Lite) - * @AR5K_RF5413: RF5413/5414/5424 (Eagle/Condor) - * @AR5K_RF2316: RF2315/2316 (Cobra SoC) - * @AR5K_RF2317: RF2317 (Spider SoC) - * @AR5K_RF2425: RF2425/2417 (Swan/Nalla) - */ +/* PHY Chips */ enum ath5k_radio { AR5K_RF5110 = 0, AR5K_RF5111 = 1, @@ -320,11 +303,11 @@ enum ath5k_radio { #define AR5K_SREV_AR5213A 0x59 /* Hainan */ #define AR5K_SREV_AR2413 0x78 /* Griffin lite */ #define AR5K_SREV_AR2414 0x70 /* Griffin */ -#define AR5K_SREV_AR2315_R6 0x86 /* AP51-Light */ -#define AR5K_SREV_AR2315_R7 0x87 /* AP51-Full */ +#define AR5K_SREV_AR2315_R6 0x86 /* AP51-Light */ +#define AR5K_SREV_AR2315_R7 0x87 /* AP51-Full */ #define AR5K_SREV_AR5424 0x90 /* Condor */ -#define AR5K_SREV_AR2317_R1 0x90 /* AP61-Light */ -#define AR5K_SREV_AR2317_R2 0x91 /* AP61-Full */ +#define AR5K_SREV_AR2317_R1 0x90 /* AP61-Light */ +#define AR5K_SREV_AR2317_R2 0x91 /* AP61-Full */ #define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ #define AR5K_SREV_AR5414 0xa0 /* Eagle */ #define AR5K_SREV_AR2415 0xb0 /* Talon */ @@ -361,40 +344,32 @@ enum ath5k_radio { /* TODO add support to mac80211 for vendor-specific rates and modes */ -/** - * DOC: Atheros XR - * +/* * Some of this information is based on Documentation from: * * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG * - * Atheros' eXtended Range - range enhancing extension is a modulation scheme - * that is supposed to double the link distance between an Atheros XR-enabled - * client device with an Atheros XR-enabled access point. This is achieved - * by increasing the receiver sensitivity up to, -105dBm, which is about 20dB - * above what the 802.11 specifications demand. In addition, new (proprietary) - * data rates are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s. + * Modulation for Atheros' eXtended Range - range enhancing extension that is + * supposed to double the distance an Atheros client device can keep a + * connection with an Atheros access point. This is achieved by increasing + * the receiver sensitivity up to, -105dBm, which is about 20dB above what + * the 802.11 specifications demand. In addition, new (proprietary) data rates + * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s. * * Please note that can you either use XR or TURBO but you cannot use both, * they are exclusive. * - * Also note that we do not plan to support XR mode at least for now. You can - * get a mode similar to XR by using 5MHz bwmode. */ - - -/** - * DOC: Atheros SuperAG - * - * In addition to XR we have another modulation scheme called TURBO mode - * that is supposed to provide a throughput transmission speed up to 40Mbit/s - * -60Mbit/s at a 108Mbit/s signaling rate achieved through the bonding of two - * 54Mbit/s 802.11g channels. To use this feature both ends must support it. +#define MODULATION_XR 0x00000200 +/* + * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a + * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s + * signaling rate achieved through the bonding of two 54Mbit/s 802.11g + * channels. To use this feature your Access Point must also support it. * There is also a distinction between "static" and "dynamic" turbo modes: * * - Static: is the dumb version: devices set to this mode stick to it until * the mode is turned off. - * * - Dynamic: is the intelligent version, the network decides itself if it * is ok to use turbo. As soon as traffic is detected on adjacent channels * (which would get used in turbo mode), or when a non-turbo station joins @@ -408,39 +383,24 @@ enum ath5k_radio { * * http://www.pcworld.com/article/id,113428-page,1/article.html * - * The channel bonding seems to be driver specific though. - * - * In addition to TURBO modes we also have the following features for even - * greater speed-up: + * The channel bonding seems to be driver specific though. In addition to + * deciding what channels will be used, these "Turbo" modes are accomplished + * by also enabling the following features: * * - Bursting: allows multiple frames to be sent at once, rather than pausing * after each frame. Bursting is a standards-compliant feature that can be * used with any Access Point. - * * - Fast frames: increases the amount of information that can be sent per * frame, also resulting in a reduction of transmission overhead. It is a * proprietary feature that needs to be supported by the Access Point. - * * - Compression: data frames are compressed in real time using a Lempel Ziv * algorithm. This is done transparently. Once this feature is enabled, * compression and decompression takes place inside the chipset, without * putting additional load on the host CPU. * - * As with XR we also don't plan to support SuperAG features for now. You can - * get a mode similar to TURBO by using 40MHz bwmode. */ +#define MODULATION_TURBO 0x00000080 - -/** - * enum ath5k_driver_mode - PHY operation mode - * @AR5K_MODE_11A: 802.11a - * @AR5K_MODE_11B: 802.11b - * @AR5K_MODE_11G: 801.11g - * @AR5K_MODE_MAX: Used for boundary checks - * - * Do not change the order here, we use these as - * array indices and it also maps EEPROM structures. - */ enum ath5k_driver_mode { AR5K_MODE_11A = 0, AR5K_MODE_11B = 1, @@ -448,64 +408,30 @@ enum ath5k_driver_mode { AR5K_MODE_MAX = 3 }; -/** - * enum ath5k_ant_mode - Antenna operation mode - * @AR5K_ANTMODE_DEFAULT: Default antenna setup - * @AR5K_ANTMODE_FIXED_A: Only antenna A is present - * @AR5K_ANTMODE_FIXED_B: Only antenna B is present - * @AR5K_ANTMODE_SINGLE_AP: STA locked on a single ap - * @AR5K_ANTMODE_SECTOR_AP: AP with tx antenna set on tx desc - * @AR5K_ANTMODE_SECTOR_STA: STA with tx antenna set on tx desc - * @AR5K_ANTMODE_DEBUG: Debug mode -A -> Rx, B-> Tx- - * @AR5K_ANTMODE_MAX: Used for boundary checks - * - * For more infos on antenna control check out phy.c - */ enum ath5k_ant_mode { - AR5K_ANTMODE_DEFAULT = 0, - AR5K_ANTMODE_FIXED_A = 1, - AR5K_ANTMODE_FIXED_B = 2, - AR5K_ANTMODE_SINGLE_AP = 3, - AR5K_ANTMODE_SECTOR_AP = 4, - AR5K_ANTMODE_SECTOR_STA = 5, - AR5K_ANTMODE_DEBUG = 6, + AR5K_ANTMODE_DEFAULT = 0, /* default antenna setup */ + AR5K_ANTMODE_FIXED_A = 1, /* only antenna A is present */ + AR5K_ANTMODE_FIXED_B = 2, /* only antenna B is present */ + AR5K_ANTMODE_SINGLE_AP = 3, /* sta locked on a single ap */ + AR5K_ANTMODE_SECTOR_AP = 4, /* AP with tx antenna set on tx desc */ + AR5K_ANTMODE_SECTOR_STA = 5, /* STA with tx antenna set on tx desc */ + AR5K_ANTMODE_DEBUG = 6, /* Debug mode -A -> Rx, B-> Tx- */ AR5K_ANTMODE_MAX, }; -/** - * enum ath5k_bw_mode - Bandwidth operation mode - * @AR5K_BWMODE_DEFAULT: 20MHz, default operation - * @AR5K_BWMODE_5MHZ: Quarter rate - * @AR5K_BWMODE_10MHZ: Half rate - * @AR5K_BWMODE_40MHZ: Turbo - */ enum ath5k_bw_mode { - AR5K_BWMODE_DEFAULT = 0, - AR5K_BWMODE_5MHZ = 1, - AR5K_BWMODE_10MHZ = 2, - AR5K_BWMODE_40MHZ = 3 + AR5K_BWMODE_DEFAULT = 0, /* 20MHz, default operation */ + AR5K_BWMODE_5MHZ = 1, /* Quarter rate */ + AR5K_BWMODE_10MHZ = 2, /* Half rate */ + AR5K_BWMODE_40MHZ = 3 /* Turbo */ }; - - /****************\ TX DEFINITIONS \****************/ -/** - * struct ath5k_tx_status - TX Status descriptor - * @ts_seqnum: Sequence number - * @ts_tstamp: Timestamp - * @ts_status: Status code - * @ts_final_idx: Final transmission series index - * @ts_final_retry: Final retry count - * @ts_rssi: RSSI for received ACK - * @ts_shortretry: Short retry count - * @ts_virtcol: Virtual collision count - * @ts_antenna: Antenna used - * - * TX status descriptor gets filled by the hw - * on each transmission attempt. +/* + * TX Status descriptor */ struct ath5k_tx_status { u16 ts_seqnum; @@ -528,6 +454,7 @@ struct ath5k_tx_status { * enum ath5k_tx_queue - Queue types used to classify tx queues. * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue * @AR5K_TX_QUEUE_DATA: A normal data queue + * @AR5K_TX_QUEUE_XR_DATA: An XR-data queue * @AR5K_TX_QUEUE_BEACON: The beacon queue * @AR5K_TX_QUEUE_CAB: The after-beacon queue * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue @@ -535,6 +462,7 @@ struct ath5k_tx_status { enum ath5k_tx_queue { AR5K_TX_QUEUE_INACTIVE = 0, AR5K_TX_QUEUE_DATA, + AR5K_TX_QUEUE_XR_DATA, AR5K_TX_QUEUE_BEACON, AR5K_TX_QUEUE_CAB, AR5K_TX_QUEUE_UAPSD, @@ -543,46 +471,36 @@ enum ath5k_tx_queue { #define AR5K_NUM_TX_QUEUES 10 #define AR5K_NUM_TX_QUEUES_NOQCU 2 -/** - * enum ath5k_tx_queue_subtype - Queue sub-types to classify normal data queues - * @AR5K_WME_AC_BK: Background traffic - * @AR5K_WME_AC_BE: Best-effort (normal) traffic - * @AR5K_WME_AC_VI: Video traffic - * @AR5K_WME_AC_VO: Voice traffic - * +/* + * Queue syb-types to classify normal data queues. * These are the 4 Access Categories as defined in * WME spec. 0 is the lowest priority and 4 is the * highest. Normal data that hasn't been classified * goes to the Best Effort AC. */ enum ath5k_tx_queue_subtype { - AR5K_WME_AC_BK = 0, - AR5K_WME_AC_BE, - AR5K_WME_AC_VI, - AR5K_WME_AC_VO, + AR5K_WME_AC_BK = 0, /*Background traffic*/ + AR5K_WME_AC_BE, /*Best-effort (normal) traffic*/ + AR5K_WME_AC_VI, /*Video traffic*/ + AR5K_WME_AC_VO, /*Voice traffic*/ }; -/** - * enum ath5k_tx_queue_id - Queue ID numbers as returned by the hw functions - * @AR5K_TX_QUEUE_ID_NOQCU_DATA: Data queue on AR5210 (no QCU available) - * @AR5K_TX_QUEUE_ID_NOQCU_BEACON: Beacon queue on AR5210 (no QCU available) - * @AR5K_TX_QUEUE_ID_DATA_MIN: Data queue min index - * @AR5K_TX_QUEUE_ID_DATA_MAX: Data queue max index - * @AR5K_TX_QUEUE_ID_CAB: Content after beacon queue - * @AR5K_TX_QUEUE_ID_BEACON: Beacon queue - * @AR5K_TX_QUEUE_ID_UAPSD: Urgent Automatic Power Save Delivery, - * - * Each number represents a hw queue. If hw does not support hw queues - * (eg 5210) all data goes in one queue. +/* + * Queue ID numbers as returned by the hw functions, each number + * represents a hw queue. If hw does not support hw queues + * (eg 5210) all data goes in one queue. These match + * d80211 definitions (net80211/MadWiFi don't use them). */ enum ath5k_tx_queue_id { AR5K_TX_QUEUE_ID_NOQCU_DATA = 0, AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1, - AR5K_TX_QUEUE_ID_DATA_MIN = 0, - AR5K_TX_QUEUE_ID_DATA_MAX = 3, - AR5K_TX_QUEUE_ID_UAPSD = 7, - AR5K_TX_QUEUE_ID_CAB = 8, - AR5K_TX_QUEUE_ID_BEACON = 9, + AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/ + AR5K_TX_QUEUE_ID_DATA_MAX = 3, /*IEEE80211_TX_QUEUE_DATA3*/ + AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/ + AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/ + AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/ + AR5K_TX_QUEUE_ID_UAPSD = 8, + AR5K_TX_QUEUE_ID_XR_DATA = 9, }; /* @@ -603,70 +521,46 @@ enum ath5k_tx_queue_id { #define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */ #define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/ -/** - * struct ath5k_txq - Transmit queue state - * @qnum: Hardware q number - * @link: Link ptr in last TX desc - * @q: Transmit queue (&struct list_head) - * @lock: Lock on q and link - * @setup: Is the queue configured - * @txq_len:Number of queued buffers - * @txq_max: Max allowed num of queued buffers - * @txq_poll_mark: Used to check if queue got stuck - * @txq_stuck: Queue stuck counter - * - * One of these exists for each hardware transmit queue. - * Packets sent to us from above are assigned to queues based - * on their priority. Not all devices support a complete set - * of hardware transmit queues. For those devices the array - * sc_ac2q will map multiple priorities to fewer hardware queues - * (typically all to one hardware queue). +/* + * Data transmit queue state. One of these exists for each + * hardware transmit queue. Packets sent to us from above + * are assigned to queues based on their priority. Not all + * devices support a complete set of hardware transmit queues. + * For those devices the array sc_ac2q will map multiple + * priorities to fewer hardware queues (typically all to one + * hardware queue). */ struct ath5k_txq { - unsigned int qnum; - u32 *link; - struct list_head q; - spinlock_t lock; + unsigned int qnum; /* hardware q number */ + u32 *link; /* link ptr in last TX desc */ + struct list_head q; /* transmit queue */ + spinlock_t lock; /* lock on q and link */ bool setup; - int txq_len; - int txq_max; + int txq_len; /* number of queued buffers */ + int txq_max; /* max allowed num of queued buffers */ bool txq_poll_mark; - unsigned int txq_stuck; + unsigned int txq_stuck; /* informational counter */ }; -/** - * struct ath5k_txq_info - A struct to hold TX queue's parameters - * @tqi_type: One of enum ath5k_tx_queue - * @tqi_subtype: One of enum ath5k_tx_queue_subtype - * @tqi_flags: TX queue flags (see above) - * @tqi_aifs: Arbitrated Inter-frame Space - * @tqi_cw_min: Minimum Contention Window - * @tqi_cw_max: Maximum Contention Window - * @tqi_cbr_period: Constant bit rate period - * @tqi_ready_time: Time queue waits after an event when RDYTIME is enabled +/* + * A struct to hold tx queue's parameters */ struct ath5k_txq_info { enum ath5k_tx_queue tqi_type; enum ath5k_tx_queue_subtype tqi_subtype; - u16 tqi_flags; - u8 tqi_aifs; - u16 tqi_cw_min; - u16 tqi_cw_max; - u32 tqi_cbr_period; + u16 tqi_flags; /* Tx queue flags (see above) */ + u8 tqi_aifs; /* Arbitrated Interframe Space */ + u16 tqi_cw_min; /* Minimum Contention Window */ + u16 tqi_cw_max; /* Maximum Contention Window */ + u32 tqi_cbr_period; /* Constant bit rate period */ u32 tqi_cbr_overflow_limit; u32 tqi_burst_time; - u32 tqi_ready_time; + u32 tqi_ready_time; /* Time queue waits after an event */ }; -/** - * enum ath5k_pkt_type - Transmit packet types - * @AR5K_PKT_TYPE_NORMAL: Normal data - * @AR5K_PKT_TYPE_ATIM: ATIM - * @AR5K_PKT_TYPE_PSPOLL: PS-Poll - * @AR5K_PKT_TYPE_BEACON: Beacon - * @AR5K_PKT_TYPE_PROBE_RESP: Probe response - * @AR5K_PKT_TYPE_PIFS: PIFS - * Used on tx control descriptor +/* + * Transmit packet types. + * used on tx control descriptor */ enum ath5k_pkt_type { AR5K_PKT_TYPE_NORMAL = 0, @@ -689,23 +583,27 @@ enum ath5k_pkt_type { (ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \ ) +/* + * DMA size definitions (2^(n+2)) + */ +enum ath5k_dmasize { + AR5K_DMASIZE_4B = 0, + AR5K_DMASIZE_8B, + AR5K_DMASIZE_16B, + AR5K_DMASIZE_32B, + AR5K_DMASIZE_64B, + AR5K_DMASIZE_128B, + AR5K_DMASIZE_256B, + AR5K_DMASIZE_512B +}; /****************\ RX DEFINITIONS \****************/ -/** - * struct ath5k_rx_status - RX Status descriptor - * @rs_datalen: Data length - * @rs_tstamp: Timestamp - * @rs_status: Status code - * @rs_phyerr: PHY error mask - * @rs_rssi: RSSI in 0.5dbm units - * @rs_keyix: Index to the key used for decrypting - * @rs_rate: Rate used to decode the frame - * @rs_antenna: Antenna used to receive the frame - * @rs_more: Indicates this is a frame fragment (Fast frames) +/* + * RX Status descriptor */ struct ath5k_rx_status { u16 rs_datalen; @@ -747,18 +645,10 @@ struct ath5k_rx_status { #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) - /*******************************\ GAIN OPTIMIZATION DEFINITIONS \*******************************/ -/** - * enum ath5k_rfgain - RF Gain optimization engine state - * @AR5K_RFGAIN_INACTIVE: Engine disabled - * @AR5K_RFGAIN_ACTIVE: Probe active - * @AR5K_RFGAIN_READ_REQUESTED: Probe requested - * @AR5K_RFGAIN_NEED_CHANGE: Gain_F needs change - */ enum ath5k_rfgain { AR5K_RFGAIN_INACTIVE = 0, AR5K_RFGAIN_ACTIVE, @@ -766,16 +656,6 @@ enum ath5k_rfgain { AR5K_RFGAIN_NEED_CHANGE, }; -/** - * struct ath5k_gain - RF Gain optimization engine state data - * @g_step_idx: Current step index - * @g_current: Current gain - * @g_target: Target gain - * @g_low: Low gain boundary - * @g_high: High gain boundary - * @g_f_corr: Gain_F correction - * @g_state: One of enum ath5k_rfgain - */ struct ath5k_gain { u8 g_step_idx; u8 g_current; @@ -786,8 +666,6 @@ struct ath5k_gain { u8 g_state; }; - - /********************\ COMMON DEFINITIONS \********************/ @@ -796,14 +674,9 @@ struct ath5k_gain { #define AR5K_SLOT_TIME_20 880 #define AR5K_SLOT_TIME_MAX 0xffff -/** - * struct ath5k_athchan_2ghz - 2GHz to 5GHZ map for RF5111 - * @a2_flags: Channel flags (internal) - * @a2_athchan: HW channel number (internal) - * - * This structure is used to map 2GHz channels to - * 5GHz Atheros channels on 2111 frequency converter - * that comes together with RF5111 +/* + * The following structure is used to map 2GHz channels to + * 5GHz Atheros channels. * TODO: Clean up */ struct ath5k_athchan_2ghz { @@ -811,80 +684,36 @@ struct ath5k_athchan_2ghz { u16 a2_athchan; }; -/** - * enum ath5k_dmasize - DMA size definitions (2^(n+2)) - * @AR5K_DMASIZE_4B: 4Bytes - * @AR5K_DMASIZE_8B: 8Bytes - * @AR5K_DMASIZE_16B: 16Bytes - * @AR5K_DMASIZE_32B: 32Bytes - * @AR5K_DMASIZE_64B: 64Bytes (Default) - * @AR5K_DMASIZE_128B: 128Bytes - * @AR5K_DMASIZE_256B: 256Bytes - * @AR5K_DMASIZE_512B: 512Bytes - * - * These are used to set DMA burst size on hw - * - * Note: Some platforms can't handle more than 4Bytes - * be careful on embedded boards. - */ -enum ath5k_dmasize { - AR5K_DMASIZE_4B = 0, - AR5K_DMASIZE_8B, - AR5K_DMASIZE_16B, - AR5K_DMASIZE_32B, - AR5K_DMASIZE_64B, - AR5K_DMASIZE_128B, - AR5K_DMASIZE_256B, - AR5K_DMASIZE_512B -}; - - /******************\ RATE DEFINITIONS \******************/ /** - * DOC: Rate codes - * * Seems the ar5xxx hardware supports up to 32 rates, indexed by 1-32. * * The rate code is used to get the RX rate or set the TX rate on the * hardware descriptors. It is also used for internal modulation control * and settings. * - * This is the hardware rate map we are aware of (html unfriendly): + * This is the hardware rate map we are aware of: + * + * rate_code 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 + * rate_kbps 3000 1000 ? ? ? 2000 500 48000 + * + * rate_code 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 + * rate_kbps 24000 12000 6000 54000 36000 18000 9000 ? * - * Rate code Rate (Kbps) - * --------- ----------- - * 0x01 3000 (XR) - * 0x02 1000 (XR) - * 0x03 250 (XR) - * 0x04 - 05 -Reserved- - * 0x06 2000 (XR) - * 0x07 500 (XR) - * 0x08 48000 (OFDM) - * 0x09 24000 (OFDM) - * 0x0A 12000 (OFDM) - * 0x0B 6000 (OFDM) - * 0x0C 54000 (OFDM) - * 0x0D 36000 (OFDM) - * 0x0E 18000 (OFDM) - * 0x0F 9000 (OFDM) - * 0x10 - 17 -Reserved- - * 0x18 11000L (CCK) - * 0x19 5500L (CCK) - * 0x1A 2000L (CCK) - * 0x1B 1000L (CCK) - * 0x1C 11000S (CCK) - * 0x1D 5500S (CCK) - * 0x1E 2000S (CCK) - * 0x1F -Reserved- + * rate_code 17 18 19 20 21 22 23 24 + * rate_kbps ? ? ? ? ? ? ? 11000 * - * "S" indicates CCK rates with short preamble and "L" with long preamble. + * rate_code 25 26 27 28 29 30 31 32 + * rate_kbps 5500 2000 1000 11000S 5500S 2000S ? ? + * + * "S" indicates CCK rates with short preamble. * * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the - * lowest 4 bits, so they are the same as above with a 0xF mask. + * lowest 4 bits, so they are the same as below with a 0xF mask. * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M). * We handle this in ath5k_setup_bands(). */ @@ -904,9 +733,13 @@ enum ath5k_dmasize { #define ATH5K_RATE_CODE_36M 0x0D #define ATH5K_RATE_CODE_48M 0x08 #define ATH5K_RATE_CODE_54M 0x0C +/* XR */ +#define ATH5K_RATE_CODE_XR_500K 0x07 +#define ATH5K_RATE_CODE_XR_1M 0x02 +#define ATH5K_RATE_CODE_XR_2M 0x06 +#define ATH5K_RATE_CODE_XR_3M 0x01 -/* Adding this flag to rate_code on B rates - * enables short preamble */ +/* adding this flag to rate_code enables short preamble */ #define AR5K_SET_SHORT_PREAMBLE 0x04 /* @@ -936,65 +769,49 @@ extern int ath5k_modparam_nohwcrypt; /** * enum ath5k_int - Hardware interrupt masks helpers - * @AR5K_INT_RXOK: Frame successfully received - * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor - * @AR5K_INT_RXERR: Frame reception failed - * @AR5K_INT_RXNOFRM: No frame received within a specified time period - * @AR5K_INT_RXEOL: Reached "End Of List", means we need more RX descriptors - * @AR5K_INT_RXORN: Indicates we got RX FIFO overrun. Note that Rx overrun is - * not always fatal, on some chips we can continue operation - * without resetting the card, that's why %AR5K_INT_FATAL is not - * common for all chips. - * @AR5K_INT_RX_ALL: Mask to identify all RX related interrupts - * - * @AR5K_INT_TXOK: Frame transmission success - * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor - * @AR5K_INT_TXERR: Frame transmission failure - * @AR5K_INT_TXEOL: Received End Of List for VEOL (Virtual End Of List). The - * Queue Control Unit (QCU) signals an EOL interrupt only if a - * descriptor's LinkPtr is NULL. For more details, refer to: - * "http://www.freepatentsonline.com/20030225739.html" - * @AR5K_INT_TXNOFRM: No frame was transmitted within a specified time period - * @AR5K_INT_TXURN: Indicates we got TX FIFO underrun. In such case we should - * increase the TX trigger threshold. - * @AR5K_INT_TX_ALL: Mask to identify all TX related interrupts * + * @AR5K_INT_RX: mask to identify received frame interrupts, of type + * AR5K_ISR_RXOK or AR5K_ISR_RXERR + * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?) + * @AR5K_INT_RXNOFRM: No frame received (?) + * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The + * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's + * LinkPtr is NULL. For more details, refer to: + * http://www.freepatentsonline.com/20030225739.html + * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors). + * Note that Rx overrun is not always fatal, on some chips we can continue + * operation without resetting the card, that's why int_fatal is not + * common for all chips. + * @AR5K_INT_TX: mask to identify received frame interrupts, of type + * AR5K_ISR_TXOK or AR5K_ISR_TXERR + * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?) + * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold + * We currently do increments on interrupt by + * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 * @AR5K_INT_MIB: Indicates the either Management Information Base counters or - * one of the PHY error counters reached the maximum value and - * should be read and cleared. - * @AR5K_INT_SWI: Software triggered interrupt. + * one of the PHY error counters reached the maximum value and should be + * read and cleared. * @AR5K_INT_RXPHY: RX PHY Error * @AR5K_INT_RXKCM: RX Key cache miss * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a - * beacon that must be handled in software. The alternative is if - * you have VEOL support, in that case you let the hardware deal - * with things. - * @AR5K_INT_BRSSI: Beacon received with an RSSI value below our threshold + * beacon that must be handled in software. The alternative is if you + * have VEOL support, in that case you let the hardware deal with things. * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing - * beacons from the AP have associated with, we should probably - * try to reassociate. When in IBSS mode this might mean we have - * not received any beacons from any local stations. Note that - * every station in an IBSS schedules to send beacons at the - * Target Beacon Transmission Time (TBTT) with a random backoff. - * @AR5K_INT_BNR: Beacon queue got triggered (DMA beacon alert) while empty. - * @AR5K_INT_TIM: Beacon with local station's TIM bit set - * @AR5K_INT_DTIM: Beacon with DTIM bit and zero DTIM count received - * @AR5K_INT_DTIM_SYNC: DTIM sync lost - * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill switches connected to - * our GPIO pins. - * @AR5K_INT_BCN_TIMEOUT: Beacon timeout, we waited after TBTT but got noting - * @AR5K_INT_CAB_TIMEOUT: We waited for CAB traffic after the beacon but got - * nothing or an incomplete CAB frame sequence. - * @AR5K_INT_QCBRORN: A queue got it's CBR counter expired - * @AR5K_INT_QCBRURN: A queue got triggered wile empty - * @AR5K_INT_QTRIG: A queue got triggered - * - * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by bus/DMA - * errors. Indicates we need to reset the card. + * beacons from the AP have associated with, we should probably try to + * reassociate. When in IBSS mode this might mean we have not received + * any beacons from any local stations. Note that every station in an + * IBSS schedules to send beacons at the Target Beacon Transmission Time + * (TBTT) with a random backoff. + * @AR5K_INT_BNR: Beacon Not Ready interrupt - ?? + * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now + * until properly handled + * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA + * errors. These types of errors we can enable seem to be of type + * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR. * @AR5K_INT_GLOBAL: Used to clear and set the IER - * @AR5K_INT_NOCARD: Signals the card has been removed - * @AR5K_INT_COMMON: Common interrupts shared among MACs with the same - * bit value + * @AR5K_INT_NOCARD: signals the card has been removed + * @AR5K_INT_COMMON: common interrupts shared among MACs with the same + * bit value * * These are mapped to take advantage of some common bits * between the MACs, to be able to set intr properties @@ -1030,15 +847,15 @@ enum ath5k_int { AR5K_INT_GPIO = 0x01000000, AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */ AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */ - AR5K_INT_QCBRORN = 0x08000000, /* Non common */ - AR5K_INT_QCBRURN = 0x10000000, /* Non common */ - AR5K_INT_QTRIG = 0x20000000, /* Non common */ + AR5K_INT_RX_DOPPLER = 0x08000000, /* Non common */ + AR5K_INT_QCBRORN = 0x10000000, /* Non common */ + AR5K_INT_QCBRURN = 0x20000000, /* Non common */ + AR5K_INT_QTRIG = 0x40000000, /* Non common */ AR5K_INT_GLOBAL = 0x80000000, AR5K_INT_TX_ALL = AR5K_INT_TXOK | AR5K_INT_TXDESC | AR5K_INT_TXERR - | AR5K_INT_TXNOFRM | AR5K_INT_TXEOL | AR5K_INT_TXURN, @@ -1074,32 +891,15 @@ enum ath5k_int { AR5K_INT_NOCARD = 0xffffffff }; -/** - * enum ath5k_calibration_mask - Mask which calibration is active at the moment - * @AR5K_CALIBRATION_FULL: Full calibration (AGC + SHORT) - * @AR5K_CALIBRATION_SHORT: Short calibration (NF + I/Q) - * @AR5K_CALIBRATION_NF: Noise Floor calibration - * @AR5K_CALIBRATION_ANI: Adaptive Noise Immunity - */ +/* mask which calibration is active at the moment */ enum ath5k_calibration_mask { AR5K_CALIBRATION_FULL = 0x01, AR5K_CALIBRATION_SHORT = 0x02, - AR5K_CALIBRATION_NF = 0x04, - AR5K_CALIBRATION_ANI = 0x08, + AR5K_CALIBRATION_ANI = 0x04, }; -/** - * enum ath5k_power_mode - Power management modes - * @AR5K_PM_UNDEFINED: Undefined - * @AR5K_PM_AUTO: Allow card to sleep if possible - * @AR5K_PM_AWAKE: Force card to wake up - * @AR5K_PM_FULL_SLEEP: Force card to full sleep (DANGEROUS) - * @AR5K_PM_NETWORK_SLEEP: Allow to sleep for a specified duration - * - * Currently only PM_AWAKE is used, FULL_SLEEP and NETWORK_SLEEP/AUTO - * are also known to have problems on some cards. This is not a big - * problem though because we can have almost the same effect as - * FULL_SLEEP by putting card on warm reset (it's almost powered down). +/* + * Power management */ enum ath5k_power_mode { AR5K_PM_UNDEFINED = 0, @@ -1157,8 +957,6 @@ struct ath5k_capabilities { } cap_queues; bool cap_has_phyerr_counters; - bool cap_has_mrr_support; - bool cap_needs_2GHz_ovr; }; /* size of noise floor history (keep it a power of two) */ @@ -1274,11 +1072,13 @@ struct ath5k_hw { dma_addr_t desc_daddr; /* DMA (physical) address */ size_t desc_len; /* size of TX/RX descriptors */ - DECLARE_BITMAP(status, 4); + DECLARE_BITMAP(status, 6); #define ATH_STAT_INVALID 0 /* disable hardware accesses */ -#define ATH_STAT_PROMISC 1 -#define ATH_STAT_LEDSOFT 2 /* enable LED gpio status */ -#define ATH_STAT_STARTED 3 /* opened & irqs enabled */ +#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ +#define ATH_STAT_PROMISC 2 +#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ +#define ATH_STAT_STARTED 4 /* opened & irqs enabled */ +#define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */ unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ struct ieee80211_channel *curchan; /* current h/w channel */ @@ -1297,7 +1097,6 @@ struct ath5k_hw { led_on; /* pin setting for LED on */ struct work_struct reset_work; /* deferred chip reset */ - struct work_struct calib_work; /* deferred phy calibration */ struct list_head rxbuf; /* receive buffer */ spinlock_t rxbuflock; @@ -1314,6 +1113,8 @@ struct ath5k_hw { struct ath5k_rfkill rf_kill; + struct tasklet_struct calib; /* calibration tasklet */ + spinlock_t block; /* protects beacon */ struct tasklet_struct beacontq; /* beacon intr tasklet */ struct list_head bcbuf; /* beacon buffer */ @@ -1343,7 +1144,7 @@ struct ath5k_hw { enum ath5k_int ah_imr; struct ieee80211_channel *ah_current_channel; - bool ah_iq_cal_needed; + bool ah_calibration; bool ah_single_chip; enum ath5k_version ah_version; @@ -1386,13 +1187,7 @@ struct ath5k_hw { u32 ah_txq_imr_cbrurn; u32 ah_txq_imr_qtrig; u32 ah_txq_imr_nofrm; - - u32 ah_txq_isr_txok_all; - u32 ah_txq_isr_txurn; - u32 ah_txq_isr_qcborn; - u32 ah_txq_isr_qcburn; - u32 ah_txq_isr_qtrig; - + u32 ah_txq_isr; u32 *ah_rf_banks; size_t ah_rf_banks_size; size_t ah_rf_regs_count; @@ -1433,8 +1228,8 @@ struct ath5k_hw { /* Calibration timestamp */ unsigned long ah_cal_next_full; - unsigned long ah_cal_next_short; unsigned long ah_cal_next_ani; + unsigned long ah_cal_next_nf; /* Calibration mask */ u8 ah_cal_mask; @@ -1543,11 +1338,11 @@ void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); void ath5k_hw_reset_tsf(struct ath5k_hw *ah); -void ath5k_hw_init_beacon_timers(struct ath5k_hw *ah, u32 next_beacon, - u32 interval); +void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); /* Init function */ -void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode); +void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, + u8 mode); /* Queue Control Unit, DFS Control Unit Functions */ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, diff --git a/trunk/drivers/net/wireless/ath/ath5k/attach.c b/trunk/drivers/net/wireless/ath/ath5k/attach.c index d7114c75fe9b..91627dd2c26a 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/attach.c +++ b/trunk/drivers/net/wireless/ath/ath5k/attach.c @@ -27,7 +27,8 @@ #include "debug.h" /** - * ath5k_hw_post() - Power On Self Test helper function + * ath5k_hw_post - Power On Self Test helper function + * * @ah: The &struct ath5k_hw */ static int ath5k_hw_post(struct ath5k_hw *ah) @@ -91,7 +92,8 @@ static int ath5k_hw_post(struct ath5k_hw *ah) } /** - * ath5k_hw_init() - Check if hw is supported and init the needed structs + * ath5k_hw_init - Check if hw is supported and init the needed structs + * * @ah: The &struct ath5k_hw associated with the device * * Check if the device is supported, perform a POST and initialize the needed @@ -296,7 +298,7 @@ int ath5k_hw_init(struct ath5k_hw *ah) /* Reset SERDES to load new settings */ ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET); - usleep_range(1000, 1500); + mdelay(1); } /* Get misc capabilities */ @@ -306,6 +308,11 @@ int ath5k_hw_init(struct ath5k_hw *ah) goto err; } + if (test_bit(ATH_STAT_2G_DISABLED, ah->status)) { + __clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode); + __clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode); + } + /* Crypto settings */ common->keymax = (ah->ah_version == AR5K_AR5210 ? AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211); @@ -342,7 +349,8 @@ int ath5k_hw_init(struct ath5k_hw *ah) } /** - * ath5k_hw_deinit() - Free the &struct ath5k_hw + * ath5k_hw_deinit - Free the ath5k_hw struct + * * @ah: The &struct ath5k_hw */ void ath5k_hw_deinit(struct ath5k_hw *ah) diff --git a/trunk/drivers/net/wireless/ath/ath5k/base.c b/trunk/drivers/net/wireless/ath/ath5k/base.c index 178a4dd10316..b346d0492001 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/base.c +++ b/trunk/drivers/net/wireless/ath/ath5k/base.c @@ -80,11 +80,6 @@ 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."); -static int ath5k_modparam_no_hw_rfkill_switch; -module_param_named(no_hw_rfkill_switch, ath5k_modparam_no_hw_rfkill_switch, - bool, S_IRUGO); -MODULE_PARM_DESC(no_hw_rfkill_switch, "Ignore the GPIO RFKill switch state"); - /* Module info */ MODULE_AUTHOR("Jiri Slaby"); @@ -188,6 +183,7 @@ static const struct ieee80211_rate ath5k_rates[] = { { .bitrate = 540, .hw_value = ATH5K_RATE_CODE_54M, .flags = 0 }, + /* XR missing */ }; static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) @@ -725,25 +721,22 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, if (ret) goto err_unmap; - /* Set up MRR descriptor */ - if (ah->ah_capabilities.cap_has_mrr_support) { - memset(mrr_rate, 0, sizeof(mrr_rate)); - memset(mrr_tries, 0, sizeof(mrr_tries)); - for (i = 0; i < 3; i++) { - rate = ieee80211_get_alt_retry_rate(ah->hw, info, i); - if (!rate) - break; - - mrr_rate[i] = rate->hw_value; - mrr_tries[i] = info->control.rates[i + 1].count; - } + memset(mrr_rate, 0, sizeof(mrr_rate)); + memset(mrr_tries, 0, sizeof(mrr_tries)); + for (i = 0; i < 3; i++) { + rate = ieee80211_get_alt_retry_rate(ah->hw, info, i); + if (!rate) + break; - ath5k_hw_setup_mrr_tx_desc(ah, ds, - mrr_rate[0], mrr_tries[0], - mrr_rate[1], mrr_tries[1], - mrr_rate[2], mrr_tries[2]); + mrr_rate[i] = rate->hw_value; + mrr_tries[i] = info->control.rates[i + 1].count; } + ath5k_hw_setup_mrr_tx_desc(ah, ds, + mrr_rate[0], mrr_tries[0], + mrr_rate[1], mrr_tries[1], + mrr_rate[2], mrr_tries[2]); + ds->ds_link = 0; ds->ds_data = bf->skbaddr; @@ -1696,7 +1689,7 @@ ath5k_tasklet_tx(unsigned long data) struct ath5k_hw *ah = (void *)data; for (i = 0; i < AR5K_NUM_TX_QUEUES; i++) - if (ah->txqs[i].setup && (ah->ah_txq_isr_txok_all & BIT(i))) + if (ah->txqs[i].setup && (ah->ah_txq_isr & BIT(i))) ath5k_tx_processq(ah, &ah->txqs[i]); ah->tx_pending = false; @@ -2012,7 +2005,7 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf) ah->nexttbtt = nexttbtt; intval |= AR5K_BEACON_ENA; - ath5k_hw_init_beacon_timers(ah, nexttbtt, intval); + ath5k_hw_init_beacon(ah, nexttbtt, intval); /* * debugging output last in order to preserve the time critical aspect @@ -2119,29 +2112,16 @@ static void ath5k_intr_calibration_poll(struct ath5k_hw *ah) { if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) && - !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL) && - !(ah->ah_cal_mask & AR5K_CALIBRATION_SHORT)) { - - /* Run ANI only when calibration is not active */ - + !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) { + /* run ANI only when full calibration is not active */ ah->ah_cal_next_ani = jiffies + msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI); tasklet_schedule(&ah->ani_tasklet); - } else if (time_is_before_eq_jiffies(ah->ah_cal_next_short) && - !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL) && - !(ah->ah_cal_mask & AR5K_CALIBRATION_SHORT)) { - - /* Run calibration only when another calibration - * is not running. - * - * Note: This is for both full/short calibration, - * if it's time for a full one, ath5k_calibrate_work will deal - * with it. */ - - ah->ah_cal_next_short = jiffies + - msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_SHORT); - ieee80211_queue_work(ah->hw, &ah->calib_work); + } else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { + ah->ah_cal_next_full = jiffies + + msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); + tasklet_schedule(&ah->calib); } /* we could use SWI to generate enough interrupts to meet our * calibration interval requirements, if necessary: @@ -2169,110 +2149,69 @@ ath5k_intr(int irq, void *dev_id) enum ath5k_int status; unsigned int counter = 1000; - - /* - * If hw is not ready (or detached) and we get an - * interrupt, or if we have no interrupts pending - * (that means it's not for us) skip it. - * - * NOTE: Group 0/1 PCI interface registers are not - * supported on WiSOCs, so we can't check for pending - * interrupts (ISR belongs to another register group - * so we are ok). - */ if (unlikely(test_bit(ATH_STAT_INVALID, ah->status) || - ((ath5k_get_bus_type(ah) != ATH_AHB) && - !ath5k_hw_is_intr_pending(ah)))) + ((ath5k_get_bus_type(ah) != ATH_AHB) && + !ath5k_hw_is_intr_pending(ah)))) return IRQ_NONE; - /** Main loop **/ do { - ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */ - + ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */ ATH5K_DBG(ah, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n", status, ah->imask); - - /* - * Fatal hw error -> Log and reset - * - * Fatal errors are unrecoverable so we have to - * reset the card. These errors include bus and - * dma errors. - */ if (unlikely(status & AR5K_INT_FATAL)) { - + /* + * Fatal errors are unrecoverable. + * Typically these are caused by DMA errors. + */ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "fatal int, resetting\n"); ieee80211_queue_work(ah->hw, &ah->reset_work); - - /* - * RX Overrun -> Count and reset if needed - * - * Receive buffers are full. Either the bus is busy or - * the CPU is not fast enough to process all received - * frames. - */ } else if (unlikely(status & AR5K_INT_RXORN)) { - /* + * Receive buffers are full. Either the bus is busy or + * the CPU is not fast enough to process all received + * frames. * Older chipsets need a reset to come out of this * condition, but we treat it as RX for newer chips. - * We don't know exactly which versions need a reset + * We don't know exactly which versions need a reset - * this guess is copied from the HAL. */ ah->stats.rxorn_intr++; - if (ah->ah_mac_srev < AR5K_SREV_AR5212) { ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "rx overrun, resetting\n"); ieee80211_queue_work(ah->hw, &ah->reset_work); } else ath5k_schedule_rx(ah); - } else { - - /* Software Beacon Alert -> Schedule beacon tasklet */ if (status & AR5K_INT_SWBA) tasklet_hi_schedule(&ah->beacontq); - /* - * No more RX descriptors -> Just count - * - * NB: the hardware should re-read the link when - * RXE bit is written, but it doesn't work at - * least on older hardware revs. - */ - if (status & AR5K_INT_RXEOL) + if (status & AR5K_INT_RXEOL) { + /* + * NB: the hardware should re-read the link when + * RXE bit is written, but it doesn't work at + * least on older hardware revs. + */ ah->stats.rxeol_intr++; - - - /* TX Underrun -> Bump tx trigger level */ - if (status & AR5K_INT_TXURN) + } + if (status & AR5K_INT_TXURN) { + /* bump tx trigger level */ ath5k_hw_update_tx_triglevel(ah, true); - - /* RX -> Schedule rx tasklet */ + } if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) ath5k_schedule_rx(ah); - - /* TX -> Schedule tx tasklet */ - if (status & (AR5K_INT_TXOK - | AR5K_INT_TXDESC - | AR5K_INT_TXERR - | AR5K_INT_TXEOL)) + if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC + | AR5K_INT_TXERR | AR5K_INT_TXEOL)) ath5k_schedule_tx(ah); - - /* Missed beacon -> TODO - if (status & AR5K_INT_BMISS) - */ - - /* MIB event -> Update counters and notify ANI */ + if (status & AR5K_INT_BMISS) { + /* TODO */ + } if (status & AR5K_INT_MIB) { ah->stats.mib_intr++; ath5k_hw_update_mib_counters(ah); ath5k_ani_mib_intr(ah); } - - /* GPIO -> Notify RFKill layer */ if (status & AR5K_INT_GPIO) tasklet_schedule(&ah->rf_kill.toggleq); @@ -2283,19 +2222,12 @@ ath5k_intr(int irq, void *dev_id) } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); - /* - * Until we handle rx/tx interrupts mask them on IMR - * - * NOTE: ah->(rx/tx)_pending are set when scheduling the tasklets - * and unset after we 've handled the interrupts. - */ if (ah->rx_pending || ah->tx_pending) ath5k_set_current_imask(ah); if (unlikely(!counter)) ATH5K_WARN(ah, "too many interrupts, giving up for now\n"); - /* Fire up calibration poll */ ath5k_intr_calibration_poll(ah); return IRQ_HANDLED; @@ -2306,58 +2238,41 @@ ath5k_intr(int irq, void *dev_id) * for temperature/environment changes. */ static void -ath5k_calibrate_work(struct work_struct *work) +ath5k_tasklet_calibrate(unsigned long data) { - struct ath5k_hw *ah = container_of(work, struct ath5k_hw, - calib_work); - - /* Should we run a full calibration ? */ - if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { - - ah->ah_cal_next_full = jiffies + - msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); - ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; - - ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, - "running full calibration\n"); - - if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) { - /* - * Rfgain is out of bounds, reset the chip - * to load new gain values. - */ - ATH5K_DBG(ah, ATH5K_DEBUG_RESET, - "got new rfgain, resetting\n"); - ieee80211_queue_work(ah->hw, &ah->reset_work); - } - - /* TODO: On full calibration we should stop TX here, - * so that it doesn't interfere (mostly due to gain_f - * calibration that messes with tx packets -see phy.c). - * - * NOTE: Stopping the queues from above is not enough - * to stop TX but saves us from disconecting (at least - * we don't lose packets). */ - ieee80211_stop_queues(ah->hw); - } else - ah->ah_cal_mask |= AR5K_CALIBRATION_SHORT; + struct ath5k_hw *ah = (void *)data; + /* Only full calibration for now */ + ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", ieee80211_frequency_to_channel(ah->curchan->center_freq), ah->curchan->hw_value); + if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) { + /* + * Rfgain is out of bounds, reset the chip + * to load new gain values. + */ + ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "calibration, resetting\n"); + ieee80211_queue_work(ah->hw, &ah->reset_work); + } if (ath5k_hw_phy_calibrate(ah, ah->curchan)) ATH5K_ERR(ah, "calibration of channel %u failed\n", ieee80211_frequency_to_channel( ah->curchan->center_freq)); - /* Clear calibration flags */ - if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) { - ieee80211_wake_queues(ah->hw); - ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; - } else if (ah->ah_cal_mask & AR5K_CALIBRATION_SHORT) - ah->ah_cal_mask &= ~AR5K_CALIBRATION_SHORT; + /* Noise floor calibration interrupts rx/tx path while I/Q calibration + * doesn't. + * TODO: We should stop TX here, so that it doesn't interfere. + * Note that stopping the queues is not enough to stop TX! */ + if (time_is_before_eq_jiffies(ah->ah_cal_next_nf)) { + ah->ah_cal_next_nf = jiffies + + msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_NF); + ath5k_hw_update_noise_floor(ah); + } + + ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; } @@ -2492,8 +2407,8 @@ ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops) if (ret) goto err_irq; - /* Set up multi-rate retry capabilities */ - if (ah->ah_capabilities.cap_has_mrr_support) { + /* set up multi-rate retry capabilities */ + if (ah->ah_version == AR5K_AR5212) { hw->max_rates = 4; hw->max_rate_tries = max(AR5K_INIT_RETRY_SHORT, AR5K_INIT_RETRY_LONG); @@ -2629,22 +2544,15 @@ int ath5k_start(struct ieee80211_hw *hw) * and then setup of the interrupt mask. */ ah->curchan = ah->hw->conf.channel; - ah->imask = AR5K_INT_RXOK - | AR5K_INT_RXERR - | AR5K_INT_RXEOL - | AR5K_INT_RXORN - | AR5K_INT_TXDESC - | AR5K_INT_TXEOL - | AR5K_INT_FATAL - | AR5K_INT_GLOBAL - | AR5K_INT_MIB; + ah->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | + AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | + AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; ret = ath5k_reset(ah, NULL, false); if (ret) goto done; - if (!ath5k_modparam_no_hw_rfkill_switch) - ath5k_rfkill_hw_start(ah); + ath5k_rfkill_hw_start(ah); /* * Reset the key cache since some parts do not reset the @@ -2677,6 +2585,7 @@ static void ath5k_stop_tasklets(struct ath5k_hw *ah) ah->tx_pending = false; tasklet_kill(&ah->rxtq); tasklet_kill(&ah->txtq); + tasklet_kill(&ah->calib); tasklet_kill(&ah->beacontq); tasklet_kill(&ah->ani_tasklet); } @@ -2728,8 +2637,7 @@ void ath5k_stop(struct ieee80211_hw *hw) cancel_delayed_work_sync(&ah->tx_complete_work); - if (!ath5k_modparam_no_hw_rfkill_switch) - ath5k_rfkill_hw_stop(ah); + ath5k_rfkill_hw_stop(ah); } /* @@ -2781,24 +2689,9 @@ ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan, ath5k_ani_init(ah, ani_mode); - /* - * Set calibration intervals - * - * Note: We don't need to run calibration imediately - * since some initial calibration is done on reset - * even for fast channel switching. Also on scanning - * this will get set again and again and it won't get - * executed unless we connect somewhere and spend some - * time on the channel (that's what calibration needs - * anyway to be accurate). - */ - ah->ah_cal_next_full = jiffies + - msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); - ah->ah_cal_next_ani = jiffies + - msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI); - ah->ah_cal_next_short = jiffies + - msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_SHORT); - + ah->ah_cal_next_full = jiffies + msecs_to_jiffies(100); + ah->ah_cal_next_ani = jiffies; + ah->ah_cal_next_nf = jiffies; ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8); /* clear survey data and cycle counters */ @@ -2851,6 +2744,20 @@ ath5k_init(struct ieee80211_hw *hw) int ret; + /* + * Check if the MAC has multi-rate retry support. + * We do this by trying to setup a fake extended + * descriptor. MACs that don't have support will + * return false w/o doing anything. MACs that do + * support it will return true w/o doing anything. + */ + ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); + + if (ret < 0) + goto err; + if (ret > 0) + __set_bit(ATH_STAT_MRRETRY, ah->status); + /* * Collect the channel list. The 802.11 layer * is responsible for filtering this list based @@ -2934,11 +2841,11 @@ ath5k_init(struct ieee80211_hw *hw) tasklet_init(&ah->rxtq, ath5k_tasklet_rx, (unsigned long)ah); tasklet_init(&ah->txtq, ath5k_tasklet_tx, (unsigned long)ah); + tasklet_init(&ah->calib, ath5k_tasklet_calibrate, (unsigned long)ah); tasklet_init(&ah->beacontq, ath5k_tasklet_beacon, (unsigned long)ah); tasklet_init(&ah->ani_tasklet, ath5k_tasklet_ani, (unsigned long)ah); INIT_WORK(&ah->reset_work, ath5k_reset_work); - INIT_WORK(&ah->calib_work, ath5k_calibrate_work); INIT_DELAYED_WORK(&ah->tx_complete_work, ath5k_tx_complete_poll_work); ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac); diff --git a/trunk/drivers/net/wireless/ath/ath5k/caps.c b/trunk/drivers/net/wireless/ath/ath5k/caps.c index 994169ad39cb..810fba96702b 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/caps.c +++ b/trunk/drivers/net/wireless/ath/ath5k/caps.c @@ -85,19 +85,12 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) caps->cap_range.range_2ghz_min = 2412; caps->cap_range.range_2ghz_max = 2732; - /* Override 2GHz modes on SoCs that need it - * NOTE: cap_needs_2GHz_ovr gets set from - * ath_ahb_probe */ - if (!caps->cap_needs_2GHz_ovr) { - if (AR5K_EEPROM_HDR_11B(ee_header)) - __set_bit(AR5K_MODE_11B, - caps->cap_mode); - - if (AR5K_EEPROM_HDR_11G(ee_header) && - ah->ah_version != AR5K_AR5211) - __set_bit(AR5K_MODE_11G, - caps->cap_mode); - } + if (AR5K_EEPROM_HDR_11B(ee_header)) + __set_bit(AR5K_MODE_11B, caps->cap_mode); + + if (AR5K_EEPROM_HDR_11G(ee_header) && + ah->ah_version != AR5K_AR5211) + __set_bit(AR5K_MODE_11G, caps->cap_mode); } } @@ -110,18 +103,12 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) else caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; - /* Newer hardware has PHY error counters */ + /* newer hardware has PHY error counters */ if (ah->ah_mac_srev >= AR5K_SREV_AR5213A) caps->cap_has_phyerr_counters = true; else caps->cap_has_phyerr_counters = false; - /* MACs since AR5212 have MRR support */ - if (ah->ah_version == AR5K_AR5212) - caps->cap_has_mrr_support = true; - else - caps->cap_has_mrr_support = false; - return 0; } diff --git a/trunk/drivers/net/wireless/ath/ath5k/desc.c b/trunk/drivers/net/wireless/ath/ath5k/desc.c index f8bfa3ac2af0..7e88dda82221 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/desc.c +++ b/trunk/drivers/net/wireless/ath/ath5k/desc.c @@ -26,61 +26,20 @@ #include "debug.h" -/** - * DOC: Hardware descriptor functions - * - * Here we handle the processing of the low-level hw descriptors - * that hw reads and writes via DMA for each TX and RX attempt (that means - * we can also have descriptors for failed TX/RX tries). We have two kind of - * descriptors for RX and TX, control descriptors tell the hw how to send or - * receive a packet where to read/write it from/to etc and status descriptors - * that contain information about how the packet was sent or received (errors - * included). - * - * Descriptor format is not exactly the same for each MAC chip version so we - * have function pointers on &struct ath5k_hw we initialize at runtime based on - * the chip used. - */ - - /************************\ * TX Control descriptors * \************************/ -/** - * ath5k_hw_setup_2word_tx_desc() - Initialize a 2-word tx control descriptor - * @ah: The &struct ath5k_hw - * @desc: The &struct ath5k_desc - * @pkt_len: Frame length in bytes - * @hdr_len: Header length in bytes (only used on AR5210) - * @padsize: Any padding we've added to the frame length - * @type: One of enum ath5k_pkt_type - * @tx_power: Tx power in 0.5dB steps - * @tx_rate0: HW idx for transmission rate - * @tx_tries0: Max number of retransmissions - * @key_index: Index on key table to use for encryption - * @antenna_mode: Which antenna to use (0 for auto) - * @flags: One of AR5K_TXDESC_* flags (desc.h) - * @rtscts_rate: HW idx for RTS/CTS transmission rate - * @rtscts_duration: What to put on duration field on the header of RTS/CTS - * - * Internal function to initialize a 2-Word TX control descriptor - * found on AR5210 and AR5211 MACs chips. - * - * Returns 0 on success or -EINVAL on false input +/* + * Initialize the 2-word tx control descriptor on 5210/5211 */ static int -ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, - struct ath5k_desc *desc, - unsigned int pkt_len, unsigned int hdr_len, - int padsize, - enum ath5k_pkt_type type, - unsigned int tx_power, - unsigned int tx_rate0, unsigned int tx_tries0, - unsigned int key_index, - unsigned int antenna_mode, - unsigned int flags, - unsigned int rtscts_rate, unsigned int rtscts_duration) +ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, + unsigned int pkt_len, unsigned int hdr_len, int padsize, + enum ath5k_pkt_type type, + unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, + unsigned int key_index, unsigned int antenna_mode, unsigned int flags, + unsigned int rtscts_rate, unsigned int rtscts_duration) { u32 frame_type; struct ath5k_hw_2w_tx_ctl *tx_ctl; @@ -213,40 +172,17 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, return 0; } -/** - * ath5k_hw_setup_4word_tx_desc() - Initialize a 4-word tx control descriptor - * @ah: The &struct ath5k_hw - * @desc: The &struct ath5k_desc - * @pkt_len: Frame length in bytes - * @hdr_len: Header length in bytes (only used on AR5210) - * @padsize: Any padding we've added to the frame length - * @type: One of enum ath5k_pkt_type - * @tx_power: Tx power in 0.5dB steps - * @tx_rate0: HW idx for transmission rate - * @tx_tries0: Max number of retransmissions - * @key_index: Index on key table to use for encryption - * @antenna_mode: Which antenna to use (0 for auto) - * @flags: One of AR5K_TXDESC_* flags (desc.h) - * @rtscts_rate: HW idx for RTS/CTS transmission rate - * @rtscts_duration: What to put on duration field on the header of RTS/CTS - * - * Internal function to initialize a 4-Word TX control descriptor - * found on AR5212 and later MACs chips. - * - * Returns 0 on success or -EINVAL on false input +/* + * Initialize the 4-word tx control descriptor on 5212 */ -static int -ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, - struct ath5k_desc *desc, - unsigned int pkt_len, unsigned int hdr_len, - int padsize, - enum ath5k_pkt_type type, - unsigned int tx_power, - unsigned int tx_rate0, unsigned int tx_tries0, - unsigned int key_index, - unsigned int antenna_mode, - unsigned int flags, - unsigned int rtscts_rate, unsigned int rtscts_duration) +static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, + struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, + int padsize, + enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, + unsigned int tx_tries0, unsigned int key_index, + unsigned int antenna_mode, unsigned int flags, + unsigned int rtscts_rate, + unsigned int rtscts_duration) { struct ath5k_hw_4w_tx_ctl *tx_ctl; unsigned int frame_len; @@ -356,29 +292,13 @@ ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, return 0; } -/** - * ath5k_hw_setup_mrr_tx_desc() - Initialize an MRR tx control descriptor - * @ah: The &struct ath5k_hw - * @desc: The &struct ath5k_desc - * @tx_rate1: HW idx for rate used on transmission series 1 - * @tx_tries1: Max number of retransmissions for transmission series 1 - * @tx_rate2: HW idx for rate used on transmission series 2 - * @tx_tries2: Max number of retransmissions for transmission series 2 - * @tx_rate3: HW idx for rate used on transmission series 3 - * @tx_tries3: Max number of retransmissions for transmission series 3 - * - * Multi rate retry (MRR) tx control descriptors are available only on AR5212 - * MACs, they are part of the normal 4-word tx control descriptor (see above) - * but we handle them through a separate function for better abstraction. - * - * Returns 0 on success or -EINVAL on invalid input +/* + * Initialize a 4-word multi rate retry tx control descriptor on 5212 */ int -ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, - struct ath5k_desc *desc, - u_int tx_rate1, u_int tx_tries1, - u_int tx_rate2, u_int tx_tries2, - u_int tx_rate3, u_int tx_tries3) +ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, + unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, + u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) { struct ath5k_hw_4w_tx_ctl *tx_ctl; @@ -430,16 +350,11 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, * TX Status descriptors * \***********************/ -/** - * ath5k_hw_proc_2word_tx_status() - Process a tx status descriptor on 5210/1 - * @ah: The &struct ath5k_hw - * @desc: The &struct ath5k_desc - * @ts: The &struct ath5k_tx_status +/* + * Process the tx status descriptor on 5210/5211 */ -static int -ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, - struct ath5k_tx_status *ts) +static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, + struct ath5k_desc *desc, struct ath5k_tx_status *ts) { struct ath5k_hw_2w_tx_ctl *tx_ctl; struct ath5k_hw_tx_status *tx_status; @@ -484,16 +399,11 @@ ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, return 0; } -/** - * ath5k_hw_proc_4word_tx_status() - Process a tx status descriptor on 5212 - * @ah: The &struct ath5k_hw - * @desc: The &struct ath5k_desc - * @ts: The &struct ath5k_tx_status +/* + * Process a tx status descriptor on 5212 */ -static int -ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, - struct ath5k_tx_status *ts) +static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, + struct ath5k_desc *desc, struct ath5k_tx_status *ts) { struct ath5k_hw_4w_tx_ctl *tx_ctl; struct ath5k_hw_tx_status *tx_status; @@ -550,17 +460,11 @@ ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, * RX Descriptors * \****************/ -/** - * ath5k_hw_setup_rx_desc() - Initialize an rx control descriptor - * @ah: The &struct ath5k_hw - * @desc: The &struct ath5k_desc - * @size: RX buffer length in bytes - * @flags: One of AR5K_RXDESC_* flags +/* + * Initialize an rx control descriptor */ -int -ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, - struct ath5k_desc *desc, - u32 size, unsigned int flags) +int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, + u32 size, unsigned int flags) { struct ath5k_hw_rx_ctl *rx_ctl; @@ -587,22 +491,11 @@ ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, return 0; } -/** - * ath5k_hw_proc_5210_rx_status() - Process the rx status descriptor on 5210/1 - * @ah: The &struct ath5k_hw - * @desc: The &struct ath5k_desc - * @rs: The &struct ath5k_rx_status - * - * Internal function used to process an RX status descriptor - * on AR5210/5211 MAC. - * - * Returns 0 on success or -EINPROGRESS in case we haven't received the who;e - * frame yet. +/* + * Process the rx status descriptor on 5210/5211 */ -static int -ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, - struct ath5k_rx_status *rs) +static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, + struct ath5k_desc *desc, struct ath5k_rx_status *rs) { struct ath5k_hw_rx_status *rx_status; @@ -681,22 +574,12 @@ ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, return 0; } -/** - * ath5k_hw_proc_5212_rx_status() - Process the rx status descriptor on 5212 - * @ah: The &struct ath5k_hw - * @desc: The &struct ath5k_desc - * @rs: The &struct ath5k_rx_status - * - * Internal function used to process an RX status descriptor - * on AR5212 and later MAC. - * - * Returns 0 on success or -EINPROGRESS in case we haven't received the who;e - * frame yet. +/* + * Process the rx status descriptor on 5212 */ -static int -ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, - struct ath5k_rx_status *rs) +static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, + struct ath5k_desc *desc, + struct ath5k_rx_status *rs) { struct ath5k_hw_rx_status *rx_status; u32 rxstat0, rxstat1; @@ -763,16 +646,10 @@ ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, * Attach * \********/ -/** - * ath5k_hw_init_desc_functions() - Init function pointers inside ah - * @ah: The &struct ath5k_hw - * - * Maps the internal descriptor functions to the function pointers on ah, used - * from above. This is used as an abstraction layer to handle the various chips - * the same way. +/* + * Init function pointers inside ath5k_hw struct */ -int -ath5k_hw_init_desc_functions(struct ath5k_hw *ah) +int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) { if (ah->ah_version == AR5K_AR5212) { ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; diff --git a/trunk/drivers/net/wireless/ath/ath5k/desc.h b/trunk/drivers/net/wireless/ath/ath5k/desc.h index 8d6c01a49ea3..cfd529b548f3 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/desc.h +++ b/trunk/drivers/net/wireless/ath/ath5k/desc.h @@ -20,30 +20,25 @@ * RX/TX descriptor structures */ -/** - * struct ath5k_hw_rx_ctl - Common hardware RX control descriptor - * @rx_control_0: RX control word 0 - * @rx_control_1: RX control word 1 +/* + * Common hardware RX control descriptor */ struct ath5k_hw_rx_ctl { - u32 rx_control_0; - u32 rx_control_1; + u32 rx_control_0; /* RX control word 0 */ + u32 rx_control_1; /* RX control word 1 */ } __packed __aligned(4); /* RX control word 1 fields/flags */ #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */ #define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 /* RX interrupt request */ -/** - * struct ath5k_hw_rx_status - Common hardware RX status descriptor - * @rx_status_0: RX status word 0 - * @rx_status_1: RX status word 1 - * +/* + * Common hardware RX status descriptor * 5210, 5211 and 5212 differ only in the fields and flags defined below */ struct ath5k_hw_rx_status { - u32 rx_status_0; - u32 rx_status_1; + u32 rx_status_0; /* RX status word 0 */ + u32 rx_status_1; /* RX status word 1 */ } __packed __aligned(4); /* 5210/5211 */ @@ -103,36 +98,17 @@ struct ath5k_hw_rx_status { /** * enum ath5k_phy_error_code - PHY Error codes - * @AR5K_RX_PHY_ERROR_UNDERRUN: Transmit underrun, [5210] No error - * @AR5K_RX_PHY_ERROR_TIMING: Timing error - * @AR5K_RX_PHY_ERROR_PARITY: Illegal parity - * @AR5K_RX_PHY_ERROR_RATE: Illegal rate - * @AR5K_RX_PHY_ERROR_LENGTH: Illegal length - * @AR5K_RX_PHY_ERROR_RADAR: Radar detect, [5210] 64 QAM rate - * @AR5K_RX_PHY_ERROR_SERVICE: Illegal service - * @AR5K_RX_PHY_ERROR_TOR: Transmit override receive - * @AR5K_RX_PHY_ERROR_OFDM_TIMING: OFDM Timing error [5212+] - * @AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY: OFDM Signal parity error [5212+] - * @AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL: OFDM Illegal rate [5212+] - * @AR5K_RX_PHY_ERROR_OFDM_LENGTH_ILLEGAL: OFDM Illegal length [5212+] - * @AR5K_RX_PHY_ERROR_OFDM_POWER_DROP: OFDM Power drop [5212+] - * @AR5K_RX_PHY_ERROR_OFDM_SERVICE: OFDM Service (?) [5212+] - * @AR5K_RX_PHY_ERROR_OFDM_RESTART: OFDM Restart (?) [5212+] - * @AR5K_RX_PHY_ERROR_CCK_TIMING: CCK Timing error [5212+] - * @AR5K_RX_PHY_ERROR_CCK_HEADER_CRC: Header CRC error [5212+] - * @AR5K_RX_PHY_ERROR_CCK_RATE_ILLEGAL: Illegal rate [5212+] - * @AR5K_RX_PHY_ERROR_CCK_SERVICE: CCK Service (?) [5212+] - * @AR5K_RX_PHY_ERROR_CCK_RESTART: CCK Restart (?) [5212+] */ enum ath5k_phy_error_code { - AR5K_RX_PHY_ERROR_UNDERRUN = 0, - AR5K_RX_PHY_ERROR_TIMING = 1, - AR5K_RX_PHY_ERROR_PARITY = 2, - AR5K_RX_PHY_ERROR_RATE = 3, - AR5K_RX_PHY_ERROR_LENGTH = 4, - AR5K_RX_PHY_ERROR_RADAR = 5, - AR5K_RX_PHY_ERROR_SERVICE = 6, - AR5K_RX_PHY_ERROR_TOR = 7, + AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun, [5210] No error */ + AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */ + AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */ + AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */ + AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */ + AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect, [5210] 64 QAM rate */ + AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */ + AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */ + /* these are specific to the 5212 */ AR5K_RX_PHY_ERROR_OFDM_TIMING = 17, AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY = 18, AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL = 19, @@ -147,14 +123,12 @@ enum ath5k_phy_error_code { AR5K_RX_PHY_ERROR_CCK_RESTART = 31, }; -/** - * struct ath5k_hw_2w_tx_ctl - 5210/5211 hardware 2-word TX control descriptor - * @tx_control_0: TX control word 0 - * @tx_control_1: TX control word 1 +/* + * 5210/5211 hardware 2-word TX control descriptor */ struct ath5k_hw_2w_tx_ctl { - u32 tx_control_0; - u32 tx_control_1; + u32 tx_control_0; /* TX control word 0 */ + u32 tx_control_1; /* TX control word 1 */ } __packed __aligned(4); /* TX control word 0 fields/flags */ @@ -203,18 +177,14 @@ struct ath5k_hw_2w_tx_ctl { #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 4 #define AR5K_AR5211_TX_DESC_FRAME_TYPE_PRESP 4 -/** - * struct ath5k_hw_4w_tx_ctl - 5212 hardware 4-word TX control descriptor - * @tx_control_0: TX control word 0 - * @tx_control_1: TX control word 1 - * @tx_control_2: TX control word 2 - * @tx_control_3: TX control word 3 +/* + * 5212 hardware 4-word TX control descriptor */ struct ath5k_hw_4w_tx_ctl { - u32 tx_control_0; - u32 tx_control_1; - u32 tx_control_2; - u32 tx_control_3; + u32 tx_control_0; /* TX control word 0 */ + u32 tx_control_1; /* TX control word 1 */ + u32 tx_control_2; /* TX control word 2 */ + u32 tx_control_3; /* TX control word 3 */ } __packed __aligned(4); /* TX control word 0 fields/flags */ @@ -268,14 +238,12 @@ struct ath5k_hw_4w_tx_ctl { #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 /* RTS or CTS rate */ #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 -/** - * struct ath5k_hw_tx_status - Common TX status descriptor - * @tx_status_0: TX status word 0 - * @tx_status_1: TX status word 1 +/* + * Common TX status descriptor */ struct ath5k_hw_tx_status { - u32 tx_status_0; - u32 tx_status_1; + u32 tx_status_0; /* TX status word 0 */ + u32 tx_status_1; /* TX status word 1 */ } __packed __aligned(4); /* TX status word 0 fields/flags */ @@ -308,47 +276,37 @@ struct ath5k_hw_tx_status { #define AR5K_DESC_TX_STATUS1_COMP_SUCCESS_5212 0x00800000 /* [5212] compression status */ #define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212 0x01000000 /* [5212] transmit antenna */ -/** - * struct ath5k_hw_5210_tx_desc - 5210/5211 hardware TX descriptor - * @tx_ctl: The &struct ath5k_hw_2w_tx_ctl - * @tx_stat: The &struct ath5k_hw_tx_status +/* + * 5210/5211 hardware TX descriptor */ struct ath5k_hw_5210_tx_desc { struct ath5k_hw_2w_tx_ctl tx_ctl; struct ath5k_hw_tx_status tx_stat; } __packed __aligned(4); -/** - * struct ath5k_hw_5212_tx_desc - 5212 hardware TX descriptor - * @tx_ctl: The &struct ath5k_hw_4w_tx_ctl - * @tx_stat: The &struct ath5k_hw_tx_status +/* + * 5212 hardware TX descriptor */ struct ath5k_hw_5212_tx_desc { struct ath5k_hw_4w_tx_ctl tx_ctl; struct ath5k_hw_tx_status tx_stat; } __packed __aligned(4); -/** - * struct ath5k_hw_all_rx_desc - Common hardware RX descriptor - * @rx_ctl: The &struct ath5k_hw_rx_ctl - * @rx_stat: The &struct ath5k_hw_rx_status +/* + * Common hardware RX descriptor */ struct ath5k_hw_all_rx_desc { struct ath5k_hw_rx_ctl rx_ctl; struct ath5k_hw_rx_status rx_stat; } __packed __aligned(4); -/** - * struct ath5k_desc - Atheros hardware DMA descriptor - * @ds_link: Physical address of the next descriptor - * @ds_data: Physical address of data buffer (skb) - * @ud: Union containing hw_5xxx_tx_desc structs and hw_all_rx_desc - * +/* + * Atheros hardware DMA descriptor * This is read and written to by the hardware */ struct ath5k_desc { - u32 ds_link; - u32 ds_data; + u32 ds_link; /* physical address of the next descriptor */ + u32 ds_data; /* physical address of data buffer (skb) */ union { struct ath5k_hw_5210_tx_desc ds_tx5210; diff --git a/trunk/drivers/net/wireless/ath/ath5k/dma.c b/trunk/drivers/net/wireless/ath/ath5k/dma.c index 5cc9aa814697..2481f9c7f4b6 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/dma.c +++ b/trunk/drivers/net/wireless/ath/ath5k/dma.c @@ -20,13 +20,16 @@ * DMA and interrupt masking functions * \*************************************/ -/** - * DOC: DMA and interrupt masking functions +/* + * dma.c - DMA and interrupt masking functions * * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and * handle queue setup for 5210 chipset (rest are handled on qcu.c). * Also we setup interrupt mask register (IMR) and read the various interrupt * status registers (ISR). + * + * TODO: Handle SISR on 5211+ and introduce a function to return the queue + * number that resulted the interrupt. */ #include "ath5k.h" @@ -39,22 +42,22 @@ \*********/ /** - * ath5k_hw_start_rx_dma() - Start DMA receive + * ath5k_hw_start_rx_dma - Start DMA receive + * * @ah: The &struct ath5k_hw */ -void -ath5k_hw_start_rx_dma(struct ath5k_hw *ah) +void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) { ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); ath5k_hw_reg_read(ah, AR5K_CR); } /** - * ath5k_hw_stop_rx_dma() - Stop DMA receive + * ath5k_hw_stop_rx_dma - Stop DMA receive + * * @ah: The &struct ath5k_hw */ -static int -ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) +static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) { unsigned int i; @@ -76,24 +79,24 @@ ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) } /** - * ath5k_hw_get_rxdp() - Get RX Descriptor's address + * ath5k_hw_get_rxdp - Get RX Descriptor's address + * * @ah: The &struct ath5k_hw */ -u32 -ath5k_hw_get_rxdp(struct ath5k_hw *ah) +u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) { return ath5k_hw_reg_read(ah, AR5K_RXDP); } /** - * ath5k_hw_set_rxdp() - Set RX Descriptor's address + * ath5k_hw_set_rxdp - Set RX Descriptor's address + * * @ah: The &struct ath5k_hw * @phys_addr: RX descriptor address * * Returns -EIO if rx is active */ -int -ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) +int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) { if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) { ATH5K_DBG(ah, ATH5K_DEBUG_DMA, @@ -111,7 +114,8 @@ ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) \**********/ /** - * ath5k_hw_start_tx_dma() - Start DMA transmit for a specific queue + * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue + * * @ah: The &struct ath5k_hw * @queue: The hw queue number * @@ -124,8 +128,7 @@ ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) * NOTE: Must be called after setting up tx control descriptor for that * queue (see below). */ -int -ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) +int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) { u32 tx_queue; @@ -174,16 +177,17 @@ ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) } /** - * ath5k_hw_stop_tx_dma() - Stop DMA transmit on a specific queue + * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue + * * @ah: The &struct ath5k_hw * @queue: The hw queue number * * Stop DMA transmit on a specific hw queue and drain queue so we don't * have any pending frames. Returns -EBUSY if we still have pending frames, * -EINVAL if queue number is out of range or inactive. + * */ -static int -ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) +static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) { unsigned int i = 40; u32 tx_queue, pending; @@ -316,14 +320,14 @@ ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) } /** - * ath5k_hw_stop_beacon_queue() - Stop beacon queue - * @ah: The &struct ath5k_hw - * @queue: The queue number + * ath5k_hw_stop_beacon_queue - Stop beacon queue + * + * @ah The &struct ath5k_hw + * @queue The queue number * * Returns -EIO if queue didn't stop */ -int -ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) +int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) { int ret; ret = ath5k_hw_stop_tx_dma(ah, queue); @@ -336,7 +340,8 @@ ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) } /** - * ath5k_hw_get_txdp() - Get TX Descriptor's address for a specific queue + * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue + * * @ah: The &struct ath5k_hw * @queue: The hw queue number * @@ -347,8 +352,7 @@ ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) * * XXX: Is TXDP read and clear ? */ -u32 -ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) +u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) { u16 tx_reg; @@ -378,10 +382,10 @@ ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) } /** - * ath5k_hw_set_txdp() - Set TX Descriptor's address for a specific queue + * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue + * * @ah: The &struct ath5k_hw * @queue: The hw queue number - * @phys_addr: The physical address * * Set TX descriptor's address for a specific queue. For 5210 we ignore * the queue number and we use tx queue type since we only have 2 queues @@ -390,8 +394,7 @@ ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still * active. */ -int -ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) +int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) { u16 tx_reg; @@ -432,7 +435,8 @@ ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) } /** - * ath5k_hw_update_tx_triglevel() - Update tx trigger level + * ath5k_hw_update_tx_triglevel - Update tx trigger level + * * @ah: The &struct ath5k_hw * @increase: Flag to force increase of trigger level * @@ -440,15 +444,15 @@ ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) * buffer (aka FIFO threshold) that is used to indicate when PCU flushes * the buffer and transmits its data. Lowering this results sending small * frames more quickly but can lead to tx underruns, raising it a lot can - * result other problems. Right now we start with the lowest possible - * (64Bytes) and if we get tx underrun we increase it using the increase - * flag. Returns -EIO if we have reached maximum/minimum. + * result other problems (i think bmiss is related). Right now we start with + * the lowest possible (64Bytes) and if we get tx underrun we increase it using + * the increase flag. Returns -EIO if we have reached maximum/minimum. * * XXX: Link this with tx DMA size ? - * XXX2: Use it to save interrupts ? + * XXX: Use it to save interrupts ? + * TODO: Needs testing, i think it's related to bmiss... */ -int -ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) +int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) { u32 trigger_level, imr; int ret = -EIO; @@ -494,20 +498,21 @@ ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) \*******************/ /** - * ath5k_hw_is_intr_pending() - Check if we have pending interrupts + * ath5k_hw_is_intr_pending - Check if we have pending interrupts + * * @ah: The &struct ath5k_hw * * Check if we have pending interrupts to process. Returns 1 if we * have pending interrupts and 0 if we haven't. */ -bool -ath5k_hw_is_intr_pending(struct ath5k_hw *ah) +bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) { return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; } /** - * ath5k_hw_get_isr() - Get interrupt status + * ath5k_hw_get_isr - Get interrupt status + * * @ah: The @struct ath5k_hw * @interrupt_mask: Driver's interrupt mask used to filter out * interrupts in sw. @@ -518,162 +523,62 @@ ath5k_hw_is_intr_pending(struct ath5k_hw *ah) * being mapped on some standard non hw-specific positions * (check out &ath5k_int). * - * NOTE: We do write-to-clear, so the active PISR/SISR bits at the time this - * function gets called are cleared on return. + * NOTE: We use read-and-clear register, so after this function is called ISR + * is zeroed. */ -int -ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) +int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) { - u32 data = 0; + u32 data; /* - * Read interrupt status from Primary Interrupt - * Register. - * - * Note: PISR/SISR Not available on 5210 + * Read interrupt status from the Interrupt Status register + * on 5210 */ if (ah->ah_version == AR5K_AR5210) { - u32 isr = 0; - isr = ath5k_hw_reg_read(ah, AR5K_ISR); - if (unlikely(isr == AR5K_INT_NOCARD)) { - *interrupt_mask = isr; + data = ath5k_hw_reg_read(ah, AR5K_ISR); + if (unlikely(data == AR5K_INT_NOCARD)) { + *interrupt_mask = data; return -ENODEV; } - - /* - * Filter out the non-common bits from the interrupt - * status. - */ - *interrupt_mask = (isr & AR5K_INT_COMMON) & ah->ah_imr; - - /* Hanlde INT_FATAL */ - if (unlikely(isr & (AR5K_ISR_SSERR | AR5K_ISR_MCABT - | AR5K_ISR_DPERR))) - *interrupt_mask |= AR5K_INT_FATAL; - - /* - * XXX: BMISS interrupts may occur after association. - * I found this on 5210 code but it needs testing. If this is - * true we should disable them before assoc and re-enable them - * after a successful assoc + some jiffies. - interrupt_mask &= ~AR5K_INT_BMISS; - */ - - data = isr; } else { - u32 pisr = 0; - u32 pisr_clear = 0; - u32 sisr0 = 0; - u32 sisr1 = 0; - u32 sisr2 = 0; - u32 sisr3 = 0; - u32 sisr4 = 0; - - /* Read PISR and SISRs... */ - pisr = ath5k_hw_reg_read(ah, AR5K_PISR); - if (unlikely(pisr == AR5K_INT_NOCARD)) { - *interrupt_mask = pisr; - return -ENODEV; - } - - sisr0 = ath5k_hw_reg_read(ah, AR5K_SISR0); - sisr1 = ath5k_hw_reg_read(ah, AR5K_SISR1); - sisr2 = ath5k_hw_reg_read(ah, AR5K_SISR2); - sisr3 = ath5k_hw_reg_read(ah, AR5K_SISR3); - sisr4 = ath5k_hw_reg_read(ah, AR5K_SISR4); - /* - * PISR holds the logical OR of interrupt bits - * from SISR registers: - * - * TXOK and TXDESC -> Logical OR of TXOK and TXDESC - * per-queue bits on SISR0 - * - * TXERR and TXEOL -> Logical OR of TXERR and TXEOL - * per-queue bits on SISR1 - * - * TXURN -> Logical OR of TXURN per-queue bits on SISR2 + * Read interrupt status from Interrupt + * Status Register shadow copy (Read And Clear) * - * HIUERR -> Logical OR of MCABT, SSERR and DPER bits on SISR2 - * - * BCNMISC -> Logical OR of TIM, CAB_END, DTIM_SYNC - * BCN_TIMEOUT, CAB_TIMEOUT and DTIM - * (and TSFOOR ?) bits on SISR2 - * - * QCBRORN and QCBRURN -> Logical OR of QCBRORN and - * QCBRURN per-queue bits on SISR3 - * QTRIG -> Logical OR of QTRIG per-queue bits on SISR4 - * - * If we clean these bits on PISR we 'll also clear all - * related bits from SISRs, e.g. if we write the TXOK bit on - * PISR we 'll clean all TXOK bits from SISR0 so if a new TXOK - * interrupt got fired for another queue while we were reading - * the interrupt registers and we write back the TXOK bit on - * PISR we 'll lose it. So make sure that we don't write back - * on PISR any bits that come from SISRs. Clearing them from - * SISRs will also clear PISR so no need to worry here. - */ - - pisr_clear = pisr & ~AR5K_ISR_BITS_FROM_SISRS; - - /* - * Write to clear them... - * Note: This means that each bit we write back - * to the registers will get cleared, leaving the - * rest unaffected. So this won't affect new interrupts - * we didn't catch while reading/processing, we 'll get - * them next time get_isr gets called. - */ - ath5k_hw_reg_write(ah, sisr0, AR5K_SISR0); - ath5k_hw_reg_write(ah, sisr1, AR5K_SISR1); - ath5k_hw_reg_write(ah, sisr2, AR5K_SISR2); - ath5k_hw_reg_write(ah, sisr3, AR5K_SISR3); - ath5k_hw_reg_write(ah, sisr4, AR5K_SISR4); - ath5k_hw_reg_write(ah, pisr_clear, AR5K_PISR); - /* Flush previous write */ - ath5k_hw_reg_read(ah, AR5K_PISR); - - /* - * Filter out the non-common bits from the interrupt - * status. + * Note: PISR/SISR Not available on 5210 */ - *interrupt_mask = (pisr & AR5K_INT_COMMON) & ah->ah_imr; - - - /* We treat TXOK,TXDESC, TXERR and TXEOL - * the same way (schedule the tx tasklet) - * so we track them all together per queue */ - if (pisr & AR5K_ISR_TXOK) - ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr0, - AR5K_SISR0_QCU_TXOK); + data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR); + if (unlikely(data == AR5K_INT_NOCARD)) { + *interrupt_mask = data; + return -ENODEV; + } + } - if (pisr & AR5K_ISR_TXDESC) - ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr0, - AR5K_SISR0_QCU_TXDESC); + /* + * Get abstract interrupt mask (driver-compatible) + */ + *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr; - if (pisr & AR5K_ISR_TXERR) - ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr1, - AR5K_SISR1_QCU_TXERR); + if (ah->ah_version != AR5K_AR5210) { + u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2); - if (pisr & AR5K_ISR_TXEOL) - ah->ah_txq_isr_txok_all |= AR5K_REG_MS(sisr1, - AR5K_SISR1_QCU_TXEOL); + /*HIU = Host Interface Unit (PCI etc)*/ + if (unlikely(data & (AR5K_ISR_HIUERR))) + *interrupt_mask |= AR5K_INT_FATAL; - /* Currently this is not much usefull since we treat - * all queues the same way if we get a TXURN (update - * tx trigger level) but we might need it later on*/ - if (pisr & AR5K_ISR_TXURN) - ah->ah_txq_isr_txurn |= AR5K_REG_MS(sisr2, - AR5K_SISR2_QCU_TXURN); + /*Beacon Not Ready*/ + if (unlikely(data & (AR5K_ISR_BNR))) + *interrupt_mask |= AR5K_INT_BNR; - /* Misc Beacon related interrupts */ + if (unlikely(sisr2 & (AR5K_SISR2_SSERR | + AR5K_SISR2_DPERR | + AR5K_SISR2_MCABT))) + *interrupt_mask |= AR5K_INT_FATAL; - /* For AR5211 */ - if (pisr & AR5K_ISR_TIM) + if (data & AR5K_ISR_TIM) *interrupt_mask |= AR5K_INT_TIM; - /* For AR5212+ */ - if (pisr & AR5K_ISR_BCNMISC) { + if (data & AR5K_ISR_BCNMISC) { if (sisr2 & AR5K_SISR2_TIM) *interrupt_mask |= AR5K_INT_TIM; if (sisr2 & AR5K_SISR2_DTIM) @@ -686,39 +591,63 @@ ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) *interrupt_mask |= AR5K_INT_CAB_TIMEOUT; } - /* Below interrupts are unlikely to happen */ - - /* HIU = Host Interface Unit (PCI etc) - * Can be one of MCABT, SSERR, DPERR from SISR2 */ - if (unlikely(pisr & (AR5K_ISR_HIUERR))) - *interrupt_mask |= AR5K_INT_FATAL; - - /*Beacon Not Ready*/ - if (unlikely(pisr & (AR5K_ISR_BNR))) - *interrupt_mask |= AR5K_INT_BNR; - - /* A queue got CBR overrun */ - if (unlikely(pisr & (AR5K_ISR_QCBRORN))) { + if (data & AR5K_ISR_RXDOPPLER) + *interrupt_mask |= AR5K_INT_RX_DOPPLER; + if (data & AR5K_ISR_QCBRORN) { *interrupt_mask |= AR5K_INT_QCBRORN; - ah->ah_txq_isr_qcborn |= AR5K_REG_MS(sisr3, - AR5K_SISR3_QCBRORN); + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR3), + AR5K_SISR3_QCBRORN); } - - /* A queue got CBR underrun */ - if (unlikely(pisr & (AR5K_ISR_QCBRURN))) { + if (data & AR5K_ISR_QCBRURN) { *interrupt_mask |= AR5K_INT_QCBRURN; - ah->ah_txq_isr_qcburn |= AR5K_REG_MS(sisr3, - AR5K_SISR3_QCBRURN); + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR3), + AR5K_SISR3_QCBRURN); } - - /* A queue got triggered */ - if (unlikely(pisr & (AR5K_ISR_QTRIG))) { + if (data & AR5K_ISR_QTRIG) { *interrupt_mask |= AR5K_INT_QTRIG; - ah->ah_txq_isr_qtrig |= AR5K_REG_MS(sisr4, - AR5K_SISR4_QTRIG); + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR4), + AR5K_SISR4_QTRIG); } - data = pisr; + if (data & AR5K_ISR_TXOK) + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR0), + AR5K_SISR0_QCU_TXOK); + + if (data & AR5K_ISR_TXDESC) + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR0), + AR5K_SISR0_QCU_TXDESC); + + if (data & AR5K_ISR_TXERR) + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR1), + AR5K_SISR1_QCU_TXERR); + + if (data & AR5K_ISR_TXEOL) + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR1), + AR5K_SISR1_QCU_TXEOL); + + if (data & AR5K_ISR_TXURN) + ah->ah_txq_isr |= AR5K_REG_MS( + ath5k_hw_reg_read(ah, AR5K_RAC_SISR2), + AR5K_SISR2_QCU_TXURN); + } else { + if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT + | AR5K_ISR_HIUERR | AR5K_ISR_DPERR))) + *interrupt_mask |= AR5K_INT_FATAL; + + /* + * XXX: BMISS interrupts may occur after association. + * I found this on 5210 code but it needs testing. If this is + * true we should disable them before assoc and re-enable them + * after a successful assoc + some jiffies. + interrupt_mask &= ~AR5K_INT_BMISS; + */ } /* @@ -732,7 +661,8 @@ ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) } /** - * ath5k_hw_set_imr() - Set interrupt mask + * ath5k_hw_set_imr - Set interrupt mask + * * @ah: The &struct ath5k_hw * @new_mask: The new interrupt mask to be set * @@ -740,8 +670,7 @@ ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) * ath5k_int bits to hw-specific bits to remove abstraction and writing * Interrupt Mask Register. */ -enum ath5k_int -ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) +enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) { enum ath5k_int old_mask, int_mask; @@ -768,14 +697,16 @@ ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2) & AR5K_SIMR2_QCU_TXURN; - /* Fatal interrupt abstraction for 5211+ */ if (new_mask & AR5K_INT_FATAL) { int_mask |= AR5K_IMR_HIUERR; simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR | AR5K_SIMR2_DPERR); } - /* Misc beacon related interrupts */ + /*Beacon Not Ready*/ + if (new_mask & AR5K_INT_BNR) + int_mask |= AR5K_INT_BNR; + if (new_mask & AR5K_INT_TIM) int_mask |= AR5K_IMR_TIM; @@ -790,9 +721,8 @@ ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) if (new_mask & AR5K_INT_CAB_TIMEOUT) simr2 |= AR5K_SISR2_CAB_TIMEOUT; - /*Beacon Not Ready*/ - if (new_mask & AR5K_INT_BNR) - int_mask |= AR5K_INT_BNR; + if (new_mask & AR5K_INT_RX_DOPPLER) + int_mask |= AR5K_IMR_RXDOPPLER; /* Note: Per queue interrupt masks * are set via ath5k_hw_reset_tx_queue() (qcu.c) */ @@ -800,12 +730,10 @@ ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2); } else { - /* Fatal interrupt abstraction for 5210 */ if (new_mask & AR5K_INT_FATAL) int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT | AR5K_IMR_HIUERR | AR5K_IMR_DPERR); - /* Only common interrupts left for 5210 (no SIMRs) */ ath5k_hw_reg_write(ah, int_mask, AR5K_IMR); } @@ -832,7 +760,8 @@ ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) \********************/ /** - * ath5k_hw_dma_init() - Initialize DMA unit + * ath5k_hw_dma_init - Initialize DMA unit + * * @ah: The &struct ath5k_hw * * Set DMA size and pre-enable interrupts @@ -841,8 +770,7 @@ ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) * * XXX: Save/restore RXDP/TXDP registers ? */ -void -ath5k_hw_dma_init(struct ath5k_hw *ah) +void ath5k_hw_dma_init(struct ath5k_hw *ah) { /* * Set Rx/Tx DMA Configuration @@ -871,7 +799,8 @@ ath5k_hw_dma_init(struct ath5k_hw *ah) } /** - * ath5k_hw_dma_stop() - stop DMA unit + * ath5k_hw_dma_stop - stop DMA unit + * * @ah: The &struct ath5k_hw * * Stop tx/rx DMA and interrupts. Returns @@ -881,8 +810,7 @@ ath5k_hw_dma_init(struct ath5k_hw *ah) * stuck frames on tx queues, only a reset * can fix that. */ -int -ath5k_hw_dma_stop(struct ath5k_hw *ah) +int ath5k_hw_dma_stop(struct ath5k_hw *ah) { int i, qmax, err; err = 0; diff --git a/trunk/drivers/net/wireless/ath/ath5k/gpio.c b/trunk/drivers/net/wireless/ath/ath5k/gpio.c index 73d3dd8a306a..859297811914 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/gpio.c +++ b/trunk/drivers/net/wireless/ath/ath5k/gpio.c @@ -24,33 +24,10 @@ #include "reg.h" #include "debug.h" - -/** - * DOC: GPIO/LED functions - * - * Here we control the 6 bidirectional GPIO pins provided by the hw. - * We can set a GPIO pin to be an input or an output pin on GPIO control - * register and then read or set its status from GPIO data input/output - * registers. - * - * We also control the two LED pins provided by the hw, LED_0 is our - * "power" LED and LED_1 is our "network activity" LED but many scenarios - * are available from hw. Vendors might also provide LEDs connected to the - * GPIO pins, we handle them through the LED subsystem on led.c - */ - - -/** - * ath5k_hw_set_ledstate() - Set led state - * @ah: The &struct ath5k_hw - * @state: One of AR5K_LED_* - * - * Used to set the LED blinking state. This only - * works for the LED connected to the LED_0, LED_1 pins, - * not the GPIO based. +/* + * Set led state */ -void -ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) +void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) { u32 led; /*5210 has different led mode handling*/ @@ -97,13 +74,10 @@ ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210); } -/** - * ath5k_hw_set_gpio_input() - Set GPIO inputs - * @ah: The &struct ath5k_hw - * @gpio: GPIO pin to set as input +/* + * Set GPIO inputs */ -int -ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) +int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) { if (gpio >= AR5K_NUM_GPIO) return -EINVAL; @@ -115,13 +89,10 @@ ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) return 0; } -/** - * ath5k_hw_set_gpio_output() - Set GPIO outputs - * @ah: The &struct ath5k_hw - * @gpio: The GPIO pin to set as output +/* + * Set GPIO outputs */ -int -ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) +int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) { if (gpio >= AR5K_NUM_GPIO) return -EINVAL; @@ -133,13 +104,10 @@ ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) return 0; } -/** - * ath5k_hw_get_gpio() - Get GPIO state - * @ah: The &struct ath5k_hw - * @gpio: The GPIO pin to read +/* + * Get GPIO state */ -u32 -ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) +u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) { if (gpio >= AR5K_NUM_GPIO) return 0xffffffff; @@ -149,14 +117,10 @@ ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) 0x1; } -/** - * ath5k_hw_set_gpio() - Set GPIO state - * @ah: The &struct ath5k_hw - * @gpio: The GPIO pin to set - * @val: Value to set (boolean) +/* + * Set GPIO state */ -int -ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) +int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) { u32 data; @@ -174,19 +138,10 @@ ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) return 0; } -/** - * ath5k_hw_set_gpio_intr() - Initialize the GPIO interrupt (RFKill switch) - * @ah: The &struct ath5k_hw - * @gpio: The GPIO pin to use - * @interrupt_level: True to generate interrupt on active pin (high) - * - * This function is used to set up the GPIO interrupt for the hw RFKill switch. - * That switch is connected to a GPIO pin and it's number is stored on EEPROM. - * It can either open or close the circuit to indicate that we should disable - * RF/Wireless to save power (we also get that from EEPROM). +/* + * Initialize the GPIO interrupt (RFKill switch) */ -void -ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, +void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level) { u32 data; diff --git a/trunk/drivers/net/wireless/ath/ath5k/initvals.c b/trunk/drivers/net/wireless/ath/ath5k/initvals.c index a1ea78e05b47..1ffecc0fd3ed 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/initvals.c +++ b/trunk/drivers/net/wireless/ath/ath5k/initvals.c @@ -23,27 +23,24 @@ #include "reg.h" #include "debug.h" -/** - * struct ath5k_ini - Mode-independent initial register writes - * @ini_register: Register address - * @ini_value: Default value - * @ini_mode: 0 to write 1 to read (and clear) +/* + * Mode-independent initial register writes */ + struct ath5k_ini { u16 ini_register; u32 ini_value; enum { AR5K_INI_WRITE = 0, /* Default */ - AR5K_INI_READ = 1, + AR5K_INI_READ = 1, /* Cleared on read */ } ini_mode; }; -/** - * struct ath5k_ini_mode - Mode specific initial register values - * @mode_register: Register address - * @mode_value: Set of values for each enum ath5k_driver_mode +/* + * Mode specific initial register values */ + struct ath5k_ini_mode { u16 mode_register; u32 mode_value[3]; @@ -389,10 +386,11 @@ static const struct ath5k_ini ar5211_ini[] = { /* Initial mode-specific settings for AR5211 * 5211 supports OFDM-only g (draft g) but we - * need to test it ! */ + * need to test it ! + */ static const struct ath5k_ini_mode ar5211_ini_mode[] = { { AR5K_TXCFG, - /* A B G */ + /* A/XR B G */ { 0x00000015, 0x0000001d, 0x00000015 } }, { AR5K_QUEUE_DFS_LOCAL_IFS(0), { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, @@ -462,7 +460,7 @@ static const struct ath5k_ini_mode ar5211_ini_mode[] = { { 0x00000010, 0x00000010, 0x00000010 } }, }; -/* Initial register settings for AR5212 and newer chips */ +/* Initial register settings for AR5212 */ static const struct ath5k_ini ar5212_ini_common_start[] = { { AR5K_RXDP, 0x00000000 }, { AR5K_RXCFG, 0x00000005 }, @@ -726,8 +724,7 @@ static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { { 0x00000000, 0x00000000, 0x00000108 } }, }; -/* Initial mode-specific settings for AR5212 + RF5111 - * (Written after ar5212_ini) */ +/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */ static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { { AR5K_TXCFG, /* A/XR B G */ @@ -760,7 +757,6 @@ static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { { 0x1883800a, 0x1873800a, 0x1883800a } }, }; -/* Common for all modes */ static const struct ath5k_ini rf5111_ini_common_end[] = { { AR5K_DCU_FP, 0x00000000 }, { AR5K_PHY_AGC, 0x00000000 }, @@ -778,9 +774,7 @@ static const struct ath5k_ini rf5111_ini_common_end[] = { { 0xa23c, 0x13c889af }, }; - -/* Initial mode-specific settings for AR5212 + RF5112 - * (Written after ar5212_ini) */ +/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */ static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { { AR5K_TXCFG, /* A/XR B G */ @@ -831,9 +825,7 @@ static const struct ath5k_ini rf5112_ini_common_end[] = { { 0xa23c, 0x13c889af }, }; - -/* Initial mode-specific settings for RF5413/5414 - * (Written after ar5212_ini) */ +/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */ static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { { AR5K_TXCFG, /* A/XR B G */ @@ -971,8 +963,7 @@ static const struct ath5k_ini rf5413_ini_common_end[] = { { 0xa384, 0xf3307ff0 }, }; -/* Initial mode-specific settings for RF2413/2414 - * (Written after ar5212_ini) */ +/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */ /* XXX: a mode ? */ static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { { AR5K_TXCFG, @@ -1094,8 +1085,7 @@ static const struct ath5k_ini rf2413_ini_common_end[] = { { 0xa384, 0xf3307ff0 }, }; -/* Initial mode-specific settings for RF2425 - * (Written after ar5212_ini) */ +/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */ /* XXX: a mode ? */ static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { { AR5K_TXCFG, @@ -1367,15 +1357,10 @@ static const struct ath5k_ini rf5112_ini_bbgain[] = { }; -/** - * ath5k_hw_ini_registers() - Write initial register dump common for all modes - * @ah: The &struct ath5k_hw - * @size: Dump size - * @ini_regs: The array of &struct ath5k_ini - * @skip_pcu: Skip PCU registers +/* + * Write initial register dump */ -static void -ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, +static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, const struct ath5k_ini *ini_regs, bool skip_pcu) { unsigned int i; @@ -1403,15 +1388,7 @@ ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, } } -/** - * ath5k_hw_ini_mode_registers() - Write initial mode-specific register dump - * @ah: The &struct ath5k_hw - * @size: Dump size - * @ini_mode: The array of &struct ath5k_ini_mode - * @mode: One of enum ath5k_driver_mode - */ -static void -ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, +static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, unsigned int size, const struct ath5k_ini_mode *ini_mode, u8 mode) { @@ -1425,17 +1402,7 @@ ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, } -/** - * ath5k_hw_write_initvals() - Write initial chip-specific register dump - * @ah: The &struct ath5k_hw - * @mode: One of enum ath5k_driver_mode - * @skip_pcu: Skip PCU registers - * - * Write initial chip-specific register dump, to get the chipset on a - * clean and ready-to-work state after warm reset. - */ -int -ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu) +int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu) { /* * Write initial register settings diff --git a/trunk/drivers/net/wireless/ath/ath5k/pci.c b/trunk/drivers/net/wireless/ath/ath5k/pci.c index 849fa060ebc4..dfa48eb7d953 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/pci.c +++ b/trunk/drivers/net/wireless/ath/ath5k/pci.c @@ -98,7 +98,7 @@ ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data) 0xffff); return true; } - usleep_range(15, 20); + udelay(15); } return false; diff --git a/trunk/drivers/net/wireless/ath/ath5k/pcu.c b/trunk/drivers/net/wireless/ath/ath5k/pcu.c index cebfd6fd31d3..a7eafa3edc21 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/pcu.c +++ b/trunk/drivers/net/wireless/ath/ath5k/pcu.c @@ -30,47 +30,11 @@ #include "reg.h" #include "debug.h" -/** - * DOC: Protocol Control Unit (PCU) functions - * - * Protocol control unit is responsible to maintain various protocol - * properties before a frame is send and after a frame is received to/from - * baseband. To be more specific, PCU handles: - * - * - Buffering of RX and TX frames (after QCU/DCUs) - * - * - Encrypting and decrypting (using the built-in engine) - * - * - Generating ACKs, RTS/CTS frames - * - * - Maintaining TSF - * - * - FCS - * - * - Updating beacon data (with TSF etc) - * - * - Generating virtual CCA - * - * - RX/Multicast filtering - * - * - BSSID filtering - * - * - Various statistics - * - * -Different operating modes: AP, STA, IBSS - * - * Note: Most of these functions can be tweaked/bypassed so you can do - * them on sw above for debugging or research. For more infos check out PCU - * registers on reg.h. - */ - -/** - * DOC: ACK rates - * +/* * AR5212+ can use higher rates for ack transmission * based on current tx rate instead of the base rate. * It does this to better utilize channel usage. - * There is a mapping between G rates (that cover both + * This is a mapping between G rates (that cover both * CCK and OFDM) and ack rates that we use when setting * rate -> duration table. This mapping is hw-based so * don't change anything. @@ -99,18 +63,17 @@ static const unsigned int ack_rates_high[] = \*******************/ /** - * ath5k_hw_get_frame_duration() - Get tx time of a frame + * ath5k_hw_get_frame_duration - Get tx time of a frame + * * @ah: The &struct ath5k_hw * @len: Frame's length in bytes * @rate: The @struct ieee80211_rate - * @shortpre: Indicate short preample * * Calculate tx duration of a frame given it's rate and length * It extends ieee80211_generic_frame_duration for non standard * bwmodes. */ -int -ath5k_hw_get_frame_duration(struct ath5k_hw *ah, +int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, int len, struct ieee80211_rate *rate, bool shortpre) { int sifs, preamble, plcp_bits, sym_time; @@ -166,11 +129,11 @@ ath5k_hw_get_frame_duration(struct ath5k_hw *ah, } /** - * ath5k_hw_get_default_slottime() - Get the default slot time for current mode + * ath5k_hw_get_default_slottime - Get the default slot time for current mode + * * @ah: The &struct ath5k_hw */ -unsigned int -ath5k_hw_get_default_slottime(struct ath5k_hw *ah) +unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) { struct ieee80211_channel *channel = ah->ah_current_channel; unsigned int slot_time; @@ -197,11 +160,11 @@ ath5k_hw_get_default_slottime(struct ath5k_hw *ah) } /** - * ath5k_hw_get_default_sifs() - Get the default SIFS for current mode + * ath5k_hw_get_default_sifs - Get the default SIFS for current mode + * * @ah: The &struct ath5k_hw */ -unsigned int -ath5k_hw_get_default_sifs(struct ath5k_hw *ah) +unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) { struct ieee80211_channel *channel = ah->ah_current_channel; unsigned int sifs; @@ -228,17 +191,17 @@ ath5k_hw_get_default_sifs(struct ath5k_hw *ah) } /** - * ath5k_hw_update_mib_counters() - Update MIB counters (mac layer statistics) + * ath5k_hw_update_mib_counters - Update MIB counters (mac layer statistics) + * * @ah: The &struct ath5k_hw * * Reads MIB counters from PCU and updates sw statistics. Is called after a * MIB interrupt, because one of these counters might have reached their maximum * and triggered the MIB interrupt, to let us read and clear the counter. * - * NOTE: Is called in interrupt context! + * Is called in interrupt context! */ -void -ath5k_hw_update_mib_counters(struct ath5k_hw *ah) +void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) { struct ath5k_statistics *stats = &ah->stats; @@ -256,8 +219,10 @@ ath5k_hw_update_mib_counters(struct ath5k_hw *ah) \******************/ /** - * ath5k_hw_write_rate_duration() - Fill rate code to duration table - * @ah: The &struct ath5k_hw + * ath5k_hw_write_rate_duration - fill rate code to duration table + * + * @ah: the &struct ath5k_hw + * @mode: one of enum ath5k_driver_mode * * Write the rate code to duration table upon hw reset. This is a helper for * ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on @@ -271,8 +236,7 @@ ath5k_hw_update_mib_counters(struct ath5k_hw *ah) * that include all OFDM and CCK rates. * */ -static inline void -ath5k_hw_write_rate_duration(struct ath5k_hw *ah) +static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) { struct ieee80211_rate *rate; unsigned int i; @@ -316,12 +280,12 @@ ath5k_hw_write_rate_duration(struct ath5k_hw *ah) } /** - * ath5k_hw_set_ack_timeout() - Set ACK timeout on PCU + * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU + * * @ah: The &struct ath5k_hw * @timeout: Timeout in usec */ -static int -ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) +static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) { if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) <= timeout) @@ -334,12 +298,12 @@ ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) } /** - * ath5k_hw_set_cts_timeout() - Set CTS timeout on PCU + * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU + * * @ah: The &struct ath5k_hw * @timeout: Timeout in usec */ -static int -ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) +static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) { if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) <= timeout) @@ -357,14 +321,14 @@ ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) \*******************/ /** - * ath5k_hw_set_lladdr() - Set station id + * ath5k_hw_set_lladdr - Set station id + * * @ah: The &struct ath5k_hw - * @mac: The card's mac address (array of octets) + * @mac: The card's mac address * * Set station id on hw using the provided mac address */ -int -ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) +int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) { struct ath_common *common = ath5k_hw_common(ah); u32 low_id, high_id; @@ -385,14 +349,14 @@ ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) } /** - * ath5k_hw_set_bssid() - Set current BSSID on hw + * ath5k_hw_set_bssid - Set current BSSID on hw + * * @ah: The &struct ath5k_hw * * Sets the current BSSID and BSSID mask we have from the * common struct into the hardware */ -void -ath5k_hw_set_bssid(struct ath5k_hw *ah) +void ath5k_hw_set_bssid(struct ath5k_hw *ah) { struct ath_common *common = ath5k_hw_common(ah); u16 tim_offset = 0; @@ -425,23 +389,7 @@ ath5k_hw_set_bssid(struct ath5k_hw *ah) ath5k_hw_enable_pspoll(ah, NULL, 0); } -/** - * ath5k_hw_set_bssid_mask() - Filter out bssids we listen - * @ah: The &struct ath5k_hw - * @mask: The BSSID mask to set (array of octets) - * - * BSSID masking is a method used by AR5212 and newer hardware to inform PCU - * which bits of the interface's MAC address should be looked at when trying - * to decide which packets to ACK. In station mode and AP mode with a single - * BSS every bit matters since we lock to only one BSS. In AP mode with - * multiple BSSes (virtual interfaces) not every bit matters because hw must - * accept frames for all BSSes and so we tweak some bits of our mac address - * in order to have multiple BSSes. - * - * For more information check out ../hw.c of the common ath module. - */ -void -ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) +void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) { struct ath_common *common = ath5k_hw_common(ah); @@ -452,21 +400,18 @@ ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) ath_hw_setbssidmask(common); } -/** - * ath5k_hw_set_mcast_filter() - Set multicast filter - * @ah: The &struct ath5k_hw - * @filter0: Lower 32bits of muticast filter - * @filter1: Higher 16bits of multicast filter +/* + * Set multicast filter */ -void -ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) +void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) { ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); } /** - * ath5k_hw_get_rx_filter() - Get current rx filter + * ath5k_hw_get_rx_filter - Get current rx filter + * * @ah: The &struct ath5k_hw * * Returns the RX filter by reading rx filter and @@ -475,8 +420,7 @@ ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) * and pass to the driver. For a list of frame types * check out reg.h. */ -u32 -ath5k_hw_get_rx_filter(struct ath5k_hw *ah) +u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) { u32 data, filter = 0; @@ -496,7 +440,8 @@ ath5k_hw_get_rx_filter(struct ath5k_hw *ah) } /** - * ath5k_hw_set_rx_filter() - Set rx filter + * ath5k_hw_set_rx_filter - Set rx filter + * * @ah: The &struct ath5k_hw * @filter: RX filter mask (see reg.h) * @@ -504,8 +449,7 @@ ath5k_hw_get_rx_filter(struct ath5k_hw *ah) * register on 5212 and newer chips so that we have proper PHY * error reporting. */ -void -ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) +void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) { u32 data = 0; @@ -549,13 +493,13 @@ ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) #define ATH5K_MAX_TSF_READ 10 /** - * ath5k_hw_get_tsf64() - Get the full 64bit TSF + * ath5k_hw_get_tsf64 - Get the full 64bit TSF + * * @ah: The &struct ath5k_hw * * Returns the current TSF */ -u64 -ath5k_hw_get_tsf64(struct ath5k_hw *ah) +u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) { u32 tsf_lower, tsf_upper1, tsf_upper2; int i; @@ -592,30 +536,28 @@ ath5k_hw_get_tsf64(struct ath5k_hw *ah) return ((u64)tsf_upper1 << 32) | tsf_lower; } -#undef ATH5K_MAX_TSF_READ - /** - * ath5k_hw_set_tsf64() - Set a new 64bit TSF + * ath5k_hw_set_tsf64 - Set a new 64bit TSF + * * @ah: The &struct ath5k_hw * @tsf64: The new 64bit TSF * * Sets the new TSF */ -void -ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) +void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) { ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); } /** - * ath5k_hw_reset_tsf() - Force a TSF reset + * ath5k_hw_reset_tsf - Force a TSF reset + * * @ah: The &struct ath5k_hw * * Forces a TSF reset on PCU */ -void -ath5k_hw_reset_tsf(struct ath5k_hw *ah) +void ath5k_hw_reset_tsf(struct ath5k_hw *ah) { u32 val; @@ -631,17 +573,10 @@ ath5k_hw_reset_tsf(struct ath5k_hw *ah) ath5k_hw_reg_write(ah, val, AR5K_BEACON); } -/** - * ath5k_hw_init_beacon_timers() - Initialize beacon timers - * @ah: The &struct ath5k_hw - * @next_beacon: Next TBTT - * @interval: Current beacon interval - * - * This function is used to initialize beacon timers based on current - * operation mode and settings. +/* + * Initialize beacon timers */ -void -ath5k_hw_init_beacon_timers(struct ath5k_hw *ah, u32 next_beacon, u32 interval) +void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) { u32 timer1, timer2, timer3; @@ -720,7 +655,8 @@ ath5k_hw_init_beacon_timers(struct ath5k_hw *ah, u32 next_beacon, u32 interval) } /** - * ath5k_check_timer_win() - Check if timer B is timer A + window + * ath5k_check_timer_win - Check if timer B is timer A + window + * * @a: timer a (before b) * @b: timer b (after a) * @window: difference between a and b @@ -750,11 +686,12 @@ ath5k_check_timer_win(int a, int b, int window, int intval) } /** - * ath5k_hw_check_beacon_timers() - Check if the beacon timers are correct + * ath5k_hw_check_beacon_timers - Check if the beacon timers are correct + * * @ah: The &struct ath5k_hw * @intval: beacon interval * - * This is a workaround for IBSS mode + * This is a workaround for IBSS mode: * * The need for this function arises from the fact that we have 4 separate * HW timer registers (TIMER0 - TIMER3), which are closely related to the @@ -809,14 +746,14 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval) } /** - * ath5k_hw_set_coverage_class() - Set IEEE 802.11 coverage class + * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class + * * @ah: The &struct ath5k_hw * @coverage_class: IEEE 802.11 coverage class number * * Sets IFS intervals and ACK/CTS timeouts for given coverage class. */ -void -ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) +void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) { /* As defined by IEEE 802.11-2007 17.3.8.6 */ int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class; @@ -835,7 +772,8 @@ ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) \***************************/ /** - * ath5k_hw_start_rx_pcu() - Start RX engine + * ath5k_hw_start_rx_pcu - Start RX engine + * * @ah: The &struct ath5k_hw * * Starts RX engine on PCU so that hw can process RXed frames @@ -843,33 +781,32 @@ ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) * * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma */ -void -ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) +void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) { AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); } /** - * at5k_hw_stop_rx_pcu() - Stop RX engine + * at5k_hw_stop_rx_pcu - Stop RX engine + * * @ah: The &struct ath5k_hw * * Stops RX engine on PCU */ -void -ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) +void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) { AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); } /** - * ath5k_hw_set_opmode() - Set PCU operating mode + * ath5k_hw_set_opmode - Set PCU operating mode + * * @ah: The &struct ath5k_hw - * @op_mode: One of enum nl80211_iftype + * @op_mode: &enum nl80211_iftype operating mode * * Configure PCU for the various operating modes (AP/STA etc) */ -int -ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) +int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) { struct ath_common *common = ath5k_hw_common(ah); u32 pcu_reg, beacon_reg, low_id, high_id; @@ -936,17 +873,8 @@ ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) return 0; } -/** - * ath5k_hw_pcu_init() - Initialize PCU - * @ah: The &struct ath5k_hw - * @op_mode: One of enum nl80211_iftype - * @mode: One of enum ath5k_driver_mode - * - * This function is used to initialize PCU by setting current - * operation mode and various other settings. - */ -void -ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode) +void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, + u8 mode) { /* Set bssid and bssid mask */ ath5k_hw_set_bssid(ah); diff --git a/trunk/drivers/net/wireless/ath/ath5k/phy.c b/trunk/drivers/net/wireless/ath/ath5k/phy.c index e1f8613426a9..01cb72de44cb 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/phy.c +++ b/trunk/drivers/net/wireless/ath/ath5k/phy.c @@ -1,4 +1,6 @@ /* + * PHY functions + * * Copyright (c) 2004-2007 Reyk Floeter * Copyright (c) 2006-2009 Nick Kossifidis * Copyright (c) 2007-2008 Jiri Slaby @@ -18,10 +20,6 @@ * */ -/***********************\ -* PHY related functions * -\***********************/ - #include #include #include @@ -33,53 +31,14 @@ #include "../regd.h" -/** - * DOC: PHY related functions - * - * Here we handle the low-level functions related to baseband - * and analog frontend (RF) parts. This is by far the most complex - * part of the hw code so make sure you know what you are doing. - * - * Here is a list of what this is all about: - * - * - Channel setting/switching - * - * - Automatic Gain Control (AGC) calibration - * - * - Noise Floor calibration - * - * - I/Q imbalance calibration (QAM correction) - * - * - Calibration due to thermal changes (gain_F) - * - * - Spur noise mitigation - * - * - RF/PHY initialization for the various operating modes and bwmodes - * - * - Antenna control - * - * - TX power control per channel/rate/packet type - * - * Also have in mind we never got documentation for most of these - * functions, what we have comes mostly from Atheros's code, reverse - * engineering and patent docs/presentations etc. - */ - - /******************\ * Helper functions * \******************/ -/** - * ath5k_hw_radio_revision() - Get the PHY Chip revision - * @ah: The &struct ath5k_hw - * @band: One of enum ieee80211_band - * - * Returns the revision number of a 2GHz, 5GHz or single chip - * radio. +/* + * Get the PHY Chip revision */ -u16 -ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band) +u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band) { unsigned int i; u32 srev; @@ -99,7 +58,7 @@ ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band) return 0; } - usleep_range(2000, 2500); + mdelay(2); /* ...wait until PHY is ready and read the selected radio revision */ ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); @@ -122,16 +81,10 @@ ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band) return ret; } -/** - * ath5k_channel_ok() - Check if a channel is supported by the hw - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * - * Note: We don't do any regulatory domain checks here, it's just - * a sanity check. +/* + * Check if a channel is supported */ -bool -ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel) +bool ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel) { u16 freq = channel->center_freq; @@ -148,13 +101,7 @@ ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel) return false; } -/** - * ath5k_hw_chan_has_spur_noise() - Check if channel is sensitive to spur noise - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - */ -bool -ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, +bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, struct ieee80211_channel *channel) { u8 refclk_freq; @@ -175,20 +122,11 @@ ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, return false; } -/** - * ath5k_hw_rfb_op() - Perform an operation on the given RF Buffer - * @ah: The &struct ath5k_hw - * @rf_regs: The struct ath5k_rf_reg - * @val: New value - * @reg_id: RF register ID - * @set: Indicate we need to swap data - * - * This is an internal function used to modify RF Banks before - * writing them to AR5K_RF_BUFFER. Check out rfbuffer.h for more - * infos. +/* + * Used to modify RF Banks before writing them to AR5K_RF_BUFFER */ -static unsigned int -ath5k_hw_rfb_op(struct ath5k_hw *ah, const struct ath5k_rf_reg *rf_regs, +static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, + const struct ath5k_rf_reg *rf_regs, u32 val, u8 reg_id, bool set) { const struct ath5k_rf_reg *rfreg = NULL; @@ -266,7 +204,8 @@ ath5k_hw_rfb_op(struct ath5k_hw *ah, const struct ath5k_rf_reg *rf_regs, } /** - * ath5k_hw_write_ofdm_timings() - set OFDM timings on AR5212 + * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 + * * @ah: the &struct ath5k_hw * @channel: the currently set channel upon reset * @@ -277,11 +216,10 @@ ath5k_hw_rfb_op(struct ath5k_hw *ah, const struct ath5k_rf_reg *rf_regs, * mantissa and provide these values on hw. * * For more infos i think this patent is related - * "http://www.freepatentsonline.com/7184495.html" + * http://www.freepatentsonline.com/7184495.html */ -static inline int -ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, - struct ieee80211_channel *channel) +static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, + struct ieee80211_channel *channel) { /* Get exponent and mantissa and set it */ u32 coef_scaled, coef_exp, coef_man, @@ -340,10 +278,6 @@ ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, return 0; } -/** - * ath5k_hw_phy_disable() - Disable PHY - * @ah: The &struct ath5k_hw - */ int ath5k_hw_phy_disable(struct ath5k_hw *ah) { /*Just a try M.F.*/ @@ -352,13 +286,10 @@ int ath5k_hw_phy_disable(struct ath5k_hw *ah) return 0; } -/** - * ath5k_hw_wait_for_synth() - Wait for synth to settle - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel +/* + * Wait for synth to settle */ -static void -ath5k_hw_wait_for_synth(struct ath5k_hw *ah, +static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah, struct ieee80211_channel *channel) { /* @@ -377,9 +308,9 @@ ath5k_hw_wait_for_synth(struct ath5k_hw *ah, delay = delay << 2; /* XXX: /2 on turbo ? Let's be safe * for now */ - usleep_range(100 + delay, 100 + (2 * delay)); + udelay(100 + delay); } else { - usleep_range(1000, 1500); + mdelay(1); } } @@ -388,9 +319,7 @@ ath5k_hw_wait_for_synth(struct ath5k_hw *ah, * RF Gain optimization * \**********************/ -/** - * DOC: RF Gain optimization - * +/* * This code is used to optimize RF gain on different environments * (temperature mostly) based on feedback from a power detector. * @@ -399,22 +328,22 @@ ath5k_hw_wait_for_synth(struct ath5k_hw *ah, * no gain optimization ladder-. * * For more infos check out this patent doc - * "http://www.freepatentsonline.com/7400691.html" + * http://www.freepatentsonline.com/7400691.html * * This paper describes power drops as seen on the receiver due to * probe packets - * "http://www.cnri.dit.ie/publications/ICT08%20-%20Practical%20Issues - * %20of%20Power%20Control.pdf" + * http://www.cnri.dit.ie/publications/ICT08%20-%20Practical%20Issues + * %20of%20Power%20Control.pdf * * And this is the MadWiFi bug entry related to the above - * "http://madwifi-project.org/ticket/1659" + * http://madwifi-project.org/ticket/1659 * with various measurements and diagrams + * + * TODO: Deal with power drops due to probes by setting an appropriate + * tx power on the probe packets ! Make this part of the calibration process. */ -/** - * ath5k_hw_rfgain_opt_init() - Initialize ah_gain during attach - * @ah: The &struct ath5k_hw - */ +/* Initialize ah_gain during attach */ int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) { /* Initialize the gain optimization values */ @@ -438,21 +367,17 @@ int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) return 0; } -/** - * ath5k_hw_request_rfgain_probe() - Request a PAPD probe packet - * @ah: The &struct ath5k_hw - * - * Schedules a gain probe check on the next transmitted packet. +/* Schedule a gain probe check on the next transmitted packet. * That means our next packet is going to be sent with lower * tx power and a Peak to Average Power Detector (PAPD) will try * to measure the gain. * - * TODO: Force a tx packet (bypassing PCU arbitrator etc) + * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc) * just after we enable the probe so that we don't mess with - * standard traffic. + * standard traffic ? Maybe it's time to use sw interrupts and + * a probe tasklet !!! */ -static void -ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) +static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) { /* Skip if gain calibration is inactive or @@ -470,15 +395,9 @@ ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) } -/** - * ath5k_hw_rf_gainf_corr() - Calculate Gain_F measurement correction - * @ah: The &struct ath5k_hw - * - * Calculate Gain_F measurement correction - * based on the current step for RF5112 rev. 2 - */ -static u32 -ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) +/* Calculate gain_F measurement correction + * based on the current step for RF5112 rev. 2 */ +static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) { u32 mix, step; u32 *rf; @@ -531,19 +450,11 @@ ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) return ah->ah_gain.g_f_corr; } -/** - * ath5k_hw_rf_check_gainf_readback() - Validate Gain_F feedback from detector - * @ah: The &struct ath5k_hw - * - * Check if current gain_F measurement is in the range of our +/* Check if current gain_F measurement is in the range of our * power detector windows. If we get a measurement outside range * we know it's not accurate (detectors can't measure anything outside - * their detection window) so we must ignore it. - * - * Returns true if readback was O.K. or false on failure - */ -static bool -ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) + * their detection window) so we must ignore it */ +static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) { const struct ath5k_rf_reg *rf_regs; u32 step, mix_ovr, level[4]; @@ -595,15 +506,9 @@ ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) ah->ah_gain.g_current <= level[3]); } -/** - * ath5k_hw_rf_gainf_adjust() - Perform Gain_F adjustment - * @ah: The &struct ath5k_hw - * - * Choose the right target gain based on current gain - * and RF gain optimization ladder - */ -static s8 -ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) +/* Perform gain_F adjustment by choosing the right set + * of parameters from RF gain optimization ladder */ +static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) { const struct ath5k_gain_opt *go; const struct ath5k_gain_opt_step *g_step; @@ -667,18 +572,13 @@ ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) return ret; } -/** - * ath5k_hw_gainf_calibrate() - Do a gain_F calibration - * @ah: The &struct ath5k_hw - * - * Main callback for thermal RF gain calibration engine +/* Main callback for thermal RF gain calibration engine * Check for a new gain reading and schedule an adjustment * if needed. * - * Returns one of enum ath5k_rfgain codes - */ -enum ath5k_rfgain -ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) + * TODO: Use sw interrupt to schedule reset if gain_F needs + * adjustment */ +enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) { u32 data, type; struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; @@ -738,18 +638,10 @@ ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) return ah->ah_gain.g_state; } -/** - * ath5k_hw_rfgain_init() - Write initial RF gain settings to hw - * @ah: The &struct ath5k_hw - * @band: One of enum ieee80211_band - * - * Write initial RF gain table to set the RF sensitivity. - * - * NOTE: This one works on all RF chips and has nothing to do - * with Gain_F calibration - */ -static int -ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band) +/* Write initial RF gain table to set the RF sensitivity + * this one works on all RF chips and has nothing to do + * with gain_F calibration */ +static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band) { const struct ath5k_ini_rfgain *ath5k_rfg; unsigned int i, size, index; @@ -796,23 +688,16 @@ ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band) } + /********************\ * RF Registers setup * \********************/ -/** - * ath5k_hw_rfregs_init() - Initialize RF register settings - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * @mode: One of enum ath5k_driver_mode - * - * Setup RF registers by writing RF buffer on hw. For - * more infos on this, check out rfbuffer.h +/* + * Setup RF registers by writing RF buffer on hw */ -static int -ath5k_hw_rfregs_init(struct ath5k_hw *ah, - struct ieee80211_channel *channel, - unsigned int mode) +static int ath5k_hw_rfregs_init(struct ath5k_hw *ah, + struct ieee80211_channel *channel, unsigned int mode) { const struct ath5k_rf_reg *rf_regs; const struct ath5k_ini_rfbuffer *ini_rfb; @@ -1170,18 +1055,19 @@ ath5k_hw_rfregs_init(struct ath5k_hw *ah, PHY/RF channel functions \**************************/ -/** - * ath5k_hw_rf5110_chan2athchan() - Convert channel freq on RF5110 - * @channel: The &struct ieee80211_channel - * - * Map channel frequency to IEEE channel number and convert it - * to an internal channel value used by the RF5110 chipset. +/* + * Conversion needed for RF5110 */ -static u32 -ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) +static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) { u32 athchan; + /* + * Convert IEEE channel/MHz to an internal channel value used + * by the AR5210 chipset. This has not been verified with + * newer chipsets like the AR5212A who have a completely + * different RF/PHY part. + */ athchan = (ath5k_hw_bitswap( (ieee80211_frequency_to_channel( channel->center_freq) - 24) / 2, 5) @@ -1189,13 +1075,10 @@ ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) return athchan; } -/** - * ath5k_hw_rf5110_channel() - Set channel frequency on RF5110 - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel +/* + * Set channel on RF5110 */ -static int -ath5k_hw_rf5110_channel(struct ath5k_hw *ah, +static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) { u32 data; @@ -1206,23 +1089,15 @@ ath5k_hw_rf5110_channel(struct ath5k_hw *ah, data = ath5k_hw_rf5110_chan2athchan(channel); ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER); ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0); - usleep_range(1000, 1500); + mdelay(1); return 0; } -/** - * ath5k_hw_rf5111_chan2athchan() - Handle 2GHz channels on RF5111/2111 - * @ieee: IEEE channel number - * @athchan: The &struct ath5k_athchan_2ghz - * - * In order to enable the RF2111 frequency converter on RF5111/2111 setups - * we need to add some offsets and extra flags to the data values we pass - * on to the PHY. So for every 2GHz channel this function gets called - * to do the conversion. +/* + * Conversion needed for 5111 */ -static int -ath5k_hw_rf5111_chan2athchan(unsigned int ieee, +static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, struct ath5k_athchan_2ghz *athchan) { int channel; @@ -1248,13 +1123,10 @@ ath5k_hw_rf5111_chan2athchan(unsigned int ieee, return 0; } -/** - * ath5k_hw_rf5111_channel() - Set channel frequency on RF5111/2111 - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel +/* + * Set channel on 5111 */ -static int -ath5k_hw_rf5111_channel(struct ath5k_hw *ah, +static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) { struct ath5k_athchan_2ghz ath5k_channel_2ghz; @@ -1299,20 +1171,10 @@ ath5k_hw_rf5111_channel(struct ath5k_hw *ah, return 0; } -/** - * ath5k_hw_rf5112_channel() - Set channel frequency on 5112 and newer - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * - * On RF5112/2112 and newer we don't need to do any conversion. - * We pass the frequency value after a few modifications to the - * chip directly. - * - * NOTE: Make sure channel frequency given is within our range or else - * we might damage the chip ! Use ath5k_channel_ok before calling this one. +/* + * Set channel on 5112 and newer */ -static int -ath5k_hw_rf5112_channel(struct ath5k_hw *ah, +static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) { u32 data, data0, data1, data2; @@ -1321,37 +1183,17 @@ ath5k_hw_rf5112_channel(struct ath5k_hw *ah, data = data0 = data1 = data2 = 0; c = channel->center_freq; - /* My guess based on code: - * 2GHz RF has 2 synth modes, one with a Local Oscillator - * at 2224Hz and one with a LO at 2192Hz. IF is 1520Hz - * (3040/2). data0 is used to set the PLL divider and data1 - * selects synth mode. */ if (c < 4800) { - /* Channel 14 and all frequencies with 2Hz spacing - * below/above (non-standard channels) */ if (!((c - 2224) % 5)) { - /* Same as (c - 2224) / 5 */ data0 = ((2 * (c - 704)) - 3040) / 10; data1 = 1; - /* Channel 1 and all frequencies with 5Hz spacing - * below/above (standard channels without channel 14) */ } else if (!((c - 2192) % 5)) { - /* Same as (c - 2192) / 5 */ data0 = ((2 * (c - 672)) - 3040) / 10; data1 = 0; } else return -EINVAL; data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); - /* This is more complex, we have a single synthesizer with - * 4 reference clock settings (?) based on frequency spacing - * and set using data2. LO is at 4800Hz and data0 is again used - * to set some divider. - * - * NOTE: There is an old atheros presentation at Stanford - * that mentions a method called dual direct conversion - * with 1GHz sliding IF for RF5110. Maybe that's what we - * have here, or an updated version. */ } else if ((c % 5) != 2 || c > 5435) { if (!(c % 20) && c >= 5120) { data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); @@ -1377,16 +1219,10 @@ ath5k_hw_rf5112_channel(struct ath5k_hw *ah, return 0; } -/** - * ath5k_hw_rf2425_channel() - Set channel frequency on RF2425 - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * - * AR2425/2417 have a different 2GHz RF so code changes - * a little bit from RF5112. +/* + * Set the channel on the RF2425 */ -static int -ath5k_hw_rf2425_channel(struct ath5k_hw *ah, +static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) { u32 data, data0, data2; @@ -1422,16 +1258,10 @@ ath5k_hw_rf2425_channel(struct ath5k_hw *ah, return 0; } -/** - * ath5k_hw_channel() - Set a channel on the radio chip - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * - * This is the main function called to set a channel on the - * radio chip based on the radio chip version. +/* + * Set a channel on the radio chip */ -static int -ath5k_hw_channel(struct ath5k_hw *ah, +static int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) { int ret; @@ -1483,46 +1313,11 @@ ath5k_hw_channel(struct ath5k_hw *ah, return 0; } - /*****************\ PHY calibration \*****************/ -/** - * DOC: PHY Calibration routines - * - * Noise floor calibration: When we tell the hardware to - * perform a noise floor calibration by setting the - * AR5K_PHY_AGCCTL_NF bit on AR5K_PHY_AGCCTL, it will periodically - * sample-and-hold the minimum noise level seen at the antennas. - * This value is then stored in a ring buffer of recently measured - * noise floor values so we have a moving window of the last few - * samples. The median of the values in the history is then loaded - * into the hardware for its own use for RSSI and CCA measurements. - * This type of calibration doesn't interfere with traffic. - * - * AGC calibration: When we tell the hardware to perform - * an AGC (Automatic Gain Control) calibration by setting the - * AR5K_PHY_AGCCTL_CAL, hw disconnects the antennas and does - * a calibration on the DC offsets of ADCs. During this period - * rx/tx gets disabled so we have to deal with it on the driver - * part. - * - * I/Q calibration: When we tell the hardware to perform - * an I/Q calibration, it tries to correct I/Q imbalance and - * fix QAM constellation by sampling data from rxed frames. - * It doesn't interfere with traffic. - * - * For more infos on AGC and I/Q calibration check out patent doc - * #03/094463. - */ - -/** - * ath5k_hw_read_measured_noise_floor() - Read measured NF from hw - * @ah: The &struct ath5k_hw - */ -static s32 -ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) +static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) { s32 val; @@ -1530,12 +1325,7 @@ ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) return sign_extend32(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 8); } -/** - * ath5k_hw_init_nfcal_hist() - Initialize NF calibration history buffer - * @ah: The &struct ath5k_hw - */ -void -ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) +void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) { int i; @@ -1544,11 +1334,6 @@ ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) ah->ah_nfcal_hist.nfval[i] = AR5K_TUNE_CCA_MAX_GOOD_VALUE; } -/** - * ath5k_hw_update_nfcal_hist() - Update NF calibration history buffer - * @ah: The &struct ath5k_hw - * @noise_floor: The NF we got from hw - */ static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor) { struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist; @@ -1556,12 +1341,7 @@ static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor) hist->nfval[hist->index] = noise_floor; } -/** - * ath5k_hw_get_median_noise_floor() - Get median NF from history buffer - * @ah: The &struct ath5k_hw - */ -static s16 -ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) +static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) { s16 sort[ATH5K_NF_CAL_HIST_MAX]; s16 tmp; @@ -1584,16 +1364,18 @@ ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) return sort[(ATH5K_NF_CAL_HIST_MAX - 1) / 2]; } -/** - * ath5k_hw_update_noise_floor() - Update NF on hardware - * @ah: The &struct ath5k_hw +/* + * When we tell the hardware to perform a noise floor calibration + * by setting the AR5K_PHY_AGCCTL_NF bit, it will periodically + * sample-and-hold the minimum noise level seen at the antennas. + * This value is then stored in a ring buffer of recently measured + * noise floor values so we have a moving window of the last few + * samples. * - * This is the main function we call to perform a NF calibration, - * it reads NF from hardware, calculates the median and updates - * NF on hw. + * The median of the values in the history is then loaded into the + * hardware for its own use for RSSI and CCA measurements. */ -void -ath5k_hw_update_noise_floor(struct ath5k_hw *ah) +void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; u32 val; @@ -1608,8 +1390,6 @@ ath5k_hw_update_noise_floor(struct ath5k_hw *ah) return; } - ah->ah_cal_mask |= AR5K_CALIBRATION_NF; - ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel); /* completed NF calibration, test threshold */ @@ -1654,29 +1434,20 @@ ath5k_hw_update_noise_floor(struct ath5k_hw *ah) ah->ah_noise_floor = nf; - ah->ah_cal_mask &= ~AR5K_CALIBRATION_NF; - ATH5K_DBG(ah, ATH5K_DEBUG_CALIBRATE, "noise floor calibrated: %d\n", nf); } -/** - * ath5k_hw_rf5110_calibrate() - Perform a PHY calibration on RF5110 - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * - * Do a complete PHY calibration (AGC + NF + I/Q) on RF5110 +/* + * Perform a PHY calibration on RF5110 + * -Fix BPSK/QAM Constellation (I/Q correction) */ -static int -ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, +static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel) { u32 phy_sig, phy_agc, phy_sat, beacon; int ret; - if (!(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) - return 0; - /* * Disable beacons and RX/TX queues, wait */ @@ -1685,7 +1456,7 @@ ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); - usleep_range(2000, 2500); + mdelay(2); /* * Set the channel (with AGC turned off) @@ -1698,7 +1469,7 @@ ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, * Activate PHY and wait */ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); - usleep_range(1000, 1500); + mdelay(1); AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); @@ -1735,7 +1506,7 @@ ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG); AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); - usleep_range(1000, 1500); + mdelay(1); /* * Enable calibration and wait until completion @@ -1766,9 +1537,8 @@ ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, return 0; } -/** - * ath5k_hw_rf511x_iq_calibrate() - Perform I/Q calibration on RF5111 and newer - * @ah: The &struct ath5k_hw +/* + * Perform I/Q calibration on RF5111/5112 and newer chips */ static int ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) @@ -1777,19 +1547,12 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; int i; - /* Skip if I/Q calibration is not needed or if it's still running */ - if (!ah->ah_iq_cal_needed) - return -EINVAL; - else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) { - ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_CALIBRATE, - "I/Q calibration still running"); - return -EBUSY; - } + if (!ah->ah_calibration || + ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) + return 0; /* Calibration has finished, get the results and re-run */ - - /* Work around for empty results which can apparently happen on 5212: - * Read registers up to 10 times until we get both i_pr and q_pwr */ + /* work around empty results which can apparently happen on 5212 */ for (i = 0; i <= 10; i++) { iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); @@ -1807,13 +1570,9 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) else q_coffd = q_pwr >> 7; - /* In case i_coffd became zero, cancel calibration - * not only it's too small, it'll also result a divide - * by zero later on. */ + /* protect against divide by 0 and loss of sign bits */ if (i_coffd == 0 || q_coffd < 2) - return -ECANCELED; - - /* Protect against loss of sign bits */ + return 0; i_coff = (-iq_corr) / i_coffd; i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ @@ -1842,17 +1601,10 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) return 0; } -/** - * ath5k_hw_phy_calibrate() - Perform a PHY calibration - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * - * The main function we call from above to perform - * a short or full PHY calibration based on RF chip - * and current channel +/* + * Perform a PHY calibration */ -int -ath5k_hw_phy_calibrate(struct ath5k_hw *ah, +int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel) { int ret; @@ -1861,43 +1613,10 @@ ath5k_hw_phy_calibrate(struct ath5k_hw *ah, return ath5k_hw_rf5110_calibrate(ah, channel); ret = ath5k_hw_rf511x_iq_calibrate(ah); - if (ret) { - ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_CALIBRATE, - "No I/Q correction performed (%uMHz)\n", - channel->center_freq); - - /* Happens all the time if there is not much - * traffic, consider it normal behaviour. */ - ret = 0; - } - - /* On full calibration do an AGC calibration and - * request a PAPD probe for gainf calibration if - * needed */ - if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) { - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL); - - ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF, - 0, false); - if (ret) { - ATH5K_ERR(ah, - "gain calibration timeout (%uMHz)\n", - channel->center_freq); - } - - if ((ah->ah_radio == AR5K_RF5111 || - ah->ah_radio == AR5K_RF5112) - && (channel->hw_value != AR5K_MODE_11B)) - ath5k_hw_request_rfgain_probe(ah); - } - - /* Update noise floor - * XXX: Only do this after AGC calibration */ - if (!(ah->ah_cal_mask & AR5K_CALIBRATION_NF)) - ath5k_hw_update_noise_floor(ah); + if ((ah->ah_radio == AR5K_RF5111 || ah->ah_radio == AR5K_RF5112) && + (channel->hw_value != AR5K_MODE_11B)) + ath5k_hw_request_rfgain_probe(ah); return ret; } @@ -1907,16 +1626,6 @@ ath5k_hw_phy_calibrate(struct ath5k_hw *ah, * Spur mitigation functions * \***************************/ -/** - * ath5k_hw_set_spur_mitigation_filter() - Configure SPUR filter - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * - * This function gets called during PHY initialization to - * configure the spur filter for the given channel. Spur is noise - * generated due to "reflection" effects, for more information on this - * method check out patent US7643810 - */ static void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, struct ieee80211_channel *channel) @@ -2156,73 +1865,15 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, * Antenna control * \*****************/ -/** - * DOC: Antenna control - * - * Hw supports up to 14 antennas ! I haven't found any card that implements - * that. The maximum number of antennas I've seen is up to 4 (2 for 2GHz and 2 - * for 5GHz). Antenna 1 (MAIN) should be omnidirectional, 2 (AUX) - * omnidirectional or sectorial and antennas 3-14 sectorial (or directional). - * - * We can have a single antenna for RX and multiple antennas for TX. - * RX antenna is our "default" antenna (usually antenna 1) set on - * DEFAULT_ANTENNA register and TX antenna is set on each TX control descriptor - * (0 for automatic selection, 1 - 14 antenna number). - * - * We can let hw do all the work doing fast antenna diversity for both - * tx and rx or we can do things manually. Here are the options we have - * (all are bits of STA_ID1 register): - * - * AR5K_STA_ID1_DEFAULT_ANTENNA -> When 0 is set as the TX antenna on TX - * control descriptor, use the default antenna to transmit or else use the last - * antenna on which we received an ACK. - * - * AR5K_STA_ID1_DESC_ANTENNA -> Update default antenna after each TX frame to - * the antenna on which we got the ACK for that frame. - * - * AR5K_STA_ID1_RTS_DEF_ANTENNA -> Use default antenna for RTS or else use the - * one on the TX descriptor. - * - * AR5K_STA_ID1_SELFGEN_DEF_ANT -> Use default antenna for self generated frames - * (ACKs etc), or else use current antenna (the one we just used for TX). - * - * Using the above we support the following scenarios: - * - * AR5K_ANTMODE_DEFAULT -> Hw handles antenna diversity etc automatically - * - * AR5K_ANTMODE_FIXED_A -> Only antenna A (MAIN) is present - * - * AR5K_ANTMODE_FIXED_B -> Only antenna B (AUX) is present - * - * AR5K_ANTMODE_SINGLE_AP -> Sta locked on a single ap - * - * AR5K_ANTMODE_SECTOR_AP -> AP with tx antenna set on tx desc - * - * AR5K_ANTMODE_SECTOR_STA -> STA with tx antenna set on tx desc - * - * AR5K_ANTMODE_DEBUG Debug mode -A -> Rx, B-> Tx- - * - * Also note that when setting antenna to F on tx descriptor card inverts - * current tx antenna. - */ - -/** - * ath5k_hw_set_def_antenna() - Set default rx antenna on AR5211/5212 and newer - * @ah: The &struct ath5k_hw - * @ant: Antenna number - */ -static void +static void /*TODO:Boundary check*/ ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) { if (ah->ah_version != AR5K_AR5210) ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); } -/** - * ath5k_hw_set_fast_div() - Enable/disable fast rx antenna diversity - * @ah: The &struct ath5k_hw - * @ee_mode: One of enum ath5k_driver_mode - * @enable: True to enable, false to disable +/* + * Enable/disable fast rx antenna diversity */ static void ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) @@ -2262,14 +1913,6 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) } } -/** - * ath5k_hw_set_antenna_switch() - Set up antenna switch table - * @ah: The &struct ath5k_hw - * @ee_mode: One of enum ath5k_driver_mode - * - * Switch table comes from EEPROM and includes information on controlling - * the 2 antenna RX attenuators - */ void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode) { @@ -2301,10 +1944,8 @@ ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode) AR5K_PHY_ANT_SWITCH_TABLE_1); } -/** - * ath5k_hw_set_antenna_mode() - Set antenna operating mode - * @ah: The &struct ath5k_hw - * @ant_mode: One of enum ath5k_ant_mode +/* + * Set antenna operating mode */ void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) @@ -2427,13 +2068,8 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) * Helper functions */ -/** - * ath5k_get_interpolated_value() - Get interpolated Y val between two points - * @target: X value of the middle point - * @x_left: X value of the left point - * @x_right: X value of the right point - * @y_left: Y value of the left point - * @y_right: Y value of the right point +/* + * Do linear interpolation between two given (x, y) points */ static s16 ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right, @@ -2460,18 +2096,13 @@ ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right, return result; } -/** - * ath5k_get_linear_pcdac_min() - Find vertical boundary (min pwr) for the - * linear PCDAC curve - * @stepL: Left array with y values (pcdac steps) - * @stepR: Right array with y values (pcdac steps) - * @pwrL: Left array with x values (power steps) - * @pwrR: Right array with x values (power steps) +/* + * Find vertical boundary (min pwr) for the linear PCDAC curve. * * Since we have the top of the curve and we draw the line below * until we reach 1 (1 pcdac step) we need to know which point - * (x value) that is so that we don't go below x axis and have negative - * pcdac values when creating the curve, or fill the table with zeros. + * (x value) that is so that we don't go below y axis and have negative + * pcdac values when creating the curve, or fill the table with zeroes. */ static s16 ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, @@ -2517,16 +2148,7 @@ ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, return max(min_pwrL, min_pwrR); } -/** - * ath5k_create_power_curve() - Create a Power to PDADC or PCDAC curve - * @pmin: Minimum power value (xmin) - * @pmax: Maximum power value (xmax) - * @pwr: Array of power steps (x values) - * @vpd: Array of matching PCDAC/PDADC steps (y values) - * @num_points: Number of provided points - * @vpd_table: Array to fill with the full PCDAC/PDADC values (y values) - * @type: One of enum ath5k_powertable_type (eeprom.h) - * +/* * Interpolate (pwr,vpd) points to create a Power to PDADC or a * Power to PCDAC curve. * @@ -2584,14 +2206,7 @@ ath5k_create_power_curve(s16 pmin, s16 pmax, } } -/** - * ath5k_get_chan_pcal_surrounding_piers() - Get surrounding calibration piers - * for a given channel. - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * @pcinfo_l: The &struct ath5k_chan_pcal_info to put the left cal. pier - * @pcinfo_r: The &struct ath5k_chan_pcal_info to put the right cal. pier - * +/* * Get the surrounding per-channel power calibration piers * for a given frequency so that we can interpolate between * them and come up with an appropriate dataset for our current @@ -2674,17 +2289,11 @@ ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah, *pcinfo_r = &pcinfo[idx_r]; } -/** - * ath5k_get_rate_pcal_data() - Get the interpolated per-rate power - * calibration data - * @ah: The &struct ath5k_hw *ah, - * @channel: The &struct ieee80211_channel - * @rates: The &struct ath5k_rate_pcal_info to fill - * +/* * Get the surrounding per-rate power calibration data * for a given frequency and interpolate between power * values to set max target power supported by hw for - * each rate on this frequency. + * each rate. */ static void ath5k_get_rate_pcal_data(struct ath5k_hw *ah, @@ -2772,11 +2381,7 @@ ath5k_get_rate_pcal_data(struct ath5k_hw *ah, rpinfo[idx_r].target_power_54); } -/** - * ath5k_get_max_ctl_power() - Get max edge power for a given frequency - * @ah: the &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * +/* * Get the max edge power for this channel if * we have such data from EEPROM's Conformance Test * Limits (CTL), and limit max power if needed. @@ -2856,39 +2461,8 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, * Power to PCDAC table functions */ -/** - * DOC: Power to PCDAC table functions - * - * For RF5111 we have an XPD -eXternal Power Detector- curve - * for each calibrated channel. Each curve has 0,5dB Power steps - * on x axis and PCDAC steps (offsets) on y axis and looks like an - * exponential function. To recreate the curve we read 11 points - * from eeprom (eeprom.c) and interpolate here. - * - * For RF5112 we have 4 XPD -eXternal Power Detector- curves - * for each calibrated channel on 0, -6, -12 and -18dBm but we only - * use the higher (3) and the lower (0) curves. Each curve again has 0.5dB - * power steps on x axis and PCDAC steps on y axis and looks like a - * linear function. To recreate the curve and pass the power values - * on hw, we get 4 points for xpd 0 (lower gain -> max power) - * and 3 points for xpd 3 (higher gain -> lower power) from eeprom (eeprom.c) - * and interpolate here. - * - * For a given channel we get the calibrated points (piers) for it or - * -if we don't have calibration data for this specific channel- from the - * available surrounding channels we have calibration data for, after we do a - * linear interpolation between them. Then since we have our calibrated points - * for this channel, we do again a linear interpolation between them to get the - * whole curve. - * - * We finally write the Y values of the curve(s) (the PCDAC values) on hw - */ - -/** - * ath5k_fill_pwr_to_pcdac_table() - Fill Power to PCDAC table on RF5111 - * @ah: The &struct ath5k_hw - * @table_min: Minimum power (x min) - * @table_max: Maximum power (x max) +/* + * Fill Power to PCDAC table on RF5111 * * No further processing is needed for RF5111, the only thing we have to * do is fill the values below and above calibration range since eeprom data @@ -2929,14 +2503,10 @@ ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min, } -/** - * ath5k_combine_linear_pcdac_curves() - Combine available PCDAC Curves - * @ah: The &struct ath5k_hw - * @table_min: Minimum power (x min) - * @table_max: Maximum power (x max) - * @pdcurves: Number of pd curves +/* + * Combine available XPD Curves and fill Linear Power to PCDAC table + * on RF5112 * - * Combine available XPD Curves and fill Linear Power to PCDAC table on RF5112 * RFX112 can have up to 2 curves (one for low txpower range and one for * higher txpower range). We need to put them both on pcdac_out and place * them in the correct location. In case we only have one curve available @@ -3038,10 +2608,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, } } -/** - * ath5k_write_pcdac_table() - Write the PCDAC values on hw - * @ah: The &struct ath5k_hw - */ +/* Write PCDAC values on hw */ static void ath5k_write_pcdac_table(struct ath5k_hw *ah) { @@ -3064,32 +2631,9 @@ ath5k_write_pcdac_table(struct ath5k_hw *ah) * Power to PDADC table functions */ -/** - * DOC: Power to PDADC table functions - * - * For RF2413 and later we have a Power to PDADC table (Power Detector) - * instead of a PCDAC (Power Control) and 4 pd gain curves for each - * calibrated channel. Each curve has power on x axis in 0.5 db steps and - * PDADC steps on y axis and looks like an exponential function like the - * RF5111 curve. - * - * To recreate the curves we read the points from eeprom (eeprom.c) - * and interpolate here. Note that in most cases only 2 (higher and lower) - * curves are used (like RF5112) but vendors have the opportunity to include - * all 4 curves on eeprom. The final curve (higher power) has an extra - * point for better accuracy like RF5112. - * - * The process is similar to what we do above for RF5111/5112 - */ - -/** - * ath5k_combine_pwr_to_pdadc_curves() - Combine the various PDADC curves - * @ah: The &struct ath5k_hw - * @pwr_min: Minimum power (x min) - * @pwr_max: Maximum power (x max) - * @pdcurves: Number of available curves +/* + * Set the gain boundaries and create final Power to PDADC table * - * Combine the various pd curves and create the final Power to PDADC table * We can have up to 4 pd curves, we need to do a similar process * as we do for RF5112. This time we don't have an edge_flag but we * set the gain boundaries on a separate register. @@ -3213,11 +2757,7 @@ ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, } -/** - * ath5k_write_pwr_to_pdadc_table() - Write the PDADC values on hw - * @ah: The &struct ath5k_hw - * @ee_mode: One of enum ath5k_driver_mode - */ +/* Write PDADC values on hw */ static void ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode) { @@ -3274,13 +2814,7 @@ ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode) * Common code for PCDAC/PDADC tables */ -/** - * ath5k_setup_channel_powertable() - Set up power table for this channel - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * @ee_mode: One of enum ath5k_driver_mode - * @type: One of enum ath5k_powertable_type (eeprom.h) - * +/* * This is the main function that uses all of the above * to set PCDAC/PDADC table on hw for the current channel. * This table is used for tx power calibration on the baseband, @@ -3478,12 +3012,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, return 0; } -/** - * ath5k_write_channel_powertable() - Set power table for current channel on hw - * @ah: The &struct ath5k_hw - * @ee_mode: One of enum ath5k_driver_mode - * @type: One of enum ath5k_powertable_type (eeprom.h) - */ +/* Write power table for current channel to hw */ static void ath5k_write_channel_powertable(struct ath5k_hw *ah, u8 ee_mode, u8 type) { @@ -3493,36 +3022,28 @@ ath5k_write_channel_powertable(struct ath5k_hw *ah, u8 ee_mode, u8 type) ath5k_write_pcdac_table(ah); } - -/** - * DOC: Per-rate tx power setting +/* + * Per-rate tx power setting * - * This is the code that sets the desired tx power limit (below + * This is the code that sets the desired tx power (below * maximum) on hw for each rate (we also have TPC that sets - * power per packet type). We do that by providing an index on the - * PCDAC/PDADC table we set up above, for each rate. + * power per packet). We do that by providing an index on the + * PCDAC/PDADC table we set up. + */ + +/* + * Set rate power table * * For now we only limit txpower based on maximum tx power - * supported by hw (what's inside rate_info) + conformance test - * limits. We need to limit this even more, based on regulatory domain - * etc to be safe. Normally this is done from above so we don't care - * here, all we care is that the tx power we set will be O.K. - * for the hw (e.g. won't create noise on PA etc). + * supported by hw (what's inside rate_info). We need to limit + * this even more, based on regulatory domain etc. * - * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps - - * x values) and is indexed as follows: + * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps) + * and is indexed as follows: * rates[0] - rates[7] -> OFDM rates * rates[8] - rates[14] -> CCK rates * rates[15] -> XR rates (they all have the same power) */ - -/** - * ath5k_setup_rate_powertable() - Set up rate power table for a given tx power - * @ah: The &struct ath5k_hw - * @max_pwr: The maximum tx power requested in 0.5dB steps - * @rate_info: The &struct ath5k_rate_pcal_info to fill - * @ee_mode: One of enum ath5k_driver_mode - */ static void ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, struct ath5k_rate_pcal_info *rate_info, @@ -3593,14 +3114,8 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, } -/** - * ath5k_hw_txpower() - Set transmission power limit for a given channel - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * @txpower: Requested tx power in 0.5dB steps - * - * Combines all of the above to set the requested tx power limit - * on hw. +/* + * Set transmission power */ static int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, @@ -3718,16 +3233,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, return 0; } -/** - * ath5k_hw_set_txpower_limit() - Set txpower limit for the current channel - * @ah: The &struct ath5k_hw - * @txpower: The requested tx power limit in 0.5dB steps - * - * This function provides access to ath5k_hw_txpower to the driver in - * case user or an application changes it while PHY is running. - */ -int -ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) +int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) { ATH5K_DBG(ah, ATH5K_DEBUG_TXPOWER, "changing txpower to %d\n", txpower); @@ -3735,26 +3241,11 @@ ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower); } - /*************\ Init function \*************/ -/** - * ath5k_hw_phy_init() - Initialize PHY - * @ah: The &struct ath5k_hw - * @channel: The @struct ieee80211_channel - * @mode: One of enum ath5k_driver_mode - * @fast: Try a fast channel switch instead - * - * This is the main function used during reset to initialize PHY - * or do a fast channel change if possible. - * - * NOTE: Do not call this one from the driver, it assumes PHY is in a - * warm reset state ! - */ -int -ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, +int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 mode, bool fast) { struct ieee80211_channel *curr_channel; @@ -3864,7 +3355,7 @@ ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, if (ret) return ret; - usleep_range(1000, 1500); + mdelay(1); /* * Write RF buffer @@ -3885,10 +3376,10 @@ ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, } } else if (ah->ah_version == AR5K_AR5210) { - usleep_range(1000, 1500); + mdelay(1); /* Disable phy and wait */ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); - usleep_range(1000, 1500); + mdelay(1); } /* Set channel on PHY */ @@ -3914,7 +3405,7 @@ ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, for (i = 0; i <= 20; i++) { if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) break; - usleep_range(200, 250); + udelay(200); } ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); @@ -3942,9 +3433,9 @@ ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, /* At the same time start I/Q calibration for QAM constellation * -no need for CCK- */ - ah->ah_iq_cal_needed = false; + ah->ah_calibration = false; if (!(mode == AR5K_MODE_11B)) { - ah->ah_iq_cal_needed = true; + ah->ah_calibration = true; AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, diff --git a/trunk/drivers/net/wireless/ath/ath5k/qcu.c b/trunk/drivers/net/wireless/ath/ath5k/qcu.c index 30b50f934172..776654228eaa 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/qcu.c +++ b/trunk/drivers/net/wireless/ath/ath5k/qcu.c @@ -17,48 +17,23 @@ */ /********************************************\ -Queue Control Unit, DCF Control Unit Functions +Queue Control Unit, DFS Control Unit Functions \********************************************/ #include "ath5k.h" #include "reg.h" #include "debug.h" -#include - -/** - * DOC: Queue Control Unit (QCU)/DCF Control Unit (DCU) functions - * - * Here we setup parameters for the 12 available TX queues. Note that - * on the various registers we can usually only map the first 10 of them so - * basically we have 10 queues to play with. Each queue has a matching - * QCU that controls when the queue will get triggered and multiple QCUs - * can be mapped to a single DCU that controls the various DFS parameters - * for the various queues. In our setup we have a 1:1 mapping between QCUs - * and DCUs allowing us to have different DFS settings for each queue. - * - * When a frame goes into a TX queue, QCU decides when it'll trigger a - * transmission based on various criteria (such as how many data we have inside - * it's buffer or -if it's a beacon queue- if it's time to fire up the queue - * based on TSF etc), DCU adds backoff, IFSes etc and then a scheduler - * (arbitrator) decides the priority of each QCU based on it's configuration - * (e.g. beacons are always transmitted when they leave DCU bypassing all other - * frames from other queues waiting to be transmitted). After a frame leaves - * the DCU it goes to PCU for further processing and then to PHY for - * the actual transmission. - */ /******************\ * Helper functions * \******************/ -/** - * ath5k_hw_num_tx_pending() - Get number of pending frames for a given queue - * @ah: The &struct ath5k_hw - * @queue: One of enum ath5k_tx_queue_id +/* + * Get number of pending frames + * for a specific queue [5211+] */ -u32 -ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) +u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) { u32 pending; AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); @@ -83,13 +58,10 @@ ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) return pending; } -/** - * ath5k_hw_release_tx_queue() - Set a transmit queue inactive - * @ah: The &struct ath5k_hw - * @queue: One of enum ath5k_tx_queue_id +/* + * Set a transmit queue inactive */ -void -ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) +void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) { if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) return; @@ -100,56 +72,34 @@ ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); } -/** - * ath5k_cw_validate() - Make sure the given cw is valid - * @cw_req: The contention window value to check - * +/* * Make sure cw is a power of 2 minus 1 and smaller than 1024 */ -static u16 -ath5k_cw_validate(u16 cw_req) +static u16 ath5k_cw_validate(u16 cw_req) { + u32 cw = 1; cw_req = min(cw_req, (u16)1023); - /* Check if cw_req + 1 a power of 2 */ - if (is_power_of_2(cw_req + 1)) - return cw_req; + while (cw < cw_req) + cw = (cw << 1) | 1; - /* Check if cw_req is a power of 2 */ - if (is_power_of_2(cw_req)) - return cw_req - 1; - - /* If none of the above is correct - * find the closest power of 2 */ - cw_req = (u16) roundup_pow_of_two(cw_req) - 1; - - return cw_req; + return cw; } -/** - * ath5k_hw_get_tx_queueprops() - Get properties for a transmit queue - * @ah: The &struct ath5k_hw - * @queue: One of enum ath5k_tx_queue_id - * @queue_info: The &struct ath5k_txq_info to fill +/* + * Get properties for a transmit queue */ -int -ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, +int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info) { memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); return 0; } -/** - * ath5k_hw_set_tx_queueprops() - Set properties for a transmit queue - * @ah: The &struct ath5k_hw - * @queue: One of enum ath5k_tx_queue_id - * @qinfo: The &struct ath5k_txq_info to use - * - * Returns 0 on success or -EIO if queue is inactive +/* + * Set properties for a transmit queue */ -int -ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, +int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, const struct ath5k_txq_info *qinfo) { struct ath5k_txq_info *qi; @@ -189,16 +139,10 @@ ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, return 0; } -/** - * ath5k_hw_setup_tx_queue() - Initialize a transmit queue - * @ah: The &struct ath5k_hw - * @queue_type: One of enum ath5k_tx_queue - * @queue_info: The &struct ath5k_txq_info to use - * - * Returns 0 on success, -EINVAL on invalid arguments +/* + * Initialize a transmit queue */ -int -ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, +int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, struct ath5k_txq_info *queue_info) { unsigned int queue; @@ -273,16 +217,10 @@ ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, * Single QCU/DCU initialization * \*******************************/ -/** - * ath5k_hw_set_tx_retry_limits() - Set tx retry limits on DCU - * @ah: The &struct ath5k_hw - * @queue: One of enum ath5k_tx_queue_id - * - * This function is used when initializing a queue, to set - * retry limits based on ah->ah_retry_* and the chipset used. +/* + * Set tx retry limits on DCU */ -void -ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, +void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, unsigned int queue) { /* Single data queue on AR5210 */ @@ -317,15 +255,15 @@ ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, } /** - * ath5k_hw_reset_tx_queue() - Initialize a single hw queue - * @ah: The &struct ath5k_hw - * @queue: One of enum ath5k_tx_queue_id + * ath5k_hw_reset_tx_queue - Initialize a single hw queue * - * Set DCF properties for the given transmit queue on DCU + * @ah The &struct ath5k_hw + * @queue The hw queue number + * + * Set DFS properties for the given transmit queue on DCU * and configures all queue-specific parameters. */ -int -ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) +int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) { struct ath5k_txq_info *tq = &ah->ah_txq[queue]; @@ -553,9 +491,10 @@ ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) \**************************/ /** - * ath5k_hw_set_ifs_intervals() - Set global inter-frame spaces on DCU - * @ah: The &struct ath5k_hw - * @slot_time: Slot time in us + * ath5k_hw_set_ifs_intervals - Set global inter-frame spaces on DCU + * + * @ah The &struct ath5k_hw + * @slot_time Slot time in us * * Sets the global IFS intervals on DCU (also works on AR5210) for * the given slot time and the current bwmode. @@ -658,15 +597,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) } -/** - * ath5k_hw_init_queues() - Initialize tx queues - * @ah: The &struct ath5k_hw - * - * Initializes all tx queues based on information on - * ah->ah_txq* set by the driver - */ -int -ath5k_hw_init_queues(struct ath5k_hw *ah) +int ath5k_hw_init_queues(struct ath5k_hw *ah) { int i, ret; diff --git a/trunk/drivers/net/wireless/ath/ath5k/reg.h b/trunk/drivers/net/wireless/ath/ath5k/reg.h index 0ea1608b47fd..f5c1000045d3 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/reg.h +++ b/trunk/drivers/net/wireless/ath/ath5k/reg.h @@ -280,10 +280,6 @@ * 5211/5212 we have one primary and 4 secondary registers. * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212. * Most of these bits are common for all chipsets. - * - * NOTE: On 5211+ TXOK, TXDESC, TXERR, TXEOL and TXURN contain - * the logical OR from per-queue interrupt bits found on SISR registers - * (see below). */ #define AR5K_ISR 0x001c /* Register Address [5210] */ #define AR5K_PISR 0x0080 /* Register Address [5211+] */ @@ -296,10 +292,7 @@ #define AR5K_ISR_TXOK 0x00000040 /* Frame successfully transmitted */ #define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */ #define AR5K_ISR_TXERR 0x00000100 /* Transmit error */ -#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmitted (transmit timeout) - * NOTE: We don't have per-queue info for this - * one, but we can enable it per-queue through - * TXNOFRM_QCU field on TXNOFRM register */ +#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmitted (transmit timeout) */ #define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */ #define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */ #define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */ @@ -309,29 +302,21 @@ #define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */ #define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */ #define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */ -#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] - * 'or' of MCABT, SSERR, DPERR from SISR2 */ +#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ #define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */ #define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */ #define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */ #define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */ -#define AR5K_ISR_DPERR 0x00400000 /* Bus parity error [5210] */ +#define AR5K_ISR_DPERR 0x00400000 /* Det par Error (?) [5210] */ #define AR5K_ISR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */ #define AR5K_ISR_TIM 0x00800000 /* [5211+] */ -#define AR5K_ISR_BCNMISC 0x00800000 /* Misc beacon related interrupt - * 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT, - * CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */ +#define AR5K_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT, + CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */ #define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill) */ #define AR5K_ISR_QCBRORN 0x02000000 /* QCU CBR overrun [5211+] */ #define AR5K_ISR_QCBRURN 0x04000000 /* QCU CBR underrun [5211+] */ #define AR5K_ISR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */ -#define AR5K_ISR_BITS_FROM_SISRS (AR5K_ISR_TXOK | AR5K_ISR_TXDESC |\ - AR5K_ISR_TXERR | AR5K_ISR_TXEOL |\ - AR5K_ISR_TXURN | AR5K_ISR_HIUERR |\ - AR5K_ISR_BCNMISC | AR5K_ISR_QCBRORN |\ - AR5K_ISR_QCBRURN | AR5K_ISR_QTRIG) - /* * Secondary status registers [5211+] (0 - 4) * @@ -362,7 +347,7 @@ #define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ #define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ #define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */ -#define AR5K_SISR2_TSFOOR 0x80000000 /* TSF Out of range */ +#define AR5K_SISR2_TSFOOR 0x80000000 /* TSF OOR (?) */ #define AR5K_SISR3 0x0090 /* Register Address [5211+] */ #define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ diff --git a/trunk/drivers/net/wireless/ath/ath5k/reset.c b/trunk/drivers/net/wireless/ath/ath5k/reset.c index 4aed3a3ab109..2abac257b4b4 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/reset.c +++ b/trunk/drivers/net/wireless/ath/ath5k/reset.c @@ -19,9 +19,9 @@ * */ -/****************************\ - Reset function and helpers -\****************************/ +/*****************************\ + Reset functions and helpers +\*****************************/ #include @@ -33,36 +33,14 @@ #include "debug.h" -/** - * DOC: Reset function and helpers - * - * Here we implement the main reset routine, used to bring the card - * to a working state and ready to receive. We also handle routines - * that don't fit on other places such as clock, sleep and power control - */ - - /******************\ * Helper functions * \******************/ -/** - * ath5k_hw_register_timeout() - Poll a register for a flag/field change - * @ah: The &struct ath5k_hw - * @reg: The register to read - * @flag: The flag/field to check on the register - * @val: The field value we expect (if we check a field) - * @is_set: Instead of checking if the flag got cleared, check if it got set - * - * Some registers contain flags that indicate that an operation is - * running. We use this function to poll these registers and check - * if these flags get cleared. We also use it to poll a register - * field (containing multiple flags) until it gets a specific value. - * - * Returns -EAGAIN if we exceeded AR5K_TUNE_REGISTER_TIMEOUT * 15us or 0 +/* + * Check if a register write has been completed */ -int -ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, +int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, bool is_set) { int i; @@ -86,48 +64,35 @@ ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, \*************************/ /** - * ath5k_hw_htoclock() - Translate usec to hw clock units + * ath5k_hw_htoclock - Translate usec to hw clock units + * * @ah: The &struct ath5k_hw * @usec: value in microseconds - * - * Translate usecs to hw clock units based on the current - * hw clock rate. - * - * Returns number of clock units */ -unsigned int -ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) +unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) { struct ath_common *common = ath5k_hw_common(ah); return usec * common->clockrate; } /** - * ath5k_hw_clocktoh() - Translate hw clock units to usec - * @ah: The &struct ath5k_hw + * ath5k_hw_clocktoh - Translate hw clock units to usec * @clock: value in hw clock units - * - * Translate hw clock units to usecs based on the current - * hw clock rate. - * - * Returns number of usecs */ -unsigned int -ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) +unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) { struct ath_common *common = ath5k_hw_common(ah); return clock / common->clockrate; } /** - * ath5k_hw_init_core_clock() - Initialize core clock - * @ah: The &struct ath5k_hw + * ath5k_hw_init_core_clock - Initialize core clock + * + * @ah The &struct ath5k_hw * - * Initialize core clock parameters (usec, usec32, latencies etc), - * based on current bwmode and chipset properties. + * Initialize core clock parameters (usec, usec32, latencies etc). */ -static void -ath5k_hw_init_core_clock(struct ath5k_hw *ah) +static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) { struct ieee80211_channel *channel = ah->ah_current_channel; struct ath_common *common = ath5k_hw_common(ah); @@ -262,21 +227,16 @@ ath5k_hw_init_core_clock(struct ath5k_hw *ah) } } -/** - * ath5k_hw_set_sleep_clock() - Setup sleep clock operation - * @ah: The &struct ath5k_hw - * @enable: Enable sleep clock operation (false to disable) - * +/* * If there is an external 32KHz crystal available, use it * as ref. clock instead of 32/40MHz clock and baseband clocks * to save power during sleep or restore normal 32/40MHz * operation. * - * NOTE: When operating on 32KHz certain PHY registers (27 - 31, - * 123 - 127) require delay on access. + * XXX: When operating on 32KHz certain PHY registers (27 - 31, + * 123 - 127) require delay on access. */ -static void -ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) +static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; u32 scal, spending, sclock; @@ -380,19 +340,10 @@ ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) * Reset/Sleep control * \*********************/ -/** - * ath5k_hw_nic_reset() - Reset the various chipset units - * @ah: The &struct ath5k_hw - * @val: Mask to indicate what units to reset - * - * To reset the various chipset units we need to write - * the mask to AR5K_RESET_CTL and poll the register until - * all flags are cleared. - * - * Returns 0 if we are O.K. or -EAGAIN (from athk5_hw_register_timeout) +/* + * Reset chipset */ -static int -ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) +static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) { int ret; u32 mask = val ? val : ~0U; @@ -406,7 +357,7 @@ ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL); /* Wait at least 128 PCI clocks */ - usleep_range(15, 20); + udelay(15); if (ah->ah_version == AR5K_AR5210) { val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA @@ -431,17 +382,12 @@ ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) return ret; } -/** - * ath5k_hw_wisoc_reset() - Reset AHB chipset - * @ah: The &struct ath5k_hw - * @flags: Mask to indicate what units to reset - * - * Same as ath5k_hw_nic_reset but for AHB based devices - * - * Returns 0 if we are O.K. or -EAGAIN (from athk5_hw_register_timeout) +/* + * Reset AHB chipset + * AR5K_RESET_CTL_PCU flag resets WMAC + * AR5K_RESET_CTL_BASEBAND flag resets WBB */ -static int -ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) +static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) { u32 mask = flags ? flags : ~0U; u32 __iomem *reg; @@ -476,7 +422,7 @@ ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) regval = __raw_readl(reg); __raw_writel(regval | val, reg); regval = __raw_readl(reg); - usleep_range(100, 150); + udelay(100); /* Bring BB/MAC out of reset */ __raw_writel(regval & ~val, reg); @@ -493,23 +439,11 @@ ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) return 0; } -/** - * ath5k_hw_set_power_mode() - Set power mode - * @ah: The &struct ath5k_hw - * @mode: One of enum ath5k_power_mode - * @set_chip: Set to true to write sleep control register - * @sleep_duration: How much time the device is allowed to sleep - * when sleep logic is enabled (in 128 microsecond increments). - * - * This function is used to configure sleep policy and allowed - * sleep modes. For more information check out the sleep control - * register on reg.h and STA_ID1. - * - * Returns 0 on success, -EIO if chip didn't wake up or -EINVAL if an invalid - * mode is requested. + +/* + * Sleep control */ -static int -ath5k_hw_set_power_mode(struct ath5k_hw *ah, enum ath5k_power_mode mode, +static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration) { unsigned int i; @@ -559,7 +493,7 @@ ath5k_hw_set_power_mode(struct ath5k_hw *ah, enum ath5k_power_mode mode, ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, AR5K_SLEEP_CTL); - usleep_range(15, 20); + udelay(15); for (i = 200; i > 0; i--) { /* Check if the chip did wake up */ @@ -568,7 +502,7 @@ ath5k_hw_set_power_mode(struct ath5k_hw *ah, enum ath5k_power_mode mode, break; /* Wait a bit and retry */ - usleep_range(50, 75); + udelay(50); ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, AR5K_SLEEP_CTL); } @@ -589,20 +523,17 @@ ath5k_hw_set_power_mode(struct ath5k_hw *ah, enum ath5k_power_mode mode, return 0; } -/** - * ath5k_hw_on_hold() - Put device on hold - * @ah: The &struct ath5k_hw +/* + * Put device on hold * - * Put MAC and Baseband on warm reset and keep that state - * (don't clean sleep control register). After this MAC - * and Baseband are disabled and a full reset is needed - * to come back. This way we save as much power as possible + * Put MAC and Baseband on warm reset and + * keep that state (don't clean sleep control + * register). After this MAC and Baseband are + * disabled and a full reset is needed to come + * back. This way we save as much power as possible * without putting the card on full sleep. - * - * Returns 0 on success or -EIO on error */ -int -ath5k_hw_on_hold(struct ath5k_hw *ah) +int ath5k_hw_on_hold(struct ath5k_hw *ah) { struct pci_dev *pdev = ah->pdev; u32 bus_flags; @@ -612,7 +543,7 @@ ath5k_hw_on_hold(struct ath5k_hw *ah) return 0; /* Make sure device is awake */ - ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); + ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); if (ret) { ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); return ret; @@ -632,7 +563,7 @@ ath5k_hw_on_hold(struct ath5k_hw *ah) ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); - usleep_range(2000, 2500); + mdelay(2); } else { ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND | bus_flags); @@ -644,7 +575,7 @@ ath5k_hw_on_hold(struct ath5k_hw *ah) } /* ...wakeup again!*/ - ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); + ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); if (ret) { ATH5K_ERR(ah, "failed to put device on hold\n"); return ret; @@ -653,18 +584,11 @@ ath5k_hw_on_hold(struct ath5k_hw *ah) return ret; } -/** - * ath5k_hw_nic_wakeup() - Force card out of sleep - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * +/* * Bring up MAC + PHY Chips and program PLL - * NOTE: Channel is NULL for the initial wakeup. - * - * Returns 0 on success, -EIO on hw failure or -EINVAL for false channel infos + * Channel is NULL for the initial wakeup. */ -int -ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) +int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) { struct pci_dev *pdev = ah->pdev; u32 turbo, mode, clock, bus_flags; @@ -676,7 +600,7 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) { /* Wakeup the device */ - ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); + ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); if (ret) { ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); return ret; @@ -697,7 +621,7 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); - usleep_range(2000, 2500); + mdelay(2); } else { if (ath5k_get_bus_type(ah) == ATH_AHB) ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU | @@ -713,7 +637,7 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) } /* ...wakeup again!...*/ - ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); + ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); if (ret) { ATH5K_ERR(ah, "failed to resume the MAC Chip\n"); return ret; @@ -815,7 +739,7 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) /* ...update PLL if needed */ if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) { ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL); - usleep_range(300, 350); + udelay(300); } /* ...set the PHY operating mode */ @@ -831,19 +755,8 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) * Post-initvals register modifications * \**************************************/ -/** - * ath5k_hw_tweak_initval_settings() - Tweak initial settings - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * - * Some settings are not handled on initvals, e.g. bwmode - * settings, some phy settings, workarounds etc that in general - * don't fit anywhere else or are too small to introduce a separate - * function for each one. So we have this function to handle - * them all during reset and complete card's initialization. - */ -static void -ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, +/* TODO: Half/Quarter rate */ +static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, struct ieee80211_channel *channel) { if (ah->ah_version == AR5K_AR5212 && @@ -962,16 +875,7 @@ ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, } } -/** - * ath5k_hw_commit_eeprom_settings() - Commit settings from EEPROM - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * - * Use settings stored on EEPROM to properly initialize the card - * based on various infos and per-mode calibration data. - */ -static void -ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, +static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, struct ieee80211_channel *channel) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; @@ -1125,23 +1029,7 @@ ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, * Main reset function * \*********************/ -/** - * ath5k_hw_reset() - The main reset function - * @ah: The &struct ath5k_hw - * @op_mode: One of enum nl80211_iftype - * @channel: The &struct ieee80211_channel - * @fast: Enable fast channel switching - * @skip_pcu: Skip pcu initialization - * - * This is the function we call each time we want to (re)initialize the - * card and pass new settings to hw. We also call it when hw runs into - * trouble to make it come back to a working state. - * - * Returns 0 on success, -EINVAL on false op_mode or channel infos, or -EIO - * on failure. - */ -int -ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, +int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool fast, bool skip_pcu) { u32 s_seq[10], s_led[3], tsf_up, tsf_lo; @@ -1354,7 +1242,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /* * Initialize PCU */ - ath5k_hw_pcu_init(ah, op_mode); + ath5k_hw_pcu_init(ah, op_mode, mode); /* * Initialize PHY diff --git a/trunk/drivers/net/wireless/ath/ath5k/rfbuffer.h b/trunk/drivers/net/wireless/ath/ath5k/rfbuffer.h index aed34d9954c0..5d11c23b4297 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/rfbuffer.h +++ b/trunk/drivers/net/wireless/ath/ath5k/rfbuffer.h @@ -18,9 +18,7 @@ */ -/** - * DOC: RF Buffer registers - * +/* * There are some special registers on the RF chip * that control various operation settings related mostly to * the analog parts (channel, gain adjustment etc). @@ -46,63 +44,40 @@ */ -/** - * struct ath5k_ini_rfbuffer - Initial RF Buffer settings - * @rfb_bank: RF Bank number - * @rfb_ctrl_register: RF Buffer control register - * @rfb_mode_data: RF Buffer data for each mode - * +/* * Struct to hold default mode specific RF - * register values (RF Banks) for each chip. + * register values (RF Banks) */ struct ath5k_ini_rfbuffer { - u8 rfb_bank; - u16 rfb_ctrl_register; - u32 rfb_mode_data[3]; + u8 rfb_bank; /* RF Bank number */ + u16 rfb_ctrl_register; /* RF Buffer control register */ + u32 rfb_mode_data[3]; /* RF Buffer data for each mode */ }; -/** - * struct ath5k_rfb_field - An RF Buffer field (register/value) - * @len: Field length - * @pos: Offset on the raw packet - * @col: Used for shifting - * +/* * Struct to hold RF Buffer field * infos used to access certain RF * analog registers */ struct ath5k_rfb_field { - u8 len; - u16 pos; - u8 col; + u8 len; /* Field length */ + u16 pos; /* Offset on the raw packet */ + u8 col; /* Column -used for shifting */ }; -/** - * struct ath5k_rf_reg - RF analog register definition - * @bank: RF Buffer Bank number - * @index: Register's index on ath5k_rf_regx_idx - * @field: The &struct ath5k_rfb_field - * - * We use this struct to define the set of RF registers - * on each chip that we want to tweak. Some RF registers - * are common between different chip versions so this saves - * us space and complexity because we can refer to an rf - * register by it's index no matter what chip we work with - * as long as it has that register. +/* + * RF analog register definition */ struct ath5k_rf_reg { - u8 bank; - u8 index; - struct ath5k_rfb_field field; + u8 bank; /* RF Buffer Bank number */ + u8 index; /* Register's index on rf_regs_idx */ + struct ath5k_rfb_field field; /* RF Buffer field for this register */ }; -/** - * enum ath5k_rf_regs_idx - Map RF registers to indexes - * +/* Map RF registers to indexes * We do this to handle common bits and make our * life easier by using an index for each register - * instead of a full rfb_field - */ + * instead of a full rfb_field */ enum ath5k_rf_regs_idx { /* BANK 2 */ AR5K_RF_TURBO = 0, diff --git a/trunk/drivers/net/wireless/ath/ath5k/rfgain.h b/trunk/drivers/net/wireless/ath/ath5k/rfgain.h index 4d21df0e5975..ebfae052d89e 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/rfgain.h +++ b/trunk/drivers/net/wireless/ath/ath5k/rfgain.h @@ -18,17 +18,13 @@ * */ -/** - * struct ath5k_ini_rfgain - RF Gain table - * @rfg_register: RF Gain register address - * @rfg_value: Register value for 5 and 2GHz - * +/* * Mode-specific RF Gain table (64bytes) for RF5111/5112 * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial * RF Gain values are included in AR5K_AR5210_INI) */ struct ath5k_ini_rfgain { - u16 rfg_register; + u16 rfg_register; /* RF Gain register address */ u32 rfg_value[2]; /* [freq (see below)] */ }; @@ -459,31 +455,18 @@ static const struct ath5k_ini_rfgain rfgain_2425[] = { #define AR5K_GAIN_CHECK_ADJUST(_g) \ ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high) -/** - * struct ath5k_gain_opt_step - An RF gain optimization step - * @gos_param: Set of parameters - * @gos_gain: Gain - */ struct ath5k_gain_opt_step { s8 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS]; s8 gos_gain; }; -/** - * struct ath5k_gain_opt - RF Gain optimization ladder - * @go_default: The default step - * @go_steps_count: How many optimization steps - * @go_step: Array of &struct ath5k_gain_opt_step - */ struct ath5k_gain_opt { u8 go_default; u8 go_steps_count; const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT]; }; - /* - * RF5111 * Parameters on gos_param: * 1) Tx clip PHY register * 2) PWD 90 RF register @@ -507,7 +490,6 @@ static const struct ath5k_gain_opt rfgain_opt_5111 = { }; /* - * RF5112 * Parameters on gos_param: * 1) Mixgain ovr RF register * 2) PWD 138 RF register diff --git a/trunk/drivers/net/wireless/ath/ath9k/Makefile b/trunk/drivers/net/wireless/ath/ath9k/Makefile index 390797db5273..49d3f25f509d 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/Makefile +++ b/trunk/drivers/net/wireless/ath/ath9k/Makefile @@ -34,8 +34,7 @@ ath9k_hw-y:= \ ar9002_mac.o \ ar9003_mac.o \ ar9003_eeprom.o \ - ar9003_paprd.o \ - ar9003_mci.o + ar9003_paprd.o obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/trunk/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 157337febc2b..88279e325dca 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -203,7 +203,7 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) i); ath_dbg(common, ATH_DBG_CALIBRATE, - "Original: Chn %d iq_corr_meas = 0x%08x\n", + "Orignal: Chn %diq_corr_meas = 0x%08x\n", i, ah->totalIqCorrMeas[i]); iqCorrNeg = 0; diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 23b3a6c57800..12a730dcb500 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -18,7 +18,6 @@ #include "hw-ops.h" #include "ar9003_phy.h" #include "ar9003_rtt.h" -#include "ar9003_mci.h" #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT #define MAX_MAG_DELTA 11 @@ -226,7 +225,7 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) i); ath_dbg(common, ATH_DBG_CALIBRATE, - "Original: Chn %d iq_corr_meas = 0x%08x\n", + "Orignal: Chn %diq_corr_meas = 0x%08x\n", i, ah->totalIqCorrMeas[i]); iqCorrNeg = 0; @@ -825,7 +824,7 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable) chan_info_tab[i] + offset); ath_dbg(common, ATH_DBG_CALIBRATE, - "IQ_RES[%d]=0x%x " + "IQ RES[%d]=0x%x" "IQ_RES[%d]=0x%x\n", idx, iq_res[idx], idx + 1, iq_res[idx + 1]); @@ -935,12 +934,10 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_hw_cal_data *caldata = ah->caldata; - struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; bool txiqcal_done = false, txclcal_done = false; bool is_reusable = true, status = true; bool run_rtt_cal = false, run_agc_cal; bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); - bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI); u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | AR_PHY_AGC_CONTROL_FLTR_CAL | AR_PHY_AGC_CONTROL_PKDET_CAL; @@ -1008,31 +1005,6 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, } else if (caldata && !caldata->done_txiqcal_once) run_agc_cal = true; - if (mci && IS_CHAN_2GHZ(chan) && - (mci_hw->bt_state == MCI_BT_AWAKE) && - run_agc_cal && - !(mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL)) { - - u32 pld[4] = {0, 0, 0, 0}; - - /* send CAL_REQ only when BT is AWAKE. */ - ath_dbg(common, ATH_DBG_MCI, "MCI send WLAN_CAL_REQ 0x%x\n", - mci_hw->wlan_cal_seq); - MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_REQ); - pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_seq++; - ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false); - - /* Wait BT_CAL_GRANT for 50ms */ - ath_dbg(common, ATH_DBG_MCI, "MCI wait for BT_CAL_GRANT"); - - if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_GRANT, 0, 50000)) - ath_dbg(common, ATH_DBG_MCI, "MCI got BT_CAL_GRANT"); - else { - is_reusable = false; - ath_dbg(common, ATH_DBG_MCI, "\nMCI BT is not responding"); - } - } - txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); udelay(5); @@ -1050,21 +1022,6 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT); } - - if (mci && IS_CHAN_2GHZ(chan) && - (mci_hw->bt_state == MCI_BT_AWAKE) && - run_agc_cal && - !(mci_hw->config & ATH_MCI_CONFIG_DISABLE_MCI_CAL)) { - - u32 pld[4] = {0, 0, 0, 0}; - - ath_dbg(common, ATH_DBG_MCI, "MCI Send WLAN_CAL_DONE 0x%x\n", - mci_hw->wlan_cal_done); - MCI_GPM_SET_CAL_TYPE(pld, MCI_GPM_WLAN_CAL_DONE); - pld[MCI_GPM_WLAN_CAL_W_SEQUENCE] = mci_hw->wlan_cal_done++; - ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false); - } - if (rtt && !run_rtt_cal) { agc_ctrl |= agc_supp_cals; REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 4ba6f52943a8..a93bd63ad23b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4779,7 +4779,7 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, { struct ath_common *common = ath9k_hw_common(ah); struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep; - u16 twiceMaxEdgePower; + u16 twiceMaxEdgePower = MAX_RATE_POWER; int i; u16 scaledPower = 0, minCtlPower; static const u16 ctlModesFor11a[] = { @@ -4880,7 +4880,6 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, ctlNum = AR9300_NUM_CTLS_5G; } - twiceMaxEdgePower = MAX_RATE_POWER; for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) { ath_dbg(common, ATH_DBG_REGULATORY, "LOOP-Ctlidx %d: cfgCtl 0x%2.2x pCtlMode 0x%2.2x ctlIndex 0x%2.2x chan %d\n", diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 95587e36ab9c..ccde784a842f 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -175,47 +175,15 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) u32 isr = 0; u32 mask2 = 0; struct ath9k_hw_capabilities *pCap = &ah->caps; + u32 sync_cause = 0; struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 sync_cause = 0, async_cause; - async_cause = REG_READ(ah, AR_INTR_ASYNC_CAUSE); - - if (async_cause & (AR_INTR_MAC_IRQ | AR_INTR_ASYNC_MASK_MCI)) { + if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON) isr = REG_READ(ah, AR_ISR); } - if (async_cause & AR_INTR_ASYNC_MASK_MCI) { - u32 raw_intr, rx_msg_intr; - - rx_msg_intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW); - raw_intr = REG_READ(ah, AR_MCI_INTERRUPT_RAW); - - if ((raw_intr == 0xdeadbeef) || (rx_msg_intr == 0xdeadbeef)) - ath_dbg(common, ATH_DBG_MCI, - "MCI gets 0xdeadbeef during MCI int processing" - "new raw_intr=0x%08x, new rx_msg_raw=0x%08x, " - "raw_intr=0x%08x, rx_msg_raw=0x%08x\n", - raw_intr, rx_msg_intr, mci->raw_intr, - mci->rx_msg_intr); - else { - mci->rx_msg_intr |= rx_msg_intr; - mci->raw_intr |= raw_intr; - *masked |= ATH9K_INT_MCI; - - if (rx_msg_intr & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) - mci->cont_status = - REG_READ(ah, AR_MCI_CONT_STATUS); - - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, rx_msg_intr); - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, raw_intr); - ath_dbg(common, ATH_DBG_MCI, "AR_INTR_SYNC_MCI\n"); - - } - } - sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT; *masked = 0; diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c deleted file mode 100644 index 8599822dc83f..000000000000 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ /dev/null @@ -1,1464 +0,0 @@ -/* - * Copyright (c) 2008-2011 Atheros Communications Inc. - * - * 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 "hw.h" -#include "ar9003_phy.h" -#include "ar9003_mci.h" - -static void ar9003_mci_reset_req_wakeup(struct ath_hw *ah) -{ - if (!AR_SREV_9462_20(ah)) - return; - - REG_RMW_FIELD(ah, AR_MCI_COMMAND2, - AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 1); - udelay(1); - REG_RMW_FIELD(ah, AR_MCI_COMMAND2, - AR_MCI_COMMAND2_RESET_REQ_WAKEUP, 0); -} - -static int ar9003_mci_wait_for_interrupt(struct ath_hw *ah, u32 address, - u32 bit_position, int time_out) -{ - struct ath_common *common = ath9k_hw_common(ah); - - while (time_out) { - - if (REG_READ(ah, address) & bit_position) { - - REG_WRITE(ah, address, bit_position); - - if (address == AR_MCI_INTERRUPT_RX_MSG_RAW) { - - if (bit_position & - AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) - ar9003_mci_reset_req_wakeup(ah); - - if (bit_position & - (AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING | - AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, - AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); - - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, - AR_MCI_INTERRUPT_RX_MSG); - } - break; - } - - udelay(10); - time_out -= 10; - - if (time_out < 0) - break; - } - - if (time_out <= 0) { - ath_dbg(common, ATH_DBG_MCI, - "MCI Wait for Reg 0x%08x = 0x%08x timeout.\n", - address, bit_position); - ath_dbg(common, ATH_DBG_MCI, - "MCI INT_RAW = 0x%08x, RX_MSG_RAW = 0x%08x", - REG_READ(ah, AR_MCI_INTERRUPT_RAW), - REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW)); - time_out = 0; - } - - return time_out; -} - -void ar9003_mci_remote_reset(struct ath_hw *ah, bool wait_done) -{ - u32 payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00}; - - ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16, - wait_done, false); - udelay(5); -} - -void ar9003_mci_send_lna_transfer(struct ath_hw *ah, bool wait_done) -{ - u32 payload = 0x00000000; - - ar9003_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1, - wait_done, false); -} - -static void ar9003_mci_send_req_wake(struct ath_hw *ah, bool wait_done) -{ - ar9003_mci_send_message(ah, MCI_REQ_WAKE, MCI_FLAG_DISABLE_TIMESTAMP, - NULL, 0, wait_done, false); - udelay(5); -} - -void ar9003_mci_send_sys_waking(struct ath_hw *ah, bool wait_done) -{ - ar9003_mci_send_message(ah, MCI_SYS_WAKING, MCI_FLAG_DISABLE_TIMESTAMP, - NULL, 0, wait_done, false); -} - -static void ar9003_mci_send_lna_take(struct ath_hw *ah, bool wait_done) -{ - u32 payload = 0x70000000; - - ar9003_mci_send_message(ah, MCI_LNA_TAKE, 0, &payload, 1, - wait_done, false); -} - -static void ar9003_mci_send_sys_sleeping(struct ath_hw *ah, bool wait_done) -{ - ar9003_mci_send_message(ah, MCI_SYS_SLEEPING, - MCI_FLAG_DISABLE_TIMESTAMP, - NULL, 0, wait_done, false); -} - -static void ar9003_mci_send_coex_version_query(struct ath_hw *ah, - bool wait_done) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 payload[4] = {0, 0, 0, 0}; - - if (!mci->bt_version_known && - (mci->bt_state != MCI_BT_SLEEP)) { - ath_dbg(common, ATH_DBG_MCI, "MCI Send Coex version query\n"); - MCI_GPM_SET_TYPE_OPCODE(payload, - MCI_GPM_COEX_AGENT, MCI_GPM_COEX_VERSION_QUERY); - ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, - wait_done, true); - } -} - -static void ar9003_mci_send_coex_version_response(struct ath_hw *ah, - bool wait_done) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 payload[4] = {0, 0, 0, 0}; - - ath_dbg(common, ATH_DBG_MCI, "MCI Send Coex version response\n"); - MCI_GPM_SET_TYPE_OPCODE(payload, MCI_GPM_COEX_AGENT, - MCI_GPM_COEX_VERSION_RESPONSE); - *(((u8 *)payload) + MCI_GPM_COEX_B_MAJOR_VERSION) = - mci->wlan_ver_major; - *(((u8 *)payload) + MCI_GPM_COEX_B_MINOR_VERSION) = - mci->wlan_ver_minor; - ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); -} - -static void ar9003_mci_send_coex_wlan_channels(struct ath_hw *ah, - bool wait_done) -{ - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 *payload = &mci->wlan_channels[0]; - - if ((mci->wlan_channels_update == true) && - (mci->bt_state != MCI_BT_SLEEP)) { - MCI_GPM_SET_TYPE_OPCODE(payload, - MCI_GPM_COEX_AGENT, MCI_GPM_COEX_WLAN_CHANNELS); - ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, - wait_done, true); - MCI_GPM_SET_TYPE_OPCODE(payload, 0xff, 0xff); - } -} - -static void ar9003_mci_send_coex_bt_status_query(struct ath_hw *ah, - bool wait_done, u8 query_type) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 payload[4] = {0, 0, 0, 0}; - bool query_btinfo = !!(query_type & (MCI_GPM_COEX_QUERY_BT_ALL_INFO | - MCI_GPM_COEX_QUERY_BT_TOPOLOGY)); - - if (mci->bt_state != MCI_BT_SLEEP) { - - ath_dbg(common, ATH_DBG_MCI, - "MCI Send Coex BT Status Query 0x%02X\n", query_type); - - MCI_GPM_SET_TYPE_OPCODE(payload, - MCI_GPM_COEX_AGENT, MCI_GPM_COEX_STATUS_QUERY); - - *(((u8 *)payload) + MCI_GPM_COEX_B_BT_BITMAP) = query_type; - /* - * If bt_status_query message is not sent successfully, - * then need_flush_btinfo should be set again. - */ - if (!ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, - wait_done, true)) { - if (query_btinfo) { - mci->need_flush_btinfo = true; - - ath_dbg(common, ATH_DBG_MCI, - "MCI send bt_status_query fail, " - "set flush flag again\n"); - } - } - - if (query_btinfo) - mci->query_bt = false; - } -} - -void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt, - bool wait_done) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 payload[4] = {0, 0, 0, 0}; - - ath_dbg(common, ATH_DBG_MCI, "MCI Send Coex %s BT GPM.\n", - (halt) ? "halt" : "unhalt"); - - MCI_GPM_SET_TYPE_OPCODE(payload, - MCI_GPM_COEX_AGENT, MCI_GPM_COEX_HALT_BT_GPM); - - if (halt) { - mci->query_bt = true; - /* Send next unhalt no matter halt sent or not */ - mci->unhalt_bt_gpm = true; - mci->need_flush_btinfo = true; - *(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) = - MCI_GPM_COEX_BT_GPM_HALT; - } else - *(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) = - MCI_GPM_COEX_BT_GPM_UNHALT; - - ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, wait_done, true); -} - - -static void ar9003_mci_prep_interface(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 saved_mci_int_en; - u32 mci_timeout = 150; - - mci->bt_state = MCI_BT_SLEEP; - saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN); - - REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW)); - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, - REG_READ(ah, AR_MCI_INTERRUPT_RAW)); - - /* Remote Reset */ - ath_dbg(common, ATH_DBG_MCI, "MCI Reset sequence start\n"); - ath_dbg(common, ATH_DBG_MCI, "MCI send REMOTE_RESET\n"); - ar9003_mci_remote_reset(ah, true); - - /* - * This delay is required for the reset delay worst case value 255 in - * MCI_COMMAND2 register - */ - - if (AR_SREV_9462_10(ah)) - udelay(252); - - ath_dbg(common, ATH_DBG_MCI, "MCI Send REQ_WAKE to remoter(BT)\n"); - ar9003_mci_send_req_wake(ah, true); - - if (ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) { - - ath_dbg(common, ATH_DBG_MCI, - "MCI SYS_WAKING from remote(BT)\n"); - mci->bt_state = MCI_BT_AWAKE; - - if (AR_SREV_9462_10(ah)) - udelay(10); - /* - * we don't need to send more remote_reset at this moment. - * If BT receive first remote_reset, then BT HW will - * be cleaned up and will be able to receive req_wake - * and BT HW will respond sys_waking. - * In this case, WLAN will receive BT's HW sys_waking. - * Otherwise, if BT SW missed initial remote_reset, - * that remote_reset will still clean up BT MCI RX, - * and the req_wake will wake BT up, - * and BT SW will respond this req_wake with a remote_reset and - * sys_waking. In this case, WLAN will receive BT's SW - * sys_waking. In either case, BT's RX is cleaned up. So we - * don't need to reply BT's remote_reset now, if any. - * Similarly, if in any case, WLAN can receive BT's sys_waking, - * that means WLAN's RX is also fine. - */ - - /* Send SYS_WAKING to BT */ - - ath_dbg(common, ATH_DBG_MCI, - "MCI send SW SYS_WAKING to remote BT\n"); - - ar9003_mci_send_sys_waking(ah, true); - udelay(10); - - /* - * Set BT priority interrupt value to be 0xff to - * avoid having too many BT PRIORITY interrupts. - */ - - REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF); - REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF); - REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF); - REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF); - REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF); - - /* - * A contention reset will be received after send out - * sys_waking. Also BT priority interrupt bits will be set. - * Clear those bits before the next step. - */ - - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_CONT_RST); - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, - AR_MCI_INTERRUPT_BT_PRI); - - if (AR_SREV_9462_10(ah) || mci->is_2g) { - /* Send LNA_TRANS */ - ath_dbg(common, ATH_DBG_MCI, - "MCI send LNA_TRANS to BT\n"); - ar9003_mci_send_lna_transfer(ah, true); - udelay(5); - } - - if (AR_SREV_9462_10(ah) || (mci->is_2g && - !mci->update_2g5g)) { - if (ar9003_mci_wait_for_interrupt(ah, - AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, - mci_timeout)) - ath_dbg(common, ATH_DBG_MCI, - "MCI WLAN has control over the LNA & " - "BT obeys it\n"); - else - ath_dbg(common, ATH_DBG_MCI, - "MCI BT didn't respond to" - "LNA_TRANS\n"); - } - - if (AR_SREV_9462_10(ah)) { - /* Send another remote_reset to deassert BT clk_req. */ - ath_dbg(common, ATH_DBG_MCI, - "MCI another remote_reset to " - "deassert clk_req\n"); - ar9003_mci_remote_reset(ah, true); - udelay(252); - } - } - - /* Clear the extra redundant SYS_WAKING from BT */ - if ((mci->bt_state == MCI_BT_AWAKE) && - (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) && - (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) { - - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING); - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, - AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); - } - - REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en); -} - -void ar9003_mci_disable_interrupt(struct ath_hw *ah) -{ - REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0); -} - -void ar9003_mci_enable_interrupt(struct ath_hw *ah) -{ - - REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT); - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, - AR_MCI_INTERRUPT_RX_MSG_DEFAULT); -} - -bool ar9003_mci_check_int(struct ath_hw *ah, u32 ints) -{ - u32 intr; - - intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW); - return ((intr & ints) == ints); -} - -void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, - u32 *rx_msg_intr) -{ - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - *raw_intr = mci->raw_intr; - *rx_msg_intr = mci->rx_msg_intr; - - /* Clean int bits after the values are read. */ - mci->raw_intr = 0; - mci->rx_msg_intr = 0; -} -EXPORT_SYMBOL(ar9003_mci_get_interrupt); - -void ar9003_mci_2g5g_changed(struct ath_hw *ah, bool is_2g) -{ - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - - if (!mci->update_2g5g && - (mci->is_2g != is_2g)) - mci->update_2g5g = true; - - mci->is_2g = is_2g; -} - -static bool ar9003_mci_is_gpm_valid(struct ath_hw *ah, u32 msg_index) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 *payload; - u32 recv_type, offset; - - if (msg_index == MCI_GPM_INVALID) - return false; - - offset = msg_index << 4; - - payload = (u32 *)(mci->gpm_buf + offset); - recv_type = MCI_GPM_TYPE(payload); - - if (recv_type == MCI_GPM_RSVD_PATTERN) { - ath_dbg(common, ATH_DBG_MCI, "MCI Skip RSVD GPM\n"); - return false; - } - - return true; -} - -static void ar9003_mci_observation_set_up(struct ath_hw *ah) -{ - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MCI) { - - ath9k_hw_cfg_output(ah, 3, - AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA); - ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK); - ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); - ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); - - } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_TXRX) { - - ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX); - ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX); - ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); - ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); - ath9k_hw_cfg_output(ah, 5, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - - } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_BT) { - - ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); - ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); - ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); - ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); - - } else - return; - - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); - - if (AR_SREV_9462_20_OR_LATER(ah)) { - REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, - AR_GLB_DS_JTAG_DISABLE, 1); - REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, - AR_GLB_WLAN_UART_INTF_EN, 0); - REG_SET_BIT(ah, AR_GLB_GPIO_CONTROL, - ATH_MCI_CONFIG_MCI_OBS_GPIO); - } - - REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_GPIO_OBS_SEL, 0); - REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL, 1); - REG_WRITE(ah, AR_OBS, 0x4b); - REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL1, 0x03); - REG_RMW_FIELD(ah, AR_DIAG_SW, AR_DIAG_OBS_PT_SEL2, 0x01); - REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_LSB, 0x02); - REG_RMW_FIELD(ah, AR_MACMISC, AR_MACMISC_MISC_OBS_BUS_MSB, 0x03); - REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, - AR_PHY_TEST_CTL_DEBUGPORT_SEL, 0x07); -} - -static bool ar9003_mci_send_coex_bt_flags(struct ath_hw *ah, bool wait_done, - u8 opcode, u32 bt_flags) -{ - struct ath_common *common = ath9k_hw_common(ah); - u32 pld[4] = {0, 0, 0, 0}; - - MCI_GPM_SET_TYPE_OPCODE(pld, - MCI_GPM_COEX_AGENT, MCI_GPM_COEX_BT_UPDATE_FLAGS); - - *(((u8 *)pld) + MCI_GPM_COEX_B_BT_FLAGS_OP) = opcode; - *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 0) = bt_flags & 0xFF; - *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 1) = (bt_flags >> 8) & 0xFF; - *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 2) = (bt_flags >> 16) & 0xFF; - *(((u8 *)pld) + MCI_GPM_COEX_W_BT_FLAGS + 3) = (bt_flags >> 24) & 0xFF; - - ath_dbg(common, ATH_DBG_MCI, - "MCI BT_MCI_FLAGS: Send Coex BT Update Flags %s 0x%08x\n", - (opcode == MCI_GPM_COEX_BT_FLAGS_READ) ? "READ" : - ((opcode == MCI_GPM_COEX_BT_FLAGS_SET) ? "SET" : "CLEAR"), - bt_flags); - - return ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, - wait_done, true); -} - -void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, - bool is_full_sleep) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 regval, thresh; - - ath_dbg(common, ATH_DBG_MCI, "MCI full_sleep = %d, is_2g = %d\n", - is_full_sleep, is_2g); - - /* - * GPM buffer and scheduling message buffer are not allocated - */ - - if (!mci->gpm_addr && !mci->sched_addr) { - ath_dbg(common, ATH_DBG_MCI, - "MCI GPM and schedule buffers are not allocated"); - return; - } - - if (REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) { - ath_dbg(common, ATH_DBG_MCI, - "MCI it's deadbeef, quit mci_reset\n"); - return; - } - - /* Program MCI DMA related registers */ - REG_WRITE(ah, AR_MCI_GPM_0, mci->gpm_addr); - REG_WRITE(ah, AR_MCI_GPM_1, mci->gpm_len); - REG_WRITE(ah, AR_MCI_SCHD_TABLE_0, mci->sched_addr); - - /* - * To avoid MCI state machine be affected by incoming remote MCI msgs, - * MCI mode will be enabled later, right before reset the MCI TX and RX. - */ - - regval = SM(1, AR_BTCOEX_CTRL_AR9462_MODE) | - SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) | - SM(1, AR_BTCOEX_CTRL_PA_SHARED) | - SM(1, AR_BTCOEX_CTRL_LNA_SHARED) | - SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) | - SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) | - SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) | - SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) | - SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); - - if (is_2g && (AR_SREV_9462_20(ah)) && - !(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) { - - regval |= SM(1, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); - ath_dbg(common, ATH_DBG_MCI, - "MCI sched one step look ahead\n"); - - if (!(mci->config & - ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { - - thresh = MS(mci->config, - ATH_MCI_CONFIG_AGGR_THRESH); - thresh &= 7; - regval |= SM(1, - AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN); - regval |= SM(thresh, AR_BTCOEX_CTRL_AGGR_THRESH); - - REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, - AR_MCI_SCHD_TABLE_2_HW_BASED, 1); - REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, - AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); - - } else - ath_dbg(common, ATH_DBG_MCI, - "MCI sched aggr thresh: off\n"); - } else - ath_dbg(common, ATH_DBG_MCI, - "MCI SCHED one step look ahead off\n"); - - if (AR_SREV_9462_10(ah)) - regval |= SM(1, AR_BTCOEX_CTRL_SPDT_ENABLE_10); - - REG_WRITE(ah, AR_BTCOEX_CTRL, regval); - - if (AR_SREV_9462_20(ah)) { - REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, - AR_BTCOEX_CTRL_SPDT_ENABLE); - REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3, - AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20); - } - - REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 1); - REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); - - thresh = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV); - REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, thresh); - REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN); - - /* Resetting the Rx and Tx paths of MCI */ - regval = REG_READ(ah, AR_MCI_COMMAND2); - regval |= SM(1, AR_MCI_COMMAND2_RESET_TX); - REG_WRITE(ah, AR_MCI_COMMAND2, regval); - - udelay(1); - - regval &= ~SM(1, AR_MCI_COMMAND2_RESET_TX); - REG_WRITE(ah, AR_MCI_COMMAND2, regval); - - if (is_full_sleep) { - ar9003_mci_mute_bt(ah); - udelay(100); - } - - regval |= SM(1, AR_MCI_COMMAND2_RESET_RX); - REG_WRITE(ah, AR_MCI_COMMAND2, regval); - udelay(1); - regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX); - REG_WRITE(ah, AR_MCI_COMMAND2, regval); - - ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET, NULL); - REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, - (SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) | - SM(0x0000, AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM))); - - REG_CLR_BIT(ah, AR_MCI_TX_CTRL, - AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); - - if (AR_SREV_9462_20_OR_LATER(ah)) - ar9003_mci_observation_set_up(ah); - - mci->ready = true; - ar9003_mci_prep_interface(ah); - - if (en_int) - ar9003_mci_enable_interrupt(ah); -} - -void ar9003_mci_mute_bt(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - - /* disable all MCI messages */ - REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000); - REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff); - REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS1, 0xffffffff); - REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS2, 0xffffffff); - REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS3, 0xffffffff); - REG_SET_BIT(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); - - /* wait pending HW messages to flush out */ - udelay(10); - - /* - * Send LNA_TAKE and SYS_SLEEPING when - * 1. reset not after resuming from full sleep - * 2. before reset MCI RX, to quiet BT and avoid MCI RX misalignment - */ - - ath_dbg(common, ATH_DBG_MCI, "MCI Send LNA take\n"); - ar9003_mci_send_lna_take(ah, true); - - udelay(5); - - ath_dbg(common, ATH_DBG_MCI, "MCI Send sys sleeping\n"); - ar9003_mci_send_sys_sleeping(ah, true); -} - -void ar9003_mci_sync_bt_state(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 cur_bt_state; - - cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL); - - if (mci->bt_state != cur_bt_state) { - ath_dbg(common, ATH_DBG_MCI, - "MCI BT state mismatches. old: %d, new: %d\n", - mci->bt_state, cur_bt_state); - mci->bt_state = cur_bt_state; - } - - if (mci->bt_state != MCI_BT_SLEEP) { - - ar9003_mci_send_coex_version_query(ah, true); - ar9003_mci_send_coex_wlan_channels(ah, true); - - if (mci->unhalt_bt_gpm == true) { - ath_dbg(common, ATH_DBG_MCI, "MCI unhalt BT GPM"); - ar9003_mci_send_coex_halt_bt_gpm(ah, false, true); - } - } -} - -static void ar9003_mci_send_2g5g_status(struct ath_hw *ah, bool wait_done) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 new_flags, to_set, to_clear; - - if (AR_SREV_9462_20(ah) && - mci->update_2g5g && - (mci->bt_state != MCI_BT_SLEEP)) { - - if (mci->is_2g) { - new_flags = MCI_2G_FLAGS; - to_clear = MCI_2G_FLAGS_CLEAR_MASK; - to_set = MCI_2G_FLAGS_SET_MASK; - } else { - new_flags = MCI_5G_FLAGS; - to_clear = MCI_5G_FLAGS_CLEAR_MASK; - to_set = MCI_5G_FLAGS_SET_MASK; - } - - ath_dbg(common, ATH_DBG_MCI, - "MCI BT_MCI_FLAGS: %s 0x%08x clr=0x%08x, set=0x%08x\n", - mci->is_2g ? "2G" : "5G", new_flags, to_clear, to_set); - - if (to_clear) - ar9003_mci_send_coex_bt_flags(ah, wait_done, - MCI_GPM_COEX_BT_FLAGS_CLEAR, to_clear); - - if (to_set) - ar9003_mci_send_coex_bt_flags(ah, wait_done, - MCI_GPM_COEX_BT_FLAGS_SET, to_set); - } - - if (AR_SREV_9462_10(ah) && (mci->bt_state != MCI_BT_SLEEP)) - mci->update_2g5g = false; -} - -static void ar9003_mci_queue_unsent_gpm(struct ath_hw *ah, u8 header, - u32 *payload, bool queue) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u8 type, opcode; - - if (queue) { - - if (payload) - ath_dbg(common, ATH_DBG_MCI, - "MCI ERROR: Send fail: %02x: %02x %02x %02x\n", - header, - *(((u8 *)payload) + 4), - *(((u8 *)payload) + 5), - *(((u8 *)payload) + 6)); - else - ath_dbg(common, ATH_DBG_MCI, - "MCI ERROR: Send fail: %02x\n", header); - } - - /* check if the message is to be queued */ - if (header != MCI_GPM) - return; - - type = MCI_GPM_TYPE(payload); - opcode = MCI_GPM_OPCODE(payload); - - if (type != MCI_GPM_COEX_AGENT) - return; - - switch (opcode) { - case MCI_GPM_COEX_BT_UPDATE_FLAGS: - - if (AR_SREV_9462_10(ah)) - break; - - if (*(((u8 *)payload) + MCI_GPM_COEX_B_BT_FLAGS_OP) == - MCI_GPM_COEX_BT_FLAGS_READ) - break; - - mci->update_2g5g = queue; - - if (queue) - ath_dbg(common, ATH_DBG_MCI, - "MCI BT_MCI_FLAGS: 2G5G status %s.\n", - mci->is_2g ? "2G" : "5G"); - else - ath_dbg(common, ATH_DBG_MCI, - "MCI BT_MCI_FLAGS: 2G5G status %s.\n", - mci->is_2g ? "2G" : "5G"); - - break; - - case MCI_GPM_COEX_WLAN_CHANNELS: - - mci->wlan_channels_update = queue; - if (queue) - ath_dbg(common, ATH_DBG_MCI, - "MCI WLAN channel map \n"); - else - ath_dbg(common, ATH_DBG_MCI, - "MCI WLAN channel map \n"); - break; - - case MCI_GPM_COEX_HALT_BT_GPM: - - if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) == - MCI_GPM_COEX_BT_GPM_UNHALT) { - - mci->unhalt_bt_gpm = queue; - - if (queue) - ath_dbg(common, ATH_DBG_MCI, - "MCI UNHALT BT GPM \n"); - else { - mci->halted_bt_gpm = false; - ath_dbg(common, ATH_DBG_MCI, - "MCI UNHALT BT GPM \n"); - } - } - - if (*(((u8 *)payload) + MCI_GPM_COEX_B_HALT_STATE) == - MCI_GPM_COEX_BT_GPM_HALT) { - - mci->halted_bt_gpm = !queue; - - if (queue) - ath_dbg(common, ATH_DBG_MCI, - "MCI HALT BT GPM \n"); - else - ath_dbg(common, ATH_DBG_MCI, - "MCI UNHALT BT GPM \n"); - } - - break; - default: - break; - } -} - -void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - - if (mci->update_2g5g) { - if (mci->is_2g) { - - ar9003_mci_send_2g5g_status(ah, true); - ath_dbg(common, ATH_DBG_MCI, "MCI Send LNA trans\n"); - ar9003_mci_send_lna_transfer(ah, true); - udelay(5); - - REG_CLR_BIT(ah, AR_MCI_TX_CTRL, - AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); - - if (AR_SREV_9462_20(ah)) { - REG_CLR_BIT(ah, AR_PHY_GLB_CONTROL, - AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); - if (!(mci->config & - ATH_MCI_CONFIG_DISABLE_OSLA)) { - REG_SET_BIT(ah, AR_BTCOEX_CTRL, - AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); - } - } - } else { - ath_dbg(common, ATH_DBG_MCI, "MCI Send LNA take\n"); - ar9003_mci_send_lna_take(ah, true); - udelay(5); - - REG_SET_BIT(ah, AR_MCI_TX_CTRL, - AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE); - - if (AR_SREV_9462_20(ah)) { - REG_SET_BIT(ah, AR_PHY_GLB_CONTROL, - AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL); - REG_CLR_BIT(ah, AR_BTCOEX_CTRL, - AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); - } - - ar9003_mci_send_2g5g_status(ah, true); - } - } -} - -bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag, - u32 *payload, u8 len, bool wait_done, - bool check_bt) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - bool msg_sent = false; - u32 regval; - u32 saved_mci_int_en; - int i; - - saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN); - regval = REG_READ(ah, AR_BTCOEX_CTRL); - - if ((regval == 0xdeadbeef) || !(regval & AR_BTCOEX_CTRL_MCI_MODE_EN)) { - - ath_dbg(common, ATH_DBG_MCI, - "MCI Not sending 0x%x. MCI is not enabled. " - "full_sleep = %d\n", header, - (ah->power_mode == ATH9K_PM_FULL_SLEEP) ? 1 : 0); - - ar9003_mci_queue_unsent_gpm(ah, header, payload, true); - return false; - - } else if (check_bt && (mci->bt_state == MCI_BT_SLEEP)) { - - ath_dbg(common, ATH_DBG_MCI, - "MCI Don't send message 0x%x. BT is in sleep state\n", header); - - ar9003_mci_queue_unsent_gpm(ah, header, payload, true); - return false; - } - - if (wait_done) - REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); - - /* Need to clear SW_MSG_DONE raw bit before wait */ - - REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, - (AR_MCI_INTERRUPT_SW_MSG_DONE | - AR_MCI_INTERRUPT_MSG_FAIL_MASK)); - - if (payload) { - for (i = 0; (i * 4) < len; i++) - REG_WRITE(ah, (AR_MCI_TX_PAYLOAD0 + i * 4), - *(payload + i)); - } - - REG_WRITE(ah, AR_MCI_COMMAND0, - (SM((flag & MCI_FLAG_DISABLE_TIMESTAMP), - AR_MCI_COMMAND0_DISABLE_TIMESTAMP) | - SM(len, AR_MCI_COMMAND0_LEN) | - SM(header, AR_MCI_COMMAND0_HEADER))); - - if (wait_done && - !(ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RAW, - AR_MCI_INTERRUPT_SW_MSG_DONE, 500))) - ar9003_mci_queue_unsent_gpm(ah, header, payload, true); - else { - ar9003_mci_queue_unsent_gpm(ah, header, payload, false); - msg_sent = true; - } - - if (wait_done) - REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en); - - return msg_sent; -} -EXPORT_SYMBOL(ar9003_mci_send_message); - -void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, - u16 len, u32 sched_addr) -{ - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - void *sched_buf = (void *)((char *) gpm_buf + (sched_addr - gpm_addr)); - - mci->gpm_addr = gpm_addr; - mci->gpm_buf = gpm_buf; - mci->gpm_len = len; - mci->sched_addr = sched_addr; - mci->sched_buf = sched_buf; - - ar9003_mci_reset(ah, true, true, true); -} -EXPORT_SYMBOL(ar9003_mci_setup); - -void ar9003_mci_cleanup(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - - /* Turn off MCI and Jupiter mode. */ - REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00); - ath_dbg(common, ATH_DBG_MCI, "MCI ar9003_mci_cleanup\n"); - ar9003_mci_disable_interrupt(ah); -} -EXPORT_SYMBOL(ar9003_mci_cleanup); - -static void ar9003_mci_process_gpm_extra(struct ath_hw *ah, u8 gpm_type, - u8 gpm_opcode, u32 *p_gpm) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u8 *p_data = (u8 *) p_gpm; - - if (gpm_type != MCI_GPM_COEX_AGENT) - return; - - switch (gpm_opcode) { - case MCI_GPM_COEX_VERSION_QUERY: - ath_dbg(common, ATH_DBG_MCI, - "MCI Recv GPM COEX Version Query\n"); - ar9003_mci_send_coex_version_response(ah, true); - break; - case MCI_GPM_COEX_VERSION_RESPONSE: - ath_dbg(common, ATH_DBG_MCI, - "MCI Recv GPM COEX Version Response\n"); - mci->bt_ver_major = - *(p_data + MCI_GPM_COEX_B_MAJOR_VERSION); - mci->bt_ver_minor = - *(p_data + MCI_GPM_COEX_B_MINOR_VERSION); - mci->bt_version_known = true; - ath_dbg(common, ATH_DBG_MCI, - "MCI BT Coex version: %d.%d\n", - mci->bt_ver_major, - mci->bt_ver_minor); - break; - case MCI_GPM_COEX_STATUS_QUERY: - ath_dbg(common, ATH_DBG_MCI, - "MCI Recv GPM COEX Status Query = 0x%02X.\n", - *(p_data + MCI_GPM_COEX_B_WLAN_BITMAP)); - mci->wlan_channels_update = true; - ar9003_mci_send_coex_wlan_channels(ah, true); - break; - case MCI_GPM_COEX_BT_PROFILE_INFO: - mci->query_bt = true; - ath_dbg(common, ATH_DBG_MCI, - "MCI Recv GPM COEX BT_Profile_Info\n"); - break; - case MCI_GPM_COEX_BT_STATUS_UPDATE: - mci->query_bt = true; - ath_dbg(common, ATH_DBG_MCI, - "MCI Recv GPM COEX BT_Status_Update " - "SEQ=%d (drop&query)\n", *(p_gpm + 3)); - break; - default: - break; - } -} - -u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type, - u8 gpm_opcode, int time_out) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 *p_gpm = NULL, mismatch = 0, more_data; - u32 offset; - u8 recv_type = 0, recv_opcode = 0; - bool b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE); - - more_data = time_out ? MCI_GPM_NOMORE : MCI_GPM_MORE; - - while (time_out > 0) { - if (p_gpm) { - MCI_GPM_RECYCLE(p_gpm); - p_gpm = NULL; - } - - if (more_data != MCI_GPM_MORE) - time_out = ar9003_mci_wait_for_interrupt(ah, - AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_GPM, - time_out); - - if (!time_out) - break; - - offset = ar9003_mci_state(ah, - MCI_STATE_NEXT_GPM_OFFSET, &more_data); - - if (offset == MCI_GPM_INVALID) - continue; - - p_gpm = (u32 *) (mci->gpm_buf + offset); - recv_type = MCI_GPM_TYPE(p_gpm); - recv_opcode = MCI_GPM_OPCODE(p_gpm); - - if (MCI_GPM_IS_CAL_TYPE(recv_type)) { - - if (recv_type == gpm_type) { - - if ((gpm_type == MCI_GPM_BT_CAL_DONE) && - !b_is_bt_cal_done) { - gpm_type = MCI_GPM_BT_CAL_GRANT; - ath_dbg(common, ATH_DBG_MCI, - "MCI Recv BT_CAL_DONE" - "wait BT_CAL_GRANT\n"); - continue; - } - - break; - } - } else if ((recv_type == gpm_type) && - (recv_opcode == gpm_opcode)) - break; - - /* not expected message */ - - /* - * check if it's cal_grant - * - * When we're waiting for cal_grant in reset routine, - * it's possible that BT sends out cal_request at the - * same time. Since BT's calibration doesn't happen - * that often, we'll let BT completes calibration then - * we continue to wait for cal_grant from BT. - * Orginal: Wait BT_CAL_GRANT. - * New: Receive BT_CAL_REQ -> send WLAN_CAL_GRANT->wait - * BT_CAL_DONE -> Wait BT_CAL_GRANT. - */ - - if ((gpm_type == MCI_GPM_BT_CAL_GRANT) && - (recv_type == MCI_GPM_BT_CAL_REQ)) { - - u32 payload[4] = {0, 0, 0, 0}; - - gpm_type = MCI_GPM_BT_CAL_DONE; - ath_dbg(common, ATH_DBG_MCI, - "MCI Rcv BT_CAL_REQ, send WLAN_CAL_GRANT\n"); - - MCI_GPM_SET_CAL_TYPE(payload, - MCI_GPM_WLAN_CAL_GRANT); - - ar9003_mci_send_message(ah, MCI_GPM, 0, payload, 16, - false, false); - - ath_dbg(common, ATH_DBG_MCI, - "MCI now wait for BT_CAL_DONE\n"); - - continue; - } else { - ath_dbg(common, ATH_DBG_MCI, "MCI GPM subtype" - "not match 0x%x\n", *(p_gpm + 1)); - mismatch++; - ar9003_mci_process_gpm_extra(ah, recv_type, - recv_opcode, p_gpm); - } - } - if (p_gpm) { - MCI_GPM_RECYCLE(p_gpm); - p_gpm = NULL; - } - - if (time_out <= 0) { - time_out = 0; - ath_dbg(common, ATH_DBG_MCI, - "MCI GPM received timeout, mismatch = %d\n", mismatch); - } else - ath_dbg(common, ATH_DBG_MCI, - "MCI Receive GPM type=0x%x, code=0x%x\n", - gpm_type, gpm_opcode); - - while (more_data == MCI_GPM_MORE) { - - ath_dbg(common, ATH_DBG_MCI, "MCI discard remaining GPM\n"); - offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET, - &more_data); - - if (offset == MCI_GPM_INVALID) - break; - - p_gpm = (u32 *) (mci->gpm_buf + offset); - recv_type = MCI_GPM_TYPE(p_gpm); - recv_opcode = MCI_GPM_OPCODE(p_gpm); - - if (!MCI_GPM_IS_CAL_TYPE(recv_type)) - ar9003_mci_process_gpm_extra(ah, recv_type, - recv_opcode, p_gpm); - - MCI_GPM_RECYCLE(p_gpm); - } - - return time_out; -} - -u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data) -{ - struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; - u32 value = 0, more_gpm = 0, gpm_ptr; - u8 query_type; - - switch (state_type) { - case MCI_STATE_ENABLE: - if (mci->ready) { - - value = REG_READ(ah, AR_BTCOEX_CTRL); - - if ((value == 0xdeadbeef) || (value == 0xffffffff)) - value = 0; - } - value &= AR_BTCOEX_CTRL_MCI_MODE_EN; - break; - case MCI_STATE_INIT_GPM_OFFSET: - value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); - ath_dbg(common, ATH_DBG_MCI, - "MCI GPM initial WRITE_PTR=%d\n", value); - mci->gpm_idx = value; - break; - case MCI_STATE_NEXT_GPM_OFFSET: - case MCI_STATE_LAST_GPM_OFFSET: - /* - * This could be useful to avoid new GPM message interrupt which - * may lead to spurious interrupt after power sleep, or multiple - * entry of ath_mci_intr(). - * Adding empty GPM check by returning HAL_MCI_GPM_INVALID can - * alleviate this effect, but clearing GPM RX interrupt bit is - * safe, because whether this is called from hw or driver code - * there must be an interrupt bit set/triggered initially - */ - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_GPM); - - gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); - value = gpm_ptr; - - if (value == 0) - value = mci->gpm_len - 1; - else if (value >= mci->gpm_len) { - if (value != 0xFFFF) { - value = 0; - ath_dbg(common, ATH_DBG_MCI, "MCI GPM offset" - "out of range\n"); - } - } else - value--; - - if (value == 0xFFFF) { - value = MCI_GPM_INVALID; - more_gpm = MCI_GPM_NOMORE; - ath_dbg(common, ATH_DBG_MCI, "MCI GPM ptr invalid" - "@ptr=%d, offset=%d, more=GPM_NOMORE\n", - gpm_ptr, value); - } else if (state_type == MCI_STATE_NEXT_GPM_OFFSET) { - - if (gpm_ptr == mci->gpm_idx) { - value = MCI_GPM_INVALID; - more_gpm = MCI_GPM_NOMORE; - - ath_dbg(common, ATH_DBG_MCI, "MCI GPM message" - "not available @ptr=%d, @offset=%d," - "more=GPM_NOMORE\n", gpm_ptr, value); - } else { - for (;;) { - - u32 temp_index; - - /* skip reserved GPM if any */ - - if (value != mci->gpm_idx) - more_gpm = MCI_GPM_MORE; - else - more_gpm = MCI_GPM_NOMORE; - - temp_index = mci->gpm_idx; - mci->gpm_idx++; - - if (mci->gpm_idx >= - mci->gpm_len) - mci->gpm_idx = 0; - - ath_dbg(common, ATH_DBG_MCI, - "MCI GPM message got ptr=%d," - "@offset=%d, more=%d\n", - gpm_ptr, temp_index, - (more_gpm == MCI_GPM_MORE)); - - if (ar9003_mci_is_gpm_valid(ah, - temp_index)) { - value = temp_index; - break; - } - - if (more_gpm == MCI_GPM_NOMORE) { - value = MCI_GPM_INVALID; - break; - } - } - } - if (p_data) - *p_data = more_gpm; - } - - if (value != MCI_GPM_INVALID) - value <<= 4; - - break; - case MCI_STATE_LAST_SCHD_MSG_OFFSET: - value = MS(REG_READ(ah, AR_MCI_RX_STATUS), - AR_MCI_RX_LAST_SCHD_MSG_INDEX); - /* Make it in bytes */ - value <<= 4; - break; - - case MCI_STATE_REMOTE_SLEEP: - value = MS(REG_READ(ah, AR_MCI_RX_STATUS), - AR_MCI_RX_REMOTE_SLEEP) ? - MCI_BT_SLEEP : MCI_BT_AWAKE; - break; - - case MCI_STATE_CONT_RSSI_POWER: - value = MS(mci->cont_status, AR_MCI_CONT_RSSI_POWER); - break; - - case MCI_STATE_CONT_PRIORITY: - value = MS(mci->cont_status, AR_MCI_CONT_RRIORITY); - break; - - case MCI_STATE_CONT_TXRX: - value = MS(mci->cont_status, AR_MCI_CONT_TXRX); - break; - - case MCI_STATE_BT: - value = mci->bt_state; - break; - - case MCI_STATE_SET_BT_SLEEP: - mci->bt_state = MCI_BT_SLEEP; - break; - - case MCI_STATE_SET_BT_AWAKE: - mci->bt_state = MCI_BT_AWAKE; - ar9003_mci_send_coex_version_query(ah, true); - ar9003_mci_send_coex_wlan_channels(ah, true); - - if (mci->unhalt_bt_gpm) { - - ath_dbg(common, ATH_DBG_MCI, - "MCI unhalt BT GPM\n"); - ar9003_mci_send_coex_halt_bt_gpm(ah, false, true); - } - - ar9003_mci_2g5g_switch(ah, true); - break; - - case MCI_STATE_SET_BT_CAL_START: - mci->bt_state = MCI_BT_CAL_START; - break; - - case MCI_STATE_SET_BT_CAL: - mci->bt_state = MCI_BT_CAL; - break; - - case MCI_STATE_RESET_REQ_WAKE: - ar9003_mci_reset_req_wakeup(ah); - mci->update_2g5g = true; - - if ((AR_SREV_9462_20_OR_LATER(ah)) && - (mci->config & ATH_MCI_CONFIG_MCI_OBS_MASK)) { - /* Check if we still have control of the GPIOs */ - if ((REG_READ(ah, AR_GLB_GPIO_CONTROL) & - ATH_MCI_CONFIG_MCI_OBS_GPIO) != - ATH_MCI_CONFIG_MCI_OBS_GPIO) { - - ath_dbg(common, ATH_DBG_MCI, - "MCI reconfigure observation"); - ar9003_mci_observation_set_up(ah); - } - } - break; - - case MCI_STATE_SEND_WLAN_COEX_VERSION: - ar9003_mci_send_coex_version_response(ah, true); - break; - - case MCI_STATE_SET_BT_COEX_VERSION: - - if (!p_data) - ath_dbg(common, ATH_DBG_MCI, - "MCI Set BT Coex version with NULL data!!\n"); - else { - mci->bt_ver_major = (*p_data >> 8) & 0xff; - mci->bt_ver_minor = (*p_data) & 0xff; - mci->bt_version_known = true; - ath_dbg(common, ATH_DBG_MCI, - "MCI BT version set: %d.%d\n", - mci->bt_ver_major, - mci->bt_ver_minor); - } - break; - - case MCI_STATE_SEND_WLAN_CHANNELS: - if (p_data) { - if (((mci->wlan_channels[1] & 0xffff0000) == - (*(p_data + 1) & 0xffff0000)) && - (mci->wlan_channels[2] == *(p_data + 2)) && - (mci->wlan_channels[3] == *(p_data + 3))) - break; - - mci->wlan_channels[0] = *p_data++; - mci->wlan_channels[1] = *p_data++; - mci->wlan_channels[2] = *p_data++; - mci->wlan_channels[3] = *p_data++; - } - mci->wlan_channels_update = true; - ar9003_mci_send_coex_wlan_channels(ah, true); - break; - - case MCI_STATE_SEND_VERSION_QUERY: - ar9003_mci_send_coex_version_query(ah, true); - break; - - case MCI_STATE_SEND_STATUS_QUERY: - query_type = (AR_SREV_9462_10(ah)) ? - MCI_GPM_COEX_QUERY_BT_ALL_INFO : - MCI_GPM_COEX_QUERY_BT_TOPOLOGY; - - ar9003_mci_send_coex_bt_status_query(ah, true, query_type); - break; - - case MCI_STATE_NEED_FLUSH_BT_INFO: - /* - * btcoex_hw.mci.unhalt_bt_gpm means whether it's - * needed to send UNHALT message. It's set whenever - * there's a request to send HALT message. - * mci_halted_bt_gpm means whether HALT message is sent - * out successfully. - * - * Checking (mci_unhalt_bt_gpm == false) instead of - * checking (ah->mci_halted_bt_gpm == false) will make - * sure currently is in UNHALT-ed mode and BT can - * respond to status query. - */ - value = (!mci->unhalt_bt_gpm && - mci->need_flush_btinfo) ? 1 : 0; - if (p_data) - mci->need_flush_btinfo = - (*p_data != 0) ? true : false; - break; - - case MCI_STATE_RECOVER_RX: - - ath_dbg(common, ATH_DBG_MCI, "MCI hw RECOVER_RX\n"); - ar9003_mci_prep_interface(ah); - mci->query_bt = true; - mci->need_flush_btinfo = true; - ar9003_mci_send_coex_wlan_channels(ah, true); - ar9003_mci_2g5g_switch(ah, true); - break; - - case MCI_STATE_NEED_FTP_STOMP: - value = !(mci->config & ATH_MCI_CONFIG_DISABLE_FTP_STOMP); - break; - - case MCI_STATE_NEED_TUNING: - value = !(mci->config & ATH_MCI_CONFIG_DISABLE_TUNING); - break; - - default: - break; - - } - - return value; -} -EXPORT_SYMBOL(ar9003_mci_state); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.h deleted file mode 100644 index 798da116a44c..000000000000 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_mci.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2010-2011 Atheros Communications Inc. - * - * 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 AR9003_MCI_H -#define AR9003_MCI_H - -#define MCI_FLAG_DISABLE_TIMESTAMP 0x00000001 /* Disable time stamp */ - -/* Default remote BT device MCI COEX version */ -#define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT 3 -#define MCI_GPM_COEX_MINOR_VERSION_DEFAULT 0 - -/* Local WLAN MCI COEX version */ -#define MCI_GPM_COEX_MAJOR_VERSION_WLAN 3 -#define MCI_GPM_COEX_MINOR_VERSION_WLAN 0 - -enum mci_gpm_coex_query_type { - MCI_GPM_COEX_QUERY_BT_ALL_INFO = BIT(0), - MCI_GPM_COEX_QUERY_BT_TOPOLOGY = BIT(1), - MCI_GPM_COEX_QUERY_BT_DEBUG = BIT(2), -}; - -enum mci_gpm_coex_halt_bt_gpm { - MCI_GPM_COEX_BT_GPM_UNHALT, - MCI_GPM_COEX_BT_GPM_HALT -}; - -enum mci_gpm_coex_bt_update_flags_op { - MCI_GPM_COEX_BT_FLAGS_READ, - MCI_GPM_COEX_BT_FLAGS_SET, - MCI_GPM_COEX_BT_FLAGS_CLEAR -}; - -#define MCI_NUM_BT_CHANNELS 79 - -#define MCI_BT_MCI_FLAGS_UPDATE_CORR 0x00000002 -#define MCI_BT_MCI_FLAGS_UPDATE_HDR 0x00000004 -#define MCI_BT_MCI_FLAGS_UPDATE_PLD 0x00000008 -#define MCI_BT_MCI_FLAGS_LNA_CTRL 0x00000010 -#define MCI_BT_MCI_FLAGS_DEBUG 0x00000020 -#define MCI_BT_MCI_FLAGS_SCHED_MSG 0x00000040 -#define MCI_BT_MCI_FLAGS_CONT_MSG 0x00000080 -#define MCI_BT_MCI_FLAGS_COEX_GPM 0x00000100 -#define MCI_BT_MCI_FLAGS_CPU_INT_MSG 0x00000200 -#define MCI_BT_MCI_FLAGS_MCI_MODE 0x00000400 -#define MCI_BT_MCI_FLAGS_AR9462_MODE 0x00001000 -#define MCI_BT_MCI_FLAGS_OTHER 0x00010000 - -#define MCI_DEFAULT_BT_MCI_FLAGS 0x00011dde - -#define MCI_TOGGLE_BT_MCI_FLAGS (MCI_BT_MCI_FLAGS_UPDATE_CORR | \ - MCI_BT_MCI_FLAGS_UPDATE_HDR | \ - MCI_BT_MCI_FLAGS_UPDATE_PLD | \ - MCI_BT_MCI_FLAGS_MCI_MODE) - -#define MCI_2G_FLAGS_CLEAR_MASK 0x00000000 -#define MCI_2G_FLAGS_SET_MASK MCI_TOGGLE_BT_MCI_FLAGS -#define MCI_2G_FLAGS MCI_DEFAULT_BT_MCI_FLAGS - -#define MCI_5G_FLAGS_CLEAR_MASK MCI_TOGGLE_BT_MCI_FLAGS -#define MCI_5G_FLAGS_SET_MASK 0x00000000 -#define MCI_5G_FLAGS (MCI_DEFAULT_BT_MCI_FLAGS & \ - ~MCI_TOGGLE_BT_MCI_FLAGS) - -/* - * Default value for AR9462 is 0x00002201 - */ -#define ATH_MCI_CONFIG_CONCUR_TX 0x00000003 -#define ATH_MCI_CONFIG_MCI_OBS_MCI 0x00000004 -#define ATH_MCI_CONFIG_MCI_OBS_TXRX 0x00000008 -#define ATH_MCI_CONFIG_MCI_OBS_BT 0x00000010 -#define ATH_MCI_CONFIG_DISABLE_MCI_CAL 0x00000020 -#define ATH_MCI_CONFIG_DISABLE_OSLA 0x00000040 -#define ATH_MCI_CONFIG_DISABLE_FTP_STOMP 0x00000080 -#define ATH_MCI_CONFIG_AGGR_THRESH 0x00000700 -#define ATH_MCI_CONFIG_AGGR_THRESH_S 8 -#define ATH_MCI_CONFIG_DISABLE_AGGR_THRESH 0x00000800 -#define ATH_MCI_CONFIG_CLK_DIV 0x00003000 -#define ATH_MCI_CONFIG_CLK_DIV_S 12 -#define ATH_MCI_CONFIG_DISABLE_TUNING 0x00004000 -#define ATH_MCI_CONFIG_MCI_WEIGHT_DBG 0x40000000 -#define ATH_MCI_CONFIG_DISABLE_MCI 0x80000000 - -#define ATH_MCI_CONFIG_MCI_OBS_MASK (ATH_MCI_CONFIG_MCI_OBS_MCI | \ - ATH_MCI_CONFIG_MCI_OBS_TXRX | \ - ATH_MCI_CONFIG_MCI_OBS_BT) -#define ATH_MCI_CONFIG_MCI_OBS_GPIO 0x0000002F - -#endif diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h index ed64114571fc..497d7461838a 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -490,8 +490,6 @@ #define AR_PHY_TEST_CTL_TSTADC_EN_S 8 #define AR_PHY_TEST_CTL_RX_OBS_SEL 0x3C00 #define AR_PHY_TEST_CTL_RX_OBS_SEL_S 10 -#define AR_PHY_TEST_CTL_DEBUGPORT_SEL 0xe0000000 -#define AR_PHY_TEST_CTL_DEBUGPORT_SEL_S 29 #define AR_PHY_TSTDAC (AR_SM_BASE + 0x168) @@ -1003,7 +1001,6 @@ /* GLB Registers */ #define AR_GLB_BASE 0x20000 -#define AR_GLB_GPIO_CONTROL (AR_GLB_BASE) #define AR_PHY_GLB_CONTROL (AR_GLB_BASE + 0x44) #define AR_GLB_SCRATCH(_ah) (AR_GLB_BASE + \ (AR_SREV_9462_20(_ah) ? 0x4c : 0x50)) diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h b/trunk/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h index dc2054f0378e..259a6f312afb 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h @@ -41,24 +41,24 @@ static const u32 ar9462_pciephy_clkreq_enable_L1_2p0[][2] = { static const u32 ar9462_2p0_baseband_postamble[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a800d}, - {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, - {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, - {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x09143e81}, + {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, + {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, + {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x5ac640de}, + {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x0796be89}, {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, - {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, - {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, - {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3376605e, 0x33795d5e}, + {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, + {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x92c84d2e}, + {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, - {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, + {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c782}, + {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x0000a204, 0x013187c0, 0x013187c4, 0x013187c4, 0x013187c0}, @@ -81,15 +81,6 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a3a4, 0x00000010, 0x00000010, 0x00000000, 0x00000000}, - {0x0000a3a8, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}, - {0x0000a3ac, 0xaaaaaa00, 0xaaaaaa30, 0xaaaaaa00, 0xaaaaaa00}, - {0x0000a41c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, - {0x0000a420, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, - {0x0000a424, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, - {0x0000a428, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce}, - {0x0000a42c, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, - {0x0000a430, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce}, {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x00100000}, {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, @@ -1116,11 +1107,11 @@ static const u32 ar9462_2p0_baseband_core[][2] = { {0x00009e30, 0x06336f77}, {0x00009e34, 0x6af6532f}, {0x00009e38, 0x0cc80c00}, - {0x00009e40, 0x15262820}, + {0x00009e40, 0x0d261820}, {0x00009e4c, 0x00001004}, {0x00009e50, 0x00ff03f1}, - {0x00009e54, 0xe4c555c2}, - {0x00009e58, 0xfd857722}, + {0x00009e54, 0xe4c355c7}, + {0x00009e58, 0xfd897735}, {0x00009e5c, 0xe9198724}, {0x00009fc0, 0x803e4788}, {0x00009fc4, 0x0001efb5}, @@ -1151,6 +1142,9 @@ static const u32 ar9462_2p0_baseband_core[][2] = { {0x0000a398, 0x001f0e0f}, {0x0000a39c, 0x0075393f}, {0x0000a3a0, 0xb79f6427}, + {0x0000a3a4, 0x00000000}, + {0x0000a3a8, 0xaaaaaaaa}, + {0x0000a3ac, 0x3c466478}, {0x0000a3c0, 0x20202020}, {0x0000a3c4, 0x22222220}, {0x0000a3c8, 0x20200020}, @@ -1173,6 +1167,12 @@ static const u32 ar9462_2p0_baseband_core[][2] = { {0x0000a40c, 0x00820820}, {0x0000a414, 0x1ce739ce}, {0x0000a418, 0x2d001dce}, + {0x0000a41c, 0x1ce739ce}, + {0x0000a420, 0x000001ce}, + {0x0000a424, 0x1ce739ce}, + {0x0000a428, 0x000001ce}, + {0x0000a42c, 0x1ce739ce}, + {0x0000a430, 0x1ce739ce}, {0x0000a434, 0x00000000}, {0x0000a438, 0x00001801}, {0x0000a43c, 0x00100000}, diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h index afc156a0a2e3..93b45b4b3033 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h @@ -462,7 +462,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc); #define ATH_LED_PIN_9287 8 #define ATH_LED_PIN_9300 10 #define ATH_LED_PIN_9485 6 -#define ATH_LED_PIN_9462 4 +#define ATH_LED_PIN_9462 0 #ifdef CONFIG_MAC80211_LEDS void ath_init_leds(struct ath_softc *sc); @@ -647,7 +647,6 @@ struct ath_softc { struct delayed_work tx_complete_work; struct delayed_work hw_pll_work; struct ath_btcoex btcoex; - struct ath_mci_coex mci_coex; struct ath_descdma txsdma; diff --git a/trunk/drivers/net/wireless/ath/ath9k/btcoex.c b/trunk/drivers/net/wireless/ath/ath9k/btcoex.c index bbb20810ec10..9ac28d9de597 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/trunk/drivers/net/wireless/ath/ath9k/btcoex.c @@ -21,7 +21,7 @@ enum ath_bt_mode { ATH_BT_COEX_MODE_LEGACY, /* legacy rx_clear mode */ ATH_BT_COEX_MODE_UNSLOTTED, /* untimed/unslotted mode */ ATH_BT_COEX_MODE_SLOTTED, /* slotted mode */ - ATH_BT_COEX_MODE_DISABLED, /* coexistence disabled */ + ATH_BT_COEX_MODE_DISALBED, /* coexistence disabled */ }; struct ath_btcoex_config { diff --git a/trunk/drivers/net/wireless/ath/ath9k/btcoex.h b/trunk/drivers/net/wireless/ath/ath9k/btcoex.h index 278361c867ca..d5e5db1faad9 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/trunk/drivers/net/wireless/ath/ath9k/btcoex.h @@ -54,39 +54,8 @@ enum ath_btcoex_scheme { ATH_BTCOEX_CFG_MCI, }; -struct ath9k_hw_mci { - u32 raw_intr; - u32 rx_msg_intr; - u32 cont_status; - u32 gpm_addr; - u32 gpm_len; - u32 gpm_idx; - u32 sched_addr; - u32 wlan_channels[4]; - u32 wlan_cal_seq; - u32 wlan_cal_done; - u32 config; - u8 *gpm_buf; - u8 *sched_buf; - bool ready; - bool update_2g5g; - bool is_2g; - bool query_bt; - bool unhalt_bt_gpm; /* need send UNHALT */ - bool halted_bt_gpm; /* HALT sent */ - bool need_flush_btinfo; - bool bt_version_known; - bool wlan_channels_update; - u8 wlan_ver_major; - u8 wlan_ver_minor; - u8 bt_ver_major; - u8 bt_ver_minor; - u8 bt_state; -}; - struct ath_btcoex_hw { enum ath_btcoex_scheme scheme; - struct ath9k_hw_mci mci; bool enabled; u8 wlanactive_gpio; u8 btactive_gpio; diff --git a/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 61fcab0e2d76..9a7520f987f0 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/trunk/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -473,7 +473,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, int i; u16 twiceMinEdgePower; - u16 twiceMaxEdgePower; + u16 twiceMaxEdgePower = MAX_RATE_POWER; u16 scaledPower = 0, minCtlPower; u16 numCtlModes; const u16 *pCtlMode; @@ -542,7 +542,9 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, else freq = centers.ctl_center; - twiceMaxEdgePower = MAX_RATE_POWER; + if (ah->eep_ops->get_eeprom_ver(ah) == 14 && + ah->eep_ops->get_eeprom_rev(ah) <= 2) + twiceMaxEdgePower = MAX_RATE_POWER; for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { diff --git a/trunk/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/trunk/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 0981c073471d..4f5c50a87ce3 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/trunk/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -569,7 +569,7 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 - u16 twiceMaxEdgePower; + u16 twiceMaxEdgePower = MAX_RATE_POWER; int i; struct cal_ctl_data_ar9287 *rep; struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, @@ -669,7 +669,6 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, else freq = centers.ctl_center; - twiceMaxEdgePower = MAX_RATE_POWER; /* Walk through the CTL indices stored in EEPROM */ for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { struct cal_ctl_edges *pRdEdgesPower; diff --git a/trunk/drivers/net/wireless/ath/ath9k/eeprom_def.c b/trunk/drivers/net/wireless/ath/ath9k/eeprom_def.c index 55a21d39167c..81e629671679 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/trunk/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -1000,7 +1000,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */ struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; - u16 twiceMaxEdgePower; + u16 twiceMaxEdgePower = MAX_RATE_POWER; int i; struct cal_ctl_data *rep; struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { @@ -1121,7 +1121,9 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, else freq = centers.ctl_center; - twiceMaxEdgePower = MAX_RATE_POWER; + if (ah->eep_ops->get_eeprom_ver(ah) == 14 && + ah->eep_ops->get_eeprom_rev(ah) <= 2) + twiceMaxEdgePower = MAX_RATE_POWER; for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { if ((((cfgCtl & ~CTL_MODE_M) | diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c index f8ce4ea6f65c..0b9a0e8a4958 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -808,8 +808,7 @@ void ath9k_htc_ani_work(struct work_struct *work) } /* Verify whether we must check ANI */ - if (ah->config.enable_ani && - (timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { + if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { aniflag = true; common->ani.checkani_timer = timestamp; } @@ -839,7 +838,7 @@ void ath9k_htc_ani_work(struct work_struct *work) * short calibration and long calibration. */ cal_interval = ATH_LONG_CALINTERVAL; - if (ah->config.enable_ani) + if (priv->ah->config.enable_ani) cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); if (!common->ani.caldone) cal_interval = min(cal_interval, (u32)short_cal_interval); diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.c b/trunk/drivers/net/wireless/ath/ath9k/hw.c index 7f8fc65f2cb4..8876134b35bd 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.c @@ -504,7 +504,7 @@ static int ath9k_hw_post_init(struct ath_hw *ah) return ecode; } - if (ah->config.enable_ani) { + if (!AR_SREV_9100(ah) && !AR_SREV_9340(ah)) { ath9k_hw_ani_setup(ah); ath9k_hw_ani_init(ah); } @@ -610,10 +610,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (!AR_SREV_9300_20_OR_LATER(ah)) ah->ani_function &= ~ATH9K_ANI_MRC_CCK; - /* disable ANI for 9340 */ - if (AR_SREV_9340(ah)) - ah->config.enable_ani = false; - ath9k_hw_init_mode_regs(ah); if (!ah->is_pciexpress) @@ -1354,7 +1350,6 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) { - bool ret = false; if (AR_SREV_9300_20_OR_LATER(ah)) { REG_WRITE(ah, AR_WA, ah->WARegVal); @@ -1366,20 +1361,13 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) switch (type) { case ATH9K_RESET_POWER_ON: - ret = ath9k_hw_set_reset_power_on(ah); - break; + return ath9k_hw_set_reset_power_on(ah); case ATH9K_RESET_WARM: case ATH9K_RESET_COLD: - ret = ath9k_hw_set_reset(ah, type); - break; + return ath9k_hw_set_reset(ah, type); default: - break; + return false; } - - if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) - REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); - - return ret; } static bool ath9k_hw_chip_reset(struct ath_hw *ah, @@ -1518,7 +1506,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, struct ath9k_hw_cal_data *caldata, bool bChannelChange) { struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; u32 saveLedState; struct ath9k_channel *curchan = ah->curchan; u32 saveDefAntenna; @@ -1526,53 +1513,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, u64 tsf = 0; int i, r; bool allow_fbs = false; - bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI); - bool save_fullsleep = ah->chip_fullsleep; - - if (mci) { - - ar9003_mci_2g5g_changed(ah, IS_CHAN_2GHZ(chan)); - - if (mci_hw->bt_state == MCI_BT_CAL_START) { - u32 payload[4] = {0, 0, 0, 0}; - - ath_dbg(common, ATH_DBG_MCI, "MCI stop rx for BT CAL"); - - mci_hw->bt_state = MCI_BT_CAL; - - /* - * MCI FIX: disable mci interrupt here. This is to avoid - * SW_MSG_DONE or RX_MSG bits to trigger MCI_INT and - * lead to mci_intr reentry. - */ - - ar9003_mci_disable_interrupt(ah); - - ath_dbg(common, ATH_DBG_MCI, "send WLAN_CAL_GRANT"); - MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_GRANT); - ar9003_mci_send_message(ah, MCI_GPM, 0, payload, - 16, true, false); - - ath_dbg(common, ATH_DBG_MCI, "\nMCI BT is calibrating"); - - /* Wait BT calibration to be completed for 25ms */ - - if (ar9003_mci_wait_for_gpm(ah, MCI_GPM_BT_CAL_DONE, - 0, 25000)) - ath_dbg(common, ATH_DBG_MCI, - "MCI got BT_CAL_DONE\n"); - else - ath_dbg(common, ATH_DBG_MCI, - "MCI ### BT cal takes to long, force" - "bt_state to be bt_awake\n"); - mci_hw->bt_state = MCI_BT_AWAKE; - /* MCI FIX: enable mci interrupt here */ - ar9003_mci_enable_interrupt(ah); - - return true; - } - } - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) return -EIO; @@ -1610,29 +1550,12 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (ath9k_hw_channel_change(ah, chan)) { ath9k_hw_loadnf(ah, ah->curchan); ath9k_hw_start_nfcal(ah, true); - if (mci && mci_hw->ready) - ar9003_mci_2g5g_switch(ah, true); - if (AR_SREV_9271(ah)) ar9002_hw_load_ani_reg(ah, chan); return 0; } } - if (mci) { - ar9003_mci_disable_interrupt(ah); - - if (mci_hw->ready && !save_fullsleep) { - ar9003_mci_mute_bt(ah); - udelay(20); - REG_WRITE(ah, AR_BTCOEX_CTRL, 0); - } - - mci_hw->bt_state = MCI_BT_SLEEP; - mci_hw->ready = false; - } - - saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); if (saveDefAntenna == 0) saveDefAntenna = 1; @@ -1688,9 +1611,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (r) return r; - if (mci) - ar9003_mci_reset(ah, false, IS_CHAN_2GHZ(chan), save_fullsleep); - /* * Some AR91xx SoC devices frequently fail to accept TSF writes * right after the chip reset. When that happens, write a new @@ -1808,55 +1728,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ath9k_hw_loadnf(ah, chan); ath9k_hw_start_nfcal(ah, true); - if (mci && mci_hw->ready) { - - if (IS_CHAN_2GHZ(chan) && - (mci_hw->bt_state == MCI_BT_SLEEP)) { - - if (ar9003_mci_check_int(ah, - AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET) || - ar9003_mci_check_int(ah, - AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE)) { - - /* - * BT is sleeping. Check if BT wakes up during - * WLAN calibration. If BT wakes up during - * WLAN calibration, need to go through all - * message exchanges again and recal. - */ - - ath_dbg(common, ATH_DBG_MCI, "MCI BT wakes up" - "during WLAN calibration\n"); - - REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, - AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET | - AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE); - ath_dbg(common, ATH_DBG_MCI, "MCI send" - "REMOTE_RESET\n"); - ar9003_mci_remote_reset(ah, true); - ar9003_mci_send_sys_waking(ah, true); - udelay(1); - if (IS_CHAN_2GHZ(chan)) - ar9003_mci_send_lna_transfer(ah, true); - - mci_hw->bt_state = MCI_BT_AWAKE; - - ath_dbg(common, ATH_DBG_MCI, "MCI re-cal\n"); - - if (caldata) { - caldata->done_txiqcal_once = false; - caldata->done_txclcal_once = false; - caldata->rtt_hist.num_readings = 0; - } - - if (!ath9k_hw_init_cal(ah, chan)) - return -EIO; - - } - } - ar9003_mci_enable_interrupt(ah); - } - ENABLE_REGWRITE_BUFFER(ah); ath9k_hw_restore_chainmask(ah); @@ -1899,21 +1770,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (ah->btcoex_hw.enabled) ath9k_hw_btcoex_enable(ah); - if (mci && mci_hw->ready) { - /* - * check BT state again to make - * sure it's not changed. - */ - - ar9003_mci_sync_bt_state(ah); - ar9003_mci_2g5g_switch(ah, true); - - if ((mci_hw->bt_state == MCI_BT_AWAKE) && - (mci_hw->query_bt == true)) { - mci_hw->need_flush_btinfo = true; - } - } - if (AR_SREV_9300_20_OR_LATER(ah)) { ar9003_hw_bb_watchdog_config(ah); @@ -2078,7 +1934,6 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) { struct ath_common *common = ath9k_hw_common(ah); - struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; int status = true, setChip = true; static const char *modes[] = { "AWAKE", @@ -2096,35 +1951,12 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) switch (mode) { case ATH9K_PM_AWAKE: status = ath9k_hw_set_power_awake(ah, setChip); - - if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) - REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); - break; case ATH9K_PM_FULL_SLEEP: - - if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) { - if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) && - (mci->bt_state != MCI_BT_SLEEP) && - !mci->halted_bt_gpm) { - ath_dbg(common, ATH_DBG_MCI, "MCI halt BT GPM" - "(full_sleep)"); - ar9003_mci_send_coex_halt_bt_gpm(ah, - true, true); - } - - mci->ready = false; - REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); - } - ath9k_set_power_sleep(ah, setChip); ah->chip_fullsleep = true; break; case ATH9K_PM_NETWORK_SLEEP: - - if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) - REG_WRITE(ah, AR_RTC_KEEP_AWAKE, 0x2); - ath9k_set_power_network_sleep(ah, setChip); break; default: @@ -2317,8 +2149,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah)) chip_chainmask = 1; - else if (AR_SREV_9462(ah)) - chip_chainmask = 3; else if (!AR_SREV_9280_20_OR_LATER(ah)) chip_chainmask = 7; else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah)) @@ -2404,9 +2234,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; if (common->btcoex_enabled) { - if (AR_SREV_9462(ah)) - btcoex_hw->scheme = ATH_BTCOEX_CFG_MCI; - else if (AR_SREV_9300_20_OR_LATER(ah)) { + if (AR_SREV_9300_20_OR_LATER(ah)) { btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300; btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300; @@ -2504,7 +2332,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if (AR_SREV_9300_20_OR_LATER(ah)) { ah->enabled_cals |= TX_IQ_CAL; - if (AR_SREV_9485_OR_LATER(ah)) + if (!AR_SREV_9330(ah)) ah->enabled_cals |= TX_IQ_ON_AGC_CAL; } if (AR_SREV_9462(ah)) diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h index 36968c046119..3cb878c28ccf 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h @@ -126,16 +126,6 @@ #define AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL 4 #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 -#define AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA 0x16 -#define AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK 0x17 -#define AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA 0x18 -#define AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK 0x19 -#define AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX 0x14 -#define AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX 0x13 -#define AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX 9 -#define AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX 8 -#define AR_GPIO_OUTPUT_MUX_AS_RUCKUS_STROBE 0x1d -#define AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA 0x1e #define AR_GPIOD_MASK 0x00001FFF #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) @@ -276,7 +266,6 @@ enum ath9k_int { ATH9K_INT_TX = 0x00000040, ATH9K_INT_TXDESC = 0x00000080, ATH9K_INT_TIM_TIMER = 0x00000100, - ATH9K_INT_MCI = 0x00000200, ATH9K_INT_BB_WATCHDOG = 0x00000400, ATH9K_INT_TXURN = 0x00000800, ATH9K_INT_MIB = 0x00001000, @@ -428,25 +417,6 @@ enum ath9k_rx_qtype { ATH9K_RX_QUEUE_MAX, }; -enum mci_message_header { /* length of payload */ - MCI_LNA_CTRL = 0x10, /* len = 0 */ - MCI_CONT_NACK = 0x20, /* len = 0 */ - MCI_CONT_INFO = 0x30, /* len = 4 */ - MCI_CONT_RST = 0x40, /* len = 0 */ - MCI_SCHD_INFO = 0x50, /* len = 16 */ - MCI_CPU_INT = 0x60, /* len = 4 */ - MCI_SYS_WAKING = 0x70, /* len = 0 */ - MCI_GPM = 0x80, /* len = 16 */ - MCI_LNA_INFO = 0x90, /* len = 1 */ - MCI_LNA_STATE = 0x94, - MCI_LNA_TAKE = 0x98, - MCI_LNA_TRANS = 0x9c, - MCI_SYS_SLEEPING = 0xa0, /* len = 0 */ - MCI_REQ_WAKE = 0xc0, /* len = 0 */ - MCI_DEBUG_16 = 0xfe, /* len = 2 */ - MCI_REMOTE_RESET = 0xff /* len = 16 */ -}; - enum ath_mci_gpm_coex_profile_type { MCI_GPM_COEX_PROFILE_UNKNOWN, MCI_GPM_COEX_PROFILE_RFCOMM, @@ -457,132 +427,6 @@ enum ath_mci_gpm_coex_profile_type { MCI_GPM_COEX_PROFILE_MAX }; -/* MCI GPM/Coex opcode/type definitions */ -enum { - MCI_GPM_COEX_W_GPM_PAYLOAD = 1, - MCI_GPM_COEX_B_GPM_TYPE = 4, - MCI_GPM_COEX_B_GPM_OPCODE = 5, - /* MCI_GPM_WLAN_CAL_REQ, MCI_GPM_WLAN_CAL_DONE */ - MCI_GPM_WLAN_CAL_W_SEQUENCE = 2, - - /* MCI_GPM_COEX_VERSION_QUERY */ - /* MCI_GPM_COEX_VERSION_RESPONSE */ - MCI_GPM_COEX_B_MAJOR_VERSION = 6, - MCI_GPM_COEX_B_MINOR_VERSION = 7, - /* MCI_GPM_COEX_STATUS_QUERY */ - MCI_GPM_COEX_B_BT_BITMAP = 6, - MCI_GPM_COEX_B_WLAN_BITMAP = 7, - /* MCI_GPM_COEX_HALT_BT_GPM */ - MCI_GPM_COEX_B_HALT_STATE = 6, - /* MCI_GPM_COEX_WLAN_CHANNELS */ - MCI_GPM_COEX_B_CHANNEL_MAP = 6, - /* MCI_GPM_COEX_BT_PROFILE_INFO */ - MCI_GPM_COEX_B_PROFILE_TYPE = 6, - MCI_GPM_COEX_B_PROFILE_LINKID = 7, - MCI_GPM_COEX_B_PROFILE_STATE = 8, - MCI_GPM_COEX_B_PROFILE_ROLE = 9, - MCI_GPM_COEX_B_PROFILE_RATE = 10, - MCI_GPM_COEX_B_PROFILE_VOTYPE = 11, - MCI_GPM_COEX_H_PROFILE_T = 12, - MCI_GPM_COEX_B_PROFILE_W = 14, - MCI_GPM_COEX_B_PROFILE_A = 15, - /* MCI_GPM_COEX_BT_STATUS_UPDATE */ - MCI_GPM_COEX_B_STATUS_TYPE = 6, - MCI_GPM_COEX_B_STATUS_LINKID = 7, - MCI_GPM_COEX_B_STATUS_STATE = 8, - /* MCI_GPM_COEX_BT_UPDATE_FLAGS */ - MCI_GPM_COEX_W_BT_FLAGS = 6, - MCI_GPM_COEX_B_BT_FLAGS_OP = 10 -}; - -enum mci_gpm_subtype { - MCI_GPM_BT_CAL_REQ = 0, - MCI_GPM_BT_CAL_GRANT = 1, - MCI_GPM_BT_CAL_DONE = 2, - MCI_GPM_WLAN_CAL_REQ = 3, - MCI_GPM_WLAN_CAL_GRANT = 4, - MCI_GPM_WLAN_CAL_DONE = 5, - MCI_GPM_COEX_AGENT = 0x0c, - MCI_GPM_RSVD_PATTERN = 0xfe, - MCI_GPM_RSVD_PATTERN32 = 0xfefefefe, - MCI_GPM_BT_DEBUG = 0xff -}; - -enum mci_bt_state { - MCI_BT_SLEEP, - MCI_BT_AWAKE, - MCI_BT_CAL_START, - MCI_BT_CAL -}; - -/* Type of state query */ -enum mci_state_type { - MCI_STATE_ENABLE, - MCI_STATE_INIT_GPM_OFFSET, - MCI_STATE_NEXT_GPM_OFFSET, - MCI_STATE_LAST_GPM_OFFSET, - MCI_STATE_BT, - MCI_STATE_SET_BT_SLEEP, - MCI_STATE_SET_BT_AWAKE, - MCI_STATE_SET_BT_CAL_START, - MCI_STATE_SET_BT_CAL, - MCI_STATE_LAST_SCHD_MSG_OFFSET, - MCI_STATE_REMOTE_SLEEP, - MCI_STATE_CONT_RSSI_POWER, - MCI_STATE_CONT_PRIORITY, - MCI_STATE_CONT_TXRX, - MCI_STATE_RESET_REQ_WAKE, - MCI_STATE_SEND_WLAN_COEX_VERSION, - MCI_STATE_SET_BT_COEX_VERSION, - MCI_STATE_SEND_WLAN_CHANNELS, - MCI_STATE_SEND_VERSION_QUERY, - MCI_STATE_SEND_STATUS_QUERY, - MCI_STATE_NEED_FLUSH_BT_INFO, - MCI_STATE_SET_CONCUR_TX_PRI, - MCI_STATE_RECOVER_RX, - MCI_STATE_NEED_FTP_STOMP, - MCI_STATE_NEED_TUNING, - MCI_STATE_DEBUG, - MCI_STATE_MAX -}; - -enum mci_gpm_coex_opcode { - MCI_GPM_COEX_VERSION_QUERY, - MCI_GPM_COEX_VERSION_RESPONSE, - MCI_GPM_COEX_STATUS_QUERY, - MCI_GPM_COEX_HALT_BT_GPM, - MCI_GPM_COEX_WLAN_CHANNELS, - MCI_GPM_COEX_BT_PROFILE_INFO, - MCI_GPM_COEX_BT_STATUS_UPDATE, - MCI_GPM_COEX_BT_UPDATE_FLAGS -}; - -#define MCI_GPM_NOMORE 0 -#define MCI_GPM_MORE 1 -#define MCI_GPM_INVALID 0xffffffff - -#define MCI_GPM_RECYCLE(_p_gpm) do { \ - *(((u32 *)_p_gpm) + MCI_GPM_COEX_W_GPM_PAYLOAD) = \ - MCI_GPM_RSVD_PATTERN32; \ -} while (0) - -#define MCI_GPM_TYPE(_p_gpm) \ - (*(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) & 0xff) - -#define MCI_GPM_OPCODE(_p_gpm) \ - (*(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_OPCODE) & 0xff) - -#define MCI_GPM_SET_CAL_TYPE(_p_gpm, _cal_type) do { \ - *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) = (_cal_type) & 0xff;\ -} while (0) - -#define MCI_GPM_SET_TYPE_OPCODE(_p_gpm, _type, _opcode) do { \ - *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_TYPE) = (_type) & 0xff; \ - *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_GPM_OPCODE) = (_opcode) & 0xff;\ -} while (0) - -#define MCI_GPM_IS_CAL_TYPE(_type) ((_type) <= MCI_GPM_WLAN_CAL_DONE) - struct ath9k_beacon_state { u32 bs_nexttbtt; u32 bs_nextdtim; @@ -1110,6 +954,7 @@ bool ath9k_hw_disable(struct ath_hw *ah); void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test); void ath9k_hw_setopmode(struct ath_hw *ah); void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); +void ath9k_hw_setbssidmask(struct ath_hw *ah); void ath9k_hw_write_associd(struct ath_hw *ah); u32 ath9k_hw_gettsf32(struct ath_hw *ah); u64 ath9k_hw_gettsf64(struct ath_hw *ah); @@ -1202,32 +1047,6 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning); void ath9k_hw_proc_mib_event(struct ath_hw *ah); void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan); -bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag, - u32 *payload, u8 len, bool wait_done, - bool check_bt); -void ar9003_mci_mute_bt(struct ath_hw *ah); -u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data); -void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, - u16 len, u32 sched_addr); -void ar9003_mci_cleanup(struct ath_hw *ah); -void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt, - bool wait_done); -u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type, - u8 gpm_opcode, int time_out); -void ar9003_mci_2g5g_changed(struct ath_hw *ah, bool is_2g); -void ar9003_mci_disable_interrupt(struct ath_hw *ah); -void ar9003_mci_enable_interrupt(struct ath_hw *ah); -void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done); -void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, - bool is_full_sleep); -bool ar9003_mci_check_int(struct ath_hw *ah, u32 ints); -void ar9003_mci_remote_reset(struct ath_hw *ah, bool wait_done); -void ar9003_mci_send_sys_waking(struct ath_hw *ah, bool wait_done); -void ar9003_mci_send_lna_transfer(struct ath_hw *ah, bool wait_done); -void ar9003_mci_sync_bt_state(struct ath_hw *ah); -void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, - u32 *rx_msg_intr); - #define ATH9K_CLOCK_RATE_CCK 22 #define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 diff --git a/trunk/drivers/net/wireless/ath/ath9k/init.c b/trunk/drivers/net/wireless/ath/ath9k/init.c index 41b72faca77f..e046de94836a 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/init.c @@ -258,8 +258,6 @@ static void setup_ht_cap(struct ath_softc *sc, if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) max_streams = 1; - else if (AR_SREV_9462(ah)) - max_streams = 2; else if (AR_SREV_9300_20_OR_LATER(ah)) max_streams = 3; else @@ -410,7 +408,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, static int ath9k_init_btcoex(struct ath_softc *sc) { struct ath_txq *txq; - struct ath_hw *ah = sc->sc_ah; int r; switch (sc->sc_ah->btcoex_hw.scheme) { @@ -426,38 +423,9 @@ static int ath9k_init_btcoex(struct ath_softc *sc) return -1; txq = sc->tx.txq_map[WME_AC_BE]; ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum); - sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; - break; - case ATH_BTCOEX_CFG_MCI: sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE; INIT_LIST_HEAD(&sc->btcoex.mci.info); - - r = ath_mci_setup(sc); - if (r) - return r; - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) { - ah->btcoex_hw.mci.ready = false; - ah->btcoex_hw.mci.bt_state = 0; - ah->btcoex_hw.mci.bt_ver_major = 3; - ah->btcoex_hw.mci.bt_ver_minor = 0; - ah->btcoex_hw.mci.bt_version_known = false; - ah->btcoex_hw.mci.update_2g5g = true; - ah->btcoex_hw.mci.is_2g = true; - ah->btcoex_hw.mci.wlan_channels_update = false; - ah->btcoex_hw.mci.wlan_channels[0] = 0x00000000; - ah->btcoex_hw.mci.wlan_channels[1] = 0xffffffff; - ah->btcoex_hw.mci.wlan_channels[2] = 0xffffffff; - ah->btcoex_hw.mci.wlan_channels[3] = 0x7fffffff; - ah->btcoex_hw.mci.query_bt = true; - ah->btcoex_hw.mci.unhalt_bt_gpm = true; - ah->btcoex_hw.mci.halted_bt_gpm = false; - ah->btcoex_hw.mci.need_flush_btinfo = false; - ah->btcoex_hw.mci.wlan_cal_seq = 0; - ah->btcoex_hw.mci.wlan_cal_done = 0; - ah->btcoex_hw.mci.config = 0x2201; - } break; default: WARN_ON(1); @@ -871,9 +839,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc) sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); - if (sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_MCI) - ath_mci_cleanup(sc); - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) if (ATH_TXQ_SETUP(sc, i)) ath_tx_cleanupq(sc, &sc->tx.txq[i]); diff --git a/trunk/drivers/net/wireless/ath/ath9k/mac.c b/trunk/drivers/net/wireless/ath/ath9k/mac.c index 0e4fbb3bea33..ecdb6fd29079 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mac.c +++ b/trunk/drivers/net/wireless/ath/ath9k/mac.c @@ -760,10 +760,7 @@ bool ath9k_hw_intrpend(struct ath_hw *ah) return true; host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); - - if (((host_isr & AR_INTR_MAC_IRQ) || - (host_isr & AR_INTR_ASYNC_MASK_MCI)) && - (host_isr != AR_INTR_SPURIOUS)) + if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) return true; host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); @@ -801,7 +798,6 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); u32 sync_default = AR_INTR_SYNC_DEFAULT; - u32 async_mask; if (!(ah->imask & ATH9K_INT_GLOBAL)) return; @@ -816,16 +812,13 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) if (AR_SREV_9340(ah)) sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; - async_mask = AR_INTR_MAC_IRQ; - - if (ah->imask & ATH9K_INT_MCI) - async_mask |= AR_INTR_ASYNC_MASK_MCI; - ath_dbg(common, ATH_DBG_INTERRUPT, "enable IER\n"); REG_WRITE(ah, AR_IER, AR_IER_ENABLE); if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, async_mask); - REG_WRITE(ah, AR_INTR_ASYNC_MASK, async_mask); + REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, + AR_INTR_MAC_IRQ); + REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); + REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default); REG_WRITE(ah, AR_INTR_SYNC_MASK, sync_default); diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index 7d920044d031..e43c41cff25b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -118,7 +118,7 @@ void ath9k_ps_restore(struct ath_softc *sc) if (--sc->ps_usecount != 0) goto unlock; - if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK)) + if (sc->ps_idle) mode = ATH9K_PM_FULL_SLEEP; else if (sc->ps_enabled && !(sc->ps_flags & (PS_WAIT_FOR_BEACON | @@ -286,7 +286,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) ath_start_ani(common); } - if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) { + if (ath9k_hw_ops(ah)->antdiv_comb_conf_get && sc->ant_rx != 3) { struct ath_hw_antcomb_conf div_ant_conf; u8 lna_conf; @@ -332,8 +332,7 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, hchan = ah->curchan; } - if (fastcc && (ah->chip_fullsleep || - !ath9k_hw_check_alive(ah))) + if (fastcc && !ath9k_hw_check_alive(ah)) fastcc = false; if (!ath_prepare_reset(sc, retry_tx, flush)) @@ -562,6 +561,7 @@ void ath_ani_calibrate(unsigned long data) /* Long calibration runs independently of short calibration. */ if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { longcal = true; + ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); common->ani.longcal_timer = timestamp; } @@ -569,6 +569,8 @@ void ath_ani_calibrate(unsigned long data) if (!common->ani.caldone) { if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { shortcal = true; + ath_dbg(common, ATH_DBG_ANI, + "shortcal @%lu\n", jiffies); common->ani.shortcal_timer = timestamp; common->ani.resetcal_timer = timestamp; } @@ -582,9 +584,8 @@ void ath_ani_calibrate(unsigned long data) } /* Verify whether we must check ANI */ - if (sc->sc_ah->config.enable_ani - && (timestamp - common->ani.checkani_timer) >= - ah->config.ani_poll_interval) { + if ((timestamp - common->ani.checkani_timer) >= + ah->config.ani_poll_interval) { aniflag = true; common->ani.checkani_timer = timestamp; } @@ -604,11 +605,6 @@ void ath_ani_calibrate(unsigned long data) ah->rxchainmask, longcal); } - ath_dbg(common, ATH_DBG_ANI, - "Calibration @%lu finished: %s %s %s, caldone: %s\n", jiffies, - longcal ? "long" : "", shortcal ? "short" : "", - aniflag ? "ani" : "", common->ani.caldone ? "true" : "false"); - ath9k_ps_restore(sc); set_timer: @@ -746,9 +742,6 @@ void ath9k_tasklet(unsigned long data) if (status & ATH9K_INT_GENTIMER) ath_gen_timer_isr(sc->sc_ah); - if (status & ATH9K_INT_MCI) - ath_mci_intr(sc); - out: /* re-enable hardware interrupt */ ath9k_hw_enable_interrupts(ah); @@ -771,8 +764,7 @@ irqreturn_t ath_isr(int irq, void *dev) ATH9K_INT_BMISS | \ ATH9K_INT_CST | \ ATH9K_INT_TSFOOR | \ - ATH9K_INT_GENTIMER | \ - ATH9K_INT_MCI) + ATH9K_INT_GENTIMER) struct ath_softc *sc = dev; struct ath_hw *ah = sc->sc_ah; @@ -890,6 +882,82 @@ irqreturn_t ath_isr(int irq, void *dev) #undef SCHED_INTR } +static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + struct ieee80211_channel *channel = hw->conf.channel; + int r; + + ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_pcu_lock); + atomic_set(&ah->intr_ref_cnt, -1); + + ath9k_hw_configpcipowersave(ah, false); + + if (!ah->curchan) + ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah); + + r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); + if (r) { + ath_err(common, + "Unable to reset channel (%u MHz), reset status %d\n", + channel->center_freq, r); + } + + ath_complete_reset(sc, true); + + /* Enable LED */ + ath9k_hw_cfg_output(ah, ah->led_pin, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(ah, ah->led_pin, 0); + + spin_unlock_bh(&sc->sc_pcu_lock); + + ath9k_ps_restore(sc); +} + +void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) +{ + struct ath_hw *ah = sc->sc_ah; + struct ieee80211_channel *channel = hw->conf.channel; + int r; + + ath9k_ps_wakeup(sc); + + ath_cancel_work(sc); + + spin_lock_bh(&sc->sc_pcu_lock); + + /* + * Keep the LED on when the radio is disabled + * during idle unassociated state. + */ + if (!sc->ps_idle) { + ath9k_hw_set_gpio(ah, ah->led_pin, 1); + ath9k_hw_cfg_gpio_input(ah, ah->led_pin); + } + + ath_prepare_reset(sc, false, true); + + if (!ah->curchan) + ah->curchan = ath9k_cmn_get_curchannel(hw, ah); + + r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); + if (r) { + ath_err(ath9k_hw_common(sc->sc_ah), + "Unable to reset channel (%u MHz), reset status %d\n", + channel->center_freq, r); + } + + ath9k_hw_phy_disable(ah); + + ath9k_hw_configpcipowersave(ah, true); + + spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_ps_restore(sc); +} + static int ath_reset(struct ath_softc *sc, bool retry_tx) { int r; @@ -1025,9 +1093,6 @@ static int ath9k_start(struct ieee80211_hw *hw) * and then setup of the interrupt mask. */ spin_lock_bh(&sc->sc_pcu_lock); - - atomic_set(&ah->intr_ref_cnt, -1); - r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); if (r) { ath_err(common, @@ -1054,9 +1119,6 @@ static int ath9k_start(struct ieee80211_hw *hw) if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) ah->imask |= ATH9K_INT_CST; - if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) - ah->imask |= ATH9K_INT_MCI; - sc->sc_flags &= ~SC_OP_INVALID; sc->sc_ah->is_monitoring = false; @@ -1069,18 +1131,6 @@ static int ath9k_start(struct ieee80211_hw *hw) goto mutex_unlock; } - if (ah->led_pin >= 0) { - ath9k_hw_cfg_output(ah, ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(ah, ah->led_pin, 0); - } - - /* - * Reset key cache to sane defaults (all entries cleared) instead of - * semi-random values after suspend/resume. - */ - ath9k_cmn_init_crypto(sc->sc_ah); - spin_unlock_bh(&sc->sc_pcu_lock); if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && @@ -1126,13 +1176,6 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) } } - /* - * Cannot tx while the hardware is in full sleep, it first needs a full - * chip reset to recover from that - */ - if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_FULL_SLEEP)) - goto exit; - if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) { /* * We are using PS-Poll and mac80211 can request TX while in @@ -1179,7 +1222,6 @@ static void ath9k_stop(struct ieee80211_hw *hw) struct ath_softc *sc = hw->priv; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); - bool prev_idle; mutex_lock(&sc->mutex); @@ -1210,45 +1252,35 @@ static void ath9k_stop(struct ieee80211_hw *hw) * before setting the invalid flag. */ ath9k_hw_disable_interrupts(ah); - spin_unlock_bh(&sc->sc_pcu_lock); - - /* we can now sync irq and kill any running tasklets, since we already - * disabled interrupts and not holding a spin lock */ - synchronize_irq(sc->irq); - tasklet_kill(&sc->intr_tq); - tasklet_kill(&sc->bcon_tasklet); - - prev_idle = sc->ps_idle; - sc->ps_idle = true; - - spin_lock_bh(&sc->sc_pcu_lock); - - if (ah->led_pin >= 0) { - ath9k_hw_set_gpio(ah, ah->led_pin, 1); - ath9k_hw_cfg_gpio_input(ah, ah->led_pin); - } - - ath_prepare_reset(sc, false, true); + if (!(sc->sc_flags & SC_OP_INVALID)) { + ath_drain_all_txq(sc, false); + ath_stoprecv(sc); + ath9k_hw_phy_disable(ah); + } else + sc->rx.rxlink = NULL; if (sc->rx.frag) { dev_kfree_skb_any(sc->rx.frag); sc->rx.frag = NULL; } - if (!ah->curchan) - ah->curchan = ath9k_cmn_get_curchannel(hw, ah); - - ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); - ath9k_hw_phy_disable(ah); - - ath9k_hw_configpcipowersave(ah, true); + /* disable HAL and put h/w to sleep */ + ath9k_hw_disable(ah); spin_unlock_bh(&sc->sc_pcu_lock); + /* we can now sync irq and kill any running tasklets, since we already + * disabled interrupts and not holding a spin lock */ + synchronize_irq(sc->irq); + tasklet_kill(&sc->intr_tq); + tasklet_kill(&sc->bcon_tasklet); + ath9k_ps_restore(sc); + sc->ps_idle = true; + ath_radio_disable(sc, hw); + sc->sc_flags |= SC_OP_INVALID; - sc->ps_idle = prev_idle; mutex_unlock(&sc->mutex); @@ -1588,8 +1620,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_conf *conf = &hw->conf; + bool disable_radio = false; - ath9k_ps_wakeup(sc); mutex_lock(&sc->mutex); /* @@ -1600,8 +1632,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) */ if (changed & IEEE80211_CONF_CHANGE_IDLE) { sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); - if (sc->ps_idle) - ath_cancel_work(sc); + if (!sc->ps_idle) { + ath_radio_enable(sc, hw); + ath_dbg(common, ATH_DBG_CONFIG, + "not-idle: enabling radio\n"); + } else { + disable_radio = true; + } } /* @@ -1708,12 +1745,18 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ath_dbg(common, ATH_DBG_CONFIG, "Set power: %d\n", conf->power_level); sc->config.txpowlimit = 2 * conf->power_level; + ath9k_ps_wakeup(sc); ath9k_cmn_update_txpow(ah, sc->curtxpow, sc->config.txpowlimit, &sc->curtxpow); + ath9k_ps_restore(sc); + } + + if (disable_radio) { + ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); + ath_radio_disable(sc, hw); } mutex_unlock(&sc->mutex); - ath9k_ps_restore(sc); return 0; } @@ -2281,6 +2324,9 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) return; } + if (drop) + timeout = 1; + for (j = 0; j < timeout; j++) { bool npend = false; @@ -2298,22 +2344,21 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) } if (!npend) - break; + goto out; } - if (drop) { - ath9k_ps_wakeup(sc); - spin_lock_bh(&sc->sc_pcu_lock); - drain_txq = ath_drain_all_txq(sc, false); - spin_unlock_bh(&sc->sc_pcu_lock); + ath9k_ps_wakeup(sc); + spin_lock_bh(&sc->sc_pcu_lock); + drain_txq = ath_drain_all_txq(sc, false); + spin_unlock_bh(&sc->sc_pcu_lock); - if (!drain_txq) - ath_reset(sc, false); + if (!drain_txq) + ath_reset(sc, false); - ath9k_ps_restore(sc); - ieee80211_wake_queues(hw); - } + ath9k_ps_restore(sc); + ieee80211_wake_queues(hw); +out: ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0); mutex_unlock(&sc->mutex); } diff --git a/trunk/drivers/net/wireless/ath/ath9k/mci.c b/trunk/drivers/net/wireless/ath/ath9k/mci.c index d6780405d6f5..0fbb141bc302 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/mci.c @@ -14,9 +14,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include -#include - #include "ath9k.h" #include "mci.h" @@ -184,56 +181,6 @@ static void ath_mci_update_scheme(struct ath_softc *sc) ath9k_btcoex_timer_resume(sc); } - -static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - u32 payload[4] = {0, 0, 0, 0}; - - switch (opcode) { - case MCI_GPM_BT_CAL_REQ: - - ath_dbg(common, ATH_DBG_MCI, "MCI received BT_CAL_REQ\n"); - - if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_AWAKE) { - ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START, NULL); - ieee80211_queue_work(sc->hw, &sc->hw_reset_work); - } else - ath_dbg(common, ATH_DBG_MCI, - "MCI State mismatches: %d\n", - ar9003_mci_state(ah, MCI_STATE_BT, NULL)); - - break; - - case MCI_GPM_BT_CAL_DONE: - - ath_dbg(common, ATH_DBG_MCI, "MCI received BT_CAL_DONE\n"); - - if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_CAL) - ath_dbg(common, ATH_DBG_MCI, "MCI error illegal!\n"); - else - ath_dbg(common, ATH_DBG_MCI, "MCI BT not in CAL state\n"); - - break; - - case MCI_GPM_BT_CAL_GRANT: - - ath_dbg(common, ATH_DBG_MCI, "MCI received BT_CAL_GRANT\n"); - - /* Send WLAN_CAL_DONE for now */ - ath_dbg(common, ATH_DBG_MCI, "MCI send WLAN_CAL_DONE\n"); - MCI_GPM_SET_CAL_TYPE(payload, MCI_GPM_WLAN_CAL_DONE); - ar9003_mci_send_message(sc->sc_ah, MCI_GPM, 0, payload, - 16, false, true); - break; - - default: - ath_dbg(common, ATH_DBG_MCI, "MCI Unknown GPM CAL message\n"); - break; - } -} - void ath_mci_process_profile(struct ath_softc *sc, struct ath_mci_profile_info *info) { @@ -305,369 +252,3 @@ void ath_mci_process_status(struct ath_softc *sc, if (old_num_mgmt != mci->num_mgmt) ath_mci_update_scheme(sc); } - -static void ath_mci_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_mci_profile_info profile_info; - struct ath_mci_profile_status profile_status; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - u32 version; - u8 major; - u8 minor; - u32 seq_num; - - switch (opcode) { - - case MCI_GPM_COEX_VERSION_QUERY: - ath_dbg(common, ATH_DBG_MCI, - "MCI Recv GPM COEX Version Query.\n"); - version = ar9003_mci_state(ah, - MCI_STATE_SEND_WLAN_COEX_VERSION, NULL); - break; - - case MCI_GPM_COEX_VERSION_RESPONSE: - ath_dbg(common, ATH_DBG_MCI, - "MCI Recv GPM COEX Version Response.\n"); - major = *(rx_payload + MCI_GPM_COEX_B_MAJOR_VERSION); - minor = *(rx_payload + MCI_GPM_COEX_B_MINOR_VERSION); - ath_dbg(common, ATH_DBG_MCI, - "MCI BT Coex version: %d.%d\n", major, minor); - version = (major << 8) + minor; - version = ar9003_mci_state(ah, - MCI_STATE_SET_BT_COEX_VERSION, &version); - break; - - case MCI_GPM_COEX_STATUS_QUERY: - ath_dbg(common, ATH_DBG_MCI, - "MCI Recv GPM COEX Status Query = 0x%02x.\n", - *(rx_payload + MCI_GPM_COEX_B_WLAN_BITMAP)); - ar9003_mci_state(ah, - MCI_STATE_SEND_WLAN_CHANNELS, NULL); - break; - - case MCI_GPM_COEX_BT_PROFILE_INFO: - ath_dbg(common, ATH_DBG_MCI, - "MCI Recv GPM Coex BT profile info\n"); - memcpy(&profile_info, - (rx_payload + MCI_GPM_COEX_B_PROFILE_TYPE), 10); - - if ((profile_info.type == MCI_GPM_COEX_PROFILE_UNKNOWN) - || (profile_info.type >= - MCI_GPM_COEX_PROFILE_MAX)) { - - ath_dbg(common, ATH_DBG_MCI, - "illegal profile type = %d," - "state = %d\n", profile_info.type, - profile_info.start); - break; - } - - ath_mci_process_profile(sc, &profile_info); - break; - - case MCI_GPM_COEX_BT_STATUS_UPDATE: - profile_status.is_link = *(rx_payload + - MCI_GPM_COEX_B_STATUS_TYPE); - profile_status.conn_handle = *(rx_payload + - MCI_GPM_COEX_B_STATUS_LINKID); - profile_status.is_critical = *(rx_payload + - MCI_GPM_COEX_B_STATUS_STATE); - - seq_num = *((u32 *)(rx_payload + 12)); - ath_dbg(common, ATH_DBG_MCI, - "MCI Recv GPM COEX BT_Status_Update: " - "is_link=%d, linkId=%d, state=%d, SEQ=%d\n", - profile_status.is_link, profile_status.conn_handle, - profile_status.is_critical, seq_num); - - ath_mci_process_status(sc, &profile_status); - break; - - default: - ath_dbg(common, ATH_DBG_MCI, - "MCI Unknown GPM COEX message = 0x%02x\n", opcode); - break; - } -} - -static int ath_mci_buf_alloc(struct ath_softc *sc, struct ath_mci_buf *buf) -{ - int error = 0; - - buf->bf_addr = dma_alloc_coherent(sc->dev, buf->bf_len, - &buf->bf_paddr, GFP_KERNEL); - - if (buf->bf_addr == NULL) { - error = -ENOMEM; - goto fail; - } - - return 0; - -fail: - memset(buf, 0, sizeof(*buf)); - return error; -} - -static void ath_mci_buf_free(struct ath_softc *sc, struct ath_mci_buf *buf) -{ - if (buf->bf_addr) { - dma_free_coherent(sc->dev, buf->bf_len, buf->bf_addr, - buf->bf_paddr); - memset(buf, 0, sizeof(*buf)); - } -} - -int ath_mci_setup(struct ath_softc *sc) -{ - struct ath_common *common = ath9k_hw_common(sc->sc_ah); - struct ath_mci_coex *mci = &sc->mci_coex; - int error = 0; - - mci->sched_buf.bf_len = ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE; - - if (ath_mci_buf_alloc(sc, &mci->sched_buf)) { - ath_dbg(common, ATH_DBG_FATAL, "MCI buffer alloc failed\n"); - error = -ENOMEM; - goto fail; - } - - mci->sched_buf.bf_len = ATH_MCI_SCHED_BUF_SIZE; - - memset(mci->sched_buf.bf_addr, MCI_GPM_RSVD_PATTERN, - mci->sched_buf.bf_len); - - mci->gpm_buf.bf_len = ATH_MCI_GPM_BUF_SIZE; - mci->gpm_buf.bf_addr = (u8 *)mci->sched_buf.bf_addr + - mci->sched_buf.bf_len; - mci->gpm_buf.bf_paddr = mci->sched_buf.bf_paddr + mci->sched_buf.bf_len; - - /* initialize the buffer */ - memset(mci->gpm_buf.bf_addr, MCI_GPM_RSVD_PATTERN, mci->gpm_buf.bf_len); - - ar9003_mci_setup(sc->sc_ah, mci->gpm_buf.bf_paddr, - mci->gpm_buf.bf_addr, (mci->gpm_buf.bf_len >> 4), - mci->sched_buf.bf_paddr); -fail: - return error; -} - -void ath_mci_cleanup(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_mci_coex *mci = &sc->mci_coex; - - /* - * both schedule and gpm buffers will be released - */ - ath_mci_buf_free(sc, &mci->sched_buf); - ar9003_mci_cleanup(ah); -} - -void ath_mci_intr(struct ath_softc *sc) -{ - struct ath_mci_coex *mci = &sc->mci_coex; - struct ath_hw *ah = sc->sc_ah; - struct ath_common *common = ath9k_hw_common(ah); - u32 mci_int, mci_int_rxmsg; - u32 offset, subtype, opcode; - u32 *pgpm; - u32 more_data = MCI_GPM_MORE; - bool skip_gpm = false; - - ar9003_mci_get_interrupt(sc->sc_ah, &mci_int, &mci_int_rxmsg); - - if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) == 0) { - - ar9003_mci_state(sc->sc_ah, MCI_STATE_INIT_GPM_OFFSET, NULL); - ath_dbg(common, ATH_DBG_MCI, - "MCI interrupt but MCI disabled\n"); - - ath_dbg(common, ATH_DBG_MCI, - "MCI interrupt: intr = 0x%x, intr_rxmsg = 0x%x\n", - mci_int, mci_int_rxmsg); - return; - } - - if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) { - u32 payload[4] = { 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffff00}; - - /* - * The following REMOTE_RESET and SYS_WAKING used to sent - * only when BT wake up. Now they are always sent, as a - * recovery method to reset BT MCI's RX alignment. - */ - ath_dbg(common, ATH_DBG_MCI, "MCI interrupt send REMOTE_RESET\n"); - - ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0, - payload, 16, true, false); - ath_dbg(common, ATH_DBG_MCI, "MCI interrupt send SYS_WAKING\n"); - ar9003_mci_send_message(ah, MCI_SYS_WAKING, 0, - NULL, 0, true, false); - - mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE; - ar9003_mci_state(ah, MCI_STATE_RESET_REQ_WAKE, NULL); - - /* - * always do this for recovery and 2G/5G toggling and LNA_TRANS - */ - ath_dbg(common, ATH_DBG_MCI, "MCI Set BT state to AWAKE.\n"); - ar9003_mci_state(ah, MCI_STATE_SET_BT_AWAKE, NULL); - } - - /* Processing SYS_WAKING/SYS_SLEEPING */ - if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING) { - mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING; - - if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_SLEEP) { - - if (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL) - == MCI_BT_SLEEP) - ath_dbg(common, ATH_DBG_MCI, - "MCI BT stays in sleep mode\n"); - else { - ath_dbg(common, ATH_DBG_MCI, - "MCI Set BT state to AWAKE.\n"); - ar9003_mci_state(ah, - MCI_STATE_SET_BT_AWAKE, NULL); - } - } else - ath_dbg(common, ATH_DBG_MCI, - "MCI BT stays in AWAKE mode.\n"); - } - - if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) { - - mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING; - - if (ar9003_mci_state(ah, MCI_STATE_BT, NULL) == MCI_BT_AWAKE) { - - if (ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL) - == MCI_BT_AWAKE) - ath_dbg(common, ATH_DBG_MCI, - "MCI BT stays in AWAKE mode.\n"); - else { - ath_dbg(common, ATH_DBG_MCI, - "MCI SetBT state to SLEEP\n"); - ar9003_mci_state(ah, MCI_STATE_SET_BT_SLEEP, - NULL); - } - } else - ath_dbg(common, ATH_DBG_MCI, - "MCI BT stays in SLEEP mode\n"); - } - - if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) || - (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) { - - ath_dbg(common, ATH_DBG_MCI, "MCI RX broken, skip GPM msgs\n"); - ar9003_mci_state(ah, MCI_STATE_RECOVER_RX, NULL); - skip_gpm = true; - } - - if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO) { - - mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO; - offset = ar9003_mci_state(ah, MCI_STATE_LAST_SCHD_MSG_OFFSET, - NULL); - } - - if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_GPM) { - - mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_GPM; - - while (more_data == MCI_GPM_MORE) { - - pgpm = mci->gpm_buf.bf_addr; - offset = ar9003_mci_state(ah, - MCI_STATE_NEXT_GPM_OFFSET, &more_data); - - if (offset == MCI_GPM_INVALID) - break; - - pgpm += (offset >> 2); - - /* - * The first dword is timer. - * The real data starts from 2nd dword. - */ - - subtype = MCI_GPM_TYPE(pgpm); - opcode = MCI_GPM_OPCODE(pgpm); - - if (!skip_gpm) { - - if (MCI_GPM_IS_CAL_TYPE(subtype)) - ath_mci_cal_msg(sc, subtype, - (u8 *) pgpm); - else { - switch (subtype) { - case MCI_GPM_COEX_AGENT: - ath_mci_msg(sc, opcode, - (u8 *) pgpm); - break; - default: - break; - } - } - } - MCI_GPM_RECYCLE(pgpm); - } - } - - if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_HW_MSG_MASK) { - - if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL) - mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL; - - if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_LNA_INFO) { - mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_LNA_INFO; - ath_dbg(common, ATH_DBG_MCI, "MCI LNA_INFO\n"); - } - - if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_INFO) { - - int value_dbm = ar9003_mci_state(ah, - MCI_STATE_CONT_RSSI_POWER, NULL); - - mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_INFO; - - if (ar9003_mci_state(ah, MCI_STATE_CONT_TXRX, NULL)) - ath_dbg(common, ATH_DBG_MCI, - "MCI CONT_INFO: " - "(tx) pri = %d, pwr = %d dBm\n", - ar9003_mci_state(ah, - MCI_STATE_CONT_PRIORITY, NULL), - value_dbm); - else - ath_dbg(common, ATH_DBG_MCI, - "MCI CONT_INFO:" - "(rx) pri = %d,pwr = %d dBm\n", - ar9003_mci_state(ah, - MCI_STATE_CONT_PRIORITY, NULL), - value_dbm); - } - - if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_NACK) { - mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_NACK; - ath_dbg(common, ATH_DBG_MCI, "MCI CONT_NACK\n"); - } - - if (mci_int_rxmsg & AR_MCI_INTERRUPT_RX_MSG_CONT_RST) { - mci_int_rxmsg &= ~AR_MCI_INTERRUPT_RX_MSG_CONT_RST; - ath_dbg(common, ATH_DBG_MCI, "MCI CONT_RST\n"); - } - } - - if ((mci_int & AR_MCI_INTERRUPT_RX_INVALID_HDR) || - (mci_int & AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT)) - mci_int &= ~(AR_MCI_INTERRUPT_RX_INVALID_HDR | - AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT); - - if (mci_int_rxmsg & 0xfffffffe) - ath_dbg(common, ATH_DBG_MCI, - "MCI not processed mci_int_rxmsg = 0x%x\n", - mci_int_rxmsg); -} diff --git a/trunk/drivers/net/wireless/ath/ath9k/mci.h b/trunk/drivers/net/wireless/ath/ath9k/mci.h index b71bdeda7c78..9590c61822d1 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mci.h +++ b/trunk/drivers/net/wireless/ath/ath9k/mci.h @@ -17,9 +17,6 @@ #ifndef MCI_H #define MCI_H -#define ATH_MCI_SCHED_BUF_SIZE (16 * 16) /* 16 entries, 4 dword each */ -#define ATH_MCI_GPM_MAX_ENTRY 16 -#define ATH_MCI_GPM_BUF_SIZE (ATH_MCI_GPM_MAX_ENTRY * 16) #define ATH_MCI_DEF_BT_PERIOD 40 #define ATH_MCI_BDR_DUTY_CYCLE 20 #define ATH_MCI_MAX_DUTY_CYCLE 90 @@ -113,26 +110,9 @@ struct ath_mci_profile { u8 num_bdr; }; - -struct ath_mci_buf { - void *bf_addr; /* virtual addr of desc */ - dma_addr_t bf_paddr; /* physical addr of buffer */ - u32 bf_len; /* len of data */ -}; - -struct ath_mci_coex { - atomic_t mci_cal_flag; - struct ath_mci_buf sched_buf; - struct ath_mci_buf gpm_buf; - u32 bt_cal_start; -}; - void ath_mci_flush_profile(struct ath_mci_profile *mci); void ath_mci_process_profile(struct ath_softc *sc, struct ath_mci_profile_info *info); void ath_mci_process_status(struct ath_softc *sc, struct ath_mci_profile_status *status); -int ath_mci_setup(struct ath_softc *sc); -void ath_mci_cleanup(struct ath_softc *sc); -void ath_mci_intr(struct ath_softc *sc); #endif diff --git a/trunk/drivers/net/wireless/ath/ath9k/pci.c b/trunk/drivers/net/wireless/ath/ath9k/pci.c index a439edc5dc06..2dcdf63cb390 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/pci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/pci.c @@ -307,11 +307,12 @@ static int ath_pci_suspend(struct device *device) struct ieee80211_hw *hw = pci_get_drvdata(pdev); struct ath_softc *sc = hw->priv; + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); + /* The device has to be moved to FULLSLEEP forcibly. * Otherwise the chip never moved to full sleep, * when no interface is up. */ - ath9k_hw_disable(sc->sc_ah); ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); return 0; @@ -320,6 +321,8 @@ static int ath_pci_suspend(struct device *device) static int ath_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath_softc *sc = hw->priv; u32 val; /* @@ -331,6 +334,22 @@ static int ath_pci_resume(struct device *device) if ((val & 0x0000ff00) != 0) pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); + ath9k_ps_wakeup(sc); + /* Enable LED */ + ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, + AR_GPIO_OUTPUT_MUX_AS_OUTPUT); + ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); + + /* + * Reset key cache to sane defaults (all entries cleared) instead of + * semi-random values after suspend/resume. + */ + ath9k_cmn_init_crypto(sc->sc_ah); + ath9k_ps_restore(sc); + + sc->ps_idle = true; + ath_radio_disable(sc, hw); + return 0; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index e0318415c2a0..4c8e296f663b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -475,6 +475,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) return rfilt; +#undef RX_FILTER_PRESERVE } int ath_startrecv(struct ath_softc *sc) @@ -1922,20 +1923,15 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) skb = hdr_skb; } - - if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) { - - /* - * change the default rx antenna if rx diversity - * chooses the other antenna 3 times in a row. - */ - if (sc->rx.defant != rs.rs_antenna) { - if (++sc->rx.rxotherant >= 3) - ath_setdefantenna(sc, rs.rs_antenna); - } else { - sc->rx.rxotherant = 0; - } - + /* + * change the default rx antenna if rx diversity chooses the + * other antenna 3 times in a row. + */ + if (sc->rx.defant != rs.rs_antenna) { + if (++sc->rx.rxotherant >= 3) + ath_setdefantenna(sc, rs.rs_antenna); + } else { + sc->rx.rxotherant = 0; } if (rxs->flag & RX_FLAG_MMIC_STRIPPED) diff --git a/trunk/drivers/net/wireless/ath/ath9k/reg.h b/trunk/drivers/net/wireless/ath/ath9k/reg.h index 6e2f18861f5d..45910975d853 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/reg.h +++ b/trunk/drivers/net/wireless/ath/ath9k/reg.h @@ -1006,8 +1006,6 @@ enum { #define AR_INTR_ASYNC_MASK (AR_SREV_9340(ah) ? 0x4018 : 0x4030) #define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 #define AR_INTR_ASYNC_MASK_GPIO_S 18 -#define AR_INTR_ASYNC_MASK_MCI 0x00000080 -#define AR_INTR_ASYNC_MASK_MCI_S 7 #define AR_INTR_SYNC_MASK (AR_SREV_9340(ah) ? 0x401c : 0x4034) #define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 @@ -1015,14 +1013,6 @@ enum { #define AR_INTR_ASYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4020 : 0x4038) #define AR_INTR_ASYNC_CAUSE (AR_SREV_9340(ah) ? 0x4020 : 0x4038) -#define AR_INTR_ASYNC_CAUSE_MCI 0x00000080 -#define AR_INTR_ASYNC_USED (AR_INTR_MAC_IRQ | \ - AR_INTR_ASYNC_CAUSE_MCI) - -/* Asynchronous Interrupt Enable Register */ -#define AR_INTR_ASYNC_ENABLE_MCI 0x00000080 -#define AR_INTR_ASYNC_ENABLE_MCI_S 7 - #define AR_INTR_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4024 : 0x403c) #define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 @@ -1279,8 +1269,6 @@ enum { #define AR_RTC_INTR_MASK \ ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058) -#define AR_RTC_KEEP_AWAKE 0x7034 - /* RTC_DERIVED_* - only for AR9100 */ #define AR_RTC_DERIVED_CLK \ @@ -1567,8 +1555,6 @@ enum { #define AR_DIAG_FRAME_NV0 0x00020000 #define AR_DIAG_OBS_PT_SEL1 0x000C0000 #define AR_DIAG_OBS_PT_SEL1_S 18 -#define AR_DIAG_OBS_PT_SEL2 0x08000000 -#define AR_DIAG_OBS_PT_SEL2_S 27 #define AR_DIAG_FORCE_RX_CLEAR 0x00100000 /* force rx_clear high */ #define AR_DIAG_IGNORE_VIRT_CS 0x00200000 #define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000 @@ -1943,277 +1929,37 @@ enum { #define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6 /* MCI Registers */ - -#define AR_MCI_COMMAND0 0x1800 -#define AR_MCI_COMMAND0_HEADER 0xFF -#define AR_MCI_COMMAND0_HEADER_S 0 -#define AR_MCI_COMMAND0_LEN 0x1f00 -#define AR_MCI_COMMAND0_LEN_S 8 -#define AR_MCI_COMMAND0_DISABLE_TIMESTAMP 0x2000 -#define AR_MCI_COMMAND0_DISABLE_TIMESTAMP_S 13 - -#define AR_MCI_COMMAND1 0x1804 - -#define AR_MCI_COMMAND2 0x1808 -#define AR_MCI_COMMAND2_RESET_TX 0x01 -#define AR_MCI_COMMAND2_RESET_TX_S 0 -#define AR_MCI_COMMAND2_RESET_RX 0x02 -#define AR_MCI_COMMAND2_RESET_RX_S 1 -#define AR_MCI_COMMAND2_RESET_RX_NUM_CYCLES 0x3FC -#define AR_MCI_COMMAND2_RESET_RX_NUM_CYCLES_S 2 -#define AR_MCI_COMMAND2_RESET_REQ_WAKEUP 0x400 -#define AR_MCI_COMMAND2_RESET_REQ_WAKEUP_S 10 - -#define AR_MCI_RX_CTRL 0x180c - -#define AR_MCI_TX_CTRL 0x1810 -/* 0 = no division, 1 = divide by 2, 2 = divide by 4, 3 = divide by 8 */ -#define AR_MCI_TX_CTRL_CLK_DIV 0x03 -#define AR_MCI_TX_CTRL_CLK_DIV_S 0 -#define AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE 0x04 -#define AR_MCI_TX_CTRL_DISABLE_LNA_UPDATE_S 2 -#define AR_MCI_TX_CTRL_GAIN_UPDATE_FREQ 0xFFFFF8 -#define AR_MCI_TX_CTRL_GAIN_UPDATE_FREQ_S 3 -#define AR_MCI_TX_CTRL_GAIN_UPDATE_NUM 0xF000000 -#define AR_MCI_TX_CTRL_GAIN_UPDATE_NUM_S 24 - -#define AR_MCI_MSG_ATTRIBUTES_TABLE 0x1814 -#define AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM 0xFFFF -#define AR_MCI_MSG_ATTRIBUTES_TABLE_CHECKSUM_S 0 -#define AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR 0xFFFF0000 -#define AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR_S 16 - -#define AR_MCI_SCHD_TABLE_0 0x1818 -#define AR_MCI_SCHD_TABLE_1 0x181c -#define AR_MCI_GPM_0 0x1820 -#define AR_MCI_GPM_1 0x1824 -#define AR_MCI_GPM_WRITE_PTR 0xFFFF0000 -#define AR_MCI_GPM_WRITE_PTR_S 16 -#define AR_MCI_GPM_BUF_LEN 0x0000FFFF -#define AR_MCI_GPM_BUF_LEN_S 0 - -#define AR_MCI_INTERRUPT_RAW 0x1828 -#define AR_MCI_INTERRUPT_EN 0x182c -#define AR_MCI_INTERRUPT_SW_MSG_DONE 0x00000001 -#define AR_MCI_INTERRUPT_SW_MSG_DONE_S 0 -#define AR_MCI_INTERRUPT_CPU_INT_MSG 0x00000002 -#define AR_MCI_INTERRUPT_CPU_INT_MSG_S 1 -#define AR_MCI_INTERRUPT_RX_CKSUM_FAIL 0x00000004 -#define AR_MCI_INTERRUPT_RX_CKSUM_FAIL_S 2 -#define AR_MCI_INTERRUPT_RX_INVALID_HDR 0x00000008 -#define AR_MCI_INTERRUPT_RX_INVALID_HDR_S 3 -#define AR_MCI_INTERRUPT_RX_HW_MSG_FAIL 0x00000010 -#define AR_MCI_INTERRUPT_RX_HW_MSG_FAIL_S 4 -#define AR_MCI_INTERRUPT_RX_SW_MSG_FAIL 0x00000020 -#define AR_MCI_INTERRUPT_RX_SW_MSG_FAIL_S 5 -#define AR_MCI_INTERRUPT_TX_HW_MSG_FAIL 0x00000080 -#define AR_MCI_INTERRUPT_TX_HW_MSG_FAIL_S 7 -#define AR_MCI_INTERRUPT_TX_SW_MSG_FAIL 0x00000100 -#define AR_MCI_INTERRUPT_TX_SW_MSG_FAIL_S 8 -#define AR_MCI_INTERRUPT_RX_MSG 0x00000200 -#define AR_MCI_INTERRUPT_RX_MSG_S 9 -#define AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE 0x00000400 -#define AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE_S 10 -#define AR_MCI_INTERRUPT_BT_PRI 0x07fff800 -#define AR_MCI_INTERRUPT_BT_PRI_S 11 -#define AR_MCI_INTERRUPT_BT_PRI_THRESH 0x08000000 -#define AR_MCI_INTERRUPT_BT_PRI_THRESH_S 27 -#define AR_MCI_INTERRUPT_BT_FREQ 0x10000000 -#define AR_MCI_INTERRUPT_BT_FREQ_S 28 -#define AR_MCI_INTERRUPT_BT_STOMP 0x20000000 -#define AR_MCI_INTERRUPT_BT_STOMP_S 29 -#define AR_MCI_INTERRUPT_BB_AIC_IRQ 0x40000000 -#define AR_MCI_INTERRUPT_BB_AIC_IRQ_S 30 -#define AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT 0x80000000 -#define AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT_S 31 - -#define AR_MCI_INTERRUPT_DEFAULT (AR_MCI_INTERRUPT_SW_MSG_DONE | \ - AR_MCI_INTERRUPT_RX_INVALID_HDR | \ - AR_MCI_INTERRUPT_RX_HW_MSG_FAIL | \ - AR_MCI_INTERRUPT_RX_SW_MSG_FAIL | \ - AR_MCI_INTERRUPT_TX_HW_MSG_FAIL | \ - AR_MCI_INTERRUPT_TX_SW_MSG_FAIL | \ - AR_MCI_INTERRUPT_RX_MSG | \ - AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE | \ - AR_MCI_INTERRUPT_CONT_INFO_TIMEOUT) - -#define AR_MCI_INTERRUPT_MSG_FAIL_MASK (AR_MCI_INTERRUPT_RX_HW_MSG_FAIL | \ - AR_MCI_INTERRUPT_RX_SW_MSG_FAIL | \ - AR_MCI_INTERRUPT_TX_HW_MSG_FAIL | \ - AR_MCI_INTERRUPT_TX_SW_MSG_FAIL) - -#define AR_MCI_REMOTE_CPU_INT 0x1830 -#define AR_MCI_REMOTE_CPU_INT_EN 0x1834 -#define AR_MCI_INTERRUPT_RX_MSG_RAW 0x1838 -#define AR_MCI_INTERRUPT_RX_MSG_EN 0x183c -#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001 -#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET_S 0 -#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002 -#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL_S 1 -#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004 -#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK_S 2 -#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008 -#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO_S 3 -#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010 -#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST_S 4 -#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020 -#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO_S 5 -#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040 -#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT_S 6 -#define AR_MCI_INTERRUPT_RX_MSG_GPM 0x00000100 -#define AR_MCI_INTERRUPT_RX_MSG_GPM_S 8 -#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200 -#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO_S 9 -#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400 -#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING_S 10 -#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800 -#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING_S 11 -#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000 -#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE_S 12 -#define AR_MCI_INTERRUPT_RX_HW_MSG_MASK (AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \ +#define AR_MCI_INTERRUPT_RX_MSG_EN 0x183c +#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET 0x00000001 +#define AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET_S 0 +#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL 0x00000002 +#define AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL_S 1 +#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK 0x00000004 +#define AR_MCI_INTERRUPT_RX_MSG_CONT_NACK_S 2 +#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO 0x00000008 +#define AR_MCI_INTERRUPT_RX_MSG_CONT_INFO_S 3 +#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST 0x00000010 +#define AR_MCI_INTERRUPT_RX_MSG_CONT_RST_S 4 +#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO 0x00000020 +#define AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO_S 5 +#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT 0x00000040 +#define AR_MCI_INTERRUPT_RX_MSG_CPU_INT_S 6 +#define AR_MCI_INTERRUPT_RX_MSG_GPM 0x00000100 +#define AR_MCI_INTERRUPT_RX_MSG_GPM_S 8 +#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO 0x00000200 +#define AR_MCI_INTERRUPT_RX_MSG_LNA_INFO_S 9 +#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING 0x00000400 +#define AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING_S 10 +#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING 0x00000800 +#define AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING_S 11 +#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE 0x00001000 +#define AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE_S 12 +#define AR_MCI_INTERRUPT_RX_HW_MSG_MASK (AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \ AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL| \ AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \ AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \ AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \ AR_MCI_INTERRUPT_RX_MSG_CONT_RST) -#define AR_MCI_INTERRUPT_RX_MSG_DEFAULT (AR_MCI_INTERRUPT_RX_MSG_GPM | \ - AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET| \ - AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING | \ - AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING| \ - AR_MCI_INTERRUPT_RX_MSG_SCHD_INFO | \ - AR_MCI_INTERRUPT_RX_MSG_LNA_CONTROL | \ - AR_MCI_INTERRUPT_RX_MSG_LNA_INFO | \ - AR_MCI_INTERRUPT_RX_MSG_CONT_NACK | \ - AR_MCI_INTERRUPT_RX_MSG_CONT_INFO | \ - AR_MCI_INTERRUPT_RX_MSG_CONT_RST | \ - AR_MCI_INTERRUPT_RX_MSG_REQ_WAKE) - -#define AR_MCI_CPU_INT 0x1840 - -#define AR_MCI_RX_STATUS 0x1844 -#define AR_MCI_RX_LAST_SCHD_MSG_INDEX 0x00000F00 -#define AR_MCI_RX_LAST_SCHD_MSG_INDEX_S 8 -#define AR_MCI_RX_REMOTE_SLEEP 0x00001000 -#define AR_MCI_RX_REMOTE_SLEEP_S 12 -#define AR_MCI_RX_MCI_CLK_REQ 0x00002000 -#define AR_MCI_RX_MCI_CLK_REQ_S 13 - -#define AR_MCI_CONT_STATUS 0x1848 -#define AR_MCI_CONT_RSSI_POWER 0x000000FF -#define AR_MCI_CONT_RSSI_POWER_S 0 -#define AR_MCI_CONT_RRIORITY 0x0000FF00 -#define AR_MCI_CONT_RRIORITY_S 8 -#define AR_MCI_CONT_TXRX 0x00010000 -#define AR_MCI_CONT_TXRX_S 16 - -#define AR_MCI_BT_PRI0 0x184c -#define AR_MCI_BT_PRI1 0x1850 -#define AR_MCI_BT_PRI2 0x1854 -#define AR_MCI_BT_PRI3 0x1858 -#define AR_MCI_BT_PRI 0x185c -#define AR_MCI_WL_FREQ0 0x1860 -#define AR_MCI_WL_FREQ1 0x1864 -#define AR_MCI_WL_FREQ2 0x1868 -#define AR_MCI_GAIN 0x186c -#define AR_MCI_WBTIMER1 0x1870 -#define AR_MCI_WBTIMER2 0x1874 -#define AR_MCI_WBTIMER3 0x1878 -#define AR_MCI_WBTIMER4 0x187c -#define AR_MCI_MAXGAIN 0x1880 -#define AR_MCI_HW_SCHD_TBL_CTL 0x1884 -#define AR_MCI_HW_SCHD_TBL_D0 0x1888 -#define AR_MCI_HW_SCHD_TBL_D1 0x188c -#define AR_MCI_HW_SCHD_TBL_D2 0x1890 -#define AR_MCI_HW_SCHD_TBL_D3 0x1894 -#define AR_MCI_TX_PAYLOAD0 0x1898 -#define AR_MCI_TX_PAYLOAD1 0x189c -#define AR_MCI_TX_PAYLOAD2 0x18a0 -#define AR_MCI_TX_PAYLOAD3 0x18a4 -#define AR_BTCOEX_WBTIMER 0x18a8 - -#define AR_BTCOEX_CTRL 0x18ac -#define AR_BTCOEX_CTRL_AR9462_MODE 0x00000001 -#define AR_BTCOEX_CTRL_AR9462_MODE_S 0 -#define AR_BTCOEX_CTRL_WBTIMER_EN 0x00000002 -#define AR_BTCOEX_CTRL_WBTIMER_EN_S 1 -#define AR_BTCOEX_CTRL_MCI_MODE_EN 0x00000004 -#define AR_BTCOEX_CTRL_MCI_MODE_EN_S 2 -#define AR_BTCOEX_CTRL_LNA_SHARED 0x00000008 -#define AR_BTCOEX_CTRL_LNA_SHARED_S 3 -#define AR_BTCOEX_CTRL_PA_SHARED 0x00000010 -#define AR_BTCOEX_CTRL_PA_SHARED_S 4 -#define AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN 0x00000020 -#define AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN_S 5 -#define AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN 0x00000040 -#define AR_BTCOEX_CTRL_TIME_TO_NEXT_BT_THRESH_EN_S 6 -#define AR_BTCOEX_CTRL_NUM_ANTENNAS 0x00000180 -#define AR_BTCOEX_CTRL_NUM_ANTENNAS_S 7 -#define AR_BTCOEX_CTRL_RX_CHAIN_MASK 0x00000E00 -#define AR_BTCOEX_CTRL_RX_CHAIN_MASK_S 9 -#define AR_BTCOEX_CTRL_AGGR_THRESH 0x00007000 -#define AR_BTCOEX_CTRL_AGGR_THRESH_S 12 -#define AR_BTCOEX_CTRL_1_CHAIN_BCN 0x00080000 -#define AR_BTCOEX_CTRL_1_CHAIN_BCN_S 19 -#define AR_BTCOEX_CTRL_1_CHAIN_ACK 0x00100000 -#define AR_BTCOEX_CTRL_1_CHAIN_ACK_S 20 -#define AR_BTCOEX_CTRL_WAIT_BA_MARGIN 0x1FE00000 -#define AR_BTCOEX_CTRL_WAIT_BA_MARGIN_S 28 -#define AR_BTCOEX_CTRL_REDUCE_TXPWR 0x20000000 -#define AR_BTCOEX_CTRL_REDUCE_TXPWR_S 29 -#define AR_BTCOEX_CTRL_SPDT_ENABLE_10 0x40000000 -#define AR_BTCOEX_CTRL_SPDT_ENABLE_10_S 30 -#define AR_BTCOEX_CTRL_SPDT_POLARITY 0x80000000 -#define AR_BTCOEX_CTRL_SPDT_POLARITY_S 31 - -#define AR_BTCOEX_WL_WEIGHTS0 0x18b0 -#define AR_BTCOEX_WL_WEIGHTS1 0x18b4 -#define AR_BTCOEX_WL_WEIGHTS2 0x18b8 -#define AR_BTCOEX_WL_WEIGHTS3 0x18bc -#define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2)) -#define AR_BTCOEX_WL_LNA 0x1940 -#define AR_BTCOEX_RFGAIN_CTRL 0x1944 - -#define AR_BTCOEX_CTRL2 0x1948 -#define AR_BTCOEX_CTRL2_TXPWR_THRESH 0x0007F800 -#define AR_BTCOEX_CTRL2_TXPWR_THRESH_S 11 -#define AR_BTCOEX_CTRL2_TX_CHAIN_MASK 0x00380000 -#define AR_BTCOEX_CTRL2_TX_CHAIN_MASK_S 19 -#define AR_BTCOEX_CTRL2_RX_DEWEIGHT 0x00400000 -#define AR_BTCOEX_CTRL2_RX_DEWEIGHT_S 22 -#define AR_BTCOEX_CTRL2_GPIO_OBS_SEL 0x00800000 -#define AR_BTCOEX_CTRL2_GPIO_OBS_SEL_S 23 -#define AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL 0x01000000 -#define AR_BTCOEX_CTRL2_MAC_BB_OBS_SEL_S 24 -#define AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE 0x02000000 -#define AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE_S 25 - -#define AR_BTCOEX_CTRL_SPDT_ENABLE 0x00000001 -#define AR_BTCOEX_CTRL_SPDT_ENABLE_S 0 -#define AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL 0x00000002 -#define AR_BTCOEX_CTRL_BT_OWN_SPDT_CTRL_S 1 -#define AR_BTCOEX_CTRL_USE_LATCHED_BT_ANT 0x00000004 -#define AR_BTCOEX_CTRL_USE_LATCHED_BT_ANT_S 2 -#define AR_GLB_WLAN_UART_INTF_EN 0x00020000 -#define AR_GLB_WLAN_UART_INTF_EN_S 17 -#define AR_GLB_DS_JTAG_DISABLE 0x00040000 -#define AR_GLB_DS_JTAG_DISABLE_S 18 - -#define AR_BTCOEX_RC 0x194c -#define AR_BTCOEX_MAX_RFGAIN(_x) (0x1950 + ((_x) << 2)) -#define AR_BTCOEX_DBG 0x1a50 -#define AR_MCI_LAST_HW_MSG_HDR 0x1a54 -#define AR_MCI_LAST_HW_MSG_BDY 0x1a58 - -#define AR_MCI_SCHD_TABLE_2 0x1a5c -#define AR_MCI_SCHD_TABLE_2_MEM_BASED 0x00000001 -#define AR_MCI_SCHD_TABLE_2_MEM_BASED_S 0 -#define AR_MCI_SCHD_TABLE_2_HW_BASED 0x00000002 -#define AR_MCI_SCHD_TABLE_2_HW_BASED_S 1 - -#define AR_BTCOEX_CTRL3 0x1a60 -#define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT 0x00000fff -#define AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT_S 0 - #endif diff --git a/trunk/drivers/net/wireless/ath/ath9k/xmit.c b/trunk/drivers/net/wireless/ath/ath9k/xmit.c index 9e65c3198ca7..55d077e7135d 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/xmit.c +++ b/trunk/drivers/net/wireless/ath/ath9k/xmit.c @@ -179,11 +179,6 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) spin_lock_bh(&txq->axq_lock); } - if (tid->baw_head == tid->baw_tail) { - tid->state &= ~AGGR_ADDBA_COMPLETE; - tid->state &= ~AGGR_CLEANUP; - } - spin_unlock_bh(&txq->axq_lock); } @@ -561,9 +556,15 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, spin_unlock_bh(&txq->axq_lock); } - if (tid->state & AGGR_CLEANUP) + if (tid->state & AGGR_CLEANUP) { ath_tx_flush_tid(sc, tid); + if (tid->baw_head == tid->baw_tail) { + tid->state &= ~AGGR_ADDBA_COMPLETE; + tid->state &= ~AGGR_CLEANUP; + } + } + rcu_read_unlock(); if (needreset) { @@ -1954,7 +1955,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, skb_pull(skb, padsize); } - if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) { + if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; ath_dbg(common, ATH_DBG_PS, "Going back to sleep after having received TX status (0x%lx)\n", diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h new file mode 100644 index 000000000000..cecb5e5f412b --- /dev/null +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmchip.h @@ -0,0 +1,25 @@ +/* + * 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 */ +/* firmware name */ +#define BCM4329_FW_NAME "brcm/bcm4329-fullmac-4.bin" +#define BCM4329_NV_NAME "brcm/bcm4329-fullmac-4.txt" + +#endif /* _bcmchip_h_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 74933dccf69e..89ff94da556a 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -40,8 +40,7 @@ static void brcmf_sdioh_irqhandler(struct sdio_func *func) { - struct brcmf_bus *bus_if = dev_get_drvdata(&func->card->dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; + struct brcmf_sdio_dev *sdiodev = dev_get_drvdata(&func->card->dev); brcmf_dbg(TRACE, "***IRQHandler\n"); @@ -223,12 +222,19 @@ bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev) return sdiodev->regfail; } -static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn, - uint flags, uint width, u32 *addr) +int +brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, + uint flags, + u8 *buf, uint nbytes, struct sk_buff *pkt) { - uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK; + 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; @@ -241,114 +247,29 @@ static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn, sdiodev->sbwad = bar0; } - *addr &= SBSDIO_SB_OFT_ADDR_MASK; - - if (width == 4) - *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - - return 0; -} - -int -brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, - uint flags, u8 *buf, uint nbytes) -{ - struct sk_buff *mypkt; - int err; - - mypkt = brcmu_pkt_buf_get_skb(nbytes); - if (!mypkt) { - brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n", - nbytes); - return -EIO; - } - - err = brcmf_sdcard_recv_pkt(sdiodev, addr, fn, flags, mypkt); - if (!err) - memcpy(buf, mypkt->data, nbytes); - - brcmu_pkt_buf_free_skb(mypkt); - return err; -} - -int -brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, - uint flags, struct sk_buff *pkt) -{ - uint incr_fix; - uint width; - int err = 0; - - brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", - fn, addr, pkt->len); - - width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; - err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); - if (err) - return err; + addr &= SBSDIO_SB_OFT_ADDR_MASK; incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; - err = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ, - fn, addr, pkt); - - return err; -} - -int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, - uint flags, struct sk_buff_head *pktq) -{ - uint incr_fix; - uint width; - int err = 0; - - brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", - fn, addr, pktq->qlen); - width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; - err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr); - if (err) - return err; + if (width == 4) + addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; - err = brcmf_sdioh_request_chain(sdiodev, incr_fix, SDIOH_READ, fn, addr, - pktq); + status = brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_READ, + fn, addr, width, nbytes, buf, pkt); - return err; + 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 *mypkt; - int err; - - mypkt = brcmu_pkt_buf_get_skb(nbytes); - if (!mypkt) { - brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n", - nbytes); - return -EIO; - } - - memcpy(mypkt->data, buf, nbytes); - err = brcmf_sdcard_send_pkt(sdiodev, addr, fn, flags, mypkt); - - brcmu_pkt_buf_free_skb(mypkt); - return err; - -} - -int -brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, - uint flags, struct sk_buff *pkt) + 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, pkt->len); + brcmf_dbg(INFO, "fun = %d, addr = 0x%x, size = %d\n", fn, addr, nbytes); /* Async not implemented yet */ if (flags & SDIO_REQ_ASYNC) @@ -370,39 +291,18 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; return brcmf_sdioh_request_buffer(sdiodev, incr_fix, SDIOH_WRITE, fn, - addr, pkt); + addr, width, nbytes, buf, pkt); } int brcmf_sdcard_rwdata(struct brcmf_sdio_dev *sdiodev, uint rw, u32 addr, u8 *buf, uint nbytes) { - struct sk_buff *mypkt; - bool write = rw ? SDIOH_WRITE : SDIOH_READ; - int err; - addr &= SBSDIO_SB_OFT_ADDR_MASK; addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - mypkt = brcmu_pkt_buf_get_skb(nbytes); - if (!mypkt) { - brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n", - nbytes); - return -EIO; - } - - /* For a write, copy the buffer data into the packet. */ - if (write) - memcpy(mypkt->data, buf, nbytes); - - err = brcmf_sdioh_request_buffer(sdiodev, SDIOH_DATA_INC, write, - SDIO_FUNC_1, addr, mypkt); - - /* For a read, copy the packet data back to the buffer. */ - if (!err && !write) - memcpy(buf, mypkt->data, nbytes); - - brcmu_pkt_buf_free_skb(mypkt); - return err; + 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) @@ -433,7 +333,7 @@ int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) sdiodev->sbwad = SI_ENUM_BASE; /* try to attach to the target device */ - sdiodev->bus = brcmf_sdbrcm_probe(regs, sdiodev); + sdiodev->bus = brcmf_sdbrcm_probe(0, 0, 0, 0, regs, sdiodev); if (!sdiodev->bus) { brcmf_dbg(ERROR, "device attach failed\n"); ret = -ENODEV; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index b416e274c677..bbaeb2d5c93a 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -204,75 +204,62 @@ int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, return err_ret; } -/* precondition: host controller is claimed */ static int -brcmf_sdioh_request_data(struct brcmf_sdio_dev *sdiodev, uint write, bool fifo, - uint func, uint addr, struct sk_buff *pkt, uint pktlen) -{ - int err_ret = 0; - - if ((write) && (!fifo)) { - err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, - ((u8 *) (pkt->data)), pktlen); - } else if (write) { - err_ret = sdio_memcpy_toio(sdiodev->func[func], addr, - ((u8 *) (pkt->data)), pktlen); - } else if (fifo) { - err_ret = sdio_readsb(sdiodev->func[func], - ((u8 *) (pkt->data)), addr, pktlen); - } else { - err_ret = sdio_memcpy_fromio(sdiodev->func[func], - ((u8 *) (pkt->data)), - addr, pktlen); - } - - return err_ret; -} - -/* - * This function takes a queue of packets. The packets on the queue - * are assumed to be properly aligned by the caller. - */ -int -brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, - uint write, uint func, uint addr, - struct sk_buff_head *pktq) +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 *pkt; + struct sk_buff *pnext; brcmf_dbg(TRACE, "Enter\n"); - brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait); + 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]); - - skb_queue_walk(pktq, pkt) { - uint pkt_len = pkt->len; + for (pnext = pkt; pnext; pnext = pnext->next) { + uint pkt_len = pnext->len; pkt_len += 3; pkt_len &= 0xFFFFFFFC; - err_ret = brcmf_sdioh_request_data(sdiodev, write, fifo, func, - addr, pkt, pkt_len); + 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", pkt, SGCount, addr, + 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", pkt, SGCount, addr, + write ? "TX" : "RX", pnext, SGCount, addr, pkt_len); } + if (!fifo) addr += pkt_len; - SGCount++; + } /* Release host controller */ @@ -283,45 +270,91 @@ brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, } /* - * This function takes a single DMA-able packet. + * 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; - uint pkt_len = pkt->len; - bool fifo = (fix_inc == SDIOH_DATA_FIX); + int Status; + struct sk_buff *mypkt = NULL; brcmf_dbg(TRACE, "Enter\n"); - if (pkt == NULL) - return -EINVAL; - 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; + } - /* Claim host controller */ - sdio_claim_host(sdiodev->func[func]); + /* 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; + } - pkt_len += 3; - pkt_len &= (uint)~3; + /* For a write, copy the buffer data into the packet. */ + if (write) + memcpy(mypkt->data, pkt->data, pkt->len); - status = brcmf_sdioh_request_data(sdiodev, write, fifo, func, - addr, pkt, pkt_len); - if (status) { - brcmf_dbg(ERROR, "%s FAILED %p, addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", - write ? "TX" : "RX", pkt, addr, pkt_len, status); - } else { - brcmf_dbg(TRACE, "%s xfr'd %p, addr=0x%05x, len=%d\n", - write ? "TX" : "RX", pkt, addr, pkt_len); - } + Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write, + func, addr, mypkt); - /* Release host controller */ - sdio_release_host(sdiodev->func[func]); + /* For a read, copy the packet data back to the buffer. */ + if (!write) + memcpy(pkt->data, mypkt->data, mypkt->len); - return status; + 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 */ @@ -461,7 +494,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, { int ret = 0; struct brcmf_sdio_dev *sdiodev; - struct brcmf_bus *bus_if; brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "func->class=%x\n", func->class); brcmf_dbg(TRACE, "sdio_vendor: 0x%04x\n", func->vendor); @@ -473,31 +505,22 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, brcmf_dbg(ERROR, "card private drvdata occupied\n"); return -ENXIO; } - bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL); - if (!bus_if) - return -ENOMEM; sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL); - if (!sdiodev) { - kfree(bus_if); + if (!sdiodev) return -ENOMEM; - } - sdiodev->dev = &func->card->dev; sdiodev->func[0] = func->card->sdio_func[0]; sdiodev->func[1] = func; - bus_if->bus_priv = sdiodev; - bus_if->type = SDIO_BUS; - dev_set_drvdata(&func->card->dev, bus_if); + 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_chain_wait); + init_waitqueue_head(&sdiodev->request_packet_wait); init_waitqueue_head(&sdiodev->request_buffer_wait); } if (func->num == 2) { - bus_if = dev_get_drvdata(&func->card->dev); - sdiodev = bus_if->bus_priv; + sdiodev = dev_get_drvdata(&func->card->dev); if ((!sdiodev) || (sdiodev->func[1]->card != func->card)) return -ENODEV; sdiodev->func[2] = func; @@ -511,7 +534,6 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, static void brcmf_ops_sdio_remove(struct sdio_func *func) { - struct brcmf_bus *bus_if; struct brcmf_sdio_dev *sdiodev; brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(INFO, "func->class=%x\n", func->class); @@ -520,12 +542,10 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) brcmf_dbg(INFO, "Function#: 0x%04x\n", func->num); if (func->num == 2) { - bus_if = dev_get_drvdata(&func->card->dev); - sdiodev = bus_if->bus_priv; + 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(bus_if); kfree(sdiodev); } } @@ -536,12 +556,11 @@ 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); - struct brcmf_bus *bus_if = dev_get_drvdata(&func->card->dev); int ret = 0; brcmf_dbg(TRACE, "\n"); - sdiodev = bus_if->bus_priv; + sdiodev = dev_get_drvdata(&func->card->dev); atomic_set(&sdiodev->suspend, true); @@ -566,9 +585,8 @@ static int brcmf_sdio_resume(struct device *dev) { struct brcmf_sdio_dev *sdiodev; struct sdio_func *func = dev_to_sdio_func(dev); - struct brcmf_bus *bus_if = dev_get_drvdata(&func->card->dev); - sdiodev = bus_if->bus_priv; + sdiodev = dev_get_drvdata(&func->card->dev); brcmf_sdio_wdtmr_enable(sdiodev, true); atomic_set(&sdiodev->suspend, false); return 0; @@ -592,26 +610,17 @@ static struct sdio_driver brcmf_sdmmc_driver = { #endif /* CONFIG_PM_SLEEP */ }; -static void __exit brcmf_sdio_exit(void) +/* bus register interface */ +int brcmf_bus_register(void) { brcmf_dbg(TRACE, "Enter\n"); - sdio_unregister_driver(&brcmf_sdmmc_driver); + return sdio_register_driver(&brcmf_sdmmc_driver); } -static int __init brcmf_sdio_init(void) +void brcmf_bus_unregister(void) { - int ret; - brcmf_dbg(TRACE, "Enter\n"); - ret = sdio_register_driver(&brcmf_sdmmc_driver); - - if (ret) - brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret); - - return ret; + sdio_unregister_driver(&brcmf_sdmmc_driver); } - -module_init(brcmf_sdio_init); -module_exit(brcmf_sdio_exit); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index b68d1363105c..6da519e7578f 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -571,14 +571,8 @@ struct brcmf_dcmd { uint needed; /* bytes needed (optional) */ }; -struct brcmf_bus { - u8 type; /* bus type */ - void *bus_priv; /* pointer to bus private structure */ - enum brcmf_bus_state state; -}; - /* Forward decls for struct brcmf_pub (see below) */ -struct brcmf_sdio; /* device bus info */ +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 */ @@ -586,16 +580,15 @@ struct brcmf_cfg80211_dev; /* cfg80211 device info */ /* Common structure for module and instance linkage */ struct brcmf_pub { /* Linkage ponters */ - struct brcmf_sdio *bus; - struct brcmf_bus *bus_if; + struct brcmf_bus *bus; struct brcmf_proto *prot; struct brcmf_info *info; struct brcmf_cfg80211_dev *config; - struct device *dev; /* fullmac dongle device pointer */ /* 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 */ @@ -663,6 +656,7 @@ struct brcmf_pub { u8 country_code[BRCM_CNTRY_BUF_SZ]; char eventmask[BRCMF_EVENTING_MASK_LEN]; + }; struct brcmf_if_event { @@ -687,8 +681,8 @@ extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen, * 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_sdio *bus, - uint bus_hdrlen, struct device *dev); +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); @@ -705,16 +699,7 @@ extern bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q, /* Receive frame for delivery to OS. Callee disposes of rxp. */ extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, - struct sk_buff_head *rxlist); -static inline void brcmf_rx_packet(struct brcmf_pub *drvr, int ifidx, - struct sk_buff *pkt) -{ - struct sk_buff_head q; - - skb_queue_head_init(&q); - skb_queue_tail(&q, pkt); - brcmf_rx_frame(drvr, ifidx, &q); -} + struct sk_buff *rxp, int numpkt); /* Return pointer to interface name */ extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); @@ -739,6 +724,8 @@ 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, char *name, u8 *mac_addr); extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index 1841f996110b..a249407c9a1b 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h @@ -27,24 +27,31 @@ * 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 device *dev); +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 device *dev); +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 device *dev, struct sk_buff *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 device *dev, unsigned char *msg, uint msglen); +brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen); extern int -brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen); +brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen); -extern void brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick); +extern void brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick); #endif /* _BRCMF_BUS_H_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index a527d5d4cc4e..e34c5c3d1d55 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c @@ -116,7 +116,7 @@ static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr) len = CDC_MAX_MSG_SIZE; /* Send request */ - return brcmf_sdbrcm_bus_txctl(drvr->dev, (unsigned char *)&prot->msg, + return brcmf_sdbrcm_bus_txctl(drvr->bus, (unsigned char *)&prot->msg, len); } @@ -128,7 +128,7 @@ static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) brcmf_dbg(TRACE, "Enter\n"); do { - ret = brcmf_sdbrcm_bus_rxctl(drvr->dev, + ret = brcmf_sdbrcm_bus_rxctl(drvr->bus, (unsigned char *)&prot->msg, len + sizeof(struct brcmf_proto_cdc_dcmd)); if (ret < 0) @@ -280,7 +280,7 @@ brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, struct brcmf_dcmd *dcmd, struct brcmf_proto *prot = drvr->prot; int ret = -1; - if (drvr->bus_if->state == BRCMF_BUS_DOWN) { + if (drvr->busstate == BRCMF_BUS_DOWN) { brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n"); return ret; } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 69f335aeb255..40928e58b6a6 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -32,6 +32,8 @@ #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) @@ -83,6 +85,19 @@ brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) 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) { diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 58d92bca9ca2..719fd9397eb6 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -43,6 +43,7 @@ #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."); @@ -76,7 +77,6 @@ struct brcmf_info { }; /* Error bits */ -int brcmf_msg_level = BRCMF_ERROR_VAL; module_param(brcmf_msg_level, int, 0); int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name) @@ -292,7 +292,7 @@ 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->bus_if->state == BRCMF_BUS_DOWN)) + if (!drvr->up || (drvr->busstate == BRCMF_BUS_DOWN)) return -ENODEV; /* Update multicast statistic */ @@ -310,7 +310,7 @@ int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf) brcmf_proto_hdrpush(drvr, ifidx, pktbuf); /* Use bus module to send data frame */ - return brcmf_sdbrcm_bus_txdata(drvr->dev, pktbuf); + return brcmf_sdbrcm_bus_txdata(drvr->bus, pktbuf); } static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) @@ -322,11 +322,9 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) brcmf_dbg(TRACE, "Enter\n"); /* Reject if down */ - if (!drvr_priv->pub.up || - (drvr_priv->pub.bus_if->state == BRCMF_BUS_DOWN)) { - brcmf_dbg(ERROR, "xmit rejected pub.up=%d state=%d\n", - drvr_priv->pub.up, - drvr_priv->pub.bus_if->state); + 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; } @@ -399,21 +397,26 @@ static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, return bcmerror; } -void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, - struct sk_buff_head *skb_list) +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 *skb, *pnext; + struct sk_buff *pnext, *save_pktbuf; + int i; struct brcmf_if *ifp; struct brcmf_event_msg event; brcmf_dbg(TRACE, "Enter\n"); - skb_queue_walk_safe(skb_list, skb, pnext) { - skb_unlink(skb, skb_list); + 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 @@ -434,12 +437,6 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, if (ifp == NULL) ifp = drvr_priv->iflist[0]; - if (!ifp || !ifp->ndev || - ifp->ndev->reg_state != NETREG_REGISTERED) { - brcmu_pkt_buf_free_skb(skb); - continue; - } - skb->dev = ifp->ndev; skb->protocol = eth_type_trans(skb, skb->dev); @@ -608,7 +605,9 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev, sprintf(info->driver, KBUILD_MODNAME); sprintf(info->version, "%lu", drvr_priv->pub.drv_version); - sprintf(info->bus_info, "%s", dev_name(drvr_priv->pub.dev)); + 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 = { @@ -762,7 +761,7 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len) buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN); /* send to dongle (must be up, and wl) */ - if ((drvr_priv->pub.bus_if->state != BRCMF_BUS_DATA)) { + if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) { brcmf_dbg(ERROR, "DONGLE_DOWN\n"); err = -EIO; goto done; @@ -941,8 +940,7 @@ void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx) } } -struct brcmf_pub *brcmf_attach(struct brcmf_sdio *bus, uint bus_hdrlen, - struct device *dev) +struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen) { struct brcmf_info *drvr_priv = NULL; @@ -961,8 +959,6 @@ struct brcmf_pub *brcmf_attach(struct brcmf_sdio *bus, uint bus_hdrlen, /* Link to bus module */ drvr_priv->pub.bus = bus; drvr_priv->pub.hdrlen = bus_hdrlen; - drvr_priv->pub.bus_if = dev_get_drvdata(dev); - drvr_priv->pub.dev = dev; /* Attach and link in the protocol */ if (brcmf_proto_attach(&drvr_priv->pub) != 0) { @@ -992,14 +988,14 @@ int brcmf_bus_start(struct brcmf_pub *drvr) brcmf_dbg(TRACE, "\n"); /* Bring up the bus */ - ret = brcmf_sdbrcm_bus_init(drvr_priv->pub.dev); + 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.bus_if->state != BRCMF_BUS_DATA) { + if (drvr_priv->pub.busstate != BRCMF_BUS_DATA) { brcmf_dbg(ERROR, "failed bus is not ready\n"); return -ENODEV; } @@ -1081,7 +1077,10 @@ int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx) /* attach to cfg80211 for primary interface */ if (!ifidx) { - drvr->config = brcmf_cfg80211_attach(ndev, drvr->dev, drvr); + drvr->config = + brcmf_cfg80211_attach(ndev, + brcmf_bus_get_device(drvr->bus), + drvr); if (drvr->config == NULL) { brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n"); goto fail; @@ -1115,7 +1114,7 @@ static void brcmf_bus_detach(struct brcmf_pub *drvr) brcmf_proto_stop(&drvr_priv->pub); /* Stop the bus module */ - brcmf_sdbrcm_bus_stop(drvr_priv->pub.dev); + brcmf_sdbrcm_bus_stop(drvr_priv->pub.bus); } } } @@ -1149,6 +1148,34 @@ void brcmf_detach(struct brcmf_pub *drvr) } } +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; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 18597fe5dfd6..22913af26db8 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -91,6 +91,7 @@ struct rte_console { #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 */ @@ -309,11 +310,6 @@ struct rte_console { /* Flags for SDH calls */ #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) -#define BRCMFMAC_FW_NAME "brcm/brcmfmac.bin" -#define BRCMFMAC_NV_NAME "brcm/brcmfmac.txt" -MODULE_FIRMWARE(BRCMFMAC_FW_NAME); -MODULE_FIRMWARE(BRCMFMAC_NV_NAME); - /* * Conversion of 802.1D priority to precedence level */ @@ -449,7 +445,7 @@ struct sdpcm_shared_le { /* misc chip info needed by some of the routines */ /* Private data for SDIO bus interaction */ -struct brcmf_sdio { +struct brcmf_bus { struct brcmf_pub *drvr; struct brcmf_sdio_dev *sdiodev; /* sdio device handler */ @@ -566,7 +562,9 @@ struct brcmf_sdio { struct semaphore sdsem; + const char *fw_name; const struct firmware *firmware; + const char *nv_name; u32 fw_ptr; }; @@ -604,7 +602,7 @@ static void pkt_align(struct sk_buff *p, int len, int align) } /* To check if there's window offered */ -static bool data_ok(struct brcmf_sdio *bus) +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; @@ -615,7 +613,7 @@ static bool data_ok(struct brcmf_sdio *bus) * adresses on the 32 bit backplane bus. */ static void -r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 reg_offset, u32 *retryvar) +r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar) { u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); *retryvar = 0; @@ -635,7 +633,7 @@ r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 reg_offset, u32 *retryvar) } static void -w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset, u32 *retryvar) +w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar) { u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); *retryvar = 0; @@ -660,14 +658,14 @@ w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset, u32 *retryvar) /* Packet free applicable unconditionally for sdio and sdspi. * Conditional if bufpool was present for gspi bus. */ -static void brcmf_sdbrcm_pktfree2(struct brcmf_sdio *bus, struct sk_buff *pkt) +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_sdio *bus, bool on, bool pendok) +static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) { int err; u8 clkctl, clkreq, devctl; @@ -788,7 +786,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) } /* Change idle/active SD state */ -static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on) +static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on) { brcmf_dbg(TRACE, "Enter\n"); @@ -801,7 +799,7 @@ static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on) } /* Transition SD and backplane clock readiness */ -static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) +static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok) { #ifdef BCMDBG uint oldstate = bus->clkstate; @@ -857,7 +855,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) return 0; } -static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) +static int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep) { uint retries = 0; @@ -929,13 +927,13 @@ static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) return 0; } -static void bus_wake(struct brcmf_sdio *bus) +static void bus_wake(struct brcmf_bus *bus) { if (bus->sleeping) brcmf_sdbrcm_bussleep(bus, false); } -static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) +static u32 brcmf_sdbrcm_hostmail(struct brcmf_bus *bus) { u32 intstatus = 0; u32 hmb_data; @@ -1011,7 +1009,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) return intstatus; } -static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) +static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx) { uint retries = 0; u16 lastrbc; @@ -1068,11 +1066,11 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) /* If we can't reach the device, signal failure */ if (err || brcmf_sdcard_regfail(bus->sdiodev)) - bus->drvr->bus_if->state = BRCMF_BUS_DOWN; + bus->drvr->busstate = BRCMF_BUS_DOWN; } /* copy a buffer into a pkt buffer chain */ -static uint brcmf_sdbrcm_glom_from_buf(struct brcmf_sdio *bus, uint len) +static uint brcmf_sdbrcm_glom_from_buf(struct brcmf_bus *bus, uint len) { uint n, ret = 0; struct sk_buff *p; @@ -1095,7 +1093,7 @@ static uint brcmf_sdbrcm_glom_from_buf(struct brcmf_sdio *bus, uint len) } /* return total length of buffer chain */ -static uint brcmf_sdbrcm_glom_len(struct brcmf_sdio *bus) +static uint brcmf_sdbrcm_glom_len(struct brcmf_bus *bus) { struct sk_buff *p; uint total; @@ -1106,7 +1104,7 @@ static uint brcmf_sdbrcm_glom_len(struct brcmf_sdio *bus) return total; } -static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) +static void brcmf_sdbrcm_free_glom(struct brcmf_bus *bus) { struct sk_buff *cur, *next; @@ -1116,13 +1114,13 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) } } -static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) +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, *pnext; + struct sk_buff *pfirst, *plast, *pnext, *save_pfirst; int errcode; u8 chan, seq, doff, sfdoff; @@ -1139,7 +1137,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) /* If there's a descriptor, generate the packet chain */ if (bus->glomd) { - pfirst = pnext = NULL; + pfirst = plast = pnext = NULL; dlen = (u16) (bus->glomd->len); dptr = bus->glomd->data; if (!dlen || (dlen & 1)) { @@ -1230,14 +1228,17 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) * packet and and copy into the chain. */ if (usechain) { - errcode = brcmf_sdcard_recv_chain(bus->sdiodev, + errcode = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, - SDIO_FUNC_2, F2SYNC, &bus->glom); + 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); + SDIO_FUNC_2, + F2SYNC, bus->dataptr, dlen, + NULL); sublen = (u16) brcmf_sdbrcm_glom_from_buf(bus, dlen); if (sublen != dlen) { brcmf_dbg(ERROR, "FAILED TO COPY, dlen %d sublen %d\n", @@ -1337,14 +1338,10 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) /* Remove superframe header, remember offset */ skb_pull(pfirst, doff); sfdoff = doff; - num = 0; /* Validate all the subframe headers */ - skb_queue_walk(&bus->glom, pnext) { - /* leave when invalid subframe is found */ - if (errcode) - break; - + for (num = 0, pnext = pfirst; pnext && !errcode; + num++, pnext = pnext->next) { dptr = (u8 *) (pnext->data); dlen = (u16) (pnext->len); sublen = get_unaligned_le16(dptr); @@ -1377,8 +1374,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) num, doff, sublen, SDPCM_HDRLEN); errcode = -1; } - /* increase the subframe count */ - num++; } if (errcode) { @@ -1399,8 +1394,13 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) } /* Basic SD framing looks ok - process each packet (header) */ + save_pfirst = pfirst; + plast = NULL; + + for (num = 0; pfirst; rxseq++, pfirst = pnext) { + pnext = pfirst->next; + pfirst->next = NULL; - skb_queue_walk_safe(&bus->glom, pfirst, pnext) { dptr = (u8 *) (pfirst->data); sublen = get_unaligned_le16(dptr); chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); @@ -1420,8 +1420,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) bus->rx_badseq++; rxseq = seq; } - rxseq++; - #ifdef BCMDBG if (BRCMF_BYTES_ON() && BRCMF_DATA_ON()) { printk(KERN_DEBUG "Rx Subframe Data:\n"); @@ -1434,22 +1432,36 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) skb_pull(pfirst, doff); if (pfirst->len == 0) { - skb_unlink(pfirst, &bus->glom); 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++; - skb_unlink(pfirst, &bus->glom); 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", - bus->glom.qlen, pfirst, pfirst->data, + num, pfirst, pfirst->data, pfirst->len, pfirst->next, pfirst->prev); print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, @@ -1458,20 +1470,19 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) } #endif /* BCMDBG */ } - /* sent any remaining packets up */ - if (bus->glom.qlen) { + if (num) { up(&bus->sdsem); - brcmf_rx_frame(bus->drvr, ifidx, &bus->glom); + brcmf_rx_frame(bus->drvr, ifidx, save_pfirst, num); down(&bus->sdsem); } bus->rxglomframes++; - bus->rxglompkts += bus->glom.qlen; + bus->rxglompkts += num; } return num; } -static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_sdio *bus, uint *condition, +static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_bus *bus, uint *condition, bool *pending) { DECLARE_WAITQUEUE(wait, current); @@ -1493,7 +1504,7 @@ static int brcmf_sdbrcm_dcmd_resp_wait(struct brcmf_sdio *bus, uint *condition, return timeout; } -static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_sdio *bus) +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); @@ -1501,7 +1512,7 @@ static int brcmf_sdbrcm_dcmd_resp_wake(struct brcmf_sdio *bus) return 0; } static void -brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) +brcmf_sdbrcm_read_control(struct brcmf_bus *bus, u8 *hdr, uint len, uint doff) { uint rdlen, pad; @@ -1559,7 +1570,8 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, SDIO_FUNC_2, - F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen); + F2SYNC, (bus->rxctl + BRCMF_FIRSTREAD), rdlen, + NULL); bus->f2rxdata++; /* Control frame failures need retransmission */ @@ -1590,7 +1602,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) } /* Pad read to blocksize for efficiency */ -static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen) +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); @@ -1603,7 +1615,7 @@ static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen) } static void -brcmf_alloc_pkt_and_read(struct brcmf_sdio *bus, u16 rdlen, +brcmf_alloc_pkt_and_read(struct brcmf_bus *bus, u16 rdlen, struct sk_buff **pkt, u8 **rxbuf) { int sdret; /* Return code from calls */ @@ -1615,8 +1627,9 @@ brcmf_alloc_pkt_and_read(struct brcmf_sdio *bus, u16 rdlen, pkt_align(*pkt, rdlen, BRCMF_SDALIGN); *rxbuf = (u8 *) ((*pkt)->data); /* Read the entire frame */ - sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, - SDIO_FUNC_2, F2SYNC, *pkt); + sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, + SDIO_FUNC_2, F2SYNC, + *rxbuf, rdlen, *pkt); bus->f2rxdata++; if (sdret < 0) { @@ -1635,7 +1648,7 @@ brcmf_alloc_pkt_and_read(struct brcmf_sdio *bus, u16 rdlen, /* Checks the header */ static int -brcmf_check_rxbuf(struct brcmf_sdio *bus, struct sk_buff *pkt, u8 *rxbuf, +brcmf_check_rxbuf(struct brcmf_bus *bus, struct sk_buff *pkt, u8 *rxbuf, u8 rxseq, u16 nextlen, u16 *len) { u16 check; @@ -1691,7 +1704,7 @@ brcmf_check_rxbuf(struct brcmf_sdio *bus, struct sk_buff *pkt, u8 *rxbuf, /* Return true if there may be more frames to read */ static uint -brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) +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 */ @@ -1714,8 +1727,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) *finished = false; for (rxseq = bus->rx_seq, rxleft = maxframes; - !bus->rxskip && rxleft && - bus->drvr->bus_if->state != BRCMF_BUS_DOWN; + !bus->rxskip && rxleft && bus->drvr->busstate != BRCMF_BUS_DOWN; rxseq++, rxleft--) { /* Handle glomming separately */ @@ -1845,7 +1857,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) /* Read frame header (hardware and software) */ sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, SDIO_FUNC_2, F2SYNC, bus->rxhdr, - BRCMF_FIRSTREAD); + BRCMF_FIRSTREAD, NULL); bus->f2rxhdrs++; if (sdret < 0) { @@ -1994,8 +2006,9 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) pkt_align(pkt, rdlen, BRCMF_SDALIGN); /* Read the remaining frame data */ - sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad, - SDIO_FUNC_2, F2SYNC, pkt); + sdret = brcmf_sdcard_recv_buf(bus->sdiodev, bus->sdiodev->sbwad, + SDIO_FUNC_2, F2SYNC, ((u8 *) (pkt->data)), + rdlen, pkt); bus->f2rxdata++; if (sdret < 0) { @@ -2062,7 +2075,7 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) /* Unlock during rx call */ up(&bus->sdsem); - brcmf_rx_packet(bus->drvr, ifidx, pkt); + brcmf_rx_frame(bus->drvr, ifidx, pkt, 1); down(&bus->sdsem); } rxcount = maxframes - rxleft; @@ -2082,8 +2095,16 @@ brcmf_sdbrcm_readframes(struct brcmf_sdio *bus, uint maxframes, bool *finished) 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_sdio *bus, bool *lockvar) +brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar) { up(&bus->sdsem); wait_event_interruptible_timeout(bus->ctrl_wait, @@ -2093,7 +2114,7 @@ brcmf_sdbrcm_wait_for_event(struct brcmf_sdio *bus, bool *lockvar) } static void -brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) +brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus) { if (waitqueue_active(&bus->ctrl_wait)) wake_up_interruptible(&bus->ctrl_wait); @@ -2102,7 +2123,7 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus) /* 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_sdio *bus, struct sk_buff *pkt, +static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, uint chan, bool free_pkt) { int ret; @@ -2191,8 +2212,9 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, if (len & (ALIGNMENT - 1)) len = roundup(len, ALIGNMENT); - ret = brcmf_sdcard_send_pkt(bus->sdiodev, bus->sdiodev->sbwad, - SDIO_FUNC_2, F2SYNC, pkt); + ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad, + SDIO_FUNC_2, F2SYNC, frame, + len, pkt); bus->f2txdata++; if (ret < 0) { @@ -2239,7 +2261,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, return ret; } -static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) +static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes) { struct sk_buff *pkt; u32 intstatus = 0; @@ -2287,14 +2309,14 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) } /* Deflow-control stack if needed */ - if (drvr->up && (drvr->bus_if->state == BRCMF_BUS_DATA) && + 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_sdio *bus) +static bool brcmf_sdbrcm_dpc(struct brcmf_bus *bus) { u32 intstatus, newstatus = 0; uint retries = 0; @@ -2322,7 +2344,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) SBSDIO_DEVICE_CTL, &err); if (err) { brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err); - bus->drvr->bus_if->state = BRCMF_BUS_DOWN; + bus->drvr->busstate = BRCMF_BUS_DOWN; } #endif /* BCMDBG */ @@ -2332,7 +2354,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) if (err) { brcmf_dbg(ERROR, "error reading CSR: %d\n", err); - bus->drvr->bus_if->state = BRCMF_BUS_DOWN; + bus->drvr->busstate = BRCMF_BUS_DOWN; } brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", @@ -2345,7 +2367,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) if (err) { brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err); - bus->drvr->bus_if->state = BRCMF_BUS_DOWN; + bus->drvr->busstate = BRCMF_BUS_DOWN; } devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, @@ -2353,7 +2375,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) if (err) { brcmf_dbg(ERROR, "error writing DEVCTL: %d\n", err); - bus->drvr->bus_if->state = BRCMF_BUS_DOWN; + bus->drvr->busstate = BRCMF_BUS_DOWN; } bus->clkstate = CLK_AVAIL; } else { @@ -2455,9 +2477,9 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) (bus->clkstate == CLK_AVAIL)) { int ret, i; - ret = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad, + ret = brcmf_sdbrcm_send_buf(bus, bus->sdiodev->sbwad, SDIO_FUNC_2, F2SYNC, (u8 *) bus->ctrl_frame_buf, - (u32) bus->ctrl_frame_len); + (u32) bus->ctrl_frame_len, NULL); if (ret < 0) { /* On failure, abort the command and @@ -2509,11 +2531,11 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) else await next interrupt */ /* On failed register access, all bets are off: no resched or interrupts */ - if ((bus->drvr->bus_if->state == BRCMF_BUS_DOWN) || + 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->bus_if->state = BRCMF_BUS_DOWN; + 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"); @@ -2540,7 +2562,7 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) static int brcmf_sdbrcm_dpc_thread(void *data) { - struct brcmf_sdio *bus = (struct brcmf_sdio *) data; + struct brcmf_bus *bus = (struct brcmf_bus *) data; allow_signal(SIGTERM); /* Run until signal received */ @@ -2550,12 +2572,12 @@ static int brcmf_sdbrcm_dpc_thread(void *data) if (!wait_for_completion_interruptible(&bus->dpc_wait)) { /* Call bus dpc unless it indicated down (then clean stop) */ - if (bus->drvr->bus_if->state != BRCMF_BUS_DOWN) { + 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->sdiodev->dev); + brcmf_sdbrcm_bus_stop(bus); bus->dpc_tsk = NULL; break; } @@ -2565,13 +2587,10 @@ static int brcmf_sdbrcm_dpc_thread(void *data) return 0; } -int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) +int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt) { int ret = -EBADE; uint datalen, prec; - struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; - struct brcmf_sdio *bus = sdiodev->bus; brcmf_dbg(TRACE, "Enter\n"); @@ -2619,7 +2638,7 @@ int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) } static int -brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data, +brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data, uint size) { int bcmerror = 0; @@ -2680,7 +2699,7 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data, #ifdef BCMDBG #define CONSOLE_LINE_MAX 192 -static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus) +static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus) { struct brcmf_console *c = &bus->console; u8 line[CONSOLE_LINE_MAX], ch; @@ -2757,14 +2776,14 @@ static int brcmf_sdbrcm_readconsole(struct brcmf_sdio *bus) } #endif /* BCMDBG */ -static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) +static int brcmf_tx_frame(struct brcmf_bus *bus, u8 *frame, u16 len) { int i; int ret; bus->ctrl_frame_stat = false; - ret = brcmf_sdcard_send_buf(bus->sdiodev, bus->sdiodev->sbwad, - SDIO_FUNC_2, F2SYNC, frame, len); + 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 */ @@ -2800,7 +2819,7 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) } int -brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) +brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) { u8 *frame; u16 len; @@ -2808,9 +2827,6 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) uint retries = 0; u8 doff = 0; int ret = -1; - struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; - struct brcmf_sdio *bus = sdiodev->bus; brcmf_dbg(TRACE, "Enter\n"); @@ -2918,14 +2934,11 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) } int -brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) +brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) { int timeleft; uint rxlen = 0; bool pending; - struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; - struct brcmf_sdio *bus = sdiodev->bus; brcmf_dbg(TRACE, "Enter\n"); @@ -2958,7 +2971,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) return rxlen ? (int)rxlen : -ETIMEDOUT; } -static int brcmf_sdbrcm_downloadvars(struct brcmf_sdio *bus, void *arg, int len) +static int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len) { int bcmerror = 0; @@ -2991,7 +3004,7 @@ static int brcmf_sdbrcm_downloadvars(struct brcmf_sdio *bus, void *arg, int len) return bcmerror; } -static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) +static int brcmf_sdbrcm_write_vars(struct brcmf_bus *bus) { int bcmerror = 0; u32 varsize; @@ -3078,7 +3091,7 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) return bcmerror; } -static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) +static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter) { uint retries; int bcmerror = 0; @@ -3121,13 +3134,13 @@ static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) /* Allow HT Clock now that the ARM is running. */ bus->alp_only = false; - bus->drvr->bus_if->state = BRCMF_BUS_LOAD; + bus->drvr->busstate = BRCMF_BUS_LOAD; } fail: return bcmerror; } -static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus) +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; @@ -3137,7 +3150,10 @@ static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_sdio *bus) return len; } -static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) +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; @@ -3146,7 +3162,8 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) brcmf_dbg(INFO, "Enter\n"); - ret = request_firmware(&bus->firmware, BRCMFMAC_FW_NAME, + 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); @@ -3236,14 +3253,15 @@ static uint brcmf_process_nvram_vars(char *varbuf, uint len) return buf_len; } -static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus) +static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus) { uint len; char *memblock = NULL; char *bufp; int ret; - ret = request_firmware(&bus->firmware, BRCMFMAC_NV_NAME, + 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); @@ -3283,7 +3301,7 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus) return ret; } -static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) +static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus) { int bcmerror = -1; @@ -3316,7 +3334,7 @@ static int _brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) } static bool -brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) +brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus) { bool ret; @@ -3330,15 +3348,12 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) return ret; } -void brcmf_sdbrcm_bus_stop(struct device *dev) +void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus) { u32 local_hostintmask; u8 saveclk; uint retries; int err; - struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; - struct brcmf_sdio *bus = sdiodev->bus; brcmf_dbg(TRACE, "Enter\n"); @@ -3367,7 +3382,7 @@ void brcmf_sdbrcm_bus_stop(struct device *dev) bus->hostintmask = 0; /* Change our idea of bus state */ - bus->drvr->bus_if->state = BRCMF_BUS_DOWN; + 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, @@ -3411,11 +3426,9 @@ void brcmf_sdbrcm_bus_stop(struct device *dev) up(&bus->sdsem); } -int brcmf_sdbrcm_bus_init(struct device *dev) +int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr) { - struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; - struct brcmf_sdio *bus = sdiodev->bus; + struct brcmf_bus *bus = drvr->bus; unsigned long timeout; uint retries = 0; u8 ready, enable; @@ -3425,7 +3438,7 @@ int brcmf_sdbrcm_bus_init(struct device *dev) brcmf_dbg(TRACE, "Enter\n"); /* try to download image and nvram to the dongle */ - if (bus_if->state == BRCMF_BUS_DOWN) { + if (drvr->busstate == BRCMF_BUS_DOWN) { if (!(brcmf_sdbrcm_download_firmware(bus))) return -1; } @@ -3491,7 +3504,7 @@ int brcmf_sdbrcm_bus_init(struct device *dev) SBSDIO_WATERMARK, 8, &err); /* Set bus state according to enable result */ - bus_if->state = BRCMF_BUS_DATA; + drvr->busstate = BRCMF_BUS_DATA; } else { @@ -3506,7 +3519,7 @@ int brcmf_sdbrcm_bus_init(struct device *dev) SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); /* If we didn't come up, turn off backplane clock */ - if (bus_if->state != BRCMF_BUS_DATA) + if (drvr->busstate != BRCMF_BUS_DATA) brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); exit: @@ -3517,7 +3530,7 @@ int brcmf_sdbrcm_bus_init(struct device *dev) void brcmf_sdbrcm_isr(void *arg) { - struct brcmf_sdio *bus = (struct brcmf_sdio *) arg; + struct brcmf_bus *bus = (struct brcmf_bus *) arg; brcmf_dbg(TRACE, "Enter\n"); @@ -3526,7 +3539,7 @@ void brcmf_sdbrcm_isr(void *arg) return; } - if (bus->drvr->bus_if->state == BRCMF_BUS_DOWN) { + if (bus->drvr->busstate == BRCMF_BUS_DOWN) { brcmf_dbg(ERROR, "bus is down. we have nothing to do\n"); return; } @@ -3549,14 +3562,14 @@ void brcmf_sdbrcm_isr(void *arg) complete(&bus->dpc_wait); } -static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) +static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_pub *drvr) { -#ifdef BCMDBG - struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev); -#endif /* BCMDBG */ + struct brcmf_bus *bus; brcmf_dbg(TIMER, "Enter\n"); + bus = drvr->bus; + /* Ignore the timer if simulating bus down */ if (bus->sleeping) return false; @@ -3600,8 +3613,7 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) } #ifdef BCMDBG /* Poll for console output periodically */ - if (bus_if->state == BRCMF_BUS_DATA && - bus->console_interval != 0) { + 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; @@ -3639,7 +3651,7 @@ static bool brcmf_sdbrcm_chipmatch(u16 chipid) return false; } -static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) +static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus) { brcmf_dbg(TRACE, "Enter\n"); @@ -3651,7 +3663,7 @@ static void brcmf_sdbrcm_release_malloc(struct brcmf_sdio *bus) bus->databuf = NULL; } -static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus) +static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus) { brcmf_dbg(TRACE, "Enter\n"); @@ -3687,7 +3699,7 @@ static bool brcmf_sdbrcm_probe_malloc(struct brcmf_sdio *bus) } static bool -brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) +brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, u32 regsva) { u8 clkctl = 0; int err = 0; @@ -3772,7 +3784,7 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) return false; } -static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) +static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus) { brcmf_dbg(TRACE, "Enter\n"); @@ -3780,7 +3792,7 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, SDIO_FUNC_ENABLE_1, NULL); - bus->drvr->bus_if->state = BRCMF_BUS_DOWN; + bus->drvr->busstate = BRCMF_BUS_DOWN; bus->sleeping = false; bus->rxflow = false; @@ -3807,7 +3819,7 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) static int brcmf_sdbrcm_watchdog_thread(void *data) { - struct brcmf_sdio *bus = (struct brcmf_sdio *)data; + struct brcmf_bus *bus = (struct brcmf_bus *)data; allow_signal(SIGTERM); /* Run until signal received */ @@ -3815,7 +3827,7 @@ brcmf_sdbrcm_watchdog_thread(void *data) if (kthread_should_stop()) break; if (!wait_for_completion_interruptible(&bus->watchdog_wait)) { - brcmf_sdbrcm_bus_watchdog(bus); + brcmf_sdbrcm_bus_watchdog(bus->drvr); /* Count the tick for reference */ bus->drvr->tickcnt++; } else @@ -3827,7 +3839,7 @@ brcmf_sdbrcm_watchdog_thread(void *data) static void brcmf_sdbrcm_watchdog(unsigned long data) { - struct brcmf_sdio *bus = (struct brcmf_sdio *)data; + struct brcmf_bus *bus = (struct brcmf_bus *)data; if (bus->watchdog_tsk) { complete(&bus->watchdog_wait); @@ -3838,7 +3850,7 @@ brcmf_sdbrcm_watchdog(unsigned long data) } } -static void brcmf_sdbrcm_release_dongle(struct brcmf_sdio *bus) +static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus) { brcmf_dbg(TRACE, "Enter\n"); @@ -3855,7 +3867,7 @@ static void brcmf_sdbrcm_release_dongle(struct brcmf_sdio *bus) } /* Detach and free everything */ -static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) +static void brcmf_sdbrcm_release(struct brcmf_bus *bus) { brcmf_dbg(TRACE, "Enter\n"); @@ -3877,10 +3889,21 @@ static void brcmf_sdbrcm_release(struct brcmf_sdio *bus) brcmf_dbg(TRACE, "Disconnected\n"); } -void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) +void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype, + u32 regsva, struct brcmf_sdio_dev *sdiodev) { int ret; - struct brcmf_sdio *bus; + 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"); @@ -3888,7 +3911,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) * regsva == SI_ENUM_BASE*/ /* Allocate private bus interface state */ - bus = kzalloc(sizeof(struct brcmf_sdio), GFP_ATOMIC); + bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC); if (!bus) goto fail; @@ -3940,7 +3963,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) } /* Attach to the brcmf/OS/network interface */ - bus->drvr = brcmf_attach(bus, SDPCM_RESERVE, bus->sdiodev->dev); + bus->drvr = brcmf_attach(bus, SDPCM_RESERVE); if (!bus->drvr) { brcmf_dbg(ERROR, "brcmf_attach failed\n"); goto fail; @@ -3992,7 +4015,7 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) void brcmf_sdbrcm_disconnect(void *ptr) { - struct brcmf_sdio *bus = (struct brcmf_sdio *)ptr; + struct brcmf_bus *bus = (struct brcmf_bus *)ptr; brcmf_dbg(TRACE, "Enter\n"); @@ -4002,8 +4025,13 @@ void brcmf_sdbrcm_disconnect(void *ptr) 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_sdio *bus, uint wdtick) +brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick) { /* Totally stop the timer */ if (!wdtick && bus->wd_timer_valid == true) { @@ -4014,7 +4042,7 @@ brcmf_sdbrcm_wd_timer(struct brcmf_sdio *bus, uint wdtick) } /* don't start the wd until fw is loaded */ - if (bus->drvr->bus_if->state == BRCMF_BUS_DOWN) + if (bus->drvr->busstate == BRCMF_BUS_DOWN) return; if (wdtick) { diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index c4c2543438ec..726fa8981113 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h @@ -132,9 +132,9 @@ struct brcmf_sdio_dev { atomic_t suspend; /* suspend flag */ wait_queue_head_t request_byte_wait; wait_queue_head_t request_word_wait; - wait_queue_head_t request_chain_wait; + wait_queue_head_t request_packet_wait; wait_queue_head_t request_buffer_wait; - struct device *dev; + }; /* Register/deregister device interrupt handler. */ @@ -182,21 +182,11 @@ extern bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev); * NOTE: Async operation is not currently supported. */ extern int -brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, - uint flags, struct sk_buff *pkt); -extern int brcmf_sdcard_send_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, - uint flags, u8 *buf, uint nbytes); - -extern int -brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, - uint flags, struct sk_buff *pkt); + 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); -extern int -brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn, - uint flags, struct sk_buff_head *pktq); + uint flags, u8 *buf, uint nbytes, struct sk_buff *pkt); /* Flags bits */ @@ -247,18 +237,16 @@ brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev, /* 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, - struct sk_buff *pkt); -extern int -brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc, - uint write, uint func, uint addr, - struct sk_buff_head *pktq); + 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(u32 regsva, struct brcmf_sdio_dev *sdiodev); +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 --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index f23b0c3e4ea3..cc19a733ac65 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -1429,7 +1429,7 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, static s32 brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, - enum nl80211_tx_power_setting type, s32 mbm) + enum nl80211_tx_power_setting type, s32 dbm) { struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); @@ -1437,7 +1437,6 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, u16 txpwrmw; s32 err = 0; s32 disable = 0; - s32 dbm = MBM_TO_DBM(mbm); WL_TRACE("Enter\n"); if (!check_sys_up(wiphy)) @@ -1447,6 +1446,12 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, 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"); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.c index b55b1f6bb4ba..0bb8c37e979e 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/dma.c @@ -1239,9 +1239,10 @@ bool dma_rxreset(struct dma_pub *pub) * 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 *p, bool commit) +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; @@ -1253,37 +1254,50 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit) txout = di->txout; /* - * obtain and initialize transmit descriptor entry. + * Walk the chain of packet buffers + * allocating and initializing transmit descriptor entries. */ - data = p->data; - len = p->len; + for (p = p0; p; p = next) { + data = p->data; + len = p->len; + next = p->next; - /* no use to transmit a zero length packet */ - if (len == 0) - return 0; + /* return nonzero if out of tx descriptors */ + if (nexttxd(di, txout) == di->txin) + goto outoftxd; - /* 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); + /* get physical address of buffer start */ + pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE); - /* 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. - */ - flags = D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF; - if (txout == (di->ntxd - 1)) - flags |= D64_CTRL1_EOT; + flags = 0; + if (p == p0) + flags |= D64_CTRL1_SOF; - dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); + /* 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); + } - 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)] = p; + di->txp[prevtxd(di, txout)] = p0; /* bump the tx descriptor index */ di->txout = txout; @@ -1300,7 +1314,7 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit) outoftxd: DMA_ERROR("%s: out of txds !!!\n", di->name); - brcmu_pkt_buf_free_skb(p); + brcmu_pkt_buf_free_skb(p0); di->dma.txavail = 0; di->dma.txnobuf++; return -1; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 76376eb112fe..ba3e4b5cba71 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -40,10 +40,10 @@ #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \ FIF_ALLMULTI | \ FIF_FCSFAIL | \ + FIF_PLCPFAIL | \ FIF_CONTROL | \ FIF_OTHER_BSS | \ - FIF_BCN_PRBRESP_PROMISC | \ - FIF_PSPOLL) + FIF_BCN_PRBRESP_PROMISC) #define CHAN2GHZ(channel, freqency, chflags) { \ .band = IEEE80211_BAND_2GHZ, \ @@ -373,7 +373,7 @@ static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed) conf->listen_interval); } if (changed & IEEE80211_CONF_CHANGE_MONITOR) - wiphy_dbg(wiphy, "%s: change monitor mode: %s\n", + wiphy_err(wiphy, "%s: change monitor mode: %s (implement)\n", __func__, conf->flags & IEEE80211_CONF_MONITOR ? "true" : "false"); if (changed & IEEE80211_CONF_CHANGE_PS) @@ -550,25 +550,29 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw, changed_flags &= MAC_FILTERS; *total_flags &= MAC_FILTERS; - if (changed_flags & FIF_PROMISC_IN_BSS) - wiphy_dbg(wiphy, "FIF_PROMISC_IN_BSS\n"); + wiphy_err(wiphy, "FIF_PROMISC_IN_BSS\n"); if (changed_flags & FIF_ALLMULTI) - wiphy_dbg(wiphy, "FIF_ALLMULTI\n"); + wiphy_err(wiphy, "FIF_ALLMULTI\n"); if (changed_flags & FIF_FCSFAIL) - wiphy_dbg(wiphy, "FIF_FCSFAIL\n"); + wiphy_err(wiphy, "FIF_FCSFAIL\n"); + if (changed_flags & FIF_PLCPFAIL) + wiphy_err(wiphy, "FIF_PLCPFAIL\n"); if (changed_flags & FIF_CONTROL) - wiphy_dbg(wiphy, "FIF_CONTROL\n"); + wiphy_err(wiphy, "FIF_CONTROL\n"); if (changed_flags & FIF_OTHER_BSS) - wiphy_dbg(wiphy, "FIF_OTHER_BSS\n"); - if (changed_flags & FIF_PSPOLL) - wiphy_dbg(wiphy, "FIF_PSPOLL\n"); - if (changed_flags & FIF_BCN_PRBRESP_PROMISC) - wiphy_dbg(wiphy, "FIF_BCN_PRBRESP_PROMISC\n"); - - spin_lock_bh(&wl->lock); - brcms_c_mac_promisc(wl->wlc, *total_flags); - spin_unlock_bh(&wl->lock); + 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; } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c index 87f8f5d3d91f..36e3e0638300 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -955,6 +955,8 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) 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); @@ -3062,7 +3064,7 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) return false; /* disallow PS when one of these meets when not scanning */ - if (wlc->filter_flags & FIF_PROMISC_IN_BSS) + if (wlc->monitor) return false; if (cfg->associated) { @@ -3582,31 +3584,29 @@ static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc, } /* - * Set or clear filtering related maccontrol bits based on - * specified filter flags + * Set or clear maccontrol bits MCTL_PROMISC, MCTL_BCNS_PROMISC and + * MCTL_KEEPCONTROL */ -void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags) +static void brcms_c_mac_promisc(struct brcms_c_info *wlc) { u32 promisc_bits = 0; - wlc->filter_flags = filter_flags; - - if (filter_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) - promisc_bits |= MCTL_PROMISC; - - if (filter_flags & FIF_BCN_PRBRESP_PROMISC) + if (wlc->bcnmisc_monitor) promisc_bits |= MCTL_BCNS_PROMISC; - if (filter_flags & FIF_FCSFAIL) - promisc_bits |= MCTL_KEEPBADFCS; - - if (filter_flags & (FIF_CONTROL | FIF_PSPOLL)) - promisc_bits |= MCTL_KEEPCONTROL; + if (wlc->monitor) + promisc_bits |= + MCTL_PROMISC | MCTL_BCNS_PROMISC | MCTL_KEEPCONTROL; brcms_b_mctrl(wlc->hw, - MCTL_PROMISC | MCTL_BCNS_PROMISC | - MCTL_KEEPCONTROL | MCTL_KEEPBADFCS, - promisc_bits); + MCTL_PROMISC | MCTL_BCNS_PROMISC | MCTL_KEEPCONTROL, + promisc_bits); +} + +void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, bool promisc) +{ + wlc->bcnmisc_monitor = promisc; + brcms_c_mac_promisc(wlc); } /* @@ -3636,6 +3636,9 @@ static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc) } else { /* disable an active IBSS if we are not on the home channel */ } + + /* update the various promisc bits */ + brcms_c_mac_promisc(wlc); } static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate, @@ -8071,8 +8074,14 @@ static void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p) len = p->len; if (rxh->RxStatus1 & RXS_FCSERR) { - if (!(wlc->filter_flags & FIF_FCSFAIL)) + 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 */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.h index e2de97d93635..251c350b3164 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.h @@ -519,7 +519,8 @@ struct brcms_c_info { struct brcms_timer *radio_timer; /* promiscuous */ - uint filter_flags; + bool monitor; + bool bcnmisc_monitor; /* driver feature */ bool _rifs; @@ -657,7 +658,8 @@ extern void brcms_c_print_txdesc(struct d11txh *txh); #endif extern int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config); -extern void brcms_c_mac_promisc(struct brcms_c_info *wlc, uint filter_flags); +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); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c index 008aab9c777c..e17edf7e6833 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c @@ -109,7 +109,7 @@ static const struct chan_info_basic chan_info_all[] = { {204, 5020}, {208, 5040}, {212, 5060}, - {216, 5080} + {216, 50800} }; static const u8 ofdm_rate_lookup[] = { diff --git a/trunk/drivers/net/wireless/hostap/hostap_cs.c b/trunk/drivers/net/wireless/hostap/hostap_cs.c index 89e9d3a78c3c..5441ad195119 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_cs.c +++ b/trunk/drivers/net/wireless/hostap/hostap_cs.c @@ -655,9 +655,6 @@ static const struct pcmcia_device_id hostap_cs_ids[] = { PCMCIA_DEVICE_PROD_ID123( "Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", 0xe6ec52ce, 0x08649af2, 0x4b74baa0), - PCMCIA_DEVICE_PROD_ID123( - "Canon", "Wireless LAN CF Card K30225", "Version 01.00", - 0x96ef6fe2, 0x263fcbab, 0xa57adb8c), PCMCIA_DEVICE_PROD_ID123( "D", "Link DWL-650 11Mbps WLAN Card", "Version 01.02", 0x71b18589, 0xb6f1b0ab, 0x4b74baa0), diff --git a/trunk/drivers/net/wireless/iwlegacy/common.c b/trunk/drivers/net/wireless/iwlegacy/common.c index 881ba043770a..7e2924f332a7 100644 --- a/trunk/drivers/net/wireless/iwlegacy/common.c +++ b/trunk/drivers/net/wireless/iwlegacy/common.c @@ -2786,8 +2786,9 @@ il_tx_queue_alloc(struct il_priv *il, struct il_tx_queue *txq, u32 id) /* Driver ilate data, only for Tx (not command) queues, * not shared with device. */ if (id != il->cmd_queue) { - txq->txb = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(txq->txb[0]), - GFP_KERNEL); + txq->txb = + kzalloc(sizeof(txq->txb[0]) * TFD_QUEUE_SIZE_MAX, + GFP_KERNEL); if (!txq->txb) { IL_ERR("kmalloc for auxiliary BD " "structures failed\n"); diff --git a/trunk/drivers/net/wireless/iwlwifi/Makefile b/trunk/drivers/net/wireless/iwlwifi/Makefile index 86344cefd32f..a7ab280994c8 100644 --- a/trunk/drivers/net/wireless/iwlwifi/Makefile +++ b/trunk/drivers/net/wireless/iwlwifi/Makefile @@ -1,7 +1,7 @@ # WIFI obj-$(CONFIG_IWLWIFI) += iwlwifi.o iwlwifi-objs := iwl-agn.o iwl-agn-rs.o iwl-mac80211.o -iwlwifi-objs += iwl-ucode.o iwl-agn-tx.o +iwlwifi-objs += iwl-agn-ucode.o iwl-agn-tx.o iwlwifi-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o iwlwifi-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-rx.o @@ -18,7 +18,7 @@ iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o -iwlwifi-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-testmode.o +iwlwifi-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-sv-open.o CFLAGS_iwl-devtrace.o := -I$(src) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c index 8d3bad7ea5d3..e12b48c2cff6 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -147,7 +147,16 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) iwl1000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ + /* Set initial calibration set */ hw_params(priv).sens = &iwl1000_sensitivity; + hw_params(priv).calib_init_cfg = + BIT(IWL_CALIB_XTAL) | + BIT(IWL_CALIB_LO) | + BIT(IWL_CALIB_TX_IQ) | + BIT(IWL_CALIB_TX_IQ_PERD) | + BIT(IWL_CALIB_BASE_BAND); + if (priv->cfg->need_dc_calib) + hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC); return 0; } @@ -182,7 +191,6 @@ static struct iwl_base_params iwl1000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 128, - .wd_disable = true, }; static struct iwl_ht_params iwl1000_ht_params = { .ht_greenfield_support = true, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c index 0c4688d95b65..b3193571ed07 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -143,7 +143,17 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) iwl2000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ + /* Set initial calibration set */ hw_params(priv).sens = &iwl2000_sensitivity; + hw_params(priv).calib_init_cfg = + BIT(IWL_CALIB_XTAL) | + BIT(IWL_CALIB_LO) | + BIT(IWL_CALIB_TX_IQ) | + BIT(IWL_CALIB_BASE_BAND); + if (priv->cfg->need_dc_calib) + hw_params(priv).calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; + if (priv->cfg->need_temp_offset_calib) + hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); return 0; } @@ -248,6 +258,7 @@ static struct iwl_bt_params iwl2030_bt_params = { .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .lib = &iwl2000_lib, \ .base_params = &iwl2000_base_params, \ + .need_dc_calib = true, \ .need_temp_offset_calib = true, \ .temp_offset_v2 = true, \ .led_mode = IWL_LED_RF_STATE, \ @@ -275,6 +286,7 @@ struct iwl_cfg iwl2000_2bgn_d_cfg = { .lib = &iwl2030_lib, \ .base_params = &iwl2030_base_params, \ .bt_params = &iwl2030_bt_params, \ + .need_dc_calib = true, \ .need_temp_offset_calib = true, \ .temp_offset_v2 = true, \ .led_mode = IWL_LED_RF_STATE, \ @@ -296,6 +308,7 @@ struct iwl_cfg iwl2030_2bgn_cfg = { .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ .lib = &iwl2000_lib, \ .base_params = &iwl2000_base_params, \ + .need_dc_calib = true, \ .need_temp_offset_calib = true, \ .temp_offset_v2 = true, \ .led_mode = IWL_LED_RF_STATE, \ @@ -325,6 +338,7 @@ struct iwl_cfg iwl105_bgn_d_cfg = { .lib = &iwl2030_lib, \ .base_params = &iwl2030_base_params, \ .bt_params = &iwl2030_bt_params, \ + .need_dc_calib = true, \ .need_temp_offset_calib = true, \ .temp_offset_v2 = true, \ .led_mode = IWL_LED_RF_STATE, \ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c index cf2fb47529b3..c511c98a89a8 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -186,7 +186,14 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) iwl5000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ + /* Set initial calibration set */ hw_params(priv).sens = &iwl5000_sensitivity; + hw_params(priv).calib_init_cfg = + BIT(IWL_CALIB_XTAL) | + BIT(IWL_CALIB_LO) | + BIT(IWL_CALIB_TX_IQ) | + BIT(IWL_CALIB_TX_IQ_PERD) | + BIT(IWL_CALIB_BASE_BAND); return 0; } @@ -215,7 +222,14 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) iwl5150_set_ct_threshold(priv); /* Set initial sensitivity parameters */ + /* Set initial calibration set */ hw_params(priv).sens = &iwl5150_sensitivity; + hw_params(priv).calib_init_cfg = + BIT(IWL_CALIB_LO) | + BIT(IWL_CALIB_TX_IQ) | + BIT(IWL_CALIB_BASE_BAND); + if (priv->cfg->need_dc_calib) + hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC); return 0; } @@ -350,7 +364,6 @@ static struct iwl_base_params iwl5000_base_params = { .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, .no_idle_support = true, - .wd_disable = true, }; static struct iwl_ht_params iwl5000_ht_params = { .ht_greenfield_support = true, @@ -420,7 +433,7 @@ struct iwl_cfg iwl5350_agn_cfg = { .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \ .lib = &iwl5150_lib, \ .base_params = &iwl5000_base_params, \ - .no_xtal_calib = true, \ + .need_dc_calib = true, \ .led_mode = IWL_LED_BLINK, \ .internal_wimax_coex = true diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c index 617ad1c0df61..ee3363fdf309 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -46,12 +46,11 @@ #include "iwl-cfg.h" /* Highest firmware API version supported */ -#define IWL6000_UCODE_API_MAX 6 +#define IWL6000_UCODE_API_MAX 4 #define IWL6050_UCODE_API_MAX 5 #define IWL6000G2_UCODE_API_MAX 6 /* Oldest version we won't warn about */ -#define IWL6000_UCODE_API_OK 4 #define IWL6000G2_UCODE_API_OK 5 /* Lowest firmware API version supported */ @@ -165,7 +164,17 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) iwl6000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ + /* Set initial calibration set */ hw_params(priv).sens = &iwl6000_sensitivity; + hw_params(priv).calib_init_cfg = + BIT(IWL_CALIB_XTAL) | + BIT(IWL_CALIB_LO) | + BIT(IWL_CALIB_TX_IQ) | + BIT(IWL_CALIB_BASE_BAND); + if (priv->cfg->need_dc_calib) + hw_params(priv).calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX; + if (priv->cfg->need_temp_offset_calib) + hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); return 0; } @@ -355,6 +364,7 @@ static struct iwl_bt_params iwl6000_bt_params = { .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ .lib = &iwl6000_lib, \ .base_params = &iwl6000_g2_base_params, \ + .need_dc_calib = true, \ .need_temp_offset_calib = true, \ .led_mode = IWL_LED_RF_STATE @@ -396,6 +406,7 @@ struct iwl_cfg iwl6005_2agn_d_cfg = { .lib = &iwl6030_lib, \ .base_params = &iwl6000_g2_base_params, \ .bt_params = &iwl6000_bt_params, \ + .need_dc_calib = true, \ .need_temp_offset_calib = true, \ .led_mode = IWL_LED_RF_STATE, \ .adv_pm = true \ @@ -458,7 +469,6 @@ struct iwl_cfg iwl130_bg_cfg = { #define IWL_DEVICE_6000i \ .fw_name_pre = IWL6000_FW_PRE, \ .ucode_api_max = IWL6000_UCODE_API_MAX, \ - .ucode_api_ok = IWL6000_UCODE_API_OK, \ .ucode_api_min = IWL6000_UCODE_API_MIN, \ .valid_tx_ant = ANT_BC, /* .cfg overwrite */ \ .valid_rx_ant = ANT_BC, /* .cfg overwrite */ \ @@ -496,6 +506,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { .eeprom_ver = EEPROM_6050_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \ .base_params = &iwl6050_base_params, \ + .need_dc_calib = true, \ .led_mode = IWL_LED_BLINK, \ .internal_wimax_coex = true @@ -519,6 +530,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { .eeprom_ver = EEPROM_6150_EEPROM_VERSION, \ .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, \ .base_params = &iwl6050_base_params, \ + .need_dc_calib = true, \ .led_mode = IWL_LED_BLINK, \ .internal_wimax_coex = true @@ -537,17 +549,17 @@ struct iwl_cfg iwl6000_3agn_cfg = { .name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN", .fw_name_pre = IWL6000_FW_PRE, .ucode_api_max = IWL6000_UCODE_API_MAX, - .ucode_api_ok = IWL6000_UCODE_API_OK, .ucode_api_min = IWL6000_UCODE_API_MIN, .eeprom_ver = EEPROM_6000_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, .lib = &iwl6000_lib, .base_params = &iwl6000_base_params, .ht_params = &iwl6000_ht_params, + .need_dc_calib = true, .led_mode = IWL_LED_BLINK, }; -MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_OK)); +MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 4d0210594956..03bac48558b2 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -84,62 +84,54 @@ struct statistics_general_data { int iwl_send_calib_results(struct iwl_priv *priv) { + int ret = 0; + int i = 0; + struct iwl_host_cmd hcmd = { .id = REPLY_PHY_CALIBRATION_CMD, .flags = CMD_SYNC, }; - struct iwl_calib_result *res; - - list_for_each_entry(res, &priv->calib_results, list) { - int ret; - - hcmd.len[0] = res->cmd_len; - hcmd.data[0] = &res->hdr; - hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; - ret = iwl_trans_send_cmd(trans(priv), &hcmd); - if (ret) { - IWL_ERR(priv, "Error %d on calib cmd %d\n", - ret, res->hdr.op_code); - return ret; + + for (i = 0; i < IWL_CALIB_MAX; i++) { + if ((BIT(i) & hw_params(priv).calib_init_cfg) && + priv->calib_results[i].buf) { + hcmd.len[0] = priv->calib_results[i].buf_len; + hcmd.data[0] = priv->calib_results[i].buf; + hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; + ret = iwl_trans_send_cmd(trans(priv), &hcmd); + if (ret) { + IWL_ERR(priv, "Error %d iteration %d\n", + ret, i); + break; + } } } - return 0; + return ret; } -int iwl_calib_set(struct iwl_priv *priv, - const struct iwl_calib_hdr *cmd, int len) +int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len) { - struct iwl_calib_result *res, *tmp; - - res = kmalloc(sizeof(*res) + len - sizeof(struct iwl_calib_hdr), - GFP_ATOMIC); - if (!res) - return -ENOMEM; - memcpy(&res->hdr, cmd, len); - res->cmd_len = len; - - list_for_each_entry(tmp, &priv->calib_results, list) { - if (tmp->hdr.op_code == res->hdr.op_code) { - list_replace(&tmp->list, &res->list); - kfree(tmp); - return 0; - } + if (res->buf_len != len) { + kfree(res->buf); + res->buf = kzalloc(len, GFP_ATOMIC); } + if (unlikely(res->buf == NULL)) + return -ENOMEM; - /* wasn't in list already */ - list_add_tail(&res->list, &priv->calib_results); - + res->buf_len = len; + memcpy(res->buf, buf, len); return 0; } void iwl_calib_free_results(struct iwl_priv *priv) { - struct iwl_calib_result *res, *tmp; + int i; - list_for_each_entry_safe(res, tmp, &priv->calib_results, list) { - list_del(&res->list); - kfree(res); + for (i = 0; i < IWL_CALIB_MAX; i++) { + kfree(priv->calib_results[i].buf); + priv->calib_results[i].buf = NULL; + priv->calib_results[i].buf_len = 0; } } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.h index 6ed806c8f80f..a869fc9205d2 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-calib.h @@ -73,8 +73,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv); void iwl_reset_run_time_calib(struct iwl_priv *priv); int iwl_send_calib_results(struct iwl_priv *priv); -int iwl_calib_set(struct iwl_priv *priv, - const struct iwl_calib_hdr *cmd, int len); +int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); void iwl_calib_free_results(struct iwl_priv *priv); #endif /* __iwl_calib_h__ */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 575d1bb8e8cc..0bc962217351 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -934,6 +934,57 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) return ant; } +/* notification wait support */ +void iwlagn_init_notification_wait(struct iwl_priv *priv, + struct iwl_notification_wait *wait_entry, + u8 cmd, + void (*fn)(struct iwl_priv *priv, + struct iwl_rx_packet *pkt, + void *data), + void *fn_data) +{ + wait_entry->fn = fn; + wait_entry->fn_data = fn_data; + wait_entry->cmd = cmd; + wait_entry->triggered = false; + wait_entry->aborted = false; + + spin_lock_bh(&priv->notif_wait_lock); + list_add(&wait_entry->list, &priv->notif_waits); + spin_unlock_bh(&priv->notif_wait_lock); +} + +int iwlagn_wait_notification(struct iwl_priv *priv, + struct iwl_notification_wait *wait_entry, + unsigned long timeout) +{ + int ret; + + ret = wait_event_timeout(priv->notif_waitq, + wait_entry->triggered || wait_entry->aborted, + timeout); + + spin_lock_bh(&priv->notif_wait_lock); + list_del(&wait_entry->list); + spin_unlock_bh(&priv->notif_wait_lock); + + if (wait_entry->aborted) + return -EIO; + + /* return value is always >= 0 */ + if (ret <= 0) + return -ETIMEDOUT; + return 0; +} + +void iwlagn_remove_notification(struct iwl_priv *priv, + struct iwl_notification_wait *wait_entry) +{ + spin_lock_bh(&priv->notif_wait_lock); + list_del(&wait_entry->list); + spin_unlock_bh(&priv->notif_wait_lock); +} + #ifdef CONFIG_PM_SLEEP static void iwlagn_convert_p1k(u16 *p1k, __le16 *out) { diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 90c55ea4cc39..fdb4c3786114 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -117,7 +117,6 @@ const char *get_cmd_string(u8 cmd) IWL_CMD(REPLY_WOWLAN_TKIP_PARAMS); IWL_CMD(REPLY_WOWLAN_KEK_KCK_MATERIAL); IWL_CMD(REPLY_WOWLAN_GET_STATUS); - IWL_CMD(REPLY_D3_CONFIG); default: return "UNKNOWN"; @@ -1131,9 +1130,9 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; /* set up notification wait support */ - spin_lock_init(&priv->shrd->notif_wait_lock); - INIT_LIST_HEAD(&priv->shrd->notif_waits); - init_waitqueue_head(&priv->shrd->notif_waitq); + spin_lock_init(&priv->notif_wait_lock); + INIT_LIST_HEAD(&priv->notif_waits); + init_waitqueue_head(&priv->notif_waitq); /* Set up BT Rx handlers */ if (priv->cfg->lib->bt_rx_handler_setup) @@ -1152,11 +1151,11 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, * even if the RX handler consumes the RXB we have * access to it in the notification wait entry. */ - if (!list_empty(&priv->shrd->notif_waits)) { + if (!list_empty(&priv->notif_waits)) { struct iwl_notification_wait *w; - spin_lock(&priv->shrd->notif_wait_lock); - list_for_each_entry(w, &priv->shrd->notif_waits, list) { + spin_lock(&priv->notif_wait_lock); + list_for_each_entry(w, &priv->notif_waits, list) { if (w->cmd != pkt->hdr.cmd) continue; IWL_DEBUG_RX(priv, @@ -1167,9 +1166,9 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, if (w->fn) w->fn(priv, pkt, w->fn_data); } - spin_unlock(&priv->shrd->notif_wait_lock); + spin_unlock(&priv->notif_wait_lock); - wake_up_all(&priv->shrd->notif_waitq); + wake_up_all(&priv->notif_waitq); } if (priv->pre_rx_handler) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 466e4ab544f7..8de97f5a1825 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -60,7 +60,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, u8 old_dev_type = send->dev_type; int ret; - iwl_init_notification_wait(priv->shrd, &disable_wait, + iwlagn_init_notification_wait(priv, &disable_wait, REPLY_WIPAN_DEACTIVATION_COMPLETE, NULL, NULL); @@ -74,9 +74,9 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, if (ret) { IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); - iwl_remove_notification(priv->shrd, &disable_wait); + iwlagn_remove_notification(priv, &disable_wait); } else { - ret = iwl_wait_notification(priv->shrd, &disable_wait, HZ); + ret = iwlagn_wait_notification(priv, &disable_wait, HZ); if (ret) IWL_ERR(priv, "Timed out waiting for PAN disable\n"); } @@ -529,24 +529,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) return 0; } -void iwlagn_config_ht40(struct ieee80211_conf *conf, - struct iwl_rxon_context *ctx) -{ - if (conf_is_ht40_minus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_BELOW; - ctx->ht.is_40mhz = true; - } else if (conf_is_ht40_plus(conf)) { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - ctx->ht.is_40mhz = true; - } else { - ctx->ht.extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_NONE; - ctx->ht.is_40mhz = false; - } -} - int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) { struct iwl_priv *priv = hw->priv; @@ -608,11 +590,19 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) ctx->ht.enabled = conf_is_ht(conf); 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) - iwlagn_config_ht40(conf, ctx); + if (conf_is_ht40_minus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_BELOW; + ctx->ht.is_40mhz = true; + } else if (conf_is_ht40_plus(conf)) { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_ABOVE; + ctx->ht.is_40mhz = true; + } else { + ctx->ht.extension_chan_offset = + IEEE80211_HT_PARAM_CHA_SEC_NONE; + ctx->ht.is_40mhz = false; + } } else ctx->ht.is_40mhz = false; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 626ed701100e..901fd9485d75 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -1250,6 +1250,9 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, switch (keyconf->cipher) { case WLAN_CIPHER_SUITE_TKIP: + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + if (sta) addr = sta->addr; else /* station mode case only */ @@ -1262,6 +1265,8 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, seq.tkip.iv32, p1k, CMD_SYNC); break; case WLAN_CIPHER_SUITE_CCMP: + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + /* fall through */ case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: ret = iwlagn_send_sta_key(priv, keyconf, sta_id, diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-ucode.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c similarity index 79% rename from trunk/drivers/net/wireless/iwlwifi/iwl-ucode.c rename to trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index b365de457b1b..9ec315b31d45 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -122,7 +122,7 @@ int iwl_alloc_fw_desc(struct iwl_bus *bus, struct fw_desc *desc, /* * ucode */ -static int iwl_load_section(struct iwl_trans *trans, const char *name, +static int iwlagn_load_section(struct iwl_trans *trans, const char *name, struct fw_desc *image, u32 dst_addr) { struct iwl_bus *bus = bus(trans); @@ -188,7 +188,7 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans, return NULL; } -static int iwl_load_given_ucode(struct iwl_trans *trans, +static int iwlagn_load_given_ucode(struct iwl_trans *trans, enum iwl_ucode_type ucode_type) { int ret = 0; @@ -201,19 +201,19 @@ static int iwl_load_given_ucode(struct iwl_trans *trans, return -EINVAL; } - ret = iwl_load_section(trans, "INST", &image->code, + ret = iwlagn_load_section(trans, "INST", &image->code, IWLAGN_RTC_INST_LOWER_BOUND); if (ret) return ret; - return iwl_load_section(trans, "DATA", &image->data, + return iwlagn_load_section(trans, "DATA", &image->data, IWLAGN_RTC_DATA_LOWER_BOUND); } /* * Calibration */ -static int iwl_set_Xtal_calib(struct iwl_priv *priv) +static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) { struct iwl_calib_xtal_freq_cmd cmd; __le16 *xtal_calib = @@ -222,10 +222,11 @@ static int iwl_set_Xtal_calib(struct iwl_priv *priv) iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); - return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); + return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], + (u8 *)&cmd, sizeof(cmd)); } -static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) +static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) { struct iwl_calib_temperature_offset_cmd cmd; __le16 *offset_calib = @@ -239,10 +240,11 @@ static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", le16_to_cpu(cmd.radio_sensor_offset)); - return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); + return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET], + (u8 *)&cmd, sizeof(cmd)); } -static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) +static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv) { struct iwl_calib_temperature_offset_v2_cmd cmd; __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv, @@ -274,10 +276,11 @@ static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n", le16_to_cpu(cmd.burntVoltageRef)); - return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); + return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET], + (u8 *)&cmd, sizeof(cmd)); } -static int iwl_send_calib_cfg(struct iwl_trans *trans) +static int iwlagn_send_calib_cfg(struct iwl_priv *priv) { struct iwl_calib_cfg_cmd calib_cfg_cmd; struct iwl_host_cmd cmd = { @@ -293,7 +296,7 @@ static int iwl_send_calib_cfg(struct iwl_trans *trans) calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; - return iwl_trans_send_cmd(trans, &cmd); + return iwl_trans_send_cmd(trans(priv), &cmd); } int iwlagn_rx_calib_result(struct iwl_priv *priv, @@ -303,14 +306,37 @@ int iwlagn_rx_calib_result(struct iwl_priv *priv, struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; + int index; /* reduce the size of the length field itself */ len -= 4; - if (iwl_calib_set(priv, hdr, len)) - IWL_ERR(priv, "Failed to record calibration data %d\n", - hdr->op_code); - + /* Define the order in which the results will be sent to the runtime + * uCode. iwl_send_calib_results sends them in a row according to + * their index. We sort them here + */ + switch (hdr->op_code) { + case IWL_PHY_CALIBRATE_DC_CMD: + index = IWL_CALIB_DC; + break; + case IWL_PHY_CALIBRATE_LO_CMD: + index = IWL_CALIB_LO; + break; + case IWL_PHY_CALIBRATE_TX_IQ_CMD: + index = IWL_CALIB_TX_IQ; + break; + case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD: + index = IWL_CALIB_TX_IQ_PERD; + break; + case IWL_PHY_CALIBRATE_BASE_BAND_CMD: + index = IWL_CALIB_BASE_BAND; + break; + default: + IWL_ERR(priv, "Unknown calibration notification %d\n", + hdr->op_code); + return -1; + } + iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); return 0; } @@ -326,14 +352,14 @@ int iwlagn_init_alive_start(struct iwl_priv *priv) * no need to close the envlope since we are going * to load the runtime uCode later. */ - ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN, + ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); if (ret) return ret; } - ret = iwl_send_calib_cfg(trans(priv)); + ret = iwlagn_send_calib_cfg(priv); if (ret) return ret; @@ -343,15 +369,15 @@ int iwlagn_init_alive_start(struct iwl_priv *priv) */ if (priv->cfg->need_temp_offset_calib) { if (priv->cfg->temp_offset_v2) - return iwl_set_temperature_offset_calib_v2(priv); + return iwlagn_set_temperature_offset_calib_v2(priv); else - return iwl_set_temperature_offset_calib(priv); + return iwlagn_set_temperature_offset_calib(priv); } return 0; } -static int iwl_send_wimax_coex(struct iwl_priv *priv) +static int iwlagn_send_wimax_coex(struct iwl_priv *priv) { struct iwl_wimax_coex_cmd coex_cmd; @@ -379,7 +405,7 @@ static int iwl_send_wimax_coex(struct iwl_priv *priv) sizeof(coex_cmd), &coex_cmd); } -static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { +static const u8 iwlagn_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | @@ -401,42 +427,42 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { 0, 0, 0, 0, 0, 0, 0 }; -void iwl_send_prio_tbl(struct iwl_trans *trans) +void iwlagn_send_prio_tbl(struct iwl_priv *priv) { struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd; - memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl, - sizeof(iwl_bt_prio_tbl)); - if (iwl_trans_send_cmd_pdu(trans, + memcpy(prio_tbl_cmd.prio_tbl, iwlagn_bt_prio_tbl, + sizeof(iwlagn_bt_prio_tbl)); + if (iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC, sizeof(prio_tbl_cmd), &prio_tbl_cmd)) - IWL_ERR(trans, "failed to send BT prio tbl command\n"); + IWL_ERR(priv, "failed to send BT prio tbl command\n"); } -int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type) +int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) { struct iwl_bt_coex_prot_env_cmd env_cmd; int ret; env_cmd.action = action; env_cmd.type = type; - ret = iwl_trans_send_cmd_pdu(trans, + ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_COEX_PROT_ENV, CMD_SYNC, sizeof(env_cmd), &env_cmd); if (ret) - IWL_ERR(trans, "failed to send BT env command\n"); + IWL_ERR(priv, "failed to send BT env command\n"); return ret; } -static int iwl_alive_notify(struct iwl_priv *priv) +static int iwlagn_alive_notify(struct iwl_priv *priv) { struct iwl_rxon_context *ctx; int ret; if (!priv->tx_cmd_pool) priv->tx_cmd_pool = - kmem_cache_create("iwl_dev_cmd", + kmem_cache_create("iwlagn_dev_cmd", sizeof(struct iwl_device_cmd), sizeof(void *), 0, NULL); @@ -447,15 +473,13 @@ static int iwl_alive_notify(struct iwl_priv *priv) for_each_context(priv, ctx) ctx->last_tx_rejected = false; - ret = iwl_send_wimax_coex(priv); + ret = iwlagn_send_wimax_coex(priv); if (ret) return ret; - if (!priv->cfg->no_xtal_calib) { - ret = iwl_set_Xtal_calib(priv); - if (ret) - return ret; - } + ret = iwlagn_set_Xtal_calib(priv); + if (ret) + return ret; return iwl_send_calib_results(priv); } @@ -548,7 +572,7 @@ struct iwlagn_alive_data { u8 subtype; }; -static void iwl_alive_fn(struct iwl_priv *priv, +static void iwlagn_alive_fn(struct iwl_priv *priv, struct iwl_rx_packet *pkt, void *data) { @@ -571,70 +595,6 @@ static void iwl_alive_fn(struct iwl_priv *priv, alive_data->valid = palive->is_valid == UCODE_VALID_OK; } -/* notification wait support */ -void iwl_init_notification_wait(struct iwl_shared *shrd, - struct iwl_notification_wait *wait_entry, - u8 cmd, - void (*fn)(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - void *data), - void *fn_data) -{ - wait_entry->fn = fn; - wait_entry->fn_data = fn_data; - wait_entry->cmd = cmd; - wait_entry->triggered = false; - wait_entry->aborted = false; - - spin_lock_bh(&shrd->notif_wait_lock); - list_add(&wait_entry->list, &shrd->notif_waits); - spin_unlock_bh(&shrd->notif_wait_lock); -} - -int iwl_wait_notification(struct iwl_shared *shrd, - struct iwl_notification_wait *wait_entry, - unsigned long timeout) -{ - int ret; - - ret = wait_event_timeout(shrd->notif_waitq, - wait_entry->triggered || wait_entry->aborted, - timeout); - - spin_lock_bh(&shrd->notif_wait_lock); - list_del(&wait_entry->list); - spin_unlock_bh(&shrd->notif_wait_lock); - - if (wait_entry->aborted) - return -EIO; - - /* return value is always >= 0 */ - if (ret <= 0) - return -ETIMEDOUT; - return 0; -} - -void iwl_remove_notification(struct iwl_shared *shrd, - struct iwl_notification_wait *wait_entry) -{ - spin_lock_bh(&shrd->notif_wait_lock); - list_del(&wait_entry->list); - spin_unlock_bh(&shrd->notif_wait_lock); -} - -void iwl_abort_notification_waits(struct iwl_shared *shrd) -{ - unsigned long flags; - struct iwl_notification_wait *wait_entry; - - spin_lock_irqsave(&shrd->notif_wait_lock, flags); - list_for_each_entry(wait_entry, &shrd->notif_waits, list) - wait_entry->aborted = true; - spin_unlock_irqrestore(&shrd->notif_wait_lock, flags); - - wake_up_all(&shrd->notif_waitq); -} - #define UCODE_ALIVE_TIMEOUT HZ #define UCODE_CALIB_TIMEOUT (2*HZ) @@ -643,43 +603,41 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, { struct iwl_notification_wait alive_wait; struct iwlagn_alive_data alive_data; - struct iwl_trans *trans = trans(priv); int ret; enum iwl_ucode_type old_type; - ret = iwl_trans_start_device(trans); + ret = iwl_trans_start_device(trans(priv)); if (ret) return ret; - iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE, - iwl_alive_fn, &alive_data); + iwlagn_init_notification_wait(priv, &alive_wait, REPLY_ALIVE, + iwlagn_alive_fn, &alive_data); - old_type = trans->shrd->ucode_type; - trans->shrd->ucode_type = ucode_type; + old_type = priv->ucode_type; + priv->ucode_type = ucode_type; - ret = iwl_load_given_ucode(trans, ucode_type); + ret = iwlagn_load_given_ucode(trans(priv), ucode_type); if (ret) { - trans->shrd->ucode_type = old_type; - iwl_remove_notification(trans->shrd, &alive_wait); + priv->ucode_type = old_type; + iwlagn_remove_notification(priv, &alive_wait); return ret; } - iwl_trans_kick_nic(trans); + iwl_trans_kick_nic(trans(priv)); /* * Some things may run in the background now, but we * just wait for the ALIVE notification here. */ - ret = iwl_wait_notification(trans->shrd, &alive_wait, - UCODE_ALIVE_TIMEOUT); + ret = iwlagn_wait_notification(priv, &alive_wait, UCODE_ALIVE_TIMEOUT); if (ret) { - trans->shrd->ucode_type = old_type; + priv->ucode_type = old_type; return ret; } if (!alive_data.valid) { IWL_ERR(priv, "Loaded ucode is not valid!\n"); - trans->shrd->ucode_type = old_type; + priv->ucode_type = old_type; return -EIO; } @@ -689,9 +647,9 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, * skip it for WoWLAN. */ if (ucode_type != IWL_UCODE_WOWLAN) { - ret = iwl_verify_ucode(trans, ucode_type); + ret = iwl_verify_ucode(trans(priv), ucode_type); if (ret) { - trans->shrd->ucode_type = old_type; + priv->ucode_type = old_type; return ret; } @@ -699,11 +657,11 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, msleep(5); } - ret = iwl_alive_notify(priv); + ret = iwlagn_alive_notify(priv); if (ret) { IWL_WARN(priv, "Could not complete ALIVE transition: %d\n", ret); - trans->shrd->ucode_type = old_type; + priv->ucode_type = old_type; return ret; } @@ -721,10 +679,10 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) if (!trans(priv)->ucode_init.code.len) return 0; - if (priv->shrd->ucode_type != IWL_UCODE_NONE) + if (priv->ucode_type != IWL_UCODE_NONE) return 0; - iwl_init_notification_wait(priv->shrd, &calib_wait, + iwlagn_init_notification_wait(priv, &calib_wait, CALIBRATION_COMPLETE_NOTIFICATION, NULL, NULL); @@ -741,13 +699,12 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv) * Some things may run in the background now, but we * just wait for the calibration complete notification. */ - ret = iwl_wait_notification(priv->shrd, &calib_wait, - UCODE_CALIB_TIMEOUT); + ret = iwlagn_wait_notification(priv, &calib_wait, UCODE_CALIB_TIMEOUT); goto out; error: - iwl_remove_notification(priv->shrd, &calib_wait); + iwlagn_remove_notification(priv, &calib_wait); out: /* Whatever happened, stop the device */ iwl_trans_stop_device(trans(priv)); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c index daf010dad70c..e235e84de8b4 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1232,14 +1232,14 @@ int iwl_alive_start(struct iwl_priv *priv) priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS; priv->cur_rssi_ctx = NULL; - iwl_send_prio_tbl(trans(priv)); + iwlagn_send_prio_tbl(priv); /* FIXME: w/a to force change uCode BT state machine */ - ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN, + ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); if (ret) return ret; - ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_CLOSE, + ret = iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); if (ret) return ret; @@ -1575,8 +1575,6 @@ static int iwl_init_drv(struct iwl_priv *priv) mutex_init(&priv->shrd->mutex); - INIT_LIST_HEAD(&priv->calib_results); - priv->ieee_channels = NULL; priv->ieee_rates = NULL; priv->band = IEEE80211_BAND_2GHZ; @@ -1682,35 +1680,6 @@ static int iwl_set_hw_params(struct iwl_priv *priv) -static void iwl_debug_config(struct iwl_priv *priv) -{ - dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEBUG " -#ifdef CONFIG_IWLWIFI_DEBUG - "enabled\n"); -#else - "disabled\n"); -#endif - dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEBUGFS " -#ifdef CONFIG_IWLWIFI_DEBUGFS - "enabled\n"); -#else - "disabled\n"); -#endif - dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_TRACING " -#ifdef CONFIG_IWLWIFI_DEVICE_TRACING - "enabled\n"); -#else - "disabled\n"); -#endif - - dev_printk(KERN_INFO, bus(priv)->dev, "CONFIG_IWLWIFI_DEVICE_SVTOOL " -#ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL - "enabled\n"); -#else - "disabled\n"); -#endif -} - int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, struct iwl_cfg *cfg) { @@ -1746,9 +1715,6 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops, SET_IEEE80211_DEV(hw, bus(priv)->dev); - /* what debugging capabilities we have */ - iwl_debug_config(priv); - IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); priv->cfg = cfg; @@ -2022,10 +1988,9 @@ 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])"); -module_param_named(wd_disable, iwlagn_mod_params.wd_disable, int, S_IRUGO); +module_param_named(wd_disable, iwlagn_mod_params.wd_disable, bool, S_IRUGO); MODULE_PARM_DESC(wd_disable, - "Disable stuck queue watchdog timer 0=system default, " - "1=disable, 2=enable (default: 0)"); + "Disable stuck queue watchdog timer (default: 0 [enabled])"); /* * set bt_coex_active to true, uCode will do kill/defer diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h index f2f10702754d..5d8d2f445923 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -101,15 +101,13 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes); -void iwlagn_config_ht40(struct ieee80211_conf *conf, - struct iwl_rxon_context *ctx); /* uCode */ int iwlagn_rx_calib_result(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, struct iwl_device_cmd *cmd); -int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type); -void iwl_send_prio_tbl(struct iwl_trans *trans); +int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); +void iwlagn_send_prio_tbl(struct iwl_priv *priv); int iwlagn_run_init_ucode(struct iwl_priv *priv); int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv, enum iwl_ucode_type ucode_type); @@ -356,6 +354,22 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv); void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); +/* notification wait support */ +void __acquires(wait_entry) +iwlagn_init_notification_wait(struct iwl_priv *priv, + struct iwl_notification_wait *wait_entry, + u8 cmd, + void (*fn)(struct iwl_priv *priv, + struct iwl_rx_packet *pkt, + void *data), + void *fn_data); +int __must_check __releases(wait_entry) +iwlagn_wait_notification(struct iwl_priv *priv, + struct iwl_notification_wait *wait_entry, + unsigned long timeout); +void __releases(wait_entry) +iwlagn_remove_notification(struct iwl_priv *priv, + struct iwl_notification_wait *wait_entry); extern int iwlagn_init_alive_start(struct iwl_priv *priv); extern int iwl_alive_start(struct iwl_priv *priv); /* svtool */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c index 3b6f48bfe0e3..f9e9170e977a 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.c @@ -836,6 +836,19 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, } #endif +static void iwlagn_abort_notification_waits(struct iwl_priv *priv) +{ + unsigned long flags; + struct iwl_notification_wait *wait_entry; + + spin_lock_irqsave(&priv->notif_wait_lock, flags); + list_for_each_entry(wait_entry, &priv->notif_waits, list) + wait_entry->aborted = true; + spin_unlock_irqrestore(&priv->notif_wait_lock, flags); + + wake_up_all(&priv->notif_waitq); +} + void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) { unsigned int reload_msec; @@ -847,7 +860,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) /* Cancel currently queued command. */ clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); - iwl_abort_notification_waits(priv->shrd); + iwlagn_abort_notification_waits(priv); /* Keep the restart process from trying to send host * commands by clearing the ready bit */ @@ -1492,23 +1505,11 @@ void iwl_setup_watchdog(struct iwl_priv *priv) { unsigned int timeout = priv->cfg->base_params->wd_timeout; - if (!iwlagn_mod_params.wd_disable) { - /* use system default */ - if (timeout && !priv->cfg->base_params->wd_disable) - mod_timer(&priv->watchdog, - jiffies + - msecs_to_jiffies(IWL_WD_TICK(timeout))); - else - del_timer(&priv->watchdog); - } else { - /* module parameter overwrite default configuration */ - if (timeout && iwlagn_mod_params.wd_disable == 2) - mod_timer(&priv->watchdog, - jiffies + - msecs_to_jiffies(IWL_WD_TICK(timeout))); - else - del_timer(&priv->watchdog); - } + if (timeout && !iwlagn_mod_params.wd_disable) + mod_timer(&priv->watchdog, + jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout))); + else + del_timer(&priv->watchdog); } /** diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h index 6da53a36c1be..fa47f75185df 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-core.h @@ -113,7 +113,6 @@ struct iwl_lib_ops { * @shadow_reg_enable: HW shadhow register bit * @no_idle_support: do not support idle mode * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up - * wd_disable: disable watchdog timer */ struct iwl_base_params { int eeprom_size; @@ -135,7 +134,6 @@ struct iwl_base_params { const bool shadow_reg_enable; const bool no_idle_support; const bool hd_v2; - const bool wd_disable; }; /* * @advanced_bt_coexist: support advanced bt coexist @@ -186,9 +184,8 @@ struct iwl_ht_params { * @ht_params: point to ht patameters * @bt_params: pointer to bt parameters * @pa_type: used by 6000 series only to identify the type of Power Amplifier + * @need_dc_calib: need to perform init dc calibration * @need_temp_offset_calib: need to perform temperature offset calibration - * @no_xtal_calib: some devices do not need crystal calibration data, - * don't send it to those * @scan_antennas: available antenna for scan operation * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) * @adv_pm: advance power management @@ -225,8 +222,8 @@ struct iwl_cfg { struct iwl_ht_params *ht_params; struct iwl_bt_params *bt_params; enum iwl_pa_type pa_type; /* if used set to IWL_PA_SYSTEM */ + const bool need_dc_calib; /* if used set to true */ const bool need_temp_offset_calib; /* if used set to true */ - const bool no_xtal_calib; u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; enum iwl_led_mode led_mode; const bool adv_pm; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h index f8fc2393dd4c..44a7bdd7ccfd 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -134,43 +134,48 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) */ /* 0x0000000F - 0x00000001 */ -#define IWL_DL_INFO 0x00000001 -#define IWL_DL_MAC80211 0x00000002 -#define IWL_DL_HCMD 0x00000004 -#define IWL_DL_STATE 0x00000008 +#define IWL_DL_INFO (1 << 0) +#define IWL_DL_MAC80211 (1 << 1) +#define IWL_DL_HCMD (1 << 2) +#define IWL_DL_STATE (1 << 3) /* 0x000000F0 - 0x00000010 */ -#define IWL_DL_EEPROM 0x00000040 -#define IWL_DL_RADIO 0x00000080 +#define IWL_DL_MACDUMP (1 << 4) +#define IWL_DL_HCMD_DUMP (1 << 5) +#define IWL_DL_EEPROM (1 << 6) +#define IWL_DL_RADIO (1 << 7) /* 0x00000F00 - 0x00000100 */ -#define IWL_DL_POWER 0x00000100 -#define IWL_DL_TEMP 0x00000200 -#define IWL_DL_SCAN 0x00000800 +#define IWL_DL_POWER (1 << 8) +#define IWL_DL_TEMP (1 << 9) +/* reserved (1 << 10) */ +#define IWL_DL_SCAN (1 << 11) /* 0x0000F000 - 0x00001000 */ -#define IWL_DL_ASSOC 0x00001000 -#define IWL_DL_DROP 0x00002000 -#define IWL_DL_COEX 0x00008000 +#define IWL_DL_ASSOC (1 << 12) +#define IWL_DL_DROP (1 << 13) +/* reserved (1 << 14) */ +#define IWL_DL_COEX (1 << 15) /* 0x000F0000 - 0x00010000 */ -#define IWL_DL_FW 0x00010000 -#define IWL_DL_RF_KILL 0x00020000 -#define IWL_DL_FW_ERRORS 0x00040000 -#define IWL_DL_LED 0x00080000 +#define IWL_DL_FW (1 << 16) +#define IWL_DL_RF_KILL (1 << 17) +#define IWL_DL_FW_ERRORS (1 << 18) +#define IWL_DL_LED (1 << 19) /* 0x00F00000 - 0x00100000 */ -#define IWL_DL_RATE 0x00100000 -#define IWL_DL_CALIB 0x00200000 -#define IWL_DL_WEP 0x00400000 -#define IWL_DL_TX 0x00800000 +#define IWL_DL_RATE (1 << 20) +#define IWL_DL_CALIB (1 << 21) +#define IWL_DL_WEP (1 << 22) +#define IWL_DL_TX (1 << 23) /* 0x0F000000 - 0x01000000 */ -#define IWL_DL_RX 0x01000000 -#define IWL_DL_ISR 0x02000000 -#define IWL_DL_HT 0x04000000 +#define IWL_DL_RX (1 << 24) +#define IWL_DL_ISR (1 << 25) +#define IWL_DL_HT (1 << 26) /* 0xF0000000 - 0x10000000 */ -#define IWL_DL_11H 0x10000000 -#define IWL_DL_STATS 0x20000000 -#define IWL_DL_TX_REPLY 0x40000000 -#define IWL_DL_TX_QUEUES 0x80000000 +#define IWL_DL_11H (1 << 28) +#define IWL_DL_STATS (1 << 29) +#define IWL_DL_TX_REPLY (1 << 30) +#define IWL_DL_TX_QUEUES (1 << 31) #define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a) #define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a) +#define IWL_DEBUG_MACDUMP(p, f, a...) IWL_DEBUG(p, IWL_DL_MACDUMP, f, ## a) #define IWL_DEBUG_TEMP(p, f, a...) IWL_DEBUG(p, IWL_DL_TEMP, f, ## a) #define IWL_DEBUG_SCAN(p, f, a...) IWL_DEBUG(p, IWL_DL_SCAN, f, ## a) #define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a) @@ -179,6 +184,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a) #define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) #define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) +#define IWL_DEBUG_HC_DUMP(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD_DUMP, f, ## a) #define IWL_DEBUG_EEPROM(p, f, a...) IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a) #define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) #define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) @@ -200,6 +206,8 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) #define IWL_DEBUG_STATS_LIMIT(p, f, a...) \ IWL_DEBUG_LIMIT(p, IWL_DL_STATS, f, ## a) #define IWL_DEBUG_TX_REPLY(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a) +#define IWL_DEBUG_TX_REPLY_LIMIT(p, f, a...) \ + IWL_DEBUG_LIMIT(p, IWL_DL_TX_REPLY, f, ## a) #define IWL_DEBUG_TX_QUEUES(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_QUEUES, f, ## a) #define IWL_DEBUG_RADIO(p, f, a...) IWL_DEBUG(p, IWL_DL_RADIO, f, ## a) #define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a) diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c index ccbcab40e78f..68b04f5b10ce 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -234,12 +234,11 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, /* default is to dump the entire data segment */ if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { - struct iwl_trans *trans = trans(priv); priv->dbgfs_sram_offset = 0x800000; - if (trans->shrd->ucode_type == IWL_UCODE_INIT) - priv->dbgfs_sram_len = trans->ucode_init.data.len; + if (priv->ucode_type == IWL_UCODE_INIT) + priv->dbgfs_sram_len = trans(priv)->ucode_init.data.len; else - priv->dbgfs_sram_len = trans->ucode_rt.data.len; + priv->dbgfs_sram_len = trans(priv)->ucode_rt.data.len; } len = priv->dbgfs_sram_len; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h index 6f6a647d34f6..556e4a2c19bc 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -442,12 +442,26 @@ enum iwlagn_chain_noise_state { }; +/* + * enum iwl_calib + * defines the order in which results of initial calibrations + * should be sent to the runtime uCode + */ +enum iwl_calib { + IWL_CALIB_XTAL, + IWL_CALIB_DC, + IWL_CALIB_LO, + IWL_CALIB_TX_IQ, + IWL_CALIB_TX_IQ_PERD, + IWL_CALIB_BASE_BAND, + IWL_CALIB_TEMP_OFFSET, + IWL_CALIB_MAX +}; + /* Opaque calibration results */ struct iwl_calib_result { - struct list_head list; - size_t cmd_len; - struct iwl_calib_hdr hdr; - /* data follows */ + void *buf; + size_t buf_len; }; /* Sensitivity calib data */ @@ -689,6 +703,35 @@ struct iwl_force_reset { */ #define IWLAGN_EXT_BEACON_TIME_POS 22 +/** + * struct iwl_notification_wait - notification wait entry + * @list: list head for global list + * @fn: function called with the notification + * @cmd: command ID + * + * This structure is not used directly, to wait for a + * notification declare it on the stack, and call + * iwlagn_init_notification_wait() with appropriate + * parameters. Then do whatever will cause the ucode + * to notify the driver, and to wait for that then + * call iwlagn_wait_notification(). + * + * Each notification is one-shot. If at some point we + * need to support multi-shot notifications (which + * can't be allocated on the stack) we need to modify + * the code for them. + */ +struct iwl_notification_wait { + struct list_head list; + + void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt, + void *data); + void *fn_data; + + u8 cmd; + bool triggered, aborted; +}; + struct iwl_rxon_context { struct ieee80211_vif *vif; @@ -761,12 +804,6 @@ struct iwl_testmode_trace { dma_addr_t dma_addr; bool trace_enabled; }; -struct iwl_testmode_sram { - u32 buff_size; - u32 num_chunks; - u8 *buff_addr; - bool sram_readed; -}; #endif struct iwl_wipan_noa_data { @@ -832,7 +869,7 @@ struct iwl_priv { s32 last_temperature; /* init calibration results */ - struct list_head calib_results; + struct iwl_calib_result calib_results[IWL_CALIB_MAX]; struct iwl_wipan_noa_data __rcu *noa_data; @@ -860,6 +897,7 @@ struct iwl_priv { u32 ucode_ver; /* version of ucode, copy of iwl_ucode.ver */ + enum iwl_ucode_type ucode_type; char firmware_name[25]; struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX]; @@ -963,6 +1001,10 @@ struct iwl_priv { /* counts reply_tx error */ struct reply_tx_error_statistics reply_tx_stats; struct reply_agg_tx_error_statistics reply_agg_tx_stats; + /* notification wait support */ + struct list_head notif_waits; + spinlock_t notif_wait_lock; + wait_queue_head_t notif_waitq; /* remain-on-channel offload support */ struct ieee80211_channel *hw_roc_channel; @@ -1042,7 +1084,6 @@ struct iwl_priv { bool led_registered; #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL struct iwl_testmode_trace testmode_trace; - struct iwl_testmode_sram testmode_sram; u32 tm_fixed_rate; #endif diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/trunk/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 55308b88faac..05b1f0d2f387 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -481,11 +481,15 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct iwl_priv *priv = hw->priv; + IWL_DEBUG_MACDUMP(priv, "enter\n"); + IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); if (iwlagn_tx_skb(priv, skb)) dev_kfree_skb_any(skb); + + IWL_DEBUG_MACDUMP(priv, "leave\n"); } static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, @@ -517,17 +521,6 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } - switch (key->cipher) { - case WLAN_CIPHER_SUITE_TKIP: - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - /* fall through */ - case WLAN_CIPHER_SUITE_CCMP: - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - break; - default: - break; - } - /* * We could program these keys into the hardware as well, but we * don't expect much multicast traffic in IBSS and having keys diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h b/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h index 39aa9cf5b847..1f7a93c67c45 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -120,7 +120,7 @@ extern struct iwl_mod_params iwlagn_mod_params; * @restart_fw: restart firmware, default = 1 * @plcp_check: enable plcp health check, default = true * @ack_check: disable ack health check, default = false - * @wd_disable: enable stuck queue check, default = 0 + * @wd_disable: enable stuck queue check, default = false * @bt_coex_active: enable bt coex, default = true * @led_mode: system default, default = 0 * @no_sleep_autoadjust: disable autoadjust, default = true @@ -141,7 +141,7 @@ struct iwl_mod_params { int restart_fw; bool plcp_check; bool ack_check; - int wd_disable; + bool wd_disable; bool bt_coex_active; int led_mode; bool no_sleep_autoadjust; @@ -174,6 +174,7 @@ struct iwl_mod_params { * @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit * relevant for 1000, 6000 and up * @wd_timeout: TX queues watchdog timeout + * @calib_init_cfg: setup initial calibrations for the hw * @calib_rt_cfg: setup runtime calibrations for the hw * @struct iwl_sensitivity_ranges: range of sensitivity values */ @@ -194,6 +195,7 @@ struct iwl_hw_params { u32 ct_kill_exit_threshold; unsigned int wd_timeout; + u32 calib_init_cfg; u32 calib_rt_cfg; const struct iwl_sensitivity_ranges *sens; }; @@ -256,52 +258,6 @@ struct iwl_tid_data { struct iwl_ht_agg agg; }; -/** - * enum iwl_ucode_type - * - * The type of ucode currently loaded on the hardware. - * - * @IWL_UCODE_NONE: No ucode loaded - * @IWL_UCODE_REGULAR: Normal runtime ucode - * @IWL_UCODE_INIT: Initial ucode - * @IWL_UCODE_WOWLAN: Wake on Wireless enabled ucode - */ -enum iwl_ucode_type { - IWL_UCODE_NONE, - IWL_UCODE_REGULAR, - IWL_UCODE_INIT, - IWL_UCODE_WOWLAN, -}; - -/** - * struct iwl_notification_wait - notification wait entry - * @list: list head for global list - * @fn: function called with the notification - * @cmd: command ID - * - * This structure is not used directly, to wait for a - * notification declare it on the stack, and call - * iwlagn_init_notification_wait() with appropriate - * parameters. Then do whatever will cause the ucode - * to notify the driver, and to wait for that then - * call iwlagn_wait_notification(). - * - * Each notification is one-shot. If at some point we - * need to support multi-shot notifications (which - * can't be allocated on the stack) we need to modify - * the code for them. - */ -struct iwl_notification_wait { - struct list_head list; - - void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt, - void *data); - void *fn_data; - - u8 cmd; - bool triggered, aborted; -}; - /** * struct iwl_shared - shared fields for all the layers of the driver * @@ -319,10 +275,6 @@ struct iwl_notification_wait { * @sta_lock: protects the station table. * If lock and sta_lock are needed, lock must be acquired first. * @mutex: - * @ucode_type: indicator of loaded ucode image - * @notif_waits: things waiting for notification - * @notif_wait_lock: lock protecting notification - * @notif_waitq: head of notification wait queue */ struct iwl_shared { #ifdef CONFIG_IWLWIFI_DEBUG @@ -350,14 +302,6 @@ struct iwl_shared { struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; wait_queue_head_t wait_command_queue; - - /* ucode related variables */ - enum iwl_ucode_type ucode_type; - - /* notification wait support */ - struct list_head notif_waits; - spinlock_t notif_wait_lock; - wait_queue_head_t notif_waitq; }; /*Whatever _m is (iwl_trans, iwl_priv, iwl_bus, these macros will work */ @@ -501,24 +445,6 @@ bool iwl_check_for_ct_kill(struct iwl_priv *priv); void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac); void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac); -/* notification wait support */ -void iwl_abort_notification_waits(struct iwl_shared *shrd); -void __acquires(wait_entry) -iwl_init_notification_wait(struct iwl_shared *shrd, - struct iwl_notification_wait *wait_entry, - u8 cmd, - void (*fn)(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - void *data), - void *fn_data); -int __must_check __releases(wait_entry) -iwl_wait_notification(struct iwl_shared *shrd, - struct iwl_notification_wait *wait_entry, - unsigned long timeout); -void __releases(wait_entry) -iwl_remove_notification(struct iwl_shared *shrd, - struct iwl_notification_wait *wait_entry); - #ifdef CONFIG_IWLWIFI_DEBUGFS void iwl_reset_traffic_log(struct iwl_priv *priv); #endif /* CONFIG_IWLWIFI_DEBUGFS */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-testmode.c b/trunk/drivers/net/wireless/iwlwifi/iwl-sv-open.c similarity index 79% rename from trunk/drivers/net/wireless/iwlwifi/iwl-testmode.c rename to trunk/drivers/net/wireless/iwlwifi/iwl-sv-open.c index ff72dbcfd52d..e3882d0cfc85 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-sv-open.c @@ -106,10 +106,6 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, }, [IWL_TM_ATTR_UCODE_OWNER] = { .type = NLA_U8, }, - - [IWL_TM_ATTR_SRAM_ADDR] = { .type = NLA_U32, }, - [IWL_TM_ATTR_SRAM_SIZE] = { .type = NLA_U32, }, - [IWL_TM_ATTR_SRAM_DUMP] = { .type = NLA_UNSPEC, }, }; /* @@ -181,18 +177,6 @@ void iwl_testmode_init(struct iwl_priv *priv) { priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; priv->testmode_trace.trace_enabled = false; - priv->testmode_sram.sram_readed = false; -} - -static void iwl_sram_cleanup(struct iwl_priv *priv) -{ - if (priv->testmode_sram.sram_readed) { - kfree(priv->testmode_sram.buff_addr); - priv->testmode_sram.buff_addr = NULL; - priv->testmode_sram.buff_size = 0; - priv->testmode_sram.num_chunks = 0; - priv->testmode_sram.sram_readed = false; - } } static void iwl_trace_cleanup(struct iwl_priv *priv) @@ -217,7 +201,6 @@ static void iwl_trace_cleanup(struct iwl_priv *priv) void iwl_testmode_cleanup(struct iwl_priv *priv) { iwl_trace_cleanup(priv); - iwl_sram_cleanup(priv); } /* @@ -293,7 +276,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) IWL_INFO(priv, "testmode register access command offset 0x%x\n", ofs); switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { - case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: + case IWL_TM_CMD_APP2DEV_REG_READ32: val32 = iwl_read32(bus(priv), ofs); IWL_INFO(priv, "32bit value to read 0x%x\n", val32); @@ -308,7 +291,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) IWL_DEBUG_INFO(priv, "Error sending msg : %d\n", status); break; - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: + case IWL_TM_CMD_APP2DEV_REG_WRITE32: if (!tb[IWL_TM_ATTR_REG_VALUE32]) { IWL_DEBUG_INFO(priv, "Error finding value to write\n"); @@ -319,7 +302,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) iwl_write32(bus(priv), ofs, val32); } break; - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: + case IWL_TM_CMD_APP2DEV_REG_WRITE8: if (!tb[IWL_TM_ATTR_REG_VALUE8]) { IWL_DEBUG_INFO(priv, "Error finding value to write\n"); return -ENOMSG; @@ -329,32 +312,6 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) iwl_write8(bus(priv), ofs, val8); } break; - case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: - val32 = iwl_read_prph(bus(priv), ofs); - IWL_INFO(priv, "32bit value to read 0x%x\n", val32); - - skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); - if (!skb) { - IWL_DEBUG_INFO(priv, "Error allocating memory\n"); - return -ENOMEM; - } - NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32); - status = cfg80211_testmode_reply(skb); - if (status < 0) - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", status); - break; - case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32: - if (!tb[IWL_TM_ATTR_REG_VALUE32]) { - IWL_DEBUG_INFO(priv, - "Error finding value to write\n"); - return -ENOMSG; - } else { - val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); - IWL_INFO(priv, "32bit value to write 0x%x\n", val32); - iwl_write_prph(bus(priv), ofs, val32); - } - break; default: IWL_DEBUG_INFO(priv, "Unknown testmode register command ID\n"); return -ENOSYS; @@ -373,7 +330,7 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) struct iwl_notification_wait calib_wait; int ret; - iwl_init_notification_wait(priv->shrd, &calib_wait, + iwlagn_init_notification_wait(priv, &calib_wait, CALIBRATION_COMPLETE_NOTIFICATION, NULL, NULL); ret = iwlagn_init_alive_start(priv); @@ -383,14 +340,14 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) goto cfg_init_calib_error; } - ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ); + ret = iwlagn_wait_notification(priv, &calib_wait, 2 * HZ); if (ret) IWL_DEBUG_INFO(priv, "Error detecting" " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); return ret; cfg_init_calib_error: - iwl_remove_notification(priv->shrd, &calib_wait); + iwlagn_remove_notification(priv, &calib_wait); return ret; } @@ -463,21 +420,6 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) "Error starting the device: %d\n", status); break; - case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: - iwl_scan_cancel_timeout(priv, 200); - iwl_trans_stop_device(trans(priv)); - status = iwlagn_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN); - if (status) { - IWL_DEBUG_INFO(priv, - "Error loading WOWLAN ucode: %d\n", status); - break; - } - status = iwl_alive_start(priv); - if (status) - IWL_DEBUG_INFO(priv, - "Error starting the device: %d\n", status); - break; - case IWL_TM_CMD_APP2DEV_GET_EEPROM: if (priv->eeprom) { skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, @@ -590,7 +532,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) } priv->testmode_trace.num_chunks = DIV_ROUND_UP(priv->testmode_trace.buff_size, - DUMP_CHUNK_SIZE); + TRACE_CHUNK_SIZE); break; case IWL_TM_CMD_APP2DEV_END_TRACE: @@ -622,15 +564,15 @@ static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb, idx = cb->args[4]; if (idx >= priv->testmode_trace.num_chunks) return -ENOENT; - length = DUMP_CHUNK_SIZE; + length = TRACE_CHUNK_SIZE; if (((idx + 1) == priv->testmode_trace.num_chunks) && - (priv->testmode_trace.buff_size % DUMP_CHUNK_SIZE)) + (priv->testmode_trace.buff_size % TRACE_CHUNK_SIZE)) length = priv->testmode_trace.buff_size % - DUMP_CHUNK_SIZE; + TRACE_CHUNK_SIZE; NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length, priv->testmode_trace.trace_addr + - (DUMP_CHUNK_SIZE * idx)); + (TRACE_CHUNK_SIZE * idx)); idx++; cb->args[4] = idx; return 0; @@ -676,110 +618,6 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) return 0; } -/* - * This function handles the user application commands for SRAM data dump - * - * It retrieves the mandatory fields IWL_TM_ATTR_SRAM_ADDR and - * IWL_TM_ATTR_SRAM_SIZE to decide the memory area for SRAM data reading - * - * Several error will be retured, -EBUSY if the SRAM data retrieved by - * previous command has not been delivered to userspace, or -ENOMSG if - * the mandatory fields (IWL_TM_ATTR_SRAM_ADDR,IWL_TM_ATTR_SRAM_SIZE) - * are missing, or -ENOMEM if the buffer allocation fails. - * - * Otherwise 0 is replied indicating the success of the SRAM reading. - * - * @hw: ieee80211_hw object that represents the device - * @tb: gnl message fields from the user space - */ -static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) -{ - struct iwl_priv *priv = hw->priv; - u32 base, ofs, size, maxsize; - - if (priv->testmode_sram.sram_readed) - return -EBUSY; - - if (!tb[IWL_TM_ATTR_SRAM_ADDR]) { - IWL_DEBUG_INFO(priv, "Error finding SRAM offset address\n"); - return -ENOMSG; - } - ofs = nla_get_u32(tb[IWL_TM_ATTR_SRAM_ADDR]); - if (!tb[IWL_TM_ATTR_SRAM_SIZE]) { - IWL_DEBUG_INFO(priv, "Error finding size for SRAM reading\n"); - return -ENOMSG; - } - size = nla_get_u32(tb[IWL_TM_ATTR_SRAM_SIZE]); - switch (priv->shrd->ucode_type) { - case IWL_UCODE_REGULAR: - maxsize = trans(priv)->ucode_rt.data.len; - break; - case IWL_UCODE_INIT: - maxsize = trans(priv)->ucode_init.data.len; - break; - case IWL_UCODE_WOWLAN: - maxsize = trans(priv)->ucode_wowlan.data.len; - break; - case IWL_UCODE_NONE: - IWL_DEBUG_INFO(priv, "Error, uCode does not been loaded\n"); - return -ENOSYS; - default: - IWL_DEBUG_INFO(priv, "Error, unsupported uCode type\n"); - return -ENOSYS; - } - if ((ofs + size) > maxsize) { - IWL_DEBUG_INFO(priv, "Invalid offset/size: out of range\n"); - return -EINVAL; - } - priv->testmode_sram.buff_size = (size / 4) * 4; - priv->testmode_sram.buff_addr = - kmalloc(priv->testmode_sram.buff_size, GFP_KERNEL); - if (priv->testmode_sram.buff_addr == NULL) { - IWL_DEBUG_INFO(priv, "Error allocating memory\n"); - return -ENOMEM; - } - base = 0x800000; - _iwl_read_targ_mem_words(bus(priv), base + ofs, - priv->testmode_sram.buff_addr, - priv->testmode_sram.buff_size / 4); - priv->testmode_sram.num_chunks = - DIV_ROUND_UP(priv->testmode_sram.buff_size, DUMP_CHUNK_SIZE); - priv->testmode_sram.sram_readed = true; - return 0; -} - -static int iwl_testmode_sram_dump(struct ieee80211_hw *hw, struct nlattr **tb, - struct sk_buff *skb, - struct netlink_callback *cb) -{ - struct iwl_priv *priv = hw->priv; - int idx, length; - - if (priv->testmode_sram.sram_readed) { - idx = cb->args[4]; - if (idx >= priv->testmode_sram.num_chunks) { - iwl_sram_cleanup(priv); - return -ENOENT; - } - length = DUMP_CHUNK_SIZE; - if (((idx + 1) == priv->testmode_sram.num_chunks) && - (priv->testmode_sram.buff_size % DUMP_CHUNK_SIZE)) - length = priv->testmode_sram.buff_size % - DUMP_CHUNK_SIZE; - - NLA_PUT(skb, IWL_TM_ATTR_SRAM_DUMP, length, - priv->testmode_sram.buff_addr + - (DUMP_CHUNK_SIZE * idx)); - idx++; - cb->args[4] = idx; - return 0; - } else - return -EFAULT; - - nla_put_failure: - return -ENOBUFS; -} - /* The testmode gnl message handler that takes the gnl message from the * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then @@ -827,11 +665,9 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) IWL_DEBUG_INFO(priv, "testmode cmd to uCode\n"); result = iwl_testmode_ucode(hw, tb); break; - case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: - case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: - case IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: - case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32: + case IWL_TM_CMD_APP2DEV_REG_READ32: + case IWL_TM_CMD_APP2DEV_REG_WRITE32: + case IWL_TM_CMD_APP2DEV_REG_WRITE8: IWL_DEBUG_INFO(priv, "testmode cmd to register\n"); result = iwl_testmode_reg(hw, tb); break; @@ -841,7 +677,6 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: case IWL_TM_CMD_APP2DEV_GET_EEPROM: case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: - case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); result = iwl_testmode_driver(hw, tb); break; @@ -858,11 +693,6 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) result = iwl_testmode_ownership(hw, tb); break; - case IWL_TM_CMD_APP2DEV_READ_SRAM: - IWL_DEBUG_INFO(priv, "testmode sram read cmd to driver\n"); - result = iwl_testmode_sram(hw, tb); - break; - default: IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); result = -ENOSYS; @@ -911,10 +741,6 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n"); result = iwl_testmode_trace_dump(hw, tb, skb, cb); break; - case IWL_TM_CMD_APP2DEV_DUMP_SRAM: - IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n"); - result = iwl_testmode_sram_dump(hw, tb, skb, cb); - break; default: result = -EINVAL; break; diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-testmode.h b/trunk/drivers/net/wireless/iwlwifi/iwl-testmode.h index deedd27c5f3d..b980bda4b0f8 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -76,9 +76,9 @@ * the actual uCode host command ID is carried with * IWL_TM_ATTR_UCODE_CMD_ID * - * @IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: - * @IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: - * @IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: + * @IWL_TM_CMD_APP2DEV_REG_READ32: + * @IWL_TM_CMD_APP2DEV_REG_WRITE32: + * @IWL_TM_CMD_APP2DEV_REG_WRITE8: * commands from user applicaiton to access register * * @IWL_TM_CMD_APP2DEV_GET_DEVICENAME: retrieve device name @@ -103,28 +103,16 @@ * @IWL_TM_CMD_DEV2APP_EEPROM_RSP: * commands from kernel space to carry the eeprom response * to user application - * * @IWL_TM_CMD_APP2DEV_OWNERSHIP: * commands from user application to own change the ownership of the uCode * if application has the ownership, the only host command from * testmode will deliver to uCode. Default owner is driver - * - * @IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32: - * @IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32: - * commands from user applicaiton to indirectly access peripheral register - * - * @IWL_TM_CMD_APP2DEV_READ_SRAM: - * @IWL_TM_CMD_APP2DEV_DUMP_SRAM: - * commands from user applicaiton to read data in sram - * - * @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Weak On Wireless LAN uCode image - * */ enum iwl_tm_cmd_t { IWL_TM_CMD_APP2DEV_UCODE = 1, - IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32 = 2, - IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32 = 3, - IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8 = 4, + IWL_TM_CMD_APP2DEV_REG_READ32 = 2, + IWL_TM_CMD_APP2DEV_REG_WRITE32 = 3, + IWL_TM_CMD_APP2DEV_REG_WRITE8 = 4, IWL_TM_CMD_APP2DEV_GET_DEVICENAME = 5, IWL_TM_CMD_APP2DEV_LOAD_INIT_FW = 6, IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB = 7, @@ -138,12 +126,7 @@ enum iwl_tm_cmd_t { IWL_TM_CMD_DEV2APP_UCODE_RX_PKT = 15, IWL_TM_CMD_DEV2APP_EEPROM_RSP = 16, IWL_TM_CMD_APP2DEV_OWNERSHIP = 17, - IWL_TM_CMD_APP2DEV_INDIRECT_REG_READ32 = 18, - IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32 = 19, - IWL_TM_CMD_APP2DEV_READ_SRAM = 20, - IWL_TM_CMD_APP2DEV_DUMP_SRAM = 21, - IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW = 22, - IWL_TM_CMD_MAX = 23, + IWL_TM_CMD_MAX = 18, }; /* @@ -213,18 +196,6 @@ enum iwl_tm_cmd_t { * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_OWNERSHIP, * The mandatory fields are: * IWL_TM_ATTR_UCODE_OWNER for the new owner - * - * @IWL_TM_ATTR_SRAM_ADDR: - * @IWL_TM_ATTR_SRAM_SIZE: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_READ_SRAM, - * The mandatory fields are: - * IWL_TM_ATTR_SRAM_ADDR for the address in sram - * IWL_TM_ATTR_SRAM_SIZE for the buffer size of data reading - * - * @IWL_TM_ATTR_SRAM_DUMP: - * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_DUMP_SRAM, - * IWL_TM_ATTR_SRAM_DUMP for the data in sram - * */ enum iwl_tm_attr_t { IWL_TM_ATTR_NOT_APPLICABLE = 0, @@ -242,10 +213,7 @@ enum iwl_tm_attr_t { IWL_TM_ATTR_TRACE_DUMP = 12, IWL_TM_ATTR_FIXRATE = 13, IWL_TM_ATTR_UCODE_OWNER = 14, - IWL_TM_ATTR_SRAM_ADDR = 15, - IWL_TM_ATTR_SRAM_SIZE = 16, - IWL_TM_ATTR_SRAM_DUMP = 17, - IWL_TM_ATTR_MAX = 18, + IWL_TM_ATTR_MAX = 15, }; /* uCode trace buffer */ @@ -253,8 +221,6 @@ enum iwl_tm_attr_t { #define TRACE_BUFF_SIZE_MIN 0x20000 #define TRACE_BUFF_SIZE_DEF TRACE_BUFF_SIZE_MIN #define TRACE_BUFF_PADD 0x2000 - -/* Maximum data size of each dump it packet */ -#define DUMP_CHUNK_SIZE (PAGE_SIZE - 1024) +#define TRACE_CHUNK_SIZE (PAGE_SIZE - 1024) #endif diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index becd92173ddd..ee126f844a5c 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -595,7 +595,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) IWL_TRANS_GET_PCIE_TRANS(trans); base = priv->device_pointers.error_event_table; - if (trans->shrd->ucode_type == IWL_UCODE_INIT) { + if (priv->ucode_type == IWL_UCODE_INIT) { if (!base) base = priv->init_errlog_ptr; } else { @@ -607,7 +607,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans) IWL_ERR(trans, "Not valid error log pointer 0x%08X for %s uCode\n", base, - (trans->shrd->ucode_type == IWL_UCODE_INIT) + (priv->ucode_type == IWL_UCODE_INIT) ? "Init" : "RT"); return; } @@ -710,7 +710,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, return pos; base = priv->device_pointers.log_event_table; - if (trans->shrd->ucode_type == IWL_UCODE_INIT) { + if (priv->ucode_type == IWL_UCODE_INIT) { if (!base) base = priv->init_evtlog_ptr; } else { @@ -824,7 +824,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, struct iwl_priv *priv = priv(trans); base = priv->device_pointers.log_event_table; - if (trans->shrd->ucode_type == IWL_UCODE_INIT) { + if (priv->ucode_type == IWL_UCODE_INIT) { logsize = priv->init_evtlog_size; if (!base) base = priv->init_evtlog_ptr; @@ -838,7 +838,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, IWL_ERR(trans, "Invalid event log pointer 0x%08X for %s uCode\n", base, - (trans->shrd->ucode_type == IWL_UCODE_INIT) + (priv->ucode_type == IWL_UCODE_INIT) ? "Init" : "RT"); return -EINVAL; } diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 304b2ea0375c..5954fdfd60dd 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1100,21 +1100,13 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, hdr->seq_ctrl = hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(seq_number); + seq_number += 0x10; /* aggregation is on for this */ if (info->flags & IEEE80211_TX_CTL_AMPDU) { - if (WARN_ON_ONCE(tid_data->agg.state != IWL_AGG_ON)) { - IWL_ERR(trans, "TX_CTL_AMPDU while not in AGG:" - " Tx flags = 0x%08x, agg.state = %d", - info->flags, tid_data->agg.state); - IWL_ERR(trans, "sta_id = %d, tid = %d " - "txq_id = %d, seq_num = %d", sta_id, - tid, tid_data->agg.txq_id, - seq_number >> 4); - } + WARN_ON_ONCE(tid_data->agg.state != IWL_AGG_ON); txq_id = tid_data->agg.txq_id; is_agg = true; } - seq_number += 0x10; } /* Copy MAC header from skb into command buffer */ diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h index 4a29b8ab998e..50227ebc0ee2 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -220,6 +220,13 @@ struct fw_img { struct fw_desc data; /* firmware data image */ }; +enum iwl_ucode_type { + IWL_UCODE_NONE, + IWL_UCODE_REGULAR, + IWL_UCODE_INIT, + IWL_UCODE_WOWLAN, +}; + /** * struct iwl_trans - transport common data * @ops - pointer to iwl_trans_ops diff --git a/trunk/drivers/net/wireless/libertas/if_spi.c b/trunk/drivers/net/wireless/libertas/if_spi.c index 50b1ee7721e9..728baa445259 100644 --- a/trunk/drivers/net/wireless/libertas/if_spi.c +++ b/trunk/drivers/net/wireless/libertas/if_spi.c @@ -1291,6 +1291,7 @@ static struct spi_driver libertas_spi_driver = { .remove = __devexit_p(libertas_spi_remove), .driver = { .name = "libertas_spi", + .bus = &spi_bus_type, .owner = THIS_MODULE, .pm = &if_spi_pm_ops, }, diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.c b/trunk/drivers/net/wireless/mwifiex/cfg80211.c index 0db97cc84cb4..e9ab9a3fbe9c 100644 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.c +++ b/trunk/drivers/net/wireless/mwifiex/cfg80211.c @@ -120,11 +120,10 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, static int mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, - int mbm) + int dbm) { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); struct mwifiex_power_cfg power_cfg; - int dbm = MBM_TO_DBM(mbm); if (type == NL80211_TX_POWER_FIXED) { power_cfg.is_power_auto = 0; diff --git a/trunk/drivers/net/wireless/p54/p54spi.c b/trunk/drivers/net/wireless/p54/p54spi.c index 7faed62c6378..2d5cf5ba319b 100644 --- a/trunk/drivers/net/wireless/p54/p54spi.c +++ b/trunk/drivers/net/wireless/p54/p54spi.c @@ -700,6 +700,7 @@ static int __devexit p54spi_remove(struct spi_device *spi) static struct spi_driver p54spi_driver = { .driver = { .name = "p54spi", + .bus = &spi_bus_type, .owner = THIS_MODULE, }, diff --git a/trunk/drivers/net/wireless/prism54/isl_ioctl.c b/trunk/drivers/net/wireless/prism54/isl_ioctl.c index 4e44b1af119a..bc2ba80c47bb 100644 --- a/trunk/drivers/net/wireless/prism54/isl_ioctl.c +++ b/trunk/drivers/net/wireless/prism54/isl_ioctl.c @@ -2493,7 +2493,323 @@ prism54_set_mac_address(struct net_device *ndev, void *addr) return ret; } +/* Note: currently, use hostapd ioctl from the Host AP driver for WPA + * support. This is to be replaced with Linux wireless extensions once they + * get WPA support. */ + +/* Note II: please leave all this together as it will be easier to remove later, + * once wireless extensions add WPA support -mcgrof */ + +/* PRISM54_HOSTAPD ioctl() cmd: */ +enum { + PRISM2_SET_ENCRYPTION = 6, + PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12, + PRISM2_HOSTAPD_MLME = 13, + PRISM2_HOSTAPD_SCAN_REQ = 14, +}; + #define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12 +#define PRISM54_HOSTAPD SIOCIWFIRSTPRIV+25 +#define PRISM54_DROP_UNENCRYPTED SIOCIWFIRSTPRIV+26 + +#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 +#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ + offsetof(struct prism2_hostapd_param, u.generic_elem.data) + +/* Maximum length for algorithm names (-1 for nul termination) + * used in ioctl() */ +#define HOSTAP_CRYPT_ALG_NAME_LEN 16 + +struct prism2_hostapd_param { + u32 cmd; + u8 sta_addr[ETH_ALEN]; + union { + struct { + u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; + u32 flags; + u32 err; + u8 idx; + u8 seq[8]; /* sequence counter (set: RX, get: TX) */ + u16 key_len; + u8 key[0]; + } crypt; + struct { + u8 len; + u8 data[0]; + } generic_elem; + struct { +#define MLME_STA_DEAUTH 0 +#define MLME_STA_DISASSOC 1 + u16 cmd; + u16 reason_code; + } mlme; + struct { + u8 ssid_len; + u8 ssid[32]; + } scan_req; + } u; +}; + + +static int +prism2_ioctl_set_encryption(struct net_device *dev, + struct prism2_hostapd_param *param, + int param_len) +{ + islpci_private *priv = netdev_priv(dev); + int rvalue = 0, force = 0; + int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; + union oid_res_t r; + + /* with the new API, it's impossible to get a NULL pointer. + * New version of iwconfig set the IW_ENCODE_NOKEY flag + * when no key is given, but older versions don't. */ + + if (param->u.crypt.key_len > 0) { + /* we have a key to set */ + int index = param->u.crypt.idx; + int current_index; + struct obj_key key = { DOT11_PRIV_TKIP, 0, "" }; + + /* get the current key index */ + rvalue = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); + current_index = r.u; + /* Verify that the key is not marked as invalid */ + if (!(param->u.crypt.flags & IW_ENCODE_NOKEY)) { + key.length = param->u.crypt.key_len > sizeof (param->u.crypt.key) ? + sizeof (param->u.crypt.key) : param->u.crypt.key_len; + memcpy(key.key, param->u.crypt.key, key.length); + if (key.length == 32) + /* we want WPA-PSK */ + key.type = DOT11_PRIV_TKIP; + if ((index < 0) || (index > 3)) + /* no index provided use the current one */ + index = current_index; + + /* now send the key to the card */ + rvalue |= + mgt_set_request(priv, DOT11_OID_DEFKEYX, index, + &key); + } + /* + * If a valid key is set, encryption should be enabled + * (user may turn it off later). + * This is also how "iwconfig ethX key on" works + */ + if ((index == current_index) && (key.length > 0)) + force = 1; + } else { + int index = (param->u.crypt.flags & IW_ENCODE_INDEX) - 1; + if ((index >= 0) && (index <= 3)) { + /* we want to set the key index */ + rvalue |= + mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, + &index); + } else { + if (!(param->u.crypt.flags & IW_ENCODE_MODE)) { + /* we cannot do anything. Complain. */ + return -EINVAL; + } + } + } + /* now read the flags */ + if (param->u.crypt.flags & IW_ENCODE_DISABLED) { + /* Encoding disabled, + * authen = DOT11_AUTH_OS; + * invoke = 0; + * exunencrypt = 0; */ + } + if (param->u.crypt.flags & IW_ENCODE_OPEN) + /* Encode but accept non-encoded packets. No auth */ + invoke = 1; + if ((param->u.crypt.flags & IW_ENCODE_RESTRICTED) || force) { + /* Refuse non-encoded packets. Auth */ + authen = DOT11_AUTH_BOTH; + invoke = 1; + exunencrypt = 1; + } + /* do the change if requested */ + if ((param->u.crypt.flags & IW_ENCODE_MODE) || force) { + rvalue |= + mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); + rvalue |= + mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &invoke); + rvalue |= + mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, + &exunencrypt); + } + return rvalue; +} + +static int +prism2_ioctl_set_generic_element(struct net_device *ndev, + struct prism2_hostapd_param *param, + int param_len) +{ + islpci_private *priv = netdev_priv(ndev); + int max_len, len, alen, ret=0; + struct obj_attachment *attach; + + len = param->u.generic_elem.len; + max_len = param_len - PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN; + if (max_len < 0 || max_len < len) + return -EINVAL; + + alen = sizeof(*attach) + len; + attach = kzalloc(alen, GFP_KERNEL); + if (attach == NULL) + return -ENOMEM; + +#define WLAN_FC_TYPE_MGMT 0 +#define WLAN_FC_STYPE_ASSOC_REQ 0 +#define WLAN_FC_STYPE_REASSOC_REQ 2 + + /* Note: endianness is covered by mgt_set_varlen */ + + attach->type = (WLAN_FC_TYPE_MGMT << 2) | + (WLAN_FC_STYPE_ASSOC_REQ << 4); + attach->id = -1; + attach->size = len; + memcpy(attach->data, param->u.generic_elem.data, len); + + ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len); + + if (ret == 0) { + attach->type = (WLAN_FC_TYPE_MGMT << 2) | + (WLAN_FC_STYPE_REASSOC_REQ << 4); + + ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len); + + if (ret == 0) + printk(KERN_DEBUG "%s: WPA IE Attachment was set\n", + ndev->name); + } + + kfree(attach); + return ret; + +} + +static int +prism2_ioctl_mlme(struct net_device *dev, struct prism2_hostapd_param *param) +{ + return -EOPNOTSUPP; +} + +static int +prism2_ioctl_scan_req(struct net_device *ndev, + struct prism2_hostapd_param *param) +{ + islpci_private *priv = netdev_priv(ndev); + struct iw_request_info info; + int i, rvalue; + struct obj_bsslist *bsslist; + u32 noise = 0; + char *extra = ""; + char *current_ev = "foo"; + union oid_res_t r; + + if (islpci_get_state(priv) < PRV_STATE_INIT) { + /* device is not ready, fail gently */ + return 0; + } + + /* first get the noise value. We will use it to report the link quality */ + rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); + noise = r.u; + + /* Ask the device for a list of known bss. We can report at most + * IW_MAX_AP=64 to the range struct. But the device won't repport anything + * if you change the value of IWMAX_BSS=24. + */ + rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); + bsslist = r.ptr; + + info.cmd = PRISM54_HOSTAPD; + info.flags = 0; + + /* ok now, scan the list and translate its info */ + for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++) + current_ev = prism54_translate_bss(ndev, &info, current_ev, + extra + IW_SCAN_MAX_DATA, + &(bsslist->bsslist[i]), + noise); + kfree(bsslist); + + return rvalue; +} + +static int +prism54_hostapd(struct net_device *ndev, struct iw_point *p) +{ + struct prism2_hostapd_param *param; + int ret = 0; + u32 uwrq; + + printk(KERN_DEBUG "prism54_hostapd - len=%d\n", p->length); + if (p->length < sizeof(struct prism2_hostapd_param) || + p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) + return -EINVAL; + + param = memdup_user(p->pointer, p->length); + if (IS_ERR(param)) + return PTR_ERR(param); + + switch (param->cmd) { + case PRISM2_SET_ENCRYPTION: + printk(KERN_DEBUG "%s: Caught WPA supplicant set encryption request\n", + ndev->name); + ret = prism2_ioctl_set_encryption(ndev, param, p->length); + break; + case PRISM2_HOSTAPD_SET_GENERIC_ELEMENT: + printk(KERN_DEBUG "%s: Caught WPA supplicant set WPA IE request\n", + ndev->name); + ret = prism2_ioctl_set_generic_element(ndev, param, + p->length); + break; + case PRISM2_HOSTAPD_MLME: + printk(KERN_DEBUG "%s: Caught WPA supplicant MLME request\n", + ndev->name); + ret = prism2_ioctl_mlme(ndev, param); + break; + case PRISM2_HOSTAPD_SCAN_REQ: + printk(KERN_DEBUG "%s: Caught WPA supplicant scan request\n", + ndev->name); + ret = prism2_ioctl_scan_req(ndev, param); + break; + case PRISM54_SET_WPA: + printk(KERN_DEBUG "%s: Caught WPA supplicant wpa init request\n", + ndev->name); + uwrq = 1; + ret = prism54_set_wpa(ndev, NULL, &uwrq, NULL); + break; + case PRISM54_DROP_UNENCRYPTED: + printk(KERN_DEBUG "%s: Caught WPA drop unencrypted request\n", + ndev->name); +#if 0 + uwrq = 0x01; + mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &uwrq); + down_write(&priv->mib_sem); + mgt_commit(priv); + up_write(&priv->mib_sem); +#endif + /* Not necessary, as set_wpa does it, should we just do it here though? */ + ret = 0; + break; + default: + printk(KERN_DEBUG "%s: Caught a WPA supplicant request that is not supported\n", + ndev->name); + ret = -EOPNOTSUPP; + break; + } + + if (ret == 0 && copy_to_user(p->pointer, param, p->length)) + ret = -EFAULT; + + kfree(param); + + return ret; +} static int prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info, @@ -2907,3 +3223,20 @@ const struct iw_handler_def prism54_handler_def = { .private_args = (struct iw_priv_args *) prism54_private_args, .get_wireless_stats = prism54_get_wireless_stats, }; + +/* For wpa_supplicant */ + +int +prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) +{ + struct iwreq *wrq = (struct iwreq *) rq; + int ret = -1; + switch (cmd) { + case PRISM54_HOSTAPD: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + ret = prism54_hostapd(ndev, &wrq->u.data); + return ret; + } + return -EOPNOTSUPP; +} diff --git a/trunk/drivers/net/wireless/prism54/isl_ioctl.h b/trunk/drivers/net/wireless/prism54/isl_ioctl.h index a34bceb6e3cd..bcfbfb9281d2 100644 --- a/trunk/drivers/net/wireless/prism54/isl_ioctl.h +++ b/trunk/drivers/net/wireless/prism54/isl_ioctl.h @@ -43,6 +43,8 @@ void prism54_wpa_bss_ie_clean(islpci_private *priv); int prism54_set_mac_address(struct net_device *, void *); +int prism54_ioctl(struct net_device *, struct ifreq *, int); + extern const struct iw_handler_def prism54_handler_def; #endif /* _ISL_IOCTL_H */ diff --git a/trunk/drivers/net/wireless/prism54/islpci_dev.c b/trunk/drivers/net/wireless/prism54/islpci_dev.c index 5970ff6f40cc..8a3cf4fe376f 100644 --- a/trunk/drivers/net/wireless/prism54/islpci_dev.c +++ b/trunk/drivers/net/wireless/prism54/islpci_dev.c @@ -804,6 +804,7 @@ static const struct ethtool_ops islpci_ethtool_ops = { static const struct net_device_ops islpci_netdev_ops = { .ndo_open = islpci_open, .ndo_stop = islpci_close, + .ndo_do_ioctl = prism54_ioctl, .ndo_start_xmit = islpci_eth_transmit, .ndo_tx_timeout = islpci_eth_tx_timeout, .ndo_set_mac_address = prism54_set_mac_address, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c index e5df380d4fbe..1ba079dffb11 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1203,10 +1203,8 @@ void rt2800_config_filter(struct rt2x00_dev *rt2x00dev, !(filter_flags & FIF_CONTROL)); rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, !(filter_flags & FIF_PSPOLL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, - !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, !(filter_flags & FIF_CONTROL)); rt2800_register_write(rt2x00dev, RX_FILTER_CFG, reg); diff --git a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c index c3e1aa7c1a80..edd317fa7c0a 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -831,11 +831,11 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, if (spec->supported_rates & SUPPORT_RATE_OFDM) num_rates += 8; - channels = kcalloc(spec->num_channels, sizeof(*channels), GFP_KERNEL); + channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL); if (!channels) return -ENOMEM; - rates = kcalloc(num_rates, sizeof(*rates), GFP_KERNEL); + rates = kzalloc(sizeof(*rates) * num_rates, GFP_KERNEL); if (!rates) goto exit_free_channels; diff --git a/trunk/drivers/net/wireless/rtlwifi/pci.c b/trunk/drivers/net/wireless/rtlwifi/pci.c index 91f0525364ea..b6683a247b51 100644 --- a/trunk/drivers/net/wireless/rtlwifi/pci.c +++ b/trunk/drivers/net/wireless/rtlwifi/pci.c @@ -780,7 +780,6 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) unsigned long flags; u32 inta = 0; u32 intb = 0; - irqreturn_t ret = IRQ_HANDLED; spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); @@ -788,10 +787,8 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) rtlpriv->cfg->ops->interrupt_recognized(hw, &inta, &intb); /*Shared IRQ or HW disappared */ - if (!inta || inta == 0xffff) { - ret = IRQ_NONE; + if (!inta || inta == 0xffff) goto done; - } /*<1> beacon related */ if (inta & rtlpriv->cfg->maps[RTL_IMR_TBDOK]) { @@ -895,7 +892,7 @@ static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id) done: spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); - return ret; + return IRQ_HANDLED; } static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw) diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index 931d97979b04..fa393dfe136c 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -262,10 +262,10 @@ 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; - pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; pfwdata = (u8 *) rtlhal->pfirmware; fwsize = rtlhal->fwsize; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c index 3b585aadabfc..592a10ac5929 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c @@ -569,7 +569,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, } case ERFSLEEP:{ if (ppsc->rfpwr_state == ERFOFF) - return false; + break; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { ring = &pcipriv->dev.tx_ring[queue_id]; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c index e49cf2244c75..72852900df84 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c @@ -548,7 +548,7 @@ static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw, break; case ERFSLEEP: if (ppsc->rfpwr_state == ERFOFF) - return false; + break; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { ring = &pcipriv->dev.tx_ring[queue_id]; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/phy.c index 0883349e1c83..3ac7af1c5509 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/phy.c @@ -3374,7 +3374,7 @@ bool rtl92d_phy_set_rf_power_state(struct ieee80211_hw *hw, break; case ERFSLEEP: if (ppsc->rfpwr_state == ERFOFF) - return false; + break; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/phy.c index f10ac1ad9087..f27171af979c 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/phy.c @@ -602,7 +602,7 @@ bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, } case ERFSLEEP: if (ppsc->rfpwr_state == ERFOFF) - return false; + break; for (queue_id = 0, i = 0; queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { diff --git a/trunk/drivers/net/wireless/wl1251/spi.c b/trunk/drivers/net/wireless/wl1251/spi.c index 6248c354fc5c..eaa5f9556200 100644 --- a/trunk/drivers/net/wireless/wl1251/spi.c +++ b/trunk/drivers/net/wireless/wl1251/spi.c @@ -319,6 +319,7 @@ static int __devexit wl1251_spi_remove(struct spi_device *spi) static struct spi_driver wl1251_spi_driver = { .driver = { .name = DRIVER_NAME, + .bus = &spi_bus_type, .owner = THIS_MODULE, }, diff --git a/trunk/drivers/net/wireless/wl12xx/Kconfig b/trunk/drivers/net/wireless/wl12xx/Kconfig index af08c8609c63..3fe388b87c2e 100644 --- a/trunk/drivers/net/wireless/wl12xx/Kconfig +++ b/trunk/drivers/net/wireless/wl12xx/Kconfig @@ -42,6 +42,16 @@ config WL12XX_SDIO If you choose to build a module, it'll be called wl12xx_sdio. Say N if unsure. +config WL12XX_SDIO_TEST + tristate "TI wl12xx SDIO testing support" + depends on WL12XX && MMC && WL12XX_SDIO + default n + ---help--- + This module adds support for the SDIO bus testing with the + TI wl12xx chipsets. You probably don't want this unless you are + testing a new hardware platform. Select this if you want to test the + SDIO bus which is connected to the wl12xx chip. + config WL12XX_PLATFORM_DATA bool depends on WL12XX_SDIO != n || WL1251_SDIO != n diff --git a/trunk/drivers/net/wireless/wl12xx/Makefile b/trunk/drivers/net/wireless/wl12xx/Makefile index fe67262ba19f..621b3483ca2c 100644 --- a/trunk/drivers/net/wireless/wl12xx/Makefile +++ b/trunk/drivers/net/wireless/wl12xx/Makefile @@ -3,11 +3,14 @@ wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ wl12xx_spi-objs = spi.o wl12xx_sdio-objs = sdio.o +wl12xx_sdio_test-objs = sdio_test.o wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o obj-$(CONFIG_WL12XX) += wl12xx.o obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o +obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o + # small builtin driver bit obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o diff --git a/trunk/drivers/net/wireless/wl12xx/acx.c b/trunk/drivers/net/wireless/wl12xx/acx.c index bde1d862bdd5..ca044a743191 100644 --- a/trunk/drivers/net/wireless/wl12xx/acx.c +++ b/trunk/drivers/net/wireless/wl12xx/acx.c @@ -29,12 +29,11 @@ #include #include "wl12xx.h" -#include "debug.h" #include "wl12xx_80211.h" #include "reg.h" #include "ps.h" -int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl1271_acx_wake_up_conditions(struct wl1271 *wl) { struct acx_wake_up_condition *wake_up; int ret; @@ -47,7 +46,7 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out; } - wake_up->role_id = wlvif->role_id; + wake_up->role_id = wl->role_id; wake_up->wake_up_event = wl->conf.conn.wake_up_event; wake_up->listen_interval = wl->conf.conn.listen_interval; @@ -85,8 +84,7 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth) return ret; } -int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif, - int power) +int wl1271_acx_tx_power(struct wl1271 *wl, int power) { struct acx_current_tx_power *acx; int ret; @@ -102,7 +100,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->current_tx_power = power * 10; ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); @@ -116,7 +114,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_acx_feature_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl1271_acx_feature_cfg(struct wl1271 *wl) { struct acx_feature_config *feature; int ret; @@ -130,7 +128,7 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif) } /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ - feature->role_id = wlvif->role_id; + feature->role_id = wl->role_id; feature->data_flow_options = 0; feature->options = 0; @@ -212,8 +210,7 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl) return ret; } -int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif, - enum acx_slot_type slot_time) +int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) { struct acx_slot *slot; int ret; @@ -226,7 +223,7 @@ int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - slot->role_id = wlvif->role_id; + slot->role_id = wl->role_id; slot->wone_index = STATION_WONE_INDEX; slot->slot_time = slot_time; @@ -241,8 +238,8 @@ int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_acx_group_address_tbl(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable, void *mc_list, u32 mc_list_len) +int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, + void *mc_list, u32 mc_list_len) { struct acx_dot11_grp_addr_tbl *acx; int ret; @@ -256,7 +253,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, struct wl12xx_vif *wlvif, } /* MAC filtering */ - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->enabled = enable; acx->num_groups = mc_list_len; memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN); @@ -273,8 +270,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_acx_service_period_timeout(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +int wl1271_acx_service_period_timeout(struct wl1271 *wl) { struct acx_rx_timeout *rx_timeout; int ret; @@ -287,7 +283,7 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl, wl1271_debug(DEBUG_ACX, "acx service period timeout"); - rx_timeout->role_id = wlvif->role_id; + rx_timeout->role_id = wl->role_id; rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout); rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout); @@ -304,8 +300,7 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl, return ret; } -int wl1271_acx_rts_threshold(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u32 rts_threshold) +int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold) { struct acx_rts_threshold *rts; int ret; @@ -325,7 +320,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - rts->role_id = wlvif->role_id; + rts->role_id = wl->role_id; rts->threshold = cpu_to_le16((u16)rts_threshold); ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); @@ -368,8 +363,7 @@ int wl1271_acx_dco_itrim_params(struct wl1271 *wl) return ret; } -int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable_filter) +int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) { struct acx_beacon_filter_option *beacon_filter = NULL; int ret = 0; @@ -386,7 +380,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - beacon_filter->role_id = wlvif->role_id; + beacon_filter->role_id = wl->role_id; beacon_filter->enable = enable_filter; /* @@ -407,8 +401,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_acx_beacon_filter_table(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +int wl1271_acx_beacon_filter_table(struct wl1271 *wl) { struct acx_beacon_filter_ie_table *ie_table; int i, idx = 0; @@ -424,7 +417,7 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl, } /* configure default beacon pass-through rules */ - ie_table->role_id = wlvif->role_id; + ie_table->role_id = wl->role_id; ie_table->num_ie = 0; for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) { struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]); @@ -465,8 +458,7 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl, #define ACX_CONN_MONIT_DISABLE_VALUE 0xffffffff -int wl1271_acx_conn_monit_params(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable) +int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable) { struct acx_conn_monit_params *acx; u32 threshold = ACX_CONN_MONIT_DISABLE_VALUE; @@ -487,7 +479,7 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl, struct wl12xx_vif *wlvif, timeout = wl->conf.conn.bss_lose_timeout; } - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->synch_fail_thold = cpu_to_le32(threshold); acx->bss_lose_timeout = cpu_to_le32(timeout); @@ -590,7 +582,7 @@ int wl1271_acx_cca_threshold(struct wl1271 *wl) return ret; } -int wl1271_acx_bcn_dtim_options(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl1271_acx_bcn_dtim_options(struct wl1271 *wl) { struct acx_beacon_broadcast *bb; int ret; @@ -603,7 +595,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out; } - bb->role_id = wlvif->role_id; + bb->role_id = wl->role_id; bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout); bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout); bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps; @@ -620,7 +612,7 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl, struct wl12xx_vif *wlvif) return ret; } -int wl1271_acx_aid(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 aid) +int wl1271_acx_aid(struct wl1271 *wl, u16 aid) { struct acx_aid *acx_aid; int ret; @@ -633,7 +625,7 @@ int wl1271_acx_aid(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 aid) goto out; } - acx_aid->role_id = wlvif->role_id; + acx_aid->role_id = wl->role_id; acx_aid->aid = cpu_to_le16(aid); ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); @@ -676,8 +668,7 @@ int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask) return ret; } -int wl1271_acx_set_preamble(struct wl1271 *wl, struct wl12xx_vif *wlvif, - enum acx_preamble_type preamble) +int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble) { struct acx_preamble *acx; int ret; @@ -690,7 +681,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->preamble = preamble; ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx)); @@ -704,7 +695,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_acx_cts_protect(struct wl1271 *wl, struct wl12xx_vif *wlvif, +int wl1271_acx_cts_protect(struct wl1271 *wl, enum acx_ctsprotect_type ctsprotect) { struct acx_ctsprotect *acx; @@ -718,7 +709,7 @@ int wl1271_acx_cts_protect(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->ctsprotect = ctsprotect; ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx)); @@ -748,7 +739,7 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) return 0; } -int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl1271_acx_sta_rate_policies(struct wl1271 *wl) { struct acx_rate_policy *acx; struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf; @@ -764,11 +755,11 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) } wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x", - wlvif->basic_rate, wlvif->rate_set); + wl->basic_rate, wl->rate_set); /* configure one basic rate class */ - acx->rate_policy_idx = cpu_to_le32(wlvif->sta.basic_rate_idx); - acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->basic_rate); + acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE); + acx->rate_policy.enabled_rates = cpu_to_le32(wl->basic_rate); acx->rate_policy.short_retry_limit = c->short_retry_limit; acx->rate_policy.long_retry_limit = c->long_retry_limit; acx->rate_policy.aflags = c->aflags; @@ -780,8 +771,8 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) } /* configure one AP supported rate class */ - acx->rate_policy_idx = cpu_to_le32(wlvif->sta.ap_rate_idx); - acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->rate_set); + acx->rate_policy_idx = cpu_to_le32(ACX_TX_AP_FULL_RATE); + acx->rate_policy.enabled_rates = cpu_to_le32(wl->rate_set); acx->rate_policy.short_retry_limit = c->short_retry_limit; acx->rate_policy.long_retry_limit = c->long_retry_limit; acx->rate_policy.aflags = c->aflags; @@ -797,7 +788,7 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) * (p2p packets should always go out with OFDM rates, even * if we are currently connected to 11b AP) */ - acx->rate_policy_idx = cpu_to_le32(wlvif->sta.p2p_rate_idx); + acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE_P2P); acx->rate_policy.enabled_rates = cpu_to_le32(CONF_TX_RATE_MASK_BASIC_P2P); acx->rate_policy.short_retry_limit = c->short_retry_limit; @@ -848,8 +839,8 @@ int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, return ret; } -int wl1271_acx_ac_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 ac, u8 cw_min, u16 cw_max, u8 aifsn, u16 txop) +int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, + u8 aifsn, u16 txop) { struct acx_ac_cfg *acx; int ret = 0; @@ -864,7 +855,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->ac = ac; acx->cw_min = cw_min; acx->cw_max = cpu_to_le16(cw_max); @@ -882,8 +873,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_acx_tid_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 queue_id, u8 channel_type, +int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, u8 tsid, u8 ps_scheme, u8 ack_policy, u32 apsd_conf0, u32 apsd_conf1) { @@ -899,7 +889,7 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->queue_id = queue_id; acx->channel_type = channel_type; acx->tsid = tsid; @@ -1108,8 +1098,7 @@ int wl1271_acx_init_rx_interrupt(struct wl1271 *wl) return ret; } -int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable) +int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) { struct wl1271_acx_bet_enable *acx = NULL; int ret = 0; @@ -1125,7 +1114,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE; acx->max_consecutive = wl->conf.conn.bet_max_consecutive; @@ -1140,8 +1129,7 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_acx_arp_ip_filter(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 enable, __be32 address) +int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address) { struct wl1271_acx_arp_filter *acx; int ret; @@ -1154,7 +1142,7 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->version = ACX_IPV4_VERSION; acx->enable = enable; @@ -1201,8 +1189,7 @@ int wl1271_acx_pm_config(struct wl1271 *wl) return ret; } -int wl1271_acx_keep_alive_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable) +int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) { struct wl1271_acx_keep_alive_mode *acx = NULL; int ret = 0; @@ -1215,7 +1202,7 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->enabled = enable; ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx)); @@ -1229,8 +1216,7 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_acx_keep_alive_config(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 index, u8 tpl_valid) +int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) { struct wl1271_acx_keep_alive_config *acx = NULL; int ret = 0; @@ -1243,7 +1229,7 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval); acx->index = index; acx->tpl_validation = tpl_valid; @@ -1261,8 +1247,8 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable, s16 thold, u8 hyst) +int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, + s16 thold, u8 hyst) { struct wl1271_acx_rssi_snr_trigger *acx = NULL; int ret = 0; @@ -1275,9 +1261,9 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - wlvif->last_rssi_event = -1; + wl->last_rssi_event = -1; - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing); acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON; acx->type = WL1271_ACX_TRIG_TYPE_EDGE; @@ -1302,8 +1288,7 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl) { struct wl1271_acx_rssi_snr_avg_weights *acx = NULL; struct conf_roam_trigger_settings *c = &wl->conf.roam_trigger; @@ -1317,7 +1302,7 @@ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl, goto out; } - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->rssi_beacon = c->avg_weight_rssi_beacon; acx->rssi_data = c->avg_weight_rssi_data; acx->snr_beacon = c->avg_weight_snr_beacon; @@ -1382,7 +1367,6 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, } int wl1271_acx_set_ht_information(struct wl1271 *wl, - struct wl12xx_vif *wlvif, u16 ht_operation_mode) { struct wl1271_acx_ht_information *acx; @@ -1396,7 +1380,7 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl, goto out; } - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->ht_protection = (u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION); acx->rifs_mode = 0; @@ -1418,8 +1402,7 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl, } /* Configure BA session initiator/receiver parameters setting in the FW. */ -int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl) { struct wl1271_acx_ba_initiator_policy *acx; int ret; @@ -1433,7 +1416,7 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl, } /* set for the current role */ - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->tid_bitmap = wl->conf.ht.tx_ba_tid_bitmap; acx->win_size = wl->conf.ht.tx_ba_win_size; acx->inactivity_timeout = wl->conf.ht.inactivity_timeout; @@ -1511,8 +1494,7 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) return ret; } -int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable) +int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable) { struct wl1271_acx_ps_rx_streaming *rx_streaming; u32 conf_queues, enable_queues; @@ -1541,7 +1523,7 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (!(conf_queues & BIT(i))) continue; - rx_streaming->role_id = wlvif->role_id; + rx_streaming->role_id = wl->role_id; rx_streaming->tid = i; rx_streaming->enable = enable_queues & BIT(i); rx_streaming->period = wl->conf.rx_streaming.interval; @@ -1560,7 +1542,7 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) { struct wl1271_acx_ap_max_tx_retry *acx = NULL; int ret; @@ -1571,7 +1553,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif) if (!acx) return -ENOMEM; - acx->role_id = wlvif->role_id; + acx->role_id = wl->role_id; acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); @@ -1585,7 +1567,7 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif) return ret; } -int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl1271_acx_config_ps(struct wl1271 *wl) { struct wl1271_acx_config_ps *config_ps; int ret; @@ -1600,7 +1582,7 @@ int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif) config_ps->exit_retries = wl->conf.conn.psm_exit_retries; config_ps->enter_retries = wl->conf.conn.psm_entry_retries; - config_ps->null_data_rate = cpu_to_le32(wlvif->basic_rate); + config_ps->null_data_rate = cpu_to_le32(wl->basic_rate); ret = wl1271_cmd_configure(wl, ACX_CONFIG_PS, config_ps, sizeof(*config_ps)); diff --git a/trunk/drivers/net/wireless/wl12xx/acx.h b/trunk/drivers/net/wireless/wl12xx/acx.h index b2d85bea6378..e3f93b4b3429 100644 --- a/trunk/drivers/net/wireless/wl12xx/acx.h +++ b/trunk/drivers/net/wireless/wl12xx/acx.h @@ -654,6 +654,11 @@ struct acx_rate_class { u8 reserved; }; +#define ACX_TX_BASIC_RATE 0 +#define ACX_TX_AP_FULL_RATE 1 +#define ACX_TX_BASIC_RATE_P2P 2 +#define ACX_TX_AP_MODE_MGMT_RATE 4 +#define ACX_TX_AP_MODE_BCST_RATE 5 struct acx_rate_policy { struct acx_header header; @@ -1229,49 +1234,39 @@ enum { }; -int wl1271_acx_wake_up_conditions(struct wl1271 *wl, - struct wl12xx_vif *wlvif); +int wl1271_acx_wake_up_conditions(struct wl1271 *wl); int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); -int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif, - int power); -int wl1271_acx_feature_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif); +int wl1271_acx_tx_power(struct wl1271 *wl, int power); +int wl1271_acx_feature_cfg(struct wl1271 *wl); int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map, size_t len); int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl); int wl1271_acx_pd_threshold(struct wl1271 *wl); -int wl1271_acx_slot(struct wl1271 *wl, struct wl12xx_vif *wlvif, - enum acx_slot_type slot_time); -int wl1271_acx_group_address_tbl(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable, void *mc_list, u32 mc_list_len); -int wl1271_acx_service_period_timeout(struct wl1271 *wl, - struct wl12xx_vif *wlvif); -int wl1271_acx_rts_threshold(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u32 rts_threshold); +int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time); +int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, + void *mc_list, u32 mc_list_len); +int wl1271_acx_service_period_timeout(struct wl1271 *wl); +int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold); int wl1271_acx_dco_itrim_params(struct wl1271 *wl); -int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable_filter); -int wl1271_acx_beacon_filter_table(struct wl1271 *wl, - struct wl12xx_vif *wlvif); -int wl1271_acx_conn_monit_params(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable); +int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); +int wl1271_acx_beacon_filter_table(struct wl1271 *wl); +int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); int wl12xx_acx_sg_cfg(struct wl1271 *wl); int wl1271_acx_cca_threshold(struct wl1271 *wl); -int wl1271_acx_bcn_dtim_options(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl1271_acx_aid(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 aid); +int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); +int wl1271_acx_aid(struct wl1271 *wl, u16 aid); int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask); -int wl1271_acx_set_preamble(struct wl1271 *wl, struct wl12xx_vif *wlvif, - enum acx_preamble_type preamble); -int wl1271_acx_cts_protect(struct wl1271 *wl, struct wl12xx_vif *wlvif, +int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); +int wl1271_acx_cts_protect(struct wl1271 *wl, enum acx_ctsprotect_type ctsprotect); int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); -int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif); +int wl1271_acx_sta_rate_policies(struct wl1271 *wl); int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, u8 idx); -int wl1271_acx_ac_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 ac, u8 cw_min, u16 cw_max, u8 aifsn, u16 txop); -int wl1271_acx_tid_cfg(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 queue_id, u8 channel_type, +int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, + u8 aifsn, u16 txop); +int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, u8 tsid, u8 ps_scheme, u8 ack_policy, u32 apsd_conf0, u32 apsd_conf1); int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold); @@ -1281,34 +1276,26 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl); int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap); int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); int wl1271_acx_smart_reflex(struct wl1271 *wl); -int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable); -int wl1271_acx_arp_ip_filter(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 enable, __be32 address); +int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); +int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address); int wl1271_acx_pm_config(struct wl1271 *wl); -int wl1271_acx_keep_alive_mode(struct wl1271 *wl, struct wl12xx_vif *vif, - bool enable); -int wl1271_acx_keep_alive_config(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 index, u8 tpl_valid); -int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable, s16 thold, u8 hyst); -int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl, - struct wl12xx_vif *wlvif); +int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); +int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); +int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, + s16 thold, u8 hyst); +int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, struct ieee80211_sta_ht_cap *ht_cap, bool allow_ht_operation, u8 hlid); int wl1271_acx_set_ht_information(struct wl1271 *wl, - struct wl12xx_vif *wlvif, u16 ht_operation_mode); -int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl, - struct wl12xx_vif *wlvif); +int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl); int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, bool enable, u8 peer_hlid); int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); -int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable); -int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl12xx_acx_config_ps(struct wl1271 *wl, struct wl12xx_vif *wlvif); +int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable); +int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); +int wl1271_acx_config_ps(struct wl1271 *wl); int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); int wl1271_acx_fm_coex(struct wl1271 *wl); int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); diff --git a/trunk/drivers/net/wireless/wl12xx/boot.c b/trunk/drivers/net/wireless/wl12xx/boot.c index 8f9cf5a816ea..681337914976 100644 --- a/trunk/drivers/net/wireless/wl12xx/boot.c +++ b/trunk/drivers/net/wireless/wl12xx/boot.c @@ -25,7 +25,6 @@ #include #include -#include "debug.h" #include "acx.h" #include "reg.h" #include "boot.h" @@ -348,9 +347,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) nvs_ptr += 3; for (i = 0; i < burst_len; i++) { - if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len) - goto out_badnvs; - val = (nvs_ptr[0] | (nvs_ptr[1] << 8) | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); @@ -362,9 +358,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) nvs_ptr += 4; dest_addr += 4; } - - if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) - goto out_badnvs; } /* @@ -376,10 +369,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) */ nvs_ptr = (u8 *)wl->nvs + ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4); - - if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) - goto out_badnvs; - nvs_len -= nvs_ptr - (u8 *)wl->nvs; /* Now we must set the partition correctly */ @@ -395,10 +384,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) kfree(nvs_aligned); return 0; - -out_badnvs: - wl1271_error("nvs data is malformed"); - return -EILSEQ; } static void wl1271_boot_enable_interrupts(struct wl1271 *wl) diff --git a/trunk/drivers/net/wireless/wl12xx/cmd.c b/trunk/drivers/net/wireless/wl12xx/cmd.c index e0d217979485..a52299e548fa 100644 --- a/trunk/drivers/net/wireless/wl12xx/cmd.c +++ b/trunk/drivers/net/wireless/wl12xx/cmd.c @@ -29,7 +29,6 @@ #include #include "wl12xx.h" -#include "debug.h" #include "reg.h" #include "io.h" #include "acx.h" @@ -121,11 +120,6 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) if (!wl->nvs) return -ENODEV; - if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { - wl1271_warning("FEM index from INI out of bounds"); - return -EINVAL; - } - gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); if (!gen_parms) return -ENOMEM; @@ -149,12 +143,6 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) gp->tx_bip_fem_manufacturer = gen_parms->general_params.tx_bip_fem_manufacturer; - if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { - wl1271_warning("FEM index from FW out of bounds"); - ret = -EINVAL; - goto out; - } - wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); @@ -174,11 +162,6 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) if (!wl->nvs) return -ENODEV; - if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { - wl1271_warning("FEM index from ini out of bounds"); - return -EINVAL; - } - gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); if (!gen_parms) return -ENOMEM; @@ -203,12 +186,6 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) gp->tx_bip_fem_manufacturer = gen_parms->general_params.tx_bip_fem_manufacturer; - if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { - wl1271_warning("FEM index from FW out of bounds"); - ret = -EINVAL; - goto out; - } - wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); @@ -381,8 +358,7 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) return 0; } -int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, - u8 *role_id) +int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id) { struct wl12xx_cmd_role_enable *cmd; int ret; @@ -405,7 +381,7 @@ int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, goto out_free; } - memcpy(cmd->mac_address, addr, ETH_ALEN); + memcpy(cmd->mac_address, wl->mac_addr, ETH_ALEN); cmd->role_type = role_type; ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0); @@ -457,41 +433,37 @@ int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id) return ret; } -int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) +static int wl12xx_allocate_link(struct wl1271 *wl, u8 *hlid) { u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS); if (link >= WL12XX_MAX_LINKS) return -EBUSY; __set_bit(link, wl->links_map); - __set_bit(link, wlvif->links_map); *hlid = link; return 0; } -void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid) +static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid) { if (*hlid == WL12XX_INVALID_LINK_ID) return; __clear_bit(*hlid, wl->links_map); - __clear_bit(*hlid, wlvif->links_map); *hlid = WL12XX_INVALID_LINK_ID; } -static int wl12xx_get_new_session_id(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static int wl12xx_get_new_session_id(struct wl1271 *wl) { - if (wlvif->session_counter >= SESSION_COUNTER_MAX) - wlvif->session_counter = 0; + if (wl->session_counter >= SESSION_COUNTER_MAX) + wl->session_counter = 0; - wlvif->session_counter++; + wl->session_counter++; - return wlvif->session_counter; + return wl->session_counter; } -static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +int wl12xx_cmd_role_start_dev(struct wl1271 *wl) { struct wl12xx_cmd_role_start *cmd; int ret; @@ -502,20 +474,20 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, goto out; } - wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wlvif->dev_role_id); + wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wl->dev_role_id); - cmd->role_id = wlvif->dev_role_id; - if (wlvif->band == IEEE80211_BAND_5GHZ) + cmd->role_id = wl->dev_role_id; + if (wl->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; - cmd->channel = wlvif->channel; + cmd->channel = wl->channel; - if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) { - ret = wl12xx_allocate_link(wl, wlvif, &wlvif->dev_hlid); + if (wl->dev_hlid == WL12XX_INVALID_LINK_ID) { + ret = wl12xx_allocate_link(wl, &wl->dev_hlid); if (ret) goto out_free; } - cmd->device.hlid = wlvif->dev_hlid; - cmd->device.session = wlvif->session_counter; + cmd->device.hlid = wl->dev_hlid; + cmd->device.session = wl->session_counter; wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d", cmd->role_id, cmd->device.hlid, cmd->device.session); @@ -530,7 +502,9 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, err_hlid: /* clear links on error */ - wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid); + __clear_bit(wl->dev_hlid, wl->links_map); + wl->dev_hlid = WL12XX_INVALID_LINK_ID; + out_free: kfree(cmd); @@ -539,13 +513,12 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, return ret; } -static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +int wl12xx_cmd_role_stop_dev(struct wl1271 *wl) { struct wl12xx_cmd_role_stop *cmd; int ret; - if (WARN_ON(wlvif->dev_hlid == WL12XX_INVALID_LINK_ID)) + if (WARN_ON(wl->dev_hlid == WL12XX_INVALID_LINK_ID)) return -EINVAL; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -556,7 +529,7 @@ static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, wl1271_debug(DEBUG_CMD, "cmd role stop dev"); - cmd->role_id = wlvif->dev_role_id; + cmd->role_id = wl->dev_role_id; cmd->disc_type = DISCONNECT_IMMEDIATE; cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); @@ -572,7 +545,7 @@ static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, goto out_free; } - wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid); + wl12xx_free_link(wl, &wl->dev_hlid); out_free: kfree(cmd); @@ -581,9 +554,8 @@ static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, return ret; } -int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl12xx_cmd_role_start_sta(struct wl1271 *wl) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct wl12xx_cmd_role_start *cmd; int ret; @@ -593,33 +565,33 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out; } - wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wlvif->role_id); + wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wl->role_id); - cmd->role_id = wlvif->role_id; - if (wlvif->band == IEEE80211_BAND_5GHZ) + cmd->role_id = wl->role_id; + if (wl->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; - cmd->channel = wlvif->channel; - cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); - cmd->sta.beacon_interval = cpu_to_le16(wlvif->beacon_int); + cmd->channel = wl->channel; + cmd->sta.basic_rate_set = cpu_to_le32(wl->basic_rate_set); + cmd->sta.beacon_interval = cpu_to_le16(wl->beacon_int); cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY; - cmd->sta.ssid_len = wlvif->ssid_len; - memcpy(cmd->sta.ssid, wlvif->ssid, wlvif->ssid_len); - memcpy(cmd->sta.bssid, vif->bss_conf.bssid, ETH_ALEN); - cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); + cmd->sta.ssid_len = wl->ssid_len; + memcpy(cmd->sta.ssid, wl->ssid, wl->ssid_len); + memcpy(cmd->sta.bssid, wl->bssid, ETH_ALEN); + cmd->sta.local_rates = cpu_to_le32(wl->rate_set); - if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { - ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid); + if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { + ret = wl12xx_allocate_link(wl, &wl->sta_hlid); if (ret) goto out_free; } - cmd->sta.hlid = wlvif->sta.hlid; - cmd->sta.session = wl12xx_get_new_session_id(wl, wlvif); - cmd->sta.remote_rates = cpu_to_le32(wlvif->rate_set); + cmd->sta.hlid = wl->sta_hlid; + cmd->sta.session = wl12xx_get_new_session_id(wl); + cmd->sta.remote_rates = cpu_to_le32(wl->rate_set); wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " "basic_rate_set: 0x%x, remote_rates: 0x%x", - wlvif->role_id, cmd->sta.hlid, cmd->sta.session, - wlvif->basic_rate_set, wlvif->rate_set); + wl->role_id, cmd->sta.hlid, cmd->sta.session, + wl->basic_rate_set, wl->rate_set); ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); if (ret < 0) { @@ -631,7 +603,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) err_hlid: /* clear links on error. */ - wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); + wl12xx_free_link(wl, &wl->sta_hlid); out_free: kfree(cmd); @@ -641,12 +613,12 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) } /* use this function to stop ibss as well */ -int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl12xx_cmd_role_stop_sta(struct wl1271 *wl) { struct wl12xx_cmd_role_stop *cmd; int ret; - if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID)) + if (WARN_ON(wl->sta_hlid == WL12XX_INVALID_LINK_ID)) return -EINVAL; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -655,9 +627,9 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out; } - wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wlvif->role_id); + wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wl->role_id); - cmd->role_id = wlvif->role_id; + cmd->role_id = wl->role_id; cmd->disc_type = DISCONNECT_IMMEDIATE; cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); @@ -667,7 +639,7 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; } - wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); + wl12xx_free_link(wl, &wl->sta_hlid); out_free: kfree(cmd); @@ -676,17 +648,16 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) return ret; } -int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl12xx_cmd_role_start_ap(struct wl1271 *wl) { struct wl12xx_cmd_role_start *cmd; - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; int ret; - wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wlvif->role_id); + wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id); /* trying to use hidden SSID with an old hostapd version */ - if (wlvif->ssid_len == 0 && !bss_conf->hidden_ssid) { + if (wl->ssid_len == 0 && !bss_conf->hidden_ssid) { wl1271_error("got a null SSID from beacon/bss"); ret = -EINVAL; goto out; @@ -698,30 +669,30 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out; } - ret = wl12xx_allocate_link(wl, wlvif, &wlvif->ap.global_hlid); + ret = wl12xx_allocate_link(wl, &wl->ap_global_hlid); if (ret < 0) goto out_free; - ret = wl12xx_allocate_link(wl, wlvif, &wlvif->ap.bcast_hlid); + ret = wl12xx_allocate_link(wl, &wl->ap_bcast_hlid); if (ret < 0) goto out_free_global; - cmd->role_id = wlvif->role_id; + cmd->role_id = wl->role_id; cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); cmd->ap.bss_index = WL1271_AP_BSS_INDEX; - cmd->ap.global_hlid = wlvif->ap.global_hlid; - cmd->ap.broadcast_hlid = wlvif->ap.bcast_hlid; - cmd->ap.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); - cmd->ap.beacon_interval = cpu_to_le16(wlvif->beacon_int); + cmd->ap.global_hlid = wl->ap_global_hlid; + cmd->ap.broadcast_hlid = wl->ap_bcast_hlid; + cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set); + cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int); cmd->ap.dtim_interval = bss_conf->dtim_period; cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; - cmd->channel = wlvif->channel; + cmd->channel = wl->channel; if (!bss_conf->hidden_ssid) { /* take the SSID from the beacon for backward compatibility */ cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC; - cmd->ap.ssid_len = wlvif->ssid_len; - memcpy(cmd->ap.ssid, wlvif->ssid, wlvif->ssid_len); + cmd->ap.ssid_len = wl->ssid_len; + memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len); } else { cmd->ap.ssid_type = WL12XX_SSID_TYPE_HIDDEN; cmd->ap.ssid_len = bss_conf->ssid_len; @@ -730,7 +701,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->ap.local_rates = cpu_to_le32(0xffffffff); - switch (wlvif->band) { + switch (wl->band) { case IEEE80211_BAND_2GHZ: cmd->band = RADIO_BAND_2_4GHZ; break; @@ -738,7 +709,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->band = RADIO_BAND_5GHZ; break; default: - wl1271_warning("ap start - unknown band: %d", (int)wlvif->band); + wl1271_warning("ap start - unknown band: %d", (int)wl->band); cmd->band = RADIO_BAND_2_4GHZ; break; } @@ -752,10 +723,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; out_free_bcast: - wl12xx_free_link(wl, wlvif, &wlvif->ap.bcast_hlid); + wl12xx_free_link(wl, &wl->ap_bcast_hlid); out_free_global: - wl12xx_free_link(wl, wlvif, &wlvif->ap.global_hlid); + wl12xx_free_link(wl, &wl->ap_global_hlid); out_free: kfree(cmd); @@ -764,7 +735,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) return ret; } -int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl12xx_cmd_role_stop_ap(struct wl1271 *wl) { struct wl12xx_cmd_role_stop *cmd; int ret; @@ -775,9 +746,9 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out; } - wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wlvif->role_id); + wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wl->role_id); - cmd->role_id = wlvif->role_id; + cmd->role_id = wl->role_id; ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); if (ret < 0) { @@ -785,8 +756,8 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out_free; } - wl12xx_free_link(wl, wlvif, &wlvif->ap.bcast_hlid); - wl12xx_free_link(wl, wlvif, &wlvif->ap.global_hlid); + wl12xx_free_link(wl, &wl->ap_bcast_hlid); + wl12xx_free_link(wl, &wl->ap_global_hlid); out_free: kfree(cmd); @@ -795,11 +766,10 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) return ret; } -int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl12xx_cmd_role_start_ibss(struct wl1271 *wl) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct wl12xx_cmd_role_start *cmd; - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; int ret; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -808,36 +778,35 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) goto out; } - wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wlvif->role_id); + wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wl->role_id); - cmd->role_id = wlvif->role_id; - if (wlvif->band == IEEE80211_BAND_5GHZ) + cmd->role_id = wl->role_id; + if (wl->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; - cmd->channel = wlvif->channel; - cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); - cmd->ibss.beacon_interval = cpu_to_le16(wlvif->beacon_int); + cmd->channel = wl->channel; + cmd->ibss.basic_rate_set = cpu_to_le32(wl->basic_rate_set); + cmd->ibss.beacon_interval = cpu_to_le16(wl->beacon_int); cmd->ibss.dtim_interval = bss_conf->dtim_period; cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY; - cmd->ibss.ssid_len = wlvif->ssid_len; - memcpy(cmd->ibss.ssid, wlvif->ssid, wlvif->ssid_len); - memcpy(cmd->ibss.bssid, vif->bss_conf.bssid, ETH_ALEN); - cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); + cmd->ibss.ssid_len = wl->ssid_len; + memcpy(cmd->ibss.ssid, wl->ssid, wl->ssid_len); + memcpy(cmd->ibss.bssid, wl->bssid, ETH_ALEN); + cmd->sta.local_rates = cpu_to_le32(wl->rate_set); - if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { - ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid); + if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { + ret = wl12xx_allocate_link(wl, &wl->sta_hlid); if (ret) goto out_free; } - cmd->ibss.hlid = wlvif->sta.hlid; - cmd->ibss.remote_rates = cpu_to_le32(wlvif->rate_set); + cmd->ibss.hlid = wl->sta_hlid; + cmd->ibss.remote_rates = cpu_to_le32(wl->rate_set); wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " "basic_rate_set: 0x%x, remote_rates: 0x%x", - wlvif->role_id, cmd->sta.hlid, cmd->sta.session, - wlvif->basic_rate_set, wlvif->rate_set); + wl->role_id, cmd->sta.hlid, cmd->sta.session, + wl->basic_rate_set, wl->rate_set); - wl1271_debug(DEBUG_CMD, "vif->bss_conf.bssid = %pM", - vif->bss_conf.bssid); + wl1271_debug(DEBUG_CMD, "wl->bssid = %pM", wl->bssid); ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); if (ret < 0) { @@ -849,7 +818,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif) err_hlid: /* clear links on error. */ - wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); + wl12xx_free_link(wl, &wl->sta_hlid); out_free: kfree(cmd); @@ -993,8 +962,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) return ret; } -int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 ps_mode) +int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) { struct wl1271_cmd_ps_params *ps_params = NULL; int ret = 0; @@ -1007,7 +975,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - ps_params->role_id = wlvif->role_id; + ps_params->role_id = wl->role_id; ps_params->ps_mode = ps_mode; ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, @@ -1062,7 +1030,7 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, return ret; } -int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl1271_cmd_build_null_data(struct wl1271 *wl) { struct sk_buff *skb = NULL; int size; @@ -1070,12 +1038,11 @@ int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif) int ret = -ENOMEM; - if (wlvif->bss_type == BSS_TYPE_IBSS) { + if (wl->bss_type == BSS_TYPE_IBSS) { size = sizeof(struct wl12xx_null_data_template); ptr = NULL; } else { - skb = ieee80211_nullfunc_get(wl->hw, - wl12xx_wlvif_to_vif(wlvif)); + skb = ieee80211_nullfunc_get(wl->hw, wl->vif); if (!skb) goto out; size = skb->len; @@ -1083,7 +1050,7 @@ int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif) } ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, - wlvif->basic_rate); + wl->basic_rate); out: dev_kfree_skb(skb); @@ -1094,21 +1061,19 @@ int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif) } -int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct sk_buff *skb = NULL; int ret = -ENOMEM; - skb = ieee80211_nullfunc_get(wl->hw, vif); + skb = ieee80211_nullfunc_get(wl->hw, wl->vif); if (!skb) goto out; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, skb->data, skb->len, CMD_TEMPL_KLV_IDX_NULL_DATA, - wlvif->basic_rate); + wl->basic_rate); out: dev_kfree_skb(skb); @@ -1119,35 +1084,32 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, } -int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u16 aid) +int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct sk_buff *skb; int ret = 0; - skb = ieee80211_pspoll_get(wl->hw, vif); + skb = ieee80211_pspoll_get(wl->hw, wl->vif); if (!skb) goto out; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, - skb->len, 0, wlvif->basic_rate_set); + skb->len, 0, wl->basic_rate_set); out: dev_kfree_skb(skb); return ret; } -int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, +int wl1271_cmd_build_probe_req(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u8 band) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct sk_buff *skb; int ret; u32 rate; - skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, + skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, ie, ie_len); if (!skb) { ret = -ENOMEM; @@ -1156,7 +1118,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); - rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); + rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); if (band == IEEE80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, skb->data, skb->len, 0, rate); @@ -1170,22 +1132,20 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, } struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, - struct wl12xx_vif *wlvif, struct sk_buff *skb) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); int ret; u32 rate; if (!skb) - skb = ieee80211_ap_probereq_get(wl->hw, vif); + skb = ieee80211_ap_probereq_get(wl->hw, wl->vif); if (!skb) goto out; wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); - rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]); - if (wlvif->band == IEEE80211_BAND_2GHZ) + rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[wl->band]); + if (wl->band == IEEE80211_BAND_2GHZ) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, skb->data, skb->len, 0, rate); else @@ -1199,11 +1159,9 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, return skb; } -int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, - __be32 ip_addr) +int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr) { int ret; - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct wl12xx_arp_rsp_template tmpl; struct ieee80211_hdr_3addr *hdr; struct arphdr *arp_hdr; @@ -1215,8 +1173,8 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | IEEE80211_FCTL_TODS); - memcpy(hdr->addr1, vif->bss_conf.bssid, ETH_ALEN); - memcpy(hdr->addr2, vif->addr, ETH_ALEN); + memcpy(hdr->addr1, wl->vif->bss_conf.bssid, ETH_ALEN); + memcpy(hdr->addr2, wl->vif->addr, ETH_ALEN); memset(hdr->addr3, 0xff, ETH_ALEN); /* llc layer */ @@ -1232,26 +1190,25 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY); /* arp payload */ - memcpy(tmpl.sender_hw, vif->addr, ETH_ALEN); + memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN); tmpl.sender_ip = ip_addr; ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, &tmpl, sizeof(tmpl), 0, - wlvif->basic_rate); + wl->basic_rate); return ret; } -int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif) +int wl1271_build_qos_null_data(struct wl1271 *wl) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct ieee80211_qos_hdr template; memset(&template, 0, sizeof(template)); - memcpy(template.addr1, vif->bss_conf.bssid, ETH_ALEN); - memcpy(template.addr2, vif->addr, ETH_ALEN); - memcpy(template.addr3, vif->bss_conf.bssid, ETH_ALEN); + memcpy(template.addr1, wl->bssid, ETH_ALEN); + memcpy(template.addr2, wl->mac_addr, ETH_ALEN); + memcpy(template.addr3, wl->bssid, ETH_ALEN); template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC | @@ -1262,7 +1219,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif) return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, sizeof(template), 0, - wlvif->basic_rate); + wl->basic_rate); } int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid) @@ -1296,8 +1253,7 @@ int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid) return ret; } -int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u16 action, u8 id, u8 key_type, +int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, u32 tx_seq_32, u16 tx_seq_16) { @@ -1305,7 +1261,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, int ret = 0; /* hlid might have already been deleted */ - if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) + if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) return 0; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); @@ -1314,7 +1270,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - cmd->hlid = wlvif->sta.hlid; + cmd->hlid = wl->sta_hlid; if (key_type == KEY_WEP) cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; @@ -1365,10 +1321,9 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, * TODO: merge with sta/ibss into 1 set_key function. * note there are slight diffs */ -int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u16 action, u8 id, u8 key_type, - u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, - u16 tx_seq_16) +int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, + u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, + u16 tx_seq_16) { struct wl1271_cmd_set_keys *cmd; int ret = 0; @@ -1378,7 +1333,7 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (!cmd) return -ENOMEM; - if (hlid == wlvif->ap.bcast_hlid) { + if (hlid == wl->ap_bcast_hlid) { if (key_type == KEY_WEP) lid_type = WEP_DEFAULT_LID_TYPE; else @@ -1456,8 +1411,7 @@ int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid) return ret; } -int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct ieee80211_sta *sta, u8 hlid) +int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) { struct wl12xx_cmd_add_peer *cmd; int i, ret; @@ -1484,13 +1438,13 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, else cmd->psd_type[i] = WL1271_PSD_LEGACY; - sta_rates = sta->supp_rates[wlvif->band]; + sta_rates = sta->supp_rates[wl->band]; if (sta->ht_cap.ht_supported) sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET; cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates, - wlvif->band)); + wl->band)); wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x", cmd->supported_rates, sta->uapsd_queues); @@ -1630,13 +1584,12 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl) return ret; } -static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 role_id) +static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id) { struct wl12xx_cmd_roc *cmd; int ret = 0; - wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wlvif->channel, role_id); + wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wl->channel, role_id); if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID)) return -EINVAL; @@ -1648,8 +1601,8 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, } cmd->role_id = role_id; - cmd->channel = wlvif->channel; - switch (wlvif->band) { + cmd->channel = wl->channel; + switch (wl->band) { case IEEE80211_BAND_2GHZ: cmd->band = RADIO_BAND_2_4GHZ; break; @@ -1657,7 +1610,7 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, cmd->band = RADIO_BAND_5GHZ; break; default: - wl1271_error("roc - unknown band: %d", (int)wlvif->band); + wl1271_error("roc - unknown band: %d", (int)wl->band); ret = -EINVAL; goto out_free; } @@ -1704,14 +1657,14 @@ static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id) return ret; } -int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id) +int wl12xx_roc(struct wl1271 *wl, u8 role_id) { int ret = 0; if (WARN_ON(test_bit(role_id, wl->roc_map))) return 0; - ret = wl12xx_cmd_roc(wl, wlvif, role_id); + ret = wl12xx_cmd_roc(wl, role_id); if (ret < 0) goto out; @@ -1800,50 +1753,3 @@ int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl) out: return ret; } - -/* start dev role and roc on its channel */ -int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) -{ - int ret; - - if (WARN_ON(!(wlvif->bss_type == BSS_TYPE_STA_BSS || - wlvif->bss_type == BSS_TYPE_IBSS))) - return -EINVAL; - - ret = wl12xx_cmd_role_start_dev(wl, wlvif); - if (ret < 0) - goto out; - - ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id); - if (ret < 0) - goto out_stop; - - return 0; - -out_stop: - wl12xx_cmd_role_stop_dev(wl, wlvif); -out: - return ret; -} - -/* croc dev hlid, and stop the role */ -int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) -{ - int ret; - - if (WARN_ON(!(wlvif->bss_type == BSS_TYPE_STA_BSS || - wlvif->bss_type == BSS_TYPE_IBSS))) - return -EINVAL; - - if (test_bit(wlvif->dev_role_id, wl->roc_map)) { - ret = wl12xx_croc(wl, wlvif->dev_role_id); - if (ret < 0) - goto out; - } - - ret = wl12xx_cmd_role_stop_dev(wl, wlvif); - if (ret < 0) - goto out; -out: - return ret; -} diff --git a/trunk/drivers/net/wireless/wl12xx/cmd.h b/trunk/drivers/net/wireless/wl12xx/cmd.h index 3f7d0b93c24d..b7bd42769aa7 100644 --- a/trunk/drivers/net/wireless/wl12xx/cmd.h +++ b/trunk/drivers/net/wireless/wl12xx/cmd.h @@ -36,54 +36,45 @@ int wl128x_cmd_general_parms(struct wl1271 *wl); int wl1271_cmd_radio_parms(struct wl1271 *wl); int wl128x_cmd_radio_parms(struct wl1271 *wl); int wl1271_cmd_ext_radio_parms(struct wl1271 *wl); -int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, - u8 *role_id); +int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id); int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); -int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif); +int wl12xx_cmd_role_start_dev(struct wl1271 *wl); +int wl12xx_cmd_role_stop_dev(struct wl1271 *wl); +int wl12xx_cmd_role_start_sta(struct wl1271 *wl); +int wl12xx_cmd_role_stop_sta(struct wl1271 *wl); +int wl12xx_cmd_role_start_ap(struct wl1271 *wl); +int wl12xx_cmd_role_stop_ap(struct wl1271 *wl); +int wl12xx_cmd_role_start_ibss(struct wl1271 *wl); int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); -int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 ps_mode); +int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, size_t len); int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, void *buf, size_t buf_len, int index, u32 rates); -int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u16 aid); -int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, +int wl1271_cmd_build_null_data(struct wl1271 *wl); +int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); +int wl1271_cmd_build_probe_req(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u8 band); struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, - struct wl12xx_vif *wlvif, struct sk_buff *skb); -int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, - __be32 ip_addr); -int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif); -int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, - struct wl12xx_vif *wlvif); +int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr); +int wl1271_build_qos_null_data(struct wl1271 *wl); +int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid); -int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u16 action, u8 id, u8 key_type, +int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, const u8 *addr, u32 tx_seq_32, u16 tx_seq_16); -int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u16 action, u8 id, u8 key_type, +int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, u16 tx_seq_16); int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid); -int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id); +int wl12xx_roc(struct wl1271 *wl, u8 role_id); int wl12xx_croc(struct wl1271 *wl, u8 role_id); -int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct ieee80211_sta *sta, u8 hlid); +int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid); int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid); int wl12xx_cmd_config_fwlog(struct wl1271 *wl); int wl12xx_cmd_start_fwlog(struct wl1271 *wl); @@ -91,9 +82,6 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl); int wl12xx_cmd_channel_switch(struct wl1271 *wl, struct ieee80211_channel_switch *ch_switch); int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl); -int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 *hlid); -void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid); enum wl1271_commands { CMD_INTERROGATE = 1, /*use this to read information elements*/ diff --git a/trunk/drivers/net/wireless/wl12xx/conf.h b/trunk/drivers/net/wireless/wl12xx/conf.h index 1bcfb017058d..04bb8fbf93f9 100644 --- a/trunk/drivers/net/wireless/wl12xx/conf.h +++ b/trunk/drivers/net/wireless/wl12xx/conf.h @@ -440,10 +440,6 @@ struct conf_rx_settings { CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ CONF_HW_BIT_RATE_54MBPS) -#define CONF_TX_CCK_RATES (CONF_HW_BIT_RATE_1MBPS | \ - CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \ - CONF_HW_BIT_RATE_11MBPS) - #define CONF_TX_OFDM_RATES (CONF_HW_BIT_RATE_6MBPS | \ CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS | \ CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ diff --git a/trunk/drivers/net/wireless/wl12xx/debug.h b/trunk/drivers/net/wireless/wl12xx/debug.h deleted file mode 100644 index b85fd8c41e8f..000000000000 --- a/trunk/drivers/net/wireless/wl12xx/debug.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is part of wl12xx - * - * Copyright (C) 2011 Texas Instruments. All rights reserved. - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * 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 __DEBUG_H__ -#define __DEBUG_H__ - -#include -#include - -#define DRIVER_NAME "wl12xx" -#define DRIVER_PREFIX DRIVER_NAME ": " - -enum { - DEBUG_NONE = 0, - DEBUG_IRQ = BIT(0), - DEBUG_SPI = BIT(1), - DEBUG_BOOT = BIT(2), - DEBUG_MAILBOX = BIT(3), - DEBUG_TESTMODE = BIT(4), - DEBUG_EVENT = BIT(5), - DEBUG_TX = BIT(6), - DEBUG_RX = BIT(7), - DEBUG_SCAN = BIT(8), - DEBUG_CRYPT = BIT(9), - DEBUG_PSM = BIT(10), - DEBUG_MAC80211 = BIT(11), - DEBUG_CMD = BIT(12), - DEBUG_ACX = BIT(13), - DEBUG_SDIO = BIT(14), - DEBUG_FILTERS = BIT(15), - DEBUG_ADHOC = BIT(16), - DEBUG_AP = BIT(17), - DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP), - DEBUG_ALL = ~0, -}; - -extern u32 wl12xx_debug_level; - -#define DEBUG_DUMP_LIMIT 1024 - -#define wl1271_error(fmt, arg...) \ - pr_err(DRIVER_PREFIX "ERROR " fmt "\n", ##arg) - -#define wl1271_warning(fmt, arg...) \ - pr_warning(DRIVER_PREFIX "WARNING " fmt "\n", ##arg) - -#define wl1271_notice(fmt, arg...) \ - pr_info(DRIVER_PREFIX fmt "\n", ##arg) - -#define wl1271_info(fmt, arg...) \ - pr_info(DRIVER_PREFIX fmt "\n", ##arg) - -#define wl1271_debug(level, fmt, arg...) \ - do { \ - if (level & wl12xx_debug_level) \ - pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \ - } while (0) - -/* TODO: use pr_debug_hex_dump when it becomes available */ -#define wl1271_dump(level, prefix, buf, len) \ - do { \ - if (level & wl12xx_debug_level) \ - print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ - DUMP_PREFIX_OFFSET, 16, 1, \ - buf, \ - min_t(size_t, len, DEBUG_DUMP_LIMIT), \ - 0); \ - } while (0) - -#define wl1271_dump_ascii(level, prefix, buf, len) \ - do { \ - if (level & wl12xx_debug_level) \ - print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ - DUMP_PREFIX_OFFSET, 16, 1, \ - buf, \ - min_t(size_t, len, DEBUG_DUMP_LIMIT), \ - true); \ - } while (0) - -#endif /* __DEBUG_H__ */ diff --git a/trunk/drivers/net/wireless/wl12xx/debugfs.c b/trunk/drivers/net/wireless/wl12xx/debugfs.c index 2e14b436101f..3999fd528302 100644 --- a/trunk/drivers/net/wireless/wl12xx/debugfs.c +++ b/trunk/drivers/net/wireless/wl12xx/debugfs.c @@ -27,7 +27,6 @@ #include #include "wl12xx.h" -#include "debug.h" #include "acx.h" #include "ps.h" #include "io.h" @@ -347,14 +346,29 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_INT(tx_results_count); DRIVER_STATE_PRINT_LHEX(flags); DRIVER_STATE_PRINT_INT(tx_blocks_freed); + DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb); DRIVER_STATE_PRINT_INT(rx_counter); + DRIVER_STATE_PRINT_INT(session_counter); DRIVER_STATE_PRINT_INT(state); + DRIVER_STATE_PRINT_INT(bss_type); DRIVER_STATE_PRINT_INT(channel); + DRIVER_STATE_PRINT_HEX(rate_set); + DRIVER_STATE_PRINT_HEX(basic_rate_set); + DRIVER_STATE_PRINT_HEX(basic_rate); DRIVER_STATE_PRINT_INT(band); + DRIVER_STATE_PRINT_INT(beacon_int); + DRIVER_STATE_PRINT_INT(psm_entry_retry); + DRIVER_STATE_PRINT_INT(ps_poll_failures); DRIVER_STATE_PRINT_INT(power_level); + DRIVER_STATE_PRINT_INT(rssi_thold); + DRIVER_STATE_PRINT_INT(last_rssi_event); DRIVER_STATE_PRINT_INT(sg_enabled); DRIVER_STATE_PRINT_INT(enable_11a); DRIVER_STATE_PRINT_INT(noise); + DRIVER_STATE_PRINT_LHEX(ap_hlid_map[0]); + DRIVER_STATE_PRINT_INT(last_tx_hlid); + DRIVER_STATE_PRINT_INT(ba_support); + DRIVER_STATE_PRINT_HEX(ba_rx_bitmap); DRIVER_STATE_PRINT_HEX(ap_fw_ps_map); DRIVER_STATE_PRINT_LHEX(ap_ps_map); DRIVER_STATE_PRINT_HEX(quirks); @@ -385,115 +399,6 @@ static const struct file_operations driver_state_ops = { .llseek = default_llseek, }; -static ssize_t vifs_state_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - struct wl12xx_vif *wlvif; - int ret, res = 0; - const int buf_size = 4096; - char *buf; - char tmp_buf[64]; - - buf = kzalloc(buf_size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - mutex_lock(&wl->mutex); - -#define VIF_STATE_PRINT(x, fmt) \ - (res += scnprintf(buf + res, buf_size - res, \ - #x " = " fmt "\n", wlvif->x)) - -#define VIF_STATE_PRINT_LONG(x) VIF_STATE_PRINT(x, "%ld") -#define VIF_STATE_PRINT_INT(x) VIF_STATE_PRINT(x, "%d") -#define VIF_STATE_PRINT_STR(x) VIF_STATE_PRINT(x, "%s") -#define VIF_STATE_PRINT_LHEX(x) VIF_STATE_PRINT(x, "0x%lx") -#define VIF_STATE_PRINT_LLHEX(x) VIF_STATE_PRINT(x, "0x%llx") -#define VIF_STATE_PRINT_HEX(x) VIF_STATE_PRINT(x, "0x%x") - -#define VIF_STATE_PRINT_NSTR(x, len) \ - do { \ - memset(tmp_buf, 0, sizeof(tmp_buf)); \ - memcpy(tmp_buf, wlvif->x, \ - min_t(u8, len, sizeof(tmp_buf) - 1)); \ - res += scnprintf(buf + res, buf_size - res, \ - #x " = %s\n", tmp_buf); \ - } while (0) - - wl12xx_for_each_wlvif(wl, wlvif) { - VIF_STATE_PRINT_INT(role_id); - VIF_STATE_PRINT_INT(bss_type); - VIF_STATE_PRINT_LHEX(flags); - VIF_STATE_PRINT_INT(p2p); - VIF_STATE_PRINT_INT(dev_role_id); - VIF_STATE_PRINT_INT(dev_hlid); - - if (wlvif->bss_type == BSS_TYPE_STA_BSS || - wlvif->bss_type == BSS_TYPE_IBSS) { - VIF_STATE_PRINT_INT(sta.hlid); - VIF_STATE_PRINT_INT(sta.ba_rx_bitmap); - VIF_STATE_PRINT_INT(sta.basic_rate_idx); - VIF_STATE_PRINT_INT(sta.ap_rate_idx); - VIF_STATE_PRINT_INT(sta.p2p_rate_idx); - } else { - VIF_STATE_PRINT_INT(ap.global_hlid); - VIF_STATE_PRINT_INT(ap.bcast_hlid); - VIF_STATE_PRINT_LHEX(ap.sta_hlid_map[0]); - VIF_STATE_PRINT_INT(ap.mgmt_rate_idx); - VIF_STATE_PRINT_INT(ap.bcast_rate_idx); - VIF_STATE_PRINT_INT(ap.ucast_rate_idx[0]); - VIF_STATE_PRINT_INT(ap.ucast_rate_idx[1]); - VIF_STATE_PRINT_INT(ap.ucast_rate_idx[2]); - VIF_STATE_PRINT_INT(ap.ucast_rate_idx[3]); - } - VIF_STATE_PRINT_INT(last_tx_hlid); - VIF_STATE_PRINT_LHEX(links_map[0]); - VIF_STATE_PRINT_NSTR(ssid, wlvif->ssid_len); - VIF_STATE_PRINT_INT(band); - VIF_STATE_PRINT_INT(channel); - VIF_STATE_PRINT_HEX(bitrate_masks[0]); - VIF_STATE_PRINT_HEX(bitrate_masks[1]); - VIF_STATE_PRINT_HEX(basic_rate_set); - VIF_STATE_PRINT_HEX(basic_rate); - VIF_STATE_PRINT_HEX(rate_set); - VIF_STATE_PRINT_INT(beacon_int); - VIF_STATE_PRINT_INT(default_key); - VIF_STATE_PRINT_INT(aid); - VIF_STATE_PRINT_INT(session_counter); - VIF_STATE_PRINT_INT(ps_poll_failures); - VIF_STATE_PRINT_INT(psm_entry_retry); - VIF_STATE_PRINT_INT(power_level); - VIF_STATE_PRINT_INT(rssi_thold); - VIF_STATE_PRINT_INT(last_rssi_event); - VIF_STATE_PRINT_INT(ba_support); - VIF_STATE_PRINT_INT(ba_allowed); - VIF_STATE_PRINT_LLHEX(tx_security_seq); - VIF_STATE_PRINT_INT(tx_security_last_seq_lsb); - } - -#undef VIF_STATE_PRINT_INT -#undef VIF_STATE_PRINT_LONG -#undef VIF_STATE_PRINT_HEX -#undef VIF_STATE_PRINT_LHEX -#undef VIF_STATE_PRINT_LLHEX -#undef VIF_STATE_PRINT_STR -#undef VIF_STATE_PRINT_NSTR -#undef VIF_STATE_PRINT - - mutex_unlock(&wl->mutex); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, res); - kfree(buf); - return ret; -} - -static const struct file_operations vifs_state_ops = { - .read = vifs_state_read, - .open = wl1271_open_file_generic, - .llseek = default_llseek, -}; - static ssize_t dtim_interval_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -615,7 +520,6 @@ static ssize_t rx_streaming_interval_write(struct file *file, size_t count, loff_t *ppos) { struct wl1271 *wl = file->private_data; - struct wl12xx_vif *wlvif; unsigned long value; int ret; @@ -639,9 +543,7 @@ static ssize_t rx_streaming_interval_write(struct file *file, if (ret < 0) goto out; - wl12xx_for_each_wlvif_sta(wl, wlvif) { - wl1271_recalc_rx_streaming(wl, wlvif); - } + wl1271_recalc_rx_streaming(wl); wl1271_ps_elp_sleep(wl); out: @@ -670,7 +572,6 @@ static ssize_t rx_streaming_always_write(struct file *file, size_t count, loff_t *ppos) { struct wl1271 *wl = file->private_data; - struct wl12xx_vif *wlvif; unsigned long value; int ret; @@ -694,9 +595,7 @@ static ssize_t rx_streaming_always_write(struct file *file, if (ret < 0) goto out; - wl12xx_for_each_wlvif_sta(wl, wlvif) { - wl1271_recalc_rx_streaming(wl, wlvif); - } + wl1271_recalc_rx_streaming(wl); wl1271_ps_elp_sleep(wl); out: @@ -725,7 +624,6 @@ static ssize_t beacon_filtering_write(struct file *file, size_t count, loff_t *ppos) { struct wl1271 *wl = file->private_data; - struct wl12xx_vif *wlvif; char buf[10]; size_t len; unsigned long value; @@ -748,9 +646,7 @@ static ssize_t beacon_filtering_write(struct file *file, if (ret < 0) goto out; - wl12xx_for_each_wlvif(wl, wlvif) { - ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value); - } + ret = wl1271_acx_beacon_filter_opt(wl, !!value); wl1271_ps_elp_sleep(wl); out: @@ -874,7 +770,6 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, DEBUGFS_ADD(gpio_power, rootdir); DEBUGFS_ADD(start_recovery, rootdir); DEBUGFS_ADD(driver_state, rootdir); - DEBUGFS_ADD(vifs_state, rootdir); DEBUGFS_ADD(dtim_interval, rootdir); DEBUGFS_ADD(beacon_interval, rootdir); DEBUGFS_ADD(beacon_filtering, rootdir); diff --git a/trunk/drivers/net/wireless/wl12xx/event.c b/trunk/drivers/net/wireless/wl12xx/event.c index 00ce794eebae..674ad2a9e409 100644 --- a/trunk/drivers/net/wireless/wl12xx/event.c +++ b/trunk/drivers/net/wireless/wl12xx/event.c @@ -22,7 +22,6 @@ */ #include "wl12xx.h" -#include "debug.h" #include "reg.h" #include "io.h" #include "event.h" @@ -32,16 +31,12 @@ void wl1271_pspoll_work(struct work_struct *work) { - struct ieee80211_vif *vif; - struct wl12xx_vif *wlvif; struct delayed_work *dwork; struct wl1271 *wl; int ret; dwork = container_of(work, struct delayed_work, work); - wlvif = container_of(dwork, struct wl12xx_vif, pspoll_work); - vif = container_of((void *)wlvif, struct ieee80211_vif, drv_priv); - wl = wlvif->wl; + wl = container_of(dwork, struct wl1271, pspoll_work); wl1271_debug(DEBUG_EVENT, "pspoll work"); @@ -50,10 +45,10 @@ void wl1271_pspoll_work(struct work_struct *work) if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; - if (!test_and_clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags)) + if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags)) goto out; - if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) goto out; /* @@ -65,33 +60,31 @@ void wl1271_pspoll_work(struct work_struct *work) if (ret < 0) goto out; - wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, - wlvif->basic_rate, true); + wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true); wl1271_ps_elp_sleep(wl); out: mutex_unlock(&wl->mutex); }; -static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl) { int delay = wl->conf.conn.ps_poll_recovery_period; int ret; - wlvif->ps_poll_failures++; - if (wlvif->ps_poll_failures == 1) + wl->ps_poll_failures++; + if (wl->ps_poll_failures == 1) wl1271_info("AP with dysfunctional ps-poll, " "trying to work around it."); /* force active mode receive data from the AP */ - if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { - ret = wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, - wlvif->basic_rate, true); + if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { + ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, + wl->basic_rate, true); if (ret < 0) return; - set_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags); - ieee80211_queue_delayed_work(wl->hw, &wlvif->pspoll_work, + set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); + ieee80211_queue_delayed_work(wl->hw, &wl->pspoll_work, msecs_to_jiffies(delay)); } @@ -104,7 +97,6 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl, } static int wl1271_event_ps_report(struct wl1271 *wl, - struct wl12xx_vif *wlvif, struct event_mailbox *mbox, bool *beacon_loss) { @@ -117,37 +109,41 @@ static int wl1271_event_ps_report(struct wl1271 *wl, case EVENT_ENTER_POWER_SAVE_FAIL: wl1271_debug(DEBUG_PSM, "PSM entry failed"); - if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { + if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { /* remain in active mode */ - wlvif->psm_entry_retry = 0; + wl->psm_entry_retry = 0; break; } - if (wlvif->psm_entry_retry < total_retries) { - wlvif->psm_entry_retry++; - ret = wl1271_ps_set_mode(wl, wlvif, - STATION_POWER_SAVE_MODE, - wlvif->basic_rate, true); + if (wl->psm_entry_retry < total_retries) { + wl->psm_entry_retry++; + ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, + wl->basic_rate, true); } else { wl1271_info("No ack to nullfunc from AP."); - wlvif->psm_entry_retry = 0; + wl->psm_entry_retry = 0; *beacon_loss = true; } break; case EVENT_ENTER_POWER_SAVE_SUCCESS: - wlvif->psm_entry_retry = 0; + wl->psm_entry_retry = 0; + + /* enable beacon filtering */ + ret = wl1271_acx_beacon_filter_opt(wl, true); + if (ret < 0) + break; /* * BET has only a minor effect in 5GHz and masks * channel switch IEs, so we only enable BET on 2.4GHz */ - if (wlvif->band == IEEE80211_BAND_2GHZ) + if (wl->band == IEEE80211_BAND_2GHZ) /* enable beacon early termination */ - ret = wl1271_acx_bet_enable(wl, wlvif, true); + ret = wl1271_acx_bet_enable(wl, true); - if (wlvif->ps_compl) { - complete(wlvif->ps_compl); - wlvif->ps_compl = NULL; + if (wl->ps_compl) { + complete(wl->ps_compl); + wl->ps_compl = NULL; } break; default: @@ -158,44 +154,39 @@ static int wl1271_event_ps_report(struct wl1271 *wl, } static void wl1271_event_rssi_trigger(struct wl1271 *wl, - struct wl12xx_vif *wlvif, struct event_mailbox *mbox) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); enum nl80211_cqm_rssi_threshold_event event; s8 metric = mbox->rssi_snr_trigger_metric[0]; wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric); - if (metric <= wlvif->rssi_thold) + if (metric <= wl->rssi_thold) event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; else event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; - if (event != wlvif->last_rssi_event) - ieee80211_cqm_rssi_notify(vif, event, GFP_KERNEL); - wlvif->last_rssi_event = event; + if (event != wl->last_rssi_event) + ieee80211_cqm_rssi_notify(wl->vif, event, GFP_KERNEL); + wl->last_rssi_event = event; } -static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) +static void wl1271_stop_ba_event(struct wl1271 *wl) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); - - if (wlvif->bss_type != BSS_TYPE_AP_BSS) { - if (!wlvif->sta.ba_rx_bitmap) + if (wl->bss_type != BSS_TYPE_AP_BSS) { + if (!wl->ba_rx_bitmap) return; - ieee80211_stop_rx_ba_session(vif, wlvif->sta.ba_rx_bitmap, - vif->bss_conf.bssid); + ieee80211_stop_rx_ba_session(wl->vif, wl->ba_rx_bitmap, + wl->bssid); } else { - u8 hlid; + int i; struct wl1271_link *lnk; - for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, - WL12XX_MAX_LINKS) { - lnk = &wl->links[hlid]; - if (!lnk->ba_bitmap) + for (i = WL1271_AP_STA_HLID_START; i < AP_MAX_LINKS; i++) { + lnk = &wl->links[i]; + if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap) continue; - ieee80211_stop_rx_ba_session(vif, + ieee80211_stop_rx_ba_session(wl->vif, lnk->ba_bitmap, lnk->addr); } @@ -205,23 +196,14 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, u8 enable) { - struct ieee80211_vif *vif; - struct wl12xx_vif *wlvif; - if (enable) { /* disable dynamic PS when requested by the firmware */ - wl12xx_for_each_wlvif_sta(wl, wlvif) { - vif = wl12xx_wlvif_to_vif(wlvif); - ieee80211_disable_dyn_ps(vif); - } + ieee80211_disable_dyn_ps(wl->vif); set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); } else { + ieee80211_enable_dyn_ps(wl->vif); clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); - wl12xx_for_each_wlvif_sta(wl, wlvif) { - vif = wl12xx_wlvif_to_vif(wlvif); - ieee80211_enable_dyn_ps(vif); - wl1271_recalc_rx_streaming(wl, wlvif); - } + wl1271_recalc_rx_streaming(wl); } } @@ -235,11 +217,10 @@ static void wl1271_event_mbox_dump(struct event_mailbox *mbox) static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) { - struct ieee80211_vif *vif; - struct wl12xx_vif *wlvif; int ret; u32 vector; bool beacon_loss = false; + bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); bool disconnect_sta = false; unsigned long sta_bitmap = 0; @@ -253,7 +234,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) wl1271_debug(DEBUG_EVENT, "status: 0x%x", mbox->scheduled_scan_status); - wl1271_scan_stm(wl, wl->scan_vif); + wl1271_scan_stm(wl); } if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { @@ -272,7 +253,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) } } - if (vector & SOFT_GEMINI_SENSE_EVENT_ID) + if (vector & SOFT_GEMINI_SENSE_EVENT_ID && + wl->bss_type == BSS_TYPE_STA_BSS) wl12xx_event_soft_gemini_sense(wl, mbox->soft_gemini_sense_info); @@ -285,54 +267,40 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. * */ - if (vector & BSS_LOSE_EVENT_ID) { - /* TODO: check for multi-role */ + if ((vector & BSS_LOSE_EVENT_ID) && !is_ap) { wl1271_info("Beacon loss detected."); /* indicate to the stack, that beacons have been lost */ beacon_loss = true; } - if (vector & PS_REPORT_EVENT_ID) { + if ((vector & PS_REPORT_EVENT_ID) && !is_ap) { wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); - wl12xx_for_each_wlvif_sta(wl, wlvif) { - ret = wl1271_event_ps_report(wl, wlvif, - mbox, &beacon_loss); - if (ret < 0) - return ret; - } + ret = wl1271_event_ps_report(wl, mbox, &beacon_loss); + if (ret < 0) + return ret; } - if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) - wl12xx_for_each_wlvif_sta(wl, wlvif) { - wl1271_event_pspoll_delivery_fail(wl, wlvif); - } + if ((vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) && !is_ap) + wl1271_event_pspoll_delivery_fail(wl); if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { - /* TODO: check actual multi-role support */ wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); - wl12xx_for_each_wlvif_sta(wl, wlvif) { - wl1271_event_rssi_trigger(wl, wlvif, mbox); - } + if (wl->vif) + wl1271_event_rssi_trigger(wl, mbox); } - if (vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) { - u8 role_id = mbox->role_id; + if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID)) { wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. " - "ba_allowed = 0x%x, role_id=%d", - mbox->rx_ba_allowed, role_id); + "ba_allowed = 0x%x", mbox->rx_ba_allowed); - wl12xx_for_each_wlvif(wl, wlvif) { - if (role_id != 0xff && role_id != wlvif->role_id) - continue; + wl->ba_allowed = !!mbox->rx_ba_allowed; - wlvif->ba_allowed = !!mbox->rx_ba_allowed; - if (!wlvif->ba_allowed) - wl1271_stop_ba_event(wl, wlvif); - } + if (wl->vif && !wl->ba_allowed) + wl1271_stop_ba_event(wl); } - if (vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) { + if ((vector & CHANNEL_SWITCH_COMPLETE_EVENT_ID) && !is_ap) { wl1271_debug(DEBUG_EVENT, "CHANNEL_SWITCH_COMPLETE_EVENT_ID. " "status = 0x%x", mbox->channel_switch_status); @@ -341,65 +309,50 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) * 1) channel switch complete with status=0 * 2) channel switch failed status=1 */ - - /* TODO: configure only the relevant vif */ - wl12xx_for_each_wlvif_sta(wl, wlvif) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); - bool success; - - if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, - &wl->flags)) - continue; - - success = mbox->channel_switch_status ? false : true; - ieee80211_chswitch_done(vif, success); - } + if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags) && + (wl->vif)) + ieee80211_chswitch_done(wl->vif, + mbox->channel_switch_status ? false : true); } if ((vector & DUMMY_PACKET_EVENT_ID)) { wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); - wl1271_tx_dummy_packet(wl); + if (wl->vif) + wl1271_tx_dummy_packet(wl); } /* * "TX retries exceeded" has a different meaning according to mode. * In AP mode the offending station is disconnected. */ - if (vector & MAX_TX_RETRY_EVENT_ID) { + if ((vector & MAX_TX_RETRY_EVENT_ID) && is_ap) { wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); disconnect_sta = true; } - if (vector & INACTIVE_STA_EVENT_ID) { + if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); disconnect_sta = true; } - if (disconnect_sta) { + if (is_ap && disconnect_sta) { u32 num_packets = wl->conf.tx.max_tx_retries; struct ieee80211_sta *sta; const u8 *addr; int h; - for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) { - bool found = false; - /* find the ap vif connected to this sta */ - wl12xx_for_each_wlvif_ap(wl, wlvif) { - if (!test_bit(h, wlvif->ap.sta_hlid_map)) - continue; - found = true; - break; - } - if (!found) + for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); + h < AP_MAX_LINKS; + h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) { + if (!wl1271_is_active_sta(wl, h)) continue; - vif = wl12xx_wlvif_to_vif(wlvif); addr = wl->links[h].addr; rcu_read_lock(); - sta = ieee80211_find_sta(vif, addr); + sta = ieee80211_find_sta(wl->vif, addr); if (sta) { wl1271_debug(DEBUG_EVENT, "remove sta %d", h); ieee80211_report_low_ack(sta, num_packets); @@ -408,11 +361,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) } } - if (beacon_loss) - wl12xx_for_each_wlvif_sta(wl, wlvif) { - vif = wl12xx_wlvif_to_vif(wlvif); - ieee80211_connection_loss(vif); - } + if (wl->vif && beacon_loss) + ieee80211_connection_loss(wl->vif); return 0; } diff --git a/trunk/drivers/net/wireless/wl12xx/event.h b/trunk/drivers/net/wireless/wl12xx/event.h index 1d878ba47bf4..49c1a0ede5b1 100644 --- a/trunk/drivers/net/wireless/wl12xx/event.h +++ b/trunk/drivers/net/wireless/wl12xx/event.h @@ -132,4 +132,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl); int wl1271_event_handle(struct wl1271 *wl, u8 mbox); void wl1271_pspoll_work(struct work_struct *work); +/* Functions from main.c */ +bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid); + #endif diff --git a/trunk/drivers/net/wireless/wl12xx/init.c b/trunk/drivers/net/wireless/wl12xx/init.c index 88891cdfdd4a..04db64c94e9a 100644 --- a/trunk/drivers/net/wireless/wl12xx/init.c +++ b/trunk/drivers/net/wireless/wl12xx/init.c @@ -25,7 +25,6 @@ #include #include -#include "debug.h" #include "init.h" #include "wl12xx_80211.h" #include "acx.h" @@ -34,7 +33,7 @@ #include "tx.h" #include "io.h" -int wl1271_init_templates_config(struct wl1271 *wl) +int wl1271_sta_init_templates_config(struct wl1271 *wl) { int ret, i; @@ -65,7 +64,7 @@ int wl1271_init_templates_config(struct wl1271 *wl) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, sizeof - (struct ieee80211_qos_hdr), + (struct wl12xx_qos_null_data_template), 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; @@ -89,33 +88,10 @@ int wl1271_init_templates_config(struct wl1271 *wl) if (ret < 0) return ret; - /* - * Put very large empty placeholders for all templates. These - * reserve memory for later. - */ - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL, - WL1271_CMD_TEMPL_MAX_SIZE, - 0, WL1271_RATE_AUTOMATIC); - if (ret < 0) - return ret; - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL, - WL1271_CMD_TEMPL_MAX_SIZE, - 0, WL1271_RATE_AUTOMATIC); - if (ret < 0) - return ret; - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL, - sizeof - (struct wl12xx_disconn_template), - 0, WL1271_RATE_AUTOMATIC); - if (ret < 0) - return ret; - for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, - sizeof(struct ieee80211_qos_hdr), - i, WL1271_RATE_AUTOMATIC); + WL1271_CMD_TEMPL_DFLT_SIZE, i, + WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; } @@ -123,8 +99,7 @@ int wl1271_init_templates_config(struct wl1271 *wl) return 0; } -static int wl1271_ap_init_deauth_template(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static int wl1271_ap_init_deauth_template(struct wl1271 *wl) { struct wl12xx_disconn_template *tmpl; int ret; @@ -139,7 +114,7 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl, tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH); - rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); + rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, tmpl, sizeof(*tmpl), 0, rate); @@ -148,10 +123,8 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl, return ret; } -static int wl1271_ap_init_null_template(struct wl1271 *wl, - struct ieee80211_vif *vif) +static int wl1271_ap_init_null_template(struct wl1271 *wl) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct ieee80211_hdr_3addr *nullfunc; int ret; u32 rate; @@ -168,10 +141,10 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl, /* nullfunc->addr1 is filled by FW */ - memcpy(nullfunc->addr2, vif->addr, ETH_ALEN); - memcpy(nullfunc->addr3, vif->addr, ETH_ALEN); + memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN); + memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN); - rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); + rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc, sizeof(*nullfunc), 0, rate); @@ -180,10 +153,8 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl, return ret; } -static int wl1271_ap_init_qos_null_template(struct wl1271 *wl, - struct ieee80211_vif *vif) +static int wl1271_ap_init_qos_null_template(struct wl1271 *wl) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct ieee80211_qos_hdr *qosnull; int ret; u32 rate; @@ -200,10 +171,10 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl, /* qosnull->addr1 is filled by FW */ - memcpy(qosnull->addr2, vif->addr, ETH_ALEN); - memcpy(qosnull->addr3, vif->addr, ETH_ALEN); + memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN); + memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN); - rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); + rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull, sizeof(*qosnull), 0, rate); @@ -212,59 +183,93 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl, return ret; } -static int wl12xx_init_rx_config(struct wl1271 *wl) +static int wl1271_ap_init_templates_config(struct wl1271 *wl) { int ret; - ret = wl1271_acx_rx_msdu_life_time(wl); + /* + * Put very large empty placeholders for all templates. These + * reserve memory for later. + */ + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL, + WL1271_CMD_TEMPL_MAX_SIZE, + 0, WL1271_RATE_AUTOMATIC); + if (ret < 0) + return ret; + + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL, + WL1271_CMD_TEMPL_MAX_SIZE, + 0, WL1271_RATE_AUTOMATIC); + if (ret < 0) + return ret; + + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL, + sizeof + (struct wl12xx_disconn_template), + 0, WL1271_RATE_AUTOMATIC); + if (ret < 0) + return ret; + + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, + sizeof(struct wl12xx_null_data_template), + 0, WL1271_RATE_AUTOMATIC); + if (ret < 0) + return ret; + + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, + sizeof + (struct wl12xx_qos_null_data_template), + 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; return 0; } -int wl1271_init_phy_config(struct wl1271 *wl) +static int wl12xx_init_rx_config(struct wl1271 *wl) { int ret; - ret = wl1271_acx_pd_threshold(wl); + ret = wl1271_acx_rx_msdu_life_time(wl); if (ret < 0) return ret; return 0; } -static int wl12xx_init_phy_vif_config(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +int wl1271_init_phy_config(struct wl1271 *wl) { int ret; - ret = wl1271_acx_slot(wl, wlvif, DEFAULT_SLOT_TIME); + ret = wl1271_acx_pd_threshold(wl); + if (ret < 0) + return ret; + + ret = wl1271_acx_slot(wl, DEFAULT_SLOT_TIME); if (ret < 0) return ret; - ret = wl1271_acx_service_period_timeout(wl, wlvif); + ret = wl1271_acx_service_period_timeout(wl); if (ret < 0) return ret; - ret = wl1271_acx_rts_threshold(wl, wlvif, wl->hw->wiphy->rts_threshold); + ret = wl1271_acx_rts_threshold(wl, wl->hw->wiphy->rts_threshold); if (ret < 0) return ret; return 0; } -static int wl1271_init_sta_beacon_filter(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static int wl1271_init_beacon_filter(struct wl1271 *wl) { int ret; - ret = wl1271_acx_beacon_filter_table(wl, wlvif); + /* disable beacon filtering at this stage */ + ret = wl1271_acx_beacon_filter_opt(wl, false); if (ret < 0) return ret; - /* enable beacon filtering */ - ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); + ret = wl1271_acx_beacon_filter_table(wl); if (ret < 0) return ret; @@ -297,12 +302,11 @@ int wl1271_init_energy_detection(struct wl1271 *wl) return 0; } -static int wl1271_init_beacon_broadcast(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static int wl1271_init_beacon_broadcast(struct wl1271 *wl) { int ret; - ret = wl1271_acx_bcn_dtim_options(wl, wlvif); + ret = wl1271_acx_bcn_dtim_options(wl); if (ret < 0) return ret; @@ -323,8 +327,7 @@ static int wl12xx_init_fwlog(struct wl1271 *wl) return 0; } -/* generic sta initialization (non vif-specific) */ -static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) +static int wl1271_sta_hw_init(struct wl1271 *wl) { int ret; @@ -335,7 +338,25 @@ static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) } /* PS config */ - ret = wl12xx_acx_config_ps(wl, wlvif); + ret = wl1271_acx_config_ps(wl); + if (ret < 0) + return ret; + + ret = wl1271_sta_init_templates_config(wl); + if (ret < 0) + return ret; + + ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0); + if (ret < 0) + return ret; + + /* Initialize connection monitoring thresholds */ + ret = wl1271_acx_conn_monit_params(wl, false); + if (ret < 0) + return ret; + + /* Beacon filtering */ + ret = wl1271_init_beacon_filter(wl); if (ret < 0) return ret; @@ -344,61 +365,103 @@ static int wl1271_sta_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) if (ret < 0) return ret; - ret = wl1271_acx_sta_rate_policies(wl, wlvif); + /* Beacons and broadcast settings */ + ret = wl1271_init_beacon_broadcast(wl); + if (ret < 0) + return ret; + + /* Configure for ELP power saving */ + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); + if (ret < 0) + return ret; + + /* Configure rssi/snr averaging weights */ + ret = wl1271_acx_rssi_snr_avg_weights(wl); + if (ret < 0) + return ret; + + ret = wl1271_acx_sta_rate_policies(wl); + if (ret < 0) + return ret; + + ret = wl12xx_acx_mem_cfg(wl); + if (ret < 0) + return ret; + + /* Configure the FW logger */ + ret = wl12xx_init_fwlog(wl); if (ret < 0) return ret; return 0; } -static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl, - struct ieee80211_vif *vif) +static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret, i; /* disable all keep-alive templates */ for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { - ret = wl1271_acx_keep_alive_config(wl, wlvif, i, + ret = wl1271_acx_keep_alive_config(wl, i, ACX_KEEP_ALIVE_TPL_INVALID); if (ret < 0) return ret; } /* disable the keep-alive feature */ - ret = wl1271_acx_keep_alive_mode(wl, wlvif, false); + ret = wl1271_acx_keep_alive_mode(wl, false); if (ret < 0) return ret; return 0; } -/* generic ap initialization (non vif-specific) */ -static int wl1271_ap_hw_init(struct wl1271 *wl, struct wl12xx_vif *wlvif) +static int wl1271_ap_hw_init(struct wl1271 *wl) { int ret; - ret = wl1271_init_ap_rates(wl, wlvif); + ret = wl1271_ap_init_templates_config(wl); + if (ret < 0) + return ret; + + /* Configure for power always on */ + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); + if (ret < 0) + return ret; + + ret = wl1271_init_ap_rates(wl); + if (ret < 0) + return ret; + + ret = wl1271_acx_ap_max_tx_retry(wl); + if (ret < 0) + return ret; + + ret = wl12xx_acx_mem_cfg(wl); + if (ret < 0) + return ret; + + /* initialize Tx power */ + ret = wl1271_acx_tx_power(wl, wl->power_level); if (ret < 0) return ret; return 0; } -int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif) +int wl1271_ap_init_templates(struct wl1271 *wl) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; - ret = wl1271_ap_init_deauth_template(wl, wlvif); + ret = wl1271_ap_init_deauth_template(wl); if (ret < 0) return ret; - ret = wl1271_ap_init_null_template(wl, vif); + ret = wl1271_ap_init_null_template(wl); if (ret < 0) return ret; - ret = wl1271_ap_init_qos_null_template(wl, vif); + ret = wl1271_ap_init_qos_null_template(wl); if (ret < 0) return ret; @@ -406,45 +469,43 @@ int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif) * when operating as AP we want to receive external beacons for * configuring ERP protection. */ - ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); + ret = wl1271_acx_beacon_filter_opt(wl, false); if (ret < 0) return ret; return 0; } -static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl, - struct ieee80211_vif *vif) +static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) { - return wl1271_ap_init_templates(wl, vif); + return wl1271_ap_init_templates(wl); } -int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl1271_init_ap_rates(struct wl1271 *wl) { int i, ret; struct conf_tx_rate_class rc; u32 supported_rates; - wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x", - wlvif->basic_rate_set); + wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x", wl->basic_rate_set); - if (wlvif->basic_rate_set == 0) + if (wl->basic_rate_set == 0) return -EINVAL; - rc.enabled_rates = wlvif->basic_rate_set; + rc.enabled_rates = wl->basic_rate_set; rc.long_retry_limit = 10; rc.short_retry_limit = 10; rc.aflags = 0; - ret = wl1271_acx_ap_rate_policy(wl, &rc, wlvif->ap.mgmt_rate_idx); + ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_MGMT_RATE); if (ret < 0) return ret; /* use the min basic rate for AP broadcast/multicast */ - rc.enabled_rates = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); + rc.enabled_rates = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); rc.short_retry_limit = 10; rc.long_retry_limit = 10; rc.aflags = 0; - ret = wl1271_acx_ap_rate_policy(wl, &rc, wlvif->ap.bcast_rate_idx); + ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_BCST_RATE); if (ret < 0) return ret; @@ -452,7 +513,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) * If the basic rates contain OFDM rates, use OFDM only * rates for unicast TX as well. Else use all supported rates. */ - if ((wlvif->basic_rate_set & CONF_TX_OFDM_RATES)) + if ((wl->basic_rate_set & CONF_TX_OFDM_RATES)) supported_rates = CONF_TX_OFDM_RATES; else supported_rates = CONF_TX_AP_ENABLED_RATES; @@ -466,8 +527,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) rc.short_retry_limit = 10; rc.long_retry_limit = 10; rc.aflags = 0; - ret = wl1271_acx_ap_rate_policy(wl, &rc, - wlvif->ap.ucast_rate_idx[i]); + ret = wl1271_acx_ap_rate_policy(wl, &rc, i); if (ret < 0) return ret; } @@ -475,23 +535,24 @@ int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif) return 0; } -static int wl1271_set_ba_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif) +static int wl1271_set_ba_policies(struct wl1271 *wl) { /* Reset the BA RX indicators */ - wlvif->ba_allowed = true; + wl->ba_rx_bitmap = 0; + wl->ba_allowed = true; wl->ba_rx_session_count = 0; /* BA is supported in STA/AP modes */ - if (wlvif->bss_type != BSS_TYPE_AP_BSS && - wlvif->bss_type != BSS_TYPE_STA_BSS) { - wlvif->ba_support = false; + if (wl->bss_type != BSS_TYPE_AP_BSS && + wl->bss_type != BSS_TYPE_STA_BSS) { + wl->ba_support = false; return 0; } - wlvif->ba_support = true; + wl->ba_support = true; /* 802.11n initiator BA session setting */ - return wl12xx_acx_set_ba_initiator_policy(wl, wlvif); + return wl12xx_acx_set_ba_initiator_policy(wl); } int wl1271_chip_specific_init(struct wl1271 *wl) @@ -501,7 +562,7 @@ int wl1271_chip_specific_init(struct wl1271 *wl) if (wl->chip.id == CHIP_ID_1283_PG20) { u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE; - if (!(wl->quirks & WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT)) + if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT) /* Enable SDIO padding */ host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK; @@ -514,150 +575,13 @@ int wl1271_chip_specific_init(struct wl1271 *wl) return ret; } -/* vif-specifc initialization */ -static int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif) -{ - int ret; - - ret = wl1271_acx_group_address_tbl(wl, wlvif, true, NULL, 0); - if (ret < 0) - return ret; - - /* Initialize connection monitoring thresholds */ - ret = wl1271_acx_conn_monit_params(wl, wlvif, false); - if (ret < 0) - return ret; - /* Beacon filtering */ - ret = wl1271_init_sta_beacon_filter(wl, wlvif); - if (ret < 0) - return ret; - - /* Beacons and broadcast settings */ - ret = wl1271_init_beacon_broadcast(wl, wlvif); - if (ret < 0) - return ret; - - /* Configure rssi/snr averaging weights */ - ret = wl1271_acx_rssi_snr_avg_weights(wl, wlvif); - if (ret < 0) - return ret; - - return 0; -} - -/* vif-specific intialization */ -static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif) -{ - int ret; - - ret = wl1271_acx_ap_max_tx_retry(wl, wlvif); - if (ret < 0) - return ret; - - /* initialize Tx power */ - ret = wl1271_acx_tx_power(wl, wlvif, wlvif->power_level); - if (ret < 0) - return ret; - - return 0; -} - -int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) +int wl1271_hw_init(struct wl1271 *wl) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct conf_tx_ac_category *conf_ac; struct conf_tx_tid *conf_tid; - bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); int ret, i; - - /* - * consider all existing roles before configuring psm. - * TODO: reconfigure on interface removal. - */ - if (!wl->ap_count) { - if (is_ap) { - /* Configure for power always on */ - ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); - if (ret < 0) - return ret; - } else if (!wl->sta_count) { - /* Configure for ELP power saving */ - ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); - if (ret < 0) - return ret; - } - } - - /* Mode specific init */ - if (is_ap) { - ret = wl1271_ap_hw_init(wl, wlvif); - if (ret < 0) - return ret; - - ret = wl12xx_init_ap_role(wl, wlvif); - if (ret < 0) - return ret; - } else { - ret = wl1271_sta_hw_init(wl, wlvif); - if (ret < 0) - return ret; - - ret = wl12xx_init_sta_role(wl, wlvif); - if (ret < 0) - return ret; - } - - wl12xx_init_phy_vif_config(wl, wlvif); - - /* Default TID/AC configuration */ - BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); - for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { - conf_ac = &wl->conf.tx.ac_conf[i]; - ret = wl1271_acx_ac_cfg(wl, wlvif, conf_ac->ac, - conf_ac->cw_min, conf_ac->cw_max, - conf_ac->aifsn, conf_ac->tx_op_limit); - if (ret < 0) - return ret; - - conf_tid = &wl->conf.tx.tid_conf[i]; - ret = wl1271_acx_tid_cfg(wl, wlvif, - conf_tid->queue_id, - conf_tid->channel_type, - conf_tid->tsid, - conf_tid->ps_scheme, - conf_tid->ack_policy, - conf_tid->apsd_conf[0], - conf_tid->apsd_conf[1]); - if (ret < 0) - return ret; - } - - /* Configure HW encryption */ - ret = wl1271_acx_feature_cfg(wl, wlvif); - if (ret < 0) - return ret; - - /* Mode specific init - post mem init */ - if (is_ap) - ret = wl1271_ap_hw_init_post_mem(wl, vif); - else - ret = wl1271_sta_hw_init_post_mem(wl, vif); - - if (ret < 0) - return ret; - - /* Configure initiator BA sessions policies */ - ret = wl1271_set_ba_policies(wl, wlvif); - if (ret < 0) - return ret; - - return 0; -} - -int wl1271_hw_init(struct wl1271 *wl) -{ - int ret; + bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); if (wl->chip.id == CHIP_ID_1283_PG20) ret = wl128x_cmd_general_parms(wl); @@ -678,17 +602,12 @@ int wl1271_hw_init(struct wl1271 *wl) if (ret < 0) return ret; - /* Init templates */ - ret = wl1271_init_templates_config(wl); - if (ret < 0) - return ret; - - ret = wl12xx_acx_mem_cfg(wl); - if (ret < 0) - return ret; + /* Mode specific init */ + if (is_ap) + ret = wl1271_ap_hw_init(wl); + else + ret = wl1271_sta_hw_init(wl); - /* Configure the FW logger */ - ret = wl12xx_init_fwlog(wl); if (ret < 0) return ret; @@ -736,20 +655,61 @@ int wl1271_hw_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; + /* Default TID/AC configuration */ + BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); + for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { + conf_ac = &wl->conf.tx.ac_conf[i]; + ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, + conf_ac->cw_max, conf_ac->aifsn, + conf_ac->tx_op_limit); + if (ret < 0) + goto out_free_memmap; + + conf_tid = &wl->conf.tx.tid_conf[i]; + ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, + conf_tid->channel_type, + conf_tid->tsid, + conf_tid->ps_scheme, + conf_tid->ack_policy, + conf_tid->apsd_conf[0], + conf_tid->apsd_conf[1]); + if (ret < 0) + goto out_free_memmap; + } + /* Enable data path */ ret = wl1271_cmd_data_path(wl, 1); if (ret < 0) goto out_free_memmap; + /* Configure HW encryption */ + ret = wl1271_acx_feature_cfg(wl); + if (ret < 0) + goto out_free_memmap; + /* configure PM */ ret = wl1271_acx_pm_config(wl); if (ret < 0) goto out_free_memmap; + /* Mode specific init - post mem init */ + if (is_ap) + ret = wl1271_ap_hw_init_post_mem(wl); + else + ret = wl1271_sta_hw_init_post_mem(wl); + + if (ret < 0) + goto out_free_memmap; + ret = wl12xx_acx_set_rate_mgmt_params(wl); if (ret < 0) goto out_free_memmap; + /* Configure initiator BA sessions policies */ + ret = wl1271_set_ba_policies(wl); + if (ret < 0) + goto out_free_memmap; + /* configure hangover */ ret = wl12xx_acx_config_hangover(wl); if (ret < 0) diff --git a/trunk/drivers/net/wireless/wl12xx/init.h b/trunk/drivers/net/wireless/wl12xx/init.h index 81140b81f654..3a3c230fd292 100644 --- a/trunk/drivers/net/wireless/wl12xx/init.h +++ b/trunk/drivers/net/wireless/wl12xx/init.h @@ -27,14 +27,13 @@ #include "wl12xx.h" int wl1271_hw_init_power_auth(struct wl1271 *wl); -int wl1271_init_templates_config(struct wl1271 *wl); +int wl1271_sta_init_templates_config(struct wl1271 *wl); int wl1271_init_phy_config(struct wl1271 *wl); int wl1271_init_pta(struct wl1271 *wl); int wl1271_init_energy_detection(struct wl1271 *wl); int wl1271_chip_specific_init(struct wl1271 *wl); int wl1271_hw_init(struct wl1271 *wl); -int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif); -int wl1271_init_ap_rates(struct wl1271 *wl, struct wl12xx_vif *wlvif); -int wl1271_ap_init_templates(struct wl1271 *wl, struct ieee80211_vif *vif); +int wl1271_init_ap_rates(struct wl1271 *wl); +int wl1271_ap_init_templates(struct wl1271 *wl); #endif diff --git a/trunk/drivers/net/wireless/wl12xx/io.c b/trunk/drivers/net/wireless/wl12xx/io.c index 079ad380e8ff..c2da66f45046 100644 --- a/trunk/drivers/net/wireless/wl12xx/io.c +++ b/trunk/drivers/net/wireless/wl12xx/io.c @@ -24,10 +24,8 @@ #include #include #include -#include #include "wl12xx.h" -#include "debug.h" #include "wl12xx_80211.h" #include "io.h" #include "tx.h" @@ -48,7 +46,7 @@ bool wl1271_set_block_size(struct wl1271 *wl) { if (wl->if_ops->set_block_size) { - wl->if_ops->set_block_size(wl->dev, WL12XX_BUS_BLOCK_SIZE); + wl->if_ops->set_block_size(wl, WL12XX_BUS_BLOCK_SIZE); return true; } @@ -57,12 +55,12 @@ bool wl1271_set_block_size(struct wl1271 *wl) void wl1271_disable_interrupts(struct wl1271 *wl) { - disable_irq(wl->irq); + wl->if_ops->disable_irq(wl); } void wl1271_enable_interrupts(struct wl1271 *wl) { - enable_irq(wl->irq); + wl->if_ops->enable_irq(wl); } /* Set the SPI partitions to access the chip addresses @@ -130,13 +128,13 @@ EXPORT_SYMBOL_GPL(wl1271_set_partition); void wl1271_io_reset(struct wl1271 *wl) { if (wl->if_ops->reset) - wl->if_ops->reset(wl->dev); + wl->if_ops->reset(wl); } void wl1271_io_init(struct wl1271 *wl) { if (wl->if_ops->init) - wl->if_ops->init(wl->dev); + wl->if_ops->init(wl); } void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val) diff --git a/trunk/drivers/net/wireless/wl12xx/io.h b/trunk/drivers/net/wireless/wl12xx/io.h index d398cbcea986..e839341dfafe 100644 --- a/trunk/drivers/net/wireless/wl12xx/io.h +++ b/trunk/drivers/net/wireless/wl12xx/io.h @@ -51,17 +51,23 @@ void wl1271_enable_interrupts(struct wl1271 *wl); void wl1271_io_reset(struct wl1271 *wl); void wl1271_io_init(struct wl1271 *wl); +static inline struct device *wl1271_wl_to_dev(struct wl1271 *wl) +{ + return wl->if_ops->dev(wl); +} + + /* Raw target IO, address is not translated */ static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { - wl->if_ops->write(wl->dev, addr, buf, len, fixed); + wl->if_ops->write(wl, addr, buf, len, fixed); } static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { - wl->if_ops->read(wl->dev, addr, buf, len, fixed); + wl->if_ops->read(wl, addr, buf, len, fixed); } static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) @@ -149,13 +155,13 @@ static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) static inline void wl1271_power_off(struct wl1271 *wl) { - wl->if_ops->power(wl->dev, false); + wl->if_ops->power(wl, false); clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); } static inline int wl1271_power_on(struct wl1271 *wl) { - int ret = wl->if_ops->power(wl->dev, true); + int ret = wl->if_ops->power(wl, true); if (ret == 0) set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); @@ -170,10 +176,15 @@ u16 wl1271_top_reg_read(struct wl1271 *wl, int addr); int wl1271_set_partition(struct wl1271 *wl, struct wl1271_partition_set *p); -bool wl1271_set_block_size(struct wl1271 *wl); - /* Functions from wl1271_main.c */ +int wl1271_register_hw(struct wl1271 *wl); +void wl1271_unregister_hw(struct wl1271 *wl); +int wl1271_init_ieee80211(struct wl1271 *wl); +struct ieee80211_hw *wl1271_alloc_hw(void); +int wl1271_free_hw(struct wl1271 *wl); +irqreturn_t wl1271_irq(int irq, void *data); +bool wl1271_set_block_size(struct wl1271 *wl); int wl1271_tx_dummy_packet(struct wl1271 *wl); #endif diff --git a/trunk/drivers/net/wireless/wl12xx/main.c b/trunk/drivers/net/wireless/wl12xx/main.c index 2f7bfa86c8cd..884f82b63219 100644 --- a/trunk/drivers/net/wireless/wl12xx/main.c +++ b/trunk/drivers/net/wireless/wl12xx/main.c @@ -32,10 +32,8 @@ #include #include #include -#include #include "wl12xx.h" -#include "debug.h" #include "wl12xx_80211.h" #include "reg.h" #include "io.h" @@ -379,30 +377,42 @@ static char *fwlog_param; static bool bug_on_recovery; static void __wl1271_op_remove_interface(struct wl1271 *wl, - struct ieee80211_vif *vif, bool reset_tx_queues); -static void wl1271_op_stop(struct ieee80211_hw *hw); -static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif); +static void wl1271_free_ap_keys(struct wl1271 *wl); + + +static void wl1271_device_release(struct device *dev) +{ + +} + +static struct platform_device wl1271_device = { + .name = "wl1271", + .id = -1, + + /* device model insists to have a release function */ + .dev = { + .release = wl1271_device_release, + }, +}; static DEFINE_MUTEX(wl_list_mutex); static LIST_HEAD(wl_list); -static int wl1271_check_operstate(struct wl1271 *wl, struct wl12xx_vif *wlvif, - unsigned char operstate) +static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate) { int ret; - if (operstate != IF_OPER_UP) return 0; - if (test_and_set_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags)) + if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) return 0; - ret = wl12xx_cmd_set_peer_state(wl, wlvif->sta.hlid); + ret = wl12xx_cmd_set_peer_state(wl, wl->sta_hlid); if (ret < 0) return ret; - wl12xx_croc(wl, wlvif->role_id); + wl12xx_croc(wl, wl->role_id); wl1271_info("Association completed."); return 0; @@ -416,7 +426,6 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, struct ieee80211_hw *hw; struct wl1271 *wl; struct wl1271 *wl_temp; - struct wl12xx_vif *wlvif; int ret = 0; /* Check that this notification is for us. */ @@ -450,18 +459,17 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, if (wl->state == WL1271_STATE_OFF) goto out; - wl12xx_for_each_wlvif_sta(wl, wlvif) { - if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) - continue; + if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + goto out; - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; - wl1271_check_operstate(wl, wlvif, dev->operstate); + wl1271_check_operstate(wl, dev->operstate); + + wl1271_ps_elp_sleep(wl); - wl1271_ps_elp_sleep(wl); - } out: mutex_unlock(&wl->mutex); @@ -490,20 +498,19 @@ static int wl1271_reg_notify(struct wiphy *wiphy, return 0; } -static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool enable) +static int wl1271_set_rx_streaming(struct wl1271 *wl, bool enable) { int ret = 0; /* we should hold wl->mutex */ - ret = wl1271_acx_ps_rx_streaming(wl, wlvif, enable); + ret = wl1271_acx_ps_rx_streaming(wl, enable); if (ret < 0) goto out; if (enable) - set_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags); + set_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags); else - clear_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags); + clear_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags); out: return ret; } @@ -512,25 +519,25 @@ static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, * this function is being called when the rx_streaming interval * has beed changed or rx_streaming should be disabled */ -int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl1271_recalc_rx_streaming(struct wl1271 *wl) { int ret = 0; int period = wl->conf.rx_streaming.interval; /* don't reconfigure if rx_streaming is disabled */ - if (!test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags)) + if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) goto out; /* reconfigure/disable according to new streaming_period */ if (period && - test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) && + test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) && (wl->conf.rx_streaming.always || test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) - ret = wl1271_set_rx_streaming(wl, wlvif, true); + ret = wl1271_set_rx_streaming(wl, true); else { - ret = wl1271_set_rx_streaming(wl, wlvif, false); + ret = wl1271_set_rx_streaming(wl, false); /* don't cancel_work_sync since we might deadlock */ - del_timer_sync(&wlvif->rx_streaming_timer); + del_timer_sync(&wl->rx_streaming_timer); } out: return ret; @@ -539,14 +546,13 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif) static void wl1271_rx_streaming_enable_work(struct work_struct *work) { int ret; - struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif, - rx_streaming_enable_work); - struct wl1271 *wl = wlvif->wl; + struct wl1271 *wl = + container_of(work, struct wl1271, rx_streaming_enable_work); mutex_lock(&wl->mutex); - if (test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags) || - !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || + if (test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags) || + !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || (!wl->conf.rx_streaming.always && !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) goto out; @@ -558,12 +564,12 @@ static void wl1271_rx_streaming_enable_work(struct work_struct *work) if (ret < 0) goto out; - ret = wl1271_set_rx_streaming(wl, wlvif, true); + ret = wl1271_set_rx_streaming(wl, true); if (ret < 0) goto out_sleep; /* stop it after some time of inactivity */ - mod_timer(&wlvif->rx_streaming_timer, + mod_timer(&wl->rx_streaming_timer, jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration)); out_sleep: @@ -575,20 +581,19 @@ static void wl1271_rx_streaming_enable_work(struct work_struct *work) static void wl1271_rx_streaming_disable_work(struct work_struct *work) { int ret; - struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif, - rx_streaming_disable_work); - struct wl1271 *wl = wlvif->wl; + struct wl1271 *wl = + container_of(work, struct wl1271, rx_streaming_disable_work); mutex_lock(&wl->mutex); - if (!test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags)) + if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) goto out; ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; - ret = wl1271_set_rx_streaming(wl, wlvif, false); + ret = wl1271_set_rx_streaming(wl, false); if (ret) goto out_sleep; @@ -600,9 +605,8 @@ static void wl1271_rx_streaming_disable_work(struct work_struct *work) static void wl1271_rx_streaming_timer(unsigned long data) { - struct wl12xx_vif *wlvif = (struct wl12xx_vif *)data; - struct wl1271 *wl = wlvif->wl; - ieee80211_queue_work(wl->hw, &wlvif->rx_streaming_disable_work); + struct wl1271 *wl = (struct wl1271 *)data; + ieee80211_queue_work(wl->hw, &wl->rx_streaming_disable_work); } static void wl1271_conf_init(struct wl1271 *wl) @@ -641,7 +645,9 @@ static void wl1271_conf_init(struct wl1271 *wl) static int wl1271_plt_init(struct wl1271 *wl) { - int ret; + struct conf_tx_ac_category *conf_ac; + struct conf_tx_tid *conf_tid; + int ret, i; if (wl->chip.id == CHIP_ID_1283_PG20) ret = wl128x_cmd_general_parms(wl); @@ -670,6 +676,10 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) return ret; + ret = wl1271_sta_init_templates_config(wl); + if (ret < 0) + return ret; + ret = wl1271_acx_init_mem_config(wl); if (ret < 0) return ret; @@ -679,10 +689,61 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) goto out_free_memmap; + ret = wl1271_acx_dco_itrim_params(wl); + if (ret < 0) + goto out_free_memmap; + + /* Initialize connection monitoring thresholds */ + ret = wl1271_acx_conn_monit_params(wl, false); + if (ret < 0) + goto out_free_memmap; + + /* Bluetooth WLAN coexistence */ + ret = wl1271_init_pta(wl); + if (ret < 0) + goto out_free_memmap; + + /* FM WLAN coexistence */ + ret = wl1271_acx_fm_coex(wl); + if (ret < 0) + goto out_free_memmap; + + /* Energy detection */ + ret = wl1271_init_energy_detection(wl); + if (ret < 0) + goto out_free_memmap; + ret = wl12xx_acx_mem_cfg(wl); if (ret < 0) goto out_free_memmap; + /* Default fragmentation threshold */ + ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); + if (ret < 0) + goto out_free_memmap; + + /* Default TID/AC configuration */ + BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); + for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { + conf_ac = &wl->conf.tx.ac_conf[i]; + ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, + conf_ac->cw_max, conf_ac->aifsn, + conf_ac->tx_op_limit); + if (ret < 0) + goto out_free_memmap; + + conf_tid = &wl->conf.tx.tid_conf[i]; + ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, + conf_tid->channel_type, + conf_tid->tsid, + conf_tid->ps_scheme, + conf_tid->ack_policy, + conf_tid->apsd_conf[0], + conf_tid->apsd_conf[1]); + if (ret < 0) + goto out_free_memmap; + } + /* Enable data path */ ret = wl1271_cmd_data_path(wl, 1); if (ret < 0) @@ -707,12 +768,14 @@ static int wl1271_plt_init(struct wl1271 *wl) return ret; } -static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, - struct wl12xx_vif *wlvif, - u8 hlid, u8 tx_pkts) +static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) { bool fw_ps, single_sta; + /* only regulate station links */ + if (hlid < WL1271_AP_STA_HLID_START) + return; + fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); single_sta = (wl->active_sta_count == 1); @@ -721,7 +784,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, * packets in FW or if the STA is awake. */ if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS) - wl12xx_ps_link_end(wl, wlvif, hlid); + wl1271_ps_link_end(wl, hlid); /* * Start high-level PS if the STA is asleep with enough blocks in FW. @@ -729,14 +792,24 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, * case FW-memory congestion is not a problem. */ else if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) - wl12xx_ps_link_start(wl, wlvif, hlid, true); + wl1271_ps_link_start(wl, hlid, true); +} + +bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) +{ + int id; + + /* global/broadcast "stations" are always active */ + if (hlid < WL1271_AP_STA_HLID_START) + return true; + + id = hlid - WL1271_AP_STA_HLID_START; + return test_bit(id, wl->ap_hlid_map); } static void wl12xx_irq_update_links_status(struct wl1271 *wl, - struct wl12xx_vif *wlvif, struct wl12xx_fw_status *status) { - struct wl1271_link *lnk; u32 cur_fw_ps_map; u8 hlid, cnt; @@ -752,22 +825,25 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, wl->ap_fw_ps_map = cur_fw_ps_map; } - for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS) { - lnk = &wl->links[hlid]; - cnt = status->tx_lnk_free_pkts[hlid] - lnk->prev_freed_pkts; + for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) { + if (!wl1271_is_active_sta(wl, hlid)) + continue; + + cnt = status->tx_lnk_free_pkts[hlid] - + wl->links[hlid].prev_freed_pkts; - lnk->prev_freed_pkts = status->tx_lnk_free_pkts[hlid]; - lnk->allocated_pkts -= cnt; + wl->links[hlid].prev_freed_pkts = + status->tx_lnk_free_pkts[hlid]; + wl->links[hlid].allocated_pkts -= cnt; - wl12xx_irq_ps_regulate_link(wl, wlvif, hlid, - lnk->allocated_pkts); + wl12xx_irq_ps_regulate_link(wl, hlid, + wl->links[hlid].allocated_pkts); } } static void wl12xx_fw_status(struct wl1271 *wl, struct wl12xx_fw_status *status) { - struct wl12xx_vif *wlvif; struct timespec ts; u32 old_tx_blk_count = wl->tx_blocks_available; int avail, freed_blocks; @@ -822,9 +898,8 @@ static void wl12xx_fw_status(struct wl1271 *wl, clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); /* for AP update num of allocated TX blocks per link and ps status */ - wl12xx_for_each_wlvif_ap(wl, wlvif) { - wl12xx_irq_update_links_status(wl, wlvif, status); - } + if (wl->bss_type == BSS_TYPE_AP_BSS) + wl12xx_irq_update_links_status(wl, status); /* update the host-chipset time offset */ getnstimeofday(&ts); @@ -857,7 +932,7 @@ static void wl1271_netstack_work(struct work_struct *work) #define WL1271_IRQ_MAX_LOOPS 256 -static irqreturn_t wl1271_irq(int irq, void *cookie) +irqreturn_t wl1271_irq(int irq, void *cookie) { int ret; u32 intr; @@ -979,6 +1054,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) return IRQ_HANDLED; } +EXPORT_SYMBOL_GPL(wl1271_irq); static int wl1271_fetch_firmware(struct wl1271 *wl) { @@ -993,10 +1069,10 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); - ret = request_firmware(&fw, fw_name, wl->dev); + ret = request_firmware(&fw, fw_name, wl1271_wl_to_dev(wl)); if (ret < 0) { - wl1271_error("could not get firmware %s: %d", fw_name, ret); + wl1271_error("could not get firmware: %d", ret); return ret; } @@ -1031,11 +1107,10 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) const struct firmware *fw; int ret; - ret = request_firmware(&fw, WL12XX_NVS_NAME, wl->dev); + ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); if (ret < 0) { - wl1271_error("could not get nvs file %s: %d", WL12XX_NVS_NAME, - ret); + wl1271_error("could not get nvs file: %d", ret); return ret; } @@ -1142,13 +1217,11 @@ static void wl1271_recovery_work(struct work_struct *work) { struct wl1271 *wl = container_of(work, struct wl1271, recovery_work); - struct wl12xx_vif *wlvif; - struct ieee80211_vif *vif; mutex_lock(&wl->mutex); if (wl->state != WL1271_STATE_ON) - goto out_unlock; + goto out; /* Avoid a recursive recovery */ set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); @@ -1165,12 +1238,9 @@ static void wl1271_recovery_work(struct work_struct *work) * in the firmware during recovery. This doens't hurt if the network is * not encrypted. */ - wl12xx_for_each_wlvif(wl, wlvif) { - if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || - test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) - wlvif->tx_security_seq += - WL1271_TX_SQN_POST_RECOVERY_PADDING; - } + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || + test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) + wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING; /* Prevent spurious TX during FW restart */ ieee80211_stop_queues(wl->hw); @@ -1181,14 +1251,7 @@ static void wl1271_recovery_work(struct work_struct *work) } /* reboot the chipset */ - while (!list_empty(&wl->wlvif_list)) { - wlvif = list_first_entry(&wl->wlvif_list, - struct wl12xx_vif, list); - vif = wl12xx_wlvif_to_vif(wlvif); - __wl1271_op_remove_interface(wl, vif, false); - } - mutex_unlock(&wl->mutex); - wl1271_op_stop(wl->hw); + __wl1271_op_remove_interface(wl, false); clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); @@ -1199,8 +1262,8 @@ static void wl1271_recovery_work(struct work_struct *work) * to restart the HW. */ ieee80211_wake_queues(wl->hw); - return; -out_unlock: + +out: mutex_unlock(&wl->mutex); } @@ -1255,16 +1318,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) /* 0. read chip id from CHIP_ID */ wl->chip.id = wl1271_read32(wl, CHIP_ID_B); - /* - * For wl127x based devices we could use the default block - * size (512 bytes), but due to a bug in the sdio driver, we - * need to set it explicitly after the chip is powered on. To - * simplify the code and since the performance impact is - * negligible, we use the same block size for all different - * chip types. - */ - if (!wl1271_set_block_size(wl)) - wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; + /* 1. check if chip id is valid */ switch (wl->chip.id) { case CHIP_ID_1271_PG10: @@ -1274,9 +1328,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) ret = wl1271_setup(wl); if (ret < 0) goto out; - wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; break; - case CHIP_ID_1271_PG20: wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", wl->chip.id); @@ -1284,9 +1336,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) ret = wl1271_setup(wl); if (ret < 0) goto out; - wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; break; - case CHIP_ID_1283_PG20: wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", wl->chip.id); @@ -1294,6 +1344,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) ret = wl1271_setup(wl); if (ret < 0) goto out; + + if (wl1271_set_block_size(wl)) + wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT; break; case CHIP_ID_1283_PG10: default: @@ -1336,6 +1389,8 @@ int wl1271_plt_start(struct wl1271 *wl) goto out; } + wl->bss_type = BSS_TYPE_STA_BSS; + while (retries) { retries--; ret = wl1271_chip_wakeup(wl); @@ -1427,33 +1482,32 @@ int wl1271_plt_stop(struct wl1271 *wl) static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) { struct wl1271 *wl = hw->priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_vif *vif = info->control.vif; - struct wl12xx_vif *wlvif = NULL; unsigned long flags; int q, mapping; - u8 hlid; - - if (vif) - wlvif = wl12xx_vif_to_data(vif); + u8 hlid = 0; mapping = skb_get_queue_mapping(skb); q = wl1271_tx_get_queue(mapping); - hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); + if (wl->bss_type == BSS_TYPE_AP_BSS) + hlid = wl12xx_tx_get_hlid_ap(wl, skb); spin_lock_irqsave(&wl->wl_lock, flags); /* queue the packet */ - if (hlid == WL12XX_INVALID_LINK_ID || - (wlvif && !test_bit(hlid, wlvif->links_map))) { - wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); - dev_kfree_skb(skb); - goto out; - } + if (wl->bss_type == BSS_TYPE_AP_BSS) { + if (!wl1271_is_active_sta(wl, hlid)) { + wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", + hlid, q); + dev_kfree_skb(skb); + goto out; + } - wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q); - skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); + wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q); + skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); + } else { + skb_queue_tail(&wl->tx_queue[q], skb); + } wl->tx_queue_count[q]++; @@ -1555,14 +1609,13 @@ static struct notifier_block wl1271_dev_notifier = { }; #ifdef CONFIG_PM -static int wl1271_configure_suspend_sta(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static int wl1271_configure_suspend_sta(struct wl1271 *wl) { int ret = 0; mutex_lock(&wl->mutex); - if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) goto out_unlock; ret = wl1271_ps_elp_wakeup(wl); @@ -1570,12 +1623,12 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, goto out_unlock; /* enter psm if needed*/ - if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { + if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { DECLARE_COMPLETION_ONSTACK(compl); - wlvif->ps_compl = &compl; - ret = wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, - wlvif->basic_rate, true); + wl->ps_compl = &compl; + ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, + wl->basic_rate, true); if (ret < 0) goto out_sleep; @@ -1607,21 +1660,20 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, } -static int wl1271_configure_suspend_ap(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static int wl1271_configure_suspend_ap(struct wl1271 *wl) { int ret = 0; mutex_lock(&wl->mutex); - if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) + if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) goto out_unlock; ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out_unlock; - ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); + ret = wl1271_acx_beacon_filter_opt(wl, true); wl1271_ps_elp_sleep(wl); out_unlock: @@ -1630,22 +1682,20 @@ static int wl1271_configure_suspend_ap(struct wl1271 *wl, } -static int wl1271_configure_suspend(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static int wl1271_configure_suspend(struct wl1271 *wl) { - if (wlvif->bss_type == BSS_TYPE_STA_BSS) - return wl1271_configure_suspend_sta(wl, wlvif); - if (wlvif->bss_type == BSS_TYPE_AP_BSS) - return wl1271_configure_suspend_ap(wl, wlvif); + if (wl->bss_type == BSS_TYPE_STA_BSS) + return wl1271_configure_suspend_sta(wl); + if (wl->bss_type == BSS_TYPE_AP_BSS) + return wl1271_configure_suspend_ap(wl); return 0; } -static void wl1271_configure_resume(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static void wl1271_configure_resume(struct wl1271 *wl) { int ret; - bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS; - bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; + bool is_sta = wl->bss_type == BSS_TYPE_STA_BSS; + bool is_ap = wl->bss_type == BSS_TYPE_AP_BSS; if (!is_sta && !is_ap) return; @@ -1657,11 +1707,11 @@ static void wl1271_configure_resume(struct wl1271 *wl, if (is_sta) { /* exit psm if it wasn't configured */ - if (!test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) - wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, - wlvif->basic_rate, true); + if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) + wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, + wl->basic_rate, true); } else if (is_ap) { - wl1271_acx_beacon_filter_opt(wl, wlvif, false); + wl1271_acx_beacon_filter_opt(wl, false); } wl1271_ps_elp_sleep(wl); @@ -1673,19 +1723,16 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif; int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); WARN_ON(!wow || !wow->any); wl->wow_enabled = true; - wl12xx_for_each_wlvif(wl, wlvif) { - ret = wl1271_configure_suspend(wl, wlvif); - if (ret < 0) { - wl1271_warning("couldn't prepare device to suspend"); - return ret; - } + ret = wl1271_configure_suspend(wl); + if (ret < 0) { + wl1271_warning("couldn't prepare device to suspend"); + return ret; } /* flush any remaining work */ wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); @@ -1704,9 +1751,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, wl1271_enable_interrupts(wl); flush_work(&wl->tx_work); - wl12xx_for_each_wlvif(wl, wlvif) { - flush_delayed_work(&wlvif->pspoll_work); - } + flush_delayed_work(&wl->pspoll_work); flush_delayed_work(&wl->elp_work); return 0; @@ -1715,7 +1760,6 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, static int wl1271_op_resume(struct ieee80211_hw *hw) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif; unsigned long flags; bool run_irq_work = false; @@ -1739,9 +1783,7 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) wl1271_irq(0, wl); wl1271_enable_interrupts(wl); } - wl12xx_for_each_wlvif(wl, wlvif) { - wl1271_configure_resume(wl, wlvif); - } + wl1271_configure_resume(wl); wl->wow_enabled = false; return 0; @@ -1768,119 +1810,20 @@ static int wl1271_op_start(struct ieee80211_hw *hw) static void wl1271_op_stop(struct ieee80211_hw *hw) { - struct wl1271 *wl = hw->priv; - int i; - wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); - - mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) { - mutex_unlock(&wl->mutex); - return; - } - /* - * this must be before the cancel_work calls below, so that the work - * functions don't perform further work. - */ - wl->state = WL1271_STATE_OFF; - mutex_unlock(&wl->mutex); - - mutex_lock(&wl_list_mutex); - list_del(&wl->list); - mutex_unlock(&wl_list_mutex); - - wl1271_disable_interrupts(wl); - wl1271_flush_deferred_work(wl); - cancel_delayed_work_sync(&wl->scan_complete_work); - cancel_work_sync(&wl->netstack_work); - cancel_work_sync(&wl->tx_work); - cancel_delayed_work_sync(&wl->elp_work); - - /* let's notify MAC80211 about the remaining pending TX frames */ - wl12xx_tx_reset(wl, true); - mutex_lock(&wl->mutex); - - wl1271_power_off(wl); - - wl->band = IEEE80211_BAND_2GHZ; - - wl->rx_counter = 0; - wl->power_level = WL1271_DEFAULT_POWER_LEVEL; - wl->tx_blocks_available = 0; - wl->tx_allocated_blocks = 0; - wl->tx_results_count = 0; - wl->tx_packets_count = 0; - wl->time_offset = 0; - wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; - wl->ap_fw_ps_map = 0; - wl->ap_ps_map = 0; - wl->sched_scanning = false; - memset(wl->roles_map, 0, sizeof(wl->roles_map)); - memset(wl->links_map, 0, sizeof(wl->links_map)); - memset(wl->roc_map, 0, sizeof(wl->roc_map)); - wl->active_sta_count = 0; - - /* The system link is always allocated */ - __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); - - /* - * this is performed after the cancel_work calls and the associated - * mutex_lock, so that wl1271_op_add_interface does not accidentally - * get executed before all these vars have been reset. - */ - wl->flags = 0; - - wl->tx_blocks_freed = 0; - - for (i = 0; i < NUM_TX_QUEUES; i++) { - wl->tx_pkts_freed[i] = 0; - wl->tx_allocated_pkts[i] = 0; - } - - wl1271_debugfs_reset(wl); - - kfree(wl->fw_status); - wl->fw_status = NULL; - kfree(wl->tx_res_if); - wl->tx_res_if = NULL; - kfree(wl->target_mem_map); - wl->target_mem_map = NULL; - - mutex_unlock(&wl->mutex); -} - -static int wl12xx_allocate_rate_policy(struct wl1271 *wl, u8 *idx) -{ - u8 policy = find_first_zero_bit(wl->rate_policies_map, - WL12XX_MAX_RATE_POLICIES); - if (policy >= WL12XX_MAX_RATE_POLICIES) - return -EBUSY; - - __set_bit(policy, wl->rate_policies_map); - *idx = policy; - return 0; } -static void wl12xx_free_rate_policy(struct wl1271 *wl, u8 *idx) +static u8 wl12xx_get_role_type(struct wl1271 *wl) { - if (WARN_ON(*idx >= WL12XX_MAX_RATE_POLICIES)) - return; - - __clear_bit(*idx, wl->rate_policies_map); - *idx = WL12XX_MAX_RATE_POLICIES; -} - -static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) -{ - switch (wlvif->bss_type) { + switch (wl->bss_type) { case BSS_TYPE_AP_BSS: - if (wlvif->p2p) + if (wl->p2p) return WL1271_ROLE_P2P_GO; else return WL1271_ROLE_AP; case BSS_TYPE_STA_BSS: - if (wlvif->p2p) + if (wl->p2p) return WL1271_ROLE_P2P_CL; else return WL1271_ROLE_STA; @@ -1889,95 +1832,78 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) return WL1271_ROLE_IBSS; default: - wl1271_error("invalid bss_type: %d", wlvif->bss_type); + wl1271_error("invalid bss_type: %d", wl->bss_type); } return WL12XX_INVALID_ROLE_TYPE; } -static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) +static int wl1271_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - int i; + struct wl1271 *wl = hw->priv; + struct wiphy *wiphy = hw->wiphy; + int retries = WL1271_BOOT_RETRIES; + int ret = 0; + u8 role_type; + bool booted = false; - /* clear everything but the persistent data */ - memset(wlvif, 0, offsetof(struct wl12xx_vif, persistent)); + wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", + ieee80211_vif_type_p2p(vif), vif->addr); + + mutex_lock(&wl->mutex); + if (wl->vif) { + wl1271_debug(DEBUG_MAC80211, + "multiple vifs are not supported yet"); + ret = -EBUSY; + goto out; + } + + /* + * in some very corner case HW recovery scenarios its possible to + * get here before __wl1271_op_remove_interface is complete, so + * opt out if that is the case. + */ + if (test_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags)) { + ret = -EBUSY; + goto out; + } switch (ieee80211_vif_type_p2p(vif)) { case NL80211_IFTYPE_P2P_CLIENT: - wlvif->p2p = 1; + wl->p2p = 1; /* fall-through */ case NL80211_IFTYPE_STATION: - wlvif->bss_type = BSS_TYPE_STA_BSS; + wl->bss_type = BSS_TYPE_STA_BSS; + wl->set_bss_type = BSS_TYPE_STA_BSS; break; case NL80211_IFTYPE_ADHOC: - wlvif->bss_type = BSS_TYPE_IBSS; + wl->bss_type = BSS_TYPE_IBSS; + wl->set_bss_type = BSS_TYPE_STA_BSS; break; case NL80211_IFTYPE_P2P_GO: - wlvif->p2p = 1; + wl->p2p = 1; /* fall-through */ case NL80211_IFTYPE_AP: - wlvif->bss_type = BSS_TYPE_AP_BSS; + wl->bss_type = BSS_TYPE_AP_BSS; break; default: - wlvif->bss_type = MAX_BSS_TYPE; - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto out; } - wlvif->role_id = WL12XX_INVALID_ROLE_ID; - wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; - wlvif->dev_hlid = WL12XX_INVALID_LINK_ID; - - if (wlvif->bss_type == BSS_TYPE_STA_BSS || - wlvif->bss_type == BSS_TYPE_IBSS) { - /* init sta/ibss data */ - wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; - wl12xx_allocate_rate_policy(wl, &wlvif->sta.basic_rate_idx); - wl12xx_allocate_rate_policy(wl, &wlvif->sta.ap_rate_idx); - wl12xx_allocate_rate_policy(wl, &wlvif->sta.p2p_rate_idx); - } else { - /* init ap data */ - wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; - wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; - wl12xx_allocate_rate_policy(wl, &wlvif->ap.mgmt_rate_idx); - wl12xx_allocate_rate_policy(wl, &wlvif->ap.bcast_rate_idx); - for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) - wl12xx_allocate_rate_policy(wl, - &wlvif->ap.ucast_rate_idx[i]); + role_type = wl12xx_get_role_type(wl); + if (role_type == WL12XX_INVALID_ROLE_TYPE) { + ret = -EINVAL; + goto out; } + memcpy(wl->mac_addr, vif->addr, ETH_ALEN); - wlvif->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; - wlvif->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; - wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; - wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; - wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; - wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; - - /* - * mac80211 configures some values globally, while we treat them - * per-interface. thus, on init, we have to copy them from wl - */ - wlvif->band = wl->band; - wlvif->channel = wl->channel; - wlvif->power_level = wl->power_level; - - INIT_WORK(&wlvif->rx_streaming_enable_work, - wl1271_rx_streaming_enable_work); - INIT_WORK(&wlvif->rx_streaming_disable_work, - wl1271_rx_streaming_disable_work); - INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work); - INIT_LIST_HEAD(&wlvif->list); - - setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, - (unsigned long) wlvif); - return 0; -} - -static bool wl12xx_init_fw(struct wl1271 *wl) -{ - int retries = WL1271_BOOT_RETRIES; - bool booted = false; - struct wiphy *wiphy = wl->hw->wiphy; - int ret; + if (wl->state != WL1271_STATE_OFF) { + wl1271_error("cannot start because not in off state: %d", + wl->state); + ret = -EBUSY; + goto out; + } while (retries) { retries--; @@ -1989,6 +1915,25 @@ static bool wl12xx_init_fw(struct wl1271 *wl) if (ret < 0) goto power_off; + if (wl->bss_type == BSS_TYPE_STA_BSS || + wl->bss_type == BSS_TYPE_IBSS) { + /* + * The device role is a special role used for + * rx and tx frames prior to association (as + * the STA role can get packets only from + * its associated bssid) + */ + ret = wl12xx_cmd_role_enable(wl, + WL1271_ROLE_DEVICE, + &wl->dev_role_id); + if (ret < 0) + goto irq_disable; + } + + ret = wl12xx_cmd_role_enable(wl, role_type, &wl->role_id); + if (ret < 0) + goto irq_disable; + ret = wl1271_hw_init(wl); if (ret < 0) goto irq_disable; @@ -2019,6 +1964,9 @@ static bool wl12xx_init_fw(struct wl1271 *wl) goto out; } + wl->vif = vif; + wl->state = WL1271_STATE_ON; + set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags); wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); /* update hw/fw version info in wiphy struct */ @@ -2036,110 +1984,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl) wl1271_debug(DEBUG_MAC80211, "11a is %ssupported", wl->enable_11a ? "" : "not "); - wl->state = WL1271_STATE_ON; -out: - return booted; -} - -static int wl1271_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - int ret = 0; - u8 role_type; - bool booted = false; - - wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", - ieee80211_vif_type_p2p(vif), vif->addr); - - mutex_lock(&wl->mutex); - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out_unlock; - - if (wl->vif) { - wl1271_debug(DEBUG_MAC80211, - "multiple vifs are not supported yet"); - ret = -EBUSY; - goto out; - } - - /* - * in some very corner case HW recovery scenarios its possible to - * get here before __wl1271_op_remove_interface is complete, so - * opt out if that is the case. - */ - if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags) || - test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) { - ret = -EBUSY; - goto out; - } - - ret = wl12xx_init_vif_data(wl, vif); - if (ret < 0) - goto out; - - wlvif->wl = wl; - role_type = wl12xx_get_role_type(wl, wlvif); - if (role_type == WL12XX_INVALID_ROLE_TYPE) { - ret = -EINVAL; - goto out; - } - - /* - * TODO: after the nvs issue will be solved, move this block - * to start(), and make sure here the driver is ON. - */ - if (wl->state == WL1271_STATE_OFF) { - /* - * we still need this in order to configure the fw - * while uploading the nvs - */ - memcpy(wl->mac_addr, vif->addr, ETH_ALEN); - - booted = wl12xx_init_fw(wl); - if (!booted) { - ret = -EINVAL; - goto out; - } - } - - if (wlvif->bss_type == BSS_TYPE_STA_BSS || - wlvif->bss_type == BSS_TYPE_IBSS) { - /* - * The device role is a special role used for - * rx and tx frames prior to association (as - * the STA role can get packets only from - * its associated bssid) - */ - ret = wl12xx_cmd_role_enable(wl, vif->addr, - WL1271_ROLE_DEVICE, - &wlvif->dev_role_id); - if (ret < 0) - goto out; - } - - ret = wl12xx_cmd_role_enable(wl, vif->addr, - role_type, &wlvif->role_id); - if (ret < 0) - goto out; - - ret = wl1271_init_vif_specific(wl, vif); - if (ret < 0) - goto out; - - wl->vif = vif; - list_add(&wlvif->list, &wl->wlvif_list); - set_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags); - - if (wlvif->bss_type == BSS_TYPE_AP_BSS) - wl->ap_count++; - else - wl->sta_count++; out: - wl1271_ps_elp_sleep(wl); -out_unlock: mutex_unlock(&wl->mutex); mutex_lock(&wl_list_mutex); @@ -2151,34 +1996,29 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, } static void __wl1271_op_remove_interface(struct wl1271 *wl, - struct ieee80211_vif *vif, bool reset_tx_queues) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - int i, ret; + int ret, i; wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); - if (!test_and_clear_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) - return; - - wl->vif = NULL; - /* because of hardware recovery, we may get here twice */ if (wl->state != WL1271_STATE_ON) return; wl1271_info("down"); + mutex_lock(&wl_list_mutex); + list_del(&wl->list); + mutex_unlock(&wl_list_mutex); + /* enable dyn ps just in case (if left on due to fw crash etc) */ - if (wlvif->bss_type == BSS_TYPE_STA_BSS) - ieee80211_enable_dyn_ps(vif); + if (wl->bss_type == BSS_TYPE_STA_BSS) + ieee80211_enable_dyn_ps(wl->vif); - if (wl->scan.state != WL1271_SCAN_STATE_IDLE && - wl->scan_vif == vif) { + if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); - wl->scan_vif = NULL; wl->scan.req = NULL; ieee80211_scan_completed(wl->hw, true); } @@ -2189,13 +2029,13 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, if (ret < 0) goto deinit; - if (wlvif->bss_type == BSS_TYPE_STA_BSS) { - ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); + if (wl->bss_type == BSS_TYPE_STA_BSS) { + ret = wl12xx_cmd_role_disable(wl, &wl->dev_role_id); if (ret < 0) goto deinit; } - ret = wl12xx_cmd_role_disable(wl, &wlvif->role_id); + ret = wl12xx_cmd_role_disable(wl, &wl->role_id); if (ret < 0) goto deinit; @@ -2203,82 +2043,120 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, } deinit: /* clear all hlids (except system_hlid) */ - wlvif->dev_hlid = WL12XX_INVALID_LINK_ID; - - if (wlvif->bss_type == BSS_TYPE_STA_BSS || - wlvif->bss_type == BSS_TYPE_IBSS) { - wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; - wl12xx_free_rate_policy(wl, &wlvif->sta.basic_rate_idx); - wl12xx_free_rate_policy(wl, &wlvif->sta.ap_rate_idx); - wl12xx_free_rate_policy(wl, &wlvif->sta.p2p_rate_idx); - } else { - wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; - wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; - wl12xx_free_rate_policy(wl, &wlvif->ap.mgmt_rate_idx); - wl12xx_free_rate_policy(wl, &wlvif->ap.bcast_rate_idx); - for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) - wl12xx_free_rate_policy(wl, - &wlvif->ap.ucast_rate_idx[i]); - } + wl->sta_hlid = WL12XX_INVALID_LINK_ID; + wl->dev_hlid = WL12XX_INVALID_LINK_ID; + wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; + wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; - wl12xx_tx_reset_wlvif(wl, wlvif); - wl1271_free_ap_keys(wl, wlvif); - if (wl->last_wlvif == wlvif) - wl->last_wlvif = NULL; - list_del(&wlvif->list); - memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map)); - wlvif->role_id = WL12XX_INVALID_ROLE_ID; - wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; - - if (wlvif->bss_type == BSS_TYPE_AP_BSS) - wl->ap_count--; - else - wl->sta_count--; + /* + * this must be before the cancel_work calls below, so that the work + * functions don't perform further work. + */ + wl->state = WL1271_STATE_OFF; mutex_unlock(&wl->mutex); - del_timer_sync(&wlvif->rx_streaming_timer); - cancel_work_sync(&wlvif->rx_streaming_enable_work); - cancel_work_sync(&wlvif->rx_streaming_disable_work); - cancel_delayed_work_sync(&wlvif->pspoll_work); + + wl1271_disable_interrupts(wl); + wl1271_flush_deferred_work(wl); + cancel_delayed_work_sync(&wl->scan_complete_work); + cancel_work_sync(&wl->netstack_work); + cancel_work_sync(&wl->tx_work); + del_timer_sync(&wl->rx_streaming_timer); + cancel_work_sync(&wl->rx_streaming_enable_work); + cancel_work_sync(&wl->rx_streaming_disable_work); + cancel_delayed_work_sync(&wl->pspoll_work); + cancel_delayed_work_sync(&wl->elp_work); mutex_lock(&wl->mutex); + + /* let's notify MAC80211 about the remaining pending TX frames */ + wl1271_tx_reset(wl, reset_tx_queues); + wl1271_power_off(wl); + + memset(wl->bssid, 0, ETH_ALEN); + memset(wl->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); + wl->ssid_len = 0; + wl->bss_type = MAX_BSS_TYPE; + wl->set_bss_type = MAX_BSS_TYPE; + wl->p2p = 0; + wl->band = IEEE80211_BAND_2GHZ; + + wl->rx_counter = 0; + wl->psm_entry_retry = 0; + wl->power_level = WL1271_DEFAULT_POWER_LEVEL; + wl->tx_blocks_available = 0; + wl->tx_allocated_blocks = 0; + wl->tx_results_count = 0; + wl->tx_packets_count = 0; + wl->time_offset = 0; + wl->session_counter = 0; + wl->rate_set = CONF_TX_RATE_MASK_BASIC; + wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; + wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; + wl->vif = NULL; + wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; + wl1271_free_ap_keys(wl); + memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); + wl->ap_fw_ps_map = 0; + wl->ap_ps_map = 0; + wl->sched_scanning = false; + wl->role_id = WL12XX_INVALID_ROLE_ID; + wl->dev_role_id = WL12XX_INVALID_ROLE_ID; + memset(wl->roles_map, 0, sizeof(wl->roles_map)); + memset(wl->links_map, 0, sizeof(wl->links_map)); + memset(wl->roc_map, 0, sizeof(wl->roc_map)); + wl->active_sta_count = 0; + + /* The system link is always allocated */ + __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); + + /* + * this is performed after the cancel_work calls and the associated + * mutex_lock, so that wl1271_op_add_interface does not accidentally + * get executed before all these vars have been reset. + */ + wl->flags = 0; + + wl->tx_blocks_freed = 0; + + for (i = 0; i < NUM_TX_QUEUES; i++) { + wl->tx_pkts_freed[i] = 0; + wl->tx_allocated_pkts[i] = 0; + } + + wl1271_debugfs_reset(wl); + + kfree(wl->fw_status); + wl->fw_status = NULL; + kfree(wl->tx_res_if); + wl->tx_res_if = NULL; + kfree(wl->target_mem_map); + wl->target_mem_map = NULL; } static void wl1271_op_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - struct wl12xx_vif *iter; mutex_lock(&wl->mutex); - - if (wl->state == WL1271_STATE_OFF || - !test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) - goto out; - /* * wl->vif can be null here if someone shuts down the interface * just when hardware recovery has been started. */ - wl12xx_for_each_wlvif(wl, iter) { - if (iter != wlvif) - continue; - - __wl1271_op_remove_interface(wl, vif, true); - break; + if (wl->vif) { + WARN_ON(wl->vif != vif); + __wl1271_op_remove_interface(wl, true); } - WARN_ON(iter != wlvif); -out: + mutex_unlock(&wl->mutex); cancel_work_sync(&wl->recovery_work); } -static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool set_assoc) +static int wl1271_join(struct wl1271 *wl, bool set_assoc) { int ret; - bool is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); + bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); /* * One of the side effects of the JOIN command is that is clears @@ -2289,20 +2167,20 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, * Keep the below message for now, unless it starts bothering * users who really like to roam a lot :) */ - if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) wl1271_info("JOIN while associated."); if (set_assoc) - set_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags); + set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); if (is_ibss) - ret = wl12xx_cmd_role_start_ibss(wl, wlvif); + ret = wl12xx_cmd_role_start_ibss(wl); else - ret = wl12xx_cmd_role_start_sta(wl, wlvif); + ret = wl12xx_cmd_role_start_sta(wl); if (ret < 0) goto out; - if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) goto out; /* @@ -2311,20 +2189,19 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, * the join. The acx_aid starts the keep-alive process, and the order * of the commands below is relevant. */ - ret = wl1271_acx_keep_alive_mode(wl, wlvif, true); + ret = wl1271_acx_keep_alive_mode(wl, true); if (ret < 0) goto out; - ret = wl1271_acx_aid(wl, wlvif, wlvif->aid); + ret = wl1271_acx_aid(wl, wl->aid); if (ret < 0) goto out; - ret = wl12xx_cmd_build_klv_null_data(wl, wlvif); + ret = wl1271_cmd_build_klv_null_data(wl); if (ret < 0) goto out; - ret = wl1271_acx_keep_alive_config(wl, wlvif, - CMD_TEMPL_KLV_IDX_NULL_DATA, + ret = wl1271_acx_keep_alive_config(wl, CMD_TEMPL_KLV_IDX_NULL_DATA, ACX_KEEP_ALIVE_TPL_VALID); if (ret < 0) goto out; @@ -2333,34 +2210,34 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif) +static int wl1271_unjoin(struct wl1271 *wl) { int ret; - if (test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags)) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); - + if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) { wl12xx_cmd_stop_channel_switch(wl); - ieee80211_chswitch_done(vif, false); + ieee80211_chswitch_done(wl->vif, false); } /* to stop listening to a channel, we disconnect */ - ret = wl12xx_cmd_role_stop_sta(wl, wlvif); + ret = wl12xx_cmd_role_stop_sta(wl); if (ret < 0) goto out; + memset(wl->bssid, 0, ETH_ALEN); + /* reset TX security counters on a clean disconnect */ - wlvif->tx_security_last_seq_lsb = 0; - wlvif->tx_security_seq = 0; + wl->tx_security_last_seq_lsb = 0; + wl->tx_security_seq = 0; out: return ret; } -static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif) +static void wl1271_set_band_rate(struct wl1271 *wl) { - wlvif->basic_rate_set = wlvif->bitrate_masks[wlvif->band]; - wlvif->rate_set = wlvif->basic_rate_set; + wl->basic_rate_set = wl->bitrate_masks[wl->band]; + wl->rate_set = wl->basic_rate_set; } static bool wl12xx_is_roc(struct wl1271 *wl) @@ -2374,25 +2251,27 @@ static bool wl12xx_is_roc(struct wl1271 *wl) return true; } -static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, - bool idle) +static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) { int ret; if (idle) { /* no need to croc if we weren't busy (e.g. during boot) */ if (wl12xx_is_roc(wl)) { - ret = wl12xx_stop_dev(wl, wlvif); + ret = wl12xx_croc(wl, wl->dev_role_id); + if (ret < 0) + goto out; + + ret = wl12xx_cmd_role_stop_dev(wl); if (ret < 0) goto out; } - wlvif->rate_set = - wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); - ret = wl1271_acx_sta_rate_policies(wl, wlvif); + wl->rate_set = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) goto out; ret = wl1271_acx_keep_alive_config( - wl, wlvif, CMD_TEMPL_KLV_IDX_NULL_DATA, + wl, CMD_TEMPL_KLV_IDX_NULL_DATA, ACX_KEEP_ALIVE_TPL_INVALID); if (ret < 0) goto out; @@ -2404,32 +2283,75 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, ieee80211_sched_scan_stopped(wl->hw); } - ret = wl12xx_start_dev(wl, wlvif); - if (ret < 0) - goto out; - clear_bit(WL1271_FLAG_IDLE, &wl->flags); - } + ret = wl12xx_cmd_role_start_dev(wl); + if (ret < 0) + goto out; + + ret = wl12xx_roc(wl, wl->dev_role_id); + if (ret < 0) + goto out; + clear_bit(WL1271_FLAG_IDLE, &wl->flags); + } + +out: + return ret; +} + +static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) +{ + struct wl1271 *wl = hw->priv; + struct ieee80211_conf *conf = &hw->conf; + int channel, ret = 0; + bool is_ap; + + channel = ieee80211_frequency_to_channel(conf->channel->center_freq); + + wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s" + " changed 0x%x", + channel, + conf->flags & IEEE80211_CONF_PS ? "on" : "off", + conf->power_level, + conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use", + changed); + + /* + * mac80211 will go to idle nearly immediately after transmitting some + * frames, such as the deauth. To make sure those frames reach the air, + * wait here until the TX queue is fully flushed. + */ + if ((changed & IEEE80211_CONF_CHANGE_IDLE) && + (conf->flags & IEEE80211_CONF_IDLE)) + wl1271_tx_flush(wl); + + mutex_lock(&wl->mutex); + + if (unlikely(wl->state == WL1271_STATE_OFF)) { + /* we support configuring the channel and band while off */ + if ((changed & IEEE80211_CONF_CHANGE_CHANNEL)) { + wl->band = conf->channel->band; + wl->channel = channel; + } + + if ((changed & IEEE80211_CONF_CHANGE_POWER)) + wl->power_level = conf->power_level; -out: - return ret; -} + goto out; + } -static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct ieee80211_conf *conf, u32 changed) -{ - bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); - int channel, ret; + is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); - channel = ieee80211_frequency_to_channel(conf->channel->center_freq); + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; /* if the channel changes while joined, join again */ if (changed & IEEE80211_CONF_CHANGE_CHANNEL && - ((wlvif->band != conf->channel->band) || - (wlvif->channel != channel))) { + ((wl->band != conf->channel->band) || + (wl->channel != channel))) { /* send all pending packets */ wl1271_tx_work_locked(wl); - wlvif->band = conf->channel->band; - wlvif->channel = channel; + wl->band = conf->channel->band; + wl->channel = channel; if (!is_ap) { /* @@ -2438,27 +2360,24 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, * possible rate for the band as a fixed rate for * association frames and other control messages. */ - if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) - wl1271_set_band_rate(wl, wlvif); + if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) + wl1271_set_band_rate(wl); - wlvif->basic_rate = - wl1271_tx_min_rate_get(wl, - wlvif->basic_rate_set); - ret = wl1271_acx_sta_rate_policies(wl, wlvif); + wl->basic_rate = + wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) wl1271_warning("rate policy for channel " "failed %d", ret); - if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, - &wlvif->flags)) { + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { if (wl12xx_is_roc(wl)) { /* roaming */ - ret = wl12xx_croc(wl, - wlvif->dev_role_id); + ret = wl12xx_croc(wl, wl->dev_role_id); if (ret < 0) - return ret; + goto out_sleep; } - ret = wl1271_join(wl, wlvif, false); + ret = wl1271_join(wl, false); if (ret < 0) wl1271_warning("cmd join on channel " "failed %d", ret); @@ -2470,112 +2389,64 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, */ if (wl12xx_is_roc(wl) && !(conf->flags & IEEE80211_CONF_IDLE)) { - ret = wl12xx_stop_dev(wl, wlvif); + ret = wl12xx_croc(wl, wl->dev_role_id); if (ret < 0) - return ret; + goto out_sleep; - ret = wl12xx_start_dev(wl, wlvif); + ret = wl12xx_roc(wl, wl->dev_role_id); if (ret < 0) - return ret; + wl1271_warning("roc failed %d", + ret); } } } } + if (changed & IEEE80211_CONF_CHANGE_IDLE && !is_ap) { + ret = wl1271_sta_handle_idle(wl, + conf->flags & IEEE80211_CONF_IDLE); + if (ret < 0) + wl1271_warning("idle mode change failed %d", ret); + } + /* * if mac80211 changes the PSM mode, make sure the mode is not * incorrectly changed after the pspoll failure active window. */ if (changed & IEEE80211_CONF_CHANGE_PS) - clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags); + clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); if (conf->flags & IEEE80211_CONF_PS && - !test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) { - set_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags); + !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { + set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); /* * We enter PSM only if we're already associated. * If we're not, we'll enter it when joining an SSID, * through the bss_info_changed() hook. */ - if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { wl1271_debug(DEBUG_PSM, "psm enabled"); - ret = wl1271_ps_set_mode(wl, wlvif, - STATION_POWER_SAVE_MODE, - wlvif->basic_rate, true); + ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, + wl->basic_rate, true); } } else if (!(conf->flags & IEEE80211_CONF_PS) && - test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) { + test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { wl1271_debug(DEBUG_PSM, "psm disabled"); - clear_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags); + clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); - if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) - ret = wl1271_ps_set_mode(wl, wlvif, - STATION_ACTIVE_MODE, - wlvif->basic_rate, true); + if (test_bit(WL1271_FLAG_PSM, &wl->flags)) + ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, + wl->basic_rate, true); } - if (conf->power_level != wlvif->power_level) { - ret = wl1271_acx_tx_power(wl, wlvif, conf->power_level); + if (conf->power_level != wl->power_level) { + ret = wl1271_acx_tx_power(wl, conf->power_level); if (ret < 0) - return ret; - - wlvif->power_level = conf->power_level; - } - - return 0; -} - -static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) -{ - struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif; - struct ieee80211_conf *conf = &hw->conf; - int channel, ret = 0; - - channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - - wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s" - " changed 0x%x", - channel, - conf->flags & IEEE80211_CONF_PS ? "on" : "off", - conf->power_level, - conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use", - changed); - - /* - * mac80211 will go to idle nearly immediately after transmitting some - * frames, such as the deauth. To make sure those frames reach the air, - * wait here until the TX queue is fully flushed. - */ - if ((changed & IEEE80211_CONF_CHANGE_IDLE) && - (conf->flags & IEEE80211_CONF_IDLE)) - wl1271_tx_flush(wl); - - mutex_lock(&wl->mutex); - - /* we support configuring the channel and band even while off */ - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - wl->band = conf->channel->band; - wl->channel = channel; - } + goto out_sleep; - if (changed & IEEE80211_CONF_CHANGE_POWER) wl->power_level = conf->power_level; - - if (unlikely(wl->state == WL1271_STATE_OFF)) - goto out; - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - /* configure each interface */ - wl12xx_for_each_wlvif(wl, wlvif) { - ret = wl12xx_config_vif(wl, wlvif, conf, changed); - if (ret < 0) - goto out_sleep; } out_sleep: @@ -2638,8 +2509,6 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, { struct wl1271_filter_params *fp = (void *)(unsigned long)multicast; struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif; - int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter changed %x" @@ -2657,20 +2526,15 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, if (ret < 0) goto out; - wl12xx_for_each_wlvif(wl, wlvif) { - if (wlvif->bss_type != BSS_TYPE_AP_BSS) { - if (*total & FIF_ALLMULTI) - ret = wl1271_acx_group_address_tbl(wl, wlvif, - false, - NULL, 0); - else if (fp) - ret = wl1271_acx_group_address_tbl(wl, wlvif, - fp->enabled, - fp->mc_list, - fp->mc_list_length); - if (ret < 0) - goto out_sleep; - } + if (wl->bss_type != BSS_TYPE_AP_BSS) { + if (*total & FIF_ALLMULTI) + ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); + else if (fp) + ret = wl1271_acx_group_address_tbl(wl, fp->enabled, + fp->mc_list, + fp->mc_list_length); + if (ret < 0) + goto out_sleep; } /* @@ -2687,10 +2551,9 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, kfree(fp); } -static int wl1271_record_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 id, u8 key_type, u8 key_size, - const u8 *key, u8 hlid, u32 tx_seq_32, - u16 tx_seq_16) +static int wl1271_record_ap_key(struct wl1271 *wl, u8 id, u8 key_type, + u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, + u16 tx_seq_16) { struct wl1271_ap_key *ap_key; int i; @@ -2705,10 +2568,10 @@ static int wl1271_record_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, * an existing key. */ for (i = 0; i < MAX_NUM_KEYS; i++) { - if (wlvif->ap.recorded_keys[i] == NULL) + if (wl->recorded_ap_keys[i] == NULL) break; - if (wlvif->ap.recorded_keys[i]->id == id) { + if (wl->recorded_ap_keys[i]->id == id) { wl1271_warning("trying to record key replacement"); return -EINVAL; } @@ -2729,21 +2592,21 @@ static int wl1271_record_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, ap_key->tx_seq_32 = tx_seq_32; ap_key->tx_seq_16 = tx_seq_16; - wlvif->ap.recorded_keys[i] = ap_key; + wl->recorded_ap_keys[i] = ap_key; return 0; } -static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif) +static void wl1271_free_ap_keys(struct wl1271 *wl) { int i; for (i = 0; i < MAX_NUM_KEYS; i++) { - kfree(wlvif->ap.recorded_keys[i]); - wlvif->ap.recorded_keys[i] = NULL; + kfree(wl->recorded_ap_keys[i]); + wl->recorded_ap_keys[i] = NULL; } } -static int wl1271_ap_init_hwenc(struct wl1271 *wl, struct wl12xx_vif *wlvif) +static int wl1271_ap_init_hwenc(struct wl1271 *wl) { int i, ret = 0; struct wl1271_ap_key *key; @@ -2751,15 +2614,15 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl, struct wl12xx_vif *wlvif) for (i = 0; i < MAX_NUM_KEYS; i++) { u8 hlid; - if (wlvif->ap.recorded_keys[i] == NULL) + if (wl->recorded_ap_keys[i] == NULL) break; - key = wlvif->ap.recorded_keys[i]; + key = wl->recorded_ap_keys[i]; hlid = key->hlid; if (hlid == WL12XX_INVALID_LINK_ID) - hlid = wlvif->ap.bcast_hlid; + hlid = wl->ap_bcast_hlid; - ret = wl1271_cmd_set_ap_key(wl, wlvif, KEY_ADD_OR_REPLACE, + ret = wl1271_cmd_set_ap_key(wl, KEY_ADD_OR_REPLACE, key->id, key->key_type, key->key_size, key->key, hlid, key->tx_seq_32, @@ -2772,24 +2635,23 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl, struct wl12xx_vif *wlvif) } if (wep_key_added) { - ret = wl12xx_cmd_set_default_wep_key(wl, wlvif->default_key, - wlvif->ap.bcast_hlid); + ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key, + wl->ap_bcast_hlid); if (ret < 0) goto out; } out: - wl1271_free_ap_keys(wl, wlvif); + wl1271_free_ap_keys(wl); return ret; } -static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u16 action, u8 id, u8 key_type, +static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, u8 key_size, const u8 *key, u32 tx_seq_32, u16 tx_seq_16, struct ieee80211_sta *sta) { int ret; - bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); + bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); if (is_ap) { struct wl1271_station *wl_sta; @@ -2799,10 +2661,10 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, wl_sta = (struct wl1271_station *)sta->drv_priv; hlid = wl_sta->hlid; } else { - hlid = wlvif->ap.bcast_hlid; + hlid = wl->ap_bcast_hlid; } - if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { + if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { /* * We do not support removing keys after AP shutdown. * Pretend we do to make mac80211 happy. @@ -2810,12 +2672,12 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (action != KEY_ADD_OR_REPLACE) return 0; - ret = wl1271_record_ap_key(wl, wlvif, id, + ret = wl1271_record_ap_key(wl, id, key_type, key_size, key, hlid, tx_seq_32, tx_seq_16); } else { - ret = wl1271_cmd_set_ap_key(wl, wlvif, action, + ret = wl1271_cmd_set_ap_key(wl, action, id, key_type, key_size, key, hlid, tx_seq_32, tx_seq_16); @@ -2856,10 +2718,10 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, /* don't remove key if hlid was already deleted */ if (action == KEY_REMOVE && - wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) + wl->sta_hlid == WL12XX_INVALID_LINK_ID) return 0; - ret = wl1271_cmd_set_sta_key(wl, wlvif, action, + ret = wl1271_cmd_set_sta_key(wl, action, id, key_type, key_size, key, addr, tx_seq_32, tx_seq_16); @@ -2869,8 +2731,8 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, /* the default WEP key needs to be configured at least once */ if (key_type == KEY_WEP) { ret = wl12xx_cmd_set_default_wep_key(wl, - wlvif->default_key, - wlvif->sta.hlid); + wl->default_key, + wl->sta_hlid); if (ret < 0) return ret; } @@ -2885,7 +2747,6 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key_conf) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; u32 tx_seq_32 = 0; u16 tx_seq_16 = 0; @@ -2921,20 +2782,20 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, key_type = KEY_TKIP; key_conf->hw_key_idx = key_conf->keyidx; - tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); - tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); + tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); + tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); break; case WLAN_CIPHER_SUITE_CCMP: key_type = KEY_AES; - key_conf->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; - tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); - tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); + key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); + tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); break; case WL1271_CIPHER_SUITE_GEM: key_type = KEY_GEM; - tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); - tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); + tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); + tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); break; default: wl1271_error("Unknown key algo 0x%x", key_conf->cipher); @@ -2945,7 +2806,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, switch (cmd) { case SET_KEY: - ret = wl1271_set_key(wl, wlvif, KEY_ADD_OR_REPLACE, + ret = wl1271_set_key(wl, KEY_ADD_OR_REPLACE, key_conf->keyidx, key_type, key_conf->keylen, key_conf->key, tx_seq_32, tx_seq_16, sta); @@ -2956,7 +2817,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, break; case DISABLE_KEY: - ret = wl1271_set_key(wl, wlvif, KEY_REMOVE, + ret = wl1271_set_key(wl, KEY_REMOVE, key_conf->keyidx, key_type, key_conf->keylen, key_conf->key, 0, 0, sta); @@ -2986,8 +2847,6 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - int ret; u8 *ssid = NULL; size_t len = 0; @@ -3017,15 +2876,16 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, /* cancel ROC before scanning */ if (wl12xx_is_roc(wl)) { - if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { /* don't allow scanning right now */ ret = -EBUSY; goto out_sleep; } - wl12xx_stop_dev(wl, wlvif); + wl12xx_croc(wl, wl->dev_role_id); + wl12xx_cmd_role_stop_dev(wl); } - ret = wl1271_scan(hw->priv, vif, ssid, len, req); + ret = wl1271_scan(hw->priv, ssid, len, req); out_sleep: wl1271_ps_elp_sleep(wl); out: @@ -3061,7 +2921,6 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw, } wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); - wl->scan_vif = NULL; wl->scan.req = NULL; ieee80211_scan_completed(wl->hw, true); @@ -3079,7 +2938,6 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, struct ieee80211_sched_scan_ies *ies) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_start"); @@ -3090,11 +2948,11 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, if (ret < 0) goto out; - ret = wl1271_scan_sched_scan_config(wl, wlvif, req, ies); + ret = wl1271_scan_sched_scan_config(wl, req, ies); if (ret < 0) goto out_sleep; - ret = wl1271_scan_sched_scan_start(wl, wlvif); + ret = wl1271_scan_sched_scan_start(wl); if (ret < 0) goto out_sleep; @@ -3159,7 +3017,6 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif; int ret = 0; mutex_lock(&wl->mutex); @@ -3173,11 +3030,10 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) if (ret < 0) goto out; - wl12xx_for_each_wlvif(wl, wlvif) { - ret = wl1271_acx_rts_threshold(wl, wlvif, value); - if (ret < 0) - wl1271_warning("set rts threshold failed: %d", ret); - } + ret = wl1271_acx_rts_threshold(wl, value); + if (ret < 0) + wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); + wl1271_ps_elp_sleep(wl); out: @@ -3186,10 +3042,9 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) return ret; } -static int wl1271_ssid_set(struct ieee80211_vif *vif, struct sk_buff *skb, +static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, int offset) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); u8 ssid_len; const u8 *ptr = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset, skb->len - offset); @@ -3205,8 +3060,8 @@ static int wl1271_ssid_set(struct ieee80211_vif *vif, struct sk_buff *skb, return -EINVAL; } - wlvif->ssid_len = ssid_len; - memcpy(wlvif->ssid, ptr+2, ssid_len); + wl->ssid_len = ssid_len; + memcpy(wl->ssid, ptr+2, ssid_len); return 0; } @@ -3241,40 +3096,18 @@ static void wl12xx_remove_vendor_ie(struct sk_buff *skb, skb_trim(skb, skb->len - len); } -static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates, - struct ieee80211_vif *vif) -{ - struct sk_buff *skb; - int ret; - - skb = ieee80211_proberesp_get(wl->hw, vif); - if (!skb) - return -EOPNOTSUPP; - - ret = wl1271_cmd_template_set(wl, - CMD_TEMPL_AP_PROBE_RESPONSE, - skb->data, - skb->len, 0, - rates); - - dev_kfree_skb(skb); - return ret; -} - -static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl, - struct ieee80211_vif *vif, - u8 *probe_rsp_data, - size_t probe_rsp_len, - u32 rates) +static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, + u8 *probe_rsp_data, + size_t probe_rsp_len, + u32 rates) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; u8 probe_rsp_templ[WL1271_CMD_TEMPL_MAX_SIZE]; int ssid_ie_offset, ie_offset, templ_len; const u8 *ptr; /* no need to change probe response if the SSID is set correctly */ - if (wlvif->ssid_len > 0) + if (wl->ssid_len > 0) return wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, probe_rsp_data, @@ -3320,18 +3153,16 @@ static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl, } static int wl1271_bss_erp_info_changed(struct wl1271 *wl, - struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changed) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret = 0; if (changed & BSS_CHANGED_ERP_SLOT) { if (bss_conf->use_short_slot) - ret = wl1271_acx_slot(wl, wlvif, SLOT_TIME_SHORT); + ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT); else - ret = wl1271_acx_slot(wl, wlvif, SLOT_TIME_LONG); + ret = wl1271_acx_slot(wl, SLOT_TIME_LONG); if (ret < 0) { wl1271_warning("Set slot time failed %d", ret); goto out; @@ -3340,18 +3171,16 @@ static int wl1271_bss_erp_info_changed(struct wl1271 *wl, if (changed & BSS_CHANGED_ERP_PREAMBLE) { if (bss_conf->use_short_preamble) - wl1271_acx_set_preamble(wl, wlvif, ACX_PREAMBLE_SHORT); + wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT); else - wl1271_acx_set_preamble(wl, wlvif, ACX_PREAMBLE_LONG); + wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG); } if (changed & BSS_CHANGED_ERP_CTS_PROT) { if (bss_conf->use_cts_prot) - ret = wl1271_acx_cts_protect(wl, wlvif, - CTSPROTECT_ENABLE); + ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE); else - ret = wl1271_acx_cts_protect(wl, wlvif, - CTSPROTECT_DISABLE); + ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE); if (ret < 0) { wl1271_warning("Set ctsprotect failed %d", ret); goto out; @@ -3367,23 +3196,14 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, struct ieee80211_bss_conf *bss_conf, u32 changed) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); + bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); int ret = 0; if ((changed & BSS_CHANGED_BEACON_INT)) { wl1271_debug(DEBUG_MASTER, "beacon interval updated: %d", bss_conf->beacon_int); - wlvif->beacon_int = bss_conf->beacon_int; - } - - if ((changed & BSS_CHANGED_AP_PROBE_RESP) && is_ap) { - u32 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); - if (!wl1271_ap_set_probe_resp_tmpl(wl, rate, vif)) { - wl1271_debug(DEBUG_AP, "probe response updated"); - set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags); - } + wl->beacon_int = bss_conf->beacon_int; } if ((changed & BSS_CHANGED_BEACON)) { @@ -3394,19 +3214,17 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); u16 tmpl_id; - if (!beacon) { - ret = -EINVAL; + if (!beacon) goto out; - } wl1271_debug(DEBUG_MASTER, "beacon updated"); - ret = wl1271_ssid_set(vif, beacon, ieoffset); + ret = wl1271_ssid_set(wl, beacon, ieoffset); if (ret < 0) { dev_kfree_skb(beacon); goto out; } - min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); + min_rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : CMD_TEMPL_BEACON; ret = wl1271_cmd_template_set(wl, tmpl_id, @@ -3418,13 +3236,6 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, goto out; } - /* - * In case we already have a probe-resp beacon set explicitly - * by usermode, don't use the beacon data. - */ - if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags)) - goto end_bcn; - /* remove TIM ie from probe response */ wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); @@ -3443,7 +3254,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP); if (is_ap) - ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif, + ret = wl1271_ap_set_probe_resp_tmpl(wl, beacon->data, beacon->len, min_rate); @@ -3453,15 +3264,12 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, beacon->data, beacon->len, 0, min_rate); -end_bcn: dev_kfree_skb(beacon); if (ret < 0) goto out; } out: - if (ret != 0) - wl1271_error("beacon info change failed: %d", ret); return ret; } @@ -3471,24 +3279,23 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, struct ieee80211_bss_conf *bss_conf, u32 changed) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret = 0; if ((changed & BSS_CHANGED_BASIC_RATES)) { u32 rates = bss_conf->basic_rates; - wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, - wlvif->band); - wlvif->basic_rate = wl1271_tx_min_rate_get(wl, - wlvif->basic_rate_set); + wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, + wl->band); + wl->basic_rate = wl1271_tx_min_rate_get(wl, + wl->basic_rate_set); - ret = wl1271_init_ap_rates(wl, wlvif); + ret = wl1271_init_ap_rates(wl); if (ret < 0) { wl1271_error("AP rate policy change failed %d", ret); goto out; } - ret = wl1271_ap_init_templates(wl, vif); + ret = wl1271_ap_init_templates(wl); if (ret < 0) goto out; } @@ -3499,40 +3306,38 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, if ((changed & BSS_CHANGED_BEACON_ENABLED)) { if (bss_conf->enable_beacon) { - if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { - ret = wl12xx_cmd_role_start_ap(wl, wlvif); + if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { + ret = wl12xx_cmd_role_start_ap(wl); if (ret < 0) goto out; - ret = wl1271_ap_init_hwenc(wl, wlvif); + ret = wl1271_ap_init_hwenc(wl); if (ret < 0) goto out; - set_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags); + set_bit(WL1271_FLAG_AP_STARTED, &wl->flags); wl1271_debug(DEBUG_AP, "started AP"); } } else { - if (test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { - ret = wl12xx_cmd_role_stop_ap(wl, wlvif); + if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { + ret = wl12xx_cmd_role_stop_ap(wl); if (ret < 0) goto out; - clear_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags); - clear_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, - &wlvif->flags); + clear_bit(WL1271_FLAG_AP_STARTED, &wl->flags); wl1271_debug(DEBUG_AP, "stopped AP"); } } } - ret = wl1271_bss_erp_info_changed(wl, vif, bss_conf, changed); + ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); if (ret < 0) goto out; /* Handle HT information change */ if ((changed & BSS_CHANGED_HT) && (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { - ret = wl1271_acx_set_ht_information(wl, wlvif, + ret = wl1271_acx_set_ht_information(wl, bss_conf->ht_operation_mode); if (ret < 0) { wl1271_warning("Set ht information failed %d", ret); @@ -3550,9 +3355,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, struct ieee80211_bss_conf *bss_conf, u32 changed) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); bool do_join = false, set_assoc = false; - bool is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); + bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); bool ibss_joined = false; u32 sta_rate_set = 0; int ret; @@ -3569,13 +3373,14 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, if (changed & BSS_CHANGED_IBSS) { if (bss_conf->ibss_joined) { - set_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags); + set_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags); ibss_joined = true; } else { - if (test_and_clear_bit(WLVIF_FLAG_IBSS_JOINED, - &wlvif->flags)) { - wl1271_unjoin(wl, wlvif); - wl12xx_start_dev(wl, wlvif); + if (test_and_clear_bit(WL1271_FLAG_IBSS_JOINED, + &wl->flags)) { + wl1271_unjoin(wl); + wl12xx_cmd_role_start_dev(wl); + wl12xx_roc(wl, wl->dev_role_id); } } } @@ -3591,40 +3396,46 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", bss_conf->enable_beacon ? "enabled" : "disabled"); + if (bss_conf->enable_beacon) + wl->set_bss_type = BSS_TYPE_IBSS; + else + wl->set_bss_type = BSS_TYPE_STA_BSS; do_join = true; } - if (changed & BSS_CHANGED_IDLE) { - ret = wl1271_sta_handle_idle(wl, wlvif, bss_conf->idle); - if (ret < 0) - wl1271_warning("idle mode change failed %d", ret); - } - if ((changed & BSS_CHANGED_CQM)) { bool enable = false; if (bss_conf->cqm_rssi_thold) enable = true; - ret = wl1271_acx_rssi_snr_trigger(wl, wlvif, enable, + ret = wl1271_acx_rssi_snr_trigger(wl, enable, bss_conf->cqm_rssi_thold, bss_conf->cqm_rssi_hyst); if (ret < 0) goto out; - wlvif->rssi_thold = bss_conf->cqm_rssi_thold; + wl->rssi_thold = bss_conf->cqm_rssi_thold; } - if (changed & BSS_CHANGED_BSSID) - if (!is_zero_ether_addr(bss_conf->bssid)) { - ret = wl12xx_cmd_build_null_data(wl, wlvif); + if ((changed & BSS_CHANGED_BSSID) && + /* + * Now we know the correct bssid, so we send a new join command + * and enable the BSSID filter + */ + memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { + memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); + + if (!is_zero_ether_addr(wl->bssid)) { + ret = wl1271_cmd_build_null_data(wl); if (ret < 0) goto out; - ret = wl1271_build_qos_null_data(wl, vif); + ret = wl1271_build_qos_null_data(wl); if (ret < 0) goto out; /* Need to update the BSSID (for filtering etc) */ do_join = true; } + } if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) { rcu_read_lock(); @@ -3648,28 +3459,26 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, if (bss_conf->assoc) { u32 rates; int ieoffset; - wlvif->aid = bss_conf->aid; + wl->aid = bss_conf->aid; set_assoc = true; - wlvif->ps_poll_failures = 0; + wl->ps_poll_failures = 0; /* * use basic rates from AP, and determine lowest rate * to use with control frames. */ rates = bss_conf->basic_rates; - wlvif->basic_rate_set = + wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, - wlvif->band); - wlvif->basic_rate = - wl1271_tx_min_rate_get(wl, - wlvif->basic_rate_set); + wl->band); + wl->basic_rate = + wl1271_tx_min_rate_get(wl, wl->basic_rate_set); if (sta_rate_set) - wlvif->rate_set = - wl1271_tx_enabled_rates_get(wl, + wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rate_set, - wlvif->band); - ret = wl1271_acx_sta_rate_policies(wl, wlvif); + wl->band); + ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) goto out; @@ -3679,56 +3488,53 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, * updates it by itself when the first beacon is * received after a join. */ - ret = wl1271_cmd_build_ps_poll(wl, wlvif, wlvif->aid); + ret = wl1271_cmd_build_ps_poll(wl, wl->aid); if (ret < 0) goto out; /* * Get a template for hardware connection maintenance */ - dev_kfree_skb(wlvif->probereq); - wlvif->probereq = wl1271_cmd_build_ap_probe_req(wl, - wlvif, - NULL); + dev_kfree_skb(wl->probereq); + wl->probereq = wl1271_cmd_build_ap_probe_req(wl, NULL); ieoffset = offsetof(struct ieee80211_mgmt, u.probe_req.variable); - wl1271_ssid_set(vif, wlvif->probereq, ieoffset); + wl1271_ssid_set(wl, wl->probereq, ieoffset); /* enable the connection monitoring feature */ - ret = wl1271_acx_conn_monit_params(wl, wlvif, true); + ret = wl1271_acx_conn_monit_params(wl, true); if (ret < 0) goto out; } else { /* use defaults when not associated */ bool was_assoc = - !!test_and_clear_bit(WLVIF_FLAG_STA_ASSOCIATED, - &wlvif->flags); + !!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED, + &wl->flags); bool was_ifup = - !!test_and_clear_bit(WLVIF_FLAG_STA_STATE_SENT, - &wlvif->flags); - wlvif->aid = 0; + !!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT, + &wl->flags); + wl->aid = 0; /* free probe-request template */ - dev_kfree_skb(wlvif->probereq); - wlvif->probereq = NULL; + dev_kfree_skb(wl->probereq); + wl->probereq = NULL; /* re-enable dynamic ps - just in case */ - ieee80211_enable_dyn_ps(vif); + ieee80211_enable_dyn_ps(wl->vif); /* revert back to minimum rates for the current band */ - wl1271_set_band_rate(wl, wlvif); - wlvif->basic_rate = - wl1271_tx_min_rate_get(wl, - wlvif->basic_rate_set); - ret = wl1271_acx_sta_rate_policies(wl, wlvif); + wl1271_set_band_rate(wl); + wl->basic_rate = + wl1271_tx_min_rate_get(wl, wl->basic_rate_set); + ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) goto out; /* disable connection monitor features */ - ret = wl1271_acx_conn_monit_params(wl, wlvif, false); + ret = wl1271_acx_conn_monit_params(wl, false); /* Disable the keep-alive feature */ - ret = wl1271_acx_keep_alive_mode(wl, wlvif, false); + ret = wl1271_acx_keep_alive_mode(wl, false); if (ret < 0) goto out; @@ -3740,7 +3546,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, * no IF_OPER_UP notification. */ if (!was_ifup) { - ret = wl12xx_croc(wl, wlvif->role_id); + ret = wl12xx_croc(wl, wl->role_id); if (ret < 0) goto out; } @@ -3749,16 +3555,17 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, * roaming on the same channel. until we will * have a better flow...) */ - if (test_bit(wlvif->dev_role_id, wl->roc_map)) { - ret = wl12xx_croc(wl, - wlvif->dev_role_id); + if (test_bit(wl->dev_role_id, wl->roc_map)) { + ret = wl12xx_croc(wl, wl->dev_role_id); if (ret < 0) goto out; } - wl1271_unjoin(wl, wlvif); - if (!(conf_flags & IEEE80211_CONF_IDLE)) - wl12xx_start_dev(wl, wlvif); + wl1271_unjoin(wl); + if (!(conf_flags & IEEE80211_CONF_IDLE)) { + wl12xx_cmd_role_start_dev(wl); + wl12xx_roc(wl, wl->dev_role_id); + } } } } @@ -3769,28 +3576,27 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, if (bss_conf->ibss_joined) { u32 rates = bss_conf->basic_rates; - wlvif->basic_rate_set = + wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, - wlvif->band); - wlvif->basic_rate = - wl1271_tx_min_rate_get(wl, - wlvif->basic_rate_set); + wl->band); + wl->basic_rate = + wl1271_tx_min_rate_get(wl, wl->basic_rate_set); /* by default, use 11b + OFDM rates */ - wlvif->rate_set = CONF_TX_IBSS_DEFAULT_RATES; - ret = wl1271_acx_sta_rate_policies(wl, wlvif); + wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; + ret = wl1271_acx_sta_rate_policies(wl); if (ret < 0) goto out; } } - ret = wl1271_bss_erp_info_changed(wl, vif, bss_conf, changed); + ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); if (ret < 0) goto out; if (changed & BSS_CHANGED_ARP_FILTER) { __be32 addr = bss_conf->arp_addr_list[0]; - WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS); + WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); if (bss_conf->arp_addr_cnt == 1 && bss_conf->arp_filter_enabled) { @@ -3800,24 +3606,24 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, * isn't being set (when sending), so we have to * reconfigure the template upon every ip change. */ - ret = wl1271_cmd_build_arp_rsp(wl, wlvif, addr); + ret = wl1271_cmd_build_arp_rsp(wl, addr); if (ret < 0) { wl1271_warning("build arp rsp failed: %d", ret); goto out; } - ret = wl1271_acx_arp_ip_filter(wl, wlvif, + ret = wl1271_acx_arp_ip_filter(wl, ACX_ARP_FILTER_ARP_FILTERING, addr); } else - ret = wl1271_acx_arp_ip_filter(wl, wlvif, 0, addr); + ret = wl1271_acx_arp_ip_filter(wl, 0, addr); if (ret < 0) goto out; } if (do_join) { - ret = wl1271_join(wl, wlvif, set_assoc); + ret = wl1271_join(wl, set_assoc); if (ret < 0) { wl1271_warning("cmd join failed %d", ret); goto out; @@ -3825,31 +3631,35 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, /* ROC until connected (after EAPOL exchange) */ if (!is_ibss) { - ret = wl12xx_roc(wl, wlvif, wlvif->role_id); + ret = wl12xx_roc(wl, wl->role_id); if (ret < 0) goto out; - wl1271_check_operstate(wl, wlvif, + wl1271_check_operstate(wl, ieee80211_get_operstate(vif)); } /* * stop device role if started (we might already be in * STA role). TODO: make it better. */ - if (wlvif->dev_role_id != WL12XX_INVALID_ROLE_ID) { - ret = wl12xx_stop_dev(wl, wlvif); + if (wl->dev_role_id != WL12XX_INVALID_ROLE_ID) { + ret = wl12xx_croc(wl, wl->dev_role_id); + if (ret < 0) + goto out; + + ret = wl12xx_cmd_role_stop_dev(wl); if (ret < 0) goto out; } /* If we want to go in PSM but we're not there yet */ - if (test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags) && - !test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { + if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && + !test_bit(WL1271_FLAG_PSM, &wl->flags)) { enum wl1271_cmd_ps_mode mode; mode = STATION_POWER_SAVE_MODE; - ret = wl1271_ps_set_mode(wl, wlvif, mode, - wlvif->basic_rate, + ret = wl1271_ps_set_mode(wl, mode, + wl->basic_rate, true); if (ret < 0) goto out; @@ -3863,7 +3673,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, true, - wlvif->sta.hlid); + wl->sta_hlid); if (ret < 0) { wl1271_warning("Set ht cap true failed %d", ret); @@ -3875,7 +3685,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, false, - wlvif->sta.hlid); + wl->sta_hlid); if (ret < 0) { wl1271_warning("Set ht cap false failed %d", ret); @@ -3887,7 +3697,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, /* Handle HT information change. Done after join. */ if ((changed & BSS_CHANGED_HT) && (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { - ret = wl1271_acx_set_ht_information(wl, wlvif, + ret = wl1271_acx_set_ht_information(wl, bss_conf->ht_operation_mode); if (ret < 0) { wl1271_warning("Set ht information failed %d", ret); @@ -3905,8 +3715,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, u32 changed) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); + bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x", @@ -3917,9 +3726,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; - if (unlikely(!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags))) - goto out; - ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; @@ -3940,7 +3746,6 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, const struct ieee80211_tx_queue_params *params) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); u8 ps_scheme; int ret = 0; @@ -3987,13 +3792,13 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, * the txop is confed in units of 32us by the mac80211, * we need us */ - ret = wl1271_acx_ac_cfg(wl, wlvif, wl1271_tx_get_queue(queue), + ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), params->cw_min, params->cw_max, params->aifs, params->txop << 5); if (ret < 0) goto out_sleep; - ret = wl1271_acx_tid_cfg(wl, wlvif, wl1271_tx_get_queue(queue), + ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), CONF_CHANNEL_TYPE_EDCF, wl1271_tx_get_queue(queue), ps_scheme, CONF_ACK_POLICY_LEGACY, @@ -4056,43 +3861,43 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, } static int wl1271_allocate_sta(struct wl1271 *wl, - struct wl12xx_vif *wlvif, - struct ieee80211_sta *sta) + struct ieee80211_sta *sta, + u8 *hlid) { struct wl1271_station *wl_sta; - int ret; + int id; - - if (wl->active_sta_count >= AP_MAX_STATIONS) { + id = find_first_zero_bit(wl->ap_hlid_map, AP_MAX_STATIONS); + if (id >= AP_MAX_STATIONS) { wl1271_warning("could not allocate HLID - too much stations"); return -EBUSY; } wl_sta = (struct wl1271_station *)sta->drv_priv; - ret = wl12xx_allocate_link(wl, wlvif, &wl_sta->hlid); - if (ret < 0) { - wl1271_warning("could not allocate HLID - too many links"); - return -EBUSY; - } - - set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map); + set_bit(id, wl->ap_hlid_map); + wl_sta->hlid = WL1271_AP_STA_HLID_START + id; + *hlid = wl_sta->hlid; memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); wl->active_sta_count++; return 0; } -void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) +void wl1271_free_sta(struct wl1271 *wl, u8 hlid) { - if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) + int id = hlid - WL1271_AP_STA_HLID_START; + + if (hlid < WL1271_AP_STA_HLID_START) + return; + + if (!test_bit(id, wl->ap_hlid_map)) return; - clear_bit(hlid, wlvif->ap.sta_hlid_map); + clear_bit(id, wl->ap_hlid_map); memset(wl->links[hlid].addr, 0, ETH_ALEN); wl->links[hlid].ba_bitmap = 0; wl1271_tx_reset_link_queues(wl, hlid); __clear_bit(hlid, &wl->ap_ps_map); __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); - wl12xx_free_link(wl, wlvif, &hlid); wl->active_sta_count--; } @@ -4101,8 +3906,6 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - struct wl1271_station *wl_sta; int ret = 0; u8 hlid; @@ -4111,23 +3914,20 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; - if (wlvif->bss_type != BSS_TYPE_AP_BSS) + if (wl->bss_type != BSS_TYPE_AP_BSS) goto out; wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); - ret = wl1271_allocate_sta(wl, wlvif, sta); + ret = wl1271_allocate_sta(wl, sta, &hlid); if (ret < 0) goto out; - wl_sta = (struct wl1271_station *)sta->drv_priv; - hlid = wl_sta->hlid; - ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out_free_sta; - ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid); + ret = wl12xx_cmd_add_peer(wl, sta, hlid); if (ret < 0) goto out_sleep; @@ -4144,7 +3944,7 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, out_free_sta: if (ret < 0) - wl1271_free_sta(wl, wlvif, hlid); + wl1271_free_sta(wl, hlid); out: mutex_unlock(&wl->mutex); @@ -4156,7 +3956,6 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271_station *wl_sta; int ret = 0, id; @@ -4165,14 +3964,14 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, if (unlikely(wl->state == WL1271_STATE_OFF)) goto out; - if (wlvif->bss_type != BSS_TYPE_AP_BSS) + if (wl->bss_type != BSS_TYPE_AP_BSS) goto out; wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid); wl_sta = (struct wl1271_station *)sta->drv_priv; - id = wl_sta->hlid; - if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map))) + id = wl_sta->hlid - WL1271_AP_STA_HLID_START; + if (WARN_ON(!test_bit(id, wl->ap_hlid_map))) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -4183,7 +3982,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, if (ret < 0) goto out_sleep; - wl1271_free_sta(wl, wlvif, wl_sta->hlid); + wl1271_free_sta(wl, wl_sta->hlid); out_sleep: wl1271_ps_elp_sleep(wl); @@ -4200,7 +3999,6 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, u8 buf_size) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret; u8 hlid, *ba_bitmap; @@ -4218,10 +4016,10 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, goto out; } - if (wlvif->bss_type == BSS_TYPE_STA_BSS) { - hlid = wlvif->sta.hlid; - ba_bitmap = &wlvif->sta.ba_rx_bitmap; - } else if (wlvif->bss_type == BSS_TYPE_AP_BSS) { + if (wl->bss_type == BSS_TYPE_STA_BSS) { + hlid = wl->sta_hlid; + ba_bitmap = &wl->ba_rx_bitmap; + } else if (wl->bss_type == BSS_TYPE_AP_BSS) { struct wl1271_station *wl_sta; wl_sta = (struct wl1271_station *)sta->drv_priv; @@ -4241,7 +4039,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: - if (!wlvif->ba_support || !wlvif->ba_allowed) { + if (!wl->ba_support || !wl->ba_allowed) { ret = -ENOTSUPP; break; } @@ -4310,9 +4108,8 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271 *wl = hw->priv; - int i, ret = 0; + int i; wl1271_debug(DEBUG_MAC80211, "mac80211 set_bitrate_mask 0x%x 0x%x", mask->control[NL80211_BAND_2GHZ].legacy, @@ -4321,39 +4118,19 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); for (i = 0; i < IEEE80211_NUM_BANDS; i++) - wlvif->bitrate_masks[i] = + wl->bitrate_masks[i] = wl1271_tx_enabled_rates_get(wl, mask->control[i].legacy, i); - - if (unlikely(wl->state == WL1271_STATE_OFF)) - goto out; - - if (wlvif->bss_type == BSS_TYPE_STA_BSS && - !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - wl1271_set_band_rate(wl, wlvif); - wlvif->basic_rate = - wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); - ret = wl1271_acx_sta_rate_policies(wl, wlvif); - - wl1271_ps_elp_sleep(wl); - } -out: mutex_unlock(&wl->mutex); - return ret; + return 0; } static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, struct ieee80211_channel_switch *ch_switch) { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif; int ret; wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch"); @@ -4361,24 +4138,19 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); if (unlikely(wl->state == WL1271_STATE_OFF)) { - wl12xx_for_each_wlvif_sta(wl, wlvif) { - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); - ieee80211_chswitch_done(vif, false); - } - goto out; + mutex_unlock(&wl->mutex); + ieee80211_chswitch_done(wl->vif, false); + return; } ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; - /* TODO: change mac80211 to pass vif as param */ - wl12xx_for_each_wlvif_sta(wl, wlvif) { - ret = wl12xx_cmd_channel_switch(wl, ch_switch); + ret = wl12xx_cmd_channel_switch(wl, ch_switch); - if (!ret) - set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags); - } + if (!ret) + set_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags); wl1271_ps_elp_sleep(wl); @@ -4398,6 +4170,10 @@ static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) /* packets are considered pending if in the TX queue or the FW */ ret = (wl1271_tx_total_queue_count(wl) > 0) || (wl->tx_frames_cnt > 0); + + /* the above is appropriate for STA mode for PS purposes */ + WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); + out: mutex_unlock(&wl->mutex); @@ -4828,7 +4604,7 @@ static struct bin_attribute fwlog_attr = { .read = wl1271_sysfs_read_fwlog, }; -static int wl1271_register_hw(struct wl1271 *wl) +int wl1271_register_hw(struct wl1271 *wl) { int ret; @@ -4869,8 +4645,9 @@ static int wl1271_register_hw(struct wl1271 *wl) return 0; } +EXPORT_SYMBOL_GPL(wl1271_register_hw); -static void wl1271_unregister_hw(struct wl1271 *wl) +void wl1271_unregister_hw(struct wl1271 *wl) { if (wl->state == WL1271_STATE_PLT) __wl1271_plt_stop(wl); @@ -4880,8 +4657,9 @@ static void wl1271_unregister_hw(struct wl1271 *wl) wl->mac80211_registered = false; } +EXPORT_SYMBOL_GPL(wl1271_unregister_hw); -static int wl1271_init_ieee80211(struct wl1271 *wl) +int wl1271_init_ieee80211(struct wl1271 *wl) { static const u32 cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, @@ -4958,33 +4736,27 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->wiphy->reg_notifier = wl1271_reg_notify; - /* the FW answers probe-requests in AP-mode */ - wl->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; - wl->hw->wiphy->probe_resp_offload = - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; - - SET_IEEE80211_DEV(wl->hw, wl->dev); + SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); wl->hw->sta_data_size = sizeof(struct wl1271_station); - wl->hw->vif_data_size = sizeof(struct wl12xx_vif); wl->hw->max_rx_aggregation_subframes = 8; return 0; } +EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); #define WL1271_DEFAULT_CHANNEL 0 -static struct ieee80211_hw *wl1271_alloc_hw(void) +struct ieee80211_hw *wl1271_alloc_hw(void) { struct ieee80211_hw *hw; + struct platform_device *plat_dev = NULL; struct wl1271 *wl; int i, j, ret; unsigned int order; - BUILD_BUG_ON(AP_MAX_STATIONS > WL12XX_MAX_LINKS); + BUILD_BUG_ON(AP_MAX_LINKS > WL12XX_MAX_LINKS); hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); if (!hw) { @@ -4993,26 +4765,41 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) goto err_hw_alloc; } + plat_dev = kmemdup(&wl1271_device, sizeof(wl1271_device), GFP_KERNEL); + if (!plat_dev) { + wl1271_error("could not allocate platform_device"); + ret = -ENOMEM; + goto err_plat_alloc; + } + wl = hw->priv; memset(wl, 0, sizeof(*wl)); INIT_LIST_HEAD(&wl->list); - INIT_LIST_HEAD(&wl->wlvif_list); wl->hw = hw; + wl->plat_dev = plat_dev; for (i = 0; i < NUM_TX_QUEUES; i++) - for (j = 0; j < WL12XX_MAX_LINKS; j++) + skb_queue_head_init(&wl->tx_queue[i]); + + for (i = 0; i < NUM_TX_QUEUES; i++) + for (j = 0; j < AP_MAX_LINKS; j++) skb_queue_head_init(&wl->links[j].tx_queue[i]); skb_queue_head_init(&wl->deferred_rx_queue); skb_queue_head_init(&wl->deferred_tx_queue); INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); + INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); INIT_WORK(&wl->netstack_work, wl1271_netstack_work); INIT_WORK(&wl->tx_work, wl1271_tx_work); INIT_WORK(&wl->recovery_work, wl1271_recovery_work); INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); + INIT_WORK(&wl->rx_streaming_enable_work, + wl1271_rx_streaming_enable_work); + INIT_WORK(&wl->rx_streaming_disable_work, + wl1271_rx_streaming_disable_work); wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); if (!wl->freezable_wq) { @@ -5021,21 +4808,41 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) } wl->channel = WL1271_DEFAULT_CHANNEL; + wl->beacon_int = WL1271_DEFAULT_BEACON_INT; + wl->default_key = 0; wl->rx_counter = 0; + wl->psm_entry_retry = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; + wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; + wl->basic_rate = CONF_TX_RATE_MASK_BASIC; + wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; wl->flags = 0; wl->sg_enabled = true; wl->hw_pg_ver = -1; + wl->bss_type = MAX_BSS_TYPE; + wl->set_bss_type = MAX_BSS_TYPE; + wl->last_tx_hlid = 0; wl->ap_ps_map = 0; wl->ap_fw_ps_map = 0; wl->quirks = 0; wl->platform_quirks = 0; wl->sched_scanning = false; + wl->tx_security_seq = 0; + wl->tx_security_last_seq_lsb = 0; wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; + wl->role_id = WL12XX_INVALID_ROLE_ID; wl->system_hlid = WL12XX_SYSTEM_HLID; + wl->sta_hlid = WL12XX_INVALID_LINK_ID; + wl->dev_role_id = WL12XX_INVALID_ROLE_ID; + wl->dev_hlid = WL12XX_INVALID_LINK_ID; + wl->session_counter = 0; + wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; + wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; wl->active_sta_count = 0; + setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, + (unsigned long) wl); wl->fwlog_size = 0; init_waitqueue_head(&wl->fwlog_waitq); @@ -5053,6 +4860,8 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) /* Apply default driver configuration. */ wl1271_conf_init(wl); + wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; + wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; order = get_order(WL1271_AGGR_BUFFER_SIZE); wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); @@ -5074,8 +4883,49 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) goto err_dummy_packet; } + /* Register platform device */ + ret = platform_device_register(wl->plat_dev); + if (ret) { + wl1271_error("couldn't register platform device"); + goto err_fwlog; + } + dev_set_drvdata(&wl->plat_dev->dev, wl); + + /* Create sysfs file to control bt coex state */ + ret = device_create_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); + if (ret < 0) { + wl1271_error("failed to create sysfs file bt_coex_state"); + goto err_platform; + } + + /* Create sysfs file to get HW PG version */ + ret = device_create_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); + if (ret < 0) { + wl1271_error("failed to create sysfs file hw_pg_ver"); + goto err_bt_coex_state; + } + + /* Create sysfs file for the FW log */ + ret = device_create_bin_file(&wl->plat_dev->dev, &fwlog_attr); + if (ret < 0) { + wl1271_error("failed to create sysfs file fwlog"); + goto err_hw_pg_ver; + } + return hw; +err_hw_pg_ver: + device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); + +err_bt_coex_state: + device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); + +err_platform: + platform_device_unregister(wl->plat_dev); + +err_fwlog: + free_page((unsigned long)wl->fwlog); + err_dummy_packet: dev_kfree_skb(wl->dummy_packet); @@ -5087,14 +4937,18 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) err_hw: wl1271_debugfs_exit(wl); + kfree(plat_dev); + +err_plat_alloc: ieee80211_free_hw(hw); err_hw_alloc: return ERR_PTR(ret); } +EXPORT_SYMBOL_GPL(wl1271_alloc_hw); -static int wl1271_free_hw(struct wl1271 *wl) +int wl1271_free_hw(struct wl1271 *wl) { /* Unblock any fwlog readers */ mutex_lock(&wl->mutex); @@ -5102,15 +4956,17 @@ static int wl1271_free_hw(struct wl1271 *wl) wake_up_interruptible_all(&wl->fwlog_waitq); mutex_unlock(&wl->mutex); - device_remove_bin_file(wl->dev, &fwlog_attr); + device_remove_bin_file(&wl->plat_dev->dev, &fwlog_attr); - device_remove_file(wl->dev, &dev_attr_hw_pg_ver); + device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); - device_remove_file(wl->dev, &dev_attr_bt_coex_state); + device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); + platform_device_unregister(wl->plat_dev); free_page((unsigned long)wl->fwlog); dev_kfree_skb(wl->dummy_packet); free_pages((unsigned long)wl->aggr_buf, get_order(WL1271_AGGR_BUFFER_SIZE)); + kfree(wl->plat_dev); wl1271_debugfs_exit(wl); @@ -5127,174 +4983,7 @@ static int wl1271_free_hw(struct wl1271 *wl) return 0; } - -static irqreturn_t wl12xx_hardirq(int irq, void *cookie) -{ - struct wl1271 *wl = cookie; - unsigned long flags; - - wl1271_debug(DEBUG_IRQ, "IRQ"); - - /* complete the ELP completion */ - spin_lock_irqsave(&wl->wl_lock, flags); - set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); - if (wl->elp_compl) { - complete(wl->elp_compl); - wl->elp_compl = NULL; - } - - if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) { - /* don't enqueue a work right now. mark it as pending */ - set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags); - wl1271_debug(DEBUG_IRQ, "should not enqueue work"); - disable_irq_nosync(wl->irq); - pm_wakeup_event(wl->dev, 0); - spin_unlock_irqrestore(&wl->wl_lock, flags); - return IRQ_HANDLED; - } - spin_unlock_irqrestore(&wl->wl_lock, flags); - - return IRQ_WAKE_THREAD; -} - -static int __devinit wl12xx_probe(struct platform_device *pdev) -{ - struct wl12xx_platform_data *pdata = pdev->dev.platform_data; - struct ieee80211_hw *hw; - struct wl1271 *wl; - unsigned long irqflags; - int ret = -ENODEV; - - hw = wl1271_alloc_hw(); - if (IS_ERR(hw)) { - wl1271_error("can't allocate hw"); - ret = PTR_ERR(hw); - goto out; - } - - wl = hw->priv; - wl->irq = platform_get_irq(pdev, 0); - wl->ref_clock = pdata->board_ref_clock; - wl->tcxo_clock = pdata->board_tcxo_clock; - wl->platform_quirks = pdata->platform_quirks; - wl->set_power = pdata->set_power; - wl->dev = &pdev->dev; - wl->if_ops = pdata->ops; - - platform_set_drvdata(pdev, wl); - - if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) - irqflags = IRQF_TRIGGER_RISING; - else - irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; - - ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wl1271_irq, - irqflags, - pdev->name, wl); - if (ret < 0) { - wl1271_error("request_irq() failed: %d", ret); - goto out_free_hw; - } - - ret = enable_irq_wake(wl->irq); - if (!ret) { - wl->irq_wake_enabled = true; - device_init_wakeup(wl->dev, 1); - if (pdata->pwr_in_suspend) - hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; - - } - disable_irq(wl->irq); - - ret = wl1271_init_ieee80211(wl); - if (ret) - goto out_irq; - - ret = wl1271_register_hw(wl); - if (ret) - goto out_irq; - - /* Create sysfs file to control bt coex state */ - ret = device_create_file(wl->dev, &dev_attr_bt_coex_state); - if (ret < 0) { - wl1271_error("failed to create sysfs file bt_coex_state"); - goto out_irq; - } - - /* Create sysfs file to get HW PG version */ - ret = device_create_file(wl->dev, &dev_attr_hw_pg_ver); - if (ret < 0) { - wl1271_error("failed to create sysfs file hw_pg_ver"); - goto out_bt_coex_state; - } - - /* Create sysfs file for the FW log */ - ret = device_create_bin_file(wl->dev, &fwlog_attr); - if (ret < 0) { - wl1271_error("failed to create sysfs file fwlog"); - goto out_hw_pg_ver; - } - - return 0; - -out_hw_pg_ver: - device_remove_file(wl->dev, &dev_attr_hw_pg_ver); - -out_bt_coex_state: - device_remove_file(wl->dev, &dev_attr_bt_coex_state); - -out_irq: - free_irq(wl->irq, wl); - -out_free_hw: - wl1271_free_hw(wl); - -out: - return ret; -} - -static int __devexit wl12xx_remove(struct platform_device *pdev) -{ - struct wl1271 *wl = platform_get_drvdata(pdev); - - if (wl->irq_wake_enabled) { - device_init_wakeup(wl->dev, 0); - disable_irq_wake(wl->irq); - } - wl1271_unregister_hw(wl); - free_irq(wl->irq, wl); - wl1271_free_hw(wl); - - return 0; -} - -static const struct platform_device_id wl12xx_id_table[] __devinitconst = { - { "wl12xx", 0 }, - { } /* Terminating Entry */ -}; -MODULE_DEVICE_TABLE(platform, wl12xx_id_table); - -static struct platform_driver wl12xx_driver = { - .probe = wl12xx_probe, - .remove = __devexit_p(wl12xx_remove), - .id_table = wl12xx_id_table, - .driver = { - .name = "wl12xx_driver", - .owner = THIS_MODULE, - } -}; - -static int __init wl12xx_init(void) -{ - return platform_driver_register(&wl12xx_driver); -} -module_init(wl12xx_init); - -static void __exit wl12xx_exit(void) -{ - platform_driver_unregister(&wl12xx_driver); -} -module_exit(wl12xx_exit); +EXPORT_SYMBOL_GPL(wl1271_free_hw); u32 wl12xx_debug_level = DEBUG_NONE; EXPORT_SYMBOL_GPL(wl12xx_debug_level); diff --git a/trunk/drivers/net/wireless/wl12xx/ps.c b/trunk/drivers/net/wireless/wl12xx/ps.c index a7a11088dd31..c15ebf2efd40 100644 --- a/trunk/drivers/net/wireless/wl12xx/ps.c +++ b/trunk/drivers/net/wireless/wl12xx/ps.c @@ -25,7 +25,6 @@ #include "ps.h" #include "io.h" #include "tx.h" -#include "debug.h" #define WL1271_WAKEUP_TIMEOUT 500 @@ -33,7 +32,6 @@ void wl1271_elp_work(struct work_struct *work) { struct delayed_work *dwork; struct wl1271 *wl; - struct wl12xx_vif *wlvif; dwork = container_of(work, struct delayed_work, work); wl = container_of(dwork, struct wl1271, elp_work); @@ -49,15 +47,11 @@ void wl1271_elp_work(struct work_struct *work) if (unlikely(!test_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) goto out; - if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) + if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || + (!test_bit(WL1271_FLAG_PSM, &wl->flags) && + !test_bit(WL1271_FLAG_IDLE, &wl->flags))) goto out; - wl12xx_for_each_wlvif(wl, wlvif) { - if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) && - !test_bit(WL1271_FLAG_IDLE, &wl->flags)) - goto out; - } - wl1271_debug(DEBUG_PSM, "chip to elp"); wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); set_bit(WL1271_FLAG_IN_ELP, &wl->flags); @@ -71,17 +65,13 @@ void wl1271_elp_work(struct work_struct *work) /* Routines to toggle sleep mode while in ELP */ void wl1271_ps_elp_sleep(struct wl1271 *wl) { - struct wl12xx_vif *wlvif; - /* we shouldn't get consecutive sleep requests */ if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) return; - wl12xx_for_each_wlvif(wl, wlvif) { - if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) && - !test_bit(WL1271_FLAG_IDLE, &wl->flags)) - return; - } + if (!test_bit(WL1271_FLAG_PSM, &wl->flags) && + !test_bit(WL1271_FLAG_IDLE, &wl->flags)) + return; ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, msecs_to_jiffies(ELP_ENTRY_DELAY)); @@ -153,8 +143,8 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) return 0; } -int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, - enum wl1271_cmd_ps_mode mode, u32 rates, bool send) +int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, + u32 rates, bool send) { int ret; @@ -162,34 +152,39 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, case STATION_POWER_SAVE_MODE: wl1271_debug(DEBUG_PSM, "entering psm"); - ret = wl1271_acx_wake_up_conditions(wl, wlvif); + ret = wl1271_acx_wake_up_conditions(wl); if (ret < 0) { wl1271_error("couldn't set wake up conditions"); return ret; } - ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_POWER_SAVE_MODE); + ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); if (ret < 0) return ret; - set_bit(WLVIF_FLAG_PSM, &wlvif->flags); + set_bit(WL1271_FLAG_PSM, &wl->flags); break; case STATION_ACTIVE_MODE: default: wl1271_debug(DEBUG_PSM, "leaving psm"); /* disable beacon early termination */ - if (wlvif->band == IEEE80211_BAND_2GHZ) { - ret = wl1271_acx_bet_enable(wl, wlvif, false); + if (wl->band == IEEE80211_BAND_2GHZ) { + ret = wl1271_acx_bet_enable(wl, false); if (ret < 0) return ret; } - ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_ACTIVE_MODE); + /* disable beacon filtering */ + ret = wl1271_acx_beacon_filter_opt(wl, false); + if (ret < 0) + return ret; + + ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE); if (ret < 0) return ret; - clear_bit(WLVIF_FLAG_PSM, &wlvif->flags); + clear_bit(WL1271_FLAG_PSM, &wl->flags); break; } @@ -228,11 +223,9 @@ static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid) wl1271_handle_tx_low_watermark(wl); } -void wl12xx_ps_link_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 hlid, bool clean_queues) +void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues) { struct ieee80211_sta *sta; - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); if (test_bit(hlid, &wl->ap_ps_map)) return; @@ -242,7 +235,7 @@ void wl12xx_ps_link_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, clean_queues); rcu_read_lock(); - sta = ieee80211_find_sta(vif, wl->links[hlid].addr); + sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr); if (!sta) { wl1271_error("could not find sta %pM for starting ps", wl->links[hlid].addr); @@ -260,10 +253,9 @@ void wl12xx_ps_link_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, __set_bit(hlid, &wl->ap_ps_map); } -void wl12xx_ps_link_end(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) +void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid) { struct ieee80211_sta *sta; - struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); if (!test_bit(hlid, &wl->ap_ps_map)) return; @@ -273,7 +265,7 @@ void wl12xx_ps_link_end(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) __clear_bit(hlid, &wl->ap_ps_map); rcu_read_lock(); - sta = ieee80211_find_sta(vif, wl->links[hlid].addr); + sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr); if (!sta) { wl1271_error("could not find sta %pM for ending ps", wl->links[hlid].addr); diff --git a/trunk/drivers/net/wireless/wl12xx/ps.h b/trunk/drivers/net/wireless/wl12xx/ps.h index a12052f02026..25eb9bc9b628 100644 --- a/trunk/drivers/net/wireless/wl12xx/ps.h +++ b/trunk/drivers/net/wireless/wl12xx/ps.h @@ -27,14 +27,13 @@ #include "wl12xx.h" #include "acx.h" -int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, - enum wl1271_cmd_ps_mode mode, u32 rates, bool send); +int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode, + u32 rates, bool send); void wl1271_ps_elp_sleep(struct wl1271 *wl); int wl1271_ps_elp_wakeup(struct wl1271 *wl); void wl1271_elp_work(struct work_struct *work); -void wl12xx_ps_link_start(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 hlid, bool clean_queues); -void wl12xx_ps_link_end(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); +void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); +void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid); #define WL1271_PS_COMPLETE_TIMEOUT 500 diff --git a/trunk/drivers/net/wireless/wl12xx/reg.h b/trunk/drivers/net/wireless/wl12xx/reg.h index df34d5977b98..3f570f397586 100644 --- a/trunk/drivers/net/wireless/wl12xx/reg.h +++ b/trunk/drivers/net/wireless/wl12xx/reg.h @@ -408,7 +408,7 @@ /* Firmware image load chunk size */ -#define CHUNK_SIZE 16384 +#define CHUNK_SIZE 512 /* Firmware image header size */ #define FW_HDR_SIZE 8 diff --git a/trunk/drivers/net/wireless/wl12xx/rx.c b/trunk/drivers/net/wireless/wl12xx/rx.c index 8c277c0cb372..dee4cfe9ccc1 100644 --- a/trunk/drivers/net/wireless/wl12xx/rx.c +++ b/trunk/drivers/net/wireless/wl12xx/rx.c @@ -25,11 +25,9 @@ #include #include "wl12xx.h" -#include "debug.h" #include "acx.h" #include "reg.h" #include "rx.h" -#include "tx.h" #include "io.h" static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status, @@ -98,7 +96,7 @@ static void wl1271_rx_status(struct wl1271 *wl, } static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, - bool unaligned, u8 *hlid) + bool unaligned) { struct wl1271_rx_descriptor *desc; struct sk_buff *skb; @@ -161,7 +159,6 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, * payload aligned to 4 bytes. */ memcpy(buf, data + sizeof(*desc), length - sizeof(*desc)); - *hlid = desc->hlid; hdr = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_beacon(hdr->frame_control)) @@ -172,10 +169,10 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); seq_num = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; - wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d hlid %d", skb, + wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s seq %d", skb, skb->len - desc->pad_len, beacon ? "beacon" : "", - seq_num, *hlid); + seq_num); skb_trim(skb, skb->len - desc->pad_len); @@ -188,7 +185,6 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) { struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; - unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; u32 buf_size; u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; @@ -196,7 +192,8 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) u32 mem_block; u32 pkt_length; u32 pkt_offset; - u8 hlid; + bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); + bool had_data = false; bool unaligned = false; while (drv_rx_counter != fw_rx_counter) { @@ -256,11 +253,8 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) */ if (wl1271_rx_handle_data(wl, wl->aggr_buf + pkt_offset, - pkt_length, unaligned, - &hlid) == 1) { - WARN_ON(hlid >= WL12XX_MAX_LINKS); - __set_bit(hlid, active_hlids); - } + pkt_length, unaligned) == 1) + had_data = true; wl->rx_counter++; drv_rx_counter++; @@ -276,5 +270,17 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status) if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); - wl12xx_rearm_rx_streaming(wl, active_hlids); + if (!is_ap && wl->conf.rx_streaming.interval && had_data && + (wl->conf.rx_streaming.always || + test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) { + u32 timeout = wl->conf.rx_streaming.duration; + + /* restart rx streaming */ + if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) + ieee80211_queue_work(wl->hw, + &wl->rx_streaming_enable_work); + + mod_timer(&wl->rx_streaming_timer, + jiffies + msecs_to_jiffies(timeout)); + } } diff --git a/trunk/drivers/net/wireless/wl12xx/scan.c b/trunk/drivers/net/wireless/wl12xx/scan.c index 8599dab1fe2a..fc29c671cf3b 100644 --- a/trunk/drivers/net/wireless/wl12xx/scan.c +++ b/trunk/drivers/net/wireless/wl12xx/scan.c @@ -24,7 +24,6 @@ #include #include "wl12xx.h" -#include "debug.h" #include "cmd.h" #include "scan.h" #include "acx.h" @@ -35,8 +34,6 @@ void wl1271_scan_complete_work(struct work_struct *work) { struct delayed_work *dwork; struct wl1271 *wl; - struct ieee80211_vif *vif; - struct wl12xx_vif *wlvif; int ret; bool is_sta, is_ibss; @@ -53,31 +50,28 @@ void wl1271_scan_complete_work(struct work_struct *work) if (wl->scan.state == WL1271_SCAN_STATE_IDLE) goto out; - vif = wl->scan_vif; - wlvif = wl12xx_vif_to_data(vif); - wl->scan.state = WL1271_SCAN_STATE_IDLE; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); wl->scan.req = NULL; - wl->scan_vif = NULL; ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; - if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { /* restore hardware connection monitoring template */ - wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq); + wl1271_cmd_build_ap_probe_req(wl, wl->probereq); } /* return to ROC if needed */ - is_sta = (wlvif->bss_type == BSS_TYPE_STA_BSS); - is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); - if (((is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) || - (is_ibss && !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags))) && - !test_bit(wlvif->dev_role_id, wl->roc_map)) { + is_sta = (wl->bss_type == BSS_TYPE_STA_BSS); + is_ibss = (wl->bss_type == BSS_TYPE_IBSS); + if (((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) || + (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) && + !test_bit(wl->dev_role_id, wl->roc_map)) { /* restore remain on channel */ - wl12xx_start_dev(wl, wlvif); + wl12xx_cmd_role_start_dev(wl); + wl12xx_roc(wl, wl->dev_role_id); } wl1271_ps_elp_sleep(wl); @@ -161,11 +155,9 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, #define WL1271_NOTHING_TO_SCAN 1 -static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, - enum ieee80211_band band, - bool passive, u32 basic_rate) +static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, + bool passive, u32 basic_rate) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl1271_cmd_scan *cmd; struct wl1271_cmd_trigger_scan_to *trigger; int ret; @@ -185,11 +177,11 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, if (passive) scan_options |= WL1271_SCAN_OPT_PASSIVE; - if (WARN_ON(wlvif->role_id == WL12XX_INVALID_ROLE_ID)) { + if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) { ret = -EINVAL; goto out; } - cmd->params.role_id = wlvif->role_id; + cmd->params.role_id = wl->role_id; cmd->params.scan_options = cpu_to_le16(scan_options); cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, @@ -202,6 +194,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, cmd->params.tx_rate = cpu_to_le32(basic_rate); cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; + cmd->params.tx_rate = cpu_to_le32(basic_rate); cmd->params.tid_trigger = 0; cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; @@ -215,11 +208,11 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len); } - memcpy(cmd->addr, vif->addr, ETH_ALEN); + memcpy(cmd->addr, wl->mac_addr, ETH_ALEN); - ret = wl1271_cmd_build_probe_req(wl, wlvif, wl->scan.ssid, - wl->scan.ssid_len, wl->scan.req->ie, - wl->scan.req->ie_len, band); + ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len, + wl->scan.req->ie, wl->scan.req->ie_len, + band); if (ret < 0) { wl1271_error("PROBE request template failed"); goto out; @@ -248,12 +241,11 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, return ret; } -void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) +void wl1271_scan_stm(struct wl1271 *wl) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); int ret = 0; enum ieee80211_band band; - u32 rate, mask; + u32 rate; switch (wl->scan.state) { case WL1271_SCAN_STATE_IDLE: @@ -261,59 +253,47 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) case WL1271_SCAN_STATE_2GHZ_ACTIVE: band = IEEE80211_BAND_2GHZ; - mask = wlvif->bitrate_masks[band]; - if (wl->scan.req->no_cck) { - mask &= ~CONF_TX_CCK_RATES; - if (!mask) - mask = CONF_TX_RATE_MASK_BASIC_P2P; - } - rate = wl1271_tx_min_rate_get(wl, mask); - ret = wl1271_scan_send(wl, vif, band, false, rate); + rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); + ret = wl1271_scan_send(wl, band, false, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; - wl1271_scan_stm(wl, vif); + wl1271_scan_stm(wl); } break; case WL1271_SCAN_STATE_2GHZ_PASSIVE: band = IEEE80211_BAND_2GHZ; - mask = wlvif->bitrate_masks[band]; - if (wl->scan.req->no_cck) { - mask &= ~CONF_TX_CCK_RATES; - if (!mask) - mask = CONF_TX_RATE_MASK_BASIC_P2P; - } - rate = wl1271_tx_min_rate_get(wl, mask); - ret = wl1271_scan_send(wl, vif, band, true, rate); + rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); + ret = wl1271_scan_send(wl, band, true, rate); if (ret == WL1271_NOTHING_TO_SCAN) { if (wl->enable_11a) wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; else wl->scan.state = WL1271_SCAN_STATE_DONE; - wl1271_scan_stm(wl, vif); + wl1271_scan_stm(wl); } break; case WL1271_SCAN_STATE_5GHZ_ACTIVE: band = IEEE80211_BAND_5GHZ; - rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); - ret = wl1271_scan_send(wl, vif, band, false, rate); + rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); + ret = wl1271_scan_send(wl, band, false, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; - wl1271_scan_stm(wl, vif); + wl1271_scan_stm(wl); } break; case WL1271_SCAN_STATE_5GHZ_PASSIVE: band = IEEE80211_BAND_5GHZ; - rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); - ret = wl1271_scan_send(wl, vif, band, true, rate); + rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); + ret = wl1271_scan_send(wl, band, true, rate); if (ret == WL1271_NOTHING_TO_SCAN) { wl->scan.state = WL1271_SCAN_STATE_DONE; - wl1271_scan_stm(wl, vif); + wl1271_scan_stm(wl); } break; @@ -337,8 +317,7 @@ void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif) } } -int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif, - const u8 *ssid, size_t ssid_len, +int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, struct cfg80211_scan_request *req) { /* @@ -359,7 +338,6 @@ int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif, wl->scan.ssid_len = 0; } - wl->scan_vif = vif; wl->scan.req = req; memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); @@ -368,7 +346,7 @@ int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif, ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work, msecs_to_jiffies(WL1271_SCAN_TIMEOUT)); - wl1271_scan_stm(wl, vif); + wl1271_scan_stm(wl); return 0; } @@ -572,9 +550,6 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, * so they're used in probe requests. */ for (i = 0; i < req->n_ssids; i++) { - if (!req->ssids[i].ssid_len) - continue; - for (j = 0; j < cmd->n_ssids; j++) if (!memcmp(req->ssids[i].ssid, cmd->ssids[j].ssid, @@ -610,7 +585,6 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, } int wl1271_scan_sched_scan_config(struct wl1271 *wl, - struct wl12xx_vif *wlvif, struct cfg80211_sched_scan_request *req, struct ieee80211_sched_scan_ies *ies) { @@ -657,7 +631,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, } if (!force_passive && cfg->active[0]) { - ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid, + ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, req->ssids[0].ssid_len, ies->ie[IEEE80211_BAND_2GHZ], ies->len[IEEE80211_BAND_2GHZ], @@ -669,7 +643,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, } if (!force_passive && cfg->active[1]) { - ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid, + ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, req->ssids[0].ssid_len, ies->ie[IEEE80211_BAND_5GHZ], ies->len[IEEE80211_BAND_5GHZ], @@ -693,14 +667,14 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, return ret; } -int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl1271_scan_sched_scan_start(struct wl1271 *wl) { struct wl1271_cmd_sched_scan_start *start; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd periodic scan start"); - if (wlvif->bss_type != BSS_TYPE_STA_BSS) + if (wl->bss_type != BSS_TYPE_STA_BSS) return -EOPNOTSUPP; if (!test_bit(WL1271_FLAG_IDLE, &wl->flags)) diff --git a/trunk/drivers/net/wireless/wl12xx/scan.h b/trunk/drivers/net/wireless/wl12xx/scan.h index a7ed43dc08c9..92115156522f 100644 --- a/trunk/drivers/net/wireless/wl12xx/scan.h +++ b/trunk/drivers/net/wireless/wl12xx/scan.h @@ -26,20 +26,18 @@ #include "wl12xx.h" -int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif, - const u8 *ssid, size_t ssid_len, +int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, struct cfg80211_scan_request *req); int wl1271_scan_stop(struct wl1271 *wl); int wl1271_scan_build_probe_req(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, u8 band); -void wl1271_scan_stm(struct wl1271 *wl, struct ieee80211_vif *vif); +void wl1271_scan_stm(struct wl1271 *wl); void wl1271_scan_complete_work(struct work_struct *work); int wl1271_scan_sched_scan_config(struct wl1271 *wl, - struct wl12xx_vif *wlvif, struct cfg80211_sched_scan_request *req, struct ieee80211_sched_scan_ies *ies); -int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif); +int wl1271_scan_sched_scan_start(struct wl1271 *wl); void wl1271_scan_sched_scan_stop(struct wl1271 *wl); void wl1271_scan_sched_scan_results(struct wl1271 *wl); diff --git a/trunk/drivers/net/wireless/wl12xx/sdio.c b/trunk/drivers/net/wireless/wl12xx/sdio.c index 468a50553fac..516a8980723c 100644 --- a/trunk/drivers/net/wireless/wl12xx/sdio.c +++ b/trunk/drivers/net/wireless/wl12xx/sdio.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -45,67 +44,107 @@ #define SDIO_DEVICE_ID_TI_WL1271 0x4076 #endif -struct wl12xx_sdio_glue { - struct device *dev; - struct platform_device *core; -}; - static const struct sdio_device_id wl1271_devices[] __devinitconst = { { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, {} }; MODULE_DEVICE_TABLE(sdio, wl1271_devices); -static void wl1271_sdio_set_block_size(struct device *child, - unsigned int blksz) +static void wl1271_sdio_set_block_size(struct wl1271 *wl, unsigned int blksz) { - struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); - struct sdio_func *func = dev_to_sdio_func(glue->dev); + sdio_claim_host(wl->if_priv); + sdio_set_block_size(wl->if_priv, blksz); + sdio_release_host(wl->if_priv); +} - sdio_claim_host(func); - sdio_set_block_size(func, blksz); - sdio_release_host(func); +static inline struct sdio_func *wl_to_func(struct wl1271 *wl) +{ + return wl->if_priv; +} + +static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) +{ + return &(wl_to_func(wl)->dev); +} + +static irqreturn_t wl1271_hardirq(int irq, void *cookie) +{ + struct wl1271 *wl = cookie; + unsigned long flags; + + wl1271_debug(DEBUG_IRQ, "IRQ"); + + /* complete the ELP completion */ + spin_lock_irqsave(&wl->wl_lock, flags); + set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); + if (wl->elp_compl) { + complete(wl->elp_compl); + wl->elp_compl = NULL; + } + + if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) { + /* don't enqueue a work right now. mark it as pending */ + set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags); + wl1271_debug(DEBUG_IRQ, "should not enqueue work"); + disable_irq_nosync(wl->irq); + pm_wakeup_event(wl1271_sdio_wl_to_dev(wl), 0); + spin_unlock_irqrestore(&wl->wl_lock, flags); + return IRQ_HANDLED; + } + spin_unlock_irqrestore(&wl->wl_lock, flags); + + return IRQ_WAKE_THREAD; } -static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, +static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) +{ + disable_irq(wl->irq); +} + +static void wl1271_sdio_enable_interrupts(struct wl1271 *wl) +{ + enable_irq(wl->irq); +} + +static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { int ret; - struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); - struct sdio_func *func = dev_to_sdio_func(glue->dev); + struct sdio_func *func = wl_to_func(wl); if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); - dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n", - addr, ((u8 *)buf)[0]); + wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", + addr, ((u8 *)buf)[0]); } else { if (fixed) ret = sdio_readsb(func, buf, addr, len); else ret = sdio_memcpy_fromio(func, buf, addr, len); - dev_dbg(child->parent, "sdio read 53 addr 0x%x, %zu bytes\n", - addr, len); + wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes", + addr, len); + wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); } if (ret) - dev_err(child->parent, "sdio read failed (%d)\n", ret); + wl1271_error("sdio read failed (%d)", ret); } -static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, +static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { int ret; - struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); - struct sdio_func *func = dev_to_sdio_func(glue->dev); + struct sdio_func *func = wl_to_func(wl); if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); - dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n", - addr, ((u8 *)buf)[0]); + wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", + addr, ((u8 *)buf)[0]); } else { - dev_dbg(child->parent, "sdio write 53 addr 0x%x, %zu bytes\n", - addr, len); + wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes", + addr, len); + wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); if (fixed) ret = sdio_writesb(func, addr, buf, len); @@ -114,13 +153,13 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, } if (ret) - dev_err(child->parent, "sdio write failed (%d)\n", ret); + wl1271_error("sdio write failed (%d)", ret); } -static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) +static int wl1271_sdio_power_on(struct wl1271 *wl) { + struct sdio_func *func = wl_to_func(wl); int ret; - struct sdio_func *func = dev_to_sdio_func(glue->dev); /* If enabled, tell runtime PM not to power off the card */ if (pm_runtime_enabled(&func->dev)) { @@ -141,10 +180,10 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) return ret; } -static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue) +static int wl1271_sdio_power_off(struct wl1271 *wl) { + struct sdio_func *func = wl_to_func(wl); int ret; - struct sdio_func *func = dev_to_sdio_func(glue->dev); sdio_disable_func(func); sdio_release_host(func); @@ -161,43 +200,46 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue) return ret; } -static int wl12xx_sdio_set_power(struct device *child, bool enable) +static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) { - struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); - if (enable) - return wl12xx_sdio_power_on(glue); + return wl1271_sdio_power_on(wl); else - return wl12xx_sdio_power_off(glue); + return wl1271_sdio_power_off(wl); } static struct wl1271_if_operations sdio_ops = { - .read = wl12xx_sdio_raw_read, - .write = wl12xx_sdio_raw_write, - .power = wl12xx_sdio_set_power, + .read = wl1271_sdio_raw_read, + .write = wl1271_sdio_raw_write, + .power = wl1271_sdio_set_power, + .dev = wl1271_sdio_wl_to_dev, + .enable_irq = wl1271_sdio_enable_interrupts, + .disable_irq = wl1271_sdio_disable_interrupts, .set_block_size = wl1271_sdio_set_block_size, }; static int __devinit wl1271_probe(struct sdio_func *func, const struct sdio_device_id *id) { - struct wl12xx_platform_data *wlan_data; - struct wl12xx_sdio_glue *glue; - struct resource res[1]; + struct ieee80211_hw *hw; + const struct wl12xx_platform_data *wlan_data; + struct wl1271 *wl; + unsigned long irqflags; mmc_pm_flag_t mmcflags; - int ret = -ENOMEM; + int ret; /* We are only able to handle the wlan function */ if (func->num != 0x02) return -ENODEV; - glue = kzalloc(sizeof(*glue), GFP_KERNEL); - if (!glue) { - dev_err(&func->dev, "can't allocate glue\n"); - goto out; - } + hw = wl1271_alloc_hw(); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + wl = hw->priv; - glue->dev = &func->dev; + wl->if_priv = func; + wl->if_ops = &sdio_ops; /* Grab access to FN0 for ELP reg. */ func->card->quirks |= MMC_QUIRK_LENIENT_FN0; @@ -208,79 +250,80 @@ static int __devinit wl1271_probe(struct sdio_func *func, wlan_data = wl12xx_get_platform_data(); if (IS_ERR(wlan_data)) { ret = PTR_ERR(wlan_data); - dev_err(glue->dev, "missing wlan platform data: %d\n", ret); - goto out_free_glue; + wl1271_error("missing wlan platform data: %d", ret); + goto out_free; } - /* if sdio can keep power while host is suspended, enable wow */ - mmcflags = sdio_get_host_pm_caps(func); - dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags); + wl->irq = wlan_data->irq; + wl->ref_clock = wlan_data->board_ref_clock; + wl->tcxo_clock = wlan_data->board_tcxo_clock; + wl->platform_quirks = wlan_data->platform_quirks; - if (mmcflags & MMC_PM_KEEP_POWER) - wlan_data->pwr_in_suspend = true; - - wlan_data->ops = &sdio_ops; + if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) + irqflags = IRQF_TRIGGER_RISING; + else + irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; + + ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, + irqflags, + DRIVER_NAME, wl); + if (ret < 0) { + wl1271_error("request_irq() failed: %d", ret); + goto out_free; + } - sdio_set_drvdata(func, glue); + ret = enable_irq_wake(wl->irq); + if (!ret) { + wl->irq_wake_enabled = true; + device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1); - /* Tell PM core that we don't need the card to be powered now */ - pm_runtime_put_noidle(&func->dev); + /* if sdio can keep power while host is suspended, enable wow */ + mmcflags = sdio_get_host_pm_caps(func); + wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags); - glue->core = platform_device_alloc("wl12xx", -1); - if (!glue->core) { - dev_err(glue->dev, "can't allocate platform_device"); - ret = -ENOMEM; - goto out_free_glue; + if (mmcflags & MMC_PM_KEEP_POWER) + hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; } + disable_irq(wl->irq); - glue->core->dev.parent = &func->dev; + ret = wl1271_init_ieee80211(wl); + if (ret) + goto out_irq; - memset(res, 0x00, sizeof(res)); + ret = wl1271_register_hw(wl); + if (ret) + goto out_irq; - res[0].start = wlan_data->irq; - res[0].flags = IORESOURCE_IRQ; - res[0].name = "irq"; + sdio_set_drvdata(func, wl); - ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); - if (ret) { - dev_err(glue->dev, "can't add resources\n"); - goto out_dev_put; - } - - ret = platform_device_add_data(glue->core, wlan_data, - sizeof(*wlan_data)); - if (ret) { - dev_err(glue->dev, "can't add platform data\n"); - goto out_dev_put; - } + /* Tell PM core that we don't need the card to be powered now */ + pm_runtime_put_noidle(&func->dev); - ret = platform_device_add(glue->core); - if (ret) { - dev_err(glue->dev, "can't add platform device\n"); - goto out_dev_put; - } return 0; -out_dev_put: - platform_device_put(glue->core); + out_irq: + free_irq(wl->irq, wl); -out_free_glue: - kfree(glue); + out_free: + wl1271_free_hw(wl); -out: return ret; } static void __devexit wl1271_remove(struct sdio_func *func) { - struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); + struct wl1271 *wl = sdio_get_drvdata(func); /* Undo decrement done above in wl1271_probe */ pm_runtime_get_noresume(&func->dev); - platform_device_del(glue->core); - platform_device_put(glue->core); - kfree(glue); + wl1271_unregister_hw(wl); + if (wl->irq_wake_enabled) { + device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0); + disable_irq_wake(wl->irq); + } + free_irq(wl->irq, wl); + wl1271_free_hw(wl); } #ifdef CONFIG_PM @@ -289,21 +332,20 @@ static int wl1271_suspend(struct device *dev) /* Tell MMC/SDIO core it's OK to power down the card * (if it isn't already), but not to remove it completely */ struct sdio_func *func = dev_to_sdio_func(dev); - struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); - struct wl1271 *wl = platform_get_drvdata(glue->core); + struct wl1271 *wl = sdio_get_drvdata(func); mmc_pm_flag_t sdio_flags; int ret = 0; - dev_dbg(dev, "wl1271 suspend. wow_enabled: %d\n", - wl->wow_enabled); + wl1271_debug(DEBUG_MAC80211, "wl1271 suspend. wow_enabled: %d", + wl->wow_enabled); /* check whether sdio should keep power */ if (wl->wow_enabled) { sdio_flags = sdio_get_host_pm_caps(func); if (!(sdio_flags & MMC_PM_KEEP_POWER)) { - dev_err(dev, "can't keep power while host " - "is suspended\n"); + wl1271_error("can't keep power while host " + "is suspended"); ret = -EINVAL; goto out; } @@ -311,7 +353,7 @@ static int wl1271_suspend(struct device *dev) /* keep power while host suspended */ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); if (ret) { - dev_err(dev, "error while trying to keep power\n"); + wl1271_error("error while trying to keep power"); goto out; } @@ -325,10 +367,9 @@ static int wl1271_suspend(struct device *dev) static int wl1271_resume(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); - struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); - struct wl1271 *wl = platform_get_drvdata(glue->core); + struct wl1271 *wl = sdio_get_drvdata(func); - dev_dbg(dev, "wl1271 resume\n"); + wl1271_debug(DEBUG_MAC80211, "wl1271 resume"); if (wl->wow_enabled) { /* claim back host */ sdio_claim_host(func); diff --git a/trunk/drivers/net/wireless/wl12xx/sdio_test.c b/trunk/drivers/net/wireless/wl12xx/sdio_test.c new file mode 100644 index 000000000000..f25d5d9212e7 --- /dev/null +++ b/trunk/drivers/net/wireless/wl12xx/sdio_test.c @@ -0,0 +1,543 @@ +/* + * SDIO testing driver for wl12xx + * + * Copyright (C) 2010 Nokia Corporation + * + * Contact: Roger Quadros + * + * wl12xx read/write routines taken from the main module + * + * 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 "wl12xx.h" +#include "io.h" +#include "boot.h" + +#ifndef SDIO_VENDOR_ID_TI +#define SDIO_VENDOR_ID_TI 0x0097 +#endif + +#ifndef SDIO_DEVICE_ID_TI_WL1271 +#define SDIO_DEVICE_ID_TI_WL1271 0x4076 +#endif + +static bool rx, tx; + +module_param(rx, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(rx, "Perform rx test. Default (0). " + "This test continuously reads data from the SDIO device.\n"); + +module_param(tx, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(tx, "Perform tx test. Default (0). " + "This test continuously writes data to the SDIO device.\n"); + +struct wl1271_test { + struct wl1271 wl; + struct task_struct *test_task; +}; + +static const struct sdio_device_id wl1271_devices[] = { + { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271) }, + {} +}; + +static inline struct sdio_func *wl_to_func(struct wl1271 *wl) +{ + return wl->if_priv; +} + +static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl) +{ + return &(wl_to_func(wl)->dev); +} + +static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) +{ + int ret = 0; + struct sdio_func *func = wl_to_func(wl); + + if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { + ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); + wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x", + addr, ((u8 *)buf)[0]); + } else { + if (fixed) + ret = sdio_readsb(func, buf, addr, len); + else + ret = sdio_memcpy_fromio(func, buf, addr, len); + + wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes", + addr, len); + wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); + } + + if (ret) + wl1271_error("sdio read failed (%d)", ret); +} + +static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) +{ + int ret = 0; + struct sdio_func *func = wl_to_func(wl); + + if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { + sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); + wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", + addr, ((u8 *)buf)[0]); + } else { + wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes", + addr, len); + wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); + + if (fixed) + ret = sdio_writesb(func, addr, buf, len); + else + ret = sdio_memcpy_toio(func, addr, buf, len); + } + if (ret) + wl1271_error("sdio write failed (%d)", ret); + +} + +static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) +{ + struct sdio_func *func = wl_to_func(wl); + int ret; + + /* Let the SDIO stack handle wlan_enable control, so we + * keep host claimed while wlan is in use to keep wl1271 + * alive. + */ + if (enable) { + /* Power up the card */ + ret = pm_runtime_get_sync(&func->dev); + if (ret < 0) + goto out; + + /* Runtime PM might be disabled, power up the card manually */ + ret = mmc_power_restore_host(func->card->host); + if (ret < 0) + goto out; + + sdio_claim_host(func); + sdio_enable_func(func); + } else { + sdio_disable_func(func); + sdio_release_host(func); + + /* Runtime PM might be disabled, power off the card manually */ + ret = mmc_power_save_host(func->card->host); + if (ret < 0) + goto out; + + /* Power down the card */ + ret = pm_runtime_put_sync(&func->dev); + } + +out: + return ret; +} + +static void wl1271_sdio_disable_interrupts(struct wl1271 *wl) +{ +} + +static void wl1271_sdio_enable_interrupts(struct wl1271 *wl) +{ +} + + +static struct wl1271_if_operations sdio_ops = { + .read = wl1271_sdio_raw_read, + .write = wl1271_sdio_raw_write, + .power = wl1271_sdio_set_power, + .dev = wl1271_sdio_wl_to_dev, + .enable_irq = wl1271_sdio_enable_interrupts, + .disable_irq = wl1271_sdio_disable_interrupts, +}; + +static void wl1271_fw_wakeup(struct wl1271 *wl) +{ + u32 elp_reg; + + elp_reg = ELPCTRL_WAKE_UP; + wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); +} + +static int wl1271_fetch_firmware(struct wl1271 *wl) +{ + const struct firmware *fw; + int ret; + + if (wl->chip.id == CHIP_ID_1283_PG20) + ret = request_firmware(&fw, WL128X_FW_NAME, + wl1271_wl_to_dev(wl)); + else + ret = request_firmware(&fw, WL127X_FW_NAME, + wl1271_wl_to_dev(wl)); + + if (ret < 0) { + wl1271_error("could not get firmware: %d", ret); + return ret; + } + + if (fw->size % 4) { + wl1271_error("firmware size is not multiple of 32 bits: %zu", + fw->size); + ret = -EILSEQ; + goto out; + } + + wl->fw_len = fw->size; + wl->fw = vmalloc(wl->fw_len); + + if (!wl->fw) { + wl1271_error("could not allocate memory for the firmware"); + ret = -ENOMEM; + goto out; + } + + memcpy(wl->fw, fw->data, wl->fw_len); + + ret = 0; + +out: + release_firmware(fw); + + return ret; +} + +static int wl1271_fetch_nvs(struct wl1271 *wl) +{ + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); + + if (ret < 0) { + wl1271_error("could not get nvs file: %d", ret); + return ret; + } + + wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); + + if (!wl->nvs) { + wl1271_error("could not allocate memory for the nvs file"); + ret = -ENOMEM; + goto out; + } + + wl->nvs_len = fw->size; + +out: + release_firmware(fw); + + return ret; +} + +static int wl1271_chip_wakeup(struct wl1271 *wl) +{ + struct wl1271_partition_set partition; + int ret; + + msleep(WL1271_PRE_POWER_ON_SLEEP); + ret = wl1271_power_on(wl); + if (ret) + return ret; + + msleep(WL1271_POWER_ON_SLEEP); + + /* We don't need a real memory partition here, because we only want + * to use the registers at this point. */ + memset(&partition, 0, sizeof(partition)); + partition.reg.start = REGISTERS_BASE; + partition.reg.size = REGISTERS_DOWN_SIZE; + wl1271_set_partition(wl, &partition); + + /* ELP module wake up */ + wl1271_fw_wakeup(wl); + + /* whal_FwCtrl_BootSm() */ + + /* 0. read chip id from CHIP_ID */ + wl->chip.id = wl1271_read32(wl, CHIP_ID_B); + + /* 1. check if chip id is valid */ + + switch (wl->chip.id) { + case CHIP_ID_1271_PG10: + wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", + wl->chip.id); + break; + case CHIP_ID_1271_PG20: + wl1271_notice("chip id 0x%x (1271 PG20)", + wl->chip.id); + break; + case CHIP_ID_1283_PG20: + wl1271_notice("chip id 0x%x (1283 PG20)", + wl->chip.id); + break; + case CHIP_ID_1283_PG10: + default: + wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); + return -ENODEV; + } + + return ret; +} + +static struct wl1271_partition_set part_down = { + .mem = { + .start = 0x00000000, + .size = 0x000177c0 + }, + .reg = { + .start = REGISTERS_BASE, + .size = 0x00008800 + }, + .mem2 = { + .start = 0x00000000, + .size = 0x00000000 + }, + .mem3 = { + .start = 0x00000000, + .size = 0x00000000 + }, +}; + +static int tester(void *data) +{ + struct wl1271 *wl = data; + struct sdio_func *func = wl_to_func(wl); + struct device *pdev = &func->dev; + int ret = 0; + bool rx_started = 0; + bool tx_started = 0; + uint8_t *tx_buf, *rx_buf; + int test_size = PAGE_SIZE; + u32 addr = 0; + struct wl1271_partition_set partition; + + /* We assume chip is powered up and firmware fetched */ + + memcpy(&partition, &part_down, sizeof(partition)); + partition.mem.start = addr; + wl1271_set_partition(wl, &partition); + + tx_buf = kmalloc(test_size, GFP_KERNEL); + rx_buf = kmalloc(test_size, GFP_KERNEL); + if (!tx_buf || !rx_buf) { + dev_err(pdev, + "Could not allocate memory. Test will not run.\n"); + ret = -ENOMEM; + goto free; + } + + memset(tx_buf, 0x5a, test_size); + + /* write something in data area so we can read it back */ + wl1271_write(wl, addr, tx_buf, test_size, false); + + while (!kthread_should_stop()) { + if (rx && !rx_started) { + dev_info(pdev, "starting rx test\n"); + rx_started = 1; + } else if (!rx && rx_started) { + dev_info(pdev, "stopping rx test\n"); + rx_started = 0; + } + + if (tx && !tx_started) { + dev_info(pdev, "starting tx test\n"); + tx_started = 1; + } else if (!tx && tx_started) { + dev_info(pdev, "stopping tx test\n"); + tx_started = 0; + } + + if (rx_started) + wl1271_read(wl, addr, rx_buf, test_size, false); + + if (tx_started) + wl1271_write(wl, addr, tx_buf, test_size, false); + + if (!rx_started && !tx_started) + msleep(100); + } + +free: + kfree(tx_buf); + kfree(rx_buf); + return ret; +} + +static int __devinit wl1271_probe(struct sdio_func *func, + const struct sdio_device_id *id) +{ + const struct wl12xx_platform_data *wlan_data; + struct wl1271 *wl; + struct wl1271_test *wl_test; + int ret = 0; + + /* wl1271 has 2 sdio functions we handle just the wlan part */ + if (func->num != 0x02) + return -ENODEV; + + wl_test = kzalloc(sizeof(struct wl1271_test), GFP_KERNEL); + if (!wl_test) { + dev_err(&func->dev, "Could not allocate memory\n"); + return -ENOMEM; + } + + wl = &wl_test->wl; + + wl->if_priv = func; + wl->if_ops = &sdio_ops; + + /* Grab access to FN0 for ELP reg. */ + func->card->quirks |= MMC_QUIRK_LENIENT_FN0; + + /* Use block mode for transferring over one block size of data */ + func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; + + wlan_data = wl12xx_get_platform_data(); + if (IS_ERR(wlan_data)) { + ret = PTR_ERR(wlan_data); + dev_err(&func->dev, "missing wlan platform data: %d\n", ret); + goto out_free; + } + + wl->irq = wlan_data->irq; + wl->ref_clock = wlan_data->board_ref_clock; + wl->tcxo_clock = wlan_data->board_tcxo_clock; + + sdio_set_drvdata(func, wl_test); + + /* power up the device */ + ret = wl1271_chip_wakeup(wl); + if (ret) { + dev_err(&func->dev, "could not wake up chip\n"); + goto out_free; + } + + if (wl->fw == NULL) { + ret = wl1271_fetch_firmware(wl); + if (ret < 0) { + dev_err(&func->dev, "firmware fetch error\n"); + goto out_off; + } + } + + /* fetch NVS */ + if (wl->nvs == NULL) { + ret = wl1271_fetch_nvs(wl); + if (ret < 0) { + dev_err(&func->dev, "NVS fetch error\n"); + goto out_off; + } + } + + ret = wl1271_load_firmware(wl); + if (ret < 0) { + dev_err(&func->dev, "firmware load error: %d\n", ret); + goto out_free; + } + + dev_info(&func->dev, "initialized\n"); + + /* I/O testing will be done in the tester thread */ + + wl_test->test_task = kthread_run(tester, wl, "sdio_tester"); + if (IS_ERR(wl_test->test_task)) { + dev_err(&func->dev, "unable to create kernel thread\n"); + ret = PTR_ERR(wl_test->test_task); + goto out_free; + } + + return 0; + +out_off: + /* power off the chip */ + wl1271_power_off(wl); + +out_free: + kfree(wl_test); + return ret; +} + +static void __devexit wl1271_remove(struct sdio_func *func) +{ + struct wl1271_test *wl_test = sdio_get_drvdata(func); + + /* stop the I/O test thread */ + kthread_stop(wl_test->test_task); + + /* power off the chip */ + wl1271_power_off(&wl_test->wl); + + vfree(wl_test->wl.fw); + wl_test->wl.fw = NULL; + kfree(wl_test->wl.nvs); + wl_test->wl.nvs = NULL; + + kfree(wl_test); +} + +static struct sdio_driver wl1271_sdio_driver = { + .name = "wl12xx_sdio_test", + .id_table = wl1271_devices, + .probe = wl1271_probe, + .remove = __devexit_p(wl1271_remove), +}; + +static int __init wl1271_init(void) +{ + int ret; + + ret = sdio_register_driver(&wl1271_sdio_driver); + if (ret < 0) + pr_err("failed to register sdio driver: %d\n", ret); + + return ret; +} +module_init(wl1271_init); + +static void __exit wl1271_exit(void) +{ + sdio_unregister_driver(&wl1271_sdio_driver); +} +module_exit(wl1271_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Roger Quadros "); + diff --git a/trunk/drivers/net/wireless/wl12xx/spi.c b/trunk/drivers/net/wireless/wl12xx/spi.c index 92caa7ce6053..0f9718677860 100644 --- a/trunk/drivers/net/wireless/wl12xx/spi.c +++ b/trunk/drivers/net/wireless/wl12xx/spi.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include "wl12xx.h" @@ -70,22 +69,35 @@ #define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) -struct wl12xx_spi_glue { - struct device *dev; - struct platform_device *core; -}; +static inline struct spi_device *wl_to_spi(struct wl1271 *wl) +{ + return wl->if_priv; +} + +static struct device *wl1271_spi_wl_to_dev(struct wl1271 *wl) +{ + return &(wl_to_spi(wl)->dev); +} + +static void wl1271_spi_disable_interrupts(struct wl1271 *wl) +{ + disable_irq(wl->irq); +} -static void wl12xx_spi_reset(struct device *child) +static void wl1271_spi_enable_interrupts(struct wl1271 *wl) +{ + enable_irq(wl->irq); +} + +static void wl1271_spi_reset(struct wl1271 *wl) { - struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); u8 *cmd; struct spi_transfer t; struct spi_message m; cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); if (!cmd) { - dev_err(child->parent, - "could not allocate cmd for spi reset\n"); + wl1271_error("could not allocate cmd for spi reset"); return; } @@ -98,22 +110,21 @@ static void wl12xx_spi_reset(struct device *child) t.len = WSPI_INIT_CMD_LEN; spi_message_add_tail(&t, &m); - spi_sync(to_spi_device(glue->dev), &m); + spi_sync(wl_to_spi(wl), &m); + wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); kfree(cmd); } -static void wl12xx_spi_init(struct device *child) +static void wl1271_spi_init(struct wl1271 *wl) { - struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; struct spi_transfer t; struct spi_message m; cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); if (!cmd) { - dev_err(child->parent, - "could not allocate cmd for spi init\n"); + wl1271_error("could not allocate cmd for spi init"); return; } @@ -154,16 +165,15 @@ static void wl12xx_spi_init(struct device *child) t.len = WSPI_INIT_CMD_LEN; spi_message_add_tail(&t, &m); - spi_sync(to_spi_device(glue->dev), &m); + spi_sync(wl_to_spi(wl), &m); + wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); kfree(cmd); } #define WL1271_BUSY_WORD_TIMEOUT 1000 -static int wl12xx_spi_read_busy(struct device *child) +static int wl1271_spi_read_busy(struct wl1271 *wl) { - struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); - struct wl1271 *wl = dev_get_drvdata(child); struct spi_transfer t[1]; struct spi_message m; u32 *busy_buf; @@ -184,22 +194,20 @@ static int wl12xx_spi_read_busy(struct device *child) t[0].len = sizeof(u32); t[0].cs_change = true; spi_message_add_tail(&t[0], &m); - spi_sync(to_spi_device(glue->dev), &m); + spi_sync(wl_to_spi(wl), &m); if (*busy_buf & 0x1) return 0; } /* The SPI bus is unresponsive, the read failed. */ - dev_err(child->parent, "SPI read busy-word timeout!\n"); + wl1271_error("SPI read busy-word timeout!\n"); return -ETIMEDOUT; } -static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, +static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed) { - struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); - struct wl1271 *wl = dev_get_drvdata(child); struct spi_transfer t[2]; struct spi_message m; u32 *busy_buf; @@ -235,10 +243,10 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, t[1].cs_change = true; spi_message_add_tail(&t[1], &m); - spi_sync(to_spi_device(glue->dev), &m); + spi_sync(wl_to_spi(wl), &m); if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && - wl12xx_spi_read_busy(child)) { + wl1271_spi_read_busy(wl)) { memset(buf, 0, chunk_len); return; } @@ -251,7 +259,10 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, t[0].cs_change = true; spi_message_add_tail(&t[0], &m); - spi_sync(to_spi_device(glue->dev), &m); + spi_sync(wl_to_spi(wl), &m); + + wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); + wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, chunk_len); if (!fixed) addr += chunk_len; @@ -260,10 +271,9 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, } } -static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf, - size_t len, bool fixed) +static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf, + size_t len, bool fixed) { - struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; struct spi_message m; u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; @@ -298,6 +308,9 @@ static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf, t[i].len = chunk_len; spi_message_add_tail(&t[i++], &m); + wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); + wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, chunk_len); + if (!fixed) addr += chunk_len; buf += chunk_len; @@ -305,41 +318,72 @@ static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf, cmd++; } - spi_sync(to_spi_device(glue->dev), &m); + spi_sync(wl_to_spi(wl), &m); +} + +static irqreturn_t wl1271_hardirq(int irq, void *cookie) +{ + struct wl1271 *wl = cookie; + unsigned long flags; + + wl1271_debug(DEBUG_IRQ, "IRQ"); + + /* complete the ELP completion */ + spin_lock_irqsave(&wl->wl_lock, flags); + set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); + if (wl->elp_compl) { + complete(wl->elp_compl); + wl->elp_compl = NULL; + } + spin_unlock_irqrestore(&wl->wl_lock, flags); + + return IRQ_WAKE_THREAD; +} + +static int wl1271_spi_set_power(struct wl1271 *wl, bool enable) +{ + if (wl->set_power) + wl->set_power(enable); + + return 0; } static struct wl1271_if_operations spi_ops = { - .read = wl12xx_spi_raw_read, - .write = wl12xx_spi_raw_write, - .reset = wl12xx_spi_reset, - .init = wl12xx_spi_init, + .read = wl1271_spi_raw_read, + .write = wl1271_spi_raw_write, + .reset = wl1271_spi_reset, + .init = wl1271_spi_init, + .power = wl1271_spi_set_power, + .dev = wl1271_spi_wl_to_dev, + .enable_irq = wl1271_spi_enable_interrupts, + .disable_irq = wl1271_spi_disable_interrupts, .set_block_size = NULL, }; static int __devinit wl1271_probe(struct spi_device *spi) { - struct wl12xx_spi_glue *glue; struct wl12xx_platform_data *pdata; - struct resource res[1]; - int ret = -ENOMEM; + struct ieee80211_hw *hw; + struct wl1271 *wl; + unsigned long irqflags; + int ret; pdata = spi->dev.platform_data; if (!pdata) { - dev_err(&spi->dev, "no platform data\n"); + wl1271_error("no platform data"); return -ENODEV; } - pdata->ops = &spi_ops; + hw = wl1271_alloc_hw(); + if (IS_ERR(hw)) + return PTR_ERR(hw); - glue = kzalloc(sizeof(*glue), GFP_KERNEL); - if (!glue) { - dev_err(&spi->dev, "can't allocate glue\n"); - goto out; - } + wl = hw->priv; - glue->dev = &spi->dev; + dev_set_drvdata(&spi->dev, wl); + wl->if_priv = spi; - spi_set_drvdata(spi, glue); + wl->if_ops = &spi_ops; /* This is the only SPI value that we need to set here, the rest * comes from the board-peripherals file */ @@ -347,61 +391,69 @@ static int __devinit wl1271_probe(struct spi_device *spi) ret = spi_setup(spi); if (ret < 0) { - dev_err(glue->dev, "spi_setup failed\n"); - goto out_free_glue; + wl1271_error("spi_setup failed"); + goto out_free; } - glue->core = platform_device_alloc("wl12xx", -1); - if (!glue->core) { - dev_err(glue->dev, "can't allocate platform_device\n"); - ret = -ENOMEM; - goto out_free_glue; + wl->set_power = pdata->set_power; + if (!wl->set_power) { + wl1271_error("set power function missing in platform data"); + ret = -ENODEV; + goto out_free; } - glue->core->dev.parent = &spi->dev; - - memset(res, 0x00, sizeof(res)); + wl->ref_clock = pdata->board_ref_clock; + wl->tcxo_clock = pdata->board_tcxo_clock; + wl->platform_quirks = pdata->platform_quirks; - res[0].start = spi->irq; - res[0].flags = IORESOURCE_IRQ; - res[0].name = "irq"; + if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) + irqflags = IRQF_TRIGGER_RISING; + else + irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; - ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); - if (ret) { - dev_err(glue->dev, "can't add resources\n"); - goto out_dev_put; + wl->irq = spi->irq; + if (wl->irq < 0) { + wl1271_error("irq missing in platform data"); + ret = -ENODEV; + goto out_free; } - ret = platform_device_add_data(glue->core, pdata, sizeof(*pdata)); - if (ret) { - dev_err(glue->dev, "can't add platform data\n"); - goto out_dev_put; + ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq, + irqflags, + DRIVER_NAME, wl); + if (ret < 0) { + wl1271_error("request_irq() failed: %d", ret); + goto out_free; } - ret = platform_device_add(glue->core); - if (ret) { - dev_err(glue->dev, "can't register platform device\n"); - goto out_dev_put; - } + disable_irq(wl->irq); + + ret = wl1271_init_ieee80211(wl); + if (ret) + goto out_irq; + + ret = wl1271_register_hw(wl); + if (ret) + goto out_irq; return 0; -out_dev_put: - platform_device_put(glue->core); + out_irq: + free_irq(wl->irq, wl); + + out_free: + wl1271_free_hw(wl); -out_free_glue: - kfree(glue); -out: return ret; } static int __devexit wl1271_remove(struct spi_device *spi) { - struct wl12xx_spi_glue *glue = spi_get_drvdata(spi); + struct wl1271 *wl = dev_get_drvdata(&spi->dev); - platform_device_del(glue->core); - platform_device_put(glue->core); - kfree(glue); + wl1271_unregister_hw(wl); + free_irq(wl->irq, wl); + wl1271_free_hw(wl); return 0; } @@ -410,6 +462,7 @@ static int __devexit wl1271_remove(struct spi_device *spi) static struct spi_driver wl1271_spi_driver = { .driver = { .name = "wl1271_spi", + .bus = &spi_bus_type, .owner = THIS_MODULE, }, diff --git a/trunk/drivers/net/wireless/wl12xx/testmode.c b/trunk/drivers/net/wireless/wl12xx/testmode.c index 978cf2de713d..4ae8effaee22 100644 --- a/trunk/drivers/net/wireless/wl12xx/testmode.c +++ b/trunk/drivers/net/wireless/wl12xx/testmode.c @@ -26,10 +26,8 @@ #include #include "wl12xx.h" -#include "debug.h" #include "acx.h" #include "reg.h" -#include "ps.h" #define WL1271_TM_MAX_DATA_LENGTH 1024 @@ -89,47 +87,31 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[]) return -EMSGSIZE; mutex_lock(&wl->mutex); - - if (wl->state == WL1271_STATE_OFF) { - ret = -EINVAL; - goto out; - } - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - ret = wl1271_cmd_test(wl, buf, buf_len, answer); + mutex_unlock(&wl->mutex); + if (ret < 0) { wl1271_warning("testmode cmd test failed: %d", ret); - goto out_sleep; + return ret; } if (answer) { len = nla_total_size(buf_len); skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len); - if (!skb) { - ret = -ENOMEM; - goto out_sleep; - } + if (!skb) + return -ENOMEM; NLA_PUT(skb, WL1271_TM_ATTR_DATA, buf_len, buf); ret = cfg80211_testmode_reply(skb); if (ret < 0) - goto out_sleep; + return ret; } -out_sleep: - wl1271_ps_elp_sleep(wl); -out: - mutex_unlock(&wl->mutex); - - return ret; + return 0; nla_put_failure: kfree_skb(skb); - ret = -EMSGSIZE; - goto out_sleep; + return -EMSGSIZE; } static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) @@ -146,53 +128,33 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]); - mutex_lock(&wl->mutex); - - if (wl->state == WL1271_STATE_OFF) { - ret = -EINVAL; - goto out; - } - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out_sleep; - } + if (!cmd) + return -ENOMEM; + mutex_lock(&wl->mutex); ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd)); + mutex_unlock(&wl->mutex); + if (ret < 0) { wl1271_warning("testmode cmd interrogate failed: %d", ret); - goto out_free; + kfree(cmd); + return ret; } skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd)); if (!skb) { - ret = -ENOMEM; - goto out_free; + kfree(cmd); + return -ENOMEM; } NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd); - ret = cfg80211_testmode_reply(skb); - if (ret < 0) - goto out_free; - -out_free: - kfree(cmd); -out_sleep: - wl1271_ps_elp_sleep(wl); -out: - mutex_unlock(&wl->mutex); - return ret; + return 0; nla_put_failure: kfree_skb(skb); - ret = -EMSGSIZE; - goto out_free; + return -EMSGSIZE; } static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[]) diff --git a/trunk/drivers/net/wireless/wl12xx/tx.c b/trunk/drivers/net/wireless/wl12xx/tx.c index 7d727ee6ddf6..bad9e29d49b0 100644 --- a/trunk/drivers/net/wireless/wl12xx/tx.c +++ b/trunk/drivers/net/wireless/wl12xx/tx.c @@ -26,24 +26,22 @@ #include #include "wl12xx.h" -#include "debug.h" #include "io.h" #include "reg.h" #include "ps.h" #include "tx.h" #include "event.h" -static int wl1271_set_default_wep_key(struct wl1271 *wl, - struct wl12xx_vif *wlvif, u8 id) +static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id) { int ret; - bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); + bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); if (is_ap) ret = wl12xx_cmd_set_default_wep_key(wl, id, - wlvif->ap.bcast_hlid); + wl->ap_bcast_hlid); else - ret = wl12xx_cmd_set_default_wep_key(wl, id, wlvif->sta.hlid); + ret = wl12xx_cmd_set_default_wep_key(wl, id, wl->sta_hlid); if (ret < 0) return ret; @@ -78,8 +76,7 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id) } static int wl1271_tx_update_filters(struct wl1271 *wl, - struct wl12xx_vif *wlvif, - struct sk_buff *skb) + struct sk_buff *skb) { struct ieee80211_hdr *hdr; int ret; @@ -95,11 +92,15 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, if (!ieee80211_is_auth(hdr->frame_control)) return 0; - if (wlvif->dev_hlid != WL12XX_INVALID_LINK_ID) + if (wl->dev_hlid != WL12XX_INVALID_LINK_ID) goto out; wl1271_debug(DEBUG_CMD, "starting device role for roaming"); - ret = wl12xx_start_dev(wl, wlvif); + ret = wl12xx_cmd_role_start_dev(wl); + if (ret < 0) + goto out; + + ret = wl12xx_roc(wl, wl->dev_role_id); if (ret < 0) goto out; out: @@ -122,16 +123,18 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, wl1271_acx_set_inconnection_sta(wl, hdr->addr1); } -static void wl1271_tx_regulate_link(struct wl1271 *wl, - struct wl12xx_vif *wlvif, - u8 hlid) +static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid) { bool fw_ps, single_sta; u8 tx_pkts; - if (WARN_ON(!test_bit(hlid, wlvif->links_map))) + /* only regulate station links */ + if (hlid < WL1271_AP_STA_HLID_START) return; + if (WARN_ON(!wl1271_is_active_sta(wl, hlid))) + return; + fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); tx_pkts = wl->links[hlid].allocated_pkts; single_sta = (wl->active_sta_count == 1); @@ -143,7 +146,7 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, * case FW-memory congestion is not a problem. */ if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) - wl12xx_ps_link_start(wl, wlvif, hlid, true); + wl1271_ps_link_start(wl, hlid, true); } bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) @@ -151,8 +154,7 @@ bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb) return wl->dummy_packet == skb; } -u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct sk_buff *skb) +u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb) { struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb); @@ -165,51 +167,49 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, } else { struct ieee80211_hdr *hdr; - if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) + if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) return wl->system_hlid; hdr = (struct ieee80211_hdr *)skb->data; if (ieee80211_is_mgmt(hdr->frame_control)) - return wlvif->ap.global_hlid; + return wl->ap_global_hlid; else - return wlvif->ap.bcast_hlid; + return wl->ap_bcast_hlid; } } -u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct sk_buff *skb) +static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - if (!wlvif || wl12xx_is_dummy_packet(wl, skb)) + if (wl12xx_is_dummy_packet(wl, skb)) return wl->system_hlid; - if (wlvif->bss_type == BSS_TYPE_AP_BSS) - return wl12xx_tx_get_hlid_ap(wl, wlvif, skb); + if (wl->bss_type == BSS_TYPE_AP_BSS) + return wl12xx_tx_get_hlid_ap(wl, skb); - wl1271_tx_update_filters(wl, wlvif, skb); + wl1271_tx_update_filters(wl, skb); - if ((test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || - test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) && + if ((test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || + test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) && !ieee80211_is_auth(hdr->frame_control) && !ieee80211_is_assoc_req(hdr->frame_control)) - return wlvif->sta.hlid; + return wl->sta_hlid; else - return wlvif->dev_hlid; + return wl->dev_hlid; } static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl, unsigned int packet_length) { - if (wl->quirks & WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT) - return ALIGN(packet_length, WL1271_TX_ALIGN_TO); - else + if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT) return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE); + else + return ALIGN(packet_length, WL1271_TX_ALIGN_TO); } -static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct sk_buff *skb, u32 extra, u32 buf_offset, - u8 hlid) +static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra, + u32 buf_offset, u8 hlid) { struct wl1271_tx_hw_descr *desc; u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; @@ -217,7 +217,6 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, u32 total_blocks; int id, ret = -EBUSY, ac; u32 spare_blocks = wl->tx_spare_blocks; - bool is_dummy = false; if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) return -EAGAIN; @@ -232,10 +231,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, len = wl12xx_calc_packet_alignment(wl, total_len); /* in case of a dummy packet, use default amount of spare mem blocks */ - if (unlikely(wl12xx_is_dummy_packet(wl, skb))) { - is_dummy = true; + if (unlikely(wl12xx_is_dummy_packet(wl, skb))) spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; - } total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE + spare_blocks; @@ -260,9 +257,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); wl->tx_allocated_pkts[ac]++; - if (!is_dummy && wlvif && - wlvif->bss_type == BSS_TYPE_AP_BSS && - test_bit(hlid, wlvif->ap.sta_hlid_map)) + if (wl->bss_type == BSS_TYPE_AP_BSS && + hlid >= WL1271_AP_STA_HLID_START) wl->links[hlid].allocated_pkts++; ret = 0; @@ -277,16 +273,15 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct sk_buff *skb, u32 extra, - struct ieee80211_tx_info *control, u8 hlid) +static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, + u32 extra, struct ieee80211_tx_info *control, + u8 hlid) { struct timespec ts; struct wl1271_tx_hw_descr *desc; int aligned_len, ac, rate_idx; s64 hosttime; - u16 tx_attr = 0; - bool is_dummy; + u16 tx_attr; desc = (struct wl1271_tx_hw_descr *) skb->data; @@ -303,8 +298,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, hosttime = (timespec_to_ns(&ts) >> 10); desc->start_time = cpu_to_le32(hosttime - wl->time_offset); - is_dummy = wl12xx_is_dummy_packet(wl, skb); - if (is_dummy || !wlvif || wlvif->bss_type != BSS_TYPE_AP_BSS) + if (wl->bss_type != BSS_TYPE_AP_BSS) desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); else desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU); @@ -313,42 +307,39 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); desc->tid = skb->priority; - if (is_dummy) { + if (wl12xx_is_dummy_packet(wl, skb)) { /* * FW expects the dummy packet to have an invalid session id - * any session id that is different than the one set in the join */ - tx_attr = (SESSION_COUNTER_INVALID << + tx_attr = ((~wl->session_counter) << TX_HW_ATTR_OFST_SESSION_COUNTER) & TX_HW_ATTR_SESSION_COUNTER; tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ; - } else if (wlvif) { + } else { /* configure the tx attributes */ - tx_attr = wlvif->session_counter << - TX_HW_ATTR_OFST_SESSION_COUNTER; + tx_attr = + wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; } desc->hlid = hlid; - if (is_dummy || !wlvif) - rate_idx = 0; - else if (wlvif->bss_type != BSS_TYPE_AP_BSS) { + + if (wl->bss_type != BSS_TYPE_AP_BSS) { /* if the packets are destined for AP (have a STA entry) send them with AP rate policies, otherwise use default basic rates */ - if (control->flags & IEEE80211_TX_CTL_NO_CCK_RATE) - rate_idx = wlvif->sta.p2p_rate_idx; - else if (control->control.sta) - rate_idx = wlvif->sta.ap_rate_idx; + if (control->control.sta) + rate_idx = ACX_TX_AP_FULL_RATE; else - rate_idx = wlvif->sta.basic_rate_idx; + rate_idx = ACX_TX_BASIC_RATE; } else { - if (hlid == wlvif->ap.global_hlid) - rate_idx = wlvif->ap.mgmt_rate_idx; - else if (hlid == wlvif->ap.bcast_hlid) - rate_idx = wlvif->ap.bcast_rate_idx; + if (hlid == wl->ap_global_hlid) + rate_idx = ACX_TX_AP_MODE_MGMT_RATE; + else if (hlid == wl->ap_bcast_hlid) + rate_idx = ACX_TX_AP_MODE_BCST_RATE; else - rate_idx = wlvif->ap.ucast_rate_idx[ac]; + rate_idx = ac; } tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY; @@ -388,24 +379,20 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, } /* caller must hold wl->mutex */ -static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct sk_buff *skb, u32 buf_offset) +static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, + u32 buf_offset) { struct ieee80211_tx_info *info; u32 extra = 0; int ret = 0; u32 total_len; u8 hlid; - bool is_dummy; if (!skb) return -EINVAL; info = IEEE80211_SKB_CB(skb); - /* TODO: handle dummy packets on multi-vifs */ - is_dummy = wl12xx_is_dummy_packet(wl, skb); - if (info->control.hw_key && info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) extra = WL1271_TKIP_IV_SPACE; @@ -418,28 +405,29 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) || (cipher == WLAN_CIPHER_SUITE_WEP104); - if (unlikely(is_wep && wlvif->default_key != idx)) { - ret = wl1271_set_default_wep_key(wl, wlvif, idx); + if (unlikely(is_wep && wl->default_key != idx)) { + ret = wl1271_set_default_wep_key(wl, idx); if (ret < 0) return ret; - wlvif->default_key = idx; + wl->default_key = idx; } } - hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); + + hlid = wl1271_tx_get_hlid(wl, skb); if (hlid == WL12XX_INVALID_LINK_ID) { wl1271_error("invalid hlid. dropping skb 0x%p", skb); return -EINVAL; } - ret = wl1271_tx_allocate(wl, wlvif, skb, extra, buf_offset, hlid); + ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid); if (ret < 0) return ret; - wl1271_tx_fill_hdr(wl, wlvif, skb, extra, info, hlid); + wl1271_tx_fill_hdr(wl, skb, extra, info, hlid); - if (!is_dummy && wlvif && wlvif->bss_type == BSS_TYPE_AP_BSS) { + if (wl->bss_type == BSS_TYPE_AP_BSS) { wl1271_tx_ap_update_inconnection_sta(wl, skb); - wl1271_tx_regulate_link(wl, wlvif, hlid); + wl1271_tx_regulate_link(wl, hlid); } /* @@ -456,7 +444,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len); /* Revert side effects in the dummy packet skb, so it can be reused */ - if (is_dummy) + if (wl12xx_is_dummy_packet(wl, skb)) skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); return total_len; @@ -534,18 +522,19 @@ static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl, return &queues[q]; } -static struct sk_buff *wl12xx_lnk_skb_dequeue(struct wl1271 *wl, - struct wl1271_link *lnk) +static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl) { - struct sk_buff *skb; + struct sk_buff *skb = NULL; unsigned long flags; struct sk_buff_head *queue; - queue = wl1271_select_queue(wl, lnk->tx_queue); + queue = wl1271_select_queue(wl, wl->tx_queue); if (!queue) - return NULL; + goto out; skb = skb_dequeue(queue); + +out: if (skb) { int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); spin_lock_irqsave(&wl->wl_lock, flags); @@ -556,33 +545,43 @@ static struct sk_buff *wl12xx_lnk_skb_dequeue(struct wl1271 *wl, return skb; } -static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl, - struct wl12xx_vif *wlvif) +static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) { struct sk_buff *skb = NULL; + unsigned long flags; int i, h, start_hlid; + struct sk_buff_head *queue; /* start from the link after the last one */ - start_hlid = (wlvif->last_tx_hlid + 1) % WL12XX_MAX_LINKS; + start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS; /* dequeue according to AC, round robin on each link */ - for (i = 0; i < WL12XX_MAX_LINKS; i++) { - h = (start_hlid + i) % WL12XX_MAX_LINKS; + for (i = 0; i < AP_MAX_LINKS; i++) { + h = (start_hlid + i) % AP_MAX_LINKS; /* only consider connected stations */ - if (!test_bit(h, wlvif->links_map)) + if (h >= WL1271_AP_STA_HLID_START && + !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map)) continue; - skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[h]); - if (!skb) + queue = wl1271_select_queue(wl, wl->links[h].tx_queue); + if (!queue) continue; - wlvif->last_tx_hlid = h; - break; + skb = skb_dequeue(queue); + if (skb) + break; } - if (!skb) - wlvif->last_tx_hlid = 0; + if (skb) { + int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); + wl->last_tx_hlid = h; + spin_lock_irqsave(&wl->wl_lock, flags); + wl->tx_queue_count[q]--; + spin_unlock_irqrestore(&wl->wl_lock, flags); + } else { + wl->last_tx_hlid = 0; + } return skb; } @@ -590,32 +589,12 @@ static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl, static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) { unsigned long flags; - struct wl12xx_vif *wlvif = wl->last_wlvif; struct sk_buff *skb = NULL; - if (wlvif) { - wl12xx_for_each_wlvif_continue(wl, wlvif) { - skb = wl12xx_vif_skb_dequeue(wl, wlvif); - if (skb) { - wl->last_wlvif = wlvif; - break; - } - } - } - - /* do another pass */ - if (!skb) { - wl12xx_for_each_wlvif(wl, wlvif) { - skb = wl12xx_vif_skb_dequeue(wl, wlvif); - if (skb) { - wl->last_wlvif = wlvif; - break; - } - } - } - - if (!skb) - skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[wl->system_hlid]); + if (wl->bss_type == BSS_TYPE_AP_BSS) + skb = wl1271_ap_skb_dequeue(wl); + else + skb = wl1271_sta_skb_dequeue(wl); if (!skb && test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { @@ -631,21 +610,21 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl) return skb; } -static void wl1271_skb_queue_head(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct sk_buff *skb) +static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb) { unsigned long flags; int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); if (wl12xx_is_dummy_packet(wl, skb)) { set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags); - } else { - u8 hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); + } else if (wl->bss_type == BSS_TYPE_AP_BSS) { + u8 hlid = wl1271_tx_get_hlid(wl, skb); skb_queue_head(&wl->links[hlid].tx_queue[q], skb); /* make sure we dequeue the same packet next time */ - wlvif->last_tx_hlid = (hlid + WL12XX_MAX_LINKS - 1) % - WL12XX_MAX_LINKS; + wl->last_tx_hlid = (hlid + AP_MAX_LINKS - 1) % AP_MAX_LINKS; + } else { + skb_queue_head(&wl->tx_queue[q], skb); } spin_lock_irqsave(&wl->wl_lock, flags); @@ -660,71 +639,29 @@ static bool wl1271_tx_is_data_present(struct sk_buff *skb) return ieee80211_is_data_present(hdr->frame_control); } -void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids) -{ - struct wl12xx_vif *wlvif; - u32 timeout; - u8 hlid; - - if (!wl->conf.rx_streaming.interval) - return; - - if (!wl->conf.rx_streaming.always && - !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags)) - return; - - timeout = wl->conf.rx_streaming.duration; - wl12xx_for_each_wlvif_sta(wl, wlvif) { - bool found = false; - for_each_set_bit(hlid, active_hlids, WL12XX_MAX_LINKS) { - if (test_bit(hlid, wlvif->links_map)) { - found = true; - break; - } - } - - if (!found) - continue; - - /* enable rx streaming */ - if (!test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags)) - ieee80211_queue_work(wl->hw, - &wlvif->rx_streaming_enable_work); - - mod_timer(&wlvif->rx_streaming_timer, - jiffies + msecs_to_jiffies(timeout)); - } -} - void wl1271_tx_work_locked(struct wl1271 *wl) { - struct wl12xx_vif *wlvif; struct sk_buff *skb; - struct wl1271_tx_hw_descr *desc; u32 buf_offset = 0; bool sent_packets = false; - unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; + bool had_data = false; + bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); int ret; if (unlikely(wl->state == WL1271_STATE_OFF)) return; while ((skb = wl1271_skb_dequeue(wl))) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - bool has_data = false; + if (wl1271_tx_is_data_present(skb)) + had_data = true; - wlvif = NULL; - if (!wl12xx_is_dummy_packet(wl, skb) && info->control.vif) - wlvif = wl12xx_vif_to_data(info->control.vif); - - has_data = wlvif && wl1271_tx_is_data_present(skb); - ret = wl1271_prepare_tx_frame(wl, wlvif, skb, buf_offset); + ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); if (ret == -EAGAIN) { /* * Aggregation buffer is full. * Flush buffer and try again. */ - wl1271_skb_queue_head(wl, wlvif, skb); + wl1271_skb_queue_head(wl, skb); wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, buf_offset, true); sent_packets = true; @@ -735,7 +672,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) * Firmware buffer is full. * Queue back last skb, and stop aggregating. */ - wl1271_skb_queue_head(wl, wlvif, skb); + wl1271_skb_queue_head(wl, skb); /* No work left, avoid scheduling redundant tx work */ set_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); goto out_ack; @@ -745,10 +682,6 @@ void wl1271_tx_work_locked(struct wl1271 *wl) } buf_offset += ret; wl->tx_packets_count++; - if (has_data) { - desc = (struct wl1271_tx_hw_descr *) skb->data; - __set_bit(desc->hlid, active_hlids); - } } out_ack: @@ -768,7 +701,19 @@ void wl1271_tx_work_locked(struct wl1271 *wl) wl1271_handle_tx_low_watermark(wl); } - wl12xx_rearm_rx_streaming(wl, active_hlids); + if (!is_ap && wl->conf.rx_streaming.interval && had_data && + (wl->conf.rx_streaming.always || + test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) { + u32 timeout = wl->conf.rx_streaming.duration; + + /* enable rx streaming */ + if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) + ieee80211_queue_work(wl->hw, + &wl->rx_streaming_enable_work); + + mod_timer(&wl->rx_streaming_timer, + jiffies + msecs_to_jiffies(timeout)); + } } void wl1271_tx_work(struct work_struct *work) @@ -792,8 +737,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, struct wl1271_tx_hw_res_descr *result) { struct ieee80211_tx_info *info; - struct ieee80211_vif *vif; - struct wl12xx_vif *wlvif; struct sk_buff *skb; int id = result->id; int rate = -1; @@ -813,16 +756,11 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, return; } - /* info->control is valid as long as we don't update info->status */ - vif = info->control.vif; - wlvif = wl12xx_vif_to_data(vif); - /* update the TX status info */ if (result->status == TX_SUCCESS) { if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_ACK; - rate = wl1271_rate_to_idx(result->rate_class_index, - wlvif->band); + rate = wl1271_rate_to_idx(result->rate_class_index, wl->band); retries = result->ack_failures; } else if (result->status == TX_RETRY_EXCEEDED) { wl->stats.excessive_retries++; @@ -845,14 +783,14 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP || info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM)) { u8 fw_lsb = result->tx_security_sequence_number_lsb; - u8 cur_lsb = wlvif->tx_security_last_seq_lsb; + u8 cur_lsb = wl->tx_security_last_seq_lsb; /* * update security sequence number, taking care of potential * wrap-around */ - wlvif->tx_security_seq += (fw_lsb - cur_lsb) & 0xff; - wlvif->tx_security_last_seq_lsb = fw_lsb; + wl->tx_security_seq += (fw_lsb - cur_lsb + 256) % 256; + wl->tx_security_last_seq_lsb = fw_lsb; } /* remove private header from packet */ @@ -948,30 +886,39 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) } /* caller must hold wl->mutex and TX must be stopped */ -void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif) +void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) { int i; + struct sk_buff *skb; + struct ieee80211_tx_info *info; /* TX failure */ - for_each_set_bit(i, wlvif->links_map, WL12XX_MAX_LINKS) { - if (wlvif->bss_type == BSS_TYPE_AP_BSS) - wl1271_free_sta(wl, wlvif, i); - else - wlvif->sta.ba_rx_bitmap = 0; + if (wl->bss_type == BSS_TYPE_AP_BSS) { + for (i = 0; i < AP_MAX_LINKS; i++) { + wl1271_free_sta(wl, i); + wl1271_tx_reset_link_queues(wl, i); + wl->links[i].allocated_pkts = 0; + wl->links[i].prev_freed_pkts = 0; + } - wl1271_tx_reset_link_queues(wl, i); - wl->links[i].allocated_pkts = 0; - wl->links[i].prev_freed_pkts = 0; - } - wlvif->last_tx_hlid = 0; + wl->last_tx_hlid = 0; + } else { + for (i = 0; i < NUM_TX_QUEUES; i++) { + while ((skb = skb_dequeue(&wl->tx_queue[i]))) { + wl1271_debug(DEBUG_TX, "freeing skb 0x%p", + skb); + + if (!wl12xx_is_dummy_packet(wl, skb)) { + info = IEEE80211_SKB_CB(skb); + info->status.rates[0].idx = -1; + info->status.rates[0].count = 0; + ieee80211_tx_status_ni(wl->hw, skb); + } + } + } -} -/* caller must hold wl->mutex and TX must be stopped */ -void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues) -{ - int i; - struct sk_buff *skb; - struct ieee80211_tx_info *info; + wl->ba_rx_bitmap = 0; + } for (i = 0; i < NUM_TX_QUEUES; i++) wl->tx_queue_count[i] = 0; diff --git a/trunk/drivers/net/wireless/wl12xx/tx.h b/trunk/drivers/net/wireless/wl12xx/tx.h index 2dbb24e6d541..dc4f09adf088 100644 --- a/trunk/drivers/net/wireless/wl12xx/tx.h +++ b/trunk/drivers/net/wireless/wl12xx/tx.h @@ -206,23 +206,18 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl) void wl1271_tx_work(struct work_struct *work); void wl1271_tx_work_locked(struct wl1271 *wl); void wl1271_tx_complete(struct wl1271 *wl); -void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); -void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues); +void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues); void wl1271_tx_flush(struct wl1271 *wl); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set, enum ieee80211_band rate_band); u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set); -u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct sk_buff *skb); -u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, - struct sk_buff *skb); +u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb); void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); void wl1271_handle_tx_low_watermark(struct wl1271 *wl); bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); -void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids); /* from main.c */ -void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid); +void wl1271_free_sta(struct wl1271 *wl, u8 hlid); #endif diff --git a/trunk/drivers/net/wireless/wl12xx/wl12xx.h b/trunk/drivers/net/wireless/wl12xx/wl12xx.h index f1c911774bfd..1ec90fc7505e 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl12xx.h +++ b/trunk/drivers/net/wireless/wl12xx/wl12xx.h @@ -35,6 +35,9 @@ #include "conf.h" #include "ini.h" +#define DRIVER_NAME "wl1271" +#define DRIVER_PREFIX DRIVER_NAME ": " + /* * FW versions support BA 11n * versions marks x.x.x.50-60.x @@ -42,6 +45,73 @@ #define WL12XX_BA_SUPPORT_FW_COST_VER2_START 50 #define WL12XX_BA_SUPPORT_FW_COST_VER2_END 60 +enum { + DEBUG_NONE = 0, + DEBUG_IRQ = BIT(0), + DEBUG_SPI = BIT(1), + DEBUG_BOOT = BIT(2), + DEBUG_MAILBOX = BIT(3), + DEBUG_TESTMODE = BIT(4), + DEBUG_EVENT = BIT(5), + DEBUG_TX = BIT(6), + DEBUG_RX = BIT(7), + DEBUG_SCAN = BIT(8), + DEBUG_CRYPT = BIT(9), + DEBUG_PSM = BIT(10), + DEBUG_MAC80211 = BIT(11), + DEBUG_CMD = BIT(12), + DEBUG_ACX = BIT(13), + DEBUG_SDIO = BIT(14), + DEBUG_FILTERS = BIT(15), + DEBUG_ADHOC = BIT(16), + DEBUG_AP = BIT(17), + DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP), + DEBUG_ALL = ~0, +}; + +extern u32 wl12xx_debug_level; + +#define DEBUG_DUMP_LIMIT 1024 + +#define wl1271_error(fmt, arg...) \ + pr_err(DRIVER_PREFIX "ERROR " fmt "\n", ##arg) + +#define wl1271_warning(fmt, arg...) \ + pr_warning(DRIVER_PREFIX "WARNING " fmt "\n", ##arg) + +#define wl1271_notice(fmt, arg...) \ + pr_info(DRIVER_PREFIX fmt "\n", ##arg) + +#define wl1271_info(fmt, arg...) \ + pr_info(DRIVER_PREFIX fmt "\n", ##arg) + +#define wl1271_debug(level, fmt, arg...) \ + do { \ + if (level & wl12xx_debug_level) \ + pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \ + } while (0) + +/* TODO: use pr_debug_hex_dump when it will be available */ +#define wl1271_dump(level, prefix, buf, len) \ + do { \ + if (level & wl12xx_debug_level) \ + print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ + DUMP_PREFIX_OFFSET, 16, 1, \ + buf, \ + min_t(size_t, len, DEBUG_DUMP_LIMIT), \ + 0); \ + } while (0) + +#define wl1271_dump_ascii(level, prefix, buf, len) \ + do { \ + if (level & wl12xx_debug_level) \ + print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ + DUMP_PREFIX_OFFSET, 16, 1, \ + buf, \ + min_t(size_t, len, DEBUG_DUMP_LIMIT), \ + true); \ + } while (0) + #define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin" #define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin" @@ -72,11 +142,15 @@ #define WL12XX_INVALID_ROLE_ID 0xff #define WL12XX_INVALID_LINK_ID 0xff -#define WL12XX_MAX_RATE_POLICIES 16 - /* Defined by FW as 0. Will not be freed or allocated. */ #define WL12XX_SYSTEM_HLID 0 +/* + * TODO: we currently don't support multirole. remove + * this constant from the code when we do. + */ +#define WL1271_AP_STA_HLID_START 3 + /* * When in AP-mode, we allow (at least) this number of packets * to be transmitted to FW for a STA in PS-mode. Only when packets are @@ -162,6 +236,13 @@ struct wl1271_stats { #define AP_MAX_STATIONS 8 +/* Broadcast and Global links + system link + links to stations */ +/* + * TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all + * the places that use this. + */ +#define AP_MAX_LINKS (AP_MAX_STATIONS + WL1271_AP_STA_HLID_START) + /* FW status registers */ struct wl12xx_fw_status { __le32 intr; @@ -218,14 +299,17 @@ struct wl1271_scan { }; struct wl1271_if_operations { - void (*read)(struct device *child, int addr, void *buf, size_t len, + void (*read)(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed); - void (*write)(struct device *child, int addr, void *buf, size_t len, + void (*write)(struct wl1271 *wl, int addr, void *buf, size_t len, bool fixed); - void (*reset)(struct device *child); - void (*init)(struct device *child); - int (*power)(struct device *child, bool enable); - void (*set_block_size) (struct device *child, unsigned int blksz); + void (*reset)(struct wl1271 *wl); + void (*init)(struct wl1271 *wl); + int (*power)(struct wl1271 *wl, bool enable); + struct device* (*dev)(struct wl1271 *wl); + void (*enable_irq)(struct wl1271 *wl); + void (*disable_irq)(struct wl1271 *wl); + void (*set_block_size) (struct wl1271 *wl, unsigned int blksz); }; #define MAX_NUM_KEYS 14 @@ -242,33 +326,29 @@ struct wl1271_ap_key { }; enum wl12xx_flags { + WL1271_FLAG_STA_ASSOCIATED, + WL1271_FLAG_IBSS_JOINED, WL1271_FLAG_GPIO_POWER, WL1271_FLAG_TX_QUEUE_STOPPED, WL1271_FLAG_TX_PENDING, WL1271_FLAG_IN_ELP, WL1271_FLAG_ELP_REQUESTED, + WL1271_FLAG_PSM, + WL1271_FLAG_PSM_REQUESTED, WL1271_FLAG_IRQ_RUNNING, WL1271_FLAG_IDLE, + WL1271_FLAG_PSPOLL_FAILURE, + WL1271_FLAG_STA_STATE_SENT, WL1271_FLAG_FW_TX_BUSY, + WL1271_FLAG_AP_STARTED, + WL1271_FLAG_IF_INITIALIZED, WL1271_FLAG_DUMMY_PACKET_PENDING, WL1271_FLAG_SUSPENDED, WL1271_FLAG_PENDING_WORK, WL1271_FLAG_SOFT_GEMINI, + WL1271_FLAG_RX_STREAMING_STARTED, WL1271_FLAG_RECOVERY_IN_PROGRESS, -}; - -enum wl12xx_vif_flags { - WLVIF_FLAG_INITIALIZED, - WLVIF_FLAG_STA_ASSOCIATED, - WLVIF_FLAG_IBSS_JOINED, - WLVIF_FLAG_AP_STARTED, - WLVIF_FLAG_PSM, - WLVIF_FLAG_PSM_REQUESTED, - WLVIF_FLAG_STA_STATE_SENT, - WLVIF_FLAG_RX_STREAMING_STARTED, - WLVIF_FLAG_PSPOLL_FAILURE, - WLVIF_FLAG_CS_PROGRESS, - WLVIF_FLAG_AP_PROBE_RESP_SET, + WL1271_FLAG_CS_PROGRESS, }; struct wl1271_link { @@ -286,11 +366,10 @@ struct wl1271_link { }; struct wl1271 { + struct platform_device *plat_dev; struct ieee80211_hw *hw; bool mac80211_registered; - struct device *dev; - void *if_priv; struct wl1271_if_operations *if_ops; @@ -320,20 +399,25 @@ struct wl1271 { s8 hw_pg_ver; + u8 bssid[ETH_ALEN]; u8 mac_addr[ETH_ALEN]; + u8 bss_type; + u8 set_bss_type; + u8 p2p; /* we are using p2p role */ + u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; + u8 ssid_len; int channel; + u8 role_id; + u8 dev_role_id; u8 system_hlid; + u8 sta_hlid; + u8 dev_hlid; + u8 ap_global_hlid; + u8 ap_bcast_hlid; unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; - unsigned long rate_policies_map[ - BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)]; - - struct list_head wlvif_list; - - u8 sta_count; - u8 ap_count; struct wl1271_acx_mem_map *target_mem_map; @@ -356,7 +440,11 @@ struct wl1271 { /* Time-offset between host and chipset clocks */ s64 time_offset; + /* Session counter for the chipset */ + int session_counter; + /* Frames scheduled for transmission, not handled yet */ + struct sk_buff_head tx_queue[NUM_TX_QUEUES]; int tx_queue_count[NUM_TX_QUEUES]; long stopped_queues_map; @@ -374,6 +462,17 @@ struct wl1271 { struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS]; int tx_frames_cnt; + /* + * Security sequence number + * bits 0-15: lower 16 bits part of sequence number + * bits 16-47: higher 32 bits part of sequence number + * bits 48-63: not in use + */ + u64 tx_security_seq; + + /* 8 bits of the last sequence number in use */ + u8 tx_security_last_seq_lsb; + /* FW Rx counter */ u32 rx_counter; @@ -408,21 +507,59 @@ struct wl1271 { u32 mbox_ptr[2]; /* Are we currently scanning */ - struct ieee80211_vif *scan_vif; struct wl1271_scan scan; struct delayed_work scan_complete_work; bool sched_scanning; + /* probe-req template for the current AP */ + struct sk_buff *probereq; + + /* Our association ID */ + u16 aid; + + /* + * currently configured rate set: + * bits 0-15 - 802.11abg rates + * bits 16-23 - 802.11n MCS index mask + * support only 1 stream, thus only 8 bits for the MCS rates (0-7). + */ + u32 basic_rate_set; + u32 basic_rate; + u32 rate_set; + u32 bitrate_masks[IEEE80211_NUM_BANDS]; + /* The current band */ enum ieee80211_band band; + /* Beaconing interval (needed for ad-hoc) */ + u32 beacon_int; + + /* Default key (for WEP) */ + u32 default_key; + + /* Rx Streaming */ + struct work_struct rx_streaming_enable_work; + struct work_struct rx_streaming_disable_work; + struct timer_list rx_streaming_timer; + struct completion *elp_compl; + struct completion *ps_compl; struct delayed_work elp_work; + struct delayed_work pspoll_work; + + /* counter for ps-poll delivery failures */ + int ps_poll_failures; + + /* retry counter for PSM entries */ + u8 psm_entry_retry; /* in dBm */ int power_level; + int rssi_thold; + int last_rssi_event; + struct wl1271_stats stats; __le32 buffer_32; @@ -446,9 +583,20 @@ struct wl1271 { /* Most recently reported noise in dBm */ s8 noise; + /* map for HLIDs of associated stations - when operating in AP mode */ + unsigned long ap_hlid_map[BITS_TO_LONGS(AP_MAX_STATIONS)]; + + /* recoreded keys for AP-mode - set here before AP startup */ + struct wl1271_ap_key *recorded_ap_keys[MAX_NUM_KEYS]; + /* bands supported by this instance of wl12xx */ struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; + /* RX BA constraint value */ + bool ba_support; + u8 ba_rx_bitmap; + bool ba_allowed; + int tcxo_clock; /* @@ -462,7 +610,10 @@ struct wl1271 { * AP-mode - links indexed by HLID. The global and broadcast links * are always active. */ - struct wl1271_link links[WL12XX_MAX_LINKS]; + struct wl1271_link links[AP_MAX_LINKS]; + + /* the hlid of the link where the last transmitted skb came from */ + int last_tx_hlid; /* AP-mode - a bitmap of links currently in PS mode according to FW */ u32 ap_fw_ps_map; @@ -481,173 +632,21 @@ struct wl1271 { /* AP-mode - number of currently connected stations */ int active_sta_count; - - /* last wlvif we transmitted from */ - struct wl12xx_vif *last_wlvif; }; struct wl1271_station { u8 hlid; }; -struct wl12xx_vif { - struct wl1271 *wl; - struct list_head list; - unsigned long flags; - u8 bss_type; - u8 p2p; /* we are using p2p role */ - u8 role_id; - - /* sta/ibss specific */ - u8 dev_role_id; - u8 dev_hlid; - - union { - struct { - u8 hlid; - u8 ba_rx_bitmap; - - u8 basic_rate_idx; - u8 ap_rate_idx; - u8 p2p_rate_idx; - } sta; - struct { - u8 global_hlid; - u8 bcast_hlid; - - /* HLIDs bitmap of associated stations */ - unsigned long sta_hlid_map[BITS_TO_LONGS( - WL12XX_MAX_LINKS)]; - - /* recoreded keys - set here before AP startup */ - struct wl1271_ap_key *recorded_keys[MAX_NUM_KEYS]; - - u8 mgmt_rate_idx; - u8 bcast_rate_idx; - u8 ucast_rate_idx[CONF_TX_MAX_AC_COUNT]; - } ap; - }; - - /* the hlid of the last transmitted skb */ - int last_tx_hlid; - - unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)]; - - u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; - u8 ssid_len; - - /* The current band */ - enum ieee80211_band band; - int channel; - - u32 bitrate_masks[IEEE80211_NUM_BANDS]; - u32 basic_rate_set; - - /* - * currently configured rate set: - * bits 0-15 - 802.11abg rates - * bits 16-23 - 802.11n MCS index mask - * support only 1 stream, thus only 8 bits for the MCS rates (0-7). - */ - u32 basic_rate; - u32 rate_set; - - /* probe-req template for the current AP */ - struct sk_buff *probereq; - - /* Beaconing interval (needed for ad-hoc) */ - u32 beacon_int; - - /* Default key (for WEP) */ - u32 default_key; - - /* Our association ID */ - u16 aid; - - /* Session counter for the chipset */ - int session_counter; - - struct completion *ps_compl; - struct delayed_work pspoll_work; - - /* counter for ps-poll delivery failures */ - int ps_poll_failures; - - /* retry counter for PSM entries */ - u8 psm_entry_retry; - - /* in dBm */ - int power_level; - - int rssi_thold; - int last_rssi_event; - - /* RX BA constraint value */ - bool ba_support; - bool ba_allowed; - - /* Rx Streaming */ - struct work_struct rx_streaming_enable_work; - struct work_struct rx_streaming_disable_work; - struct timer_list rx_streaming_timer; - - /* - * This struct must be last! - * data that has to be saved acrossed reconfigs (e.g. recovery) - * should be declared in this struct. - */ - struct { - u8 persistent[0]; - /* - * Security sequence number - * bits 0-15: lower 16 bits part of sequence number - * bits 16-47: higher 32 bits part of sequence number - * bits 48-63: not in use - */ - u64 tx_security_seq; - - /* 8 bits of the last sequence number in use */ - u8 tx_security_last_seq_lsb; - }; -}; - -static inline struct wl12xx_vif *wl12xx_vif_to_data(struct ieee80211_vif *vif) -{ - return (struct wl12xx_vif *)vif->drv_priv; -} - -static inline -struct ieee80211_vif *wl12xx_wlvif_to_vif(struct wl12xx_vif *wlvif) -{ - return container_of((void *)wlvif, struct ieee80211_vif, drv_priv); -} - -#define wl12xx_for_each_wlvif(wl, wlvif) \ - list_for_each_entry(wlvif, &wl->wlvif_list, list) - -#define wl12xx_for_each_wlvif_continue(wl, wlvif) \ - list_for_each_entry_continue(wlvif, &wl->wlvif_list, list) - -#define wl12xx_for_each_wlvif_bss_type(wl, wlvif, _bss_type) \ - wl12xx_for_each_wlvif(wl, wlvif) \ - if (wlvif->bss_type == _bss_type) - -#define wl12xx_for_each_wlvif_sta(wl, wlvif) \ - wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_STA_BSS) - -#define wl12xx_for_each_wlvif_ap(wl, wlvif) \ - wl12xx_for_each_wlvif_bss_type(wl, wlvif, BSS_TYPE_AP_BSS) - int wl1271_plt_start(struct wl1271 *wl); int wl1271_plt_stop(struct wl1271 *wl); -int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif); +int wl1271_recalc_rx_streaming(struct wl1271 *wl); void wl12xx_queue_recovery_work(struct wl1271 *wl); size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); #define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ -#define SESSION_COUNTER_MAX 6 /* maximum value for the session counter */ -#define SESSION_COUNTER_INVALID 7 /* used with dummy_packet */ +#define SESSION_COUNTER_MAX 7 /* maximum value for the session counter */ #define WL1271_DEFAULT_POWER_LEVEL 0 @@ -670,8 +669,8 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); /* Each RX/TX transaction requires an end-of-transaction transfer */ #define WL12XX_QUIRK_END_OF_TRANSACTION BIT(0) -/* wl127x and SPI don't support SDIO block size alignment */ -#define WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT BIT(2) +/* WL128X requires aggregated packets to be aligned to the SDIO block size */ +#define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT BIT(2) /* Older firmwares did not implement the FW logger over bus feature */ #define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED BIT(4) diff --git a/trunk/drivers/net/wireless/wl12xx/wl12xx_80211.h b/trunk/drivers/net/wireless/wl12xx/wl12xx_80211.h index 8f0ffaf62309..f7971d3b0898 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ b/trunk/drivers/net/wireless/wl12xx/wl12xx_80211.h @@ -116,6 +116,11 @@ struct wl12xx_ps_poll_template { u8 ta[ETH_ALEN]; } __packed; +struct wl12xx_qos_null_data_template { + struct ieee80211_header header; + __le16 qos_ctl; +} __packed; + struct wl12xx_arp_rsp_template { struct ieee80211_hdr_3addr hdr; diff --git a/trunk/drivers/net/wireless/wl12xx/wl12xx_platform_data.c b/trunk/drivers/net/wireless/wl12xx/wl12xx_platform_data.c index 3c96b332184e..973b11060a8f 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl12xx_platform_data.c +++ b/trunk/drivers/net/wireless/wl12xx/wl12xx_platform_data.c @@ -2,7 +2,7 @@ #include #include -static struct wl12xx_platform_data *platform_data; +static const struct wl12xx_platform_data *platform_data; int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data) { @@ -18,7 +18,7 @@ int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data) return 0; } -struct wl12xx_platform_data *wl12xx_get_platform_data(void) +const struct wl12xx_platform_data *wl12xx_get_platform_data(void) { if (!platform_data) return ERR_PTR(-ENODEV); diff --git a/trunk/drivers/net/xen-netback/netback.c b/trunk/drivers/net/xen-netback/netback.c index 639cf8ab62ba..1ae270eed51a 100644 --- a/trunk/drivers/net/xen-netback/netback.c +++ b/trunk/drivers/net/xen-netback/netback.c @@ -395,7 +395,7 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, struct gnttab_copy *copy_gop; struct netbk_rx_meta *meta; /* - * These variables are used iff get_page_ext returns true, + * These variables a used iff get_page_ext returns true, * in which case they are guaranteed to be initialized. */ unsigned int uninitialized_var(group), uninitialized_var(idx); @@ -940,6 +940,8 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, if (!page) return NULL; + netbk->mmap_pages[pending_idx] = page; + gop->source.u.ref = txp->gref; gop->source.domid = vif->domid; gop->source.offset = txp->offset; @@ -1334,6 +1336,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) continue; } + netbk->mmap_pages[pending_idx] = page; + gop->source.u.ref = txreq.gref; gop->source.domid = vif->domid; gop->source.offset = txreq.offset; @@ -1664,7 +1668,7 @@ static int __init netback_init(void) "netback/%u", group); if (IS_ERR(netbk->task)) { - printk(KERN_ALERT "kthread_create() fails at netback\n"); + printk(KERN_ALERT "kthread_run() fails at netback\n"); del_timer(&netbk->net_timer); rc = PTR_ERR(netbk->task); goto failed_init; diff --git a/trunk/drivers/net/xen-netfront.c b/trunk/drivers/net/xen-netfront.c index 0a59c57864f5..4312db8cdeab 100644 --- a/trunk/drivers/net/xen-netfront.c +++ b/trunk/drivers/net/xen-netfront.c @@ -1709,6 +1709,7 @@ static void netback_changed(struct xenbus_device *dev, case XenbusStateInitialised: case XenbusStateReconfiguring: case XenbusStateReconfigured: + case XenbusStateConnected: case XenbusStateUnknown: case XenbusStateClosed: break; @@ -1719,9 +1720,6 @@ static void netback_changed(struct xenbus_device *dev, if (xennet_connect(netdev) != 0) break; xenbus_switch_state(dev, XenbusStateConnected); - break; - - case XenbusStateConnected: netif_notify_peers(netdev); break; diff --git a/trunk/drivers/nfc/pn533.c b/trunk/drivers/nfc/pn533.c index dbf214ef7321..7bcb1febef0d 100644 --- a/trunk/drivers/nfc/pn533.c +++ b/trunk/drivers/nfc/pn533.c @@ -1339,7 +1339,7 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, return 0; } -static int pn533_data_exchange(struct nfc_dev *nfc_dev, u32 target_idx, +int pn533_data_exchange(struct nfc_dev *nfc_dev, u32 target_idx, struct sk_buff *skb, data_exchange_cb_t cb, void *cb_context) diff --git a/trunk/drivers/oprofile/oprof.c b/trunk/drivers/oprofile/oprof.c index f8c752e408a6..dccd8636095c 100644 --- a/trunk/drivers/oprofile/oprof.c +++ b/trunk/drivers/oprofile/oprof.c @@ -239,45 +239,26 @@ int oprofile_set_ulong(unsigned long *addr, unsigned long val) return err; } -static int timer_mode; - static int __init oprofile_init(void) { int err; - /* always init architecture to setup backtrace support */ err = oprofile_arch_init(&oprofile_ops); - - timer_mode = err || timer; /* fall back to timer mode on errors */ - if (timer_mode) { - if (!err) - oprofile_arch_exit(); + if (err < 0 || timer) { + printk(KERN_INFO "oprofile: using timer interrupt.\n"); err = oprofile_timer_init(&oprofile_ops); if (err) return err; } - - err = oprofilefs_register(); - if (!err) - return 0; - - /* failed */ - if (timer_mode) - oprofile_timer_exit(); - else - oprofile_arch_exit(); - - return err; + return oprofilefs_register(); } static void __exit oprofile_exit(void) { + oprofile_timer_exit(); oprofilefs_unregister(); - if (timer_mode) - oprofile_timer_exit(); - else - oprofile_arch_exit(); + oprofile_arch_exit(); } diff --git a/trunk/drivers/oprofile/timer_int.c b/trunk/drivers/oprofile/timer_int.c index 878fba126582..3ef44624f510 100644 --- a/trunk/drivers/oprofile/timer_int.c +++ b/trunk/drivers/oprofile/timer_int.c @@ -110,7 +110,6 @@ int oprofile_timer_init(struct oprofile_operations *ops) ops->start = oprofile_hrtimer_start; ops->stop = oprofile_hrtimer_stop; ops->cpu_type = "timer"; - printk(KERN_INFO "oprofile: using timer interrupt.\n"); return 0; } diff --git a/trunk/drivers/platform/x86/toshiba_acpi.c b/trunk/drivers/platform/x86/toshiba_acpi.c index dcdc1f4a4624..13ef8c37471d 100644 --- a/trunk/drivers/platform/x86/toshiba_acpi.c +++ b/trunk/drivers/platform/x86/toshiba_acpi.c @@ -121,7 +121,6 @@ struct toshiba_acpi_dev { int illumination_supported:1; int video_supported:1; int fan_supported:1; - int system_event_supported:1; struct mutex mutex; }; @@ -725,7 +724,7 @@ static int keys_proc_show(struct seq_file *m, void *v) u32 hci_result; u32 value; - if (!dev->key_event_valid && dev->system_event_supported) { + if (!dev->key_event_valid) { hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result); if (hci_result == HCI_SUCCESS) { dev->key_event_valid = 1; @@ -965,8 +964,6 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev) /* enable event fifo */ hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); - if (hci_result == HCI_SUCCESS) - dev->system_event_supported = 1; props.type = BACKLIGHT_PLATFORM; props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1; @@ -1035,15 +1032,12 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) { struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); u32 hci_result, value; - int retries = 3; - if (!dev->system_event_supported || event != 0x80) + if (event != 0x80) return; - do { hci_read1(dev, HCI_SYSTEM_EVENT, &value, &hci_result); - switch (hci_result) { - case HCI_SUCCESS: + if (hci_result == HCI_SUCCESS) { if (value == 0x100) continue; /* act on key press; ignore key release */ @@ -1055,19 +1049,14 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) pr_info("Unknown key %x\n", value); } - break; - case HCI_NOT_SUPPORTED: + } else if (hci_result == HCI_NOT_SUPPORTED) { /* This is a workaround for an unresolved issue on * some machines where system events sporadically * become disabled. */ hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result); pr_notice("Re-enabled hotkeys\n"); - /* fall through */ - default: - retries--; - break; } - } while (retries && hci_result != HCI_EMPTY); + } while (hci_result != HCI_EMPTY); } diff --git a/trunk/drivers/power/intel_mid_battery.c b/trunk/drivers/power/intel_mid_battery.c index 01fa671ec97f..cffcb7c00b00 100644 --- a/trunk/drivers/power/intel_mid_battery.c +++ b/trunk/drivers/power/intel_mid_battery.c @@ -61,8 +61,7 @@ MODULE_PARM_DESC(debug, "Flag to enable PMIC Battery debug messages."); #define PMIC_BATT_CHR_SBATDET_MASK (1 << 5) #define PMIC_BATT_CHR_SDCLMT_MASK (1 << 6) #define PMIC_BATT_CHR_SUSBOVP_MASK (1 << 7) -#define PMIC_BATT_CHR_EXCPT_MASK 0x86 - +#define PMIC_BATT_CHR_EXCPT_MASK 0xC6 #define PMIC_BATT_ADC_ACCCHRG_MASK (1 << 31) #define PMIC_BATT_ADC_ACCCHRGVAL_MASK 0x7FFFFFFF @@ -305,6 +304,11 @@ static void pmic_battery_read_status(struct pmic_power_module_info *pbi) pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; pmic_battery_log_event(BATT_EVENT_BATOVP_EXCPT); batt_exception = 1; + } else if (r8 & PMIC_BATT_CHR_SDCLMT_MASK) { + pbi->batt_health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; + pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; + pmic_battery_log_event(BATT_EVENT_DCLMT_EXCPT); + batt_exception = 1; } else if (r8 & PMIC_BATT_CHR_STEMP_MASK) { pbi->batt_health = POWER_SUPPLY_HEALTH_OVERHEAT; pbi->batt_status = POWER_SUPPLY_STATUS_NOT_CHARGING; @@ -312,10 +316,6 @@ static void pmic_battery_read_status(struct pmic_power_module_info *pbi) batt_exception = 1; } else { pbi->batt_health = POWER_SUPPLY_HEALTH_GOOD; - if (r8 & PMIC_BATT_CHR_SDCLMT_MASK) { - /* PMIC will change charging current automatically */ - pmic_battery_log_event(BATT_EVENT_DCLMT_EXCPT); - } } } diff --git a/trunk/drivers/rtc/class.c b/trunk/drivers/rtc/class.c index dc4c2748bbc3..e8326f26fa2f 100644 --- a/trunk/drivers/rtc/class.c +++ b/trunk/drivers/rtc/class.c @@ -63,7 +63,7 @@ static int rtc_suspend(struct device *dev, pm_message_t mesg) */ delta = timespec_sub(old_system, old_rtc); delta_delta = timespec_sub(delta, old_delta); - if (delta_delta.tv_sec < -2 || delta_delta.tv_sec >= 2) { + if (abs(delta_delta.tv_sec) >= 2) { /* * if delta_delta is too large, assume time correction * has occured and set old_delta to the current delta. @@ -97,8 +97,9 @@ static int rtc_resume(struct device *dev) rtc_tm_to_time(&tm, &new_rtc.tv_sec); new_rtc.tv_nsec = 0; - if (new_rtc.tv_sec < old_rtc.tv_sec) { - pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); + if (new_rtc.tv_sec <= old_rtc.tv_sec) { + if (new_rtc.tv_sec < old_rtc.tv_sec) + pr_debug("%s: time travel!\n", dev_name(&rtc->dev)); return 0; } @@ -115,8 +116,7 @@ static int rtc_resume(struct device *dev) sleep_time = timespec_sub(sleep_time, timespec_sub(new_system, old_system)); - if (sleep_time.tv_sec >= 0) - timekeeping_inject_sleeptime(&sleep_time); + timekeeping_inject_sleeptime(&sleep_time); return 0; } diff --git a/trunk/drivers/rtc/interface.c b/trunk/drivers/rtc/interface.c index fa4d9f324189..8e286259a007 100644 --- a/trunk/drivers/rtc/interface.c +++ b/trunk/drivers/rtc/interface.c @@ -319,20 +319,6 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) } EXPORT_SYMBOL_GPL(rtc_read_alarm); -static int ___rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) -{ - int err; - - if (!rtc->ops) - err = -ENODEV; - else if (!rtc->ops->set_alarm) - err = -EINVAL; - else - err = rtc->ops->set_alarm(rtc->dev.parent, alarm); - - return err; -} - static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { struct rtc_time tm; @@ -356,7 +342,14 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) * over right here, before we set the alarm. */ - return ___rtc_set_alarm(rtc, alarm); + if (!rtc->ops) + err = -ENODEV; + else if (!rtc->ops->set_alarm) + err = -EINVAL; + else + err = rtc->ops->set_alarm(rtc->dev.parent, alarm); + + return err; } int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) @@ -770,20 +763,6 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) return 0; } -static void rtc_alarm_disable(struct rtc_device *rtc) -{ - struct rtc_wkalrm alarm; - struct rtc_time tm; - - __rtc_read_time(rtc, &tm); - - alarm.time = rtc_ktime_to_tm(ktime_add(rtc_tm_to_ktime(tm), - ktime_set(300, 0))); - alarm.enabled = 0; - - ___rtc_set_alarm(rtc, &alarm); -} - /** * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue * @rtc rtc device @@ -805,10 +784,8 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) struct rtc_wkalrm alarm; int err; next = timerqueue_getnext(&rtc->timerqueue); - if (!next) { - rtc_alarm_disable(rtc); + if (!next) return; - } alarm.time = rtc_ktime_to_tm(next->expires); alarm.enabled = 1; err = __rtc_set_alarm(rtc, &alarm); @@ -870,8 +847,7 @@ void rtc_timer_do_work(struct work_struct *work) err = __rtc_set_alarm(rtc, &alarm); if (err == -ETIME) goto again; - } else - rtc_alarm_disable(rtc); + } mutex_unlock(&rtc->ops_lock); } diff --git a/trunk/drivers/s390/cio/chsc.c b/trunk/drivers/s390/cio/chsc.c index a84631a7391d..75c3f1f8fd43 100644 --- a/trunk/drivers/s390/cio/chsc.c +++ b/trunk/drivers/s390/cio/chsc.c @@ -529,7 +529,10 @@ __s390_vary_chpid_on(struct subchannel_id schid, void *data) int chsc_chp_vary(struct chp_id chpid, int on) { struct channel_path *chp = chpid_to_chp(chpid); + struct chp_link link; + memset(&link, 0, sizeof(struct chp_link)); + link.chpid = chpid; /* Wait until previous actions have settled. */ css_wait_for_slow_path(); /* @@ -539,10 +542,10 @@ int chsc_chp_vary(struct chp_id chpid, int on) /* Try to update the channel path descritor. */ chsc_determine_base_channel_path_desc(chpid, &chp->desc); for_each_subchannel_staged(s390_subchannel_vary_chpid_on, - __s390_vary_chpid_on, &chpid); + __s390_vary_chpid_on, &link); } else for_each_subchannel_staged(s390_subchannel_vary_chpid_off, - NULL, &chpid); + NULL, &link); return 0; } diff --git a/trunk/drivers/s390/cio/cio.h b/trunk/drivers/s390/cio/cio.h index 4a1ff5c2eb88..155a82bcb9e5 100644 --- a/trunk/drivers/s390/cio/cio.h +++ b/trunk/drivers/s390/cio/cio.h @@ -68,13 +68,8 @@ struct schib { __u8 mda[4]; /* model dependent area */ } __attribute__ ((packed,aligned(4))); -/* - * When rescheduled, todo's with higher values will overwrite those - * with lower values. - */ enum sch_todo { SCH_TODO_NOTHING, - SCH_TODO_EVAL, SCH_TODO_UNREG, }; diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index 21908e67bf67..92d7324acb1c 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -195,6 +195,51 @@ void css_sch_device_unregister(struct subchannel *sch) } EXPORT_SYMBOL_GPL(css_sch_device_unregister); +static void css_sch_todo(struct work_struct *work) +{ + struct subchannel *sch; + enum sch_todo todo; + + sch = container_of(work, struct subchannel, todo_work); + /* Find out todo. */ + spin_lock_irq(sch->lock); + todo = sch->todo; + CIO_MSG_EVENT(4, "sch_todo: sch=0.%x.%04x, todo=%d\n", sch->schid.ssid, + sch->schid.sch_no, todo); + sch->todo = SCH_TODO_NOTHING; + spin_unlock_irq(sch->lock); + /* Perform todo. */ + if (todo == SCH_TODO_UNREG) + css_sch_device_unregister(sch); + /* Release workqueue ref. */ + put_device(&sch->dev); +} + +/** + * css_sched_sch_todo - schedule a subchannel operation + * @sch: subchannel + * @todo: todo + * + * Schedule the operation identified by @todo to be performed on the slow path + * workqueue. Do nothing if another operation with higher priority is already + * scheduled. Needs to be called with subchannel lock held. + */ +void css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo) +{ + CIO_MSG_EVENT(4, "sch_todo: sched sch=0.%x.%04x todo=%d\n", + sch->schid.ssid, sch->schid.sch_no, todo); + if (sch->todo >= todo) + return; + /* Get workqueue ref. */ + if (!get_device(&sch->dev)) + return; + sch->todo = todo; + if (!queue_work(cio_work_q, &sch->todo_work)) { + /* Already queued, release workqueue ref. */ + put_device(&sch->dev); + } +} + static void ssd_from_pmcw(struct chsc_ssd_info *ssd, struct pmcw *pmcw) { int i; @@ -421,65 +466,6 @@ static void css_evaluate_subchannel(struct subchannel_id schid, int slow) css_schedule_eval(schid); } -/** - * css_sched_sch_todo - schedule a subchannel operation - * @sch: subchannel - * @todo: todo - * - * Schedule the operation identified by @todo to be performed on the slow path - * workqueue. Do nothing if another operation with higher priority is already - * scheduled. Needs to be called with subchannel lock held. - */ -void css_sched_sch_todo(struct subchannel *sch, enum sch_todo todo) -{ - CIO_MSG_EVENT(4, "sch_todo: sched sch=0.%x.%04x todo=%d\n", - sch->schid.ssid, sch->schid.sch_no, todo); - if (sch->todo >= todo) - return; - /* Get workqueue ref. */ - if (!get_device(&sch->dev)) - return; - sch->todo = todo; - if (!queue_work(cio_work_q, &sch->todo_work)) { - /* Already queued, release workqueue ref. */ - put_device(&sch->dev); - } -} - -static void css_sch_todo(struct work_struct *work) -{ - struct subchannel *sch; - enum sch_todo todo; - int ret; - - sch = container_of(work, struct subchannel, todo_work); - /* Find out todo. */ - spin_lock_irq(sch->lock); - todo = sch->todo; - CIO_MSG_EVENT(4, "sch_todo: sch=0.%x.%04x, todo=%d\n", sch->schid.ssid, - sch->schid.sch_no, todo); - sch->todo = SCH_TODO_NOTHING; - spin_unlock_irq(sch->lock); - /* Perform todo. */ - switch (todo) { - case SCH_TODO_NOTHING: - break; - case SCH_TODO_EVAL: - ret = css_evaluate_known_subchannel(sch, 1); - if (ret == -EAGAIN) { - spin_lock_irq(sch->lock); - css_sched_sch_todo(sch, todo); - spin_unlock_irq(sch->lock); - } - break; - case SCH_TODO_UNREG: - css_sch_device_unregister(sch); - break; - } - /* Release workqueue ref. */ - put_device(&sch->dev); -} - static struct idset *slow_subchannel_set; static spinlock_t slow_subchannel_lock; static wait_queue_head_t css_eval_wq; diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index 47269858ecb6..d734f4a0ecac 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -1868,9 +1868,9 @@ static void __ccw_device_pm_restore(struct ccw_device *cdev) */ cdev->private->flags.resuming = 1; cdev->private->path_new_mask = LPM_ANYPATH; - css_sched_sch_todo(sch, SCH_TODO_EVAL); + css_schedule_eval(sch->schid); spin_unlock_irq(sch->lock); - css_wait_for_slow_path(); + css_complete_work(); /* cdev may have been moved to a different subchannel. */ sch = to_subchannel(cdev->dev.parent); diff --git a/trunk/drivers/s390/cio/device_fsm.c b/trunk/drivers/s390/cio/device_fsm.c index 1b853513c891..52c233fa2b12 100644 --- a/trunk/drivers/s390/cio/device_fsm.c +++ b/trunk/drivers/s390/cio/device_fsm.c @@ -496,26 +496,8 @@ static void ccw_device_reset_path_events(struct ccw_device *cdev) cdev->private->pgid_reset_mask = 0; } -static void create_fake_irb(struct irb *irb, int type) -{ - memset(irb, 0, sizeof(*irb)); - if (type == FAKE_CMD_IRB) { - struct cmd_scsw *scsw = &irb->scsw.cmd; - scsw->cc = 1; - scsw->fctl = SCSW_FCTL_START_FUNC; - scsw->actl = SCSW_ACTL_START_PEND; - scsw->stctl = SCSW_STCTL_STATUS_PEND; - } else if (type == FAKE_TM_IRB) { - struct tm_scsw *scsw = &irb->scsw.tm; - scsw->x = 1; - scsw->cc = 1; - scsw->fctl = SCSW_FCTL_START_FUNC; - scsw->actl = SCSW_ACTL_START_PEND; - scsw->stctl = SCSW_STCTL_STATUS_PEND; - } -} - -void ccw_device_verify_done(struct ccw_device *cdev, int err) +void +ccw_device_verify_done(struct ccw_device *cdev, int err) { struct subchannel *sch; @@ -538,8 +520,12 @@ void ccw_device_verify_done(struct ccw_device *cdev, int err) ccw_device_done(cdev, DEV_STATE_ONLINE); /* Deliver fake irb to device driver, if needed. */ if (cdev->private->flags.fake_irb) { - create_fake_irb(&cdev->private->irb, - cdev->private->flags.fake_irb); + memset(&cdev->private->irb, 0, sizeof(struct irb)); + cdev->private->irb.scsw.cmd.cc = 1; + cdev->private->irb.scsw.cmd.fctl = SCSW_FCTL_START_FUNC; + cdev->private->irb.scsw.cmd.actl = SCSW_ACTL_START_PEND; + cdev->private->irb.scsw.cmd.stctl = + SCSW_STCTL_STATUS_PEND; cdev->private->flags.fake_irb = 0; if (cdev->handler) cdev->handler(cdev, cdev->private->intparm, diff --git a/trunk/drivers/s390/cio/device_ops.c b/trunk/drivers/s390/cio/device_ops.c index ec7fb6d3b479..f98698d5735e 100644 --- a/trunk/drivers/s390/cio/device_ops.c +++ b/trunk/drivers/s390/cio/device_ops.c @@ -198,7 +198,7 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, if (cdev->private->state == DEV_STATE_VERIFY) { /* Remember to fake irb when finished. */ if (!cdev->private->flags.fake_irb) { - cdev->private->flags.fake_irb = FAKE_CMD_IRB; + cdev->private->flags.fake_irb = 1; cdev->private->intparm = intparm; return 0; } else @@ -213,9 +213,9 @@ int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, ret = cio_set_options (sch, flags); if (ret) return ret; - /* Adjust requested path mask to exclude unusable paths. */ + /* Adjust requested path mask to excluded varied off paths. */ if (lpm) { - lpm &= sch->lpm; + lpm &= sch->opm; if (lpm == 0) return -EACCES; } @@ -605,21 +605,11 @@ int ccw_device_tm_start_key(struct ccw_device *cdev, struct tcw *tcw, sch = to_subchannel(cdev->dev.parent); if (!sch->schib.pmcw.ena) return -EINVAL; - if (cdev->private->state == DEV_STATE_VERIFY) { - /* Remember to fake irb when finished. */ - if (!cdev->private->flags.fake_irb) { - cdev->private->flags.fake_irb = FAKE_TM_IRB; - cdev->private->intparm = intparm; - return 0; - } else - /* There's already a fake I/O around. */ - return -EBUSY; - } if (cdev->private->state != DEV_STATE_ONLINE) return -EIO; - /* Adjust requested path mask to exclude unusable paths. */ + /* Adjust requested path mask to excluded varied off paths. */ if (lpm) { - lpm &= sch->lpm; + lpm &= sch->opm; if (lpm == 0) return -EACCES; } diff --git a/trunk/drivers/s390/cio/io_sch.h b/trunk/drivers/s390/cio/io_sch.h index 76253dfcc1be..2ebb492a5c17 100644 --- a/trunk/drivers/s390/cio/io_sch.h +++ b/trunk/drivers/s390/cio/io_sch.h @@ -111,9 +111,6 @@ enum cdev_todo { CDEV_TODO_UNREG_EVAL, }; -#define FAKE_CMD_IRB 1 -#define FAKE_TM_IRB 2 - struct ccw_device_private { struct ccw_device *cdev; struct subchannel *sch; @@ -141,7 +138,7 @@ struct ccw_device_private { unsigned int doverify:1; /* delayed path verification */ unsigned int donotify:1; /* call notify function */ unsigned int recog_done:1; /* dev. recog. complete */ - unsigned int fake_irb:2; /* deliver faked irb */ + unsigned int fake_irb:1; /* deliver faked irb */ unsigned int resuming:1; /* recognition while resume */ unsigned int pgroup:1; /* pathgroup is set up */ unsigned int mpath:1; /* multipathing is set up */ diff --git a/trunk/drivers/s390/crypto/ap_bus.c b/trunk/drivers/s390/crypto/ap_bus.c index 96bbe9d12a79..ec94f049e995 100644 --- a/trunk/drivers/s390/crypto/ap_bus.c +++ b/trunk/drivers/s390/crypto/ap_bus.c @@ -1552,8 +1552,6 @@ static void ap_reset(struct ap_device *ap_dev) rc = ap_init_queue(ap_dev->qid); if (rc == -ENODEV) ap_dev->unregistered = 1; - else - __ap_schedule_poll_timer(); } static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags) diff --git a/trunk/drivers/s390/net/qeth_l2_main.c b/trunk/drivers/s390/net/qeth_l2_main.c index c4e2004bd0e8..a21ae3d549db 100644 --- a/trunk/drivers/s390/net/qeth_l2_main.c +++ b/trunk/drivers/s390/net/qeth_l2_main.c @@ -301,21 +301,21 @@ static void qeth_l2_process_vlans(struct qeth_card *card) spin_unlock_bh(&card->vlanlock); } -static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) +static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { struct qeth_card *card = dev->ml_priv; struct qeth_vlan_vid *id; QETH_CARD_TEXT_(card, 4, "aid:%d", vid); if (!vid) - return 0; + return; if (card->info.type == QETH_CARD_TYPE_OSM) { QETH_CARD_TEXT(card, 3, "aidOSM"); - return 0; + return; } if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { QETH_CARD_TEXT(card, 3, "aidREC"); - return 0; + return; } id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC); if (id) { @@ -324,13 +324,10 @@ static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) spin_lock_bh(&card->vlanlock); list_add_tail(&id->list, &card->vid_list); spin_unlock_bh(&card->vlanlock); - } else { - return -ENOMEM; } - return 0; } -static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +static void qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct qeth_vlan_vid *id, *tmpid = NULL; struct qeth_card *card = dev->ml_priv; @@ -338,11 +335,11 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) QETH_CARD_TEXT_(card, 4, "kid:%d", vid); if (card->info.type == QETH_CARD_TYPE_OSM) { QETH_CARD_TEXT(card, 3, "kidOSM"); - return 0; + return; } if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { QETH_CARD_TEXT(card, 3, "kidREC"); - return 0; + return; } spin_lock_bh(&card->vlanlock); list_for_each_entry(id, &card->vid_list, list) { @@ -358,7 +355,6 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) kfree(tmpid); } qeth_l2_set_multicast_list(card->dev); - return 0; } static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) diff --git a/trunk/drivers/s390/net/qeth_l3_main.c b/trunk/drivers/s390/net/qeth_l3_main.c index b3b045c21e2c..b2a55e3fde0b 100644 --- a/trunk/drivers/s390/net/qeth_l3_main.c +++ b/trunk/drivers/s390/net/qeth_l3_main.c @@ -1869,15 +1869,15 @@ static void qeth_l3_free_vlan_addresses(struct qeth_card *card, qeth_l3_free_vlan_addresses6(card, vid); } -static int qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) +static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { struct qeth_card *card = dev->ml_priv; set_bit(vid, card->active_vlans); - return 0; + return; } -static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) { struct qeth_card *card = dev->ml_priv; unsigned long flags; @@ -1885,7 +1885,7 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) QETH_CARD_TEXT_(card, 4, "kid:%d", vid); if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { QETH_CARD_TEXT(card, 3, "kidREC"); - return 0; + return; } spin_lock_irqsave(&card->vlanlock, flags); /* unregister IP addresses of vlan device */ @@ -1893,7 +1893,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) clear_bit(vid, card->active_vlans); spin_unlock_irqrestore(&card->vlanlock, flags); qeth_l3_set_multicast_list(card->dev); - return 0; } static inline int qeth_l3_rebuild_skb(struct qeth_card *card, diff --git a/trunk/drivers/ssb/driver_pcicore.c b/trunk/drivers/ssb/driver_pcicore.c index 520e8286db28..84c934c0a545 100644 --- a/trunk/drivers/ssb/driver_pcicore.c +++ b/trunk/drivers/ssb/driver_pcicore.c @@ -517,14 +517,10 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc) static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc) { - struct ssb_device *pdev = pc->dev; - struct ssb_bus *bus = pdev->bus; - - if (bus->bustype == SSB_BUSTYPE_PCI) - ssb_pcicore_fix_sprom_core_index(pc); + ssb_pcicore_fix_sprom_core_index(pc); /* Disable PCI interrupts. */ - ssb_write32(pdev, SSB_INTVEC, 0); + ssb_write32(pc->dev, SSB_INTVEC, 0); /* Additional PCIe always once-executed workarounds */ if (pc->dev->id.coreid == SSB_DEV_PCIE) { diff --git a/trunk/drivers/staging/comedi/comedi_fops.c b/trunk/drivers/staging/comedi/comedi_fops.c index 5e78c77d5a08..21d8c1c16cd8 100644 --- a/trunk/drivers/staging/comedi/comedi_fops.c +++ b/trunk/drivers/staging/comedi/comedi_fops.c @@ -671,7 +671,7 @@ static int do_insnlist_ioctl(struct comedi_device *dev, } insns = - kcalloc(insnlist.n_insns, sizeof(struct comedi_insn), GFP_KERNEL); + kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL); if (!insns) { DPRINTK("kmalloc failed\n"); ret = -ENOMEM; @@ -1432,21 +1432,7 @@ static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return ret; } - -static void comedi_vm_open(struct vm_area_struct *area) -{ - struct comedi_async *async; - struct comedi_device *dev; - - async = area->vm_private_data; - dev = async->subdevice->device; - - mutex_lock(&dev->mutex); - async->mmap_count++; - mutex_unlock(&dev->mutex); -} - -static void comedi_vm_close(struct vm_area_struct *area) +static void comedi_unmap(struct vm_area_struct *area) { struct comedi_async *async; struct comedi_device *dev; @@ -1460,13 +1446,15 @@ static void comedi_vm_close(struct vm_area_struct *area) } static struct vm_operations_struct comedi_vm_ops = { - .open = comedi_vm_open, - .close = comedi_vm_close, + .close = comedi_unmap, }; static int comedi_mmap(struct file *file, struct vm_area_struct *vma) { const unsigned minor = iminor(file->f_dentry->d_inode); + struct comedi_device_file_info *dev_file_info = + comedi_get_device_file_info(minor); + struct comedi_device *dev = dev_file_info->device; struct comedi_async *async = NULL; unsigned long start = vma->vm_start; unsigned long size; @@ -1474,15 +1462,6 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) int i; int retval; struct comedi_subdevice *s; - struct comedi_device_file_info *dev_file_info; - struct comedi_device *dev; - - dev_file_info = comedi_get_device_file_info(minor); - if (dev_file_info == NULL) - return -ENODEV; - dev = dev_file_info->device; - if (dev == NULL) - return -ENODEV; mutex_lock(&dev->mutex); if (!dev->attached) { @@ -1549,17 +1528,11 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait) { unsigned int mask = 0; const unsigned minor = iminor(file->f_dentry->d_inode); + struct comedi_device_file_info *dev_file_info = + comedi_get_device_file_info(minor); + struct comedi_device *dev = dev_file_info->device; struct comedi_subdevice *read_subdev; struct comedi_subdevice *write_subdev; - struct comedi_device_file_info *dev_file_info; - struct comedi_device *dev; - dev_file_info = comedi_get_device_file_info(minor); - - if (dev_file_info == NULL) - return -ENODEV; - dev = dev_file_info->device; - if (dev == NULL) - return -ENODEV; mutex_lock(&dev->mutex); if (!dev->attached) { @@ -1605,15 +1578,9 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info; - struct comedi_device *dev; - dev_file_info = comedi_get_device_file_info(minor); - - if (dev_file_info == NULL) - return -ENODEV; - dev = dev_file_info->device; - if (dev == NULL) - return -ENODEV; + struct comedi_device_file_info *dev_file_info = + comedi_get_device_file_info(minor); + struct comedi_device *dev = dev_file_info->device; if (!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); @@ -1673,11 +1640,11 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, retval = -EAGAIN; break; } - schedule(); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } + schedule(); if (!s->busy) break; if (s->busy != file) { @@ -1716,15 +1683,9 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, int n, m, count = 0, retval = 0; DECLARE_WAITQUEUE(wait, current); const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info; - struct comedi_device *dev; - dev_file_info = comedi_get_device_file_info(minor); - - if (dev_file_info == NULL) - return -ENODEV; - dev = dev_file_info->device; - if (dev == NULL) - return -ENODEV; + struct comedi_device_file_info *dev_file_info = + comedi_get_device_file_info(minor); + struct comedi_device *dev = dev_file_info->device; if (!dev->attached) { DPRINTK("no driver configured on comedi%i\n", dev->minor); @@ -1780,11 +1741,11 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, retval = -EAGAIN; break; } - schedule(); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } + schedule(); if (!s->busy) { retval = 0; break; @@ -1924,17 +1885,11 @@ static int comedi_open(struct inode *inode, struct file *file) static int comedi_close(struct inode *inode, struct file *file) { const unsigned minor = iminor(inode); + struct comedi_device_file_info *dev_file_info = + comedi_get_device_file_info(minor); + struct comedi_device *dev = dev_file_info->device; struct comedi_subdevice *s = NULL; int i; - struct comedi_device_file_info *dev_file_info; - struct comedi_device *dev; - dev_file_info = comedi_get_device_file_info(minor); - - if (dev_file_info == NULL) - return -ENODEV; - dev = dev_file_info->device; - if (dev == NULL) - return -ENODEV; mutex_lock(&dev->mutex); @@ -1968,15 +1923,10 @@ static int comedi_close(struct inode *inode, struct file *file) static int comedi_fasync(int fd, struct file *file, int on) { const unsigned minor = iminor(file->f_dentry->d_inode); - struct comedi_device_file_info *dev_file_info; - struct comedi_device *dev; - dev_file_info = comedi_get_device_file_info(minor); + struct comedi_device_file_info *dev_file_info = + comedi_get_device_file_info(minor); - if (dev_file_info == NULL) - return -ENODEV; - dev = dev_file_info->device; - if (dev == NULL) - return -ENODEV; + struct comedi_device *dev = dev_file_info->device; return fasync_helper(fd, file, on, &dev->async_queue); } diff --git a/trunk/drivers/staging/comedi/drivers/usbduxsigma.c b/trunk/drivers/staging/comedi/drivers/usbduxsigma.c index 6144afb8cbaa..a8fea9a91733 100644 --- a/trunk/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/trunk/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1,4 +1,4 @@ -#define DRIVER_VERSION "v0.6" +#define DRIVER_VERSION "v0.5" #define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" #define DRIVER_DESC "Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com" /* @@ -25,7 +25,7 @@ Driver: usbduxsigma Description: University of Stirling USB DAQ & INCITE Technology Limited Devices: [ITL] USB-DUX (usbduxsigma.o) Author: Bernd Porr -Updated: 8 Nov 2011 +Updated: 21 Jul 2011 Status: testing */ /* @@ -44,7 +44,6 @@ Status: testing * 0.3: proper vendor ID and driver name * 0.4: fixed D/A voltage range * 0.5: various bug fixes, health check at startup - * 0.6: corrected wrong input range */ /* generates loads of debug info */ @@ -176,7 +175,7 @@ Status: testing /* comedi constants */ static const struct comedi_lrange range_usbdux_ai_range = { 1, { BIP_RANGE - (2.65/2.0) + (2.65) } }; diff --git a/trunk/drivers/staging/rts_pstor/rtsx.c b/trunk/drivers/staging/rts_pstor/rtsx.c index 115635f95024..480b0ed2e4de 100644 --- a/trunk/drivers/staging/rts_pstor/rtsx.c +++ b/trunk/drivers/staging/rts_pstor/rtsx.c @@ -1021,7 +1021,6 @@ static int __devinit rtsx_probe(struct pci_dev *pci, th = kthread_create(rtsx_scan_thread, dev, "rtsx-scan"); if (IS_ERR(th)) { printk(KERN_ERR "Unable to start the device-scanning thread\n"); - complete(&dev->scanning_done); quiesce_and_remove_host(dev); err = PTR_ERR(th); goto errout; diff --git a/trunk/drivers/staging/usbip/vhci_rx.c b/trunk/drivers/staging/usbip/vhci_rx.c index 3872b8cccdcf..09c44abb89e8 100644 --- a/trunk/drivers/staging/usbip/vhci_rx.c +++ b/trunk/drivers/staging/usbip/vhci_rx.c @@ -68,7 +68,6 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, { struct usbip_device *ud = &vdev->ud; struct urb *urb; - unsigned long flags; spin_lock(&vdev->priv_lock); urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); @@ -102,9 +101,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, usbip_dbg_vhci_rx("now giveback urb %p\n", urb); - spin_lock_irqsave(&the_controller->lock, flags); + spin_lock(&the_controller->lock); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock_irqrestore(&the_controller->lock, flags); + spin_unlock(&the_controller->lock); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); @@ -142,7 +141,6 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, { struct vhci_unlink *unlink; struct urb *urb; - unsigned long flags; usbip_dump_header(pdu); @@ -172,9 +170,9 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, urb->status = pdu->u.ret_unlink.status; pr_info("urb->status %d\n", urb->status); - spin_lock_irqsave(&the_controller->lock, flags); + spin_lock(&the_controller->lock); usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); - spin_unlock_irqrestore(&the_controller->lock, flags); + spin_unlock(&the_controller->lock); usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); diff --git a/trunk/drivers/usb/gadget/amd5536udc.c b/trunk/drivers/usb/gadget/amd5536udc.c index 45f422ac103f..4730016d7cd4 100644 --- a/trunk/drivers/usb/gadget/amd5536udc.c +++ b/trunk/drivers/usb/gadget/amd5536udc.c @@ -1959,7 +1959,7 @@ static int amd5536_start(struct usb_gadget_driver *driver, u32 tmp; if (!driver || !bind || !driver->setup - || driver->speed < USB_SPEED_HIGH) + || driver->speed != USB_SPEED_HIGH) return -EINVAL; if (!dev) return -ENODEV; diff --git a/trunk/drivers/usb/gadget/f_serial.c b/trunk/drivers/usb/gadget/f_serial.c index cf33a8d0fd5d..91fdf790ed20 100644 --- a/trunk/drivers/usb/gadget/f_serial.c +++ b/trunk/drivers/usb/gadget/f_serial.c @@ -131,8 +131,8 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt) } if (!gser->port.in->desc || !gser->port.out->desc) { DBG(cdev, "activate generic ttyGS%d\n", gser->port_num); - if (config_ep_by_speed(cdev->gadget, f, gser->port.in) || - config_ep_by_speed(cdev->gadget, f, gser->port.out)) { + if (!config_ep_by_speed(cdev->gadget, f, gser->port.in) || + !config_ep_by_speed(cdev->gadget, f, gser->port.out)) { gser->port.in->desc = NULL; gser->port.out->desc = NULL; return -EINVAL; diff --git a/trunk/drivers/usb/gadget/fsl_mxc_udc.c b/trunk/drivers/usb/gadget/fsl_mxc_udc.c index dcbc0a2e48dd..43a49ecc1f36 100644 --- a/trunk/drivers/usb/gadget/fsl_mxc_udc.c +++ b/trunk/drivers/usb/gadget/fsl_mxc_udc.c @@ -16,7 +16,6 @@ #include #include #include -#include #include @@ -89,6 +88,7 @@ int fsl_udc_clk_init(struct platform_device *pdev) void fsl_udc_clk_finalize(struct platform_device *pdev) { struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; +#if defined(CONFIG_SOC_IMX35) if (cpu_is_mx35()) { unsigned int v; @@ -101,6 +101,7 @@ void fsl_udc_clk_finalize(struct platform_device *pdev) USBPHYCTRL_OTGBASE_OFFSET)); } } +#endif /* ULPI transceivers don't need usbpll */ if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { diff --git a/trunk/drivers/usb/gadget/fsl_qe_udc.c b/trunk/drivers/usb/gadget/fsl_qe_udc.c index e00cf92409ce..2a03e4de11c1 100644 --- a/trunk/drivers/usb/gadget/fsl_qe_udc.c +++ b/trunk/drivers/usb/gadget/fsl_qe_udc.c @@ -2336,7 +2336,8 @@ static int fsl_qe_start(struct usb_gadget_driver *driver, if (!udc_controller) return -ENODEV; - if (!driver || driver->speed < USB_SPEED_FULL + if (!driver || (driver->speed != USB_SPEED_FULL + && driver->speed != USB_SPEED_HIGH) || !bind || !driver->disconnect || !driver->setup) return -EINVAL; diff --git a/trunk/drivers/usb/gadget/fsl_udc_core.c b/trunk/drivers/usb/gadget/fsl_udc_core.c index dd28ef3def71..b3b3d83b7c33 100644 --- a/trunk/drivers/usb/gadget/fsl_udc_core.c +++ b/trunk/drivers/usb/gadget/fsl_udc_core.c @@ -696,31 +696,12 @@ static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req) kfree(req); } -/* Actually add a dTD chain to an empty dQH and let go */ -static void fsl_prime_ep(struct fsl_ep *ep, struct ep_td_struct *td) -{ - struct ep_queue_head *qh = get_qh_by_ep(ep); - - /* Write dQH next pointer and terminate bit to 0 */ - qh->next_dtd_ptr = cpu_to_hc32(td->td_dma - & EP_QUEUE_HEAD_NEXT_POINTER_MASK); - - /* Clear active and halt bit */ - qh->size_ioc_int_sts &= cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE - | EP_QUEUE_HEAD_STATUS_HALT)); - - /* Ensure that updates to the QH will occur before priming. */ - wmb(); - - /* Prime endpoint by writing correct bit to ENDPTPRIME */ - fsl_writel(ep_is_in(ep) ? (1 << (ep_index(ep) + 16)) - : (1 << (ep_index(ep))), &dr_regs->endpointprime); -} - -/* Add dTD chain to the dQH of an EP */ +/*-------------------------------------------------------------------------*/ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) { + int i = ep_index(ep) * 2 + ep_is_in(ep); u32 temp, bitmask, tmp_stat; + struct ep_queue_head *dQH = &ep->udc->ep_qh[i]; /* VDBG("QH addr Register 0x%8x", dr_regs->endpointlistaddr); VDBG("ep_qh[%d] addr is 0x%8x", i, (u32)&(ep->udc->ep_qh[i])); */ @@ -738,7 +719,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK); /* Read prime bit, if 1 goto done */ if (fsl_readl(&dr_regs->endpointprime) & bitmask) - return; + goto out; do { /* Set ATDTW bit in USBCMD */ @@ -755,10 +736,28 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) fsl_writel(temp & ~USB_CMD_ATDTW, &dr_regs->usbcmd); if (tmp_stat) - return; + goto out; } - fsl_prime_ep(ep, req->head); + /* Write dQH next pointer and terminate bit to 0 */ + temp = req->head->td_dma & EP_QUEUE_HEAD_NEXT_POINTER_MASK; + dQH->next_dtd_ptr = cpu_to_hc32(temp); + + /* Clear active and halt bit */ + temp = cpu_to_hc32(~(EP_QUEUE_HEAD_STATUS_ACTIVE + | EP_QUEUE_HEAD_STATUS_HALT)); + dQH->size_ioc_int_sts &= temp; + + /* Ensure that updates to the QH will occur before priming. */ + wmb(); + + /* Prime endpoint by writing 1 to ENDPTPRIME */ + temp = ep_is_in(ep) + ? (1 << (ep_index(ep) + 16)) + : (1 << (ep_index(ep))); + fsl_writel(temp, &dr_regs->endpointprime); +out: + return; } /* Fill in the dTD structure @@ -878,7 +877,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) VDBG("%s, bad ep", __func__); return -EINVAL; } - if (usb_endpoint_xfer_isoc(ep->desc)) { + if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { if (req->req.length > ep->ep.maxpacket) return -EMSGSIZE; } @@ -974,20 +973,25 @@ static int fsl_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) /* The request isn't the last request in this ep queue */ if (req->queue.next != &ep->queue) { + struct ep_queue_head *qh; struct fsl_req *next_req; + qh = ep->qh; next_req = list_entry(req->queue.next, struct fsl_req, queue); - /* prime with dTD of next request */ - fsl_prime_ep(ep, next_req->head); + /* Point the QH to the first TD of next request */ + fsl_writel((u32) next_req->head, &qh->curr_dtd_ptr); } - /* The request hasn't been processed, patch up the TD chain */ + + /* The request hasn't been processed, patch up the TD chain */ } else { struct fsl_req *prev_req; prev_req = list_entry(req->queue.prev, struct fsl_req, queue); - prev_req->tail->next_td_ptr = req->tail->next_td_ptr; + fsl_writel(fsl_readl(&req->tail->next_td_ptr), + &prev_req->tail->next_td_ptr); + } done(ep, req, -ECONNRESET); @@ -1028,7 +1032,7 @@ static int fsl_ep_set_halt(struct usb_ep *_ep, int value) goto out; } - if (usb_endpoint_xfer_isoc(ep->desc)) { + if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { status = -EOPNOTSUPP; goto out; } @@ -1064,7 +1068,7 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep) struct fsl_udc *udc; int size = 0; u32 bitmask; - struct ep_queue_head *qh; + struct ep_queue_head *d_qh; ep = container_of(_ep, struct fsl_ep, ep); if (!_ep || (!ep->desc && ep_index(ep) != 0)) @@ -1075,13 +1079,13 @@ static int fsl_ep_fifo_status(struct usb_ep *_ep) if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; - qh = get_qh_by_ep(ep); + d_qh = &ep->udc->ep_qh[ep_index(ep) * 2 + ep_is_in(ep)]; bitmask = (ep_is_in(ep)) ? (1 << (ep_index(ep) + 16)) : (1 << (ep_index(ep))); if (fsl_readl(&dr_regs->endptstatus) & bitmask) - size = (qh->size_ioc_int_sts & DTD_PACKET_SIZE) + size = (d_qh->size_ioc_int_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS; pr_debug("%s %u\n", __func__, size); @@ -1934,7 +1938,8 @@ static int fsl_start(struct usb_gadget_driver *driver, if (!udc_controller) return -ENODEV; - if (!driver || driver->speed < USB_SPEED_FULL + if (!driver || (driver->speed != USB_SPEED_FULL + && driver->speed != USB_SPEED_HIGH) || !bind || !driver->disconnect || !driver->setup) return -EINVAL; diff --git a/trunk/drivers/usb/gadget/fsl_usb2_udc.h b/trunk/drivers/usb/gadget/fsl_usb2_udc.h index f781f5dec417..1d51be83fda8 100644 --- a/trunk/drivers/usb/gadget/fsl_usb2_udc.h +++ b/trunk/drivers/usb/gadget/fsl_usb2_udc.h @@ -569,16 +569,6 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length) * 2 + ((windex & USB_DIR_IN) ? 1 : 0)) #define get_pipe_by_ep(EP) (ep_index(EP) * 2 + ep_is_in(EP)) -static inline struct ep_queue_head *get_qh_by_ep(struct fsl_ep *ep) -{ - /* we only have one ep0 structure but two queue heads */ - if (ep_index(ep) != 0) - return ep->qh; - else - return &ep->udc->ep_qh[(ep->udc->ep0_dir == - USB_DIR_IN) ? 1 : 0]; -} - struct platform_device; #ifdef CONFIG_ARCH_MXC int fsl_udc_clk_init(struct platform_device *pdev); diff --git a/trunk/drivers/usb/gadget/m66592-udc.c b/trunk/drivers/usb/gadget/m66592-udc.c index 9aa1cbbee45b..91d0af2a24a8 100644 --- a/trunk/drivers/usb/gadget/m66592-udc.c +++ b/trunk/drivers/usb/gadget/m66592-udc.c @@ -1472,7 +1472,7 @@ static int m66592_start(struct usb_gadget_driver *driver, int retval; if (!driver - || driver->speed < USB_SPEED_HIGH + || driver->speed != USB_SPEED_HIGH || !bind || !driver->setup) return -EINVAL; diff --git a/trunk/drivers/usb/gadget/net2280.c b/trunk/drivers/usb/gadget/net2280.c index da2b9d0be3ca..7f1bc9a73cda 100644 --- a/trunk/drivers/usb/gadget/net2280.c +++ b/trunk/drivers/usb/gadget/net2280.c @@ -1881,7 +1881,7 @@ static int net2280_start(struct usb_gadget *_gadget, * (dev->usb->xcvrdiag & FORCE_FULL_SPEED_MODE) * "must not be used in normal operation" */ - if (!driver || driver->speed < USB_SPEED_HIGH + if (!driver || driver->speed != USB_SPEED_HIGH || !driver->setup) return -EINVAL; diff --git a/trunk/drivers/usb/gadget/r8a66597-udc.c b/trunk/drivers/usb/gadget/r8a66597-udc.c index fc719a3f8557..24f84b210ce1 100644 --- a/trunk/drivers/usb/gadget/r8a66597-udc.c +++ b/trunk/drivers/usb/gadget/r8a66597-udc.c @@ -1746,7 +1746,7 @@ static int r8a66597_start(struct usb_gadget *gadget, struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget); if (!driver - || driver->speed < USB_SPEED_HIGH + || driver->speed != USB_SPEED_HIGH || !driver->setup) return -EINVAL; if (!r8a66597) diff --git a/trunk/drivers/usb/gadget/s3c-hsotg.c b/trunk/drivers/usb/gadget/s3c-hsotg.c index b31448229f0b..a552453dc946 100644 --- a/trunk/drivers/usb/gadget/s3c-hsotg.c +++ b/trunk/drivers/usb/gadget/s3c-hsotg.c @@ -2586,8 +2586,10 @@ static int s3c_hsotg_start(struct usb_gadget_driver *driver, return -EINVAL; } - if (driver->speed < USB_SPEED_FULL) + if (driver->speed != USB_SPEED_HIGH && + driver->speed != USB_SPEED_FULL) { dev_err(hsotg->dev, "%s: bad speed\n", __func__); + } if (!bind || !driver->setup) { dev_err(hsotg->dev, "%s: missing entry points\n", __func__); diff --git a/trunk/drivers/usb/gadget/s3c-hsudc.c b/trunk/drivers/usb/gadget/s3c-hsudc.c index 20a553b46aed..8d54f893cefe 100644 --- a/trunk/drivers/usb/gadget/s3c-hsudc.c +++ b/trunk/drivers/usb/gadget/s3c-hsudc.c @@ -1142,7 +1142,8 @@ static int s3c_hsudc_start(struct usb_gadget_driver *driver, int ret; if (!driver - || driver->speed < USB_SPEED_FULL + || (driver->speed != USB_SPEED_FULL && + driver->speed != USB_SPEED_HIGH) || !bind || !driver->unbind || !driver->disconnect || !driver->setup) return -EINVAL; diff --git a/trunk/drivers/usb/host/ehci-sched.c b/trunk/drivers/usb/host/ehci-sched.c index a60679cbbf85..56a32033adb3 100644 --- a/trunk/drivers/usb/host/ehci-sched.c +++ b/trunk/drivers/usb/host/ehci-sched.c @@ -1475,7 +1475,6 @@ iso_stream_schedule ( * jump until after the queue is primed. */ else { - int done = 0; start = SCHEDULE_SLOP + (now & ~0x07); /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ @@ -1493,18 +1492,18 @@ iso_stream_schedule ( if (stream->highspeed) { if (itd_slot_ok(ehci, mod, start, stream->usecs, period)) - done = 1; + break; } else { if ((start % 8) >= 6) continue; if (sitd_slot_ok(ehci, mod, stream, start, sched, period)) - done = 1; + break; } - } while (start > next && !done); + } while (start > next); /* no room in the schedule */ - if (!done) { + if (start == next) { ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n", urb, now, now + mod); status = -ENOSPC; diff --git a/trunk/drivers/usb/host/whci/qset.c b/trunk/drivers/usb/host/whci/qset.c index a403b53e86b9..d6e175428618 100644 --- a/trunk/drivers/usb/host/whci/qset.c +++ b/trunk/drivers/usb/host/whci/qset.c @@ -124,7 +124,7 @@ void qset_clear(struct whc *whc, struct whc_qset *qset) { qset->td_start = qset->td_end = qset->ntds = 0; - qset->qh.link = cpu_to_le64(QH_LINK_NTDS(8) | QH_LINK_T); + qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK; qset->qh.err_count = 0; qset->qh.scratch[0] = 0; diff --git a/trunk/drivers/usb/host/xhci.c b/trunk/drivers/usb/host/xhci.c index a1afb7c39f7e..aa94c0195791 100644 --- a/trunk/drivers/usb/host/xhci.c +++ b/trunk/drivers/usb/host/xhci.c @@ -711,10 +711,7 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci) ring = xhci->cmd_ring; seg = ring->deq_seg; do { - memset(seg->trbs, 0, - sizeof(union xhci_trb) * (TRBS_PER_SEGMENT - 1)); - seg->trbs[TRBS_PER_SEGMENT - 1].link.control &= - cpu_to_le32(~TRB_CYCLE); + memset(seg->trbs, 0, SEGMENT_SIZE); seg = seg->next; } while (seg != ring->deq_seg); diff --git a/trunk/drivers/usb/musb/musb_core.c b/trunk/drivers/usb/musb/musb_core.c index b63ab1570103..c1fa12ec7a9a 100644 --- a/trunk/drivers/usb/musb/musb_core.c +++ b/trunk/drivers/usb/musb/musb_core.c @@ -2301,12 +2301,18 @@ static int musb_suspend(struct device *dev) */ } + musb_save_context(musb); + spin_unlock_irqrestore(&musb->lock, flags); return 0; } static int musb_resume_noirq(struct device *dev) { + struct musb *musb = dev_to_musb(dev); + + musb_restore_context(musb); + /* for static cmos like DaVinci, register values were preserved * unless for some reason the whole soc powered down or the USB * module got reset through the PSC (vs just being disabled). diff --git a/trunk/drivers/usb/musb/musb_gadget.c b/trunk/drivers/usb/musb/musb_gadget.c index 922148ff8d29..d51043acfe1a 100644 --- a/trunk/drivers/usb/musb/musb_gadget.c +++ b/trunk/drivers/usb/musb/musb_gadget.c @@ -1903,7 +1903,7 @@ static int musb_gadget_start(struct usb_gadget *g, unsigned long flags; int retval = -EINVAL; - if (driver->speed < USB_SPEED_HIGH) + if (driver->speed != USB_SPEED_HIGH) goto err0; pm_runtime_get_sync(musb->controller); diff --git a/trunk/drivers/usb/renesas_usbhs/mod_gadget.c b/trunk/drivers/usb/renesas_usbhs/mod_gadget.c index 7f4e80338570..d9717e0bc1ff 100644 --- a/trunk/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/trunk/drivers/usb/renesas_usbhs/mod_gadget.c @@ -751,32 +751,53 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); - struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); + struct usbhs_priv *priv; + struct device *dev; + int ret; if (!driver || !driver->setup || - driver->speed < USB_SPEED_FULL) + driver->speed != USB_SPEED_HIGH) return -EINVAL; + dev = usbhsg_gpriv_to_dev(gpriv); + priv = usbhsg_gpriv_to_priv(gpriv); + /* first hook up the driver ... */ gpriv->driver = driver; gpriv->gadget.dev.driver = &driver->driver; + ret = device_add(&gpriv->gadget.dev); + if (ret) { + dev_err(dev, "device_add error %d\n", ret); + goto add_fail; + } + return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD); + +add_fail: + gpriv->driver = NULL; + gpriv->gadget.dev.driver = NULL; + + return ret; } static int usbhsg_gadget_stop(struct usb_gadget *gadget, struct usb_gadget_driver *driver) { struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget); - struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); + struct usbhs_priv *priv; + struct device *dev; if (!driver || !driver->unbind) return -EINVAL; + dev = usbhsg_gpriv_to_dev(gpriv); + priv = usbhsg_gpriv_to_priv(gpriv); + usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD); - gpriv->gadget.dev.driver = NULL; + device_del(&gpriv->gadget.dev); gpriv->driver = NULL; return 0; @@ -806,13 +827,6 @@ static int usbhsg_start(struct usbhs_priv *priv) static int usbhsg_stop(struct usbhs_priv *priv) { - struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); - - /* cable disconnect */ - if (gpriv->driver && - gpriv->driver->disconnect) - gpriv->driver->disconnect(&gpriv->gadget); - return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); } @@ -862,14 +876,12 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) /* * init gadget */ + device_initialize(&gpriv->gadget.dev); dev_set_name(&gpriv->gadget.dev, "gadget"); gpriv->gadget.dev.parent = dev; gpriv->gadget.name = "renesas_usbhs_udc"; gpriv->gadget.ops = &usbhsg_gadget_ops; gpriv->gadget.is_dualspeed = 1; - ret = device_register(&gpriv->gadget.dev); - if (ret < 0) - goto err_add_udc; INIT_LIST_HEAD(&gpriv->gadget.ep_list); @@ -900,15 +912,12 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) ret = usb_add_gadget_udc(dev, &gpriv->gadget); if (ret) - goto err_register; + goto err_add_udc; dev_info(dev, "gadget probed\n"); return 0; - -err_register: - device_unregister(&gpriv->gadget.dev); err_add_udc: kfree(gpriv->uep); @@ -924,8 +933,6 @@ void usbhs_mod_gadget_remove(struct usbhs_priv *priv) usb_del_gadget_udc(&gpriv->gadget); - device_unregister(&gpriv->gadget.dev); - usbhsg_controller_unregister(gpriv); kfree(gpriv->uep); diff --git a/trunk/drivers/usb/serial/ftdi_sio.c b/trunk/drivers/usb/serial/ftdi_sio.c index ff3db5d056a5..bd4298bb6750 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.c +++ b/trunk/drivers/usb/serial/ftdi_sio.c @@ -736,7 +736,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_PROPOX_ISPCABLEIII_PID) }, { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), diff --git a/trunk/drivers/usb/serial/ftdi_sio_ids.h b/trunk/drivers/usb/serial/ftdi_sio_ids.h index 055b64ef0bba..571fa96b49c7 100644 --- a/trunk/drivers/usb/serial/ftdi_sio_ids.h +++ b/trunk/drivers/usb/serial/ftdi_sio_ids.h @@ -112,7 +112,6 @@ /* Propox devices */ #define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 -#define FTDI_PROPOX_ISPCABLEIII_PID 0xD739 /* Lenz LI-USB Computer Interface. */ #define FTDI_LENZ_LIUSB_PID 0xD780 diff --git a/trunk/drivers/usb/serial/option.c b/trunk/drivers/usb/serial/option.c index e3426602dc82..d865878c9f97 100644 --- a/trunk/drivers/usb/serial/option.c +++ b/trunk/drivers/usb/serial/option.c @@ -661,9 +661,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x08) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, @@ -750,7 +747,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ - { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, diff --git a/trunk/drivers/usb/storage/unusual_devs.h b/trunk/drivers/usb/storage/unusual_devs.h index 24caba79d722..3041a974faf3 100644 --- a/trunk/drivers/usb/storage/unusual_devs.h +++ b/trunk/drivers/usb/storage/unusual_devs.h @@ -1854,13 +1854,6 @@ UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Reported by Qinglin Ye */ -UNUSUAL_DEV( 0x13fe, 0x3600, 0x0100, 0x0100, - "Kingston", - "DT 101 G2", - USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_BULK_IGNORE_TAG ), - /* Reported by Francesco Foresti */ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201, "Super Top", diff --git a/trunk/fs/xfs/xfs_acl.c b/trunk/fs/xfs/xfs_acl.c index 76e4266d2e7e..b6c4b3795c4a 100644 --- a/trunk/fs/xfs/xfs_acl.c +++ b/trunk/fs/xfs/xfs_acl.c @@ -42,8 +42,6 @@ xfs_acl_from_disk(struct xfs_acl *aclp) int count, i; count = be32_to_cpu(aclp->acl_cnt); - if (count > XFS_ACL_MAX_ENTRIES) - return ERR_PTR(-EFSCORRUPTED); acl = posix_acl_alloc(count, GFP_KERNEL); if (!acl) diff --git a/trunk/fs/xfs/xfs_attr_leaf.c b/trunk/fs/xfs/xfs_attr_leaf.c index c1b55e596551..d4906e7c9787 100644 --- a/trunk/fs/xfs/xfs_attr_leaf.c +++ b/trunk/fs/xfs/xfs_attr_leaf.c @@ -110,7 +110,6 @@ xfs_attr_namesp_match(int arg_flags, int ondisk_flags) /* * Query whether the requested number of additional bytes of extended * attribute space will be able to fit inline. - * * Returns zero if not, else the di_forkoff fork offset to be used in the * literal area for attribute data once the new bytes have been added. * @@ -123,7 +122,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) int offset; int minforkoff; /* lower limit on valid forkoff locations */ int maxforkoff; /* upper limit on valid forkoff locations */ - int dsize; + int dsize; xfs_mount_t *mp = dp->i_mount; offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */ @@ -137,60 +136,47 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) return (offset >= minforkoff) ? minforkoff : 0; } - /* - * If the requested numbers of bytes is smaller or equal to the - * current attribute fork size we can always proceed. - * - * Note that if_bytes in the data fork might actually be larger than - * the current data fork size is due to delalloc extents. In that - * case either the extent count will go down when they are converted - * to real extents, or the delalloc conversion will take care of the - * literal area rebalancing. - */ - if (bytes <= XFS_IFORK_ASIZE(dp)) - return dp->i_d.di_forkoff; - - /* - * For attr2 we can try to move the forkoff if there is space in the - * literal area, but for the old format we are done if there is no - * space in the fixed attribute fork. - */ - if (!(mp->m_flags & XFS_MOUNT_ATTR2)) + if (!(mp->m_flags & XFS_MOUNT_ATTR2)) { + if (bytes <= XFS_IFORK_ASIZE(dp)) + return dp->i_d.di_forkoff; return 0; + } dsize = dp->i_df.if_bytes; - + switch (dp->i_d.di_format) { case XFS_DINODE_FMT_EXTENTS: - /* + /* * If there is no attr fork and the data fork is extents, - * determine if creating the default attr fork will result - * in the extents form migrating to btree. If so, the - * minimum offset only needs to be the space required for + * determine if creating the default attr fork will result + * in the extents form migrating to btree. If so, the + * minimum offset only needs to be the space required for * the btree root. - */ + */ if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > xfs_default_attroffset(dp)) dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS); break; + case XFS_DINODE_FMT_BTREE: /* - * If we have a data btree then keep forkoff if we have one, - * otherwise we are adding a new attr, so then we set - * minforkoff to where the btree root can finish so we have + * If have data btree then keep forkoff if we have one, + * otherwise we are adding a new attr, so then we set + * minforkoff to where the btree root can finish so we have * plenty of room for attrs */ if (dp->i_d.di_forkoff) { - if (offset < dp->i_d.di_forkoff) + if (offset < dp->i_d.di_forkoff) return 0; - return dp->i_d.di_forkoff; - } - dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot); + else + return dp->i_d.di_forkoff; + } else + dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot); break; } - - /* - * A data fork btree root must have space for at least + + /* + * A data fork btree root must have space for at least * MINDBTPTRS key/ptr pairs if the data fork is small or empty. */ minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS)); @@ -200,10 +186,10 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS); maxforkoff = maxforkoff >> 3; /* rounded down */ + if (offset >= minforkoff && offset < maxforkoff) + return offset; if (offset >= maxforkoff) return maxforkoff; - if (offset >= minforkoff) - return offset; return 0; } diff --git a/trunk/fs/xfs/xfs_inode.c b/trunk/fs/xfs/xfs_inode.c index 755ee8164880..c0237c602f11 100644 --- a/trunk/fs/xfs/xfs_inode.c +++ b/trunk/fs/xfs/xfs_inode.c @@ -2835,27 +2835,6 @@ xfs_iflush_int( return XFS_ERROR(EFSCORRUPTED); } -void -xfs_promote_inode( - struct xfs_inode *ip) -{ - struct xfs_buf *bp; - - ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)); - - bp = xfs_incore(ip->i_mount->m_ddev_targp, ip->i_imap.im_blkno, - ip->i_imap.im_len, XBF_TRYLOCK); - if (!bp) - return; - - if (XFS_BUF_ISDELAYWRITE(bp)) { - xfs_buf_delwri_promote(bp); - wake_up_process(ip->i_mount->m_ddev_targp->bt_task); - } - - xfs_buf_relse(bp); -} - /* * Return a pointer to the extent record at file index idx. */ diff --git a/trunk/fs/xfs/xfs_inode.h b/trunk/fs/xfs/xfs_inode.h index b4cd4739f98e..760140d1dd66 100644 --- a/trunk/fs/xfs/xfs_inode.h +++ b/trunk/fs/xfs/xfs_inode.h @@ -498,7 +498,6 @@ int xfs_iunlink(struct xfs_trans *, xfs_inode_t *); void xfs_iext_realloc(xfs_inode_t *, int, int); void xfs_iunpin_wait(xfs_inode_t *); int xfs_iflush(xfs_inode_t *, uint); -void xfs_promote_inode(struct xfs_inode *); void xfs_lock_inodes(xfs_inode_t **, int, uint); void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); diff --git a/trunk/fs/xfs/xfs_sync.c b/trunk/fs/xfs/xfs_sync.c index be5c51d8f757..aa3dc1a4d53d 100644 --- a/trunk/fs/xfs/xfs_sync.c +++ b/trunk/fs/xfs/xfs_sync.c @@ -770,17 +770,6 @@ xfs_reclaim_inode( if (!xfs_iflock_nowait(ip)) { if (!(sync_mode & SYNC_WAIT)) goto out; - - /* - * If we only have a single dirty inode in a cluster there is - * a fair chance that the AIL push may have pushed it into - * the buffer, but xfsbufd won't touch it until 30 seconds - * from now, and thus we will lock up here. - * - * Promote the inode buffer to the front of the delwri list - * and wake up xfsbufd now. - */ - xfs_promote_inode(ip); xfs_iflock(ip); } diff --git a/trunk/include/drm/drm_pciids.h b/trunk/include/drm/drm_pciids.h index 4e4fbb820e20..f81676f1b310 100644 --- a/trunk/include/drm/drm_pciids.h +++ b/trunk/include/drm/drm_pciids.h @@ -197,14 +197,6 @@ {0x1002, 0x6770, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6778, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6779, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6841, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6842, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6843, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6849, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6858, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6859, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6888, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6889, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \ diff --git a/trunk/include/linux/errqueue.h b/trunk/include/linux/errqueue.h index fd0628be45ce..c9f522bd17e4 100644 --- a/trunk/include/linux/errqueue.h +++ b/trunk/include/linux/errqueue.h @@ -25,7 +25,7 @@ struct sock_extended_err { #ifdef __KERNEL__ #include -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) #include #endif @@ -34,7 +34,7 @@ struct sock_extended_err { struct sock_exterr_skb { union { struct inet_skb_parm h4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) struct inet6_skb_parm h6; #endif } header; diff --git a/trunk/include/linux/ethtool.h b/trunk/include/linux/ethtool.h index b38bf69310ee..20db5b275c3f 100644 --- a/trunk/include/linux/ethtool.h +++ b/trunk/include/linux/ethtool.h @@ -543,15 +543,9 @@ struct compat_ethtool_rxnfc { /** * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR - * @size: On entry, the array size of the user buffer, which may be zero. - * On return from %ETHTOOL_GRXFHINDIR, the array size of the hardware - * indirection table. + * @size: On entry, the array size of the user buffer. On return from + * %ETHTOOL_GRXFHINDIR, the array size of the hardware indirection table. * @ring_index: RX ring/queue index for each hash value - * - * For %ETHTOOL_GRXFHINDIR, a @size of zero means that only the size - * should be returned. For %ETHTOOL_SRXFHINDIR, a @size of zero means - * the table should be reset to default values. This last feature - * is not supported by the original implementations. */ struct ethtool_rxfh_indir { __u32 cmd; @@ -754,18 +748,6 @@ struct net_device; /* Some generic methods drivers may use in their ethtool_ops */ u32 ethtool_op_get_link(struct net_device *dev); -/** - * ethtool_rxfh_indir_default - get default value for RX flow hash indirection - * @index: Index in RX flow hash indirection table - * @n_rx_rings: Number of RX rings to use - * - * This function provides the default policy for RX flow hash indirection. - */ -static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings) -{ - return index % n_rx_rings; -} - /** * struct ethtool_ops - optional netdev operations * @get_settings: Get various device settings including Ethernet link @@ -845,13 +827,9 @@ static inline u32 ethtool_rxfh_indir_default(u32 index, u32 n_rx_rings) * error code or zero. * @set_rx_ntuple: Set an RX n-tuple rule. Returns a negative error code * or zero. - * @get_rxfh_indir_size: Get the size of the RX flow hash indirection table. - * Returns zero if not supported for this specific device. * @get_rxfh_indir: Get the contents of the RX flow hash indirection table. - * Will not be called if @get_rxfh_indir_size returns zero. * Returns a negative error code or zero. * @set_rxfh_indir: Set the contents of the RX flow hash indirection table. - * Will not be called if @get_rxfh_indir_size returns zero. * Returns a negative error code or zero. * @get_channels: Get number of channels. * @set_channels: Set number of channels. Returns a negative error code or @@ -915,9 +893,10 @@ struct ethtool_ops { int (*reset)(struct net_device *, u32 *); int (*set_rx_ntuple)(struct net_device *, struct ethtool_rx_ntuple *); - u32 (*get_rxfh_indir_size)(struct net_device *); - int (*get_rxfh_indir)(struct net_device *, u32 *); - int (*set_rxfh_indir)(struct net_device *, const u32 *); + int (*get_rxfh_indir)(struct net_device *, + struct ethtool_rxfh_indir *); + int (*set_rxfh_indir)(struct net_device *, + const struct ethtool_rxfh_indir *); void (*get_channels)(struct net_device *, struct ethtool_channels *); int (*set_channels)(struct net_device *, struct ethtool_channels *); int (*get_dump_flag)(struct net_device *, struct ethtool_dump *); diff --git a/trunk/include/linux/ftrace_event.h b/trunk/include/linux/ftrace_event.h index c3da42dd22ba..96efa6794ea5 100644 --- a/trunk/include/linux/ftrace_event.h +++ b/trunk/include/linux/ftrace_event.h @@ -172,7 +172,6 @@ enum { TRACE_EVENT_FL_FILTERED_BIT, TRACE_EVENT_FL_RECORDED_CMD_BIT, TRACE_EVENT_FL_CAP_ANY_BIT, - TRACE_EVENT_FL_NO_SET_FILTER_BIT, }; enum { @@ -180,7 +179,6 @@ enum { TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT), TRACE_EVENT_FL_RECORDED_CMD = (1 << TRACE_EVENT_FL_RECORDED_CMD_BIT), TRACE_EVENT_FL_CAP_ANY = (1 << TRACE_EVENT_FL_CAP_ANY_BIT), - TRACE_EVENT_FL_NO_SET_FILTER = (1 << TRACE_EVENT_FL_NO_SET_FILTER_BIT), }; struct ftrace_event_call { diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h index 17f2a768e2ad..66cedf6eb5c2 100644 --- a/trunk/include/linux/ieee80211.h +++ b/trunk/include/linux/ieee80211.h @@ -1694,23 +1694,6 @@ static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) return false; } -/** - * ieee80211_is_public_action - check if frame is a public action frame - * @hdr: the frame - * @len: length of the frame - */ -static inline bool ieee80211_is_public_action(struct ieee80211_hdr *hdr, - size_t len) -{ - struct ieee80211_mgmt *mgmt = (void *)hdr; - - if (len < IEEE80211_MIN_ACTION_SIZE) - return false; - if (!ieee80211_is_action(hdr->frame_control)) - return false; - return mgmt->u.action.category == WLAN_CATEGORY_PUBLIC; -} - /** * ieee80211_fhss_chan_to_freq - get channel frequency * @channel: the FHSS channel diff --git a/trunk/include/linux/if_vlan.h b/trunk/include/linux/if_vlan.h index 13aff1e2183b..070ac50c1d2d 100644 --- a/trunk/include/linux/if_vlan.h +++ b/trunk/include/linux/if_vlan.h @@ -74,7 +74,22 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb) /* found in socket.c */ extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *)); -struct vlan_info; +/* if this changes, algorithm will have to be reworked because this + * depends on completely exhausting the VLAN identifier space. Thus + * it gives constant time look-up, but in many cases it wastes memory. + */ +#define VLAN_GROUP_ARRAY_SPLIT_PARTS 8 +#define VLAN_GROUP_ARRAY_PART_LEN (VLAN_N_VID/VLAN_GROUP_ARRAY_SPLIT_PARTS) + +struct vlan_group { + struct net_device *real_dev; /* The ethernet(like) device + * the vlan is attached to. + */ + unsigned int nr_vlans; + struct hlist_node hlist; /* linked list */ + struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS]; + struct rcu_head rcu; +}; static inline int is_vlan_dev(struct net_device *dev) { @@ -94,13 +109,6 @@ extern u16 vlan_dev_vlan_id(const struct net_device *dev); extern bool vlan_do_receive(struct sk_buff **skb, bool last_handler); extern struct sk_buff *vlan_untag(struct sk_buff *skb); -extern int vlan_vid_add(struct net_device *dev, unsigned short vid); -extern void vlan_vid_del(struct net_device *dev, unsigned short vid); - -extern int vlan_vids_add_by_dev(struct net_device *dev, - const struct net_device *by_dev); -extern void vlan_vids_del_by_dev(struct net_device *dev, - const struct net_device *by_dev); #else static inline struct net_device * __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) @@ -131,26 +139,6 @@ static inline struct sk_buff *vlan_untag(struct sk_buff *skb) { return skb; } - -static inline int vlan_vid_add(struct net_device *dev, unsigned short vid) -{ - return 0; -} - -static inline void vlan_vid_del(struct net_device *dev, unsigned short vid) -{ -} - -static inline int vlan_vids_add_by_dev(struct net_device *dev, - const struct net_device *by_dev) -{ - return 0; -} - -static inline void vlan_vids_del_by_dev(struct net_device *dev, - const struct net_device *by_dev) -{ -} #endif /** @@ -398,7 +386,7 @@ struct vlan_ioctl_args { unsigned int skb_priority; unsigned int name_type; unsigned int bind_type; - unsigned int flag; /* Matches vlan_dev_priv flags */ + unsigned int flag; /* Matches vlan_dev_info flags */ } u; short vlan_qos; diff --git a/trunk/include/linux/inet_diag.h b/trunk/include/linux/inet_diag.h index afa5d5c74169..abf5028db981 100644 --- a/trunk/include/linux/inet_diag.h +++ b/trunk/include/linux/inet_diag.h @@ -22,7 +22,7 @@ struct inet_diag_sockid { /* Request structure */ -struct inet_diag_req_compat { +struct inet_diag_req { __u8 idiag_family; /* Family of addresses. */ __u8 idiag_src_len; __u8 idiag_dst_len; @@ -34,15 +34,6 @@ struct inet_diag_req_compat { __u32 idiag_dbs; /* Tables to dump (NI) */ }; -struct inet_diag_req { - __u8 sdiag_family; - __u8 sdiag_protocol; - __u8 idiag_ext; - __u8 pad; - __u32 idiag_states; - struct inet_diag_sockid id; -}; - enum { INET_DIAG_REQ_NONE, INET_DIAG_REQ_BYTECODE, @@ -134,41 +125,16 @@ struct tcpvegas_info { #ifdef __KERNEL__ struct sock; struct inet_hashinfo; -struct nlattr; -struct nlmsghdr; -struct sk_buff; -struct netlink_callback; struct inet_diag_handler { - void (*dump)(struct sk_buff *skb, - struct netlink_callback *cb, - struct inet_diag_req *r, - struct nlattr *bc); - - int (*dump_one)(struct sk_buff *in_skb, - const struct nlmsghdr *nlh, - struct inet_diag_req *req); - + struct inet_hashinfo *idiag_hashinfo; void (*idiag_get_info)(struct sock *sk, struct inet_diag_msg *r, void *info); + __u16 idiag_info_size; __u16 idiag_type; }; -struct inet_connection_sock; -int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, - struct sk_buff *skb, struct inet_diag_req *req, - u32 pid, u32 seq, u16 nlmsg_flags, - const struct nlmsghdr *unlh); -void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb, - struct netlink_callback *cb, struct inet_diag_req *r, - struct nlattr *bc); -int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, - struct sk_buff *in_skb, const struct nlmsghdr *nlh, - struct inet_diag_req *req); - -int inet_diag_bc_sk(const struct nlattr *_bc, struct sock *sk); - extern int inet_diag_register(const struct inet_diag_handler *handler); extern void inet_diag_unregister(const struct inet_diag_handler *handler); #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/init_task.h b/trunk/include/linux/init_task.h index 32574eef9394..94b1e356c02a 100644 --- a/trunk/include/linux/init_task.h +++ b/trunk/include/linux/init_task.h @@ -126,8 +126,6 @@ extern struct cred init_cred; # define INIT_PERF_EVENTS(tsk) #endif -#define INIT_TASK_COMM "swapper" - /* * INIT_TASK is used to set up the first task table, touch at * your own risk!. Base=0, limit=0x1fffff (=2MB) @@ -164,7 +162,7 @@ extern struct cred init_cred; .group_leader = &tsk, \ RCU_INIT_POINTER(.real_cred, &init_cred), \ RCU_INIT_POINTER(.cred, &init_cred), \ - .comm = INIT_TASK_COMM, \ + .comm = "swapper", \ .thread = INIT_THREAD, \ .fs = &init_fs, \ .files = &init_files, \ diff --git a/trunk/include/linux/ipv6.h b/trunk/include/linux/ipv6.h index 6318268dcaf5..0c997767429a 100644 --- a/trunk/include/linux/ipv6.h +++ b/trunk/include/linux/ipv6.h @@ -404,7 +404,7 @@ struct tcp6_sock { extern int inet6_sk_rebuild_header(struct sock *sk); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static inline struct ipv6_pinfo * inet6_sk(const struct sock *__sk) { return inet_sk(__sk)->pinet6; @@ -515,7 +515,7 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk) #define inet6_rcv_saddr(__sk) NULL #define tcp_twsk_ipv6only(__sk) 0 #define inet_v6_ipv6only(__sk) 0 -#endif /* IS_ENABLED(CONFIG_IPV6) */ +#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ #define INET6_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif)\ (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net) && \ diff --git a/trunk/include/linux/lockd/lockd.h b/trunk/include/linux/lockd/lockd.h index 90b0656a869e..ff9abff55aa0 100644 --- a/trunk/include/linux/lockd/lockd.h +++ b/trunk/include/linux/lockd/lockd.h @@ -301,7 +301,7 @@ static inline int __nlm_privileged_request4(const struct sockaddr *sap) return ipv4_is_loopback(sin->sin_addr.s_addr); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static inline int __nlm_privileged_request6(const struct sockaddr *sap) { const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; @@ -314,12 +314,12 @@ static inline int __nlm_privileged_request6(const struct sockaddr *sap) return ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LOOPBACK; } -#else /* IS_ENABLED(CONFIG_IPV6) */ +#else /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ static inline int __nlm_privileged_request6(const struct sockaddr *sap) { return 0; } -#endif /* IS_ENABLED(CONFIG_IPV6) */ +#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ /* * Ensure incoming requests are from local privileged callers. diff --git a/trunk/include/linux/memcontrol.h b/trunk/include/linux/memcontrol.h index 9b296ea41bb8..b87068a1a09e 100644 --- a/trunk/include/linux/memcontrol.h +++ b/trunk/include/linux/memcontrol.h @@ -85,9 +85,6 @@ extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page); extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p); extern struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm); -extern struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *memcg); -extern struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont); - static inline int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup) { @@ -384,25 +381,5 @@ mem_cgroup_print_bad_page(struct page *page) } #endif -enum { - UNDER_LIMIT, - SOFT_LIMIT, - OVER_LIMIT, -}; - -#ifdef CONFIG_INET -struct sock; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM -void sock_update_memcg(struct sock *sk); -void sock_release_memcg(struct sock *sk); -#else -static inline void sock_update_memcg(struct sock *sk) -{ -} -static inline void sock_release_memcg(struct sock *sk) -{ -} -#endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */ -#endif /* CONFIG_INET */ #endif /* _LINUX_MEMCONTROL_H */ diff --git a/trunk/include/linux/mlx4/cmd.h b/trunk/include/linux/mlx4/cmd.h index 9958ff2cad3c..b56e4587208d 100644 --- a/trunk/include/linux/mlx4/cmd.h +++ b/trunk/include/linux/mlx4/cmd.h @@ -59,15 +59,12 @@ enum { MLX4_CMD_HW_HEALTH_CHECK = 0x50, MLX4_CMD_SET_PORT = 0xc, MLX4_CMD_SET_NODE = 0x5a, - MLX4_CMD_QUERY_FUNC = 0x56, MLX4_CMD_ACCESS_DDR = 0x2e, MLX4_CMD_MAP_ICM = 0xffa, MLX4_CMD_UNMAP_ICM = 0xff9, MLX4_CMD_MAP_ICM_AUX = 0xffc, MLX4_CMD_UNMAP_ICM_AUX = 0xffb, MLX4_CMD_SET_ICM_SIZE = 0xffd, - /*master notify fw on finish for slave's flr*/ - MLX4_CMD_INFORM_FLR_DONE = 0x5b, /* TPT commands */ MLX4_CMD_SW2HW_MPT = 0xd, @@ -122,26 +119,6 @@ enum { /* miscellaneous commands */ MLX4_CMD_DIAG_RPRT = 0x30, MLX4_CMD_NOP = 0x31, - MLX4_CMD_ACCESS_MEM = 0x2e, - MLX4_CMD_SET_VEP = 0x52, - - /* Ethernet specific commands */ - MLX4_CMD_SET_VLAN_FLTR = 0x47, - MLX4_CMD_SET_MCAST_FLTR = 0x48, - MLX4_CMD_DUMP_ETH_STATS = 0x49, - - /* Communication channel commands */ - MLX4_CMD_ARM_COMM_CHANNEL = 0x57, - MLX4_CMD_GEN_EQE = 0x58, - - /* virtual commands */ - MLX4_CMD_ALLOC_RES = 0xf00, - MLX4_CMD_FREE_RES = 0xf01, - MLX4_CMD_MCAST_ATTACH = 0xf05, - MLX4_CMD_UCAST_ATTACH = 0xf06, - MLX4_CMD_PROMISC = 0xf08, - MLX4_CMD_QUERY_FUNC_CAP = 0xf0a, - MLX4_CMD_QP_ATTACH = 0xf0b, /* debug commands */ MLX4_CMD_QUERY_DEBUG_MSG = 0x2a, @@ -149,7 +126,6 @@ enum { /* statistics commands */ MLX4_CMD_QUERY_IF_STAT = 0X54, - MLX4_CMD_SET_IF_STAT = 0X55, }; enum { @@ -159,8 +135,7 @@ enum { }; enum { - MLX4_MAILBOX_SIZE = 4096, - MLX4_ACCESS_MEM_ALIGN = 256, + MLX4_MAILBOX_SIZE = 4096 }; enum { @@ -173,11 +148,6 @@ enum { MLX4_SET_PORT_GID_TABLE = 0x5, }; -enum { - MLX4_CMD_WRAPPED, - MLX4_CMD_NATIVE -}; - struct mlx4_dev; struct mlx4_cmd_mailbox { @@ -187,24 +157,23 @@ struct mlx4_cmd_mailbox { int __mlx4_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, int out_is_imm, u32 in_modifier, u8 op_modifier, - u16 op, unsigned long timeout, int native); + u16 op, unsigned long timeout); /* Invoke a command with no output parameter */ static inline int mlx4_cmd(struct mlx4_dev *dev, u64 in_param, u32 in_modifier, - u8 op_modifier, u16 op, unsigned long timeout, - int native) + u8 op_modifier, u16 op, unsigned long timeout) { return __mlx4_cmd(dev, in_param, NULL, 0, in_modifier, - op_modifier, op, timeout, native); + op_modifier, op, timeout); } /* Invoke a command with an output mailbox */ static inline int mlx4_cmd_box(struct mlx4_dev *dev, u64 in_param, u64 out_param, u32 in_modifier, u8 op_modifier, u16 op, - unsigned long timeout, int native) + unsigned long timeout) { return __mlx4_cmd(dev, in_param, &out_param, 0, in_modifier, - op_modifier, op, timeout, native); + op_modifier, op, timeout); } /* @@ -214,17 +183,13 @@ static inline int mlx4_cmd_box(struct mlx4_dev *dev, u64 in_param, u64 out_param */ static inline int mlx4_cmd_imm(struct mlx4_dev *dev, u64 in_param, u64 *out_param, u32 in_modifier, u8 op_modifier, u16 op, - unsigned long timeout, int native) + unsigned long timeout) { return __mlx4_cmd(dev, in_param, out_param, 1, in_modifier, - op_modifier, op, timeout, native); + op_modifier, op, timeout); } struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev); void mlx4_free_cmd_mailbox(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox); -u32 mlx4_comm_get_version(void); - -#define MLX4_COMM_GET_IF_REV(cmd_chan_ver) (u8)((cmd_chan_ver) >> 8) - #endif /* MLX4_CMD_H */ diff --git a/trunk/include/linux/mlx4/device.h b/trunk/include/linux/mlx4/device.h index 5f784ff6a36e..ca2c39771c38 100644 --- a/trunk/include/linux/mlx4/device.h +++ b/trunk/include/linux/mlx4/device.h @@ -47,9 +47,6 @@ enum { MLX4_FLAG_MSI_X = 1 << 0, MLX4_FLAG_OLD_PORT_CMDS = 1 << 1, - MLX4_FLAG_MASTER = 1 << 2, - MLX4_FLAG_SLAVE = 1 << 3, - MLX4_FLAG_SRIOV = 1 << 4, }; enum { @@ -60,15 +57,6 @@ enum { MLX4_BOARD_ID_LEN = 64 }; -enum { - MLX4_MAX_NUM_PF = 16, - MLX4_MAX_NUM_VF = 64, - MLX4_MFUNC_MAX = 80, - MLX4_MFUNC_EQ_NUM = 4, - MLX4_MFUNC_MAX_EQES = 8, - MLX4_MFUNC_EQE_MASK = (MLX4_MFUNC_MAX_EQES - 1) -}; - enum { MLX4_DEV_CAP_FLAG_RC = 1LL << 0, MLX4_DEV_CAP_FLAG_UC = 1LL << 1, @@ -129,11 +117,7 @@ enum mlx4_event { MLX4_EVENT_TYPE_PORT_CHANGE = 0x09, MLX4_EVENT_TYPE_EQ_OVERFLOW = 0x0f, MLX4_EVENT_TYPE_ECC_DETECT = 0x0e, - MLX4_EVENT_TYPE_CMD = 0x0a, - MLX4_EVENT_TYPE_VEP_UPDATE = 0x19, - MLX4_EVENT_TYPE_COMM_CHANNEL = 0x18, - MLX4_EVENT_TYPE_FLR_EVENT = 0x1c, - MLX4_EVENT_TYPE_NONE = 0xff, + MLX4_EVENT_TYPE_CMD = 0x0a }; enum { @@ -200,7 +184,6 @@ enum mlx4_qp_region { }; enum mlx4_port_type { - MLX4_PORT_TYPE_NONE = 0, MLX4_PORT_TYPE_IB = 1, MLX4_PORT_TYPE_ETH = 2, MLX4_PORT_TYPE_AUTO = 3 @@ -233,7 +216,6 @@ static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor) struct mlx4_caps { u64 fw_ver; - u32 function; int num_ports; int vl_cap[MLX4_MAX_PORTS + 1]; int ib_mtu_cap[MLX4_MAX_PORTS + 1]; @@ -248,7 +230,6 @@ struct mlx4_caps { u64 trans_code[MLX4_MAX_PORTS + 1]; int local_ca_ack_delay; int num_uars; - u32 uar_page_size; int bf_reg_size; int bf_regs_per_page; int max_sq_sg; @@ -272,7 +253,8 @@ struct mlx4_caps { int num_comp_vectors; int comp_pool; int num_mpts; - int num_mtts; + int num_mtt_segs; + int mtts_per_seg; int fmr_reserved_mtts; int reserved_mtts; int reserved_mrws; @@ -302,7 +284,7 @@ struct mlx4_caps { int log_num_prios; enum mlx4_port_type port_type[MLX4_MAX_PORTS + 1]; u8 supported_type[MLX4_MAX_PORTS + 1]; - u32 port_mask[MLX4_MAX_PORTS + 1]; + u32 port_mask; enum mlx4_port_type possible_type[MLX4_MAX_PORTS + 1]; u32 max_counters; u8 ext_port_cap[MLX4_MAX_PORTS + 1]; @@ -322,7 +304,7 @@ struct mlx4_buf { }; struct mlx4_mtt { - u32 offset; + u32 first_seg; int order; int page_shift; }; @@ -484,12 +466,10 @@ struct mlx4_counter { struct mlx4_dev { struct pci_dev *pdev; unsigned long flags; - unsigned long num_slaves; struct mlx4_caps caps; struct radix_tree_root qp_table_tree; u8 rev_id; char board_id[MLX4_BOARD_ID_LEN]; - int num_vfs; }; struct mlx4_init_port_param { @@ -508,32 +488,14 @@ struct mlx4_init_port_param { #define mlx4_foreach_port(port, dev, type) \ for ((port) = 1; (port) <= (dev)->caps.num_ports; (port)++) \ - if ((type) == (dev)->caps.port_mask[(port)]) - -#define mlx4_foreach_ib_transport_port(port, dev) \ - for ((port) = 1; (port) <= (dev)->caps.num_ports; (port)++) \ - if (((dev)->caps.port_mask[port] == MLX4_PORT_TYPE_IB) || \ - ((dev)->caps.flags & MLX4_DEV_CAP_FLAG_IBOE)) + if (((type) == MLX4_PORT_TYPE_IB ? (dev)->caps.port_mask : \ + ~(dev)->caps.port_mask) & 1 << ((port) - 1)) -static inline int mlx4_is_master(struct mlx4_dev *dev) -{ - return dev->flags & MLX4_FLAG_MASTER; -} - -static inline int mlx4_is_qp_reserved(struct mlx4_dev *dev, u32 qpn) -{ - return (qpn < dev->caps.sqp_start + 8); -} - -static inline int mlx4_is_mfunc(struct mlx4_dev *dev) -{ - return dev->flags & (MLX4_FLAG_SLAVE | MLX4_FLAG_MASTER); -} +#define mlx4_foreach_ib_transport_port(port, dev) \ + for ((port) = 1; (port) <= (dev)->caps.num_ports; (port)++) \ + if (((dev)->caps.port_mask & 1 << ((port) - 1)) || \ + ((dev)->caps.flags & MLX4_DEV_CAP_FLAG_IBOE)) -static inline int mlx4_is_slave(struct mlx4_dev *dev) -{ - return dev->flags & MLX4_FLAG_SLAVE; -} int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct, struct mlx4_buf *buf); @@ -599,10 +561,6 @@ int mlx4_srq_query(struct mlx4_dev *dev, struct mlx4_srq *srq, int *limit_waterm int mlx4_INIT_PORT(struct mlx4_dev *dev, int port); int mlx4_CLOSE_PORT(struct mlx4_dev *dev, int port); -int mlx4_unicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], - int block_mcast_loopback, enum mlx4_protocol prot); -int mlx4_unicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], - enum mlx4_protocol prot); int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], int block_mcast_loopback, enum mlx4_protocol protocol); int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16], @@ -613,11 +571,9 @@ int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port); int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port); int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode); -int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac); -void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac); -int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac); -int mlx4_get_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn); -void mlx4_put_eth_qp(struct mlx4_dev *dev, u8 port, u64 mac, int qpn); +int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap); +void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn); +int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wrap); int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx); int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 6b9d4edb7c26..eef257c76a40 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -55,6 +55,7 @@ #include +struct vlan_group; struct netpoll_info; struct phy_device; /* 802.11 specific */ @@ -791,11 +792,11 @@ struct netdev_tc_txq { * 3. Update dev->stats asynchronously and atomically, and define * neither operation. * - * int (*ndo_vlan_rx_add_vid)(struct net_device *dev, unsigned short vid); + * void (*ndo_vlan_rx_add_vid)(struct net_device *dev, unsigned short vid); * If device support VLAN filtering (dev->features & NETIF_F_HW_VLAN_FILTER) * this function is called when a VLAN id is registered. * - * int (*ndo_vlan_rx_kill_vid)(struct net_device *dev, unsigned short vid); + * void (*ndo_vlan_rx_kill_vid)(struct net_device *dev, unsigned short vid); * If device support VLAN filtering (dev->features & NETIF_F_HW_VLAN_FILTER) * this function is called when a VLAN id is unregistered. * @@ -910,9 +911,9 @@ struct net_device_ops { struct rtnl_link_stats64 *storage); struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); - int (*ndo_vlan_rx_add_vid)(struct net_device *dev, + void (*ndo_vlan_rx_add_vid)(struct net_device *dev, unsigned short vid); - int (*ndo_vlan_rx_kill_vid)(struct net_device *dev, + void (*ndo_vlan_rx_kill_vid)(struct net_device *dev, unsigned short vid); #ifdef CONFIG_NET_POLL_CONTROLLER void (*ndo_poll_controller)(struct net_device *dev); @@ -974,6 +975,7 @@ struct net_device_ops { int (*ndo_set_features)(struct net_device *dev, netdev_features_t features); int (*ndo_neigh_construct)(struct neighbour *n); + void (*ndo_neigh_destroy)(struct neighbour *n); }; /* @@ -1094,7 +1096,7 @@ struct net_device { /* Protocol specific pointers */ #if IS_ENABLED(CONFIG_VLAN_8021Q) - struct vlan_info __rcu *vlan_info; /* VLAN info */ + struct vlan_group __rcu *vlgrp; /* VLAN group */ #endif #if IS_ENABLED(CONFIG_NET_DSA) struct dsa_switch_tree *dsa_ptr; /* dsa specific data */ diff --git a/trunk/include/linux/netlink.h b/trunk/include/linux/netlink.h index 52e48959cfa1..8374d2967362 100644 --- a/trunk/include/linux/netlink.h +++ b/trunk/include/linux/netlink.h @@ -8,7 +8,7 @@ #define NETLINK_UNUSED 1 /* Unused number */ #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ #define NETLINK_FIREWALL 3 /* Firewalling hook */ -#define NETLINK_SOCK_DIAG 4 /* socket monitoring */ +#define NETLINK_INET_DIAG 4 /* INET socket monitoring */ #define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ #define NETLINK_XFRM 6 /* ipsec */ #define NETLINK_SELINUX 7 /* SELinux event notifications */ @@ -27,8 +27,6 @@ #define NETLINK_RDMA 20 #define NETLINK_CRYPTO 21 /* Crypto layer */ -#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG - #define MAX_LINKS 32 struct sockaddr_nl { diff --git a/trunk/include/linux/nl80211.h b/trunk/include/linux/nl80211.h index a18760684fc9..97bfebfcce90 100644 --- a/trunk/include/linux/nl80211.h +++ b/trunk/include/linux/nl80211.h @@ -538,9 +538,6 @@ * OLBC handling in hostapd. Beacons are reported in %NL80211_CMD_FRAME * messages. Note that per PHY only one application may register. * - * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether - * No Acknowledgement Policy should be applied. - * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -678,8 +675,6 @@ enum nl80211_commands { NL80211_CMD_UNEXPECTED_4ADDR_FRAME, - NL80211_CMD_SET_NOACK_MAP, - /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1190,9 +1185,6 @@ enum nl80211_commands { * abides to when initiating radiation on DFS channels. A country maps * to one DFS region. * - * @NL80211_ATTR_NOACK_MAP: This u16 bitmap contains the No Ack Policy of - * up to 16 TIDs. - * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1436,8 +1428,6 @@ enum nl80211_attrs { NL80211_ATTR_DISABLE_HT, NL80211_ATTR_HT_CAPABILITY_MASK, - NL80211_ATTR_NOACK_MAP, - /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -2094,10 +2084,6 @@ enum nl80211_mntr_flags { * access to a broader network beyond the MBSS. This is done via Root * Announcement frames. * - * @NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL: The minimum interval of time (in - * TUs) during which a mesh STA can send only one Action frame containing a - * PERR element. - * * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use @@ -2121,7 +2107,6 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_ELEMENT_TTL, NL80211_MESHCONF_HWMP_RANN_INTERVAL, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, - NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, @@ -2785,11 +2770,9 @@ enum nl80211_ap_sme_features { * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back * TX status to the socket error queue when requested with the * socket option. - * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates. */ enum nl80211_feature_flags { NL80211_FEATURE_SK_TX_STATUS = 1 << 0, - NL80211_FEATURE_HT_IBSS = 1 << 1, }; /** diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index 2aaee0ca9da8..172ba70306d1 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -517,12 +517,8 @@ #define PCI_DEVICE_ID_AMD_11H_NB_DRAM 0x1302 #define PCI_DEVICE_ID_AMD_11H_NB_MISC 0x1303 #define PCI_DEVICE_ID_AMD_11H_NB_LINK 0x1304 -#define PCI_DEVICE_ID_AMD_15H_NB_F0 0x1600 -#define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 -#define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 #define PCI_DEVICE_ID_AMD_15H_NB_F3 0x1603 #define PCI_DEVICE_ID_AMD_15H_NB_F4 0x1604 -#define PCI_DEVICE_ID_AMD_15H_NB_F5 0x1605 #define PCI_DEVICE_ID_AMD_CNB17H_F3 0x1703 #define PCI_DEVICE_ID_AMD_LANCE 0x2000 #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 diff --git a/trunk/include/linux/perf_event.h b/trunk/include/linux/perf_event.h index b1f89122bf6a..1e9ebe5e0091 100644 --- a/trunk/include/linux/perf_event.h +++ b/trunk/include/linux/perf_event.h @@ -822,7 +822,6 @@ struct perf_event { int mmap_locked; struct user_struct *mmap_user; struct ring_buffer *rb; - struct list_head rb_entry; /* poll related */ wait_queue_head_t waitq; diff --git a/trunk/include/linux/pkt_sched.h b/trunk/include/linux/pkt_sched.h index 8daced32a014..fb556dc594d3 100644 --- a/trunk/include/linux/pkt_sched.h +++ b/trunk/include/linux/pkt_sched.h @@ -181,7 +181,6 @@ enum { TCA_RED_UNSPEC, TCA_RED_PARMS, TCA_RED_STAB, - TCA_RED_MAX_P, __TCA_RED_MAX, }; @@ -195,9 +194,8 @@ struct tc_red_qopt { unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ unsigned char Scell_log; /* cell size for idle damping */ unsigned char flags; -#define TC_RED_ECN 1 -#define TC_RED_HARDDROP 2 -#define TC_RED_ADAPTATIVE 4 +#define TC_RED_ECN 1 +#define TC_RED_HARDDROP 2 }; struct tc_red_xstats { @@ -216,7 +214,6 @@ enum { TCA_GRED_PARMS, TCA_GRED_STAB, TCA_GRED_DPS, - TCA_GRED_MAX_P, __TCA_GRED_MAX, }; @@ -256,7 +253,6 @@ enum { TCA_CHOKE_UNSPEC, TCA_CHOKE_PARMS, TCA_CHOKE_STAB, - TCA_CHOKE_MAX_P, __TCA_CHOKE_MAX, }; @@ -502,9 +498,6 @@ struct tc_netem_corrupt { struct tc_netem_rate { __u32 rate; /* byte/s */ - __s32 packet_overhead; - __u32 cell_size; - __s32 cell_overhead; }; enum { diff --git a/trunk/include/linux/sigma.h b/trunk/include/linux/sigma.h index d0de882c0d96..e2accb3164d8 100644 --- a/trunk/include/linux/sigma.h +++ b/trunk/include/linux/sigma.h @@ -24,7 +24,7 @@ struct sigma_firmware { struct sigma_firmware_header { unsigned char magic[7]; u8 version; - __le32 crc; + u32 crc; }; enum { @@ -40,14 +40,19 @@ enum { struct sigma_action { u8 instr; u8 len_hi; - __le16 len; - __be16 addr; + u16 len; + u16 addr; unsigned char payload[]; }; static inline u32 sigma_action_len(struct sigma_action *sa) { - return (sa->len_hi << 16) | le16_to_cpu(sa->len); + return (sa->len_hi << 16) | sa->len; +} + +static inline size_t sigma_action_size(struct sigma_action *sa, u32 payload_len) +{ + return sizeof(*sa) + payload_len + (payload_len % 2); } extern int process_sigma_firmware(struct i2c_client *client, const char *name); diff --git a/trunk/include/linux/sock_diag.h b/trunk/include/linux/sock_diag.h deleted file mode 100644 index 379d5dccf8e1..000000000000 --- a/trunk/include/linux/sock_diag.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __SOCK_DIAG_H__ -#define __SOCK_DIAG_H__ - -#define SOCK_DIAG_BY_FAMILY 20 - -struct sk_buff; -struct nlmsghdr; - -struct sock_diag_req { - __u8 sdiag_family; - __u8 sdiag_protocol; -}; - -struct sock_diag_handler { - __u8 family; - int (*dump)(struct sk_buff *skb, struct nlmsghdr *nlh); -}; - -int sock_diag_register(struct sock_diag_handler *h); -void sock_diag_unregister(struct sock_diag_handler *h); - -void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)); -void sock_diag_unregister_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)); - -int sock_diag_check_cookie(void *sk, __u32 *cookie); -void sock_diag_save_cookie(void *sk, __u32 *cookie); - -extern struct sock *sock_diag_nlsk; -#endif diff --git a/trunk/include/linux/sunrpc/clnt.h b/trunk/include/linux/sunrpc/clnt.h index 2c5993a17c33..f15fd985b08a 100644 --- a/trunk/include/linux/sunrpc/clnt.h +++ b/trunk/include/linux/sunrpc/clnt.h @@ -215,7 +215,7 @@ static inline bool __rpc_copy_addr4(struct sockaddr *dst, return true; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1, const struct sockaddr *sap2) { @@ -240,7 +240,7 @@ static inline bool __rpc_copy_addr6(struct sockaddr *dst, dsin6->sin6_addr = ssin6->sin6_addr; return true; } -#else /* !(IS_ENABLED(CONFIG_IPV6) */ +#else /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */ static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1, const struct sockaddr *sap2) { @@ -252,7 +252,7 @@ static inline bool __rpc_copy_addr6(struct sockaddr *dst, { return false; } -#endif /* !(IS_ENABLED(CONFIG_IPV6) */ +#endif /* !(CONFIG_IPV6 || CONFIG_IPV6_MODULE) */ /** * rpc_cmp_addr - compare the address portion of two sockaddrs. diff --git a/trunk/include/linux/unix_diag.h b/trunk/include/linux/unix_diag.h deleted file mode 100644 index 3f7afb007d70..000000000000 --- a/trunk/include/linux/unix_diag.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __UNIX_DIAG_H__ -#define __UNIX_DIAG_H__ - -struct unix_diag_req { - __u8 sdiag_family; - __u8 sdiag_protocol; - __u16 pad; - __u32 udiag_states; - __u32 udiag_ino; - __u32 udiag_show; - __u32 udiag_cookie[2]; -}; - -#define UDIAG_SHOW_NAME 0x00000001 /* show name (not path) */ -#define UDIAG_SHOW_VFS 0x00000002 /* show VFS inode info */ -#define UDIAG_SHOW_PEER 0x00000004 /* show peer socket info */ -#define UDIAG_SHOW_ICONS 0x00000008 /* show pending connections */ -#define UDIAG_SHOW_RQLEN 0x00000010 /* show skb receive queue len */ - -struct unix_diag_msg { - __u8 udiag_family; - __u8 udiag_type; - __u8 udiag_state; - __u8 pad; - - __u32 udiag_ino; - __u32 udiag_cookie[2]; -}; - -enum { - UNIX_DIAG_NAME, - UNIX_DIAG_VFS, - UNIX_DIAG_PEER, - UNIX_DIAG_ICONS, - UNIX_DIAG_RQLEN, - - UNIX_DIAG_MAX, -}; - -struct unix_diag_vfs { - __u32 udiag_vfs_ino; - __u32 udiag_vfs_dev; -}; - -#endif diff --git a/trunk/include/linux/wl12xx.h b/trunk/include/linux/wl12xx.h index 0d6373195d32..4b697395326e 100644 --- a/trunk/include/linux/wl12xx.h +++ b/trunk/include/linux/wl12xx.h @@ -54,9 +54,6 @@ struct wl12xx_platform_data { int board_ref_clock; int board_tcxo_clock; unsigned long platform_quirks; - bool pwr_in_suspend; - - struct wl1271_if_operations *ops; }; /* Platform does not support level trigger interrupts */ @@ -76,6 +73,6 @@ int wl12xx_set_platform_data(const struct wl12xx_platform_data *data) #endif -struct wl12xx_platform_data *wl12xx_get_platform_data(void); +const struct wl12xx_platform_data *wl12xx_get_platform_data(void); #endif diff --git a/trunk/include/net/af_unix.h b/trunk/include/net/af_unix.h index 63b17816e0ba..91ab5b01678a 100644 --- a/trunk/include/net/af_unix.h +++ b/trunk/include/net/af_unix.h @@ -11,13 +11,10 @@ extern void unix_notinflight(struct file *fp); extern void unix_gc(void); extern void wait_for_unix_gc(void); extern struct sock *unix_get_socket(struct file *filp); -extern struct sock *unix_peer_get(struct sock *); #define UNIX_HASH_SIZE 256 extern unsigned int unix_tot_inflight; -extern spinlock_t unix_table_lock; -extern struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; struct unix_address { atomic_t refcnt; diff --git a/trunk/include/net/bluetooth/bluetooth.h b/trunk/include/net/bluetooth/bluetooth.h index 980e59f37d4f..835f3b229b84 100644 --- a/trunk/include/net/bluetooth/bluetooth.h +++ b/trunk/include/net/bluetooth/bluetooth.h @@ -36,11 +36,6 @@ #define PF_BLUETOOTH AF_BLUETOOTH #endif -/* Bluetooth versions */ -#define BLUETOOTH_VER_1_1 1 -#define BLUETOOTH_VER_1_2 2 -#define BLUETOOTH_VER_2_0 3 - /* Reserv for core and drivers use */ #define BT_SKB_RESERVE 8 diff --git a/trunk/include/net/bluetooth/hci.h b/trunk/include/net/bluetooth/hci.h index 67ad98430348..139ce2aa6eee 100644 --- a/trunk/include/net/bluetooth/hci.h +++ b/trunk/include/net/bluetooth/hci.h @@ -88,14 +88,6 @@ enum { HCI_RESET, }; -/* - * BR/EDR and/or LE controller flags: the flags defined here should represent - * states from the controller. - */ -enum { - HCI_LE_SCAN, -}; - /* HCI ioctl defines */ #define HCIDEVUP _IOW('H', 201, int) #define HCIDEVDOWN _IOW('H', 202, int) @@ -461,14 +453,6 @@ struct hci_rp_user_confirm_reply { #define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d -#define HCI_OP_USER_PASSKEY_REPLY 0x042e -struct hci_cp_user_passkey_reply { - bdaddr_t bdaddr; - __le32 passkey; -} __packed; - -#define HCI_OP_USER_PASSKEY_NEG_REPLY 0x042f - #define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430 struct hci_cp_remote_oob_data_reply { bdaddr_t bdaddr; @@ -685,12 +669,6 @@ struct hci_rp_read_local_oob_data { #define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58 -#define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66 -struct hci_rp_read_flow_control_mode { - __u8 status; - __u8 mode; -} __packed; - #define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d struct hci_cp_write_le_host_supported { __u8 le; @@ -782,15 +760,6 @@ struct hci_rp_le_read_buffer_size { __u8 le_max_pkt; } __packed; -#define HCI_OP_LE_SET_SCAN_PARAM 0x200b -struct hci_cp_le_set_scan_param { - __u8 type; - __le16 interval; - __le16 window; - __u8 own_address_type; - __u8 filter_policy; -} __packed; - #define HCI_OP_LE_SET_SCAN_ENABLE 0x200c struct hci_cp_le_set_scan_enable { __u8 enable; @@ -1107,11 +1076,6 @@ struct hci_ev_user_confirm_req { __le32 passkey; } __packed; -#define HCI_EV_USER_PASSKEY_REQUEST 0x34 -struct hci_ev_user_passkey_req { - bdaddr_t bdaddr; -} __packed; - #define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35 struct hci_ev_remote_oob_data_request { bdaddr_t bdaddr; @@ -1367,6 +1331,4 @@ struct hci_inquiry_req { }; #define IREQ_CACHE_FLUSH 0x0001 -extern int enable_hs; - #endif /* __HCI_H */ diff --git a/trunk/include/net/bluetooth/hci_core.h b/trunk/include/net/bluetooth/hci_core.h index ea4395f1d260..f333e7682607 100644 --- a/trunk/include/net/bluetooth/hci_core.h +++ b/trunk/include/net/bluetooth/hci_core.h @@ -170,8 +170,6 @@ struct hci_dev { __u32 amp_max_flush_to; __u32 amp_be_flush_to; - __u8 flow_ctl_mode; - unsigned int auto_accept_delay; unsigned long quirks; @@ -252,8 +250,6 @@ struct hci_dev { struct module *owner; - unsigned long dev_flags; - int (*open)(struct hci_dev *hdev); int (*close)(struct hci_dev *hdev); int (*flush)(struct hci_dev *hdev); @@ -921,13 +917,11 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable); int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, u8 persistent); -int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, - u8 addr_type); -int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, - u8 addr_type); -int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); -int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, - u8 addr_type, u8 status); +int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); +int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); +int mgmt_disconnect_failed(struct hci_dev *hdev); +int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, + u8 status); int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure); int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); @@ -939,20 +933,14 @@ int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); -int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr); -int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 status); -int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, - bdaddr_t *bdaddr, u8 status); int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, u8 *randomizer, u8 status); -int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, - u8 addr_type, u8 *dev_class, s8 rssi, u8 *eir); +int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, + u8 *dev_class, s8 rssi, u8 *eir); int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name); -int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status); -int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status); +int mgmt_inquiry_failed(struct hci_dev *hdev, u8 status); int mgmt_discovering(struct hci_dev *hdev, u8 discovering); int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr); int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr); diff --git a/trunk/include/net/bluetooth/l2cap.h b/trunk/include/net/bluetooth/l2cap.h index 30719eb2e77c..875021ad0675 100644 --- a/trunk/include/net/bluetooth/l2cap.h +++ b/trunk/include/net/bluetooth/l2cap.h @@ -792,6 +792,7 @@ static inline __u8 __ctrl_size(struct l2cap_chan *chan) } extern int disable_ertm; +extern int enable_hs; int l2cap_init_sockets(void); void l2cap_cleanup_sockets(void); @@ -809,6 +810,5 @@ int l2cap_chan_connect(struct l2cap_chan *chan); int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u32 priority); void l2cap_chan_busy(struct l2cap_chan *chan, int busy); -int l2cap_chan_check_security(struct l2cap_chan *chan); #endif /* __L2CAP_H */ diff --git a/trunk/include/net/bluetooth/mgmt.h b/trunk/include/net/bluetooth/mgmt.h index 3b6880690a78..3e320c9cae8f 100644 --- a/trunk/include/net/bluetooth/mgmt.h +++ b/trunk/include/net/bluetooth/mgmt.h @@ -23,23 +23,6 @@ #define MGMT_INDEX_NONE 0xFFFF -#define MGMT_STATUS_SUCCESS 0x00 -#define MGMT_STATUS_UNKNOWN_COMMAND 0x01 -#define MGMT_STATUS_NOT_CONNECTED 0x02 -#define MGMT_STATUS_FAILED 0x03 -#define MGMT_STATUS_CONNECT_FAILED 0x04 -#define MGMT_STATUS_AUTH_FAILED 0x05 -#define MGMT_STATUS_NOT_PAIRED 0x06 -#define MGMT_STATUS_NO_RESOURCES 0x07 -#define MGMT_STATUS_TIMEOUT 0x08 -#define MGMT_STATUS_ALREADY_CONNECTED 0x09 -#define MGMT_STATUS_BUSY 0x0a -#define MGMT_STATUS_REJECTED 0x0b -#define MGMT_STATUS_NOT_SUPPORTED 0x0c -#define MGMT_STATUS_INVALID_PARAMS 0x0d -#define MGMT_STATUS_DISCONNECTED 0x0e -#define MGMT_STATUS_NOT_POWERED 0x0f - struct mgmt_hdr { __le16 opcode; __le16 index; @@ -136,10 +119,6 @@ struct mgmt_cp_remove_keys { bdaddr_t bdaddr; __u8 disconnect; } __packed; -struct mgmt_rp_remove_keys { - bdaddr_t bdaddr; - __u8 status; -}; #define MGMT_OP_DISCONNECT 0x000F struct mgmt_cp_disconnect { @@ -147,12 +126,11 @@ struct mgmt_cp_disconnect { } __packed; struct mgmt_rp_disconnect { bdaddr_t bdaddr; - __u8 status; } __packed; #define MGMT_ADDR_BREDR 0x00 -#define MGMT_ADDR_LE_PUBLIC 0x01 -#define MGMT_ADDR_LE_RANDOM 0x02 +#define MGMT_ADDR_LE 0x01 +#define MGMT_ADDR_BREDR_LE 0x02 #define MGMT_ADDR_INVALID 0xff struct mgmt_addr_info { @@ -189,11 +167,11 @@ struct mgmt_cp_set_io_capability { #define MGMT_OP_PAIR_DEVICE 0x0014 struct mgmt_cp_pair_device { - struct mgmt_addr_info addr; + bdaddr_t bdaddr; __u8 io_cap; } __packed; struct mgmt_rp_pair_device { - struct mgmt_addr_info addr; + bdaddr_t bdaddr; __u8 status; } __packed; @@ -232,9 +210,6 @@ struct mgmt_cp_remove_remote_oob_data { } __packed; #define MGMT_OP_START_DISCOVERY 0x001B -struct mgmt_cp_start_discovery { - __u8 type; -} __packed; #define MGMT_OP_STOP_DISCOVERY 0x001C @@ -253,17 +228,6 @@ struct mgmt_cp_set_fast_connectable { __u8 enable; } __packed; -#define MGMT_OP_USER_PASSKEY_REPLY 0x0020 -struct mgmt_cp_user_passkey_reply { - bdaddr_t bdaddr; - __le32 passkey; -} __packed; - -#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x0021 -struct mgmt_cp_user_passkey_neg_reply { - bdaddr_t bdaddr; -} __packed; - #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; @@ -358,8 +322,3 @@ struct mgmt_ev_device_blocked { struct mgmt_ev_device_unblocked { bdaddr_t bdaddr; } __packed; - -#define MGMT_EV_USER_PASSKEY_REQUEST 0x0017 -struct mgmt_ev_user_passkey_request { - bdaddr_t bdaddr; -} __packed; diff --git a/trunk/include/net/caif/caif_spi.h b/trunk/include/net/caif/caif_spi.h index aa6a485b0545..87c3d11b8e55 100644 --- a/trunk/include/net/caif/caif_spi.h +++ b/trunk/include/net/caif/caif_spi.h @@ -55,8 +55,8 @@ struct cfspi_xfer { u16 tx_dma_len; u16 rx_dma_len; - void *va_tx[2]; - dma_addr_t pa_tx[2]; + void *va_tx; + dma_addr_t pa_tx; void *va_rx; dma_addr_t pa_rx; }; diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index 3de1c39d03e5..d5e18913f293 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -782,7 +782,6 @@ struct mesh_config { u16 min_discovery_timeout; u32 dot11MeshHWMPactivePathTimeout; u16 dot11MeshHWMPpreqMinInterval; - u16 dot11MeshHWMPperrMinInterval; u16 dot11MeshHWMPnetDiameterTraversalTime; u8 dot11MeshHWMPRootMode; u16 dot11MeshHWMPRannInterval; @@ -803,7 +802,6 @@ struct mesh_config { * @ie_len: length of vendor information elements * @is_authenticated: this mesh requires authentication * @is_secure: this mesh uses security - * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a] * * These parameters are fixed when the mesh is created. */ @@ -816,7 +814,6 @@ struct mesh_setup { u8 ie_len; bool is_authenticated; bool is_secure; - int mcast_rate[IEEE80211_NUM_BANDS]; }; /** @@ -1149,7 +1146,6 @@ struct cfg80211_ibss_params { u8 *ssid; u8 *bssid; struct ieee80211_channel *channel; - enum nl80211_channel_type channel_type; u8 *ie; u8 ssid_len, ie_len; u16 beacon_interval; @@ -1403,8 +1399,7 @@ struct cfg80211_gtk_rekey_data { * have changed. The actual parameter values are available in * struct wiphy. If returning an error, no value should be changed. * - * @set_tx_power: set the transmit power according to the parameters, - * the power passed is in mBm, to get dBm use MBM_TO_DBM(). + * @set_tx_power: set the transmit power according to the parameters * @get_tx_power: store the current TX power into the dbm variable; * return 0 if successful * @@ -1470,8 +1465,6 @@ struct cfg80211_gtk_rekey_data { * * @probe_client: probe an associated client, must return a cookie that it * later passes to cfg80211_probe_status(). - * - * @set_noack_map: Set the NoAck Map for the TIDs. */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); @@ -1665,10 +1658,6 @@ struct cfg80211_ops { int (*probe_client)(struct wiphy *wiphy, struct net_device *dev, const u8 *peer, u64 *cookie); - int (*set_noack_map)(struct wiphy *wiphy, - struct net_device *dev, - u16 noack_map); - struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy); }; @@ -3268,16 +3257,6 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, const u8 *frame, size_t len, int freq, gfp_t gfp); -/* - * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used - * @wiphy: the wiphy - * @chan: main channel - * @channel_type: HT mode - */ -int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type); - /* Logging, debugging and troubleshooting/diagnostic helpers. */ /* wiphy_printk helpers, similar to dev_printk */ diff --git a/trunk/include/net/inet6_hashtables.h b/trunk/include/net/inet6_hashtables.h index 00cbb4384c79..e46674d5daea 100644 --- a/trunk/include/net/inet6_hashtables.h +++ b/trunk/include/net/inet6_hashtables.h @@ -15,7 +15,7 @@ #define _INET6_HASHTABLES_H -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) #include #include #include @@ -110,5 +110,5 @@ extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, const __be16 dport, const int dif); -#endif /* IS_ENABLED(CONFIG_IPV6) */ +#endif /* defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) */ #endif /* _INET6_HASHTABLES_H */ diff --git a/trunk/include/net/inet_sock.h b/trunk/include/net/inet_sock.h index e3e405106afe..f941964a9931 100644 --- a/trunk/include/net/inet_sock.h +++ b/trunk/include/net/inet_sock.h @@ -71,7 +71,7 @@ struct ip_options_data { struct inet_request_sock { struct request_sock req; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) u16 inet6_rsk_offset; #endif __be16 loc_port; @@ -139,7 +139,7 @@ struct rtable; struct inet_sock { /* sk and pinet6 has to be the first two members of inet_sock */ struct sock sk; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct ipv6_pinfo *pinet6; #endif /* Socket demultiplex comparisons on incoming packets. */ @@ -188,7 +188,7 @@ static inline void __inet_sk_copy_descendant(struct sock *sk_to, memcpy(inet_sk(sk_to) + 1, inet_sk(sk_from) + 1, sk_from->sk_prot->obj_size - ancestor_size); } -#if !(IS_ENABLED(CONFIG_IPV6)) +#if !(defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)) static inline void inet_sk_copy_descendant(struct sock *sk_to, const struct sock *sk_from) { diff --git a/trunk/include/net/inet_timewait_sock.h b/trunk/include/net/inet_timewait_sock.h index ba52c830a7a5..e8c25b981205 100644 --- a/trunk/include/net/inet_timewait_sock.h +++ b/trunk/include/net/inet_timewait_sock.h @@ -218,12 +218,20 @@ extern void inet_twsk_purge(struct inet_hashinfo *hashinfo, static inline struct net *twsk_net(const struct inet_timewait_sock *twsk) { - return read_pnet(&twsk->tw_net); +#ifdef CONFIG_NET_NS + return rcu_dereference_raw(twsk->tw_net); /* protected by locking, */ + /* reference counting, */ + /* initialization, or RCU. */ +#else + return &init_net; +#endif } static inline void twsk_net_set(struct inet_timewait_sock *twsk, struct net *net) { - write_pnet(&twsk->tw_net, net); +#ifdef CONFIG_NET_NS + rcu_assign_pointer(twsk->tw_net, net); +#endif } #endif /* _INET_TIMEWAIT_SOCK_ */ diff --git a/trunk/include/net/ip.h b/trunk/include/net/ip.h index 775009f9eaba..fd1561e88a1a 100644 --- a/trunk/include/net/ip.h +++ b/trunk/include/net/ip.h @@ -353,14 +353,14 @@ static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, memcpy(buf, &naddr, sizeof(naddr)); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #include #endif static __inline__ void inet_reset_saddr(struct sock *sk) { inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if (sk->sk_family == PF_INET6) { struct ipv6_pinfo *np = inet6_sk(sk); @@ -379,7 +379,7 @@ static inline int sk_mc_loop(struct sock *sk) switch (sk->sk_family) { case AF_INET: return inet_sk(sk)->mc_loop; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: return inet6_sk(sk)->mc_loop; #endif diff --git a/trunk/include/net/ip6_route.h b/trunk/include/net/ip6_route.h index 789d5f47d5e3..5e91b72fc718 100644 --- a/trunk/include/net/ip6_route.h +++ b/trunk/include/net/ip6_route.h @@ -95,14 +95,14 @@ extern struct rt6_info *rt6_lookup(struct net *net, extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev, struct neighbour *neigh, - struct flowi6 *fl6); + const struct in6_addr *addr); extern int icmp6_dst_gc(void); extern void fib6_force_start_gc(struct net *net); extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, const struct in6_addr *addr, - bool anycast); + int anycast); extern int ip6_dst_hoplimit(struct dst_entry *dst); diff --git a/trunk/include/net/neighbour.h b/trunk/include/net/neighbour.h index 6814c4d61c1c..e31f0a86f9b7 100644 --- a/trunk/include/net/neighbour.h +++ b/trunk/include/net/neighbour.h @@ -43,6 +43,7 @@ struct neigh_parms { #endif struct net_device *dev; struct neigh_parms *next; + int (*neigh_setup)(struct neighbour *); void (*neigh_cleanup)(struct neighbour *); struct neigh_table *tbl; diff --git a/trunk/include/net/net_namespace.h b/trunk/include/net/net_namespace.h index ee547c149810..3bb6fa0eace0 100644 --- a/trunk/include/net/net_namespace.h +++ b/trunk/include/net/net_namespace.h @@ -77,7 +77,7 @@ struct net { struct netns_packet packet; struct netns_unix unx; struct netns_ipv4 ipv4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct netns_ipv6 ipv6; #endif #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) diff --git a/trunk/include/net/netfilter/nf_tproxy_core.h b/trunk/include/net/netfilter/nf_tproxy_core.h index 75ca9291cf2c..e505358d8999 100644 --- a/trunk/include/net/netfilter/nf_tproxy_core.h +++ b/trunk/include/net/netfilter/nf_tproxy_core.h @@ -131,7 +131,7 @@ nf_tproxy_get_sock_v4(struct net *net, const u8 protocol, return sk; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static inline struct sock * nf_tproxy_get_sock_v6(struct net *net, const u8 protocol, const struct in6_addr *saddr, const struct in6_addr *daddr, diff --git a/trunk/include/net/netns/ipv4.h b/trunk/include/net/netns/ipv4.h index bbd023a1c9b9..d786b4fc02a4 100644 --- a/trunk/include/net/netns/ipv4.h +++ b/trunk/include/net/netns/ipv4.h @@ -55,7 +55,6 @@ struct netns_ipv4 { int current_rt_cache_rebuild_count; unsigned int sysctl_ping_group_range[2]; - long sysctl_tcp_mem[3]; atomic_t rt_genid; atomic_t dev_addr_genid; diff --git a/trunk/include/net/netns/mib.h b/trunk/include/net/netns/mib.h index d542a4b28cca..30f6728ee98c 100644 --- a/trunk/include/net/netns/mib.h +++ b/trunk/include/net/netns/mib.h @@ -12,7 +12,7 @@ struct netns_mib { DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics); DEFINE_SNMP_STAT_ATOMIC(struct icmpmsg_mib, icmpmsg_statistics); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct proc_dir_entry *proc_net_devsnmp6; DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6); DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6); diff --git a/trunk/include/net/netns/xfrm.h b/trunk/include/net/netns/xfrm.h index 5299e69a32af..748f91f87cd5 100644 --- a/trunk/include/net/netns/xfrm.h +++ b/trunk/include/net/netns/xfrm.h @@ -56,7 +56,7 @@ struct netns_xfrm { #endif struct dst_ops xfrm4_dst_ops; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct dst_ops xfrm6_dst_ops; #endif }; diff --git a/trunk/include/net/protocol.h b/trunk/include/net/protocol.h index 875f4895b033..e182e13d6391 100644 --- a/trunk/include/net/protocol.h +++ b/trunk/include/net/protocol.h @@ -25,7 +25,7 @@ #define _PROTOCOL_H #include -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) #include #endif @@ -46,7 +46,7 @@ struct net_protocol { netns_ok:1; }; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) struct inet6_protocol { int (*handler)(struct sk_buff *skb); @@ -91,7 +91,7 @@ struct inet_protosw { extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS]; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS]; #endif @@ -100,7 +100,7 @@ extern int inet_del_protocol(const struct net_protocol *prot, unsigned char num) extern void inet_register_protosw(struct inet_protosw *p); extern void inet_unregister_protosw(struct inet_protosw *p); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) extern int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num); extern int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num); extern int inet6_register_protosw(struct inet_protosw *p); diff --git a/trunk/include/net/red.h b/trunk/include/net/red.h index ef715a16cce4..b72a3b833936 100644 --- a/trunk/include/net/red.h +++ b/trunk/include/net/red.h @@ -5,7 +5,6 @@ #include #include #include -#include /* Random Early Detection (RED) algorithm. ======================================= @@ -88,29 +87,6 @@ etc. */ -/* - * Adaptative RED : An Algorithm for Increasing the Robustness of RED's AQM - * (Sally FLoyd, Ramakrishna Gummadi, and Scott Shenker) August 2001 - * - * Every 500 ms: - * if (avg > target and max_p <= 0.5) - * increase max_p : max_p += alpha; - * else if (avg < target and max_p >= 0.01) - * decrease max_p : max_p *= beta; - * - * target :[qth_min + 0.4*(qth_min - qth_max), - * qth_min + 0.6*(qth_min - qth_max)]. - * alpha : min(0.01, max_p / 4) - * beta : 0.9 - * max_P is a Q0.32 fixed point number (with 32 bits mantissa) - * max_P between 0.01 and 0.5 (1% - 50%) [ Its no longer a negative power of two ] - */ -#define RED_ONE_PERCENT ((u32)DIV_ROUND_CLOSEST(1ULL<<32, 100)) - -#define MAX_P_MIN (1 * RED_ONE_PERCENT) -#define MAX_P_MAX (50 * RED_ONE_PERCENT) -#define MAX_P_ALPHA(val) min(MAX_P_MIN, val / 4) - #define RED_STAB_SIZE 256 #define RED_STAB_MASK (RED_STAB_SIZE - 1) @@ -125,14 +101,10 @@ struct red_stats { struct red_parms { /* Parameters */ - u32 qth_min; /* Min avg length threshold: Wlog scaled */ - u32 qth_max; /* Max avg length threshold: Wlog scaled */ + u32 qth_min; /* Min avg length threshold: A scaled */ + u32 qth_max; /* Max avg length threshold: A scaled */ u32 Scell_max; - u32 max_P; /* probability, [0 .. 1.0] 32 scaled */ - u32 max_P_reciprocal; /* reciprocal_value(max_P / qth_delta) */ - u32 qth_delta; /* max_th - min_th */ - u32 target_min; /* min_th + 0.4*(max_th - min_th) */ - u32 target_max; /* min_th + 0.6*(max_th - min_th) */ + u32 Rmask; /* Cached random mask, see red_rmask */ u8 Scell_log; u8 Wlog; /* log(W) */ u8 Plog; /* random number bits */ @@ -143,23 +115,19 @@ struct red_parms { number generation */ u32 qR; /* Cached random number */ - unsigned long qavg; /* Average queue length: Wlog scaled */ + unsigned long qavg; /* Average queue length: A scaled */ ktime_t qidlestart; /* Start of current idle period */ }; -static inline u32 red_maxp(u8 Plog) +static inline u32 red_rmask(u8 Plog) { - return Plog < 32 ? (~0U >> Plog) : ~0U; + return Plog < 32 ? ((1 << Plog) - 1) : ~0UL; } - static inline void red_set_parms(struct red_parms *p, u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog, - u8 Scell_log, u8 *stab, u32 max_P) + u8 Scell_log, u8 *stab) { - int delta = qth_max - qth_min; - u32 max_p_delta; - /* Reset average queue length, the value is strictly bound * to the parameters below, reseting hurts a bit but leaving * it might result in an unreasonable qavg for a while. --TGR @@ -171,33 +139,14 @@ static inline void red_set_parms(struct red_parms *p, p->qth_max = qth_max << Wlog; p->Wlog = Wlog; p->Plog = Plog; - if (delta < 0) - delta = 1; - p->qth_delta = delta; - if (!max_P) { - max_P = red_maxp(Plog); - max_P *= delta; /* max_P = (qth_max - qth_min)/2^Plog */ - } - p->max_P = max_P; - max_p_delta = max_P / delta; - max_p_delta = max(max_p_delta, 1U); - p->max_P_reciprocal = reciprocal_value(max_p_delta); - - /* RED Adaptative target : - * [min_th + 0.4*(min_th - max_th), - * min_th + 0.6*(min_th - max_th)]. - */ - delta /= 5; - p->target_min = qth_min + 2*delta; - p->target_max = qth_min + 3*delta; - + p->Rmask = red_rmask(Plog); p->Scell_log = Scell_log; p->Scell_max = (255 << Scell_log); memcpy(p->Stab, stab, sizeof(p->Stab)); } -static inline int red_is_idling(const struct red_parms *p) +static inline int red_is_idling(struct red_parms *p) { return p->qidlestart.tv64 != 0; } @@ -219,7 +168,7 @@ static inline void red_restart(struct red_parms *p) p->qcount = -1; } -static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms *p) +static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p) { s64 delta = ktime_us_delta(ktime_get(), p->qidlestart); long us_idle = min_t(s64, delta, p->Scell_max); @@ -266,7 +215,7 @@ static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms } } -static inline unsigned long red_calc_qavg_no_idle_time(const struct red_parms *p, +static inline unsigned long red_calc_qavg_no_idle_time(struct red_parms *p, unsigned int backlog) { /* @@ -281,7 +230,7 @@ static inline unsigned long red_calc_qavg_no_idle_time(const struct red_parms *p return p->qavg + (backlog - (p->qavg >> p->Wlog)); } -static inline unsigned long red_calc_qavg(const struct red_parms *p, +static inline unsigned long red_calc_qavg(struct red_parms *p, unsigned int backlog) { if (!red_is_idling(p)) @@ -290,24 +239,23 @@ static inline unsigned long red_calc_qavg(const struct red_parms *p, return red_calc_qavg_from_idle_time(p); } - -static inline u32 red_random(const struct red_parms *p) +static inline u32 red_random(struct red_parms *p) { - return reciprocal_divide(net_random(), p->max_P_reciprocal); + return net_random() & p->Rmask; } -static inline int red_mark_probability(const struct red_parms *p, unsigned long qavg) +static inline int red_mark_probability(struct red_parms *p, unsigned long qavg) { /* The formula used below causes questions. - OK. qR is random number in the interval - (0..1/max_P)*(qth_max-qth_min) + OK. qR is random number in the interval 0..Rmask i.e. 0..(2^Plog). If we used floating point arithmetics, it would be: (2^Plog)*rnd_num, where rnd_num is less 1. Taking into account, that qavg have fixed - point at Wlog, two lines + point at Wlog, and Plog is related to max_P by + max_P = (qth_max-qth_min)/2^Plog; two lines below have the following floating point equivalent: max_P*(qavg - qth_min)/(qth_max-qth_min) < rnd/qcount @@ -367,25 +315,4 @@ static inline int red_action(struct red_parms *p, unsigned long qavg) return RED_DONT_MARK; } -static inline void red_adaptative_algo(struct red_parms *p) -{ - unsigned long qavg; - u32 max_p_delta; - - qavg = p->qavg; - if (red_is_idling(p)) - qavg = red_calc_qavg_from_idle_time(p); - - /* p->qavg is fixed point number with point at Wlog */ - qavg >>= p->Wlog; - - if (qavg > p->target_max && p->max_P <= MAX_P_MAX) - p->max_P += MAX_P_ALPHA(p->max_P); /* maxp = maxp + alpha */ - else if (qavg < p->target_min && p->max_P >= MAX_P_MIN) - p->max_P = (p->max_P/10)*9; /* maxp = maxp * Beta */ - - max_p_delta = DIV_ROUND_CLOSEST(p->max_P, p->qth_delta); - max_p_delta = max(max_p_delta, 1U); - p->max_P_reciprocal = reciprocal_value(max_p_delta); -} #endif diff --git a/trunk/include/net/sctp/sctp.h b/trunk/include/net/sctp/sctp.h index d3685615a8b0..6a72a58cde59 100644 --- a/trunk/include/net/sctp/sctp.h +++ b/trunk/include/net/sctp/sctp.h @@ -71,7 +71,7 @@ #include #include -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #include #include #endif @@ -383,7 +383,7 @@ static inline void sctp_sysctl_unregister(void) { return; } /* Size of Supported Address Parameter for 'x' address types. */ #define SCTP_SAT_LEN(x) (sizeof(struct sctp_paramhdr) + (x) * sizeof(__u16)) -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) void sctp_v6_pf_init(void); void sctp_v6_pf_exit(void); diff --git a/trunk/include/net/sctp/structs.h b/trunk/include/net/sctp/structs.h index ad0e31bf7450..3382615bd710 100644 --- a/trunk/include/net/sctp/structs.h +++ b/trunk/include/net/sctp/structs.h @@ -365,7 +365,7 @@ static inline struct sock *sctp_opt2sk(const struct sctp_sock *sp) return (struct sock *)sp; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct sctp6_sock { struct sctp_sock sctp; struct ipv6_pinfo inet6; diff --git a/trunk/include/net/sock.h b/trunk/include/net/sock.h index 6fe0dae81451..8ac338cb39ce 100644 --- a/trunk/include/net/sock.h +++ b/trunk/include/net/sock.h @@ -53,8 +53,6 @@ #include #include #include -#include -#include #include #include @@ -64,10 +62,6 @@ #include #include -struct cgroup; -struct cgroup_subsys; -int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss); -void mem_cgroup_sockets_destroy(struct cgroup *cgrp, struct cgroup_subsys *ss); /* * This structure really needs to be cleaned up. * Most of it is for TCP, and not used by any of @@ -173,7 +167,6 @@ struct sock_common { /* public: */ }; -struct cg_proto; /** * struct sock - network layer representation of sockets * @__sk_common: shared layout with inet_timewait_sock @@ -234,7 +227,6 @@ struct cg_proto; * @sk_security: used by security modules * @sk_mark: generic packet mark * @sk_classid: this socket's cgroup classid - * @sk_cgrp: this socket's cgroup-specific proto data * @sk_write_pending: a write to stream socket waits to start * @sk_state_change: callback to indicate change in the state of the sock * @sk_data_ready: callback to indicate there is data to be processed @@ -349,7 +341,6 @@ struct sock { #endif __u32 sk_mark; u32 sk_classid; - struct cg_proto *sk_cgrp; void (*sk_state_change)(struct sock *sk); void (*sk_data_ready)(struct sock *sk, int bytes); void (*sk_write_space)(struct sock *sk); @@ -846,37 +837,6 @@ struct proto { #ifdef SOCK_REFCNT_DEBUG atomic_t socks; #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM - /* - * cgroup specific init/deinit functions. Called once for all - * protocols that implement it, from cgroups populate function. - * This function has to setup any files the protocol want to - * appear in the kmem cgroup filesystem. - */ - int (*init_cgroup)(struct cgroup *cgrp, - struct cgroup_subsys *ss); - void (*destroy_cgroup)(struct cgroup *cgrp, - struct cgroup_subsys *ss); - struct cg_proto *(*proto_cgroup)(struct mem_cgroup *memcg); -#endif -}; - -struct cg_proto { - void (*enter_memory_pressure)(struct sock *sk); - struct res_counter *memory_allocated; /* Current allocated memory. */ - struct percpu_counter *sockets_allocated; /* Current number of sockets. */ - int *memory_pressure; - long *sysctl_mem; - /* - * memcg field is used to find which memcg we belong directly - * Each memcg struct can hold more than one cg_proto, so container_of - * won't really cut. - * - * The elegant solution would be having an inverse function to - * proto_cgroup in struct proto, but that means polluting the structure - * for everybody, instead of just for memcg users. - */ - struct mem_cgroup *memcg; }; extern int proto_register(struct proto *prot, int alloc_slab); @@ -895,7 +855,7 @@ static inline void sk_refcnt_debug_dec(struct sock *sk) sk->sk_prot->name, sk, atomic_read(&sk->sk_prot->socks)); } -inline void sk_refcnt_debug_release(const struct sock *sk) +static inline void sk_refcnt_debug_release(const struct sock *sk) { if (atomic_read(&sk->sk_refcnt) != 1) printk(KERN_DEBUG "Destruction of the %s socket %p delayed, refcnt=%d\n", @@ -907,208 +867,6 @@ inline void sk_refcnt_debug_release(const struct sock *sk) #define sk_refcnt_debug_release(sk) do { } while (0) #endif /* SOCK_REFCNT_DEBUG */ -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM -extern struct jump_label_key memcg_socket_limit_enabled; -static inline struct cg_proto *parent_cg_proto(struct proto *proto, - struct cg_proto *cg_proto) -{ - return proto->proto_cgroup(parent_mem_cgroup(cg_proto->memcg)); -} -#define mem_cgroup_sockets_enabled static_branch(&memcg_socket_limit_enabled) -#else -#define mem_cgroup_sockets_enabled 0 -static inline struct cg_proto *parent_cg_proto(struct proto *proto, - struct cg_proto *cg_proto) -{ - return NULL; -} -#endif - - -static inline bool sk_has_memory_pressure(const struct sock *sk) -{ - return sk->sk_prot->memory_pressure != NULL; -} - -static inline bool sk_under_memory_pressure(const struct sock *sk) -{ - if (!sk->sk_prot->memory_pressure) - return false; - - if (mem_cgroup_sockets_enabled && sk->sk_cgrp) - return !!*sk->sk_cgrp->memory_pressure; - - return !!*sk->sk_prot->memory_pressure; -} - -static inline void sk_leave_memory_pressure(struct sock *sk) -{ - int *memory_pressure = sk->sk_prot->memory_pressure; - - if (!memory_pressure) - return; - - if (*memory_pressure) - *memory_pressure = 0; - - if (mem_cgroup_sockets_enabled && sk->sk_cgrp) { - struct cg_proto *cg_proto = sk->sk_cgrp; - struct proto *prot = sk->sk_prot; - - for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto)) - if (*cg_proto->memory_pressure) - *cg_proto->memory_pressure = 0; - } - -} - -static inline void sk_enter_memory_pressure(struct sock *sk) -{ - if (!sk->sk_prot->enter_memory_pressure) - return; - - if (mem_cgroup_sockets_enabled && sk->sk_cgrp) { - struct cg_proto *cg_proto = sk->sk_cgrp; - struct proto *prot = sk->sk_prot; - - for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto)) - cg_proto->enter_memory_pressure(sk); - } - - sk->sk_prot->enter_memory_pressure(sk); -} - -static inline long sk_prot_mem_limits(const struct sock *sk, int index) -{ - long *prot = sk->sk_prot->sysctl_mem; - if (mem_cgroup_sockets_enabled && sk->sk_cgrp) - prot = sk->sk_cgrp->sysctl_mem; - return prot[index]; -} - -static inline void memcg_memory_allocated_add(struct cg_proto *prot, - unsigned long amt, - int *parent_status) -{ - struct res_counter *fail; - int ret; - - ret = res_counter_charge(prot->memory_allocated, - amt << PAGE_SHIFT, &fail); - - if (ret < 0) - *parent_status = OVER_LIMIT; -} - -static inline void memcg_memory_allocated_sub(struct cg_proto *prot, - unsigned long amt) -{ - res_counter_uncharge(prot->memory_allocated, amt << PAGE_SHIFT); -} - -static inline u64 memcg_memory_allocated_read(struct cg_proto *prot) -{ - u64 ret; - ret = res_counter_read_u64(prot->memory_allocated, RES_USAGE); - return ret >> PAGE_SHIFT; -} - -static inline long -sk_memory_allocated(const struct sock *sk) -{ - struct proto *prot = sk->sk_prot; - if (mem_cgroup_sockets_enabled && sk->sk_cgrp) - return memcg_memory_allocated_read(sk->sk_cgrp); - - return atomic_long_read(prot->memory_allocated); -} - -static inline long -sk_memory_allocated_add(struct sock *sk, int amt, int *parent_status) -{ - struct proto *prot = sk->sk_prot; - - if (mem_cgroup_sockets_enabled && sk->sk_cgrp) { - memcg_memory_allocated_add(sk->sk_cgrp, amt, parent_status); - /* update the root cgroup regardless */ - atomic_long_add_return(amt, prot->memory_allocated); - return memcg_memory_allocated_read(sk->sk_cgrp); - } - - return atomic_long_add_return(amt, prot->memory_allocated); -} - -static inline void -sk_memory_allocated_sub(struct sock *sk, int amt, int parent_status) -{ - struct proto *prot = sk->sk_prot; - - if (mem_cgroup_sockets_enabled && sk->sk_cgrp && - parent_status != OVER_LIMIT) /* Otherwise was uncharged already */ - memcg_memory_allocated_sub(sk->sk_cgrp, amt); - - atomic_long_sub(amt, prot->memory_allocated); -} - -static inline void sk_sockets_allocated_dec(struct sock *sk) -{ - struct proto *prot = sk->sk_prot; - - if (mem_cgroup_sockets_enabled && sk->sk_cgrp) { - struct cg_proto *cg_proto = sk->sk_cgrp; - - for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto)) - percpu_counter_dec(cg_proto->sockets_allocated); - } - - percpu_counter_dec(prot->sockets_allocated); -} - -static inline void sk_sockets_allocated_inc(struct sock *sk) -{ - struct proto *prot = sk->sk_prot; - - if (mem_cgroup_sockets_enabled && sk->sk_cgrp) { - struct cg_proto *cg_proto = sk->sk_cgrp; - - for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto)) - percpu_counter_inc(cg_proto->sockets_allocated); - } - - percpu_counter_inc(prot->sockets_allocated); -} - -static inline int -sk_sockets_allocated_read_positive(struct sock *sk) -{ - struct proto *prot = sk->sk_prot; - - if (mem_cgroup_sockets_enabled && sk->sk_cgrp) - return percpu_counter_sum_positive(sk->sk_cgrp->sockets_allocated); - - return percpu_counter_sum_positive(prot->sockets_allocated); -} - -static inline int -proto_sockets_allocated_sum_positive(struct proto *prot) -{ - return percpu_counter_sum_positive(prot->sockets_allocated); -} - -static inline long -proto_memory_allocated(struct proto *prot) -{ - return atomic_long_read(prot->memory_allocated); -} - -static inline bool -proto_memory_pressure(struct proto *prot) -{ - if (!prot->memory_pressure) - return false; - return !!*prot->memory_pressure; -} - #ifdef CONFIG_PROC_FS /* Called with local bh disabled */ @@ -1916,7 +1674,7 @@ static inline struct page *sk_stream_alloc_page(struct sock *sk) page = alloc_pages(sk->sk_allocation, 0); if (!page) { - sk_enter_memory_pressure(sk); + sk->sk_prot->enter_memory_pressure(sk); sk_stream_moderate_sndbuf(sk); } return page; diff --git a/trunk/include/net/tcp.h b/trunk/include/net/tcp.h index a4f52e154843..87e3c80bfa00 100644 --- a/trunk/include/net/tcp.h +++ b/trunk/include/net/tcp.h @@ -44,7 +44,6 @@ #include #include -#include extern struct inet_hashinfo tcp_hashinfo; @@ -230,6 +229,7 @@ extern int sysctl_tcp_fack; extern int sysctl_tcp_reordering; extern int sysctl_tcp_ecn; extern int sysctl_tcp_dsack; +extern long sysctl_tcp_mem[3]; extern int sysctl_tcp_wmem[3]; extern int sysctl_tcp_rmem[3]; extern int sysctl_tcp_app_win; @@ -285,7 +285,7 @@ static inline bool tcp_too_many_orphans(struct sock *sk, int shift) } if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF && - sk_memory_allocated(sk) > sk_prot_mem_limits(sk, 2)) + atomic_long_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]) return true; return false; } @@ -628,7 +628,7 @@ extern u32 __tcp_select_window(struct sock *sk); struct tcp_skb_cb { union { struct inet_skb_parm h4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) struct inet6_skb_parm h6; #endif } header; /* For incoming frames */ @@ -1152,7 +1152,7 @@ struct tcp6_md5sig_key { /* - sock block */ struct tcp_md5sig_info { struct tcp4_md5sig_key *keys4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct tcp6_md5sig_key *keys6; u32 entries6; u32 alloced6; @@ -1179,7 +1179,7 @@ struct tcp6_pseudohdr { union tcp_md5sum_block { struct tcp4_pseudohdr ip4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct tcp6_pseudohdr ip6; #endif }; diff --git a/trunk/include/net/tcp_memcontrol.h b/trunk/include/net/tcp_memcontrol.h deleted file mode 100644 index 3512082fa909..000000000000 --- a/trunk/include/net/tcp_memcontrol.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _TCP_MEMCG_H -#define _TCP_MEMCG_H - -struct tcp_memcontrol { - struct cg_proto cg_proto; - /* per-cgroup tcp memory pressure knobs */ - struct res_counter tcp_memory_allocated; - struct percpu_counter tcp_sockets_allocated; - /* those two are read-mostly, leave them at the end */ - long tcp_prot_mem[3]; - int tcp_memory_pressure; -}; - -struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg); -int tcp_init_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss); -void tcp_destroy_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss); -unsigned long long tcp_max_memory(const struct mem_cgroup *memcg); -void tcp_prot_mem(struct mem_cgroup *memcg, long val, int idx); -#endif /* _TCP_MEMCG_H */ diff --git a/trunk/include/net/udp.h b/trunk/include/net/udp.h index e39592f682c3..f54a5156b248 100644 --- a/trunk/include/net/udp.h +++ b/trunk/include/net/udp.h @@ -41,7 +41,7 @@ struct udp_skb_cb { union { struct inet_skb_parm h4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) struct inet6_skb_parm h6; #endif } header; @@ -194,15 +194,9 @@ extern int udp_lib_setsockopt(struct sock *sk, int level, int optname, extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, __be32 daddr, __be16 dport, int dif); -extern struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, - __be32 daddr, __be16 dport, - int dif, struct udp_table *tbl); extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, __be16 dport, int dif); -extern struct sock *__udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, - const struct in6_addr *daddr, __be16 dport, - int dif, struct udp_table *tbl); /* * SNMP statistics for UDP and UDP-Lite @@ -223,7 +217,7 @@ extern struct sock *__udp6_lib_lookup(struct net *net, const struct in6_addr *sa else SNMP_INC_STATS_USER((net)->mib.udp_stats_in6, field); \ } while(0) -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #define UDPX_INC_STATS_BH(sk, field) \ do { \ if ((sk)->sk_family == AF_INET) \ diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index b8930d5a8325..43298f9810fb 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -689,17 +689,6 @@ config CGROUP_MEM_RES_CTLR_SWAP_ENABLED For those who want to have the feature enabled by default should select this option (if, for some reason, they need to disable it then swapaccount=0 does the trick). -config CGROUP_MEM_RES_CTLR_KMEM - bool "Memory Resource Controller Kernel Memory accounting (EXPERIMENTAL)" - depends on CGROUP_MEM_RES_CTLR && EXPERIMENTAL - default n - help - The Kernel Memory extension for Memory Resource Controller can limit - the amount of memory used by kernel objects in the system. Those are - fundamentally different from the entities handled by the standard - Memory Controller, which are page-based, and can be swapped. Users of - the kmem extension can use it to guarantee that no group of processes - will ever exhaust kernel resources alone. config CGROUP_PERF bool "Enable perf_event per-cpu per-container group (cgroup) monitoring" diff --git a/trunk/kernel/events/core.c b/trunk/kernel/events/core.c index 600c1629b64d..0e8457da6f95 100644 --- a/trunk/kernel/events/core.c +++ b/trunk/kernel/events/core.c @@ -185,9 +185,6 @@ static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx, static void update_context_time(struct perf_event_context *ctx); static u64 perf_event_time(struct perf_event *event); -static void ring_buffer_attach(struct perf_event *event, - struct ring_buffer *rb); - void __weak perf_event_print_debug(void) { } extern __weak const char *perf_pmu_name(void) @@ -2176,8 +2173,7 @@ static void perf_event_context_sched_in(struct perf_event_context *ctx, perf_event_sched_in(cpuctx, ctx, task); - if (ctx->nr_events) - cpuctx->task_ctx = ctx; + cpuctx->task_ctx = ctx; perf_pmu_enable(ctx->pmu); perf_ctx_unlock(cpuctx, ctx); @@ -3194,33 +3190,12 @@ static unsigned int perf_poll(struct file *file, poll_table *wait) struct ring_buffer *rb; unsigned int events = POLL_HUP; - /* - * Race between perf_event_set_output() and perf_poll(): perf_poll() - * grabs the rb reference but perf_event_set_output() overrides it. - * Here is the timeline for two threads T1, T2: - * t0: T1, rb = rcu_dereference(event->rb) - * t1: T2, old_rb = event->rb - * t2: T2, event->rb = new rb - * t3: T2, ring_buffer_detach(old_rb) - * t4: T1, ring_buffer_attach(rb1) - * t5: T1, poll_wait(event->waitq) - * - * To avoid this problem, we grab mmap_mutex in perf_poll() - * thereby ensuring that the assignment of the new ring buffer - * and the detachment of the old buffer appear atomic to perf_poll() - */ - mutex_lock(&event->mmap_mutex); - rcu_read_lock(); rb = rcu_dereference(event->rb); - if (rb) { - ring_buffer_attach(event, rb); + if (rb) events = atomic_xchg(&rb->poll, 0); - } rcu_read_unlock(); - mutex_unlock(&event->mmap_mutex); - poll_wait(file, &event->waitq, wait); return events; @@ -3521,49 +3496,6 @@ static int perf_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) return ret; } -static void ring_buffer_attach(struct perf_event *event, - struct ring_buffer *rb) -{ - unsigned long flags; - - if (!list_empty(&event->rb_entry)) - return; - - spin_lock_irqsave(&rb->event_lock, flags); - if (!list_empty(&event->rb_entry)) - goto unlock; - - list_add(&event->rb_entry, &rb->event_list); -unlock: - spin_unlock_irqrestore(&rb->event_lock, flags); -} - -static void ring_buffer_detach(struct perf_event *event, - struct ring_buffer *rb) -{ - unsigned long flags; - - if (list_empty(&event->rb_entry)) - return; - - spin_lock_irqsave(&rb->event_lock, flags); - list_del_init(&event->rb_entry); - wake_up_all(&event->waitq); - spin_unlock_irqrestore(&rb->event_lock, flags); -} - -static void ring_buffer_wakeup(struct perf_event *event) -{ - struct ring_buffer *rb; - - rcu_read_lock(); - rb = rcu_dereference(event->rb); - list_for_each_entry_rcu(event, &rb->event_list, rb_entry) { - wake_up_all(&event->waitq); - } - rcu_read_unlock(); -} - static void rb_free_rcu(struct rcu_head *rcu_head) { struct ring_buffer *rb; @@ -3589,19 +3521,9 @@ static struct ring_buffer *ring_buffer_get(struct perf_event *event) static void ring_buffer_put(struct ring_buffer *rb) { - struct perf_event *event, *n; - unsigned long flags; - if (!atomic_dec_and_test(&rb->refcount)) return; - spin_lock_irqsave(&rb->event_lock, flags); - list_for_each_entry_safe(event, n, &rb->event_list, rb_entry) { - list_del_init(&event->rb_entry); - wake_up_all(&event->waitq); - } - spin_unlock_irqrestore(&rb->event_lock, flags); - call_rcu(&rb->rcu_head, rb_free_rcu); } @@ -3624,7 +3546,6 @@ static void perf_mmap_close(struct vm_area_struct *vma) atomic_long_sub((size >> PAGE_SHIFT) + 1, &user->locked_vm); vma->vm_mm->pinned_vm -= event->mmap_locked; rcu_assign_pointer(event->rb, NULL); - ring_buffer_detach(event, rb); mutex_unlock(&event->mmap_mutex); ring_buffer_put(rb); @@ -3779,7 +3700,7 @@ static const struct file_operations perf_fops = { void perf_event_wakeup(struct perf_event *event) { - ring_buffer_wakeup(event); + wake_up_all(&event->waitq); if (event->pending_kill) { kill_fasync(&event->fasync, SIGIO, event->pending_kill); @@ -5901,8 +5822,6 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, INIT_LIST_HEAD(&event->group_entry); INIT_LIST_HEAD(&event->event_entry); INIT_LIST_HEAD(&event->sibling_list); - INIT_LIST_HEAD(&event->rb_entry); - init_waitqueue_head(&event->waitq); init_irq_work(&event->pending, perf_pending_event); @@ -6109,8 +6028,6 @@ perf_event_set_output(struct perf_event *event, struct perf_event *output_event) old_rb = event->rb; rcu_assign_pointer(event->rb, rb); - if (old_rb) - ring_buffer_detach(event, old_rb); ret = 0; unlock: mutex_unlock(&event->mmap_mutex); diff --git a/trunk/kernel/events/internal.h b/trunk/kernel/events/internal.h index 64568a699375..09097dd8116c 100644 --- a/trunk/kernel/events/internal.h +++ b/trunk/kernel/events/internal.h @@ -22,9 +22,6 @@ struct ring_buffer { local_t lost; /* nr records lost */ long watermark; /* wakeup watermark */ - /* poll crap */ - spinlock_t event_lock; - struct list_head event_list; struct perf_event_mmap_page *user_page; void *data_pages[0]; diff --git a/trunk/kernel/events/ring_buffer.c b/trunk/kernel/events/ring_buffer.c index 7f3011c6b57f..a2a29205cc0f 100644 --- a/trunk/kernel/events/ring_buffer.c +++ b/trunk/kernel/events/ring_buffer.c @@ -209,9 +209,6 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) rb->writable = 1; atomic_set(&rb->refcount, 1); - - INIT_LIST_HEAD(&rb->event_list); - spin_lock_init(&rb->event_lock); } #ifndef CONFIG_PERF_USE_VMALLOC diff --git a/trunk/kernel/irq/manage.c b/trunk/kernel/irq/manage.c index 1da999f5e746..0e2b179bc7b3 100644 --- a/trunk/kernel/irq/manage.c +++ b/trunk/kernel/irq/manage.c @@ -623,9 +623,8 @@ static irqreturn_t irq_nested_primary_handler(int irq, void *dev_id) static int irq_wait_for_interrupt(struct irqaction *action) { - set_current_state(TASK_INTERRUPTIBLE); - while (!kthread_should_stop()) { + set_current_state(TASK_INTERRUPTIBLE); if (test_and_clear_bit(IRQTF_RUNTHREAD, &action->thread_flags)) { @@ -633,9 +632,7 @@ static int irq_wait_for_interrupt(struct irqaction *action) return 0; } schedule(); - set_current_state(TASK_INTERRUPTIBLE); } - __set_current_state(TASK_RUNNING); return -1; } diff --git a/trunk/kernel/jump_label.c b/trunk/kernel/jump_label.c index 66ff7109f697..bbdfe2a462a0 100644 --- a/trunk/kernel/jump_label.c +++ b/trunk/kernel/jump_label.c @@ -66,9 +66,8 @@ void jump_label_inc(struct jump_label_key *key) return; jump_label_lock(); - if (atomic_read(&key->enabled) == 0) + if (atomic_add_return(1, &key->enabled) == 1) jump_label_update(key, JUMP_LABEL_ENABLE); - atomic_inc(&key->enabled); jump_label_unlock(); } diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index d6b149ccf925..0e9344a71be3 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -71,7 +71,6 @@ #include #include #include -#include #include #include @@ -4811,9 +4810,6 @@ EXPORT_SYMBOL(wait_for_completion); * This waits for either a completion of a specific task to be signaled or for a * specified timeout to expire. The timeout is in jiffies. It is not * interruptible. - * - * The return value is 0 if timed out, and positive (at least 1, or number of - * jiffies left till timeout) if completed. */ unsigned long __sched wait_for_completion_timeout(struct completion *x, unsigned long timeout) @@ -4828,8 +4824,6 @@ EXPORT_SYMBOL(wait_for_completion_timeout); * * This waits for completion of a specific task to be signaled. It is * interruptible. - * - * The return value is -ERESTARTSYS if interrupted, 0 if completed. */ int __sched wait_for_completion_interruptible(struct completion *x) { @@ -4847,9 +4841,6 @@ EXPORT_SYMBOL(wait_for_completion_interruptible); * * This waits for either a completion of a specific task to be signaled or for a * specified timeout to expire. It is interruptible. The timeout is in jiffies. - * - * The return value is -ERESTARTSYS if interrupted, 0 if timed out, - * positive (at least 1, or number of jiffies left till timeout) if completed. */ long __sched wait_for_completion_interruptible_timeout(struct completion *x, @@ -4865,8 +4856,6 @@ EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); * * This waits to be signaled for completion of a specific task. It can be * interrupted by a kill signal. - * - * The return value is -ERESTARTSYS if interrupted, 0 if completed. */ int __sched wait_for_completion_killable(struct completion *x) { @@ -4885,9 +4874,6 @@ EXPORT_SYMBOL(wait_for_completion_killable); * This waits for either a completion of a specific task to be * signaled or for a specified timeout to expire. It can be * interrupted by a kill signal. The timeout is in jiffies. - * - * The return value is -ERESTARTSYS if interrupted, 0 if timed out, - * positive (at least 1, or number of jiffies left till timeout) if completed. */ long __sched wait_for_completion_killable_timeout(struct completion *x, @@ -6113,9 +6099,6 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu) */ idle->sched_class = &idle_sched_class; ftrace_graph_init_idle_task(idle, cpu); -#if defined(CONFIG_SMP) - sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu); -#endif } /* diff --git a/trunk/kernel/sched_fair.c b/trunk/kernel/sched_fair.c index a78ed2736ba7..5c9e67923b7c 100644 --- a/trunk/kernel/sched_fair.c +++ b/trunk/kernel/sched_fair.c @@ -772,32 +772,19 @@ static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update) list_del_leaf_cfs_rq(cfs_rq); } -static inline long calc_tg_weight(struct task_group *tg, struct cfs_rq *cfs_rq) -{ - long tg_weight; - - /* - * Use this CPU's actual weight instead of the last load_contribution - * to gain a more accurate current total weight. See - * update_cfs_rq_load_contribution(). - */ - tg_weight = atomic_read(&tg->load_weight); - tg_weight -= cfs_rq->load_contribution; - tg_weight += cfs_rq->load.weight; - - return tg_weight; -} - static long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg) { - long tg_weight, load, shares; + long load_weight, load, shares; - tg_weight = calc_tg_weight(tg, cfs_rq); load = cfs_rq->load.weight; + load_weight = atomic_read(&tg->load_weight); + load_weight += load; + load_weight -= cfs_rq->load_contribution; + shares = (tg->shares * load); - if (tg_weight) - shares /= tg_weight; + if (load_weight) + shares /= load_weight; if (shares < MIN_SHARES) shares = MIN_SHARES; @@ -1756,7 +1743,7 @@ static void __return_cfs_rq_runtime(struct cfs_rq *cfs_rq) static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) { - if (!cfs_rq->runtime_enabled || cfs_rq->nr_running) + if (!cfs_rq->runtime_enabled || !cfs_rq->nr_running) return; __return_cfs_rq_runtime(cfs_rq); @@ -2049,100 +2036,36 @@ static void task_waking_fair(struct task_struct *p) * Adding load to a group doesn't make a group heavier, but can cause movement * of group shares between cpus. Assuming the shares were perfectly aligned one * can calculate the shift in shares. - * - * Calculate the effective load difference if @wl is added (subtracted) to @tg - * on this @cpu and results in a total addition (subtraction) of @wg to the - * total group weight. - * - * Given a runqueue weight distribution (rw_i) we can compute a shares - * distribution (s_i) using: - * - * s_i = rw_i / \Sum rw_j (1) - * - * Suppose we have 4 CPUs and our @tg is a direct child of the root group and - * has 7 equal weight tasks, distributed as below (rw_i), with the resulting - * shares distribution (s_i): - * - * rw_i = { 2, 4, 1, 0 } - * s_i = { 2/7, 4/7, 1/7, 0 } - * - * As per wake_affine() we're interested in the load of two CPUs (the CPU the - * task used to run on and the CPU the waker is running on), we need to - * compute the effect of waking a task on either CPU and, in case of a sync - * wakeup, compute the effect of the current task going to sleep. - * - * So for a change of @wl to the local @cpu with an overall group weight change - * of @wl we can compute the new shares distribution (s'_i) using: - * - * s'_i = (rw_i + @wl) / (@wg + \Sum rw_j) (2) - * - * Suppose we're interested in CPUs 0 and 1, and want to compute the load - * differences in waking a task to CPU 0. The additional task changes the - * weight and shares distributions like: - * - * rw'_i = { 3, 4, 1, 0 } - * s'_i = { 3/8, 4/8, 1/8, 0 } - * - * We can then compute the difference in effective weight by using: - * - * dw_i = S * (s'_i - s_i) (3) - * - * Where 'S' is the group weight as seen by its parent. - * - * Therefore the effective change in loads on CPU 0 would be 5/56 (3/8 - 2/7) - * times the weight of the group. The effect on CPU 1 would be -4/56 (4/8 - - * 4/7) times the weight of the group. */ static long effective_load(struct task_group *tg, int cpu, long wl, long wg) { struct sched_entity *se = tg->se[cpu]; - if (!tg->parent) /* the trivial, non-cgroup case */ + if (!tg->parent) return wl; for_each_sched_entity(se) { - long w, W; + long lw, w; tg = se->my_q->tg; + w = se->my_q->load.weight; - /* - * W = @wg + \Sum rw_j - */ - W = wg + calc_tg_weight(tg, se->my_q); + /* use this cpu's instantaneous contribution */ + lw = atomic_read(&tg->load_weight); + lw -= se->my_q->load_contribution; + lw += w + wg; - /* - * w = rw_i + @wl - */ - w = se->my_q->load.weight + wl; + wl += w; - /* - * wl = S * s'_i; see (2) - */ - if (W > 0 && w < W) - wl = (w * tg->shares) / W; + if (lw > 0 && wl < lw) + wl = (wl * tg->shares) / lw; else wl = tg->shares; - /* - * Per the above, wl is the new se->load.weight value; since - * those are clipped to [MIN_SHARES, ...) do so now. See - * calc_cfs_shares(). - */ + /* zero point is MIN_SHARES */ if (wl < MIN_SHARES) wl = MIN_SHARES; - - /* - * wl = dw_i = S * (s'_i - s_i); see (3) - */ wl -= se->load.weight; - - /* - * Recursively apply this logic to all parent groups to compute - * the final effective load change on the root group. Since - * only the @tg group gets extra weight, all parent groups can - * only redistribute existing shares. @wl is the shift in shares - * resulting from this level per the above. - */ wg = 0; } @@ -2326,8 +2249,7 @@ static int select_idle_sibling(struct task_struct *p, int target) int cpu = smp_processor_id(); int prev_cpu = task_cpu(p); struct sched_domain *sd; - struct sched_group *sg; - int i, smt = 0; + int i; /* * If the task is going to be woken-up on this cpu and if it is @@ -2347,38 +2269,25 @@ static int select_idle_sibling(struct task_struct *p, int target) * Otherwise, iterate the domains and find an elegible idle cpu. */ rcu_read_lock(); -again: for_each_domain(target, sd) { - if (!smt && (sd->flags & SD_SHARE_CPUPOWER)) - continue; - - if (!(sd->flags & SD_SHARE_PKG_RESOURCES)) { - if (!smt) { - smt = 1; - goto again; - } + if (!(sd->flags & SD_SHARE_PKG_RESOURCES)) break; - } - - sg = sd->groups; - do { - if (!cpumask_intersects(sched_group_cpus(sg), - tsk_cpus_allowed(p))) - goto next; - for_each_cpu(i, sched_group_cpus(sg)) { - if (!idle_cpu(i)) - goto next; + for_each_cpu_and(i, sched_domain_span(sd), tsk_cpus_allowed(p)) { + if (idle_cpu(i)) { + target = i; + break; } + } - target = cpumask_first_and(sched_group_cpus(sg), - tsk_cpus_allowed(p)); - goto done; -next: - sg = sg->next; - } while (sg != sd->groups); + /* + * Lets stop looking for an idle sibling when we reached + * the domain that spans the current cpu and prev_cpu. + */ + if (cpumask_test_cpu(cpu, sched_domain_span(sd)) && + cpumask_test_cpu(prev_cpu, sched_domain_span(sd))) + break; } -done: rcu_read_unlock(); return target; @@ -3602,7 +3511,7 @@ static bool update_sd_pick_busiest(struct sched_domain *sd, } /** - * update_sd_lb_stats - Update sched_domain's statistics for load balancing. + * update_sd_lb_stats - Update sched_group's statistics for load balancing. * @sd: sched_domain whose statistics are to be updated. * @this_cpu: Cpu for which load balance is currently performed. * @idle: Idle status of this_cpu diff --git a/trunk/kernel/sched_features.h b/trunk/kernel/sched_features.h index 84802245abd2..efa0a7b75dde 100644 --- a/trunk/kernel/sched_features.h +++ b/trunk/kernel/sched_features.h @@ -67,4 +67,3 @@ SCHED_FEAT(NONTASK_POWER, 1) SCHED_FEAT(TTWU_QUEUE, 1) SCHED_FEAT(FORCE_SD_OVERLAP, 0) -SCHED_FEAT(RT_RUNTIME_SHARE, 1) diff --git a/trunk/kernel/sched_rt.c b/trunk/kernel/sched_rt.c index 583a1368afe6..056cbd2e2a27 100644 --- a/trunk/kernel/sched_rt.c +++ b/trunk/kernel/sched_rt.c @@ -560,9 +560,6 @@ static int balance_runtime(struct rt_rq *rt_rq) { int more = 0; - if (!sched_feat(RT_RUNTIME_SHARE)) - return more; - if (rt_rq->rt_time > rt_rq->rt_runtime) { raw_spin_unlock(&rt_rq->rt_runtime_lock); more = do_balance_runtime(rt_rq); diff --git a/trunk/kernel/time/clockevents.c b/trunk/kernel/time/clockevents.c index c4eb71c8b2ea..1ecd6ba36d6c 100644 --- a/trunk/kernel/time/clockevents.c +++ b/trunk/kernel/time/clockevents.c @@ -387,7 +387,6 @@ void clockevents_exchange_device(struct clock_event_device *old, * released list and do a notify add later. */ if (old) { - old->event_handler = clockevents_handle_noop; clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED); list_del(&old->list); list_add(&old->list, &clockevents_released); diff --git a/trunk/kernel/time/clocksource.c b/trunk/kernel/time/clocksource.c index da2f760e780c..cfc65e1eb9fb 100644 --- a/trunk/kernel/time/clocksource.c +++ b/trunk/kernel/time/clocksource.c @@ -548,7 +548,7 @@ static u64 clocksource_max_deferment(struct clocksource *cs) * note a margin of 12.5% is used because this can be computed with * a shift, versus say 10% which would require division. */ - return max_nsecs - (max_nsecs >> 3); + return max_nsecs - (max_nsecs >> 5); } #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET @@ -669,7 +669,7 @@ void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq) * ~ 0.06ppm granularity for NTP. We apply the same 12.5% * margin as we do in clocksource_max_deferment() */ - sec = (cs->mask - (cs->mask >> 3)); + sec = (cs->mask - (cs->mask >> 5)); do_div(sec, freq); do_div(sec, scale); if (!sec) diff --git a/trunk/kernel/time/tick-broadcast.c b/trunk/kernel/time/tick-broadcast.c index fd4a7b1625a2..f954282d9a82 100644 --- a/trunk/kernel/time/tick-broadcast.c +++ b/trunk/kernel/time/tick-broadcast.c @@ -71,7 +71,7 @@ int tick_check_broadcast_device(struct clock_event_device *dev) (dev->features & CLOCK_EVT_FEAT_C3STOP)) return 0; - clockevents_exchange_device(tick_broadcast_device.evtdev, dev); + clockevents_exchange_device(NULL, dev); tick_broadcast_device.evtdev = dev; if (!cpumask_empty(tick_get_broadcast_mask())) tick_broadcast_start_periodic(dev); diff --git a/trunk/kernel/trace/ftrace.c b/trunk/kernel/trace/ftrace.c index b1e8943fed1d..900b409543db 100644 --- a/trunk/kernel/trace/ftrace.c +++ b/trunk/kernel/trace/ftrace.c @@ -152,6 +152,7 @@ void clear_ftrace_function(void) ftrace_pid_function = ftrace_stub; } +#undef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST #ifndef CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST /* * For those archs that do not test ftrace_trace_stop in their @@ -1211,9 +1212,7 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable, if (!src->count) { free_ftrace_hash_rcu(*dst); rcu_assign_pointer(*dst, EMPTY_HASH); - /* still need to update the function records */ - ret = 0; - goto out; + return 0; } /* diff --git a/trunk/kernel/trace/trace_events.c b/trunk/kernel/trace/trace_events.c index c212a7f934ec..581876f9f387 100644 --- a/trunk/kernel/trace/trace_events.c +++ b/trunk/kernel/trace/trace_events.c @@ -1078,6 +1078,7 @@ event_subsystem_dir(const char *name, struct dentry *d_events) /* First see if we did not already create this dir */ list_for_each_entry(system, &event_subsystems, list) { if (strcmp(system->name, name) == 0) { + __get_system(system); system->nr_events++; return system->entry; } diff --git a/trunk/kernel/trace/trace_events_filter.c b/trunk/kernel/trace/trace_events_filter.c index 95dc31efd6dd..816d3d074979 100644 --- a/trunk/kernel/trace/trace_events_filter.c +++ b/trunk/kernel/trace/trace_events_filter.c @@ -1649,9 +1649,7 @@ static int replace_system_preds(struct event_subsystem *system, */ err = replace_preds(call, NULL, ps, filter_string, true); if (err) - call->flags |= TRACE_EVENT_FL_NO_SET_FILTER; - else - call->flags &= ~TRACE_EVENT_FL_NO_SET_FILTER; + goto fail; } list_for_each_entry(call, &ftrace_events, list) { @@ -1660,9 +1658,6 @@ static int replace_system_preds(struct event_subsystem *system, if (strcmp(call->class->system, system->name) != 0) continue; - if (call->flags & TRACE_EVENT_FL_NO_SET_FILTER) - continue; - filter_item = kzalloc(sizeof(*filter_item), GFP_KERNEL); if (!filter_item) goto fail_mem; @@ -1691,7 +1686,7 @@ static int replace_system_preds(struct event_subsystem *system, * replace the filter for the call. */ filter = call->filter; - rcu_assign_pointer(call->filter, filter_item->filter); + call->filter = filter_item->filter; filter_item->filter = filter; fail = false; @@ -1746,7 +1741,7 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string) filter = call->filter; if (!filter) goto out_unlock; - RCU_INIT_POINTER(call->filter, NULL); + call->filter = NULL; /* Make sure the filter is not being used */ synchronize_sched(); __free_filter(filter); @@ -1787,7 +1782,7 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string) * string */ tmp = call->filter; - rcu_assign_pointer(call->filter, filter); + call->filter = filter; if (tmp) { /* Make sure the call is done with the filter */ synchronize_sched(); diff --git a/trunk/lib/reciprocal_div.c b/trunk/lib/reciprocal_div.c index 75510e94f7d0..6a3bd48fa2a0 100644 --- a/trunk/lib/reciprocal_div.c +++ b/trunk/lib/reciprocal_div.c @@ -1,6 +1,5 @@ #include #include -#include u32 reciprocal_value(u32 k) { @@ -8,4 +7,3 @@ u32 reciprocal_value(u32 k) do_div(val, k); return (u32)val; } -EXPORT_SYMBOL(reciprocal_value); diff --git a/trunk/mm/memcontrol.c b/trunk/mm/memcontrol.c index 7266202fa7cf..6aff93c98aca 100644 --- a/trunk/mm/memcontrol.c +++ b/trunk/mm/memcontrol.c @@ -50,8 +50,6 @@ #include #include #include "internal.h" -#include -#include #include @@ -228,10 +226,6 @@ struct mem_cgroup { * the counter to account for mem+swap usage. */ struct res_counter memsw; - /* - * the counter to account for kmem usage. - */ - struct res_counter kmem; /* * Per cgroup active and inactive list, similar to the * per zone LRU lists. @@ -282,11 +276,6 @@ struct mem_cgroup { * mem_cgroup ? And what type of charges should we move ? */ unsigned long move_charge_at_immigrate; - /* - * Should kernel memory limits be stabilished independently - * from user memory ? - */ - int kmem_independent_accounting; /* * percpu counter. */ @@ -297,10 +286,6 @@ struct mem_cgroup { */ struct mem_cgroup_stat_cpu nocpu_base; spinlock_t pcp_counter_lock; - -#ifdef CONFIG_INET - struct tcp_memcontrol tcp_mem; -#endif }; /* Stuffs for move charges at task migration. */ @@ -359,14 +344,9 @@ enum charge_type { }; /* for encoding cft->private value on file */ - -enum mem_type { - _MEM = 0, - _MEMSWAP, - _OOM_TYPE, - _KMEM, -}; - +#define _MEM (0) +#define _MEMSWAP (1) +#define _OOM_TYPE (2) #define MEMFILE_PRIVATE(x, val) (((x) << 16) | (val)) #define MEMFILE_TYPE(val) (((val) >> 16) & 0xffff) #define MEMFILE_ATTR(val) ((val) & 0xffff) @@ -385,58 +365,7 @@ enum mem_type { static void mem_cgroup_get(struct mem_cgroup *memcg); static void mem_cgroup_put(struct mem_cgroup *memcg); - -/* Writing them here to avoid exposing memcg's inner layout */ -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM -#ifdef CONFIG_INET -#include -#include - -static bool mem_cgroup_is_root(struct mem_cgroup *memcg); -void sock_update_memcg(struct sock *sk) -{ - /* A socket spends its whole life in the same cgroup */ - if (sk->sk_cgrp) { - WARN_ON(1); - return; - } - if (static_branch(&memcg_socket_limit_enabled)) { - struct mem_cgroup *memcg; - - BUG_ON(!sk->sk_prot->proto_cgroup); - - rcu_read_lock(); - memcg = mem_cgroup_from_task(current); - if (!mem_cgroup_is_root(memcg)) { - mem_cgroup_get(memcg); - sk->sk_cgrp = sk->sk_prot->proto_cgroup(memcg); - } - rcu_read_unlock(); - } -} -EXPORT_SYMBOL(sock_update_memcg); - -void sock_release_memcg(struct sock *sk) -{ - if (static_branch(&memcg_socket_limit_enabled) && sk->sk_cgrp) { - struct mem_cgroup *memcg; - WARN_ON(!sk->sk_cgrp->memcg); - memcg = sk->sk_cgrp->memcg; - mem_cgroup_put(memcg); - } -} - -struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg) -{ - if (!memcg || mem_cgroup_is_root(memcg)) - return NULL; - - return &memcg->tcp_mem.cg_proto; -} -EXPORT_SYMBOL(tcp_proto_cgroup); -#endif /* CONFIG_INET */ -#endif /* CONFIG_CGROUP_MEM_RES_CTLR_KMEM */ - +static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *memcg); static void drain_all_stock_async(struct mem_cgroup *memcg); static struct mem_cgroup_per_zone * @@ -816,7 +745,7 @@ static void memcg_check_events(struct mem_cgroup *memcg, struct page *page) preempt_enable(); } -struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont) +static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont) { return container_of(cgroup_subsys_state(cont, mem_cgroup_subsys_id), struct mem_cgroup, @@ -3919,17 +3848,10 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap) u64 val; if (!mem_cgroup_is_root(memcg)) { - val = 0; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM - if (!memcg->kmem_independent_accounting) - val = res_counter_read_u64(&memcg->kmem, RES_USAGE); -#endif if (!swap) - val += res_counter_read_u64(&memcg->res, RES_USAGE); + return res_counter_read_u64(&memcg->res, RES_USAGE); else - val += res_counter_read_u64(&memcg->memsw, RES_USAGE); - - return val; + return res_counter_read_u64(&memcg->memsw, RES_USAGE); } val = mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_CACHE); @@ -3962,11 +3884,6 @@ static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) else val = res_counter_read_u64(&memcg->memsw, name); break; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM - case _KMEM: - val = res_counter_read_u64(&memcg->kmem, name); - break; -#endif default: BUG(); break; @@ -4695,89 +4612,6 @@ static int mem_control_numa_stat_open(struct inode *unused, struct file *file) } #endif /* CONFIG_NUMA */ -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM -static u64 kmem_limit_independent_read(struct cgroup *cgroup, struct cftype *cft) -{ - return mem_cgroup_from_cont(cgroup)->kmem_independent_accounting; -} - -static int kmem_limit_independent_write(struct cgroup *cgroup, struct cftype *cft, - u64 val) -{ - struct mem_cgroup *memcg = mem_cgroup_from_cont(cgroup); - struct mem_cgroup *parent = parent_mem_cgroup(memcg); - - val = !!val; - - /* - * This follows the same hierarchy restrictions than - * mem_cgroup_hierarchy_write() - */ - if (!parent || !parent->use_hierarchy) { - if (list_empty(&cgroup->children)) - memcg->kmem_independent_accounting = val; - else - return -EBUSY; - } - else - return -EINVAL; - - return 0; -} -static struct cftype kmem_cgroup_files[] = { - { - .name = "independent_kmem_limit", - .read_u64 = kmem_limit_independent_read, - .write_u64 = kmem_limit_independent_write, - }, - { - .name = "kmem.usage_in_bytes", - .private = MEMFILE_PRIVATE(_KMEM, RES_USAGE), - .read_u64 = mem_cgroup_read, - }, - { - .name = "kmem.limit_in_bytes", - .private = MEMFILE_PRIVATE(_KMEM, RES_LIMIT), - .read_u64 = mem_cgroup_read, - }, -}; - -static int register_kmem_files(struct cgroup *cont, struct cgroup_subsys *ss) -{ - int ret = 0; - - ret = cgroup_add_files(cont, ss, kmem_cgroup_files, - ARRAY_SIZE(kmem_cgroup_files)); - - /* - * Part of this would be better living in a separate allocation - * function, leaving us with just the cgroup tree population work. - * We, however, depend on state such as network's proto_list that - * is only initialized after cgroup creation. I found the less - * cumbersome way to deal with it to defer it all to populate time - */ - if (!ret) - ret = mem_cgroup_sockets_init(cont, ss); - return ret; -}; - -static void kmem_cgroup_destroy(struct cgroup_subsys *ss, - struct cgroup *cont) -{ - mem_cgroup_sockets_destroy(cont, ss); -} -#else -static int register_kmem_files(struct cgroup *cont, struct cgroup_subsys *ss) -{ - return 0; -} - -static void kmem_cgroup_destroy(struct cgroup_subsys *ss, - struct cgroup *cont) -{ -} -#endif - static struct cftype mem_cgroup_files[] = { { .name = "usage_in_bytes", @@ -5009,13 +4843,12 @@ static void mem_cgroup_put(struct mem_cgroup *memcg) /* * Returns the parent mem_cgroup in memcgroup hierarchy with hierarchy enabled. */ -struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *memcg) +static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *memcg) { if (!memcg->res.parent) return NULL; return mem_cgroup_from_res_counter(memcg->res.parent, res); } -EXPORT_SYMBOL(parent_mem_cgroup); #ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP static void __init enable_swap_cgroup(void) @@ -5092,7 +4925,6 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) if (parent && parent->use_hierarchy) { res_counter_init(&memcg->res, &parent->res); res_counter_init(&memcg->memsw, &parent->memsw); - res_counter_init(&memcg->kmem, &parent->kmem); /* * We increment refcnt of the parent to ensure that we can * safely access it on res_counter_charge/uncharge. @@ -5103,7 +4935,6 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) } else { res_counter_init(&memcg->res, NULL); res_counter_init(&memcg->memsw, NULL); - res_counter_init(&memcg->kmem, NULL); } memcg->last_scanned_child = 0; memcg->last_scanned_node = MAX_NUMNODES; @@ -5134,8 +4965,6 @@ static void mem_cgroup_destroy(struct cgroup_subsys *ss, { struct mem_cgroup *memcg = mem_cgroup_from_cont(cont); - kmem_cgroup_destroy(ss, cont); - mem_cgroup_put(memcg); } @@ -5149,10 +4978,6 @@ static int mem_cgroup_populate(struct cgroup_subsys *ss, if (!ret) ret = register_memsw_files(cont, ss); - - if (!ret) - ret = register_kmem_files(cont, ss); - return ret; } diff --git a/trunk/mm/slab.c b/trunk/mm/slab.c index 83311c9aaf9d..708efe886154 100644 --- a/trunk/mm/slab.c +++ b/trunk/mm/slab.c @@ -595,7 +595,6 @@ static enum { PARTIAL_AC, PARTIAL_L3, EARLY, - LATE, FULL } g_cpucache_up; @@ -672,7 +671,7 @@ static void init_node_lock_keys(int q) { struct cache_sizes *s = malloc_sizes; - if (g_cpucache_up < LATE) + if (g_cpucache_up != FULL) return; for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) { @@ -1667,8 +1666,6 @@ void __init kmem_cache_init_late(void) { struct kmem_cache *cachep; - g_cpucache_up = LATE; - /* Annotate slab for lockdep -- annotate the malloc caches */ init_lock_keys(); diff --git a/trunk/net/8021q/vlan.c b/trunk/net/8021q/vlan.c index efea35b02e7f..5471628d3ffe 100644 --- a/trunk/net/8021q/vlan.c +++ b/trunk/net/8021q/vlan.c @@ -51,6 +51,27 @@ const char vlan_version[] = DRV_VERSION; /* End of global variables definitions. */ +static void vlan_group_free(struct vlan_group *grp) +{ + int i; + + for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) + kfree(grp->vlan_devices_arrays[i]); + kfree(grp); +} + +static struct vlan_group *vlan_group_alloc(struct net_device *real_dev) +{ + struct vlan_group *grp; + + grp = kzalloc(sizeof(struct vlan_group), GFP_KERNEL); + if (!grp) + return NULL; + + grp->real_dev = real_dev; + return grp; +} + static int vlan_group_prealloc_vid(struct vlan_group *vg, u16 vlan_id) { struct net_device **array; @@ -71,29 +92,32 @@ static int vlan_group_prealloc_vid(struct vlan_group *vg, u16 vlan_id) return 0; } +static void vlan_rcu_free(struct rcu_head *rcu) +{ + vlan_group_free(container_of(rcu, struct vlan_group, rcu)); +} + void unregister_vlan_dev(struct net_device *dev, struct list_head *head) { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct vlan_dev_info *vlan = vlan_dev_info(dev); struct net_device *real_dev = vlan->real_dev; - struct vlan_info *vlan_info; + const struct net_device_ops *ops = real_dev->netdev_ops; struct vlan_group *grp; u16 vlan_id = vlan->vlan_id; ASSERT_RTNL(); - vlan_info = rtnl_dereference(real_dev->vlan_info); - BUG_ON(!vlan_info); - - grp = &vlan_info->grp; + grp = rtnl_dereference(real_dev->vlgrp); + BUG_ON(!grp); /* Take it out of our own structures, but be sure to interlock with * HW accelerating devices or SW vlan input packet processing if * VLAN is not 0 (leave it there for 802.1p). */ - if (vlan_id) - vlan_vid_del(real_dev, vlan_id); + if (vlan_id && (real_dev->features & NETIF_F_HW_VLAN_FILTER)) + ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id); - grp->nr_vlan_devs--; + grp->nr_vlans--; if (vlan->flags & VLAN_FLAG_GVRP) vlan_gvrp_request_leave(dev); @@ -105,9 +129,16 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) */ unregister_netdevice_queue(dev, head); - if (grp->nr_vlan_devs == 0) + /* If the group is now empty, kill off the group. */ + if (grp->nr_vlans == 0) { vlan_gvrp_uninit_applicant(real_dev); + RCU_INIT_POINTER(real_dev->vlgrp, NULL); + + /* Free the group, after all cpu's are done. */ + call_rcu(&grp->rcu, vlan_rcu_free); + } + /* Get rid of the vlan's reference to real_dev */ dev_put(real_dev); } @@ -136,26 +167,21 @@ int vlan_check_real_dev(struct net_device *real_dev, u16 vlan_id) int register_vlan_dev(struct net_device *dev) { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct vlan_dev_info *vlan = vlan_dev_info(dev); struct net_device *real_dev = vlan->real_dev; + const struct net_device_ops *ops = real_dev->netdev_ops; u16 vlan_id = vlan->vlan_id; - struct vlan_info *vlan_info; - struct vlan_group *grp; + struct vlan_group *grp, *ngrp = NULL; int err; - err = vlan_vid_add(real_dev, vlan_id); - if (err) - return err; - - vlan_info = rtnl_dereference(real_dev->vlan_info); - /* vlan_info should be there now. vlan_vid_add took care of it */ - BUG_ON(!vlan_info); - - grp = &vlan_info->grp; - if (grp->nr_vlan_devs == 0) { + grp = rtnl_dereference(real_dev->vlgrp); + if (!grp) { + ngrp = grp = vlan_group_alloc(real_dev); + if (!grp) + return -ENOBUFS; err = vlan_gvrp_init_applicant(real_dev); if (err < 0) - goto out_vid_del; + goto out_free_group; } err = vlan_group_prealloc_vid(grp, vlan_id); @@ -166,7 +192,7 @@ int register_vlan_dev(struct net_device *dev) if (err < 0) goto out_uninit_applicant; - /* Account for reference in struct vlan_dev_priv */ + /* Account for reference in struct vlan_dev_info */ dev_hold(real_dev); netif_stacked_transfer_operstate(real_dev, dev); @@ -176,15 +202,24 @@ int register_vlan_dev(struct net_device *dev) * it into our local structure. */ vlan_group_set_device(grp, vlan_id, dev); - grp->nr_vlan_devs++; + grp->nr_vlans++; + + if (ngrp) { + rcu_assign_pointer(real_dev->vlgrp, ngrp); + } + if (real_dev->features & NETIF_F_HW_VLAN_FILTER) + ops->ndo_vlan_rx_add_vid(real_dev, vlan_id); return 0; out_uninit_applicant: - if (grp->nr_vlan_devs == 0) + if (ngrp) vlan_gvrp_uninit_applicant(real_dev); -out_vid_del: - vlan_vid_del(real_dev, vlan_id); +out_free_group: + if (ngrp) { + /* Free the group, after all cpu's are done. */ + call_rcu(&ngrp->rcu, vlan_rcu_free); + } return err; } @@ -232,7 +267,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id); } - new_dev = alloc_netdev(sizeof(struct vlan_dev_priv), name, vlan_setup); + new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name, vlan_setup); if (new_dev == NULL) return -ENOBUFS; @@ -243,10 +278,10 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) */ new_dev->mtu = real_dev->mtu; - vlan_dev_priv(new_dev)->vlan_id = vlan_id; - vlan_dev_priv(new_dev)->real_dev = real_dev; - vlan_dev_priv(new_dev)->dent = NULL; - vlan_dev_priv(new_dev)->flags = VLAN_FLAG_REORDER_HDR; + vlan_dev_info(new_dev)->vlan_id = vlan_id; + vlan_dev_info(new_dev)->real_dev = real_dev; + vlan_dev_info(new_dev)->dent = NULL; + vlan_dev_info(new_dev)->flags = VLAN_FLAG_REORDER_HDR; new_dev->rtnl_link_ops = &vlan_link_ops; err = register_vlan_dev(new_dev); @@ -263,7 +298,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) static void vlan_sync_address(struct net_device *dev, struct net_device *vlandev) { - struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev); + struct vlan_dev_info *vlan = vlan_dev_info(vlandev); /* May be called without an actual change */ if (!compare_ether_addr(vlan->real_dev_addr, dev->dev_addr)) @@ -325,26 +360,25 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, { struct net_device *dev = ptr; struct vlan_group *grp; - struct vlan_info *vlan_info; int i, flgs; struct net_device *vlandev; - struct vlan_dev_priv *vlan; + struct vlan_dev_info *vlan; LIST_HEAD(list); if (is_vlan_dev(dev)) __vlan_device_event(dev, event); if ((event == NETDEV_UP) && - (dev->features & NETIF_F_HW_VLAN_FILTER)) { + (dev->features & NETIF_F_HW_VLAN_FILTER) && + dev->netdev_ops->ndo_vlan_rx_add_vid) { pr_info("adding VLAN 0 to HW filter on device %s\n", dev->name); - vlan_vid_add(dev, 0); + dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0); } - vlan_info = rtnl_dereference(dev->vlan_info); - if (!vlan_info) + grp = rtnl_dereference(dev->vlgrp); + if (!grp) goto out; - grp = &vlan_info->grp; /* It is OK that we do not hold the group lock right now, * as we run under the RTNL lock. @@ -413,7 +447,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, if (!(flgs & IFF_UP)) continue; - vlan = vlan_dev_priv(vlandev); + vlan = vlan_dev_info(vlandev); if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) dev_change_flags(vlandev, flgs & ~IFF_UP); netif_stacked_transfer_operstate(dev, vlandev); @@ -431,7 +465,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, if (flgs & IFF_UP) continue; - vlan = vlan_dev_priv(vlandev); + vlan = vlan_dev_info(vlandev); if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) dev_change_flags(vlandev, flgs | IFF_UP); netif_stacked_transfer_operstate(dev, vlandev); @@ -448,9 +482,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, if (!vlandev) continue; - /* removal of last vid destroys vlan_info, abort + /* unregistration of last vlan destroys group, abort * afterwards */ - if (vlan_info->nr_vids == 1) + if (grp->nr_vlans == 1) i = VLAN_N_VID; unregister_vlan_dev(vlandev, &list); diff --git a/trunk/net/8021q/vlan.h b/trunk/net/8021q/vlan.h index a4886d94c40c..9fd45f3571f9 100644 --- a/trunk/net/8021q/vlan.h +++ b/trunk/net/8021q/vlan.h @@ -3,7 +3,6 @@ #include #include -#include /** @@ -41,10 +40,8 @@ struct vlan_pcpu_stats { u32 tx_dropped; }; -struct netpoll; - /** - * struct vlan_dev_priv - VLAN private device data + * struct vlan_dev_info - VLAN private device data * @nr_ingress_mappings: number of ingress priority mappings * @ingress_priority_map: ingress priority mappings * @nr_egress_mappings: number of egress priority mappings @@ -56,7 +53,7 @@ struct netpoll; * @dent: proc dir entry * @vlan_pcpu_stats: ptr to percpu rx stats */ -struct vlan_dev_priv { +struct vlan_dev_info { unsigned int nr_ingress_mappings; u32 ingress_priority_map[8]; unsigned int nr_egress_mappings; @@ -70,39 +67,13 @@ struct vlan_dev_priv { struct proc_dir_entry *dent; struct vlan_pcpu_stats __percpu *vlan_pcpu_stats; -#ifdef CONFIG_NET_POLL_CONTROLLER - struct netpoll *netpoll; -#endif }; -static inline struct vlan_dev_priv *vlan_dev_priv(const struct net_device *dev) +static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev) { return netdev_priv(dev); } -/* if this changes, algorithm will have to be reworked because this - * depends on completely exhausting the VLAN identifier space. Thus - * it gives constant time look-up, but in many cases it wastes memory. - */ -#define VLAN_GROUP_ARRAY_SPLIT_PARTS 8 -#define VLAN_GROUP_ARRAY_PART_LEN (VLAN_N_VID/VLAN_GROUP_ARRAY_SPLIT_PARTS) - -struct vlan_group { - unsigned int nr_vlan_devs; - struct hlist_node hlist; /* linked list */ - struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS]; -}; - -struct vlan_info { - struct net_device *real_dev; /* The ethernet(like) device - * the vlan is attached to. - */ - struct vlan_group grp; - struct list_head vid_list; - unsigned int nr_vids; - struct rcu_head rcu; -}; - static inline struct net_device *vlan_group_get_device(struct vlan_group *vg, u16 vlan_id) { @@ -126,10 +97,10 @@ static inline void vlan_group_set_device(struct vlan_group *vg, static inline struct net_device *vlan_find_dev(struct net_device *real_dev, u16 vlan_id) { - struct vlan_info *vlan_info = rcu_dereference_rtnl(real_dev->vlan_info); + struct vlan_group *grp = rcu_dereference_rtnl(real_dev->vlgrp); - if (vlan_info) - return vlan_group_get_device(&vlan_info->grp, vlan_id); + if (grp) + return vlan_group_get_device(grp, vlan_id); return NULL; } @@ -150,7 +121,7 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head); static inline u32 vlan_get_ingress_priority(struct net_device *dev, u16 vlan_tci) { - struct vlan_dev_priv *vip = vlan_dev_priv(dev); + struct vlan_dev_info *vip = vlan_dev_info(dev); return vip->ingress_priority_map[(vlan_tci >> VLAN_PRIO_SHIFT) & 0x7]; } diff --git a/trunk/net/8021q/vlan_core.c b/trunk/net/8021q/vlan_core.c index 4d39d802be2c..9c95e8e054f9 100644 --- a/trunk/net/8021q/vlan_core.c +++ b/trunk/net/8021q/vlan_core.c @@ -36,7 +36,7 @@ bool vlan_do_receive(struct sk_buff **skbp, bool last_handler) skb->pkt_type = PACKET_HOST; } - if (!(vlan_dev_priv(vlan_dev)->flags & VLAN_FLAG_REORDER_HDR)) { + if (!(vlan_dev_info(vlan_dev)->flags & VLAN_FLAG_REORDER_HDR)) { unsigned int offset = skb->data - skb_mac_header(skb); /* @@ -55,7 +55,7 @@ bool vlan_do_receive(struct sk_buff **skbp, bool last_handler) skb->priority = vlan_get_ingress_priority(vlan_dev, skb->vlan_tci); skb->vlan_tci = 0; - rx_stats = this_cpu_ptr(vlan_dev_priv(vlan_dev)->vlan_pcpu_stats); + rx_stats = this_cpu_ptr(vlan_dev_info(vlan_dev)->vlan_pcpu_stats); u64_stats_update_begin(&rx_stats->syncp); rx_stats->rx_packets++; @@ -71,10 +71,10 @@ bool vlan_do_receive(struct sk_buff **skbp, bool last_handler) struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) { - struct vlan_info *vlan_info = rcu_dereference_rtnl(real_dev->vlan_info); + struct vlan_group *grp = rcu_dereference_rtnl(real_dev->vlgrp); - if (vlan_info) { - return vlan_group_get_device(&vlan_info->grp, vlan_id); + if (grp) { + return vlan_group_get_device(grp, vlan_id); } else { /* * Bonding slaves do not have grp assigned to themselves. @@ -90,13 +90,13 @@ EXPORT_SYMBOL(__vlan_find_dev_deep); struct net_device *vlan_dev_real_dev(const struct net_device *dev) { - return vlan_dev_priv(dev)->real_dev; + return vlan_dev_info(dev)->real_dev; } EXPORT_SYMBOL(vlan_dev_real_dev); u16 vlan_dev_vlan_id(const struct net_device *dev) { - return vlan_dev_priv(dev)->vlan_id; + return vlan_dev_info(dev)->vlan_id; } EXPORT_SYMBOL(vlan_dev_vlan_id); @@ -146,226 +146,3 @@ struct sk_buff *vlan_untag(struct sk_buff *skb) kfree_skb(skb); return NULL; } - - -/* - * vlan info and vid list - */ - -static void vlan_group_free(struct vlan_group *grp) -{ - int i; - - for (i = 0; i < VLAN_GROUP_ARRAY_SPLIT_PARTS; i++) - kfree(grp->vlan_devices_arrays[i]); -} - -static void vlan_info_free(struct vlan_info *vlan_info) -{ - vlan_group_free(&vlan_info->grp); - kfree(vlan_info); -} - -static void vlan_info_rcu_free(struct rcu_head *rcu) -{ - vlan_info_free(container_of(rcu, struct vlan_info, rcu)); -} - -static struct vlan_info *vlan_info_alloc(struct net_device *dev) -{ - struct vlan_info *vlan_info; - - vlan_info = kzalloc(sizeof(struct vlan_info), GFP_KERNEL); - if (!vlan_info) - return NULL; - - vlan_info->real_dev = dev; - INIT_LIST_HEAD(&vlan_info->vid_list); - return vlan_info; -} - -struct vlan_vid_info { - struct list_head list; - unsigned short vid; - int refcount; -}; - -static struct vlan_vid_info *vlan_vid_info_get(struct vlan_info *vlan_info, - unsigned short vid) -{ - struct vlan_vid_info *vid_info; - - list_for_each_entry(vid_info, &vlan_info->vid_list, list) { - if (vid_info->vid == vid) - return vid_info; - } - return NULL; -} - -static struct vlan_vid_info *vlan_vid_info_alloc(unsigned short vid) -{ - struct vlan_vid_info *vid_info; - - vid_info = kzalloc(sizeof(struct vlan_vid_info), GFP_KERNEL); - if (!vid_info) - return NULL; - vid_info->vid = vid; - - return vid_info; -} - -static int __vlan_vid_add(struct vlan_info *vlan_info, unsigned short vid, - struct vlan_vid_info **pvid_info) -{ - struct net_device *dev = vlan_info->real_dev; - const struct net_device_ops *ops = dev->netdev_ops; - struct vlan_vid_info *vid_info; - int err; - - vid_info = vlan_vid_info_alloc(vid); - if (!vid_info) - return -ENOMEM; - - if ((dev->features & NETIF_F_HW_VLAN_FILTER) && - ops->ndo_vlan_rx_add_vid) { - err = ops->ndo_vlan_rx_add_vid(dev, vid); - if (err) { - kfree(vid_info); - return err; - } - } - list_add(&vid_info->list, &vlan_info->vid_list); - vlan_info->nr_vids++; - *pvid_info = vid_info; - return 0; -} - -int vlan_vid_add(struct net_device *dev, unsigned short vid) -{ - struct vlan_info *vlan_info; - struct vlan_vid_info *vid_info; - bool vlan_info_created = false; - int err; - - ASSERT_RTNL(); - - vlan_info = rtnl_dereference(dev->vlan_info); - if (!vlan_info) { - vlan_info = vlan_info_alloc(dev); - if (!vlan_info) - return -ENOMEM; - vlan_info_created = true; - } - vid_info = vlan_vid_info_get(vlan_info, vid); - if (!vid_info) { - err = __vlan_vid_add(vlan_info, vid, &vid_info); - if (err) - goto out_free_vlan_info; - } - vid_info->refcount++; - - if (vlan_info_created) - rcu_assign_pointer(dev->vlan_info, vlan_info); - - return 0; - -out_free_vlan_info: - if (vlan_info_created) - kfree(vlan_info); - return err; -} -EXPORT_SYMBOL(vlan_vid_add); - -static void __vlan_vid_del(struct vlan_info *vlan_info, - struct vlan_vid_info *vid_info) -{ - struct net_device *dev = vlan_info->real_dev; - const struct net_device_ops *ops = dev->netdev_ops; - unsigned short vid = vid_info->vid; - int err; - - if ((dev->features & NETIF_F_HW_VLAN_FILTER) && - ops->ndo_vlan_rx_kill_vid) { - err = ops->ndo_vlan_rx_kill_vid(dev, vid); - if (err) { - pr_warn("failed to kill vid %d for device %s\n", - vid, dev->name); - } - } - list_del(&vid_info->list); - kfree(vid_info); - vlan_info->nr_vids--; -} - -void vlan_vid_del(struct net_device *dev, unsigned short vid) -{ - struct vlan_info *vlan_info; - struct vlan_vid_info *vid_info; - - ASSERT_RTNL(); - - vlan_info = rtnl_dereference(dev->vlan_info); - if (!vlan_info) - return; - - vid_info = vlan_vid_info_get(vlan_info, vid); - if (!vid_info) - return; - vid_info->refcount--; - if (vid_info->refcount == 0) { - __vlan_vid_del(vlan_info, vid_info); - if (vlan_info->nr_vids == 0) { - RCU_INIT_POINTER(dev->vlan_info, NULL); - call_rcu(&vlan_info->rcu, vlan_info_rcu_free); - } - } -} -EXPORT_SYMBOL(vlan_vid_del); - -int vlan_vids_add_by_dev(struct net_device *dev, - const struct net_device *by_dev) -{ - struct vlan_vid_info *vid_info; - struct vlan_info *vlan_info; - int err; - - ASSERT_RTNL(); - - vlan_info = rtnl_dereference(by_dev->vlan_info); - if (!vlan_info) - return 0; - - list_for_each_entry(vid_info, &vlan_info->vid_list, list) { - err = vlan_vid_add(dev, vid_info->vid); - if (err) - goto unwind; - } - return 0; - -unwind: - list_for_each_entry_continue_reverse(vid_info, - &vlan_info->vid_list, - list) { - vlan_vid_del(dev, vid_info->vid); - } - - return err; -} -EXPORT_SYMBOL(vlan_vids_add_by_dev); - -void vlan_vids_del_by_dev(struct net_device *dev, - const struct net_device *by_dev) -{ - struct vlan_vid_info *vid_info; - struct vlan_info *vlan_info; - - ASSERT_RTNL(); - - vlan_info = rtnl_dereference(by_dev->vlan_info); - if (!vlan_info) - return; - - list_for_each_entry(vid_info, &vlan_info->vid_list, list) - vlan_vid_del(dev, vid_info->vid); -} -EXPORT_SYMBOL(vlan_vids_del_by_dev); diff --git a/trunk/net/8021q/vlan_dev.c b/trunk/net/8021q/vlan_dev.c index 9988d4abb372..2b5fcde1f629 100644 --- a/trunk/net/8021q/vlan_dev.c +++ b/trunk/net/8021q/vlan_dev.c @@ -33,7 +33,6 @@ #include "vlan.h" #include "vlanproc.h" #include -#include /* * Rebuild the Ethernet MAC header. This is called after an ARP @@ -73,7 +72,7 @@ vlan_dev_get_egress_qos_mask(struct net_device *dev, struct sk_buff *skb) { struct vlan_priority_tci_mapping *mp; - mp = vlan_dev_priv(dev)->egress_priority_map[(skb->priority & 0xF)]; + mp = vlan_dev_info(dev)->egress_priority_map[(skb->priority & 0xF)]; while (mp) { if (mp->priority == skb->priority) { return mp->vlan_qos; /* This should already be shifted @@ -104,10 +103,10 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, u16 vlan_tci = 0; int rc; - if (!(vlan_dev_priv(dev)->flags & VLAN_FLAG_REORDER_HDR)) { + if (!(vlan_dev_info(dev)->flags & VLAN_FLAG_REORDER_HDR)) { vhdr = (struct vlan_hdr *) skb_push(skb, VLAN_HLEN); - vlan_tci = vlan_dev_priv(dev)->vlan_id; + vlan_tci = vlan_dev_info(dev)->vlan_id; vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); vhdr->h_vlan_TCI = htons(vlan_tci); @@ -130,7 +129,7 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, saddr = dev->dev_addr; /* Now make the underlying real hard header */ - dev = vlan_dev_priv(dev)->real_dev; + dev = vlan_dev_info(dev)->real_dev; rc = dev_hard_header(skb, dev, type, daddr, saddr, len + vhdrlen); if (rc > 0) rc += vhdrlen; @@ -150,29 +149,27 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... */ if (veth->h_vlan_proto != htons(ETH_P_8021Q) || - vlan_dev_priv(dev)->flags & VLAN_FLAG_REORDER_HDR) { + vlan_dev_info(dev)->flags & VLAN_FLAG_REORDER_HDR) { u16 vlan_tci; - vlan_tci = vlan_dev_priv(dev)->vlan_id; + vlan_tci = vlan_dev_info(dev)->vlan_id; vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); skb = __vlan_hwaccel_put_tag(skb, vlan_tci); } - skb_set_dev(skb, vlan_dev_priv(dev)->real_dev); + skb_set_dev(skb, vlan_dev_info(dev)->real_dev); len = skb->len; - if (netpoll_tx_running(dev)) - return skb->dev->netdev_ops->ndo_start_xmit(skb, skb->dev); ret = dev_queue_xmit(skb); if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { struct vlan_pcpu_stats *stats; - stats = this_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats); + stats = this_cpu_ptr(vlan_dev_info(dev)->vlan_pcpu_stats); u64_stats_update_begin(&stats->syncp); stats->tx_packets++; stats->tx_bytes += len; u64_stats_update_end(&stats->syncp); } else { - this_cpu_inc(vlan_dev_priv(dev)->vlan_pcpu_stats->tx_dropped); + this_cpu_inc(vlan_dev_info(dev)->vlan_pcpu_stats->tx_dropped); } return ret; @@ -183,7 +180,7 @@ static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) /* TODO: gotta make sure the underlying layer can handle it, * maybe an IFF_VLAN_CAPABLE flag for devices? */ - if (vlan_dev_priv(dev)->real_dev->mtu < new_mtu) + if (vlan_dev_info(dev)->real_dev->mtu < new_mtu) return -ERANGE; dev->mtu = new_mtu; @@ -194,7 +191,7 @@ static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) void vlan_dev_set_ingress_priority(const struct net_device *dev, u32 skb_prio, u16 vlan_prio) { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct vlan_dev_info *vlan = vlan_dev_info(dev); if (vlan->ingress_priority_map[vlan_prio & 0x7] && !skb_prio) vlan->nr_ingress_mappings--; @@ -207,7 +204,7 @@ void vlan_dev_set_ingress_priority(const struct net_device *dev, int vlan_dev_set_egress_priority(const struct net_device *dev, u32 skb_prio, u16 vlan_prio) { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct vlan_dev_info *vlan = vlan_dev_info(dev); struct vlan_priority_tci_mapping *mp = NULL; struct vlan_priority_tci_mapping *np; u32 vlan_qos = (vlan_prio << VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK; @@ -244,7 +241,7 @@ int vlan_dev_set_egress_priority(const struct net_device *dev, /* Flags are defined in the vlan_flags enum in include/linux/if_vlan.h file. */ int vlan_dev_change_flags(const struct net_device *dev, u32 flags, u32 mask) { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct vlan_dev_info *vlan = vlan_dev_info(dev); u32 old_flags = vlan->flags; if (mask & ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP | @@ -264,12 +261,12 @@ int vlan_dev_change_flags(const struct net_device *dev, u32 flags, u32 mask) void vlan_dev_get_realdev_name(const struct net_device *dev, char *result) { - strncpy(result, vlan_dev_priv(dev)->real_dev->name, 23); + strncpy(result, vlan_dev_info(dev)->real_dev->name, 23); } static int vlan_dev_open(struct net_device *dev) { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct vlan_dev_info *vlan = vlan_dev_info(dev); struct net_device *real_dev = vlan->real_dev; int err; @@ -316,7 +313,7 @@ static int vlan_dev_open(struct net_device *dev) static int vlan_dev_stop(struct net_device *dev) { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct vlan_dev_info *vlan = vlan_dev_info(dev); struct net_device *real_dev = vlan->real_dev; dev_mc_unsync(real_dev, dev); @@ -335,7 +332,7 @@ static int vlan_dev_stop(struct net_device *dev) static int vlan_dev_set_mac_address(struct net_device *dev, void *p) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; struct sockaddr *addr = p; int err; @@ -361,7 +358,7 @@ static int vlan_dev_set_mac_address(struct net_device *dev, void *p) static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; const struct net_device_ops *ops = real_dev->netdev_ops; struct ifreq ifrr; int err = -EOPNOTSUPP; @@ -386,7 +383,7 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static int vlan_dev_neigh_setup(struct net_device *dev, struct neigh_parms *pa) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; const struct net_device_ops *ops = real_dev->netdev_ops; int err = 0; @@ -400,7 +397,7 @@ static int vlan_dev_neigh_setup(struct net_device *dev, struct neigh_parms *pa) static int vlan_dev_fcoe_ddp_setup(struct net_device *dev, u16 xid, struct scatterlist *sgl, unsigned int sgc) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; const struct net_device_ops *ops = real_dev->netdev_ops; int rc = 0; @@ -412,7 +409,7 @@ static int vlan_dev_fcoe_ddp_setup(struct net_device *dev, u16 xid, static int vlan_dev_fcoe_ddp_done(struct net_device *dev, u16 xid) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; const struct net_device_ops *ops = real_dev->netdev_ops; int len = 0; @@ -424,7 +421,7 @@ static int vlan_dev_fcoe_ddp_done(struct net_device *dev, u16 xid) static int vlan_dev_fcoe_enable(struct net_device *dev) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; const struct net_device_ops *ops = real_dev->netdev_ops; int rc = -EINVAL; @@ -435,7 +432,7 @@ static int vlan_dev_fcoe_enable(struct net_device *dev) static int vlan_dev_fcoe_disable(struct net_device *dev) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; const struct net_device_ops *ops = real_dev->netdev_ops; int rc = -EINVAL; @@ -446,7 +443,7 @@ static int vlan_dev_fcoe_disable(struct net_device *dev) static int vlan_dev_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; const struct net_device_ops *ops = real_dev->netdev_ops; int rc = -EINVAL; @@ -458,7 +455,7 @@ static int vlan_dev_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type) static int vlan_dev_fcoe_ddp_target(struct net_device *dev, u16 xid, struct scatterlist *sgl, unsigned int sgc) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; const struct net_device_ops *ops = real_dev->netdev_ops; int rc = 0; @@ -471,7 +468,7 @@ static int vlan_dev_fcoe_ddp_target(struct net_device *dev, u16 xid, static void vlan_dev_change_rx_flags(struct net_device *dev, int change) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; if (dev->flags & IFF_UP) { if (change & IFF_ALLMULTI) @@ -483,8 +480,8 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change) static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) { - dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); - dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); + dev_mc_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev); + dev_uc_sync(vlan_dev_info(vlan_dev)->real_dev, vlan_dev); } /* @@ -522,7 +519,7 @@ static const struct net_device_ops vlan_netdev_ops; static int vlan_dev_init(struct net_device *dev) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; int subclass = 0; netif_carrier_off(dev); @@ -571,8 +568,8 @@ static int vlan_dev_init(struct net_device *dev) vlan_dev_set_lockdep_class(dev, subclass); - vlan_dev_priv(dev)->vlan_pcpu_stats = alloc_percpu(struct vlan_pcpu_stats); - if (!vlan_dev_priv(dev)->vlan_pcpu_stats) + vlan_dev_info(dev)->vlan_pcpu_stats = alloc_percpu(struct vlan_pcpu_stats); + if (!vlan_dev_info(dev)->vlan_pcpu_stats) return -ENOMEM; return 0; @@ -581,7 +578,7 @@ static int vlan_dev_init(struct net_device *dev) static void vlan_dev_uninit(struct net_device *dev) { struct vlan_priority_tci_mapping *pm; - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct vlan_dev_info *vlan = vlan_dev_info(dev); int i; free_percpu(vlan->vlan_pcpu_stats); @@ -597,7 +594,7 @@ static void vlan_dev_uninit(struct net_device *dev) static netdev_features_t vlan_dev_fix_features(struct net_device *dev, netdev_features_t features) { - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; + struct net_device *real_dev = vlan_dev_info(dev)->real_dev; u32 old_features = features; features &= real_dev->vlan_features; @@ -613,7 +610,7 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev, static int vlan_ethtool_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { - const struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + const struct vlan_dev_info *vlan = vlan_dev_info(dev); return __ethtool_get_settings(vlan->real_dev, cmd); } @@ -629,7 +626,7 @@ static void vlan_ethtool_get_drvinfo(struct net_device *dev, static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { - if (vlan_dev_priv(dev)->vlan_pcpu_stats) { + if (vlan_dev_info(dev)->vlan_pcpu_stats) { struct vlan_pcpu_stats *p; u32 rx_errors = 0, tx_dropped = 0; int i; @@ -638,7 +635,7 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st u64 rxpackets, rxbytes, rxmulticast, txpackets, txbytes; unsigned int start; - p = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, i); + p = per_cpu_ptr(vlan_dev_info(dev)->vlan_pcpu_stats, i); do { start = u64_stats_fetch_begin_bh(&p->syncp); rxpackets = p->rx_packets; @@ -663,57 +660,6 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st return stats; } -#ifdef CONFIG_NET_POLL_CONTROLLER -static void vlan_dev_poll_controller(struct net_device *dev) -{ - return; -} - -static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo) -{ - struct vlan_dev_priv *info = vlan_dev_priv(dev); - struct net_device *real_dev = info->real_dev; - struct netpoll *netpoll; - int err = 0; - - netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL); - err = -ENOMEM; - if (!netpoll) - goto out; - - netpoll->dev = real_dev; - strlcpy(netpoll->dev_name, real_dev->name, IFNAMSIZ); - - err = __netpoll_setup(netpoll); - if (err) { - kfree(netpoll); - goto out; - } - - info->netpoll = netpoll; - -out: - return err; -} - -static void vlan_dev_netpoll_cleanup(struct net_device *dev) -{ - struct vlan_dev_priv *info = vlan_dev_priv(dev); - struct netpoll *netpoll = info->netpoll; - - if (!netpoll) - return; - - info->netpoll = NULL; - - /* Wait for transmitting packets to finish before freeing. */ - synchronize_rcu_bh(); - - __netpoll_cleanup(netpoll); - kfree(netpoll); -} -#endif /* CONFIG_NET_POLL_CONTROLLER */ - static const struct ethtool_ops vlan_ethtool_ops = { .get_settings = vlan_ethtool_get_settings, .get_drvinfo = vlan_ethtool_get_drvinfo, @@ -741,11 +687,6 @@ static const struct net_device_ops vlan_netdev_ops = { .ndo_fcoe_disable = vlan_dev_fcoe_disable, .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, .ndo_fcoe_ddp_target = vlan_dev_fcoe_ddp_target, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = vlan_dev_poll_controller, - .ndo_netpoll_setup = vlan_dev_netpoll_setup, - .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup, #endif .ndo_fix_features = vlan_dev_fix_features, }; diff --git a/trunk/net/8021q/vlan_gvrp.c b/trunk/net/8021q/vlan_gvrp.c index 6f9755352760..061ceceeef12 100644 --- a/trunk/net/8021q/vlan_gvrp.c +++ b/trunk/net/8021q/vlan_gvrp.c @@ -29,7 +29,7 @@ static struct garp_application vlan_gvrp_app __read_mostly = { int vlan_gvrp_request_join(const struct net_device *dev) { - const struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + const struct vlan_dev_info *vlan = vlan_dev_info(dev); __be16 vlan_id = htons(vlan->vlan_id); return garp_request_join(vlan->real_dev, &vlan_gvrp_app, @@ -38,7 +38,7 @@ int vlan_gvrp_request_join(const struct net_device *dev) void vlan_gvrp_request_leave(const struct net_device *dev) { - const struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + const struct vlan_dev_info *vlan = vlan_dev_info(dev); __be16 vlan_id = htons(vlan->vlan_id); garp_request_leave(vlan->real_dev, &vlan_gvrp_app, diff --git a/trunk/net/8021q/vlan_netlink.c b/trunk/net/8021q/vlan_netlink.c index 50711368ad6a..235c2197dbb6 100644 --- a/trunk/net/8021q/vlan_netlink.c +++ b/trunk/net/8021q/vlan_netlink.c @@ -105,7 +105,7 @@ static int vlan_changelink(struct net_device *dev, static int vlan_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct vlan_dev_info *vlan = vlan_dev_info(dev); struct net_device *real_dev; int err; @@ -149,7 +149,7 @@ static inline size_t vlan_qos_map_size(unsigned int n) static size_t vlan_get_size(const struct net_device *dev) { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct vlan_dev_info *vlan = vlan_dev_info(dev); return nla_total_size(2) + /* IFLA_VLAN_ID */ sizeof(struct ifla_vlan_flags) + /* IFLA_VLAN_FLAGS */ @@ -159,14 +159,14 @@ static size_t vlan_get_size(const struct net_device *dev) static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev) { - struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct vlan_dev_info *vlan = vlan_dev_info(dev); struct vlan_priority_tci_mapping *pm; struct ifla_vlan_flags f; struct ifla_vlan_qos_mapping m; struct nlattr *nest; unsigned int i; - NLA_PUT_U16(skb, IFLA_VLAN_ID, vlan_dev_priv(dev)->vlan_id); + NLA_PUT_U16(skb, IFLA_VLAN_ID, vlan_dev_info(dev)->vlan_id); if (vlan->flags) { f.flags = vlan->flags; f.mask = ~0; @@ -218,7 +218,7 @@ struct rtnl_link_ops vlan_link_ops __read_mostly = { .kind = "vlan", .maxtype = IFLA_VLAN_MAX, .policy = vlan_policy, - .priv_size = sizeof(struct vlan_dev_priv), + .priv_size = sizeof(struct vlan_dev_info), .setup = vlan_setup, .validate = vlan_validate, .newlink = vlan_newlink, diff --git a/trunk/net/8021q/vlanproc.c b/trunk/net/8021q/vlanproc.c index c718fd3664b6..d34b6daf8930 100644 --- a/trunk/net/8021q/vlanproc.c +++ b/trunk/net/8021q/vlanproc.c @@ -168,13 +168,13 @@ int __net_init vlan_proc_init(struct net *net) int vlan_proc_add_dev(struct net_device *vlandev) { - struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev); + struct vlan_dev_info *dev_info = vlan_dev_info(vlandev); struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id); - vlan->dent = + dev_info->dent = proc_create_data(vlandev->name, S_IFREG|S_IRUSR|S_IWUSR, vn->proc_vlan_dir, &vlandev_fops, vlandev); - if (!vlan->dent) + if (!dev_info->dent) return -ENOBUFS; return 0; } @@ -187,10 +187,10 @@ int vlan_proc_rem_dev(struct net_device *vlandev) struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id); /** NOTE: This will consume the memory pointed to by dent, it seems. */ - if (vlan_dev_priv(vlandev)->dent) { - remove_proc_entry(vlan_dev_priv(vlandev)->dent->name, + if (vlan_dev_info(vlandev)->dent) { + remove_proc_entry(vlan_dev_info(vlandev)->dent->name, vn->proc_vlan_dir); - vlan_dev_priv(vlandev)->dent = NULL; + vlan_dev_info(vlandev)->dent = NULL; } return 0; } @@ -268,10 +268,10 @@ static int vlan_seq_show(struct seq_file *seq, void *v) nmtype ? nmtype : "UNKNOWN"); } else { const struct net_device *vlandev = v; - const struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev); + const struct vlan_dev_info *dev_info = vlan_dev_info(vlandev); seq_printf(seq, "%-15s| %d | %s\n", vlandev->name, - vlan->vlan_id, vlan->real_dev->name); + dev_info->vlan_id, dev_info->real_dev->name); } return 0; } @@ -279,7 +279,7 @@ static int vlan_seq_show(struct seq_file *seq, void *v) static int vlandev_seq_show(struct seq_file *seq, void *offset) { struct net_device *vlandev = (struct net_device *) seq->private; - const struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev); + const struct vlan_dev_info *dev_info = vlan_dev_info(vlandev); struct rtnl_link_stats64 temp; const struct rtnl_link_stats64 *stats; static const char fmt64[] = "%30s %12llu\n"; @@ -291,8 +291,8 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) stats = dev_get_stats(vlandev, &temp); seq_printf(seq, "%s VID: %d REORDER_HDR: %i dev->priv_flags: %hx\n", - vlandev->name, vlan->vlan_id, - (int)(vlan->flags & 1), vlandev->priv_flags); + vlandev->name, dev_info->vlan_id, + (int)(dev_info->flags & 1), vlandev->priv_flags); seq_printf(seq, fmt64, "total frames received", stats->rx_packets); seq_printf(seq, fmt64, "total bytes received", stats->rx_bytes); @@ -300,23 +300,23 @@ static int vlandev_seq_show(struct seq_file *seq, void *offset) seq_puts(seq, "\n"); seq_printf(seq, fmt64, "total frames transmitted", stats->tx_packets); seq_printf(seq, fmt64, "total bytes transmitted", stats->tx_bytes); - seq_printf(seq, "Device: %s", vlan->real_dev->name); + seq_printf(seq, "Device: %s", dev_info->real_dev->name); /* now show all PRIORITY mappings relating to this VLAN */ seq_printf(seq, "\nINGRESS priority mappings: " "0:%u 1:%u 2:%u 3:%u 4:%u 5:%u 6:%u 7:%u\n", - vlan->ingress_priority_map[0], - vlan->ingress_priority_map[1], - vlan->ingress_priority_map[2], - vlan->ingress_priority_map[3], - vlan->ingress_priority_map[4], - vlan->ingress_priority_map[5], - vlan->ingress_priority_map[6], - vlan->ingress_priority_map[7]); + dev_info->ingress_priority_map[0], + dev_info->ingress_priority_map[1], + dev_info->ingress_priority_map[2], + dev_info->ingress_priority_map[3], + dev_info->ingress_priority_map[4], + dev_info->ingress_priority_map[5], + dev_info->ingress_priority_map[6], + dev_info->ingress_priority_map[7]); seq_printf(seq, " EGRESS priority mappings: "); for (i = 0; i < 16; i++) { const struct vlan_priority_tci_mapping *mp - = vlan->egress_priority_map[i]; + = dev_info->egress_priority_map[i]; while (mp) { seq_printf(seq, "%u:%hu ", mp->priority, ((mp->vlan_qos >> 13) & 0x7)); diff --git a/trunk/net/batman-adv/gateway_client.c b/trunk/net/batman-adv/gateway_client.c index 24403a7350f7..9373a143c6d4 100644 --- a/trunk/net/batman-adv/gateway_client.c +++ b/trunk/net/batman-adv/gateway_client.c @@ -695,7 +695,7 @@ bool gw_out_of_range(struct bat_priv *bat_priv, } neigh_old = find_router(bat_priv, orig_dst_node, NULL); - if (!neigh_old) + if (!!neigh_old) goto out; if (curr_tq_avg - neigh_old->tq_avg > GW_THRESHOLD) diff --git a/trunk/net/batman-adv/icmp_socket.c b/trunk/net/batman-adv/icmp_socket.c index d9c1e7bb7fbf..ac3520e057c0 100644 --- a/trunk/net/batman-adv/icmp_socket.c +++ b/trunk/net/batman-adv/icmp_socket.c @@ -136,9 +136,10 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf, spin_unlock_bh(&socket_client->lock); - packet_len = min(count, socket_packet->icmp_len); - error = copy_to_user(buf, &socket_packet->icmp_packet, packet_len); + error = __copy_to_user(buf, &socket_packet->icmp_packet, + socket_packet->icmp_len); + packet_len = socket_packet->icmp_len; kfree(socket_packet); if (error) @@ -186,7 +187,12 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, skb_reserve(skb, sizeof(struct ethhdr)); icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); - if (copy_from_user(icmp_packet, buff, packet_len)) { + if (!access_ok(VERIFY_READ, buff, packet_len)) { + len = -EFAULT; + goto free_skb; + } + + if (__copy_from_user(icmp_packet, buff, packet_len)) { len = -EFAULT; goto free_skb; } @@ -211,7 +217,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, if (icmp_packet->version != COMPAT_VERSION) { icmp_packet->msg_type = PARAMETER_PROBLEM; - icmp_packet->version = COMPAT_VERSION; + icmp_packet->ttl = COMPAT_VERSION; bat_socket_add_packet(socket_client, icmp_packet, packet_len); goto free_skb; } diff --git a/trunk/net/batman-adv/routing.c b/trunk/net/batman-adv/routing.c index 773e606f9702..ef24a7205f65 100644 --- a/trunk/net/batman-adv/routing.c +++ b/trunk/net/batman-adv/routing.c @@ -627,7 +627,8 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if) /* Ensure we have all the claimed data */ if (unlikely(skb_headlen(skb) < - sizeof(struct tt_query_packet) + tt_len)) + sizeof(struct tt_query_packet) + + tt_len)) goto out; handle_tt_response(bat_priv, tt_query); diff --git a/trunk/net/batman-adv/soft-interface.c b/trunk/net/batman-adv/soft-interface.c index 987c75a775f9..45297c843092 100644 --- a/trunk/net/batman-adv/soft-interface.c +++ b/trunk/net/batman-adv/soft-interface.c @@ -874,7 +874,7 @@ struct net_device *softif_create(const char *name) unreg_sysfs: sysfs_del_meshif(soft_iface); unreg_soft_iface: - unregister_netdevice(soft_iface); + unregister_netdev(soft_iface); return NULL; free_soft_iface: diff --git a/trunk/net/batman-adv/translation-table.c b/trunk/net/batman-adv/translation-table.c index ab8dea8b0b2e..78b9528bfc2a 100644 --- a/trunk/net/batman-adv/translation-table.c +++ b/trunk/net/batman-adv/translation-table.c @@ -36,9 +36,18 @@ static void _tt_global_del(struct bat_priv *bat_priv, static void tt_purge(struct work_struct *work); /* returns 1 if they are the same mac addr */ -static int compare_tt(const struct hlist_node *node, const void *data2) +static int compare_ltt(const struct hlist_node *node, const void *data2) { - const void *data1 = container_of(node, struct tt_common_entry, + const void *data1 = container_of(node, struct tt_local_entry, + hash_entry); + + return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); +} + +/* returns 1 if they are the same mac addr */ +static int compare_gtt(const struct hlist_node *node, const void *data2) +{ + const void *data1 = container_of(node, struct tt_global_entry, hash_entry); return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); @@ -51,12 +60,13 @@ static void tt_start_timer(struct bat_priv *bat_priv) msecs_to_jiffies(5000)); } -static struct tt_common_entry *tt_hash_find(struct hashtable_t *hash, - const void *data) +static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv, + const void *data) { + struct hashtable_t *hash = bat_priv->tt_local_hash; struct hlist_head *head; struct hlist_node *node; - struct tt_common_entry *tt_common_entry, *tt_common_entry_tmp = NULL; + struct tt_local_entry *tt_local_entry, *tt_local_entry_tmp = NULL; uint32_t index; if (!hash) @@ -66,46 +76,51 @@ static struct tt_common_entry *tt_hash_find(struct hashtable_t *hash, head = &hash->table[index]; rcu_read_lock(); - hlist_for_each_entry_rcu(tt_common_entry, node, head, hash_entry) { - if (!compare_eth(tt_common_entry, data)) + hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { + if (!compare_eth(tt_local_entry, data)) continue; - if (!atomic_inc_not_zero(&tt_common_entry->refcount)) + if (!atomic_inc_not_zero(&tt_local_entry->refcount)) continue; - tt_common_entry_tmp = tt_common_entry; + tt_local_entry_tmp = tt_local_entry; break; } rcu_read_unlock(); - return tt_common_entry_tmp; -} - -static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv, - const void *data) -{ - struct tt_common_entry *tt_common_entry; - struct tt_local_entry *tt_local_entry = NULL; - - tt_common_entry = tt_hash_find(bat_priv->tt_local_hash, data); - if (tt_common_entry) - tt_local_entry = container_of(tt_common_entry, - struct tt_local_entry, common); - return tt_local_entry; + return tt_local_entry_tmp; } static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv, const void *data) { - struct tt_common_entry *tt_common_entry; - struct tt_global_entry *tt_global_entry = NULL; + struct hashtable_t *hash = bat_priv->tt_global_hash; + struct hlist_head *head; + struct hlist_node *node; + struct tt_global_entry *tt_global_entry; + struct tt_global_entry *tt_global_entry_tmp = NULL; + uint32_t index; - tt_common_entry = tt_hash_find(bat_priv->tt_global_hash, data); - if (tt_common_entry) - tt_global_entry = container_of(tt_common_entry, - struct tt_global_entry, common); - return tt_global_entry; + if (!hash) + return NULL; + index = choose_orig(data, hash->size); + head = &hash->table[index]; + + rcu_read_lock(); + hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) { + if (!compare_eth(tt_global_entry, data)) + continue; + + if (!atomic_inc_not_zero(&tt_global_entry->refcount)) + continue; + + tt_global_entry_tmp = tt_global_entry; + break; + } + rcu_read_unlock(); + + return tt_global_entry_tmp; } static bool is_out_of_time(unsigned long starting_time, unsigned long timeout) @@ -118,18 +133,15 @@ static bool is_out_of_time(unsigned long starting_time, unsigned long timeout) static void tt_local_entry_free_ref(struct tt_local_entry *tt_local_entry) { - if (atomic_dec_and_test(&tt_local_entry->common.refcount)) - kfree_rcu(tt_local_entry, common.rcu); + if (atomic_dec_and_test(&tt_local_entry->refcount)) + kfree_rcu(tt_local_entry, rcu); } static void tt_global_entry_free_rcu(struct rcu_head *rcu) { - struct tt_common_entry *tt_common_entry; struct tt_global_entry *tt_global_entry; - tt_common_entry = container_of(rcu, struct tt_common_entry, rcu); - tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, - common); + tt_global_entry = container_of(rcu, struct tt_global_entry, rcu); if (tt_global_entry->orig_node) orig_node_free_ref(tt_global_entry->orig_node); @@ -139,9 +151,8 @@ static void tt_global_entry_free_rcu(struct rcu_head *rcu) static void tt_global_entry_free_ref(struct tt_global_entry *tt_global_entry) { - if (atomic_dec_and_test(&tt_global_entry->common.refcount)) - call_rcu(&tt_global_entry->common.rcu, - tt_global_entry_free_rcu); + if (atomic_dec_and_test(&tt_global_entry->refcount)) + call_rcu(&tt_global_entry->rcu, tt_global_entry_free_rcu); } static void tt_local_event(struct bat_priv *bat_priv, const uint8_t *addr, @@ -190,7 +201,6 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, struct bat_priv *bat_priv = netdev_priv(soft_iface); struct tt_local_entry *tt_local_entry = NULL; struct tt_global_entry *tt_global_entry = NULL; - int hash_added; tt_local_entry = tt_local_hash_find(bat_priv, addr); @@ -207,33 +217,26 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, "Creating new local tt entry: %pM (ttvn: %d)\n", addr, (uint8_t)atomic_read(&bat_priv->ttvn)); - memcpy(tt_local_entry->common.addr, addr, ETH_ALEN); - tt_local_entry->common.flags = NO_FLAGS; - if (is_wifi_iface(ifindex)) - tt_local_entry->common.flags |= TT_CLIENT_WIFI; - atomic_set(&tt_local_entry->common.refcount, 2); + memcpy(tt_local_entry->addr, addr, ETH_ALEN); tt_local_entry->last_seen = jiffies; + tt_local_entry->flags = NO_FLAGS; + if (is_wifi_iface(ifindex)) + tt_local_entry->flags |= TT_CLIENT_WIFI; + atomic_set(&tt_local_entry->refcount, 2); /* the batman interface mac address should never be purged */ if (compare_eth(addr, soft_iface->dev_addr)) - tt_local_entry->common.flags |= TT_CLIENT_NOPURGE; + tt_local_entry->flags |= TT_CLIENT_NOPURGE; - hash_added = hash_add(bat_priv->tt_local_hash, compare_tt, choose_orig, - &tt_local_entry->common, - &tt_local_entry->common.hash_entry); - - if (unlikely(hash_added != 0)) { - /* remove the reference for the hash */ - tt_local_entry_free_ref(tt_local_entry); - goto out; - } - - tt_local_event(bat_priv, addr, tt_local_entry->common.flags); + tt_local_event(bat_priv, addr, tt_local_entry->flags); /* The local entry has to be marked as NEW to avoid to send it in * a full table response going out before the next ttvn increment * (consistency check) */ - tt_local_entry->common.flags |= TT_CLIENT_NEW; + tt_local_entry->flags |= TT_CLIENT_NEW; + + hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig, + tt_local_entry, &tt_local_entry->hash_entry); /* remove address from global hash if present */ tt_global_entry = tt_global_hash_find(bat_priv, addr); @@ -242,11 +245,10 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, if (tt_global_entry) { /* This node is probably going to update its tt table */ tt_global_entry->orig_node->tt_poss_change = true; - /* The global entry has to be marked as ROAMING and has to be + /* The global entry has to be marked as PENDING and has to be * kept for consistency purpose */ - tt_global_entry->common.flags |= TT_CLIENT_ROAM; - tt_global_entry->roam_at = jiffies; - send_roam_adv(bat_priv, tt_global_entry->common.addr, + tt_global_entry->flags |= TT_CLIENT_PENDING; + send_roam_adv(bat_priv, tt_global_entry->addr, tt_global_entry->orig_node); } out: @@ -308,7 +310,7 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset) struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hashtable_t *hash = bat_priv->tt_local_hash; - struct tt_common_entry *tt_common_entry; + struct tt_local_entry *tt_local_entry; struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; @@ -338,19 +340,19 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset) head = &hash->table[i]; rcu_read_lock(); - hlist_for_each_entry_rcu(tt_common_entry, node, + hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { seq_printf(seq, " * %pM [%c%c%c%c%c]\n", - tt_common_entry->addr, - (tt_common_entry->flags & + tt_local_entry->addr, + (tt_local_entry->flags & TT_CLIENT_ROAM ? 'R' : '.'), - (tt_common_entry->flags & + (tt_local_entry->flags & TT_CLIENT_NOPURGE ? 'P' : '.'), - (tt_common_entry->flags & + (tt_local_entry->flags & TT_CLIENT_NEW ? 'N' : '.'), - (tt_common_entry->flags & + (tt_local_entry->flags & TT_CLIENT_PENDING ? 'X' : '.'), - (tt_common_entry->flags & + (tt_local_entry->flags & TT_CLIENT_WIFI ? 'W' : '.')); } rcu_read_unlock(); @@ -365,13 +367,13 @@ static void tt_local_set_pending(struct bat_priv *bat_priv, struct tt_local_entry *tt_local_entry, uint16_t flags) { - tt_local_event(bat_priv, tt_local_entry->common.addr, - tt_local_entry->common.flags | flags); + tt_local_event(bat_priv, tt_local_entry->addr, + tt_local_entry->flags | flags); /* The local client has to be marked as "pending to be removed" but has * to be kept in the table in order to send it in a full table * response issued before the net ttvn increment (consistency check) */ - tt_local_entry->common.flags |= TT_CLIENT_PENDING; + tt_local_entry->flags |= TT_CLIENT_PENDING; } void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, @@ -387,7 +389,7 @@ void tt_local_remove(struct bat_priv *bat_priv, const uint8_t *addr, (roaming ? TT_CLIENT_ROAM : NO_FLAGS)); bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) pending to be removed: " - "%s\n", tt_local_entry->common.addr, message); + "%s\n", tt_local_entry->addr, message); out: if (tt_local_entry) tt_local_entry_free_ref(tt_local_entry); @@ -397,7 +399,6 @@ static void tt_local_purge(struct bat_priv *bat_priv) { struct hashtable_t *hash = bat_priv->tt_local_hash; struct tt_local_entry *tt_local_entry; - struct tt_common_entry *tt_common_entry; struct hlist_node *node, *node_tmp; struct hlist_head *head; spinlock_t *list_lock; /* protects write access to the hash lists */ @@ -408,16 +409,13 @@ static void tt_local_purge(struct bat_priv *bat_priv) list_lock = &hash->list_locks[i]; spin_lock_bh(list_lock); - hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, + hlist_for_each_entry_safe(tt_local_entry, node, node_tmp, head, hash_entry) { - tt_local_entry = container_of(tt_common_entry, - struct tt_local_entry, - common); - if (tt_local_entry->common.flags & TT_CLIENT_NOPURGE) + if (tt_local_entry->flags & TT_CLIENT_NOPURGE) continue; /* entry already marked for deletion */ - if (tt_local_entry->common.flags & TT_CLIENT_PENDING) + if (tt_local_entry->flags & TT_CLIENT_PENDING) continue; if (!is_out_of_time(tt_local_entry->last_seen, @@ -428,7 +426,7 @@ static void tt_local_purge(struct bat_priv *bat_priv) TT_CLIENT_DEL); bat_dbg(DBG_TT, bat_priv, "Local tt entry (%pM) " "pending to be removed: timed out\n", - tt_local_entry->common.addr); + tt_local_entry->addr); } spin_unlock_bh(list_lock); } @@ -439,7 +437,6 @@ static void tt_local_table_free(struct bat_priv *bat_priv) { struct hashtable_t *hash; spinlock_t *list_lock; /* protects write access to the hash lists */ - struct tt_common_entry *tt_common_entry; struct tt_local_entry *tt_local_entry; struct hlist_node *node, *node_tmp; struct hlist_head *head; @@ -455,12 +452,9 @@ static void tt_local_table_free(struct bat_priv *bat_priv) list_lock = &hash->list_locks[i]; spin_lock_bh(list_lock); - hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, + hlist_for_each_entry_safe(tt_local_entry, node, node_tmp, head, hash_entry) { hlist_del_rcu(node); - tt_local_entry = container_of(tt_common_entry, - struct tt_local_entry, - common); tt_local_entry_free_ref(tt_local_entry); } spin_unlock_bh(list_lock); @@ -508,7 +502,6 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, struct tt_global_entry *tt_global_entry; struct orig_node *orig_node_tmp; int ret = 0; - int hash_added; tt_global_entry = tt_global_hash_find(bat_priv, tt_addr); @@ -519,24 +512,18 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, if (!tt_global_entry) goto out; - memcpy(tt_global_entry->common.addr, tt_addr, ETH_ALEN); - tt_global_entry->common.flags = NO_FLAGS; - atomic_set(&tt_global_entry->common.refcount, 2); + memcpy(tt_global_entry->addr, tt_addr, ETH_ALEN); /* Assign the new orig_node */ atomic_inc(&orig_node->refcount); tt_global_entry->orig_node = orig_node; tt_global_entry->ttvn = ttvn; + tt_global_entry->flags = NO_FLAGS; tt_global_entry->roam_at = 0; + atomic_set(&tt_global_entry->refcount, 2); - hash_added = hash_add(bat_priv->tt_global_hash, compare_tt, - choose_orig, &tt_global_entry->common, - &tt_global_entry->common.hash_entry); - - if (unlikely(hash_added != 0)) { - /* remove the reference for the hash */ - tt_global_entry_free_ref(tt_global_entry); - goto out_remove; - } + hash_add(bat_priv->tt_global_hash, compare_gtt, + choose_orig, tt_global_entry, + &tt_global_entry->hash_entry); atomic_inc(&orig_node->tt_size); } else { if (tt_global_entry->orig_node != orig_node) { @@ -547,21 +534,20 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, orig_node_free_ref(orig_node_tmp); atomic_inc(&orig_node->tt_size); } - tt_global_entry->common.flags = NO_FLAGS; tt_global_entry->ttvn = ttvn; + tt_global_entry->flags = NO_FLAGS; tt_global_entry->roam_at = 0; } if (wifi) - tt_global_entry->common.flags |= TT_CLIENT_WIFI; + tt_global_entry->flags |= TT_CLIENT_WIFI; bat_dbg(DBG_TT, bat_priv, "Creating new global tt entry: %pM (via %pM)\n", - tt_global_entry->common.addr, orig_node->orig); + tt_global_entry->addr, orig_node->orig); -out_remove: /* remove address from local hash if present */ - tt_local_remove(bat_priv, tt_global_entry->common.addr, + tt_local_remove(bat_priv, tt_global_entry->addr, "global tt received", roaming); ret = 1; out: @@ -575,7 +561,6 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hashtable_t *hash = bat_priv->tt_global_hash; - struct tt_common_entry *tt_common_entry; struct tt_global_entry *tt_global_entry; struct hard_iface *primary_if; struct hlist_node *node; @@ -608,24 +593,20 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) head = &hash->table[i]; rcu_read_lock(); - hlist_for_each_entry_rcu(tt_common_entry, node, + hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) { - tt_global_entry = container_of(tt_common_entry, - struct tt_global_entry, - common); seq_printf(seq, " * %pM (%3u) via %pM (%3u) " - "[%c%c%c]\n", - tt_global_entry->common.addr, + "[%c%c%c]\n", tt_global_entry->addr, tt_global_entry->ttvn, tt_global_entry->orig_node->orig, (uint8_t) atomic_read( &tt_global_entry->orig_node-> last_ttvn), - (tt_global_entry->common.flags & + (tt_global_entry->flags & TT_CLIENT_ROAM ? 'R' : '.'), - (tt_global_entry->common.flags & + (tt_global_entry->flags & TT_CLIENT_PENDING ? 'X' : '.'), - (tt_global_entry->common.flags & + (tt_global_entry->flags & TT_CLIENT_WIFI ? 'W' : '.')); } rcu_read_unlock(); @@ -645,13 +626,13 @@ static void _tt_global_del(struct bat_priv *bat_priv, bat_dbg(DBG_TT, bat_priv, "Deleting global tt entry %pM (via %pM): %s\n", - tt_global_entry->common.addr, tt_global_entry->orig_node->orig, + tt_global_entry->addr, tt_global_entry->orig_node->orig, message); atomic_dec(&tt_global_entry->orig_node->tt_size); - hash_remove(bat_priv->tt_global_hash, compare_tt, choose_orig, - tt_global_entry->common.addr); + hash_remove(bat_priv->tt_global_hash, compare_gtt, choose_orig, + tt_global_entry->addr); out: if (tt_global_entry) tt_global_entry_free_ref(tt_global_entry); @@ -662,7 +643,6 @@ void tt_global_del(struct bat_priv *bat_priv, const char *message, bool roaming) { struct tt_global_entry *tt_global_entry = NULL; - struct tt_local_entry *tt_local_entry = NULL; tt_global_entry = tt_global_hash_find(bat_priv, addr); if (!tt_global_entry) @@ -670,36 +650,21 @@ void tt_global_del(struct bat_priv *bat_priv, if (tt_global_entry->orig_node == orig_node) { if (roaming) { - /* if we are deleting a global entry due to a roam - * event, there are two possibilities: - * 1) the client roamed from node A to node B => we mark - * it with TT_CLIENT_ROAM, we start a timer and we - * wait for node B to claim it. In case of timeout - * the entry is purged. - * 2) the client roamed to us => we can directly delete - * the global entry, since it is useless now. */ - tt_local_entry = tt_local_hash_find(bat_priv, - tt_global_entry->common.addr); - if (!tt_local_entry) { - tt_global_entry->common.flags |= TT_CLIENT_ROAM; - tt_global_entry->roam_at = jiffies; - goto out; - } + tt_global_entry->flags |= TT_CLIENT_ROAM; + tt_global_entry->roam_at = jiffies; + goto out; } _tt_global_del(bat_priv, tt_global_entry, message); } out: if (tt_global_entry) tt_global_entry_free_ref(tt_global_entry); - if (tt_local_entry) - tt_local_entry_free_ref(tt_local_entry); } void tt_global_del_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, const char *message) { struct tt_global_entry *tt_global_entry; - struct tt_common_entry *tt_common_entry; uint32_t i; struct hashtable_t *hash = bat_priv->tt_global_hash; struct hlist_node *node, *safe; @@ -714,16 +679,13 @@ void tt_global_del_orig(struct bat_priv *bat_priv, list_lock = &hash->list_locks[i]; spin_lock_bh(list_lock); - hlist_for_each_entry_safe(tt_common_entry, node, safe, + hlist_for_each_entry_safe(tt_global_entry, node, safe, head, hash_entry) { - tt_global_entry = container_of(tt_common_entry, - struct tt_global_entry, - common); if (tt_global_entry->orig_node == orig_node) { bat_dbg(DBG_TT, bat_priv, "Deleting global tt entry %pM " "(via %pM): %s\n", - tt_global_entry->common.addr, + tt_global_entry->addr, tt_global_entry->orig_node->orig, message); hlist_del_rcu(node); @@ -738,7 +700,6 @@ void tt_global_del_orig(struct bat_priv *bat_priv, static void tt_global_roam_purge(struct bat_priv *bat_priv) { struct hashtable_t *hash = bat_priv->tt_global_hash; - struct tt_common_entry *tt_common_entry; struct tt_global_entry *tt_global_entry; struct hlist_node *node, *node_tmp; struct hlist_head *head; @@ -750,12 +711,9 @@ static void tt_global_roam_purge(struct bat_priv *bat_priv) list_lock = &hash->list_locks[i]; spin_lock_bh(list_lock); - hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, + hlist_for_each_entry_safe(tt_global_entry, node, node_tmp, head, hash_entry) { - tt_global_entry = container_of(tt_common_entry, - struct tt_global_entry, - common); - if (!(tt_global_entry->common.flags & TT_CLIENT_ROAM)) + if (!(tt_global_entry->flags & TT_CLIENT_ROAM)) continue; if (!is_out_of_time(tt_global_entry->roam_at, TT_CLIENT_ROAM_TIMEOUT * 1000)) @@ -763,7 +721,7 @@ static void tt_global_roam_purge(struct bat_priv *bat_priv) bat_dbg(DBG_TT, bat_priv, "Deleting global " "tt entry (%pM): Roaming timeout\n", - tt_global_entry->common.addr); + tt_global_entry->addr); atomic_dec(&tt_global_entry->orig_node->tt_size); hlist_del_rcu(node); tt_global_entry_free_ref(tt_global_entry); @@ -777,7 +735,6 @@ static void tt_global_table_free(struct bat_priv *bat_priv) { struct hashtable_t *hash; spinlock_t *list_lock; /* protects write access to the hash lists */ - struct tt_common_entry *tt_common_entry; struct tt_global_entry *tt_global_entry; struct hlist_node *node, *node_tmp; struct hlist_head *head; @@ -793,12 +750,9 @@ static void tt_global_table_free(struct bat_priv *bat_priv) list_lock = &hash->list_locks[i]; spin_lock_bh(list_lock); - hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, + hlist_for_each_entry_safe(tt_global_entry, node, node_tmp, head, hash_entry) { hlist_del_rcu(node); - tt_global_entry = container_of(tt_common_entry, - struct tt_global_entry, - common); tt_global_entry_free_ref(tt_global_entry); } spin_unlock_bh(list_lock); @@ -814,8 +768,8 @@ static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry, { bool ret = false; - if (tt_local_entry->common.flags & TT_CLIENT_WIFI && - tt_global_entry->common.flags & TT_CLIENT_WIFI) + if (tt_local_entry->flags & TT_CLIENT_WIFI && + tt_global_entry->flags & TT_CLIENT_WIFI) ret = true; return ret; @@ -848,7 +802,7 @@ struct orig_node *transtable_search(struct bat_priv *bat_priv, /* A global client marked as PENDING has already moved from that * originator */ - if (tt_global_entry->common.flags & TT_CLIENT_PENDING) + if (tt_global_entry->flags & TT_CLIENT_PENDING) goto out; orig_node = tt_global_entry->orig_node; @@ -867,7 +821,6 @@ uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node) { uint16_t total = 0, total_one; struct hashtable_t *hash = bat_priv->tt_global_hash; - struct tt_common_entry *tt_common_entry; struct tt_global_entry *tt_global_entry; struct hlist_node *node; struct hlist_head *head; @@ -878,23 +831,20 @@ uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node) head = &hash->table[i]; rcu_read_lock(); - hlist_for_each_entry_rcu(tt_common_entry, node, + hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) { - tt_global_entry = container_of(tt_common_entry, - struct tt_global_entry, - common); if (compare_eth(tt_global_entry->orig_node, orig_node)) { /* Roaming clients are in the global table for * consistency only. They don't have to be * taken into account while computing the * global crc */ - if (tt_common_entry->flags & TT_CLIENT_ROAM) + if (tt_global_entry->flags & TT_CLIENT_ROAM) continue; total_one = 0; for (j = 0; j < ETH_ALEN; j++) total_one = crc16_byte(total_one, - tt_common_entry->addr[j]); + tt_global_entry->addr[j]); total ^= total_one; } } @@ -909,7 +859,7 @@ uint16_t tt_local_crc(struct bat_priv *bat_priv) { uint16_t total = 0, total_one; struct hashtable_t *hash = bat_priv->tt_local_hash; - struct tt_common_entry *tt_common_entry; + struct tt_local_entry *tt_local_entry; struct hlist_node *node; struct hlist_head *head; uint32_t i; @@ -919,16 +869,16 @@ uint16_t tt_local_crc(struct bat_priv *bat_priv) head = &hash->table[i]; rcu_read_lock(); - hlist_for_each_entry_rcu(tt_common_entry, node, + hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { /* not yet committed clients have not to be taken into * account while computing the CRC */ - if (tt_common_entry->flags & TT_CLIENT_NEW) + if (tt_local_entry->flags & TT_CLIENT_NEW) continue; total_one = 0; for (j = 0; j < ETH_ALEN; j++) total_one = crc16_byte(total_one, - tt_common_entry->addr[j]); + tt_local_entry->addr[j]); total ^= total_one; } rcu_read_unlock(); @@ -1017,25 +967,21 @@ static struct tt_req_node *new_tt_req_node(struct bat_priv *bat_priv, /* data_ptr is useless here, but has to be kept to respect the prototype */ static int tt_local_valid_entry(const void *entry_ptr, const void *data_ptr) { - const struct tt_common_entry *tt_common_entry = entry_ptr; + const struct tt_local_entry *tt_local_entry = entry_ptr; - if (tt_common_entry->flags & TT_CLIENT_NEW) + if (tt_local_entry->flags & TT_CLIENT_NEW) return 0; return 1; } static int tt_global_valid_entry(const void *entry_ptr, const void *data_ptr) { - const struct tt_common_entry *tt_common_entry = entry_ptr; - const struct tt_global_entry *tt_global_entry; + const struct tt_global_entry *tt_global_entry = entry_ptr; const struct orig_node *orig_node = data_ptr; - if (tt_common_entry->flags & TT_CLIENT_ROAM) + if (tt_global_entry->flags & TT_CLIENT_ROAM) return 0; - tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, - common); - return (tt_global_entry->orig_node == orig_node); } @@ -1046,7 +992,7 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, const void *), void *cb_data) { - struct tt_common_entry *tt_common_entry; + struct tt_local_entry *tt_local_entry; struct tt_query_packet *tt_response; struct tt_change *tt_change; struct hlist_node *node; @@ -1078,16 +1024,15 @@ static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, for (i = 0; i < hash->size; i++) { head = &hash->table[i]; - hlist_for_each_entry_rcu(tt_common_entry, node, + hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { if (tt_count == tt_tot) break; - if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) + if ((valid_cb) && (!valid_cb(tt_local_entry, cb_data))) continue; - memcpy(tt_change->addr, tt_common_entry->addr, - ETH_ALEN); + memcpy(tt_change->addr, tt_local_entry->addr, ETH_ALEN); tt_change->flags = NO_FLAGS; tt_count++; @@ -1504,7 +1449,7 @@ bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr) goto out; /* Check if the client has been logically deleted (but is kept for * consistency purpose) */ - if (tt_local_entry->common.flags & TT_CLIENT_PENDING) + if (tt_local_entry->flags & TT_CLIENT_PENDING) goto out; ret = true; out: @@ -1727,48 +1672,40 @@ void tt_free(struct bat_priv *bat_priv) kfree(bat_priv->tt_buff); } -/* This function will enable or disable the specified flags for all the entries - * in the given hash table and returns the number of modified entries */ -static uint16_t tt_set_flags(struct hashtable_t *hash, uint16_t flags, - bool enable) +/* This function will reset the specified flags from all the entries in + * the given hash table and will increment num_local_tt for each involved + * entry */ +static void tt_local_reset_flags(struct bat_priv *bat_priv, uint16_t flags) { uint32_t i; - uint16_t changed_num = 0; + struct hashtable_t *hash = bat_priv->tt_local_hash; struct hlist_head *head; struct hlist_node *node; - struct tt_common_entry *tt_common_entry; + struct tt_local_entry *tt_local_entry; if (!hash) - goto out; + return; for (i = 0; i < hash->size; i++) { head = &hash->table[i]; rcu_read_lock(); - hlist_for_each_entry_rcu(tt_common_entry, node, + hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { - if (enable) { - if ((tt_common_entry->flags & flags) == flags) - continue; - tt_common_entry->flags |= flags; - } else { - if (!(tt_common_entry->flags & flags)) - continue; - tt_common_entry->flags &= ~flags; - } - changed_num++; + if (!(tt_local_entry->flags & flags)) + continue; + tt_local_entry->flags &= ~flags; + atomic_inc(&bat_priv->num_local_tt); } rcu_read_unlock(); } -out: - return changed_num; + } /* Purge out all the tt local entries marked with TT_CLIENT_PENDING */ static void tt_local_purge_pending_clients(struct bat_priv *bat_priv) { struct hashtable_t *hash = bat_priv->tt_local_hash; - struct tt_common_entry *tt_common_entry; struct tt_local_entry *tt_local_entry; struct hlist_node *node, *node_tmp; struct hlist_head *head; @@ -1783,19 +1720,16 @@ static void tt_local_purge_pending_clients(struct bat_priv *bat_priv) list_lock = &hash->list_locks[i]; spin_lock_bh(list_lock); - hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, + hlist_for_each_entry_safe(tt_local_entry, node, node_tmp, head, hash_entry) { - if (!(tt_common_entry->flags & TT_CLIENT_PENDING)) + if (!(tt_local_entry->flags & TT_CLIENT_PENDING)) continue; bat_dbg(DBG_TT, bat_priv, "Deleting local tt entry " - "(%pM): pending\n", tt_common_entry->addr); + "(%pM): pending\n", tt_local_entry->addr); atomic_dec(&bat_priv->num_local_tt); hlist_del_rcu(node); - tt_local_entry = container_of(tt_common_entry, - struct tt_local_entry, - common); tt_local_entry_free_ref(tt_local_entry); } spin_unlock_bh(list_lock); @@ -1805,11 +1739,7 @@ static void tt_local_purge_pending_clients(struct bat_priv *bat_priv) void tt_commit_changes(struct bat_priv *bat_priv) { - uint16_t changed_num = tt_set_flags(bat_priv->tt_local_hash, - TT_CLIENT_NEW, false); - /* all the reset entries have now to be effectively counted as local - * entries */ - atomic_add(changed_num, &bat_priv->num_local_tt); + tt_local_reset_flags(bat_priv, TT_CLIENT_NEW); tt_local_purge_pending_clients(bat_priv); /* Increment the TTVN only once per OGM interval */ diff --git a/trunk/net/batman-adv/types.h b/trunk/net/batman-adv/types.h index e9eb043719ac..ab8d0fe6df5a 100644 --- a/trunk/net/batman-adv/types.h +++ b/trunk/net/batman-adv/types.h @@ -222,24 +222,24 @@ struct socket_packet { struct icmp_packet_rr icmp_packet; }; -struct tt_common_entry { +struct tt_local_entry { uint8_t addr[ETH_ALEN]; struct hlist_node hash_entry; + unsigned long last_seen; uint16_t flags; atomic_t refcount; struct rcu_head rcu; }; -struct tt_local_entry { - struct tt_common_entry common; - unsigned long last_seen; -}; - struct tt_global_entry { - struct tt_common_entry common; + uint8_t addr[ETH_ALEN]; + struct hlist_node hash_entry; /* entry in the global table */ struct orig_node *orig_node; uint8_t ttvn; + uint16_t flags; /* only TT_GLOBAL_ROAM is used */ unsigned long roam_at; /* time at which TT_GLOBAL_ROAM was set */ + atomic_t refcount; + struct rcu_head rcu; }; struct tt_change_node { diff --git a/trunk/net/batman-adv/vis.c b/trunk/net/batman-adv/vis.c index cc3b9f2f3b5d..7445413253ca 100644 --- a/trunk/net/batman-adv/vis.c +++ b/trunk/net/batman-adv/vis.c @@ -609,7 +609,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv) struct vis_info *info = bat_priv->my_vis_info; struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; struct vis_info_entry *entry; - struct tt_common_entry *tt_common_entry; + struct tt_local_entry *tt_local_entry; int best_tq = -1; uint32_t i; @@ -672,13 +672,13 @@ static int generate_vis_packet(struct bat_priv *bat_priv) head = &hash->table[i]; rcu_read_lock(); - hlist_for_each_entry_rcu(tt_common_entry, node, head, + hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { entry = (struct vis_info_entry *) skb_put(info->skb_packet, sizeof(*entry)); memset(entry->src, 0, ETH_ALEN); - memcpy(entry->dest, tt_common_entry->addr, ETH_ALEN); + memcpy(entry->dest, tt_local_entry->addr, ETH_ALEN); entry->quality = 0; /* 0 means TT */ packet->entries++; diff --git a/trunk/net/bluetooth/bnep/core.c b/trunk/net/bluetooth/bnep/core.c index 42d53b85a808..a6cd856046ab 100644 --- a/trunk/net/bluetooth/bnep/core.c +++ b/trunk/net/bluetooth/bnep/core.c @@ -77,12 +77,17 @@ static struct bnep_session *__bnep_get_session(u8 *dst) static void __bnep_link_session(struct bnep_session *s) { + /* It's safe to call __module_get() here because sessions are added + by the socket layer which has to hold the reference to this module. + */ + __module_get(THIS_MODULE); list_add(&s->list, &bnep_session_list); } static void __bnep_unlink_session(struct bnep_session *s) { list_del(&s->list); + module_put(THIS_MODULE); } static int bnep_send(struct bnep_session *s, void *data, size_t len) @@ -523,7 +528,6 @@ static int bnep_session(void *arg) up_write(&bnep_session_sem); free_netdev(dev); - module_put_and_exit(0); return 0; } @@ -610,11 +614,9 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) __bnep_link_session(s); - __module_get(THIS_MODULE); s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name); if (IS_ERR(s->task)) { /* Session thread start failed, gotta cleanup. */ - module_put(THIS_MODULE); unregister_netdev(dev); __bnep_unlink_session(s); err = PTR_ERR(s->task); diff --git a/trunk/net/bluetooth/cmtp/core.c b/trunk/net/bluetooth/cmtp/core.c index 6c9c1fd601ca..9e8940b24bba 100644 --- a/trunk/net/bluetooth/cmtp/core.c +++ b/trunk/net/bluetooth/cmtp/core.c @@ -65,12 +65,14 @@ static struct cmtp_session *__cmtp_get_session(bdaddr_t *bdaddr) static void __cmtp_link_session(struct cmtp_session *session) { + __module_get(THIS_MODULE); list_add(&session->list, &cmtp_session_list); } static void __cmtp_unlink_session(struct cmtp_session *session) { list_del(&session->list); + module_put(THIS_MODULE); } static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci) @@ -323,7 +325,6 @@ static int cmtp_session(void *arg) up_write(&cmtp_session_sem); kfree(session); - module_put_and_exit(0); return 0; } @@ -373,11 +374,9 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) __cmtp_link_session(session); - __module_get(THIS_MODULE); session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d", session->num); if (IS_ERR(session->task)) { - module_put(THIS_MODULE); err = PTR_ERR(session->task); goto unlink; } diff --git a/trunk/net/bluetooth/hci_conn.c b/trunk/net/bluetooth/hci_conn.c index b328ac611ccd..de0b93e45980 100644 --- a/trunk/net/bluetooth/hci_conn.c +++ b/trunk/net/bluetooth/hci_conn.c @@ -123,7 +123,7 @@ static void hci_acl_connect_cancel(struct hci_conn *conn) BT_DBG("%p", conn); - if (conn->hdev->hci_ver < BLUETOOTH_VER_1_2) + if (conn->hdev->hci_ver < 2) return; bacpy(&cp.bdaddr, &conn->dst); diff --git a/trunk/net/bluetooth/hci_core.c b/trunk/net/bluetooth/hci_core.c index ce3727ecc0c4..fb3feeb185d7 100644 --- a/trunk/net/bluetooth/hci_core.c +++ b/trunk/net/bluetooth/hci_core.c @@ -54,8 +54,6 @@ #define AUTO_OFF_TIMEOUT 2000 -int enable_hs; - static void hci_cmd_task(unsigned long arg); static void hci_rx_task(unsigned long arg); static void hci_tx_task(unsigned long arg); @@ -230,6 +228,18 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) /* Read Buffer Size (ACL mtu, max pkt, etc.) */ hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); +#if 0 + /* Host buffer size */ + { + struct hci_cp_host_buffer_size cp; + cp.acl_mtu = cpu_to_le16(HCI_MAX_ACL_SIZE); + cp.sco_mtu = HCI_MAX_SCO_SIZE; + cp.acl_max_pkt = cpu_to_le16(0xffff); + cp.sco_max_pkt = cpu_to_le16(0xffff); + hci_send_cmd(hdev, HCI_OP_HOST_BUFFER_SIZE, sizeof(cp), &cp); + } +#endif + /* Read BD Address */ hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); @@ -511,9 +521,8 @@ int hci_dev_open(__u16 dev) if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) set_bit(HCI_RAW, &hdev->flags); - /* Treat all non BR/EDR controllers as raw devices if - enable_hs is not set */ - if (hdev->dev_type != HCI_BREDR && !enable_hs) + /* Treat all non BR/EDR controllers as raw devices for now */ + if (hdev->dev_type != HCI_BREDR) set_bit(HCI_RAW, &hdev->flags); if (hdev->open(hdev)) { @@ -1327,12 +1336,14 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr) { struct bdaddr_list *entry; - if (bacmp(bdaddr, BDADDR_ANY) == 0) + if (bacmp(bdaddr, BDADDR_ANY) == 0) { return hci_blacklist_clear(hdev); + } entry = hci_blacklist_lookup(hdev, bdaddr); - if (!entry) + if (!entry) { return -ENOENT; + } list_del(&entry->list); kfree(entry); @@ -1440,13 +1451,12 @@ int hci_register_dev(struct hci_dev *hdev) sprintf(hdev->name, "hci%d", id); hdev->id = id; - list_add_tail(&hdev->list, head); + list_add(&hdev->list, head); atomic_set(&hdev->refcnt, 1); spin_lock_init(&hdev->lock); hdev->flags = 0; - hdev->dev_flags = 0; hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); hdev->esco_type = (ESCO_HV1); hdev->link_mode = (HCI_LM_ACCEPT); @@ -2604,6 +2614,3 @@ int hci_cancel_inquiry(struct hci_dev *hdev) return hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL); } - -module_param(enable_hs, bool, 0644); -MODULE_PARM_DESC(enable_hs, "Enable High Speed"); diff --git a/trunk/net/bluetooth/hci_event.c b/trunk/net/bluetooth/hci_event.c index 35cb56ed3b0b..a89cf1f24e47 100644 --- a/trunk/net/bluetooth/hci_event.c +++ b/trunk/net/bluetooth/hci_event.c @@ -55,12 +55,8 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s status 0x%x", hdev->name, status); - if (status) { - hci_dev_lock(hdev); - mgmt_stop_discovery_failed(hdev, status); - hci_dev_unlock(hdev); + if (status) return; - } clear_bit(HCI_INQUIRY, &hdev->flags); @@ -194,8 +190,6 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) clear_bit(HCI_RESET, &hdev->flags); hci_req_complete(hdev, HCI_OP_RESET, status); - - hdev->dev_flags = 0; } static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) @@ -500,7 +494,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) /* CSR 1.1 dongles does not accept any bitfield so don't try to set * any event mask for pre 1.2 devices */ - if (hdev->hci_ver < BLUETOOTH_VER_1_2) + if (hdev->lmp_ver <= 1) return; events[4] |= 0x01; /* Flow Specification Complete */ @@ -564,7 +558,7 @@ static void hci_setup(struct hci_dev *hdev) { hci_setup_event_mask(hdev); - if (hdev->hci_ver > BLUETOOTH_VER_1_1) + if (hdev->lmp_ver > 1) hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); if (hdev->features[6] & LMP_SIMPLE_PAIR) { @@ -719,21 +713,6 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); } -static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, - struct sk_buff *skb) -{ - struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; - - BT_DBG("%s status 0x%x", hdev->name, rp->status); - - if (rp->status) - return; - - hdev->flow_ctl_mode = rp->mode; - - hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); -} - static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_rp_read_buffer_size *rp = (void *) skb->data; @@ -948,37 +927,6 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) -{ - struct hci_rp_user_confirm_reply *rp = (void *) skb->data; - - BT_DBG("%s status 0x%x", hdev->name, rp->status); - - hci_dev_lock(hdev); - - if (test_bit(HCI_MGMT, &hdev->flags)) - mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, - rp->status); - - hci_dev_unlock(hdev); -} - -static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, - struct sk_buff *skb) -{ - struct hci_rp_user_confirm_reply *rp = (void *) skb->data; - - BT_DBG("%s status 0x%x", hdev->name, rp->status); - - hci_dev_lock(hdev); - - if (test_bit(HCI_MGMT, &hdev->flags)) - mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr, - rp->status); - - hci_dev_unlock(hdev); -} - static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, struct sk_buff *skb) { @@ -992,13 +940,6 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) -{ - __u8 status = *((__u8 *) skb->data); - - BT_DBG("%s status 0x%x", hdev->name, status); -} - static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) { @@ -1015,16 +956,12 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, return; if (cp->enable == 0x01) { - set_bit(HCI_LE_SCAN, &hdev->dev_flags); - del_timer(&hdev->adv_timer); hci_dev_lock(hdev); hci_adv_entries_clear(hdev); hci_dev_unlock(hdev); } else if (cp->enable == 0x00) { - clear_bit(HCI_LE_SCAN, &hdev->dev_flags); - mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); } } @@ -1077,7 +1014,7 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) hci_conn_check_pending(hdev); hci_dev_lock(hdev); if (test_bit(HCI_MGMT, &hdev->flags)) - mgmt_start_discovery_failed(hdev, status); + mgmt_inquiry_failed(hdev, status); hci_dev_unlock(hdev); return; } @@ -1500,7 +1437,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff * data.rssi = 0x00; data.ssp_mode = 0x00; hci_inquiry_cache_update(hdev, &data); - mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, + mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, info->dev_class, 0, NULL); } @@ -1535,8 +1472,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s conn->state = BT_CONFIG; hci_conn_hold(conn); conn->disc_timeout = HCI_DISCONN_TIMEOUT; - mgmt_connected(hdev, &ev->bdaddr, conn->type, - conn->dst_type); + mgmt_connected(hdev, &ev->bdaddr, conn->type); } else conn->state = BT_CONNECTED; @@ -1558,7 +1494,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s } /* Set packet type for incoming connection */ - if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { + if (!conn->out && hdev->hci_ver < 3) { struct hci_cp_change_conn_ptype cp; cp.handle = ev->handle; cp.pkt_type = cpu_to_le16(conn->pkt_type); @@ -1569,7 +1505,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s conn->state = BT_CLOSED; if (conn->type == ACL_LINK) mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, - conn->dst_type, ev->status); + ev->status); } if (conn->type == ACL_LINK) @@ -1668,27 +1604,26 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff BT_DBG("%s status %d", hdev->name, ev->status); + if (ev->status) { + hci_dev_lock(hdev); + mgmt_disconnect_failed(hdev); + hci_dev_unlock(hdev); + return; + } + hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); if (!conn) goto unlock; - if (ev->status == 0) - conn->state = BT_CLOSED; + conn->state = BT_CLOSED; - if (conn->type == ACL_LINK || conn->type == LE_LINK) { - if (ev->status != 0) - mgmt_disconnect_failed(hdev, &conn->dst, ev->status); - else - mgmt_disconnected(hdev, &conn->dst, conn->type, - conn->dst_type); - } + if (conn->type == ACL_LINK || conn->type == LE_LINK) + mgmt_disconnected(hdev, &conn->dst, conn->type); - if (ev->status == 0) { - hci_proto_disconn_cfm(conn, ev->reason); - hci_conn_del(conn); - } + hci_proto_disconn_cfm(conn, ev->reason); + hci_conn_del(conn); unlock: hci_dev_unlock(hdev); @@ -2026,10 +1961,6 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk hci_cc_write_ca_timeout(hdev, skb); break; - case HCI_OP_READ_FLOW_CONTROL_MODE: - hci_cc_read_flow_control_mode(hdev, skb); - break; - case HCI_OP_READ_LOCAL_AMP_INFO: hci_cc_read_local_amp_info(hdev, skb); break; @@ -2078,17 +2009,6 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk hci_cc_user_confirm_neg_reply(hdev, skb); break; - case HCI_OP_USER_PASSKEY_REPLY: - hci_cc_user_passkey_reply(hdev, skb); - break; - - case HCI_OP_USER_PASSKEY_NEG_REPLY: - hci_cc_user_passkey_neg_reply(hdev, skb); - - case HCI_OP_LE_SET_SCAN_PARAM: - hci_cc_le_set_scan_param(hdev, skb); - break; - case HCI_OP_LE_SET_SCAN_ENABLE: hci_cc_le_set_scan_enable(hdev, skb); break; @@ -2176,7 +2096,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) case HCI_OP_DISCONNECT: if (ev->status != 0) - mgmt_disconnect_failed(hdev, NULL, ev->status); + mgmt_disconnect_failed(hdev); break; case HCI_OP_LE_CREATE_CONN: @@ -2524,7 +2444,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct data.rssi = info->rssi; data.ssp_mode = 0x00; hci_inquiry_cache_update(hdev, &data); - mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, + mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, info->dev_class, info->rssi, NULL); } @@ -2541,7 +2461,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct data.rssi = info->rssi; data.ssp_mode = 0x00; hci_inquiry_cache_update(hdev, &data); - mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, + mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, info->dev_class, info->rssi, NULL); } @@ -2684,7 +2604,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct data.rssi = info->rssi; data.ssp_mode = 0x01; hci_inquiry_cache_update(hdev, &data); - mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, + mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, info->dev_class, info->rssi, info->data); } @@ -2848,21 +2768,6 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static inline void hci_user_passkey_request_evt(struct hci_dev *hdev, - struct sk_buff *skb) -{ - struct hci_ev_user_passkey_req *ev = (void *) skb->data; - - BT_DBG("%s", hdev->name); - - hci_dev_lock(hdev); - - if (test_bit(HCI_MGMT, &hdev->flags)) - mgmt_user_passkey_request(hdev, &ev->bdaddr); - - hci_dev_unlock(hdev); -} - static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_simple_pair_complete *ev = (void *) skb->data; @@ -2963,15 +2868,14 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff } if (ev->status) { - mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, - conn->dst_type, ev->status); + mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, ev->status); hci_proto_connect_cfm(conn, ev->status); conn->state = BT_CLOSED; hci_conn_del(conn); goto unlock; } - mgmt_connected(hdev, &ev->bdaddr, conn->type, conn->dst_type); + mgmt_connected(hdev, &ev->bdaddr, conn->type); conn->sec_level = BT_SECURITY_LOW; conn->handle = __le16_to_cpu(ev->handle); @@ -3202,10 +3106,6 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_user_confirm_request_evt(hdev, skb); break; - case HCI_EV_USER_PASSKEY_REQUEST: - hci_user_passkey_request_evt(hdev, skb); - break; - case HCI_EV_SIMPLE_PAIR_COMPLETE: hci_simple_pair_complete_evt(hdev, skb); break; diff --git a/trunk/net/bluetooth/l2cap_core.c b/trunk/net/bluetooth/l2cap_core.c index 014fdec17113..e8a6837996cf 100644 --- a/trunk/net/bluetooth/l2cap_core.c +++ b/trunk/net/bluetooth/l2cap_core.c @@ -57,6 +57,7 @@ #include int disable_ertm; +int enable_hs; static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, }; @@ -96,6 +97,7 @@ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 return c; } return NULL; + } static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) @@ -152,9 +154,12 @@ static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) list_for_each_entry(c, &chan_list, global_l) { if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) - return c; + goto found; } - return NULL; + + c = NULL; +found: + return c; } int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) @@ -229,37 +234,8 @@ static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer) chan_put(chan); } -static char *state_to_string(int state) -{ - switch(state) { - case BT_CONNECTED: - return "BT_CONNECTED"; - case BT_OPEN: - return "BT_OPEN"; - case BT_BOUND: - return "BT_BOUND"; - case BT_LISTEN: - return "BT_LISTEN"; - case BT_CONNECT: - return "BT_CONNECT"; - case BT_CONNECT2: - return "BT_CONNECT2"; - case BT_CONFIG: - return "BT_CONFIG"; - case BT_DISCONN: - return "BT_DISCONN"; - case BT_CLOSED: - return "BT_CLOSED"; - } - - return "invalid state"; -} - static void l2cap_state_change(struct l2cap_chan *chan, int state) { - BT_DBG("%p %s -> %s", chan, state_to_string(chan->state), - state_to_string(state)); - chan->state = state; chan->ops->state_change(chan->data, state); } @@ -542,7 +518,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) } /* Service level security */ -int l2cap_chan_check_security(struct l2cap_chan *chan) +static inline int l2cap_check_security(struct l2cap_chan *chan) { struct l2cap_conn *conn = chan->conn; __u8 auth_type; @@ -688,7 +664,7 @@ static void l2cap_do_start(struct l2cap_chan *chan) if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) return; - if (l2cap_chan_check_security(chan) && + if (l2cap_check_security(chan) && __l2cap_no_conn_pending(chan)) { struct l2cap_conn_req req; req.scid = cpu_to_le16(chan->scid); @@ -778,7 +754,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) if (chan->state == BT_CONNECT) { struct l2cap_conn_req req; - if (!l2cap_chan_check_security(chan) || + if (!l2cap_check_security(chan) || !__l2cap_no_conn_pending(chan)) { bh_unlock_sock(sk); continue; @@ -811,7 +787,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) rsp.scid = cpu_to_le16(chan->dcid); rsp.dcid = cpu_to_le16(chan->scid); - if (l2cap_chan_check_security(chan)) { + if (l2cap_check_security(chan)) { if (bt_sk(sk)->defer_setup) { struct sock *parent = bt_sk(sk)->parent; rsp.result = cpu_to_le16(L2CAP_CR_PEND); @@ -1205,7 +1181,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan) if (hcon->state == BT_CONNECTED) { if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { __clear_chan_timer(chan); - if (l2cap_chan_check_security(chan)) + if (l2cap_check_security(chan)) l2cap_state_change(chan, BT_CONNECTED); } else l2cap_do_start(chan); @@ -1342,12 +1318,14 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u16 tx_seq) if (!skb) return; - while (bt_cb(skb)->tx_seq != tx_seq) { + do { + if (bt_cb(skb)->tx_seq == tx_seq) + break; + if (skb_queue_is_last(&chan->tx_q, skb)) return; - skb = skb_queue_next(&chan->tx_q, skb); - } + } while ((skb = skb_queue_next(&chan->tx_q, skb))); if (chan->remote_max_tx && bt_cb(skb)->retries == chan->remote_max_tx) { @@ -1928,7 +1906,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) { struct l2cap_conf_efs efs; - switch (chan->mode) { + switch(chan->mode) { case L2CAP_MODE_ERTM: efs.id = chan->local_id; efs.stype = chan->local_stype; @@ -2628,7 +2606,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd chan->ident = cmd->ident; if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { - if (l2cap_chan_check_security(chan)) { + if (l2cap_check_security(chan)) { if (bt_sk(sk)->defer_setup) { l2cap_state_change(chan, BT_CONNECT2); result = L2CAP_CR_PEND; @@ -3041,7 +3019,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd /* don't delete l2cap channel if sk is owned by user */ if (sock_owned_by_user(sk)) { - l2cap_state_change(chan, BT_DISCONN); + l2cap_state_change(chan,BT_DISCONN); __clear_chan_timer(chan); __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); bh_unlock_sock(sk); @@ -3584,10 +3562,14 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, bt_cb(skb)->sar = sar; next_skb = skb_peek(&chan->srej_q); + if (!next_skb) { + __skb_queue_tail(&chan->srej_q, skb); + return 0; + } tx_seq_offset = __seq_offset(chan, tx_seq, chan->buffer_seq); - while (next_skb) { + do { if (bt_cb(next_skb)->tx_seq == tx_seq) return -EINVAL; @@ -3600,10 +3582,9 @@ static int l2cap_add_to_srej_queue(struct l2cap_chan *chan, struct sk_buff *skb, } if (skb_queue_is_last(&chan->srej_q, next_skb)) - next_skb = NULL; - else - next_skb = skb_queue_next(&chan->srej_q, next_skb); - } + break; + + } while ((next_skb = skb_queue_next(&chan->srej_q, next_skb))); __skb_queue_tail(&chan->srej_q, skb); @@ -3807,7 +3788,7 @@ static void l2cap_resend_srejframe(struct l2cap_chan *chan, u16 tx_seq) } } -static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) +static void l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) { struct srej_list *new; u32 control; @@ -3818,9 +3799,6 @@ static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) l2cap_send_sframe(chan, control); new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC); - if (!new) - return -ENOMEM; - new->tx_seq = chan->expected_tx_seq; chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); @@ -3829,8 +3807,6 @@ static int l2cap_send_srejframe(struct l2cap_chan *chan, u16 tx_seq) } chan->expected_tx_seq = __next_seq(chan, chan->expected_tx_seq); - - return 0; } static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_control, struct sk_buff *skb) @@ -3901,12 +3877,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont return 0; } } - - err = l2cap_send_srejframe(chan, tx_seq); - if (err < 0) { - l2cap_send_disconn_req(chan->conn, chan, -err); - return err; - } + l2cap_send_srejframe(chan, tx_seq); } } else { expected_tx_seq_offset = __seq_offset(chan, @@ -3928,11 +3899,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont set_bit(CONN_SEND_PBIT, &chan->conn_state); - err = l2cap_send_srejframe(chan, tx_seq); - if (err < 0) { - l2cap_send_disconn_req(chan->conn, chan, -err); - return err; - } + l2cap_send_srejframe(chan, tx_seq); __clear_ack_timer(chan); } @@ -3961,12 +3928,11 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u32 rx_cont l2cap_retransmit_frames(chan); } + __set_ack_timer(chan); chan->num_acked = (chan->num_acked + 1) % num_to_ack; if (chan->num_acked == num_to_ack - 1) l2cap_send_ack(chan); - else - __set_ack_timer(chan); return 0; @@ -4802,3 +4768,6 @@ void l2cap_exit(void) module_param(disable_ertm, bool, 0644); MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode"); + +module_param(enable_hs, bool, 0644); +MODULE_PARM_DESC(enable_hs, "Enable High Speed"); diff --git a/trunk/net/bluetooth/l2cap_sock.c b/trunk/net/bluetooth/l2cap_sock.c index f73704321a77..e2e785c74630 100644 --- a/trunk/net/bluetooth/l2cap_sock.c +++ b/trunk/net/bluetooth/l2cap_sock.c @@ -626,13 +626,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch chan->sec_level = sec.level; - if (!chan->conn) - break; - conn = chan->conn; - - /*change security for LE channels */ - if (chan->scid == L2CAP_CID_LE_DATA) { + if (conn && chan->scid == L2CAP_CID_LE_DATA) { if (!conn->hcon->out) { err = -EINVAL; break; @@ -640,14 +635,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch if (smp_conn_security(conn, sec.level)) break; - sk->sk_state = BT_CONFIG; - /* or for ACL link, under defer_setup time */ - } else if (sk->sk_state == BT_CONNECT2 && - bt_sk(sk)->defer_setup) { - err = l2cap_chan_check_security(chan); - } else { - err = -EINVAL; + err = 0; + sk->sk_state = BT_CONFIG; } break; diff --git a/trunk/net/bluetooth/mgmt.c b/trunk/net/bluetooth/mgmt.c index 1ce549bae241..94739d3c4f59 100644 --- a/trunk/net/bluetooth/mgmt.c +++ b/trunk/net/bluetooth/mgmt.c @@ -22,7 +22,6 @@ /* Bluetooth HCI Management interface */ -#include #include #include #include @@ -45,79 +44,6 @@ struct pending_cmd { void *user_data; }; -/* HCI to MGMT error code conversion table */ -static u8 mgmt_status_table[] = { - MGMT_STATUS_SUCCESS, - MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */ - MGMT_STATUS_NOT_CONNECTED, /* No Connection */ - MGMT_STATUS_FAILED, /* Hardware Failure */ - MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */ - MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */ - MGMT_STATUS_NOT_PAIRED, /* PIN or Key Missing */ - MGMT_STATUS_NO_RESOURCES, /* Memory Full */ - MGMT_STATUS_TIMEOUT, /* Connection Timeout */ - MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */ - MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */ - MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */ - MGMT_STATUS_BUSY, /* Command Disallowed */ - MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */ - MGMT_STATUS_REJECTED, /* Rejected Security */ - MGMT_STATUS_REJECTED, /* Rejected Personal */ - MGMT_STATUS_TIMEOUT, /* Host Timeout */ - MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */ - MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */ - MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */ - MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */ - MGMT_STATUS_DISCONNECTED, /* OE Power Off */ - MGMT_STATUS_DISCONNECTED, /* Connection Terminated */ - MGMT_STATUS_BUSY, /* Repeated Attempts */ - MGMT_STATUS_REJECTED, /* Pairing Not Allowed */ - MGMT_STATUS_FAILED, /* Unknown LMP PDU */ - MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */ - MGMT_STATUS_REJECTED, /* SCO Offset Rejected */ - MGMT_STATUS_REJECTED, /* SCO Interval Rejected */ - MGMT_STATUS_REJECTED, /* Air Mode Rejected */ - MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */ - MGMT_STATUS_FAILED, /* Unspecified Error */ - MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */ - MGMT_STATUS_FAILED, /* Role Change Not Allowed */ - MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */ - MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */ - MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */ - MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */ - MGMT_STATUS_FAILED, /* Unit Link Key Used */ - MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */ - MGMT_STATUS_TIMEOUT, /* Instant Passed */ - MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */ - MGMT_STATUS_FAILED, /* Transaction Collision */ - MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */ - MGMT_STATUS_REJECTED, /* QoS Rejected */ - MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */ - MGMT_STATUS_REJECTED, /* Insufficient Security */ - MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */ - MGMT_STATUS_BUSY, /* Role Switch Pending */ - MGMT_STATUS_FAILED, /* Slot Violation */ - MGMT_STATUS_FAILED, /* Role Switch Failed */ - MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */ - MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */ - MGMT_STATUS_BUSY, /* Host Busy Pairing */ - MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */ - MGMT_STATUS_BUSY, /* Controller Busy */ - MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */ - MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */ - MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */ - MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */ - MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */ -}; - -static u8 mgmt_status(u8 hci_status) -{ - if (hci_status < ARRAY_SIZE(mgmt_status_table)) - return mgmt_status_table[hci_status]; - - return MGMT_STATUS_FAILED; -} - static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) { struct sk_buff *skb; @@ -252,8 +178,7 @@ static int read_controller_info(struct sock *sk, u16 index) hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_READ_INFO, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_READ_INFO, ENODEV); if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags)) cancel_delayed_work_sync(&hdev->power_off); @@ -366,15 +291,6 @@ static void mgmt_pending_remove(struct pending_cmd *cmd) mgmt_pending_free(cmd); } -static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val) -{ - struct mgmt_mode rp; - - rp.val = val; - - return cmd_complete(sk, index, opcode, &rp, sizeof(rp)); -} - static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) { struct mgmt_mode *cp; @@ -387,25 +303,22 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) BT_DBG("request for hci%u", index); if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_SET_POWERED, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_POWERED, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_POWERED, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV); hci_dev_lock_bh(hdev); up = test_bit(HCI_UP, &hdev->flags); if ((cp->val && up) || (!cp->val && !up)) { - err = send_mode_rsp(sk, index, MGMT_OP_SET_POWERED, cp->val); + err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EALREADY); goto failed; } if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) { - err = cmd_status(sk, index, MGMT_OP_SET_POWERED, - MGMT_STATUS_BUSY); + err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EBUSY); goto failed; } @@ -442,33 +355,28 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, BT_DBG("request for hci%u", index); if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV); hci_dev_lock_bh(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { - err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, - MGMT_STATUS_NOT_POWERED); + err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN); goto failed; } if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { - err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, - MGMT_STATUS_BUSY); + err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EBUSY); goto failed; } if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) && test_bit(HCI_PSCAN, &hdev->flags)) { - err = send_mode_rsp(sk, index, MGMT_OP_SET_DISCOVERABLE, - cp->val); + err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EALREADY); goto failed; } @@ -513,32 +421,27 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, BT_DBG("request for hci%u", index); if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV); hci_dev_lock_bh(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { - err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, - MGMT_STATUS_NOT_POWERED); + err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN); goto failed; } if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) || mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) { - err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, - MGMT_STATUS_BUSY); + err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EBUSY); goto failed; } if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { - err = send_mode_rsp(sk, index, MGMT_OP_SET_CONNECTABLE, - cp->val); + err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EALREADY); goto failed; } @@ -593,6 +496,15 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, return 0; } +static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val) +{ + struct mgmt_mode rp; + + rp.val = val; + + return cmd_complete(sk, index, opcode, &rp, sizeof(rp)); +} + static int set_pairable(struct sock *sk, u16 index, unsigned char *data, u16 len) { @@ -605,13 +517,11 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, BT_DBG("request for hci%u", index); if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV); hci_dev_lock_bh(hdev); @@ -820,13 +730,11 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) BT_DBG("request for hci%u", index); if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_ADD_UUID, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_ADD_UUID, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_ADD_UUID, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV); hci_dev_lock_bh(hdev); @@ -871,13 +779,11 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) BT_DBG("request for hci%u", index); if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV); hci_dev_lock_bh(hdev); @@ -899,8 +805,7 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) } if (found == 0) { - err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID, - MGMT_STATUS_INVALID_PARAMS); + err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENOENT); goto unlock; } @@ -933,13 +838,11 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data, BT_DBG("request for hci%u", index); if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV); hci_dev_lock_bh(hdev); @@ -967,13 +870,11 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, cp = (void *) data; if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV); hci_dev_lock_bh(hdev); @@ -1013,8 +914,7 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data, cp = (void *) data; if (len < sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, EINVAL); key_count = get_unaligned_le16(&cp->key_count); @@ -1023,14 +923,12 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data, if (expected_len != len) { BT_ERR("load_link_keys: expected %u bytes, got %u bytes", len, expected_len); - return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, EINVAL); } hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_LOAD_LINK_KEYS, ENODEV); BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys, key_count); @@ -1053,8 +951,6 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data, key->pin_len); } - cmd_complete(sk, index, MGMT_OP_LOAD_LINK_KEYS, NULL, 0); - hci_dev_unlock_bh(hdev); hci_dev_put(hdev); @@ -1066,64 +962,41 @@ static int remove_keys(struct sock *sk, u16 index, unsigned char *data, { struct hci_dev *hdev; struct mgmt_cp_remove_keys *cp; - struct mgmt_rp_remove_keys rp; - struct hci_cp_disconnect dc; - struct pending_cmd *cmd; struct hci_conn *conn; int err; cp = (void *) data; if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, ENODEV); hci_dev_lock_bh(hdev); - memset(&rp, 0, sizeof(rp)); - bacpy(&rp.bdaddr, &cp->bdaddr); - rp.status = MGMT_STATUS_FAILED; - err = hci_remove_link_key(hdev, &cp->bdaddr); if (err < 0) { - rp.status = MGMT_STATUS_NOT_PAIRED; + err = cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, -err); goto unlock; } - if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect) { - err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp, - sizeof(rp)); + err = 0; + + if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect) goto unlock; - } conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); - if (!conn) { - err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp, - sizeof(rp)); - goto unlock; - } + if (conn) { + struct hci_cp_disconnect dc; - cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_KEYS, hdev, cp, sizeof(*cp)); - if (!cmd) { - err = -ENOMEM; - goto unlock; + put_unaligned_le16(conn->handle, &dc.handle); + dc.reason = 0x13; /* Remote User Terminated Connection */ + err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc); } - put_unaligned_le16(conn->handle, &dc.handle); - dc.reason = 0x13; /* Remote User Terminated Connection */ - err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc); - if (err < 0) - mgmt_pending_remove(cmd); - unlock: - if (err < 0) - err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp, - sizeof(rp)); hci_dev_unlock_bh(hdev); hci_dev_put(hdev); @@ -1144,25 +1017,21 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) cp = (void *) data; if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_DISCONNECT, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_DISCONNECT, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_DISCONNECT, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV); hci_dev_lock_bh(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { - err = cmd_status(sk, index, MGMT_OP_DISCONNECT, - MGMT_STATUS_NOT_POWERED); + err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN); goto failed; } if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) { - err = cmd_status(sk, index, MGMT_OP_DISCONNECT, - MGMT_STATUS_BUSY); + err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY); goto failed; } @@ -1171,8 +1040,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr); if (!conn) { - err = cmd_status(sk, index, MGMT_OP_DISCONNECT, - MGMT_STATUS_NOT_CONNECTED); + err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENOTCONN); goto failed; } @@ -1196,18 +1064,11 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) return err; } -static u8 link_to_mgmt(u8 link_type, u8 addr_type) +static u8 link_to_mgmt(u8 link_type) { switch (link_type) { case LE_LINK: - switch (addr_type) { - case ADDR_LE_DEV_PUBLIC: - return MGMT_ADDR_LE_PUBLIC; - case ADDR_LE_DEV_RANDOM: - return MGMT_ADDR_LE_RANDOM; - default: - return MGMT_ADDR_INVALID; - } + return MGMT_ADDR_LE; case ACL_LINK: return MGMT_ADDR_BREDR; default: @@ -1229,8 +1090,7 @@ static int get_connections(struct sock *sk, u16 index) hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV); hci_dev_lock_bh(hdev); @@ -1251,7 +1111,7 @@ static int get_connections(struct sock *sk, u16 index) i = 0; list_for_each_entry(c, &hdev->conn_hash.list, list) { bacpy(&rp->addr[i].bdaddr, &c->dst); - rp->addr[i].type = link_to_mgmt(c->type, c->dst_type); + rp->addr[i].type = link_to_mgmt(c->type); if (rp->addr[i].type == MGMT_ADDR_INVALID) continue; i++; @@ -1304,26 +1164,22 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, cp = (void *) data; if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV); hci_dev_lock_bh(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { - err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, - MGMT_STATUS_NOT_POWERED); + err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN); goto failed; } conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); if (!conn) { - err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, - MGMT_STATUS_NOT_CONNECTED); + err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENOTCONN); goto failed; } @@ -1335,7 +1191,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, err = send_pin_code_neg_reply(sk, index, hdev, &ncp); if (err >= 0) err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, - MGMT_STATUS_INVALID_PARAMS); + EINVAL); goto failed; } @@ -1374,18 +1230,18 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data, if (len != sizeof(*cp)) return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, - MGMT_STATUS_INVALID_PARAMS); + EINVAL); hdev = hci_dev_get(index); if (!hdev) return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, - MGMT_STATUS_INVALID_PARAMS); + ENODEV); hci_dev_lock_bh(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, - MGMT_STATUS_NOT_POWERED); + ENETDOWN); goto failed; } @@ -1409,13 +1265,11 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data, cp = (void *) data; if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV); hci_dev_lock_bh(hdev); @@ -1453,8 +1307,7 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status) struct mgmt_rp_pair_device rp; struct hci_conn *conn = cmd->user_data; - bacpy(&rp.addr.bdaddr, &conn->dst); - rp.addr.type = link_to_mgmt(conn->type, conn->dst_type); + bacpy(&rp.bdaddr, &conn->dst); rp.status = status; cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp)); @@ -1472,22 +1325,27 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status) static void pairing_complete_cb(struct hci_conn *conn, u8 status) { struct pending_cmd *cmd; + struct hci_dev *hdev = conn->hdev; BT_DBG("status %u", status); + hci_dev_lock_bh(hdev); + cmd = find_pairing(conn); if (!cmd) BT_DBG("Unable to find a pending command"); else pairing_complete(cmd, status); + + hci_dev_unlock_bh(hdev); } static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) { struct hci_dev *hdev; struct mgmt_cp_pair_device *cp; - struct mgmt_rp_pair_device rp; struct pending_cmd *cmd; + struct adv_entry *entry; u8 sec_level, auth_type; struct hci_conn *conn; int err; @@ -1497,13 +1355,11 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) cp = (void *) data; if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV); hci_dev_lock_bh(hdev); @@ -1513,29 +1369,22 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) else auth_type = HCI_AT_DEDICATED_BONDING_MITM; - if (cp->addr.type == MGMT_ADDR_BREDR) - conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr, sec_level, + entry = hci_find_adv_entry(hdev, &cp->bdaddr); + if (entry) + conn = hci_connect(hdev, LE_LINK, &cp->bdaddr, sec_level, auth_type); else - conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, sec_level, + conn = hci_connect(hdev, ACL_LINK, &cp->bdaddr, sec_level, auth_type); - memset(&rp, 0, sizeof(rp)); - bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); - rp.addr.type = cp->addr.type; - if (IS_ERR(conn)) { - rp.status = -PTR_ERR(conn); - err = cmd_complete(sk, index, MGMT_OP_PAIR_DEVICE, - &rp, sizeof(rp)); + err = PTR_ERR(conn); goto unlock; } if (conn->connect_cfm_cb) { hci_conn_put(conn); - rp.status = EBUSY; - err = cmd_complete(sk, index, MGMT_OP_PAIR_DEVICE, - &rp, sizeof(rp)); + err = cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EBUSY); goto unlock; } @@ -1547,7 +1396,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) } /* For LE, just connecting isn't a proof that the pairing finished */ - if (cp->addr.type == MGMT_ADDR_BREDR) + if (!entry) conn->connect_cfm_cb = pairing_complete_cb; conn->security_cfm_cb = pairing_complete_cb; @@ -1568,138 +1417,56 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) return err; } -static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr, - u16 mgmt_op, u16 hci_op, __le32 passkey) +static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, + u16 len, int success) { + struct mgmt_cp_user_confirm_reply *cp = (void *) data; + u16 mgmt_op, hci_op; struct pending_cmd *cmd; struct hci_dev *hdev; - struct hci_conn *conn; int err; + BT_DBG(""); + + if (success) { + mgmt_op = MGMT_OP_USER_CONFIRM_REPLY; + hci_op = HCI_OP_USER_CONFIRM_REPLY; + } else { + mgmt_op = MGMT_OP_USER_CONFIRM_NEG_REPLY; + hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY; + } + + if (len != sizeof(*cp)) + return cmd_status(sk, index, mgmt_op, EINVAL); + hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, mgmt_op, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, mgmt_op, ENODEV); hci_dev_lock_bh(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { - err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_NOT_POWERED); - goto done; - } - - /* - * Check for an existing ACL link, if present pair via - * HCI commands. - * - * If no ACL link is present, check for an LE link and if - * present, pair via the SMP engine. - * - * If neither ACL nor LE links are present, fail with error. - */ - conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr); - if (!conn) { - conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr); - if (!conn) { - err = cmd_status(sk, index, mgmt_op, - MGMT_STATUS_NOT_CONNECTED); - goto done; - } - - /* Continue with pairing via SMP */ - - err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_SUCCESS); - goto done; + err = cmd_status(sk, index, mgmt_op, ENETDOWN); + goto failed; } - cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr)); + cmd = mgmt_pending_add(sk, mgmt_op, hdev, data, len); if (!cmd) { err = -ENOMEM; - goto done; + goto failed; } - /* Continue with pairing via HCI */ - if (hci_op == HCI_OP_USER_PASSKEY_REPLY) { - struct hci_cp_user_passkey_reply cp; - - bacpy(&cp.bdaddr, bdaddr); - cp.passkey = passkey; - err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp); - } else - err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr); - + err = hci_send_cmd(hdev, hci_op, sizeof(cp->bdaddr), &cp->bdaddr); if (err < 0) mgmt_pending_remove(cmd); -done: +failed: hci_dev_unlock_bh(hdev); hci_dev_put(hdev); return err; } -static int user_confirm_reply(struct sock *sk, u16 index, void *data, u16 len) -{ - struct mgmt_cp_user_confirm_reply *cp = (void *) data; - - BT_DBG(""); - - if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_REPLY, - MGMT_STATUS_INVALID_PARAMS); - - return user_pairing_resp(sk, index, &cp->bdaddr, - MGMT_OP_USER_CONFIRM_REPLY, - HCI_OP_USER_CONFIRM_REPLY, 0); -} - -static int user_confirm_neg_reply(struct sock *sk, u16 index, void *data, - u16 len) -{ - struct mgmt_cp_user_confirm_reply *cp = (void *) data; - - BT_DBG(""); - - if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_NEG_REPLY, - MGMT_STATUS_INVALID_PARAMS); - - return user_pairing_resp(sk, index, &cp->bdaddr, - MGMT_OP_USER_CONFIRM_NEG_REPLY, - HCI_OP_USER_CONFIRM_NEG_REPLY, 0); -} - -static int user_passkey_reply(struct sock *sk, u16 index, void *data, u16 len) -{ - struct mgmt_cp_user_passkey_reply *cp = (void *) data; - - BT_DBG(""); - - if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY, - EINVAL); - - return user_pairing_resp(sk, index, &cp->bdaddr, - MGMT_OP_USER_PASSKEY_REPLY, - HCI_OP_USER_PASSKEY_REPLY, cp->passkey); -} - -static int user_passkey_neg_reply(struct sock *sk, u16 index, void *data, - u16 len) -{ - struct mgmt_cp_user_passkey_neg_reply *cp = (void *) data; - - BT_DBG(""); - - if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_NEG_REPLY, - EINVAL); - - return user_pairing_resp(sk, index, &cp->bdaddr, - MGMT_OP_USER_PASSKEY_NEG_REPLY, - HCI_OP_USER_PASSKEY_NEG_REPLY, 0); -} - static int set_local_name(struct sock *sk, u16 index, unsigned char *data, u16 len) { @@ -1712,13 +1479,11 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data, BT_DBG(""); if (len != sizeof(*mgmt_cp)) - return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, EINVAL); hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, ENODEV); hci_dev_lock_bh(hdev); @@ -1752,25 +1517,24 @@ static int read_local_oob_data(struct sock *sk, u16 index) hdev = hci_dev_get(index); if (!hdev) return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, - MGMT_STATUS_INVALID_PARAMS); + ENODEV); hci_dev_lock_bh(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, - MGMT_STATUS_NOT_POWERED); + ENETDOWN); goto unlock; } if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, - MGMT_STATUS_NOT_SUPPORTED); + EOPNOTSUPP); goto unlock; } if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) { - err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, - MGMT_STATUS_BUSY); + err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, EBUSY); goto unlock; } @@ -1802,20 +1566,19 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data, if (len != sizeof(*cp)) return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, - MGMT_STATUS_INVALID_PARAMS); + EINVAL); hdev = hci_dev_get(index); if (!hdev) return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, - MGMT_STATUS_INVALID_PARAMS); + ENODEV); hci_dev_lock_bh(hdev); err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash, cp->randomizer); if (err < 0) - err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, - MGMT_STATUS_FAILED); + err = cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, -err); else err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL, 0); @@ -1837,19 +1600,19 @@ static int remove_remote_oob_data(struct sock *sk, u16 index, if (len != sizeof(*cp)) return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, - MGMT_STATUS_INVALID_PARAMS); + EINVAL); hdev = hci_dev_get(index); if (!hdev) return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, - MGMT_STATUS_INVALID_PARAMS); + ENODEV); hci_dev_lock_bh(hdev); err = hci_remove_remote_oob_data(hdev, &cp->bdaddr); if (err < 0) err = cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, - MGMT_STATUS_INVALID_PARAMS); + -err); else err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, NULL, 0); @@ -1860,30 +1623,22 @@ static int remove_remote_oob_data(struct sock *sk, u16 index, return err; } -static int start_discovery(struct sock *sk, u16 index, - unsigned char *data, u16 len) +static int start_discovery(struct sock *sk, u16 index) { - struct mgmt_cp_start_discovery *cp = (void *) data; struct pending_cmd *cmd; struct hci_dev *hdev; int err; BT_DBG("hci%u", index); - if (len != sizeof(*cp)) - return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, - MGMT_STATUS_INVALID_PARAMS); - hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENODEV); hci_dev_lock_bh(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { - err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY, - MGMT_STATUS_NOT_POWERED); + err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY, ENETDOWN); goto failed; } @@ -1914,8 +1669,7 @@ static int stop_discovery(struct sock *sk, u16 index) hdev = hci_dev_get(index); if (!hdev) - return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, - MGMT_STATUS_INVALID_PARAMS); + return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, ENODEV); hci_dev_lock_bh(hdev); @@ -1947,19 +1701,18 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data, if (len != sizeof(*cp)) return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, - MGMT_STATUS_INVALID_PARAMS); + EINVAL); hdev = hci_dev_get(index); if (!hdev) return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, - MGMT_STATUS_INVALID_PARAMS); + ENODEV); hci_dev_lock_bh(hdev); err = hci_blacklist_add(hdev, &cp->bdaddr); if (err < 0) - err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, - MGMT_STATUS_FAILED); + err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, -err); else err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE, NULL, 0); @@ -1981,20 +1734,19 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data, if (len != sizeof(*cp)) return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, - MGMT_STATUS_INVALID_PARAMS); + EINVAL); hdev = hci_dev_get(index); if (!hdev) return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, - MGMT_STATUS_INVALID_PARAMS); + ENODEV); hci_dev_lock_bh(hdev); err = hci_blacklist_del(hdev, &cp->bdaddr); if (err < 0) - err = cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, - MGMT_STATUS_INVALID_PARAMS); + err = cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, -err); else err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE, NULL, 0); @@ -2018,12 +1770,12 @@ static int set_fast_connectable(struct sock *sk, u16 index, if (len != sizeof(*cp)) return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, - MGMT_STATUS_INVALID_PARAMS); + EINVAL); hdev = hci_dev_get(index); if (!hdev) return cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, - MGMT_STATUS_INVALID_PARAMS); + ENODEV); hci_dev_lock(hdev); @@ -2041,14 +1793,14 @@ static int set_fast_connectable(struct sock *sk, u16 index, sizeof(acp), &acp); if (err < 0) { err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, - MGMT_STATUS_FAILED); + -err); goto done; } err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); if (err < 0) { err = cmd_status(sk, index, MGMT_OP_SET_FAST_CONNECTABLE, - MGMT_STATUS_FAILED); + -err); goto done; } @@ -2151,18 +1903,10 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) err = pair_device(sk, index, buf + sizeof(*hdr), len); break; case MGMT_OP_USER_CONFIRM_REPLY: - err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len); + err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 1); break; case MGMT_OP_USER_CONFIRM_NEG_REPLY: - err = user_confirm_neg_reply(sk, index, buf + sizeof(*hdr), - len); - break; - case MGMT_OP_USER_PASSKEY_REPLY: - err = user_passkey_reply(sk, index, buf + sizeof(*hdr), len); - break; - case MGMT_OP_USER_PASSKEY_NEG_REPLY: - err = user_passkey_neg_reply(sk, index, buf + sizeof(*hdr), - len); + err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0); break; case MGMT_OP_SET_LOCAL_NAME: err = set_local_name(sk, index, buf + sizeof(*hdr), len); @@ -2178,7 +1922,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) len); break; case MGMT_OP_START_DISCOVERY: - err = start_discovery(sk, index, buf + sizeof(*hdr), len); + err = start_discovery(sk, index); break; case MGMT_OP_STOP_DISCOVERY: err = stop_discovery(sk, index); @@ -2195,8 +1939,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) break; default: BT_DBG("Unknown op %u", opcode); - err = cmd_status(sk, index, opcode, - MGMT_STATUS_UNKNOWN_COMMAND); + err = cmd_status(sk, index, opcode, 0x01); break; } @@ -2319,15 +2062,13 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable) int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) { - u8 mgmt_err = mgmt_status(status); - if (scan & SCAN_PAGE) mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, - cmd_status_rsp, &mgmt_err); + cmd_status_rsp, &status); if (scan & SCAN_INQUIRY) mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, - cmd_status_rsp, &mgmt_err); + cmd_status_rsp, &status); return 0; } @@ -2348,13 +2089,12 @@ int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); } -int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, - u8 addr_type) +int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type) { struct mgmt_addr_info ev; bacpy(&ev.bdaddr, bdaddr); - ev.type = link_to_mgmt(link_type, addr_type); + ev.type = link_to_mgmt(link_type); return mgmt_event(MGMT_EV_CONNECTED, hdev, &ev, sizeof(ev), NULL); } @@ -2366,7 +2106,6 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data) struct mgmt_rp_disconnect rp; bacpy(&rp.bdaddr, &cp->bdaddr); - rp.status = 0; cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp)); @@ -2376,25 +2115,7 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data) mgmt_pending_remove(cmd); } -static void remove_keys_rsp(struct pending_cmd *cmd, void *data) -{ - u8 *status = data; - struct mgmt_cp_remove_keys *cp = cmd->param; - struct mgmt_rp_remove_keys rp; - - memset(&rp, 0, sizeof(rp)); - bacpy(&rp.bdaddr, &cp->bdaddr); - if (status != NULL) - rp.status = *status; - - cmd_complete(cmd->sk, cmd->index, MGMT_OP_REMOVE_KEYS, &rp, - sizeof(rp)); - - mgmt_pending_remove(cmd); -} - -int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, - u8 addr_type) +int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) { struct mgmt_addr_info ev; struct sock *sk = NULL; @@ -2403,53 +2124,40 @@ int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); bacpy(&ev.bdaddr, bdaddr); - ev.type = link_to_mgmt(link_type, addr_type); + ev.type = link_to_mgmt(type); err = mgmt_event(MGMT_EV_DISCONNECTED, hdev, &ev, sizeof(ev), sk); if (sk) sock_put(sk); - mgmt_pending_foreach(MGMT_OP_REMOVE_KEYS, hdev, remove_keys_rsp, NULL); - return err; } -int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status) +int mgmt_disconnect_failed(struct hci_dev *hdev) { struct pending_cmd *cmd; - u8 mgmt_err = mgmt_status(status); int err; cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev); if (!cmd) return -ENOENT; - if (bdaddr) { - struct mgmt_rp_disconnect rp; - - bacpy(&rp.bdaddr, bdaddr); - rp.status = status; - - err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, - &rp, sizeof(rp)); - } else - err = cmd_status(cmd->sk, hdev->id, MGMT_OP_DISCONNECT, - mgmt_err); + err = cmd_status(cmd->sk, hdev->id, MGMT_OP_DISCONNECT, EIO); mgmt_pending_remove(cmd); return err; } -int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, - u8 addr_type, u8 status) +int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, + u8 status) { struct mgmt_ev_connect_failed ev; bacpy(&ev.addr.bdaddr, bdaddr); - ev.addr.type = link_to_mgmt(link_type, addr_type); - ev.status = mgmt_status(status); + ev.addr.type = link_to_mgmt(type); + ev.status = status; return mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL); } @@ -2477,7 +2185,7 @@ int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, return -ENOENT; bacpy(&rp.bdaddr, bdaddr); - rp.status = mgmt_status(status); + rp.status = status; err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, &rp, sizeof(rp)); @@ -2499,7 +2207,7 @@ int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, return -ENOENT; bacpy(&rp.bdaddr, bdaddr); - rp.status = mgmt_status(status); + rp.status = status; err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY, &rp, sizeof(rp)); @@ -2524,19 +2232,7 @@ int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, NULL); } -int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr) -{ - struct mgmt_ev_user_passkey_request ev; - - BT_DBG("%s", hdev->name); - - bacpy(&ev.bdaddr, bdaddr); - - return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev), - NULL); -} - -static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, +static int confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status, u8 opcode) { struct pending_cmd *cmd; @@ -2548,7 +2244,7 @@ static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, return -ENOENT; bacpy(&rp.bdaddr, bdaddr); - rp.status = mgmt_status(status); + rp.status = status; err = cmd_complete(cmd->sk, hdev->id, opcode, &rp, sizeof(rp)); mgmt_pending_remove(cmd); @@ -2559,37 +2255,23 @@ static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status) { - return user_pairing_resp_complete(hdev, bdaddr, status, + return confirm_reply_complete(hdev, bdaddr, status, MGMT_OP_USER_CONFIRM_REPLY); } int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status) { - return user_pairing_resp_complete(hdev, bdaddr, status, + return confirm_reply_complete(hdev, bdaddr, status, MGMT_OP_USER_CONFIRM_NEG_REPLY); } -int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 status) -{ - return user_pairing_resp_complete(hdev, bdaddr, status, - MGMT_OP_USER_PASSKEY_REPLY); -} - -int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, - bdaddr_t *bdaddr, u8 status) -{ - return user_pairing_resp_complete(hdev, bdaddr, status, - MGMT_OP_USER_PASSKEY_NEG_REPLY); -} - int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status) { struct mgmt_ev_auth_failed ev; bacpy(&ev.bdaddr, bdaddr); - ev.status = mgmt_status(status); + ev.status = status; return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL); } @@ -2609,7 +2291,7 @@ int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) if (status) { err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, - mgmt_status(status)); + EIO); goto failed; } @@ -2644,8 +2326,7 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, if (status) { err = cmd_status(cmd->sk, hdev->id, - MGMT_OP_READ_LOCAL_OOB_DATA, - mgmt_status(status)); + MGMT_OP_READ_LOCAL_OOB_DATA, EIO); } else { struct mgmt_rp_read_local_oob_data rp; @@ -2662,15 +2343,15 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, return err; } -int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, - u8 addr_type, u8 *dev_class, s8 rssi, u8 *eir) +int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, + u8 *dev_class, s8 rssi, u8 *eir) { struct mgmt_ev_device_found ev; memset(&ev, 0, sizeof(ev)); bacpy(&ev.addr.bdaddr, bdaddr); - ev.addr.type = link_to_mgmt(link_type, addr_type); + ev.addr.type = link_to_mgmt(type); ev.rssi = rssi; if (eir) @@ -2694,7 +2375,7 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name) return mgmt_event(MGMT_EV_REMOTE_NAME, hdev, &ev, sizeof(ev), NULL); } -int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status) +int mgmt_inquiry_failed(struct hci_dev *hdev, u8 status) { struct pending_cmd *cmd; int err; @@ -2703,21 +2384,6 @@ int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status) if (!cmd) return -ENOENT; - err = cmd_status(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status)); - mgmt_pending_remove(cmd); - - return err; -} - -int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status) -{ - struct pending_cmd *cmd; - int err; - - cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev); - if (!cmd) - return -ENOENT; - err = cmd_status(cmd->sk, hdev->id, cmd->opcode, status); mgmt_pending_remove(cmd); diff --git a/trunk/net/bluetooth/smp.c b/trunk/net/bluetooth/smp.c index 0b96737d0ad3..94e94ca35384 100644 --- a/trunk/net/bluetooth/smp.c +++ b/trunk/net/bluetooth/smp.c @@ -232,18 +232,6 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) return 0; } -static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) -{ - if (send) - smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), - &reason); - - clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->pend); - mgmt_auth_failed(conn->hcon->hdev, conn->dst, reason); - del_timer(&conn->security_timer); - smp_chan_destroy(conn); -} - static void confirm_work(struct work_struct *work) { struct smp_chan *smp = container_of(work, struct smp_chan, confirm); @@ -282,7 +270,8 @@ static void confirm_work(struct work_struct *work) return; error: - smp_failure(conn, reason, 1); + smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); + smp_chan_destroy(conn); } static void random_work(struct work_struct *work) @@ -365,7 +354,8 @@ static void random_work(struct work_struct *work) return; error: - smp_failure(conn, reason, 1); + smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); + smp_chan_destroy(conn); } static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) @@ -389,15 +379,7 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) void smp_chan_destroy(struct l2cap_conn *conn) { - struct smp_chan *smp = conn->smp_chan; - - clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->pend); - - if (smp->tfm) - crypto_free_blkcipher(smp->tfm); - - kfree(smp); - conn->smp_chan = NULL; + kfree(conn->smp_chan); hci_conn_put(conn->hcon); } @@ -665,7 +647,6 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) break; case SMP_CMD_PAIRING_FAIL: - smp_failure(conn, skb->data[0], 0); reason = 0; err = -EPERM; break; @@ -711,7 +692,8 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) done: if (reason) - smp_failure(conn, reason, 1); + smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), + &reason); kfree_skb(skb); return err; diff --git a/trunk/net/bridge/br_device.c b/trunk/net/bridge/br_device.c index 71773b014e0c..a3754ac262c3 100644 --- a/trunk/net/bridge/br_device.c +++ b/trunk/net/bridge/br_device.c @@ -170,11 +170,8 @@ static int br_set_mac_address(struct net_device *dev, void *p) return -EINVAL; spin_lock_bh(&br->lock); - if (compare_ether_addr(dev->dev_addr, addr->sa_data)) { - memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - br_fdb_change_mac_address(br, addr->sa_data); - br_stp_change_bridge_id(br, addr->sa_data); - } + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + br_stp_change_bridge_id(br, addr->sa_data); br->flags |= BR_SET_MAC_ADDR; spin_unlock_bh(&br->lock); diff --git a/trunk/net/bridge/br_fdb.c b/trunk/net/bridge/br_fdb.c index a1429afca443..973813e34428 100644 --- a/trunk/net/bridge/br_fdb.c +++ b/trunk/net/bridge/br_fdb.c @@ -28,8 +28,7 @@ static struct kmem_cache *br_fdb_cache __read_mostly; static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr); -static void fdb_notify(struct net_bridge *br, - const struct net_bridge_fdb_entry *, int); +static void fdb_notify(const struct net_bridge_fdb_entry *, int); static u32 fdb_salt __read_mostly; @@ -81,10 +80,10 @@ static void fdb_rcu_free(struct rcu_head *head) kmem_cache_free(br_fdb_cache, ent); } -static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f) +static inline void fdb_delete(struct net_bridge_fdb_entry *f) { + fdb_notify(f, RTM_DELNEIGH); hlist_del_rcu(&f->hlist); - fdb_notify(br, f, RTM_DELNEIGH); call_rcu(&f->rcu, fdb_rcu_free); } @@ -115,7 +114,7 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) } /* delete old one */ - fdb_delete(br, f); + fdb_delete(f); goto insert; } } @@ -127,18 +126,6 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) spin_unlock_bh(&br->hash_lock); } -void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr) -{ - struct net_bridge_fdb_entry *f; - - /* If old entry was unassociated with any port, then delete it. */ - f = __br_fdb_get(br, br->dev->dev_addr); - if (f && f->is_local && !f->dst) - fdb_delete(br, f); - - fdb_insert(br, NULL, newaddr); -} - void br_fdb_cleanup(unsigned long _data) { struct net_bridge *br = (struct net_bridge *)_data; @@ -157,7 +144,7 @@ void br_fdb_cleanup(unsigned long _data) continue; this_timer = f->updated + delay; if (time_before_eq(this_timer, jiffies)) - fdb_delete(br, f); + fdb_delete(f); else if (time_before(this_timer, next_timer)) next_timer = this_timer; } @@ -178,7 +165,7 @@ void br_fdb_flush(struct net_bridge *br) struct hlist_node *h, *n; hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) { if (!f->is_static) - fdb_delete(br, f); + fdb_delete(f); } } spin_unlock_bh(&br->hash_lock); @@ -222,7 +209,7 @@ void br_fdb_delete_by_port(struct net_bridge *br, } } - fdb_delete(br, f); + fdb_delete(f); skip_delete: ; } } @@ -262,7 +249,7 @@ int br_fdb_test_addr(struct net_device *dev, unsigned char *addr) ret = 0; else { fdb = __br_fdb_get(port->br, addr); - ret = fdb && fdb->dst && fdb->dst->dev != dev && + ret = fdb && fdb->dst->dev != dev && fdb->dst->state == BR_STATE_FORWARDING; } rcu_read_unlock(); @@ -294,10 +281,6 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, if (has_expired(br, f)) continue; - /* ignore pseudo entry for local MAC address */ - if (!f->dst) - continue; - if (skip) { --skip; continue; @@ -364,6 +347,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, fdb->is_static = 0; fdb->updated = fdb->used = jiffies; hlist_add_head_rcu(&fdb->hlist, head); + fdb_notify(fdb, RTM_NEWNEIGH); } return fdb; } @@ -387,7 +371,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, br_warn(br, "adding interface %s with same address " "as a received packet\n", source->dev->name); - fdb_delete(br, fdb); + fdb_delete(fdb); } fdb = fdb_create(head, source, addr); @@ -395,7 +379,6 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, return -ENOMEM; fdb->is_local = fdb->is_static = 1; - fdb_notify(br, fdb, RTM_NEWNEIGH); return 0; } @@ -441,11 +424,9 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, } } else { spin_lock(&br->hash_lock); - if (likely(!fdb_find(head, addr))) { - fdb = fdb_create(head, source, addr); - if (fdb) - fdb_notify(br, fdb, RTM_NEWNEIGH); - } + if (likely(!fdb_find(head, addr))) + fdb_create(head, source, addr); + /* else we lose race and someone else inserts * it first, don't bother updating */ @@ -465,7 +446,7 @@ static int fdb_to_nud(const struct net_bridge_fdb_entry *fdb) return NUD_REACHABLE; } -static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br, +static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge_fdb_entry *fdb, u32 pid, u32 seq, int type, unsigned int flags) { @@ -478,13 +459,14 @@ static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br, if (nlh == NULL) return -EMSGSIZE; + ndm = nlmsg_data(nlh); ndm->ndm_family = AF_BRIDGE; ndm->ndm_pad1 = 0; ndm->ndm_pad2 = 0; ndm->ndm_flags = 0; ndm->ndm_type = 0; - ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex; + ndm->ndm_ifindex = fdb->dst->dev->ifindex; ndm->ndm_state = fdb_to_nud(fdb); NLA_PUT(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr); @@ -509,10 +491,9 @@ static inline size_t fdb_nlmsg_size(void) + nla_total_size(sizeof(struct nda_cacheinfo)); } -static void fdb_notify(struct net_bridge *br, - const struct net_bridge_fdb_entry *fdb, int type) +static void fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) { - struct net *net = dev_net(br->dev); + struct net *net = dev_net(fdb->dst->dev); struct sk_buff *skb; int err = -ENOBUFS; @@ -520,7 +501,7 @@ static void fdb_notify(struct net_bridge *br, if (skb == NULL) goto errout; - err = fdb_fill_info(skb, br, fdb, 0, 0, type, 0); + err = fdb_fill_info(skb, fdb, 0, 0, type, 0); if (err < 0) { /* -EMSGSIZE implies BUG in fdb_nlmsg_size() */ WARN_ON(err == -EMSGSIZE); @@ -557,7 +538,7 @@ int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) if (idx < cb->args[0]) goto skip; - if (fdb_fill_info(skb, br, f, + if (fdb_fill_info(skb, f, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWNEIGH, @@ -591,7 +572,6 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, fdb = fdb_create(head, source, addr); if (!fdb) return -ENOMEM; - fdb_notify(br, fdb, RTM_NEWNEIGH); } else { if (flags & NLM_F_EXCL) return -EEXIST; @@ -607,7 +587,7 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, fdb->is_local = fdb->is_static = 0; fdb->updated = fdb->used = jiffies; - fdb_notify(br, fdb, RTM_NEWNEIGH); + fdb_notify(fdb, RTM_NEWNEIGH); } return 0; @@ -687,7 +667,7 @@ static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr) if (!fdb) return -ENOENT; - fdb_delete(p->br, fdb); + fdb_delete(fdb); return 0; } diff --git a/trunk/net/bridge/br_forward.c b/trunk/net/bridge/br_forward.c index 61f65344e711..ee64287f1290 100644 --- a/trunk/net/bridge/br_forward.c +++ b/trunk/net/bridge/br_forward.c @@ -98,7 +98,7 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) /* called with rcu_read_lock */ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) { - if (to && should_deliver(to, skb)) { + if (should_deliver(to, skb)) { __br_deliver(to, skb); return; } diff --git a/trunk/net/bridge/br_multicast.c b/trunk/net/bridge/br_multicast.c index 568d5bf17534..375417e633c9 100644 --- a/trunk/net/bridge/br_multicast.c +++ b/trunk/net/bridge/br_multicast.c @@ -24,7 +24,7 @@ #include #include #include -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #include #include #include @@ -36,7 +36,7 @@ #define mlock_dereference(X, br) \ rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock)) -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static inline int ipv6_is_transient_multicast(const struct in6_addr *addr) { if (ipv6_addr_is_multicast(addr) && IPV6_ADDR_MC_FLAG_TRANSIENT(addr)) @@ -52,7 +52,7 @@ static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b) switch (a->proto) { case htons(ETH_P_IP): return a->u.ip4 == b->u.ip4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case htons(ETH_P_IPV6): return ipv6_addr_equal(&a->u.ip6, &b->u.ip6); #endif @@ -65,7 +65,7 @@ static inline int __br_ip4_hash(struct net_bridge_mdb_htable *mdb, __be32 ip) return jhash_1word(mdb->secret, (__force u32)ip) & (mdb->max - 1); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static inline int __br_ip6_hash(struct net_bridge_mdb_htable *mdb, const struct in6_addr *ip) { @@ -79,7 +79,7 @@ static inline int br_ip_hash(struct net_bridge_mdb_htable *mdb, switch (ip->proto) { case htons(ETH_P_IP): return __br_ip4_hash(mdb, ip->u.ip4); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case htons(ETH_P_IPV6): return __br_ip6_hash(mdb, &ip->u.ip6); #endif @@ -121,7 +121,7 @@ static struct net_bridge_mdb_entry *br_mdb_ip4_get( return br_mdb_ip_get(mdb, &br_dst); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static struct net_bridge_mdb_entry *br_mdb_ip6_get( struct net_bridge_mdb_htable *mdb, const struct in6_addr *dst) { @@ -152,7 +152,7 @@ struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, case htons(ETH_P_IP): ip.u.ip4 = ip_hdr(skb)->daddr; break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case htons(ETH_P_IPV6): ip.u.ip6 = ipv6_hdr(skb)->daddr; break; @@ -411,7 +411,7 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br, return skb; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, const struct in6_addr *group) { @@ -496,7 +496,7 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, switch (addr->proto) { case htons(ETH_P_IP): return br_ip4_multicast_alloc_query(br, addr->u.ip4); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case htons(ETH_P_IPV6): return br_ip6_multicast_alloc_query(br, &addr->u.ip6); #endif @@ -773,7 +773,7 @@ static int br_ip4_multicast_add_group(struct net_bridge *br, return br_multicast_add_group(br, port, &br_group); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static int br_ip6_multicast_add_group(struct net_bridge *br, struct net_bridge_port *port, const struct in6_addr *group) @@ -845,7 +845,7 @@ static void br_multicast_send_query(struct net_bridge *br, br_group.proto = htons(ETH_P_IP); __br_multicast_send_query(br, port, &br_group); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) br_group.proto = htons(ETH_P_IPV6); __br_multicast_send_query(br, port, &br_group); #endif @@ -989,7 +989,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, return err; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static int br_ip6_multicast_mld2_report(struct net_bridge *br, struct net_bridge_port *port, struct sk_buff *skb) @@ -1185,7 +1185,7 @@ static int br_ip4_multicast_query(struct net_bridge *br, return err; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static int br_ip6_multicast_query(struct net_bridge *br, struct net_bridge_port *port, struct sk_buff *skb) @@ -1334,7 +1334,7 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br, br_multicast_leave_group(br, port, &br_group); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static void br_ip6_multicast_leave_group(struct net_bridge *br, struct net_bridge_port *port, const struct in6_addr *group) @@ -1449,7 +1449,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, return err; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static int br_multicast_ipv6_rcv(struct net_bridge *br, struct net_bridge_port *port, struct sk_buff *skb) @@ -1596,7 +1596,7 @@ int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, switch (skb->protocol) { case htons(ETH_P_IP): return br_multicast_ipv4_rcv(br, port, skb); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case htons(ETH_P_IPV6): return br_multicast_ipv6_rcv(br, port, skb); #endif diff --git a/trunk/net/bridge/br_private.h b/trunk/net/bridge/br_private.h index 57dcd1489f3f..4027029aa5e4 100644 --- a/trunk/net/bridge/br_private.h +++ b/trunk/net/bridge/br_private.h @@ -56,7 +56,7 @@ struct br_ip { union { __be32 ip4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct in6_addr ip6; #endif } u; @@ -348,7 +348,6 @@ extern void br_fdb_fini(void); extern void br_fdb_flush(struct net_bridge *br); extern void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr); -extern void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr); extern void br_fdb_cleanup(unsigned long arg); extern void br_fdb_delete_by_port(struct net_bridge *br, const struct net_bridge_port *p, int do_all); diff --git a/trunk/net/caif/caif_dev.c b/trunk/net/caif/caif_dev.c index b0ce14fbf6ef..9b298c14028d 100644 --- a/trunk/net/caif/caif_dev.c +++ b/trunk/net/caif/caif_dev.c @@ -58,6 +58,7 @@ static int q_high = 50; /* Percent */ struct cfcnfg *get_cfcnfg(struct net *net) { struct caif_net *caifn; + BUG_ON(!net); caifn = net_generic(net, caif_net_id); if (!caifn) return NULL; @@ -68,6 +69,7 @@ EXPORT_SYMBOL(get_cfcnfg); static struct caif_device_entry_list *caif_device_list(struct net *net) { struct caif_net *caifn; + BUG_ON(!net); caifn = net_generic(net, caif_net_id); if (!caifn) return NULL; @@ -505,15 +507,15 @@ static struct notifier_block caif_device_notifier = { static int caif_init_net(struct net *net) { struct caif_net *caifn = net_generic(net, caif_net_id); - if (WARN_ON(!caifn)) - return -EINVAL; - + BUG_ON(!caifn); INIT_LIST_HEAD(&caifn->caifdevs.list); mutex_init(&caifn->caifdevs.lock); caifn->cfg = cfcnfg_create(); - if (!caifn->cfg) + if (!caifn->cfg) { + pr_warn("can't create cfcnfg\n"); return -ENOMEM; + } return 0; } diff --git a/trunk/net/caif/cfrfml.c b/trunk/net/caif/cfrfml.c index 6dc75d4f8d94..81660f809713 100644 --- a/trunk/net/caif/cfrfml.c +++ b/trunk/net/caif/cfrfml.c @@ -190,7 +190,7 @@ static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt) static int cfrfml_transmit_segment(struct cfrfml *rfml, struct cfpkt *pkt) { - caif_assert(cfpkt_getlen(pkt) < rfml->fragment_size + RFM_HEAD_SIZE); + caif_assert(cfpkt_getlen(pkt) < rfml->fragment_size); /* Add info for MUX-layer to route the packet out. */ cfpkt_info(pkt)->channel_id = rfml->serv.layer.id; diff --git a/trunk/net/core/Makefile b/trunk/net/core/Makefile index 674641b13aea..c4ecc864020f 100644 --- a/trunk/net/core/Makefile +++ b/trunk/net/core/Makefile @@ -8,8 +8,7 @@ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o obj-y += dev.o ethtool.o dev_addr_lists.o dst.o netevent.o \ - neighbour.o rtnetlink.o utils.o link_watch.o filter.o \ - sock_diag.o + neighbour.o rtnetlink.o utils.o link_watch.o filter.o obj-$(CONFIG_XFRM) += flow.o obj-y += net-sysfs.o diff --git a/trunk/net/core/ethtool.c b/trunk/net/core/ethtool.c index 597732c989ca..31b0b7f5383e 100644 --- a/trunk/net/core/ethtool.c +++ b/trunk/net/core/ethtool.c @@ -515,44 +515,34 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev, void __user *useraddr) { - u32 user_size, dev_size; - u32 *indir; + struct ethtool_rxfh_indir *indir; + u32 table_size; + size_t full_size; int ret; - if (!dev->ethtool_ops->get_rxfh_indir_size || - !dev->ethtool_ops->get_rxfh_indir) - return -EOPNOTSUPP; - dev_size = dev->ethtool_ops->get_rxfh_indir_size(dev); - if (dev_size == 0) + if (!dev->ethtool_ops->get_rxfh_indir) return -EOPNOTSUPP; - if (copy_from_user(&user_size, + if (copy_from_user(&table_size, useraddr + offsetof(struct ethtool_rxfh_indir, size), - sizeof(user_size))) - return -EFAULT; - - if (copy_to_user(useraddr + offsetof(struct ethtool_rxfh_indir, size), - &dev_size, sizeof(dev_size))) + sizeof(table_size))) return -EFAULT; - /* If the user buffer size is 0, this is just a query for the - * device table size. Otherwise, if it's smaller than the - * device table size it's an error. - */ - if (user_size < dev_size) - return user_size == 0 ? 0 : -EINVAL; - - indir = kcalloc(dev_size, sizeof(indir[0]), GFP_USER); + if (table_size > + (KMALLOC_MAX_SIZE - sizeof(*indir)) / sizeof(*indir->ring_index)) + return -ENOMEM; + full_size = sizeof(*indir) + sizeof(*indir->ring_index) * table_size; + indir = kzalloc(full_size, GFP_USER); if (!indir) return -ENOMEM; + indir->cmd = ETHTOOL_GRXFHINDIR; + indir->size = table_size; ret = dev->ethtool_ops->get_rxfh_indir(dev, indir); if (ret) goto out; - if (copy_to_user(useraddr + - offsetof(struct ethtool_rxfh_indir, ring_index[0]), - indir, dev_size * sizeof(indir[0]))) + if (copy_to_user(useraddr, indir, full_size)) ret = -EFAULT; out: @@ -563,56 +553,30 @@ static noinline_for_stack int ethtool_get_rxfh_indir(struct net_device *dev, static noinline_for_stack int ethtool_set_rxfh_indir(struct net_device *dev, void __user *useraddr) { - struct ethtool_rxnfc rx_rings; - u32 user_size, dev_size, i; - u32 *indir; + struct ethtool_rxfh_indir *indir; + u32 table_size; + size_t full_size; int ret; - if (!dev->ethtool_ops->get_rxfh_indir_size || - !dev->ethtool_ops->set_rxfh_indir || - !dev->ethtool_ops->get_rxnfc) - return -EOPNOTSUPP; - dev_size = dev->ethtool_ops->get_rxfh_indir_size(dev); - if (dev_size == 0) + if (!dev->ethtool_ops->set_rxfh_indir) return -EOPNOTSUPP; - if (copy_from_user(&user_size, + if (copy_from_user(&table_size, useraddr + offsetof(struct ethtool_rxfh_indir, size), - sizeof(user_size))) + sizeof(table_size))) return -EFAULT; - if (user_size != 0 && user_size != dev_size) - return -EINVAL; - - indir = kcalloc(dev_size, sizeof(indir[0]), GFP_USER); + if (table_size > + (KMALLOC_MAX_SIZE - sizeof(*indir)) / sizeof(*indir->ring_index)) + return -ENOMEM; + full_size = sizeof(*indir) + sizeof(*indir->ring_index) * table_size; + indir = kmalloc(full_size, GFP_USER); if (!indir) return -ENOMEM; - rx_rings.cmd = ETHTOOL_GRXRINGS; - ret = dev->ethtool_ops->get_rxnfc(dev, &rx_rings, NULL); - if (ret) + if (copy_from_user(indir, useraddr, full_size)) { + ret = -EFAULT; goto out; - - if (user_size == 0) { - for (i = 0; i < dev_size; i++) - indir[i] = ethtool_rxfh_indir_default(i, rx_rings.data); - } else { - if (copy_from_user(indir, - useraddr + - offsetof(struct ethtool_rxfh_indir, - ring_index[0]), - dev_size * sizeof(indir[0]))) { - ret = -EFAULT; - goto out; - } - - /* Validate ring indices */ - for (i = 0; i < dev_size; i++) { - if (indir[i] >= rx_rings.data) { - ret = -EINVAL; - goto out; - } - } } ret = dev->ethtool_ops->set_rxfh_indir(dev, indir); diff --git a/trunk/net/core/neighbour.c b/trunk/net/core/neighbour.c index d57a40a2598c..4af151e1bf5d 100644 --- a/trunk/net/core/neighbour.c +++ b/trunk/net/core/neighbour.c @@ -497,6 +497,13 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey, } } + /* Device specific setup. */ + if (n->parms->neigh_setup && + (error = n->parms->neigh_setup(n)) < 0) { + rc = ERR_PTR(error); + goto out_neigh_release; + } + n->confirmed = jiffies - (n->parms->base_reachable_time << 1); write_lock_bh(&tbl->lock); @@ -710,6 +717,9 @@ void neigh_destroy(struct neighbour *neigh) skb_queue_purge(&neigh->arp_queue); neigh->arp_queue_len_bytes = 0; + if (dev->netdev_ops->ndo_neigh_destroy) + dev->netdev_ops->ndo_neigh_destroy(neigh); + dev_put(dev); neigh_parms_put(neigh->parms); diff --git a/trunk/net/core/request_sock.c b/trunk/net/core/request_sock.c index 9b570a6a33c5..182236b2510a 100644 --- a/trunk/net/core/request_sock.c +++ b/trunk/net/core/request_sock.c @@ -26,11 +26,10 @@ * but then some measure against one socket starving all other sockets * would be needed. * - * The minimum value of it is 128. Experiments with real servers show that + * It was 128 by default. Experiments with real servers show, that * it is absolutely not enough even at 100conn/sec. 256 cures most - * of problems. - * This value is adjusted to 128 for low memory machines, - * and it will increase in proportion to the memory of machine. + * of problems. This value is adjusted to 128 for very small machines + * (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb). * Note : Dont forget somaxconn that may limit backlog too. */ int sysctl_max_syn_backlog = 256; diff --git a/trunk/net/core/rtnetlink.c b/trunk/net/core/rtnetlink.c index dbf2ddafd52d..9083e82bdae5 100644 --- a/trunk/net/core/rtnetlink.c +++ b/trunk/net/core/rtnetlink.c @@ -273,17 +273,6 @@ EXPORT_SYMBOL_GPL(rtnl_unregister_all); static LIST_HEAD(link_ops); -static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) -{ - const struct rtnl_link_ops *ops; - - list_for_each_entry(ops, &link_ops, list) { - if (!strcmp(ops->kind, kind)) - return ops; - } - return NULL; -} - /** * __rtnl_link_register - Register rtnl_link_ops with rtnetlink. * @ops: struct rtnl_link_ops * to register @@ -296,9 +285,6 @@ static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) */ int __rtnl_link_register(struct rtnl_link_ops *ops) { - if (rtnl_link_ops_get(ops->kind)) - return -EEXIST; - if (!ops->dellink) ops->dellink = unregister_netdevice_queue; @@ -365,6 +351,17 @@ void rtnl_link_unregister(struct rtnl_link_ops *ops) } EXPORT_SYMBOL_GPL(rtnl_link_unregister); +static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) +{ + const struct rtnl_link_ops *ops; + + list_for_each_entry(ops, &link_ops, list) { + if (!strcmp(ops->kind, kind)) + return ops; + } + return NULL; +} + static size_t rtnl_link_get_size(const struct net_device *dev) { const struct rtnl_link_ops *ops = dev->rtnl_link_ops; diff --git a/trunk/net/core/secure_seq.c b/trunk/net/core/secure_seq.c index 9fbca46f3e74..025233de25f9 100644 --- a/trunk/net/core/secure_seq.c +++ b/trunk/net/core/secure_seq.c @@ -19,7 +19,6 @@ static int __init net_secret_init(void) } late_initcall(net_secret_init); -#ifdef CONFIG_INET static u32 seq_scale(u32 seq) { /* @@ -34,9 +33,8 @@ static u32 seq_scale(u32 seq) */ return seq + (ktime_to_ns(ktime_get_real()) >> 6); } -#endif -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr, __be16 sport, __be16 dport) { @@ -156,7 +154,7 @@ u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, } EXPORT_SYMBOL(secure_dccp_sequence_number); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, __be16 sport, __be16 dport) { diff --git a/trunk/net/core/sock.c b/trunk/net/core/sock.c index 5a6a90620656..9777da86aeac 100644 --- a/trunk/net/core/sock.c +++ b/trunk/net/core/sock.c @@ -111,7 +111,6 @@ #include #include #include -#include #include #include @@ -136,46 +135,6 @@ #include #endif -static DEFINE_RWLOCK(proto_list_lock); -static LIST_HEAD(proto_list); - -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM -int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss) -{ - struct proto *proto; - int ret = 0; - - read_lock(&proto_list_lock); - list_for_each_entry(proto, &proto_list, node) { - if (proto->init_cgroup) { - ret = proto->init_cgroup(cgrp, ss); - if (ret) - goto out; - } - } - - read_unlock(&proto_list_lock); - return ret; -out: - list_for_each_entry_continue_reverse(proto, &proto_list, node) - if (proto->destroy_cgroup) - proto->destroy_cgroup(cgrp, ss); - read_unlock(&proto_list_lock); - return ret; -} - -void mem_cgroup_sockets_destroy(struct cgroup *cgrp, struct cgroup_subsys *ss) -{ - struct proto *proto; - - read_lock(&proto_list_lock); - list_for_each_entry_reverse(proto, &proto_list, node) - if (proto->destroy_cgroup) - proto->destroy_cgroup(cgrp, ss); - read_unlock(&proto_list_lock); -} -#endif - /* * Each address family might have different locking rules, so we have * one slock key per address family: @@ -183,9 +142,6 @@ void mem_cgroup_sockets_destroy(struct cgroup *cgrp, struct cgroup_subsys *ss) static struct lock_class_key af_family_keys[AF_MAX]; static struct lock_class_key af_family_slock_keys[AF_MAX]; -struct jump_label_key memcg_socket_limit_enabled; -EXPORT_SYMBOL(memcg_socket_limit_enabled); - /* * Make lock validator output more readable. (we pre-construct these * strings build-time, so that runtime initialization of socket @@ -1367,7 +1323,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) newsk->sk_wq = NULL; if (newsk->sk_prot->sockets_allocated) - sk_sockets_allocated_inc(newsk); + percpu_counter_inc(newsk->sk_prot->sockets_allocated); if (newsk->sk_flags & SK_FLAGS_TIMESTAMP) net_enable_timestamp(); @@ -1755,34 +1711,30 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind) struct proto *prot = sk->sk_prot; int amt = sk_mem_pages(size); long allocated; - int parent_status = UNDER_LIMIT; sk->sk_forward_alloc += amt * SK_MEM_QUANTUM; - - allocated = sk_memory_allocated_add(sk, amt, &parent_status); + allocated = atomic_long_add_return(amt, prot->memory_allocated); /* Under limit. */ - if (parent_status == UNDER_LIMIT && - allocated <= sk_prot_mem_limits(sk, 0)) { - sk_leave_memory_pressure(sk); + if (allocated <= prot->sysctl_mem[0]) { + if (prot->memory_pressure && *prot->memory_pressure) + *prot->memory_pressure = 0; return 1; } - /* Under pressure. (we or our parents) */ - if ((parent_status > SOFT_LIMIT) || - allocated > sk_prot_mem_limits(sk, 1)) - sk_enter_memory_pressure(sk); + /* Under pressure. */ + if (allocated > prot->sysctl_mem[1]) + if (prot->enter_memory_pressure) + prot->enter_memory_pressure(sk); - /* Over hard limit (we or our parents) */ - if ((parent_status == OVER_LIMIT) || - (allocated > sk_prot_mem_limits(sk, 2))) + /* Over hard limit. */ + if (allocated > prot->sysctl_mem[2]) goto suppress_allocation; /* guarantee minimum buffer size under pressure */ if (kind == SK_MEM_RECV) { if (atomic_read(&sk->sk_rmem_alloc) < prot->sysctl_rmem[0]) return 1; - } else { /* SK_MEM_SEND */ if (sk->sk_type == SOCK_STREAM) { if (sk->sk_wmem_queued < prot->sysctl_wmem[0]) @@ -1792,13 +1744,13 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind) return 1; } - if (sk_has_memory_pressure(sk)) { + if (prot->memory_pressure) { int alloc; - if (!sk_under_memory_pressure(sk)) + if (!*prot->memory_pressure) return 1; - alloc = sk_sockets_allocated_read_positive(sk); - if (sk_prot_mem_limits(sk, 2) > alloc * + alloc = percpu_counter_read_positive(prot->sockets_allocated); + if (prot->sysctl_mem[2] > alloc * sk_mem_pages(sk->sk_wmem_queued + atomic_read(&sk->sk_rmem_alloc) + sk->sk_forward_alloc)) @@ -1821,9 +1773,7 @@ int __sk_mem_schedule(struct sock *sk, int size, int kind) /* Alas. Undo changes. */ sk->sk_forward_alloc -= amt * SK_MEM_QUANTUM; - - sk_memory_allocated_sub(sk, amt, parent_status); - + atomic_long_sub(amt, prot->memory_allocated); return 0; } EXPORT_SYMBOL(__sk_mem_schedule); @@ -1834,13 +1784,15 @@ EXPORT_SYMBOL(__sk_mem_schedule); */ void __sk_mem_reclaim(struct sock *sk) { - sk_memory_allocated_sub(sk, - sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT, 0); + struct proto *prot = sk->sk_prot; + + atomic_long_sub(sk->sk_forward_alloc >> SK_MEM_QUANTUM_SHIFT, + prot->memory_allocated); sk->sk_forward_alloc &= SK_MEM_QUANTUM - 1; - if (sk_under_memory_pressure(sk) && - (sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0))) - sk_leave_memory_pressure(sk); + if (prot->memory_pressure && *prot->memory_pressure && + (atomic_long_read(prot->memory_allocated) < prot->sysctl_mem[0])) + *prot->memory_pressure = 0; } EXPORT_SYMBOL(__sk_mem_reclaim); @@ -2331,6 +2283,9 @@ void sk_common_release(struct sock *sk) } EXPORT_SYMBOL(sk_common_release); +static DEFINE_RWLOCK(proto_list_lock); +static LIST_HEAD(proto_list); + #ifdef CONFIG_PROC_FS #define PROTO_INUSE_NR 64 /* should be enough for the first time */ struct prot_inuse { @@ -2552,27 +2507,16 @@ static char proto_method_implemented(const void *method) { return method == NULL ? 'n' : 'y'; } -static long sock_prot_memory_allocated(struct proto *proto) -{ - return proto->memory_allocated != NULL ? proto_memory_allocated(proto): -1L; -} - -static char *sock_prot_memory_pressure(struct proto *proto) -{ - return proto->memory_pressure != NULL ? - proto_memory_pressure(proto) ? "yes" : "no" : "NI"; -} static void proto_seq_printf(struct seq_file *seq, struct proto *proto) { - seq_printf(seq, "%-9s %4u %6d %6ld %-3s %6u %-3s %-10s " "%2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c %2c\n", proto->name, proto->obj_size, sock_prot_inuse_get(seq_file_net(seq), proto), - sock_prot_memory_allocated(proto), - sock_prot_memory_pressure(proto), + proto->memory_allocated != NULL ? atomic_long_read(proto->memory_allocated) : -1L, + proto->memory_pressure != NULL ? *proto->memory_pressure ? "yes" : "no" : "NI", proto->max_header, proto->slab == NULL ? "no" : "yes", module_name(proto->owner), diff --git a/trunk/net/core/sock_diag.c b/trunk/net/core/sock_diag.c deleted file mode 100644 index 711bdefe7753..000000000000 --- a/trunk/net/core/sock_diag.c +++ /dev/null @@ -1,169 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include - -static struct sock_diag_handler *sock_diag_handlers[AF_MAX]; -static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh); -static DEFINE_MUTEX(sock_diag_table_mutex); - -int sock_diag_check_cookie(void *sk, __u32 *cookie) -{ - if ((cookie[0] != INET_DIAG_NOCOOKIE || - cookie[1] != INET_DIAG_NOCOOKIE) && - ((u32)(unsigned long)sk != cookie[0] || - (u32)((((unsigned long)sk) >> 31) >> 1) != cookie[1])) - return -ESTALE; - else - return 0; -} -EXPORT_SYMBOL_GPL(sock_diag_check_cookie); - -void sock_diag_save_cookie(void *sk, __u32 *cookie) -{ - cookie[0] = (u32)(unsigned long)sk; - cookie[1] = (u32)(((unsigned long)sk >> 31) >> 1); -} -EXPORT_SYMBOL_GPL(sock_diag_save_cookie); - -void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)) -{ - mutex_lock(&sock_diag_table_mutex); - inet_rcv_compat = fn; - mutex_unlock(&sock_diag_table_mutex); -} -EXPORT_SYMBOL_GPL(sock_diag_register_inet_compat); - -void sock_diag_unregister_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)) -{ - mutex_lock(&sock_diag_table_mutex); - inet_rcv_compat = NULL; - mutex_unlock(&sock_diag_table_mutex); -} -EXPORT_SYMBOL_GPL(sock_diag_unregister_inet_compat); - -int sock_diag_register(struct sock_diag_handler *hndl) -{ - int err = 0; - - if (hndl->family >= AF_MAX) - return -EINVAL; - - mutex_lock(&sock_diag_table_mutex); - if (sock_diag_handlers[hndl->family]) - err = -EBUSY; - else - sock_diag_handlers[hndl->family] = hndl; - mutex_unlock(&sock_diag_table_mutex); - - return err; -} -EXPORT_SYMBOL_GPL(sock_diag_register); - -void sock_diag_unregister(struct sock_diag_handler *hnld) -{ - int family = hnld->family; - - if (family >= AF_MAX) - return; - - mutex_lock(&sock_diag_table_mutex); - BUG_ON(sock_diag_handlers[family] != hnld); - sock_diag_handlers[family] = NULL; - mutex_unlock(&sock_diag_table_mutex); -} -EXPORT_SYMBOL_GPL(sock_diag_unregister); - -static inline struct sock_diag_handler *sock_diag_lock_handler(int family) -{ - if (sock_diag_handlers[family] == NULL) - request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, - NETLINK_SOCK_DIAG, family); - - mutex_lock(&sock_diag_table_mutex); - return sock_diag_handlers[family]; -} - -static inline void sock_diag_unlock_handler(struct sock_diag_handler *h) -{ - mutex_unlock(&sock_diag_table_mutex); -} - -static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) -{ - int err; - struct sock_diag_req *req = NLMSG_DATA(nlh); - struct sock_diag_handler *hndl; - - if (nlmsg_len(nlh) < sizeof(*req)) - return -EINVAL; - - hndl = sock_diag_lock_handler(req->sdiag_family); - if (hndl == NULL) - err = -ENOENT; - else - err = hndl->dump(skb, nlh); - sock_diag_unlock_handler(hndl); - - return err; -} - -static int sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) -{ - int ret; - - switch (nlh->nlmsg_type) { - case TCPDIAG_GETSOCK: - case DCCPDIAG_GETSOCK: - if (inet_rcv_compat == NULL) - request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, - NETLINK_SOCK_DIAG, AF_INET); - - mutex_lock(&sock_diag_table_mutex); - if (inet_rcv_compat != NULL) - ret = inet_rcv_compat(skb, nlh); - else - ret = -EOPNOTSUPP; - mutex_unlock(&sock_diag_table_mutex); - - return ret; - case SOCK_DIAG_BY_FAMILY: - return __sock_diag_rcv_msg(skb, nlh); - default: - return -EINVAL; - } -} - -static DEFINE_MUTEX(sock_diag_mutex); - -static void sock_diag_rcv(struct sk_buff *skb) -{ - mutex_lock(&sock_diag_mutex); - netlink_rcv_skb(skb, &sock_diag_rcv_msg); - mutex_unlock(&sock_diag_mutex); -} - -struct sock *sock_diag_nlsk; -EXPORT_SYMBOL_GPL(sock_diag_nlsk); - -static int __init sock_diag_init(void) -{ - sock_diag_nlsk = netlink_kernel_create(&init_net, NETLINK_SOCK_DIAG, 0, - sock_diag_rcv, NULL, THIS_MODULE); - return sock_diag_nlsk == NULL ? -ENOMEM : 0; -} - -static void __exit sock_diag_exit(void) -{ - netlink_kernel_release(sock_diag_nlsk); -} - -module_init(sock_diag_init); -module_exit(sock_diag_exit); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_SOCK_DIAG); diff --git a/trunk/net/dccp/dccp.h b/trunk/net/dccp/dccp.h index 5818032e35a9..583490aaf56f 100644 --- a/trunk/net/dccp/dccp.h +++ b/trunk/net/dccp/dccp.h @@ -357,7 +357,7 @@ static inline int dccp_bad_service_code(const struct sock *sk, struct dccp_skb_cb { union { struct inet_skb_parm h4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) struct inet6_skb_parm h6; #endif } header; diff --git a/trunk/net/dccp/diag.c b/trunk/net/dccp/diag.c index 8f1625753377..b21f261da75e 100644 --- a/trunk/net/dccp/diag.c +++ b/trunk/net/dccp/diag.c @@ -48,23 +48,11 @@ static void dccp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, dccp_get_info(sk, _info); } -static void dccp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, struct nlattr *bc) -{ - inet_diag_dump_icsk(&dccp_hashinfo, skb, cb, r, bc); -} - -static int dccp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, - struct inet_diag_req *req) -{ - return inet_diag_dump_one_icsk(&dccp_hashinfo, in_skb, nlh, req); -} - static const struct inet_diag_handler dccp_diag_handler = { - .dump = dccp_diag_dump, - .dump_one = dccp_diag_dump_one, + .idiag_hashinfo = &dccp_hashinfo, .idiag_get_info = dccp_diag_get_info, - .idiag_type = IPPROTO_DCCP, + .idiag_type = DCCPDIAG_GETSOCK, + .idiag_info_size = sizeof(struct tcp_info), }; static int __init dccp_diag_init(void) @@ -83,4 +71,4 @@ module_exit(dccp_diag_fini); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Arnaldo Carvalho de Melo "); MODULE_DESCRIPTION("DCCP inet_diag handler"); -MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-33 /* AF_INET - IPPROTO_DCCP */); +MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_INET_DIAG, DCCPDIAG_GETSOCK); diff --git a/trunk/net/dccp/minisocks.c b/trunk/net/dccp/minisocks.c index 5a7f90bbffac..b50d5fd3d696 100644 --- a/trunk/net/dccp/minisocks.c +++ b/trunk/net/dccp/minisocks.c @@ -53,7 +53,7 @@ void dccp_time_wait(struct sock *sk, int state, int timeo) if (tw != NULL) { const struct inet_connection_sock *icsk = inet_csk(sk); const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if (tw->tw_family == PF_INET6) { const struct ipv6_pinfo *np = inet6_sk(sk); struct inet6_timewait_sock *tw6; diff --git a/trunk/net/ipv4/Kconfig b/trunk/net/ipv4/Kconfig index 1a8f93bd2d4f..cbb505ba9324 100644 --- a/trunk/net/ipv4/Kconfig +++ b/trunk/net/ipv4/Kconfig @@ -409,10 +409,6 @@ config INET_TCP_DIAG depends on INET_DIAG def_tristate INET_DIAG -config INET_UDP_DIAG - depends on INET_DIAG - def_tristate INET_DIAG && IPV6 - menuconfig TCP_CONG_ADVANCED bool "TCP: advanced congestion control" ---help--- diff --git a/trunk/net/ipv4/Makefile b/trunk/net/ipv4/Makefile index ff75d3bbcd6a..f2dc69cffb57 100644 --- a/trunk/net/ipv4/Makefile +++ b/trunk/net/ipv4/Makefile @@ -34,7 +34,6 @@ obj-$(CONFIG_IP_PNP) += ipconfig.o obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/ obj-$(CONFIG_INET_DIAG) += inet_diag.o obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o -obj-$(CONFIG_INET_UDP_DIAG) += udp_diag.o obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o obj-$(CONFIG_TCP_CONG_CUBIC) += tcp_cubic.o @@ -48,7 +47,6 @@ obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.o obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o -obj-$(CONFIG_CGROUP_MEM_RES_CTLR_KMEM) += tcp_memcontrol.o obj-$(CONFIG_NETLABEL) += cipso_ipv4.o obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ diff --git a/trunk/net/ipv4/af_inet.c b/trunk/net/ipv4/af_inet.c index f7b5670744f0..15dc4c4828de 100644 --- a/trunk/net/ipv4/af_inet.c +++ b/trunk/net/ipv4/af_inet.c @@ -1672,8 +1672,6 @@ static int __init inet_init(void) ip_static_sysctl_init(); #endif - tcp_prot.sysctl_mem = init_net.ipv4.sysctl_tcp_mem; - /* * Add all the base protocols. */ diff --git a/trunk/net/ipv4/inet_connection_sock.c b/trunk/net/ipv4/inet_connection_sock.c index 2e4e24476c4c..a598768c616c 100644 --- a/trunk/net/ipv4/inet_connection_sock.c +++ b/trunk/net/ipv4/inet_connection_sock.c @@ -418,7 +418,7 @@ static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport, return jhash_2words((__force u32)raddr, (__force u32)rport, rnd) & (synq_hsize - 1); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #define AF_INET_FAMILY(fam) ((fam) == AF_INET) #else #define AF_INET_FAMILY(fam) 1 diff --git a/trunk/net/ipv4/inet_diag.c b/trunk/net/ipv4/inet_diag.c index fb2e47ff59f7..0a46c541b477 100644 --- a/trunk/net/ipv4/inet_diag.c +++ b/trunk/net/ipv4/inet_diag.c @@ -33,7 +33,6 @@ #include #include -#include static const struct inet_diag_handler **inet_diag_table; @@ -46,22 +45,24 @@ struct inet_diag_entry { u16 userlocks; }; +static struct sock *idiagnl; + #define INET_DIAG_PUT(skb, attrtype, attrlen) \ RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) static DEFINE_MUTEX(inet_diag_table_mutex); -static const struct inet_diag_handler *inet_diag_lock_handler(int proto) +static const struct inet_diag_handler *inet_diag_lock_handler(int type) { - if (!inet_diag_table[proto]) - request_module("net-pf-%d-proto-%d-type-%d-%d", PF_NETLINK, - NETLINK_SOCK_DIAG, AF_INET, proto); + if (!inet_diag_table[type]) + request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK, + NETLINK_INET_DIAG, type); mutex_lock(&inet_diag_table_mutex); - if (!inet_diag_table[proto]) + if (!inet_diag_table[type]) return ERR_PTR(-ENOENT); - return inet_diag_table[proto]; + return inet_diag_table[type]; } static inline void inet_diag_unlock_handler( @@ -70,21 +71,21 @@ static inline void inet_diag_unlock_handler( mutex_unlock(&inet_diag_table_mutex); } -int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, - struct sk_buff *skb, struct inet_diag_req *req, - u32 pid, u32 seq, u16 nlmsg_flags, +static int inet_csk_diag_fill(struct sock *sk, + struct sk_buff *skb, + int ext, u32 pid, u32 seq, u16 nlmsg_flags, const struct nlmsghdr *unlh) { const struct inet_sock *inet = inet_sk(sk); + const struct inet_connection_sock *icsk = inet_csk(sk); struct inet_diag_msg *r; struct nlmsghdr *nlh; void *info = NULL; struct inet_diag_meminfo *minfo = NULL; unsigned char *b = skb_tail_pointer(skb); const struct inet_diag_handler *handler; - int ext = req->idiag_ext; - handler = inet_diag_table[req->sdiag_protocol]; + handler = inet_diag_table[unlh->nlmsg_type]; BUG_ON(handler == NULL); nlh = NLMSG_PUT(skb, pid, seq, unlh->nlmsg_type, sizeof(*r)); @@ -96,13 +97,25 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, if (ext & (1 << (INET_DIAG_MEMINFO - 1))) minfo = INET_DIAG_PUT(skb, INET_DIAG_MEMINFO, sizeof(*minfo)); + if (ext & (1 << (INET_DIAG_INFO - 1))) + info = INET_DIAG_PUT(skb, INET_DIAG_INFO, + handler->idiag_info_size); + + if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) { + const size_t len = strlen(icsk->icsk_ca_ops->name); + + strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1), + icsk->icsk_ca_ops->name); + } + r->idiag_family = sk->sk_family; r->idiag_state = sk->sk_state; r->idiag_timer = 0; r->idiag_retrans = 0; r->id.idiag_if = sk->sk_bound_dev_if; - sock_diag_save_cookie(sk, r->id.idiag_cookie); + r->id.idiag_cookie[0] = (u32)(unsigned long)sk; + r->id.idiag_cookie[1] = (u32)(((unsigned long)sk >> 31) >> 1); r->id.idiag_sport = inet->inet_sport; r->id.idiag_dport = inet->inet_dport; @@ -115,7 +128,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, if (ext & (1 << (INET_DIAG_TOS - 1))) RTA_PUT_U8(skb, INET_DIAG_TOS, inet->tos); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (r->idiag_family == AF_INET6) { const struct ipv6_pinfo *np = inet6_sk(sk); @@ -126,21 +139,6 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, } #endif - r->idiag_uid = sock_i_uid(sk); - r->idiag_inode = sock_i_ino(sk); - - if (minfo) { - minfo->idiag_rmem = sk_rmem_alloc_get(sk); - minfo->idiag_wmem = sk->sk_wmem_queued; - minfo->idiag_fmem = sk->sk_forward_alloc; - minfo->idiag_tmem = sk_wmem_alloc_get(sk); - } - - if (icsk == NULL) { - r->idiag_rqueue = r->idiag_wqueue = 0; - goto out; - } - #define EXPIRES_IN_MS(tmo) DIV_ROUND_UP((tmo - jiffies) * 1000, HZ) if (icsk->icsk_pending == ICSK_TIME_RETRANS) { @@ -161,14 +159,14 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, } #undef EXPIRES_IN_MS - if (ext & (1 << (INET_DIAG_INFO - 1))) - info = INET_DIAG_PUT(skb, INET_DIAG_INFO, sizeof(struct tcp_info)); - - if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) { - const size_t len = strlen(icsk->icsk_ca_ops->name); + r->idiag_uid = sock_i_uid(sk); + r->idiag_inode = sock_i_ino(sk); - strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1), - icsk->icsk_ca_ops->name); + if (minfo) { + minfo->idiag_rmem = sk_rmem_alloc_get(sk); + minfo->idiag_wmem = sk->sk_wmem_queued; + minfo->idiag_fmem = sk->sk_forward_alloc; + minfo->idiag_tmem = sk_wmem_alloc_get(sk); } handler->idiag_get_info(sk, r, info); @@ -177,7 +175,6 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, icsk->icsk_ca_ops && icsk->icsk_ca_ops->get_info) icsk->icsk_ca_ops->get_info(sk, ext, skb); -out: nlh->nlmsg_len = skb_tail_pointer(skb) - b; return skb->len; @@ -186,20 +183,10 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, nlmsg_trim(skb, b); return -EMSGSIZE; } -EXPORT_SYMBOL_GPL(inet_sk_diag_fill); - -static int inet_csk_diag_fill(struct sock *sk, - struct sk_buff *skb, struct inet_diag_req *req, - u32 pid, u32 seq, u16 nlmsg_flags, - const struct nlmsghdr *unlh) -{ - return inet_sk_diag_fill(sk, inet_csk(sk), - skb, req, pid, seq, nlmsg_flags, unlh); -} static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, - struct sk_buff *skb, struct inet_diag_req *req, - u32 pid, u32 seq, u16 nlmsg_flags, + struct sk_buff *skb, int ext, u32 pid, + u32 seq, u16 nlmsg_flags, const struct nlmsghdr *unlh) { long tmo; @@ -220,7 +207,8 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, r->idiag_family = tw->tw_family; r->idiag_retrans = 0; r->id.idiag_if = tw->tw_bound_dev_if; - sock_diag_save_cookie(tw, r->id.idiag_cookie); + r->id.idiag_cookie[0] = (u32)(unsigned long)tw; + r->id.idiag_cookie[1] = (u32)(((unsigned long)tw >> 31) >> 1); r->id.idiag_sport = tw->tw_sport; r->id.idiag_dport = tw->tw_dport; r->id.idiag_src[0] = tw->tw_rcv_saddr; @@ -232,7 +220,7 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, r->idiag_wqueue = 0; r->idiag_uid = 0; r->idiag_inode = 0; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (tw->tw_family == AF_INET6) { const struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); @@ -249,31 +237,42 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, } static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, - struct inet_diag_req *r, u32 pid, u32 seq, u16 nlmsg_flags, + int ext, u32 pid, u32 seq, u16 nlmsg_flags, const struct nlmsghdr *unlh) { if (sk->sk_state == TCP_TIME_WAIT) return inet_twsk_diag_fill((struct inet_timewait_sock *)sk, - skb, r, pid, seq, nlmsg_flags, + skb, ext, pid, seq, nlmsg_flags, unlh); - return inet_csk_diag_fill(sk, skb, r, pid, seq, nlmsg_flags, unlh); + return inet_csk_diag_fill(sk, skb, ext, pid, seq, nlmsg_flags, unlh); } -int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_skb, - const struct nlmsghdr *nlh, struct inet_diag_req *req) +static int inet_diag_get_exact(struct sk_buff *in_skb, + const struct nlmsghdr *nlh) { int err; struct sock *sk; + struct inet_diag_req *req = NLMSG_DATA(nlh); struct sk_buff *rep; + struct inet_hashinfo *hashinfo; + const struct inet_diag_handler *handler; + handler = inet_diag_lock_handler(nlh->nlmsg_type); + if (IS_ERR(handler)) { + err = PTR_ERR(handler); + goto unlock; + } + + hashinfo = handler->idiag_hashinfo; err = -EINVAL; - if (req->sdiag_family == AF_INET) { + + if (req->idiag_family == AF_INET) { sk = inet_lookup(&init_net, hashinfo, req->id.idiag_dst[0], req->id.idiag_dport, req->id.idiag_src[0], req->id.idiag_sport, req->id.idiag_if); } -#if IS_ENABLED(CONFIG_IPV6) - else if (req->sdiag_family == AF_INET6) { +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + else if (req->idiag_family == AF_INET6) { sk = inet6_lookup(&init_net, hashinfo, (struct in6_addr *)req->id.idiag_dst, req->id.idiag_dport, @@ -283,26 +282,29 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s } #endif else { - goto out_nosk; + goto unlock; } err = -ENOENT; if (sk == NULL) - goto out_nosk; + goto unlock; - err = sock_diag_check_cookie(sk, req->id.idiag_cookie); - if (err) + err = -ESTALE; + if ((req->id.idiag_cookie[0] != INET_DIAG_NOCOOKIE || + req->id.idiag_cookie[1] != INET_DIAG_NOCOOKIE) && + ((u32)(unsigned long)sk != req->id.idiag_cookie[0] || + (u32)((((unsigned long)sk) >> 31) >> 1) != req->id.idiag_cookie[1])) goto out; err = -ENOMEM; rep = alloc_skb(NLMSG_SPACE((sizeof(struct inet_diag_msg) + sizeof(struct inet_diag_meminfo) + - sizeof(struct tcp_info) + 64)), + handler->idiag_info_size + 64)), GFP_KERNEL); if (!rep) goto out; - err = sk_diag_fill(sk, rep, req, + err = sk_diag_fill(sk, rep, req->idiag_ext, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, 0, nlh); if (err < 0) { @@ -310,7 +312,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s kfree_skb(rep); goto out; } - err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, + err = netlink_unicast(idiagnl, rep, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); if (err > 0) err = 0; @@ -322,25 +324,8 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s else sock_put(sk); } -out_nosk: - return err; -} -EXPORT_SYMBOL_GPL(inet_diag_dump_one_icsk); - -static int inet_diag_get_exact(struct sk_buff *in_skb, - const struct nlmsghdr *nlh, - struct inet_diag_req *req) -{ - const struct inet_diag_handler *handler; - int err; - - handler = inet_diag_lock_handler(req->sdiag_protocol); - if (IS_ERR(handler)) - err = PTR_ERR(handler); - else - err = handler->dump_one(in_skb, nlh, req); +unlock: inet_diag_unlock_handler(handler); - return err; } @@ -371,12 +356,9 @@ static int bitstring_match(const __be32 *a1, const __be32 *a2, int bits) } -static int inet_diag_bc_run(const struct nlattr *_bc, - const struct inet_diag_entry *entry) +static int inet_diag_bc_run(const void *bc, int len, + const struct inet_diag_entry *entry) { - const void *bc = nla_data(_bc); - int len = nla_len(_bc); - while (len > 0) { int yes = 1; const struct inet_diag_bc_op *op = bc; @@ -450,35 +432,6 @@ static int inet_diag_bc_run(const struct nlattr *_bc, return len == 0; } -int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk) -{ - struct inet_diag_entry entry; - struct inet_sock *inet = inet_sk(sk); - - if (bc == NULL) - return 1; - - entry.family = sk->sk_family; -#if IS_ENABLED(CONFIG_IPV6) - if (entry.family == AF_INET6) { - struct ipv6_pinfo *np = inet6_sk(sk); - - entry.saddr = np->rcv_saddr.s6_addr32; - entry.daddr = np->daddr.s6_addr32; - } else -#endif - { - entry.saddr = &inet->inet_rcv_saddr; - entry.daddr = &inet->inet_daddr; - } - entry.sport = inet->inet_num; - entry.dport = ntohs(inet->inet_dport); - entry.userlocks = sk->sk_userlocks; - - return inet_diag_bc_run(bc, &entry); -} -EXPORT_SYMBOL_GPL(inet_diag_bc_sk); - static int valid_cc(const void *bc, int len, int cc) { while (len >= 0) { @@ -535,29 +488,57 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) static int inet_csk_diag_dump(struct sock *sk, struct sk_buff *skb, - struct netlink_callback *cb, - struct inet_diag_req *r, - const struct nlattr *bc) + struct netlink_callback *cb) { - if (!inet_diag_bc_sk(bc, sk)) - return 0; + struct inet_diag_req *r = NLMSG_DATA(cb->nlh); - return inet_csk_diag_fill(sk, skb, r, + if (nlmsg_attrlen(cb->nlh, sizeof(*r))) { + struct inet_diag_entry entry; + const struct nlattr *bc = nlmsg_find_attr(cb->nlh, + sizeof(*r), + INET_DIAG_REQ_BYTECODE); + struct inet_sock *inet = inet_sk(sk); + + entry.family = sk->sk_family; +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + if (entry.family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + + entry.saddr = np->rcv_saddr.s6_addr32; + entry.daddr = np->daddr.s6_addr32; + } else +#endif + { + entry.saddr = &inet->inet_rcv_saddr; + entry.daddr = &inet->inet_daddr; + } + entry.sport = inet->inet_num; + entry.dport = ntohs(inet->inet_dport); + entry.userlocks = sk->sk_userlocks; + + if (!inet_diag_bc_run(nla_data(bc), nla_len(bc), &entry)) + return 0; + } + + return inet_csk_diag_fill(sk, skb, r->idiag_ext, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); } static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, struct sk_buff *skb, - struct netlink_callback *cb, - struct inet_diag_req *r, - const struct nlattr *bc) + struct netlink_callback *cb) { - if (bc != NULL) { + struct inet_diag_req *r = NLMSG_DATA(cb->nlh); + + if (nlmsg_attrlen(cb->nlh, sizeof(*r))) { struct inet_diag_entry entry; + const struct nlattr *bc = nlmsg_find_attr(cb->nlh, + sizeof(*r), + INET_DIAG_REQ_BYTECODE); entry.family = tw->tw_family; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (tw->tw_family == AF_INET6) { struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); @@ -573,11 +554,11 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, entry.dport = ntohs(tw->tw_dport); entry.userlocks = 0; - if (!inet_diag_bc_run(bc, &entry)) + if (!inet_diag_bc_run(nla_data(bc), nla_len(bc), &entry)) return 0; } - return inet_twsk_diag_fill(tw, skb, r, + return inet_twsk_diag_fill(tw, skb, r->idiag_ext, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); } @@ -603,7 +584,8 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, r->idiag_retrans = req->retrans; r->id.idiag_if = sk->sk_bound_dev_if; - sock_diag_save_cookie(req, r->id.idiag_cookie); + r->id.idiag_cookie[0] = (u32)(unsigned long)req; + r->id.idiag_cookie[1] = (u32)(((unsigned long)req >> 31) >> 1); tmo = req->expires - jiffies; if (tmo < 0) @@ -618,7 +600,7 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, r->idiag_wqueue = 0; r->idiag_uid = sock_i_uid(sk); r->idiag_inode = 0; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) if (r->idiag_family == AF_INET6) { *(struct in6_addr *)r->id.idiag_src = inet6_rsk(req)->loc_addr; *(struct in6_addr *)r->id.idiag_dst = inet6_rsk(req)->rmt_addr; @@ -634,13 +616,13 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, } static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, - struct netlink_callback *cb, - struct inet_diag_req *r, - const struct nlattr *bc) + struct netlink_callback *cb) { struct inet_diag_entry entry; + struct inet_diag_req *r = NLMSG_DATA(cb->nlh); struct inet_connection_sock *icsk = inet_csk(sk); struct listen_sock *lopt; + const struct nlattr *bc = NULL; struct inet_sock *inet = inet_sk(sk); int j, s_j; int reqnum, s_reqnum; @@ -660,7 +642,9 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, if (!lopt || !lopt->qlen) goto out; - if (bc != NULL) { + if (nlmsg_attrlen(cb->nlh, sizeof(*r))) { + bc = nlmsg_find_attr(cb->nlh, sizeof(*r), + INET_DIAG_REQ_BYTECODE); entry.sport = inet->inet_num; entry.userlocks = sk->sk_userlocks; } @@ -680,20 +664,21 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, if (bc) { entry.saddr = -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) (entry.family == AF_INET6) ? inet6_rsk(req)->loc_addr.s6_addr32 : #endif &ireq->loc_addr; entry.daddr = -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) (entry.family == AF_INET6) ? inet6_rsk(req)->rmt_addr.s6_addr32 : #endif &ireq->rmt_addr; entry.dport = ntohs(ireq->rmt_port); - if (!inet_diag_bc_run(bc, &entry)) + if (!inet_diag_bc_run(nla_data(bc), + nla_len(bc), &entry)) continue; } @@ -716,11 +701,19 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, return err; } -void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, - struct netlink_callback *cb, struct inet_diag_req *r, struct nlattr *bc) +static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) { int i, num; int s_i, s_num; + struct inet_diag_req *r = NLMSG_DATA(cb->nlh); + const struct inet_diag_handler *handler; + struct inet_hashinfo *hashinfo; + + handler = inet_diag_lock_handler(cb->nlh->nlmsg_type); + if (IS_ERR(handler)) + goto unlock; + + hashinfo = handler->idiag_hashinfo; s_i = cb->args[1]; s_num = num = cb->args[2]; @@ -745,10 +738,6 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, continue; } - if (r->sdiag_family != AF_UNSPEC && - sk->sk_family != r->sdiag_family) - goto next_listen; - if (r->id.idiag_sport != inet->inet_sport && r->id.idiag_sport) goto next_listen; @@ -758,7 +747,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, cb->args[3] > 0) goto syn_recv; - if (inet_csk_diag_dump(sk, skb, cb, r, bc) < 0) { + if (inet_csk_diag_dump(sk, skb, cb) < 0) { spin_unlock_bh(&ilb->lock); goto done; } @@ -767,7 +756,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, if (!(r->idiag_states & TCPF_SYN_RECV)) goto next_listen; - if (inet_diag_dump_reqs(skb, sk, cb, r, bc) < 0) { + if (inet_diag_dump_reqs(skb, sk, cb) < 0) { spin_unlock_bh(&ilb->lock); goto done; } @@ -789,7 +778,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, } if (!(r->idiag_states & ~(TCPF_LISTEN | TCPF_SYN_RECV))) - goto out; + goto unlock; for (i = s_i; i <= hashinfo->ehash_mask; i++) { struct inet_ehash_bucket *head = &hashinfo->ehash[i]; @@ -814,16 +803,13 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, goto next_normal; if (!(r->idiag_states & (1 << sk->sk_state))) goto next_normal; - if (r->sdiag_family != AF_UNSPEC && - sk->sk_family != r->sdiag_family) - goto next_normal; if (r->id.idiag_sport != inet->inet_sport && r->id.idiag_sport) goto next_normal; if (r->id.idiag_dport != inet->inet_dport && r->id.idiag_dport) goto next_normal; - if (inet_csk_diag_dump(sk, skb, cb, r, bc) < 0) { + if (inet_csk_diag_dump(sk, skb, cb) < 0) { spin_unlock_bh(lock); goto done; } @@ -839,16 +825,13 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, if (num < s_num) goto next_dying; - if (r->sdiag_family != AF_UNSPEC && - tw->tw_family != r->sdiag_family) - goto next_dying; if (r->id.idiag_sport != tw->tw_sport && r->id.idiag_sport) goto next_dying; if (r->id.idiag_dport != tw->tw_dport && r->id.idiag_dport) goto next_dying; - if (inet_twsk_diag_dump(tw, skb, cb, r, bc) < 0) { + if (inet_twsk_diag_dump(tw, skb, cb) < 0) { spin_unlock_bh(lock); goto done; } @@ -862,85 +845,15 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, done: cb->args[1] = i; cb->args[2] = num; -out: - ; -} -EXPORT_SYMBOL_GPL(inet_diag_dump_icsk); - -static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, struct nlattr *bc) -{ - const struct inet_diag_handler *handler; - - handler = inet_diag_lock_handler(r->sdiag_protocol); - if (!IS_ERR(handler)) - handler->dump(skb, cb, r, bc); +unlock: inet_diag_unlock_handler(handler); - return skb->len; } -static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) +static int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { - struct nlattr *bc = NULL; int hdrlen = sizeof(struct inet_diag_req); - if (nlmsg_attrlen(cb->nlh, hdrlen)) - bc = nlmsg_find_attr(cb->nlh, hdrlen, INET_DIAG_REQ_BYTECODE); - - return __inet_diag_dump(skb, cb, (struct inet_diag_req *)NLMSG_DATA(cb->nlh), bc); -} - -static inline int inet_diag_type2proto(int type) -{ - switch (type) { - case TCPDIAG_GETSOCK: - return IPPROTO_TCP; - case DCCPDIAG_GETSOCK: - return IPPROTO_DCCP; - default: - return 0; - } -} - -static int inet_diag_dump_compat(struct sk_buff *skb, struct netlink_callback *cb) -{ - struct inet_diag_req_compat *rc = NLMSG_DATA(cb->nlh); - struct inet_diag_req req; - struct nlattr *bc = NULL; - int hdrlen = sizeof(struct inet_diag_req_compat); - - req.sdiag_family = AF_UNSPEC; /* compatibility */ - req.sdiag_protocol = inet_diag_type2proto(cb->nlh->nlmsg_type); - req.idiag_ext = rc->idiag_ext; - req.idiag_states = rc->idiag_states; - req.id = rc->id; - - if (nlmsg_attrlen(cb->nlh, hdrlen)) - bc = nlmsg_find_attr(cb->nlh, hdrlen, INET_DIAG_REQ_BYTECODE); - - return __inet_diag_dump(skb, cb, &req, bc); -} - -static int inet_diag_get_exact_compat(struct sk_buff *in_skb, - const struct nlmsghdr *nlh) -{ - struct inet_diag_req_compat *rc = NLMSG_DATA(nlh); - struct inet_diag_req req; - - req.sdiag_family = rc->idiag_family; - req.sdiag_protocol = inet_diag_type2proto(nlh->nlmsg_type); - req.idiag_ext = rc->idiag_ext; - req.idiag_states = rc->idiag_states; - req.id = rc->id; - - return inet_diag_get_exact(in_skb, nlh, &req); -} - -static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) -{ - int hdrlen = sizeof(struct inet_diag_req_compat); - if (nlh->nlmsg_type >= INET_DIAG_GETSOCK_MAX || nlmsg_len(nlh) < hdrlen) return -EINVAL; @@ -957,54 +870,28 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh) return -EINVAL; } - return netlink_dump_start(sock_diag_nlsk, skb, nlh, - inet_diag_dump_compat, NULL, 0); - } - - return inet_diag_get_exact_compat(skb, nlh); -} - -static int inet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) -{ - int hdrlen = sizeof(struct inet_diag_req); - - if (nlmsg_len(h) < hdrlen) - return -EINVAL; - - if (h->nlmsg_flags & NLM_F_DUMP) { - if (nlmsg_attrlen(h, hdrlen)) { - struct nlattr *attr; - attr = nlmsg_find_attr(h, hdrlen, - INET_DIAG_REQ_BYTECODE); - if (attr == NULL || - nla_len(attr) < sizeof(struct inet_diag_bc_op) || - inet_diag_bc_audit(nla_data(attr), nla_len(attr))) - return -EINVAL; - } - - return netlink_dump_start(sock_diag_nlsk, skb, h, + return netlink_dump_start(idiagnl, skb, nlh, inet_diag_dump, NULL, 0); } - return inet_diag_get_exact(skb, h, (struct inet_diag_req *)NLMSG_DATA(h)); + return inet_diag_get_exact(skb, nlh); } -static struct sock_diag_handler inet_diag_handler = { - .family = AF_INET, - .dump = inet_diag_handler_dump, -}; +static DEFINE_MUTEX(inet_diag_mutex); -static struct sock_diag_handler inet6_diag_handler = { - .family = AF_INET6, - .dump = inet_diag_handler_dump, -}; +static void inet_diag_rcv(struct sk_buff *skb) +{ + mutex_lock(&inet_diag_mutex); + netlink_rcv_skb(skb, &inet_diag_rcv_msg); + mutex_unlock(&inet_diag_mutex); +} int inet_diag_register(const struct inet_diag_handler *h) { const __u16 type = h->idiag_type; int err = -EINVAL; - if (type >= IPPROTO_MAX) + if (type >= INET_DIAG_GETSOCK_MAX) goto out; mutex_lock(&inet_diag_table_mutex); @@ -1023,7 +910,7 @@ void inet_diag_unregister(const struct inet_diag_handler *h) { const __u16 type = h->idiag_type; - if (type >= IPPROTO_MAX) + if (type >= INET_DIAG_GETSOCK_MAX) return; mutex_lock(&inet_diag_table_mutex); @@ -1034,7 +921,7 @@ EXPORT_SYMBOL_GPL(inet_diag_unregister); static int __init inet_diag_init(void) { - const int inet_diag_table_size = (IPPROTO_MAX * + const int inet_diag_table_size = (INET_DIAG_GETSOCK_MAX * sizeof(struct inet_diag_handler *)); int err = -ENOMEM; @@ -1042,35 +929,25 @@ static int __init inet_diag_init(void) if (!inet_diag_table) goto out; - err = sock_diag_register(&inet_diag_handler); - if (err) - goto out_free_nl; - - err = sock_diag_register(&inet6_diag_handler); - if (err) - goto out_free_inet; - - sock_diag_register_inet_compat(inet_diag_rcv_msg_compat); + idiagnl = netlink_kernel_create(&init_net, NETLINK_INET_DIAG, 0, + inet_diag_rcv, NULL, THIS_MODULE); + if (idiagnl == NULL) + goto out_free_table; + err = 0; out: return err; - -out_free_inet: - sock_diag_unregister(&inet_diag_handler); -out_free_nl: +out_free_table: kfree(inet_diag_table); goto out; } static void __exit inet_diag_exit(void) { - sock_diag_unregister(&inet6_diag_handler); - sock_diag_unregister(&inet_diag_handler); - sock_diag_unregister_inet_compat(inet_diag_rcv_msg_compat); + netlink_kernel_release(idiagnl); kfree(inet_diag_table); } module_init(inet_diag_init); module_exit(inet_diag_exit); MODULE_LICENSE("GPL"); -MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2 /* AF_INET */); -MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 10 /* AF_INET6 */); +MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_INET_DIAG); diff --git a/trunk/net/ipv4/ip_gre.c b/trunk/net/ipv4/ip_gre.c index 2b53a1f7abf6..fe070c1593ab 100644 --- a/trunk/net/ipv4/ip_gre.c +++ b/trunk/net/ipv4/ip_gre.c @@ -46,7 +46,7 @@ #include #include -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #include #include #include @@ -729,7 +729,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev if ((dst = rt->rt_gateway) == 0) goto tx_error_icmp; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (skb->protocol == htons(ETH_P_IPV6)) { struct neighbour *neigh = dst_get_neighbour_noref(skb_dst(skb)); const struct in6_addr *addr6; @@ -799,7 +799,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev goto tx_error; } } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (skb->protocol == htons(ETH_P_IPV6)) { struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb); @@ -875,7 +875,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev if ((iph->ttl = tiph->ttl) == 0) { if (skb->protocol == htons(ETH_P_IP)) iph->ttl = old_iph->ttl; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (skb->protocol == htons(ETH_P_IPV6)) iph->ttl = ((const struct ipv6hdr *)old_iph)->hop_limit; #endif diff --git a/trunk/net/ipv4/ip_sockglue.c b/trunk/net/ipv4/ip_sockglue.c index 8aa87c19fa00..80d5fa450210 100644 --- a/trunk/net/ipv4/ip_sockglue.c +++ b/trunk/net/ipv4/ip_sockglue.c @@ -37,7 +37,7 @@ #include #include #include -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #include #endif @@ -508,7 +508,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, sock_owned_by_user(sk)); if (inet->is_icsk) { struct inet_connection_sock *icsk = inet_csk(sk); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if (sk->sk_family == PF_INET || (!((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE)) && @@ -519,7 +519,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, if (opt) icsk->icsk_ext_hdr_len += opt->opt.optlen; icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) } #endif } diff --git a/trunk/net/ipv4/ipip.c b/trunk/net/ipv4/ipip.c index 413ed1ba7a5a..94906908a416 100644 --- a/trunk/net/ipv4/ipip.c +++ b/trunk/net/ipv4/ipip.c @@ -285,8 +285,6 @@ static struct ip_tunnel * ipip_tunnel_locate(struct net *net, if (register_netdevice(dev) < 0) goto failed_free; - strcpy(nt->parms.name, dev->name); - dev_hold(dev); ipip_tunnel_link(ipn, nt); return nt; @@ -761,6 +759,7 @@ static int ipip_tunnel_init(struct net_device *dev) struct ip_tunnel *tunnel = netdev_priv(dev); tunnel->dev = dev; + strcpy(tunnel->parms.name, dev->name); memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); @@ -826,7 +825,6 @@ static void ipip_destroy_tunnels(struct ipip_net *ipn, struct list_head *head) static int __net_init ipip_init_net(struct net *net) { struct ipip_net *ipn = net_generic(net, ipip_net_id); - struct ip_tunnel *t; int err; ipn->tunnels[0] = ipn->tunnels_wc; @@ -850,9 +848,6 @@ static int __net_init ipip_init_net(struct net *net) if ((err = register_netdev(ipn->fb_tunnel_dev))) goto err_reg_dev; - t = netdev_priv(ipn->fb_tunnel_dev); - - strcpy(t->parms.name, ipn->fb_tunnel_dev->name); return 0; err_reg_dev: diff --git a/trunk/net/ipv4/proc.c b/trunk/net/ipv4/proc.c index 3569d8ecaeac..961eed4f510a 100644 --- a/trunk/net/ipv4/proc.c +++ b/trunk/net/ipv4/proc.c @@ -56,17 +56,17 @@ static int sockstat_seq_show(struct seq_file *seq, void *v) local_bh_disable(); orphans = percpu_counter_sum_positive(&tcp_orphan_count); - sockets = proto_sockets_allocated_sum_positive(&tcp_prot); + sockets = percpu_counter_sum_positive(&tcp_sockets_allocated); local_bh_enable(); socket_seq_show(seq); seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %ld\n", sock_prot_inuse_get(net, &tcp_prot), orphans, tcp_death_row.tw_count, sockets, - proto_memory_allocated(&tcp_prot)); + atomic_long_read(&tcp_memory_allocated)); seq_printf(seq, "UDP: inuse %d mem %ld\n", sock_prot_inuse_get(net, &udp_prot), - proto_memory_allocated(&udp_prot)); + atomic_long_read(&udp_memory_allocated)); seq_printf(seq, "UDPLITE: inuse %d\n", sock_prot_inuse_get(net, &udplite_prot)); seq_printf(seq, "RAW: inuse %d\n", diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index f30112f7559a..90402a2a26a9 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -111,7 +111,7 @@ #include #define RT_FL_TOS(oldflp4) \ - ((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)) + ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))) #define IP_MAX_MTU 0xFFF0 @@ -1304,7 +1304,7 @@ static void rt_del(unsigned hash, struct rtable *rt) spin_unlock_bh(rt_hash_lock_addr(hash)); } -static void check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) +static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) { struct rtable *rt = (struct rtable *) dst; __be32 orig_gw = rt->rt_gateway; @@ -1315,19 +1315,21 @@ static void check_peer_redir(struct dst_entry *dst, struct inet_peer *peer) rt->rt_gateway = peer->redirect_learned.a4; n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway); - if (IS_ERR(n)) { - rt->rt_gateway = orig_gw; - return; - } + if (IS_ERR(n)) + return PTR_ERR(n); old_n = xchg(&rt->dst._neighbour, n); if (old_n) neigh_release(old_n); - if (!(n->nud_state & NUD_VALID)) { - neigh_event_send(n, NULL); + if (!n || !(n->nud_state & NUD_VALID)) { + if (n) + neigh_event_send(n, NULL); + rt->rt_gateway = orig_gw; + return -EAGAIN; } else { rt->rt_flags |= RTCF_REDIRECTED; call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n); } + return 0; } /* called in rcu_read_lock() section */ @@ -1685,7 +1687,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) } -static void ipv4_validate_peer(struct rtable *rt) +static struct rtable *ipv4_validate_peer(struct rtable *rt) { if (rt->rt_peer_genid != rt_peer_genid()) { struct inet_peer *peer; @@ -1700,12 +1702,15 @@ static void ipv4_validate_peer(struct rtable *rt) if (peer->redirect_genid != redirect_genid) peer->redirect_learned.a4 = 0; if (peer->redirect_learned.a4 && - peer->redirect_learned.a4 != rt->rt_gateway) - check_peer_redir(&rt->dst, peer); + peer->redirect_learned.a4 != rt->rt_gateway) { + if (check_peer_redir(&rt->dst, peer)) + return NULL; + } } rt->rt_peer_genid = rt_peer_genid(); } + return rt; } static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) @@ -1714,7 +1719,7 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) if (rt_is_expired(rt)) return NULL; - ipv4_validate_peer(rt); + dst = (struct dst_entry *) ipv4_validate_peer(rt); return dst; } @@ -2369,7 +2374,9 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_mark == skb->mark && net_eq(dev_net(rth->dst.dev), net) && !rt_is_expired(rth)) { - ipv4_validate_peer(rth); + rth = ipv4_validate_peer(rth); + if (!rth) + continue; if (noref) { dst_use_noref(&rth->dst, jiffies); skb_dst_set_noref(skb, &rth->dst); @@ -2428,11 +2435,11 @@ EXPORT_SYMBOL(ip_route_input_common); static struct rtable *__mkroute_output(const struct fib_result *res, const struct flowi4 *fl4, __be32 orig_daddr, __be32 orig_saddr, - int orig_oif, __u8 orig_rtos, - struct net_device *dev_out, + int orig_oif, struct net_device *dev_out, unsigned int flags) { struct fib_info *fi = res->fi; + u32 tos = RT_FL_TOS(fl4); struct in_device *in_dev; u16 type = res->type; struct rtable *rth; @@ -2483,7 +2490,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rth->rt_genid = rt_genid(dev_net(dev_out)); rth->rt_flags = flags; rth->rt_type = type; - rth->rt_key_tos = orig_rtos; + rth->rt_key_tos = tos; rth->rt_dst = fl4->daddr; rth->rt_src = fl4->saddr; rth->rt_route_iif = 0; @@ -2533,7 +2540,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4) { struct net_device *dev_out = NULL; - __u8 tos = RT_FL_TOS(fl4); + u32 tos = RT_FL_TOS(fl4); unsigned int flags = 0; struct fib_result res; struct rtable *rth; @@ -2709,7 +2716,7 @@ static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4) make_route: rth = __mkroute_output(&res, fl4, orig_daddr, orig_saddr, orig_oif, - tos, dev_out, flags); + dev_out, flags); if (!IS_ERR(rth)) { unsigned int hash; @@ -2745,7 +2752,9 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4) (IPTOS_RT_MASK | RTO_ONLINK)) && net_eq(dev_net(rth->dst.dev), net) && !rt_is_expired(rth)) { - ipv4_validate_peer(rth); + rth = ipv4_validate_peer(rth); + if (!rth) + continue; dst_use(&rth->dst, jiffies); RT_CACHE_STAT_INC(out_hit); rcu_read_unlock_bh(); diff --git a/trunk/net/ipv4/sysctl_net_ipv4.c b/trunk/net/ipv4/sysctl_net_ipv4.c index 4aa7e9dc0cbb..69fd7201129a 100644 --- a/trunk/net/ipv4/sysctl_net_ipv4.c +++ b/trunk/net/ipv4/sysctl_net_ipv4.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -24,7 +23,6 @@ #include #include #include -#include static int zero; static int tcp_retr1_max = 255; @@ -75,7 +73,7 @@ static int ipv4_local_port_range(ctl_table *table, int write, } -static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, gid_t *high) +void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, gid_t *high) { gid_t *data = table->data; unsigned seq; @@ -88,7 +86,7 @@ static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, } /* Update system visible IP port range */ -static void set_ping_group_range(struct ctl_table *table, gid_t range[2]) +static void set_ping_group_range(struct ctl_table *table, int range[2]) { gid_t *data = table->data; write_seqlock(&sysctl_local_ports.lock); @@ -176,49 +174,6 @@ static int proc_allowed_congestion_control(ctl_table *ctl, return ret; } -static int ipv4_tcp_mem(ctl_table *ctl, int write, - void __user *buffer, size_t *lenp, - loff_t *ppos) -{ - int ret; - unsigned long vec[3]; - struct net *net = current->nsproxy->net_ns; -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM - struct mem_cgroup *memcg; -#endif - - ctl_table tmp = { - .data = &vec, - .maxlen = sizeof(vec), - .mode = ctl->mode, - }; - - if (!write) { - ctl->data = &net->ipv4.sysctl_tcp_mem; - return proc_doulongvec_minmax(ctl, write, buffer, lenp, ppos); - } - - ret = proc_doulongvec_minmax(&tmp, write, buffer, lenp, ppos); - if (ret) - return ret; - -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM - rcu_read_lock(); - memcg = mem_cgroup_from_task(current); - - tcp_prot_mem(memcg, vec[0], 0); - tcp_prot_mem(memcg, vec[1], 1); - tcp_prot_mem(memcg, vec[2], 2); - rcu_read_unlock(); -#endif - - net->ipv4.sysctl_tcp_mem[0] = vec[0]; - net->ipv4.sysctl_tcp_mem[1] = vec[1]; - net->ipv4.sysctl_tcp_mem[2] = vec[2]; - - return 0; -} - static struct ctl_table ipv4_table[] = { { .procname = "tcp_timestamps", @@ -477,6 +432,13 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "tcp_mem", + .data = &sysctl_tcp_mem, + .maxlen = sizeof(sysctl_tcp_mem), + .mode = 0644, + .proc_handler = proc_doulongvec_minmax + }, { .procname = "tcp_wmem", .data = &sysctl_tcp_wmem, @@ -759,12 +721,6 @@ static struct ctl_table ipv4_net_table[] = { .mode = 0644, .proc_handler = ipv4_ping_group_range, }, - { - .procname = "tcp_mem", - .maxlen = sizeof(init_net.ipv4.sysctl_tcp_mem), - .mode = 0644, - .proc_handler = ipv4_tcp_mem, - }, { } }; @@ -778,7 +734,6 @@ EXPORT_SYMBOL_GPL(net_ipv4_ctl_path); static __net_init int ipv4_sysctl_init_net(struct net *net) { struct ctl_table *table; - unsigned long limit; table = ipv4_net_table; if (!net_eq(net, &init_net)) { @@ -814,12 +769,6 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) net->ipv4.sysctl_rt_cache_rebuild_count = 4; - limit = nr_free_buffer_pages() / 8; - limit = max(limit, 128UL); - net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3; - net->ipv4.sysctl_tcp_mem[1] = limit; - net->ipv4.sysctl_tcp_mem[2] = net->ipv4.sysctl_tcp_mem[0] * 2; - net->ipv4.ipv4_hdr = register_net_sysctl_table(net, net_ipv4_ctl_path, table); if (net->ipv4.ipv4_hdr == NULL) diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index 9bcdec3ad772..43dfccce62e9 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -282,9 +282,11 @@ int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; struct percpu_counter tcp_orphan_count; EXPORT_SYMBOL_GPL(tcp_orphan_count); +long sysctl_tcp_mem[3] __read_mostly; int sysctl_tcp_wmem[3] __read_mostly; int sysctl_tcp_rmem[3] __read_mostly; +EXPORT_SYMBOL(sysctl_tcp_mem); EXPORT_SYMBOL(sysctl_tcp_rmem); EXPORT_SYMBOL(sysctl_tcp_wmem); @@ -3276,9 +3278,14 @@ void __init tcp_init(void) sysctl_tcp_max_orphans = cnt / 2; sysctl_max_syn_backlog = max(128, cnt / 256); + limit = nr_free_buffer_pages() / 8; + limit = max(limit, 128UL); + sysctl_tcp_mem[0] = limit / 4 * 3; + sysctl_tcp_mem[1] = limit; + sysctl_tcp_mem[2] = sysctl_tcp_mem[0] * 2; + /* Set per-socket limits to no more than 1/128 the pressure threshold */ - limit = ((unsigned long)init_net.ipv4.sysctl_tcp_mem[1]) - << (PAGE_SHIFT - 7); + limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7); max_share = min(4UL*1024*1024, limit); sysctl_tcp_wmem[0] = SK_MEM_QUANTUM; diff --git a/trunk/net/ipv4/tcp_diag.c b/trunk/net/ipv4/tcp_diag.c index 8cd357a8be79..939edb3b8e4d 100644 --- a/trunk/net/ipv4/tcp_diag.c +++ b/trunk/net/ipv4/tcp_diag.c @@ -34,23 +34,11 @@ static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, tcp_get_info(sk, info); } -static void tcp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, struct nlattr *bc) -{ - inet_diag_dump_icsk(&tcp_hashinfo, skb, cb, r, bc); -} - -static int tcp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, - struct inet_diag_req *req) -{ - return inet_diag_dump_one_icsk(&tcp_hashinfo, in_skb, nlh, req); -} - static const struct inet_diag_handler tcp_diag_handler = { - .dump = tcp_diag_dump, - .dump_one = tcp_diag_dump_one, + .idiag_hashinfo = &tcp_hashinfo, .idiag_get_info = tcp_diag_get_info, - .idiag_type = IPPROTO_TCP, + .idiag_type = TCPDIAG_GETSOCK, + .idiag_info_size = sizeof(struct tcp_info), }; static int __init tcp_diag_init(void) @@ -66,4 +54,4 @@ static void __exit tcp_diag_exit(void) module_init(tcp_diag_init); module_exit(tcp_diag_exit); MODULE_LICENSE("GPL"); -MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-6 /* AF_INET - IPPROTO_TCP */); +MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_INET_DIAG, TCPDIAG_GETSOCK); diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index f131d92d25ee..0cbb44076cfa 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -322,7 +322,7 @@ static void tcp_grow_window(struct sock *sk, const struct sk_buff *skb) /* Check #1 */ if (tp->rcv_ssthresh < tp->window_clamp && (int)tp->rcv_ssthresh < tcp_space(sk) && - !sk_under_memory_pressure(sk)) { + !tcp_memory_pressure) { int incr; /* Check #2. Increase window, if skb with such overhead @@ -411,8 +411,8 @@ static void tcp_clamp_window(struct sock *sk) if (sk->sk_rcvbuf < sysctl_tcp_rmem[2] && !(sk->sk_userlocks & SOCK_RCVBUF_LOCK) && - !sk_under_memory_pressure(sk) && - sk_memory_allocated(sk) < sk_prot_mem_limits(sk, 0)) { + !tcp_memory_pressure && + atomic_long_read(&tcp_memory_allocated) < sysctl_tcp_mem[0]) { sk->sk_rcvbuf = min(atomic_read(&sk->sk_rmem_alloc), sysctl_tcp_rmem[2]); } @@ -2663,7 +2663,7 @@ static void DBGUNDO(struct sock *sk, const char *msg) tp->snd_ssthresh, tp->prior_ssthresh, tp->packets_out); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (sk->sk_family == AF_INET6) { struct ipv6_pinfo *np = inet6_sk(sk); printk(KERN_DEBUG "Undo %s %pI6/%u c%u l%u ss%u/%u p%u\n", @@ -4866,7 +4866,7 @@ static int tcp_prune_queue(struct sock *sk) if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) tcp_clamp_window(sk); - else if (sk_under_memory_pressure(sk)) + else if (tcp_memory_pressure) tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss); tcp_collapse_ofo_queue(sk); @@ -4932,11 +4932,11 @@ static int tcp_should_expand_sndbuf(const struct sock *sk) return 0; /* If we are under global TCP memory pressure, do not expand. */ - if (sk_under_memory_pressure(sk)) + if (tcp_memory_pressure) return 0; /* If we are under soft global TCP memory pressure, do not expand. */ - if (sk_memory_allocated(sk) >= sk_prot_mem_limits(sk, 0)) + if (atomic_long_read(&tcp_memory_allocated) >= sysctl_tcp_mem[0]) return 0; /* If we filled the congestion window, do not expand. */ diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index 1eb4ad57670e..c4b8b09db9f5 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -73,7 +73,6 @@ #include #include #include -#include #include #include @@ -1918,8 +1917,7 @@ static int tcp_v4_init_sock(struct sock *sk) sk->sk_rcvbuf = sysctl_tcp_rmem[1]; local_bh_disable(); - sock_update_memcg(sk); - sk_sockets_allocated_inc(sk); + percpu_counter_inc(&tcp_sockets_allocated); local_bh_enable(); return 0; @@ -1975,8 +1973,7 @@ void tcp_v4_destroy_sock(struct sock *sk) tp->cookie_values = NULL; } - sk_sockets_allocated_dec(sk); - sock_release_memcg(sk); + percpu_counter_dec(&tcp_sockets_allocated); } EXPORT_SYMBOL(tcp_v4_destroy_sock); @@ -2623,6 +2620,7 @@ struct proto tcp_prot = { .orphan_count = &tcp_orphan_count, .memory_allocated = &tcp_memory_allocated, .memory_pressure = &tcp_memory_pressure, + .sysctl_mem = sysctl_tcp_mem, .sysctl_wmem = sysctl_tcp_wmem, .sysctl_rmem = sysctl_tcp_rmem, .max_header = MAX_TCP_HEADER, @@ -2636,14 +2634,10 @@ struct proto tcp_prot = { .compat_setsockopt = compat_tcp_setsockopt, .compat_getsockopt = compat_tcp_getsockopt, #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM - .init_cgroup = tcp_init_cgroup, - .destroy_cgroup = tcp_destroy_cgroup, - .proto_cgroup = tcp_proto_cgroup, -#endif }; EXPORT_SYMBOL(tcp_prot); + static int __net_init tcp_sk_init(struct net *net) { return inet_ctl_sock_create(&net->ipv4.tcp_sock, diff --git a/trunk/net/ipv4/tcp_memcontrol.c b/trunk/net/ipv4/tcp_memcontrol.c deleted file mode 100644 index 7fed04f875c1..000000000000 --- a/trunk/net/ipv4/tcp_memcontrol.c +++ /dev/null @@ -1,272 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -static u64 tcp_cgroup_read(struct cgroup *cont, struct cftype *cft); -static int tcp_cgroup_write(struct cgroup *cont, struct cftype *cft, - const char *buffer); -static int tcp_cgroup_reset(struct cgroup *cont, unsigned int event); - -static struct cftype tcp_files[] = { - { - .name = "kmem.tcp.limit_in_bytes", - .write_string = tcp_cgroup_write, - .read_u64 = tcp_cgroup_read, - .private = RES_LIMIT, - }, - { - .name = "kmem.tcp.usage_in_bytes", - .read_u64 = tcp_cgroup_read, - .private = RES_USAGE, - }, - { - .name = "kmem.tcp.failcnt", - .private = RES_FAILCNT, - .trigger = tcp_cgroup_reset, - .read_u64 = tcp_cgroup_read, - }, - { - .name = "kmem.tcp.max_usage_in_bytes", - .private = RES_MAX_USAGE, - .trigger = tcp_cgroup_reset, - .read_u64 = tcp_cgroup_read, - }, -}; - -static inline struct tcp_memcontrol *tcp_from_cgproto(struct cg_proto *cg_proto) -{ - return container_of(cg_proto, struct tcp_memcontrol, cg_proto); -} - -static void memcg_tcp_enter_memory_pressure(struct sock *sk) -{ - if (sk->sk_cgrp->memory_pressure) - *sk->sk_cgrp->memory_pressure = 1; -} -EXPORT_SYMBOL(memcg_tcp_enter_memory_pressure); - -int tcp_init_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss) -{ - /* - * The root cgroup does not use res_counters, but rather, - * rely on the data already collected by the network - * subsystem - */ - struct res_counter *res_parent = NULL; - struct cg_proto *cg_proto, *parent_cg; - struct tcp_memcontrol *tcp; - struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); - struct mem_cgroup *parent = parent_mem_cgroup(memcg); - struct net *net = current->nsproxy->net_ns; - - cg_proto = tcp_prot.proto_cgroup(memcg); - if (!cg_proto) - goto create_files; - - tcp = tcp_from_cgproto(cg_proto); - - tcp->tcp_prot_mem[0] = net->ipv4.sysctl_tcp_mem[0]; - tcp->tcp_prot_mem[1] = net->ipv4.sysctl_tcp_mem[1]; - tcp->tcp_prot_mem[2] = net->ipv4.sysctl_tcp_mem[2]; - tcp->tcp_memory_pressure = 0; - - parent_cg = tcp_prot.proto_cgroup(parent); - if (parent_cg) - res_parent = parent_cg->memory_allocated; - - res_counter_init(&tcp->tcp_memory_allocated, res_parent); - percpu_counter_init(&tcp->tcp_sockets_allocated, 0); - - cg_proto->enter_memory_pressure = memcg_tcp_enter_memory_pressure; - cg_proto->memory_pressure = &tcp->tcp_memory_pressure; - cg_proto->sysctl_mem = tcp->tcp_prot_mem; - cg_proto->memory_allocated = &tcp->tcp_memory_allocated; - cg_proto->sockets_allocated = &tcp->tcp_sockets_allocated; - cg_proto->memcg = memcg; - -create_files: - return cgroup_add_files(cgrp, ss, tcp_files, - ARRAY_SIZE(tcp_files)); -} -EXPORT_SYMBOL(tcp_init_cgroup); - -void tcp_destroy_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss) -{ - struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); - struct cg_proto *cg_proto; - struct tcp_memcontrol *tcp; - u64 val; - - cg_proto = tcp_prot.proto_cgroup(memcg); - if (!cg_proto) - return; - - tcp = tcp_from_cgproto(cg_proto); - percpu_counter_destroy(&tcp->tcp_sockets_allocated); - - val = res_counter_read_u64(&tcp->tcp_memory_allocated, RES_USAGE); - - if (val != RESOURCE_MAX) - jump_label_dec(&memcg_socket_limit_enabled); -} -EXPORT_SYMBOL(tcp_destroy_cgroup); - -static int tcp_update_limit(struct mem_cgroup *memcg, u64 val) -{ - struct net *net = current->nsproxy->net_ns; - struct tcp_memcontrol *tcp; - struct cg_proto *cg_proto; - u64 old_lim; - int i; - int ret; - - cg_proto = tcp_prot.proto_cgroup(memcg); - if (!cg_proto) - return -EINVAL; - - if (val > RESOURCE_MAX) - val = RESOURCE_MAX; - - tcp = tcp_from_cgproto(cg_proto); - - old_lim = res_counter_read_u64(&tcp->tcp_memory_allocated, RES_LIMIT); - ret = res_counter_set_limit(&tcp->tcp_memory_allocated, val); - if (ret) - return ret; - - for (i = 0; i < 3; i++) - tcp->tcp_prot_mem[i] = min_t(long, val >> PAGE_SHIFT, - net->ipv4.sysctl_tcp_mem[i]); - - if (val == RESOURCE_MAX && old_lim != RESOURCE_MAX) - jump_label_dec(&memcg_socket_limit_enabled); - else if (old_lim == RESOURCE_MAX && val != RESOURCE_MAX) - jump_label_inc(&memcg_socket_limit_enabled); - - return 0; -} - -static int tcp_cgroup_write(struct cgroup *cont, struct cftype *cft, - const char *buffer) -{ - struct mem_cgroup *memcg = mem_cgroup_from_cont(cont); - unsigned long long val; - int ret = 0; - - switch (cft->private) { - case RES_LIMIT: - /* see memcontrol.c */ - ret = res_counter_memparse_write_strategy(buffer, &val); - if (ret) - break; - ret = tcp_update_limit(memcg, val); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -static u64 tcp_read_stat(struct mem_cgroup *memcg, int type, u64 default_val) -{ - struct tcp_memcontrol *tcp; - struct cg_proto *cg_proto; - - cg_proto = tcp_prot.proto_cgroup(memcg); - if (!cg_proto) - return default_val; - - tcp = tcp_from_cgproto(cg_proto); - return res_counter_read_u64(&tcp->tcp_memory_allocated, type); -} - -static u64 tcp_read_usage(struct mem_cgroup *memcg) -{ - struct tcp_memcontrol *tcp; - struct cg_proto *cg_proto; - - cg_proto = tcp_prot.proto_cgroup(memcg); - if (!cg_proto) - return atomic_long_read(&tcp_memory_allocated) << PAGE_SHIFT; - - tcp = tcp_from_cgproto(cg_proto); - return res_counter_read_u64(&tcp->tcp_memory_allocated, RES_USAGE); -} - -static u64 tcp_cgroup_read(struct cgroup *cont, struct cftype *cft) -{ - struct mem_cgroup *memcg = mem_cgroup_from_cont(cont); - u64 val; - - switch (cft->private) { - case RES_LIMIT: - val = tcp_read_stat(memcg, RES_LIMIT, RESOURCE_MAX); - break; - case RES_USAGE: - val = tcp_read_usage(memcg); - break; - case RES_FAILCNT: - case RES_MAX_USAGE: - val = tcp_read_stat(memcg, cft->private, 0); - break; - default: - BUG(); - } - return val; -} - -static int tcp_cgroup_reset(struct cgroup *cont, unsigned int event) -{ - struct mem_cgroup *memcg; - struct tcp_memcontrol *tcp; - struct cg_proto *cg_proto; - - memcg = mem_cgroup_from_cont(cont); - cg_proto = tcp_prot.proto_cgroup(memcg); - if (!cg_proto) - return 0; - tcp = tcp_from_cgproto(cg_proto); - - switch (event) { - case RES_MAX_USAGE: - res_counter_reset_max(&tcp->tcp_memory_allocated); - break; - case RES_FAILCNT: - res_counter_reset_failcnt(&tcp->tcp_memory_allocated); - break; - } - - return 0; -} - -unsigned long long tcp_max_memory(const struct mem_cgroup *memcg) -{ - struct tcp_memcontrol *tcp; - struct cg_proto *cg_proto; - - cg_proto = tcp_prot.proto_cgroup((struct mem_cgroup *)memcg); - if (!cg_proto) - return 0; - - tcp = tcp_from_cgproto(cg_proto); - return res_counter_read_u64(&tcp->tcp_memory_allocated, RES_LIMIT); -} - -void tcp_prot_mem(struct mem_cgroup *memcg, long val, int idx) -{ - struct tcp_memcontrol *tcp; - struct cg_proto *cg_proto; - - cg_proto = tcp_prot.proto_cgroup(memcg); - if (!cg_proto) - return; - - tcp = tcp_from_cgproto(cg_proto); - - tcp->tcp_prot_mem[idx] = val; -} diff --git a/trunk/net/ipv4/tcp_minisocks.c b/trunk/net/ipv4/tcp_minisocks.c index 550e755747e0..9dc146e5ed65 100644 --- a/trunk/net/ipv4/tcp_minisocks.c +++ b/trunk/net/ipv4/tcp_minisocks.c @@ -336,7 +336,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) tcptw->tw_ts_recent = tp->rx_opt.ts_recent; tcptw->tw_ts_recent_stamp = tp->rx_opt.ts_recent_stamp; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if (tw->tw_family == PF_INET6) { struct ipv6_pinfo *np = inet6_sk(sk); struct inet6_timewait_sock *tw6; diff --git a/trunk/net/ipv4/tcp_output.c b/trunk/net/ipv4/tcp_output.c index 8c8de2780c7a..cf3068038942 100644 --- a/trunk/net/ipv4/tcp_output.c +++ b/trunk/net/ipv4/tcp_output.c @@ -1922,7 +1922,7 @@ u32 __tcp_select_window(struct sock *sk) if (free_space < (full_space >> 1)) { icsk->icsk_ack.quick = 0; - if (sk_under_memory_pressure(sk)) + if (tcp_memory_pressure) tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss); diff --git a/trunk/net/ipv4/tcp_timer.c b/trunk/net/ipv4/tcp_timer.c index 40a41f077981..2e0f0af76c19 100644 --- a/trunk/net/ipv4/tcp_timer.c +++ b/trunk/net/ipv4/tcp_timer.c @@ -261,7 +261,7 @@ static void tcp_delack_timer(unsigned long data) } out: - if (sk_under_memory_pressure(sk)) + if (tcp_memory_pressure) sk_mem_reclaim(sk); out_unlock: bh_unlock_sock(sk); @@ -340,7 +340,7 @@ void tcp_retransmit_timer(struct sock *sk) &inet->inet_daddr, ntohs(inet->inet_dport), inet->inet_num, tp->snd_una, tp->snd_nxt); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) else if (sk->sk_family == AF_INET6) { struct ipv6_pinfo *np = inet6_sk(sk); LIMIT_NETDEBUG(KERN_DEBUG "TCP: Peer %pI6:%u/%u unexpectedly shrunk window %u:%u (repaired)\n", diff --git a/trunk/net/ipv4/tunnel4.c b/trunk/net/ipv4/tunnel4.c index 01775983b997..ac3b3ee4b07c 100644 --- a/trunk/net/ipv4/tunnel4.c +++ b/trunk/net/ipv4/tunnel4.c @@ -105,7 +105,7 @@ static int tunnel4_rcv(struct sk_buff *skb) return 0; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static int tunnel64_rcv(struct sk_buff *skb) { struct xfrm_tunnel *handler; @@ -134,7 +134,7 @@ static void tunnel4_err(struct sk_buff *skb, u32 info) break; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static void tunnel64_err(struct sk_buff *skb, u32 info) { struct xfrm_tunnel *handler; @@ -152,7 +152,7 @@ static const struct net_protocol tunnel4_protocol = { .netns_ok = 1, }; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static const struct net_protocol tunnel64_protocol = { .handler = tunnel64_rcv, .err_handler = tunnel64_err, @@ -167,7 +167,7 @@ static int __init tunnel4_init(void) printk(KERN_ERR "tunnel4 init: can't add protocol\n"); return -EAGAIN; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) { printk(KERN_ERR "tunnel64 init: can't add protocol\n"); inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP); @@ -179,7 +179,7 @@ static int __init tunnel4_init(void) static void __exit tunnel4_fini(void) { -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6)) printk(KERN_ERR "tunnel64 close: can't remove protocol\n"); #endif diff --git a/trunk/net/ipv4/udp.c b/trunk/net/ipv4/udp.c index 5d075b5f70fc..ad481b32f1e3 100644 --- a/trunk/net/ipv4/udp.c +++ b/trunk/net/ipv4/udp.c @@ -445,7 +445,7 @@ static struct sock *udp4_lib_lookup2(struct net *net, /* UDP is nearly always wildcards out the wazoo, it makes no sense to try * harder than this. -DaveM */ -struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, +static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, __be32 daddr, __be16 dport, int dif, struct udp_table *udptable) { @@ -512,7 +512,6 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, rcu_read_unlock(); return result; } -EXPORT_SYMBOL_GPL(__udp4_lib_lookup); static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb, __be16 sport, __be16 dport, diff --git a/trunk/net/ipv4/udp_diag.c b/trunk/net/ipv4/udp_diag.c deleted file mode 100644 index 69f8a7ca63dd..000000000000 --- a/trunk/net/ipv4/udp_diag.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * udp_diag.c Module for monitoring UDP transport protocols sockets. - * - * Authors: Pavel Emelyanov, - * - * 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 - -static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, - struct netlink_callback *cb, struct inet_diag_req *req, - struct nlattr *bc) -{ - if (!inet_diag_bc_sk(bc, sk)) - return 0; - - return inet_sk_diag_fill(sk, NULL, skb, req, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); -} - -static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, - const struct nlmsghdr *nlh, struct inet_diag_req *req) -{ - int err = -EINVAL; - struct sock *sk; - struct sk_buff *rep; - - if (req->sdiag_family == AF_INET) - sk = __udp4_lib_lookup(&init_net, - req->id.idiag_src[0], req->id.idiag_sport, - req->id.idiag_dst[0], req->id.idiag_dport, - req->id.idiag_if, tbl); -#if IS_ENABLED(CONFIG_IPV6) - else if (req->sdiag_family == AF_INET6) - sk = __udp6_lib_lookup(&init_net, - (struct in6_addr *)req->id.idiag_src, - req->id.idiag_sport, - (struct in6_addr *)req->id.idiag_dst, - req->id.idiag_dport, - req->id.idiag_if, tbl); -#endif - else - goto out_nosk; - - err = -ENOENT; - if (sk == NULL) - goto out_nosk; - - err = sock_diag_check_cookie(sk, req->id.idiag_cookie); - if (err) - goto out; - - err = -ENOMEM; - rep = alloc_skb(NLMSG_SPACE((sizeof(struct inet_diag_msg) + - sizeof(struct inet_diag_meminfo) + - 64)), GFP_KERNEL); - if (!rep) - goto out; - - err = inet_sk_diag_fill(sk, NULL, rep, req, - NETLINK_CB(in_skb).pid, - nlh->nlmsg_seq, 0, nlh); - if (err < 0) { - WARN_ON(err == -EMSGSIZE); - kfree_skb(rep); - goto out; - } - err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, - MSG_DONTWAIT); - if (err > 0) - err = 0; -out: - if (sk) - sock_put(sk); -out_nosk: - return err; -} - -static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, struct nlattr *bc) -{ - int num, s_num, slot, s_slot; - - s_slot = cb->args[0]; - num = s_num = cb->args[1]; - - for (slot = s_slot; slot <= table->mask; num = s_num = 0, slot++) { - struct sock *sk; - struct hlist_nulls_node *node; - struct udp_hslot *hslot = &table->hash[slot]; - - if (hlist_nulls_empty(&hslot->head)) - continue; - - spin_lock_bh(&hslot->lock); - sk_nulls_for_each(sk, node, &hslot->head) { - struct inet_sock *inet = inet_sk(sk); - - if (num < s_num) - goto next; - if (!(r->idiag_states & (1 << sk->sk_state))) - goto next; - if (r->sdiag_family != AF_UNSPEC && - sk->sk_family != r->sdiag_family) - goto next; - if (r->id.idiag_sport != inet->inet_sport && - r->id.idiag_sport) - goto next; - if (r->id.idiag_dport != inet->inet_dport && - r->id.idiag_dport) - goto next; - - if (sk_diag_dump(sk, skb, cb, r, bc) < 0) { - spin_unlock_bh(&hslot->lock); - goto done; - } -next: - num++; - } - spin_unlock_bh(&hslot->lock); - } -done: - cb->args[0] = slot; - cb->args[1] = num; -} - -static void udp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, struct nlattr *bc) -{ - udp_dump(&udp_table, skb, cb, r, bc); -} - -static int udp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, - struct inet_diag_req *req) -{ - return udp_dump_one(&udp_table, in_skb, nlh, req); -} - -static const struct inet_diag_handler udp_diag_handler = { - .dump = udp_diag_dump, - .dump_one = udp_diag_dump_one, - .idiag_type = IPPROTO_UDP, -}; - -static void udplite_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, - struct inet_diag_req *r, struct nlattr *bc) -{ - udp_dump(&udplite_table, skb, cb, r, bc); -} - -static int udplite_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh, - struct inet_diag_req *req) -{ - return udp_dump_one(&udplite_table, in_skb, nlh, req); -} - -static const struct inet_diag_handler udplite_diag_handler = { - .dump = udplite_diag_dump, - .dump_one = udplite_diag_dump_one, - .idiag_type = IPPROTO_UDPLITE, -}; - -static int __init udp_diag_init(void) -{ - int err; - - err = inet_diag_register(&udp_diag_handler); - if (err) - goto out; - err = inet_diag_register(&udplite_diag_handler); - if (err) - goto out_lite; -out: - return err; -out_lite: - inet_diag_unregister(&udp_diag_handler); - goto out; -} - -static void __exit udp_diag_exit(void) -{ - inet_diag_unregister(&udplite_diag_handler); - inet_diag_unregister(&udp_diag_handler); -} - -module_init(udp_diag_init); -module_exit(udp_diag_exit); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-17 /* AF_INET - IPPROTO_UDP */); -MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2-136 /* AF_INET - IPPROTO_UDPLITE */); diff --git a/trunk/net/ipv4/xfrm4_tunnel.c b/trunk/net/ipv4/xfrm4_tunnel.c index 9247d9d70e9d..82806455e859 100644 --- a/trunk/net/ipv4/xfrm4_tunnel.c +++ b/trunk/net/ipv4/xfrm4_tunnel.c @@ -64,7 +64,7 @@ static struct xfrm_tunnel xfrm_tunnel_handler __read_mostly = { .priority = 2, }; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static struct xfrm_tunnel xfrm64_tunnel_handler __read_mostly = { .handler = xfrm_tunnel_rcv, .err_handler = xfrm_tunnel_err, @@ -84,7 +84,7 @@ static int __init ipip_init(void) xfrm_unregister_type(&ipip_type, AF_INET); return -EAGAIN; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) { printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET6\n"); xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET); @@ -97,7 +97,7 @@ static int __init ipip_init(void) static void __exit ipip_fini(void) { -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6)) printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET6\n"); #endif diff --git a/trunk/net/ipv6/addrconf.c b/trunk/net/ipv6/addrconf.c index 59a9d0e1da56..058cc222b3f1 100644 --- a/trunk/net/ipv6/addrconf.c +++ b/trunk/net/ipv6/addrconf.c @@ -630,7 +630,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, goto out; } - rt = addrconf_dst_alloc(idev, addr, false); + rt = addrconf_dst_alloc(idev, addr, 0); if (IS_ERR(rt)) { err = PTR_ERR(rt); goto out; @@ -1805,8 +1805,7 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) return ERR_PTR(-EACCES); /* Add default multicast route */ - if (!(dev->flags & IFF_LOOPBACK)) - addrconf_add_mroute(dev); + addrconf_add_mroute(dev); /* Add link local route */ addrconf_add_lroute(dev); diff --git a/trunk/net/ipv6/af_inet6.c b/trunk/net/ipv6/af_inet6.c index 273f48d1df2e..7694c82e629d 100644 --- a/trunk/net/ipv6/af_inet6.c +++ b/trunk/net/ipv6/af_inet6.c @@ -1116,8 +1116,6 @@ static int __init inet6_init(void) if (err) goto static_sysctl_fail; #endif - tcpv6_prot.sysctl_mem = init_net.ipv4.sysctl_tcp_mem; - /* * ipngwg API draft makes clear that the correct semantics * for TCP and UDP is to consider one TCP and UDP instance diff --git a/trunk/net/ipv6/anycast.c b/trunk/net/ipv6/anycast.c index cc540f9ad130..fc1cdcd7041a 100644 --- a/trunk/net/ipv6/anycast.c +++ b/trunk/net/ipv6/anycast.c @@ -289,7 +289,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr) goto out; } - rt = addrconf_dst_alloc(idev, addr, true); + rt = addrconf_dst_alloc(idev, addr, 1); if (IS_ERR(rt)) { kfree(aca); err = PTR_ERR(rt); diff --git a/trunk/net/ipv6/mcast.c b/trunk/net/ipv6/mcast.c index ea34d58e836d..518cbb90c44b 100644 --- a/trunk/net/ipv6/mcast.c +++ b/trunk/net/ipv6/mcast.c @@ -1410,11 +1410,18 @@ static void mld_sendpack(struct sk_buff *skb) csum_partial(skb_transport_header(skb), mldlen, 0)); + dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); + + if (!dst) { + err = -ENOMEM; + goto err_out; + } + icmpv6_flow_init(net->ipv6.igmp_sk, &fl6, ICMPV6_MLD2_REPORT, &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, skb->dev->ifindex); - dst = icmp6_dst_alloc(skb->dev, NULL, &fl6); + dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); err = 0; if (IS_ERR(dst)) { err = PTR_ERR(dst); @@ -1778,10 +1785,17 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) rcu_read_lock(); idev = __in6_dev_get(skb->dev); + dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr); + if (!dst) { + err = -ENOMEM; + goto err_out; + } + icmpv6_flow_init(sk, &fl6, type, &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, skb->dev->ifindex); - dst = icmp6_dst_alloc(skb->dev, NULL, &fl6); + + dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); if (IS_ERR(dst)) { err = PTR_ERR(dst); goto err_out; diff --git a/trunk/net/ipv6/ndisc.c b/trunk/net/ipv6/ndisc.c index f3e50c29add4..e72c8af85781 100644 --- a/trunk/net/ipv6/ndisc.c +++ b/trunk/net/ipv6/ndisc.c @@ -516,7 +516,14 @@ void ndisc_send_skb(struct sk_buff *skb, type = icmp6h->icmp6_type; icmpv6_flow_init(sk, &fl6, type, saddr, daddr, dev->ifindex); - dst = icmp6_dst_alloc(dev, neigh, &fl6); + + dst = icmp6_dst_alloc(dev, neigh, daddr); + if (!dst) { + kfree_skb(skb); + return; + } + + dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); if (IS_ERR(dst)) { kfree_skb(skb); return; diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index ad438546d915..09412baf1ca6 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -728,7 +728,7 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, int attempts = !in_softirq(); if (!(rt->rt6i_flags & RTF_GATEWAY)) { - if (ort->rt6i_dst.plen != 128 && + if (rt->rt6i_dst.plen != 128 && ipv6_addr_equal(&ort->rt6i_dst.addr, daddr)) rt->rt6i_flags |= RTF_ANYCAST; rt->rt6i_gateway = *daddr; @@ -1068,9 +1068,8 @@ static DEFINE_SPINLOCK(icmp6_dst_lock); struct dst_entry *icmp6_dst_alloc(struct net_device *dev, struct neighbour *neigh, - struct flowi6 *fl6) + const struct in6_addr *addr) { - struct dst_entry *dst; struct rt6_info *rt; struct inet6_dev *idev = in6_dev_get(dev); struct net *net = dev_net(dev); @@ -1081,25 +1080,22 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev, 0); if (unlikely(!rt)) { in6_dev_put(idev); - dst = ERR_PTR(-ENOMEM); goto out; } if (neigh) neigh_hold(neigh); else { - neigh = __neigh_lookup_errno(&nd_tbl, &fl6->daddr, dev); - if (IS_ERR(neigh)) { - dst_free(&rt->dst); - return ERR_CAST(neigh); - } + neigh = __neigh_lookup_errno(&nd_tbl, addr, dev); + if (IS_ERR(neigh)) + neigh = NULL; } rt->dst.flags |= DST_HOST; rt->dst.output = ip6_output; dst_set_neighbour(&rt->dst, neigh); atomic_set(&rt->dst.__refcnt, 1); - rt->rt6i_dst.addr = fl6->daddr; + rt->rt6i_dst.addr = *addr; rt->rt6i_dst.plen = 128; rt->rt6i_idev = idev; dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); @@ -1111,10 +1107,8 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, fib6_force_start_gc(net); - dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0); - out: - return dst; + return &rt->dst; } int icmp6_dst_gc(void) @@ -2062,7 +2056,7 @@ static int ip6_pkt_prohibit_out(struct sk_buff *skb) struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, const struct in6_addr *addr, - bool anycast) + int anycast) { struct net *net = dev_net(idev->dev); struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, diff --git a/trunk/net/ipv6/sit.c b/trunk/net/ipv6/sit.c index 3b6dac956bb0..b7d14cc12ee8 100644 --- a/trunk/net/ipv6/sit.c +++ b/trunk/net/ipv6/sit.c @@ -263,8 +263,6 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, if (register_netdevice(dev) < 0) goto failed_free; - strcpy(nt->parms.name, dev->name); - dev_hold(dev); ipip6_tunnel_link(sitn, nt); @@ -1146,6 +1144,7 @@ static int ipip6_tunnel_init(struct net_device *dev) struct ip_tunnel *tunnel = netdev_priv(dev); tunnel->dev = dev; + strcpy(tunnel->parms.name, dev->name); memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); @@ -1208,7 +1207,6 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea static int __net_init sit_init_net(struct net *net) { struct sit_net *sitn = net_generic(net, sit_net_id); - struct ip_tunnel *t; int err; sitn->tunnels[0] = sitn->tunnels_wc; @@ -1233,9 +1231,6 @@ static int __net_init sit_init_net(struct net *net) if ((err = register_netdev(sitn->fb_tunnel_dev))) goto err_reg_dev; - t = netdev_priv(sitn->fb_tunnel_dev); - - strcpy(t->parms.name, sitn->fb_tunnel_dev->name); return 0; err_reg_dev: diff --git a/trunk/net/ipv6/tcp_ipv6.c b/trunk/net/ipv6/tcp_ipv6.c index 906c7ca43542..9d74eee334d6 100644 --- a/trunk/net/ipv6/tcp_ipv6.c +++ b/trunk/net/ipv6/tcp_ipv6.c @@ -62,7 +62,6 @@ #include #include #include -#include #include @@ -1995,8 +1994,7 @@ static int tcp_v6_init_sock(struct sock *sk) sk->sk_rcvbuf = sysctl_tcp_rmem[1]; local_bh_disable(); - sock_update_memcg(sk); - sk_sockets_allocated_inc(sk); + percpu_counter_inc(&tcp_sockets_allocated); local_bh_enable(); return 0; @@ -2215,6 +2213,7 @@ struct proto tcpv6_prot = { .memory_allocated = &tcp_memory_allocated, .memory_pressure = &tcp_memory_pressure, .orphan_count = &tcp_orphan_count, + .sysctl_mem = sysctl_tcp_mem, .sysctl_wmem = sysctl_tcp_wmem, .sysctl_rmem = sysctl_tcp_rmem, .max_header = MAX_TCP_HEADER, @@ -2228,9 +2227,6 @@ struct proto tcpv6_prot = { .compat_setsockopt = compat_tcp_setsockopt, .compat_getsockopt = compat_tcp_getsockopt, #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM - .proto_cgroup = tcp_proto_cgroup, -#endif }; static const struct inet6_protocol tcpv6_protocol = { diff --git a/trunk/net/ipv6/udp.c b/trunk/net/ipv6/udp.c index 4f96b5c63685..adfe26a7fc63 100644 --- a/trunk/net/ipv6/udp.c +++ b/trunk/net/ipv6/udp.c @@ -238,7 +238,7 @@ static struct sock *udp6_lib_lookup2(struct net *net, return result; } -struct sock *__udp6_lib_lookup(struct net *net, +static struct sock *__udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, __be16 dport, int dif, struct udp_table *udptable) @@ -305,7 +305,6 @@ struct sock *__udp6_lib_lookup(struct net *net, rcu_read_unlock(); return result; } -EXPORT_SYMBOL_GPL(__udp6_lib_lookup); static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, __be16 sport, __be16 dport, diff --git a/trunk/net/key/af_key.c b/trunk/net/key/af_key.c index 11dbb2255ccb..bfc0bef170cb 100644 --- a/trunk/net/key/af_key.c +++ b/trunk/net/key/af_key.c @@ -375,7 +375,7 @@ static int verify_address_len(const void *p) const struct sadb_address *sp = p; const struct sockaddr *addr = (const struct sockaddr *)(sp + 1); const struct sockaddr_in *sin; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) const struct sockaddr_in6 *sin6; #endif int len; @@ -387,7 +387,7 @@ static int verify_address_len(const void *p) sp->sadb_address_prefixlen > 32) return -EINVAL; break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: len = DIV_ROUND_UP(sizeof(*sp) + sizeof(*sin6), sizeof(uint64_t)); if (sp->sadb_address_len != len || @@ -469,7 +469,7 @@ static int present_and_same_family(const struct sadb_address *src, if (s_addr->sa_family != d_addr->sa_family) return 0; if (s_addr->sa_family != AF_INET -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) && s_addr->sa_family != AF_INET6 #endif ) @@ -579,7 +579,7 @@ static inline int pfkey_sockaddr_len(sa_family_t family) switch (family) { case AF_INET: return sizeof(struct sockaddr_in); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: return sizeof(struct sockaddr_in6); #endif @@ -595,7 +595,7 @@ int pfkey_sockaddr_extract(const struct sockaddr *sa, xfrm_address_t *xaddr) xaddr->a4 = ((struct sockaddr_in *)sa)->sin_addr.s_addr; return AF_INET; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: memcpy(xaddr->a6, &((struct sockaddr_in6 *)sa)->sin6_addr, @@ -639,7 +639,7 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct net *net, const struct case AF_INET: xaddr = (xfrm_address_t *)&((const struct sockaddr_in *)(addr + 1))->sin_addr; break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: xaddr = (xfrm_address_t *)&((const struct sockaddr_in6 *)(addr + 1))->sin6_addr; break; @@ -705,7 +705,7 @@ static unsigned int pfkey_sockaddr_fill(const xfrm_address_t *xaddr, __be16 port memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); return 32; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; @@ -1311,7 +1311,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_ xdaddr = (xfrm_address_t *)&((struct sockaddr_in *)(daddr + 1))->sin_addr.s_addr; xsaddr = (xfrm_address_t *)&((struct sockaddr_in *)(saddr + 1))->sin_addr.s_addr; break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: xdaddr = (xfrm_address_t *)&((struct sockaddr_in6 *)(daddr + 1))->sin6_addr; xsaddr = (xfrm_address_t *)&((struct sockaddr_in6 *)(saddr + 1))->sin6_addr; @@ -3146,7 +3146,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, return NULL; } break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: if (opt != IPV6_IPSEC_POLICY) { *dir = -EOPNOTSUPP; diff --git a/trunk/net/mac80211/Kconfig b/trunk/net/mac80211/Kconfig index 96ddb72760b9..7d3b438755f0 100644 --- a/trunk/net/mac80211/Kconfig +++ b/trunk/net/mac80211/Kconfig @@ -247,3 +247,15 @@ config MAC80211_DEBUG_COUNTERS and show them in debugfs. If unsure, say N. + +config MAC80211_DRIVER_API_TRACER + bool "Driver API tracer" + depends on MAC80211_DEBUG_MENU + depends on EVENT_TRACING + help + Say Y here to make mac80211 register with the ftrace + framework for the driver API -- you can then see which + driver methods it is calling and which API functions + drivers are calling by looking at the trace. + + If unsure, say Y. diff --git a/trunk/net/mac80211/Makefile b/trunk/net/mac80211/Makefile index d540c3b160f3..fdb54e61d637 100644 --- a/trunk/net/mac80211/Makefile +++ b/trunk/net/mac80211/Makefile @@ -24,8 +24,7 @@ mac80211-y := \ util.o \ wme.o \ event.o \ - chan.o \ - driver-trace.o + chan.o mac80211-$(CONFIG_MAC80211_LEDS) += led.o mac80211-$(CONFIG_MAC80211_DEBUGFS) += \ @@ -42,6 +41,7 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ mac80211-$(CONFIG_PM) += pm.o +mac80211-$(CONFIG_MAC80211_DRIVER_API_TRACER) += driver-trace.o CFLAGS_driver-trace.o := -I$(src) # objects for PID algorithm diff --git a/trunk/net/mac80211/agg-rx.c b/trunk/net/mac80211/agg-rx.c index 96debba2c407..476b106c0b1c 100644 --- a/trunk/net/mac80211/agg-rx.c +++ b/trunk/net/mac80211/agg-rx.c @@ -73,11 +73,8 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL); #ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG - "Rx BA session stop requested for %pM tid %u %s reason: %d\n", - sta->sta.addr, tid, - initiator == WLAN_BACK_RECIPIENT ? "recipient" : "inititator", - (int)reason); + printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", + sta->sta.addr, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, @@ -88,7 +85,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, /* check if this is a self generated aggregation halt */ if (initiator == WLAN_BACK_RECIPIENT && tx) ieee80211_send_delba(sta->sdata, sta->sta.addr, - tid, WLAN_BACK_RECIPIENT, reason); + tid, 0, reason); del_timer_sync(&tid_rx->session_timer); del_timer_sync(&tid_rx->reorder_timer); @@ -112,7 +109,7 @@ void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap, int i; rcu_read_lock(); - sta = sta_info_get_bss(sdata, addr); + sta = sta_info_get(sdata, addr); if (!sta) { rcu_read_unlock(); return; @@ -185,8 +182,6 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); else if (sdata->vif.type == NL80211_IFTYPE_STATION) memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); - else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); diff --git a/trunk/net/mac80211/agg-tx.c b/trunk/net/mac80211/agg-tx.c index 7380287f010e..556765749b9c 100644 --- a/trunk/net/mac80211/agg-tx.c +++ b/trunk/net/mac80211/agg-tx.c @@ -83,8 +83,6 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); else if (sdata->vif.type == NL80211_IFTYPE_STATION) memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); - else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); @@ -188,7 +186,6 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, #endif /* CONFIG_MAC80211_HT_DEBUG */ del_timer_sync(&tid_tx->addba_resp_timer); - del_timer_sync(&tid_tx->session_timer); /* * After this packets are no longer handed right through @@ -307,38 +304,6 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) __release(agg_queue); } -/* - * splice packets from the STA's pending to the local pending, - * requires a call to ieee80211_agg_splice_finish later - */ -static void __acquires(agg_queue) -ieee80211_agg_splice_packets(struct ieee80211_local *local, - struct tid_ampdu_tx *tid_tx, u16 tid) -{ - int queue = ieee80211_ac_from_tid(tid); - unsigned long flags; - - ieee80211_stop_queue_agg(local, tid); - - if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" - " from the pending queue\n", tid)) - return; - - if (!skb_queue_empty(&tid_tx->pending)) { - spin_lock_irqsave(&local->queue_stop_reason_lock, flags); - /* copy over remaining packets */ - skb_queue_splice_tail_init(&tid_tx->pending, - &local->pending[queue]); - spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); - } -} - -static void __releases(agg_queue) -ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) -{ - ieee80211_wake_queue_agg(local, tid); -} - void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) { struct tid_ampdu_tx *tid_tx; @@ -350,17 +315,19 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) tid_tx = rcu_dereference_protected_tid_tx(sta, tid); /* - * Start queuing up packets for this aggregation session. - * We're going to release them once the driver is OK with - * that. + * While we're asking the driver about the aggregation, + * stop the AC queue so that we don't have to worry + * about frames that came in while we were doing that, + * which would require us to put them to the AC pending + * afterwards which just makes the code more complex. */ + ieee80211_stop_queue_agg(local, tid); + clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); /* - * Make sure no packets are being processed. This ensures that - * we have a valid starting sequence number and that in-flight - * packets have been flushed out and no packets for this TID - * will go into the driver during the ampdu_action call. + * make sure no packets are being processed to get + * valid starting sequence number */ synchronize_net(); @@ -374,15 +341,17 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) " tid %d\n", tid); #endif spin_lock_bh(&sta->lock); - ieee80211_agg_splice_packets(local, tid_tx, tid); ieee80211_assign_tid_tx(sta, tid, NULL); - ieee80211_agg_splice_finish(local, tid); spin_unlock_bh(&sta->lock); + ieee80211_wake_queue_agg(local, tid); kfree_rcu(tid_tx, rcu_head); return; } + /* we can take packets again now */ + ieee80211_wake_queue_agg(local, tid); + /* activate the timer for the recipient's addBA response */ mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); #ifdef CONFIG_MAC80211_HT_DEBUG @@ -400,28 +369,6 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) tid_tx->timeout); } -/* - * After accepting the AddBA Response we activated a timer, - * resetting it after each frame that we send. - */ -static void sta_tx_agg_session_timer_expired(unsigned long data) -{ - /* not an elegant detour, but there is no choice as the timer passes - * only one argument, and various sta_info are needed here, so init - * flow in sta_info_create gives the TID as data, while the timer_to_id - * array gives the sta through container_of */ - u8 *ptid = (u8 *)data; - u8 *timer_to_id = ptid - *ptid; - struct sta_info *sta = container_of(timer_to_id, struct sta_info, - timer_to_tid[0]); - -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid); -#endif - - ieee80211_stop_tx_ba_session(&sta->sta, *ptid); -} - int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, u16 timeout) { @@ -449,8 +396,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, if (sdata->vif.type != NL80211_IFTYPE_STATION && sdata->vif.type != NL80211_IFTYPE_MESH_POINT && sdata->vif.type != NL80211_IFTYPE_AP_VLAN && - sdata->vif.type != NL80211_IFTYPE_AP && - sdata->vif.type != NL80211_IFTYPE_ADHOC) + sdata->vif.type != NL80211_IFTYPE_AP) return -EINVAL; if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { @@ -461,27 +407,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, return -EINVAL; } - /* - * 802.11n-2009 11.5.1.1: If the initiating STA is an HT STA, is a - * member of an IBSS, and has no other existing Block Ack agreement - * with the recipient STA, then the initiating STA shall transmit a - * Probe Request frame to the recipient STA and shall not transmit an - * ADDBA Request frame unless it receives a Probe Response frame - * from the recipient within dot11ADDBAFailureTimeout. - * - * The probe request mechanism for ADDBA is currently not implemented, - * but we only build up Block Ack session with HT STAs. This information - * is set when we receive a bss info from a probe response or a beacon. - */ - if (sta->sdata->vif.type == NL80211_IFTYPE_ADHOC && - !sta->sta.ht_cap.ht_supported) { -#ifdef CONFIG_MAC80211_HT_DEBUG - printk(KERN_DEBUG "BA request denied - IBSS STA %pM" - "does not advertise HT support\n", pubsta->addr); -#endif /* CONFIG_MAC80211_HT_DEBUG */ - return -EINVAL; - } - spin_lock_bh(&sta->lock); /* we have tried too many times, receiver does not want A-MPDU */ @@ -513,16 +438,11 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, tid_tx->timeout = timeout; - /* response timer */ + /* Tx timer */ tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired; tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid]; init_timer(&tid_tx->addba_resp_timer); - /* tx timer */ - tid_tx->session_timer.function = sta_tx_agg_session_timer_expired; - tid_tx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; - init_timer(&tid_tx->session_timer); - /* assign a dialog token */ sta->ampdu_mlme.dialog_token_allocator++; tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator; @@ -542,6 +462,38 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, } EXPORT_SYMBOL(ieee80211_start_tx_ba_session); +/* + * splice packets from the STA's pending to the local pending, + * requires a call to ieee80211_agg_splice_finish later + */ +static void __acquires(agg_queue) +ieee80211_agg_splice_packets(struct ieee80211_local *local, + struct tid_ampdu_tx *tid_tx, u16 tid) +{ + int queue = ieee80211_ac_from_tid(tid); + unsigned long flags; + + ieee80211_stop_queue_agg(local, tid); + + if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" + " from the pending queue\n", tid)) + return; + + if (!skb_queue_empty(&tid_tx->pending)) { + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + /* copy over remaining packets */ + skb_queue_splice_tail_init(&tid_tx->pending, + &local->pending[queue]); + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + } +} + +static void __releases(agg_queue) +ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) +{ + ieee80211_wake_queue_agg(local, tid); +} + static void ieee80211_agg_tx_operational(struct ieee80211_local *local, struct sta_info *sta, u16 tid) { @@ -595,7 +547,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) } mutex_lock(&local->sta_mtx); - sta = sta_info_get_bss(sdata, ra); + sta = sta_info_get(sdata, ra); if (!sta) { mutex_unlock(&local->sta_mtx); #ifdef CONFIG_MAC80211_HT_DEBUG @@ -724,7 +676,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) mutex_lock(&local->sta_mtx); - sta = sta_info_get_bss(sdata, ra); + sta = sta_info_get(sdata, ra); if (!sta) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Could not find station: %pM\n", ra); @@ -862,11 +814,6 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, ieee80211_agg_tx_operational(local, sta, tid); sta->ampdu_mlme.addba_req_num[tid] = 0; - - if (tid_tx->timeout) - mod_timer(&tid_tx->session_timer, - TU_TO_EXP_TIME(tid_tx->timeout)); - } else { ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, true); diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index 393b2a4445b8..2577c45069e5 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -102,16 +102,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, return 0; } -static int ieee80211_set_noack_map(struct wiphy *wiphy, - struct net_device *dev, - u16 noack_map) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - sdata->noack_map = noack_map; - return 0; -} - static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params) @@ -509,7 +499,7 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, if (!resp || !resp_len) return -EINVAL; - old = rtnl_dereference(sdata->u.ap.probe_resp); + old = sdata->u.ap.probe_resp; new = dev_alloc_skb(resp_len); if (!new) @@ -1195,8 +1185,6 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, { u8 *new_ie; const u8 *old_ie; - struct ieee80211_sub_if_data *sdata = container_of(ifmsh, - struct ieee80211_sub_if_data, u.mesh); /* allocate information elements */ new_ie = NULL; @@ -1223,10 +1211,6 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, if (setup->is_secure) ifmsh->security |= IEEE80211_MESH_SEC_SECURED; - /* mcast rate setting in Mesh Node */ - memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate, - sizeof(setup->mcast_rate)); - return 0; } @@ -1272,9 +1256,6 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask)) conf->dot11MeshHWMPpreqMinInterval = nconf->dot11MeshHWMPpreqMinInterval; - if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, mask)) - conf->dot11MeshHWMPperrMinInterval = - nconf->dot11MeshHWMPperrMinInterval; if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, mask)) conf->dot11MeshHWMPnetDiameterTraversalTime = @@ -2717,5 +2698,4 @@ struct cfg80211_ops mac80211_config_ops = { .tdls_mgmt = ieee80211_tdls_mgmt, .probe_client = ieee80211_probe_client, .get_channel = ieee80211_wiphy_get_channel, - .set_noack_map = ieee80211_set_noack_map, }; diff --git a/trunk/net/mac80211/debugfs.c b/trunk/net/mac80211/debugfs.c index 90baea53e7c5..00cefcb493eb 100644 --- a/trunk/net/mac80211/debugfs.c +++ b/trunk/net/mac80211/debugfs.c @@ -97,6 +97,40 @@ static const struct file_operations reset_ops = { .llseek = noop_llseek, }; +static ssize_t noack_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + + return mac80211_format_buffer(user_buf, count, ppos, "%d\n", + local->wifi_wme_noack_test); +} + +static ssize_t noack_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + char buf[10]; + size_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + buf[len] = '\0'; + + local->wifi_wme_noack_test = !!simple_strtoul(buf, NULL, 0); + + return count; +} + +static const struct file_operations noack_ops = { + .read = noack_read, + .write = noack_write, + .open = mac80211_open_file_generic, + .llseek = default_llseek, +}; + static ssize_t uapsd_queues_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -364,6 +398,7 @@ void debugfs_hw_add(struct ieee80211_local *local) DEBUGFS_ADD(wep_iv); DEBUGFS_ADD(queues); DEBUGFS_ADD_MODE(reset, 0200); + DEBUGFS_ADD(noack); DEBUGFS_ADD(uapsd_queues); DEBUGFS_ADD(uapsd_max_sp_len); DEBUGFS_ADD(channel_type); diff --git a/trunk/net/mac80211/debugfs_netdev.c b/trunk/net/mac80211/debugfs_netdev.c index 8df28910b8ee..9352819a986b 100644 --- a/trunk/net/mac80211/debugfs_netdev.c +++ b/trunk/net/mac80211/debugfs_netdev.c @@ -405,8 +405,6 @@ IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout, u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC); IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval, u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC); -IEEE80211_IF_FILE(dot11MeshHWMPperrMinInterval, - u.mesh.mshcfg.dot11MeshHWMPperrMinInterval, DEC); IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime, u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC); IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries, @@ -536,7 +534,6 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) MESHPARAMS_ADD(dot11MeshMaxPeerLinks); MESHPARAMS_ADD(dot11MeshHWMPactivePathTimeout); MESHPARAMS_ADD(dot11MeshHWMPpreqMinInterval); - MESHPARAMS_ADD(dot11MeshHWMPperrMinInterval); MESHPARAMS_ADD(dot11MeshHWMPnetDiameterTraversalTime); MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries); MESHPARAMS_ADD(path_refresh_time); diff --git a/trunk/net/mac80211/driver-ops.h b/trunk/net/mac80211/driver-ops.h index e8960ae39861..49cc5e0e8a6a 100644 --- a/trunk/net/mac80211/driver-ops.h +++ b/trunk/net/mac80211/driver-ops.h @@ -10,16 +10,6 @@ static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) WARN_ON(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER)); } -static inline struct ieee80211_sub_if_data * -get_bss_sdata(struct ieee80211_sub_if_data *sdata) -{ - if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) - sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, - u.ap); - - return sdata; -} - static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb) { local->ops->tx(&local->hw, skb); @@ -431,7 +421,6 @@ static inline void drv_sta_notify(struct ieee80211_local *local, enum sta_notify_cmd cmd, struct ieee80211_sta *sta) { - sdata = get_bss_sdata(sdata); check_sdata_in_driver(sdata); trace_drv_sta_notify(local, sdata, cmd, sta); @@ -448,7 +437,6 @@ static inline int drv_sta_add(struct ieee80211_local *local, might_sleep(); - sdata = get_bss_sdata(sdata); check_sdata_in_driver(sdata); trace_drv_sta_add(local, sdata, sta); @@ -466,7 +454,6 @@ static inline void drv_sta_remove(struct ieee80211_local *local, { might_sleep(); - sdata = get_bss_sdata(sdata); check_sdata_in_driver(sdata); trace_drv_sta_remove(local, sdata, sta); @@ -560,7 +547,6 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, might_sleep(); - sdata = get_bss_sdata(sdata); check_sdata_in_driver(sdata); trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); diff --git a/trunk/net/mac80211/driver-trace.h b/trunk/net/mac80211/driver-trace.h index 6e9df8fd8fb8..2af4fca55337 100644 --- a/trunk/net/mac80211/driver-trace.h +++ b/trunk/net/mac80211/driver-trace.h @@ -5,6 +5,17 @@ #include #include "ieee80211_i.h" +#if !defined(CONFIG_MAC80211_DRIVER_API_TRACER) || defined(__CHECKER__) +#undef TRACE_EVENT +#define TRACE_EVENT(name, proto, ...) \ +static inline void trace_ ## name(proto) {} +#undef DECLARE_EVENT_CLASS +#define DECLARE_EVENT_CLASS(...) +#undef DEFINE_EVENT +#define DEFINE_EVENT(evt_class, name, proto, ...) \ +static inline void trace_ ## name(proto) {} +#endif + #undef TRACE_SYSTEM #define TRACE_SYSTEM mac80211 diff --git a/trunk/net/mac80211/ht.c b/trunk/net/mac80211/ht.c index 0fd9c2a7f242..810cfbea6ad1 100644 --- a/trunk/net/mac80211/ht.c +++ b/trunk/net/mac80211/ht.c @@ -28,9 +28,9 @@ bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata) return false; } -static void __check_htcap_disable(struct ieee80211_sub_if_data *sdata, - struct ieee80211_sta_ht_cap *ht_cap, - u16 flag) +void __check_htcap_disable(struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta_ht_cap *ht_cap, + u16 flag) { __le16 le_flag = cpu_to_le16(flag); if (sdata->u.mgd.ht_capa_mask.cap_info & le_flag) { @@ -47,9 +47,7 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, int i; if (sdata->vif.type != NL80211_IFTYPE_STATION) { - /* AP interfaces call this code when adding new stations, - * so just silently ignore non station interfaces. - */ + WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); return; } @@ -284,8 +282,6 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); else if (sdata->vif.type == NL80211_IFTYPE_STATION) memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); - else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION); diff --git a/trunk/net/mac80211/ibss.c b/trunk/net/mac80211/ibss.c index 3f830ac159e5..7d84af70132f 100644 --- a/trunk/net/mac80211/ibss.c +++ b/trunk/net/mac80211/ibss.c @@ -77,7 +77,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, struct cfg80211_bss *bss; u32 bss_change; u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; - enum nl80211_channel_type channel_type; lockdep_assert_held(&ifibss->mtx); @@ -106,16 +105,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - channel_type = ifibss->channel_type; - if (channel_type > NL80211_CHAN_HT20 && - !cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) - channel_type = NL80211_CHAN_HT20; - if (!ieee80211_set_channel_type(local, sdata, channel_type)) { - /* can only fail due to HT40+/- mismatch */ - channel_type = NL80211_CHAN_HT20; - WARN_ON(!ieee80211_set_channel_type(local, sdata, - NL80211_CHAN_HT20)); - } + local->oper_channel = chan; + WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT)); ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); sband = local->hw.wiphy->bands[chan->band]; @@ -181,19 +172,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, memcpy(skb_put(skb, ifibss->ie_len), ifibss->ie, ifibss->ie_len); - /* add HT capability and information IEs */ - if (channel_type && sband->ht_cap.ht_supported) { - pos = skb_put(skb, 4 + - sizeof(struct ieee80211_ht_cap) + - sizeof(struct ieee80211_ht_info)); - pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, - sband->ht_cap.cap); - pos = ieee80211_ie_build_ht_info(pos, - &sband->ht_cap, - chan, - channel_type); - } - if (local->hw.queues >= 4) { pos = skb_put(skb, 9); *pos++ = WLAN_EID_VENDOR_SPECIFIC; @@ -217,7 +195,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, bss_change |= BSS_CHANGED_BEACON; bss_change |= BSS_CHANGED_BEACON_ENABLED; bss_change |= BSS_CHANGED_BASIC_RATES; - bss_change |= BSS_CHANGED_HT; bss_change |= BSS_CHANGED_IBSS; sdata->vif.bss_conf.ibss_joined = true; ieee80211_bss_info_change_notify(sdata, bss_change); @@ -291,8 +268,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, u64 beacon_timestamp, rx_timestamp; u32 supp_rates = 0; enum ieee80211_band band = rx_status->band; - struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; - bool rates_updated = false; if (elems->ds_params && elems->ds_params_len == 1) freq = ieee80211_channel_to_frequency(elems->ds_params[0], @@ -332,7 +307,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, prev_rates, sta->sta.supp_rates[band]); #endif - rates_updated = true; + rate_control_rate_init(sta); } } else sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, @@ -343,39 +318,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, if (sta && elems->wmm_info) set_sta_flag(sta, WLAN_STA_WME); - if (sta && elems->ht_info_elem && elems->ht_cap_elem && - sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { - /* we both use HT */ - struct ieee80211_sta_ht_cap sta_ht_cap_new; - enum nl80211_channel_type channel_type = - ieee80211_ht_info_to_channel_type( - elems->ht_info_elem); - - ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, - elems->ht_cap_elem, - &sta_ht_cap_new); - - /* - * fall back to HT20 if we don't use or use - * the other extension channel - */ - if ((channel_type == NL80211_CHAN_HT40MINUS || - channel_type == NL80211_CHAN_HT40PLUS) && - channel_type != sdata->u.ibss.channel_type) - sta_ht_cap_new.cap &= - ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - - if (memcmp(&sta->sta.ht_cap, &sta_ht_cap_new, - sizeof(sta_ht_cap_new))) { - memcpy(&sta->sta.ht_cap, &sta_ht_cap_new, - sizeof(sta_ht_cap_new)); - rates_updated = true; - } - } - - if (sta && rates_updated) - rate_control_rate_init(sta); - rcu_read_unlock(); } @@ -954,18 +896,12 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, struct cfg80211_ibss_params *params) { struct sk_buff *skb; - u32 changed = 0; skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + - sizeof(struct ieee80211_hdr_3addr) + - 12 /* struct ieee80211_mgmt.u.beacon */ + - 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ + - 2 + 8 /* max Supported Rates */ + - 3 /* max DS params */ + - 4 /* IBSS params */ + - 2 + (IEEE80211_MAX_SUPP_RATES - 8) + - 2 + sizeof(struct ieee80211_ht_cap) + - 2 + sizeof(struct ieee80211_ht_info) + + 36 /* bitrates */ + + 34 /* SSID */ + + 3 /* DS params */ + + 4 /* IBSS params */ + params->ie_len); if (!skb) return -ENOMEM; @@ -986,15 +922,13 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, sdata->vif.bss_conf.beacon_int = params->beacon_interval; sdata->u.ibss.channel = params->channel; - sdata->u.ibss.channel_type = params->channel_type; sdata->u.ibss.fixed_channel = params->channel_fixed; /* fix ourselves to that channel now already */ if (params->channel_fixed) { sdata->local->oper_channel = params->channel; - if (!ieee80211_set_channel_type(sdata->local, sdata, - params->channel_type)) - return -EINVAL; + WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata, + NL80211_CHAN_NO_HT)); } if (params->ie) { @@ -1017,23 +951,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, ieee80211_recalc_idle(sdata->local); mutex_unlock(&sdata->local->mtx); - /* - * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is - * reserved, but an HT STA shall protect HT transmissions as though - * the HT Protection field were set to non-HT mixed mode. - * - * In an IBSS, the RIFS Mode field of the HT Operation element is - * also reserved, but an HT STA shall operate as though this field - * were set to 1. - */ - - sdata->vif.bss_conf.ht_operation_mode |= - IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED - | IEEE80211_HT_PARAM_RIFS_MODE; - - changed |= BSS_CHANGED_HT; - ieee80211_bss_info_change_notify(sdata, changed); - ieee80211_queue_work(&sdata->local->hw, &sdata->work); return 0; diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index 96fe75410bbe..762243e469df 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -474,7 +474,6 @@ struct ieee80211_if_ibss { u8 ssid_len, ie_len; u8 *ie; struct ieee80211_channel *channel; - enum nl80211_channel_type channel_type; unsigned long ibss_join_req; /* probe response/beacon for IBSS */ @@ -515,9 +514,7 @@ struct ieee80211_if_mesh { atomic_t mpaths; /* Timestamp of last SN update */ unsigned long last_sn_update; - /* Time when it's ok to send next PERR */ - unsigned long next_perr; - /* Timestamp of last PREQ sent */ + /* Timestamp of last SN sent */ unsigned long last_preq; struct mesh_rmc *rmc; spinlock_t mesh_preq_queue_lock; @@ -614,9 +611,6 @@ struct ieee80211_sub_if_data { struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; unsigned int fragment_next; - /* TID bitmap for NoAck policy */ - u16 noack_map; - struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; struct ieee80211_key __rcu *default_unicast_key; struct ieee80211_key __rcu *default_multicast_key; @@ -967,6 +961,7 @@ struct ieee80211_local { int total_ps_buffered; /* total number of all buffered unicast and * multicast packets for power saving stations */ + int wifi_wme_noack_test; unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ /* @@ -1221,11 +1216,13 @@ 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_return(struct ieee80211_local *local, + bool enable_beaconing, bool offchannel_ps_disable); void ieee80211_hw_roc_setup(struct ieee80211_local *local); diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index 3d3bb5e9d8fa..b34ca0cbdf6c 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -672,6 +672,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, struct ieee80211_local *local = sdata->local; struct ieee80211_hdr *hdr; struct ieee80211_radiotap_header *rtap = (void *)skb->data; + u8 *p; if (local->hw.queues < 4) return 0; @@ -682,7 +683,19 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); - return ieee80211_select_queue_80211(local, skb, hdr); + if (!ieee80211_is_data(hdr->frame_control)) { + skb->priority = 7; + return ieee802_1d_to_ac[skb->priority]; + } + if (!ieee80211_is_data_qos(hdr->frame_control)) { + skb->priority = 0; + return ieee802_1d_to_ac[skb->priority]; + } + + p = ieee80211_get_qos_ctl(hdr); + skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; + + return ieee80211_downgrade_queue(local, skb); } static const struct net_device_ops ieee80211_monitorif_ops = { @@ -853,8 +866,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); sdata->control_port_no_encrypt = false; - sdata->noack_map = 0; - /* only monitor differs */ sdata->dev->type = ARPHRD_ETHER; diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index 60198ac664a0..dddedfad5404 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -92,6 +92,47 @@ 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; + 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 = 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; @@ -570,8 +611,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - wiphy->features = NL80211_FEATURE_SK_TX_STATUS | - NL80211_FEATURE_HT_IBSS; + wiphy->features = NL80211_FEATURE_SK_TX_STATUS; if (!ops->set_key) wiphy->flags |= WIPHY_FLAG_IBSS_RSN; @@ -739,12 +779,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (!local->int_scan_req) return -ENOMEM; - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - if (!local->hw.wiphy->bands[band]) - continue; - local->int_scan_req->rates[band] = (u32) -1; - } - /* if low-level driver supports AP, we also support VLAN */ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); diff --git a/trunk/net/mac80211/mesh.c b/trunk/net/mac80211/mesh.c index c707c8bf6d2c..ee82d2f7f114 100644 --- a/trunk/net/mac80211/mesh.c +++ b/trunk/net/mac80211/mesh.c @@ -749,7 +749,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) atomic_set(&ifmsh->mpaths, 0); mesh_rmc_init(sdata); ifmsh->last_preq = jiffies; - ifmsh->next_perr = jiffies; /* Allocate all mesh structures when creating the first mesh interface. */ if (!mesh_allocated) ieee80211s_init(); diff --git a/trunk/net/mac80211/mesh.h b/trunk/net/mac80211/mesh.h index bd14bd26a2b6..622cc96eb4de 100644 --- a/trunk/net/mac80211/mesh.h +++ b/trunk/net/mac80211/mesh.h @@ -233,8 +233,6 @@ void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh); /* Mesh paths */ int mesh_nexthop_lookup(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); -int mesh_nexthop_resolve(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata); void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata); diff --git a/trunk/net/mac80211/mesh_hwmp.c b/trunk/net/mac80211/mesh_hwmp.c index 73abb7524b2c..ce3db2735d7c 100644 --- a/trunk/net/mac80211/mesh_hwmp.c +++ b/trunk/net/mac80211/mesh_hwmp.c @@ -241,15 +241,11 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, { struct ieee80211_local *local = sdata->local; struct sk_buff *skb; - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; struct ieee80211_mgmt *mgmt; u8 *pos, ie_len; int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) + sizeof(mgmt->u.action.u.mesh_action); - if (time_before(jiffies, ifmsh->next_perr)) - return -EAGAIN; - skb = dev_alloc_skb(local->hw.extra_tx_headroom + hdr_len + 2 + 15 /* PERR IE */); @@ -294,8 +290,6 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, /* see note in function header */ prepare_frame_for_deferred_tx(sdata, skb); - ifmsh->next_perr = TU_TO_EXP_TIME( - ifmsh->mshcfg.dot11MeshHWMPperrMinInterval); ieee80211_add_pending_skb(local, skb); return 0; } @@ -399,13 +393,15 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, orig_metric = PREQ_IE_METRIC(hwmp_ie); break; case MPATH_PREP: - /* Originator here refers to the MP that was the target in the - * Path Request. We divert from the nomenclature in the draft + /* Originator here refers to the MP that was the destination in + * the Path Request. The draft refers to that MP as the + * destination address, even though usually it is the origin of + * the PREP frame. We divert from the nomenclature in the draft * so that we can easily use a single function to gather path * information from both PREQ and PREP frames. */ - orig_addr = PREP_IE_TARGET_ADDR(hwmp_ie); - orig_sn = PREP_IE_TARGET_SN(hwmp_ie); + orig_addr = PREP_IE_ORIG_ADDR(hwmp_ie); + orig_sn = PREP_IE_ORIG_SN(hwmp_ie); orig_lifetime = PREP_IE_LIFETIME(hwmp_ie); orig_metric = PREP_IE_METRIC(hwmp_ie); break; @@ -566,9 +562,9 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, ttl = ifmsh->mshcfg.element_ttl; if (ttl != 0) { mhwmp_dbg("replying to the PREQ"); - mesh_path_sel_frame_tx(MPATH_PREP, 0, orig_addr, - cpu_to_le32(orig_sn), 0, target_addr, - cpu_to_le32(target_sn), mgmt->sa, 0, ttl, + mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr, + cpu_to_le32(target_sn), 0, orig_addr, + cpu_to_le32(orig_sn), mgmt->sa, 0, ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), 0, sdata); } else @@ -622,8 +618,14 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem)); - orig_addr = PREP_IE_ORIG_ADDR(prep_elem); - if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) + /* Note that we divert from the draft nomenclature and denominate + * destination to what the draft refers to as origininator. So in this + * function destnation refers to the final destination of the PREP, + * which corresponds with the originator of the PREQ which this PREP + * replies + */ + target_addr = PREP_IE_TARGET_ADDR(prep_elem); + if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) /* destination, no forwarding required */ return; @@ -634,7 +636,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, } rcu_read_lock(); - mpath = mesh_path_lookup(orig_addr, sdata); + mpath = mesh_path_lookup(target_addr, sdata); if (mpath) spin_lock_bh(&mpath->state_lock); else @@ -649,7 +651,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, flags = PREP_IE_FLAGS(prep_elem); lifetime = PREP_IE_LIFETIME(prep_elem); hopcount = PREP_IE_HOPCOUNT(prep_elem) + 1; - target_addr = PREP_IE_TARGET_ADDR(prep_elem); + orig_addr = PREP_IE_ORIG_ADDR(prep_elem); target_sn = PREP_IE_TARGET_SN(prep_elem); orig_sn = PREP_IE_ORIG_SN(prep_elem); @@ -982,97 +984,71 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) kfree(preq_node); } -/* mesh_nexthop_resolve - lookup next hop for given skb and start path - * discovery if no forwarding information is found. +/** + * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame * * @skb: 802.11 frame to be sent * @sdata: network subif the frame will be sent through * - * Returns: 0 if the next hop was found and -ENOENT if the frame was queued. - * skb is freeed here if no mpath could be allocated. + * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is + * found, the function will start a path discovery and queue the frame so it is + * sent when the path is resolved. This means the caller must not free the skb + * in this case. */ -int mesh_nexthop_resolve(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata) +int mesh_nexthop_lookup(struct sk_buff *skb, + struct ieee80211_sub_if_data *sdata) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct mesh_path *mpath; struct sk_buff *skb_to_free = NULL; + struct mesh_path *mpath; + struct sta_info *next_hop; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; u8 *target_addr = hdr->addr3; int err = 0; rcu_read_lock(); - err = mesh_nexthop_lookup(skb, sdata); - if (!err) - goto endlookup; - - /* no nexthop found, start resolving */ mpath = mesh_path_lookup(target_addr, sdata); + if (!mpath) { mesh_path_add(target_addr, sdata); mpath = mesh_path_lookup(target_addr, sdata); if (!mpath) { - mesh_path_discard_frame(skb, sdata); + sdata->u.mesh.mshstats.dropped_frames_no_route++; err = -ENOSPC; goto endlookup; } } - if (!(mpath->flags & MESH_PATH_RESOLVING)) - mesh_queue_preq(mpath, PREQ_Q_F_START); - - if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN) - skb_to_free = skb_dequeue(&mpath->frame_queue); - - info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; - ieee80211_set_qos_hdr(sdata, skb); - skb_queue_tail(&mpath->frame_queue, skb); - err = -ENOENT; - if (skb_to_free) - mesh_path_discard_frame(skb_to_free, sdata); - -endlookup: - rcu_read_unlock(); - return err; -} -/** - * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling - * this function is considered "using" the associated mpath, so preempt a path - * refresh if this mpath expires soon. - * - * @skb: 802.11 frame to be sent - * @sdata: network subif the frame will be sent through - * - * Returns: 0 if the next hop was found. Nonzero otherwise. - */ -int mesh_nexthop_lookup(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata) -{ - struct mesh_path *mpath; - struct sta_info *next_hop; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - u8 *target_addr = hdr->addr3; - int err = -ENOENT; - - rcu_read_lock(); - mpath = mesh_path_lookup(target_addr, sdata); - - if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE)) - goto endlookup; + if (mpath->flags & MESH_PATH_ACTIVE) { + if (time_after(jiffies, + mpath->exp_time - + msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && + !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) && + !(mpath->flags & MESH_PATH_RESOLVING) && + !(mpath->flags & MESH_PATH_FIXED)) { + mesh_queue_preq(mpath, + PREQ_Q_F_START | PREQ_Q_F_REFRESH); + } + next_hop = rcu_dereference(mpath->next_hop); + if (next_hop) + memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); + else + err = -ENOENT; + } else { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + if (!(mpath->flags & MESH_PATH_RESOLVING)) { + /* Start discovery only if it is not running yet */ + mesh_queue_preq(mpath, PREQ_Q_F_START); + } - if (time_after(jiffies, - mpath->exp_time - - msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) && - !memcmp(sdata->vif.addr, hdr->addr4, ETH_ALEN) && - !(mpath->flags & MESH_PATH_RESOLVING) && - !(mpath->flags & MESH_PATH_FIXED)) - mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); + if (skb_queue_len(&mpath->frame_queue) >= MESH_FRAME_QUEUE_LEN) + skb_to_free = skb_dequeue(&mpath->frame_queue); - next_hop = rcu_dereference(mpath->next_hop); - if (next_hop) { - memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); - memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); - err = 0; + info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; + ieee80211_set_qos_hdr(sdata, skb); + skb_queue_tail(&mpath->frame_queue, skb); + if (skb_to_free) + mesh_path_discard_frame(skb_to_free, sdata); + err = -ENOENT; } endlookup: diff --git a/trunk/net/mac80211/mesh_pathtbl.c b/trunk/net/mac80211/mesh_pathtbl.c index edf167e3b8f3..7bd2a76aef0e 100644 --- a/trunk/net/mac80211/mesh_pathtbl.c +++ b/trunk/net/mac80211/mesh_pathtbl.c @@ -221,7 +221,6 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) { hdr = (struct ieee80211_hdr *) skb->data; memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); - memcpy(hdr->addr2, mpath->sdata->vif.addr, ETH_ALEN); __skb_queue_tail(&tmpq, skb); } @@ -265,7 +264,6 @@ static void prepare_for_gate(struct sk_buff *skb, char *dst_addr, next_hop = rcu_dereference(gate_mpath->next_hop)->sta.addr; memcpy(hdr->addr1, next_hop, ETH_ALEN); rcu_read_unlock(); - memcpy(hdr->addr2, gate_mpath->sdata->vif.addr, ETH_ALEN); memcpy(hdr->addr3, dst_addr, ETH_ALEN); } @@ -973,11 +971,38 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) * @skb: frame to discard * @sdata: network subif the frame was to be sent through * + * If the frame was being forwarded from another MP, a PERR frame will be sent + * to the precursor. The precursor's address (i.e. the previous hop) was saved + * in addr1 of the frame-to-be-forwarded, and would only be overwritten once + * the destination is successfully resolved. + * * Locking: the function must me called within a rcu_read_lock region */ void mesh_path_discard_frame(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct mesh_path *mpath; + u32 sn = 0; + __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD); + + if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) { + u8 *ra, *da; + + da = hdr->addr3; + ra = hdr->addr1; + rcu_read_lock(); + mpath = mesh_path_lookup(da, sdata); + if (mpath) { + spin_lock_bh(&mpath->state_lock); + sn = ++mpath->sn; + spin_unlock_bh(&mpath->state_lock); + } + rcu_read_unlock(); + mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data, + cpu_to_le32(sn), reason, ra, sdata); + } + kfree_skb(skb); sdata->u.mesh.mshstats.dropped_frames_no_route++; } diff --git a/trunk/net/mac80211/offchannel.c b/trunk/net/mac80211/offchannel.c index e4330d843575..ebd8cccac8f2 100644 --- a/trunk/net/mac80211/offchannel.c +++ b/trunk/net/mac80211/offchannel.c @@ -156,6 +156,7 @@ void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, } void ieee80211_offchannel_return(struct ieee80211_local *local, + bool enable_beaconing, bool offchannel_ps_disable) { struct ieee80211_sub_if_data *sdata; @@ -187,9 +188,11 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, netif_tx_wake_all_queues(sdata->dev); } - if (sdata->vif.type == NL80211_IFTYPE_AP || - sdata->vif.type == NL80211_IFTYPE_ADHOC || - sdata->vif.type == NL80211_IFTYPE_MESH_POINT) + /* Check to see if we should re-enable beaconing */ + if (enable_beaconing && + (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); } diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c index 7d226417ef46..d1a8869fe05d 100644 --- a/trunk/net/mac80211/rx.c +++ b/trunk/net/mac80211/rx.c @@ -1895,16 +1895,13 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) static ieee80211_rx_result ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) { - struct ieee80211_hdr *fwd_hdr, *hdr; - struct ieee80211_tx_info *info; + struct ieee80211_hdr *hdr; struct ieee80211s_hdr *mesh_hdr; + unsigned int hdrlen; struct sk_buff *skb = rx->skb, *fwd_skb; struct ieee80211_local *local = rx->local; struct ieee80211_sub_if_data *sdata = rx->sdata; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - __le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD); - u16 q, hdrlen; hdr = (struct ieee80211_hdr *) skb->data; hdrlen = ieee80211_hdrlen(hdr->frame_control); @@ -1920,7 +1917,14 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) return RX_CONTINUE; if (!mesh_hdr->ttl) + /* illegal frame */ + return RX_DROP_MONITOR; + + if (ieee80211_queue_stopped(&local->hw, skb_get_queue_mapping(skb))) { + IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, + dropped_frames_congestion); return RX_DROP_MONITOR; + } if (mesh_hdr->flags & MESH_FLAGS_AE) { struct mesh_path *mppath; @@ -1953,50 +1957,59 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) compare_ether_addr(sdata->vif.addr, hdr->addr3) == 0) return RX_CONTINUE; - q = ieee80211_select_queue_80211(local, skb, hdr); - if (ieee80211_queue_stopped(&local->hw, q)) { - IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion); - return RX_DROP_MONITOR; - } - skb_set_queue_mapping(skb, q); - - if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) - goto out; + skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, skb)); + mesh_hdr->ttl--; - if (!--mesh_hdr->ttl) { - IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); - return RX_DROP_MONITOR; - } - - fwd_skb = skb_copy(skb, GFP_ATOMIC); - if (!fwd_skb) { - if (net_ratelimit()) - printk(KERN_DEBUG "%s: failed to clone mesh frame\n", - sdata->name); - goto out; - } - - fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; - info = IEEE80211_SKB_CB(fwd_skb); - memset(info, 0, sizeof(*info)); - info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; - info->control.vif = &rx->sdata->vif; - info->control.jiffies = jiffies; - if (is_multicast_ether_addr(fwd_hdr->addr1)) { - IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast); - memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); - } else if (!mesh_nexthop_lookup(fwd_skb, sdata)) { - IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); - } else { - /* unable to resolve next hop */ - mesh_path_error_tx(ifmsh->mshcfg.element_ttl, fwd_hdr->addr3, - 0, reason, fwd_hdr->addr2, sdata); - IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); - return RX_DROP_MONITOR; + if (status->rx_flags & IEEE80211_RX_RA_MATCH) { + if (!mesh_hdr->ttl) + IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh, + dropped_frames_ttl); + else { + struct ieee80211_hdr *fwd_hdr; + struct ieee80211_tx_info *info; + + fwd_skb = skb_copy(skb, GFP_ATOMIC); + + if (!fwd_skb && net_ratelimit()) + printk(KERN_DEBUG "%s: failed to clone mesh frame\n", + sdata->name); + if (!fwd_skb) + goto out; + + fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; + memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); + info = IEEE80211_SKB_CB(fwd_skb); + memset(info, 0, sizeof(*info)); + info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; + info->control.vif = &rx->sdata->vif; + info->control.jiffies = jiffies; + if (is_multicast_ether_addr(fwd_hdr->addr1)) { + IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, + fwded_mcast); + } else { + int err; + /* + * Save TA to addr1 to send TA a path error if a + * suitable next hop is not found + */ + memcpy(fwd_hdr->addr1, fwd_hdr->addr2, + ETH_ALEN); + err = mesh_nexthop_lookup(fwd_skb, sdata); + /* Failed to immediately resolve next hop: + * fwded frame was dropped or will be added + * later to the pending skb queue. */ + if (err) + return RX_DROP_MONITOR; + + IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, + fwded_unicast); + } + IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, + fwded_frames); + ieee80211_add_pending_skb(local, fwd_skb); + } } - IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames); - ieee80211_add_pending_skb(local, fwd_skb); out: if (is_multicast_ether_addr(hdr->addr1) || sdata->dev->flags & IFF_PROMISC) @@ -2237,8 +2250,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) if (sdata->vif.type != NL80211_IFTYPE_STATION && sdata->vif.type != NL80211_IFTYPE_MESH_POINT && sdata->vif.type != NL80211_IFTYPE_AP_VLAN && - sdata->vif.type != NL80211_IFTYPE_AP && - sdata->vif.type != NL80211_IFTYPE_ADHOC) + sdata->vif.type != NL80211_IFTYPE_AP) break; /* verify action_code is present */ @@ -2797,17 +2809,10 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, return 0; } else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) { - /* - * Accept public action frames even when the - * BSSID doesn't match, this is used for P2P - * and location updates. Note that mac80211 - * itself never looks at these frames. - */ - if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && - ieee80211_is_public_action(hdr, skb->len)) - return 1; if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && - !ieee80211_is_beacon(hdr->frame_control)) + !ieee80211_is_beacon(hdr->frame_control) && + !(ieee80211_is_action(hdr->frame_control) && + sdata->vif.p2p)) return 0; status->rx_flags &= ~IEEE80211_RX_RA_MATCH; } diff --git a/trunk/net/mac80211/scan.c b/trunk/net/mac80211/scan.c index 2c5041cc71f8..81863031e0a3 100644 --- a/trunk/net/mac80211/scan.c +++ b/trunk/net/mac80211/scan.c @@ -297,7 +297,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, if (!was_hw_scan) { ieee80211_configure_filter(local); drv_sw_scan_complete(local); - ieee80211_offchannel_return(local, true); + ieee80211_offchannel_return(local, true, true); } ieee80211_recalc_idle(local); @@ -602,7 +602,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, * in off-channel state..will put that back * on-channel at the end of scanning. */ - ieee80211_offchannel_return(local, false); + ieee80211_offchannel_return(local, true, false); *next_delay = HZ / 5; /* afterwards, resume scan & go to next channel */ diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index f98235262006..8eaa746ec7a2 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -351,6 +351,10 @@ static int sta_info_finish_insert(struct sta_info *sta, if (!sta->dummy || dummy_reinsert) { /* notify driver */ + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, + u.ap); err = drv_sta_add(local, sdata, &sta->sta); if (err) { if (!async) diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h index 1a14fab4bc9a..6280e8bca49d 100644 --- a/trunk/net/mac80211/sta_info.h +++ b/trunk/net/mac80211/sta_info.h @@ -88,7 +88,6 @@ enum ieee80211_sta_info_flags { * struct tid_ampdu_tx - TID aggregation information (Tx). * * @rcu_head: rcu head for freeing structure - * @session_timer: check if we keep Tx-ing on the TID (by timeout value) * @addba_resp_timer: timer for peer's response to addba request * @pending: pending frames queue -- use sta's spinlock to protect * @dialog_token: dialog token for aggregation session @@ -111,7 +110,6 @@ enum ieee80211_sta_info_flags { */ struct tid_ampdu_tx { struct rcu_head rcu_head; - struct timer_list session_timer; struct timer_list addba_resp_timer; struct sk_buff_head pending; unsigned long state; @@ -499,6 +497,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, */ int sta_info_insert(struct sta_info *sta); int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU); +int sta_info_insert_atomic(struct sta_info *sta); int sta_info_reinsert(struct sta_info *sta); int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index e74652d38245..8d31933abe6a 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -151,15 +151,11 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, rate = mrate; } - /* Don't calculate ACKs for QoS Frames with NoAck Policy set */ - if (ieee80211_is_data_qos(hdr->frame_control) && - *(ieee80211_get_qos_ctl(hdr)) | IEEE80211_QOS_CTL_ACK_POLICY_NOACK) - dur = 0; - else - /* Time needed to transmit ACK - * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up - * to closest integer */ - dur = ieee80211_frame_duration(local, 10, rate, erp, + /* Time needed to transmit ACK + * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up + * to closest integer */ + + dur = ieee80211_frame_duration(local, 10, rate, erp, tx->sdata->vif.bss_conf.use_short_preamble); if (next_frag_len) { @@ -640,7 +636,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) else txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || - tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || tx->sdata->vif.type == NL80211_IFTYPE_ADHOC); /* set up RTS protection if desired */ @@ -1068,11 +1063,9 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, int tid) { bool queued = false; - bool reset_agg_timer = false; if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { info->flags |= IEEE80211_TX_CTL_AMPDU; - reset_agg_timer = true; } else if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { /* * nothing -- this aggregation session is being started @@ -1104,7 +1097,6 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, /* do nothing, let packet pass through */ } else if (test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state)) { info->flags |= IEEE80211_TX_CTL_AMPDU; - reset_agg_timer = true; } else { queued = true; info->control.vif = &tx->sdata->vif; @@ -1114,11 +1106,6 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, spin_unlock(&tx->sta->lock); } - /* reset session timer */ - if (reset_agg_timer && tid_tx->timeout) - mod_timer(&tid_tx->session_timer, - TU_TO_EXP_TIME(tid_tx->timeout)); - return queued; } @@ -1186,8 +1173,16 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, if (is_multicast_ether_addr(hdr->addr1)) { tx->flags &= ~IEEE80211_TX_UNICAST; info->flags |= IEEE80211_TX_CTL_NO_ACK; - } else + } else { tx->flags |= IEEE80211_TX_UNICAST; + if (unlikely(local->wifi_wme_noack_test)) + info->flags |= IEEE80211_TX_CTL_NO_ACK; + /* + * Flags are initialized to 0. Hence, no need to + * explicitly unset IEEE80211_TX_CTL_NO_ACK since + * it might already be set for injected frames. + */ + } if (!(info->flags & IEEE80211_TX_CTL_DONTFRAG)) { if (!(tx->flags & IEEE80211_TX_UNICAST) || @@ -1228,10 +1223,9 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, * queue is woken again. */ if (txpending) - skb_queue_splice_init(skbs, &local->pending[q]); + skb_queue_splice(skbs, &local->pending[q]); else - skb_queue_splice_tail_init(skbs, - &local->pending[q]); + skb_queue_splice_tail(skbs, &local->pending[q]); spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); @@ -1303,7 +1297,7 @@ static bool __ieee80211_tx(struct ieee80211_local *local, ieee80211_tpt_led_trig_tx(local, fc, led_len); ieee80211_led_tx(local, 1); - WARN_ON_ONCE(!skb_queue_empty(skbs)); + WARN_ON(!skb_queue_empty(skbs)); return result; } @@ -1332,11 +1326,8 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) CALL_TXH(ieee80211_tx_h_rate_ctrl); - if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) { - __skb_queue_tail(&tx->skbs, tx->skb); - tx->skb = NULL; + if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) goto txh_done; - } CALL_TXH(ieee80211_tx_h_michael_mic_add); CALL_TXH(ieee80211_tx_h_sequence); @@ -1467,7 +1458,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) if (ieee80211_vif_is_mesh(&sdata->vif) && ieee80211_is_data(hdr->frame_control) && !is_multicast_ether_addr(hdr->addr1)) - if (mesh_nexthop_resolve(skb, sdata)) { + if (mesh_nexthop_lookup(skb, sdata)) { /* skb queued: don't free */ rcu_read_unlock(); return; @@ -2269,10 +2260,10 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss, /* Bitmap control */ *pos++ = n1 | aid0; /* Part Virt Bitmap */ - skb_put(skb, n2 - n1); memcpy(pos, bss->tim + n1, n2 - n1 + 1); tim[1] = n2 - n1 + 4; + skb_put(skb, n2 - n1); } else { *pos++ = aid0; /* Bitmap control */ *pos++ = 0; /* Part Virt Bitmap */ diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index ac7ea2949de0..3b9b492e9403 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -1192,6 +1192,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) struct ieee80211_sub_if_data, u.ap); + memset(&sta->sta.drv_priv, 0, hw->sta_data_size); WARN_ON(drv_sta_add(local, sdata, &sta->sta)); } } @@ -1243,11 +1244,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) changed |= BSS_CHANGED_IBSS; /* fall through */ case NL80211_IFTYPE_AP: - changed |= BSS_CHANGED_SSID; - - if (sdata->vif.type == NL80211_IFTYPE_AP) - changed |= BSS_CHANGED_AP_PROBE_RESP; - + changed |= BSS_CHANGED_SSID | + BSS_CHANGED_AP_PROBE_RESP; /* fall through */ case NL80211_IFTYPE_MESH_POINT: changed |= BSS_CHANGED_BEACON | @@ -1587,11 +1585,6 @@ u8 *ieee80211_ie_build_ht_info(u8 *pos, } if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; - - /* - * Note: According to 802.11n-2009 9.13.3.1, HT Protection field and - * RIFS Mode are reserved in IBSS mode, therefore keep them at 0 - */ ht_info->operation_mode = 0x0000; ht_info->stbc_param = 0x0000; diff --git a/trunk/net/mac80211/wme.c b/trunk/net/mac80211/wme.c index 89511be3111e..43327115b490 100644 --- a/trunk/net/mac80211/wme.c +++ b/trunk/net/mac80211/wme.c @@ -52,30 +52,6 @@ static int wme_downgrade_ac(struct sk_buff *skb) } } -/* Indicate which queue to use for this fully formed 802.11 frame */ -u16 ieee80211_select_queue_80211(struct ieee80211_local *local, - struct sk_buff *skb, - struct ieee80211_hdr *hdr) -{ - u8 *p; - - if (local->hw.queues < 4) - return 0; - - if (!ieee80211_is_data(hdr->frame_control)) { - skb->priority = 7; - return ieee802_1d_to_ac[skb->priority]; - } - if (!ieee80211_is_data_qos(hdr->frame_control)) { - skb->priority = 0; - return ieee802_1d_to_ac[skb->priority]; - } - - p = ieee80211_get_qos_ctl(hdr); - skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; - - return ieee80211_downgrade_queue(local, skb); -} /* Indicate which queue to use. */ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, @@ -163,7 +139,6 @@ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (void *)skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); /* Fill in the QoS header if there is one. */ if (ieee80211_is_data_qos(hdr->frame_control)) { @@ -175,12 +150,9 @@ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, /* preserve EOSP bit */ ack_policy = *p & IEEE80211_QOS_CTL_EOSP; - if (is_multicast_ether_addr(hdr->addr1) || - sdata->noack_map & BIT(tid)) { + if (unlikely(sdata->local->wifi_wme_noack_test) || + is_multicast_ether_addr(hdr->addr1)) ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; - info->flags |= IEEE80211_TX_CTL_NO_ACK; - } - /* qos header is 2 bytes */ *p++ = ack_policy | tid; *p = ieee80211_vif_is_mesh(&sdata->vif) ? diff --git a/trunk/net/mac80211/wme.h b/trunk/net/mac80211/wme.h index 94edceb617ff..34e166fbf4d4 100644 --- a/trunk/net/mac80211/wme.h +++ b/trunk/net/mac80211/wme.h @@ -15,9 +15,6 @@ extern const int ieee802_1d_to_ac[8]; -u16 ieee80211_select_queue_80211(struct ieee80211_local *local, - struct sk_buff *skb, - struct ieee80211_hdr *hdr); u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, diff --git a/trunk/net/mac80211/work.c b/trunk/net/mac80211/work.c index c6dd01a05291..6884a2d986dc 100644 --- a/trunk/net/mac80211/work.c +++ b/trunk/net/mac80211/work.c @@ -862,6 +862,44 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, kfree_skb(skb); } +static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct, + enum nl80211_channel_type oper_ct) +{ + switch (wk_ct) { + case NL80211_CHAN_NO_HT: + return true; + case NL80211_CHAN_HT20: + if (oper_ct != NL80211_CHAN_NO_HT) + return true; + return false; + case NL80211_CHAN_HT40MINUS: + case NL80211_CHAN_HT40PLUS: + return (wk_ct == oper_ct); + } + WARN_ON(1); /* shouldn't get here */ + 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; @@ -912,12 +950,40 @@ static void ieee80211_work_work(struct work_struct *work) } if (!started && !local->tmp_channel) { - ieee80211_offchannel_stop_vifs(local, true); + bool on_oper_chan, on_oper_chan2; + enum nl80211_channel_type wk_ct; - local->tmp_channel = wk->chan; - local->tmp_channel_type = wk->chan_type; + on_oper_chan = ieee80211_cfg_on_oper_channel(local); - ieee80211_hw_config(local, 0); + /* 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); + + 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. + */ + 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); + } + } started = true; wk->timeout = jiffies; @@ -986,17 +1052,34 @@ static void ieee80211_work_work(struct work_struct *work) list_for_each_entry(wk, &local->work_list, list) { if (!wk->started) continue; - if (wk->chan != local->tmp_channel || - wk->chan_type != local->tmp_channel_type) + if (wk->chan != local->tmp_channel) + continue; + if (!ieee80211_work_ct_coexists(wk->chan_type, + local->tmp_channel_type)) continue; remain_off_channel = true; } if (!remain_off_channel && local->tmp_channel) { local->tmp_channel = NULL; - ieee80211_hw_config(local, 0); + /* If tmp_channel wasn't operating channel, then + * we need to go back on-channel. + * NOTE: If we can ever be here while scannning, + * or if the hw_config() channel config logic changes, + * then we may need to do a more thorough check to see if + * 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_offchannel_return(local, true); + /* At the least, we need to disable offchannel_ps, + * so just go ahead and run the entire offchannel + * return logic here. We *could* skip enabling + * beaconing if we were already on-oper-channel + * as a future optimization. + */ + ieee80211_offchannel_return(local, true, true); /* give connection some time to breathe */ run_again(local, jiffies + HZ/2); diff --git a/trunk/net/netfilter/xt_TEE.c b/trunk/net/netfilter/xt_TEE.c index 68349c31083c..5f054a0dbbb1 100644 --- a/trunk/net/netfilter/xt_TEE.c +++ b/trunk/net/netfilter/xt_TEE.c @@ -29,6 +29,9 @@ # define WITH_CONNTRACK 1 # include #endif +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +# define WITH_IPV6 1 +#endif struct xt_tee_priv { struct notifier_block notifier; @@ -133,7 +136,7 @@ tee_tg4(struct sk_buff *skb, const struct xt_action_param *par) return XT_CONTINUE; } -#if IS_ENABLED(CONFIG_IPV6) +#ifdef WITH_IPV6 static bool tee_tg_route6(struct sk_buff *skb, const struct xt_tee_tginfo *info) { @@ -193,7 +196,7 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par) } return XT_CONTINUE; } -#endif +#endif /* WITH_IPV6 */ static int tee_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) @@ -273,7 +276,7 @@ static struct xt_target tee_tg_reg[] __read_mostly = { .destroy = tee_tg_destroy, .me = THIS_MODULE, }, -#if IS_ENABLED(CONFIG_IPV6) +#ifdef WITH_IPV6 { .name = "TEE", .revision = 1, diff --git a/trunk/net/netlabel/netlabel_addrlist.c b/trunk/net/netlabel/netlabel_addrlist.c index 6f1701322fb6..96b749dacc34 100644 --- a/trunk/net/netlabel/netlabel_addrlist.c +++ b/trunk/net/netlabel/netlabel_addrlist.c @@ -96,7 +96,7 @@ struct netlbl_af4list *netlbl_af4list_search_exact(__be32 addr, } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) /** * netlbl_af6list_search - Search for a matching IPv6 address entry * @addr: IPv6 address @@ -185,7 +185,7 @@ int netlbl_af4list_add(struct netlbl_af4list *entry, struct list_head *head) return 0; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) /** * netlbl_af6list_add - Add a new IPv6 address entry to a list * @entry: address entry @@ -263,7 +263,7 @@ struct netlbl_af4list *netlbl_af4list_remove(__be32 addr, __be32 mask, return entry; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) /** * netlbl_af6list_remove_entry - Remove an IPv6 address entry * @entry: address entry @@ -342,7 +342,7 @@ void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf, } } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) /** * netlbl_af6list_audit_addr - Audit an IPv6 address * @audit_buf: audit buffer diff --git a/trunk/net/netlabel/netlabel_addrlist.h b/trunk/net/netlabel/netlabel_addrlist.h index a1287ce18130..fdbc1d2c7352 100644 --- a/trunk/net/netlabel/netlabel_addrlist.h +++ b/trunk/net/netlabel/netlabel_addrlist.h @@ -133,7 +133,7 @@ static inline void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf, } #endif -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #define __af6list_entry(ptr) container_of(ptr, struct netlbl_af6list, list) diff --git a/trunk/net/netlabel/netlabel_domainhash.c b/trunk/net/netlabel/netlabel_domainhash.c index 38204112b9f4..3f905e5370c2 100644 --- a/trunk/net/netlabel/netlabel_domainhash.c +++ b/trunk/net/netlabel/netlabel_domainhash.c @@ -78,7 +78,7 @@ static void netlbl_domhsh_free_entry(struct rcu_head *entry) struct netlbl_dom_map *ptr; struct netlbl_af4list *iter4; struct netlbl_af4list *tmp4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct netlbl_af6list *iter6; struct netlbl_af6list *tmp6; #endif /* IPv6 */ @@ -90,7 +90,7 @@ static void netlbl_domhsh_free_entry(struct rcu_head *entry) netlbl_af4list_remove_entry(iter4); kfree(netlbl_domhsh_addr4_entry(iter4)); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) netlbl_af6list_foreach_safe(iter6, tmp6, &ptr->type_def.addrsel->list6) { netlbl_af6list_remove_entry(iter6); @@ -217,7 +217,7 @@ static void netlbl_domhsh_audit_add(struct netlbl_dom_map *entry, cipsov4 = map4->type_def.cipsov4; netlbl_af4list_audit_addr(audit_buf, 0, NULL, addr4->addr, addr4->mask); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) } else if (addr6 != NULL) { struct netlbl_domaddr6_map *map6; map6 = netlbl_domhsh_addr6_entry(addr6); @@ -306,7 +306,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, struct netlbl_dom_map *entry_old; struct netlbl_af4list *iter4; struct netlbl_af4list *tmp4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct netlbl_af6list *iter6; struct netlbl_af6list *tmp6; #endif /* IPv6 */ @@ -338,7 +338,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, &entry->type_def.addrsel->list4) netlbl_domhsh_audit_add(entry, iter4, NULL, ret_val, audit_info); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) netlbl_af6list_foreach_rcu(iter6, &entry->type_def.addrsel->list6) netlbl_domhsh_audit_add(entry, NULL, iter6, @@ -365,7 +365,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, ret_val = -EEXIST; goto add_return; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) netlbl_af6list_foreach_rcu(iter6, &entry->type_def.addrsel->list6) if (netlbl_af6list_search_exact(&iter6->addr, @@ -386,7 +386,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, if (ret_val != 0) goto add_return; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) netlbl_af6list_foreach_safe(iter6, tmp6, &entry->type_def.addrsel->list6) { netlbl_af6list_remove_entry(iter6); @@ -510,7 +510,7 @@ int netlbl_domhsh_remove_af4(const char *domain, struct netlbl_dom_map *entry_map; struct netlbl_af4list *entry_addr; struct netlbl_af4list *iter4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct netlbl_af6list *iter6; #endif /* IPv6 */ struct netlbl_domaddr4_map *entry; @@ -533,7 +533,7 @@ int netlbl_domhsh_remove_af4(const char *domain, goto remove_af4_failure; netlbl_af4list_foreach_rcu(iter4, &entry_map->type_def.addrsel->list4) goto remove_af4_single_addr; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) netlbl_af6list_foreach_rcu(iter6, &entry_map->type_def.addrsel->list6) goto remove_af4_single_addr; #endif /* IPv6 */ @@ -644,7 +644,7 @@ struct netlbl_domaddr4_map *netlbl_domhsh_getentry_af4(const char *domain, return netlbl_domhsh_addr4_entry(addr_iter); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) /** * netlbl_domhsh_getentry_af6 - Get an entry from the domain hash table * @domain: the domain name to search for diff --git a/trunk/net/netlabel/netlabel_domainhash.h b/trunk/net/netlabel/netlabel_domainhash.h index 90872c4ca30f..bfcc0f7024c5 100644 --- a/trunk/net/netlabel/netlabel_domainhash.h +++ b/trunk/net/netlabel/netlabel_domainhash.h @@ -104,7 +104,7 @@ int netlbl_domhsh_walk(u32 *skip_bkt, int (*callback) (struct netlbl_dom_map *entry, void *arg), void *cb_arg); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct netlbl_domaddr6_map *netlbl_domhsh_getentry_af6(const char *domain, const struct in6_addr *addr); #endif /* IPv6 */ diff --git a/trunk/net/netlabel/netlabel_kapi.c b/trunk/net/netlabel/netlabel_kapi.c index 2560e7b441c6..5952237c0c86 100644 --- a/trunk/net/netlabel/netlabel_kapi.c +++ b/trunk/net/netlabel/netlabel_kapi.c @@ -147,7 +147,7 @@ int netlbl_cfg_unlbl_map_add(const char *domain, goto cfg_unlbl_map_add_failure; break; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: { const struct in6_addr *addr6 = addr; const struct in6_addr *mask6 = mask; @@ -227,7 +227,7 @@ int netlbl_cfg_unlbl_static_add(struct net *net, case AF_INET: addr_len = sizeof(struct in_addr); break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: addr_len = sizeof(struct in6_addr); break; @@ -270,7 +270,7 @@ int netlbl_cfg_unlbl_static_del(struct net *net, case AF_INET: addr_len = sizeof(struct in_addr); break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: addr_len = sizeof(struct in6_addr); break; @@ -673,7 +673,7 @@ int netlbl_sock_setattr(struct sock *sk, ret_val = -ENOENT; } break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: /* since we don't support any IPv6 labeling protocols right * now we can optimize everything away until we do */ @@ -724,7 +724,7 @@ int netlbl_sock_getattr(struct sock *sk, case AF_INET: ret_val = cipso_v4_sock_getattr(sk, secattr); break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: ret_val = -ENOMSG; break; @@ -782,7 +782,7 @@ int netlbl_conn_setattr(struct sock *sk, ret_val = -ENOENT; } break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: /* since we don't support any IPv6 labeling protocols right * now we can optimize everything away until we do */ @@ -853,7 +853,7 @@ int netlbl_req_setattr(struct request_sock *req, ret_val = -ENOENT; } break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: /* since we don't support any IPv6 labeling protocols right * now we can optimize everything away until we do */ @@ -926,7 +926,7 @@ int netlbl_skbuff_setattr(struct sk_buff *skb, ret_val = -ENOENT; } break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: /* since we don't support any IPv6 labeling protocols right * now we can optimize everything away until we do */ @@ -965,7 +965,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, cipso_v4_skbuff_getattr(skb, secattr) == 0) return 0; break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: break; #endif /* IPv6 */ diff --git a/trunk/net/netlabel/netlabel_mgmt.c b/trunk/net/netlabel/netlabel_mgmt.c index 4809e2e48b02..9879300beefd 100644 --- a/trunk/net/netlabel/netlabel_mgmt.c +++ b/trunk/net/netlabel/netlabel_mgmt.c @@ -184,7 +184,7 @@ static int netlbl_mgmt_add_common(struct genl_info *info, entry->type = NETLBL_NLTYPE_ADDRSELECT; entry->type_def.addrsel = addrmap; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) } else if (info->attrs[NLBL_MGMT_A_IPV6ADDR]) { struct in6_addr *addr; struct in6_addr *mask; @@ -270,7 +270,7 @@ static int netlbl_mgmt_listentry(struct sk_buff *skb, struct nlattr *nla_a; struct nlattr *nla_b; struct netlbl_af4list *iter4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct netlbl_af6list *iter6; #endif @@ -324,7 +324,7 @@ static int netlbl_mgmt_listentry(struct sk_buff *skb, nla_nest_end(skb, nla_b); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) netlbl_af6list_foreach_rcu(iter6, &entry->type_def.addrsel->list6) { struct netlbl_domaddr6_map *map6; diff --git a/trunk/net/netlabel/netlabel_unlabeled.c b/trunk/net/netlabel/netlabel_unlabeled.c index 4b5fa0fe78fd..049ccd2447d7 100644 --- a/trunk/net/netlabel/netlabel_unlabeled.c +++ b/trunk/net/netlabel/netlabel_unlabeled.c @@ -170,7 +170,7 @@ static void netlbl_unlhsh_free_iface(struct rcu_head *entry) struct netlbl_unlhsh_iface *iface; struct netlbl_af4list *iter4; struct netlbl_af4list *tmp4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct netlbl_af6list *iter6; struct netlbl_af6list *tmp6; #endif /* IPv6 */ @@ -184,7 +184,7 @@ static void netlbl_unlhsh_free_iface(struct rcu_head *entry) netlbl_af4list_remove_entry(iter4); kfree(netlbl_unlhsh_addr4_entry(iter4)); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) netlbl_af6list_foreach_safe(iter6, tmp6, &iface->addr6_list) { netlbl_af6list_remove_entry(iter6); kfree(netlbl_unlhsh_addr6_entry(iter6)); @@ -274,7 +274,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, return ret_val; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) /** * netlbl_unlhsh_add_addr6 - Add a new IPv6 address entry to the hash table * @iface: the associated interface entry @@ -436,7 +436,7 @@ int netlbl_unlhsh_add(struct net *net, mask4->s_addr); break; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case sizeof(struct in6_addr): { const struct in6_addr *addr6 = addr; const struct in6_addr *mask6 = mask; @@ -531,7 +531,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net, return 0; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) /** * netlbl_unlhsh_remove_addr6 - Remove an IPv6 address entry * @net: network namespace @@ -606,14 +606,14 @@ static int netlbl_unlhsh_remove_addr6(struct net *net, static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface) { struct netlbl_af4list *iter4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct netlbl_af6list *iter6; #endif /* IPv6 */ spin_lock(&netlbl_unlhsh_lock); netlbl_af4list_foreach_rcu(iter4, &iface->addr4_list) goto unlhsh_condremove_failure; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) netlbl_af6list_foreach_rcu(iter6, &iface->addr6_list) goto unlhsh_condremove_failure; #endif /* IPv6 */ @@ -680,7 +680,7 @@ int netlbl_unlhsh_remove(struct net *net, iface, addr, mask, audit_info); break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case sizeof(struct in6_addr): ret_val = netlbl_unlhsh_remove_addr6(net, iface, addr, mask, @@ -1196,7 +1196,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, struct netlbl_unlhsh_iface *iface; struct list_head *iter_list; struct netlbl_af4list *addr4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct netlbl_af6list *addr6; #endif @@ -1228,7 +1228,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, goto unlabel_staticlist_return; } } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) { if (iter_addr6++ < skip_addr6) @@ -1277,7 +1277,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, u32 skip_addr6 = cb->args[1]; u32 iter_addr4 = 0; struct netlbl_af4list *addr4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) u32 iter_addr6 = 0; struct netlbl_af6list *addr6; #endif @@ -1303,7 +1303,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, goto unlabel_staticlistdef_return; } } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) { if (iter_addr6++ < skip_addr6) continue; @@ -1494,7 +1494,7 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb, secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid; break; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case PF_INET6: { struct ipv6hdr *hdr6; struct netlbl_af6list *addr6; diff --git a/trunk/net/nfc/core.c b/trunk/net/nfc/core.c index 3ebc6b3aabac..47e02c1b8c02 100644 --- a/trunk/net/nfc/core.c +++ b/trunk/net/nfc/core.c @@ -21,8 +21,6 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -35,6 +33,25 @@ int nfc_devlist_generation; DEFINE_MUTEX(nfc_devlist_mutex); +int nfc_printk(const char *level, const char *format, ...) +{ + struct va_format vaf; + va_list args; + int r; + + va_start(args, format); + + vaf.fmt = format; + vaf.va = &args; + + r = printk("%sNFC: %pV\n", level, &vaf); + + va_end(args); + + return r; +} +EXPORT_SYMBOL(nfc_printk); + /** * nfc_dev_up - turn on the NFC device * @@ -46,7 +63,7 @@ int nfc_dev_up(struct nfc_dev *dev) { int rc = 0; - pr_debug("dev_name=%s\n", dev_name(&dev->dev)); + nfc_dbg("dev_name=%s", dev_name(&dev->dev)); device_lock(&dev->dev); @@ -80,7 +97,7 @@ int nfc_dev_down(struct nfc_dev *dev) { int rc = 0; - pr_debug("dev_name=%s\n", dev_name(&dev->dev)); + nfc_dbg("dev_name=%s", dev_name(&dev->dev)); device_lock(&dev->dev); @@ -122,8 +139,7 @@ int nfc_start_poll(struct nfc_dev *dev, u32 protocols) { int rc; - pr_debug("dev_name=%s protocols=0x%x\n", - dev_name(&dev->dev), protocols); + nfc_dbg("dev_name=%s protocols=0x%x", dev_name(&dev->dev), protocols); if (!protocols) return -EINVAL; @@ -158,7 +174,7 @@ int nfc_stop_poll(struct nfc_dev *dev) { int rc = 0; - pr_debug("dev_name=%s\n", dev_name(&dev->dev)); + nfc_dbg("dev_name=%s", dev_name(&dev->dev)); device_lock(&dev->dev); @@ -191,8 +207,8 @@ int nfc_activate_target(struct nfc_dev *dev, u32 target_idx, u32 protocol) { int rc; - pr_debug("dev_name=%s target_idx=%u protocol=%u\n", - dev_name(&dev->dev), target_idx, protocol); + nfc_dbg("dev_name=%s target_idx=%u protocol=%u", dev_name(&dev->dev), + target_idx, protocol); device_lock(&dev->dev); @@ -220,8 +236,7 @@ int nfc_deactivate_target(struct nfc_dev *dev, u32 target_idx) { int rc = 0; - pr_debug("dev_name=%s target_idx=%u\n", - dev_name(&dev->dev), target_idx); + nfc_dbg("dev_name=%s target_idx=%u", dev_name(&dev->dev), target_idx); device_lock(&dev->dev); @@ -256,8 +271,8 @@ int nfc_data_exchange(struct nfc_dev *dev, u32 target_idx, { int rc; - pr_debug("dev_name=%s target_idx=%u skb->len=%u\n", - dev_name(&dev->dev), target_idx, skb->len); + nfc_dbg("dev_name=%s target_idx=%u skb->len=%u", dev_name(&dev->dev), + target_idx, skb->len); device_lock(&dev->dev); @@ -311,7 +326,7 @@ int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets, { int i; - pr_debug("dev_name=%s n_targets=%d\n", dev_name(&dev->dev), n_targets); + nfc_dbg("dev_name=%s n_targets=%d", dev_name(&dev->dev), n_targets); dev->polling = false; @@ -345,7 +360,7 @@ static void nfc_release(struct device *d) { struct nfc_dev *dev = to_nfc_dev(d); - pr_debug("dev_name=%s\n", dev_name(&dev->dev)); + nfc_dbg("dev_name=%s", dev_name(&dev->dev)); nfc_genl_data_exit(&dev->genl_data); kfree(dev->targets); @@ -431,7 +446,7 @@ int nfc_register_device(struct nfc_dev *dev) { int rc; - pr_debug("dev_name=%s\n", dev_name(&dev->dev)); + nfc_dbg("dev_name=%s", dev_name(&dev->dev)); mutex_lock(&nfc_devlist_mutex); nfc_devlist_generation++; @@ -443,8 +458,9 @@ int nfc_register_device(struct nfc_dev *dev) rc = nfc_genl_device_added(dev); if (rc) - pr_debug("The userspace won't be notified that the device %s was added\n", - dev_name(&dev->dev)); + nfc_dbg("The userspace won't be notified that the device %s was" + " added", dev_name(&dev->dev)); + return 0; } @@ -459,7 +475,7 @@ void nfc_unregister_device(struct nfc_dev *dev) { int rc; - pr_debug("dev_name=%s\n", dev_name(&dev->dev)); + nfc_dbg("dev_name=%s", dev_name(&dev->dev)); mutex_lock(&nfc_devlist_mutex); nfc_devlist_generation++; @@ -474,8 +490,8 @@ void nfc_unregister_device(struct nfc_dev *dev) rc = nfc_genl_device_removed(dev); if (rc) - pr_debug("The userspace won't be notified that the device %s was removed\n", - dev_name(&dev->dev)); + nfc_dbg("The userspace won't be notified that the device %s" + " was removed", dev_name(&dev->dev)); } EXPORT_SYMBOL(nfc_unregister_device); @@ -484,7 +500,7 @@ static int __init nfc_init(void) { int rc; - pr_info("NFC Core ver %s\n", VERSION); + nfc_info("NFC Core ver %s", VERSION); rc = class_register(&nfc_class); if (rc) diff --git a/trunk/net/nfc/nci/core.c b/trunk/net/nfc/nci/core.c index 37de28e97330..fe5ca89abfce 100644 --- a/trunk/net/nfc/nci/core.c +++ b/trunk/net/nfc/nci/core.c @@ -25,8 +25,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -81,7 +79,7 @@ static int __nci_request(struct nci_dev *ndev, &ndev->req_completion, timeout); - pr_debug("wait_for_completion return %ld\n", completion_rc); + nfc_dbg("wait_for_completion return %ld", completion_rc); if (completion_rc > 0) { switch (ndev->req_status) { @@ -98,8 +96,8 @@ static int __nci_request(struct nci_dev *ndev, break; } } else { - pr_err("wait_for_completion_interruptible_timeout failed %ld\n", - completion_rc); + nfc_err("wait_for_completion_interruptible_timeout failed %ld", + completion_rc); rc = ((completion_rc == 0) ? (-ETIMEDOUT) : (completion_rc)); } @@ -325,6 +323,8 @@ static void nci_cmd_timer(unsigned long arg) { struct nci_dev *ndev = (void *) arg; + nfc_dbg("entry"); + atomic_set(&ndev->cmd_cnt, 1); queue_work(ndev->cmd_wq, &ndev->cmd_work); } @@ -333,6 +333,8 @@ static int nci_dev_up(struct nfc_dev *nfc_dev) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); + nfc_dbg("entry"); + return nci_open_device(ndev); } @@ -340,6 +342,8 @@ static int nci_dev_down(struct nfc_dev *nfc_dev) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); + nfc_dbg("entry"); + return nci_close_device(ndev); } @@ -348,18 +352,20 @@ static int nci_start_poll(struct nfc_dev *nfc_dev, __u32 protocols) struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); int rc; + nfc_dbg("entry"); + if (test_bit(NCI_DISCOVERY, &ndev->flags)) { - pr_err("unable to start poll, since poll is already active\n"); + nfc_err("unable to start poll, since poll is already active"); return -EBUSY; } if (ndev->target_active_prot) { - pr_err("there is an active target\n"); + nfc_err("there is an active target"); return -EBUSY; } if (test_bit(NCI_POLL_ACTIVE, &ndev->flags)) { - pr_debug("target is active, implicitly deactivate...\n"); + nfc_dbg("target is active, implicitly deactivate..."); rc = nci_request(ndev, nci_rf_deactivate_req, 0, msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT)); @@ -380,8 +386,10 @@ static void nci_stop_poll(struct nfc_dev *nfc_dev) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); + nfc_dbg("entry"); + if (!test_bit(NCI_DISCOVERY, &ndev->flags)) { - pr_err("unable to stop poll, since poll is not active\n"); + nfc_err("unable to stop poll, since poll is not active"); return; } @@ -394,21 +402,21 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, __u32 target_idx, { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); - pr_debug("target_idx %d, protocol 0x%x\n", target_idx, protocol); + nfc_dbg("entry, target_idx %d, protocol 0x%x", target_idx, protocol); if (!test_bit(NCI_POLL_ACTIVE, &ndev->flags)) { - pr_err("there is no available target to activate\n"); + nfc_err("there is no available target to activate"); return -EINVAL; } if (ndev->target_active_prot) { - pr_err("there is already an active target\n"); + nfc_err("there is already an active target"); return -EBUSY; } if (!(ndev->target_available_prots & (1 << protocol))) { - pr_err("target does not support the requested protocol 0x%x\n", - protocol); + nfc_err("target does not support the requested protocol 0x%x", + protocol); return -EINVAL; } @@ -422,10 +430,10 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, __u32 target_idx) { struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); - pr_debug("target_idx %d\n", target_idx); + nfc_dbg("entry, target_idx %d", target_idx); if (!ndev->target_active_prot) { - pr_err("unable to deactivate target, no active target\n"); + nfc_err("unable to deactivate target, no active target"); return; } @@ -445,10 +453,10 @@ static int nci_data_exchange(struct nfc_dev *nfc_dev, __u32 target_idx, struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); int rc; - pr_debug("target_idx %d, len %d\n", target_idx, skb->len); + nfc_dbg("entry, target_idx %d, len %d", target_idx, skb->len); if (!ndev->target_active_prot) { - pr_err("unable to exchange data, no active target\n"); + nfc_err("unable to exchange data, no active target"); return -EINVAL; } @@ -491,7 +499,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, { struct nci_dev *ndev; - pr_debug("supported_protocols 0x%x\n", supported_protocols); + nfc_dbg("entry, supported_protocols 0x%x", supported_protocols); if (!ops->open || !ops->close || !ops->send) return NULL; @@ -531,6 +539,8 @@ EXPORT_SYMBOL(nci_allocate_device); */ void nci_free_device(struct nci_dev *ndev) { + nfc_dbg("entry"); + nfc_free_device(ndev->nfc_dev); kfree(ndev); } @@ -547,6 +557,8 @@ int nci_register_device(struct nci_dev *ndev) struct device *dev = &ndev->nfc_dev->dev; char name[32]; + nfc_dbg("entry"); + rc = nfc_register_device(ndev->nfc_dev); if (rc) goto exit; @@ -609,6 +621,8 @@ EXPORT_SYMBOL(nci_register_device); */ void nci_unregister_device(struct nci_dev *ndev) { + nfc_dbg("entry"); + nci_close_device(ndev); destroy_workqueue(ndev->cmd_wq); @@ -628,7 +642,7 @@ int nci_recv_frame(struct sk_buff *skb) { struct nci_dev *ndev = (struct nci_dev *) skb->dev; - pr_debug("len %d\n", skb->len); + nfc_dbg("entry, len %d", skb->len); if (!ndev || (!test_bit(NCI_UP, &ndev->flags) && !test_bit(NCI_INIT, &ndev->flags))) { @@ -648,7 +662,7 @@ static int nci_send_frame(struct sk_buff *skb) { struct nci_dev *ndev = (struct nci_dev *) skb->dev; - pr_debug("len %d\n", skb->len); + nfc_dbg("entry, len %d", skb->len); if (!ndev) { kfree_skb(skb); @@ -667,11 +681,11 @@ int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload) struct nci_ctrl_hdr *hdr; struct sk_buff *skb; - pr_debug("opcode 0x%x, plen %d\n", opcode, plen); + nfc_dbg("entry, opcode 0x%x, plen %d", opcode, plen); skb = nci_skb_alloc(ndev, (NCI_CTRL_HDR_SIZE + plen), GFP_KERNEL); if (!skb) { - pr_err("no memory for command\n"); + nfc_err("no memory for command"); return -ENOMEM; } @@ -701,7 +715,7 @@ static void nci_tx_work(struct work_struct *work) struct nci_dev *ndev = container_of(work, struct nci_dev, tx_work); struct sk_buff *skb; - pr_debug("credits_cnt %d\n", atomic_read(&ndev->credits_cnt)); + nfc_dbg("entry, credits_cnt %d", atomic_read(&ndev->credits_cnt)); /* Send queued tx data */ while (atomic_read(&ndev->credits_cnt)) { @@ -714,10 +728,10 @@ static void nci_tx_work(struct work_struct *work) NCI_DATA_FLOW_CONTROL_NOT_USED) atomic_dec(&ndev->credits_cnt); - pr_debug("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d\n", - nci_pbf(skb->data), - nci_conn_id(skb->data), - nci_plen(skb->data)); + nfc_dbg("NCI TX: MT=data, PBF=%d, conn_id=%d, plen=%d", + nci_pbf(skb->data), + nci_conn_id(skb->data), + nci_plen(skb->data)); nci_send_frame(skb); } @@ -746,7 +760,7 @@ static void nci_rx_work(struct work_struct *work) break; default: - pr_err("unknown MT 0x%x\n", nci_mt(skb->data)); + nfc_err("unknown MT 0x%x", nci_mt(skb->data)); kfree_skb(skb); break; } @@ -760,7 +774,7 @@ static void nci_cmd_work(struct work_struct *work) struct nci_dev *ndev = container_of(work, struct nci_dev, cmd_work); struct sk_buff *skb; - pr_debug("cmd_cnt %d\n", atomic_read(&ndev->cmd_cnt)); + nfc_dbg("entry, cmd_cnt %d", atomic_read(&ndev->cmd_cnt)); /* Send queued command */ if (atomic_read(&ndev->cmd_cnt)) { @@ -770,11 +784,11 @@ static void nci_cmd_work(struct work_struct *work) atomic_dec(&ndev->cmd_cnt); - pr_debug("NCI TX: MT=cmd, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n", - nci_pbf(skb->data), - nci_opcode_gid(nci_opcode(skb->data)), - nci_opcode_oid(nci_opcode(skb->data)), - nci_plen(skb->data)); + nfc_dbg("NCI TX: MT=cmd, PBF=%d, GID=0x%x, OID=0x%x, plen=%d", + nci_pbf(skb->data), + nci_opcode_gid(nci_opcode(skb->data)), + nci_opcode_oid(nci_opcode(skb->data)), + nci_plen(skb->data)); nci_send_frame(skb); diff --git a/trunk/net/nfc/nci/data.c b/trunk/net/nfc/nci/data.c index 1e040feb2f84..511fb96e21bc 100644 --- a/trunk/net/nfc/nci/data.c +++ b/trunk/net/nfc/nci/data.c @@ -21,8 +21,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -42,7 +40,7 @@ void nci_data_exchange_complete(struct nci_dev *ndev, data_exchange_cb_t cb = ndev->data_exchange_cb; void *cb_context = ndev->data_exchange_cb_context; - pr_debug("len %d, err %d\n", skb ? skb->len : 0, err); + nfc_dbg("entry, len %d, err %d", ((skb) ? (skb->len) : (0)), err); if (cb) { ndev->data_exchange_cb = NULL; @@ -51,7 +49,7 @@ void nci_data_exchange_complete(struct nci_dev *ndev, /* forward skb to nfc core */ cb(cb_context, skb, err); } else if (skb) { - pr_err("no rx callback, dropping rx data...\n"); + nfc_err("no rx callback, dropping rx data..."); /* no waiting callback, free skb */ kfree_skb(skb); @@ -92,7 +90,7 @@ static int nci_queue_tx_data_frags(struct nci_dev *ndev, int frag_len; int rc = 0; - pr_debug("conn_id 0x%x, total_len %d\n", conn_id, total_len); + nfc_dbg("entry, conn_id 0x%x, total_len %d", conn_id, total_len); __skb_queue_head_init(&frags_q); @@ -121,8 +119,8 @@ static int nci_queue_tx_data_frags(struct nci_dev *ndev, data += frag_len; total_len -= frag_len; - pr_debug("frag_len %d, remaining total_len %d\n", - frag_len, total_len); + nfc_dbg("frag_len %d, remaining total_len %d", + frag_len, total_len); } /* queue all fragments atomically */ @@ -151,7 +149,7 @@ int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb) { int rc = 0; - pr_debug("conn_id 0x%x, plen %d\n", conn_id, skb->len); + nfc_dbg("entry, conn_id 0x%x, plen %d", conn_id, skb->len); /* check if the packet need to be fragmented */ if (skb->len <= ndev->max_data_pkt_payload_size) { @@ -163,7 +161,7 @@ int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb) /* fragment packet and queue the fragments */ rc = nci_queue_tx_data_frags(ndev, conn_id, skb); if (rc) { - pr_err("failed to fragment tx data packet\n"); + nfc_err("failed to fragment tx data packet"); goto free_exit; } } @@ -193,7 +191,7 @@ static void nci_add_rx_data_frag(struct nci_dev *ndev, /* first, make enough room for the already accumulated data */ if (skb_cow_head(skb, reassembly_len)) { - pr_err("error adding room for accumulated rx data\n"); + nfc_err("error adding room for accumulated rx data"); kfree_skb(skb); skb = 0; @@ -230,19 +228,19 @@ void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb) { __u8 pbf = nci_pbf(skb->data); - pr_debug("len %d\n", skb->len); + nfc_dbg("entry, len %d", skb->len); - pr_debug("NCI RX: MT=data, PBF=%d, conn_id=%d, plen=%d\n", - nci_pbf(skb->data), - nci_conn_id(skb->data), - nci_plen(skb->data)); + nfc_dbg("NCI RX: MT=data, PBF=%d, conn_id=%d, plen=%d", + nci_pbf(skb->data), + nci_conn_id(skb->data), + nci_plen(skb->data)); /* strip the nci data header */ skb_pull(skb, NCI_DATA_HDR_SIZE); if (ndev->target_active_prot == NFC_PROTO_MIFARE) { /* frame I/F => remove the status byte */ - pr_debug("NFC_PROTO_MIFARE => remove the status byte\n"); + nfc_dbg("NFC_PROTO_MIFARE => remove the status byte"); skb_trim(skb, (skb->len - 1)); } diff --git a/trunk/net/nfc/nci/ntf.c b/trunk/net/nfc/nci/ntf.c index c36bd4a09abb..c1bf54172c25 100644 --- a/trunk/net/nfc/nci/ntf.c +++ b/trunk/net/nfc/nci/ntf.c @@ -25,8 +25,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -45,16 +43,16 @@ static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, struct nci_core_conn_credit_ntf *ntf = (void *) skb->data; int i; - pr_debug("num_entries %d\n", ntf->num_entries); + nfc_dbg("entry, num_entries %d", ntf->num_entries); if (ntf->num_entries > NCI_MAX_NUM_CONN) ntf->num_entries = NCI_MAX_NUM_CONN; /* update the credits */ for (i = 0; i < ntf->num_entries; i++) { - pr_debug("entry[%d]: conn_id %d, credits %d\n", - i, ntf->conn_entries[i].conn_id, - ntf->conn_entries[i].credits); + nfc_dbg("entry[%d]: conn_id %d, credits %d", i, + ntf->conn_entries[i].conn_id, + ntf->conn_entries[i].credits); if (ntf->conn_entries[i].conn_id == NCI_STATIC_RF_CONN_ID) { /* found static rf connection */ @@ -80,8 +78,9 @@ static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, nfca_poll->nfcid1_len = *data++; - pr_debug("sens_res 0x%x, nfcid1_len %d\n", - nfca_poll->sens_res, nfca_poll->nfcid1_len); + nfc_dbg("sens_res 0x%x, nfcid1_len %d", + nfca_poll->sens_res, + nfca_poll->nfcid1_len); memcpy(nfca_poll->nfcid1, data, nfca_poll->nfcid1_len); data += nfca_poll->nfcid1_len; @@ -91,9 +90,9 @@ static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, if (nfca_poll->sel_res_len != 0) nfca_poll->sel_res = *data++; - pr_debug("sel_res_len %d, sel_res 0x%x\n", - nfca_poll->sel_res_len, - nfca_poll->sel_res); + nfc_dbg("sel_res_len %d, sel_res 0x%x", + nfca_poll->sel_res_len, + nfca_poll->sel_res); return data; } @@ -115,8 +114,8 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev, break; default: - pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", - ntf->activation_rf_tech_and_mode); + nfc_err("unsupported activation_rf_tech_and_mode 0x%x", + ntf->activation_rf_tech_and_mode); return -EPROTO; } @@ -139,12 +138,12 @@ static void nci_target_found(struct nci_dev *ndev, nfc_tgt.sel_res = ntf->rf_tech_specific_params.nfca_poll.sel_res; if (!(nfc_tgt.supported_protocols & ndev->poll_prots)) { - pr_debug("the target found does not have the desired protocol\n"); + nfc_dbg("the target found does not have the desired protocol"); return; } - pr_debug("new target found, supported_protocols 0x%x\n", - nfc_tgt.supported_protocols); + nfc_dbg("new target found, supported_protocols 0x%x", + nfc_tgt.supported_protocols); ndev->target_available_prots = nfc_tgt.supported_protocols; @@ -167,13 +166,13 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, ntf.activation_rf_tech_and_mode = *data++; ntf.rf_tech_specific_params_len = *data++; - pr_debug("rf_discovery_id %d\n", ntf.rf_discovery_id); - pr_debug("rf_interface_type 0x%x\n", ntf.rf_interface_type); - pr_debug("rf_protocol 0x%x\n", ntf.rf_protocol); - pr_debug("activation_rf_tech_and_mode 0x%x\n", - ntf.activation_rf_tech_and_mode); - pr_debug("rf_tech_specific_params_len %d\n", - ntf.rf_tech_specific_params_len); + nfc_dbg("rf_discovery_id %d", ntf.rf_discovery_id); + nfc_dbg("rf_interface_type 0x%x", ntf.rf_interface_type); + nfc_dbg("rf_protocol 0x%x", ntf.rf_protocol); + nfc_dbg("activation_rf_tech_and_mode 0x%x", + ntf.activation_rf_tech_and_mode); + nfc_dbg("rf_tech_specific_params_len %d", + ntf.rf_tech_specific_params_len); if (ntf.rf_tech_specific_params_len > 0) { switch (ntf.activation_rf_tech_and_mode) { @@ -183,8 +182,8 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, break; default: - pr_err("unsupported activation_rf_tech_and_mode 0x%x\n", - ntf.activation_rf_tech_and_mode); + nfc_err("unsupported activation_rf_tech_and_mode 0x%x", + ntf.activation_rf_tech_and_mode); return; } } @@ -194,14 +193,14 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, ntf.data_exch_rx_bit_rate = *data++; ntf.activation_params_len = *data++; - pr_debug("data_exch_rf_tech_and_mode 0x%x\n", - ntf.data_exch_rf_tech_and_mode); - pr_debug("data_exch_tx_bit_rate 0x%x\n", - ntf.data_exch_tx_bit_rate); - pr_debug("data_exch_rx_bit_rate 0x%x\n", - ntf.data_exch_rx_bit_rate); - pr_debug("activation_params_len %d\n", - ntf.activation_params_len); + nfc_dbg("data_exch_rf_tech_and_mode 0x%x", + ntf.data_exch_rf_tech_and_mode); + nfc_dbg("data_exch_tx_bit_rate 0x%x", + ntf.data_exch_tx_bit_rate); + nfc_dbg("data_exch_rx_bit_rate 0x%x", + ntf.data_exch_rx_bit_rate); + nfc_dbg("activation_params_len %d", + ntf.activation_params_len); if (ntf.activation_params_len > 0) { switch (ntf.rf_interface_type) { @@ -215,8 +214,8 @@ static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev, break; default: - pr_err("unsupported rf_interface_type 0x%x\n", - ntf.rf_interface_type); + nfc_err("unsupported rf_interface_type 0x%x", + ntf.rf_interface_type); return; } } @@ -230,7 +229,7 @@ static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, { struct nci_rf_deactivate_ntf *ntf = (void *) skb->data; - pr_debug("entry, type 0x%x, reason 0x%x\n", ntf->type, ntf->reason); + nfc_dbg("entry, type 0x%x, reason 0x%x", ntf->type, ntf->reason); clear_bit(NCI_POLL_ACTIVE, &ndev->flags); ndev->target_active_prot = 0; @@ -256,11 +255,11 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) { __u16 ntf_opcode = nci_opcode(skb->data); - pr_debug("NCI RX: MT=ntf, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n", - nci_pbf(skb->data), - nci_opcode_gid(ntf_opcode), - nci_opcode_oid(ntf_opcode), - nci_plen(skb->data)); + nfc_dbg("NCI RX: MT=ntf, PBF=%d, GID=0x%x, OID=0x%x, plen=%d", + nci_pbf(skb->data), + nci_opcode_gid(ntf_opcode), + nci_opcode_oid(ntf_opcode), + nci_plen(skb->data)); /* strip the nci control header */ skb_pull(skb, NCI_CTRL_HDR_SIZE); @@ -279,7 +278,7 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) break; default: - pr_err("unknown ntf opcode 0x%x\n", ntf_opcode); + nfc_err("unknown ntf opcode 0x%x", ntf_opcode); break; } diff --git a/trunk/net/nfc/nci/rsp.c b/trunk/net/nfc/nci/rsp.c index ca611c52aaaa..0591f5aff89f 100644 --- a/trunk/net/nfc/nci/rsp.c +++ b/trunk/net/nfc/nci/rsp.c @@ -25,8 +25,6 @@ * */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -42,12 +40,12 @@ static void nci_core_reset_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) { struct nci_core_reset_rsp *rsp = (void *) skb->data; - pr_debug("status 0x%x\n", rsp->status); + nfc_dbg("entry, status 0x%x", rsp->status); if (rsp->status == NCI_STATUS_OK) { ndev->nci_ver = rsp->nci_ver; - pr_debug("nci_ver 0x%x, config_status 0x%x\n", - rsp->nci_ver, rsp->config_status); + nfc_dbg("nci_ver 0x%x, config_status 0x%x", + rsp->nci_ver, rsp->config_status); } nci_req_complete(ndev, rsp->status); @@ -58,7 +56,7 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) struct nci_core_init_rsp_1 *rsp_1 = (void *) skb->data; struct nci_core_init_rsp_2 *rsp_2; - pr_debug("status 0x%x\n", rsp_1->status); + nfc_dbg("entry, status 0x%x", rsp_1->status); if (rsp_1->status != NCI_STATUS_OK) goto exit; @@ -97,34 +95,34 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) atomic_set(&ndev->credits_cnt, ndev->initial_num_credits); - pr_debug("nfcc_features 0x%x\n", - ndev->nfcc_features); - pr_debug("num_supported_rf_interfaces %d\n", - ndev->num_supported_rf_interfaces); - pr_debug("supported_rf_interfaces[0] 0x%x\n", - ndev->supported_rf_interfaces[0]); - pr_debug("supported_rf_interfaces[1] 0x%x\n", - ndev->supported_rf_interfaces[1]); - pr_debug("supported_rf_interfaces[2] 0x%x\n", - ndev->supported_rf_interfaces[2]); - pr_debug("supported_rf_interfaces[3] 0x%x\n", - ndev->supported_rf_interfaces[3]); - pr_debug("max_logical_connections %d\n", - ndev->max_logical_connections); - pr_debug("max_routing_table_size %d\n", - ndev->max_routing_table_size); - pr_debug("max_ctrl_pkt_payload_len %d\n", - ndev->max_ctrl_pkt_payload_len); - pr_debug("max_size_for_large_params %d\n", - ndev->max_size_for_large_params); - pr_debug("max_data_pkt_payload_size %d\n", - ndev->max_data_pkt_payload_size); - pr_debug("initial_num_credits %d\n", - ndev->initial_num_credits); - pr_debug("manufact_id 0x%x\n", - ndev->manufact_id); - pr_debug("manufact_specific_info 0x%x\n", - ndev->manufact_specific_info); + nfc_dbg("nfcc_features 0x%x", + ndev->nfcc_features); + nfc_dbg("num_supported_rf_interfaces %d", + ndev->num_supported_rf_interfaces); + nfc_dbg("supported_rf_interfaces[0] 0x%x", + ndev->supported_rf_interfaces[0]); + nfc_dbg("supported_rf_interfaces[1] 0x%x", + ndev->supported_rf_interfaces[1]); + nfc_dbg("supported_rf_interfaces[2] 0x%x", + ndev->supported_rf_interfaces[2]); + nfc_dbg("supported_rf_interfaces[3] 0x%x", + ndev->supported_rf_interfaces[3]); + nfc_dbg("max_logical_connections %d", + ndev->max_logical_connections); + nfc_dbg("max_routing_table_size %d", + ndev->max_routing_table_size); + nfc_dbg("max_ctrl_pkt_payload_len %d", + ndev->max_ctrl_pkt_payload_len); + nfc_dbg("max_size_for_large_params %d", + ndev->max_size_for_large_params); + nfc_dbg("max_data_pkt_payload_size %d", + ndev->max_data_pkt_payload_size); + nfc_dbg("initial_num_credits %d", + ndev->initial_num_credits); + nfc_dbg("manufact_id 0x%x", + ndev->manufact_id); + nfc_dbg("manufact_specific_info 0x%x", + ndev->manufact_specific_info); exit: nci_req_complete(ndev, rsp_1->status); @@ -135,7 +133,7 @@ static void nci_rf_disc_map_rsp_packet(struct nci_dev *ndev, { __u8 status = skb->data[0]; - pr_debug("status 0x%x\n", status); + nfc_dbg("entry, status 0x%x", status); nci_req_complete(ndev, status); } @@ -144,7 +142,7 @@ static void nci_rf_disc_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) { __u8 status = skb->data[0]; - pr_debug("status 0x%x\n", status); + nfc_dbg("entry, status 0x%x", status); if (status == NCI_STATUS_OK) set_bit(NCI_DISCOVERY, &ndev->flags); @@ -157,7 +155,7 @@ static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev, { __u8 status = skb->data[0]; - pr_debug("status 0x%x\n", status); + nfc_dbg("entry, status 0x%x", status); clear_bit(NCI_DISCOVERY, &ndev->flags); @@ -171,11 +169,11 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) /* we got a rsp, stop the cmd timer */ del_timer(&ndev->cmd_timer); - pr_debug("NCI RX: MT=rsp, PBF=%d, GID=0x%x, OID=0x%x, plen=%d\n", - nci_pbf(skb->data), - nci_opcode_gid(rsp_opcode), - nci_opcode_oid(rsp_opcode), - nci_plen(skb->data)); + nfc_dbg("NCI RX: MT=rsp, PBF=%d, GID=0x%x, OID=0x%x, plen=%d", + nci_pbf(skb->data), + nci_opcode_gid(rsp_opcode), + nci_opcode_oid(rsp_opcode), + nci_plen(skb->data)); /* strip the nci control header */ skb_pull(skb, NCI_CTRL_HDR_SIZE); @@ -202,7 +200,7 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) break; default: - pr_err("unknown rsp opcode 0x%x\n", rsp_opcode); + nfc_err("unknown rsp opcode 0x%x", rsp_opcode); break; } diff --git a/trunk/net/nfc/netlink.c b/trunk/net/nfc/netlink.c index c10e9b8c5ad9..03f8818e1f16 100644 --- a/trunk/net/nfc/netlink.c +++ b/trunk/net/nfc/netlink.c @@ -21,8 +21,6 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -53,6 +51,8 @@ static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, { void *hdr; + nfc_dbg("entry"); + hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, &nfc_genl_family, flags, NFC_CMD_GET_TARGET); if (!hdr) @@ -105,6 +105,8 @@ static int nfc_genl_dump_targets(struct sk_buff *skb, struct nfc_dev *dev = (struct nfc_dev *) cb->args[1]; int rc; + nfc_dbg("entry"); + if (!dev) { dev = __get_device_from_cb(cb); if (IS_ERR(dev)) @@ -137,6 +139,8 @@ static int nfc_genl_dump_targets_done(struct netlink_callback *cb) { struct nfc_dev *dev = (struct nfc_dev *) cb->args[1]; + nfc_dbg("entry"); + if (dev) nfc_put_device(dev); @@ -148,6 +152,8 @@ int nfc_genl_targets_found(struct nfc_dev *dev) struct sk_buff *msg; void *hdr; + nfc_dbg("entry"); + dev->genl_data.poll_req_pid = 0; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); @@ -177,6 +183,8 @@ int nfc_genl_device_added(struct nfc_dev *dev) struct sk_buff *msg; void *hdr; + nfc_dbg("entry"); + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) return -ENOMEM; @@ -208,6 +216,8 @@ int nfc_genl_device_removed(struct nfc_dev *dev) struct sk_buff *msg; void *hdr; + nfc_dbg("entry"); + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) return -ENOMEM; @@ -239,6 +249,8 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, { void *hdr; + nfc_dbg("entry"); + hdr = genlmsg_put(msg, pid, seq, &nfc_genl_family, flags, NFC_CMD_GET_DEVICE); if (!hdr) @@ -265,6 +277,8 @@ static int nfc_genl_dump_devices(struct sk_buff *skb, struct nfc_dev *dev = (struct nfc_dev *) cb->args[1]; bool first_call = false; + nfc_dbg("entry"); + if (!iter) { first_call = true; iter = kmalloc(sizeof(struct class_dev_iter), GFP_KERNEL); @@ -305,6 +319,8 @@ static int nfc_genl_dump_devices_done(struct netlink_callback *cb) { struct class_dev_iter *iter = (struct class_dev_iter *) cb->args[0]; + nfc_dbg("entry"); + nfc_device_iter_exit(iter); kfree(iter); @@ -318,6 +334,8 @@ static int nfc_genl_get_device(struct sk_buff *skb, struct genl_info *info) u32 idx; int rc = -ENOBUFS; + nfc_dbg("entry"); + if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) return -EINVAL; @@ -355,6 +373,8 @@ static int nfc_genl_dev_up(struct sk_buff *skb, struct genl_info *info) int rc; u32 idx; + nfc_dbg("entry"); + if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) return -EINVAL; @@ -376,6 +396,8 @@ static int nfc_genl_dev_down(struct sk_buff *skb, struct genl_info *info) int rc; u32 idx; + nfc_dbg("entry"); + if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) return -EINVAL; @@ -398,6 +420,8 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) u32 idx; u32 protocols; + nfc_dbg("entry"); + if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || !info->attrs[NFC_ATTR_PROTOCOLS]) return -EINVAL; @@ -427,6 +451,8 @@ static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info) int rc; u32 idx; + nfc_dbg("entry"); + if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) return -EINVAL; @@ -498,7 +524,7 @@ static int nfc_genl_rcv_nl_event(struct notifier_block *this, if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC) goto out; - pr_debug("NETLINK_URELEASE event from id %d\n", n->pid); + nfc_dbg("NETLINK_URELEASE event from id %d", n->pid); nfc_device_iter_init(&iter); dev = nfc_device_iter_next(&iter); diff --git a/trunk/net/nfc/nfc.h b/trunk/net/nfc/nfc.h index 67d605015304..d86583f4831d 100644 --- a/trunk/net/nfc/nfc.h +++ b/trunk/net/nfc/nfc.h @@ -27,6 +27,13 @@ #include #include +__printf(2, 3) +int nfc_printk(const char *level, const char *fmt, ...); + +#define nfc_info(fmt, arg...) nfc_printk(KERN_INFO, fmt, ##arg) +#define nfc_err(fmt, arg...) nfc_printk(KERN_ERR, fmt, ##arg) +#define nfc_dbg(fmt, arg...) pr_debug(fmt "\n", ##arg) + struct nfc_protocol { int id; struct proto *proto; diff --git a/trunk/net/nfc/rawsock.c b/trunk/net/nfc/rawsock.c index 68ecf3fa94e0..ee7b2b365ef2 100644 --- a/trunk/net/nfc/rawsock.c +++ b/trunk/net/nfc/rawsock.c @@ -21,8 +21,6 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include #include #include @@ -31,7 +29,7 @@ static void rawsock_write_queue_purge(struct sock *sk) { - pr_debug("sk=%p\n", sk); + nfc_dbg("sk=%p", sk); spin_lock_bh(&sk->sk_write_queue.lock); __skb_queue_purge(&sk->sk_write_queue); @@ -41,7 +39,7 @@ static void rawsock_write_queue_purge(struct sock *sk) static void rawsock_report_error(struct sock *sk, int err) { - pr_debug("sk=%p err=%d\n", sk, err); + nfc_dbg("sk=%p err=%d", sk, err); sk->sk_shutdown = SHUTDOWN_MASK; sk->sk_err = -err; @@ -54,7 +52,7 @@ static int rawsock_release(struct socket *sock) { struct sock *sk = sock->sk; - pr_debug("sock=%p\n", sock); + nfc_dbg("sock=%p", sock); sock_orphan(sk); sock_put(sk); @@ -70,14 +68,14 @@ static int rawsock_connect(struct socket *sock, struct sockaddr *_addr, struct nfc_dev *dev; int rc = 0; - pr_debug("sock=%p sk=%p flags=%d\n", sock, sk, flags); + nfc_dbg("sock=%p sk=%p flags=%d", sock, sk, flags); if (!addr || len < sizeof(struct sockaddr_nfc) || addr->sa_family != AF_NFC) return -EINVAL; - pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", - addr->dev_idx, addr->target_idx, addr->nfc_protocol); + nfc_dbg("addr dev_idx=%u target_idx=%u protocol=%u", addr->dev_idx, + addr->target_idx, addr->nfc_protocol); lock_sock(sk); @@ -138,7 +136,7 @@ static void rawsock_data_exchange_complete(void *context, struct sk_buff *skb, BUG_ON(in_irq()); - pr_debug("sk=%p err=%d\n", sk, err); + nfc_dbg("sk=%p err=%d", sk, err); if (err) goto error; @@ -174,7 +172,7 @@ static void rawsock_tx_work(struct work_struct *work) struct sk_buff *skb; int rc; - pr_debug("sk=%p target_idx=%u\n", sk, target_idx); + nfc_dbg("sk=%p target_idx=%u", sk, target_idx); if (sk->sk_shutdown & SEND_SHUTDOWN) { rawsock_write_queue_purge(sk); @@ -200,7 +198,7 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb; int rc; - pr_debug("sock=%p sk=%p len=%zu\n", sock, sk, len); + nfc_dbg("sock=%p sk=%p len=%zu", sock, sk, len); if (msg->msg_namelen) return -EOPNOTSUPP; @@ -241,7 +239,7 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock, int copied; int rc; - pr_debug("sock=%p sk=%p len=%zu flags=%d\n", sock, sk, len, flags); + nfc_dbg("sock=%p sk=%p len=%zu flags=%d", sock, sk, len, flags); skb = skb_recv_datagram(sk, flags, noblock, &rc); if (!skb) @@ -285,7 +283,7 @@ static const struct proto_ops rawsock_ops = { static void rawsock_destruct(struct sock *sk) { - pr_debug("sk=%p\n", sk); + nfc_dbg("sk=%p", sk); if (sk->sk_state == TCP_ESTABLISHED) { nfc_deactivate_target(nfc_rawsock(sk)->dev, @@ -296,7 +294,7 @@ static void rawsock_destruct(struct sock *sk) skb_queue_purge(&sk->sk_receive_queue); if (!sock_flag(sk, SOCK_DEAD)) { - pr_err("Freeing alive NFC raw socket %p\n", sk); + nfc_err("Freeing alive NFC raw socket %p", sk); return; } } @@ -306,7 +304,7 @@ static int rawsock_create(struct net *net, struct socket *sock, { struct sock *sk; - pr_debug("sock=%p\n", sock); + nfc_dbg("sock=%p", sock); if (sock->type != SOCK_SEQPACKET) return -ESOCKTNOSUPPORT; diff --git a/trunk/net/openvswitch/vport.c b/trunk/net/openvswitch/vport.c index 7f0ef3794c51..6cd760131f15 100644 --- a/trunk/net/openvswitch/vport.c +++ b/trunk/net/openvswitch/vport.c @@ -127,10 +127,8 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops, vport->ops = ops; vport->percpu_stats = alloc_percpu(struct vport_percpu_stats); - if (!vport->percpu_stats) { - kfree(vport); + if (!vport->percpu_stats) return ERR_PTR(-ENOMEM); - } spin_lock_init(&vport->stats_lock); diff --git a/trunk/net/rfkill/rfkill-gpio.c b/trunk/net/rfkill/rfkill-gpio.c index ca355e7e58b4..128677d69056 100644 --- a/trunk/net/rfkill/rfkill-gpio.c +++ b/trunk/net/rfkill/rfkill-gpio.c @@ -220,7 +220,18 @@ static struct platform_driver rfkill_gpio_driver = { }, }; -module_platform_driver(rfkill_gpio_driver); +static int __init rfkill_gpio_init(void) +{ + return platform_driver_register(&rfkill_gpio_driver); +} + +static void __exit rfkill_gpio_exit(void) +{ + platform_driver_unregister(&rfkill_gpio_driver); +} + +module_init(rfkill_gpio_init); +module_exit(rfkill_gpio_exit); MODULE_DESCRIPTION("gpio rfkill"); MODULE_AUTHOR("NVIDIA"); diff --git a/trunk/net/rfkill/rfkill-regulator.c b/trunk/net/rfkill/rfkill-regulator.c index 2ebfe8d0e873..3ca7277a3c36 100644 --- a/trunk/net/rfkill/rfkill-regulator.c +++ b/trunk/net/rfkill/rfkill-regulator.c @@ -144,7 +144,17 @@ static struct platform_driver rfkill_regulator_driver = { }, }; -module_platform_driver(rfkill_regulator_driver); +static int __init rfkill_regulator_init(void) +{ + return platform_driver_register(&rfkill_regulator_driver); +} +module_init(rfkill_regulator_init); + +static void __exit rfkill_regulator_exit(void) +{ + platform_driver_unregister(&rfkill_regulator_driver); +} +module_exit(rfkill_regulator_exit); MODULE_AUTHOR("Guiming Zhuo "); MODULE_AUTHOR("Antonio Ospite "); diff --git a/trunk/net/sched/cls_flow.c b/trunk/net/sched/cls_flow.c index 1d8bd0dbcd1f..51ff19485e12 100644 --- a/trunk/net/sched/cls_flow.c +++ b/trunk/net/sched/cls_flow.c @@ -285,7 +285,7 @@ static int flow_classify(struct sk_buff *skb, const struct tcf_proto *tp, int r; list_for_each_entry(f, &head->filters, list) { - u32 keys[FLOW_KEY_MAX + 1]; + u32 keys[f->nkeys]; struct flow_keys flow_keys; if (!tcf_em_tree_match(skb, &f->ematches, NULL)) diff --git a/trunk/net/sched/sch_choke.c b/trunk/net/sched/sch_choke.c index bef00acb8bd2..205d369a217c 100644 --- a/trunk/net/sched/sch_choke.c +++ b/trunk/net/sched/sch_choke.c @@ -394,7 +394,6 @@ static void choke_reset(struct Qdisc *sch) static const struct nla_policy choke_policy[TCA_CHOKE_MAX + 1] = { [TCA_CHOKE_PARMS] = { .len = sizeof(struct tc_red_qopt) }, [TCA_CHOKE_STAB] = { .len = RED_STAB_SIZE }, - [TCA_CHOKE_MAX_P] = { .type = NLA_U32 }, }; @@ -416,7 +415,6 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt) int err; struct sk_buff **old = NULL; unsigned int mask; - u32 max_P; if (opt == NULL) return -EINVAL; @@ -429,8 +427,6 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt) tb[TCA_CHOKE_STAB] == NULL) return -EINVAL; - max_P = tb[TCA_CHOKE_MAX_P] ? nla_get_u32(tb[TCA_CHOKE_MAX_P]) : 0; - ctl = nla_data(tb[TCA_CHOKE_PARMS]); if (ctl->limit > CHOKE_MAX_QUEUE) @@ -480,8 +476,7 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt) red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Plog, ctl->Scell_log, - nla_data(tb[TCA_CHOKE_STAB]), - max_P); + nla_data(tb[TCA_CHOKE_STAB])); if (q->head == q->tail) red_end_of_idle_period(&q->parms); @@ -515,7 +510,6 @@ static int choke_dump(struct Qdisc *sch, struct sk_buff *skb) goto nla_put_failure; NLA_PUT(skb, TCA_CHOKE_PARMS, sizeof(opt), &opt); - NLA_PUT_U32(skb, TCA_CHOKE_MAX_P, q->parms.max_P); return nla_nest_end(skb, opts); nla_put_failure: diff --git a/trunk/net/sched/sch_gred.c b/trunk/net/sched/sch_gred.c index 1b5e63126cb3..b9493a09a870 100644 --- a/trunk/net/sched/sch_gred.c +++ b/trunk/net/sched/sch_gred.c @@ -34,7 +34,7 @@ struct gred_sched; struct gred_sched_data { u32 limit; /* HARD maximal queue length */ - u32 DP; /* the drop parameters */ + u32 DP; /* the drop pramaters */ u32 bytesin; /* bytes seen on virtualQ so far*/ u32 packetsin; /* packets seen on virtualQ so far*/ u32 backlog; /* bytes on the virtualQ */ @@ -379,14 +379,13 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps) } static inline int gred_change_vq(struct Qdisc *sch, int dp, - struct tc_gred_qopt *ctl, int prio, - u8 *stab, u32 max_P) + struct tc_gred_qopt *ctl, int prio, u8 *stab) { struct gred_sched *table = qdisc_priv(sch); struct gred_sched_data *q; if (table->tab[dp] == NULL) { - table->tab[dp] = kzalloc(sizeof(*q), GFP_ATOMIC); + table->tab[dp] = kzalloc(sizeof(*q), GFP_KERNEL); if (table->tab[dp] == NULL) return -ENOMEM; } @@ -401,7 +400,7 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp, red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Plog, - ctl->Scell_log, stab, max_P); + ctl->Scell_log, stab); return 0; } @@ -410,7 +409,6 @@ static const struct nla_policy gred_policy[TCA_GRED_MAX + 1] = { [TCA_GRED_PARMS] = { .len = sizeof(struct tc_gred_qopt) }, [TCA_GRED_STAB] = { .len = 256 }, [TCA_GRED_DPS] = { .len = sizeof(struct tc_gred_sopt) }, - [TCA_GRED_MAX_P] = { .type = NLA_U32 }, }; static int gred_change(struct Qdisc *sch, struct nlattr *opt) @@ -420,7 +418,6 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt) struct nlattr *tb[TCA_GRED_MAX + 1]; int err, prio = GRED_DEF_PRIO; u8 *stab; - u32 max_P; if (opt == NULL) return -EINVAL; @@ -436,8 +433,6 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt) tb[TCA_GRED_STAB] == NULL) return -EINVAL; - max_P = tb[TCA_GRED_MAX_P] ? nla_get_u32(tb[TCA_GRED_MAX_P]) : 0; - err = -EINVAL; ctl = nla_data(tb[TCA_GRED_PARMS]); stab = nla_data(tb[TCA_GRED_STAB]); @@ -462,7 +457,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt) sch_tree_lock(sch); - err = gred_change_vq(sch, ctl->DP, ctl, prio, stab, max_P); + err = gred_change_vq(sch, ctl->DP, ctl, prio, stab); if (err < 0) goto errout_locked; @@ -503,7 +498,6 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) struct gred_sched *table = qdisc_priv(sch); struct nlattr *parms, *opts = NULL; int i; - u32 max_p[MAX_DPs]; struct tc_gred_sopt sopt = { .DPs = table->DPs, .def_DP = table->def, @@ -515,14 +509,6 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) if (opts == NULL) goto nla_put_failure; NLA_PUT(skb, TCA_GRED_DPS, sizeof(sopt), &sopt); - - for (i = 0; i < MAX_DPs; i++) { - struct gred_sched_data *q = table->tab[i]; - - max_p[i] = q ? q->parms.max_P : 0; - } - NLA_PUT(skb, TCA_GRED_MAX_P, sizeof(max_p), max_p); - parms = nla_nest_start(skb, TCA_GRED_PARMS); if (parms == NULL) goto nla_put_failure; diff --git a/trunk/net/sched/sch_netem.c b/trunk/net/sched/sch_netem.c index 1fa2f903d221..3bfd73344f76 100644 --- a/trunk/net/sched/sch_netem.c +++ b/trunk/net/sched/sch_netem.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -81,10 +80,6 @@ struct netem_sched_data { u32 reorder; u32 corrupt; u32 rate; - s32 packet_overhead; - u32 cell_size; - u32 cell_size_reciprocal; - s32 cell_overhead; struct crndstate { u32 last; @@ -304,23 +299,11 @@ static psched_tdiff_t tabledist(psched_tdiff_t mu, psched_tdiff_t sigma, return x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu; } -static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sched_data *q) +static psched_time_t packet_len_2_sched_time(unsigned int len, u32 rate) { - u64 ticks; + u64 ticks = (u64)len * NSEC_PER_SEC; - len += q->packet_overhead; - - if (q->cell_size) { - u32 cells = reciprocal_divide(len, q->cell_size_reciprocal); - - if (len > cells * q->cell_size) /* extra cell needed for remainder */ - cells++; - len = cells * (q->cell_size + q->cell_overhead); - } - - ticks = (u64)len * NSEC_PER_SEC; - - do_div(ticks, q->rate); + do_div(ticks, rate); return PSCHED_NS2TICKS(ticks); } @@ -401,7 +384,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) if (q->rate) { struct sk_buff_head *list = &q->qdisc->q; - delay += packet_len_2_sched_time(skb->len, q); + delay += packet_len_2_sched_time(skb->len, q->rate); if (!skb_queue_empty(list)) { /* @@ -585,11 +568,6 @@ static void get_rate(struct Qdisc *sch, const struct nlattr *attr) const struct tc_netem_rate *r = nla_data(attr); q->rate = r->rate; - q->packet_overhead = r->packet_overhead; - q->cell_size = r->cell_size; - if (q->cell_size) - q->cell_size_reciprocal = reciprocal_value(q->cell_size); - q->cell_overhead = r->cell_overhead; } static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr) @@ -931,9 +909,6 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb) NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt); rate.rate = q->rate; - rate.packet_overhead = q->packet_overhead; - rate.cell_size = q->cell_size; - rate.cell_overhead = q->cell_overhead; NLA_PUT(skb, TCA_NETEM_RATE, sizeof(rate), &rate); if (dump_loss_model(q, skb) != 0) diff --git a/trunk/net/sched/sch_red.c b/trunk/net/sched/sch_red.c index ce2256a17d7e..d617161f8dd3 100644 --- a/trunk/net/sched/sch_red.c +++ b/trunk/net/sched/sch_red.c @@ -39,7 +39,6 @@ struct red_sched_data { u32 limit; /* HARD maximal queue length */ unsigned char flags; - struct timer_list adapt_timer; struct red_parms parms; struct red_stats stats; struct Qdisc *qdisc; @@ -162,15 +161,12 @@ static void red_reset(struct Qdisc *sch) static void red_destroy(struct Qdisc *sch) { struct red_sched_data *q = qdisc_priv(sch); - - del_timer_sync(&q->adapt_timer); qdisc_destroy(q->qdisc); } static const struct nla_policy red_policy[TCA_RED_MAX + 1] = { [TCA_RED_PARMS] = { .len = sizeof(struct tc_red_qopt) }, [TCA_RED_STAB] = { .len = RED_STAB_SIZE }, - [TCA_RED_MAX_P] = { .type = NLA_U32 }, }; static int red_change(struct Qdisc *sch, struct nlattr *opt) @@ -180,7 +176,6 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) struct tc_red_qopt *ctl; struct Qdisc *child = NULL; int err; - u32 max_P; if (opt == NULL) return -EINVAL; @@ -193,8 +188,6 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) tb[TCA_RED_STAB] == NULL) return -EINVAL; - max_P = tb[TCA_RED_MAX_P] ? nla_get_u32(tb[TCA_RED_MAX_P]) : 0; - ctl = nla_data(tb[TCA_RED_PARMS]); if (ctl->limit > 0) { @@ -213,13 +206,8 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) } red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, - ctl->Plog, ctl->Scell_log, - nla_data(tb[TCA_RED_STAB]), - max_P); - - del_timer(&q->adapt_timer); - if (ctl->flags & TC_RED_ADAPTATIVE) - mod_timer(&q->adapt_timer, jiffies + HZ/2); + ctl->Plog, ctl->Scell_log, + nla_data(tb[TCA_RED_STAB])); if (!q->qdisc->q.qlen) red_start_of_idle_period(&q->parms); @@ -228,24 +216,11 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) return 0; } -static inline void red_adaptative_timer(unsigned long arg) -{ - struct Qdisc *sch = (struct Qdisc *)arg; - struct red_sched_data *q = qdisc_priv(sch); - spinlock_t *root_lock = qdisc_lock(qdisc_root_sleeping(sch)); - - spin_lock(root_lock); - red_adaptative_algo(&q->parms); - mod_timer(&q->adapt_timer, jiffies + HZ/2); - spin_unlock(root_lock); -} - static int red_init(struct Qdisc *sch, struct nlattr *opt) { struct red_sched_data *q = qdisc_priv(sch); q->qdisc = &noop_qdisc; - setup_timer(&q->adapt_timer, red_adaptative_timer, (unsigned long)sch); return red_change(sch, opt); } @@ -268,7 +243,6 @@ static int red_dump(struct Qdisc *sch, struct sk_buff *skb) if (opts == NULL) goto nla_put_failure; NLA_PUT(skb, TCA_RED_PARMS, sizeof(opt), &opt); - NLA_PUT_U32(skb, TCA_RED_MAX_P, q->parms.max_P); return nla_nest_end(skb, opts); nla_put_failure: diff --git a/trunk/net/sctp/input.c b/trunk/net/sctp/input.c index 80f71af71384..b7692aab6e9c 100644 --- a/trunk/net/sctp/input.c +++ b/trunk/net/sctp/input.c @@ -105,7 +105,7 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb) struct sctp_input_cb { union { struct inet_skb_parm h4; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) struct inet6_skb_parm h6; #endif } header; diff --git a/trunk/net/sctp/protocol.c b/trunk/net/sctp/protocol.c index 544a9b68eb53..61b9fca5a173 100644 --- a/trunk/net/sctp/protocol.c +++ b/trunk/net/sctp/protocol.c @@ -637,7 +637,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) " for cmd %d at entry %p\n", &sctp_addr_waitq, &addrw->a, addrw->state, addrw); -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) /* Now we send an ASCONF for each association */ /* Note. we currently don't handle link local IPv6 addressees */ if (addrw->a.sa.sa_family == AF_INET6) { diff --git a/trunk/net/sctp/socket.c b/trunk/net/sctp/socket.c index db0308344d07..d56c07a3d435 100644 --- a/trunk/net/sctp/socket.c +++ b/trunk/net/sctp/socket.c @@ -6841,7 +6841,7 @@ struct proto sctp_prot = { .sockets_allocated = &sctp_sockets_allocated, }; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct proto sctpv6_prot = { .name = "SCTPv6", @@ -6872,4 +6872,4 @@ struct proto sctpv6_prot = { .memory_allocated = &sctp_memory_allocated, .sockets_allocated = &sctp_sockets_allocated, }; -#endif /* IS_ENABLED(CONFIG_IPV6) */ +#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ diff --git a/trunk/net/sunrpc/addr.c b/trunk/net/sunrpc/addr.c index ee77742e0ed6..67a655ee82a9 100644 --- a/trunk/net/sunrpc/addr.c +++ b/trunk/net/sunrpc/addr.c @@ -21,7 +21,7 @@ #include #include -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap, char *buf, const int buflen) @@ -91,7 +91,7 @@ static size_t rpc_ntop6(const struct sockaddr *sap, return len; } -#else /* !IS_ENABLED(CONFIG_IPV6) */ +#else /* !(defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)) */ static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap, char *buf, const int buflen) @@ -105,7 +105,7 @@ static size_t rpc_ntop6(const struct sockaddr *sap, return 0; } -#endif /* !IS_ENABLED(CONFIG_IPV6) */ +#endif /* !(defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)) */ static int rpc_ntop4(const struct sockaddr *sap, char *buf, const size_t buflen) @@ -155,7 +155,7 @@ static size_t rpc_pton4(const char *buf, const size_t buflen, return sizeof(struct sockaddr_in); } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static int rpc_parse_scope_id(const char *buf, const size_t buflen, const char *delim, struct sockaddr_in6 *sin6) { diff --git a/trunk/net/sunrpc/svc.c b/trunk/net/sunrpc/svc.c index 9d01d46b05f3..6e038884ae0c 100644 --- a/trunk/net/sunrpc/svc.c +++ b/trunk/net/sunrpc/svc.c @@ -826,7 +826,7 @@ static int __svc_rpcb_register4(const u32 program, const u32 version, return error; } -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) /* * Register an "inet6" protocol family netid with the local * rpcbind daemon via an rpcbind v4 SET request. @@ -872,7 +872,7 @@ static int __svc_rpcb_register6(const u32 program, const u32 version, return error; } -#endif /* IS_ENABLED(CONFIG_IPV6) */ +#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ /* * Register a kernel RPC service via rpcbind version 4. @@ -893,11 +893,11 @@ static int __svc_register(const char *progname, error = __svc_rpcb_register4(program, version, protocol, port); break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case PF_INET6: error = __svc_rpcb_register6(program, version, protocol, port); -#endif +#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ } if (error < 0) diff --git a/trunk/net/sunrpc/svc_xprt.c b/trunk/net/sunrpc/svc_xprt.c index 38649cfa4e81..447cd0eb415c 100644 --- a/trunk/net/sunrpc/svc_xprt.c +++ b/trunk/net/sunrpc/svc_xprt.c @@ -179,13 +179,13 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, .sin_addr.s_addr = htonl(INADDR_ANY), .sin_port = htons(port), }; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) struct sockaddr_in6 sin6 = { .sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(port), }; -#endif +#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ struct sockaddr *sap; size_t len; @@ -194,12 +194,12 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, sap = (struct sockaddr *)&sin; len = sizeof(sin); break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case PF_INET6: sap = (struct sockaddr *)&sin6; len = sizeof(sin6); break; -#endif +#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ default: return ERR_PTR(-EAFNOSUPPORT); } diff --git a/trunk/net/sunrpc/svcauth_unix.c b/trunk/net/sunrpc/svcauth_unix.c index 01153ead1dba..fe258fc37f50 100644 --- a/trunk/net/sunrpc/svcauth_unix.c +++ b/trunk/net/sunrpc/svcauth_unix.c @@ -220,7 +220,7 @@ static int ip_map_parse(struct cache_detail *cd, ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr, &sin6.sin6_addr); break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: memcpy(&sin6, &address.s6, sizeof(sin6)); break; diff --git a/trunk/net/unix/Kconfig b/trunk/net/unix/Kconfig index c2128b10e5f9..5a69733bcdad 100644 --- a/trunk/net/unix/Kconfig +++ b/trunk/net/unix/Kconfig @@ -19,10 +19,3 @@ config UNIX Say Y unless you know what you are doing. -config UNIX_DIAG - tristate "UNIX: socket monitoring interface" - depends on UNIX - default UNIX - ---help--- - Support for UNIX socket monitoring interface used by the ss tool. - If unsure, say Y. diff --git a/trunk/net/unix/Makefile b/trunk/net/unix/Makefile index b663c607b1c6..b852a2bde9a8 100644 --- a/trunk/net/unix/Makefile +++ b/trunk/net/unix/Makefile @@ -6,6 +6,3 @@ obj-$(CONFIG_UNIX) += unix.o unix-y := af_unix.o garbage.o unix-$(CONFIG_SYSCTL) += sysctl_net_unix.o - -obj-$(CONFIG_UNIX_DIAG) += unix_diag.o -unix_diag-y := diag.o diff --git a/trunk/net/unix/af_unix.c b/trunk/net/unix/af_unix.c index e1b9358a211d..b595a3d8679f 100644 --- a/trunk/net/unix/af_unix.c +++ b/trunk/net/unix/af_unix.c @@ -115,10 +115,8 @@ #include #include -struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; -EXPORT_SYMBOL_GPL(unix_socket_table); -DEFINE_SPINLOCK(unix_table_lock); -EXPORT_SYMBOL_GPL(unix_table_lock); +static struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; +static DEFINE_SPINLOCK(unix_table_lock); static atomic_long_t unix_nr_socks; #define unix_sockets_unbound (&unix_socket_table[UNIX_HASH_SIZE]) @@ -174,7 +172,7 @@ static inline int unix_recvq_full(struct sock const *sk) return skb_queue_len(&sk->sk_receive_queue) > sk->sk_max_ack_backlog; } -struct sock *unix_peer_get(struct sock *s) +static struct sock *unix_peer_get(struct sock *s) { struct sock *peer; @@ -185,7 +183,6 @@ struct sock *unix_peer_get(struct sock *s) unix_state_unlock(s); return peer; } -EXPORT_SYMBOL_GPL(unix_peer_get); static inline void unix_release_addr(struct unix_address *addr) { diff --git a/trunk/net/unix/diag.c b/trunk/net/unix/diag.c deleted file mode 100644 index a5c4aab0380d..000000000000 --- a/trunk/net/unix/diag.c +++ /dev/null @@ -1,313 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#define UNIX_DIAG_PUT(skb, attrtype, attrlen) \ - RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) - -static int sk_diag_dump_name(struct sock *sk, struct sk_buff *nlskb) -{ - struct unix_address *addr = unix_sk(sk)->addr; - char *s; - - if (addr) { - s = UNIX_DIAG_PUT(nlskb, UNIX_DIAG_NAME, addr->len - sizeof(short)); - memcpy(s, addr->name->sun_path, addr->len - sizeof(short)); - } - - return 0; - -rtattr_failure: - return -EMSGSIZE; -} - -static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb) -{ - struct dentry *dentry = unix_sk(sk)->dentry; - struct unix_diag_vfs *uv; - - if (dentry) { - uv = UNIX_DIAG_PUT(nlskb, UNIX_DIAG_VFS, sizeof(*uv)); - uv->udiag_vfs_ino = dentry->d_inode->i_ino; - uv->udiag_vfs_dev = dentry->d_sb->s_dev; - } - - return 0; - -rtattr_failure: - return -EMSGSIZE; -} - -static int sk_diag_dump_peer(struct sock *sk, struct sk_buff *nlskb) -{ - struct sock *peer; - int ino; - - peer = unix_peer_get(sk); - if (peer) { - unix_state_lock(peer); - ino = sock_i_ino(peer); - unix_state_unlock(peer); - sock_put(peer); - - RTA_PUT_U32(nlskb, UNIX_DIAG_PEER, ino); - } - - return 0; -rtattr_failure: - return -EMSGSIZE; -} - -static int sk_diag_dump_icons(struct sock *sk, struct sk_buff *nlskb) -{ - struct sk_buff *skb; - u32 *buf; - int i; - - if (sk->sk_state == TCP_LISTEN) { - spin_lock(&sk->sk_receive_queue.lock); - buf = UNIX_DIAG_PUT(nlskb, UNIX_DIAG_ICONS, sk->sk_receive_queue.qlen); - i = 0; - skb_queue_walk(&sk->sk_receive_queue, skb) { - struct sock *req, *peer; - - req = skb->sk; - /* - * The state lock is outer for the same sk's - * queue lock. With the other's queue locked it's - * OK to lock the state. - */ - unix_state_lock_nested(req); - peer = unix_sk(req)->peer; - if (peer) - buf[i++] = sock_i_ino(peer); - unix_state_unlock(req); - } - spin_unlock(&sk->sk_receive_queue.lock); - } - - return 0; - -rtattr_failure: - spin_unlock(&sk->sk_receive_queue.lock); - return -EMSGSIZE; -} - -static int sk_diag_show_rqlen(struct sock *sk, struct sk_buff *nlskb) -{ - RTA_PUT_U32(nlskb, UNIX_DIAG_RQLEN, sk->sk_receive_queue.qlen); - return 0; - -rtattr_failure: - return -EMSGSIZE; -} - -static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req, - u32 pid, u32 seq, u32 flags, int sk_ino) -{ - unsigned char *b = skb_tail_pointer(skb); - struct nlmsghdr *nlh; - struct unix_diag_msg *rep; - - nlh = NLMSG_PUT(skb, pid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rep)); - nlh->nlmsg_flags = flags; - - rep = NLMSG_DATA(nlh); - - rep->udiag_family = AF_UNIX; - rep->udiag_type = sk->sk_type; - rep->udiag_state = sk->sk_state; - rep->udiag_ino = sk_ino; - sock_diag_save_cookie(sk, rep->udiag_cookie); - - if ((req->udiag_show & UDIAG_SHOW_NAME) && - sk_diag_dump_name(sk, skb)) - goto nlmsg_failure; - - if ((req->udiag_show & UDIAG_SHOW_VFS) && - sk_diag_dump_vfs(sk, skb)) - goto nlmsg_failure; - - if ((req->udiag_show & UDIAG_SHOW_PEER) && - sk_diag_dump_peer(sk, skb)) - goto nlmsg_failure; - - if ((req->udiag_show & UDIAG_SHOW_ICONS) && - sk_diag_dump_icons(sk, skb)) - goto nlmsg_failure; - - if ((req->udiag_show & UDIAG_SHOW_RQLEN) && - sk_diag_show_rqlen(sk, skb)) - goto nlmsg_failure; - - nlh->nlmsg_len = skb_tail_pointer(skb) - b; - return skb->len; - -nlmsg_failure: - nlmsg_trim(skb, b); - return -EMSGSIZE; -} - -static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, struct unix_diag_req *req, - u32 pid, u32 seq, u32 flags) -{ - int sk_ino; - - unix_state_lock(sk); - sk_ino = sock_i_ino(sk); - unix_state_unlock(sk); - - if (!sk_ino) - return 0; - - return sk_diag_fill(sk, skb, req, pid, seq, flags, sk_ino); -} - -static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) -{ - struct unix_diag_req *req; - int num, s_num, slot, s_slot; - - req = NLMSG_DATA(cb->nlh); - - s_slot = cb->args[0]; - num = s_num = cb->args[1]; - - spin_lock(&unix_table_lock); - for (slot = s_slot; slot <= UNIX_HASH_SIZE; s_num = 0, slot++) { - struct sock *sk; - struct hlist_node *node; - - num = 0; - sk_for_each(sk, node, &unix_socket_table[slot]) { - if (num < s_num) - goto next; - if (!(req->udiag_states & (1 << sk->sk_state))) - goto next; - if (sk_diag_dump(sk, skb, req, - NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - NLM_F_MULTI) < 0) - goto done; -next: - num++; - } - } -done: - spin_unlock(&unix_table_lock); - cb->args[0] = slot; - cb->args[1] = num; - - return skb->len; -} - -static struct sock *unix_lookup_by_ino(int ino) -{ - int i; - struct sock *sk; - - spin_lock(&unix_table_lock); - for (i = 0; i <= UNIX_HASH_SIZE; i++) { - struct hlist_node *node; - - sk_for_each(sk, node, &unix_socket_table[i]) - if (ino == sock_i_ino(sk)) { - sock_hold(sk); - spin_unlock(&unix_table_lock); - - return sk; - } - } - - spin_unlock(&unix_table_lock); - return NULL; -} - -static int unix_diag_get_exact(struct sk_buff *in_skb, - const struct nlmsghdr *nlh, - struct unix_diag_req *req) -{ - int err = -EINVAL; - struct sock *sk; - struct sk_buff *rep; - unsigned int extra_len; - - if (req->udiag_ino == 0) - goto out_nosk; - - sk = unix_lookup_by_ino(req->udiag_ino); - err = -ENOENT; - if (sk == NULL) - goto out_nosk; - - err = sock_diag_check_cookie(sk, req->udiag_cookie); - if (err) - goto out; - - extra_len = 256; -again: - err = -ENOMEM; - rep = alloc_skb(NLMSG_SPACE((sizeof(struct unix_diag_msg) + extra_len)), - GFP_KERNEL); - if (!rep) - goto out; - - err = sk_diag_fill(sk, rep, req, NETLINK_CB(in_skb).pid, - nlh->nlmsg_seq, 0, req->udiag_ino); - if (err < 0) { - kfree_skb(rep); - extra_len += 256; - if (extra_len >= PAGE_SIZE) - goto out; - - goto again; - } - err = netlink_unicast(sock_diag_nlsk, rep, NETLINK_CB(in_skb).pid, - MSG_DONTWAIT); - if (err > 0) - err = 0; -out: - if (sk) - sock_put(sk); -out_nosk: - return err; -} - -static int unix_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) -{ - int hdrlen = sizeof(struct unix_diag_req); - - if (nlmsg_len(h) < hdrlen) - return -EINVAL; - - if (h->nlmsg_flags & NLM_F_DUMP) - return netlink_dump_start(sock_diag_nlsk, skb, h, - unix_diag_dump, NULL, 0); - else - return unix_diag_get_exact(skb, h, (struct unix_diag_req *)NLMSG_DATA(h)); -} - -static struct sock_diag_handler unix_diag_handler = { - .family = AF_UNIX, - .dump = unix_diag_handler_dump, -}; - -static int __init unix_diag_init(void) -{ - return sock_diag_register(&unix_diag_handler); -} - -static void __exit unix_diag_exit(void) -{ - sock_diag_unregister(&unix_diag_handler); -} - -module_init(unix_diag_init); -module_exit(unix_diag_exit); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 1 /* AF_LOCAL */); diff --git a/trunk/net/wireless/Kconfig b/trunk/net/wireless/Kconfig index 2e4444fedbe0..1f1ef70f34f2 100644 --- a/trunk/net/wireless/Kconfig +++ b/trunk/net/wireless/Kconfig @@ -121,16 +121,15 @@ config CFG80211_WEXT config WIRELESS_EXT_SYSFS bool "Wireless extensions sysfs files" + default y depends on WEXT_CORE && SYSFS help This option enables the deprecated wireless statistics files in /sys/class/net/*/wireless/. The same information is available via the ioctls as well. - Say N. If you know you have ancient tools requiring it, - like very old versions of hal (prior to 0.5.12 release), - say Y and update the tools as soon as possible as this - option will be removed soon. + Say Y if you have programs using it, like old versions of + hal. config LIB80211 tristate "Common routines for IEEE802.11 drivers" diff --git a/trunk/net/wireless/chan.c b/trunk/net/wireless/chan.c index 2fcfe0993ca2..17cd0c04d139 100644 --- a/trunk/net/wireless/chan.c +++ b/trunk/net/wireless/chan.c @@ -6,7 +6,6 @@ * Copyright 2009 Johannes Berg */ -#include #include #include "core.h" @@ -45,9 +44,9 @@ rdev_freq_to_chan(struct cfg80211_registered_device *rdev, return chan; } -int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type) +static bool can_beacon_sec_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type) { struct ieee80211_channel *sec_chan; int diff; @@ -76,7 +75,6 @@ int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, return true; } -EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan); int cfg80211_set_freq(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, int freq, @@ -111,8 +109,8 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev, switch (channel_type) { case NL80211_CHAN_HT40PLUS: case NL80211_CHAN_HT40MINUS: - if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, chan, - channel_type)) { + if (!can_beacon_sec_chan(&rdev->wiphy, chan, + channel_type)) { printk(KERN_DEBUG "cfg80211: Secondary channel not " "allowed to initiate communication\n"); diff --git a/trunk/net/wireless/mesh.c b/trunk/net/wireless/mesh.c index 8c550df13037..b7b7868f4128 100644 --- a/trunk/net/wireless/mesh.c +++ b/trunk/net/wireless/mesh.c @@ -20,7 +20,6 @@ * interface */ #define MESH_PREQ_MIN_INT 10 -#define MESH_PERR_MIN_INT 100 #define MESH_DIAM_TRAVERSAL_TIME 50 /* @@ -48,7 +47,6 @@ const struct mesh_config default_mesh_config = { .dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS, .dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT, .dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT, - .dot11MeshHWMPperrMinInterval = MESH_PERR_MIN_INT, .dot11MeshHWMPnetDiameterTraversalTime = MESH_DIAM_TRAVERSAL_TIME, .dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES, .path_refresh_time = MESH_PATH_REFRESH_TIME, diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index ba439664c2e0..eee9ccc7adaf 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -204,7 +204,6 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_HT_CAPABILITY_MASK] = { .len = NL80211_HT_CAPABILITY_LEN }, - [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 }, }; /* policy for the key attributes */ @@ -905,7 +904,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) CMD(sched_scan_start, START_SCHED_SCAN); CMD(probe_client, PROBE_CLIENT); - CMD(set_noack_map, SET_NOACK_MAP); if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) { i++; NLA_PUT_U32(msg, i, NL80211_CMD_REGISTER_BEACONS); @@ -1761,23 +1759,6 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) return rdev->ops->del_virtual_intf(&rdev->wiphy, dev); } -static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info) -{ - struct cfg80211_registered_device *rdev = info->user_ptr[0]; - struct net_device *dev = info->user_ptr[1]; - u16 noack_map; - - if (!info->attrs[NL80211_ATTR_NOACK_MAP]) - return -EINVAL; - - if (!rdev->ops->set_noack_map) - return -EOPNOTSUPP; - - noack_map = nla_get_u16(info->attrs[NL80211_ATTR_NOACK_MAP]); - - return rdev->ops->set_noack_map(&rdev->wiphy, dev, noack_map); -} - struct get_key_cookie { struct sk_buff *msg; int error; @@ -3195,8 +3176,6 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, cur_params.dot11MeshHWMPactivePathTimeout); NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, cur_params.dot11MeshHWMPpreqMinInterval); - NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, - cur_params.dot11MeshHWMPperrMinInterval); NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, cur_params.dot11MeshHWMPnetDiameterTraversalTime); NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_ROOTMODE, @@ -3231,7 +3210,6 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 }, [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 }, [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 }, - [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] = { .type = NLA_U16 }, [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 }, [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 }, @@ -3306,9 +3284,6 @@ do {\ FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPpreqMinInterval, mask, NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, nla_get_u16); - FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPperrMinInterval, - mask, NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, - nla_get_u16); FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPnetDiameterTraversalTime, mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, @@ -4682,41 +4657,13 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); } - if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { - enum nl80211_channel_type channel_type; - - channel_type = nla_get_u32( - info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); - if (channel_type != NL80211_CHAN_NO_HT && - channel_type != NL80211_CHAN_HT20 && - channel_type != NL80211_CHAN_HT40MINUS && - channel_type != NL80211_CHAN_HT40PLUS) - return -EINVAL; - - if (channel_type != NL80211_CHAN_NO_HT && - !(wiphy->features & NL80211_FEATURE_HT_IBSS)) - return -EINVAL; - - ibss.channel_type = channel_type; - } else { - ibss.channel_type = NL80211_CHAN_NO_HT; - } - - ibss.channel = rdev_freq_to_chan(rdev, - nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]), - ibss.channel_type); + ibss.channel = ieee80211_get_channel(wiphy, + nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); if (!ibss.channel || ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || ibss.channel->flags & IEEE80211_CHAN_DISABLED) return -EINVAL; - /* Both channels should be able to initiate communication */ - if ((ibss.channel_type == NL80211_CHAN_HT40PLUS || - ibss.channel_type == NL80211_CHAN_HT40MINUS) && - !cfg80211_can_beacon_sec_chan(&rdev->wiphy, ibss.channel, - ibss.channel_type)) - return -EINVAL; - ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; @@ -5701,11 +5648,6 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info) setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]); setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); - if (info->attrs[NL80211_ATTR_MCAST_RATE] && - !nl80211_parse_mcast_rate(rdev, setup.mcast_rate, - nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]))) - return -EINVAL; - if (info->attrs[NL80211_ATTR_MESH_SETUP]) { /* parse additional setup parameters if given */ err = nl80211_parse_mesh_setup(info, &setup); @@ -6662,15 +6604,6 @@ static struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_WIPHY | NL80211_FLAG_NEED_RTNL, }, - { - .cmd = NL80211_CMD_SET_NOACK_MAP, - .doit = nl80211_set_noack_map, - .policy = nl80211_policy, - .flags = GENL_ADMIN_PERM, - .internal_flags = NL80211_FLAG_NEED_NETDEV | - NL80211_FLAG_NEED_RTNL, - }, - }; static struct genl_multicast_group nl80211_mlme_mcgrp = { diff --git a/trunk/net/wireless/reg.c b/trunk/net/wireless/reg.c index 70b171a52aea..76b35df39623 100644 --- a/trunk/net/wireless/reg.c +++ b/trunk/net/wireless/reg.c @@ -57,17 +57,8 @@ #define REG_DBG_PRINT(args...) #endif -static struct regulatory_request core_request_world = { - .initiator = NL80211_REGDOM_SET_BY_CORE, - .alpha2[0] = '0', - .alpha2[1] = '0', - .intersect = false, - .processed = true, - .country_ie_env = ENVIRON_ANY, -}; - /* Receipt of information from last regulatory request */ -static struct regulatory_request *last_request = &core_request_world; +static struct regulatory_request *last_request; /* To trigger userspace events */ static struct platform_device *reg_pdev; @@ -159,7 +150,7 @@ static char user_alpha2[2]; module_param(ieee80211_regdom, charp, 0444); MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); -static void reset_regdomains(bool full_reset) +static void reset_regdomains(void) { /* avoid freeing static information or freeing something twice */ if (cfg80211_regdomain == cfg80211_world_regdom) @@ -174,13 +165,6 @@ static void reset_regdomains(bool full_reset) cfg80211_world_regdom = &world_regdom; cfg80211_regdomain = NULL; - - if (!full_reset) - return; - - if (last_request != &core_request_world) - kfree(last_request); - last_request = &core_request_world; } /* @@ -191,7 +175,7 @@ static void update_world_regdomain(const struct ieee80211_regdomain *rd) { BUG_ON(!last_request); - reset_regdomains(false); + reset_regdomains(); cfg80211_world_regdom = rd; cfg80211_regdomain = rd; @@ -1425,8 +1409,7 @@ static int __regulatory_hint(struct wiphy *wiphy, } new_request: - if (last_request != &core_request_world) - kfree(last_request); + kfree(last_request); last_request = pending_request; last_request->intersect = intersect; @@ -1596,6 +1579,9 @@ static int regulatory_hint_core(const char *alpha2) { struct regulatory_request *request; + kfree(last_request); + last_request = NULL; + request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL); if (!request) @@ -1793,7 +1779,7 @@ static void restore_regulatory_settings(bool reset_user) mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex); - reset_regdomains(true); + reset_regdomains(); restore_alpha2(alpha2, reset_user); /* @@ -2090,10 +2076,8 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) } request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); - if (!request_wiphy && - (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER || - last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) { - schedule_delayed_work(®_timeout, 0); + if (!request_wiphy) { + reg_set_request_processed(); return -ENODEV; } @@ -2101,7 +2085,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) int r; if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) { - reset_regdomains(false); + reset_regdomains(); cfg80211_regdomain = rd; return 0; } @@ -2122,7 +2106,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) if (r) return r; - reset_regdomains(false); + reset_regdomains(); cfg80211_regdomain = rd; return 0; } @@ -2147,7 +2131,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) rd = NULL; - reset_regdomains(false); + reset_regdomains(); cfg80211_regdomain = intersected_rd; return 0; @@ -2167,7 +2151,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) kfree(rd); rd = NULL; - reset_regdomains(false); + reset_regdomains(); cfg80211_regdomain = intersected_rd; return 0; @@ -2320,8 +2304,11 @@ void /* __init_or_exit */ regulatory_exit(void) mutex_lock(&cfg80211_mutex); mutex_lock(®_mutex); - reset_regdomains(true); + reset_regdomains(); + + kfree(last_request); + last_request = NULL; dev_set_uevent_suppress(®_pdev->dev, true); platform_device_unregister(reg_pdev); diff --git a/trunk/net/xfrm/xfrm_policy.c b/trunk/net/xfrm/xfrm_policy.c index eb6b0b7781a5..82e803b56952 100644 --- a/trunk/net/xfrm/xfrm_policy.c +++ b/trunk/net/xfrm/xfrm_policy.c @@ -1340,7 +1340,7 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) case AF_INET: dst_ops = &net->xfrm.xfrm4_dst_ops; break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: dst_ops = &net->xfrm.xfrm6_dst_ops; break; @@ -2435,7 +2435,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) case AF_INET: xfrm_dst_ops = &net->xfrm.xfrm4_dst_ops; break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: xfrm_dst_ops = &net->xfrm.xfrm6_dst_ops; break; @@ -2485,7 +2485,7 @@ static void __net_init xfrm_dst_ops_init(struct net *net) afinfo = xfrm_policy_afinfo[AF_INET]; if (afinfo) net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) afinfo = xfrm_policy_afinfo[AF_INET6]; if (afinfo) net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops; diff --git a/trunk/net/xfrm/xfrm_user.c b/trunk/net/xfrm/xfrm_user.c index e0d747a2e803..d0a42df5160e 100644 --- a/trunk/net/xfrm/xfrm_user.c +++ b/trunk/net/xfrm/xfrm_user.c @@ -28,7 +28,7 @@ #include #include #include -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #include #endif @@ -150,7 +150,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, break; case AF_INET6: -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) break; #else err = -EAFNOSUPPORT; @@ -201,7 +201,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, goto out; break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case IPPROTO_DSTOPTS: case IPPROTO_ROUTING: if (attrs[XFRMA_ALG_COMP] || @@ -1160,7 +1160,7 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) break; case AF_INET6: -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) break; #else return -EAFNOSUPPORT; @@ -1231,7 +1231,7 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) switch (ut[i].family) { case AF_INET: break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: break; #endif @@ -2604,7 +2604,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, return NULL; } break; -#if IS_ENABLED(CONFIG_IPV6) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: if (opt != IPV6_XFRM_POLICY) { *dir = -EOPNOTSUPP; diff --git a/trunk/security/selinux/hooks.c b/trunk/security/selinux/hooks.c index 86305c2f555a..cca09bb46502 100644 --- a/trunk/security/selinux/hooks.c +++ b/trunk/security/selinux/hooks.c @@ -1090,7 +1090,7 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc return SECCLASS_NETLINK_ROUTE_SOCKET; case NETLINK_FIREWALL: return SECCLASS_NETLINK_FIREWALL_SOCKET; - case NETLINK_SOCK_DIAG: + case NETLINK_INET_DIAG: return SECCLASS_NETLINK_TCPDIAG_SOCKET; case NETLINK_NFLOG: return SECCLASS_NETLINK_NFLOG_SOCKET; diff --git a/trunk/sound/pci/hda/hda_intel.c b/trunk/sound/pci/hda/hda_intel.c index 7d98240def0b..096507d2ca9a 100644 --- a/trunk/sound/pci/hda/hda_intel.c +++ b/trunk/sound/pci/hda/hda_intel.c @@ -2508,6 +2508,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), + SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB), SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), diff --git a/trunk/sound/pci/hda/patch_sigmatel.c b/trunk/sound/pci/hda/patch_sigmatel.c index d8d2f9dccd9b..f3658658548e 100644 --- a/trunk/sound/pci/hda/patch_sigmatel.c +++ b/trunk/sound/pci/hda/patch_sigmatel.c @@ -4441,9 +4441,7 @@ static int stac92xx_init(struct hda_codec *codec) int pinctl, def_conf; /* power on when no jack detection is available */ - /* or when the VREF is used for controlling LED */ - if (!spec->hp_detect || - (spec->gpio_led > 8 && spec->gpio_led == nid)) { + if (!spec->hp_detect) { stac_toggle_power_map(codec, nid, 1); continue; } @@ -5057,6 +5055,20 @@ static int stac92xx_pre_resume(struct hda_codec *codec) return 0; } +static int stac92xx_post_suspend(struct hda_codec *codec) +{ + struct sigmatel_spec *spec = codec->spec; + if (spec->gpio_led > 8) { + /* with vref-out pin used for mute led control + * codec AFG is prevented from D3 state, but on + * system suspend it can (and should) be used + */ + snd_hda_codec_read(codec, codec->afg, 0, + AC_VERB_SET_POWER_STATE, AC_PWRST_D3); + } + return 0; +} + static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, unsigned int power_state) { @@ -5656,6 +5668,8 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) } else { codec->patch_ops.set_power_state = stac92xx_set_power_state; + codec->patch_ops.post_suspend = + stac92xx_post_suspend; } codec->patch_ops.pre_resume = stac92xx_pre_resume; codec->patch_ops.check_power_status = @@ -5969,6 +5983,8 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) } else { codec->patch_ops.set_power_state = stac92xx_set_power_state; + codec->patch_ops.post_suspend = + stac92xx_post_suspend; } codec->patch_ops.pre_resume = stac92xx_pre_resume; codec->patch_ops.check_power_status = diff --git a/trunk/sound/soc/atmel/Kconfig b/trunk/sound/soc/atmel/Kconfig index d1fcc816ce97..bee3c94f58b0 100644 --- a/trunk/sound/soc/atmel/Kconfig +++ b/trunk/sound/soc/atmel/Kconfig @@ -1,6 +1,6 @@ config SND_ATMEL_SOC tristate "SoC Audio for the Atmel System-on-Chip" - depends on ARCH_AT91 + depends on ARCH_AT91 || AVR32 help Say Y or M if you want to add support for codecs attached to the ATMEL SSC interface. You will also need @@ -24,6 +24,25 @@ config SND_AT91_SOC_SAM9G20_WM8731 Say Y if you want to add support for SoC audio on WM8731-based AT91sam9g20 evaluation board. +config SND_AT32_SOC_PLAYPAQ + tristate "SoC Audio support for PlayPaq with WM8510" + depends on SND_ATMEL_SOC && BOARD_PLAYPAQ && AT91_PROGRAMMABLE_CLOCKS + select SND_ATMEL_SOC_SSC + select SND_SOC_WM8510 + help + Say Y or M here if you want to add support for SoC audio + on the LRS PlayPaq. + +config SND_AT32_SOC_PLAYPAQ_SLAVE + bool "Run CODEC on PlayPaq in slave mode" + depends on SND_AT32_SOC_PLAYPAQ + default n + help + Say Y if you want to run with the AT32 SSC generating the BCLK + and FRAME signals on the PlayPaq. Unless you want to play + with the AT32 as the SSC master, you probably want to say N here, + as this will give you better sound quality. + config SND_AT91_SOC_AFEB9260 tristate "SoC Audio support for AFEB9260 board" depends on ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC diff --git a/trunk/sound/soc/atmel/Makefile b/trunk/sound/soc/atmel/Makefile index a5c0bf19da78..e7ea56bd5f82 100644 --- a/trunk/sound/soc/atmel/Makefile +++ b/trunk/sound/soc/atmel/Makefile @@ -8,5 +8,9 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o # AT91 Machine Support snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o +# AT32 Machine Support +snd-soc-playpaq-objs := playpaq_wm8510.o + obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o +obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o diff --git a/trunk/sound/soc/atmel/playpaq_wm8510.c b/trunk/sound/soc/atmel/playpaq_wm8510.c new file mode 100644 index 000000000000..73ae99ad4578 --- /dev/null +++ b/trunk/sound/soc/atmel/playpaq_wm8510.c @@ -0,0 +1,473 @@ +/* sound/soc/at32/playpaq_wm8510.c + * ASoC machine driver for PlayPaq using WM8510 codec + * + * Copyright (C) 2008 Long Range Systems + * Geoffrey Wossum + * + * 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 code is largely inspired by sound/soc/at91/eti_b1_wm8731.c + * + * NOTE: If you don't have the AT32 enhanced portmux configured (which + * isn't currently in the mainline or Atmel patched kernel), you will + * need to set the MCLK pin (PA30) to peripheral A in your board initialization + * code. Something like: + * at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); + * + */ + +/* #define DEBUG */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "../codecs/wm8510.h" +#include "atmel-pcm.h" +#include "atmel_ssc_dai.h" + + +/*-------------------------------------------------------------------------*\ + * constants +\*-------------------------------------------------------------------------*/ +#define MCLK_PIN GPIO_PIN_PA(30) +#define MCLK_PERIPH GPIO_PERIPH_A + + +/*-------------------------------------------------------------------------*\ + * data types +\*-------------------------------------------------------------------------*/ +/* SSC clocking data */ +struct ssc_clock_data { + /* CMR div */ + unsigned int cmr_div; + + /* Frame period (as needed by xCMR.PERIOD) */ + unsigned int period; + + /* The SSC clock rate these settings where calculated for */ + unsigned long ssc_rate; +}; + + +/*-------------------------------------------------------------------------*\ + * module data +\*-------------------------------------------------------------------------*/ +static struct clk *_gclk0; +static struct clk *_pll0; + +#define CODEC_CLK (_gclk0) + + +/*-------------------------------------------------------------------------*\ + * Sound SOC operations +\*-------------------------------------------------------------------------*/ +#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE +static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock( + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) +{ + struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); + struct ssc_device *ssc = ssc_p->ssc; + struct ssc_clock_data cd; + unsigned int rate, width_bits, channels; + unsigned int bitrate, ssc_div; + unsigned actual_rate; + + + /* + * Figure out required bitrate + */ + rate = params_rate(params); + channels = params_channels(params); + width_bits = snd_pcm_format_physical_width(params_format(params)); + bitrate = rate * width_bits * channels; + + + /* + * Figure out required SSC divider and period for required bitrate + */ + cd.ssc_rate = clk_get_rate(ssc->clk); + ssc_div = cd.ssc_rate / bitrate; + cd.cmr_div = ssc_div / 2; + if (ssc_div & 1) { + /* round cmr_div up */ + cd.cmr_div++; + } + cd.period = width_bits - 1; + + + /* + * Find actual rate, compare to requested rate + */ + actual_rate = (cd.ssc_rate / (cd.cmr_div * 2)) / (2 * (cd.period + 1)); + pr_debug("playpaq_wm8510: Request rate = %u, actual rate = %u\n", + rate, actual_rate); + + + return cd; +} +#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ + + + +static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai); + struct ssc_device *ssc = ssc_p->ssc; + unsigned int pll_out = 0, bclk = 0, mclk_div = 0; + int ret; + + + /* Due to difficulties with getting the correct clocks from the AT32's + * PLL0, we're going to let the CODEC be in charge of all the clocks + */ +#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE + const unsigned int fmt = (SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBM_CFM); +#else + struct ssc_clock_data cd; + const unsigned int fmt = (SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS); +#endif + + if (ssc == NULL) { + pr_warning("playpaq_wm8510_hw_params: ssc is NULL!\n"); + return -EINVAL; + } + + + /* + * Figure out PLL and BCLK dividers for WM8510 + */ + switch (params_rate(params)) { + case 48000: + pll_out = 24576000; + mclk_div = WM8510_MCLKDIV_2; + bclk = WM8510_BCLKDIV_8; + break; + + case 44100: + pll_out = 22579200; + mclk_div = WM8510_MCLKDIV_2; + bclk = WM8510_BCLKDIV_8; + break; + + case 22050: + pll_out = 22579200; + mclk_div = WM8510_MCLKDIV_4; + bclk = WM8510_BCLKDIV_8; + break; + + case 16000: + pll_out = 24576000; + mclk_div = WM8510_MCLKDIV_6; + bclk = WM8510_BCLKDIV_8; + break; + + case 11025: + pll_out = 22579200; + mclk_div = WM8510_MCLKDIV_8; + bclk = WM8510_BCLKDIV_8; + break; + + case 8000: + pll_out = 24576000; + mclk_div = WM8510_MCLKDIV_12; + bclk = WM8510_BCLKDIV_8; + break; + + default: + pr_warning("playpaq_wm8510: Unsupported sample rate %d\n", + params_rate(params)); + return -EINVAL; + } + + + /* + * set CPU and CODEC DAI configuration + */ + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret < 0) { + pr_warning("playpaq_wm8510: " + "Failed to set CODEC DAI format (%d)\n", + ret); + return ret; + } + ret = snd_soc_dai_set_fmt(cpu_dai, fmt); + if (ret < 0) { + pr_warning("playpaq_wm8510: " + "Failed to set CPU DAI format (%d)\n", + ret); + return ret; + } + + + /* + * Set CPU clock configuration + */ +#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE + cd = playpaq_wm8510_calc_ssc_clock(params, cpu_dai); + pr_debug("playpaq_wm8510: cmr_div = %d, period = %d\n", + cd.cmr_div, cd.period); + ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_CMR_DIV, cd.cmr_div); + if (ret < 0) { + pr_warning("playpaq_wm8510: Failed to set CPU CMR_DIV (%d)\n", + ret); + return ret; + } + ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_TCMR_PERIOD, + cd.period); + if (ret < 0) { + pr_warning("playpaq_wm8510: " + "Failed to set CPU transmit period (%d)\n", + ret); + return ret; + } +#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ + + + /* + * Set CODEC clock configuration + */ + pr_debug("playpaq_wm8510: " + "pll_in = %ld, pll_out = %u, bclk = %x, mclk = %x\n", + clk_get_rate(CODEC_CLK), pll_out, bclk, mclk_div); + + +#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE + ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_BCLKDIV, bclk); + if (ret < 0) { + pr_warning + ("playpaq_wm8510: Failed to set CODEC DAI BCLKDIV (%d)\n", + ret); + return ret; + } +#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ + + + ret = snd_soc_dai_set_pll(codec_dai, 0, 0, + clk_get_rate(CODEC_CLK), pll_out); + if (ret < 0) { + pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n", + ret); + return ret; + } + + + ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_MCLKDIV, mclk_div); + if (ret < 0) { + pr_warning("playpaq_wm8510: Failed to set CODEC MCLKDIV (%d)\n", + ret); + return ret; + } + + + return 0; +} + + + +static struct snd_soc_ops playpaq_wm8510_ops = { + .hw_params = playpaq_wm8510_hw_params, +}; + + + +static const struct snd_soc_dapm_widget playpaq_dapm_widgets[] = { + SND_SOC_DAPM_MIC("Int Mic", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), +}; + + + +static const struct snd_soc_dapm_route intercon[] = { + /* speaker connected to SPKOUT */ + {"Ext Spk", NULL, "SPKOUTP"}, + {"Ext Spk", NULL, "SPKOUTN"}, + + {"Mic Bias", NULL, "Int Mic"}, + {"MICN", NULL, "Mic Bias"}, + {"MICP", NULL, "Mic Bias"}, +}; + + + +static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_dapm_context *dapm = &codec->dapm; + int i; + + /* + * Add DAPM widgets + */ + for (i = 0; i < ARRAY_SIZE(playpaq_dapm_widgets); i++) + snd_soc_dapm_new_control(dapm, &playpaq_dapm_widgets[i]); + + + + /* + * Setup audio path interconnects + */ + snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); + + + + /* always connected pins */ + snd_soc_dapm_enable_pin(dapm, "Int Mic"); + snd_soc_dapm_enable_pin(dapm, "Ext Spk"); + + + + /* Make CSB show PLL rate */ + snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV, + WM8510_OPCLKDIV_1 | 4); + + return 0; +} + + + +static struct snd_soc_dai_link playpaq_wm8510_dai = { + .name = "WM8510", + .stream_name = "WM8510 PCM", + .cpu_dai_name= "atmel-ssc-dai.0", + .platform_name = "atmel-pcm-audio", + .codec_name = "wm8510-codec.0-0x1a", + .codec_dai_name = "wm8510-hifi", + .init = playpaq_wm8510_init, + .ops = &playpaq_wm8510_ops, +}; + + + +static struct snd_soc_card snd_soc_playpaq = { + .name = "LRS_PlayPaq_WM8510", + .dai_link = &playpaq_wm8510_dai, + .num_links = 1, +}; + +static struct platform_device *playpaq_snd_device; + + +static int __init playpaq_asoc_init(void) +{ + int ret = 0; + + /* + * Configure MCLK for WM8510 + */ + _gclk0 = clk_get(NULL, "gclk0"); + if (IS_ERR(_gclk0)) { + _gclk0 = NULL; + ret = PTR_ERR(_gclk0); + goto err_gclk0; + } + _pll0 = clk_get(NULL, "pll0"); + if (IS_ERR(_pll0)) { + _pll0 = NULL; + ret = PTR_ERR(_pll0); + goto err_pll0; + } + ret = clk_set_parent(_gclk0, _pll0); + if (ret) { + pr_warning("snd-soc-playpaq: " + "Failed to set PLL0 as parent for DAC clock\n"); + goto err_set_clk; + } + clk_set_rate(CODEC_CLK, 12000000); + clk_enable(CODEC_CLK); + +#if defined CONFIG_AT32_ENHANCED_PORTMUX + at32_select_periph(MCLK_PIN, MCLK_PERIPH, 0); +#endif + + + /* + * Create and register platform device + */ + playpaq_snd_device = platform_device_alloc("soc-audio", 0); + if (playpaq_snd_device == NULL) { + ret = -ENOMEM; + goto err_device_alloc; + } + + platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq); + + ret = platform_device_add(playpaq_snd_device); + if (ret) { + pr_warning("playpaq_wm8510: platform_device_add failed (%d)\n", + ret); + goto err_device_add; + } + + return 0; + + +err_device_add: + if (playpaq_snd_device != NULL) { + platform_device_put(playpaq_snd_device); + playpaq_snd_device = NULL; + } +err_device_alloc: +err_set_clk: + if (_pll0 != NULL) { + clk_put(_pll0); + _pll0 = NULL; + } +err_pll0: + if (_gclk0 != NULL) { + clk_put(_gclk0); + _gclk0 = NULL; + } + return ret; +} + + +static void __exit playpaq_asoc_exit(void) +{ + if (_gclk0 != NULL) { + clk_put(_gclk0); + _gclk0 = NULL; + } + if (_pll0 != NULL) { + clk_put(_pll0); + _pll0 = NULL; + } + +#if defined CONFIG_AT32_ENHANCED_PORTMUX + at32_free_pin(MCLK_PIN); +#endif + + platform_device_unregister(playpaq_snd_device); + playpaq_snd_device = NULL; +} + +module_init(playpaq_asoc_init); +module_exit(playpaq_asoc_exit); + +MODULE_AUTHOR("Geoffrey Wossum "); +MODULE_DESCRIPTION("ASoC machine driver for LRS PlayPaq"); +MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/ad1836.h b/trunk/sound/soc/codecs/ad1836.h index dd7be0dbbc58..444747f0db26 100644 --- a/trunk/sound/soc/codecs/ad1836.h +++ b/trunk/sound/soc/codecs/ad1836.h @@ -34,7 +34,7 @@ #define AD1836_ADC_CTRL2 13 #define AD1836_ADC_WORD_LEN_MASK 0x30 -#define AD1836_ADC_WORD_OFFSET 4 +#define AD1836_ADC_WORD_OFFSET 5 #define AD1836_ADC_SERFMT_MASK (7 << 6) #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) diff --git a/trunk/sound/soc/codecs/cs4270.c b/trunk/sound/soc/codecs/cs4270.c index 73f46eb459f1..f1f237ecec2a 100644 --- a/trunk/sound/soc/codecs/cs4270.c +++ b/trunk/sound/soc/codecs/cs4270.c @@ -601,6 +601,7 @@ static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg) static int cs4270_soc_resume(struct snd_soc_codec *codec) { struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); + struct i2c_client *i2c_client = to_i2c_client(codec->dev); int reg; regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), @@ -611,7 +612,14 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec) ndelay(500); /* first restore the entire register cache ... */ - snd_soc_cache_sync(codec); + for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) { + u8 val = snd_soc_read(codec, reg); + + if (i2c_smbus_write_byte_data(i2c_client, reg, val)) { + dev_err(codec->dev, "i2c write failed\n"); + return -EIO; + } + } /* ... then disable the power-down bits */ reg = snd_soc_read(codec, CS4270_PWRCTL); diff --git a/trunk/sound/soc/codecs/cs42l51.c b/trunk/sound/soc/codecs/cs42l51.c index 1ee66361f61b..8c3c8205d19e 100644 --- a/trunk/sound/soc/codecs/cs42l51.c +++ b/trunk/sound/soc/codecs/cs42l51.c @@ -555,7 +555,7 @@ static int cs42l51_probe(struct snd_soc_codec *codec) static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { .probe = cs42l51_probe, - .reg_cache_size = CS42L51_NUMREGS + 1, + .reg_cache_size = CS42L51_NUMREGS, .reg_word_size = sizeof(u8), }; diff --git a/trunk/sound/soc/codecs/max9877.c b/trunk/sound/soc/codecs/max9877.c index dcf6f2a1600a..9e7e964a5fa3 100644 --- a/trunk/sound/soc/codecs/max9877.c +++ b/trunk/sound/soc/codecs/max9877.c @@ -106,13 +106,13 @@ static int max9877_set_2reg(struct snd_kcontrol *kcontrol, unsigned int mask = mc->max; unsigned int val = (ucontrol->value.integer.value[0] & mask); unsigned int val2 = (ucontrol->value.integer.value[1] & mask); - unsigned int change = 0; + unsigned int change = 1; - if (((max9877_regs[reg] >> shift) & mask) != val) - change = 1; + if (((max9877_regs[reg] >> shift) & mask) == val) + change = 0; - if (((max9877_regs[reg2] >> shift) & mask) != val2) - change = 1; + if (((max9877_regs[reg2] >> shift) & mask) == val2) + change = 0; if (change) { max9877_regs[reg] &= ~(mask << shift); diff --git a/trunk/sound/soc/codecs/wm8994.c b/trunk/sound/soc/codecs/wm8994.c index 6c2988549003..9c982e47eb99 100644 --- a/trunk/sound/soc/codecs/wm8994.c +++ b/trunk/sound/soc/codecs/wm8994.c @@ -2357,11 +2357,6 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT; lrclk = bclk_rate / params_rate(params); - if (!lrclk) { - dev_err(dai->dev, "Unable to generate LRCLK from %dHz BCLK\n", - bclk_rate); - return -EINVAL; - } dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n", lrclk, bclk_rate / lrclk); @@ -3183,8 +3178,6 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) switch (wm8994->revision) { case 0: case 1: - case 2: - case 3: wm8994->hubs.dcs_codes_l = -9; wm8994->hubs.dcs_codes_r = -5; break; diff --git a/trunk/sound/soc/fsl/mpc8610_hpcd.c b/trunk/sound/soc/fsl/mpc8610_hpcd.c index ae49f1c78c6d..31af405bda84 100644 --- a/trunk/sound/soc/fsl/mpc8610_hpcd.c +++ b/trunk/sound/soc/fsl/mpc8610_hpcd.c @@ -392,8 +392,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) } if (strcasecmp(sprop, "i2s-slave") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM; + machine_data->dai_format = SND_SOC_DAIFMT_I2S; machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; @@ -410,38 +409,31 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) } machine_data->clk_frequency = be32_to_cpup(iprop); } else if (strcasecmp(sprop, "i2s-master") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS; + machine_data->dai_format = SND_SOC_DAIFMT_I2S; machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else if (strcasecmp(sprop, "lj-slave") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM; + machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J; machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; } else if (strcasecmp(sprop, "lj-master") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS; + machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J; machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else if (strcasecmp(sprop, "rj-slave") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM; + machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J; machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; } else if (strcasecmp(sprop, "rj-master") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS; + machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J; machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else if (strcasecmp(sprop, "ac97-slave") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM; + machine_data->dai_format = SND_SOC_DAIFMT_AC97; machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; } else if (strcasecmp(sprop, "ac97-master") == 0) { - machine_data->dai_format = - SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS; + machine_data->dai_format = SND_SOC_DAIFMT_AC97; machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else { diff --git a/trunk/sound/soc/samsung/smdk_wm8994.c b/trunk/sound/soc/samsung/smdk_wm8994.c index ad9ac42522e2..f75e43997d5b 100644 --- a/trunk/sound/soc/samsung/smdk_wm8994.c +++ b/trunk/sound/soc/samsung/smdk_wm8994.c @@ -9,7 +9,6 @@ #include "../codecs/wm8994.h" #include -#include /* * Default CFG switch settings to use this driver: diff --git a/trunk/sound/soc/samsung/speyside.c b/trunk/sound/soc/samsung/speyside.c index 4b8e35410eb1..85bf541a771d 100644 --- a/trunk/sound/soc/samsung/speyside.c +++ b/trunk/sound/soc/samsung/speyside.c @@ -191,7 +191,7 @@ static int speyside_late_probe(struct snd_soc_card *card) snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic"); snd_soc_dapm_ignore_suspend(&card->dapm, "Main AMIC"); snd_soc_dapm_ignore_suspend(&card->dapm, "Main DMIC"); - snd_soc_dapm_ignore_suspend(&card->dapm, "Main Speaker"); + snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker"); snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Output"); snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Input"); diff --git a/trunk/sound/soc/soc-core.c b/trunk/sound/soc/soc-core.c index a25fa63ce9a2..a5d3685a5d38 100644 --- a/trunk/sound/soc/soc-core.c +++ b/trunk/sound/soc/soc-core.c @@ -709,12 +709,6 @@ int snd_soc_resume(struct device *dev) struct snd_soc_card *card = dev_get_drvdata(dev); int i, ac97_control = 0; - /* If the initialization of this soc device failed, there is no codec - * associated with it. Just bail out in this case. - */ - if (list_empty(&card->codec_dev_list)) - return 0; - /* AC97 devices might have other drivers hanging off them so * need to resume immediately. Other drivers don't have that * problem and may take a substantial amount of time to resume diff --git a/trunk/sound/usb/quirks-table.h b/trunk/sound/usb/quirks-table.h index 32d2a21f2e3b..b61945f3af9e 100644 --- a/trunk/sound/usb/quirks-table.h +++ b/trunk/sound/usb/quirks-table.h @@ -1632,37 +1632,6 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, -{ - /* Roland GAIA SH-01 */ - USB_DEVICE(0x0582, 0x0111), - .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { - .vendor_name = "Roland", - .product_name = "GAIA", - .ifnum = QUIRK_ANY_INTERFACE, - .type = QUIRK_COMPOSITE, - .data = (const struct snd_usb_audio_quirk[]) { - { - .ifnum = 0, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 1, - .type = QUIRK_AUDIO_STANDARD_INTERFACE - }, - { - .ifnum = 2, - .type = QUIRK_MIDI_FIXED_ENDPOINT, - .data = &(const struct snd_usb_midi_endpoint_info) { - .out_cables = 0x0003, - .in_cables = 0x0003 - } - }, - { - .ifnum = -1 - } - } - } -}, { USB_DEVICE(0x0582, 0x0113), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { diff --git a/trunk/tools/perf/util/evsel.c b/trunk/tools/perf/util/evsel.c index d7915d4e77cb..e42626422587 100644 --- a/trunk/tools/perf/util/evsel.c +++ b/trunk/tools/perf/util/evsel.c @@ -34,16 +34,6 @@ int __perf_evsel__sample_size(u64 sample_type) return size; } -static void hists__init(struct hists *hists) -{ - memset(hists, 0, sizeof(*hists)); - hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; - hists->entries_in = &hists->entries_in_array[0]; - hists->entries_collapsed = RB_ROOT; - hists->entries = RB_ROOT; - pthread_mutex_init(&hists->lock, NULL); -} - void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr, int idx) { diff --git a/trunk/tools/perf/util/hist.c b/trunk/tools/perf/util/hist.c index abef2703cd24..a36a3fa81ffb 100644 --- a/trunk/tools/perf/util/hist.c +++ b/trunk/tools/perf/util/hist.c @@ -1211,3 +1211,13 @@ size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp) return ret; } + +void hists__init(struct hists *hists) +{ + memset(hists, 0, sizeof(*hists)); + hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; + hists->entries_in = &hists->entries_in_array[0]; + hists->entries_collapsed = RB_ROOT; + hists->entries = RB_ROOT; + pthread_mutex_init(&hists->lock, NULL); +} diff --git a/trunk/tools/perf/util/hist.h b/trunk/tools/perf/util/hist.h index 89289c8e935e..c86c1d27bd1e 100644 --- a/trunk/tools/perf/util/hist.h +++ b/trunk/tools/perf/util/hist.h @@ -63,6 +63,8 @@ struct hists { struct callchain_cursor callchain_cursor; }; +void hists__init(struct hists *hists); + struct hist_entry *__hists__add_entry(struct hists *self, struct addr_location *al, struct symbol *parent, u64 period); diff --git a/trunk/tools/perf/util/session.c b/trunk/tools/perf/util/session.c index 0f4555ce9063..85c1e6b76f0a 100644 --- a/trunk/tools/perf/util/session.c +++ b/trunk/tools/perf/util/session.c @@ -1333,10 +1333,6 @@ int perf_session__cpu_bitmap(struct perf_session *session, } map = cpu_map__new(cpu_list); - if (map == NULL) { - pr_err("Invalid cpu_list\n"); - return -1; - } for (i = 0; i < map->nr; i++) { int cpu = map->map[i]; diff --git a/trunk/tools/perf/util/trace-event-parse.c b/trunk/tools/perf/util/trace-event-parse.c index 6c164dc9ee95..0a7ed5b5e281 100644 --- a/trunk/tools/perf/util/trace-event-parse.c +++ b/trunk/tools/perf/util/trace-event-parse.c @@ -1537,8 +1537,6 @@ process_flags(struct event *event, struct print_arg *arg, char **tok) field = malloc_or_die(sizeof(*field)); type = process_arg(event, field, &token); - while (type == EVENT_OP) - type = process_op(event, field, &token); if (test_type_token(type, token, EVENT_DELIM, ",")) goto out_free;