dect
/
linux-2.6
Archived
13
0
Fork 0

Merge branch 'spi-linus' into spi-next

This commit is contained in:
Mark Brown 2012-11-06 10:03:29 +01:00
commit 70324494b6
196 changed files with 2199 additions and 1186 deletions

View File

@ -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>;
};

View File

@ -10,7 +10,7 @@ Supported chips:
BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors
(not yet published) (not yet published)
Author: Andreas Herrmann <andreas.herrmann3@amd.com> Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
Description Description
----------- -----------

View File

@ -503,7 +503,7 @@ F: include/linux/altera_uart.h
F: include/linux/altera_jtaguart.h F: include/linux/altera_jtaguart.h
AMD FAM15H PROCESSOR POWER MONITORING DRIVER 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 L: lm-sensors@lm-sensors.org
S: Maintained S: Maintained
F: Documentation/hwmon/fam15h_power 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: Seung-Woo Kim <sw0312.kim@samsung.com>
M: Kyungmin Park <kyungmin.park@samsung.com> M: Kyungmin Park <kyungmin.park@samsung.com>
L: dri-devel@lists.freedesktop.org L: dri-devel@lists.freedesktop.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git
S: Supported S: Supported
F: drivers/gpu/drm/exynos F: drivers/gpu/drm/exynos
F: include/drm/exynos* F: include/drm/exynos*
@ -5647,7 +5648,7 @@ S: Maintained
F: drivers/pinctrl/spear/ F: drivers/pinctrl/spear/
PKTCDVD DRIVER PKTCDVD DRIVER
M: Peter Osterlund <petero2@telia.com> M: Jiri Kosina <jkosina@suse.cz>
S: Maintained S: Maintained
F: drivers/block/pktcdvd.c F: drivers/block/pktcdvd.c
F: include/linux/pktcdvd.h F: include/linux/pktcdvd.h

View File

@ -1,7 +1,7 @@
VERSION = 3 VERSION = 3
PATCHLEVEL = 7 PATCHLEVEL = 7
SUBLEVEL = 0 SUBLEVEL = 0
EXTRAVERSION = -rc3 EXTRAVERSION = -rc4
NAME = Terrified Chipmunk NAME = Terrified Chipmunk
# *DOCUMENTATION* # *DOCUMENTATION*

View File

@ -48,20 +48,16 @@
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/assembler.h> #include <asm/assembler.h>
#include <asm/opcodes-virt.h>
#include <xen/interface/xen.h> #include <xen/interface/xen.h>
/* HVC 0xEA1 */ #define XEN_IMM 0xEA1
#ifdef CONFIG_THUMB2_KERNEL
#define xen_hvc .word 0xf7e08ea1
#else
#define xen_hvc .word 0xe140ea71
#endif
#define HYPERCALL_SIMPLE(hypercall) \ #define HYPERCALL_SIMPLE(hypercall) \
ENTRY(HYPERVISOR_##hypercall) \ ENTRY(HYPERVISOR_##hypercall) \
mov r12, #__HYPERVISOR_##hypercall; \ mov r12, #__HYPERVISOR_##hypercall; \
xen_hvc; \ __HVC(XEN_IMM); \
mov pc, lr; \ mov pc, lr; \
ENDPROC(HYPERVISOR_##hypercall) ENDPROC(HYPERVISOR_##hypercall)
@ -76,7 +72,7 @@ ENTRY(HYPERVISOR_##hypercall) \
stmdb sp!, {r4} \ stmdb sp!, {r4} \
ldr r4, [sp, #4] \ ldr r4, [sp, #4] \
mov r12, #__HYPERVISOR_##hypercall; \ mov r12, #__HYPERVISOR_##hypercall; \
xen_hvc \ __HVC(XEN_IMM); \
ldm sp!, {r4} \ ldm sp!, {r4} \
mov pc, lr \ mov pc, lr \
ENDPROC(HYPERVISOR_##hypercall) ENDPROC(HYPERVISOR_##hypercall)
@ -100,7 +96,7 @@ ENTRY(privcmd_call)
mov r2, r3 mov r2, r3
ldr r3, [sp, #8] ldr r3, [sp, #8]
ldr r4, [sp, #4] ldr r4, [sp, #4]
xen_hvc __HVC(XEN_IMM)
ldm sp!, {r4} ldm sp!, {r4}
mov pc, lr mov pc, lr
ENDPROC(privcmd_call); ENDPROC(privcmd_call);

View File

@ -13,6 +13,7 @@ config FRV
select GENERIC_CPU_DEVICES select GENERIC_CPU_DEVICES
select ARCH_WANT_IPC_PARSE_VERSION select ARCH_WANT_IPC_PARSE_VERSION
select GENERIC_KERNEL_THREAD select GENERIC_KERNEL_THREAD
select GENERIC_KERNEL_EXECVE
config ZONE_DMA config ZONE_DMA
bool bool

View File

@ -17,6 +17,8 @@ PARAMS_PHYS = 0x0207c000
INITRD_PHYS = 0x02180000 INITRD_PHYS = 0x02180000
INITRD_VIRT = 0x02180000 INITRD_VIRT = 0x02180000
OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment
# #
# If you don't define ZRELADDR above, # If you don't define ZRELADDR above,
# then it defaults to ZTEXTADDR # then it defaults to ZTEXTADDR
@ -32,18 +34,18 @@ Image: $(obj)/Image
targets: $(obj)/Image targets: $(obj)/Image
$(obj)/Image: vmlinux FORCE $(obj)/Image: vmlinux FORCE
$(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@ $(OBJCOPY) $(OBJCOPYFLAGS) -S vmlinux $@
#$(obj)/Image: $(CONFIGURE) $(SYSTEM) #$(obj)/Image: $(CONFIGURE) $(SYSTEM)
# $(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@ # $(OBJCOPY) $(OBJCOPYFLAGS) -g -S $(SYSTEM) $@
bzImage: zImage bzImage: zImage
zImage: $(CONFIGURE) compressed/$(LINUX) zImage: $(CONFIGURE) compressed/$(LINUX)
$(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@ $(OBJCOPY) $(OBJCOPYFLAGS) -S compressed/$(LINUX) $@
bootpImage: bootp/bootp bootpImage: bootp/bootp
$(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@ $(OBJCOPY) $(OBJCOPYFLAGS) -S bootp/bootp $@
compressed/$(LINUX): $(LINUX) dep compressed/$(LINUX): $(LINUX) dep
@$(MAKE) -C compressed $(LINUX) @$(MAKE) -C compressed $(LINUX)

View File

@ -30,7 +30,6 @@
#define __ARCH_WANT_SYS_RT_SIGACTION #define __ARCH_WANT_SYS_RT_SIGACTION
#define __ARCH_WANT_SYS_RT_SIGSUSPEND #define __ARCH_WANT_SYS_RT_SIGSUSPEND
#define __ARCH_WANT_SYS_EXECVE #define __ARCH_WANT_SYS_EXECVE
#define __ARCH_WANT_KERNEL_EXECVE
/* /*
* "Conditional" syscalls * "Conditional" syscalls

View File

@ -869,11 +869,6 @@ ret_from_kernel_thread:
call schedule_tail call schedule_tail
calll.p @(gr21,gr0) calll.p @(gr21,gr0)
or gr20,gr20,gr8 or gr20,gr20,gr8
bra sys_exit
.globl ret_from_kernel_execve
ret_from_kernel_execve:
ori gr28,0,sp
bra __syscall_exit bra __syscall_exit
################################################################################################### ###################################################################################################
@ -1080,27 +1075,10 @@ __entry_return_from_kernel_interrupt:
subicc gr5,#0,gr0,icc0 subicc gr5,#0,gr0,icc0
beq icc0,#0,__entry_return_direct beq icc0,#0,__entry_return_direct
__entry_preempt_need_resched: subcc gr0,gr0,gr0,icc2 /* set Z and clear C */
ldi @(gr15,#TI_FLAGS),gr4 call preempt_schedule_irq
andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0
beq icc0,#1,__entry_return_direct
setlos #PREEMPT_ACTIVE,gr5
sti gr5,@(gr15,#TI_FLAGS)
andi gr23,#~PSR_PIL,gr23
movgs gr23,psr
call schedule
sti gr0,@(gr15,#TI_PRE_COUNT)
movsg psr,gr23
ori gr23,#PSR_PIL_14,gr23
movgs gr23,psr
bra __entry_preempt_need_resched
#else
bra __entry_return_direct
#endif #endif
bra __entry_return_direct
############################################################################### ###############################################################################

View File

@ -181,6 +181,9 @@ int copy_thread(unsigned long clone_flags,
childregs = (struct pt_regs *) childregs = (struct pt_regs *)
(task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE); (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
/* set up the userspace frame (the only place that the USP is stored) */
*childregs = *__kernel_frame0_ptr;
p->set_child_tid = p->clear_child_tid = NULL; p->set_child_tid = p->clear_child_tid = NULL;
p->thread.frame = childregs; p->thread.frame = childregs;
@ -191,10 +194,8 @@ int copy_thread(unsigned long clone_flags,
p->thread.frame0 = childregs; p->thread.frame0 = childregs;
if (unlikely(!regs)) { if (unlikely(!regs)) {
memset(childregs, 0, sizeof(struct pt_regs));
childregs->gr9 = usp; /* function */ childregs->gr9 = usp; /* function */
childregs->gr8 = arg; childregs->gr8 = arg;
childregs->psr = PSR_S;
p->thread.pc = (unsigned long) ret_from_kernel_thread; p->thread.pc = (unsigned long) ret_from_kernel_thread;
save_user_regs(p->thread.user); save_user_regs(p->thread.user);
return 0; return 0;

View File

@ -11,6 +11,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/export.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/pci.h> #include <linux/pci.h>

View File

@ -33,7 +33,6 @@
#ifndef _ASM_X86_XEN_HYPERVISOR_H #ifndef _ASM_X86_XEN_HYPERVISOR_H
#define _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 shared_info *HYPERVISOR_shared_info;
extern struct start_info *xen_start_info; extern struct start_info *xen_start_info;

View File

@ -3779,7 +3779,7 @@ static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
{ {
struct kvm_mmio_fragment *frag = &vcpu->mmio_fragments[0]; struct kvm_mmio_fragment *frag = &vcpu->mmio_fragments[0];
memcpy(vcpu->run->mmio.data, frag->data, frag->len); memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len));
return X86EMUL_CONTINUE; return X86EMUL_CONTINUE;
} }
@ -3832,18 +3832,11 @@ mmio:
bytes -= handled; bytes -= handled;
val += handled; val += handled;
while (bytes) { WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS);
unsigned now = min(bytes, 8U); frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
frag->gpa = gpa;
frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++]; frag->data = val;
frag->gpa = gpa; frag->len = bytes;
frag->data = val;
frag->len = now;
gpa += now;
val += now;
bytes -= now;
}
return X86EMUL_CONTINUE; return X86EMUL_CONTINUE;
} }
@ -3890,7 +3883,7 @@ int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
vcpu->mmio_needed = 1; vcpu->mmio_needed = 1;
vcpu->mmio_cur_fragment = 0; vcpu->mmio_cur_fragment = 0;
vcpu->run->mmio.len = vcpu->mmio_fragments[0].len; vcpu->run->mmio.len = min(8u, vcpu->mmio_fragments[0].len);
vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write; vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write;
vcpu->run->exit_reason = KVM_EXIT_MMIO; vcpu->run->exit_reason = KVM_EXIT_MMIO;
vcpu->run->mmio.phys_addr = gpa; vcpu->run->mmio.phys_addr = gpa;
@ -5522,28 +5515,44 @@ static int complete_emulated_pio(struct kvm_vcpu *vcpu)
* *
* read: * read:
* for each fragment * for each fragment
* write gpa, len * for each mmio piece in the fragment
* exit * write gpa, len
* copy data * exit
* copy data
* execute insn * execute insn
* *
* write: * write:
* for each fragment * for each fragment
* write gpa, len * for each mmio piece in the fragment
* copy data * write gpa, len
* exit * copy data
* exit
*/ */
static int complete_emulated_mmio(struct kvm_vcpu *vcpu) static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
{ {
struct kvm_run *run = vcpu->run; struct kvm_run *run = vcpu->run;
struct kvm_mmio_fragment *frag; struct kvm_mmio_fragment *frag;
unsigned len;
BUG_ON(!vcpu->mmio_needed); BUG_ON(!vcpu->mmio_needed);
/* Complete previous fragment */ /* Complete previous fragment */
frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++]; frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment];
len = min(8u, frag->len);
if (!vcpu->mmio_is_write) if (!vcpu->mmio_is_write)
memcpy(frag->data, run->mmio.data, frag->len); memcpy(frag->data, run->mmio.data, len);
if (frag->len <= 8) {
/* Switch to the next fragment. */
frag++;
vcpu->mmio_cur_fragment++;
} else {
/* Go forward to the next mmio piece. */
frag->data += len;
frag->gpa += len;
frag->len -= len;
}
if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) { if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
vcpu->mmio_needed = 0; vcpu->mmio_needed = 0;
if (vcpu->mmio_is_write) if (vcpu->mmio_is_write)
@ -5551,13 +5560,12 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
vcpu->mmio_read_completed = 1; vcpu->mmio_read_completed = 1;
return complete_emulated_io(vcpu); return complete_emulated_io(vcpu);
} }
/* Initiate next fragment */
++frag;
run->exit_reason = KVM_EXIT_MMIO; run->exit_reason = KVM_EXIT_MMIO;
run->mmio.phys_addr = frag->gpa; run->mmio.phys_addr = frag->gpa;
if (vcpu->mmio_is_write) if (vcpu->mmio_is_write)
memcpy(run->mmio.data, frag->data, frag->len); memcpy(run->mmio.data, frag->data, min(8u, frag->len));
run->mmio.len = frag->len; run->mmio.len = min(8u, frag->len);
run->mmio.is_write = vcpu->mmio_is_write; run->mmio.is_write = vcpu->mmio_is_write;
vcpu->arch.complete_userspace_io = complete_emulated_mmio; vcpu->arch.complete_userspace_io = complete_emulated_mmio;
return 0; return 0;

View File

@ -1288,6 +1288,25 @@ unsigned long xen_read_cr2_direct(void)
return this_cpu_read(xen_vcpu_info.arch.cr2); 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) static void xen_flush_tlb(void)
{ {
struct mmuext_op *op; struct mmuext_op *op;
@ -2518,7 +2537,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
err = 0; err = 0;
out: out:
flush_tlb_all(); xen_flush_tlb_all();
return err; return err;
} }

View File

@ -13,6 +13,8 @@ config XTENSA
select GENERIC_CPU_DEVICES select GENERIC_CPU_DEVICES
select MODULES_USE_ELF_RELA select MODULES_USE_ELF_RELA
select GENERIC_PCI_IOMAP select GENERIC_PCI_IOMAP
select GENERIC_KERNEL_THREAD
select GENERIC_KERNEL_EXECVE
select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_OPTIONAL_GPIOLIB
help help
Xtensa processors are 32-bit RISC machines designed by Tensilica Xtensa processors are 32-bit RISC machines designed by Tensilica

View File

@ -62,6 +62,10 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
static inline void iounmap(volatile void __iomem *addr) static inline void iounmap(volatile void __iomem *addr)
{ {
} }
#define virt_to_bus virt_to_phys
#define bus_to_virt phys_to_virt
#endif /* CONFIG_MMU */ #endif /* CONFIG_MMU */
/* /*

View File

@ -152,6 +152,7 @@ struct thread_struct {
/* Clearing a0 terminates the backtrace. */ /* Clearing a0 terminates the backtrace. */
#define start_thread(regs, new_pc, new_sp) \ #define start_thread(regs, new_pc, new_sp) \
memset(regs, 0, sizeof(*regs)); \
regs->pc = new_pc; \ regs->pc = new_pc; \
regs->ps = USER_PS_VALUE; \ regs->ps = USER_PS_VALUE; \
regs->areg[1] = new_sp; \ regs->areg[1] = new_sp; \
@ -168,9 +169,6 @@ struct mm_struct;
/* Free all resources held by a thread. */ /* Free all resources held by a thread. */
#define release_thread(thread) do { } while(0) #define release_thread(thread) do { } while(0)
/* Create a kernel thread without removing it from tasklists */
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
/* Copy and release all segment info associated with a VM */ /* Copy and release all segment info associated with a VM */
#define copy_segments(p, mm) do { } while(0) #define copy_segments(p, mm) do { } while(0)
#define release_segments(mm) do { } while(0) #define release_segments(mm) do { } while(0)

View File

@ -10,7 +10,7 @@
struct pt_regs; struct pt_regs;
struct sigaction; struct sigaction;
asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*); asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*);
asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*); asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
asmlinkage long xtensa_ptrace(long, long, long, long); asmlinkage long xtensa_ptrace(long, long, long, long);
asmlinkage long xtensa_sigreturn(struct pt_regs*); asmlinkage long xtensa_sigreturn(struct pt_regs*);

View File

@ -1,16 +1,9 @@
/* #ifndef _XTENSA_UNISTD_H
* include/asm-xtensa/unistd.h #define _XTENSA_UNISTD_H
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2001 - 2005 Tensilica Inc.
*/
#define __ARCH_WANT_SYS_EXECVE
#include <uapi/asm/unistd.h> #include <uapi/asm/unistd.h>
/* /*
* "Conditional" syscalls * "Conditional" syscalls
* *
@ -37,3 +30,5 @@
#define __IGNORE_mmap /* use mmap2 */ #define __IGNORE_mmap /* use mmap2 */
#define __IGNORE_vfork /* use clone */ #define __IGNORE_vfork /* use clone */
#define __IGNORE_fadvise64 /* use fadvise64_64 */ #define __IGNORE_fadvise64 /* use fadvise64_64 */
#endif /* _XTENSA_UNISTD_H */

View File

@ -1,14 +1,4 @@
/* #if !defined(_UAPI_XTENSA_UNISTD_H) || defined(__SYSCALL)
* include/asm-xtensa/unistd.h
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2001 - 2012 Tensilica Inc.
*/
#ifndef _UAPI_XTENSA_UNISTD_H
#define _UAPI_XTENSA_UNISTD_H #define _UAPI_XTENSA_UNISTD_H
#ifndef __SYSCALL #ifndef __SYSCALL
@ -272,7 +262,7 @@ __SYSCALL(115, sys_sendmmsg, 4)
#define __NR_clone 116 #define __NR_clone 116
__SYSCALL(116, xtensa_clone, 5) __SYSCALL(116, xtensa_clone, 5)
#define __NR_execve 117 #define __NR_execve 117
__SYSCALL(117, xtensa_execve, 3) __SYSCALL(117, sys_execve, 3)
#define __NR_exit 118 #define __NR_exit 118
__SYSCALL(118, sys_exit, 1) __SYSCALL(118, sys_exit, 1)
#define __NR_exit_group 119 #define __NR_exit_group 119
@ -759,4 +749,6 @@ __SYSCALL(331, sys_kcmp, 5)
#define SYS_XTENSA_COUNT 5 /* count */ #define SYS_XTENSA_COUNT 5 /* count */
#undef __SYSCALL
#endif /* _UAPI_XTENSA_UNISTD_H */ #endif /* _UAPI_XTENSA_UNISTD_H */

View File

@ -1832,50 +1832,6 @@ ENTRY(system_call)
retw retw
/*
* Create a kernel thread
*
* int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
* a2 a2 a3 a4
*/
ENTRY(kernel_thread)
entry a1, 16
mov a5, a2 # preserve fn over syscall
mov a7, a3 # preserve args over syscall
movi a3, _CLONE_VM | _CLONE_UNTRACED
movi a2, __NR_clone
or a6, a4, a3 # arg0: flags
mov a3, a1 # arg1: sp
syscall
beq a3, a1, 1f # branch if parent
mov a6, a7 # args
callx4 a5 # fn(args)
movi a2, __NR_exit
syscall # return value of fn(args) still in a6
1: retw
/*
* Do a system call from kernel instead of calling sys_execve, so we end up
* with proper pt_regs.
*
* int kernel_execve(const char *fname, char *const argv[], charg *const envp[])
* a2 a2 a3 a4
*/
ENTRY(kernel_execve)
entry a1, 16
mov a6, a2 # arg0 is in a6
movi a2, __NR_execve
syscall
retw
/* /*
* Task switch. * Task switch.
* *
@ -1958,3 +1914,16 @@ ENTRY(ret_from_fork)
j common_exception_return j common_exception_return
/*
* Kernel thread creation helper
* On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg
* left from _switch_to: a6 = prev
*/
ENTRY(ret_from_kernel_thread)
call4 schedule_tail
mov a6, a3
callx4 a2
j common_exception_return
ENDPROC(ret_from_kernel_thread)

View File

@ -45,6 +45,7 @@
#include <asm/regs.h> #include <asm/regs.h>
extern void ret_from_fork(void); extern void ret_from_fork(void);
extern void ret_from_kernel_thread(void);
struct task_struct *current_set[NR_CPUS] = {&init_task, }; struct task_struct *current_set[NR_CPUS] = {&init_task, };
@ -158,18 +159,30 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
/* /*
* Copy thread. * Copy thread.
* *
* There are two modes in which this function is called:
* 1) Userspace thread creation,
* regs != NULL, usp_thread_fn is userspace stack pointer.
* It is expected to copy parent regs (in case CLONE_VM is not set
* in the clone_flags) and set up passed usp in the childregs.
* 2) Kernel thread creation,
* regs == NULL, usp_thread_fn is the function to run in the new thread
* and thread_fn_arg is its parameter.
* childregs are not used for the kernel threads.
*
* The stack layout for the new thread looks like this: * The stack layout for the new thread looks like this:
* *
* +------------------------+ <- sp in childregs (= tos) * +------------------------+
* | childregs | * | childregs |
* +------------------------+ <- thread.sp = sp in dummy-frame * +------------------------+ <- thread.sp = sp in dummy-frame
* | dummy-frame | (saved in dummy-frame spill-area) * | dummy-frame | (saved in dummy-frame spill-area)
* +------------------------+ * +------------------------+
* *
* We create a dummy frame to return to ret_from_fork: * We create a dummy frame to return to either ret_from_fork or
* a0 points to ret_from_fork (simulating a call4) * ret_from_kernel_thread:
* a0 points to ret_from_fork/ret_from_kernel_thread (simulating a call4)
* sp points to itself (thread.sp) * sp points to itself (thread.sp)
* a2, a3 are unused. * a2, a3 are unused for userspace threads,
* a2 points to thread_fn, a3 holds thread_fn arg for kernel threads.
* *
* Note: This is a pristine frame, so we don't need any spill region on top of * Note: This is a pristine frame, so we don't need any spill region on top of
* childregs. * childregs.
@ -185,43 +198,63 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
* involved. Much simpler to just not copy those live frames across. * involved. Much simpler to just not copy those live frames across.
*/ */
int copy_thread(unsigned long clone_flags, unsigned long usp, int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
unsigned long unused, unsigned long thread_fn_arg,
struct task_struct * p, struct pt_regs * regs) struct task_struct *p, struct pt_regs *unused)
{ {
struct pt_regs *childregs; struct pt_regs *childregs = task_pt_regs(p);
unsigned long tos;
int user_mode = user_mode(regs);
#if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
struct thread_info *ti; struct thread_info *ti;
#endif #endif
/* Set up new TSS. */
tos = (unsigned long)task_stack_page(p) + THREAD_SIZE;
if (user_mode)
childregs = (struct pt_regs*)(tos - PT_USER_SIZE);
else
childregs = (struct pt_regs*)tos - 1;
/* This does not copy all the regs. In a bout of brilliance or madness,
ARs beyond a0-a15 exist past the end of the struct. */
*childregs = *regs;
/* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */ /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */
*((int*)childregs - 3) = (unsigned long)childregs; *((int*)childregs - 3) = (unsigned long)childregs;
*((int*)childregs - 4) = 0; *((int*)childregs - 4) = 0;
childregs->areg[2] = 0;
p->set_child_tid = p->clear_child_tid = NULL;
p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1);
p->thread.sp = (unsigned long)childregs; p->thread.sp = (unsigned long)childregs;
if (user_mode(regs)) { if (!(p->flags & PF_KTHREAD)) {
struct pt_regs *regs = current_pt_regs();
unsigned long usp = usp_thread_fn ?
usp_thread_fn : regs->areg[1];
p->thread.ra = MAKE_RA_FOR_CALL(
(unsigned long)ret_from_fork, 0x1);
/* This does not copy all the regs.
* In a bout of brilliance or madness,
* ARs beyond a0-a15 exist past the end of the struct.
*/
*childregs = *regs;
childregs->areg[1] = usp; childregs->areg[1] = usp;
childregs->areg[2] = 0;
/* When sharing memory with the parent thread, the child
usually starts on a pristine stack, so we have to reset
windowbase, windowstart and wmask.
(Note that such a new thread is required to always create
an initial call4 frame)
The exception is vfork, where the new thread continues to
run on the parent's stack until it calls execve. This could
be a call8 or call12, which requires a legal stack frame
of the previous caller for the overflow handlers to work.
(Note that it's always legal to overflow live registers).
In this case, ensure to spill at least the stack pointer
of that frame. */
if (clone_flags & CLONE_VM) { if (clone_flags & CLONE_VM) {
childregs->wmask = 1; /* can't share live windows */ /* check that caller window is live and same stack */
int len = childregs->wmask & ~0xf;
if (regs->areg[1] == usp && len != 0) {
int callinc = (regs->areg[0] >> 30) & 3;
int caller_ars = XCHAL_NUM_AREGS - callinc * 4;
put_user(regs->areg[caller_ars+1],
(unsigned __user*)(usp - 12));
}
childregs->wmask = 1;
childregs->windowstart = 1;
childregs->windowbase = 0;
} else { } else {
int len = childregs->wmask & ~0xf; int len = childregs->wmask & ~0xf;
memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4], memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
@ -230,11 +263,19 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
// FIXME: we need to set THREADPTR in thread_info... // FIXME: we need to set THREADPTR in thread_info...
if (clone_flags & CLONE_SETTLS) if (clone_flags & CLONE_SETTLS)
childregs->areg[2] = childregs->areg[6]; childregs->areg[2] = childregs->areg[6];
} else { } else {
/* In kernel space, we start a new thread with a new stack. */ p->thread.ra = MAKE_RA_FOR_CALL(
childregs->wmask = 1; (unsigned long)ret_from_kernel_thread, 1);
childregs->areg[1] = tos;
/* pass parameters to ret_from_kernel_thread:
* a2 = thread_fn, a3 = thread_fn arg
*/
*((int *)childregs - 1) = thread_fn_arg;
*((int *)childregs - 2) = usp_thread_fn;
/* Childregs are only used when we're going to userspace
* in which case start_thread will set them up.
*/
} }
#if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
@ -330,32 +371,5 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
void __user *child_tid, long a5, void __user *child_tid, long a5,
struct pt_regs *regs) struct pt_regs *regs)
{ {
if (!newsp)
newsp = regs->areg[1];
return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
} }
/*
* xtensa_execve() executes a new program.
*/
asmlinkage
long xtensa_execve(const char __user *name,
const char __user *const __user *argv,
const char __user *const __user *envp,
long a3, long a4, long a5,
struct pt_regs *regs)
{
long error;
struct filename *filename;
filename = getname(name);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename->name, argv, envp, regs);
putname(filename);
out:
return error;
}

View File

@ -32,10 +32,8 @@ typedef void (*syscall_t)(void);
syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= { syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
[0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall, [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall,
#undef __SYSCALL
#define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol, #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol,
#undef __KERNEL_SYSCALLS__ #include <uapi/asm/unistd.h>
#include <asm/unistd.h>
}; };
asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
@ -49,7 +47,8 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
return (long)ret; return (long)ret;
} }
asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len) asmlinkage long xtensa_fadvise64_64(int fd, int advice,
unsigned long long offset, unsigned long long len)
{ {
return sys_fadvise64_64(fd, offset, len, advice); return sys_fadvise64_64(fd, offset, len, advice);
} }

View File

@ -43,7 +43,6 @@ EXPORT_SYMBOL(__strncpy_user);
EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(clear_page);
EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(copy_page);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(empty_zero_page);
/* /*

View File

@ -89,7 +89,7 @@ config BLK_DEV_INTEGRITY
config BLK_DEV_THROTTLING config BLK_DEV_THROTTLING
bool "Block layer bio throttling support" bool "Block layer bio throttling support"
depends on BLK_CGROUP=y && EXPERIMENTAL depends on BLK_CGROUP=y
default n default n
---help--- ---help---
Block layer bio throttling support. It can be used to limit Block layer bio throttling support. It can be used to limit

View File

@ -285,6 +285,13 @@ static void blkg_destroy_all(struct request_queue *q)
blkg_destroy(blkg); blkg_destroy(blkg);
spin_unlock(&blkcg->lock); spin_unlock(&blkcg->lock);
} }
/*
* root blkg is destroyed. Just clear the pointer since
* root_rl does not take reference on root blkg.
*/
q->root_blkg = NULL;
q->root_rl.blkg = NULL;
} }
static void blkg_rcu_free(struct rcu_head *rcu_head) static void blkg_rcu_free(struct rcu_head *rcu_head)
@ -326,6 +333,9 @@ struct request_list *__blk_queue_next_rl(struct request_list *rl,
*/ */
if (rl == &q->root_rl) { if (rl == &q->root_rl) {
ent = &q->blkg_list; ent = &q->blkg_list;
/* There are no more block groups, hence no request lists */
if (list_empty(ent))
return NULL;
} else { } else {
blkg = container_of(rl, struct blkcg_gq, rl); blkg = container_of(rl, struct blkcg_gq, rl);
ent = &blkg->q_node; ent = &blkg->q_node;

View File

@ -2868,7 +2868,8 @@ static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b)
struct request *rqa = container_of(a, struct request, queuelist); struct request *rqa = container_of(a, struct request, queuelist);
struct request *rqb = container_of(b, struct request, queuelist); struct request *rqb = container_of(b, struct request, queuelist);
return !(rqa->q <= rqb->q); return !(rqa->q < rqb->q ||
(rqa->q == rqb->q && blk_rq_pos(rqa) < blk_rq_pos(rqb)));
} }
/* /*

View File

@ -1345,12 +1345,15 @@ static int
acpi_video_bus_get_devices(struct acpi_video_bus *video, acpi_video_bus_get_devices(struct acpi_video_bus *video,
struct acpi_device *device) struct acpi_device *device)
{ {
int status; int status = 0;
struct acpi_device *dev; struct acpi_device *dev;
status = acpi_video_device_enumerate(video); /*
if (status) * There are systems where video module known to work fine regardless
return status; * 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) { list_for_each_entry(dev, &device->children, node) {

View File

@ -131,6 +131,7 @@ config BLK_CPQ_DA
config BLK_CPQ_CISS_DA config BLK_CPQ_CISS_DA
tristate "Compaq Smart Array 5xxx support" tristate "Compaq Smart Array 5xxx support"
depends on PCI depends on PCI
select CHECK_SIGNATURE
help help
This is the driver for Compaq Smart Array 5xxx controllers. This is the driver for Compaq Smart Array 5xxx controllers.
Everyone using these boards should say Y here. Everyone using these boards should say Y here.
@ -166,8 +167,8 @@ config BLK_DEV_DAC960
module will be called DAC960. module will be called DAC960.
config BLK_DEV_UMEM config BLK_DEV_UMEM
tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)" tristate "Micro Memory MM5415 Battery Backed RAM support"
depends on PCI && EXPERIMENTAL depends on PCI
---help--- ---help---
Saying Y here will include support for the MM5415 family of Saying Y here will include support for the MM5415 family of
battery backed (Non-volatile) RAM cards. battery backed (Non-volatile) RAM cards.
@ -430,8 +431,8 @@ config CDROM_PKTCDVD_BUFFERS
a disc is opened for writing. a disc is opened for writing.
config CDROM_PKTCDVD_WCACHE config CDROM_PKTCDVD_WCACHE
bool "Enable write caching (EXPERIMENTAL)" bool "Enable write caching"
depends on CDROM_PKTCDVD && EXPERIMENTAL depends on CDROM_PKTCDVD
help help
If enabled, write caching will be set for the CD-R/W device. For now If enabled, write caching will be set for the CD-R/W device. For now
this option is dangerous unless the CD-RW media is known good, as we this option is dangerous unless the CD-RW media is known good, as we
@ -508,8 +509,8 @@ config XEN_BLKDEV_BACKEND
config VIRTIO_BLK config VIRTIO_BLK
tristate "Virtio block driver (EXPERIMENTAL)" tristate "Virtio block driver"
depends on EXPERIMENTAL && VIRTIO depends on VIRTIO
---help--- ---help---
This is the virtual block driver for virtio. It can be used with This is the virtual block driver for virtio. It can be used with
lguest or QEMU based VMMs (like KVM or Xen). Say Y or M. lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
@ -528,7 +529,7 @@ config BLK_DEV_HD
config BLK_DEV_RBD config BLK_DEV_RBD
tristate "Rados block device (RBD)" tristate "Rados block device (RBD)"
depends on INET && EXPERIMENTAL && BLOCK depends on INET && BLOCK
select CEPH_LIB select CEPH_LIB
select LIBCRC32C select LIBCRC32C
select CRYPTO_AES select CRYPTO_AES

View File

@ -5205,7 +5205,6 @@ static void cciss_shutdown(struct pci_dev *pdev)
return; return;
} }
/* write all data in the battery backed cache to disk */ /* write all data in the battery backed cache to disk */
memset(flush_buf, 0, 4);
return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf, return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf,
4, 0, CTLR_LUNID, TYPE_CMD); 4, 0, CTLR_LUNID, TYPE_CMD);
kfree(flush_buf); kfree(flush_buf);

View File

@ -4109,12 +4109,19 @@ static struct platform_driver floppy_driver = {
static struct platform_device floppy_device[N_DRIVE]; static struct platform_device floppy_device[N_DRIVE];
static bool floppy_available(int drive)
{
if (!(allowed_drive_mask & (1 << drive)))
return false;
if (fdc_state[FDC(drive)].version == FDC_NONE)
return false;
return true;
}
static struct kobject *floppy_find(dev_t dev, int *part, void *data) static struct kobject *floppy_find(dev_t dev, int *part, void *data)
{ {
int drive = (*part & 3) | ((*part & 0x80) >> 5); int drive = (*part & 3) | ((*part & 0x80) >> 5);
if (drive >= N_DRIVE || if (drive >= N_DRIVE || !floppy_available(drive))
!(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE)
return NULL; return NULL;
if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type)) if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
return NULL; return NULL;
@ -4124,8 +4131,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
static int __init do_floppy_init(void) static int __init do_floppy_init(void)
{ {
int i, unit, drive; int i, unit, drive, err;
int err, dr;
set_debugt(); set_debugt();
interruptjiffies = resultjiffies = jiffies; interruptjiffies = resultjiffies = jiffies;
@ -4137,34 +4143,32 @@ static int __init do_floppy_init(void)
raw_cmd = NULL; raw_cmd = NULL;
for (dr = 0; dr < N_DRIVE; dr++) { floppy_wq = alloc_ordered_workqueue("floppy", 0);
disks[dr] = alloc_disk(1); if (!floppy_wq)
if (!disks[dr]) { return -ENOMEM;
for (drive = 0; drive < N_DRIVE; drive++) {
disks[drive] = alloc_disk(1);
if (!disks[drive]) {
err = -ENOMEM; err = -ENOMEM;
goto out_put_disk; goto out_put_disk;
} }
floppy_wq = alloc_ordered_workqueue("floppy", 0); disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock);
if (!floppy_wq) { if (!disks[drive]->queue) {
err = -ENOMEM; err = -ENOMEM;
goto out_put_disk; goto out_put_disk;
} }
disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); blk_queue_max_hw_sectors(disks[drive]->queue, 64);
if (!disks[dr]->queue) { disks[drive]->major = FLOPPY_MAJOR;
err = -ENOMEM; disks[drive]->first_minor = TOMINOR(drive);
goto out_destroy_workq; disks[drive]->fops = &floppy_fops;
} sprintf(disks[drive]->disk_name, "fd%d", drive);
blk_queue_max_hw_sectors(disks[dr]->queue, 64); init_timer(&motor_off_timer[drive]);
disks[dr]->major = FLOPPY_MAJOR; motor_off_timer[drive].data = drive;
disks[dr]->first_minor = TOMINOR(dr); motor_off_timer[drive].function = motor_off_callback;
disks[dr]->fops = &floppy_fops;
sprintf(disks[dr]->disk_name, "fd%d", dr);
init_timer(&motor_off_timer[dr]);
motor_off_timer[dr].data = dr;
motor_off_timer[dr].function = motor_off_callback;
} }
err = register_blkdev(FLOPPY_MAJOR, "fd"); err = register_blkdev(FLOPPY_MAJOR, "fd");
@ -4282,9 +4286,7 @@ static int __init do_floppy_init(void)
} }
for (drive = 0; drive < N_DRIVE; drive++) { for (drive = 0; drive < N_DRIVE; drive++) {
if (!(allowed_drive_mask & (1 << drive))) if (!floppy_available(drive))
continue;
if (fdc_state[FDC(drive)].version == FDC_NONE)
continue; continue;
floppy_device[drive].name = floppy_device_name; floppy_device[drive].name = floppy_device_name;
@ -4293,7 +4295,7 @@ static int __init do_floppy_init(void)
err = platform_device_register(&floppy_device[drive]); err = platform_device_register(&floppy_device[drive]);
if (err) if (err)
goto out_release_dma; goto out_remove_drives;
err = device_create_file(&floppy_device[drive].dev, err = device_create_file(&floppy_device[drive].dev,
&dev_attr_cmos); &dev_attr_cmos);
@ -4311,29 +4313,34 @@ static int __init do_floppy_init(void)
out_unreg_platform_dev: out_unreg_platform_dev:
platform_device_unregister(&floppy_device[drive]); platform_device_unregister(&floppy_device[drive]);
out_remove_drives:
while (drive--) {
if (floppy_available(drive)) {
del_gendisk(disks[drive]);
device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
platform_device_unregister(&floppy_device[drive]);
}
}
out_release_dma: out_release_dma:
if (atomic_read(&usage_count)) if (atomic_read(&usage_count))
floppy_release_irq_and_dma(); floppy_release_irq_and_dma();
out_unreg_region: out_unreg_region:
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
platform_driver_unregister(&floppy_driver); platform_driver_unregister(&floppy_driver);
out_destroy_workq:
destroy_workqueue(floppy_wq);
out_unreg_blkdev: out_unreg_blkdev:
unregister_blkdev(FLOPPY_MAJOR, "fd"); unregister_blkdev(FLOPPY_MAJOR, "fd");
out_put_disk: out_put_disk:
while (dr--) { for (drive = 0; drive < N_DRIVE; drive++) {
del_timer_sync(&motor_off_timer[dr]); if (!disks[drive])
if (disks[dr]->queue) { break;
blk_cleanup_queue(disks[dr]->queue); if (disks[drive]->queue) {
/* del_timer_sync(&motor_off_timer[drive]);
* put_disk() is not paired with add_disk() and blk_cleanup_queue(disks[drive]->queue);
* will put queue reference one extra time. fix it. disks[drive]->queue = NULL;
*/
disks[dr]->queue = NULL;
} }
put_disk(disks[dr]); put_disk(disks[drive]);
} }
destroy_workqueue(floppy_wq);
return err; return err;
} }
@ -4551,8 +4558,7 @@ static void __exit floppy_module_exit(void)
for (drive = 0; drive < N_DRIVE; drive++) { for (drive = 0; drive < N_DRIVE; drive++) {
del_timer_sync(&motor_off_timer[drive]); del_timer_sync(&motor_off_timer[drive]);
if ((allowed_drive_mask & (1 << drive)) && if (floppy_available(drive)) {
fdc_state[FDC(drive)].version != FDC_NONE) {
del_gendisk(disks[drive]); del_gendisk(disks[drive]);
device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
platform_device_unregister(&floppy_device[drive]); platform_device_unregister(&floppy_device[drive]);

View File

@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo)
if (lo->lo_state != Lo_bound) if (lo->lo_state != Lo_bound)
return -ENXIO; return -ENXIO;
if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */ /*
return -EBUSY; * If we've explicitly asked to tear down the loop device,
* and it has an elevated reference count, set it for auto-teardown when
* the last reference goes away. This stops $!~#$@ udev from
* preventing teardown because it decided that it needs to run blkid on
* the loopback device whenever they appear. xfstests is notorious for
* failing tests because blkid via udev races with a losetup
* <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
* command to fail with EBUSY.
*/
if (lo->lo_refcnt > 1) {
lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
mutex_unlock(&lo->lo_ctl_mutex);
return 0;
}
if (filp == NULL) if (filp == NULL)
return -EINVAL; return -EINVAL;

View File

@ -2035,8 +2035,9 @@ static unsigned int implicit_sector(unsigned char command,
} }
return rv; return rv;
} }
static void mtip_set_timeout(struct driver_data *dd,
static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout) struct host_to_dev_fis *fis,
unsigned int *timeout, u8 erasemode)
{ {
switch (fis->command) { switch (fis->command) {
case ATA_CMD_DOWNLOAD_MICRO: case ATA_CMD_DOWNLOAD_MICRO:
@ -2044,7 +2045,10 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
break; break;
case ATA_CMD_SEC_ERASE_UNIT: case ATA_CMD_SEC_ERASE_UNIT:
case 0xFC: case 0xFC:
*timeout = 240000; /* 4 minutes */ if (erasemode)
*timeout = ((*(dd->port->identify + 90) * 2) * 60000);
else
*timeout = ((*(dd->port->identify + 89) * 2) * 60000);
break; break;
case ATA_CMD_STANDBYNOW1: case ATA_CMD_STANDBYNOW1:
*timeout = 120000; /* 2 minutes */ *timeout = 120000; /* 2 minutes */
@ -2087,6 +2091,7 @@ static int exec_drive_taskfile(struct driver_data *dd,
unsigned int transfer_size; unsigned int transfer_size;
unsigned long task_file_data; unsigned long task_file_data;
int intotal = outtotal + req_task->out_size; int intotal = outtotal + req_task->out_size;
int erasemode = 0;
taskout = req_task->out_size; taskout = req_task->out_size;
taskin = req_task->in_size; taskin = req_task->in_size;
@ -2212,7 +2217,13 @@ static int exec_drive_taskfile(struct driver_data *dd,
fis.lba_hi, fis.lba_hi,
fis.device); fis.device);
mtip_set_timeout(&fis, &timeout); /* check for erase mode support during secure erase.*/
if ((fis.command == ATA_CMD_SEC_ERASE_UNIT)
&& (outbuf[0] & MTIP_SEC_ERASE_MODE)) {
erasemode = 1;
}
mtip_set_timeout(dd, &fis, &timeout, erasemode);
/* Determine the correct transfer size.*/ /* Determine the correct transfer size.*/
if (force_single_sector) if (force_single_sector)

View File

@ -33,6 +33,9 @@
/* offset of Device Control register in PCIe extended capabilites space */ /* offset of Device Control register in PCIe extended capabilites space */
#define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48 #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48
/* check for erase mode support during secure erase */
#define MTIP_SEC_ERASE_MODE 0x3
/* # of times to retry timed out/failed IOs */ /* # of times to retry timed out/failed IOs */
#define MTIP_MAX_RETRIES 2 #define MTIP_MAX_RETRIES 2

View File

@ -158,8 +158,8 @@ struct xen_vbd {
struct block_device *bdev; struct block_device *bdev;
/* Cached size parameter. */ /* Cached size parameter. */
sector_t size; sector_t size;
bool flush_support; unsigned int flush_support:1;
bool discard_secure; unsigned int discard_secure:1;
}; };
struct backend_info; struct backend_info;

View File

@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
{ {
struct xen_blkif *blkif; struct xen_blkif *blkif;
blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL); blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL);
if (!blkif) if (!blkif)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
memset(blkif, 0, sizeof(*blkif));
blkif->domid = domid; blkif->domid = domid;
spin_lock_init(&blkif->blk_ring_lock); spin_lock_init(&blkif->blk_ring_lock);
atomic_set(&blkif->refcnt, 1); atomic_set(&blkif->refcnt, 1);
@ -196,7 +195,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)
} }
} }
void xen_blkif_free(struct xen_blkif *blkif) static void xen_blkif_free(struct xen_blkif *blkif)
{ {
if (!atomic_dec_and_test(&blkif->refcnt)) if (!atomic_dec_and_test(&blkif->refcnt))
BUG(); BUG();
@ -257,7 +256,7 @@ static struct attribute_group xen_vbdstat_group = {
VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor); VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
VBD_SHOW(mode, "%s\n", be->mode); VBD_SHOW(mode, "%s\n", be->mode);
int xenvbd_sysfs_addif(struct xenbus_device *dev) static int xenvbd_sysfs_addif(struct xenbus_device *dev)
{ {
int error; int error;
@ -281,7 +280,7 @@ fail1: device_remove_file(&dev->dev, &dev_attr_physical_device);
return error; return error;
} }
void xenvbd_sysfs_delif(struct xenbus_device *dev) static void xenvbd_sysfs_delif(struct xenbus_device *dev)
{ {
sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group); sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group);
device_remove_file(&dev->dev, &dev_attr_mode); device_remove_file(&dev->dev, &dev_attr_mode);

View File

@ -5,7 +5,7 @@
* http://www.gnu.org/licenses/gpl.html * http://www.gnu.org/licenses/gpl.html
* *
* Maintainer: * 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. * Based on the powernow-k7.c module written by Dave Jones.
* (C) 2003 Dave Jones on behalf of SuSE Labs * (C) 2003 Dave Jones on behalf of SuSE Labs

View File

@ -153,7 +153,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
} }
chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers; chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL); chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL);
if (!chip->buffer) { if (!chip->buffer) {
ret = -ENOMEM; ret = -ENOMEM;
goto exit_destroy; goto exit_destroy;

View File

@ -244,6 +244,8 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
if (ret) if (ret)
return ret; return ret;
mvebu_gpio_set(chip, pin, value);
spin_lock_irqsave(&mvchip->lock, flags); spin_lock_irqsave(&mvchip->lock, flags);
u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)); u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
u &= ~(1 << pin); u &= ~(1 << pin);
@ -644,7 +646,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
ct->handler = handle_edge_irq; ct->handler = handle_edge_irq;
ct->chip.name = mvchip->chip.label; ct->chip.name = mvchip->chip.label;
irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE, irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,
IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
/* Setup irq domain on top of the generic chip. */ /* Setup irq domain on top of the generic chip. */

View File

@ -251,6 +251,40 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
} }
} }
/**
* _clear_gpio_debounce - clear debounce settings for a gpio
* @bank: the gpio bank we're acting upon
* @gpio: the gpio number on this @gpio
*
* If a gpio is using debounce, then clear the debounce enable bit and if
* this is the only gpio in this bank using debounce, then clear the debounce
* time too. The debounce clock will also be disabled when calling this function
* if this is the only gpio in the bank using debounce.
*/
static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
{
u32 gpio_bit = GPIO_BIT(bank, gpio);
if (!bank->dbck_flag)
return;
if (!(bank->dbck_enable_mask & gpio_bit))
return;
bank->dbck_enable_mask &= ~gpio_bit;
bank->context.debounce_en &= ~gpio_bit;
__raw_writel(bank->context.debounce_en,
bank->base + bank->regs->debounce_en);
if (!bank->dbck_enable_mask) {
bank->context.debounce = 0;
__raw_writel(bank->context.debounce, bank->base +
bank->regs->debounce);
clk_disable(bank->dbck);
bank->dbck_enabled = false;
}
}
static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio, static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
unsigned trigger) unsigned trigger)
{ {
@ -539,6 +573,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
_set_gpio_irqenable(bank, gpio, 0); _set_gpio_irqenable(bank, gpio, 0);
_clear_gpio_irqstatus(bank, gpio); _clear_gpio_irqstatus(bank, gpio);
_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
_clear_gpio_debounce(bank, gpio);
} }
/* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */

View File

@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tgpio->lock, flags); spin_lock_irqsave(&tgpio->lock, flags);
tgpio->last_ier &= ~(1 << offset); tgpio->last_ier &= ~(1UL << offset);
iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
spin_unlock_irqrestore(&tgpio->lock, flags); spin_unlock_irqrestore(&tgpio->lock, flags);
} }
@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&tgpio->lock, flags); spin_lock_irqsave(&tgpio->lock, flags);
tgpio->last_ier |= 1 << offset; tgpio->last_ier |= 1UL << offset;
iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
spin_unlock_irqrestore(&tgpio->lock, flags); spin_unlock_irqrestore(&tgpio->lock, flags);
} }

View File

@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class,
*/ */
status = gpio_request(gpio, "sysfs"); status = gpio_request(gpio, "sysfs");
if (status < 0) if (status < 0) {
if (status == -EPROBE_DEFER)
status = -ENODEV;
goto done; goto done;
}
status = gpio_export(gpio, true); status = gpio_export(gpio, true);
if (status < 0) if (status < 0)
gpio_free(gpio); gpio_free(gpio);
@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label)
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
if (!gpio_is_valid(gpio)) if (!gpio_is_valid(gpio)) {
status = -EINVAL;
goto done; goto done;
}
desc = &gpio_desc[gpio]; desc = &gpio_desc[gpio];
chip = desc->chip; chip = desc->chip;
if (chip == NULL) if (chip == NULL)

View File

@ -1,6 +1,6 @@
config DRM_EXYNOS config DRM_EXYNOS
tristate "DRM Support for Samsung SoC EXYNOS Series" 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 DRM_KMS_HELPER
select FB_CFB_FILLRECT select FB_CFB_FILLRECT
select FB_CFB_COPYAREA select FB_CFB_COPYAREA

View File

@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
exynos_connector->encoder_id = encoder->base.id; exynos_connector->encoder_id = encoder->base.id;
exynos_connector->manager = manager; exynos_connector->manager = manager;
exynos_connector->dpms = DRM_MODE_DPMS_OFF; exynos_connector->dpms = DRM_MODE_DPMS_OFF;
connector->dpms = DRM_MODE_DPMS_OFF;
connector->encoder = encoder; connector->encoder = encoder;
err = drm_mode_connector_attach_encoder(connector, encoder); err = drm_mode_connector_attach_encoder(connector, encoder);

View File

