mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-28 04:17:47 +00:00
Merge branch 'arch-arm64' into no-rebases
This commit is contained in:
commit
9526d9bc23
@ -27,17 +27,17 @@ Start End Size Use
|
||||
-----------------------------------------------------------------------
|
||||
0000000000000000 0000007fffffffff 512GB user
|
||||
|
||||
ffffff8000000000 ffffffbbfffcffff ~240GB vmalloc
|
||||
ffffff8000000000 ffffffbbfffeffff ~240GB vmalloc
|
||||
|
||||
ffffffbbfffd0000 ffffffbcfffdffff 64KB [guard page]
|
||||
|
||||
ffffffbbfffe0000 ffffffbcfffeffff 64KB PCI I/O space
|
||||
|
||||
ffffffbbffff0000 ffffffbcffffffff 64KB [guard page]
|
||||
ffffffbbffff0000 ffffffbbffffffff 64KB [guard page]
|
||||
|
||||
ffffffbc00000000 ffffffbdffffffff 8GB vmemmap
|
||||
|
||||
ffffffbe00000000 ffffffbffbffffff ~8GB [guard, future vmmemap]
|
||||
ffffffbe00000000 ffffffbffbbfffff ~8GB [guard, future vmmemap]
|
||||
|
||||
ffffffbffbe00000 ffffffbffbe0ffff 64KB PCI I/O space
|
||||
|
||||
ffffffbbffff0000 ffffffbcffffffff ~2MB [guard]
|
||||
|
||||
ffffffbffc000000 ffffffbfffffffff 64MB modules
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
* EETI eGalax Multiple Touch Controller
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "eeti,egalax_ts"
|
||||
- reg: i2c slave address
|
||||
- interrupt-parent: the phandle for the interrupt controller
|
||||
- interrupts: touch controller interrupt
|
||||
- wakeup-gpios: the gpio pin to be used for waking up the controller
|
||||
as well as uased as irq pin
|
||||
|
||||
Example:
|
||||
|
||||
egalax_ts@04 {
|
||||
compatible = "eeti,egalax_ts";
|
||||
reg = <0x04>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <9 2>;
|
||||
wakeup-gpios = <&gpio1 9 0>;
|
||||
};
|
@ -10,7 +10,7 @@ Supported chips:
|
||||
BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors
|
||||
(not yet published)
|
||||
|
||||
Author: Andreas Herrmann <andreas.herrmann3@amd.com>
|
||||
Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
@ -503,7 +503,7 @@ F: include/linux/altera_uart.h
|
||||
F: include/linux/altera_jtaguart.h
|
||||
|
||||
AMD FAM15H PROCESSOR POWER MONITORING DRIVER
|
||||
M: Andreas Herrmann <andreas.herrmann3@amd.com>
|
||||
M: Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/fam15h_power
|
||||
@ -2507,6 +2507,7 @@ M: Joonyoung Shim <jy0922.shim@samsung.com>
|
||||
M: Seung-Woo Kim <sw0312.kim@samsung.com>
|
||||
M: Kyungmin Park <kyungmin.park@samsung.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git
|
||||
S: Supported
|
||||
F: drivers/gpu/drm/exynos
|
||||
F: include/drm/exynos*
|
||||
|
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
VERSION = 3
|
||||
PATCHLEVEL = 7
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc3
|
||||
EXTRAVERSION = -rc4
|
||||
NAME = Terrified Chipmunk
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
@ -48,20 +48,16 @@
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/opcodes-virt.h>
|
||||
#include <xen/interface/xen.h>
|
||||
|
||||
|
||||
/* HVC 0xEA1 */
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
#define xen_hvc .word 0xf7e08ea1
|
||||
#else
|
||||
#define xen_hvc .word 0xe140ea71
|
||||
#endif
|
||||
#define XEN_IMM 0xEA1
|
||||
|
||||
#define HYPERCALL_SIMPLE(hypercall) \
|
||||
ENTRY(HYPERVISOR_##hypercall) \
|
||||
mov r12, #__HYPERVISOR_##hypercall; \
|
||||
xen_hvc; \
|
||||
__HVC(XEN_IMM); \
|
||||
mov pc, lr; \
|
||||
ENDPROC(HYPERVISOR_##hypercall)
|
||||
|
||||
@ -76,7 +72,7 @@ ENTRY(HYPERVISOR_##hypercall) \
|
||||
stmdb sp!, {r4} \
|
||||
ldr r4, [sp, #4] \
|
||||
mov r12, #__HYPERVISOR_##hypercall; \
|
||||
xen_hvc \
|
||||
__HVC(XEN_IMM); \
|
||||
ldm sp!, {r4} \
|
||||
mov pc, lr \
|
||||
ENDPROC(HYPERVISOR_##hypercall)
|
||||
@ -100,7 +96,7 @@ ENTRY(privcmd_call)
|
||||
mov r2, r3
|
||||
ldr r3, [sp, #8]
|
||||
ldr r4, [sp, #4]
|
||||
xen_hvc
|
||||
__HVC(XEN_IMM)
|
||||
ldm sp!, {r4}
|
||||
mov pc, lr
|
||||
ENDPROC(privcmd_call);
|
||||
|
@ -25,12 +25,10 @@
|
||||
#include <asm/user.h>
|
||||
|
||||
typedef unsigned long elf_greg_t;
|
||||
typedef unsigned long elf_freg_t[3];
|
||||
|
||||
#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
|
||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||
|
||||
typedef struct user_fp elf_fpregset_t;
|
||||
typedef struct user_fpsimd_state elf_fpregset_t;
|
||||
|
||||
#define EM_AARCH64 183
|
||||
|
||||
@ -87,7 +85,6 @@ typedef struct user_fp elf_fpregset_t;
|
||||
#define R_AARCH64_MOVW_PREL_G2_NC 292
|
||||
#define R_AARCH64_MOVW_PREL_G3 293
|
||||
|
||||
|
||||
/*
|
||||
* These are used to set parameters in the core dumps.
|
||||
*/
|
||||
|
@ -25,9 +25,8 @@
|
||||
* - FPSR and FPCR
|
||||
* - 32 128-bit data registers
|
||||
*
|
||||
* Note that user_fp forms a prefix of this structure, which is relied
|
||||
* upon in the ptrace FP/SIMD accessors. struct user_fpsimd_state must
|
||||
* form a prefix of struct fpsimd_state.
|
||||
* Note that user_fpsimd forms a prefix of this structure, which is
|
||||
* relied upon in the ptrace FP/SIMD accessors.
|
||||
*/
|
||||
struct fpsimd_state {
|
||||
union {
|
||||
|
@ -114,7 +114,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
|
||||
* I/O port access primitives.
|
||||
*/
|
||||
#define IO_SPACE_LIMIT 0xffff
|
||||
#define PCI_IOBASE ((void __iomem *)0xffffffbbfffe0000UL)
|
||||
#define PCI_IOBASE ((void __iomem *)(MODULES_VADDR - SZ_2M))
|
||||
|
||||
static inline u8 inb(unsigned long addr)
|
||||
{
|
||||
@ -225,9 +225,9 @@ extern void __iounmap(volatile void __iomem *addr);
|
||||
#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
|
||||
#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC))
|
||||
|
||||
#define ioremap(addr, size) __ioremap((addr), (size), PROT_DEVICE_nGnRE)
|
||||
#define ioremap_nocache(addr, size) __ioremap((addr), (size), PROT_DEVICE_nGnRE)
|
||||
#define ioremap_wc(addr, size) __ioremap((addr), (size), PROT_NORMAL_NC)
|
||||
#define ioremap(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
|
||||
#define ioremap_nocache(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
|
||||
#define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
|
||||
#define iounmap __iounmap
|
||||
|
||||
#define ARCH_HAS_IOREMAP_WC
|
||||
|
@ -23,15 +23,16 @@
|
||||
/*
|
||||
* System call wrappers implemented in kernel/entry.S.
|
||||
*/
|
||||
asmlinkage long sys_clone_wrapper(unsigned long clone_flags,
|
||||
unsigned long newsp,
|
||||
void __user *parent_tid,
|
||||
unsigned long tls_val,
|
||||
void __user *child_tid);
|
||||
asmlinkage long sys_rt_sigreturn_wrapper(void);
|
||||
asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss,
|
||||
stack_t __user *uoss);
|
||||
|
||||
/*
|
||||
* AArch64 sys_clone implementation has a different prototype than the generic
|
||||
* one (additional TLS value argument).
|
||||
*/
|
||||
#define sys_clone sys_clone
|
||||
|
||||
#include <asm-generic/syscalls.h>
|
||||
|
||||
#endif /* __ASM_SYSCALLS_H */
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
__SYSCALL(0, sys_restart_syscall)
|
||||
__SYSCALL(1, sys_exit)
|
||||
__SYSCALL(2, compat_sys_fork_wrapper)
|
||||
__SYSCALL(2, compat_sys_fork)
|
||||
__SYSCALL(3, sys_read)
|
||||
__SYSCALL(4, sys_write)
|
||||
__SYSCALL(5, compat_sys_open)
|
||||
@ -141,7 +141,7 @@ __SYSCALL(116, compat_sys_sysinfo)
|
||||
__SYSCALL(117, sys_ni_syscall) /* 117 was sys_ipc */
|
||||
__SYSCALL(118, sys_fsync)
|
||||
__SYSCALL(119, compat_sys_sigreturn_wrapper)
|
||||
__SYSCALL(120, compat_sys_clone_wrapper)
|
||||
__SYSCALL(120, sys_clone)
|
||||
__SYSCALL(121, sys_setdomainname)
|
||||
__SYSCALL(122, sys_newuname)
|
||||
__SYSCALL(123, sys_ni_syscall) /* 123 was sys_modify_ldt */
|
||||
@ -211,7 +211,7 @@ __SYSCALL(186, compat_sys_sigaltstack_wrapper)
|
||||
__SYSCALL(187, compat_sys_sendfile)
|
||||
__SYSCALL(188, sys_ni_syscall) /* 188 reserved */
|
||||
__SYSCALL(189, sys_ni_syscall) /* 189 reserved */
|
||||
__SYSCALL(190, compat_sys_vfork_wrapper)
|
||||
__SYSCALL(190, compat_sys_vfork)
|
||||
__SYSCALL(191, compat_sys_getrlimit) /* SuS compliant getrlimit */
|
||||
__SYSCALL(192, sys_mmap_pgoff)
|
||||
__SYSCALL(193, compat_sys_truncate64_wrapper)
|
||||
|
@ -676,11 +676,6 @@ __sys_trace_return:
|
||||
/*
|
||||
* Special system call wrappers.
|
||||
*/
|
||||
ENTRY(sys_clone_wrapper)
|
||||
mov x5, sp
|
||||
b sys_clone
|
||||
ENDPROC(sys_clone_wrapper)
|
||||
|
||||
ENTRY(sys_rt_sigreturn_wrapper)
|
||||
mov x0, sp
|
||||
b sys_rt_sigreturn
|
||||
|
@ -613,17 +613,11 @@ enum armv8_pmuv3_perf_types {
|
||||
ARMV8_PMUV3_PERFCTR_BUS_ACCESS = 0x19,
|
||||
ARMV8_PMUV3_PERFCTR_MEM_ERROR = 0x1A,
|
||||
ARMV8_PMUV3_PERFCTR_BUS_CYCLES = 0x1D,
|
||||
|
||||
/*
|
||||
* This isn't an architected event.
|
||||
* We detect this event number and use the cycle counter instead.
|
||||
*/
|
||||
ARMV8_PMUV3_PERFCTR_CPU_CYCLES = 0xFF,
|
||||
};
|
||||
|
||||
/* PMUv3 HW events mapping. */
|
||||
static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
|
||||
[PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
|
||||
[PERF_COUNT_HW_CPU_CYCLES] = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
|
||||
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
|
||||
[PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
|
||||
[PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
|
||||
@ -1106,7 +1100,7 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc,
|
||||
unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT;
|
||||
|
||||
/* Always place a cycle counter into the cycle counter. */
|
||||
if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) {
|
||||
if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) {
|
||||
if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask))
|
||||
return -EAGAIN;
|
||||
|
||||
|
@ -246,14 +246,20 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
|
||||
*childregs = *regs;
|
||||
childregs->regs[0] = 0;
|
||||
if (is_compat_thread(task_thread_info(p))) {
|
||||
childregs->compat_sp = stack_start;
|
||||
if (stack_start)
|
||||
childregs->compat_sp = stack_start;
|
||||
} else {
|
||||
/*
|
||||
* Read the current TLS pointer from tpidr_el0 as it may be
|
||||
* out-of-sync with the saved value.
|
||||
*/
|
||||
asm("mrs %0, tpidr_el0" : "=r" (tls));
|
||||
childregs->sp = stack_start;
|
||||
if (stack_start) {
|
||||
/* 16-byte aligned stack mandatory on AArch64 */
|
||||
if (stack_start & 15)
|
||||
return -EINVAL;
|
||||
childregs->sp = stack_start;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If a TLS pointer was passed to clone (4th argument), use it
|
||||
@ -317,24 +323,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
|
||||
return last;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the task's elfregs structure for a core dump.
|
||||
*/
|
||||
int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
|
||||
{
|
||||
elf_core_copy_regs(elfregs, task_pt_regs(t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* fill in the fpe structure for a core dump...
|
||||
*/
|
||||
int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dump_fpu);
|
||||
|
||||
unsigned long get_wchan(struct task_struct *p)
|
||||
{
|
||||
struct stackframe frame;
|
||||
|
@ -31,14 +31,10 @@
|
||||
*/
|
||||
asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
|
||||
int __user *parent_tidptr, unsigned long tls_val,
|
||||
int __user *child_tidptr, struct pt_regs *regs)
|
||||
int __user *child_tidptr)
|
||||
{
|
||||
if (!newsp)
|
||||
newsp = regs->sp;
|
||||
/* 16-byte aligned stack mandatory on AArch64 */
|
||||
if (newsp & 15)
|
||||
return -EINVAL;
|
||||
return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
|
||||
return do_fork(clone_flags, newsp, current_pt_regs(), 0,
|
||||
parent_tidptr, child_tidptr);
|
||||
}
|
||||
|
||||
asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
|
||||
@ -54,7 +50,6 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
|
||||
/*
|
||||
* Wrappers to pass the pt_regs argument.
|
||||
*/
|
||||
#define sys_clone sys_clone_wrapper
|
||||
#define sys_rt_sigreturn sys_rt_sigreturn_wrapper
|
||||
#define sys_sigaltstack sys_sigaltstack_wrapper
|
||||
|
||||
|
@ -26,20 +26,6 @@
|
||||
/*
|
||||
* System call wrappers for the AArch32 compatibility layer.
|
||||
*/
|
||||
compat_sys_fork_wrapper:
|
||||
mov x0, sp
|
||||
b compat_sys_fork
|
||||
ENDPROC(compat_sys_fork_wrapper)
|
||||
|
||||
compat_sys_vfork_wrapper:
|
||||
mov x0, sp
|
||||
b compat_sys_vfork
|
||||
ENDPROC(compat_sys_vfork_wrapper)
|
||||
|
||||
compat_sys_clone_wrapper:
|
||||
mov x5, sp
|
||||
b compat_sys_clone
|
||||
ENDPROC(compat_sys_clone_wrapper)
|
||||
|
||||
compat_sys_sigreturn_wrapper:
|
||||
mov x0, sp
|
||||
|
@ -28,25 +28,15 @@
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/unistd32.h>
|
||||
|
||||
asmlinkage int compat_sys_fork(struct pt_regs *regs)
|
||||
asmlinkage int compat_sys_fork(void)
|
||||
{
|
||||
return do_fork(SIGCHLD, regs->compat_sp, regs, 0, NULL, NULL);
|
||||
return do_fork(SIGCHLD, 0, current_pt_regs(), 0, NULL, NULL);
|
||||
}
|
||||
|
||||
asmlinkage int compat_sys_clone(unsigned long clone_flags, unsigned long newsp,
|
||||
int __user *parent_tidptr, int tls_val,
|
||||
int __user *child_tidptr, struct pt_regs *regs)
|
||||
asmlinkage int compat_sys_vfork(void)
|
||||
{
|
||||
if (!newsp)
|
||||
newsp = regs->compat_sp;
|
||||
|
||||
return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
|
||||
}
|
||||
|
||||
asmlinkage int compat_sys_vfork(struct pt_regs *regs)
|
||||
{
|
||||
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->compat_sp,
|
||||
regs, 0, NULL, NULL);
|
||||
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0,
|
||||
current_pt_regs(), 0, NULL, NULL);
|
||||
}
|
||||
|
||||
asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid,
|
||||
|
@ -33,7 +33,6 @@
|
||||
#ifndef _ASM_X86_XEN_HYPERVISOR_H
|
||||
#define _ASM_X86_XEN_HYPERVISOR_H
|
||||
|
||||
/* arch/i386/kernel/setup.c */
|
||||
extern struct shared_info *HYPERVISOR_shared_info;
|
||||
extern struct start_info *xen_start_info;
|
||||
|
||||
|
@ -1288,6 +1288,25 @@ unsigned long xen_read_cr2_direct(void)
|
||||
return this_cpu_read(xen_vcpu_info.arch.cr2);
|
||||
}
|
||||
|
||||
void xen_flush_tlb_all(void)
|
||||
{
|
||||
struct mmuext_op *op;
|
||||
struct multicall_space mcs;
|
||||
|
||||
trace_xen_mmu_flush_tlb_all(0);
|
||||
|
||||
preempt_disable();
|
||||
|
||||
mcs = xen_mc_entry(sizeof(*op));
|
||||
|
||||
op = mcs.args;
|
||||
op->cmd = MMUEXT_TLB_FLUSH_ALL;
|
||||
MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
|
||||
|
||||
xen_mc_issue(PARAVIRT_LAZY_MMU);
|
||||
|
||||
preempt_enable();
|
||||
}
|
||||
static void xen_flush_tlb(void)
|
||||
{
|
||||
struct mmuext_op *op;
|
||||
@ -2518,7 +2537,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
|
||||
err = 0;
|
||||
out:
|
||||
|
||||
flush_tlb_all();
|
||||
xen_flush_tlb_all();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -1345,12 +1345,15 @@ static int
|
||||
acpi_video_bus_get_devices(struct acpi_video_bus *video,
|
||||
struct acpi_device *device)
|
||||
{
|
||||
int status;
|
||||
int status = 0;
|
||||
struct acpi_device *dev;
|
||||
|
||||
status = acpi_video_device_enumerate(video);
|
||||
if (status)
|
||||
return status;
|
||||
/*
|
||||
* There are systems where video module known to work fine regardless
|
||||
* of broken _DOD and ignoring returned value here doesn't cause
|
||||
* any issues later.
|
||||
*/
|
||||
acpi_video_device_enumerate(video);
|
||||
|
||||
list_for_each_entry(dev, &device->children, node) {
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Maintainer:
|
||||
* Andreas Herrmann <andreas.herrmann3@amd.com>
|
||||
* Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
*
|
||||
* Based on the powernow-k7.c module written by Dave Jones.
|
||||
* (C) 2003 Dave Jones on behalf of SuSE Labs
|
||||
|
@ -1,6 +1,6 @@
|
||||
config DRM_EXYNOS
|
||||
tristate "DRM Support for Samsung SoC EXYNOS Series"
|
||||
depends on DRM && PLAT_SAMSUNG
|
||||
depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)
|
||||
select DRM_KMS_HELPER
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
|
@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
|
||||
exynos_connector->encoder_id = encoder->base.id;
|
||||
exynos_connector->manager = manager;
|
||||
exynos_connector->dpms = DRM_MODE_DPMS_OFF;
|
||||
connector->dpms = DRM_MODE_DPMS_OFF;
|
||||
connector->encoder = encoder;
|
||||
|
||||
err = drm_mode_connector_attach_encoder(connector, encoder);
|
||||
|
@ -43,12 +43,14 @@
|
||||
* @manager: specific encoder has its own manager to control a hardware
|
||||
* appropriately and we can access a hardware drawing on this manager.
|
||||
* @dpms: store the encoder dpms value.
|
||||
* @updated: indicate whether overlay data updating is needed or not.
|
||||
*/
|
||||
struct exynos_drm_encoder {
|
||||
struct drm_crtc *old_crtc;
|
||||
struct drm_encoder drm_encoder;
|
||||
struct exynos_drm_manager *manager;
|
||||
int dpms;
|
||||
int dpms;
|
||||
bool updated;
|
||||
};
|
||||
|
||||
static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
|
||||
@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
if (manager_ops && manager_ops->apply)
|
||||
manager_ops->apply(manager->dev);
|
||||
if (!exynos_encoder->updated)
|
||||
manager_ops->apply(manager->dev);
|
||||
|
||||
exynos_drm_connector_power(encoder, mode);
|
||||
exynos_encoder->dpms = mode;
|
||||
break;
|
||||
@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
exynos_drm_connector_power(encoder, mode);
|
||||
exynos_encoder->dpms = mode;
|
||||
exynos_encoder->updated = false;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unspecified mode %d\n", mode);
|
||||
@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
|
||||
|
||||
static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
|
||||
{
|
||||
struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
|
||||
struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
|
||||
struct exynos_drm_manager *manager = exynos_encoder->manager;
|
||||
struct exynos_drm_manager_ops *manager_ops = manager->ops;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (manager_ops && manager_ops->commit)
|
||||
manager_ops->commit(manager->dev);
|
||||
|
||||
/*
|
||||
* this will avoid one issue that overlay data is updated to
|
||||
* real hardware two times.
|
||||
* And this variable will be used to check if the data was
|
||||
* already updated or not by exynos_drm_encoder_dpms function.
|
||||
*/
|
||||
exynos_encoder->updated = true;
|
||||
}
|
||||
|
||||
static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
|
||||
@ -400,19 +414,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
|
||||
if (manager_ops && manager_ops->dpms)
|
||||
manager_ops->dpms(manager->dev, mode);
|
||||
|
||||
/*
|
||||
* set current mode to new one so that data aren't updated into
|
||||
* registers by drm_helper_connector_dpms two times.
|
||||
*
|
||||
* in case that drm_crtc_helper_set_mode() is called,
|
||||
* overlay_ops->commit() and manager_ops->commit() callbacks
|
||||
* can be called two times, first at drm_crtc_helper_set_mode()
|
||||
* and second at drm_helper_connector_dpms().
|
||||
* so with this setting, when drm_helper_connector_dpms() is called
|
||||
* encoder->funcs->dpms() will be ignored.
|
||||
*/
|
||||
exynos_encoder->dpms = mode;
|
||||
|
||||
/*
|
||||
* if this condition is ok then it means that the crtc is already
|
||||
* detached from encoder and last function for detaching is properly
|
||||
|
@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)
|
||||
const struct of_device_id *match;
|
||||
match = of_match_node(of_match_ptr(mixer_match_types),
|
||||
pdev->dev.of_node);
|
||||
drv = match->data;
|
||||
drv = (struct mixer_drv_data *)match->data;
|
||||
} else {
|
||||
drv = (struct mixer_drv_data *)
|
||||
platform_get_device_id(pdev)->driver_data;
|
||||
|
@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
goto put_gmch;
|
||||
}
|
||||
|
||||
i915_kick_out_firmware_fb(dev_priv);
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
i915_kick_out_firmware_fb(dev_priv);
|
||||
|
||||
pci_set_master(dev->pdev);
|
||||
|
||||
|
@ -729,7 +729,7 @@ void intel_crt_init(struct drm_device *dev)
|
||||
|
||||
crt->base.type = INTEL_OUTPUT_ANALOG;
|
||||
crt->base.cloneable = true;
|
||||
if (IS_HASWELL(dev))
|
||||
if (IS_HASWELL(dev) || IS_I830(dev))
|
||||
crt->base.crtc_mask = (1 << 0);
|
||||
else
|
||||
crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
|
||||
|
@ -341,9 +341,17 @@ static int intel_overlay_off(struct intel_overlay *overlay)
|
||||
intel_ring_emit(ring, flip_addr);
|
||||
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
/* turn overlay off */
|
||||
intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
||||
intel_ring_emit(ring, flip_addr);
|
||||
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
if (IS_I830(dev)) {
|
||||
/* Workaround: Don't disable the overlay fully, since otherwise
|
||||
* it dies on the next OVERLAY_ON cmd. */
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
} else {
|
||||
intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
||||
intel_ring_emit(ring, flip_addr);
|
||||
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
}
|
||||
intel_ring_advance(ring);
|
||||
|
||||
return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
|
||||
|
@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev)
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.max_brightness = _intel_panel_get_max_backlight(dev);
|
||||
if (props.max_brightness == 0) {
|
||||
DRM_ERROR("Failed to get maximum backlight value\n");
|
||||
DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
dev_priv->backlight =
|
||||
|
@ -894,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
|
||||
unsigned if_index, uint8_t tx_rate,
|
||||
uint8_t *data, unsigned length)
|
||||
{
|
||||
uint8_t set_buf_index[2] = { if_index, 0 };
|
||||
uint8_t hbuf_size, tmp[8];
|
||||
int i;
|
||||
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_INDEX,
|
||||
set_buf_index, 2))
|
||||
return false;
|
||||
|
||||
if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO,
|
||||
&hbuf_size, 1))
|
||||
return false;
|
||||
|
||||
/* Buffer size is 0 based, hooray! */
|
||||
hbuf_size++;
|
||||
|
||||
DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n",
|
||||
if_index, length, hbuf_size);
|
||||
|
||||
for (i = 0; i < hbuf_size; i += 8) {
|
||||
memset(tmp, 0, 8);
|
||||
if (i < length)
|
||||
memcpy(tmp, data + i, min_t(unsigned, 8, length - i));
|
||||
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_DATA,
|
||||
tmp, 8))
|
||||
return false;
|
||||
}
|
||||
|
||||
return intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_TXRATE,
|
||||
&tx_rate, 1);
|
||||
}
|
||||
|
||||
static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
|
||||
{
|
||||
struct dip_infoframe avi_if = {
|
||||
@ -901,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
|
||||
.ver = DIP_VERSION_AVI,
|
||||
.len = DIP_LEN_AVI,
|
||||
};
|
||||
uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
|
||||
uint8_t set_buf_index[2] = { 1, 0 };
|
||||
uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
|
||||
uint64_t *data = (uint64_t *)sdvo_data;
|
||||
unsigned i;
|
||||
|
||||
intel_dip_infoframe_csum(&avi_if);
|
||||
|
||||
@ -915,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
|
||||
sdvo_data[3] = avi_if.checksum;
|
||||
memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
|
||||
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_INDEX,
|
||||
set_buf_index, 2))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < sizeof(sdvo_data); i += 8) {
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_DATA,
|
||||
data, 8))
|
||||
return false;
|
||||
data++;
|
||||
}
|
||||
|
||||
return intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_TXRATE,
|
||||
&tx_rate, 1);
|
||||
return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
|
||||
SDVO_HBUF_TX_VSYNC,
|
||||
sdvo_data, sizeof(sdvo_data));
|
||||
}
|
||||
|
||||
static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
|
||||
|
@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {
|
||||
#define SDVO_CMD_SET_AUDIO_STAT 0x91
|
||||
#define SDVO_CMD_GET_AUDIO_STAT 0x92
|
||||
#define SDVO_CMD_SET_HBUF_INDEX 0x93
|
||||
#define SDVO_HBUF_INDEX_ELD 0
|
||||
#define SDVO_HBUF_INDEX_AVI_IF 1
|
||||
#define SDVO_CMD_GET_HBUF_INDEX 0x94
|
||||
#define SDVO_CMD_GET_HBUF_INFO 0x95
|
||||
#define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96
|
||||
|
@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p,
|
||||
/* macro tile width & height */
|
||||
palign = (8 * surf->bankw * track->npipes) * surf->mtilea;
|
||||
halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea;
|
||||
mtileb = (palign / 8) * (halign / 8) * tileb;;
|
||||
mtileb = (palign / 8) * (halign / 8) * tileb;
|
||||
mtile_pr = surf->nbx / palign;
|
||||
mtile_ps = (mtile_pr * surf->nby) / halign;
|
||||
surf->layer_size = mtile_ps * mtileb * slice_pt;
|
||||
|
@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
|
||||
}
|
||||
|
||||
/**
|
||||
* radeon_atpx_switchto - switch to the requested GPU
|
||||
* radeon_atpx_power_state - power down/up the requested GPU
|
||||
*
|
||||
* @id: GPU to switch to
|
||||
* @id: GPU to power down/up
|
||||
* @state: requested power state (0 = off, 1 = on)
|
||||
*
|
||||
* Execute the necessary ATPX function to power down/up the discrete GPU
|
||||
|
@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
||||
struct drm_mode_object *obj;
|
||||
int i;
|
||||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
bool dret = false;
|
||||
bool dret = false, broken_edid = false;
|
||||
|
||||
if (!force && radeon_check_hpd_status_unchanged(connector))
|
||||
return connector->status;
|
||||
@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
||||
ret = connector_status_disconnected;
|
||||
DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));
|
||||
radeon_connector->ddc_bus = NULL;
|
||||
} else {
|
||||
ret = connector_status_connected;
|
||||
broken_edid = true; /* defer use_digital to later */
|
||||
}
|
||||
} else {
|
||||
radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
|
||||
@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
||||
|
||||
encoder_funcs = encoder->helper_private;
|
||||
if (encoder_funcs->detect) {
|
||||
if (ret != connector_status_connected) {
|
||||
ret = encoder_funcs->detect(encoder, connector);
|
||||
if (ret == connector_status_connected) {
|
||||
radeon_connector->use_digital = false;
|
||||
if (!broken_edid) {
|
||||
if (ret != connector_status_connected) {
|
||||
/* deal with analog monitors without DDC */
|
||||
ret = encoder_funcs->detect(encoder, connector);
|
||||
if (ret == connector_status_connected) {
|
||||
radeon_connector->use_digital = false;
|
||||
}
|
||||
if (ret != connector_status_disconnected)
|
||||
radeon_connector->detected_by_load = true;
|
||||
}
|
||||
if (ret != connector_status_disconnected)
|
||||
radeon_connector->detected_by_load = true;
|
||||
} else {
|
||||
enum drm_connector_status lret;
|
||||
/* assume digital unless load detected otherwise */
|
||||
radeon_connector->use_digital = true;
|
||||
lret = encoder_funcs->detect(encoder, connector);
|
||||
DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret);
|
||||
if (lret == connector_status_connected)
|
||||
radeon_connector->use_digital = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t crtc_ext_cntl = 0;
|
||||
uint32_t mask;
|
||||
|
||||
if (radeon_crtc->crtc_id)
|
||||
@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
RADEON_CRTC_VSYNC_DIS |
|
||||
RADEON_CRTC_HSYNC_DIS);
|
||||
|
||||
/*
|
||||
* On all dual CRTC GPUs this bit controls the CRTC of the primary DAC.
|
||||
* Therefore it is set in the DAC DMPS function.
|
||||
* This is different for GPU's with a single CRTC but a primary and a
|
||||
* TV DAC: here it controls the single CRTC no matter where it is
|
||||
* routed. Therefore we set it here.
|
||||
*/
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC)
|
||||
crtc_ext_cntl = RADEON_CRTC_CRT_ON;
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
radeon_crtc->enabled = true;
|
||||
@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
else {
|
||||
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
|
||||
RADEON_CRTC_DISP_REQ_EN_B));
|
||||
WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask);
|
||||
WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));
|
||||
}
|
||||
drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
|
||||
radeon_crtc_load_lut(crtc);
|
||||
@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
else {
|
||||
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
|
||||
RADEON_CRTC_DISP_REQ_EN_B));
|
||||
WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
|
||||
WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl));
|
||||
}
|
||||
radeon_crtc->enabled = false;
|
||||
/* adjust pm to dpms changes AFTER disabling crtcs */
|
||||
|
@ -537,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
|
||||
break;
|
||||
}
|
||||
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
|
||||
/* handled in radeon_crtc_dpms() */
|
||||
if (!(rdev->flags & RADEON_SINGLE_CRTC))
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
|
||||
WREG32(RADEON_DAC_CNTL, dac_cntl);
|
||||
WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
|
||||
|
||||
@ -662,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
|
||||
|
||||
if (ASIC_IS_R300(rdev))
|
||||
tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
|
||||
else if (ASIC_IS_RV100(rdev))
|
||||
tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);
|
||||
else
|
||||
tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
|
||||
|
||||
@ -671,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
|
||||
tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
|
||||
WREG32(RADEON_DAC_CNTL, tmp);
|
||||
|
||||
tmp = dac_macro_cntl;
|
||||
tmp &= ~(RADEON_DAC_PDWN_R |
|
||||
RADEON_DAC_PDWN_G |
|
||||
RADEON_DAC_PDWN_B);
|
||||
@ -1092,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
|
||||
} else {
|
||||
if (is_tv)
|
||||
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
|
||||
else
|
||||
/* handled in radeon_crtc_dpms() */
|
||||
else if (!(rdev->flags & RADEON_SINGLE_CRTC))
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
|
||||
}
|
||||
@ -1416,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
|
||||
return found;
|
||||
}
|
||||
|
||||
static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
|
||||
uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
|
||||
uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
|
||||
uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp;
|
||||
uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
|
||||
bool found = false;
|
||||
int i;
|
||||
|
||||
/* save the regs we need */
|
||||
gpio_monid = RREG32(RADEON_GPIO_MONID);
|
||||
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
|
||||
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
|
||||
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A);
|
||||
disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B);
|
||||
disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C);
|
||||
disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D);
|
||||
disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E);
|
||||
disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F);
|
||||
crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP);
|
||||
crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP);
|
||||
crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID);
|
||||
crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID);
|
||||
|
||||
tmp = RREG32(RADEON_GPIO_MONID);
|
||||
tmp &= ~RADEON_GPIO_A_0;
|
||||
WREG32(RADEON_GPIO_MONID, tmp);
|
||||
|
||||
WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON |
|
||||
RADEON_FP2_PANEL_FORMAT |
|
||||
R200_FP2_SOURCE_SEL_TRANS_UNIT |
|
||||
RADEON_FP2_DVO_EN |
|
||||
R200_FP2_DVO_RATE_SEL_SDR));
|
||||
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX |
|
||||
RADEON_DISP_TRANS_MATRIX_GRAPHICS));
|
||||
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN |
|
||||
RADEON_CRTC2_DISP_REQ_EN_B));
|
||||
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
|
||||
|
||||
WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
|
||||
WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
|
||||
WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
|
||||
WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
|
||||
|
||||
for (i = 0; i < 200; i++) {
|
||||
tmp = RREG32(RADEON_GPIO_MONID);
|
||||
if (tmp & RADEON_GPIO_Y_0)
|
||||
found = true;
|
||||
|
||||
if (found)
|
||||
break;
|
||||
|
||||
if (!drm_can_sleep())
|
||||
mdelay(1);
|
||||
else
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
/* restore the regs we used */
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
|
||||
WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
|
||||
WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
|
||||
WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
|
||||
WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
|
||||
WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
|
||||
WREG32(RADEON_GPIO_MONID, gpio_monid);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
|
||||
uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
|
||||
uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
|
||||
uint32_t gpiopad_a = 0, pixclks_cntl, tmp;
|
||||
uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;
|
||||
enum drm_connector_status found = connector_status_disconnected;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
@ -1459,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
/* R200 uses an external DAC for secondary DAC */
|
||||
if (rdev->family == CHIP_R200) {
|
||||
if (radeon_legacy_ext_dac_detect(encoder, connector))
|
||||
found = connector_status_connected;
|
||||
return found;
|
||||
}
|
||||
|
||||
/* save the regs we need */
|
||||
pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
|
||||
gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0;
|
||||
disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0;
|
||||
disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG);
|
||||
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC) {
|
||||
crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
|
||||
} else {
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
gpiopad_a = RREG32(RADEON_GPIOPAD_A);
|
||||
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
|
||||
} else {
|
||||
disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
|
||||
}
|
||||
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
}
|
||||
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
|
||||
dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
|
||||
dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
|
||||
@ -1473,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
|
||||
| RADEON_PIX2CLK_DAC_ALWAYS_ONb);
|
||||
WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
|
||||
|
||||
if (ASIC_IS_R300(rdev))
|
||||
WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
|
||||
|
||||
tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
|
||||
tmp |= RADEON_CRTC2_CRT2_ON |
|
||||
(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
|
||||
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
|
||||
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC) {
|
||||
tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, tmp);
|
||||
} else {
|
||||
tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
|
||||
WREG32(RADEON_DISP_HW_DEBUG, tmp);
|
||||
tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
|
||||
tmp |= RADEON_CRTC2_CRT2_ON |
|
||||
(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
|
||||
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
|
||||
tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
|
||||
} else {
|
||||
tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
|
||||
WREG32(RADEON_DISP_HW_DEBUG, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
tmp = RADEON_TV_DAC_NBLANK |
|
||||
@ -1530,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
|
||||
WREG32(RADEON_DAC_CNTL2, dac_cntl2);
|
||||
WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
|
||||
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
|
||||
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC) {
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
|
||||
} else {
|
||||
WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
|
||||
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
|
||||
} else {
|
||||
WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
|
||||
}
|
||||
}
|
||||
|
||||
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
|
||||
|
||||
return found;
|
||||
|
@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev,
|
||||
|
||||
int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
|
||||
const char *front, char **urb_buf_ptr,
|
||||
u32 byte_offset, u32 byte_width,
|
||||
u32 byte_offset, u32 device_byte_offset, u32 byte_width,
|
||||
int *ident_ptr, int *sent_ptr);
|
||||
|
||||
int udl_dumb_create(struct drm_file *file_priv,
|
||||
|
@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info,
|
||||
list_for_each_entry(cur, &fbdefio->pagelist, lru) {
|
||||
|
||||
if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8),
|
||||
&urb, (char *) info->fix.smem_start,
|
||||
&cmd, cur->index << PAGE_SHIFT,
|
||||
PAGE_SIZE, &bytes_identical, &bytes_sent))
|
||||
&urb, (char *) info->fix.smem_start,
|
||||
&cmd, cur->index << PAGE_SHIFT,
|
||||
cur->index << PAGE_SHIFT,
|
||||
PAGE_SIZE, &bytes_identical, &bytes_sent))
|
||||
goto error;
|
||||
bytes_rendered += PAGE_SIZE;
|
||||
}
|
||||
@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
|
||||
for (i = y; i < y + height ; i++) {
|
||||
const int line_offset = fb->base.pitches[0] * i;
|
||||
const int byte_offset = line_offset + (x * bpp);
|
||||
|
||||
const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
|
||||
if (udl_render_hline(dev, bpp, &urb,
|
||||
(char *) fb->obj->vmapping,
|
||||
&cmd, byte_offset, width * bpp,
|
||||
&cmd, byte_offset, dev_byte_offset,
|
||||
width * bpp,
|
||||
&bytes_identical, &bytes_sent))
|
||||
goto error;
|
||||
}
|
||||
|
@ -213,11 +213,12 @@ static void udl_compress_hline16(
|
||||
*/
|
||||
int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
|
||||
const char *front, char **urb_buf_ptr,
|
||||
u32 byte_offset, u32 byte_width,
|
||||
u32 byte_offset, u32 device_byte_offset,
|
||||
u32 byte_width,
|
||||
int *ident_ptr, int *sent_ptr)
|
||||
{
|
||||
const u8 *line_start, *line_end, *next_pixel;
|
||||
u32 base16 = 0 + (byte_offset / bpp) * 2;
|
||||
u32 base16 = 0 + (device_byte_offset / bpp) * 2;
|
||||
struct urb *urb = *urb_ptr;
|
||||
u8 *cmd = *urb_buf_ptr;
|
||||
u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
|
||||
|
@ -2,7 +2,7 @@
|
||||
* fam15h_power.c - AMD Family 15h processor power monitoring
|
||||
*
|
||||
* Copyright (c) 2011 Advanced Micro Devices, Inc.
|
||||
* Author: Andreas Herrmann <andreas.herrmann3@amd.com>
|
||||
* Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
*
|
||||
*
|
||||
* This driver is free software; you can redistribute it and/or
|
||||
@ -28,7 +28,7 @@
|
||||
#include <asm/processor.h>
|
||||
|
||||
MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor");
|
||||
MODULE_AUTHOR("Andreas Herrmann <andreas.herrmann3@amd.com>");
|
||||
MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* D18F3 */
|
||||
|
@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = {
|
||||
.driver = {
|
||||
.name = "gpio-fan",
|
||||
.pm = GPIO_FAN_PM,
|
||||
#ifdef CONFIG_OF_GPIO
|
||||
.of_match_table = of_match_ptr(of_gpio_fan_match),
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Freescale MXS I2C bus driver
|
||||
*
|
||||
* Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
|
||||
* Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K.
|
||||
*
|
||||
* based on a (non-working) driver which was:
|
||||
*
|
||||
@ -35,10 +35,6 @@
|
||||
|
||||
#define DRIVER_NAME "mxs-i2c"
|
||||
|
||||
static bool use_pioqueue;
|
||||
module_param(use_pioqueue, bool, 0);
|
||||
MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
|
||||
|
||||
#define MXS_I2C_CTRL0 (0x00)
|
||||
#define MXS_I2C_CTRL0_SET (0x04)
|
||||
|
||||
@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
|
||||
MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \
|
||||
MXS_I2C_CTRL1_SLAVE_IRQ)
|
||||
|
||||
#define MXS_I2C_QUEUECTRL (0x60)
|
||||
#define MXS_I2C_QUEUECTRL_SET (0x64)
|
||||
#define MXS_I2C_QUEUECTRL_CLR (0x68)
|
||||
|
||||
#define MXS_I2C_QUEUECTRL_QUEUE_RUN 0x20
|
||||
#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE 0x04
|
||||
|
||||
#define MXS_I2C_QUEUESTAT (0x70)
|
||||
#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY 0x00002000
|
||||
#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F
|
||||
|
||||
#define MXS_I2C_QUEUECMD (0x80)
|
||||
|
||||
#define MXS_I2C_QUEUEDATA (0x90)
|
||||
|
||||
#define MXS_I2C_DATA (0xa0)
|
||||
|
||||
|
||||
#define MXS_CMD_I2C_SELECT (MXS_I2C_CTRL0_RETAIN_CLOCK | \
|
||||
MXS_I2C_CTRL0_PRE_SEND_START | \
|
||||
@ -153,7 +132,6 @@ struct mxs_i2c_dev {
|
||||
const struct mxs_i2c_speed_config *speed;
|
||||
|
||||
/* DMA support components */
|
||||
bool dma_mode;
|
||||
int dma_channel;
|
||||
struct dma_chan *dmach;
|
||||
struct mxs_dma_data dma_data;
|
||||
@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
|
||||
writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
|
||||
|
||||
writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
|
||||
if (i2c->dma_mode)
|
||||
writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
|
||||
i2c->regs + MXS_I2C_QUEUECTRL_CLR);
|
||||
else
|
||||
writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
|
||||
i2c->regs + MXS_I2C_QUEUECTRL_SET);
|
||||
}
|
||||
|
||||
static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len,
|
||||
int flags)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD);
|
||||
|
||||
data = (addr << 1) | I2C_SMBUS_READ;
|
||||
writel(data, i2c->regs + MXS_I2C_DATA);
|
||||
|
||||
data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags;
|
||||
writel(data, i2c->regs + MXS_I2C_QUEUECMD);
|
||||
}
|
||||
|
||||
static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c,
|
||||
u8 addr, u8 *buf, int len, int flags)
|
||||
{
|
||||
u32 data;
|
||||
int i, shifts_left;
|
||||
|
||||
data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags;
|
||||
writel(data, i2c->regs + MXS_I2C_QUEUECMD);
|
||||
|
||||
/*
|
||||
* We have to copy the slave address (u8) and buffer (arbitrary number
|
||||
* of u8) into the data register (u32). To achieve that, the u8 are put
|
||||
* into the MSBs of 'data' which is then shifted for the next u8. When
|
||||
* appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32
|
||||
* looks like this:
|
||||
*
|
||||
* 3 2 1 0
|
||||
* 10987654|32109876|54321098|76543210
|
||||
* --------+--------+--------+--------
|
||||
* buffer+2|buffer+1|buffer+0|slave_addr
|
||||
*/
|
||||
|
||||
data = ((addr << 1) | I2C_SMBUS_WRITE) << 24;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
data >>= 8;
|
||||
data |= buf[i] << 24;
|
||||
if ((i & 3) == 2)
|
||||
writel(data, i2c->regs + MXS_I2C_DATA);
|
||||
}
|
||||
|
||||
/* Write out the remaining bytes if any */
|
||||
shifts_left = 24 - (i & 3) * 8;
|
||||
if (shifts_left)
|
||||
writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the
|
||||
* rd_threshold to 1). Couldn't get this to work, though.
|
||||
*/
|
||||
static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
|
||||
|
||||
while (readl(i2c->regs + MXS_I2C_QUEUESTAT)
|
||||
& MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) {
|
||||
if (time_after(jiffies, timeout))
|
||||
return -ETIMEDOUT;
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
|
||||
{
|
||||
u32 uninitialized_var(data);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((i & 3) == 0) {
|
||||
if (mxs_i2c_wait_for_data(i2c))
|
||||
return -ETIMEDOUT;
|
||||
data = readl(i2c->regs + MXS_I2C_QUEUEDATA);
|
||||
}
|
||||
buf[i] = data & 0xff;
|
||||
data >>= 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
|
||||
@ -432,39 +317,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
|
||||
init_completion(&i2c->cmd_complete);
|
||||
i2c->cmd_err = 0;
|
||||
|
||||
if (i2c->dma_mode) {
|
||||
ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
if (msg->flags & I2C_M_RD) {
|
||||
mxs_i2c_pioq_setup_read(i2c, msg->addr,
|
||||
msg->len, flags);
|
||||
} else {
|
||||
mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf,
|
||||
msg->len, flags);
|
||||
}
|
||||
|
||||
writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
|
||||
i2c->regs + MXS_I2C_QUEUECTRL_SET);
|
||||
}
|
||||
ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = wait_for_completion_timeout(&i2c->cmd_complete,
|
||||
msecs_to_jiffies(1000));
|
||||
if (ret == 0)
|
||||
goto timeout;
|
||||
|
||||
if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) {
|
||||
ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
|
||||
if (ret)
|
||||
goto timeout;
|
||||
}
|
||||
|
||||
if (i2c->cmd_err == -ENXIO)
|
||||
mxs_i2c_reset(i2c);
|
||||
else
|
||||
writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
|
||||
i2c->regs + MXS_I2C_QUEUECTRL_CLR);
|
||||
|
||||
dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err);
|
||||
|
||||
@ -472,8 +335,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
|
||||
|
||||
timeout:
|
||||
dev_dbg(i2c->dev, "Timeout!\n");
|
||||
if (i2c->dma_mode)
|
||||
mxs_i2c_dma_finish(i2c);
|
||||
mxs_i2c_dma_finish(i2c);
|
||||
mxs_i2c_reset(i2c);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
@ -502,7 +364,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
|
||||
{
|
||||
struct mxs_i2c_dev *i2c = dev_id;
|
||||
u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK;
|
||||
bool is_last_cmd;
|
||||
|
||||
if (!stat)
|
||||
return IRQ_NONE;
|
||||
@ -515,14 +376,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
|
||||
/* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
|
||||
i2c->cmd_err = -EIO;
|
||||
|
||||
if (!i2c->dma_mode) {
|
||||
is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
|
||||
MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
|
||||
|
||||
if (is_last_cmd || i2c->cmd_err)
|
||||
complete(&i2c->cmd_complete);
|
||||
}
|
||||
|
||||
writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@ -555,15 +408,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
|
||||
struct device_node *node = dev->of_node;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The MXS I2C DMA mode is prefered and enabled by default.
|
||||
* The PIO mode is still supported, but should be used only
|
||||
* for debuging purposes etc.
|
||||
*/
|
||||
i2c->dma_mode = !use_pioqueue;
|
||||
if (!i2c->dma_mode)
|
||||
dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n");
|
||||
|
||||
/*
|
||||
* TODO: This is a temporary solution and should be changed
|
||||
* to use generic DMA binding later when the helpers get in.
|
||||
@ -571,8 +415,8 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
|
||||
ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
|
||||
&i2c->dma_channel);
|
||||
if (ret) {
|
||||
dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n");
|
||||
i2c->dma_mode = 0;
|
||||
dev_err(dev, "Failed to get DMA channel!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "clock-frequency", &speed);
|
||||
@ -634,15 +478,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Setup the DMA */
|
||||
if (i2c->dma_mode) {
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
i2c->dma_data.chan_irq = dmairq;
|
||||
i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
|
||||
if (!i2c->dmach) {
|
||||
dev_err(dev, "Failed to request dma\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
i2c->dma_data.chan_irq = dmairq;
|
||||
i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
|
||||
if (!i2c->dmach) {
|
||||
dev_err(dev, "Failed to request dma\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, i2c);
|
||||
|
@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
|
||||
pm_runtime_get_sync(&dev->adev->dev);
|
||||
|
||||
clk_enable(dev->clk);
|
||||
status = clk_prepare_enable(dev->clk);
|
||||
if (status) {
|
||||
dev_err(&dev->adev->dev, "can't prepare_enable clock\n");
|
||||
goto out_clk;
|
||||
}
|
||||
|
||||
status = init_hw(dev);
|
||||
if (status)
|
||||
@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
|
||||
}
|
||||
|
||||
out:
|
||||
clk_disable(dev->clk);
|
||||
clk_disable_unprepare(dev->clk);
|
||||
out_clk:
|
||||
pm_runtime_put_sync(&dev->adev->dev);
|
||||
|
||||
dev->busy = false;
|
||||
|
@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
|
||||
tegra_i2c_isr, 0, pdev->name, i2c_dev);
|
||||
tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
|
||||
return ret;
|
||||
|
@ -335,6 +335,7 @@ config KEYBOARD_LOCOMO
|
||||
config KEYBOARD_LPC32XX
|
||||
tristate "LPC32XX matrix key scanner support"
|
||||
depends on ARCH_LPC32XX && OF
|
||||
select INPUT_MATRIXKMAP
|
||||
help
|
||||
Say Y here if you want to use NXP LPC32XX SoC key scanner interface,
|
||||
connected to a key matrix.
|
||||
|
@ -368,6 +368,9 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
|
||||
unsigned int mask = 0, direct_key_num = 0;
|
||||
unsigned long kpc = 0;
|
||||
|
||||
/* clear pending interrupt bit */
|
||||
keypad_readl(KPC);
|
||||
|
||||
/* enable matrix keys with automatic scan */
|
||||
if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
|
||||
kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
|
||||
|
@ -311,7 +311,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
|
||||
case XenbusStateReconfiguring:
|
||||
case XenbusStateReconfigured:
|
||||
case XenbusStateUnknown:
|
||||
case XenbusStateClosed:
|
||||
break;
|
||||
|
||||
case XenbusStateInitWait:
|
||||
@ -350,6 +349,10 @@ InitWait:
|
||||
|
||||
break;
|
||||
|
||||
case XenbusStateClosed:
|
||||
if (dev->state == XenbusStateClosed)
|
||||
break;
|
||||
/* Missed the backend's CLOSING state -- fallthrough */
|
||||
case XenbusStateClosing:
|
||||
xenbus_frontend_closed(dev);
|
||||
break;
|
||||
|
@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
|
||||
features->pktlen = WACOM_PKGLEN_TPC2FG;
|
||||
}
|
||||
|
||||
if (features->type == MTSCREEN || WACOM_24HDT)
|
||||
if (features->type == MTSCREEN || features->type == WACOM_24HDT)
|
||||
features->pktlen = WACOM_PKGLEN_MTOUCH;
|
||||
|
||||
if (features->type == BAMBOO_PT) {
|
||||
|
@ -1518,6 +1518,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
|
||||
|
||||
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
|
||||
|
||||
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
|
||||
|
||||
wacom_setup_cintiq(wacom_wac);
|
||||
break;
|
||||
|
||||
|
@ -239,7 +239,7 @@ config TOUCHSCREEN_EETI
|
||||
|
||||
config TOUCHSCREEN_EGALAX
|
||||
tristate "EETI eGalax multi-touch panel support"
|
||||
depends on I2C
|
||||
depends on I2C && OF
|
||||
help
|
||||
Say Y here to enable support for I2C connected EETI
|
||||
eGalax multi-touch panels.
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
/*
|
||||
* Mouse Mode: some panel may configure the controller to mouse mode,
|
||||
@ -122,9 +123,17 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
|
||||
/* wake up controller by an falling edge of interrupt gpio. */
|
||||
static int egalax_wake_up_device(struct i2c_client *client)
|
||||
{
|
||||
int gpio = irq_to_gpio(client->irq);
|
||||
struct device_node *np = client->dev.of_node;
|
||||
int gpio;
|
||||
int ret;
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
gpio = of_get_named_gpio(np, "wakeup-gpios", 0);
|
||||
if (!gpio_is_valid(gpio))
|
||||
return -ENODEV;
|
||||
|
||||
ret = gpio_request(gpio, "egalax_irq");
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev,
|
||||
@ -181,7 +190,11 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,
|
||||
ts->input_dev = input_dev;
|
||||
|
||||
/* controller may be in sleep, wake it up. */
|
||||
egalax_wake_up_device(client);
|
||||
error = egalax_wake_up_device(client);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "Failed to wake up the controller\n");
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
ret = egalax_firmware_version(client);
|
||||
if (ret < 0) {
|
||||
@ -274,11 +287,17 @@ static int egalax_ts_resume(struct device *dev)
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume);
|
||||
|
||||
static struct of_device_id egalax_ts_dt_ids[] = {
|
||||
{ .compatible = "eeti,egalax_ts" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct i2c_driver egalax_ts_driver = {
|
||||
.driver = {
|
||||
.name = "egalax_ts",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &egalax_ts_pm_ops,
|
||||
.of_match_table = of_match_ptr(egalax_ts_dt_ids),
|
||||
},
|
||||
.id_table = egalax_ts_id,
|
||||
.probe = egalax_ts_probe,
|
||||
|
@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)
|
||||
__set_bit(BTN_TOUCH, input_dev->keybit);
|
||||
input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);
|
||||
input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0);
|
||||
input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0);
|
||||
|
||||
serio_set_drvdata(serio, ptsc);
|
||||
|
||||
|
@ -1060,7 +1060,7 @@ static ssize_t bonding_store_primary(struct device *d,
|
||||
goto out;
|
||||
}
|
||||
|
||||
sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
|
||||
sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
|
||||
|
||||
/* check to see if we are clearing primary */
|
||||
if (!strlen(ifname) || buf[0] == '\n') {
|
||||
@ -1237,7 +1237,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
|
||||
goto out;
|
||||
}
|
||||
|
||||
sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
|
||||
sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
|
||||
|
||||
/* check to see if we are clearing active */
|
||||
if (!strlen(ifname) || buf[0] == '\n') {
|
||||
|
@ -137,7 +137,16 @@
|
||||
#define LINK_20GTFD LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
|
||||
#define LINK_20GXFD LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
|
||||
|
||||
|
||||
#define LINK_UPDATE_MASK \
|
||||
(LINK_STATUS_SPEED_AND_DUPLEX_MASK | \
|
||||
LINK_STATUS_LINK_UP | \
|
||||
LINK_STATUS_PHYSICAL_LINK_FLAG | \
|
||||
LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \
|
||||
LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \
|
||||
LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \
|
||||
LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \
|
||||
LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \
|
||||
LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)
|
||||
|
||||
#define SFP_EEPROM_CON_TYPE_ADDR 0x2
|
||||
#define SFP_EEPROM_CON_TYPE_VAL_LC 0x7
|
||||
@ -3295,6 +3304,21 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
|
||||
DEFAULT_PHY_DEV_ADDR);
|
||||
}
|
||||
|
||||
static void bnx2x_xgxs_specific_func(struct bnx2x_phy *phy,
|
||||
struct link_params *params,
|
||||
u32 action)
|
||||
{
|
||||
struct bnx2x *bp = params->bp;
|
||||
switch (action) {
|
||||
case PHY_INIT:
|
||||
/* Set correct devad */
|
||||
REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0);
|
||||
REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
|
||||
phy->def_md_devad);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void bnx2x_xgxs_deassert(struct link_params *params)
|
||||
{
|
||||
struct bnx2x *bp = params->bp;
|
||||
@ -3309,10 +3333,8 @@ static void bnx2x_xgxs_deassert(struct link_params *params)
|
||||
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
|
||||
udelay(500);
|
||||
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
|
||||
|
||||
REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0);
|
||||
REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
|
||||
params->phy[INT_PHY].def_md_devad);
|
||||
bnx2x_xgxs_specific_func(¶ms->phy[INT_PHY], params,
|
||||
PHY_INIT);
|
||||
}
|
||||
|
||||
static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
|
||||
@ -3545,14 +3567,11 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
|
||||
static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
|
||||
struct link_params *params,
|
||||
struct link_vars *vars) {
|
||||
u16 val16 = 0, lane, i;
|
||||
u16 lane, i, cl72_ctrl, an_adv = 0;
|
||||
u16 ucode_ver;
|
||||
struct bnx2x *bp = params->bp;
|
||||
static struct bnx2x_reg_set reg_set[] = {
|
||||
{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
|
||||
{MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
|
||||
{MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0},
|
||||
{MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff},
|
||||
{MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555},
|
||||
{MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0},
|
||||
{MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},
|
||||
{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190},
|
||||
@ -3565,12 +3584,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
|
||||
bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
|
||||
reg_set[i].val);
|
||||
|
||||
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
|
||||
MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
|
||||
cl72_ctrl &= 0xf8ff;
|
||||
cl72_ctrl |= 0x3800;
|
||||
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
|
||||
MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
|
||||
|
||||
/* Check adding advertisement for 1G KX */
|
||||
if (((vars->line_speed == SPEED_AUTO_NEG) &&
|
||||
(phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
|
||||
(vars->line_speed == SPEED_1000)) {
|
||||
u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2;
|
||||
val16 |= (1<<5);
|
||||
an_adv |= (1<<5);
|
||||
|
||||
/* Enable CL37 1G Parallel Detect */
|
||||
bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1);
|
||||
@ -3580,11 +3606,14 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
|
||||
(phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
|
||||
(vars->line_speed == SPEED_10000)) {
|
||||
/* Check adding advertisement for 10G KR */
|
||||
val16 |= (1<<7);
|
||||
an_adv |= (1<<7);
|
||||
/* Enable 10G Parallel Detect */
|
||||
CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
|
||||
MDIO_AER_BLOCK_AER_REG, 0);
|
||||
|
||||
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
|
||||
MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
|
||||
|
||||
bnx2x_set_aer_mmd(params, phy);
|
||||
DP(NETIF_MSG_LINK, "Advertize 10G\n");
|
||||
}
|
||||
|
||||
@ -3604,7 +3633,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
|
||||
|
||||
/* Advertised speeds */
|
||||
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
|
||||
MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
|
||||
MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv);
|
||||
|
||||
/* Advertised and set FEC (Forward Error Correction) */
|
||||
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
|
||||
@ -3628,9 +3657,10 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
|
||||
/* Set KR Autoneg Work-Around flag for Warpcore version older than D108
|
||||
*/
|
||||
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
|
||||
MDIO_WC_REG_UC_INFO_B1_VERSION, &val16);
|
||||
if (val16 < 0xd108) {
|
||||
DP(NETIF_MSG_LINK, "Enable AN KR work-around\n");
|
||||
MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver);
|
||||
if (ucode_ver < 0xd108) {
|
||||
DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n",
|
||||
ucode_ver);
|
||||
vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
|
||||
}
|
||||
bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
|
||||
@ -3651,21 +3681,16 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
|
||||
struct link_vars *vars)
|
||||
{
|
||||
struct bnx2x *bp = params->bp;
|
||||
u16 i;
|
||||
u16 val16, i, lane;
|
||||
static struct bnx2x_reg_set reg_set[] = {
|
||||
/* Disable Autoneg */
|
||||
{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
|
||||
{MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
|
||||
{MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
|
||||
0x3f00},
|
||||
{MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0},
|
||||
{MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0},
|
||||
{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},
|
||||
{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa},
|
||||
/* Disable CL36 PCS Tx */
|
||||
{MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0},
|
||||
/* Double Wide Single Data Rate @ pll rate */
|
||||
{MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF},
|
||||
/* Leave cl72 training enable, needed for KR */
|
||||
{MDIO_PMA_DEVAD,
|
||||
MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
|
||||
@ -3676,11 +3701,24 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
|
||||
bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
|
||||
reg_set[i].val);
|
||||
|
||||
/* Leave CL72 enabled */
|
||||
bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
|
||||
MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
|
||||
0x3800);
|
||||
lane = bnx2x_get_warpcore_lane(phy, params);
|
||||
/* Global registers */
|
||||
CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
|
||||
MDIO_AER_BLOCK_AER_REG, 0);
|
||||
/* Disable CL36 PCS Tx */
|
||||
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
|
||||
MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
|
||||
val16 &= ~(0x0011 << lane);
|
||||
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
|
||||
MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
|
||||
|
||||
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
|
||||
MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
|
||||
val16 |= (0x0303 << (lane << 1));
|
||||
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
|
||||
MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
|
||||
/* Restore AER */
|
||||
bnx2x_set_aer_mmd(params, phy);
|
||||
/* Set speed via PMA/PMD register */
|
||||
bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
|
||||
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
|
||||
@ -4303,7 +4341,7 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
|
||||
struct link_params *params)
|
||||
{
|
||||
struct bnx2x *bp = params->bp;
|
||||
u16 val16;
|
||||
u16 val16, lane;
|
||||
bnx2x_sfp_e3_set_transmitter(params, phy, 0);
|
||||
bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
|
||||
bnx2x_set_aer_mmd(params, phy);
|
||||
@ -4340,6 +4378,30 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
|
||||
MDIO_WC_REG_XGXSBLK1_LANECTRL2,
|
||||
val16 & 0xff00);
|
||||
|
||||
lane = bnx2x_get_warpcore_lane(phy, params);
|
||||
/* Disable CL36 PCS Tx */
|
||||
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
|
||||
MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
|
||||
val16 |= (0x11 << lane);
|
||||
if (phy->flags & FLAGS_WC_DUAL_MODE)
|
||||
val16 |= (0x22 << lane);
|
||||
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
|
||||
MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
|
||||
|
||||
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
|
||||
MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
|
||||
val16 &= ~(0x0303 << (lane << 1));
|
||||
val16 |= (0x0101 << (lane << 1));
|
||||
if (phy->flags & FLAGS_WC_DUAL_MODE) {
|
||||
val16 &= ~(0x0c0c << (lane << 1));
|
||||
val16 |= (0x0404 << (lane << 1));
|
||||
}
|
||||
|
||||
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
|
||||
MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
|
||||
/* Restore AER */
|
||||
bnx2x_set_aer_mmd(params, phy);
|
||||
|
||||
}
|
||||
|
||||
static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
|
||||
@ -6296,15 +6358,7 @@ static int bnx2x_update_link_down(struct link_params *params,
|
||||
vars->mac_type = MAC_TYPE_NONE;
|
||||
|
||||
/* Update shared memory */
|
||||
vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
|
||||
LINK_STATUS_LINK_UP |
|
||||
LINK_STATUS_PHYSICAL_LINK_FLAG |
|
||||
LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
|
||||
LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
|
||||
LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
|
||||
LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK |
|
||||
LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE |
|
||||
LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE);
|
||||
vars->link_status &= ~LINK_UPDATE_MASK;
|
||||
vars->line_speed = 0;
|
||||
bnx2x_update_mng(params, vars->link_status);
|
||||
|
||||
@ -6452,6 +6506,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
|
||||
u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
|
||||
u8 active_external_phy = INT_PHY;
|
||||
vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
|
||||
vars->link_status &= ~LINK_UPDATE_MASK;
|
||||
for (phy_index = INT_PHY; phy_index < params->num_phys;
|
||||
phy_index++) {
|
||||
phy_vars[phy_index].flow_ctrl = 0;
|
||||
@ -7579,7 +7634,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params,
|
||||
static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
|
||||
struct link_params *params,
|
||||
u16 addr, u8 byte_cnt,
|
||||
u8 *o_buf)
|
||||
u8 *o_buf, u8 is_init)
|
||||
{
|
||||
int rc = 0;
|
||||
u8 i, j = 0, cnt = 0;
|
||||
@ -7596,10 +7651,10 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
|
||||
/* 4 byte aligned address */
|
||||
addr32 = addr & (~0x3);
|
||||
do {
|
||||
if (cnt == I2C_WA_PWR_ITER) {
|
||||
if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {
|
||||
bnx2x_warpcore_power_module(params, phy, 0);
|
||||
/* Note that 100us are not enough here */
|
||||
usleep_range(1000,1000);
|
||||
usleep_range(1000, 2000);
|
||||
bnx2x_warpcore_power_module(params, phy, 1);
|
||||
}
|
||||
rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
|
||||
@ -7719,7 +7774,7 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
|
||||
break;
|
||||
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
|
||||
rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
|
||||
byte_cnt, o_buf);
|
||||
byte_cnt, o_buf, 0);
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
@ -7923,6 +7978,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
|
||||
|
||||
{
|
||||
u8 val;
|
||||
int rc;
|
||||
struct bnx2x *bp = params->bp;
|
||||
u16 timeout;
|
||||
/* Initialization time after hot-plug may take up to 300ms for
|
||||
@ -7930,8 +7986,14 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
|
||||
*/
|
||||
|
||||
for (timeout = 0; timeout < 60; timeout++) {
|
||||
if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
|
||||
== 0) {
|
||||
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
|
||||
rc = bnx2x_warpcore_read_sfp_module_eeprom(phy,
|
||||
params, 1,
|
||||
1, &val, 1);
|
||||
else
|
||||
rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1,
|
||||
&val);
|
||||
if (rc == 0) {
|
||||
DP(NETIF_MSG_LINK,
|
||||
"SFP+ module initialization took %d ms\n",
|
||||
timeout * 5);
|
||||
@ -7939,7 +8001,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
|
||||
}
|
||||
usleep_range(5000, 10000);
|
||||
}
|
||||
return -EINVAL;
|
||||
rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void bnx2x_8727_power_module(struct bnx2x *bp,
|
||||
@ -10993,7 +11056,7 @@ static struct bnx2x_phy phy_xgxs = {
|
||||
.format_fw_ver = (format_fw_ver_t)NULL,
|
||||
.hw_reset = (hw_reset_t)NULL,
|
||||
.set_link_led = (set_link_led_t)NULL,
|
||||
.phy_specific_func = (phy_specific_func_t)NULL
|
||||
.phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func
|
||||
};
|
||||
static struct bnx2x_phy phy_warpcore = {
|
||||
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
|
||||
@ -11465,6 +11528,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
|
||||
phy->media_type = ETH_PHY_BASE_T;
|
||||
break;
|
||||
case PORT_HW_CFG_NET_SERDES_IF_XFI:
|
||||
phy->supported &= (SUPPORTED_1000baseT_Full |
|
||||
SUPPORTED_10000baseT_Full |
|
||||
SUPPORTED_FIBRE |
|
||||
SUPPORTED_Pause |
|
||||
SUPPORTED_Asym_Pause);
|
||||
phy->media_type = ETH_PHY_XFP_FIBER;
|
||||
break;
|
||||
case PORT_HW_CFG_NET_SERDES_IF_SFI:
|
||||
|
@ -6794,8 +6794,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
|
||||
|
||||
bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
|
||||
|
||||
bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
|
||||
|
||||
if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
|
||||
bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
|
||||
|
||||
if (IS_MF(bp))
|
||||
low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
|
||||
@ -11902,7 +11903,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
|
||||
/* disable FCOE L2 queue for E1x */
|
||||
if (CHIP_IS_E1x(bp))
|
||||
bp->flags |= NO_FCOE_FLAG;
|
||||
|
||||
/* disable FCOE for 57840 device, until FW supports it */
|
||||
switch (ent->driver_data) {
|
||||
case BCM57840_O:
|
||||
case BCM57840_4_10:
|
||||
case BCM57840_2_20:
|
||||
case BCM57840_MFO:
|
||||
case BCM57840_MF:
|
||||
bp->flags |= NO_FCOE_FLAG;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -3415,16 +3415,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
|
||||
"mismatch: [fini] csum=%#x, computed csum=%#x\n",
|
||||
finicsum, cfcsum);
|
||||
|
||||
/*
|
||||
* If we're a pure NIC driver then disable all offloading facilities.
|
||||
* This will allow the firmware to optimize aspects of the hardware
|
||||
* configuration which will result in improved performance.
|
||||
*/
|
||||
caps_cmd.ofldcaps = 0;
|
||||
caps_cmd.iscsicaps = 0;
|
||||
caps_cmd.rdmacaps = 0;
|
||||
caps_cmd.fcoecaps = 0;
|
||||
|
||||
/*
|
||||
* And now tell the firmware to use the configuration we just loaded.
|
||||
*/
|
||||
|
@ -2673,6 +2673,9 @@ static int ixgbe_get_ts_info(struct net_device *dev,
|
||||
case ixgbe_mac_X540:
|
||||
case ixgbe_mac_82599EB:
|
||||
info->so_timestamping =
|
||||
SOF_TIMESTAMPING_TX_SOFTWARE |
|
||||
SOF_TIMESTAMPING_RX_SOFTWARE |
|
||||
SOF_TIMESTAMPING_SOFTWARE |
|
||||
SOF_TIMESTAMPING_TX_HARDWARE |
|
||||
SOF_TIMESTAMPING_RX_HARDWARE |
|
||||
SOF_TIMESTAMPING_RAW_HARDWARE;
|
||||
|
@ -1524,6 +1524,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
|
||||
pldat->dma_buff_base_p);
|
||||
free_irq(ndev->irq, ndev);
|
||||
iounmap(pldat->net_base);
|
||||
mdiobus_unregister(pldat->mii_bus);
|
||||
mdiobus_free(pldat->mii_bus);
|
||||
clk_disable(pldat->clk);
|
||||
clk_put(pldat->clk);
|
||||
|
@ -234,6 +234,7 @@ void free_mdio_bitbang(struct mii_bus *bus)
|
||||
struct mdiobb_ctrl *ctrl = bus->priv;
|
||||
|
||||
module_put(ctrl->ops->owner);
|
||||
mdiobus_unregister(bus);
|
||||
mdiobus_free(bus);
|
||||
}
|
||||
EXPORT_SYMBOL(free_mdio_bitbang);
|
||||
|
@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
|
||||
|
||||
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
||||
const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
|
||||
u32 buf_size;
|
||||
|
||||
tbi = tq->buf_info + tq->tx_ring.next2fill;
|
||||
tbi->map_type = VMXNET3_MAP_PAGE;
|
||||
tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
|
||||
0, skb_frag_size(frag),
|
||||
DMA_TO_DEVICE);
|
||||
buf_offset = 0;
|
||||
len = skb_frag_size(frag);
|
||||
while (len) {
|
||||
tbi = tq->buf_info + tq->tx_ring.next2fill;
|
||||
if (len < VMXNET3_MAX_TX_BUF_SIZE) {
|
||||
buf_size = len;
|
||||
dw2 |= len;
|
||||
} else {
|
||||
buf_size = VMXNET3_MAX_TX_BUF_SIZE;
|
||||
/* spec says that for TxDesc.len, 0 == 2^14 */
|
||||
}
|
||||
tbi->map_type = VMXNET3_MAP_PAGE;
|
||||
tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
|
||||
buf_offset, buf_size,
|
||||
DMA_TO_DEVICE);
|
||||
|
||||
tbi->len = skb_frag_size(frag);
|
||||
tbi->len = buf_size;
|
||||
|
||||
gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
|
||||
BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
|
||||
gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
|
||||
BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
|
||||
|
||||
gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
|
||||
gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag));
|
||||
gdesc->dword[3] = 0;
|
||||
gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
|
||||
gdesc->dword[2] = cpu_to_le32(dw2);
|
||||
gdesc->dword[3] = 0;
|
||||
|
||||
dev_dbg(&adapter->netdev->dev,
|
||||
"txd[%u]: 0x%llu %u %u\n",
|
||||
tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
|
||||
le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
|
||||
vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
|
||||
dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
|
||||
dev_dbg(&adapter->netdev->dev,
|
||||
"txd[%u]: 0x%llu %u %u\n",
|
||||
tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
|
||||
le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
|
||||
vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
|
||||
dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
|
||||
|
||||
len -= buf_size;
|
||||
buf_offset += buf_size;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->eop_txd = gdesc;
|
||||
@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
static int txd_estimate(const struct sk_buff *skb)
|
||||
{
|
||||
int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
|
||||
const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
|
||||
|
||||
count += VMXNET3_TXD_NEEDED(skb_frag_size(frag));
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transmits a pkt thru a given tq
|
||||
@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
|
||||
union Vmxnet3_GenericDesc tempTxDesc;
|
||||
#endif
|
||||
|
||||
/* conservatively estimate # of descriptors to use */
|
||||
count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
|
||||
skb_shinfo(skb)->nr_frags + 1;
|
||||
count = txd_estimate(skb);
|
||||
|
||||
ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
|
||||
|
||||
|
@ -816,7 +816,7 @@ static void vxlan_cleanup(unsigned long arg)
|
||||
= container_of(p, struct vxlan_fdb, hlist);
|
||||
unsigned long timeout;
|
||||
|
||||
if (f->state == NUD_PERMANENT)
|
||||
if (f->state & NUD_PERMANENT)
|
||||
continue;
|
||||
|
||||
timeout = f->used + vxlan->age_interval * HZ;
|
||||
|
@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
|
||||
}
|
||||
|
||||
bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
|
||||
bf->bf_next = NULL;
|
||||
list_del(&bf->list);
|
||||
|
||||
spin_unlock_bh(&sc->tx.txbuflock);
|
||||
@ -393,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;
|
||||
u32 ba[WME_BA_BMP_SIZE >> 5];
|
||||
int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
|
||||
bool rc_update = true;
|
||||
bool rc_update = true, isba;
|
||||
struct ieee80211_tx_rate rates[4];
|
||||
struct ath_frame_info *fi;
|
||||
int nframes;
|
||||
@ -437,13 +438,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
|
||||
tid = ATH_AN_2_TID(an, tidno);
|
||||
seq_first = tid->seq_start;
|
||||
isba = ts->ts_flags & ATH9K_TX_BA;
|
||||
|
||||
/*
|
||||
* The hardware occasionally sends a tx status for the wrong TID.
|
||||
* In this case, the BA status cannot be considered valid and all
|
||||
* subframes need to be retransmitted
|
||||
*
|
||||
* Only BlockAcks have a TID and therefore normal Acks cannot be
|
||||
* checked
|
||||
*/
|
||||
if (tidno != ts->tid)
|
||||
if (isba && tidno != ts->tid)
|
||||
txok = false;
|
||||
|
||||
isaggr = bf_isaggr(bf);
|
||||
@ -1774,6 +1779,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
|
||||
list_add_tail(&bf->list, &bf_head);
|
||||
bf->bf_state.bf_type = 0;
|
||||
|
||||
bf->bf_next = NULL;
|
||||
bf->bf_lastbf = bf;
|
||||
ath_tx_fill_desc(sc, bf, txq, fi->framelen);
|
||||
ath_tx_txqaddbuf(sc, txq, &bf_head, false);
|
||||
|
@ -2449,7 +2449,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* Check if temperature compensation is supported.
|
||||
*/
|
||||
if (tssi_bounds[4] == 0xff)
|
||||
if (tssi_bounds[4] == 0xff || step == 0xff)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
@ -3719,7 +3719,9 @@ restart:
|
||||
*/
|
||||
iscsit_thread_check_cpumask(conn, current, 1);
|
||||
|
||||
schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
|
||||
wait_event_interruptible(conn->queues_wq,
|
||||
!iscsit_conn_all_queues_empty(conn) ||
|
||||
ts->status == ISCSI_THREAD_SET_RESET);
|
||||
|
||||
if ((ts->status == ISCSI_THREAD_SET_RESET) ||
|
||||
signal_pending(current))
|
||||
|
@ -486,6 +486,7 @@ struct iscsi_tmr_req {
|
||||
};
|
||||
|
||||
struct iscsi_conn {
|
||||
wait_queue_head_t queues_wq;
|
||||
/* Authentication Successful for this connection */
|
||||
u8 auth_complete;
|
||||
/* State connection is currently in */
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
static int iscsi_login_init_conn(struct iscsi_conn *conn)
|
||||
{
|
||||
init_waitqueue_head(&conn->queues_wq);
|
||||
INIT_LIST_HEAD(&conn->conn_list);
|
||||
INIT_LIST_HEAD(&conn->conn_cmd_list);
|
||||
INIT_LIST_HEAD(&conn->immed_queue_list);
|
||||
|
@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue(
|
||||
atomic_set(&conn->check_immediate_queue, 1);
|
||||
spin_unlock_bh(&conn->immed_queue_lock);
|
||||
|
||||
wake_up_process(conn->thread_set->tx_thread);
|
||||
wake_up(&conn->queues_wq);
|
||||
}
|
||||
|
||||
struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn)
|
||||
@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue(
|
||||
atomic_inc(&cmd->response_queue_count);
|
||||
spin_unlock_bh(&conn->response_queue_lock);
|
||||
|
||||
wake_up_process(conn->thread_set->tx_thread);
|
||||
wake_up(&conn->queues_wq);
|
||||
}
|
||||
|
||||
struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn)
|
||||
@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue(
|
||||
}
|
||||
}
|
||||
|
||||
bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn)
|
||||
{
|
||||
bool empty;
|
||||
|
||||
spin_lock_bh(&conn->immed_queue_lock);
|
||||
empty = list_empty(&conn->immed_queue_list);
|
||||
spin_unlock_bh(&conn->immed_queue_lock);
|
||||
|
||||
if (!empty)
|
||||
return empty;
|
||||
|
||||
spin_lock_bh(&conn->response_queue_lock);
|
||||
empty = list_empty(&conn->response_queue_list);
|
||||
spin_unlock_bh(&conn->response_queue_lock);
|
||||
|
||||
return empty;
|
||||
}
|
||||
|
||||
void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
|
||||
{
|
||||
struct iscsi_queue_req *qr, *qr_tmp;
|
||||
|
@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_
|
||||
extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);
|
||||
extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *);
|
||||
extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *);
|
||||
extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *);
|
||||
extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);
|
||||
extern void iscsit_release_cmd(struct iscsi_cmd *);
|
||||
extern void iscsit_free_cmd(struct iscsi_cmd *);
|
||||
|
@ -3206,7 +3206,8 @@ static int __init target_core_init_configfs(void)
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (core_dev_setup_virtual_lun0() < 0)
|
||||
ret = core_dev_setup_virtual_lun0();
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
|
@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev)
|
||||
|
||||
static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
|
||||
{
|
||||
u32 tmp, aligned_max_sectors;
|
||||
u32 aligned_max_sectors;
|
||||
u32 alignment;
|
||||
/*
|
||||
* Limit max_sectors to a PAGE_SIZE aligned value for modern
|
||||
* transport_allocate_data_tasks() operation.
|
||||
*/
|
||||
tmp = rounddown((max_sectors * block_size), PAGE_SIZE);
|
||||
aligned_max_sectors = (tmp / block_size);
|
||||
if (max_sectors != aligned_max_sectors) {
|
||||
printk(KERN_INFO "Rounding down aligned max_sectors from %u"
|
||||
" to %u\n", max_sectors, aligned_max_sectors);
|
||||
return aligned_max_sectors;
|
||||
}
|
||||
alignment = max(1ul, PAGE_SIZE / block_size);
|
||||
aligned_max_sectors = rounddown(max_sectors, alignment);
|
||||
|
||||
return max_sectors;
|
||||
if (max_sectors != aligned_max_sectors)
|
||||
pr_info("Rounding down aligned max_sectors from %u to %u\n",
|
||||
max_sectors, aligned_max_sectors);
|
||||
|
||||
return aligned_max_sectors;
|
||||
}
|
||||
|
||||
void se_dev_set_default_attribs(
|
||||
|
@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
|
||||
unsigned char buf[SE_INQUIRY_BUF];
|
||||
int p, ret;
|
||||
|
||||
memset(buf, 0, SE_INQUIRY_BUF);
|
||||
|
||||
if (dev == tpg->tpg_virt_lun0.lun_se_dev)
|
||||
buf[0] = 0x3f; /* Not connected */
|
||||
else
|
||||
|
@ -140,15 +140,15 @@ void core_tmr_abort_task(
|
||||
printk("ABORT_TASK: Found referenced %s task_tag: %u\n",
|
||||
se_cmd->se_tfo->get_fabric_name(), ref_tag);
|
||||
|
||||
spin_lock_irq(&se_cmd->t_state_lock);
|
||||
spin_lock(&se_cmd->t_state_lock);
|
||||
if (se_cmd->transport_state & CMD_T_COMPLETE) {
|
||||
printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag);
|
||||
spin_unlock_irq(&se_cmd->t_state_lock);
|
||||
spin_unlock(&se_cmd->t_state_lock);
|
||||
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
||||
goto out;
|
||||
}
|
||||
se_cmd->transport_state |= CMD_T_ABORTED;
|
||||
spin_unlock_irq(&se_cmd->t_state_lock);
|
||||
spin_unlock(&se_cmd->t_state_lock);
|
||||
|
||||
list_del_init(&se_cmd->se_cmd_list);
|
||||
kref_get(&se_cmd->cmd_kref);
|
||||
|
@ -815,7 +815,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = {
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, exynos4_tmu_driver_ids);
|
||||
MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
|
||||
|
||||
static inline struct exynos_tmu_platform_data *exynos_get_driver_data(
|
||||
struct platform_device *pdev)
|
||||
|
@ -210,7 +210,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
|
||||
goto error_free_priv;
|
||||
}
|
||||
|
||||
zone = thermal_zone_device_register("rcar_thermal", 0, priv,
|
||||
zone = thermal_zone_device_register("rcar_thermal", 0, 0, priv,
|
||||
&rcar_thermal_zone_ops, 0, 0);
|
||||
if (IS_ERR(zone)) {
|
||||
dev_err(&pdev->dev, "thermal zone device is NULL\n");
|
||||
|
@ -641,7 +641,6 @@ static void xenfb_backend_changed(struct xenbus_device *dev,
|
||||
case XenbusStateReconfiguring:
|
||||
case XenbusStateReconfigured:
|
||||
case XenbusStateUnknown:
|
||||
case XenbusStateClosed:
|
||||
break;
|
||||
|
||||
case XenbusStateInitWait:
|
||||
@ -670,6 +669,10 @@ InitWait:
|
||||
info->feature_resize = val;
|
||||
break;
|
||||
|
||||
case XenbusStateClosed:
|
||||
if (dev->state == XenbusStateClosed)
|
||||
break;
|
||||
/* Missed the backend's CLOSING state -- fallthrough */
|
||||
case XenbusStateClosing:
|
||||
xenbus_frontend_closed(dev);
|
||||
break;
|
||||
|
@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv,
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gntdev_free_map(struct grant_map *map)
|
||||
{
|
||||
if (map == NULL)
|
||||
return;
|
||||
|
||||
if (map->pages)
|
||||
free_xenballooned_pages(map->count, map->pages);
|
||||
kfree(map->pages);
|
||||
kfree(map->grants);
|
||||
kfree(map->map_ops);
|
||||
kfree(map->unmap_ops);
|
||||
kfree(map->kmap_ops);
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
|
||||
{
|
||||
struct grant_map *add;
|
||||
@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
|
||||
return add;
|
||||
|
||||
err:
|
||||
kfree(add->pages);
|
||||
kfree(add->grants);
|
||||
kfree(add->map_ops);
|
||||
kfree(add->unmap_ops);
|
||||
kfree(add->kmap_ops);
|
||||
kfree(add);
|
||||
gntdev_free_map(add);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map)
|
||||
evtchn_put(map->notify.event);
|
||||
}
|
||||
|
||||
if (map->pages) {
|
||||
if (!use_ptemod)
|
||||
unmap_grant_pages(map, 0, map->count);
|
||||
|
||||
free_xenballooned_pages(map->count, map->pages);
|
||||
}
|
||||
kfree(map->pages);
|
||||
kfree(map->grants);
|
||||
kfree(map->map_ops);
|
||||
kfree(map->unmap_ops);
|
||||
kfree(map);
|
||||
if (map->pages && !use_ptemod)
|
||||
unmap_grant_pages(map, 0, map->count);
|
||||
gntdev_free_map(map);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
@ -458,7 +458,7 @@ static ssize_t xenbus_file_write(struct file *filp,
|
||||
goto out;
|
||||
|
||||
/* Can't write a xenbus message larger we can buffer */
|
||||
if ((len + u->len) > sizeof(u->u.buffer)) {
|
||||
if (len > sizeof(u->u.buffer) - u->len) {
|
||||
/* On error, dump existing buffer */
|
||||
u->len = 0;
|
||||
rc = -EINVAL;
|
||||
|
@ -217,7 +217,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
|
||||
{
|
||||
char buf1[NFS_DNS_HOSTNAME_MAXLEN+1];
|
||||
struct nfs_dns_ent key, *item;
|
||||
unsigned long ttl;
|
||||
unsigned int ttl;
|
||||
ssize_t len;
|
||||
int ret = -EINVAL;
|
||||
|
||||
@ -240,7 +240,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
|
||||
key.namelen = len;
|
||||
memset(&key.h, 0, sizeof(key.h));
|
||||
|
||||
ttl = get_expiry(&buf);
|
||||
if (get_uint(&buf, &ttl) < 0)
|
||||
goto out;
|
||||
if (ttl == 0)
|
||||
goto out;
|
||||
key.h.expiry_time = ttl + seconds_since_boot();
|
||||
|
@ -685,7 +685,10 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
|
||||
if (ctx->cred != NULL)
|
||||
put_rpccred(ctx->cred);
|
||||
dput(ctx->dentry);
|
||||
nfs_sb_deactive(sb);
|
||||
if (is_sync)
|
||||
nfs_sb_deactive(sb);
|
||||
else
|
||||
nfs_sb_deactive_async(sb);
|
||||
kfree(ctx->mdsthreshold);
|
||||
kfree(ctx);
|
||||
}
|
||||
|
@ -351,10 +351,12 @@ extern int __init register_nfs_fs(void);
|
||||
extern void __exit unregister_nfs_fs(void);
|
||||
extern void nfs_sb_active(struct super_block *sb);
|
||||
extern void nfs_sb_deactive(struct super_block *sb);
|
||||
extern void nfs_sb_deactive_async(struct super_block *sb);
|
||||
|
||||
/* namespace.c */
|
||||
#define NFS_PATH_CANONICAL 1
|
||||
extern char *nfs_path(char **p, struct dentry *dentry,
|
||||
char *buffer, ssize_t buflen);
|
||||
char *buffer, ssize_t buflen, unsigned flags);
|
||||
extern struct vfsmount *nfs_d_automount(struct path *path);
|
||||
struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *,
|
||||
struct nfs_fh *, struct nfs_fattr *);
|
||||
@ -498,7 +500,7 @@ static inline char *nfs_devname(struct dentry *dentry,
|
||||
char *buffer, ssize_t buflen)
|
||||
{
|
||||
char *dummy;
|
||||
return nfs_path(&dummy, dentry, buffer, buflen);
|
||||
return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info)
|
||||
else
|
||||
msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT];
|
||||
|
||||
status = rpc_call_sync(mnt_clnt, &msg, 0);
|
||||
status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT);
|
||||
rpc_shutdown_client(mnt_clnt);
|
||||
|
||||
if (status < 0)
|
||||
|
@ -33,6 +33,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
|
||||
* @dentry - pointer to dentry
|
||||
* @buffer - result buffer
|
||||
* @buflen - length of buffer
|
||||
* @flags - options (see below)
|
||||
*
|
||||
* Helper function for constructing the server pathname
|
||||
* by arbitrary hashed dentry.
|
||||
@ -40,8 +41,14 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
|
||||
* This is mainly for use in figuring out the path on the
|
||||
* server side when automounting on top of an existing partition
|
||||
* and in generating /proc/mounts and friends.
|
||||
*
|
||||
* Supported flags:
|
||||
* NFS_PATH_CANONICAL: ensure there is exactly one slash after
|
||||
* the original device (export) name
|
||||
* (if unset, the original name is returned verbatim)
|
||||
*/
|
||||
char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen)
|
||||
char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen,
|
||||
unsigned flags)
|
||||
{
|
||||
char *end;
|
||||
int namelen;
|
||||
@ -74,7 +81,7 @@ rename_retry:
|
||||
rcu_read_unlock();
|
||||
goto rename_retry;
|
||||
}
|
||||
if (*end != '/') {
|
||||
if ((flags & NFS_PATH_CANONICAL) && *end != '/') {
|
||||
if (--buflen < 0) {
|
||||
spin_unlock(&dentry->d_lock);
|
||||
rcu_read_unlock();
|
||||
@ -91,9 +98,11 @@ rename_retry:
|
||||
return end;
|
||||
}
|
||||
namelen = strlen(base);
|
||||
/* Strip off excess slashes in base string */
|
||||
while (namelen > 0 && base[namelen - 1] == '/')
|
||||
namelen--;
|
||||
if (flags & NFS_PATH_CANONICAL) {
|
||||
/* Strip off excess slashes in base string */
|
||||
while (namelen > 0 && base[namelen - 1] == '/')
|
||||
namelen--;
|
||||
}
|
||||
buflen -= namelen;
|
||||
if (buflen < 0) {
|
||||
spin_unlock(&dentry->d_lock);
|
||||
|
@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end)
|
||||
static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
|
||||
{
|
||||
char *limit;
|
||||
char *path = nfs_path(&limit, dentry, buffer, buflen);
|
||||
char *path = nfs_path(&limit, dentry, buffer, buflen,
|
||||
NFS_PATH_CANONICAL);
|
||||
if (!IS_ERR(path)) {
|
||||
char *path_component = nfs_path_component(path, limit);
|
||||
if (path_component)
|
||||
|
@ -339,8 +339,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
|
||||
dprintk("%s ERROR: %d Reset session\n", __func__,
|
||||
errorcode);
|
||||
nfs4_schedule_session_recovery(clp->cl_session, errorcode);
|
||||
exception->retry = 1;
|
||||
break;
|
||||
goto wait_on_recovery;
|
||||
#endif /* defined(CONFIG_NFS_V4_1) */
|
||||
case -NFS4ERR_FILE_OPEN:
|
||||
if (exception->timeout > HZ) {
|
||||
@ -1572,9 +1571,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
|
||||
data->timestamp = jiffies;
|
||||
if (nfs4_setup_sequence(data->o_arg.server,
|
||||
&data->o_arg.seq_args,
|
||||
&data->o_res.seq_res, task))
|
||||
return;
|
||||
rpc_call_start(task);
|
||||
&data->o_res.seq_res,
|
||||
task) != 0)
|
||||
nfs_release_seqid(data->o_arg.seqid);
|
||||
else
|
||||
rpc_call_start(task);
|
||||
return;
|
||||
unlock_no_action:
|
||||
rcu_read_unlock();
|
||||
@ -1748,7 +1749,7 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
|
||||
|
||||
/* even though OPEN succeeded, access is denied. Close the file */
|
||||
nfs4_close_state(state, fmode);
|
||||
return -NFS4ERR_ACCESS;
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2196,7 +2197,7 @@ static void nfs4_free_closedata(void *data)
|
||||
nfs4_put_open_state(calldata->state);
|
||||
nfs_free_seqid(calldata->arg.seqid);
|
||||
nfs4_put_state_owner(sp);
|
||||
nfs_sb_deactive(sb);
|
||||
nfs_sb_deactive_async(sb);
|
||||
kfree(calldata);
|
||||
}
|
||||
|
||||
@ -2296,9 +2297,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
|
||||
if (nfs4_setup_sequence(NFS_SERVER(inode),
|
||||
&calldata->arg.seq_args,
|
||||
&calldata->res.seq_res,
|
||||
task))
|
||||
goto out;
|
||||
rpc_call_start(task);
|
||||
task) != 0)
|
||||
nfs_release_seqid(calldata->arg.seqid);
|
||||
else
|
||||
rpc_call_start(task);
|
||||
out:
|
||||
dprintk("%s: done!\n", __func__);
|
||||
}
|
||||
@ -4529,6 +4531,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
|
||||
if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
|
||||
rpc_restart_call_prepare(task);
|
||||
}
|
||||
nfs_release_seqid(calldata->arg.seqid);
|
||||
}
|
||||
|
||||
static void nfs4_locku_prepare(struct rpc_task *task, void *data)
|
||||
@ -4545,9 +4548,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
|
||||
calldata->timestamp = jiffies;
|
||||
if (nfs4_setup_sequence(calldata->server,
|
||||
&calldata->arg.seq_args,
|
||||
&calldata->res.seq_res, task))
|
||||
return;
|
||||
rpc_call_start(task);
|
||||
&calldata->res.seq_res,
|
||||
task) != 0)
|
||||
nfs_release_seqid(calldata->arg.seqid);
|
||||
else
|
||||
rpc_call_start(task);
|
||||
}
|
||||
|
||||
static const struct rpc_call_ops nfs4_locku_ops = {
|
||||
@ -4692,7 +4697,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
|
||||
/* Do we need to do an open_to_lock_owner? */
|
||||
if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
|
||||
if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0)
|
||||
return;
|
||||
goto out_release_lock_seqid;
|
||||
data->arg.open_stateid = &state->stateid;
|
||||
data->arg.new_lock_owner = 1;
|
||||
data->res.open_seqid = data->arg.open_seqid;
|
||||
@ -4701,10 +4706,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
|
||||
data->timestamp = jiffies;
|
||||
if (nfs4_setup_sequence(data->server,
|
||||
&data->arg.seq_args,
|
||||
&data->res.seq_res, task))
|
||||
&data->res.seq_res,
|
||||
task) == 0) {
|
||||
rpc_call_start(task);
|
||||
return;
|
||||
rpc_call_start(task);
|
||||
dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
|
||||
}
|
||||
nfs_release_seqid(data->arg.open_seqid);
|
||||
out_release_lock_seqid:
|
||||
nfs_release_seqid(data->arg.lock_seqid);
|
||||
dprintk("%s: done!, ret = %d\n", __func__, task->tk_status);
|
||||
}
|
||||
|
||||
static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata)
|
||||
@ -5667,7 +5677,7 @@ static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
|
||||
tbl->slots = new;
|
||||
tbl->max_slots = max_slots;
|
||||
}
|
||||
tbl->highest_used_slotid = -1; /* no slot is currently used */
|
||||
tbl->highest_used_slotid = NFS4_NO_SLOT;
|
||||
for (i = 0; i < tbl->max_slots; i++)
|
||||
tbl->slots[i].seq_nr = ivalue;
|
||||
spin_unlock(&tbl->slot_tbl_lock);
|
||||
|
@ -925,8 +925,8 @@ pnfs_find_alloc_layout(struct inode *ino,
|
||||
if (likely(nfsi->layout == NULL)) { /* Won the race? */
|
||||
nfsi->layout = new;
|
||||
return new;
|
||||
}
|
||||
pnfs_free_layout_hdr(new);
|
||||
} else if (new != NULL)
|
||||
pnfs_free_layout_hdr(new);
|
||||
out_existing:
|
||||
pnfs_get_layout_hdr(nfsi->layout);
|
||||
return nfsi->layout;
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include <linux/parser.h>
|
||||
#include <linux/nsproxy.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
@ -415,6 +416,54 @@ void nfs_sb_deactive(struct super_block *sb)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_sb_deactive);
|
||||
|
||||
static int nfs_deactivate_super_async_work(void *ptr)
|
||||
{
|
||||
struct super_block *sb = ptr;
|
||||
|
||||
deactivate_super(sb);
|
||||
module_put_and_exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* same effect as deactivate_super, but will do final unmount in kthread
|
||||
* context
|
||||
*/
|
||||
static void nfs_deactivate_super_async(struct super_block *sb)
|
||||
{
|
||||
struct task_struct *task;
|
||||
char buf[INET6_ADDRSTRLEN + 1];
|
||||
struct nfs_server *server = NFS_SB(sb);
|
||||
struct nfs_client *clp = server->nfs_client;
|
||||
|
||||
if (!atomic_add_unless(&sb->s_active, -1, 1)) {
|
||||
rcu_read_lock();
|
||||
snprintf(buf, sizeof(buf),
|
||||
rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR));
|
||||
rcu_read_unlock();
|
||||
|
||||
__module_get(THIS_MODULE);
|
||||
task = kthread_run(nfs_deactivate_super_async_work, sb,
|
||||
"%s-deactivate-super", buf);
|
||||
if (IS_ERR(task)) {
|
||||
pr_err("%s: kthread_run: %ld\n",
|
||||
__func__, PTR_ERR(task));
|
||||
/* make synchronous call and hope for the best */
|
||||
deactivate_super(sb);
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nfs_sb_deactive_async(struct super_block *sb)
|
||||
{
|
||||
struct nfs_server *server = NFS_SB(sb);
|
||||
|
||||
if (atomic_dec_and_test(&server->active))
|
||||
nfs_deactivate_super_async(sb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_sb_deactive_async);
|
||||
|
||||
/*
|
||||
* Deliver file system statistics to userspace
|
||||
*/
|
||||
@ -771,7 +820,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root)
|
||||
int err = 0;
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
devname = nfs_path(&dummy, root, page, PAGE_SIZE);
|
||||
devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0);
|
||||
if (IS_ERR(devname))
|
||||
err = PTR_ERR(devname);
|
||||
else
|
||||
|
@ -95,7 +95,7 @@ static void nfs_async_unlink_release(void *calldata)
|
||||
|
||||
nfs_dec_sillycount(data->dir);
|
||||
nfs_free_unlinkdata(data);
|
||||
nfs_sb_deactive(sb);
|
||||
nfs_sb_deactive_async(sb);
|
||||
}
|
||||
|
||||
static void nfs_unlink_prepare(struct rpc_task *task, void *calldata)
|
||||
|
192
include/linux/hashtable.h
Normal file
192
include/linux/hashtable.h
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Statically sized hash table implementation
|
||||
* (C) 2012 Sasha Levin <levinsasha928@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_HASHTABLE_H
|
||||
#define _LINUX_HASHTABLE_H
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/rculist.h>
|
||||
|
||||
#define DEFINE_HASHTABLE(name, bits) \
|
||||
struct hlist_head name[1 << (bits)] = \
|
||||
{ [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
|
||||
|
||||
#define DECLARE_HASHTABLE(name, bits) \
|
||||
struct hlist_head name[1 << (bits)]
|
||||
|
||||
#define HASH_SIZE(name) (ARRAY_SIZE(name))
|
||||
#define HASH_BITS(name) ilog2(HASH_SIZE(name))
|
||||
|
||||
/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
|
||||
#define hash_min(val, bits) \
|
||||
(sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits))
|
||||
|
||||
static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sz; i++)
|
||||
INIT_HLIST_HEAD(&ht[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* hash_init - initialize a hash table
|
||||
* @hashtable: hashtable to be initialized
|
||||
*
|
||||
* Calculates the size of the hashtable from the given parameter, otherwise
|
||||
* same as hash_init_size.
|
||||
*
|
||||
* This has to be a macro since HASH_BITS() will not work on pointers since
|
||||
* it calculates the size during preprocessing.
|
||||
*/
|
||||
#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable))
|
||||
|
||||
/**
|
||||
* hash_add - add an object to a hashtable
|
||||
* @hashtable: hashtable to add to
|
||||
* @node: the &struct hlist_node of the object to be added
|
||||
* @key: the key of the object to be added
|
||||
*/
|
||||
#define hash_add(hashtable, node, key) \
|
||||
hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
|
||||
|
||||
/**
|
||||
* hash_add_rcu - add an object to a rcu enabled hashtable
|
||||
* @hashtable: hashtable to add to
|
||||
* @node: the &struct hlist_node of the object to be added
|
||||
* @key: the key of the object to be added
|
||||
*/
|
||||
#define hash_add_rcu(hashtable, node, key) \
|
||||
hlist_add_head_rcu(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
|
||||
|
||||
/**
|
||||
* hash_hashed - check whether an object is in any hashtable
|
||||
* @node: the &struct hlist_node of the object to be checked
|
||||
*/
|
||||
static inline bool hash_hashed(struct hlist_node *node)
|
||||
{
|
||||
return !hlist_unhashed(node);
|
||||
}
|
||||
|
||||
static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sz; i++)
|
||||
if (!hlist_empty(&ht[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* hash_empty - check whether a hashtable is empty
|
||||
* @hashtable: hashtable to check
|
||||
*
|
||||
* This has to be a macro since HASH_BITS() will not work on pointers since
|
||||
* it calculates the size during preprocessing.
|
||||
*/
|
||||
#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable))
|
||||
|
||||
/**
|
||||
* hash_del - remove an object from a hashtable
|
||||
* @node: &struct hlist_node of the object to remove
|
||||
*/
|
||||
static inline void hash_del(struct hlist_node *node)
|
||||
{
|
||||
hlist_del_init(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* hash_del_rcu - remove an object from a rcu enabled hashtable
|
||||
* @node: &struct hlist_node of the object to remove
|
||||
*/
|
||||
static inline void hash_del_rcu(struct hlist_node *node)
|
||||
{
|
||||
hlist_del_init_rcu(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* hash_for_each - iterate over a hashtable
|
||||
* @name: hashtable to iterate
|
||||
* @bkt: integer to use as bucket loop cursor
|
||||
* @node: the &struct list_head to use as a loop cursor for each entry
|
||||
* @obj: the type * to use as a loop cursor for each entry
|
||||
* @member: the name of the hlist_node within the struct
|
||||
*/
|
||||
#define hash_for_each(name, bkt, node, obj, member) \
|
||||
for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
|
||||
hlist_for_each_entry(obj, node, &name[bkt], member)
|
||||
|
||||
/**
|
||||
* hash_for_each_rcu - iterate over a rcu enabled hashtable
|
||||
* @name: hashtable to iterate
|
||||
* @bkt: integer to use as bucket loop cursor
|
||||
* @node: the &struct list_head to use as a loop cursor for each entry
|
||||
* @obj: the type * to use as a loop cursor for each entry
|
||||
* @member: the name of the hlist_node within the struct
|
||||
*/
|
||||
#define hash_for_each_rcu(name, bkt, node, obj, member) \
|
||||
for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
|
||||
hlist_for_each_entry_rcu(obj, node, &name[bkt], member)
|
||||
|
||||
/**
|
||||
* hash_for_each_safe - iterate over a hashtable safe against removal of
|
||||
* hash entry
|
||||
* @name: hashtable to iterate
|
||||
* @bkt: integer to use as bucket loop cursor
|
||||
* @node: the &struct list_head to use as a loop cursor for each entry
|
||||
* @tmp: a &struct used for temporary storage
|
||||
* @obj: the type * to use as a loop cursor for each entry
|
||||
* @member: the name of the hlist_node within the struct
|
||||
*/
|
||||
#define hash_for_each_safe(name, bkt, node, tmp, obj, member) \
|
||||
for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
|
||||
hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member)
|
||||
|
||||
/**
|
||||
* hash_for_each_possible - iterate over all possible objects hashing to the
|
||||
* same bucket
|
||||
* @name: hashtable to iterate
|
||||
* @obj: the type * to use as a loop cursor for each entry
|
||||
* @node: the &struct list_head to use as a loop cursor for each entry
|
||||
* @member: the name of the hlist_node within the struct
|
||||
* @key: the key of the objects to iterate over
|
||||
*/
|
||||
#define hash_for_each_possible(name, obj, node, member, key) \
|
||||
hlist_for_each_entry(obj, node, &name[hash_min(key, HASH_BITS(name))], member)
|
||||
|
||||
/**
|
||||
* hash_for_each_possible_rcu - iterate over all possible objects hashing to the
|
||||
* same bucket in an rcu enabled hashtable
|
||||
* in a rcu enabled hashtable
|
||||
* @name: hashtable to iterate
|
||||
* @obj: the type * to use as a loop cursor for each entry
|
||||
* @node: the &struct list_head to use as a loop cursor for each entry
|
||||
* @member: the name of the hlist_node within the struct
|
||||
* @key: the key of the objects to iterate over
|
||||
*/
|
||||
#define hash_for_each_possible_rcu(name, obj, node, member, key) \
|
||||
hlist_for_each_entry_rcu(obj, node, &name[hash_min(key, HASH_BITS(name))], member)
|
||||
|
||||
/**
|
||||
* hash_for_each_possible_safe - iterate over all possible objects hashing to the
|
||||
* same bucket safe against removals
|
||||
* @name: hashtable to iterate
|
||||
* @obj: the type * to use as a loop cursor for each entry
|
||||
* @node: the &struct list_head to use as a loop cursor for each entry
|
||||
* @tmp: a &struct used for temporary storage
|
||||
* @member: the name of the hlist_node within the struct
|
||||
* @key: the key of the objects to iterate over
|
||||
*/
|
||||
#define hash_for_each_possible_safe(name, obj, node, tmp, member, key) \
|
||||
hlist_for_each_entry_safe(obj, node, tmp, \
|
||||
&name[hash_min(key, HASH_BITS(name))], member)
|
||||
|
||||
|
||||
#endif
|
@ -2651,6 +2651,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
|
||||
*/
|
||||
unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
|
||||
|
||||
/**
|
||||
* ieee80211_get_mesh_hdrlen - get mesh extension header length
|
||||
* @meshhdr: the mesh extension header, only the flags field
|
||||
* (first byte) will be accessed
|
||||
* Returns the length of the extension header, which is always at
|
||||
* least 6 bytes and at most 18 if address 5 and 6 are present.
|
||||
*/
|
||||
unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
|
||||
|
||||
/**
|
||||
* DOC: Data path helpers
|
||||
*
|
||||
|
@ -377,6 +377,14 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd,
|
||||
DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin);
|
||||
DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin);
|
||||
|
||||
TRACE_EVENT(xen_mmu_flush_tlb_all,
|
||||
TP_PROTO(int x),
|
||||
TP_ARGS(x),
|
||||
TP_STRUCT__entry(__array(char, x, 0)),
|
||||
TP_fast_assign((void)x),
|
||||
TP_printk("%s", "")
|
||||
);
|
||||
|
||||
TRACE_EVENT(xen_mmu_flush_tlb,
|
||||
TP_PROTO(int x),
|
||||
TP_ARGS(x),
|
||||
|
@ -184,7 +184,8 @@ nf_nat_ipv4_out(unsigned int hooknum,
|
||||
|
||||
if ((ct->tuplehash[dir].tuple.src.u3.ip !=
|
||||
ct->tuplehash[!dir].tuple.dst.u3.ip) ||
|
||||
(ct->tuplehash[dir].tuple.src.u.all !=
|
||||
(ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
|
||||
ct->tuplehash[dir].tuple.src.u.all !=
|
||||
ct->tuplehash[!dir].tuple.dst.u.all))
|
||||
if (nf_xfrm_me_harder(skb, AF_INET) < 0)
|
||||
ret = NF_DROP;
|
||||
@ -221,6 +222,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,
|
||||
}
|
||||
#ifdef CONFIG_XFRM
|
||||
else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
|
||||
ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
|
||||
ct->tuplehash[dir].tuple.dst.u.all !=
|
||||
ct->tuplehash[!dir].tuple.src.u.all)
|
||||
if (nf_xfrm_me_harder(skb, AF_INET) < 0)
|
||||
|
@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext,
|
||||
.tcpv_rttcnt = ca->cnt_rtt,
|
||||
.tcpv_minrtt = ca->base_rtt,
|
||||
};
|
||||
u64 t = ca->sum_rtt;
|
||||
|
||||
do_div(t, ca->cnt_rtt);
|
||||
info.tcpv_rtt = t;
|
||||
if (info.tcpv_rttcnt > 0) {
|
||||
u64 t = ca->sum_rtt;
|
||||
|
||||
do_div(t, info.tcpv_rttcnt);
|
||||
info.tcpv_rtt = t;
|
||||
}
|
||||
nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);
|
||||
}
|
||||
}
|
||||
|
@ -4529,6 +4529,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size)
|
||||
struct tcphdr *th;
|
||||
bool fragstolen;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
skb = alloc_skb(size + sizeof(*th), sk->sk_allocation);
|
||||
if (!skb)
|
||||
goto err;
|
||||
|
@ -864,7 +864,7 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
|
||||
}
|
||||
a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6];
|
||||
if (a) {
|
||||
if (nla_len(a) != sizeof(sizeof(struct in6_addr)))
|
||||
if (nla_len(a) != sizeof(struct in6_addr))
|
||||
return -EINVAL;
|
||||
addr->family = AF_INET6;
|
||||
memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6));
|
||||
|
@ -186,7 +186,8 @@ nf_nat_ipv6_out(unsigned int hooknum,
|
||||
|
||||
if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3) ||
|
||||
(ct->tuplehash[dir].tuple.src.u.all !=
|
||||
(ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
|
||||
ct->tuplehash[dir].tuple.src.u.all !=
|
||||
ct->tuplehash[!dir].tuple.dst.u.all))
|
||||
if (nf_xfrm_me_harder(skb, AF_INET6) < 0)
|
||||
ret = NF_DROP;
|
||||
@ -222,6 +223,7 @@ nf_nat_ipv6_local_fn(unsigned int hooknum,
|
||||
}
|
||||
#ifdef CONFIG_XFRM
|
||||
else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
|
||||
ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
|
||||
ct->tuplehash[dir].tuple.dst.u.all !=
|
||||
ct->tuplehash[!dir].tuple.src.u.all)
|
||||
if (nf_xfrm_me_harder(skb, AF_INET6))
|
||||
|
@ -85,7 +85,7 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static int __net_init nf_ct_frag6_sysctl_register(struct net *net)
|
||||
static int nf_ct_frag6_sysctl_register(struct net *net)
|
||||
{
|
||||
struct ctl_table *table;
|
||||
struct ctl_table_header *hdr;
|
||||
@ -127,7 +127,7 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)
|
||||
}
|
||||
|
||||
#else
|
||||
static int __net_init nf_ct_frag6_sysctl_register(struct net *net)
|
||||
static int nf_ct_frag6_sysctl_register(struct net *net)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -291,6 +291,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
|
||||
|
||||
out_del_dev:
|
||||
free_netdev(dev);
|
||||
spriv->dev = NULL;
|
||||
out_del_session:
|
||||
l2tp_session_delete(session);
|
||||
out:
|
||||
|
@ -1108,7 +1108,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
|
||||
sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
|
||||
sdata->u.ibss.ibss_join_req = jiffies;
|
||||
|
||||
memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
|
||||
memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
|
||||
sdata->u.ibss.ssid_len = params->ssid_len;
|
||||
|
||||
mutex_unlock(&sdata->u.ibss.mtx);
|
||||
|
@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
|
||||
|
||||
if (ieee80211_is_action(hdr->frame_control)) {
|
||||
u8 category;
|
||||
|
||||
/* make sure category field is present */
|
||||
if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
mgmt = (struct ieee80211_mgmt *)hdr;
|
||||
category = mgmt->u.action.category;
|
||||
if (category != WLAN_CATEGORY_MESH_ACTION &&
|
||||
@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
|
||||
*/
|
||||
if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
ieee80211_is_data_present(hdr->frame_control)) {
|
||||
u16 ethertype;
|
||||
u8 *payload;
|
||||
unsigned int hdrlen;
|
||||
__be16 ethertype;
|
||||
|
||||
payload = rx->skb->data +
|
||||
ieee80211_hdrlen(hdr->frame_control);
|
||||
ethertype = (payload[6] << 8) | payload[7];
|
||||
if (cpu_to_be16(ethertype) ==
|
||||
rx->sdata->control_port_protocol)
|
||||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
||||
if (rx->skb->len < hdrlen + 8)
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2);
|
||||
if (ethertype == rx->sdata->control_port_protocol)
|
||||
return RX_CONTINUE;
|
||||
}
|
||||
|
||||
@ -1462,11 +1469,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
||||
|
||||
hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||
fc = hdr->frame_control;
|
||||
|
||||
if (ieee80211_is_ctl(fc))
|
||||
return RX_CONTINUE;
|
||||
|
||||
sc = le16_to_cpu(hdr->seq_ctrl);
|
||||
frag = sc & IEEE80211_SCTL_FRAG;
|
||||
|
||||
if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
|
||||
(rx->skb)->len < 24 ||
|
||||
is_multicast_ether_addr(hdr->addr1))) {
|
||||
/* not fragmented */
|
||||
goto out;
|
||||
@ -1889,6 +1899,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
||||
/* make sure fixed part of mesh header is there, also checks skb len */
|
||||
if (!pskb_may_pull(rx->skb, hdrlen + 6))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
|
||||
|
||||
/* make sure full mesh header is there, also checks skb len */
|
||||
if (!pskb_may_pull(rx->skb,
|
||||
hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
/* reload pointers */
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
|
||||
|
||||
/* frame is in RMC, don't forward */
|
||||
@ -1897,7 +1921,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||
mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
if (!ieee80211_is_data(hdr->frame_control))
|
||||
if (!ieee80211_is_data(hdr->frame_control) ||
|
||||
!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
||||
return RX_CONTINUE;
|
||||
|
||||
if (!mesh_hdr->ttl)
|
||||
@ -1911,9 +1936,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||
if (is_multicast_ether_addr(hdr->addr1)) {
|
||||
mpp_addr = hdr->addr3;
|
||||
proxied_addr = mesh_hdr->eaddr1;
|
||||
} else {
|
||||
} else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
|
||||
/* has_a4 already checked in ieee80211_rx_mesh_check */
|
||||
mpp_addr = hdr->addr4;
|
||||
proxied_addr = mesh_hdr->eaddr2;
|
||||
} else {
|
||||
return RX_DROP_MONITOR;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
@ -1941,12 +1969,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||
}
|
||||
skb_set_queue_mapping(skb, q);
|
||||
|
||||
if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
||||
goto out;
|
||||
|
||||
if (!--mesh_hdr->ttl) {
|
||||
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
|
||||
return RX_DROP_MONITOR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ifmsh->mshcfg.dot11MeshForwarding)
|
||||
@ -2353,6 +2378,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||
}
|
||||
break;
|
||||
case WLAN_CATEGORY_SELF_PROTECTED:
|
||||
if (len < (IEEE80211_MIN_ACTION_SIZE +
|
||||
sizeof(mgmt->u.action.u.self_prot.action_code)))
|
||||
break;
|
||||
|
||||
switch (mgmt->u.action.u.self_prot.action_code) {
|
||||
case WLAN_SP_MESH_PEERING_OPEN:
|
||||
case WLAN_SP_MESH_PEERING_CLOSE:
|
||||
@ -2371,6 +2400,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||
}
|
||||
break;
|
||||
case WLAN_CATEGORY_MESH_ACTION:
|
||||
if (len < (IEEE80211_MIN_ACTION_SIZE +
|
||||
sizeof(mgmt->u.action.u.mesh_action.action_code)))
|
||||
break;
|
||||
|
||||
if (!ieee80211_vif_is_mesh(&sdata->vif))
|
||||
break;
|
||||
if (mesh_action_is_path_sel(mgmt) &&
|
||||
@ -2913,10 +2946,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
|
||||
if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
|
||||
local->dot11ReceivedFragmentCount++;
|
||||
|
||||
if (ieee80211_is_mgmt(fc))
|
||||
err = skb_linearize(skb);
|
||||
else
|
||||
if (ieee80211_is_mgmt(fc)) {
|
||||
/* drop frame if too short for header */
|
||||
if (skb->len < ieee80211_hdrlen(fc))
|
||||
err = -ENOBUFS;
|
||||
else
|
||||
err = skb_linearize(skb);
|
||||
} else {
|
||||
err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
|
||||
}
|
||||
|
||||
if (err) {
|
||||
dev_kfree_skb(skb);
|
||||
|
@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
|
||||
break;
|
||||
}
|
||||
|
||||
if (id != WLAN_EID_VENDOR_SPECIFIC &&
|
||||
id != WLAN_EID_QUIET &&
|
||||
test_bit(id, seen_elems)) {
|
||||
elems->parse_error = true;
|
||||
left -= elen;
|
||||
pos += elen;
|
||||
continue;
|
||||
switch (id) {
|
||||
case WLAN_EID_SSID:
|
||||
case WLAN_EID_SUPP_RATES:
|
||||
case WLAN_EID_FH_PARAMS:
|
||||
case WLAN_EID_DS_PARAMS:
|
||||
case WLAN_EID_CF_PARAMS:
|
||||
case WLAN_EID_TIM:
|
||||
case WLAN_EID_IBSS_PARAMS:
|
||||
case WLAN_EID_CHALLENGE:
|
||||
case WLAN_EID_RSN:
|
||||
case WLAN_EID_ERP_INFO:
|
||||
case WLAN_EID_EXT_SUPP_RATES:
|
||||
case WLAN_EID_HT_CAPABILITY:
|
||||
case WLAN_EID_HT_OPERATION:
|
||||
case WLAN_EID_VHT_CAPABILITY:
|
||||
case WLAN_EID_VHT_OPERATION:
|
||||
case WLAN_EID_MESH_ID:
|
||||
case WLAN_EID_MESH_CONFIG:
|
||||
case WLAN_EID_PEER_MGMT:
|
||||
case WLAN_EID_PREQ:
|
||||
case WLAN_EID_PREP:
|
||||
case WLAN_EID_PERR:
|
||||
case WLAN_EID_RANN:
|
||||
case WLAN_EID_CHANNEL_SWITCH:
|
||||
case WLAN_EID_EXT_CHANSWITCH_ANN:
|
||||
case WLAN_EID_COUNTRY:
|
||||
case WLAN_EID_PWR_CONSTRAINT:
|
||||
case WLAN_EID_TIMEOUT_INTERVAL:
|
||||
if (test_bit(id, seen_elems)) {
|
||||
elems->parse_error = true;
|
||||
left -= elen;
|
||||
pos += elen;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (calc_crc && id < 64 && (filter & (1ULL << id)))
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user