Merge branch 'devel/debug_ll_init' into zynq/multiplatform
This commit is contained in:
Коммит
84d2e38e93
|
@ -0,0 +1,19 @@
|
|||
* EETI eGalax Multiple Touch Controller
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "eeti,egalax_ts"
|
||||
- reg: i2c slave address
|
||||
- interrupt-parent: the phandle for the interrupt controller
|
||||
- interrupts: touch controller interrupt
|
||||
- wakeup-gpios: the gpio pin to be used for waking up the controller
|
||||
as well as uased as irq pin
|
||||
|
||||
Example:
|
||||
|
||||
egalax_ts@04 {
|
||||
compatible = "eeti,egalax_ts";
|
||||
reg = <0x04>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <9 2>;
|
||||
wakeup-gpios = <&gpio1 9 0>;
|
||||
};
|
|
@ -10,7 +10,7 @@ Supported chips:
|
|||
BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors
|
||||
(not yet published)
|
||||
|
||||
Author: Andreas Herrmann <andreas.herrmann3@amd.com>
|
||||
Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
|
|
@ -503,7 +503,7 @@ F: include/linux/altera_uart.h
|
|||
F: include/linux/altera_jtaguart.h
|
||||
|
||||
AMD FAM15H PROCESSOR POWER MONITORING DRIVER
|
||||
M: Andreas Herrmann <andreas.herrmann3@amd.com>
|
||||
M: Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/fam15h_power
|
||||
|
@ -2507,6 +2507,7 @@ M: Joonyoung Shim <jy0922.shim@samsung.com>
|
|||
M: Seung-Woo Kim <sw0312.kim@samsung.com>
|
||||
M: Kyungmin Park <kyungmin.park@samsung.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git
|
||||
S: Supported
|
||||
F: drivers/gpu/drm/exynos
|
||||
F: include/drm/exynos*
|
||||
|
@ -5647,7 +5648,7 @@ S: Maintained
|
|||
F: drivers/pinctrl/spear/
|
||||
|
||||
PKTCDVD DRIVER
|
||||
M: Peter Osterlund <petero2@telia.com>
|
||||
M: Jiri Kosina <jkosina@suse.cz>
|
||||
S: Maintained
|
||||
F: drivers/block/pktcdvd.c
|
||||
F: include/linux/pktcdvd.h
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 3
|
||||
PATCHLEVEL = 7
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc3
|
||||
EXTRAVERSION = -rc4
|
||||
NAME = Terrified Chipmunk
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -40,6 +40,13 @@ extern void iotable_init(struct map_desc *, int);
|
|||
extern void vm_reserve_area_early(unsigned long addr, unsigned long size,
|
||||
void *caller);
|
||||
|
||||
#ifdef CONFIG_DEBUG_LL
|
||||
extern void debug_ll_addr(unsigned long *paddr, unsigned long *vaddr);
|
||||
extern void debug_ll_io_init(void);
|
||||
#else
|
||||
static inline void debug_ll_io_init(void) {}
|
||||
#endif
|
||||
|
||||
struct mem_type;
|
||||
extern const struct mem_type *get_mem_type(unsigned int type);
|
||||
/*
|
||||
|
|
|
@ -100,6 +100,13 @@ ENTRY(printch)
|
|||
b 1b
|
||||
ENDPROC(printch)
|
||||
|
||||
ENTRY(debug_ll_addr)
|
||||
addruart r2, r3, ip
|
||||
str r2, [r0]
|
||||
str r3, [r1]
|
||||
mov pc, lr
|
||||
ENDPROC(debug_ll_addr)
|
||||
|
||||
#else
|
||||
|
||||
ENTRY(printascii)
|
||||
|
@ -119,4 +126,11 @@ ENTRY(printch)
|
|||
mov pc, lr
|
||||
ENDPROC(printch)
|
||||
|
||||
ENTRY(debug_ll_addr)
|
||||
mov r2, #0
|
||||
str r2, [r0]
|
||||
str r2, [r1]
|
||||
mov pc, lr
|
||||
ENDPROC(debug_ll_addr)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -876,6 +876,22 @@ static void __init pci_reserve_io(void)
|
|||
#define pci_reserve_io() do { } while (0)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_LL
|
||||
void __init debug_ll_io_init(void)
|
||||
{
|
||||
struct map_desc map;
|
||||
|
||||
debug_ll_addr(&map.pfn, &map.virtual);
|
||||
if (!map.pfn || !map.virtual)
|
||||
return;
|
||||
map.pfn = __phys_to_pfn(map.pfn);
|
||||
map.virtual &= PAGE_MASK;
|
||||
map.length = PAGE_SIZE;
|
||||
map.type = MT_DEVICE;
|
||||
create_mapping(&map);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void * __initdata vmalloc_min =
|
||||
(void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET);
|
||||
|
||||
|
|
|
@ -48,20 +48,16 @@
|
|||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/opcodes-virt.h>
|
||||
#include <xen/interface/xen.h>
|
||||
|
||||
|
||||
/* HVC 0xEA1 */
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
#define xen_hvc .word 0xf7e08ea1
|
||||
#else
|
||||
#define xen_hvc .word 0xe140ea71
|
||||
#endif
|
||||
#define XEN_IMM 0xEA1
|
||||
|
||||
#define HYPERCALL_SIMPLE(hypercall) \
|
||||
ENTRY(HYPERVISOR_##hypercall) \
|
||||
mov r12, #__HYPERVISOR_##hypercall; \
|
||||
xen_hvc; \
|
||||
__HVC(XEN_IMM); \
|
||||
mov pc, lr; \
|
||||
ENDPROC(HYPERVISOR_##hypercall)
|
||||
|
||||
|
@ -76,7 +72,7 @@ ENTRY(HYPERVISOR_##hypercall) \
|
|||
stmdb sp!, {r4} \
|
||||
ldr r4, [sp, #4] \
|
||||
mov r12, #__HYPERVISOR_##hypercall; \
|
||||
xen_hvc \
|
||||
__HVC(XEN_IMM); \
|
||||
ldm sp!, {r4} \
|
||||
mov pc, lr \
|
||||
ENDPROC(HYPERVISOR_##hypercall)
|
||||
|
@ -100,7 +96,7 @@ ENTRY(privcmd_call)
|
|||
mov r2, r3
|
||||
ldr r3, [sp, #8]
|
||||
ldr r4, [sp, #4]
|
||||
xen_hvc
|
||||
__HVC(XEN_IMM)
|
||||
ldm sp!, {r4}
|
||||
mov pc, lr
|
||||
ENDPROC(privcmd_call);
|
||||
|
|
|
@ -13,6 +13,7 @@ config FRV
|
|||
select GENERIC_CPU_DEVICES
|
||||
select ARCH_WANT_IPC_PARSE_VERSION
|
||||
select GENERIC_KERNEL_THREAD
|
||||
select GENERIC_KERNEL_EXECVE
|
||||
|
||||
config ZONE_DMA
|
||||
bool
|
||||
|
|
|
@ -17,6 +17,8 @@ PARAMS_PHYS = 0x0207c000
|
|||
INITRD_PHYS = 0x02180000
|
||||
INITRD_VIRT = 0x02180000
|
||||
|
||||
OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment
|
||||
|
||||
#
|
||||
# If you don't define ZRELADDR above,
|
||||
# then it defaults to ZTEXTADDR
|
||||
|
@ -32,18 +34,18 @@ Image: $(obj)/Image
|
|||
targets: $(obj)/Image
|
||||
|
||||
$(obj)/Image: vmlinux FORCE
|
||||
$(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) -S vmlinux $@
|
||||
|
||||
#$(obj)/Image: $(CONFIGURE) $(SYSTEM)
|
||||
# $(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@
|
||||
# $(OBJCOPY) $(OBJCOPYFLAGS) -g -S $(SYSTEM) $@
|
||||
|
||||
bzImage: zImage
|
||||
|
||||
zImage: $(CONFIGURE) compressed/$(LINUX)
|
||||
$(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) -S compressed/$(LINUX) $@
|
||||
|
||||
bootpImage: bootp/bootp
|
||||
$(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@
|
||||
$(OBJCOPY) $(OBJCOPYFLAGS) -S bootp/bootp $@
|
||||
|
||||
compressed/$(LINUX): $(LINUX) dep
|
||||
@$(MAKE) -C compressed $(LINUX)
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#define __ARCH_WANT_SYS_RT_SIGACTION
|
||||
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||
#define __ARCH_WANT_SYS_EXECVE
|
||||
#define __ARCH_WANT_KERNEL_EXECVE
|
||||
|
||||
/*
|
||||
* "Conditional" syscalls
|
||||
|
|
|
@ -869,11 +869,6 @@ ret_from_kernel_thread:
|
|||
call schedule_tail
|
||||
calll.p @(gr21,gr0)
|
||||
or gr20,gr20,gr8
|
||||
bra sys_exit
|
||||
|
||||
.globl ret_from_kernel_execve
|
||||
ret_from_kernel_execve:
|
||||
ori gr28,0,sp
|
||||
bra __syscall_exit
|
||||
|
||||
###################################################################################################
|
||||
|
@ -1080,27 +1075,10 @@ __entry_return_from_kernel_interrupt:
|
|||
subicc gr5,#0,gr0,icc0
|
||||
beq icc0,#0,__entry_return_direct
|
||||
|
||||
__entry_preempt_need_resched:
|
||||
ldi @(gr15,#TI_FLAGS),gr4
|
||||
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
|
||||
subcc gr0,gr0,gr0,icc2 /* set Z and clear C */
|
||||
call preempt_schedule_irq
|
||||
#endif
|
||||
bra __entry_return_direct
|
||||
|
||||
|
||||
###############################################################################
|
||||
|
|
|
@ -181,6 +181,9 @@ int copy_thread(unsigned long clone_flags,
|
|||
childregs = (struct pt_regs *)
|
||||
(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->thread.frame = childregs;
|
||||
|
@ -191,10 +194,8 @@ int copy_thread(unsigned long clone_flags,
|
|||
p->thread.frame0 = childregs;
|
||||
|
||||
if (unlikely(!regs)) {
|
||||
memset(childregs, 0, sizeof(struct pt_regs));
|
||||
childregs->gr9 = usp; /* function */
|
||||
childregs->gr8 = arg;
|
||||
childregs->psr = PSR_S;
|
||||
p->thread.pc = (unsigned long) ret_from_kernel_thread;
|
||||
save_user_regs(p->thread.user);
|
||||
return 0;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/pci.h>
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#ifndef _ASM_X86_XEN_HYPERVISOR_H
|
||||
#define _ASM_X86_XEN_HYPERVISOR_H
|
||||
|
||||
/* arch/i386/kernel/setup.c */
|
||||
extern struct shared_info *HYPERVISOR_shared_info;
|
||||
extern struct start_info *xen_start_info;
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
memcpy(vcpu->run->mmio.data, frag->data, frag->len);
|
||||
memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len));
|
||||
return X86EMUL_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -3832,18 +3832,11 @@ mmio:
|
|||
bytes -= handled;
|
||||
val += handled;
|
||||
|
||||
while (bytes) {
|
||||
unsigned now = min(bytes, 8U);
|
||||
|
||||
frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
|
||||
frag->gpa = gpa;
|
||||
frag->data = val;
|
||||
frag->len = now;
|
||||
|
||||
gpa += now;
|
||||
val += now;
|
||||
bytes -= now;
|
||||
}
|
||||
WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS);
|
||||
frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
|
||||
frag->gpa = gpa;
|
||||
frag->data = val;
|
||||
frag->len = bytes;
|
||||
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_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->exit_reason = KVM_EXIT_MMIO;
|
||||
vcpu->run->mmio.phys_addr = gpa;
|
||||
|
@ -5522,28 +5515,44 @@ static int complete_emulated_pio(struct kvm_vcpu *vcpu)
|
|||
*
|
||||
* read:
|
||||
* for each fragment
|
||||
* write gpa, len
|
||||
* exit
|
||||
* copy data
|
||||
* for each mmio piece in the fragment
|
||||
* write gpa, len
|
||||
* exit
|
||||
* copy data
|
||||
* execute insn
|
||||
*
|
||||
* write:
|
||||
* for each fragment
|
||||
* write gpa, len
|
||||
* copy data
|
||||
* exit
|
||||
* for each mmio piece in the fragment
|
||||
* write gpa, len
|
||||
* copy data
|
||||
* exit
|
||||
*/
|
||||
static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct kvm_run *run = vcpu->run;
|
||||
struct kvm_mmio_fragment *frag;
|
||||
unsigned len;
|
||||
|
||||
BUG_ON(!vcpu->mmio_needed);
|
||||
|
||||
/* 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)
|
||||
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) {
|
||||
vcpu->mmio_needed = 0;
|
||||
if (vcpu->mmio_is_write)
|
||||
|
@ -5551,13 +5560,12 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
|
|||
vcpu->mmio_read_completed = 1;
|
||||
return complete_emulated_io(vcpu);
|
||||
}
|
||||
/* Initiate next fragment */
|
||||
++frag;
|
||||
|
||||
run->exit_reason = KVM_EXIT_MMIO;
|
||||
run->mmio.phys_addr = frag->gpa;
|
||||
if (vcpu->mmio_is_write)
|
||||
memcpy(run->mmio.data, frag->data, frag->len);
|
||||
run->mmio.len = frag->len;
|
||||
memcpy(run->mmio.data, frag->data, min(8u, frag->len));
|
||||
run->mmio.len = min(8u, frag->len);
|
||||
run->mmio.is_write = vcpu->mmio_is_write;
|
||||
vcpu->arch.complete_userspace_io = complete_emulated_mmio;
|
||||
return 0;
|
||||
|
|
|
@ -1288,6 +1288,25 @@ unsigned long xen_read_cr2_direct(void)
|
|||
return this_cpu_read(xen_vcpu_info.arch.cr2);
|
||||
}
|
||||
|
||||
void xen_flush_tlb_all(void)
|
||||
{
|
||||
struct mmuext_op *op;
|
||||
struct multicall_space mcs;
|
||||
|
||||
trace_xen_mmu_flush_tlb_all(0);
|
||||
|
||||
preempt_disable();
|
||||
|
||||
mcs = xen_mc_entry(sizeof(*op));
|
||||
|
||||
op = mcs.args;
|
||||
op->cmd = MMUEXT_TLB_FLUSH_ALL;
|
||||
MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
|
||||
|
||||
xen_mc_issue(PARAVIRT_LAZY_MMU);
|
||||
|
||||
preempt_enable();
|
||||
}
|
||||
static void xen_flush_tlb(void)
|
||||
{
|
||||
struct mmuext_op *op;
|
||||
|
@ -2518,7 +2537,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
|
|||
err = 0;
|
||||
out:
|
||||
|
||||
flush_tlb_all();
|
||||
xen_flush_tlb_all();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ config XTENSA
|
|||
select GENERIC_CPU_DEVICES
|
||||
select MODULES_USE_ELF_RELA
|
||||
select GENERIC_PCI_IOMAP
|
||||
select GENERIC_KERNEL_THREAD
|
||||
select GENERIC_KERNEL_EXECVE
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
help
|
||||
Xtensa processors are 32-bit RISC machines designed by Tensilica
|
||||
|
|
|
@ -62,6 +62,10 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
|
|||
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 */
|
||||
|
||||
/*
|
||||
|
|
|
@ -152,6 +152,7 @@ struct thread_struct {
|
|||
|
||||
/* Clearing a0 terminates the backtrace. */
|
||||
#define start_thread(regs, new_pc, new_sp) \
|
||||
memset(regs, 0, sizeof(*regs)); \
|
||||
regs->pc = new_pc; \
|
||||
regs->ps = USER_PS_VALUE; \
|
||||
regs->areg[1] = new_sp; \
|
||||
|
@ -168,9 +169,6 @@ struct mm_struct;
|
|||
/* Free all resources held by a thread. */
|
||||
#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 */
|
||||
#define copy_segments(p, mm) do { } while(0)
|
||||
#define release_segments(mm) do { } while(0)
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
struct pt_regs;
|
||||
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_ptrace(long, long, long, long);
|
||||
asmlinkage long xtensa_sigreturn(struct pt_regs*);
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
/*
|
||||
* 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 - 2005 Tensilica Inc.
|
||||
*/
|
||||
#ifndef _XTENSA_UNISTD_H
|
||||
#define _XTENSA_UNISTD_H
|
||||
|
||||
#define __ARCH_WANT_SYS_EXECVE
|
||||
#include <uapi/asm/unistd.h>
|
||||
|
||||
|
||||
/*
|
||||
* "Conditional" syscalls
|
||||
*
|
||||
|
@ -37,3 +30,5 @@
|
|||
#define __IGNORE_mmap /* use mmap2 */
|
||||
#define __IGNORE_vfork /* use clone */
|
||||
#define __IGNORE_fadvise64 /* use fadvise64_64 */
|
||||
|
||||
#endif /* _XTENSA_UNISTD_H */
|
||||
|
|
|
@ -1,14 +1,4 @@
|
|||
/*
|
||||
* 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
|
||||
#if !defined(_UAPI_XTENSA_UNISTD_H) || defined(__SYSCALL)
|
||||
#define _UAPI_XTENSA_UNISTD_H
|
||||
|
||||
#ifndef __SYSCALL
|
||||
|
@ -272,7 +262,7 @@ __SYSCALL(115, sys_sendmmsg, 4)
|
|||
#define __NR_clone 116
|
||||
__SYSCALL(116, xtensa_clone, 5)
|
||||
#define __NR_execve 117
|
||||
__SYSCALL(117, xtensa_execve, 3)
|
||||
__SYSCALL(117, sys_execve, 3)
|
||||
#define __NR_exit 118
|
||||
__SYSCALL(118, sys_exit, 1)
|
||||
#define __NR_exit_group 119
|
||||
|
@ -759,4 +749,6 @@ __SYSCALL(331, sys_kcmp, 5)
|
|||
|
||||
#define SYS_XTENSA_COUNT 5 /* count */
|
||||
|
||||
#undef __SYSCALL
|
||||
|
||||
#endif /* _UAPI_XTENSA_UNISTD_H */
|
||||
|
|
|
@ -1832,50 +1832,6 @@ ENTRY(system_call)
|
|||
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.
|
||||
*
|
||||
|
@ -1958,3 +1914,16 @@ ENTRY(ret_from_fork)
|
|||
|
||||
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)
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <asm/regs.h>
|
||||
|
||||
extern void ret_from_fork(void);
|
||||
extern void ret_from_kernel_thread(void);
|
||||
|
||||
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.
|
||||
*
|
||||
* 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:
|
||||
*
|
||||
* +------------------------+ <- sp in childregs (= tos)
|
||||
* +------------------------+
|
||||
* | childregs |
|
||||
* +------------------------+ <- thread.sp = sp in dummy-frame
|
||||
* | dummy-frame | (saved in dummy-frame spill-area)
|
||||
* +------------------------+
|
||||
*
|
||||
* We create a dummy frame to return to ret_from_fork:
|
||||
* a0 points to ret_from_fork (simulating a call4)
|
||||
* We create a dummy frame to return to either ret_from_fork or
|
||||
* ret_from_kernel_thread:
|
||||
* a0 points to ret_from_fork/ret_from_kernel_thread (simulating a call4)
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
int copy_thread(unsigned long clone_flags, unsigned long usp,
|
||||
unsigned long unused,
|
||||
struct task_struct * p, struct pt_regs * regs)
|
||||
int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
|
||||
unsigned long thread_fn_arg,
|
||||
struct task_struct *p, struct pt_regs *unused)
|
||||
{
|
||||
struct pt_regs *childregs;
|
||||
unsigned long tos;
|
||||
int user_mode = user_mode(regs);
|
||||
struct pt_regs *childregs = task_pt_regs(p);
|
||||
|
||||
#if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
|
||||
struct thread_info *ti;
|
||||
#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. */
|
||||
*((int*)childregs - 3) = (unsigned long)childregs;
|
||||
*((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;
|
||||
|
||||
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[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) {
|
||||
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 {
|
||||
int len = childregs->wmask & ~0xf;
|
||||
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...
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
childregs->areg[2] = childregs->areg[6];
|
||||
|
||||
} else {
|
||||
/* In kernel space, we start a new thread with a new stack. */
|
||||
childregs->wmask = 1;
|
||||
childregs->areg[1] = tos;
|
||||
p->thread.ra = MAKE_RA_FOR_CALL(
|
||||
(unsigned long)ret_from_kernel_thread, 1);
|
||||
|
||||
/* 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)
|
||||
|
@ -330,32 +371,5 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
|
|||
void __user *child_tid, long a5,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if (!newsp)
|
||||
newsp = regs->areg[1];
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,10 +32,8 @@ typedef void (*syscall_t)(void);
|
|||
syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
|
||||
[0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall,
|
||||
|
||||
#undef __SYSCALL
|
||||
#define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol,
|
||||
#undef __KERNEL_SYSCALLS__
|
||||
#include <asm/unistd.h>
|
||||
#include <uapi/asm/unistd.h>
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ EXPORT_SYMBOL(__strncpy_user);
|
|||
EXPORT_SYMBOL(clear_page);
|
||||
EXPORT_SYMBOL(copy_page);
|
||||
|
||||
EXPORT_SYMBOL(kernel_thread);
|
||||
EXPORT_SYMBOL(empty_zero_page);
|
||||
|
||||
/*
|
||||
|
|
|
@ -89,7 +89,7 @@ config BLK_DEV_INTEGRITY
|
|||
|
||||
config BLK_DEV_THROTTLING
|
||||
bool "Block layer bio throttling support"
|
||||
depends on BLK_CGROUP=y && EXPERIMENTAL
|
||||
depends on BLK_CGROUP=y
|
||||
default n
|
||||
---help---
|
||||
Block layer bio throttling support. It can be used to limit
|
||||
|
|
|
@ -285,6 +285,13 @@ static void blkg_destroy_all(struct request_queue *q)
|
|||
blkg_destroy(blkg);
|
||||
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)
|
||||
|
@ -326,6 +333,9 @@ struct request_list *__blk_queue_next_rl(struct request_list *rl,
|
|||
*/
|
||||
if (rl == &q->root_rl) {
|
||||
ent = &q->blkg_list;
|
||||
/* There are no more block groups, hence no request lists */
|
||||
if (list_empty(ent))
|
||||
return NULL;
|
||||
} else {
|
||||
blkg = container_of(rl, struct blkcg_gq, rl);
|
||||
ent = &blkg->q_node;
|
||||
|
|
|
@ -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 *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)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1345,12 +1345,15 @@ static int
|
|||
acpi_video_bus_get_devices(struct acpi_video_bus *video,
|
||||
struct acpi_device *device)
|
||||
{
|
||||
int status;
|
||||
int status = 0;
|
||||
struct acpi_device *dev;
|
||||
|
||||
status = acpi_video_device_enumerate(video);
|
||||
if (status)
|
||||
return status;
|
||||
/*
|
||||
* There are systems where video module known to work fine regardless
|
||||
* of broken _DOD and ignoring returned value here doesn't cause
|
||||
* any issues later.
|
||||
*/
|
||||
acpi_video_device_enumerate(video);
|
||||
|
||||
list_for_each_entry(dev, &device->children, node) {
|
||||
|
||||
|
|
|
@ -131,6 +131,7 @@ config BLK_CPQ_DA
|
|||
config BLK_CPQ_CISS_DA
|
||||
tristate "Compaq Smart Array 5xxx support"
|
||||
depends on PCI
|
||||
select CHECK_SIGNATURE
|
||||
help
|
||||
This is the driver for Compaq Smart Array 5xxx controllers.
|
||||
Everyone using these boards should say Y here.
|
||||
|
@ -166,8 +167,8 @@ config BLK_DEV_DAC960
|
|||
module will be called DAC960.
|
||||
|
||||
config BLK_DEV_UMEM
|
||||
tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)"
|
||||
depends on PCI && EXPERIMENTAL
|
||||
tristate "Micro Memory MM5415 Battery Backed RAM support"
|
||||
depends on PCI
|
||||
---help---
|
||||
Saying Y here will include support for the MM5415 family of
|
||||
battery backed (Non-volatile) RAM cards.
|
||||
|
@ -430,8 +431,8 @@ config CDROM_PKTCDVD_BUFFERS
|
|||
a disc is opened for writing.
|
||||
|
||||
config CDROM_PKTCDVD_WCACHE
|
||||
bool "Enable write caching (EXPERIMENTAL)"
|
||||
depends on CDROM_PKTCDVD && EXPERIMENTAL
|
||||
bool "Enable write caching"
|
||||
depends on CDROM_PKTCDVD
|
||||
help
|
||||
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
|
||||
|
@ -508,8 +509,8 @@ config XEN_BLKDEV_BACKEND
|
|||
|
||||
|
||||
config VIRTIO_BLK
|
||||
tristate "Virtio block driver (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL && VIRTIO
|
||||
tristate "Virtio block driver"
|
||||
depends on VIRTIO
|
||||
---help---
|
||||
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.
|
||||
|
@ -528,7 +529,7 @@ config BLK_DEV_HD
|
|||
|
||||
config BLK_DEV_RBD
|
||||
tristate "Rados block device (RBD)"
|
||||
depends on INET && EXPERIMENTAL && BLOCK
|
||||
depends on INET && BLOCK
|
||||
select CEPH_LIB
|
||||
select LIBCRC32C
|
||||
select CRYPTO_AES
|
||||
|
|
|
@ -5205,7 +5205,6 @@ static void cciss_shutdown(struct pci_dev *pdev)
|
|||
return;
|
||||
}
|
||||
/* 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,
|
||||
4, 0, CTLR_LUNID, TYPE_CMD);
|
||||
kfree(flush_buf);
|
||||
|
|
|
@ -4109,12 +4109,19 @@ static struct platform_driver floppy_driver = {
|
|||
|
||||
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)
|
||||
{
|
||||
int drive = (*part & 3) | ((*part & 0x80) >> 5);
|
||||
if (drive >= N_DRIVE ||
|
||||
!(allowed_drive_mask & (1 << drive)) ||
|
||||
fdc_state[FDC(drive)].version == FDC_NONE)
|
||||
if (drive >= N_DRIVE || !floppy_available(drive))
|
||||
return NULL;
|
||||
if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
|
||||
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)
|
||||
{
|
||||
int i, unit, drive;
|
||||
int err, dr;
|
||||
int i, unit, drive, err;
|
||||
|
||||
set_debugt();
|
||||
interruptjiffies = resultjiffies = jiffies;
|
||||
|
@ -4137,34 +4143,32 @@ static int __init do_floppy_init(void)
|
|||
|
||||
raw_cmd = NULL;
|
||||
|
||||
for (dr = 0; dr < N_DRIVE; dr++) {
|
||||
disks[dr] = alloc_disk(1);
|
||||
if (!disks[dr]) {
|
||||
floppy_wq = alloc_ordered_workqueue("floppy", 0);
|
||||
if (!floppy_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
for (drive = 0; drive < N_DRIVE; drive++) {
|
||||
disks[drive] = alloc_disk(1);
|
||||
if (!disks[drive]) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_disk;
|
||||
}
|
||||
|
||||
floppy_wq = alloc_ordered_workqueue("floppy", 0);
|
||||
if (!floppy_wq) {
|
||||
disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock);
|
||||
if (!disks[drive]->queue) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_disk;
|
||||
}
|
||||
|
||||
disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
|
||||
if (!disks[dr]->queue) {
|
||||
err = -ENOMEM;
|
||||
goto out_destroy_workq;
|
||||
}
|
||||
blk_queue_max_hw_sectors(disks[drive]->queue, 64);
|
||||
disks[drive]->major = FLOPPY_MAJOR;
|
||||
disks[drive]->first_minor = TOMINOR(drive);
|
||||
disks[drive]->fops = &floppy_fops;
|
||||
sprintf(disks[drive]->disk_name, "fd%d", drive);
|
||||
|
||||
blk_queue_max_hw_sectors(disks[dr]->queue, 64);
|
||||
disks[dr]->major = FLOPPY_MAJOR;
|
||||
disks[dr]->first_minor = TOMINOR(dr);
|
||||
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;
|
||||
init_timer(&motor_off_timer[drive]);
|
||||
motor_off_timer[drive].data = drive;
|
||||
motor_off_timer[drive].function = motor_off_callback;
|
||||
}
|
||||
|
||||
err = register_blkdev(FLOPPY_MAJOR, "fd");
|
||||
|
@ -4282,9 +4286,7 @@ static int __init do_floppy_init(void)
|
|||
}
|
||||
|
||||
for (drive = 0; drive < N_DRIVE; drive++) {
|
||||
if (!(allowed_drive_mask & (1 << drive)))
|
||||
continue;
|
||||
if (fdc_state[FDC(drive)].version == FDC_NONE)
|
||||
if (!floppy_available(drive))
|
||||
continue;
|
||||
|
||||
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]);
|
||||
if (err)
|
||||
goto out_release_dma;
|
||||
goto out_remove_drives;
|
||||
|
||||
err = device_create_file(&floppy_device[drive].dev,
|
||||
&dev_attr_cmos);
|
||||
|
@ -4311,29 +4313,34 @@ static int __init do_floppy_init(void)
|
|||
|
||||
out_unreg_platform_dev:
|
||||
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:
|
||||
if (atomic_read(&usage_count))
|
||||
floppy_release_irq_and_dma();
|
||||
out_unreg_region:
|
||||
blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
|
||||
platform_driver_unregister(&floppy_driver);
|
||||
out_destroy_workq:
|
||||
destroy_workqueue(floppy_wq);
|
||||
out_unreg_blkdev:
|
||||
unregister_blkdev(FLOPPY_MAJOR, "fd");
|
||||
out_put_disk:
|
||||
while (dr--) {
|
||||
del_timer_sync(&motor_off_timer[dr]);
|
||||
if (disks[dr]->queue) {
|
||||
blk_cleanup_queue(disks[dr]->queue);
|
||||
/*
|
||||
* put_disk() is not paired with add_disk() and
|
||||
* will put queue reference one extra time. fix it.
|
||||
*/
|
||||
disks[dr]->queue = NULL;
|
||||
for (drive = 0; drive < N_DRIVE; drive++) {
|
||||
if (!disks[drive])
|
||||
break;
|
||||
if (disks[drive]->queue) {
|
||||
del_timer_sync(&motor_off_timer[drive]);
|
||||
blk_cleanup_queue(disks[drive]->queue);
|
||||
disks[drive]->queue = NULL;
|
||||
}
|
||||
put_disk(disks[dr]);
|
||||
put_disk(disks[drive]);
|
||||
}
|
||||
destroy_workqueue(floppy_wq);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -4551,8 +4558,7 @@ static void __exit floppy_module_exit(void)
|
|||
for (drive = 0; drive < N_DRIVE; drive++) {
|
||||
del_timer_sync(&motor_off_timer[drive]);
|
||||
|
||||
if ((allowed_drive_mask & (1 << drive)) &&
|
||||
fdc_state[FDC(drive)].version != FDC_NONE) {
|
||||
if (floppy_available(drive)) {
|
||||
del_gendisk(disks[drive]);
|
||||
device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
|
||||
platform_device_unregister(&floppy_device[drive]);
|
||||
|
|
|
@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo)
|
|||
if (lo->lo_state != Lo_bound)
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -2035,8 +2035,9 @@ static unsigned int implicit_sector(unsigned char command,
|
|||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
|
||||
static void mtip_set_timeout(struct driver_data *dd,
|
||||
struct host_to_dev_fis *fis,
|
||||
unsigned int *timeout, u8 erasemode)
|
||||
{
|
||||
switch (fis->command) {
|
||||
case ATA_CMD_DOWNLOAD_MICRO:
|
||||
|
@ -2044,7 +2045,10 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
|
|||
break;
|
||||
case ATA_CMD_SEC_ERASE_UNIT:
|
||||
case 0xFC:
|
||||
*timeout = 240000; /* 4 minutes */
|
||||
if (erasemode)
|
||||
*timeout = ((*(dd->port->identify + 90) * 2) * 60000);
|
||||
else
|
||||
*timeout = ((*(dd->port->identify + 89) * 2) * 60000);
|
||||
break;
|
||||
case ATA_CMD_STANDBYNOW1:
|
||||
*timeout = 120000; /* 2 minutes */
|
||||
|
@ -2087,6 +2091,7 @@ static int exec_drive_taskfile(struct driver_data *dd,
|
|||
unsigned int transfer_size;
|
||||
unsigned long task_file_data;
|
||||
int intotal = outtotal + req_task->out_size;
|
||||
int erasemode = 0;
|
||||
|
||||
taskout = req_task->out_size;
|
||||
taskin = req_task->in_size;
|
||||
|
@ -2212,7 +2217,13 @@ static int exec_drive_taskfile(struct driver_data *dd,
|
|||
fis.lba_hi,
|
||||
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.*/
|
||||
if (force_single_sector)
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
/* offset of Device Control register in PCIe extended capabilites space */
|
||||
#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 */
|
||||
#define MTIP_MAX_RETRIES 2
|
||||
|
||||
|
|
|
@ -158,8 +158,8 @@ struct xen_vbd {
|
|||
struct block_device *bdev;
|
||||
/* Cached size parameter. */
|
||||
sector_t size;
|
||||
bool flush_support;
|
||||
bool discard_secure;
|
||||
unsigned int flush_support:1;
|
||||
unsigned int discard_secure:1;
|
||||
};
|
||||
|
||||
struct backend_info;
|
||||
|
|
|
@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
|
|||
{
|
||||
struct xen_blkif *blkif;
|
||||
|
||||
blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL);
|
||||
blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL);
|
||||
if (!blkif)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memset(blkif, 0, sizeof(*blkif));
|
||||
blkif->domid = domid;
|
||||
spin_lock_init(&blkif->blk_ring_lock);
|
||||
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))
|
||||
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(mode, "%s\n", be->mode);
|
||||
|
||||
int xenvbd_sysfs_addif(struct xenbus_device *dev)
|
||||
static int xenvbd_sysfs_addif(struct xenbus_device *dev)
|
||||
{
|
||||
int error;
|
||||
|
||||
|
@ -281,7 +280,7 @@ fail1: device_remove_file(&dev->dev, &dev_attr_physical_device);
|
|||
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);
|
||||
device_remove_file(&dev->dev, &dev_attr_mode);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Maintainer:
|
||||
* Andreas Herrmann <andreas.herrmann3@amd.com>
|
||||
* Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
*
|
||||
* Based on the powernow-k7.c module written by Dave Jones.
|
||||
* (C) 2003 Dave Jones on behalf of SuSE Labs
|
||||
|
|
|
@ -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->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL);
|
||||
chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL);
|
||||
if (!chip->buffer) {
|
||||
ret = -ENOMEM;
|
||||
goto exit_destroy;
|
||||
|
|
|
@ -244,6 +244,8 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
mvebu_gpio_set(chip, pin, value);
|
||||
|
||||
spin_lock_irqsave(&mvchip->lock, flags);
|
||||
u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
|
||||
u &= ~(1 << pin);
|
||||
|
@ -644,7 +646,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
|
|||
ct->handler = handle_edge_irq;
|
||||
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);
|
||||
|
||||
/* Setup irq domain on top of the generic chip. */
|
||||
|
|
|
@ -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,
|
||||
unsigned trigger)
|
||||
{
|
||||
|
@ -539,6 +573,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
|
|||
_set_gpio_irqenable(bank, gpio, 0);
|
||||
_clear_gpio_irqstatus(bank, gpio);
|
||||
_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 */
|
||||
|
|
|
@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d)
|
|||
unsigned long 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);
|
||||
spin_unlock_irqrestore(&tgpio->lock, flags);
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d)
|
|||
unsigned long 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);
|
||||
spin_unlock_irqrestore(&tgpio->lock, flags);
|
||||
}
|
||||
|
|
|
@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class,
|
|||
*/
|
||||
|
||||
status = gpio_request(gpio, "sysfs");
|
||||
if (status < 0)
|
||||
if (status < 0) {
|
||||
if (status == -EPROBE_DEFER)
|
||||
status = -ENODEV;
|
||||
goto done;
|
||||
|
||||
}
|
||||
status = gpio_export(gpio, true);
|
||||
if (status < 0)
|
||||
gpio_free(gpio);
|
||||
|
@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label)
|
|||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
if (!gpio_is_valid(gpio))
|
||||
if (!gpio_is_valid(gpio)) {
|
||||
status = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
desc = &gpio_desc[gpio];
|
||||
chip = desc->chip;
|
||||
if (chip == NULL)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
config DRM_EXYNOS
|
||||
tristate "DRM Support for Samsung SoC EXYNOS Series"
|
||||
depends on DRM && PLAT_SAMSUNG
|
||||
depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)
|
||||
select DRM_KMS_HELPER
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
|
|
|
@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
|
|||
exynos_connector->encoder_id = encoder->base.id;
|
||||
exynos_connector->manager = manager;
|
||||
exynos_connector->dpms = DRM_MODE_DPMS_OFF;
|
||||
connector->dpms = DRM_MODE_DPMS_OFF;
|
||||
connector->encoder = encoder;
|
||||
|
||||
err = drm_mode_connector_attach_encoder(connector, encoder);
|
||||
|
|
|
@ -43,12 +43,14 @@
|
|||
* @manager: specific encoder has its own manager to control a hardware
|
||||
* appropriately and we can access a hardware drawing on this manager.
|
||||
* @dpms: store the encoder dpms value.
|
||||
* @updated: indicate whether overlay data updating is needed or not.
|
||||
*/
|
||||
struct exynos_drm_encoder {
|
||||
struct drm_crtc *old_crtc;
|
||||
struct drm_encoder drm_encoder;
|
||||
struct exynos_drm_manager *manager;
|
||||
int dpms;
|
||||
int dpms;
|
||||
bool updated;
|
||||
};
|
||||
|
||||
static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
|
||||
|
@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
|
|||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
if (manager_ops && manager_ops->apply)
|
||||
manager_ops->apply(manager->dev);
|
||||
if (!exynos_encoder->updated)
|
||||
manager_ops->apply(manager->dev);
|
||||
|
||||
exynos_drm_connector_power(encoder, mode);
|
||||
exynos_encoder->dpms = mode;
|
||||
break;
|
||||
|
@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
|
|||
case DRM_MODE_DPMS_OFF:
|
||||
exynos_drm_connector_power(encoder, mode);
|
||||
exynos_encoder->dpms = mode;
|
||||
exynos_encoder->updated = false;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unspecified mode %d\n", mode);
|
||||
|
@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
|
|||
|
||||
static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
|
||||
{
|
||||
struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
|
||||
struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
|
||||
struct exynos_drm_manager *manager = exynos_encoder->manager;
|
||||
struct exynos_drm_manager_ops *manager_ops = manager->ops;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (manager_ops && manager_ops->commit)
|
||||
manager_ops->commit(manager->dev);
|
||||
|
||||
/*
|
||||
* this will avoid one issue that overlay data is updated to
|
||||
* real hardware two times.
|
||||
* And this variable will be used to check if the data was
|
||||
* already updated or not by exynos_drm_encoder_dpms function.
|
||||
*/
|
||||
exynos_encoder->updated = true;
|
||||
}
|
||||
|
||||
static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
|
||||
|
@ -400,19 +414,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
|
|||
if (manager_ops && manager_ops->dpms)
|
||||
manager_ops->dpms(manager->dev, mode);
|
||||
|
||||
/*
|
||||
* set current mode to new one so that data aren't updated into
|
||||
* registers by drm_helper_connector_dpms two times.
|
||||
*
|
||||
* in case that drm_crtc_helper_set_mode() is called,
|
||||
* overlay_ops->commit() and manager_ops->commit() callbacks
|
||||
* can be called two times, first at drm_crtc_helper_set_mode()
|
||||
* and second at drm_helper_connector_dpms().
|
||||
* so with this setting, when drm_helper_connector_dpms() is called
|
||||
* encoder->funcs->dpms() will be ignored.
|
||||
*/
|
||||
exynos_encoder->dpms = mode;
|
||||
|
||||
/*
|
||||
* if this condition is ok then it means that the crtc is already
|
||||
* detached from encoder and last function for detaching is properly
|
||||
|
|
|
@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)
|
|||
const struct of_device_id *match;
|
||||
match = of_match_node(of_match_ptr(mixer_match_types),
|
||||
pdev->dev.of_node);
|
||||
drv = match->data;
|
||||
drv = (struct mixer_drv_data *)match->data;
|
||||
} else {
|
||||
drv = (struct mixer_drv_data *)
|
||||
platform_get_device_id(pdev)->driver_data;
|
||||
|
|
|
@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
goto put_gmch;
|
||||
}
|
||||
|
||||
i915_kick_out_firmware_fb(dev_priv);
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
i915_kick_out_firmware_fb(dev_priv);
|
||||
|
||||
pci_set_master(dev->pdev);
|
||||
|
||||
|
|
|
@ -729,7 +729,7 @@ void intel_crt_init(struct drm_device *dev)
|
|||
|
||||
crt->base.type = INTEL_OUTPUT_ANALOG;
|
||||
crt->base.cloneable = true;
|
||||
if (IS_HASWELL(dev))
|
||||
if (IS_HASWELL(dev) || IS_I830(dev))
|
||||
crt->base.crtc_mask = (1 << 0);
|
||||
else
|
||||
crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
|
||||
|
|
|
@ -341,9 +341,17 @@ static int intel_overlay_off(struct intel_overlay *overlay)
|
|||
intel_ring_emit(ring, flip_addr);
|
||||
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
/* turn overlay off */
|
||||
intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
||||
intel_ring_emit(ring, flip_addr);
|
||||
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
if (IS_I830(dev)) {
|
||||
/* Workaround: Don't disable the overlay fully, since otherwise
|
||||
* it dies on the next OVERLAY_ON cmd. */
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
} else {
|
||||
intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
|
||||
intel_ring_emit(ring, flip_addr);
|
||||
intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
|
||||
}
|
||||
intel_ring_advance(ring);
|
||||
|
||||
return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
|
||||
|
|
|
@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev)
|
|||
props.type = BACKLIGHT_RAW;
|
||||
props.max_brightness = _intel_panel_get_max_backlight(dev);
|
||||
if (props.max_brightness == 0) {
|
||||
DRM_ERROR("Failed to get maximum backlight value\n");
|
||||
DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
dev_priv->backlight =
|
||||
|
|
|
@ -894,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
|
|||
}
|
||||
#endif
|
||||
|
||||
static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
|
||||
unsigned if_index, uint8_t tx_rate,
|
||||
uint8_t *data, unsigned length)
|
||||
{
|
||||
uint8_t set_buf_index[2] = { if_index, 0 };
|
||||
uint8_t hbuf_size, tmp[8];
|
||||
int i;
|
||||
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_INDEX,
|
||||
set_buf_index, 2))
|
||||
return false;
|
||||
|
||||
if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO,
|
||||
&hbuf_size, 1))
|
||||
return false;
|
||||
|
||||
/* Buffer size is 0 based, hooray! */
|
||||
hbuf_size++;
|
||||
|
||||
DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n",
|
||||
if_index, length, hbuf_size);
|
||||
|
||||
for (i = 0; i < hbuf_size; i += 8) {
|
||||
memset(tmp, 0, 8);
|
||||
if (i < length)
|
||||
memcpy(tmp, data + i, min_t(unsigned, 8, length - i));
|
||||
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_DATA,
|
||||
tmp, 8))
|
||||
return false;
|
||||
}
|
||||
|
||||
return intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_TXRATE,
|
||||
&tx_rate, 1);
|
||||
}
|
||||
|
||||
static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
|
||||
{
|
||||
struct dip_infoframe avi_if = {
|
||||
|
@ -901,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
|
|||
.ver = DIP_VERSION_AVI,
|
||||
.len = DIP_LEN_AVI,
|
||||
};
|
||||
uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
|
||||
uint8_t set_buf_index[2] = { 1, 0 };
|
||||
uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
|
||||
uint64_t *data = (uint64_t *)sdvo_data;
|
||||
unsigned i;
|
||||
|
||||
intel_dip_infoframe_csum(&avi_if);
|
||||
|
||||
|
@ -915,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
|
|||
sdvo_data[3] = avi_if.checksum;
|
||||
memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
|
||||
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_INDEX,
|
||||
set_buf_index, 2))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < sizeof(sdvo_data); i += 8) {
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_DATA,
|
||||
data, 8))
|
||||
return false;
|
||||
data++;
|
||||
}
|
||||
|
||||
return intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_TXRATE,
|
||||
&tx_rate, 1);
|
||||
return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
|
||||
SDVO_HBUF_TX_VSYNC,
|
||||
sdvo_data, sizeof(sdvo_data));
|
||||
}
|
||||
|
||||
static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
|
||||
|
|
|
@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {
|
|||
#define SDVO_CMD_SET_AUDIO_STAT 0x91
|
||||
#define SDVO_CMD_GET_AUDIO_STAT 0x92
|
||||
#define SDVO_CMD_SET_HBUF_INDEX 0x93
|
||||
#define SDVO_HBUF_INDEX_ELD 0
|
||||
#define SDVO_HBUF_INDEX_AVI_IF 1
|
||||
#define SDVO_CMD_GET_HBUF_INDEX 0x94
|
||||
#define SDVO_CMD_GET_HBUF_INFO 0x95
|
||||
#define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96
|
||||
|
|
|
@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
|
|||
node = kzalloc(sizeof(*node), GFP_KERNEL);
|
||||
if (!node)
|
||||
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->fl_entry, &mm->free);
|
||||
mm->heap_nodes++;
|
||||
mm->heap_size += length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ struct nouveau_mm {
|
|||
|
||||
u32 block_size;
|
||||
int heap_nodes;
|
||||
u32 heap_size;
|
||||
};
|
||||
|
||||
int nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
|
||||
|
|
|
@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
((priv->base.ram.size & 0x000000ff) << 32);
|
||||
|
||||
tags = nv_rd32(priv, 0x100320);
|
||||
if (tags) {
|
||||
ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
|
||||
if (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;
|
||||
switch (device->chipset) {
|
||||
|
|
|
@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||
case DCB_I2C_NVIO_BIT:
|
||||
port->drive = info.drive & 0x0f;
|
||||
if (device->card_type < NV_D0) {
|
||||
if (info.drive >= ARRAY_SIZE(nv50_i2c_port))
|
||||
if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
|
||||
break;
|
||||
port->drive = nv50_i2c_port[port->drive];
|
||||
port->sense = port->drive;
|
||||
|
|
|
@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)
|
|||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nouveau_disp *pdisp = nouveau_disp(drm->device);
|
||||
struct nouveau_display *disp;
|
||||
u32 pclass = dev->pdev->class >> 8;
|
||||
int ret, gen;
|
||||
|
||||
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_disable(dev);
|
||||
|
||||
if (nv_device(drm->device)->card_type < NV_50)
|
||||
ret = nv04_display_create(dev);
|
||||
else
|
||||
if (nv_device(drm->device)->card_type < NV_D0)
|
||||
ret = nv50_display_create(dev);
|
||||
else
|
||||
ret = nvd0_display_create(dev);
|
||||
if (ret)
|
||||
goto disp_create_err;
|
||||
|
||||
if (dev->mode_config.num_crtc) {
|
||||
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
|
||||
if (nouveau_modeset == 1 ||
|
||||
(nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) {
|
||||
if (nv_device(drm->device)->card_type < NV_50)
|
||||
ret = nv04_display_create(dev);
|
||||
else
|
||||
if (nv_device(drm->device)->card_type < NV_D0)
|
||||
ret = nv50_display_create(dev);
|
||||
else
|
||||
ret = nvd0_display_create(dev);
|
||||
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;
|
||||
|
||||
vblank_err:
|
||||
|
@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)
|
|||
nouveau_backlight_exit(dev);
|
||||
drm_vblank_cleanup(dev);
|
||||
|
||||
disp->dtor(dev);
|
||||
if (disp->dtor)
|
||||
disp->dtor(dev);
|
||||
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
drm_mode_config_cleanup(dev);
|
||||
|
|
|
@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");
|
|||
static int nouveau_noaccel = 0;
|
||||
module_param_named(noaccel, nouveau_noaccel, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(modeset, "enable driver");
|
||||
static int nouveau_modeset = -1;
|
||||
MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
|
||||
"0 = disabled, 1 = enabled, 2 = headless)");
|
||||
int nouveau_modeset = -1;
|
||||
module_param_named(modeset, nouveau_modeset, int, 0400);
|
||||
|
||||
static struct drm_driver driver;
|
||||
|
@ -363,7 +364,8 @@ nouveau_drm_unload(struct drm_device *dev)
|
|||
|
||||
nouveau_pm_fini(dev);
|
||||
|
||||
nouveau_display_fini(dev);
|
||||
if (dev->mode_config.num_crtc)
|
||||
nouveau_display_fini(dev);
|
||||
nouveau_display_destroy(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)
|
||||
return 0;
|
||||
|
||||
NV_INFO(drm, "suspending fbcon...\n");
|
||||
nouveau_fbcon_set_suspend(dev, 1);
|
||||
if (dev->mode_config.num_crtc) {
|
||||
NV_INFO(drm, "suspending fbcon...\n");
|
||||
nouveau_fbcon_set_suspend(dev, 1);
|
||||
|
||||
NV_INFO(drm, "suspending display...\n");
|
||||
ret = nouveau_display_suspend(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
NV_INFO(drm, "suspending display...\n");
|
||||
ret = nouveau_display_suspend(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
NV_INFO(drm, "evicting buffers...\n");
|
||||
ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
|
||||
|
@ -445,8 +449,10 @@ fail_client:
|
|||
nouveau_client_init(&cli->base);
|
||||
}
|
||||
|
||||
NV_INFO(drm, "resuming display...\n");
|
||||
nouveau_display_resume(dev);
|
||||
if (dev->mode_config.num_crtc) {
|
||||
NV_INFO(drm, "resuming display...\n");
|
||||
nouveau_display_resume(dev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -486,8 +492,10 @@ nouveau_drm_resume(struct pci_dev *pdev)
|
|||
nouveau_irq_postinstall(dev);
|
||||
nouveau_pm_resume(dev);
|
||||
|
||||
NV_INFO(drm, "resuming display...\n");
|
||||
nouveau_display_resume(dev);
|
||||
if (dev->mode_config.num_crtc) {
|
||||
NV_INFO(drm, "resuming display...\n");
|
||||
nouveau_display_resume(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -662,9 +670,7 @@ nouveau_drm_init(void)
|
|||
#ifdef CONFIG_VGA_CONSOLE
|
||||
if (vgacon_text_force())
|
||||
nouveau_modeset = 0;
|
||||
else
|
||||
#endif
|
||||
nouveau_modeset = 1;
|
||||
}
|
||||
|
||||
if (!nouveau_modeset)
|
||||
|
|
|
@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);
|
|||
nv_info((cli), fmt, ##args); \
|
||||
} while (0)
|
||||
|
||||
extern int nouveau_modeset;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
|
|||
|
||||
nv_subdev(pmc)->intr(nv_subdev(pmc));
|
||||
|
||||
if (device->card_type >= NV_D0) {
|
||||
if (nv_rd32(device, 0x000100) & 0x04000000)
|
||||
nvd0_display_intr(dev);
|
||||
} else
|
||||
if (device->card_type >= NV_50) {
|
||||
if (nv_rd32(device, 0x000100) & 0x04000000)
|
||||
nv50_display_intr(dev);
|
||||
if (dev->mode_config.num_crtc) {
|
||||
if (device->card_type >= NV_D0) {
|
||||
if (nv_rd32(device, 0x000100) & 0x04000000)
|
||||
nvd0_display_intr(dev);
|
||||
} else
|
||||
if (device->card_type >= NV_50) {
|
||||
if (nv_rd32(device, 0x000100) & 0x04000000)
|
||||
nv50_display_intr(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
|
|
@ -220,7 +220,7 @@ out:
|
|||
NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
|
|||
|
||||
if (nv17_dac_sample_load(encoder) &
|
||||
NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
|
||||
NV_INFO(drm, "Load detected on output %c\n",
|
||||
'@' + ffs(dcb->or));
|
||||
NV_DEBUG(drm, "Load detected on output %c\n",
|
||||
'@' + ffs(dcb->or));
|
||||
return connector_status_connected;
|
||||
} else {
|
||||
return connector_status_disconnected;
|
||||
|
@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)
|
|||
|
||||
helper->dpms(encoder, DRM_MODE_DPMS_ON);
|
||||
|
||||
NV_INFO(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, '@' + ffs(nv_encoder->dcb->or));
|
||||
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, '@' + ffs(nv_encoder->dcb->or));
|
||||
}
|
||||
|
||||
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;
|
||||
nv_encoder->last_dpms = mode;
|
||||
|
||||
NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
|
||||
nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
|
||||
}
|
||||
|
|
|
@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
|
|||
|
||||
helper->dpms(encoder, DRM_MODE_DPMS_ON);
|
||||
|
||||
NV_INFO(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, '@' + ffs(nv_encoder->dcb->or));
|
||||
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, '@' + ffs(nv_encoder->dcb->or));
|
||||
}
|
||||
|
||||
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;
|
||||
nv_encoder->last_dpms = mode;
|
||||
|
||||
NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
|
||||
if (was_powersaving && is_powersaving_dpms(mode))
|
||||
return;
|
||||
|
@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
|
|||
return;
|
||||
nv_encoder->last_dpms = mode;
|
||||
|
||||
NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
|
||||
nv04_dfp_update_backlight(encoder, mode);
|
||||
nv04_dfp_update_fp_control(encoder, mode);
|
||||
|
|
|
@ -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;
|
||||
uint8_t crtc1A;
|
||||
|
||||
NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
|
||||
mode, nv_encoder->dcb->index);
|
||||
|
||||
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);
|
||||
|
||||
NV_INFO(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,
|
||||
'@' + ffs(nv_encoder->dcb->or));
|
||||
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, '@' + ffs(nv_encoder->dcb->or));
|
||||
}
|
||||
|
||||
static void nv04_tv_destroy(struct drm_encoder *encoder)
|
||||
|
|
|
@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p,
|
|||
/* macro tile width & height */
|
||||
palign = (8 * surf->bankw * track->npipes) * surf->mtilea;
|
||||
halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea;
|
||||
mtileb = (palign / 8) * (halign / 8) * tileb;;
|
||||
mtileb = (palign / 8) * (halign / 8) * tileb;
|
||||
mtile_pr = surf->nbx / palign;
|
||||
mtile_ps = (mtile_pr * surf->nby) / halign;
|
||||
surf->layer_size = mtile_ps * mtileb * slice_pt;
|
||||
|
|
|
@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
|
|||
}
|
||||
|
||||
/**
|
||||
* radeon_atpx_switchto - switch to the requested GPU
|
||||
* radeon_atpx_power_state - power down/up the requested GPU
|
||||
*
|
||||
* @id: GPU to switch to
|
||||
* @id: GPU to power down/up
|
||||
* @state: requested power state (0 = off, 1 = on)
|
||||
*
|
||||
* Execute the necessary ATPX function to power down/up the discrete GPU
|
||||
|
|
|
@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
|||
struct drm_mode_object *obj;
|
||||
int i;
|
||||
enum drm_connector_status ret = connector_status_disconnected;
|
||||
bool dret = false;
|
||||
bool dret = false, broken_edid = false;
|
||||
|
||||
if (!force && radeon_check_hpd_status_unchanged(connector))
|
||||
return connector->status;
|
||||
|
@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
|||
ret = connector_status_disconnected;
|
||||
DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));
|
||||
radeon_connector->ddc_bus = NULL;
|
||||
} else {
|
||||
ret = connector_status_connected;
|
||||
broken_edid = true; /* defer use_digital to later */
|
||||
}
|
||||
} else {
|
||||
radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
|
||||
|
@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
|||
|
||||
encoder_funcs = encoder->helper_private;
|
||||
if (encoder_funcs->detect) {
|
||||
if (ret != connector_status_connected) {
|
||||
ret = encoder_funcs->detect(encoder, connector);
|
||||
if (ret == connector_status_connected) {
|
||||
radeon_connector->use_digital = false;
|
||||
if (!broken_edid) {
|
||||
if (ret != connector_status_connected) {
|
||||
/* deal with analog monitors without DDC */
|
||||
ret = encoder_funcs->detect(encoder, connector);
|
||||
if (ret == connector_status_connected) {
|
||||
radeon_connector->use_digital = false;
|
||||
}
|
||||
if (ret != connector_status_disconnected)
|
||||
radeon_connector->detected_by_load = true;
|
||||
}
|
||||
if (ret != connector_status_disconnected)
|
||||
radeon_connector->detected_by_load = true;
|
||||
} else {
|
||||
enum drm_connector_status lret;
|
||||
/* assume digital unless load detected otherwise */
|
||||
radeon_connector->use_digital = true;
|
||||
lret = encoder_funcs->detect(encoder, connector);
|
||||
DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret);
|
||||
if (lret == connector_status_connected)
|
||||
radeon_connector->use_digital = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t crtc_ext_cntl = 0;
|
||||
uint32_t mask;
|
||||
|
||||
if (radeon_crtc->crtc_id)
|
||||
|
@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
RADEON_CRTC_VSYNC_DIS |
|
||||
RADEON_CRTC_HSYNC_DIS);
|
||||
|
||||
/*
|
||||
* On all dual CRTC GPUs this bit controls the CRTC of the primary DAC.
|
||||
* Therefore it is set in the DAC DMPS function.
|
||||
* This is different for GPU's with a single CRTC but a primary and a
|
||||
* TV DAC: here it controls the single CRTC no matter where it is
|
||||
* routed. Therefore we set it here.
|
||||
*/
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC)
|
||||
crtc_ext_cntl = RADEON_CRTC_CRT_ON;
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
radeon_crtc->enabled = true;
|
||||
|
@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
else {
|
||||
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
|
||||
RADEON_CRTC_DISP_REQ_EN_B));
|
||||
WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask);
|
||||
WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));
|
||||
}
|
||||
drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
|
||||
radeon_crtc_load_lut(crtc);
|
||||
|
@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
else {
|
||||
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
|
||||
RADEON_CRTC_DISP_REQ_EN_B));
|
||||
WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
|
||||
WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl));
|
||||
}
|
||||
radeon_crtc->enabled = false;
|
||||
/* adjust pm to dpms changes AFTER disabling crtcs */
|
||||
|
|
|
@ -537,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
|
|||
break;
|
||||
}
|
||||
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
|
||||
/* handled in radeon_crtc_dpms() */
|
||||
if (!(rdev->flags & RADEON_SINGLE_CRTC))
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
|
||||
WREG32(RADEON_DAC_CNTL, dac_cntl);
|
||||
WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
|
||||
|
||||
|
@ -662,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
|
|||
|
||||
if (ASIC_IS_R300(rdev))
|
||||
tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
|
||||
else if (ASIC_IS_RV100(rdev))
|
||||
tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);
|
||||
else
|
||||
tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
|
||||
|
||||
|
@ -671,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
|
|||
tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
|
||||
WREG32(RADEON_DAC_CNTL, tmp);
|
||||
|
||||
tmp = dac_macro_cntl;
|
||||
tmp &= ~(RADEON_DAC_PDWN_R |
|
||||
RADEON_DAC_PDWN_G |
|
||||
RADEON_DAC_PDWN_B);
|
||||
|
@ -1092,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
|
|||
} else {
|
||||
if (is_tv)
|
||||
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
|
||||
else
|
||||
/* handled in radeon_crtc_dpms() */
|
||||
else if (!(rdev->flags & RADEON_SINGLE_CRTC))
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
|
||||
}
|
||||
|
@ -1416,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
|
|||
return found;
|
||||
}
|
||||
|
||||
static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
|
||||
uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
|
||||
uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
|
||||
uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp;
|
||||
uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
|
||||
bool found = false;
|
||||
int i;
|
||||
|
||||
/* save the regs we need */
|
||||
gpio_monid = RREG32(RADEON_GPIO_MONID);
|
||||
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
|
||||
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
|
||||
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A);
|
||||
disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B);
|
||||
disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C);
|
||||
disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D);
|
||||
disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E);
|
||||
disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F);
|
||||
crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP);
|
||||
crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP);
|
||||
crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID);
|
||||
crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID);
|
||||
|
||||
tmp = RREG32(RADEON_GPIO_MONID);
|
||||
tmp &= ~RADEON_GPIO_A_0;
|
||||
WREG32(RADEON_GPIO_MONID, tmp);
|
||||
|
||||
WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON |
|
||||
RADEON_FP2_PANEL_FORMAT |
|
||||
R200_FP2_SOURCE_SEL_TRANS_UNIT |
|
||||
RADEON_FP2_DVO_EN |
|
||||
R200_FP2_DVO_RATE_SEL_SDR));
|
||||
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX |
|
||||
RADEON_DISP_TRANS_MATRIX_GRAPHICS));
|
||||
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN |
|
||||
RADEON_CRTC2_DISP_REQ_EN_B));
|
||||
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
|
||||
|
||||
WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
|
||||
WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
|
||||
WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
|
||||
WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
|
||||
|
||||
for (i = 0; i < 200; i++) {
|
||||
tmp = RREG32(RADEON_GPIO_MONID);
|
||||
if (tmp & RADEON_GPIO_Y_0)
|
||||
found = true;
|
||||
|
||||
if (found)
|
||||
break;
|
||||
|
||||
if (!drm_can_sleep())
|
||||
mdelay(1);
|
||||
else
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
/* restore the regs we used */
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
|
||||
WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
|
||||
WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
|
||||
WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
|
||||
WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
|
||||
WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
|
||||
WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
|
||||
WREG32(RADEON_GPIO_MONID, gpio_monid);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = encoder->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
|
||||
uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
|
||||
uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
|
||||
uint32_t gpiopad_a = 0, pixclks_cntl, tmp;
|
||||
uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;
|
||||
enum drm_connector_status found = connector_status_disconnected;
|
||||
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
|
||||
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
|
||||
|
@ -1459,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
|
|||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
/* R200 uses an external DAC for secondary DAC */
|
||||
if (rdev->family == CHIP_R200) {
|
||||
if (radeon_legacy_ext_dac_detect(encoder, connector))
|
||||
found = connector_status_connected;
|
||||
return found;
|
||||
}
|
||||
|
||||
/* save the regs we need */
|
||||
pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
|
||||
gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0;
|
||||
disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0;
|
||||
disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG);
|
||||
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC) {
|
||||
crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
|
||||
} else {
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
gpiopad_a = RREG32(RADEON_GPIOPAD_A);
|
||||
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
|
||||
} else {
|
||||
disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
|
||||
}
|
||||
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
|
||||
}
|
||||
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
|
||||
dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
|
||||
dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
|
||||
|
@ -1473,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
|
|||
| RADEON_PIX2CLK_DAC_ALWAYS_ONb);
|
||||
WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
|
||||
|
||||
if (ASIC_IS_R300(rdev))
|
||||
WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
|
||||
|
||||
tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
|
||||
tmp |= RADEON_CRTC2_CRT2_ON |
|
||||
(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
|
||||
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
|
||||
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC) {
|
||||
tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, tmp);
|
||||
} else {
|
||||
tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
|
||||
WREG32(RADEON_DISP_HW_DEBUG, tmp);
|
||||
tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
|
||||
tmp |= RADEON_CRTC2_CRT2_ON |
|
||||
(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
|
||||
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
|
||||
tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
|
||||
tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
|
||||
} else {
|
||||
tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
|
||||
WREG32(RADEON_DISP_HW_DEBUG, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
tmp = RADEON_TV_DAC_NBLANK |
|
||||
|
@ -1530,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
|
|||
WREG32(RADEON_DAC_CNTL2, dac_cntl2);
|
||||
WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
|
||||
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
|
||||
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
|
||||
if (rdev->flags & RADEON_SINGLE_CRTC) {
|
||||
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
|
||||
} else {
|
||||
WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
|
||||
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
|
||||
if (ASIC_IS_R300(rdev)) {
|
||||
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
|
||||
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
|
||||
} else {
|
||||
WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
|
||||
}
|
||||
}
|
||||
|
||||
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
|
||||
|
||||
return found;
|
||||
|
|
|
@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev,
|
|||
|
||||
int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
|
||||
const char *front, char **urb_buf_ptr,
|
||||
u32 byte_offset, u32 byte_width,
|
||||
u32 byte_offset, u32 device_byte_offset, u32 byte_width,
|
||||
int *ident_ptr, int *sent_ptr);
|
||||
|
||||
int udl_dumb_create(struct drm_file *file_priv,
|
||||
|
|
|
@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info,
|
|||
list_for_each_entry(cur, &fbdefio->pagelist, lru) {
|
||||
|
||||
if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8),
|
||||
&urb, (char *) info->fix.smem_start,
|
||||
&cmd, cur->index << PAGE_SHIFT,
|
||||
PAGE_SIZE, &bytes_identical, &bytes_sent))
|
||||
&urb, (char *) info->fix.smem_start,
|
||||
&cmd, cur->index << PAGE_SHIFT,
|
||||
cur->index << PAGE_SHIFT,
|
||||
PAGE_SIZE, &bytes_identical, &bytes_sent))
|
||||
goto error;
|
||||
bytes_rendered += PAGE_SIZE;
|
||||
}
|
||||
|
@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
|
|||
for (i = y; i < y + height ; i++) {
|
||||
const int line_offset = fb->base.pitches[0] * i;
|
||||
const int byte_offset = line_offset + (x * bpp);
|
||||
|
||||
const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
|
||||
if (udl_render_hline(dev, bpp, &urb,
|
||||
(char *) fb->obj->vmapping,
|
||||
&cmd, byte_offset, width * bpp,
|
||||
&cmd, byte_offset, dev_byte_offset,
|
||||
width * bpp,
|
||||
&bytes_identical, &bytes_sent))
|
||||
goto error;
|
||||
}
|
||||
|
|
|
@ -213,11 +213,12 @@ static void udl_compress_hline16(
|
|||
*/
|
||||
int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
|
||||
const char *front, char **urb_buf_ptr,
|
||||
u32 byte_offset, u32 byte_width,
|
||||
u32 byte_offset, u32 device_byte_offset,
|
||||
u32 byte_width,
|
||||
int *ident_ptr, int *sent_ptr)
|
||||
{
|
||||
const u8 *line_start, *line_end, *next_pixel;
|
||||
u32 base16 = 0 + (byte_offset / bpp) * 2;
|
||||
u32 base16 = 0 + (device_byte_offset / bpp) * 2;
|
||||
struct urb *urb = *urb_ptr;
|
||||
u8 *cmd = *urb_buf_ptr;
|
||||
u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
|
||||
|
|
|
@ -522,6 +522,12 @@ static const struct hid_device_id apple_devices[] = {
|
|||
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_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),
|
||||
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
|
||||
|
|
|
@ -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_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_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_ISO) },
|
||||
{ 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_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_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_GEYSER1_TP_ONLY) },
|
||||
{ }
|
||||
|
|
|
@ -118,6 +118,9 @@
|
|||
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253
|
||||
#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_ISO 0x024a
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS 0x024b
|
||||
|
|
|
@ -28,22 +28,30 @@
|
|||
#define MS_RDESC 0x08
|
||||
#define MS_NOGET 0x10
|
||||
#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,
|
||||
unsigned int *rsize)
|
||||
{
|
||||
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 &&
|
||||
rdesc[559] == 0x29) {
|
||||
hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
|
||||
rdesc[557] = 0x35;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
.driver_data = MS_PRESENTER },
|
||||
{ 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),
|
||||
.driver_data = MS_NOGET },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
|
||||
|
|
|
@ -210,8 +210,7 @@ static struct mt_class mt_classes[] = {
|
|||
},
|
||||
{ .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
|
||||
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
|
||||
MT_QUIRK_SLOT_IS_CONTACTNUMBER,
|
||||
.maxcontacts = 10
|
||||
MT_QUIRK_SLOT_IS_CONTACTNUMBER
|
||||
},
|
||||
|
||||
{ .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 */
|
||||
td->last_field_index = field->index;
|
||||
return -1;
|
||||
}
|
||||
case HID_DG_TOUCH:
|
||||
/* Legacy devices use TIPSWITCH and not TOUCH.
|
||||
* Let's just ignore this field. */
|
||||
return -1;
|
||||
}
|
||||
/* let hid-input decide for the others */
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* fam15h_power.c - AMD Family 15h processor power monitoring
|
||||
*
|
||||
* Copyright (c) 2011 Advanced Micro Devices, Inc.
|
||||
* Author: Andreas Herrmann <andreas.herrmann3@amd.com>
|
||||
* Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
*
|
||||
*
|
||||
* This driver is free software; you can redistribute it and/or
|
||||
|
@ -28,7 +28,7 @@
|
|||
#include <asm/processor.h>
|
||||
|
||||
MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor");
|
||||
MODULE_AUTHOR("Andreas Herrmann <andreas.herrmann3@amd.com>");
|
||||
MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/* D18F3 */
|
||||
|
|
|
@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = {
|
|||
.driver = {
|
||||
.name = "gpio-fan",
|
||||
.pm = GPIO_FAN_PM,
|
||||
#ifdef CONFIG_OF_GPIO
|
||||
.of_match_table = of_match_ptr(of_gpio_fan_match),
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
|
|||
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
|
||||
obj-$(CONFIG_I2C_MUX) += i2c-mux.o
|
||||
obj-y += algos/ busses/ muxes/
|
||||
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
|
||||
|
||||
ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
|
||||
CFLAGS_i2c-core.o := -Wno-deprecated-declarations
|
||||
|
|
|
@ -81,7 +81,6 @@ config I2C_I801
|
|||
tristate "Intel 82801 (ICH/PCH)"
|
||||
depends on PCI
|
||||
select CHECK_SIGNATURE if X86 && DMI
|
||||
select GPIOLIB if I2C_MUX
|
||||
help
|
||||
If you say yes to this option, support will be included for the Intel
|
||||
801 family of mainboard I2C interfaces. Specifically, the following
|
||||
|
|
|
@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
|
|||
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
|
||||
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.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_I2C) += scx200_i2c.o
|
||||
|
||||
|
|
|
@ -82,7 +82,8 @@
|
|||
#include <linux/wait.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/i2c-mux-gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
@ -192,7 +193,8 @@ struct i801_priv {
|
|||
int len;
|
||||
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;
|
||||
struct platform_device *mux_pdev;
|
||||
#endif
|
||||
|
@ -921,7 +923,8 @@ static void __init input_apanel_init(void) {}
|
|||
static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
|
||||
#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 = {
|
||||
.gpio_chip = "gpio_ich",
|
||||
.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);
|
||||
if (id) {
|
||||
/* Remove from branch classes from trunk */
|
||||
/* Remove branch classes from trunk */
|
||||
mux_config = id->driver_data;
|
||||
for (i = 0; i < mux_config->n_values; i++)
|
||||
class &= ~mux_config->classes[i];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Freescale MXS I2C bus driver
|
||||
*
|
||||
* Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
|
||||
* Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K.
|
||||
*
|
||||
* based on a (non-working) driver which was:
|
||||
*
|
||||
|
@ -35,10 +35,6 @@
|
|||
|
||||
#define DRIVER_NAME "mxs-i2c"
|
||||
|
||||
static bool use_pioqueue;
|
||||
module_param(use_pioqueue, bool, 0);
|
||||
MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
|
||||
|
||||
#define MXS_I2C_CTRL0 (0x00)
|
||||
#define MXS_I2C_CTRL0_SET (0x04)
|
||||
|
||||
|
@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
|
|||
MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \
|
||||
MXS_I2C_CTRL1_SLAVE_IRQ)
|
||||
|
||||
#define MXS_I2C_QUEUECTRL (0x60)
|
||||
#define MXS_I2C_QUEUECTRL_SET (0x64)
|
||||
#define MXS_I2C_QUEUECTRL_CLR (0x68)
|
||||
|
||||
#define MXS_I2C_QUEUECTRL_QUEUE_RUN 0x20
|
||||
#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE 0x04
|
||||
|
||||
#define MXS_I2C_QUEUESTAT (0x70)
|
||||
#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY 0x00002000
|
||||
#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F
|
||||
|
||||
#define MXS_I2C_QUEUECMD (0x80)
|
||||
|
||||
#define MXS_I2C_QUEUEDATA (0x90)
|
||||
|
||||
#define MXS_I2C_DATA (0xa0)
|
||||
|
||||
|
||||
#define MXS_CMD_I2C_SELECT (MXS_I2C_CTRL0_RETAIN_CLOCK | \
|
||||
MXS_I2C_CTRL0_PRE_SEND_START | \
|
||||
|
@ -153,7 +132,6 @@ struct mxs_i2c_dev {
|
|||
const struct mxs_i2c_speed_config *speed;
|
||||
|
||||
/* DMA support components */
|
||||
bool dma_mode;
|
||||
int dma_channel;
|
||||
struct dma_chan *dmach;
|
||||
struct mxs_dma_data dma_data;
|
||||
|
@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
|
|||
writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
|
||||
|
||||
writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
|
||||
if (i2c->dma_mode)
|
||||
writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
|
||||
i2c->regs + MXS_I2C_QUEUECTRL_CLR);
|
||||
else
|
||||
writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
|
||||
i2c->regs + MXS_I2C_QUEUECTRL_SET);
|
||||
}
|
||||
|
||||
static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len,
|
||||
int flags)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD);
|
||||
|
||||
data = (addr << 1) | I2C_SMBUS_READ;
|
||||
writel(data, i2c->regs + MXS_I2C_DATA);
|
||||
|
||||
data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags;
|
||||
writel(data, i2c->regs + MXS_I2C_QUEUECMD);
|
||||
}
|
||||
|
||||
static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c,
|
||||
u8 addr, u8 *buf, int len, int flags)
|
||||
{
|
||||
u32 data;
|
||||
int i, shifts_left;
|
||||
|
||||
data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags;
|
||||
writel(data, i2c->regs + MXS_I2C_QUEUECMD);
|
||||
|
||||
/*
|
||||
* We have to copy the slave address (u8) and buffer (arbitrary number
|
||||
* of u8) into the data register (u32). To achieve that, the u8 are put
|
||||
* into the MSBs of 'data' which is then shifted for the next u8. When
|
||||
* appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32
|
||||
* looks like this:
|
||||
*
|
||||
* 3 2 1 0
|
||||
* 10987654|32109876|54321098|76543210
|
||||
* --------+--------+--------+--------
|
||||
* buffer+2|buffer+1|buffer+0|slave_addr
|
||||
*/
|
||||
|
||||
data = ((addr << 1) | I2C_SMBUS_WRITE) << 24;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
data >>= 8;
|
||||
data |= buf[i] << 24;
|
||||
if ((i & 3) == 2)
|
||||
writel(data, i2c->regs + MXS_I2C_DATA);
|
||||
}
|
||||
|
||||
/* Write out the remaining bytes if any */
|
||||
shifts_left = 24 - (i & 3) * 8;
|
||||
if (shifts_left)
|
||||
writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the
|
||||
* rd_threshold to 1). Couldn't get this to work, though.
|
||||
*/
|
||||
static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
|
||||
|
||||
while (readl(i2c->regs + MXS_I2C_QUEUESTAT)
|
||||
& MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) {
|
||||
if (time_after(jiffies, timeout))
|
||||
return -ETIMEDOUT;
|
||||
cond_resched();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
|
||||
{
|
||||
u32 uninitialized_var(data);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((i & 3) == 0) {
|
||||
if (mxs_i2c_wait_for_data(i2c))
|
||||
return -ETIMEDOUT;
|
||||
data = readl(i2c->regs + MXS_I2C_QUEUEDATA);
|
||||
}
|
||||
buf[i] = data & 0xff;
|
||||
data >>= 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
|
||||
|
@ -432,39 +317,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
|
|||
init_completion(&i2c->cmd_complete);
|
||||
i2c->cmd_err = 0;
|
||||
|
||||
if (i2c->dma_mode) {
|
||||
ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
if (msg->flags & I2C_M_RD) {
|
||||
mxs_i2c_pioq_setup_read(i2c, msg->addr,
|
||||
msg->len, flags);
|
||||
} else {
|
||||
mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf,
|
||||
msg->len, flags);
|
||||
}
|
||||
|
||||
writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
|
||||
i2c->regs + MXS_I2C_QUEUECTRL_SET);
|
||||
}
|
||||
ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = wait_for_completion_timeout(&i2c->cmd_complete,
|
||||
msecs_to_jiffies(1000));
|
||||
if (ret == 0)
|
||||
goto timeout;
|
||||
|
||||
if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) {
|
||||
ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
|
||||
if (ret)
|
||||
goto timeout;
|
||||
}
|
||||
|
||||
if (i2c->cmd_err == -ENXIO)
|
||||
mxs_i2c_reset(i2c);
|
||||
else
|
||||
writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
|
||||
i2c->regs + MXS_I2C_QUEUECTRL_CLR);
|
||||
|
||||
dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err);
|
||||
|
||||
|
@ -472,8 +335,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
|
|||
|
||||
timeout:
|
||||
dev_dbg(i2c->dev, "Timeout!\n");
|
||||
if (i2c->dma_mode)
|
||||
mxs_i2c_dma_finish(i2c);
|
||||
mxs_i2c_dma_finish(i2c);
|
||||
mxs_i2c_reset(i2c);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
@ -502,7 +364,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
|
|||
{
|
||||
struct mxs_i2c_dev *i2c = dev_id;
|
||||
u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK;
|
||||
bool is_last_cmd;
|
||||
|
||||
if (!stat)
|
||||
return IRQ_NONE;
|
||||
|
@ -515,14 +376,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
|
|||
/* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
|
||||
i2c->cmd_err = -EIO;
|
||||
|
||||
if (!i2c->dma_mode) {
|
||||
is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
|
||||
MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
|
||||
|
||||
if (is_last_cmd || i2c->cmd_err)
|
||||
complete(&i2c->cmd_complete);
|
||||
}
|
||||
|
||||
writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -555,15 +408,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
|
|||
struct device_node *node = dev->of_node;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The MXS I2C DMA mode is prefered and enabled by default.
|
||||
* The PIO mode is still supported, but should be used only
|
||||
* for debuging purposes etc.
|
||||
*/
|
||||
i2c->dma_mode = !use_pioqueue;
|
||||
if (!i2c->dma_mode)
|
||||
dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n");
|
||||
|
||||
/*
|
||||
* TODO: This is a temporary solution and should be changed
|
||||
* to use generic DMA binding later when the helpers get in.
|
||||
|
@ -571,8 +415,8 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
|
|||
ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
|
||||
&i2c->dma_channel);
|
||||
if (ret) {
|
||||
dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n");
|
||||
i2c->dma_mode = 0;
|
||||
dev_err(dev, "Failed to get DMA channel!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "clock-frequency", &speed);
|
||||
|
@ -634,15 +478,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
/* Setup the DMA */
|
||||
if (i2c->dma_mode) {
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
i2c->dma_data.chan_irq = dmairq;
|
||||
i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
|
||||
if (!i2c->dmach) {
|
||||
dev_err(dev, "Failed to request dma\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
i2c->dma_data.chan_irq = dmairq;
|
||||
i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
|
||||
if (!i2c->dmach) {
|
||||
dev_err(dev, "Failed to request dma\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, i2c);
|
||||
|
|
|
@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
|
|||
|
||||
pm_runtime_get_sync(&dev->adev->dev);
|
||||
|
||||
clk_enable(dev->clk);
|
||||
status = clk_prepare_enable(dev->clk);
|
||||
if (status) {
|
||||
dev_err(&dev->adev->dev, "can't prepare_enable clock\n");
|
||||
goto out_clk;
|
||||
}
|
||||
|
||||
status = init_hw(dev);
|
||||
if (status)
|
||||
|
@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
|
|||
}
|
||||
|
||||
out:
|
||||
clk_disable(dev->clk);
|
||||
clk_disable_unprepare(dev->clk);
|
||||
out_clk:
|
||||
pm_runtime_put_sync(&dev->adev->dev);
|
||||
|
||||
dev->busy = false;
|
||||
|
|
|
@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
|
||||
tegra_i2c_isr, 0, pdev->name, i2c_dev);
|
||||
tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
|
||||
return ret;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
i2c-stub.c - I2C/SMBus chip emulator
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
/* Return negative errno on error. */
|
||||
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)
|
||||
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)
|
||||
{
|
||||
s32 ret;
|
||||
int i, len;
|
||||
|
@ -78,14 +78,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
|
|||
case I2C_SMBUS_BYTE:
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
chip->pointer = command;
|
||||
dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
|
||||
"wrote 0x%02x.\n",
|
||||
addr, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"smbus byte - addr 0x%02x, wrote 0x%02x.\n",
|
||||
addr, command);
|
||||
} else {
|
||||
data->byte = chip->words[chip->pointer++] & 0xff;
|
||||
dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
|
||||
"read 0x%02x.\n",
|
||||
addr, data->byte);
|
||||
dev_dbg(&adap->dev,
|
||||
"smbus byte - addr 0x%02x, read 0x%02x.\n",
|
||||
addr, data->byte);
|
||||
}
|
||||
|
||||
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) {
|
||||
chip->words[command] &= 0xff00;
|
||||
chip->words[command] |= data->byte;
|
||||
dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
|
||||
"wrote 0x%02x at 0x%02x.\n",
|
||||
addr, data->byte, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n",
|
||||
addr, data->byte, command);
|
||||
} else {
|
||||
data->byte = chip->words[command] & 0xff;
|
||||
dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
|
||||
"read 0x%02x at 0x%02x.\n",
|
||||
addr, data->byte, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"smbus byte data - addr 0x%02x, read 0x%02x at 0x%02x.\n",
|
||||
addr, data->byte, command);
|
||||
}
|
||||
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:
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
chip->words[command] = data->word;
|
||||
dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
|
||||
"wrote 0x%04x at 0x%02x.\n",
|
||||
addr, data->word, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n",
|
||||
addr, data->word, command);
|
||||
} else {
|
||||
data->word = chip->words[command];
|
||||
dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
|
||||
"read 0x%04x at 0x%02x.\n",
|
||||
addr, data->word, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"smbus word data - addr 0x%02x, read 0x%04x at 0x%02x.\n",
|
||||
addr, data->word, command);
|
||||
}
|
||||
|
||||
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] |= data->block[1 + i];
|
||||
}
|
||||
dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
|
||||
"wrote %d bytes at 0x%02x.\n",
|
||||
addr, len, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n",
|
||||
addr, len, command);
|
||||
} else {
|
||||
for (i = 0; i < len; i++) {
|
||||
data->block[1 + i] =
|
||||
chip->words[command + i] & 0xff;
|
||||
}
|
||||
dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
|
||||
"read %d bytes at 0x%02x.\n",
|
||||
addr, len, command);
|
||||
dev_dbg(&adap->dev,
|
||||
"i2c block data - addr 0x%02x, read %d bytes at 0x%02x.\n",
|
||||
addr, len, command);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
@ -179,25 +179,24 @@ static int __init i2c_stub_init(void)
|
|||
int i, ret;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
|
||||
if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) {
|
||||
printk(KERN_ERR "i2c-stub: Invalid chip address "
|
||||
"0x%02x\n", chip_addr[i]);
|
||||
pr_err("i2c-stub: Invalid chip address 0x%02x\n",
|
||||
chip_addr[i]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n",
|
||||
chip_addr[i]);
|
||||
pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]);
|
||||
}
|
||||
|
||||
/* Allocate memory for all chips at once */
|
||||
stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
|
||||
if (!stub_chips) {
|
||||
printk(KERN_ERR "i2c-stub: Out of memory\n");
|
||||
pr_err("i2c-stub: Out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -219,4 +218,3 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
module_init(i2c_stub_init);
|
||||
module_exit(i2c_stub_exit);
|
||||
|
|
@ -335,6 +335,7 @@ config KEYBOARD_LOCOMO
|
|||
config KEYBOARD_LPC32XX
|
||||
tristate "LPC32XX matrix key scanner support"
|
||||
depends on ARCH_LPC32XX && OF
|
||||
select INPUT_MATRIXKMAP
|
||||
help
|
||||
Say Y here if you want to use NXP LPC32XX SoC key scanner interface,
|
||||
connected to a key matrix.
|
||||
|
|
|
@ -368,6 +368,9 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
|
|||
unsigned int mask = 0, direct_key_num = 0;
|
||||
unsigned long kpc = 0;
|
||||
|
||||
/* clear pending interrupt bit */
|
||||
keypad_readl(KPC);
|
||||
|
||||
/* enable matrix keys with automatic scan */
|
||||
if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
|
||||
kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
|
||||
|
|
|
@ -311,7 +311,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
|
|||
case XenbusStateReconfiguring:
|
||||
case XenbusStateReconfigured:
|
||||
case XenbusStateUnknown:
|
||||
case XenbusStateClosed:
|
||||
break;
|
||||
|
||||
case XenbusStateInitWait:
|
||||
|
@ -350,6 +349,10 @@ InitWait:
|
|||
|
||||
break;
|
||||
|
||||
case XenbusStateClosed:
|
||||
if (dev->state == XenbusStateClosed)
|
||||
break;
|
||||
/* Missed the backend's CLOSING state -- fallthrough */
|
||||
case XenbusStateClosing:
|
||||
xenbus_frontend_closed(dev);
|
||||
break;
|
||||
|
|
|
@ -84,6 +84,10 @@
|
|||
#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263
|
||||
#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) { \
|
||||
.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_ISO),
|
||||
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 */
|
||||
{}
|
||||
};
|
||||
|
@ -379,6 +387,19 @@ static const struct bcm5974_config bcm5974_config_table[] = {
|
|||
{ SN_COORD, -150, 6730 },
|
||||
{ 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 }
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
|
|||
features->pktlen = WACOM_PKGLEN_TPC2FG;
|
||||
}
|
||||
|
||||
if (features->type == MTSCREEN || WACOM_24HDT)
|
||||
if (features->type == MTSCREEN || features->type == WACOM_24HDT)
|
||||
features->pktlen = WACOM_PKGLEN_MTOUCH;
|
||||
|
||||
if (features->type == BAMBOO_PT) {
|
||||
|
|
|
@ -1518,6 +1518,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
|
|||
|
||||
input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
|
||||
|
||||
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
|
||||
|
||||
wacom_setup_cintiq(wacom_wac);
|
||||
break;
|
||||
|
||||
|
|
|
@ -239,7 +239,7 @@ config TOUCHSCREEN_EETI
|
|||
|
||||
config TOUCHSCREEN_EGALAX
|
||||
tristate "EETI eGalax multi-touch panel support"
|
||||
depends on I2C
|
||||
depends on I2C && OF
|
||||
help
|
||||
Say Y here to enable support for I2C connected EETI
|
||||
eGalax multi-touch panels.
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/input/mt.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
/*
|
||||
* Mouse Mode: some panel may configure the controller to mouse mode,
|
||||
|
@ -122,9 +123,17 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
|
|||
/* wake up controller by an falling edge of interrupt gpio. */
|
||||
static int egalax_wake_up_device(struct i2c_client *client)
|
||||
{
|
||||
int gpio = irq_to_gpio(client->irq);
|
||||
struct device_node *np = client->dev.of_node;
|
||||
int gpio;
|
||||
int ret;
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
gpio = of_get_named_gpio(np, "wakeup-gpios", 0);
|
||||
if (!gpio_is_valid(gpio))
|
||||
return -ENODEV;
|
||||
|
||||
ret = gpio_request(gpio, "egalax_irq");
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev,
|
||||
|
@ -181,7 +190,11 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,
|
|||
ts->input_dev = input_dev;
|
||||
|
||||
/* controller may be in sleep, wake it up. */
|
||||
egalax_wake_up_device(client);
|
||||
error = egalax_wake_up_device(client);
|
||||
if (error) {
|
||||
dev_err(&client->dev, "Failed to wake up the controller\n");
|
||||
goto err_free_dev;
|
||||
}
|
||||
|
||||
ret = egalax_firmware_version(client);
|
||||
if (ret < 0) {
|
||||
|
@ -274,11 +287,17 @@ static int egalax_ts_resume(struct device *dev)
|
|||
|
||||
static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume);
|
||||
|
||||
static struct of_device_id egalax_ts_dt_ids[] = {
|
||||
{ .compatible = "eeti,egalax_ts" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct i2c_driver egalax_ts_driver = {
|
||||
.driver = {
|
||||
.name = "egalax_ts",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &egalax_ts_pm_ops,
|
||||
.of_match_table = of_match_ptr(egalax_ts_dt_ids),
|
||||
},
|
||||
.id_table = egalax_ts_id,
|
||||
.probe = egalax_ts_probe,
|
||||
|
|
|
@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)
|
|||
__set_bit(BTN_TOUCH, input_dev->keybit);
|
||||
input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);
|
||||
input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0);
|
||||
input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0);
|
||||
|
||||
serio_set_drvdata(serio, ptsc);
|
||||
|
||||
|
|
|
@ -315,8 +315,11 @@ static int run(struct mddev *mddev)
|
|||
}
|
||||
conf->nfaults = 0;
|
||||
|
||||
rdev_for_each(rdev, mddev)
|
||||
rdev_for_each(rdev, mddev) {
|
||||
conf->rdev = rdev;
|
||||
disk_stack_limits(mddev->gendisk, rdev->bdev,
|
||||
rdev->data_offset << 9);
|
||||
}
|
||||
|
||||
md_set_array_sectors(mddev, faulty_size(mddev, 0, 0));
|
||||
mddev->private = conf;
|
||||
|
|
|
@ -2710,7 +2710,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)
|
|||
|| disk_idx < 0)
|
||||
continue;
|
||||
if (test_bit(Replacement, &rdev->flags))
|
||||
disk = conf->mirrors + conf->raid_disks + disk_idx;
|
||||
disk = conf->mirrors + mddev->raid_disks + disk_idx;
|
||||
else
|
||||
disk = conf->mirrors + disk_idx;
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче