mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
Merge branch 'linus' into tracing/blktrace
Conflicts: block/blktrace.c Semantic merge: kernel/trace/blktrace.c Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
commit
72c26c9a26
1
CREDITS
1
CREDITS
@ -2166,7 +2166,6 @@ D: Initial implementation of VC's, pty's and select()
|
||||
|
||||
N: Pavel Machek
|
||||
E: pavel@ucw.cz
|
||||
E: pavel@suse.cz
|
||||
D: Softcursor for vga, hypertech cdrom support, vcsa bugfix, nbd
|
||||
D: sun4/330 port, capabilities for elf, speedup for rm on ext2, USB,
|
||||
D: work on suspend-to-ram/disk, killing duplicates from ioctl32
|
||||
|
@ -1,6 +1,6 @@
|
||||
What: /sys/firmware/memmap/
|
||||
Date: June 2008
|
||||
Contact: Bernhard Walle <bwalle@suse.de>
|
||||
Contact: Bernhard Walle <bernhard.walle@gmx.de>
|
||||
Description:
|
||||
On all platforms, the firmware provides a memory map which the
|
||||
kernel reads. The resources from that memory map are registered
|
||||
|
@ -93,7 +93,7 @@ the PCI Express Port Bus driver from loading a service driver.
|
||||
|
||||
int pcie_port_service_register(struct pcie_port_service_driver *new)
|
||||
|
||||
This API replaces the Linux Driver Model's pci_module_init API. A
|
||||
This API replaces the Linux Driver Model's pci_register_driver API. A
|
||||
service driver should always calls pcie_port_service_register at
|
||||
module init. Note that after service driver being loaded, calls
|
||||
such as pci_enable_device(dev) and pci_set_master(dev) are no longer
|
||||
|
@ -252,10 +252,8 @@ cgroup file system directories.
|
||||
When a task is moved from one cgroup to another, it gets a new
|
||||
css_set pointer - if there's an already existing css_set with the
|
||||
desired collection of cgroups then that group is reused, else a new
|
||||
css_set is allocated. Note that the current implementation uses a
|
||||
linear search to locate an appropriate existing css_set, so isn't
|
||||
very efficient. A future version will use a hash table for better
|
||||
performance.
|
||||
css_set is allocated. The appropriate existing css_set is located by
|
||||
looking into a hash table.
|
||||
|
||||
To allow access from a cgroup to the css_sets (and hence tasks)
|
||||
that comprise it, a set of cg_cgroup_link objects form a lattice;
|
||||
|
101
Documentation/hwmon/hpfall.c
Normal file
101
Documentation/hwmon/hpfall.c
Normal file
@ -0,0 +1,101 @@
|
||||
/* Disk protection for HP machines.
|
||||
*
|
||||
* Copyright 2008 Eric Piel
|
||||
* Copyright 2009 Pavel Machek <pavel@suse.cz>
|
||||
*
|
||||
* GPLv2.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
void write_int(char *path, int i)
|
||||
{
|
||||
char buf[1024];
|
||||
int fd = open(path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
sprintf(buf, "%d", i);
|
||||
if (write(fd, buf, strlen(buf)) != strlen(buf)) {
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void set_led(int on)
|
||||
{
|
||||
write_int("/sys/class/leds/hp::hddprotect/brightness", on);
|
||||
}
|
||||
|
||||
void protect(int seconds)
|
||||
{
|
||||
write_int("/sys/block/sda/device/unload_heads", seconds*1000);
|
||||
}
|
||||
|
||||
int on_ac(void)
|
||||
{
|
||||
// /sys/class/power_supply/AC0/online
|
||||
}
|
||||
|
||||
int lid_open(void)
|
||||
{
|
||||
// /proc/acpi/button/lid/LID/state
|
||||
}
|
||||
|
||||
void ignore_me(void)
|
||||
{
|
||||
protect(0);
|
||||
set_led(0);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int fd, ret;
|
||||
|
||||
fd = open("/dev/freefall", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
signal(SIGALRM, ignore_me);
|
||||
|
||||
for (;;) {
|
||||
unsigned char count;
|
||||
|
||||
ret = read(fd, &count, sizeof(count));
|
||||
alarm(0);
|
||||
if ((ret == -1) && (errno == EINTR)) {
|
||||
/* Alarm expired, time to unpark the heads */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret != sizeof(count)) {
|
||||
perror("read");
|
||||
break;
|
||||
}
|
||||
|
||||
protect(21);
|
||||
set_led(1);
|
||||
if (1 || on_ac() || lid_open()) {
|
||||
alarm(2);
|
||||
} else {
|
||||
alarm(20);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -33,6 +33,14 @@ rate - reports the sampling rate of the accelerometer device in HZ
|
||||
This driver also provides an absolute input class device, allowing
|
||||
the laptop to act as a pinball machine-esque joystick.
|
||||
|
||||
Another feature of the driver is misc device called "freefall" that
|
||||
acts similar to /dev/rtc and reacts on free-fall interrupts received
|
||||
from the device. It supports blocking operations, poll/select and
|
||||
fasync operation modes. You must read 1 bytes from the device. The
|
||||
result is number of free-fall interrupts since the last successful
|
||||
read (or 255 if number of interrupts would not fit).
|
||||
|
||||
|
||||
Axes orientation
|
||||
----------------
|
||||
|
||||
|
18
MAINTAINERS
18
MAINTAINERS
@ -1905,10 +1905,10 @@ W: http://gigaset307x.sourceforge.net/
|
||||
S: Maintained
|
||||
|
||||
HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
|
||||
P: Robert Love
|
||||
M: rlove@rlove.org
|
||||
M: linux-kernel@vger.kernel.org
|
||||
W: http://www.kernel.org/pub/linux/kernel/people/rml/hdaps/
|
||||
P: Frank Seidel
|
||||
M: frank@f-seidel.de
|
||||
L: lm-sensors@lm-sensors.org
|
||||
W: http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
|
||||
S: Maintained
|
||||
|
||||
GSPCA FINEPIX SUBDRIVER
|
||||
@ -2001,7 +2001,7 @@ S: Maintained
|
||||
|
||||
HIBERNATION (aka Software Suspend, aka swsusp)
|
||||
P: Pavel Machek
|
||||
M: pavel@suse.cz
|
||||
M: pavel@ucw.cz
|
||||
P: Rafael J. Wysocki
|
||||
M: rjw@sisk.pl
|
||||
L: linux-pm@lists.linux-foundation.org
|
||||
@ -4178,7 +4178,7 @@ SUSPEND TO RAM
|
||||
P: Len Brown
|
||||
M: len.brown@intel.com
|
||||
P: Pavel Machek
|
||||
M: pavel@suse.cz
|
||||
M: pavel@ucw.cz
|
||||
P: Rafael J. Wysocki
|
||||
M: rjw@sisk.pl
|
||||
L: linux-pm@lists.linux-foundation.org
|
||||
@ -4930,11 +4930,11 @@ L: zd1211-devs@lists.sourceforge.net (subscribers-only)
|
||||
S: Maintained
|
||||
|
||||
ZR36067 VIDEO FOR LINUX DRIVER
|
||||
P: Ronald Bultje
|
||||
M: rbultje@ronald.bitfreak.net
|
||||
L: mjpeg-users@lists.sourceforge.net
|
||||
L: linux-media@vger.kernel.org
|
||||
W: http://mjpeg.sourceforge.net/driver-zoran/
|
||||
S: Maintained
|
||||
T: Mercurial http://linuxtv.org/hg/v4l-dvb
|
||||
S: Odd Fixes
|
||||
|
||||
ZS DECSTATION Z85C30 SERIAL DRIVER
|
||||
P: Maciej W. Rozycki
|
||||
|
2
Makefile
2
Makefile
@ -389,6 +389,7 @@ PHONY += outputmakefile
|
||||
# output directory.
|
||||
outputmakefile:
|
||||
ifneq ($(KBUILD_SRC),)
|
||||
$(Q)ln -fsn $(srctree) source
|
||||
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
|
||||
$(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
|
||||
endif
|
||||
@ -946,7 +947,6 @@ ifneq ($(KBUILD_SRC),)
|
||||
mkdir -p include2; \
|
||||
ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm; \
|
||||
fi
|
||||
ln -fsn $(srctree) source
|
||||
endif
|
||||
|
||||
# prepare2 creates a makefile if using a separate output directory
|
||||
|
@ -93,8 +93,8 @@ common_shutdown_1(void *generic_ptr)
|
||||
if (cpuid != boot_cpuid) {
|
||||
flags |= 0x00040000UL; /* "remain halted" */
|
||||
*pflags = flags;
|
||||
cpu_clear(cpuid, cpu_present_map);
|
||||
cpu_clear(cpuid, cpu_possible_map);
|
||||
set_cpu_present(cpuid, false);
|
||||
set_cpu_possible(cpuid, false);
|
||||
halt();
|
||||
}
|
||||
#endif
|
||||
@ -120,8 +120,8 @@ common_shutdown_1(void *generic_ptr)
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Wait for the secondaries to halt. */
|
||||
cpu_clear(boot_cpuid, cpu_present_map);
|
||||
cpu_clear(boot_cpuid, cpu_possible_map);
|
||||
set_cpu_present(boot_cpuid, false);
|
||||
set_cpu_possible(boot_cpuid, false);
|
||||
while (cpus_weight(cpu_present_map))
|
||||
barrier();
|
||||
#endif
|
||||
|
@ -120,12 +120,12 @@ void __cpuinit
|
||||
smp_callin(void)
|
||||
{
|
||||
int cpuid = hard_smp_processor_id();
|
||||
cpumask_t mask = cpu_online_map;
|
||||
|
||||
if (cpu_test_and_set(cpuid, mask)) {
|
||||
if (cpu_online(cpuid)) {
|
||||
printk("??, cpu 0x%x already present??\n", cpuid);
|
||||
BUG();
|
||||
}
|
||||
set_cpu_online(cpuid, true);
|
||||
|
||||
/* Turn on machine checks. */
|
||||
wrmces(7);
|
||||
@ -436,8 +436,8 @@ setup_smp(void)
|
||||
((char *)cpubase + i*hwrpb->processor_size);
|
||||
if ((cpu->flags & 0x1cc) == 0x1cc) {
|
||||
smp_num_probed++;
|
||||
cpu_set(i, cpu_possible_map);
|
||||
cpu_set(i, cpu_present_map);
|
||||
set_cpu_possible(i, true);
|
||||
set_cpu_present(i, true);
|
||||
cpu->pal_revision = boot_cpu_palrev;
|
||||
}
|
||||
|
||||
@ -470,8 +470,8 @@ smp_prepare_cpus(unsigned int max_cpus)
|
||||
|
||||
/* Nothing to do on a UP box, or when told not to. */
|
||||
if (smp_num_probed == 1 || max_cpus == 0) {
|
||||
cpu_possible_map = cpumask_of_cpu(boot_cpuid);
|
||||
cpu_present_map = cpumask_of_cpu(boot_cpuid);
|
||||
init_cpu_possible(cpumask_of(boot_cpuid));
|
||||
init_cpu_present(cpumask_of(boot_cpuid));
|
||||
printk(KERN_INFO "SMP mode deactivated.\n");
|
||||
return;
|
||||
}
|
||||
|
@ -25,6 +25,10 @@
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
/* Select x86 specific features in <linux/kvm.h> */
|
||||
#define __KVM_HAVE_IOAPIC
|
||||
#define __KVM_HAVE_DEVICE_ASSIGNMENT
|
||||
|
||||
/* Architectural interrupt line count. */
|
||||
#define KVM_NR_INTERRUPTS 256
|
||||
|
||||
|
@ -31,10 +31,6 @@ static inline int pfn_to_nid(unsigned long pfn)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
|
||||
extern int early_pfn_to_nid(unsigned long pfn);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IA64_DIG /* DIG systems are small */
|
||||
# define MAX_PHYSNODE_ID 8
|
||||
# define NR_NODE_MEMBLKS (MAX_NUMNODES * 8)
|
||||
|
@ -1337,6 +1337,10 @@ static void kvm_release_vm_pages(struct kvm *kvm)
|
||||
}
|
||||
}
|
||||
|
||||
void kvm_arch_sync_events(struct kvm *kvm)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_arch_destroy_vm(struct kvm *kvm)
|
||||
{
|
||||
kvm_iommu_unmap_guest(kvm);
|
||||
|
@ -455,13 +455,18 @@ fpswa_ret_t vmm_fp_emulate(int fp_fault, void *bundle, unsigned long *ipsr,
|
||||
if (!vmm_fpswa_interface)
|
||||
return (fpswa_ret_t) {-1, 0, 0, 0};
|
||||
|
||||
/*
|
||||
* Just let fpswa driver to use hardware fp registers.
|
||||
* No fp register is valid in memory.
|
||||
*/
|
||||
memset(&fp_state, 0, sizeof(fp_state_t));
|
||||
|
||||
/*
|
||||
* compute fp_state. only FP registers f6 - f11 are used by the
|
||||
* vmm, so set those bits in the mask and set the low volatile
|
||||
* pointer to point to these registers.
|
||||
*/
|
||||
fp_state.bitmask_low64 = 0xfc0; /* bit6..bit11 */
|
||||
|
||||
fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) ®s->f6;
|
||||
|
||||
/*
|
||||
* unsigned long (*EFI_FPSWA) (
|
||||
* unsigned long trap_type,
|
||||
* void *Bundle,
|
||||
@ -545,10 +550,6 @@ void reflect_interruption(u64 ifa, u64 isr, u64 iim,
|
||||
status = vmm_handle_fpu_swa(0, regs, isr);
|
||||
if (!status)
|
||||
return ;
|
||||
else if (-EAGAIN == status) {
|
||||
vcpu_decrement_iip(vcpu);
|
||||
return ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ paddr_to_nid(unsigned long paddr)
|
||||
* SPARSEMEM to allocate the SPARSEMEM sectionmap on the NUMA node where
|
||||
* the section resides.
|
||||
*/
|
||||
int early_pfn_to_nid(unsigned long pfn)
|
||||
int __meminit __early_pfn_to_nid(unsigned long pfn)
|
||||
{
|
||||
int i, section = pfn >> PFN_SECTION_SHIFT, ssec, esec;
|
||||
|
||||
@ -70,7 +70,7 @@ int early_pfn_to_nid(unsigned long pfn)
|
||||
return node_memblk[i].nid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
|
@ -60,7 +60,7 @@
|
||||
/* It should be preserving the high 48 bits and then specifically */
|
||||
/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */
|
||||
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \
|
||||
_PAGE_HPTEFLAGS)
|
||||
_PAGE_HPTEFLAGS | _PAGE_SPECIAL)
|
||||
|
||||
/* Bits to mask out from a PMD to get to the PTE page */
|
||||
#define PMD_MASKED_BITS 0
|
||||
|
@ -114,7 +114,7 @@ static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd)
|
||||
* pgprot changes
|
||||
*/
|
||||
#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
|
||||
_PAGE_ACCESSED)
|
||||
_PAGE_ACCESSED | _PAGE_SPECIAL)
|
||||
|
||||
/* Bits to mask out from a PMD to get to the PTE page */
|
||||
#define PMD_MASKED_BITS 0x1ff
|
||||
|
@ -429,7 +429,8 @@ extern int icache_44x_need_flush;
|
||||
#define PMD_PAGE_SIZE(pmd) bad_call_to_PMD_PAGE_SIZE()
|
||||
#endif
|
||||
|
||||
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
|
||||
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \
|
||||
_PAGE_SPECIAL)
|
||||
|
||||
|
||||
#define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
|
||||
|
@ -646,11 +646,16 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
|
||||
unsigned int areg, struct pt_regs *regs,
|
||||
unsigned int flags, unsigned int length)
|
||||
{
|
||||
char *ptr = (char *) ¤t->thread.TS_FPR(reg);
|
||||
char *ptr;
|
||||
int ret = 0;
|
||||
|
||||
flush_vsx_to_thread(current);
|
||||
|
||||
if (reg < 32)
|
||||
ptr = (char *) ¤t->thread.TS_FPR(reg);
|
||||
else
|
||||
ptr = (char *) ¤t->thread.vr[reg - 32];
|
||||
|
||||
if (flags & ST)
|
||||
ret = __copy_to_user(addr, ptr, length);
|
||||
else {
|
||||
|
@ -125,6 +125,10 @@ static void kvmppc_free_vcpus(struct kvm *kvm)
|
||||
}
|
||||
}
|
||||
|
||||
void kvm_arch_sync_events(struct kvm *kvm)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_arch_destroy_vm(struct kvm *kvm)
|
||||
{
|
||||
kvmppc_free_vcpus(kvm);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/lmb.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pfn.h>
|
||||
#include <asm/sparsemem.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/system.h>
|
||||
@ -882,7 +883,7 @@ static void mark_reserved_regions_for_nid(int nid)
|
||||
unsigned long physbase = lmb.reserved.region[i].base;
|
||||
unsigned long size = lmb.reserved.region[i].size;
|
||||
unsigned long start_pfn = physbase >> PAGE_SHIFT;
|
||||
unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT);
|
||||
unsigned long end_pfn = PFN_UP(physbase + size);
|
||||
struct node_active_region node_ar;
|
||||
unsigned long node_end_pfn = node->node_start_pfn +
|
||||
node->node_spanned_pages;
|
||||
@ -908,7 +909,7 @@ static void mark_reserved_regions_for_nid(int nid)
|
||||
*/
|
||||
if (end_pfn > node_ar.end_pfn)
|
||||
reserve_size = (node_ar.end_pfn << PAGE_SHIFT)
|
||||
- (start_pfn << PAGE_SHIFT);
|
||||
- physbase;
|
||||
/*
|
||||
* Only worry about *this* node, others may not
|
||||
* yet have valid NODE_DATA().
|
||||
|
@ -328,7 +328,7 @@ static int __init ps3_mm_add_memory(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
core_initcall(ps3_mm_add_memory);
|
||||
device_initcall(ps3_mm_add_memory);
|
||||
|
||||
/*============================================================================*/
|
||||
/* dma routines */
|
||||
|
@ -212,6 +212,10 @@ static void kvm_free_vcpus(struct kvm *kvm)
|
||||
}
|
||||
}
|
||||
|
||||
void kvm_arch_sync_events(struct kvm *kvm)
|
||||
{
|
||||
}
|
||||
|
||||
void kvm_arch_destroy_vm(struct kvm *kvm)
|
||||
{
|
||||
kvm_free_vcpus(kvm);
|
||||
|
@ -9,6 +9,13 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
/* Select x86 specific features in <linux/kvm.h> */
|
||||
#define __KVM_HAVE_PIT
|
||||
#define __KVM_HAVE_IOAPIC
|
||||
#define __KVM_HAVE_DEVICE_ASSIGNMENT
|
||||
#define __KVM_HAVE_MSI
|
||||
#define __KVM_HAVE_USER_NMI
|
||||
|
||||
/* Architectural interrupt line count. */
|
||||
#define KVM_NR_INTERRUPTS 256
|
||||
|
||||
|
@ -32,8 +32,6 @@ static inline void get_memcfg_numa(void)
|
||||
get_memcfg_numa_flat();
|
||||
}
|
||||
|
||||
extern int early_pfn_to_nid(unsigned long pfn);
|
||||
|
||||
extern void resume_map_numa_kva(pgd_t *pgd);
|
||||
|
||||
#else /* !CONFIG_NUMA */
|
||||
|
@ -40,8 +40,6 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
|
||||
#define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \
|
||||
NODE_DATA(nid)->node_spanned_pages)
|
||||
|
||||
extern int early_pfn_to_nid(unsigned long pfn);
|
||||
|
||||
#ifdef CONFIG_NUMA_EMU
|
||||
#define FAKE_NODE_MIN_SIZE (64 * 1024 * 1024)
|
||||
#define FAKE_NODE_MIN_HASH_MASK (~(FAKE_NODE_MIN_SIZE - 1UL))
|
||||
|
@ -57,7 +57,6 @@ typedef struct { pgdval_t pgd; } pgd_t;
|
||||
typedef struct { pgprotval_t pgprot; } pgprot_t;
|
||||
|
||||
extern int page_is_ram(unsigned long pagenr);
|
||||
extern int pagerange_is_ram(unsigned long start, unsigned long end);
|
||||
extern int devmem_is_allowed(unsigned long pagenr);
|
||||
extern void map_devmem(unsigned long pfn, unsigned long size,
|
||||
pgprot_t vma_prot);
|
||||
|
@ -1352,14 +1352,7 @@ static inline void arch_leave_lazy_cpu_mode(void)
|
||||
PVOP_VCALL0(pv_cpu_ops.lazy_mode.leave);
|
||||
}
|
||||
|
||||
static inline void arch_flush_lazy_cpu_mode(void)
|
||||
{
|
||||
if (unlikely(paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU)) {
|
||||
arch_leave_lazy_cpu_mode();
|
||||
arch_enter_lazy_cpu_mode();
|
||||
}
|
||||
}
|
||||
|
||||
void arch_flush_lazy_cpu_mode(void);
|
||||
|
||||
#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
|
||||
static inline void arch_enter_lazy_mmu_mode(void)
|
||||
@ -1372,13 +1365,7 @@ static inline void arch_leave_lazy_mmu_mode(void)
|
||||
PVOP_VCALL0(pv_mmu_ops.lazy_mode.leave);
|
||||
}
|
||||
|
||||
static inline void arch_flush_lazy_mmu_mode(void)
|
||||
{
|
||||
if (unlikely(paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU)) {
|
||||
arch_leave_lazy_mmu_mode();
|
||||
arch_enter_lazy_mmu_mode();
|
||||
}
|
||||
}
|
||||
void arch_flush_lazy_mmu_mode(void);
|
||||
|
||||
static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx,
|
||||
unsigned long phys, pgprot_t flags)
|
||||
|
@ -1157,8 +1157,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
|
||||
data->cpu = pol->cpu;
|
||||
data->currpstate = HW_PSTATE_INVALID;
|
||||
|
||||
rc = powernow_k8_cpu_init_acpi(data);
|
||||
if (rc) {
|
||||
if (powernow_k8_cpu_init_acpi(data)) {
|
||||
/*
|
||||
* Use the PSB BIOS structure. This is only availabe on
|
||||
* an UP version, and is deprecated by AMD.
|
||||
@ -1176,17 +1175,20 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
|
||||
"ACPI maintainers and complain to your BIOS "
|
||||
"vendor.\n");
|
||||
#endif
|
||||
goto err_out;
|
||||
kfree(data);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (pol->cpu != 0) {
|
||||
printk(KERN_ERR FW_BUG PFX "No ACPI _PSS objects for "
|
||||
"CPU other than CPU0. Complain to your BIOS "
|
||||
"vendor.\n");
|
||||
goto err_out;
|
||||
kfree(data);
|
||||
return -ENODEV;
|
||||
}
|
||||
rc = find_psb_table(data);
|
||||
if (rc) {
|
||||
goto err_out;
|
||||
kfree(data);
|
||||
return -ENODEV;
|
||||
}
|
||||
/* Take a crude guess here.
|
||||
* That guess was in microseconds, so multiply with 1000 */
|
||||
|
@ -269,6 +269,8 @@ static void hpet_set_mode(enum clock_event_mode mode,
|
||||
now = hpet_readl(HPET_COUNTER);
|
||||
cmp = now + (unsigned long) delta;
|
||||
cfg = hpet_readl(HPET_Tn_CFG(timer));
|
||||
/* Make sure we use edge triggered interrupts */
|
||||
cfg &= ~HPET_TN_LEVEL;
|
||||
cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
|
||||
HPET_TN_SETVAL | HPET_TN_32BIT;
|
||||
hpet_writel(cfg, HPET_Tn_CFG(timer));
|
||||
|
@ -203,7 +203,7 @@ static void __init platform_detect(void)
|
||||
static void __init platform_detect(void)
|
||||
{
|
||||
/* stopgap until OFW support is added to the kernel */
|
||||
olpc_platform_info.boardrev = 0xc2;
|
||||
olpc_platform_info.boardrev = olpc_board(0xc2);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -268,6 +268,32 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
|
||||
return __get_cpu_var(paravirt_lazy_mode);
|
||||
}
|
||||
|
||||
void arch_flush_lazy_mmu_mode(void)
|
||||
{
|
||||
preempt_disable();
|
||||
|
||||
if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
|
||||
WARN_ON(preempt_count() == 1);
|
||||
arch_leave_lazy_mmu_mode();
|
||||
arch_enter_lazy_mmu_mode();
|
||||
}
|
||||
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
void arch_flush_lazy_cpu_mode(void)
|
||||
{
|
||||
preempt_disable();
|
||||
|
||||
if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_CPU) {
|
||||
WARN_ON(preempt_count() == 1);
|
||||
arch_leave_lazy_cpu_mode();
|
||||
arch_enter_lazy_cpu_mode();
|
||||
}
|
||||
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
struct pv_info pv_info = {
|
||||
.name = "bare hardware",
|
||||
.paravirt_enabled = 0,
|
||||
|
@ -810,12 +810,16 @@ static void ptrace_bts_untrace(struct task_struct *child)
|
||||
|
||||
static void ptrace_bts_detach(struct task_struct *child)
|
||||
{
|
||||
if (unlikely(child->bts)) {
|
||||
ds_release_bts(child->bts);
|
||||
child->bts = NULL;
|
||||
|
||||
ptrace_bts_free_buffer(child);
|
||||
}
|
||||
/*
|
||||
* Ptrace_detach() races with ptrace_untrace() in case
|
||||
* the child dies and is reaped by another thread.
|
||||
*
|
||||
* We only do the memory accounting at this point and
|
||||
* leave the buffer deallocation and the bts tracer
|
||||
* release to ptrace_bts_untrace() which will be called
|
||||
* later on with tasklist_lock held.
|
||||
*/
|
||||
release_locked_buffer(child->bts_buffer, child->bts_size);
|
||||
}
|
||||
#else
|
||||
static inline void ptrace_bts_fork(struct task_struct *tsk) {}
|
||||
|
@ -99,6 +99,12 @@ static inline void preempt_conditional_sti(struct pt_regs *regs)
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
static inline void conditional_cli(struct pt_regs *regs)
|
||||
{
|
||||
if (regs->flags & X86_EFLAGS_IF)
|
||||
local_irq_disable();
|
||||
}
|
||||
|
||||
static inline void preempt_conditional_cli(struct pt_regs *regs)
|
||||
{
|
||||
if (regs->flags & X86_EFLAGS_IF)
|
||||
@ -626,8 +632,10 @@ clear_dr7:
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
debug_vm86:
|
||||
/* reenable preemption: handle_vm86_trap() might sleep */
|
||||
dec_preempt_count();
|
||||
handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
|
||||
preempt_conditional_cli(regs);
|
||||
conditional_cli(regs);
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
@ -207,7 +207,7 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps)
|
||||
hrtimer_add_expires_ns(&pt->timer, pt->period);
|
||||
pt->scheduled = hrtimer_get_expires_ns(&pt->timer);
|
||||
if (pt->period)
|
||||
ps->channels[0].count_load_time = hrtimer_get_expires(&pt->timer);
|
||||
ps->channels[0].count_load_time = ktime_get();
|
||||
|
||||
return (pt->period == 0 ? 0 : 1);
|
||||
}
|
||||
|
@ -87,13 +87,6 @@ void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);
|
||||
|
||||
void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
|
||||
{
|
||||
kvm_apic_timer_intr_post(vcpu, vec);
|
||||
/* TODO: PIT, RTC etc. */
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kvm_timer_intr_post);
|
||||
|
||||
void __kvm_migrate_timers(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
__kvm_migrate_apic_timer(vcpu);
|
||||
|
@ -89,7 +89,6 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
|
||||
|
||||
void kvm_pic_reset(struct kvm_kpic_state *s);
|
||||
|
||||
void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
|
||||
void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
|
||||
void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);
|
||||
void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu);
|
||||
|
@ -35,6 +35,12 @@
|
||||
#include "kvm_cache_regs.h"
|
||||
#include "irq.h"
|
||||
|
||||
#ifndef CONFIG_X86_64
|
||||
#define mod_64(x, y) ((x) - (y) * div64_u64(x, y))
|
||||
#else
|
||||
#define mod_64(x, y) ((x) % (y))
|
||||
#endif
|
||||
|
||||
#define PRId64 "d"
|
||||
#define PRIx64 "llx"
|
||||
#define PRIu64 "u"
|
||||
@ -511,52 +517,22 @@ static void apic_send_ipi(struct kvm_lapic *apic)
|
||||
|
||||
static u32 apic_get_tmcct(struct kvm_lapic *apic)
|
||||
{
|
||||
u64 counter_passed;
|
||||
ktime_t passed, now;
|
||||
ktime_t remaining;
|
||||
s64 ns;
|
||||
u32 tmcct;
|
||||
|
||||
ASSERT(apic != NULL);
|
||||
|
||||
now = apic->timer.dev.base->get_time();
|
||||
tmcct = apic_get_reg(apic, APIC_TMICT);
|
||||
|
||||
/* if initial count is 0, current count should also be 0 */
|
||||
if (tmcct == 0)
|
||||
if (apic_get_reg(apic, APIC_TMICT) == 0)
|
||||
return 0;
|
||||
|
||||
if (unlikely(ktime_to_ns(now) <=
|
||||
ktime_to_ns(apic->timer.last_update))) {
|
||||
/* Wrap around */
|
||||
passed = ktime_add(( {
|
||||
(ktime_t) {
|
||||
.tv64 = KTIME_MAX -
|
||||
(apic->timer.last_update).tv64}; }
|
||||
), now);
|
||||
apic_debug("time elapsed\n");
|
||||
} else
|
||||
passed = ktime_sub(now, apic->timer.last_update);
|
||||
remaining = hrtimer_expires_remaining(&apic->timer.dev);
|
||||
if (ktime_to_ns(remaining) < 0)
|
||||
remaining = ktime_set(0, 0);
|
||||
|
||||
counter_passed = div64_u64(ktime_to_ns(passed),
|
||||
(APIC_BUS_CYCLE_NS * apic->timer.divide_count));
|
||||
|
||||
if (counter_passed > tmcct) {
|
||||
if (unlikely(!apic_lvtt_period(apic))) {
|
||||
/* one-shot timers stick at 0 until reset */
|
||||
tmcct = 0;
|
||||
} else {
|
||||
/*
|
||||
* periodic timers reset to APIC_TMICT when they
|
||||
* hit 0. The while loop simulates this happening N
|
||||
* times. (counter_passed %= tmcct) would also work,
|
||||
* but might be slower or not work on 32-bit??
|
||||
*/
|
||||
while (counter_passed > tmcct)
|
||||
counter_passed -= tmcct;
|
||||
tmcct -= counter_passed;
|
||||
}
|
||||
} else {
|
||||
tmcct -= counter_passed;
|
||||
}
|
||||
ns = mod_64(ktime_to_ns(remaining), apic->timer.period);
|
||||
tmcct = div64_u64(ns, (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
|
||||
|
||||
return tmcct;
|
||||
}
|
||||
@ -653,8 +629,6 @@ static void start_apic_timer(struct kvm_lapic *apic)
|
||||
{
|
||||
ktime_t now = apic->timer.dev.base->get_time();
|
||||
|
||||
apic->timer.last_update = now;
|
||||
|
||||
apic->timer.period = apic_get_reg(apic, APIC_TMICT) *
|
||||
APIC_BUS_CYCLE_NS * apic->timer.divide_count;
|
||||
atomic_set(&apic->timer.pending, 0);
|
||||
@ -1110,16 +1084,6 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
}
|
||||
|
||||
void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
|
||||
{
|
||||
struct kvm_lapic *apic = vcpu->arch.apic;
|
||||
|
||||
if (apic && apic_lvt_vector(apic, APIC_LVTT) == vec)
|
||||
apic->timer.last_update = ktime_add_ns(
|
||||
apic->timer.last_update,
|
||||
apic->timer.period);
|
||||
}
|
||||
|
||||
int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
int vector = kvm_apic_has_interrupt(vcpu);
|
||||
|
@ -12,7 +12,6 @@ struct kvm_lapic {
|
||||
atomic_t pending;
|
||||
s64 period; /* unit: ns */
|
||||
u32 divide_count;
|
||||
ktime_t last_update;
|
||||
struct hrtimer dev;
|
||||
} timer;
|
||||
struct kvm_vcpu *vcpu;
|
||||
@ -42,7 +41,6 @@ void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
|
||||
void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
|
||||
int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
|
||||
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
|
||||
void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
|
||||
|
||||
void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
|
||||
void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
|
||||
|
@ -1698,8 +1698,13 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
|
||||
if (largepage)
|
||||
spte |= PT_PAGE_SIZE_MASK;
|
||||
if (mt_mask) {
|
||||
mt_mask = get_memory_type(vcpu, gfn) <<
|
||||
kvm_x86_ops->get_mt_mask_shift();
|
||||
if (!kvm_is_mmio_pfn(pfn)) {
|
||||
mt_mask = get_memory_type(vcpu, gfn) <<
|
||||
kvm_x86_ops->get_mt_mask_shift();
|
||||
mt_mask |= VMX_EPT_IGMT_BIT;
|
||||
} else
|
||||
mt_mask = MTRR_TYPE_UNCACHABLE <<
|
||||
kvm_x86_ops->get_mt_mask_shift();
|
||||
spte |= mt_mask;
|
||||
}
|
||||
|
||||
|
@ -1600,7 +1600,6 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu)
|
||||
/* Okay, we can deliver the interrupt: grab it and update PIC state. */
|
||||
intr_vector = kvm_cpu_get_interrupt(vcpu);
|
||||
svm_inject_irq(svm, intr_vector);
|
||||
kvm_timer_intr_post(vcpu, intr_vector);
|
||||
out:
|
||||
update_cr8_intercept(vcpu);
|
||||
}
|
||||
|
@ -903,6 +903,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
|
||||
data = vmcs_readl(GUEST_SYSENTER_ESP);
|
||||
break;
|
||||
default:
|
||||
vmx_load_host_state(to_vmx(vcpu));
|
||||
msr = find_msr_entry(to_vmx(vcpu), msr_index);
|
||||
if (msr) {
|
||||
data = msr->data;
|
||||
@ -3285,7 +3286,6 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
if (vcpu->arch.interrupt.pending) {
|
||||
vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
|
||||
kvm_timer_intr_post(vcpu, vcpu->arch.interrupt.nr);
|
||||
if (kvm_cpu_has_interrupt(vcpu))
|
||||
enable_irq_window(vcpu);
|
||||
}
|
||||
@ -3687,8 +3687,7 @@ static int __init vmx_init(void)
|
||||
if (vm_need_ept()) {
|
||||
bypass_guest_pf = 0;
|
||||
kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
|
||||
VMX_EPT_WRITABLE_MASK |
|
||||
VMX_EPT_IGMT_BIT);
|
||||
VMX_EPT_WRITABLE_MASK);
|
||||
kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull,
|
||||
VMX_EPT_EXECUTABLE_MASK,
|
||||
VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT);
|
||||
|
@ -967,7 +967,6 @@ int kvm_dev_ioctl_check_extension(long ext)
|
||||
case KVM_CAP_MMU_SHADOW_CACHE_CONTROL:
|
||||
case KVM_CAP_SET_TSS_ADDR:
|
||||
case KVM_CAP_EXT_CPUID:
|
||||
case KVM_CAP_CLOCKSOURCE:
|
||||
case KVM_CAP_PIT:
|
||||
case KVM_CAP_NOP_IO_DELAY:
|
||||
case KVM_CAP_MP_STATE:
|
||||
@ -992,6 +991,9 @@ int kvm_dev_ioctl_check_extension(long ext)
|
||||
case KVM_CAP_IOMMU:
|
||||
r = iommu_found();
|
||||
break;
|
||||
case KVM_CAP_CLOCKSOURCE:
|
||||
r = boot_cpu_has(X86_FEATURE_CONSTANT_TSC);
|
||||
break;
|
||||
default:
|
||||
r = 0;
|
||||
break;
|
||||
@ -4127,9 +4129,13 @@ static void kvm_free_vcpus(struct kvm *kvm)
|
||||
|
||||
}
|
||||
|
||||
void kvm_arch_destroy_vm(struct kvm *kvm)
|
||||
void kvm_arch_sync_events(struct kvm *kvm)
|
||||
{
|
||||
kvm_free_all_assigned_devices(kvm);
|
||||
}
|
||||
|
||||
void kvm_arch_destroy_vm(struct kvm *kvm)
|
||||
{
|
||||
kvm_iommu_unmap_guest(kvm);
|
||||
kvm_free_pit(kvm);
|
||||
kfree(kvm->arch.vpic);
|
||||
|
@ -134,25 +134,6 @@ int page_is_ram(unsigned long pagenr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pagerange_is_ram(unsigned long start, unsigned long end)
|
||||
{
|
||||
int ram_page = 0, not_rampage = 0;
|
||||
unsigned long page_nr;
|
||||
|
||||
for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT);
|
||||
++page_nr) {
|
||||
if (page_is_ram(page_nr))
|
||||
ram_page = 1;
|
||||
else
|
||||
not_rampage = 1;
|
||||
|
||||
if (ram_page == not_rampage)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ram_page;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix up the linear direct mapping of the kernel to avoid cache attribute
|
||||
* conflicts.
|
||||
|
@ -145,7 +145,7 @@ int __init compute_hash_shift(struct bootnode *nodes, int numnodes,
|
||||
return shift;
|
||||
}
|
||||
|
||||
int early_pfn_to_nid(unsigned long pfn)
|
||||
int __meminit __early_pfn_to_nid(unsigned long pfn)
|
||||
{
|
||||
return phys_to_nid(pfn << PAGE_SHIFT);
|
||||
}
|
||||
|
@ -575,7 +575,6 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
|
||||
address = cpa->vaddr[cpa->curpage];
|
||||
else
|
||||
address = *cpa->vaddr;
|
||||
|
||||
repeat:
|
||||
kpte = lookup_address(address, &level);
|
||||
if (!kpte)
|
||||
@ -812,6 +811,13 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
|
||||
|
||||
vm_unmap_aliases();
|
||||
|
||||
/*
|
||||
* If we're called with lazy mmu updates enabled, the
|
||||
* in-memory pte state may be stale. Flush pending updates to
|
||||
* bring them up to date.
|
||||
*/
|
||||
arch_flush_lazy_mmu_mode();
|
||||
|
||||
cpa.vaddr = addr;
|
||||
cpa.numpages = numpages;
|
||||
cpa.mask_set = mask_set;
|
||||
@ -854,6 +860,13 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
|
||||
} else
|
||||
cpa_flush_all(cache);
|
||||
|
||||
/*
|
||||
* If we've been called with lazy mmu updates enabled, then
|
||||
* make sure that everything gets flushed out before we
|
||||
* return.
|
||||
*/
|
||||
arch_flush_lazy_mmu_mode();
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -211,6 +211,33 @@ chk_conflict(struct memtype *new, struct memtype *entry, unsigned long *type)
|
||||
static struct memtype *cached_entry;
|
||||
static u64 cached_start;
|
||||
|
||||
static int pat_pagerange_is_ram(unsigned long start, unsigned long end)
|
||||
{
|
||||
int ram_page = 0, not_rampage = 0;
|
||||
unsigned long page_nr;
|
||||
|
||||
for (page_nr = (start >> PAGE_SHIFT); page_nr < (end >> PAGE_SHIFT);
|
||||
++page_nr) {
|
||||
/*
|
||||
* For legacy reasons, physical address range in the legacy ISA
|
||||
* region is tracked as non-RAM. This will allow users of
|
||||
* /dev/mem to map portions of legacy ISA region, even when
|
||||
* some of those portions are listed(or not even listed) with
|
||||
* different e820 types(RAM/reserved/..)
|
||||
*/
|
||||
if (page_nr >= (ISA_END_ADDRESS >> PAGE_SHIFT) &&
|
||||
page_is_ram(page_nr))
|
||||
ram_page = 1;
|
||||
else
|
||||
not_rampage = 1;
|
||||
|
||||
if (ram_page == not_rampage)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ram_page;
|
||||
}
|
||||
|
||||
/*
|
||||
* For RAM pages, mark the pages as non WB memory type using
|
||||
* PageNonWB (PG_arch_1). We allow only one set_memory_uc() or
|
||||
@ -336,20 +363,12 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
|
||||
if (new_type)
|
||||
*new_type = actual_type;
|
||||
|
||||
/*
|
||||
* For legacy reasons, some parts of the physical address range in the
|
||||
* legacy 1MB region is treated as non-RAM (even when listed as RAM in
|
||||
* the e820 tables). So we will track the memory attributes of this
|
||||
* legacy 1MB region using the linear memtype_list always.
|
||||
*/
|
||||
if (end >= ISA_END_ADDRESS) {
|
||||
is_range_ram = pagerange_is_ram(start, end);
|
||||
if (is_range_ram == 1)
|
||||
return reserve_ram_pages_type(start, end, req_type,
|
||||
new_type);
|
||||
else if (is_range_ram < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
is_range_ram = pat_pagerange_is_ram(start, end);
|
||||
if (is_range_ram == 1)
|
||||
return reserve_ram_pages_type(start, end, req_type,
|
||||
new_type);
|
||||
else if (is_range_ram < 0)
|
||||
return -EINVAL;
|
||||
|
||||
new = kmalloc(sizeof(struct memtype), GFP_KERNEL);
|
||||
if (!new)
|
||||
@ -446,19 +465,11 @@ int free_memtype(u64 start, u64 end)
|
||||
if (is_ISA_range(start, end - 1))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* For legacy reasons, some parts of the physical address range in the
|
||||
* legacy 1MB region is treated as non-RAM (even when listed as RAM in
|
||||
* the e820 tables). So we will track the memory attributes of this
|
||||
* legacy 1MB region using the linear memtype_list always.
|
||||
*/
|
||||
if (end >= ISA_END_ADDRESS) {
|
||||
is_range_ram = pagerange_is_ram(start, end);
|
||||
if (is_range_ram == 1)
|
||||
return free_ram_pages_type(start, end);
|
||||
else if (is_range_ram < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
is_range_ram = pat_pagerange_is_ram(start, end);
|
||||
if (is_range_ram == 1)
|
||||
return free_ram_pages_type(start, end);
|
||||
else if (is_range_ram < 0)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&memtype_lock);
|
||||
list_for_each_entry(entry, &memtype_list, nd) {
|
||||
@ -626,17 +637,13 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
|
||||
unsigned long flags;
|
||||
unsigned long want_flags = (pgprot_val(*vma_prot) & _PAGE_CACHE_MASK);
|
||||
|
||||
is_ram = pagerange_is_ram(paddr, paddr + size);
|
||||
is_ram = pat_pagerange_is_ram(paddr, paddr + size);
|
||||
|
||||
if (is_ram != 0) {
|
||||
/*
|
||||
* For mapping RAM pages, drivers need to call
|
||||
* set_memory_[uc|wc|wb] directly, for reserve and free, before
|
||||
* setting up the PTE.
|
||||
*/
|
||||
WARN_ON_ONCE(1);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* reserve_pfn_range() doesn't support RAM pages.
|
||||
*/
|
||||
if (is_ram != 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = reserve_memtype(paddr, paddr + size, want_flags, &flags);
|
||||
if (ret)
|
||||
@ -693,7 +700,7 @@ static void free_pfn_range(u64 paddr, unsigned long size)
|
||||
{
|
||||
int is_ram;
|
||||
|
||||
is_ram = pagerange_is_ram(paddr, paddr + size);
|
||||
is_ram = pat_pagerange_is_ram(paddr, paddr + size);
|
||||
if (is_ram == 0)
|
||||
free_memtype(paddr, paddr + size);
|
||||
}
|
||||
|
@ -209,12 +209,19 @@ void blk_abort_queue(struct request_queue *q)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct request *rq, *tmp;
|
||||
LIST_HEAD(list);
|
||||
|
||||
spin_lock_irqsave(q->queue_lock, flags);
|
||||
|
||||
elv_abort_queue(q);
|
||||
|
||||
list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list)
|
||||
/*
|
||||
* Splice entries to local list, to avoid deadlocking if entries
|
||||
* get readded to the timeout list by error handling
|
||||
*/
|
||||
list_splice_init(&q->timeout_list, &list);
|
||||
|
||||
list_for_each_entry_safe(rq, tmp, &list, timeout_list)
|
||||
blk_abort_request(rq);
|
||||
|
||||
spin_unlock_irqrestore(q->queue_lock, flags);
|
||||
|
17
block/bsg.c
17
block/bsg.c
@ -244,7 +244,8 @@ bsg_validate_sgv4_hdr(struct request_queue *q, struct sg_io_v4 *hdr, int *rw)
|
||||
* map sg_io_v4 to a request.
|
||||
*/
|
||||
static struct request *
|
||||
bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm)
|
||||
bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
|
||||
u8 *sense)
|
||||
{
|
||||
struct request_queue *q = bd->queue;
|
||||
struct request *rq, *next_rq = NULL;
|
||||
@ -306,6 +307,10 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm)
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rq->sense = sense;
|
||||
rq->sense_len = 0;
|
||||
|
||||
return rq;
|
||||
out:
|
||||
if (rq->cmd != rq->__cmd)
|
||||
@ -348,9 +353,6 @@ static void bsg_rq_end_io(struct request *rq, int uptodate)
|
||||
static void bsg_add_command(struct bsg_device *bd, struct request_queue *q,
|
||||
struct bsg_command *bc, struct request *rq)
|
||||
{
|
||||
rq->sense = bc->sense;
|
||||
rq->sense_len = 0;
|
||||
|
||||
/*
|
||||
* add bc command to busy queue and submit rq for io
|
||||
*/
|
||||
@ -419,7 +421,7 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
dprintk("rq %p bio %p %u\n", rq, bio, rq->errors);
|
||||
dprintk("rq %p bio %p 0x%x\n", rq, bio, rq->errors);
|
||||
/*
|
||||
* fill in all the output members
|
||||
*/
|
||||
@ -635,7 +637,7 @@ static int __bsg_write(struct bsg_device *bd, const char __user *buf,
|
||||
/*
|
||||
* get a request, fill in the blanks, and add to request queue
|
||||
*/
|
||||
rq = bsg_map_hdr(bd, &bc->hdr, has_write_perm);
|
||||
rq = bsg_map_hdr(bd, &bc->hdr, has_write_perm, bc->sense);
|
||||
if (IS_ERR(rq)) {
|
||||
ret = PTR_ERR(rq);
|
||||
rq = NULL;
|
||||
@ -922,11 +924,12 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
struct request *rq;
|
||||
struct bio *bio, *bidi_bio = NULL;
|
||||
struct sg_io_v4 hdr;
|
||||
u8 sense[SCSI_SENSE_BUFFERSIZE];
|
||||
|
||||
if (copy_from_user(&hdr, uarg, sizeof(hdr)))
|
||||
return -EFAULT;
|
||||
|
||||
rq = bsg_map_hdr(bd, &hdr, file->f_mode & FMODE_WRITE);
|
||||
rq = bsg_map_hdr(bd, &hdr, file->f_mode & FMODE_WRITE, sense);
|
||||
if (IS_ERR(rq))
|
||||
return PTR_ERR(rq);
|
||||
|
||||
|
@ -1087,6 +1087,14 @@ dev_t blk_lookup_devt(const char *name, int partno)
|
||||
if (strcmp(dev_name(dev), name))
|
||||
continue;
|
||||
|
||||
if (partno < disk->minors) {
|
||||
/* We need to return the right devno, even
|
||||
* if the partition doesn't exist yet.
|
||||
*/
|
||||
devt = MKDEV(MAJOR(dev->devt),
|
||||
MINOR(dev->devt) + partno);
|
||||
break;
|
||||
}
|
||||
part = disk_get_part(disk, partno);
|
||||
if (part) {
|
||||
devt = part_devt(part);
|
||||
|
@ -45,7 +45,13 @@ struct priv {
|
||||
|
||||
static inline void setbit128_bbe(void *b, int bit)
|
||||
{
|
||||
__set_bit(bit ^ 0x78, b);
|
||||
__set_bit(bit ^ (0x80 -
|
||||
#ifdef __BIG_ENDIAN
|
||||
BITS_PER_LONG
|
||||
#else
|
||||
BITS_PER_BYTE
|
||||
#endif
|
||||
), b);
|
||||
}
|
||||
|
||||
static int setkey(struct crypto_tfm *parent, const u8 *key,
|
||||
|
@ -773,18 +773,32 @@ unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf,
|
||||
else
|
||||
iowrite32_rep(data_addr, buf, words);
|
||||
|
||||
/* Transfer trailing bytes, if any */
|
||||
if (unlikely(slop)) {
|
||||
__le32 pad;
|
||||
unsigned char pad[4];
|
||||
|
||||
/* Point buf to the tail of buffer */
|
||||
buf += buflen - slop;
|
||||
|
||||
/*
|
||||
* Use io*_rep() accessors here as well to avoid pointlessly
|
||||
* swapping bytes to and fro on the big endian machines...
|
||||
*/
|
||||
if (rw == READ) {
|
||||
pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
|
||||
memcpy(buf + buflen - slop, &pad, slop);
|
||||
if (slop < 3)
|
||||
ioread16_rep(data_addr, pad, 1);
|
||||
else
|
||||
ioread32_rep(data_addr, pad, 1);
|
||||
memcpy(buf, pad, slop);
|
||||
} else {
|
||||
memcpy(&pad, buf + buflen - slop, slop);
|
||||
iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
|
||||
memcpy(pad, buf, slop);
|
||||
if (slop < 3)
|
||||
iowrite16_rep(data_addr, pad, 1);
|
||||
else
|
||||
iowrite32_rep(data_addr, pad, 1);
|
||||
}
|
||||
words++;
|
||||
}
|
||||
return words << 2;
|
||||
return (buflen + 1) & ~1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_sff_data_xfer32);
|
||||
|
||||
|
@ -110,7 +110,8 @@ static const struct via_isa_bridge {
|
||||
{ "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
|
||||
{ "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
|
||||
{ "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA },
|
||||
{ "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES},
|
||||
{ "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
|
||||
{ "vt6415", PCI_DEVICE_ID_VIA_6415, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
|
||||
{ "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
|
||||
{ "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
|
||||
{ "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
|
||||
@ -593,6 +594,7 @@ static int via_reinit_one(struct pci_dev *pdev)
|
||||
#endif
|
||||
|
||||
static const struct pci_device_id via[] = {
|
||||
{ PCI_VDEVICE(VIA, 0x0415), },
|
||||
{ PCI_VDEVICE(VIA, 0x0571), },
|
||||
{ PCI_VDEVICE(VIA, 0x0581), },
|
||||
{ PCI_VDEVICE(VIA, 0x1571), },
|
||||
|
@ -421,19 +421,21 @@ static struct ata_port_operations nv_generic_ops = {
|
||||
.hardreset = ATA_OP_NULL,
|
||||
};
|
||||
|
||||
/* OSDL bz3352 reports that nf2/3 controllers can't determine device
|
||||
* signature reliably. Also, the following thread reports detection
|
||||
* failure on cold boot with the standard debouncing timing.
|
||||
/* nf2 is ripe with hardreset related problems.
|
||||
*
|
||||
* kernel bz#3352 reports nf2/3 controllers can't determine device
|
||||
* signature reliably. The following thread reports detection failure
|
||||
* on cold boot with the standard debouncing timing.
|
||||
*
|
||||
* http://thread.gmane.org/gmane.linux.ide/34098
|
||||
*
|
||||
* Debounce with hotplug timing and request follow-up SRST.
|
||||
* And bz#12176 reports that hardreset simply doesn't work on nf2.
|
||||
* Give up on it and just don't do hardreset.
|
||||
*/
|
||||
static struct ata_port_operations nv_nf2_ops = {
|
||||
.inherits = &nv_common_ops,
|
||||
.inherits = &nv_generic_ops,
|
||||
.freeze = nv_nf2_freeze,
|
||||
.thaw = nv_nf2_thaw,
|
||||
.hardreset = nv_noclassify_hardreset,
|
||||
};
|
||||
|
||||
/* For initial probing after boot and hot plugging, hardreset mostly
|
||||
|
@ -18,6 +18,7 @@
|
||||
enum {
|
||||
AOECMD_ATA,
|
||||
AOECMD_CFG,
|
||||
AOECMD_VEND_MIN = 0xf0,
|
||||
|
||||
AOEFL_RSP = (1<<3),
|
||||
AOEFL_ERR = (1<<2),
|
||||
|
@ -142,6 +142,8 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
|
||||
aoecmd_cfg_rsp(skb);
|
||||
break;
|
||||
default:
|
||||
if (h->cmd >= AOECMD_VEND_MIN)
|
||||
break; /* don't complain about vendor commands */
|
||||
printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd);
|
||||
}
|
||||
exit:
|
||||
|
@ -3390,6 +3390,203 @@ static void free_hba(int i)
|
||||
kfree(p);
|
||||
}
|
||||
|
||||
/* Send a message CDB to the firmware. */
|
||||
static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, unsigned char type)
|
||||
{
|
||||
typedef struct {
|
||||
CommandListHeader_struct CommandHeader;
|
||||
RequestBlock_struct Request;
|
||||
ErrDescriptor_struct ErrorDescriptor;
|
||||
} Command;
|
||||
static const size_t cmd_sz = sizeof(Command) + sizeof(ErrorInfo_struct);
|
||||
Command *cmd;
|
||||
dma_addr_t paddr64;
|
||||
uint32_t paddr32, tag;
|
||||
void __iomem *vaddr;
|
||||
int i, err;
|
||||
|
||||
vaddr = ioremap_nocache(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
|
||||
if (vaddr == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* The Inbound Post Queue only accepts 32-bit physical addresses for the
|
||||
CCISS commands, so they must be allocated from the lower 4GiB of
|
||||
memory. */
|
||||
err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
|
||||
if (err) {
|
||||
iounmap(vaddr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmd = pci_alloc_consistent(pdev, cmd_sz, &paddr64);
|
||||
if (cmd == NULL) {
|
||||
iounmap(vaddr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* This must fit, because of the 32-bit consistent DMA mask. Also,
|
||||
although there's no guarantee, we assume that the address is at
|
||||
least 4-byte aligned (most likely, it's page-aligned). */
|
||||
paddr32 = paddr64;
|
||||
|
||||
cmd->CommandHeader.ReplyQueue = 0;
|
||||
cmd->CommandHeader.SGList = 0;
|
||||
cmd->CommandHeader.SGTotal = 0;
|
||||
cmd->CommandHeader.Tag.lower = paddr32;
|
||||
cmd->CommandHeader.Tag.upper = 0;
|
||||
memset(&cmd->CommandHeader.LUN.LunAddrBytes, 0, 8);
|
||||
|
||||
cmd->Request.CDBLen = 16;
|
||||
cmd->Request.Type.Type = TYPE_MSG;
|
||||
cmd->Request.Type.Attribute = ATTR_HEADOFQUEUE;
|
||||
cmd->Request.Type.Direction = XFER_NONE;
|
||||
cmd->Request.Timeout = 0; /* Don't time out */
|
||||
cmd->Request.CDB[0] = opcode;
|
||||
cmd->Request.CDB[1] = type;
|
||||
memset(&cmd->Request.CDB[2], 0, 14); /* the rest of the CDB is reserved */
|
||||
|
||||
cmd->ErrorDescriptor.Addr.lower = paddr32 + sizeof(Command);
|
||||
cmd->ErrorDescriptor.Addr.upper = 0;
|
||||
cmd->ErrorDescriptor.Len = sizeof(ErrorInfo_struct);
|
||||
|
||||
writel(paddr32, vaddr + SA5_REQUEST_PORT_OFFSET);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
tag = readl(vaddr + SA5_REPLY_PORT_OFFSET);
|
||||
if ((tag & ~3) == paddr32)
|
||||
break;
|
||||
schedule_timeout_uninterruptible(HZ);
|
||||
}
|
||||
|
||||
iounmap(vaddr);
|
||||
|
||||
/* we leak the DMA buffer here ... no choice since the controller could
|
||||
still complete the command. */
|
||||
if (i == 10) {
|
||||
printk(KERN_ERR "cciss: controller message %02x:%02x timed out\n",
|
||||
opcode, type);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
pci_free_consistent(pdev, cmd_sz, cmd, paddr64);
|
||||
|
||||
if (tag & 2) {
|
||||
printk(KERN_ERR "cciss: controller message %02x:%02x failed\n",
|
||||
opcode, type);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "cciss: controller message %02x:%02x succeeded\n",
|
||||
opcode, type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define cciss_soft_reset_controller(p) cciss_message(p, 1, 0)
|
||||
#define cciss_noop(p) cciss_message(p, 3, 0)
|
||||
|
||||
static __devinit int cciss_reset_msi(struct pci_dev *pdev)
|
||||
{
|
||||
/* the #defines are stolen from drivers/pci/msi.h. */
|
||||
#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
|
||||
#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
|
||||
|
||||
int pos;
|
||||
u16 control = 0;
|
||||
|
||||
pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
|
||||
if (pos) {
|
||||
pci_read_config_word(pdev, msi_control_reg(pos), &control);
|
||||
if (control & PCI_MSI_FLAGS_ENABLE) {
|
||||
printk(KERN_INFO "cciss: resetting MSI\n");
|
||||
pci_write_config_word(pdev, msi_control_reg(pos), control & ~PCI_MSI_FLAGS_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
|
||||
if (pos) {
|
||||
pci_read_config_word(pdev, msi_control_reg(pos), &control);
|
||||
if (control & PCI_MSIX_FLAGS_ENABLE) {
|
||||
printk(KERN_INFO "cciss: resetting MSI-X\n");
|
||||
pci_write_config_word(pdev, msi_control_reg(pos), control & ~PCI_MSIX_FLAGS_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This does a hard reset of the controller using PCI power management
|
||||
* states. */
|
||||
static __devinit int cciss_hard_reset_controller(struct pci_dev *pdev)
|
||||
{
|
||||
u16 pmcsr, saved_config_space[32];
|
||||
int i, pos;
|
||||
|
||||
printk(KERN_INFO "cciss: using PCI PM to reset controller\n");
|
||||
|
||||
/* This is very nearly the same thing as
|
||||
|
||||
pci_save_state(pci_dev);
|
||||
pci_set_power_state(pci_dev, PCI_D3hot);
|
||||
pci_set_power_state(pci_dev, PCI_D0);
|
||||
pci_restore_state(pci_dev);
|
||||
|
||||
but we can't use these nice canned kernel routines on
|
||||
kexec, because they also check the MSI/MSI-X state in PCI
|
||||
configuration space and do the wrong thing when it is
|
||||
set/cleared. Also, the pci_save/restore_state functions
|
||||
violate the ordering requirements for restoring the
|
||||
configuration space from the CCISS document (see the
|
||||
comment below). So we roll our own .... */
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
pci_read_config_word(pdev, 2*i, &saved_config_space[i]);
|
||||
|
||||
pos = pci_find_capability(pdev, PCI_CAP_ID_PM);
|
||||
if (pos == 0) {
|
||||
printk(KERN_ERR "cciss_reset_controller: PCI PM not supported\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Quoting from the Open CISS Specification: "The Power
|
||||
* Management Control/Status Register (CSR) controls the power
|
||||
* state of the device. The normal operating state is D0,
|
||||
* CSR=00h. The software off state is D3, CSR=03h. To reset
|
||||
* the controller, place the interface device in D3 then to
|
||||
* D0, this causes a secondary PCI reset which will reset the
|
||||
* controller." */
|
||||
|
||||
/* enter the D3hot power management state */
|
||||
pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr);
|
||||
pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
|
||||
pmcsr |= PCI_D3hot;
|
||||
pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
|
||||
|
||||
schedule_timeout_uninterruptible(HZ >> 1);
|
||||
|
||||
/* enter the D0 power management state */
|
||||
pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
|
||||
pmcsr |= PCI_D0;
|
||||
pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
|
||||
|
||||
schedule_timeout_uninterruptible(HZ >> 1);
|
||||
|
||||
/* Restore the PCI configuration space. The Open CISS
|
||||
* Specification says, "Restore the PCI Configuration
|
||||
* Registers, offsets 00h through 60h. It is important to
|
||||
* restore the command register, 16-bits at offset 04h,
|
||||
* last. Do not restore the configuration status register,
|
||||
* 16-bits at offset 06h." Note that the offset is 2*i. */
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (i == 2 || i == 3)
|
||||
continue;
|
||||
pci_write_config_word(pdev, 2*i, saved_config_space[i]);
|
||||
}
|
||||
wmb();
|
||||
pci_write_config_word(pdev, 4, saved_config_space[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is it. Find all the controllers and register them. I really hate
|
||||
* stealing all these major device numbers.
|
||||
@ -3404,6 +3601,24 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
|
||||
int dac, return_code;
|
||||
InquiryData_struct *inq_buff = NULL;
|
||||
|
||||
if (reset_devices) {
|
||||
/* Reset the controller with a PCI power-cycle */
|
||||
if (cciss_hard_reset_controller(pdev) || cciss_reset_msi(pdev))
|
||||
return -ENODEV;
|
||||
|
||||
/* Some devices (notably the HP Smart Array 5i Controller)
|
||||
need a little pause here */
|
||||
schedule_timeout_uninterruptible(30*HZ);
|
||||
|
||||
/* Now try to get the controller to respond to a no-op */
|
||||
for (i=0; i<12; i++) {
|
||||
if (cciss_noop(pdev) == 0)
|
||||
break;
|
||||
else
|
||||
printk("cciss: no-op failed%s\n", (i < 11 ? "; re-trying" : ""));
|
||||
}
|
||||
}
|
||||
|
||||
i = alloc_cciss_hba();
|
||||
if (i < 0)
|
||||
return -1;
|
||||
|
@ -558,6 +558,8 @@ static void process_fd_request(void);
|
||||
static void recalibrate_floppy(void);
|
||||
static void floppy_shutdown(unsigned long);
|
||||
|
||||
static int floppy_request_regions(int);
|
||||
static void floppy_release_regions(int);
|
||||
static int floppy_grab_irq_and_dma(void);
|
||||
static void floppy_release_irq_and_dma(void);
|
||||
|
||||
@ -4274,8 +4276,7 @@ static int __init floppy_init(void)
|
||||
FDCS->rawcmd = 2;
|
||||
if (user_reset_fdc(-1, FD_RESET_ALWAYS, 0)) {
|
||||
/* free ioports reserved by floppy_grab_irq_and_dma() */
|
||||
release_region(FDCS->address + 2, 4);
|
||||
release_region(FDCS->address + 7, 1);
|
||||
floppy_release_regions(fdc);
|
||||
FDCS->address = -1;
|
||||
FDCS->version = FDC_NONE;
|
||||
continue;
|
||||
@ -4284,8 +4285,7 @@ static int __init floppy_init(void)
|
||||
FDCS->version = get_fdc_version();
|
||||
if (FDCS->version == FDC_NONE) {
|
||||
/* free ioports reserved by floppy_grab_irq_and_dma() */
|
||||
release_region(FDCS->address + 2, 4);
|
||||
release_region(FDCS->address + 7, 1);
|
||||
floppy_release_regions(fdc);
|
||||
FDCS->address = -1;
|
||||
continue;
|
||||
}
|
||||
@ -4358,6 +4358,47 @@ out_put_disk:
|
||||
|
||||
static DEFINE_SPINLOCK(floppy_usage_lock);
|
||||
|
||||
static const struct io_region {
|
||||
int offset;
|
||||
int size;
|
||||
} io_regions[] = {
|
||||
{ 2, 1 },
|
||||
/* address + 3 is sometimes reserved by pnp bios for motherboard */
|
||||
{ 4, 2 },
|
||||
/* address + 6 is reserved, and may be taken by IDE.
|
||||
* Unfortunately, Adaptec doesn't know this :-(, */
|
||||
{ 7, 1 },
|
||||
};
|
||||
|
||||
static void floppy_release_allocated_regions(int fdc, const struct io_region *p)
|
||||
{
|
||||
while (p != io_regions) {
|
||||
p--;
|
||||
release_region(FDCS->address + p->offset, p->size);
|
||||
}
|
||||
}
|
||||
|
||||
#define ARRAY_END(X) (&((X)[ARRAY_SIZE(X)]))
|
||||
|
||||
static int floppy_request_regions(int fdc)
|
||||
{
|
||||
const struct io_region *p;
|
||||
|
||||
for (p = io_regions; p < ARRAY_END(io_regions); p++) {
|
||||
if (!request_region(FDCS->address + p->offset, p->size, "floppy")) {
|
||||
DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address + p->offset);
|
||||
floppy_release_allocated_regions(fdc, p);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void floppy_release_regions(int fdc)
|
||||
{
|
||||
floppy_release_allocated_regions(fdc, ARRAY_END(io_regions));
|
||||
}
|
||||
|
||||
static int floppy_grab_irq_and_dma(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
@ -4399,18 +4440,8 @@ static int floppy_grab_irq_and_dma(void)
|
||||
|
||||
for (fdc = 0; fdc < N_FDC; fdc++) {
|
||||
if (FDCS->address != -1) {
|
||||
if (!request_region(FDCS->address + 2, 4, "floppy")) {
|
||||
DPRINT("Floppy io-port 0x%04lx in use\n",
|
||||
FDCS->address + 2);
|
||||
goto cleanup1;
|
||||
}
|
||||
if (!request_region(FDCS->address + 7, 1, "floppy DIR")) {
|
||||
DPRINT("Floppy io-port 0x%04lx in use\n",
|
||||
FDCS->address + 7);
|
||||
goto cleanup2;
|
||||
}
|
||||
/* address + 6 is reserved, and may be taken by IDE.
|
||||
* Unfortunately, Adaptec doesn't know this :-(, */
|
||||
if (floppy_request_regions(fdc))
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
for (fdc = 0; fdc < N_FDC; fdc++) {
|
||||
@ -4432,15 +4463,11 @@ static int floppy_grab_irq_and_dma(void)
|
||||
fdc = 0;
|
||||
irqdma_allocated = 1;
|
||||
return 0;
|
||||
cleanup2:
|
||||
release_region(FDCS->address + 2, 4);
|
||||
cleanup1:
|
||||
cleanup:
|
||||
fd_free_irq();
|
||||
fd_free_dma();
|
||||
while (--fdc >= 0) {
|
||||
release_region(FDCS->address + 2, 4);
|
||||
release_region(FDCS->address + 7, 1);
|
||||
}
|
||||
while (--fdc >= 0)
|
||||
floppy_release_regions(fdc);
|
||||
spin_lock_irqsave(&floppy_usage_lock, flags);
|
||||
usage_count--;
|
||||
spin_unlock_irqrestore(&floppy_usage_lock, flags);
|
||||
@ -4501,10 +4528,8 @@ static void floppy_release_irq_and_dma(void)
|
||||
#endif
|
||||
old_fdc = fdc;
|
||||
for (fdc = 0; fdc < N_FDC; fdc++)
|
||||
if (FDCS->address != -1) {
|
||||
release_region(FDCS->address + 2, 4);
|
||||
release_region(FDCS->address + 7, 1);
|
||||
}
|
||||
if (FDCS->address != -1)
|
||||
floppy_release_regions(fdc);
|
||||
fdc = old_fdc;
|
||||
}
|
||||
|
||||
|
@ -422,7 +422,7 @@ static void xs(char *buf, char *targ, int len)
|
||||
|
||||
for (k = 0; k < len; k++) {
|
||||
char c = *buf++;
|
||||
if (c != ' ' || c != l)
|
||||
if (c != ' ' && c != l)
|
||||
l = *targ++ = c;
|
||||
}
|
||||
if (l == ' ')
|
||||
|
@ -518,6 +518,7 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v
|
||||
dma_chan_name(chan), err);
|
||||
else
|
||||
break;
|
||||
chan->private = NULL;
|
||||
chan = NULL;
|
||||
}
|
||||
}
|
||||
@ -536,6 +537,7 @@ void dma_release_channel(struct dma_chan *chan)
|
||||
WARN_ONCE(chan->client_count != 1,
|
||||
"chan reference count %d != 1\n", chan->client_count);
|
||||
dma_chan_put(chan);
|
||||
chan->private = NULL;
|
||||
mutex_unlock(&dma_list_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_release_channel);
|
||||
|
@ -560,7 +560,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
|
||||
struct dw_dma_slave *dws = dwc->dws;
|
||||
struct dw_dma_slave *dws = chan->private;
|
||||
struct dw_desc *prev;
|
||||
struct dw_desc *first;
|
||||
u32 ctllo;
|
||||
@ -790,7 +790,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
|
||||
cfghi = DWC_CFGH_FIFO_MODE;
|
||||
cfglo = 0;
|
||||
|
||||
dws = dwc->dws;
|
||||
dws = chan->private;
|
||||
if (dws) {
|
||||
/*
|
||||
* We need controller-specific data to set up slave
|
||||
@ -866,7 +866,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
|
||||
spin_lock_bh(&dwc->lock);
|
||||
list_splice_init(&dwc->free_list, &list);
|
||||
dwc->descs_allocated = 0;
|
||||
dwc->dws = NULL;
|
||||
|
||||
/* Disable interrupts */
|
||||
channel_clear_bit(dw, MASK.XFER, dwc->mask);
|
||||
|
@ -139,8 +139,6 @@ struct dw_dma_chan {
|
||||
struct list_head queue;
|
||||
struct list_head free_list;
|
||||
|
||||
struct dw_dma_slave *dws;
|
||||
|
||||
unsigned int descs_allocated;
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* linux/drivers/firmware/memmap.c
|
||||
* Copyright (C) 2008 SUSE LINUX Products GmbH
|
||||
* by Bernhard Walle <bwalle@suse.de>
|
||||
* by Bernhard Walle <bernhard.walle@gmx.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License v2.0 as published by
|
||||
|
@ -80,18 +80,17 @@ config DRM_I915
|
||||
XFree86 4.4 and above. If unsure, build this and i830 as modules and
|
||||
the X server will load the correct one.
|
||||
|
||||
endchoice
|
||||
|
||||
config DRM_I915_KMS
|
||||
bool "Enable modesetting on intel by default"
|
||||
depends on DRM_I915
|
||||
help
|
||||
Choose this option if you want kernel modesetting enabled by default,
|
||||
and you have a new enough userspace to support this. Running old
|
||||
userspaces with this enabled will cause pain. Note that this causes
|
||||
the driver to bind to PCI devices, which precludes loading things
|
||||
like intelfb.
|
||||
Choose this option if you want kernel modesetting enabled by default,
|
||||
and you have a new enough userspace to support this. Running old
|
||||
userspaces with this enabled will cause pain. Note that this causes
|
||||
the driver to bind to PCI devices, which precludes loading things
|
||||
like intelfb.
|
||||
|
||||
endchoice
|
||||
|
||||
config DRM_MGA
|
||||
tristate "Matrox g200/g400"
|
||||
|
@ -1300,7 +1300,13 @@ static const struct hid_device_id hid_blacklist[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
|
||||
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
|
||||
@ -1605,6 +1611,7 @@ static const struct hid_device_id hid_ignore_list[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3) },
|
||||
@ -1612,10 +1619,6 @@ static const struct hid_device_id hid_ignore_list[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD5) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
|
||||
@ -1626,8 +1629,6 @@ static const struct hid_device_id hid_ignore_list[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -348,6 +348,9 @@
|
||||
#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
|
||||
#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
|
||||
|
||||
#define USB_VENDOR_ID_POWERCOM 0x0d9f
|
||||
#define USB_DEVICE_ID_POWERCOM_UPS 0x0002
|
||||
|
||||
#define USB_VENDOR_ID_SAITEK 0x06a3
|
||||
#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
|
||||
|
||||
|
@ -267,8 +267,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
|
||||
default:
|
||||
{
|
||||
struct hid_device *hid = dev->hid;
|
||||
if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
|
||||
return -EINVAL;
|
||||
if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
|
||||
int len;
|
||||
@ -277,8 +279,9 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
|
||||
len = strlen(hid->name) + 1;
|
||||
if (len > _IOC_SIZE(cmd))
|
||||
len = _IOC_SIZE(cmd);
|
||||
return copy_to_user(user_arg, hid->name, len) ?
|
||||
ret = copy_to_user(user_arg, hid->name, len) ?
|
||||
-EFAULT : len;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
|
||||
@ -288,12 +291,13 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
|
||||
len = strlen(hid->phys) + 1;
|
||||
if (len > _IOC_SIZE(cmd))
|
||||
len = _IOC_SIZE(cmd);
|
||||
return copy_to_user(user_arg, hid->phys, len) ?
|
||||
ret = copy_to_user(user_arg, hid->phys, len) ?
|
||||
-EFAULT : len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = -ENOTTY;
|
||||
ret = -ENOTTY;
|
||||
}
|
||||
unlock_kernel();
|
||||
return ret;
|
||||
|
@ -1872,7 +1872,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
|
||||
|
||||
devid = superio_inw(sioaddr, SIO_REG_MANID);
|
||||
if (devid != SIO_FINTEK_ID) {
|
||||
printk(KERN_INFO DRVNAME ": Not a Fintek device\n");
|
||||
pr_debug(DRVNAME ": Not a Fintek device\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@ -1932,7 +1932,7 @@ static int __init f71882fg_device_add(unsigned short address,
|
||||
res.name = f71882fg_pdev->name;
|
||||
err = acpi_check_resource_conflict(&res);
|
||||
if (err)
|
||||
return err;
|
||||
goto exit_device_put;
|
||||
|
||||
err = platform_device_add_resources(f71882fg_pdev, &res, 1);
|
||||
if (err) {
|
||||
|
@ -166,6 +166,18 @@ static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3};
|
||||
}, \
|
||||
.driver_data = &lis3lv02d_axis_##_axis \
|
||||
}
|
||||
|
||||
#define AXIS_DMI_MATCH2(_ident, _class1, _name1, \
|
||||
_class2, _name2, \
|
||||
_axis) { \
|
||||
.ident = _ident, \
|
||||
.callback = lis3lv02d_dmi_matched, \
|
||||
.matches = { \
|
||||
DMI_MATCH(DMI_##_class1, _name1), \
|
||||
DMI_MATCH(DMI_##_class2, _name2), \
|
||||
}, \
|
||||
.driver_data = &lis3lv02d_axis_##_axis \
|
||||
}
|
||||
static struct dmi_system_id lis3lv02d_dmi_ids[] = {
|
||||
/* product names are truncated to match all kinds of a same model */
|
||||
AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
|
||||
@ -179,6 +191,16 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
|
||||
AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd),
|
||||
AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
|
||||
AXIS_DMI_MATCH("NC671xx", "HP Compaq 671", xy_swap_yz_inverted),
|
||||
/* Intel-based HP Pavilion dv5 */
|
||||
AXIS_DMI_MATCH2("HPDV5_I",
|
||||
PRODUCT_NAME, "HP Pavilion dv5",
|
||||
BOARD_NAME, "3603",
|
||||
x_inverted),
|
||||
/* AMD-based HP Pavilion dv5 */
|
||||
AXIS_DMI_MATCH2("HPDV5_A",
|
||||
PRODUCT_NAME, "HP Pavilion dv5",
|
||||
BOARD_NAME, "3600",
|
||||
y_inverted),
|
||||
{ NULL, }
|
||||
/* Laptop models without axis info (yet):
|
||||
* "NC6910" "HP Compaq 6910"
|
||||
@ -213,9 +235,49 @@ static struct delayed_led_classdev hpled_led = {
|
||||
.set_brightness = hpled_set,
|
||||
};
|
||||
|
||||
static acpi_status
|
||||
lis3lv02d_get_resource(struct acpi_resource *resource, void *context)
|
||||
{
|
||||
if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
|
||||
struct acpi_resource_extended_irq *irq;
|
||||
u32 *device_irq = context;
|
||||
|
||||
irq = &resource->data.extended_irq;
|
||||
*device_irq = irq->interrupts[0];
|
||||
}
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static void lis3lv02d_enum_resources(struct acpi_device *device)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
|
||||
lis3lv02d_get_resource, &adev.irq);
|
||||
if (ACPI_FAILURE(status))
|
||||
printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
|
||||
}
|
||||
|
||||
static s16 lis3lv02d_read_16(acpi_handle handle, int reg)
|
||||
{
|
||||
u8 lo, hi;
|
||||
|
||||
adev.read(handle, reg - 1, &lo);
|
||||
adev.read(handle, reg, &hi);
|
||||
/* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
|
||||
return (s16)((hi << 8) | lo);
|
||||
}
|
||||
|
||||
static s16 lis3lv02d_read_8(acpi_handle handle, int reg)
|
||||
{
|
||||
s8 lo;
|
||||
adev.read(handle, reg, &lo);
|
||||
return lo;
|
||||
}
|
||||
|
||||
static int lis3lv02d_add(struct acpi_device *device)
|
||||
{
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
if (!device)
|
||||
@ -229,10 +291,22 @@ static int lis3lv02d_add(struct acpi_device *device)
|
||||
strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
|
||||
device->driver_data = &adev;
|
||||
|
||||
lis3lv02d_acpi_read(device->handle, WHO_AM_I, &val);
|
||||
if ((val != LIS3LV02DL_ID) && (val != LIS302DL_ID)) {
|
||||
lis3lv02d_acpi_read(device->handle, WHO_AM_I, &adev.whoami);
|
||||
switch (adev.whoami) {
|
||||
case LIS_DOUBLE_ID:
|
||||
printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n");
|
||||
adev.read_data = lis3lv02d_read_16;
|
||||
adev.mdps_max_val = 2048;
|
||||
break;
|
||||
case LIS_SINGLE_ID:
|
||||
printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n");
|
||||
adev.read_data = lis3lv02d_read_8;
|
||||
adev.mdps_max_val = 128;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR DRIVER_NAME
|
||||
": Accelerometer chip not LIS3LV02D{L,Q}\n");
|
||||
": unknown sensor type 0x%X\n", adev.whoami);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If possible use a "standard" axes order */
|
||||
@ -247,6 +321,9 @@ static int lis3lv02d_add(struct acpi_device *device)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* obtain IRQ number of our device from ACPI */
|
||||
lis3lv02d_enum_resources(adev.device);
|
||||
|
||||
ret = lis3lv02d_init_device(&adev);
|
||||
if (ret) {
|
||||
flush_work(&hpled_led.work);
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright (C) 2007-2008 Yan Burman
|
||||
* Copyright (C) 2008 Eric Piel
|
||||
* Copyright (C) 2008 Pavel Machek
|
||||
* Copyright (C) 2008-2009 Pavel Machek
|
||||
*
|
||||
* 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
|
||||
@ -35,6 +35,7 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <asm/atomic.h>
|
||||
#include "lis3lv02d.h"
|
||||
@ -52,24 +53,14 @@
|
||||
* joystick.
|
||||
*/
|
||||
|
||||
/* Maximum value our axis may get for the input device (signed 12 bits) */
|
||||
#define MDPS_MAX_VAL 2048
|
||||
struct acpi_lis3lv02d adev = {
|
||||
.misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(adev.misc_wait),
|
||||
};
|
||||
|
||||
struct acpi_lis3lv02d adev;
|
||||
EXPORT_SYMBOL_GPL(adev);
|
||||
|
||||
static int lis3lv02d_add_fs(struct acpi_device *device);
|
||||
|
||||
static s16 lis3lv02d_read_16(acpi_handle handle, int reg)
|
||||
{
|
||||
u8 lo, hi;
|
||||
|
||||
adev.read(handle, reg, &lo);
|
||||
adev.read(handle, reg + 1, &hi);
|
||||
/* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
|
||||
return (s16)((hi << 8) | lo);
|
||||
}
|
||||
|
||||
/**
|
||||
* lis3lv02d_get_axis - For the given axis, give the value converted
|
||||
* @axis: 1,2,3 - can also be negative
|
||||
@ -98,9 +89,9 @@ static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z)
|
||||
{
|
||||
int position[3];
|
||||
|
||||
position[0] = lis3lv02d_read_16(handle, OUTX_L);
|
||||
position[1] = lis3lv02d_read_16(handle, OUTY_L);
|
||||
position[2] = lis3lv02d_read_16(handle, OUTZ_L);
|
||||
position[0] = adev.read_data(handle, OUTX);
|
||||
position[1] = adev.read_data(handle, OUTY);
|
||||
position[2] = adev.read_data(handle, OUTZ);
|
||||
|
||||
*x = lis3lv02d_get_axis(adev.ac.x, position);
|
||||
*y = lis3lv02d_get_axis(adev.ac.y, position);
|
||||
@ -110,26 +101,13 @@ static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z)
|
||||
void lis3lv02d_poweroff(acpi_handle handle)
|
||||
{
|
||||
adev.is_on = 0;
|
||||
/* disable X,Y,Z axis and power down */
|
||||
adev.write(handle, CTRL_REG1, 0x00);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
|
||||
|
||||
void lis3lv02d_poweron(acpi_handle handle)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
adev.is_on = 1;
|
||||
adev.init(handle);
|
||||
adev.write(handle, FF_WU_CFG, 0);
|
||||
/*
|
||||
* BDU: LSB and MSB values are not updated until both have been read.
|
||||
* So the value read will always be correct.
|
||||
* IEN: Interrupt for free-fall and DD, not for data-ready.
|
||||
*/
|
||||
adev.read(handle, CTRL_REG2, &val);
|
||||
val |= CTRL2_BDU | CTRL2_IEN;
|
||||
adev.write(handle, CTRL_REG2, val);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
|
||||
|
||||
@ -162,6 +140,140 @@ static void lis3lv02d_decrease_use(struct acpi_lis3lv02d *dev)
|
||||
mutex_unlock(&dev->lock);
|
||||
}
|
||||
|
||||
static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
|
||||
{
|
||||
/*
|
||||
* Be careful: on some HP laptops the bios force DD when on battery and
|
||||
* the lid is closed. This leads to interrupts as soon as a little move
|
||||
* is done.
|
||||
*/
|
||||
atomic_inc(&adev.count);
|
||||
|
||||
wake_up_interruptible(&adev.misc_wait);
|
||||
kill_fasync(&adev.async_queue, SIGIO, POLL_IN);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (test_and_set_bit(0, &adev.misc_opened))
|
||||
return -EBUSY; /* already open */
|
||||
|
||||
atomic_set(&adev.count, 0);
|
||||
|
||||
/*
|
||||
* The sensor can generate interrupts for free-fall and direction
|
||||
* detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
|
||||
* the things simple and _fast_ we activate it only for free-fall, so
|
||||
* no need to read register (very slow with ACPI). For the same reason,
|
||||
* we forbid shared interrupts.
|
||||
*
|
||||
* IRQF_TRIGGER_RISING seems pointless on HP laptops because the
|
||||
* io-apic is not configurable (and generates a warning) but I keep it
|
||||
* in case of support for other hardware.
|
||||
*/
|
||||
ret = request_irq(adev.irq, lis302dl_interrupt, IRQF_TRIGGER_RISING,
|
||||
DRIVER_NAME, &adev);
|
||||
|
||||
if (ret) {
|
||||
clear_bit(0, &adev.misc_opened);
|
||||
printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", adev.irq);
|
||||
return -EBUSY;
|
||||
}
|
||||
lis3lv02d_increase_use(&adev);
|
||||
printk("lis3: registered interrupt %d\n", adev.irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
fasync_helper(-1, file, 0, &adev.async_queue);
|
||||
lis3lv02d_decrease_use(&adev);
|
||||
free_irq(adev.irq, &adev);
|
||||
clear_bit(0, &adev.misc_opened); /* release the device */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
u32 data;
|
||||
unsigned char byte_data;
|
||||
ssize_t retval = 1;
|
||||
|
||||
if (count < 1)
|
||||
return -EINVAL;
|
||||
|
||||
add_wait_queue(&adev.misc_wait, &wait);
|
||||
while (true) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
data = atomic_xchg(&adev.count, 0);
|
||||
if (data)
|
||||
break;
|
||||
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
retval = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (signal_pending(current)) {
|
||||
retval = -ERESTARTSYS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
schedule();
|
||||
}
|
||||
|
||||
if (data < 255)
|
||||
byte_data = data;
|
||||
else
|
||||
byte_data = 255;
|
||||
|
||||
/* make sure we are not going into copy_to_user() with
|
||||
* TASK_INTERRUPTIBLE state */
|
||||
set_current_state(TASK_RUNNING);
|
||||
if (copy_to_user(buf, &byte_data, sizeof(byte_data)))
|
||||
retval = -EFAULT;
|
||||
|
||||
out:
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&adev.misc_wait, &wait);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
poll_wait(file, &adev.misc_wait, wait);
|
||||
if (atomic_read(&adev.count))
|
||||
return POLLIN | POLLRDNORM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
|
||||
{
|
||||
return fasync_helper(fd, file, on, &adev.async_queue);
|
||||
}
|
||||
|
||||
static const struct file_operations lis3lv02d_misc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = no_llseek,
|
||||
.read = lis3lv02d_misc_read,
|
||||
.open = lis3lv02d_misc_open,
|
||||
.release = lis3lv02d_misc_release,
|
||||
.poll = lis3lv02d_misc_poll,
|
||||
.fasync = lis3lv02d_misc_fasync,
|
||||
};
|
||||
|
||||
static struct miscdevice lis3lv02d_misc_device = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "freefall",
|
||||
.fops = &lis3lv02d_misc_fops,
|
||||
};
|
||||
|
||||
/**
|
||||
* lis3lv02d_joystick_kthread - Kthread polling function
|
||||
* @data: unused - here to conform to threadfn prototype
|
||||
@ -203,7 +315,6 @@ static void lis3lv02d_joystick_close(struct input_dev *input)
|
||||
lis3lv02d_decrease_use(&adev);
|
||||
}
|
||||
|
||||
|
||||
static inline void lis3lv02d_calibrate_joystick(void)
|
||||
{
|
||||
lis3lv02d_get_xyz(adev.device->handle, &adev.xcalib, &adev.ycalib, &adev.zcalib);
|
||||
@ -231,9 +342,9 @@ int lis3lv02d_joystick_enable(void)
|
||||
adev.idev->close = lis3lv02d_joystick_close;
|
||||
|
||||
set_bit(EV_ABS, adev.idev->evbit);
|
||||
input_set_abs_params(adev.idev, ABS_X, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3);
|
||||
input_set_abs_params(adev.idev, ABS_Y, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3);
|
||||
input_set_abs_params(adev.idev, ABS_Z, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3);
|
||||
input_set_abs_params(adev.idev, ABS_X, -adev.mdps_max_val, adev.mdps_max_val, 3, 3);
|
||||
input_set_abs_params(adev.idev, ABS_Y, -adev.mdps_max_val, adev.mdps_max_val, 3, 3);
|
||||
input_set_abs_params(adev.idev, ABS_Z, -adev.mdps_max_val, adev.mdps_max_val, 3, 3);
|
||||
|
||||
err = input_register_device(adev.idev);
|
||||
if (err) {
|
||||
@ -250,6 +361,7 @@ void lis3lv02d_joystick_disable(void)
|
||||
if (!adev.idev)
|
||||
return;
|
||||
|
||||
misc_deregister(&lis3lv02d_misc_device);
|
||||
input_unregister_device(adev.idev);
|
||||
adev.idev = NULL;
|
||||
}
|
||||
@ -268,6 +380,19 @@ int lis3lv02d_init_device(struct acpi_lis3lv02d *dev)
|
||||
if (lis3lv02d_joystick_enable())
|
||||
printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
|
||||
|
||||
printk("lis3_init_device: irq %d\n", dev->irq);
|
||||
|
||||
/* if we did not get an IRQ from ACPI - we have nothing more to do */
|
||||
if (!dev->irq) {
|
||||
printk(KERN_ERR DRIVER_NAME
|
||||
": No IRQ in ACPI. Disabling /dev/freefall\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
printk("lis3: registering device\n");
|
||||
if (misc_register(&lis3lv02d_misc_device))
|
||||
printk(KERN_ERR DRIVER_NAME ": misc_register failed\n");
|
||||
out:
|
||||
lis3lv02d_decrease_use(dev);
|
||||
return 0;
|
||||
}
|
||||
@ -351,6 +476,6 @@ int lis3lv02d_remove_fs(void)
|
||||
EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
|
||||
|
||||
MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
|
||||
MODULE_AUTHOR("Yan Burman and Eric Piel");
|
||||
MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
@ -22,12 +22,15 @@
|
||||
/*
|
||||
* The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to
|
||||
* be connected via SPI. There exists also several similar chips (such as LIS302DL or
|
||||
* LIS3L02DQ) but not in the HP laptops and they have slightly different registers.
|
||||
* LIS3L02DQ) and they have slightly different registers, but we can provide a
|
||||
* common interface for all of them.
|
||||
* They can also be connected via I²C.
|
||||
*/
|
||||
|
||||
#define LIS3LV02DL_ID 0x3A /* Also the LIS3LV02DQ */
|
||||
#define LIS302DL_ID 0x3B /* Also the LIS202DL! */
|
||||
/* 2-byte registers */
|
||||
#define LIS_DOUBLE_ID 0x3A /* LIS3LV02D[LQ] */
|
||||
/* 1-byte registers */
|
||||
#define LIS_SINGLE_ID 0x3B /* LIS[32]02DL and others */
|
||||
|
||||
enum lis3lv02d_reg {
|
||||
WHO_AM_I = 0x0F,
|
||||
@ -44,10 +47,13 @@ enum lis3lv02d_reg {
|
||||
STATUS_REG = 0x27,
|
||||
OUTX_L = 0x28,
|
||||
OUTX_H = 0x29,
|
||||
OUTX = 0x29,
|
||||
OUTY_L = 0x2A,
|
||||
OUTY_H = 0x2B,
|
||||
OUTY = 0x2B,
|
||||
OUTZ_L = 0x2C,
|
||||
OUTZ_H = 0x2D,
|
||||
OUTZ = 0x2D,
|
||||
FF_WU_CFG = 0x30,
|
||||
FF_WU_SRC = 0x31,
|
||||
FF_WU_ACK = 0x32,
|
||||
@ -159,6 +165,10 @@ struct acpi_lis3lv02d {
|
||||
acpi_status (*write) (acpi_handle handle, int reg, u8 val);
|
||||
acpi_status (*read) (acpi_handle handle, int reg, u8 *ret);
|
||||
|
||||
u8 whoami; /* 3Ah: 2-byte registries, 3Bh: 1-byte registries */
|
||||
s16 (*read_data) (acpi_handle handle, int reg);
|
||||
int mdps_max_val;
|
||||
|
||||
struct input_dev *idev; /* input device */
|
||||
struct task_struct *kthread; /* kthread for input */
|
||||
struct mutex lock;
|
||||
@ -170,6 +180,11 @@ struct acpi_lis3lv02d {
|
||||
unsigned char is_on; /* whether the device is on or off */
|
||||
unsigned char usage; /* usage counter */
|
||||
struct axis_conversion ac; /* hw -> logical axis */
|
||||
|
||||
u32 irq; /* IRQ number */
|
||||
struct fasync_struct *async_queue; /* queue for the misc device */
|
||||
wait_queue_head_t misc_wait; /* Wait queue for the misc device */
|
||||
unsigned long misc_opened; /* bit0: whether the device is open */
|
||||
};
|
||||
|
||||
int lis3lv02d_init_device(struct acpi_lis3lv02d *dev);
|
||||
|
@ -1262,7 +1262,7 @@ static int __init vt1211_device_add(unsigned short address)
|
||||
res.name = pdev->name;
|
||||
err = acpi_check_resource_conflict(&res);
|
||||
if (err)
|
||||
goto EXIT;
|
||||
goto EXIT_DEV_PUT;
|
||||
|
||||
err = platform_device_add_resources(pdev, &res, 1);
|
||||
if (err) {
|
||||
|
@ -1548,7 +1548,7 @@ static int __init sensors_w83627ehf_init(void)
|
||||
|
||||
err = acpi_check_resource_conflict(&res);
|
||||
if (err)
|
||||
goto exit;
|
||||
goto exit_device_put;
|
||||
|
||||
err = platform_device_add_resources(pdev, &res, 1);
|
||||
if (err) {
|
||||
|
@ -328,7 +328,7 @@ static void dispatch_io(int rw, unsigned int num_regions,
|
||||
struct dpages old_pages = *dp;
|
||||
|
||||
if (sync)
|
||||
rw |= (1 << BIO_RW_SYNC);
|
||||
rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
|
||||
|
||||
/*
|
||||
* For multiple regions we need to be careful to rewind
|
||||
|
@ -344,7 +344,7 @@ static int run_io_job(struct kcopyd_job *job)
|
||||
{
|
||||
int r;
|
||||
struct dm_io_request io_req = {
|
||||
.bi_rw = job->rw | (1 << BIO_RW_SYNC),
|
||||
.bi_rw = job->rw | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG),
|
||||
.mem.type = DM_IO_PAGE_LIST,
|
||||
.mem.ptr.pl = job->pages,
|
||||
.mem.offset = job->offset,
|
||||
|
@ -474,7 +474,7 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
|
||||
* causes ENOTSUPP, we allocate a spare bio...
|
||||
*/
|
||||
struct bio *bio = bio_alloc(GFP_NOIO, 1);
|
||||
int rw = (1<<BIO_RW) | (1<<BIO_RW_SYNC);
|
||||
int rw = (1<<BIO_RW) | (1<<BIO_RW_SYNCIO) | (1<<BIO_RW_UNPLUG);
|
||||
|
||||
bio->bi_bdev = rdev->bdev;
|
||||
bio->bi_sector = sector;
|
||||
@ -531,7 +531,7 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size,
|
||||
struct completion event;
|
||||
int ret;
|
||||
|
||||
rw |= (1 << BIO_RW_SYNC);
|
||||
rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
|
||||
|
||||
bio->bi_bdev = bdev;
|
||||
bio->bi_sector = sector;
|
||||
|
@ -318,7 +318,6 @@ static int simple_std_setup(struct dvb_frontend *fe,
|
||||
u8 *config, u8 *cb)
|
||||
{
|
||||
struct tuner_simple_priv *priv = fe->tuner_priv;
|
||||
u8 tuneraddr;
|
||||
int rc;
|
||||
|
||||
/* tv norm specific stuff for multi-norm tuners */
|
||||
@ -387,6 +386,7 @@ static int simple_std_setup(struct dvb_frontend *fe,
|
||||
|
||||
case TUNER_PHILIPS_TUV1236D:
|
||||
{
|
||||
struct tuner_i2c_props i2c = priv->i2c_props;
|
||||
/* 0x40 -> ATSC antenna input 1 */
|
||||
/* 0x48 -> ATSC antenna input 2 */
|
||||
/* 0x00 -> NTSC antenna input 1 */
|
||||
@ -398,17 +398,15 @@ static int simple_std_setup(struct dvb_frontend *fe,
|
||||
buffer[1] = 0x04;
|
||||
}
|
||||
/* set to the correct mode (analog or digital) */
|
||||
tuneraddr = priv->i2c_props.addr;
|
||||
priv->i2c_props.addr = 0x0a;
|
||||
rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2);
|
||||
i2c.addr = 0x0a;
|
||||
rc = tuner_i2c_xfer_send(&i2c, &buffer[0], 2);
|
||||
if (2 != rc)
|
||||
tuner_warn("i2c i/o error: rc == %d "
|
||||
"(should be 2)\n", rc);
|
||||
rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2);
|
||||
rc = tuner_i2c_xfer_send(&i2c, &buffer[2], 2);
|
||||
if (2 != rc)
|
||||
tuner_warn("i2c i/o error: rc == %d "
|
||||
"(should be 2)\n", rc);
|
||||
priv->i2c_props.addr = tuneraddr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -364,16 +364,15 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
enum dmx_success success)
|
||||
{
|
||||
struct dmxdev_filter *dmxdevfilter = filter->priv;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (dmxdevfilter->buffer.error) {
|
||||
wake_up(&dmxdevfilter->buffer.queue);
|
||||
return 0;
|
||||
}
|
||||
spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
|
||||
spin_lock(&dmxdevfilter->dev->lock);
|
||||
if (dmxdevfilter->state != DMXDEV_STATE_GO) {
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
return 0;
|
||||
}
|
||||
del_timer(&dmxdevfilter->timer);
|
||||
@ -392,7 +391,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
}
|
||||
if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
|
||||
dmxdevfilter->state = DMXDEV_STATE_DONE;
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
wake_up(&dmxdevfilter->buffer.queue);
|
||||
return 0;
|
||||
}
|
||||
@ -404,12 +403,11 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
{
|
||||
struct dmxdev_filter *dmxdevfilter = feed->priv;
|
||||
struct dvb_ringbuffer *buffer;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
|
||||
spin_lock(&dmxdevfilter->dev->lock);
|
||||
if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -419,7 +417,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
else
|
||||
buffer = &dmxdevfilter->dev->dvr_buffer;
|
||||
if (buffer->error) {
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
wake_up(&buffer->queue);
|
||||
return 0;
|
||||
}
|
||||
@ -430,7 +428,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
|
||||
dvb_ringbuffer_flush(buffer);
|
||||
buffer->error = ret;
|
||||
}
|
||||
spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
|
||||
spin_unlock(&dmxdevfilter->dev->lock);
|
||||
wake_up(&buffer->queue);
|
||||
return 0;
|
||||
}
|
||||
|
@ -399,9 +399,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
|
||||
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
|
||||
size_t count)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
spin_lock(&demux->lock);
|
||||
|
||||
while (count--) {
|
||||
if (buf[0] == 0x47)
|
||||
@ -409,17 +407,16 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
|
||||
buf += 188;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
spin_unlock(&demux->lock);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
|
||||
|
||||
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
{
|
||||
unsigned long flags;
|
||||
int p = 0, i, j;
|
||||
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
spin_lock(&demux->lock);
|
||||
|
||||
if (demux->tsbufp) {
|
||||
i = demux->tsbufp;
|
||||
@ -452,18 +449,17 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
}
|
||||
|
||||
bailout:
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
spin_unlock(&demux->lock);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter);
|
||||
|
||||
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
{
|
||||
unsigned long flags;
|
||||
int p = 0, i, j;
|
||||
u8 tmppack[188];
|
||||
|
||||
spin_lock_irqsave(&demux->lock, flags);
|
||||
spin_lock(&demux->lock);
|
||||
|
||||
if (demux->tsbufp) {
|
||||
i = demux->tsbufp;
|
||||
@ -504,7 +500,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
|
||||
}
|
||||
|
||||
bailout:
|
||||
spin_unlock_irqrestore(&demux->lock, flags);
|
||||
spin_unlock(&demux->lock);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dvb_dmx_swfilter_204);
|
||||
|
@ -98,11 +98,16 @@
|
||||
* - blacklisted KWorld radio in hid-core.c and hid-ids.h
|
||||
* 2008-12-03 Mark Lord <mlord@pobox.com>
|
||||
* - add support for DealExtreme USB Radio
|
||||
* 2009-01-31 Bob Ross <pigiron@gmx.com>
|
||||
* - correction of stereo detection/setting
|
||||
* - correction of signal strength indicator scaling
|
||||
* 2009-01-31 Rick Bronson <rick@efn.org>
|
||||
* Tobias Lorenz <tobias.lorenz@gmx.net>
|
||||
* - add LED status output
|
||||
*
|
||||
* ToDo:
|
||||
* - add firmware download/update support
|
||||
* - RDS support: interrupt mode, instead of polling
|
||||
* - add LED status output (check if that's not already done in firmware)
|
||||
*/
|
||||
|
||||
|
||||
@ -881,6 +886,30 @@ static int si470x_rds_on(struct si470x_device *radio)
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* General Driver Functions - LED_REPORT
|
||||
**************************************************************************/
|
||||
|
||||
/*
|
||||
* si470x_set_led_state - sets the led state
|
||||
*/
|
||||
static int si470x_set_led_state(struct si470x_device *radio,
|
||||
unsigned char led_state)
|
||||
{
|
||||
unsigned char buf[LED_REPORT_SIZE];
|
||||
int retval;
|
||||
|
||||
buf[0] = LED_REPORT;
|
||||
buf[1] = LED_COMMAND;
|
||||
buf[2] = led_state;
|
||||
|
||||
retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
|
||||
|
||||
return (retval < 0) ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* RDS Driver Functions
|
||||
**************************************************************************/
|
||||
@ -1385,20 +1414,22 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
|
||||
};
|
||||
|
||||
/* stereo indicator == stereo (instead of mono) */
|
||||
if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 1)
|
||||
tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
|
||||
else
|
||||
if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0)
|
||||
tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
|
||||
else
|
||||
tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
|
||||
|
||||
/* mono/stereo selector */
|
||||
if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 1)
|
||||
tuner->audmode = V4L2_TUNER_MODE_MONO;
|
||||
else
|
||||
if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0)
|
||||
tuner->audmode = V4L2_TUNER_MODE_STEREO;
|
||||
else
|
||||
tuner->audmode = V4L2_TUNER_MODE_MONO;
|
||||
|
||||
/* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
|
||||
tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI)
|
||||
* 0x0101;
|
||||
/* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */
|
||||
tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
|
||||
/* the ideal factor is 0xffff/75 = 873,8 */
|
||||
tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
|
||||
|
||||
/* automatic frequency control: -1: freq to low, 1 freq to high */
|
||||
/* AFCRL does only indicate that freq. differs, not if too low/high */
|
||||
@ -1632,6 +1663,9 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
|
||||
/* set initial frequency */
|
||||
si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
|
||||
|
||||
/* set led to connect state */
|
||||
si470x_set_led_state(radio, BLINK_GREEN_LED);
|
||||
|
||||
/* rds buffer allocation */
|
||||
radio->buf_size = rds_buf * 3;
|
||||
radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
|
||||
@ -1715,6 +1749,9 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
|
||||
cancel_delayed_work_sync(&radio->work);
|
||||
usb_set_intfdata(intf, NULL);
|
||||
if (radio->users == 0) {
|
||||
/* set led to disconnect state */
|
||||
si470x_set_led_state(radio, BLINK_ORANGE_LED);
|
||||
|
||||
video_unregister_device(radio->videodev);
|
||||
kfree(radio->buffer);
|
||||
kfree(radio);
|
||||
|
@ -422,6 +422,7 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
|
||||
if (urb == NULL)
|
||||
break;
|
||||
|
||||
BUG_ON(!gspca_dev->dev);
|
||||
gspca_dev->urb[i] = NULL;
|
||||
if (!gspca_dev->present)
|
||||
usb_kill_urb(urb);
|
||||
@ -1950,8 +1951,12 @@ void gspca_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
|
||||
|
||||
mutex_lock(&gspca_dev->usb_lock);
|
||||
gspca_dev->present = 0;
|
||||
mutex_unlock(&gspca_dev->usb_lock);
|
||||
|
||||
destroy_urbs(gspca_dev);
|
||||
gspca_dev->dev = NULL;
|
||||
usb_set_intfdata(intf, NULL);
|
||||
|
||||
/* release the device */
|
||||
|
@ -393,7 +393,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo
|
||||
return 0;
|
||||
}
|
||||
|
||||
v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
|
||||
v4l2_subdev_call(itv->sd_video, video, g_fmt, fmt);
|
||||
vbifmt->service_set = ivtv_get_service_set(vbifmt);
|
||||
return 0;
|
||||
}
|
||||
@ -1748,6 +1748,18 @@ static long ivtv_default(struct file *file, void *fh, int cmd, void *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
case IVTV_IOC_DMA_FRAME:
|
||||
case VIDEO_GET_PTS:
|
||||
case VIDEO_GET_FRAME_COUNT:
|
||||
case VIDEO_GET_EVENT:
|
||||
case VIDEO_PLAY:
|
||||
case VIDEO_STOP:
|
||||
case VIDEO_FREEZE:
|
||||
case VIDEO_CONTINUE:
|
||||
case VIDEO_COMMAND:
|
||||
case VIDEO_TRY_COMMAND:
|
||||
return ivtv_decoder_ioctls(file, cmd, (void *)arg);
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1790,18 +1802,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
|
||||
ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
|
||||
return 0;
|
||||
|
||||
case IVTV_IOC_DMA_FRAME:
|
||||
case VIDEO_GET_PTS:
|
||||
case VIDEO_GET_FRAME_COUNT:
|
||||
case VIDEO_GET_EVENT:
|
||||
case VIDEO_PLAY:
|
||||
case VIDEO_STOP:
|
||||
case VIDEO_FREEZE:
|
||||
case VIDEO_CONTINUE:
|
||||
case VIDEO_COMMAND:
|
||||
case VIDEO_TRY_COMMAND:
|
||||
return ivtv_decoder_ioctls(filp, cmd, (void *)arg);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ static int __init egpio_probe(struct platform_device *pdev)
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
goto fail;
|
||||
ei->base_addr = ioremap_nocache(res->start, res->end - res->start);
|
||||
ei->base_addr = ioremap_nocache(res->start, resource_size(res));
|
||||
if (!ei->base_addr)
|
||||
goto fail;
|
||||
pr_debug("EGPIO phys=%08x virt=%p\n", (u32)res->start, ei->base_addr);
|
||||
@ -307,7 +307,7 @@ static int __init egpio_probe(struct platform_device *pdev)
|
||||
|
||||
ei->nchips = pdata->num_chips;
|
||||
ei->chip = kzalloc(sizeof(struct egpio_chip) * ei->nchips, GFP_KERNEL);
|
||||
if (!ei) {
|
||||
if (!ei->chip) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
@ -678,6 +678,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
|
||||
|
||||
static struct i2c_device_id pcf50633_id_table[] = {
|
||||
{"pcf50633", 0x73},
|
||||
{/* end of list */}
|
||||
};
|
||||
|
||||
static struct i2c_driver pcf50633_driver = {
|
||||
|
@ -1050,7 +1050,7 @@ static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
|
||||
return gpiochip_add(gchip);
|
||||
}
|
||||
|
||||
static int sm501_register_gpio(struct sm501_devdata *sm)
|
||||
static int __devinit sm501_register_gpio(struct sm501_devdata *sm)
|
||||
{
|
||||
struct sm501_gpio *gpio = &sm->gpio;
|
||||
resource_size_t iobase = sm->io_res->start + SM501_GPIO;
|
||||
@ -1321,7 +1321,7 @@ static unsigned int sm501_mem_local[] = {
|
||||
* Common init code for an SM501
|
||||
*/
|
||||
|
||||
static int sm501_init_dev(struct sm501_devdata *sm)
|
||||
static int __devinit sm501_init_dev(struct sm501_devdata *sm)
|
||||
{
|
||||
struct sm501_initdata *idata;
|
||||
struct sm501_platdata *pdata;
|
||||
@ -1397,7 +1397,7 @@ static int sm501_init_dev(struct sm501_devdata *sm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sm501_plat_probe(struct platform_device *dev)
|
||||
static int __devinit sm501_plat_probe(struct platform_device *dev)
|
||||
{
|
||||
struct sm501_devdata *sm;
|
||||
int ret;
|
||||
@ -1586,8 +1586,8 @@ static struct sm501_platdata sm501_pci_platdata = {
|
||||
.gpio_base = -1,
|
||||
};
|
||||
|
||||
static int sm501_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *id)
|
||||
static int __devinit sm501_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
struct sm501_devdata *sm;
|
||||
int err;
|
||||
@ -1693,7 +1693,7 @@ static void sm501_dev_remove(struct sm501_devdata *sm)
|
||||
sm501_gpio_remove(sm);
|
||||
}
|
||||
|
||||
static void sm501_pci_remove(struct pci_dev *dev)
|
||||
static void __devexit sm501_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
struct sm501_devdata *sm = pci_get_drvdata(dev);
|
||||
|
||||
@ -1727,16 +1727,16 @@ static struct pci_device_id sm501_pci_tbl[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, sm501_pci_tbl);
|
||||
|
||||
static struct pci_driver sm501_pci_drv = {
|
||||
static struct pci_driver sm501_pci_driver = {
|
||||
.name = "sm501",
|
||||
.id_table = sm501_pci_tbl,
|
||||
.probe = sm501_pci_probe,
|
||||
.remove = sm501_pci_remove,
|
||||
.remove = __devexit_p(sm501_pci_remove),
|
||||
};
|
||||
|
||||
MODULE_ALIAS("platform:sm501");
|
||||
|
||||
static struct platform_driver sm501_plat_drv = {
|
||||
static struct platform_driver sm501_plat_driver = {
|
||||
.driver = {
|
||||
.name = "sm501",
|
||||
.owner = THIS_MODULE,
|
||||
@ -1749,14 +1749,14 @@ static struct platform_driver sm501_plat_drv = {
|
||||
|
||||
static int __init sm501_base_init(void)
|
||||
{
|
||||
platform_driver_register(&sm501_plat_drv);
|
||||
return pci_register_driver(&sm501_pci_drv);
|
||||
platform_driver_register(&sm501_plat_driver);
|
||||
return pci_register_driver(&sm501_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit sm501_base_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&sm501_plat_drv);
|
||||
pci_unregister_driver(&sm501_pci_drv);
|
||||
platform_driver_unregister(&sm501_plat_driver);
|
||||
pci_unregister_driver(&sm501_pci_driver);
|
||||
}
|
||||
|
||||
module_init(sm501_base_init);
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c/twl4030.h>
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
|
||||
#include <mach/cpu.h>
|
||||
#endif
|
||||
|
||||
|
@ -1111,7 +1111,7 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
|
||||
do {
|
||||
schedule_timeout_interruptible(1);
|
||||
reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
|
||||
} while (tries-- && (reg & WM8350_AUXADC_POLL));
|
||||
} while (--tries && (reg & WM8350_AUXADC_POLL));
|
||||
|
||||
if (!tries)
|
||||
dev_err(wm8350->dev, "adc chn %d read timeout\n", channel);
|
||||
@ -1297,14 +1297,29 @@ static void wm8350_client_dev_register(struct wm8350 *wm8350,
|
||||
int wm8350_device_init(struct wm8350 *wm8350, int irq,
|
||||
struct wm8350_platform_data *pdata)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int ret;
|
||||
u16 id1, id2, mask_rev;
|
||||
u16 cust_id, mode, chip_rev;
|
||||
|
||||
/* get WM8350 revision and config mode */
|
||||
wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
|
||||
wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
|
||||
wm8350->read_dev(wm8350, WM8350_REVISION, sizeof(mask_rev), &mask_rev);
|
||||
ret = wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
|
||||
if (ret != 0) {
|
||||
dev_err(wm8350->dev, "Failed to read ID: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
|
||||
if (ret != 0) {
|
||||
dev_err(wm8350->dev, "Failed to read ID: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = wm8350->read_dev(wm8350, WM8350_REVISION, sizeof(mask_rev),
|
||||
&mask_rev);
|
||||
if (ret != 0) {
|
||||
dev_err(wm8350->dev, "Failed to read revision: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
id1 = be16_to_cpu(id1);
|
||||
id2 = be16_to_cpu(id2);
|
||||
@ -1404,14 +1419,12 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pdata && pdata->init) {
|
||||
ret = pdata->init(wm8350);
|
||||
if (ret != 0) {
|
||||
dev_err(wm8350->dev, "Platform init() failed: %d\n",
|
||||
ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF);
|
||||
wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK, 0xFFFF);
|
||||
wm8350_reg_write(wm8350, WM8350_INT_STATUS_2_MASK, 0xFFFF);
|
||||
wm8350_reg_write(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, 0xFFFF);
|
||||
wm8350_reg_write(wm8350, WM8350_GPIO_INT_STATUS_MASK, 0xFFFF);
|
||||
wm8350_reg_write(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK, 0xFFFF);
|
||||
|
||||
mutex_init(&wm8350->auxadc_mutex);
|
||||
mutex_init(&wm8350->irq_mutex);
|
||||
@ -1430,6 +1443,15 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
|
||||
}
|
||||
wm8350->chip_irq = irq;
|
||||
|
||||
if (pdata && pdata->init) {
|
||||
ret = pdata->init(wm8350);
|
||||
if (ret != 0) {
|
||||
dev_err(wm8350->dev, "Platform init() failed: %d\n",
|
||||
ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0x0);
|
||||
|
||||
wm8350_client_dev_register(wm8350, "wm8350-codec",
|
||||
|
@ -3188,7 +3188,7 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = {
|
||||
{ 0x7CFF, 0x0C00, 0x7FFF }, /* R1 - ID */
|
||||
{ 0x0000, 0x0000, 0x0000 }, /* R2 */
|
||||
{ 0xBE3B, 0xBE3B, 0x8000 }, /* R3 - System Control 1 */
|
||||
{ 0xFCF7, 0xFCF7, 0xF800 }, /* R4 - System Control 2 */
|
||||
{ 0xFEF7, 0xFEF7, 0xF800 }, /* R4 - System Control 2 */
|
||||
{ 0x80FF, 0x80FF, 0x8000 }, /* R5 - System Hibernate */
|
||||
{ 0xFB0E, 0xFB0E, 0x0000 }, /* R6 - Interface Control */
|
||||
{ 0x0000, 0x0000, 0x0000 }, /* R7 */
|
||||
|
@ -584,7 +584,7 @@ static int mmc_blk_probe(struct mmc_card *card)
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
string_get_size(get_capacity(md->disk) << 9, STRING_UNITS_2,
|
||||
string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
|
||||
cap_str, sizeof(cap_str));
|
||||
printk(KERN_INFO "%s: %s %s %s %s\n",
|
||||
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
|
||||
|
@ -494,7 +494,7 @@ static int mmc_test_basic_read(struct mmc_test_card *test)
|
||||
|
||||
sg_init_one(&sg, test->buffer, 512);
|
||||
|
||||
ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
|
||||
ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -1548,9 +1548,10 @@ static bool filter(struct dma_chan *chan, void *slave)
|
||||
{
|
||||
struct dw_dma_slave *dws = slave;
|
||||
|
||||
if (dws->dma_dev == chan->device->dev)
|
||||
if (dws->dma_dev == chan->device->dev) {
|
||||
chan->private = dws;
|
||||
return true;
|
||||
else
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
@ -55,6 +55,7 @@
|
||||
#define VS30 (1 << 25)
|
||||
#define SDVS18 (0x5 << 9)
|
||||
#define SDVS30 (0x6 << 9)
|
||||
#define SDVS33 (0x7 << 9)
|
||||
#define SDVSCLR 0xFFFFF1FF
|
||||
#define SDVSDET 0x00000400
|
||||
#define AUTOIDLE 0x1
|
||||
@ -375,6 +376,32 @@ static void mmc_omap_report_irq(struct mmc_omap_host *host, u32 status)
|
||||
}
|
||||
#endif /* CONFIG_MMC_DEBUG */
|
||||
|
||||
/*
|
||||
* MMC controller internal state machines reset
|
||||
*
|
||||
* Used to reset command or data internal state machines, using respectively
|
||||
* SRC or SRD bit of SYSCTL register
|
||||
* Can be called from interrupt context
|
||||
*/
|
||||
static inline void mmc_omap_reset_controller_fsm(struct mmc_omap_host *host,
|
||||
unsigned long bit)
|
||||
{
|
||||
unsigned long i = 0;
|
||||
unsigned long limit = (loops_per_jiffy *
|
||||
msecs_to_jiffies(MMC_TIMEOUT_MS));
|
||||
|
||||
OMAP_HSMMC_WRITE(host->base, SYSCTL,
|
||||
OMAP_HSMMC_READ(host->base, SYSCTL) | bit);
|
||||
|
||||
while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) &&
|
||||
(i++ < limit))
|
||||
cpu_relax();
|
||||
|
||||
if (OMAP_HSMMC_READ(host->base, SYSCTL) & bit)
|
||||
dev_err(mmc_dev(host->mmc),
|
||||
"Timeout waiting on controller reset in %s\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
/*
|
||||
* MMC controller IRQ handler
|
||||
@ -403,21 +430,17 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
|
||||
(status & CMD_CRC)) {
|
||||
if (host->cmd) {
|
||||
if (status & CMD_TIMEOUT) {
|
||||
OMAP_HSMMC_WRITE(host->base, SYSCTL,
|
||||
OMAP_HSMMC_READ(host->base,
|
||||
SYSCTL) | SRC);
|
||||
while (OMAP_HSMMC_READ(host->base,
|
||||
SYSCTL) & SRC)
|
||||
;
|
||||
|
||||
mmc_omap_reset_controller_fsm(host, SRC);
|
||||
host->cmd->error = -ETIMEDOUT;
|
||||
} else {
|
||||
host->cmd->error = -EILSEQ;
|
||||
}
|
||||
end_cmd = 1;
|
||||
}
|
||||
if (host->data)
|
||||
if (host->data) {
|
||||
mmc_dma_cleanup(host);
|
||||
mmc_omap_reset_controller_fsm(host, SRD);
|
||||
}
|
||||
}
|
||||
if ((status & DATA_TIMEOUT) ||
|
||||
(status & DATA_CRC)) {
|
||||
@ -426,12 +449,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
|
||||
mmc_dma_cleanup(host);
|
||||
else
|
||||
host->data->error = -EILSEQ;
|
||||
OMAP_HSMMC_WRITE(host->base, SYSCTL,
|
||||
OMAP_HSMMC_READ(host->base,
|
||||
SYSCTL) | SRD);
|
||||
while (OMAP_HSMMC_READ(host->base,
|
||||
SYSCTL) & SRD)
|
||||
;
|
||||
mmc_omap_reset_controller_fsm(host, SRD);
|
||||
end_trans = 1;
|
||||
}
|
||||
}
|
||||
@ -456,13 +474,20 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch MMC operating voltage
|
||||
* Switch MMC interface voltage ... only relevant for MMC1.
|
||||
*
|
||||
* MMC2 and MMC3 use fixed 1.8V levels, and maybe a transceiver.
|
||||
* The MMC2 transceiver controls are used instead of DAT4..DAT7.
|
||||
* Some chips, like eMMC ones, use internal transceivers.
|
||||
*/
|
||||
static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
|
||||
{
|
||||
u32 reg_val = 0;
|
||||
int ret;
|
||||
|
||||
if (host->id != OMAP_MMC1_DEVID)
|
||||
return 0;
|
||||
|
||||
/* Disable the clocks */
|
||||
clk_disable(host->fclk);
|
||||
clk_disable(host->iclk);
|
||||
@ -485,19 +510,26 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
|
||||
OMAP_HSMMC_WRITE(host->base, HCTL,
|
||||
OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR);
|
||||
reg_val = OMAP_HSMMC_READ(host->base, HCTL);
|
||||
|
||||
/*
|
||||
* If a MMC dual voltage card is detected, the set_ios fn calls
|
||||
* this fn with VDD bit set for 1.8V. Upon card removal from the
|
||||
* slot, omap_mmc_set_ios sets the VDD back to 3V on MMC_POWER_OFF.
|
||||
*
|
||||
* Only MMC1 supports 3.0V. MMC2 will not function if SDVS30 is
|
||||
* set in HCTL.
|
||||
* Cope with a bit of slop in the range ... per data sheets:
|
||||
* - "1.8V" for vdds_mmc1/vdds_mmc1a can be up to 2.45V max,
|
||||
* but recommended values are 1.71V to 1.89V
|
||||
* - "3.0V" for vdds_mmc1/vdds_mmc1a can be up to 3.5V max,
|
||||
* but recommended values are 2.7V to 3.3V
|
||||
*
|
||||
* Board setup code shouldn't permit anything very out-of-range.
|
||||
* TWL4030-family VMMC1 and VSIM regulators are fine (avoiding the
|
||||
* middle range) but VSIM can't power DAT4..DAT7 at more than 3V.
|
||||
*/
|
||||
if (host->id == OMAP_MMC1_DEVID && (((1 << vdd) == MMC_VDD_32_33) ||
|
||||
((1 << vdd) == MMC_VDD_33_34)))
|
||||
reg_val |= SDVS30;
|
||||
if ((1 << vdd) == MMC_VDD_165_195)
|
||||
if ((1 << vdd) <= MMC_VDD_23_24)
|
||||
reg_val |= SDVS18;
|
||||
else
|
||||
reg_val |= SDVS30;
|
||||
|
||||
OMAP_HSMMC_WRITE(host->base, HCTL, reg_val);
|
||||
|
||||
@ -517,16 +549,15 @@ static void mmc_omap_detect(struct work_struct *work)
|
||||
{
|
||||
struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
|
||||
mmc_carddetect_work);
|
||||
struct omap_mmc_slot_data *slot = &mmc_slot(host);
|
||||
|
||||
host->carddetect = slot->card_detect(slot->card_detect_irq);
|
||||
|
||||
sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
|
||||
if (host->carddetect) {
|
||||
mmc_detect_change(host->mmc, (HZ * 200) / 1000);
|
||||
} else {
|
||||
OMAP_HSMMC_WRITE(host->base, SYSCTL,
|
||||
OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
|
||||
while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
|
||||
;
|
||||
|
||||
mmc_omap_reset_controller_fsm(host, SRD);
|
||||
mmc_detect_change(host->mmc, (HZ * 50) / 1000);
|
||||
}
|
||||
}
|
||||
@ -538,7 +569,6 @@ static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id;
|
||||
|
||||
host->carddetect = mmc_slot(host).card_detect(irq);
|
||||
schedule_work(&host->mmc_carddetect_work);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@ -757,10 +787,14 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
case MMC_POWER_OFF:
|
||||
mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
|
||||
/*
|
||||
* Reset bus voltage to 3V if it got set to 1.8V earlier.
|
||||
* Reset interface voltage to 3V if it's 1.8V now;
|
||||
* only relevant on MMC-1, the others always use 1.8V.
|
||||
*
|
||||
* REVISIT: If we are able to detect cards after unplugging
|
||||
* a 1.8V card, this code should not be needed.
|
||||
*/
|
||||
if (host->id != OMAP_MMC1_DEVID)
|
||||
break;
|
||||
if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
|
||||
int vdd = fls(host->mmc->ocr_avail) - 1;
|
||||
if (omap_mmc_switch_opcond(host, vdd) != 0)
|
||||
@ -784,7 +818,9 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
}
|
||||
|
||||
if (host->id == OMAP_MMC1_DEVID) {
|
||||
/* Only MMC1 can operate at 3V/1.8V */
|
||||
/* Only MMC1 can interface at 3V without some flavor
|
||||
* of external transceiver; but they all handle 1.8V.
|
||||
*/
|
||||
if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) &&
|
||||
(ios->vdd == DUAL_VOLT_OCR_BIT)) {
|
||||
/*
|
||||
@ -1137,7 +1173,9 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
" level suspend\n");
|
||||
}
|
||||
|
||||
if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
|
||||
if (host->id == OMAP_MMC1_DEVID
|
||||
&& !(OMAP_HSMMC_READ(host->base, HCTL)
|
||||
& SDVSDET)) {
|
||||
OMAP_HSMMC_WRITE(host->base, HCTL,
|
||||
OMAP_HSMMC_READ(host->base, HCTL)
|
||||
& SDVSCLR);
|
||||
|
@ -329,7 +329,7 @@ static void do_pio_write(struct s3cmci_host *host)
|
||||
|
||||
to_ptr = host->base + host->sdidata;
|
||||
|
||||
while ((fifo = fifo_free(host))) {
|
||||
while ((fifo = fifo_free(host)) > 3) {
|
||||
if (!host->pio_bytes) {
|
||||
res = get_data_buffer(host, &host->pio_bytes,
|
||||
&host->pio_ptr);
|
||||
|
@ -144,8 +144,7 @@ static int jmicron_probe(struct sdhci_pci_chip *chip)
|
||||
SDHCI_QUIRK_32BIT_DMA_SIZE |
|
||||
SDHCI_QUIRK_32BIT_ADMA_SIZE |
|
||||
SDHCI_QUIRK_RESET_AFTER_REQUEST |
|
||||
SDHCI_QUIRK_BROKEN_SMALL_PIO |
|
||||
SDHCI_QUIRK_FORCE_HIGHSPEED;
|
||||
SDHCI_QUIRK_BROKEN_SMALL_PIO;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1636,8 +1636,7 @@ int sdhci_add_host(struct sdhci_host *host)
|
||||
mmc->f_max = host->max_clk;
|
||||
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
|
||||
|
||||
if ((caps & SDHCI_CAN_DO_HISPD) ||
|
||||
(host->quirks & SDHCI_QUIRK_FORCE_HIGHSPEED))
|
||||
if (caps & SDHCI_CAN_DO_HISPD)
|
||||
mmc->caps |= MMC_CAP_SD_HIGHSPEED;
|
||||
|
||||
mmc->ocr_avail = 0;
|
||||
@ -1723,7 +1722,9 @@ int sdhci_add_host(struct sdhci_host *host)
|
||||
#endif
|
||||
|
||||
#ifdef SDHCI_USE_LEDS_CLASS
|
||||
host->led.name = mmc_hostname(mmc);
|
||||
snprintf(host->led_name, sizeof(host->led_name),
|
||||
"%s::", mmc_hostname(mmc));
|
||||
host->led.name = host->led_name;
|
||||
host->led.brightness = LED_OFF;
|
||||
host->led.default_trigger = mmc_hostname(mmc);
|
||||
host->led.brightness_set = sdhci_led_control;
|
||||
|
@ -208,8 +208,6 @@ struct sdhci_host {
|
||||
#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12)
|
||||
/* Controller has an issue with buffer bits for small transfers */
|
||||
#define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13)
|
||||
/* Controller supports high speed but doesn't have the caps bit set */
|
||||
#define SDHCI_QUIRK_FORCE_HIGHSPEED (1<<14)
|
||||
|
||||
int irq; /* Device IRQ */
|
||||
void __iomem * ioaddr; /* Mapped address */
|
||||
@ -222,6 +220,7 @@ struct sdhci_host {
|
||||
|
||||
#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
|
||||
struct led_classdev led; /* LED control */
|
||||
char led_name[32];
|
||||
#endif
|
||||
|
||||
spinlock_t lock; /* Mutex */
|
||||
|
@ -61,6 +61,8 @@
|
||||
/* global iommu list, set NULL for ignored DMAR units */
|
||||
static struct intel_iommu **g_iommus;
|
||||
|
||||
static int rwbf_quirk;
|
||||
|
||||
/*
|
||||
* 0: Present
|
||||
* 1-11: Reserved
|
||||
@ -785,7 +787,7 @@ static void iommu_flush_write_buffer(struct intel_iommu *iommu)
|
||||
u32 val;
|
||||
unsigned long flag;
|
||||
|
||||
if (!cap_rwbf(iommu->cap))
|
||||
if (!rwbf_quirk && !cap_rwbf(iommu->cap))
|
||||
return;
|
||||
val = iommu->gcmd | DMA_GCMD_WBF;
|
||||
|
||||
@ -3137,3 +3139,15 @@ static struct iommu_ops intel_iommu_ops = {
|
||||
.unmap = intel_iommu_unmap_range,
|
||||
.iova_to_phys = intel_iommu_iova_to_phys,
|
||||
};
|
||||
|
||||
static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
|
||||
{
|
||||
/*
|
||||
* Mobile 4 Series Chipset neglects to set RWBF capability,
|
||||
* but needs it:
|
||||
*/
|
||||
printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
|
||||
rwbf_quirk = 1;
|
||||
}
|
||||
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
|
||||
|
@ -103,14 +103,12 @@ static void msix_set_enable(struct pci_dev *dev, int enable)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Essentially, this is ((1 << (1 << x)) - 1), but without the
|
||||
* undefinedness of a << 32.
|
||||
*/
|
||||
static inline __attribute_const__ u32 msi_mask(unsigned x)
|
||||
{
|
||||
static const u32 mask[] = { 1, 2, 4, 0xf, 0xff, 0xffff, 0xffffffff };
|
||||
return mask[x];
|
||||
/* Don't shift by >= width of type */
|
||||
if (x >= 5)
|
||||
return 0xffffffff;
|
||||
return (1 << (1 << x)) - 1;
|
||||
}
|
||||
|
||||
static void msix_flush_writes(struct irq_desc *desc)
|
||||
|
@ -1540,16 +1540,21 @@ void pci_release_region(struct pci_dev *pdev, int bar)
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_request_region - Reserved PCI I/O and memory resource
|
||||
* __pci_request_region - Reserved PCI I/O and memory resource
|
||||
* @pdev: PCI device whose resources are to be reserved
|
||||
* @bar: BAR to be reserved
|
||||
* @res_name: Name to be associated with resource.
|
||||
* @exclusive: whether the region access is exclusive or not
|
||||
*
|
||||
* Mark the PCI region associated with PCI device @pdev BR @bar as
|
||||
* being reserved by owner @res_name. Do not access any
|
||||
* address inside the PCI regions unless this call returns
|
||||
* successfully.
|
||||
*
|
||||
* If @exclusive is set, then the region is marked so that userspace
|
||||
* is explicitly not allowed to map the resource via /dev/mem or
|
||||
* sysfs MMIO access.
|
||||
*
|
||||
* Returns 0 on success, or %EBUSY on error. A warning
|
||||
* message is also printed on failure.
|
||||
*/
|
||||
@ -1588,12 +1593,12 @@ err_out:
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_request_region - Reserved PCI I/O and memory resource
|
||||
* pci_request_region - Reserve PCI I/O and memory resource
|
||||
* @pdev: PCI device whose resources are to be reserved
|
||||
* @bar: BAR to be reserved
|
||||
* @res_name: Name to be associated with resource.
|
||||
* @res_name: Name to be associated with resource
|
||||
*
|
||||
* Mark the PCI region associated with PCI device @pdev BR @bar as
|
||||
* Mark the PCI region associated with PCI device @pdev BAR @bar as
|
||||
* being reserved by owner @res_name. Do not access any
|
||||
* address inside the PCI regions unless this call returns
|
||||
* successfully.
|
||||
|
@ -16,21 +16,21 @@ extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Firmware PM callbacks
|
||||
* struct pci_platform_pm_ops - Firmware PM callbacks
|
||||
*
|
||||
* @is_manageable - returns 'true' if given device is power manageable by the
|
||||
* platform firmware
|
||||
* @is_manageable: returns 'true' if given device is power manageable by the
|
||||
* platform firmware
|
||||
*
|
||||
* @set_state - invokes the platform firmware to set the device's power state
|
||||
* @set_state: invokes the platform firmware to set the device's power state
|
||||
*
|
||||
* @choose_state - returns PCI power state of given device preferred by the
|
||||
* platform; to be used during system-wide transitions from a
|
||||
* sleeping state to the working state and vice versa
|
||||
* @choose_state: returns PCI power state of given device preferred by the
|
||||
* platform; to be used during system-wide transitions from a
|
||||
* sleeping state to the working state and vice versa
|
||||
*
|
||||
* @can_wakeup - returns 'true' if given device is capable of waking up the
|
||||
* system from a sleeping state
|
||||
* @can_wakeup: returns 'true' if given device is capable of waking up the
|
||||
* system from a sleeping state
|
||||
*
|
||||
* @sleep_wake - enables/disables the system wake up capability of given device
|
||||
* @sleep_wake: enables/disables the system wake up capability of given device
|
||||
*
|
||||
* If given platform is generally capable of power managing PCI devices, all of
|
||||
* these callbacks are mandatory.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user