@ -43,12 +43,14 @@
* @manager: specific encoder has its own manager to control a hardware * @manager: specific encoder has its own manager to control a hardware
* appropriately and we can access a hardware drawing on this manager. * appropriately and we can access a hardware drawing on this manager.
* @dpms: store the encoder dpms value. * @dpms: store the encoder dpms value.
* @updated: indicate whether overlay data updating is needed or not.
*/ */
struct exynos_drm_encoder { struct exynos_drm_encoder {
struct drm_crtc *old_crtc; struct drm_crtc *old_crtc;
struct drm_encoder drm_encoder; struct drm_encoder drm_encoder;
struct exynos_drm_manager *manager; struct exynos_drm_manager *manager;
int dpms; int dpms;
bool updated;
}; };
static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode) 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) { switch (mode) {
case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_ON:
if (manager_ops && manager_ops->apply) 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_drm_connector_power(encoder, mode);
exynos_encoder->dpms = mode; exynos_encoder->dpms = mode;
break; break;
@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
case DRM_MODE_DPMS_OFF: case DRM_MODE_DPMS_OFF:
exynos_drm_connector_power(encoder, mode); exynos_drm_connector_power(encoder, mode);
exynos_encoder->dpms = mode; exynos_encoder->dpms = mode;
exynos_encoder->updated = false;
break; break;
default: default:
DRM_ERROR("unspecified mode %d\n", mode); 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) 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; struct exynos_drm_manager_ops *manager_ops = manager->ops;
DRM_DEBUG_KMS("%s\n", __FILE__); DRM_DEBUG_KMS("%s\n", __FILE__);
if (manager_ops && manager_ops->commit) if (manager_ops && manager_ops->commit)
manager_ops->commit(manager->dev); 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) 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) if (manager_ops && manager_ops->dpms)
manager_ops->dpms(manager->dev, mode); 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 * if this condition is ok then it means that the crtc is already
* detached from encoder and last function for detaching is properly * detached from encoder and last function for detaching is properly

View File

@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)
const struct of_device_id *match; const struct of_device_id *match;
match = of_match_node(of_match_ptr(mixer_match_types), match = of_match_node(of_match_ptr(mixer_match_types),
pdev->dev.of_node); pdev->dev.of_node);
drv = match->data; drv = (struct mixer_drv_data *)match->data;
} else { } else {
drv = (struct mixer_drv_data *) drv = (struct mixer_drv_data *)
platform_get_device_id(pdev)->driver_data; platform_get_device_id(pdev)->driver_data;

View File

@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
goto put_gmch; 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); pci_set_master(dev->pdev);

View File

@ -729,7 +729,7 @@ void intel_crt_init(struct drm_device *dev)
crt->base.type = INTEL_OUTPUT_ANALOG; crt->base.type = INTEL_OUTPUT_ANALOG;
crt->base.cloneable = true; crt->base.cloneable = true;
if (IS_HASWELL(dev)) if (IS_HASWELL(dev) || IS_I830(dev))
crt->base.crtc_mask = (1 << 0); crt->base.crtc_mask = (1 << 0);
else else
crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);

View File

@ -341,9 +341,17 @@ static int intel_overlay_off(struct intel_overlay *overlay)
intel_ring_emit(ring, flip_addr); intel_ring_emit(ring, flip_addr);
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
/* turn overlay off */ /* turn overlay off */
intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); if (IS_I830(dev)) {
intel_ring_emit(ring, flip_addr); /* Workaround: Don't disable the overlay fully, since otherwise
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); * 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); intel_ring_advance(ring);
return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail); return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);

View File

@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev)
props.type = BACKLIGHT_RAW; props.type = BACKLIGHT_RAW;
props.max_brightness = _intel_panel_get_max_backlight(dev); props.max_brightness = _intel_panel_get_max_backlight(dev);
if (props.max_brightness == 0) { 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; return -ENODEV;
} }
dev_priv->backlight = dev_priv->backlight =

View File

@ -894,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
} }
#endif #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) static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
{ {
struct dip_infoframe avi_if = { 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, .ver = DIP_VERSION_AVI,
.len = DIP_LEN_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)]; 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); 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; sdvo_data[3] = avi_if.checksum;
memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
if (!intel_sdvo_set_value(intel_sdvo, return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
SDVO_CMD_SET_HBUF_INDEX, SDVO_HBUF_TX_VSYNC,
set_buf_index, 2)) sdvo_data, sizeof(sdvo_data));
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);
} }
static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)

View File

@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {
#define SDVO_CMD_SET_AUDIO_STAT 0x91 #define SDVO_CMD_SET_AUDIO_STAT 0x91
#define SDVO_CMD_GET_AUDIO_STAT 0x92 #define SDVO_CMD_GET_AUDIO_STAT 0x92
#define SDVO_CMD_SET_HBUF_INDEX 0x93 #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_INDEX 0x94
#define SDVO_CMD_GET_HBUF_INFO 0x95 #define SDVO_CMD_GET_HBUF_INFO 0x95
#define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 #define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96

View File

@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
node = kzalloc(sizeof(*node), GFP_KERNEL); node = kzalloc(sizeof(*node), GFP_KERNEL);
if (!node) if (!node)
return -ENOMEM; return -ENOMEM;
node->offset = roundup(offset, mm->block_size);
node->length = rounddown(offset + length, mm->block_size) - node->offset; if (length) {
node->offset = roundup(offset, mm->block_size);
node->length = rounddown(offset + length, mm->block_size);
node->length -= node->offset;
}
list_add_tail(&node->nl_entry, &mm->nodes); list_add_tail(&node->nl_entry, &mm->nodes);
list_add_tail(&node->fl_entry, &mm->free); list_add_tail(&node->fl_entry, &mm->free);
mm->heap_nodes++; mm->heap_nodes++;
mm->heap_size += length;
return 0; return 0;
} }

View File

@ -19,7 +19,6 @@ struct nouveau_mm {
u32 block_size; u32 block_size;
int heap_nodes; int heap_nodes;
u32 heap_size;
}; };
int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);

View File

@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
((priv->base.ram.size & 0x000000ff) << 32); ((priv->base.ram.size & 0x000000ff) << 32);
tags = nv_rd32(priv, 0x100320); tags = nv_rd32(priv, 0x100320);
if (tags) { ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); if (ret)
if (ret) return ret;
return ret;
nv_debug(priv, "%d compression tags\n", tags); nv_debug(priv, "%d compression tags\n", tags);
}
size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail; size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
switch (device->chipset) { switch (device->chipset) {

View File

@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
case DCB_I2C_NVIO_BIT: case DCB_I2C_NVIO_BIT:
port->drive = info.drive & 0x0f; port->drive = info.drive & 0x0f;
if (device->card_type < NV_D0) { if (device->card_type < NV_D0) {
if (info.drive >= ARRAY_SIZE(nv50_i2c_port)) if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
break; break;
port->drive = nv50_i2c_port[port->drive]; port->drive = nv50_i2c_port[port->drive];
port->sense = port->drive; port->sense = port->drive;

View File

@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)
struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_disp *pdisp = nouveau_disp(drm->device); struct nouveau_disp *pdisp = nouveau_disp(drm->device);
struct nouveau_display *disp; struct nouveau_display *disp;
u32 pclass = dev->pdev->class >> 8;
int ret, gen; int ret, gen;
disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev)
drm_kms_helper_poll_init(dev); drm_kms_helper_poll_init(dev);
drm_kms_helper_poll_disable(dev); drm_kms_helper_poll_disable(dev);
if (nv_device(drm->device)->card_type < NV_50) if (nouveau_modeset == 1 ||
ret = nv04_display_create(dev); (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) {
else if (nv_device(drm->device)->card_type < NV_50)
if (nv_device(drm->device)->card_type < NV_D0) ret = nv04_display_create(dev);
ret = nv50_display_create(dev); else
else if (nv_device(drm->device)->card_type < NV_D0)
ret = nvd0_display_create(dev); ret = nv50_display_create(dev);
if (ret) else
goto disp_create_err; ret = nvd0_display_create(dev);
if (dev->mode_config.num_crtc) {
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
if (ret) if (ret)
goto vblank_err; goto disp_create_err;
if (dev->mode_config.num_crtc) {
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
if (ret)
goto vblank_err;
}
nouveau_backlight_init(dev);
} }
nouveau_backlight_init(dev);
return 0; return 0;
vblank_err: vblank_err:
@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)
nouveau_backlight_exit(dev); nouveau_backlight_exit(dev);
drm_vblank_cleanup(dev); drm_vblank_cleanup(dev);
disp->dtor(dev); if (disp->dtor)
disp->dtor(dev);
drm_kms_helper_poll_fini(dev); drm_kms_helper_poll_fini(dev);
drm_mode_config_cleanup(dev); drm_mode_config_cleanup(dev);

View File

@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");
static int nouveau_noaccel = 0; static int nouveau_noaccel = 0;
module_param_named(noaccel, nouveau_noaccel, int, 0400); module_param_named(noaccel, nouveau_noaccel, int, 0400);
MODULE_PARM_DESC(modeset, "enable driver"); MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
static int nouveau_modeset = -1; "0 = disabled, 1 = enabled, 2 = headless)");
int nouveau_modeset = -1;
module_param_named(modeset, nouveau_modeset, int, 0400); module_param_named(modeset, nouveau_modeset, int, 0400);
static struct drm_driver driver; static struct drm_driver driver;
@ -363,7 +364,8 @@ nouveau_drm_unload(struct drm_device *dev)
nouveau_pm_fini(dev); nouveau_pm_fini(dev);
nouveau_display_fini(dev); if (dev->mode_config.num_crtc)
nouveau_display_fini(dev);
nouveau_display_destroy(dev); nouveau_display_destroy(dev);
nouveau_irq_fini(dev); nouveau_irq_fini(dev);
@ -403,13 +405,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
pm_state.event == PM_EVENT_PRETHAW) pm_state.event == PM_EVENT_PRETHAW)
return 0; return 0;
NV_INFO(drm, "suspending fbcon...\n"); if (dev->mode_config.num_crtc) {
nouveau_fbcon_set_suspend(dev, 1); NV_INFO(drm, "suspending fbcon...\n");
nouveau_fbcon_set_suspend(dev, 1);
NV_INFO(drm, "suspending display...\n"); NV_INFO(drm, "suspending display...\n");
ret = nouveau_display_suspend(dev); ret = nouveau_display_suspend(dev);
if (ret) if (ret)
return ret; return ret;
}
NV_INFO(drm, "evicting buffers...\n"); NV_INFO(drm, "evicting buffers...\n");
ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM); ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
@ -445,8 +449,10 @@ fail_client:
nouveau_client_init(&cli->base); nouveau_client_init(&cli->base);
} }
NV_INFO(drm, "resuming display...\n"); if (dev->mode_config.num_crtc) {
nouveau_display_resume(dev); NV_INFO(drm, "resuming display...\n");
nouveau_display_resume(dev);
}
return ret; return ret;
} }
@ -486,8 +492,10 @@ nouveau_drm_resume(struct pci_dev *pdev)
nouveau_irq_postinstall(dev); nouveau_irq_postinstall(dev);
nouveau_pm_resume(dev); nouveau_pm_resume(dev);
NV_INFO(drm, "resuming display...\n"); if (dev->mode_config.num_crtc) {
nouveau_display_resume(dev); NV_INFO(drm, "resuming display...\n");
nouveau_display_resume(dev);
}
return 0; return 0;
} }
@ -662,9 +670,7 @@ nouveau_drm_init(void)
#ifdef CONFIG_VGA_CONSOLE #ifdef CONFIG_VGA_CONSOLE
if (vgacon_text_force()) if (vgacon_text_force())
nouveau_modeset = 0; nouveau_modeset = 0;
else
#endif #endif
nouveau_modeset = 1;
} }
if (!nouveau_modeset) if (!nouveau_modeset)

View File

@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);
nv_info((cli), fmt, ##args); \ nv_info((cli), fmt, ##args); \
} while (0) } while (0)
extern int nouveau_modeset;
#endif #endif

View File

@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
nv_subdev(pmc)->intr(nv_subdev(pmc)); nv_subdev(pmc)->intr(nv_subdev(pmc));
if (device->card_type >= NV_D0) { if (dev->mode_config.num_crtc) {
if (nv_rd32(device, 0x000100) & 0x04000000) if (device->card_type >= NV_D0) {
nvd0_display_intr(dev); if (nv_rd32(device, 0x000100) & 0x04000000)
} else nvd0_display_intr(dev);
if (device->card_type >= NV_50) { } else
if (nv_rd32(device, 0x000100) & 0x04000000) if (device->card_type >= NV_50) {
nv50_display_intr(dev); if (nv_rd32(device, 0x000100) & 0x04000000)
nv50_display_intr(dev);
}
} }
return IRQ_HANDLED; return IRQ_HANDLED;

View File

@ -220,7 +220,7 @@ out:
NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode); NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);
if (blue == 0x18) { if (blue == 0x18) {
NV_INFO(drm, "Load detected on head A\n"); NV_DEBUG(drm, "Load detected on head A\n");
return connector_status_connected; return connector_status_connected;
} }
@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
if (nv17_dac_sample_load(encoder) & if (nv17_dac_sample_load(encoder) &
NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
NV_INFO(drm, "Load detected on output %c\n", NV_DEBUG(drm, "Load detected on output %c\n",
'@' + ffs(dcb->or)); '@' + ffs(dcb->or));
return connector_status_connected; return connector_status_connected;
} else { } else {
return connector_status_disconnected; return connector_status_disconnected;
@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)
helper->dpms(encoder, DRM_MODE_DPMS_ON); helper->dpms(encoder, DRM_MODE_DPMS_ON);
NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
} }
void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
return; return;
nv_encoder->last_dpms = mode; nv_encoder->last_dpms = mode;
NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n", NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
mode, nv_encoder->dcb->index); mode, nv_encoder->dcb->index);
nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
} }

View File

@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
helper->dpms(encoder, DRM_MODE_DPMS_ON); helper->dpms(encoder, DRM_MODE_DPMS_ON);
NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
} }
static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
return; return;
nv_encoder->last_dpms = mode; nv_encoder->last_dpms = mode;
NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
mode, nv_encoder->dcb->index); mode, nv_encoder->dcb->index);
if (was_powersaving && is_powersaving_dpms(mode)) if (was_powersaving && is_powersaving_dpms(mode))
return; return;
@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
return; return;
nv_encoder->last_dpms = mode; nv_encoder->last_dpms = mode;
NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
mode, nv_encoder->dcb->index); mode, nv_encoder->dcb->index);
nv04_dfp_update_backlight(encoder, mode); nv04_dfp_update_backlight(encoder, mode);
nv04_dfp_update_fp_control(encoder, mode); nv04_dfp_update_fp_control(encoder, mode);

View File

@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)
struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
uint8_t crtc1A; uint8_t crtc1A;
NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n", NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
mode, nv_encoder->dcb->index); mode, nv_encoder->dcb->index);
state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK);
@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
helper->dpms(encoder, DRM_MODE_DPMS_ON); helper->dpms(encoder, DRM_MODE_DPMS_ON);
NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
'@' + ffs(nv_encoder->dcb->or));
} }
static void nv04_tv_destroy(struct drm_encoder *encoder) static void nv04_tv_destroy(struct drm_encoder *encoder)

View File

@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p,
/* macro tile width & height */ /* macro tile width & height */
palign = (8 * surf->bankw * track->npipes) * surf->mtilea; palign = (8 * surf->bankw * track->npipes) * surf->mtilea;
halign = (8 * surf->bankh * surf->nbanks) / 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_pr = surf->nbx / palign;
mtile_ps = (mtile_pr * surf->nby) / halign; mtile_ps = (mtile_pr * surf->nby) / halign;
surf->layer_size = mtile_ps * mtileb * slice_pt; surf->layer_size = mtile_ps * mtileb * slice_pt;

View File

@ -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) * @state: requested power state (0 = off, 1 = on)
* *
* Execute the necessary ATPX function to power down/up the discrete GPU * Execute the necessary ATPX function to power down/up the discrete GPU

View File

@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
struct drm_mode_object *obj; struct drm_mode_object *obj;
int i; int i;
enum drm_connector_status ret = connector_status_disconnected; 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)) if (!force && radeon_check_hpd_status_unchanged(connector))
return connector->status; return connector->status;
@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
ret = connector_status_disconnected; ret = connector_status_disconnected;
DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));
radeon_connector->ddc_bus = NULL; radeon_connector->ddc_bus = NULL;
} else {
ret = connector_status_connected;
broken_edid = true; /* defer use_digital to later */
} }
} else { } else {
radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); 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; encoder_funcs = encoder->helper_private;
if (encoder_funcs->detect) { if (encoder_funcs->detect) {
if (ret != connector_status_connected) { if (!broken_edid) {
ret = encoder_funcs->detect(encoder, connector); if (ret != connector_status_connected) {
if (ret == connector_status_connected) { /* deal with analog monitors without DDC */
radeon_connector->use_digital = false; 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) } else {
radeon_connector->detected_by_load = true; 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; break;
} }

View File

@ -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 radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
uint32_t crtc_ext_cntl = 0;
uint32_t mask; uint32_t mask;
if (radeon_crtc->crtc_id) 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_VSYNC_DIS |
RADEON_CRTC_HSYNC_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) { switch (mode) {
case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_ON:
radeon_crtc->enabled = true; radeon_crtc->enabled = true;
@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
else { else {
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN | WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
RADEON_CRTC_DISP_REQ_EN_B)); 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); drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
radeon_crtc_load_lut(crtc); radeon_crtc_load_lut(crtc);
@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
else { else {
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN | WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
RADEON_CRTC_DISP_REQ_EN_B)); 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; radeon_crtc->enabled = false;
/* adjust pm to dpms changes AFTER disabling crtcs */ /* adjust pm to dpms changes AFTER disabling crtcs */

View File

@ -537,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
break; 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_CNTL, dac_cntl);
WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_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)) if (ASIC_IS_R300(rdev))
tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
else if (ASIC_IS_RV100(rdev))
tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);
else else
tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); 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; tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
WREG32(RADEON_DAC_CNTL, tmp); WREG32(RADEON_DAC_CNTL, tmp);
tmp = dac_macro_cntl;
tmp &= ~(RADEON_DAC_PDWN_R | tmp &= ~(RADEON_DAC_PDWN_R |
RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_G |
RADEON_DAC_PDWN_B); RADEON_DAC_PDWN_B);
@ -1092,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
} else { } else {
if (is_tv) if (is_tv)
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); 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_CRTC2_GEN_CNTL, crtc2_gen_cntl);
WREG32(RADEON_TV_DAC_CNTL, tv_dac_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; 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, static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
struct drm_connector *connector) struct drm_connector *connector)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; 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; enum drm_connector_status found = connector_status_disconnected;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; 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; 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 */ /* save the regs we need */
pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); 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; if (rdev->flags & RADEON_SINGLE_CRTC) {
disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG); crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_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); tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
dac_cntl2 = RREG32(RADEON_DAC_CNTL2); 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); | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
if (ASIC_IS_R300(rdev)) if (rdev->flags & RADEON_SINGLE_CRTC) {
WREG32_P(RADEON_GPIOPAD_A, 1, ~1); tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
WREG32(RADEON_CRTC_EXT_CNTL, 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)) {
tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
} else { } else {
tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
WREG32(RADEON_DISP_HW_DEBUG, tmp); 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 | 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_CNTL2, dac_cntl2);
WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
if (ASIC_IS_R300(rdev)) { if (rdev->flags & RADEON_SINGLE_CRTC) {
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
} else { } 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); WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
return found; return found;

View File

@ -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, int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
const char *front, char **urb_buf_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 *ident_ptr, int *sent_ptr);
int udl_dumb_create(struct drm_file *file_priv, int udl_dumb_create(struct drm_file *file_priv,

View File

@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info,
list_for_each_entry(cur, &fbdefio->pagelist, lru) { list_for_each_entry(cur, &fbdefio->pagelist, lru) {
if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8),
&urb, (char *) info->fix.smem_start, &urb, (char *) info->fix.smem_start,
&cmd, cur->index << PAGE_SHIFT, &cmd, cur->index << PAGE_SHIFT,
PAGE_SIZE, &bytes_identical, &bytes_sent)) cur->index << PAGE_SHIFT,
PAGE_SIZE, &bytes_identical, &bytes_sent))
goto error; goto error;
bytes_rendered += PAGE_SIZE; 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++) { for (i = y; i < y + height ; i++) {
const int line_offset = fb->base.pitches[0] * i; const int line_offset = fb->base.pitches[0] * i;
const int byte_offset = line_offset + (x * bpp); 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, if (udl_render_hline(dev, bpp, &urb,
(char *) fb->obj->vmapping, (char *) fb->obj->vmapping,
&cmd, byte_offset, width * bpp, &cmd, byte_offset, dev_byte_offset,
width * bpp,
&bytes_identical, &bytes_sent)) &bytes_identical, &bytes_sent))
goto error; goto error;
} }

View File

@ -213,11 +213,12 @@ static void udl_compress_hline16(
*/ */
int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
const char *front, char **urb_buf_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 *ident_ptr, int *sent_ptr)
{ {
const u8 *line_start, *line_end, *next_pixel; 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; struct urb *urb = *urb_ptr;
u8 *cmd = *urb_buf_ptr; u8 *cmd = *urb_buf_ptr;
u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;

View File

@ -522,6 +522,12 @@ static const struct hid_device_id apple_devices[] = {
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
.driver_data = APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),

View File

@ -1532,6 +1532,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@ -2139,6 +2142,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ } { }

View File

@ -118,6 +118,9 @@
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI 0x0249
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO 0x024a
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b

View File

@ -28,22 +28,30 @@
#define MS_RDESC 0x08 #define MS_RDESC 0x08
#define MS_NOGET 0x10 #define MS_NOGET 0x10
#define MS_DUPLICATE_USAGES 0x20 #define MS_DUPLICATE_USAGES 0x20
#define MS_RDESC_3K 0x40
/*
* Microsoft Wireless Desktop Receiver (Model 1028) has
* 'Usage Min/Max' where it ought to have 'Physical Min/Max'
*/
static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize) unsigned int *rsize)
{ {
unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
/*
* Microsoft Wireless Desktop Receiver (Model 1028) has
* 'Usage Min/Max' where it ought to have 'Physical Min/Max'
*/
if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 && if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&
rdesc[559] == 0x29) { rdesc[559] == 0x29) {
hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n"); hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
rdesc[557] = 0x35; rdesc[557] = 0x35;
rdesc[559] = 0x45; rdesc[559] = 0x45;
} }
/* the same as above (s/usage/physical/) */
if ((quirks & MS_RDESC_3K) && *rsize == 106 &&
!memcmp((char []){ 0x19, 0x00, 0x29, 0xff },
&rdesc[94], 4)) {
rdesc[94] = 0x35;
rdesc[96] = 0x45;
}
return rdesc; return rdesc;
} }
@ -192,7 +200,7 @@ static const struct hid_device_id ms_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
.driver_data = MS_PRESENTER }, .driver_data = MS_PRESENTER },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K),
.driver_data = MS_ERGONOMY }, .driver_data = MS_ERGONOMY | MS_RDESC_3K },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
.driver_data = MS_NOGET }, .driver_data = MS_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),

View File

@ -210,8 +210,7 @@ static struct mt_class mt_classes[] = {
}, },
{ .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS, { .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
MT_QUIRK_SLOT_IS_CONTACTNUMBER, MT_QUIRK_SLOT_IS_CONTACTNUMBER
.maxcontacts = 10
}, },
{ .name = MT_CLS_FLATFROG, { .name = MT_CLS_FLATFROG,
@ -421,11 +420,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
* contact max are global to the report */ * contact max are global to the report */
td->last_field_index = field->index; td->last_field_index = field->index;
return -1; return -1;
}
case HID_DG_TOUCH: case HID_DG_TOUCH:
/* Legacy devices use TIPSWITCH and not TOUCH. /* Legacy devices use TIPSWITCH and not TOUCH.
* Let's just ignore this field. */ * Let's just ignore this field. */
return -1; return -1;
}
/* let hid-input decide for the others */ /* let hid-input decide for the others */
return 0; return 0;

View File

@ -2,7 +2,7 @@
* fam15h_power.c - AMD Family 15h processor power monitoring * fam15h_power.c - AMD Family 15h processor power monitoring
* *
* Copyright (c) 2011 Advanced Micro Devices, Inc. * 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 * This driver is free software; you can redistribute it and/or
@ -28,7 +28,7 @@
#include <asm/processor.h> #include <asm/processor.h>
MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor"); 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"); MODULE_LICENSE("GPL");
/* D18F3 */ /* D18F3 */

View File

@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = {
.driver = { .driver = {
.name = "gpio-fan", .name = "gpio-fan",
.pm = GPIO_FAN_PM, .pm = GPIO_FAN_PM,
#ifdef CONFIG_OF_GPIO
.of_match_table = of_match_ptr(of_gpio_fan_match), .of_match_table = of_match_ptr(of_gpio_fan_match),
#endif
}, },
}; };

View File

@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-$(CONFIG_I2C_MUX) += i2c-mux.o obj-$(CONFIG_I2C_MUX) += i2c-mux.o
obj-y += algos/ busses/ muxes/ obj-y += algos/ busses/ muxes/
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
CFLAGS_i2c-core.o := -Wno-deprecated-declarations CFLAGS_i2c-core.o := -Wno-deprecated-declarations

View File

@ -81,7 +81,6 @@ config I2C_I801
tristate "Intel 82801 (ICH/PCH)" tristate "Intel 82801 (ICH/PCH)"
depends on PCI depends on PCI
select CHECK_SIGNATURE if X86 && DMI select CHECK_SIGNATURE if X86 && DMI
select GPIOLIB if I2C_MUX
help help
If you say yes to this option, support will be included for the Intel If you say yes to this option, support will be included for the Intel
801 family of mainboard I2C interfaces. Specifically, the following 801 family of mainboard I2C interfaces. Specifically, the following

View File

@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o

View File

@ -82,7 +82,8 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/err.h> #include <linux/err.h>
#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
defined CONFIG_DMI
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/i2c-mux-gpio.h> #include <linux/i2c-mux-gpio.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
@ -192,7 +193,8 @@ struct i801_priv {
int len; int len;
u8 *data; u8 *data;
#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
defined CONFIG_DMI
const struct i801_mux_config *mux_drvdata; const struct i801_mux_config *mux_drvdata;
struct platform_device *mux_pdev; struct platform_device *mux_pdev;
#endif #endif
@ -921,7 +923,8 @@ static void __init input_apanel_init(void) {}
static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {} static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
#endif /* CONFIG_X86 && CONFIG_DMI */ #endif /* CONFIG_X86 && CONFIG_DMI */
#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
defined CONFIG_DMI
static struct i801_mux_config i801_mux_config_asus_z8_d12 = { static struct i801_mux_config i801_mux_config_asus_z8_d12 = {
.gpio_chip = "gpio_ich", .gpio_chip = "gpio_ich",
.values = { 0x02, 0x03 }, .values = { 0x02, 0x03 },
@ -1059,7 +1062,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)
id = dmi_first_match(mux_dmi_table); id = dmi_first_match(mux_dmi_table);
if (id) { if (id) {
/* Remove from branch classes from trunk */ /* Remove branch classes from trunk */
mux_config = id->driver_data; mux_config = id->driver_data;
for (i = 0; i < mux_config->n_values; i++) for (i = 0; i < mux_config->n_values; i++)
class &= ~mux_config->classes[i]; class &= ~mux_config->classes[i];

View File

@ -1,7 +1,7 @@
/* /*
* Freescale MXS I2C bus driver * 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: * based on a (non-working) driver which was:
* *
@ -35,10 +35,6 @@
#define DRIVER_NAME "mxs-i2c" #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 (0x00)
#define MXS_I2C_CTRL0_SET (0x04) #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_STOP_IRQ | \
MXS_I2C_CTRL1_SLAVE_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 | \ #define MXS_CMD_I2C_SELECT (MXS_I2C_CTRL0_RETAIN_CLOCK | \
MXS_I2C_CTRL0_PRE_SEND_START | \ MXS_I2C_CTRL0_PRE_SEND_START | \
@ -153,7 +132,6 @@ struct mxs_i2c_dev {
const struct mxs_i2c_speed_config *speed; const struct mxs_i2c_speed_config *speed;
/* DMA support components */ /* DMA support components */
bool dma_mode;
int dma_channel; int dma_channel;
struct dma_chan *dmach; struct dma_chan *dmach;
struct mxs_dma_data dma_data; 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(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); 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) 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); init_completion(&i2c->cmd_complete);
i2c->cmd_err = 0; i2c->cmd_err = 0;
if (i2c->dma_mode) { ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); if (ret)
if (ret) return 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 = wait_for_completion_timeout(&i2c->cmd_complete, ret = wait_for_completion_timeout(&i2c->cmd_complete,
msecs_to_jiffies(1000)); msecs_to_jiffies(1000));
if (ret == 0) if (ret == 0)
goto timeout; 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) if (i2c->cmd_err == -ENXIO)
mxs_i2c_reset(i2c); 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); 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: timeout:
dev_dbg(i2c->dev, "Timeout!\n"); dev_dbg(i2c->dev, "Timeout!\n");
if (i2c->dma_mode) mxs_i2c_dma_finish(i2c);
mxs_i2c_dma_finish(i2c);
mxs_i2c_reset(i2c); mxs_i2c_reset(i2c);
return -ETIMEDOUT; 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; struct mxs_i2c_dev *i2c = dev_id;
u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK; u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK;
bool is_last_cmd;
if (!stat) if (!stat)
return IRQ_NONE; 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 */ /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
i2c->cmd_err = -EIO; 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); writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
return IRQ_HANDLED; 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; struct device_node *node = dev->of_node;
int ret; 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 * TODO: This is a temporary solution and should be changed
* to use generic DMA binding later when the helpers get in. * 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", ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
&i2c->dma_channel); &i2c->dma_channel);
if (ret) { if (ret) {
dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n"); dev_err(dev, "Failed to get DMA channel!\n");
i2c->dma_mode = 0; return -ENODEV;
} }
ret = of_property_read_u32(node, "clock-frequency", &speed); 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 */ /* Setup the DMA */
if (i2c->dma_mode) { dma_cap_zero(mask);
dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask);
dma_cap_set(DMA_SLAVE, mask); i2c->dma_data.chan_irq = dmairq;
i2c->dma_data.chan_irq = dmairq; i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c); if (!i2c->dmach) {
if (!i2c->dmach) { dev_err(dev, "Failed to request dma\n");
dev_err(dev, "Failed to request dma\n"); return -ENODEV;
return -ENODEV;
}
} }
platform_set_drvdata(pdev, i2c); platform_set_drvdata(pdev, i2c);

View File

@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
pm_runtime_get_sync(&dev->adev->dev); 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); status = init_hw(dev);
if (status) if (status)
@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
} }
out: out:
clk_disable(dev->clk); clk_disable_unprepare(dev->clk);
out_clk:
pm_runtime_put_sync(&dev->adev->dev); pm_runtime_put_sync(&dev->adev->dev);
dev->busy = false; dev->busy = false;

View File

@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
} }
ret = devm_request_irq(&pdev->dev, i2c_dev->irq, 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) { if (ret) {
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
return ret; return ret;

View File

@ -2,7 +2,7 @@
i2c-stub.c - I2C/SMBus chip emulator i2c-stub.c - I2C/SMBus chip emulator
Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com> Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
Copyright (C) 2007 Jean Delvare <khali@linux-fr.org> Copyright (C) 2007, 2012 Jean Delvare <khali@linux-fr.org>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -51,8 +51,8 @@ struct stub_chip {
static struct stub_chip *stub_chips; static struct stub_chip *stub_chips;
/* Return negative errno on error. */ /* Return negative errno on error. */
static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
char read_write, u8 command, int size, union i2c_smbus_data * data) char read_write, u8 command, int size, union i2c_smbus_data *data)
{ {
s32 ret; s32 ret;
int i, len; int i, len;
@ -78,14 +78,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
case I2C_SMBUS_BYTE: case I2C_SMBUS_BYTE:
if (read_write == I2C_SMBUS_WRITE) { if (read_write == I2C_SMBUS_WRITE) {
chip->pointer = command; chip->pointer = command;
dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " dev_dbg(&adap->dev,
"wrote 0x%02x.\n", "smbus byte - addr 0x%02x, wrote 0x%02x.\n",
addr, command); addr, command);
} else { } else {
data->byte = chip->words[chip->pointer++] & 0xff; data->byte = chip->words[chip->pointer++] & 0xff;
dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " dev_dbg(&adap->dev,
"read 0x%02x.\n", "smbus byte - addr 0x%02x, read 0x%02x.\n",
addr, data->byte); addr, data->byte);
} }
ret = 0; ret = 0;
@ -95,14 +95,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
if (read_write == I2C_SMBUS_WRITE) { if (read_write == I2C_SMBUS_WRITE) {
chip->words[command] &= 0xff00; chip->words[command] &= 0xff00;
chip->words[command] |= data->byte; chip->words[command] |= data->byte;
dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " dev_dbg(&adap->dev,
"wrote 0x%02x at 0x%02x.\n", "smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n",
addr, data->byte, command); addr, data->byte, command);
} else { } else {
data->byte = chip->words[command] & 0xff; data->byte = chip->words[command] & 0xff;
dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " dev_dbg(&adap->dev,
"read 0x%02x at 0x%02x.\n", "smbus byte data - addr 0x%02x, read 0x%02x at 0x%02x.\n",
addr, data->byte, command); addr, data->byte, command);
} }
chip->pointer = command + 1; chip->pointer = command + 1;
@ -112,14 +112,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
case I2C_SMBUS_WORD_DATA: case I2C_SMBUS_WORD_DATA:
if (read_write == I2C_SMBUS_WRITE) { if (read_write == I2C_SMBUS_WRITE) {
chip->words[command] = data->word; chip->words[command] = data->word;
dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " dev_dbg(&adap->dev,
"wrote 0x%04x at 0x%02x.\n", "smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n",
addr, data->word, command); addr, data->word, command);
} else { } else {
data->word = chip->words[command]; data->word = chip->words[command];
dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " dev_dbg(&adap->dev,
"read 0x%04x at 0x%02x.\n", "smbus word data - addr 0x%02x, read 0x%04x at 0x%02x.\n",
addr, data->word, command); addr, data->word, command);
} }
ret = 0; ret = 0;
@ -132,17 +132,17 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
chip->words[command + i] &= 0xff00; chip->words[command + i] &= 0xff00;
chip->words[command + i] |= data->block[1 + i]; chip->words[command + i] |= data->block[1 + i];
} }
dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " dev_dbg(&adap->dev,
"wrote %d bytes at 0x%02x.\n", "i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n",
addr, len, command); addr, len, command);
} else { } else {
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
data->block[1 + i] = data->block[1 + i] =
chip->words[command + i] & 0xff; chip->words[command + i] & 0xff;
} }
dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " dev_dbg(&adap->dev,
"read %d bytes at 0x%02x.\n", "i2c block data - addr 0x%02x, read %d bytes at 0x%02x.\n",
addr, len, command); addr, len, command);
} }
ret = 0; ret = 0;
@ -179,25 +179,24 @@ static int __init i2c_stub_init(void)
int i, ret; int i, ret;
if (!chip_addr[0]) { if (!chip_addr[0]) {
printk(KERN_ERR "i2c-stub: Please specify a chip address\n"); pr_err("i2c-stub: Please specify a chip address\n");
return -ENODEV; return -ENODEV;
} }
for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) { if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) {
printk(KERN_ERR "i2c-stub: Invalid chip address " pr_err("i2c-stub: Invalid chip address 0x%02x\n",
"0x%02x\n", chip_addr[i]); chip_addr[i]);
return -EINVAL; return -EINVAL;
} }
printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]);
chip_addr[i]);
} }
/* Allocate memory for all chips at once */ /* Allocate memory for all chips at once */
stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL); stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
if (!stub_chips) { if (!stub_chips) {
printk(KERN_ERR "i2c-stub: Out of memory\n"); pr_err("i2c-stub: Out of memory\n");
return -ENOMEM; return -ENOMEM;
} }
@ -219,4 +218,3 @@ MODULE_LICENSE("GPL");
module_init(i2c_stub_init); module_init(i2c_stub_init);
module_exit(i2c_stub_exit); module_exit(i2c_stub_exit);

View File

@ -335,6 +335,7 @@ config KEYBOARD_LOCOMO
config KEYBOARD_LPC32XX config KEYBOARD_LPC32XX
tristate "LPC32XX matrix key scanner support" tristate "LPC32XX matrix key scanner support"
depends on ARCH_LPC32XX && OF depends on ARCH_LPC32XX && OF
select INPUT_MATRIXKMAP
help help
Say Y here if you want to use NXP LPC32XX SoC key scanner interface, Say Y here if you want to use NXP LPC32XX SoC key scanner interface,
connected to a key matrix. connected to a key matrix.

View File

@ -368,6 +368,9 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
unsigned int mask = 0, direct_key_num = 0; unsigned int mask = 0, direct_key_num = 0;
unsigned long kpc = 0; unsigned long kpc = 0;
/* clear pending interrupt bit */
keypad_readl(KPC);
/* enable matrix keys with automatic scan */ /* enable matrix keys with automatic scan */
if (pdata->matrix_key_rows && pdata->matrix_key_cols) { if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL; kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;

View File

@ -311,7 +311,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
case XenbusStateReconfiguring: case XenbusStateReconfiguring:
case XenbusStateReconfigured: case XenbusStateReconfigured:
case XenbusStateUnknown: case XenbusStateUnknown:
case XenbusStateClosed:
break; break;
case XenbusStateInitWait: case XenbusStateInitWait:
@ -350,6 +349,10 @@ InitWait:
break; break;
case XenbusStateClosed:
if (dev->state == XenbusStateClosed)
break;
/* Missed the backend's CLOSING state -- fallthrough */
case XenbusStateClosing: case XenbusStateClosing:
xenbus_frontend_closed(dev); xenbus_frontend_closed(dev);
break; break;

View File

@ -84,6 +84,10 @@
#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262
#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263
#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264 #define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264
/* MacbookPro10,2 (unibody, October 2012) */
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI 0x0259
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO 0x025a
#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS 0x025b
#define BCM5974_DEVICE(prod) { \ #define BCM5974_DEVICE(prod) { \
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
@ -137,6 +141,10 @@ static const struct usb_device_id bcm5974_table[] = {
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
/* MacbookPro10,2 */
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
/* Terminating entry */ /* Terminating entry */
{} {}
}; };
@ -379,6 +387,19 @@ static const struct bcm5974_config bcm5974_config_table[] = {
{ SN_COORD, -150, 6730 }, { SN_COORD, -150, 6730 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
}, },
{
USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct bt_data),
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4750, 5280 },
{ SN_COORD, -150, 6730 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
{} {}
}; };

View File

@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
features->pktlen = WACOM_PKGLEN_TPC2FG; features->pktlen = WACOM_PKGLEN_TPC2FG;
} }
if (features->type == MTSCREEN || WACOM_24HDT) if (features->type == MTSCREEN || features->type == WACOM_24HDT)
features->pktlen = WACOM_PKGLEN_MTOUCH; features->pktlen = WACOM_PKGLEN_MTOUCH;
if (features->type == BAMBOO_PT) { if (features->type == BAMBOO_PT) {

View File

@ -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_Z, -900, 899, 0, 0);
input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 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); wacom_setup_cintiq(wacom_wac);
break; break;

View File

@ -239,7 +239,7 @@ config TOUCHSCREEN_EETI
config TOUCHSCREEN_EGALAX config TOUCHSCREEN_EGALAX
tristate "EETI eGalax multi-touch panel support" tristate "EETI eGalax multi-touch panel support"
depends on I2C depends on I2C && OF
help help
Say Y here to enable support for I2C connected EETI Say Y here to enable support for I2C connected EETI
eGalax multi-touch panels. eGalax multi-touch panels.

View File

@ -28,6 +28,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/input/mt.h> #include <linux/input/mt.h>
#include <linux/of_gpio.h>
/* /*
* Mouse Mode: some panel may configure the controller to mouse mode, * 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. */ /* wake up controller by an falling edge of interrupt gpio. */
static int egalax_wake_up_device(struct i2c_client *client) 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; 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"); ret = gpio_request(gpio, "egalax_irq");
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, dev_err(&client->dev,
@ -181,7 +190,11 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,
ts->input_dev = input_dev; ts->input_dev = input_dev;
/* controller may be in sleep, wake it up. */ /* 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); ret = egalax_firmware_version(client);
if (ret < 0) { 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 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 = { static struct i2c_driver egalax_ts_driver = {
.driver = { .driver = {
.name = "egalax_ts", .name = "egalax_ts",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &egalax_ts_pm_ops, .pm = &egalax_ts_pm_ops,
.of_match_table = of_match_ptr(egalax_ts_dt_ids),
}, },
.id_table = egalax_ts_id, .id_table = egalax_ts_id,
.probe = egalax_ts_probe, .probe = egalax_ts_probe,

View File

@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)
__set_bit(BTN_TOUCH, input_dev->keybit); __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_X, 0, 0x3ff, 0, 0);
input_set_abs_params(ptsc->dev, ABS_Y, 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); serio_set_drvdata(serio, ptsc);

View File

@ -315,8 +315,11 @@ static int run(struct mddev *mddev)
} }
conf->nfaults = 0; conf->nfaults = 0;
rdev_for_each(rdev, mddev) rdev_for_each(rdev, mddev) {
conf->rdev = rdev; conf->rdev = rdev;
disk_stack_limits(mddev->gendisk, rdev->bdev,
rdev->data_offset << 9);
}
md_set_array_sectors(mddev, faulty_size(mddev, 0, 0)); md_set_array_sectors(mddev, faulty_size(mddev, 0, 0));
mddev->private = conf; mddev->private = conf;

View File

@ -2710,7 +2710,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)
|| disk_idx < 0) || disk_idx < 0)
continue; continue;
if (test_bit(Replacement, &rdev->flags)) if (test_bit(Replacement, &rdev->flags))
disk = conf->mirrors + conf->raid_disks + disk_idx; disk = conf->mirrors + mddev->raid_disks + disk_idx;
else else
disk = conf->mirrors + disk_idx; disk = conf->mirrors + disk_idx;

View File

@ -1783,7 +1783,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
clear_bit(Unmerged, &rdev->flags); clear_bit(Unmerged, &rdev->flags);
} }
md_integrity_add_rdev(rdev, mddev); md_integrity_add_rdev(rdev, mddev);
if (blk_queue_discard(bdev_get_queue(rdev->bdev))) if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
print_conf(conf); print_conf(conf);
@ -3613,11 +3613,14 @@ static int run(struct mddev *mddev)
discard_supported = true; discard_supported = true;
} }
if (discard_supported) if (mddev->queue) {
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); if (discard_supported)
else queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); mddev->queue);
else
queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD,
mddev->queue);
}
/* need to check that every block has at least one working mirror */ /* need to check that every block has at least one working mirror */
if (!enough(conf, -1)) { if (!enough(conf, -1)) {
printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n", printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n",

View File

@ -1060,7 +1060,7 @@ static ssize_t bonding_store_primary(struct device *d,
goto out; goto out;
} }
sscanf(buf, "%16s", ifname); /* IFNAMSIZ */ sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
/* check to see if we are clearing primary */ /* check to see if we are clearing primary */
if (!strlen(ifname) || buf[0] == '\n') { if (!strlen(ifname) || buf[0] == '\n') {
@ -1237,7 +1237,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
goto out; goto out;
} }
sscanf(buf, "%16s", ifname); /* IFNAMSIZ */ sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
/* check to see if we are clearing active */ /* check to see if we are clearing active */
if (!strlen(ifname) || buf[0] == '\n') { if (!strlen(ifname) || buf[0] == '\n') {

View File

@ -137,7 +137,16 @@
#define LINK_20GTFD LINK_STATUS_SPEED_AND_DUPLEX_20GTFD #define LINK_20GTFD LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
#define LINK_20GXFD LINK_STATUS_SPEED_AND_DUPLEX_20GXFD #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_ADDR 0x2
#define SFP_EEPROM_CON_TYPE_VAL_LC 0x7 #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); 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) static void bnx2x_xgxs_deassert(struct link_params *params)
{ {
struct bnx2x *bp = params->bp; 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); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
udelay(500); udelay(500);
REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
bnx2x_xgxs_specific_func(&params->phy[INT_PHY], params,
REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0); PHY_INIT);
REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
params->phy[INT_PHY].def_md_devad);
} }
static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy, 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, static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
struct link_params *params, struct link_params *params,
struct link_vars *vars) { 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; struct bnx2x *bp = params->bp;
static struct bnx2x_reg_set reg_set[] = { static struct bnx2x_reg_set reg_set[] = {
{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, {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_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0},
{MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415}, {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},
{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190}, {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, bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
reg_set[i].val); 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 */ /* Check adding advertisement for 1G KX */
if (((vars->line_speed == SPEED_AUTO_NEG) && if (((vars->line_speed == SPEED_AUTO_NEG) &&
(phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
(vars->line_speed == SPEED_1000)) { (vars->line_speed == SPEED_1000)) {
u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2; u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2;
val16 |= (1<<5); an_adv |= (1<<5);
/* Enable CL37 1G Parallel Detect */ /* Enable CL37 1G Parallel Detect */
bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1); 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)) || (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
(vars->line_speed == SPEED_10000)) { (vars->line_speed == SPEED_10000)) {
/* Check adding advertisement for 10G KR */ /* Check adding advertisement for 10G KR */
val16 |= (1<<7); an_adv |= (1<<7);
/* Enable 10G Parallel Detect */ /* 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, bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
MDIO_WC_REG_PAR_DET_10G_CTRL, 1); MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
bnx2x_set_aer_mmd(params, phy);
DP(NETIF_MSG_LINK, "Advertize 10G\n"); DP(NETIF_MSG_LINK, "Advertize 10G\n");
} }
@ -3604,7 +3633,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
/* Advertised speeds */ /* Advertised speeds */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, 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) */ /* Advertised and set FEC (Forward Error Correction) */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, 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 /* Set KR Autoneg Work-Around flag for Warpcore version older than D108
*/ */
bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_UC_INFO_B1_VERSION, &val16); MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver);
if (val16 < 0xd108) { if (ucode_ver < 0xd108) {
DP(NETIF_MSG_LINK, "Enable AN KR work-around\n"); 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; vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
} }
bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, 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 link_vars *vars)
{ {
struct bnx2x *bp = params->bp; struct bnx2x *bp = params->bp;
u16 i; u16 val16, i, lane;
static struct bnx2x_reg_set reg_set[] = { static struct bnx2x_reg_set reg_set[] = {
/* Disable Autoneg */ /* Disable Autoneg */
{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, {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, {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
0x3f00}, 0x3f00},
{MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0}, {MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0},
{MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0}, {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0},
{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1}, {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},
{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa}, {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 */ /* Leave cl72 training enable, needed for KR */
{MDIO_PMA_DEVAD, {MDIO_PMA_DEVAD,
MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150, 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, bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
reg_set[i].val); reg_set[i].val);
/* Leave CL72 enabled */ lane = bnx2x_get_warpcore_lane(phy, params);
bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, /* Global registers */
MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
0x3800); 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 */ /* Set speed via PMA/PMD register */
bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040); 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 link_params *params)
{ {
struct bnx2x *bp = params->bp; struct bnx2x *bp = params->bp;
u16 val16; u16 val16, lane;
bnx2x_sfp_e3_set_transmitter(params, phy, 0); bnx2x_sfp_e3_set_transmitter(params, phy, 0);
bnx2x_set_mdio_clk(bp, params->chip_id, params->port); bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
bnx2x_set_aer_mmd(params, phy); 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, MDIO_WC_REG_XGXSBLK1_LANECTRL2,
val16 & 0xff00); 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, 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; vars->mac_type = MAC_TYPE_NONE;
/* Update shared memory */ /* Update shared memory */
vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK | vars->link_status &= ~LINK_UPDATE_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->line_speed = 0; vars->line_speed = 0;
bnx2x_update_mng(params, vars->link_status); 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; u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
u8 active_external_phy = INT_PHY; u8 active_external_phy = INT_PHY;
vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
vars->link_status &= ~LINK_UPDATE_MASK;
for (phy_index = INT_PHY; phy_index < params->num_phys; for (phy_index = INT_PHY; phy_index < params->num_phys;
phy_index++) { phy_index++) {
phy_vars[phy_index].flow_ctrl = 0; 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, static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
struct link_params *params, struct link_params *params,
u16 addr, u8 byte_cnt, u16 addr, u8 byte_cnt,
u8 *o_buf) u8 *o_buf, u8 is_init)
{ {
int rc = 0; int rc = 0;
u8 i, j = 0, cnt = 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 */ /* 4 byte aligned address */
addr32 = addr & (~0x3); addr32 = addr & (~0x3);
do { do {
if (cnt == I2C_WA_PWR_ITER) { if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {
bnx2x_warpcore_power_module(params, phy, 0); bnx2x_warpcore_power_module(params, phy, 0);
/* Note that 100us are not enough here */ /* Note that 100us are not enough here */
usleep_range(1000,1000); usleep_range(1000, 2000);
bnx2x_warpcore_power_module(params, phy, 1); bnx2x_warpcore_power_module(params, phy, 1);
} }
rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt, 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; break;
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr, rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
byte_cnt, o_buf); byte_cnt, o_buf, 0);
break; break;
} }
return rc; return rc;
@ -7923,6 +7978,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
{ {
u8 val; u8 val;
int rc;
struct bnx2x *bp = params->bp; struct bnx2x *bp = params->bp;
u16 timeout; u16 timeout;
/* Initialization time after hot-plug may take up to 300ms for /* 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++) { for (timeout = 0; timeout < 60; timeout++) {
if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val) if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
== 0) { 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, DP(NETIF_MSG_LINK,
"SFP+ module initialization took %d ms\n", "SFP+ module initialization took %d ms\n",
timeout * 5); timeout * 5);
@ -7939,7 +8001,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
} }
usleep_range(5000, 10000); 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, 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, .format_fw_ver = (format_fw_ver_t)NULL,
.hw_reset = (hw_reset_t)NULL, .hw_reset = (hw_reset_t)NULL,
.set_link_led = (set_link_led_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 = { static struct bnx2x_phy phy_warpcore = {
.type = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, .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; phy->media_type = ETH_PHY_BASE_T;
break; break;
case PORT_HW_CFG_NET_SERDES_IF_XFI: 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; phy->media_type = ETH_PHY_XFP_FIBER;
break; break;
case PORT_HW_CFG_NET_SERDES_IF_SFI: case PORT_HW_CFG_NET_SERDES_IF_SFI:

Some files were not shown because too many files have changed in this diff Show More