Compare commits
147 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e34454757f | |||
| 5f96452125 | |||
| 9fc79ab9a3 | |||
| 24016c735e | |||
| 5a9b5af39e | |||
| 52f8cf35ef | |||
| d6af238175 | |||
| 0702b646e5 | |||
| 7b0e385048 | |||
| cbe8fe4ae7 | |||
| fb1c95cd6b | |||
| bc7bc5df2d | |||
| e8c4851a2a | |||
| 7c3dbe6360 | |||
| 18020173f9 | |||
| a6d2078da9 | |||
| fc66cf4790 | |||
| 6f771da5da | |||
| 1350e5c494 | |||
| fda28853bc | |||
| 35fe207a08 | |||
| 4be149f9b6 | |||
| 082240d791 | |||
| 5c435c37e2 | |||
| 0857bb0606 | |||
| 43fce3f341 | |||
| 74c646d9ca | |||
| d4845ceede | |||
| b21c6d2897 | |||
| 14be1689c9 | |||
| d683876908 | |||
| 2a3403fd95 | |||
| 6c6737beae | |||
| edc9c87244 | |||
| 926e66275d | |||
| 9feb2c00e5 | |||
| 68890fb0ba | |||
| d11a29e323 | |||
| 7b457a610d | |||
| cf3c4fa34d | |||
| 3f22ebd2f4 | |||
| 94835d2bc7 | |||
| f2fcdb15eb | |||
| 55e3b46ded | |||
| 3fe90c4dc5 | |||
| 39cd13c96c | |||
| 22f45438e5 | |||
| b76d2b612c | |||
| 10b9c3cd88 | |||
| df76bd846a | |||
| 37a8bca218 | |||
| ed960ac61e | |||
| 6bc1b5deb4 | |||
| 3b3e59f78d | |||
| 3eb67e6061 | |||
| fce2b77a3f | |||
| df5b6025d1 | |||
| 33d06566b5 | |||
| 43a00bbcf5 | |||
| d92281c908 | |||
| 3ee793df8f | |||
| 8068bd7e04 | |||
| e231d89b16 | |||
| 135c58d2f1 | |||
| 07280df84a | |||
| 6858778b9c | |||
| 187ab6618c | |||
| 91cd4d9b40 | |||
| bab57a80d2 | |||
| d4a0936d21 | |||
| ee21b9af3d | |||
| 037e58f985 | |||
| 14e4f36b87 | |||
| 717ff47217 | |||
| d7715a3e33 | |||
| 68ad5ef008 | |||
| 98bf3a0cf2 | |||
| 1b5479d3a6 | |||
| 517f1a189b | |||
| 1d2c2b49a9 | |||
| f9469a013b | |||
| d1ea508946 | |||
| 1317b1720e | |||
| 89051add55 | |||
| c780bee65d | |||
| fe27c364b5 | |||
| 06016ed06d | |||
| 538c7aac35 | |||
| d930ec7bcd | |||
| 32626208c6 | |||
| 69186bb21b | |||
| f8629efabc | |||
| c3d8209374 | |||
| 45b143c705 | |||
| e76f9b67d8 | |||
| 763cf396b7 | |||
| eddabbbaa0 | |||
| a30c361654 | |||
| dd3fa60c0e | |||
| 97ecdadc28 | |||
| 8d7bff2d72 | |||
| bb70446264 | |||
| 5d8a29ae73 | |||
| b6816b7061 | |||
| 8796fc28c0 | |||
| 716fd1dac0 | |||
| cbb76e6c20 | |||
| 4d25e3d037 | |||
| ab62416897 | |||
| 73dffc3a1e | |||
| 67df6428d5 | |||
| 178e0475b5 | |||
| 393c20529e | |||
| 4a78cb55e5 | |||
| e1b427acc9 | |||
| ce6d13d7f4 | |||
| 84a31107de | |||
| fdc0359dc4 | |||
| 96c7a7e7ff | |||
| 81c10c80c5 | |||
| 86046cf121 | |||
| 4e3278e0e8 | |||
| 7549374c39 | |||
| f27eae2ce9 | |||
| 0e8cb3e1de | |||
| 15bd8021d8 | |||
| db257505aa | |||
| 7b2b76da5c | |||
| bf2d225b46 | |||
| fb2d617e4b | |||
| 8bc20526fc | |||
| 46d2a92135 | |||
| 35f0b41fd7 | |||
| 0b7f8d0aba | |||
| f438349efb | |||
| a9620fdcb8 | |||
| e6c7f8a29d | |||
| 7127941c0e | |||
| 760053b650 | |||
| 39f8c8a3ef | |||
| ce2a2dc252 | |||
| c8289b1f3f | |||
| ed421a6482 | |||
| 813352bc33 | |||
| dcd2d49aa7 | |||
| efc337c45a | |||
| cbb1dbb632 |
@@ -1242,7 +1242,7 @@ monitoring is enabled, and vice-versa.
|
||||
To add ARP targets:
|
||||
# echo +192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target
|
||||
# echo +192.168.0.101 > /sys/class/net/bond0/bonding/arp_ip_target
|
||||
NOTE: up to 10 target addresses may be specified.
|
||||
NOTE: up to 16 target addresses may be specified.
|
||||
|
||||
To remove an ARP target:
|
||||
# echo -192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 29
|
||||
EXTRAVERSION =
|
||||
EXTRAVERSION = .2
|
||||
NAME = Temporary Tasmanian Devil
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
||||
@@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t;
|
||||
#define R_ARM_ABS32 2
|
||||
#define R_ARM_CALL 28
|
||||
#define R_ARM_JUMP24 29
|
||||
#define R_ARM_V4BX 40
|
||||
|
||||
/*
|
||||
* These are used to set parameters in the core dumps.
|
||||
|
||||
@@ -132,6 +132,15 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
|
||||
*(u32 *)loc |= offset & 0x00ffffff;
|
||||
break;
|
||||
|
||||
case R_ARM_V4BX:
|
||||
/* Preserve Rm and the condition code. Alter
|
||||
* other bits to re-code instruction as
|
||||
* MOV PC,Rm.
|
||||
*/
|
||||
*(u32 *)loc &= 0xf000000f;
|
||||
*(u32 *)loc |= 0x01a0f000;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "%s: unknown relocation: %u\n",
|
||||
module->name, ELF32_R_TYPE(rel->r_info));
|
||||
|
||||
@@ -1026,8 +1026,10 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
|
||||
which_atu = 0;
|
||||
}
|
||||
|
||||
if (!which_atu)
|
||||
if (!which_atu) {
|
||||
kfree(res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(which_atu) {
|
||||
case IOP13XX_INIT_ATU_ATUX:
|
||||
@@ -1074,6 +1076,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
|
||||
sys->map_irq = iop13xx_pcie_map_irq;
|
||||
break;
|
||||
default:
|
||||
kfree(res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -397,6 +397,7 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
|
||||
break;
|
||||
default:
|
||||
pr_err("MMC%d configuration not supported!\n", c->mmc);
|
||||
kfree(mmc);
|
||||
continue;
|
||||
}
|
||||
hsmmc_data[c->mmc - 1] = mmc;
|
||||
|
||||
+1
-1
@@ -694,7 +694,7 @@ static void __init sanity_check_meminfo(void)
|
||||
* the vmalloc area.
|
||||
*/
|
||||
if (__va(bank->start) >= VMALLOC_MIN ||
|
||||
__va(bank->start) < PAGE_OFFSET) {
|
||||
__va(bank->start) < (void *)PAGE_OFFSET) {
|
||||
printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx "
|
||||
"(vmalloc region overlap).\n",
|
||||
bank->start, bank->start + bank->size - 1);
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
config HAVE_KVM
|
||||
bool
|
||||
|
||||
config HAVE_KVM_IRQCHIP
|
||||
bool
|
||||
default y
|
||||
|
||||
menuconfig VIRTUALIZATION
|
||||
bool "Virtualization"
|
||||
depends on HAVE_KVM || IA64
|
||||
|
||||
@@ -134,9 +134,9 @@ SYSCALL_DEFINE4(32_ftruncate64, unsigned long, fd, unsigned long, __dummy,
|
||||
return sys_ftruncate(fd, merge_64(a2, a3));
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE5(32_llseek, unsigned long, fd, unsigned long, offset_high,
|
||||
unsigned long, offset_low, loff_t __user *, result,
|
||||
unsigned long, origin)
|
||||
SYSCALL_DEFINE5(32_llseek, unsigned int, fd, unsigned int, offset_high,
|
||||
unsigned int, offset_low, loff_t __user *, result,
|
||||
unsigned int, origin)
|
||||
{
|
||||
return sys_llseek(fd, offset_high, offset_low, result, origin);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
PPC_LONG "1b,4b,2b,4b\n" \
|
||||
".previous" \
|
||||
: "=&r" (oldval), "=&r" (ret) \
|
||||
: "b" (uaddr), "i" (-EFAULT), "1" (oparg) \
|
||||
: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
|
||||
: "cr0", "memory")
|
||||
|
||||
static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
|
||||
@@ -47,19 +47,19 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
|
||||
|
||||
switch (op) {
|
||||
case FUTEX_OP_SET:
|
||||
__futex_atomic_op("", ret, oldval, uaddr, oparg);
|
||||
__futex_atomic_op("mr %1,%4\n", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
case FUTEX_OP_ADD:
|
||||
__futex_atomic_op("add %1,%0,%1\n", ret, oldval, uaddr, oparg);
|
||||
__futex_atomic_op("add %1,%0,%4\n", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
case FUTEX_OP_OR:
|
||||
__futex_atomic_op("or %1,%0,%1\n", ret, oldval, uaddr, oparg);
|
||||
__futex_atomic_op("or %1,%0,%4\n", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
case FUTEX_OP_ANDN:
|
||||
__futex_atomic_op("andc %1,%0,%1\n", ret, oldval, uaddr, oparg);
|
||||
__futex_atomic_op("andc %1,%0,%4\n", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
case FUTEX_OP_XOR:
|
||||
__futex_atomic_op("xor %1,%0,%1\n", ret, oldval, uaddr, oparg);
|
||||
__futex_atomic_op("xor %1,%0,%4\n", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
# KVM configuration
|
||||
#
|
||||
|
||||
config HAVE_KVM_IRQCHIP
|
||||
bool
|
||||
|
||||
menuconfig VIRTUALIZATION
|
||||
bool "Virtualization"
|
||||
---help---
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
config HAVE_KVM
|
||||
bool
|
||||
|
||||
config HAVE_KVM_IRQCHIP
|
||||
bool
|
||||
|
||||
menuconfig VIRTUALIZATION
|
||||
bool "Virtualization"
|
||||
default y
|
||||
|
||||
@@ -57,6 +57,8 @@ static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, unsigned i
|
||||
|
||||
static inline void tlb_flush_mmu(struct mmu_gather *mp)
|
||||
{
|
||||
if (!mp->fullmm)
|
||||
flush_tlb_pending();
|
||||
if (mp->need_flush) {
|
||||
free_pages_and_swap_cache(mp->pages, mp->pages_nr);
|
||||
mp->pages_nr = 0;
|
||||
@@ -78,8 +80,6 @@ static inline void tlb_finish_mmu(struct mmu_gather *mp, unsigned long start, un
|
||||
|
||||
if (mp->fullmm)
|
||||
mp->fullmm = 0;
|
||||
else
|
||||
flush_tlb_pending();
|
||||
|
||||
/* keep the page table cache within bounds */
|
||||
check_pgt_cache();
|
||||
|
||||
+22
-1
@@ -13,6 +13,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/delay.h>
|
||||
@@ -206,13 +207,33 @@ void nmi_adjust_hz(unsigned int new_hz)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nmi_adjust_hz);
|
||||
|
||||
static int nmi_shutdown(struct notifier_block *nb, unsigned long cmd, void *p)
|
||||
{
|
||||
on_each_cpu(stop_watchdog, NULL, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct notifier_block nmi_reboot_notifier = {
|
||||
.notifier_call = nmi_shutdown,
|
||||
};
|
||||
|
||||
int __init nmi_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
nmi_usable = 1;
|
||||
|
||||
on_each_cpu(start_watchdog, NULL, 1);
|
||||
|
||||
return check_nmi_watchdog();
|
||||
err = check_nmi_watchdog();
|
||||
if (!err) {
|
||||
err = register_reboot_notifier(&nmi_reboot_notifier);
|
||||
if (err) {
|
||||
nmi_usable = 0;
|
||||
on_each_cpu(stop_watchdog, NULL, 1);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __init setup_nmi_watchdog(char *str)
|
||||
|
||||
@@ -1031,7 +1031,7 @@ void smp_fetch_global_regs(void)
|
||||
* If the address space is non-shared (ie. mm->count == 1) we avoid
|
||||
* cross calls when we want to flush the currently running process's
|
||||
* tlb state. This is done by clearing all cpu bits except the current
|
||||
* processor's in current->active_mm->cpu_vm_mask and performing the
|
||||
* processor's in current->mm->cpu_vm_mask and performing the
|
||||
* flush locally only. This will force any subsequent cpus which run
|
||||
* this task to flush the context from the local tlb if the process
|
||||
* migrates to another cpu (again).
|
||||
@@ -1074,7 +1074,7 @@ void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long
|
||||
u32 ctx = CTX_HWBITS(mm->context);
|
||||
int cpu = get_cpu();
|
||||
|
||||
if (mm == current->active_mm && atomic_read(&mm->mm_users) == 1)
|
||||
if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
|
||||
mm->cpu_vm_mask = cpumask_of_cpu(cpu);
|
||||
else
|
||||
smp_cross_call_masked(&xcall_flush_tlb_pending,
|
||||
|
||||
@@ -523,6 +523,7 @@ config X86_PTRACE_BTS
|
||||
bool "Branch Trace Store"
|
||||
default y
|
||||
depends on X86_DEBUGCTLMSR
|
||||
depends on BROKEN
|
||||
help
|
||||
This adds a ptrace interface to the hardware's branch trace store.
|
||||
|
||||
|
||||
@@ -27,13 +27,14 @@ static int detect_memory_e820(void)
|
||||
do {
|
||||
size = sizeof(struct e820entry);
|
||||
|
||||
/* Important: %edx is clobbered by some BIOSes,
|
||||
so it must be either used for the error output
|
||||
/* Important: %edx and %esi are clobbered by some BIOSes,
|
||||
so they must be either used for the error output
|
||||
or explicitly marked clobbered. */
|
||||
asm("int $0x15; setc %0"
|
||||
: "=d" (err), "+b" (next), "=a" (id), "+c" (size),
|
||||
"=m" (*desc)
|
||||
: "D" (desc), "d" (SMAP), "a" (0xe820));
|
||||
: "D" (desc), "d" (SMAP), "a" (0xe820)
|
||||
: "esi");
|
||||
|
||||
/* BIOSes which terminate the chain with CF = 1 as opposed
|
||||
to %ebx = 0 don't always report the SMAP signature on
|
||||
|
||||
@@ -86,12 +86,12 @@ void __init setup_bios_corruption_check(void)
|
||||
if (addr == 0)
|
||||
break;
|
||||
|
||||
if (addr >= corruption_check_size)
|
||||
break;
|
||||
|
||||
if ((addr + size) > corruption_check_size)
|
||||
size = corruption_check_size - addr;
|
||||
|
||||
if (size == 0)
|
||||
break;
|
||||
|
||||
e820_update_range(addr, size, E820_RAM, E820_RESERVED);
|
||||
scan_areas[num_scan_areas].addr = addr;
|
||||
scan_areas[num_scan_areas].size = size;
|
||||
|
||||
@@ -680,6 +680,18 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||
perf->states[i].transition_latency * 1000;
|
||||
}
|
||||
|
||||
/* Check for high latency (>20uS) from buggy BIOSes, like on T42 */
|
||||
if (perf->control_register.space_id == ACPI_ADR_SPACE_FIXED_HARDWARE &&
|
||||
policy->cpuinfo.transition_latency > 20 * 1000) {
|
||||
static int print_once;
|
||||
policy->cpuinfo.transition_latency = 20 * 1000;
|
||||
if (!print_once) {
|
||||
print_once = 1;
|
||||
printk(KERN_INFO "Capping off P-state tranision latency"
|
||||
" at 20 uS\n");
|
||||
}
|
||||
}
|
||||
|
||||
data->max_freq = perf->states[0].core_frequency * 1000;
|
||||
/* table init */
|
||||
for (i=0; i<perf->state_count; i++) {
|
||||
|
||||
@@ -41,6 +41,32 @@ static int __init mtrr_debug(char *opt)
|
||||
}
|
||||
early_param("mtrr.show", mtrr_debug);
|
||||
|
||||
/**
|
||||
* BIOS is expected to clear MtrrFixDramModEn bit, see for example
|
||||
* "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
|
||||
* Opteron Processors" (26094 Rev. 3.30 February 2006), section
|
||||
* "13.2.1.2 SYSCFG Register": "The MtrrFixDramModEn bit should be set
|
||||
* to 1 during BIOS initalization of the fixed MTRRs, then cleared to
|
||||
* 0 for operation."
|
||||
*/
|
||||
static inline void k8_check_syscfg_dram_mod_en(void)
|
||||
{
|
||||
u32 lo, hi;
|
||||
|
||||
if (!((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
|
||||
(boot_cpu_data.x86 >= 0x0f)))
|
||||
return;
|
||||
|
||||
rdmsr(MSR_K8_SYSCFG, lo, hi);
|
||||
if (lo & K8_MTRRFIXRANGE_DRAM_MODIFY) {
|
||||
printk(KERN_ERR FW_WARN "MTRR: CPU %u: SYSCFG[MtrrFixDramModEn]"
|
||||
" not cleared by BIOS, clearing this bit\n",
|
||||
smp_processor_id());
|
||||
lo &= ~K8_MTRRFIXRANGE_DRAM_MODIFY;
|
||||
mtrr_wrmsr(MSR_K8_SYSCFG, lo, hi);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the effective MTRR type for the region
|
||||
* Error returns:
|
||||
@@ -174,6 +200,8 @@ get_fixed_ranges(mtrr_type * frs)
|
||||
unsigned int *p = (unsigned int *) frs;
|
||||
int i;
|
||||
|
||||
k8_check_syscfg_dram_mod_en();
|
||||
|
||||
rdmsr(MTRRfix64K_00000_MSR, p[0], p[1]);
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
@@ -307,28 +335,11 @@ void mtrr_wrmsr(unsigned msr, unsigned a, unsigned b)
|
||||
smp_processor_id(), msr, a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable and allow read/write of extended fixed-range MTRR bits on K8 CPUs
|
||||
* see AMD publication no. 24593, chapter 3.2.1 for more information
|
||||
*/
|
||||
static inline void k8_enable_fixed_iorrs(void)
|
||||
{
|
||||
unsigned lo, hi;
|
||||
|
||||
rdmsr(MSR_K8_SYSCFG, lo, hi);
|
||||
mtrr_wrmsr(MSR_K8_SYSCFG, lo
|
||||
| K8_MTRRFIXRANGE_DRAM_ENABLE
|
||||
| K8_MTRRFIXRANGE_DRAM_MODIFY, hi);
|
||||
}
|
||||
|
||||
/**
|
||||
* set_fixed_range - checks & updates a fixed-range MTRR if it differs from the value it should have
|
||||
* @msr: MSR address of the MTTR which should be checked and updated
|
||||
* @changed: pointer which indicates whether the MTRR needed to be changed
|
||||
* @msrwords: pointer to the MSR values which the MSR should have
|
||||
*
|
||||
* If K8 extentions are wanted, update the K8 SYSCFG MSR also.
|
||||
* See AMD publication no. 24593, chapter 7.8.1, page 233 for more information.
|
||||
*/
|
||||
static void set_fixed_range(int msr, bool *changed, unsigned int *msrwords)
|
||||
{
|
||||
@@ -337,10 +348,6 @@ static void set_fixed_range(int msr, bool *changed, unsigned int *msrwords)
|
||||
rdmsr(msr, lo, hi);
|
||||
|
||||
if (lo != msrwords[0] || hi != msrwords[1]) {
|
||||
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
|
||||
(boot_cpu_data.x86 >= 0x0f && boot_cpu_data.x86 <= 0x11) &&
|
||||
((msrwords[0] | msrwords[1]) & K8_MTRR_RDMEM_WRMEM_MASK))
|
||||
k8_enable_fixed_iorrs();
|
||||
mtrr_wrmsr(msr, msrwords[0], msrwords[1]);
|
||||
*changed = true;
|
||||
}
|
||||
@@ -419,6 +426,8 @@ static int set_fixed_ranges(mtrr_type * frs)
|
||||
bool changed = false;
|
||||
int block=-1, range;
|
||||
|
||||
k8_check_syscfg_dram_mod_en();
|
||||
|
||||
while (fixed_range_blocks[++block].ranges)
|
||||
for (range=0; range < fixed_range_blocks[block].ranges; range++)
|
||||
set_fixed_range(fixed_range_blocks[block].base_msr + range,
|
||||
|
||||
@@ -2475,6 +2475,7 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
|
||||
me = smp_processor_id();
|
||||
for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
|
||||
unsigned int irq;
|
||||
unsigned int irr;
|
||||
struct irq_desc *desc;
|
||||
struct irq_cfg *cfg;
|
||||
irq = __get_cpu_var(vector_irq)[vector];
|
||||
@@ -2494,6 +2495,18 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
|
||||
if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
|
||||
goto unlock;
|
||||
|
||||
irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
|
||||
/*
|
||||
* Check if the vector that needs to be cleanedup is
|
||||
* registered at the cpu's IRR. If so, then this is not
|
||||
* the best time to clean it up. Lets clean it up in the
|
||||
* next attempt by sending another IRQ_MOVE_CLEANUP_VECTOR
|
||||
* to myself.
|
||||
*/
|
||||
if (irr & (1 << (vector % 32))) {
|
||||
send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
|
||||
goto unlock;
|
||||
}
|
||||
__get_cpu_var(vector_irq)[vector] = -1;
|
||||
cfg->move_cleanup_count--;
|
||||
unlock:
|
||||
|
||||
@@ -690,9 +690,8 @@ static int ptrace_bts_config(struct task_struct *child,
|
||||
if (!cfg.signal)
|
||||
return -EINVAL;
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
child->thread.bts_ovfl_signal = cfg.signal;
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if ((cfg.flags & PTRACE_BTS_O_ALLOC) &&
|
||||
|
||||
@@ -742,7 +742,7 @@ static int __init uv_bau_init(void)
|
||||
int node;
|
||||
int nblades;
|
||||
int last_blade;
|
||||
int cur_cpu = 0;
|
||||
int cur_cpu;
|
||||
|
||||
if (!is_uv_system())
|
||||
return 0;
|
||||
@@ -752,6 +752,7 @@ static int __init uv_bau_init(void)
|
||||
uv_mmask = (1UL << uv_hub_info->n_val) - 1;
|
||||
nblades = 0;
|
||||
last_blade = -1;
|
||||
cur_cpu = 0;
|
||||
for_each_online_node(node) {
|
||||
blade = uv_node_to_blade_id(node);
|
||||
if (blade == last_blade)
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
config HAVE_KVM
|
||||
bool
|
||||
|
||||
config HAVE_KVM_IRQCHIP
|
||||
bool
|
||||
default y
|
||||
|
||||
menuconfig VIRTUALIZATION
|
||||
bool "Virtualization"
|
||||
depends on HAVE_KVM || X86
|
||||
|
||||
@@ -536,6 +536,16 @@ void kvm_pit_reset(struct kvm_pit *pit)
|
||||
pit->pit_state.irq_ack = 1;
|
||||
}
|
||||
|
||||
static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask)
|
||||
{
|
||||
struct kvm_pit *pit = container_of(kimn, struct kvm_pit, mask_notifier);
|
||||
|
||||
if (!mask) {
|
||||
atomic_set(&pit->pit_state.pit_timer.pending, 0);
|
||||
pit->pit_state.irq_ack = 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct kvm_pit *kvm_create_pit(struct kvm *kvm)
|
||||
{
|
||||
struct kvm_pit *pit;
|
||||
@@ -584,6 +594,9 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm)
|
||||
|
||||
kvm_pit_reset(pit);
|
||||
|
||||
pit->mask_notifier.func = pit_mask_notifer;
|
||||
kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier);
|
||||
|
||||
return pit;
|
||||
}
|
||||
|
||||
@@ -592,6 +605,8 @@ void kvm_free_pit(struct kvm *kvm)
|
||||
struct hrtimer *timer;
|
||||
|
||||
if (kvm->arch.vpit) {
|
||||
kvm_unregister_irq_mask_notifier(kvm, 0,
|
||||
&kvm->arch.vpit->mask_notifier);
|
||||
mutex_lock(&kvm->arch.vpit->pit_state.lock);
|
||||
timer = &kvm->arch.vpit->pit_state.pit_timer.timer;
|
||||
hrtimer_cancel(timer);
|
||||
|
||||
@@ -45,6 +45,7 @@ struct kvm_pit {
|
||||
struct kvm *kvm;
|
||||
struct kvm_kpit_state pit_state;
|
||||
int irq_source_id;
|
||||
struct kvm_irq_mask_notifier mask_notifier;
|
||||
};
|
||||
|
||||
#define KVM_PIT_BASE_ADDRESS 0x40
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ static inline int kvm_mmu_reload(struct kvm_vcpu *vcpu)
|
||||
static inline int is_long_mode(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
#ifdef CONFIG_X86_64
|
||||
return vcpu->arch.shadow_efer & EFER_LME;
|
||||
return vcpu->arch.shadow_efer & EFER_LMA;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
@@ -314,9 +314,9 @@ static int FNAME(shadow_walk_entry)(struct kvm_shadow_walk *_sw,
|
||||
return 0;
|
||||
|
||||
if (is_large_pte(*sptep)) {
|
||||
rmap_remove(vcpu->kvm, sptep);
|
||||
set_shadow_pte(sptep, shadow_trap_nonpresent_pte);
|
||||
kvm_flush_remote_tlbs(vcpu->kvm);
|
||||
rmap_remove(vcpu->kvm, sptep);
|
||||
}
|
||||
|
||||
if (level == PT_DIRECTORY_LEVEL && gw->level == PT_DIRECTORY_LEVEL) {
|
||||
@@ -476,16 +476,20 @@ static int FNAME(shadow_invlpg_entry)(struct kvm_shadow_walk *_sw,
|
||||
if (level == PT_PAGE_TABLE_LEVEL ||
|
||||
((level == PT_DIRECTORY_LEVEL) && is_large_pte(*sptep))) {
|
||||
struct kvm_mmu_page *sp = page_header(__pa(sptep));
|
||||
int need_flush = 0;
|
||||
|
||||
sw->pte_gpa = (sp->gfn << PAGE_SHIFT);
|
||||
sw->pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t);
|
||||
|
||||
if (is_shadow_present_pte(*sptep)) {
|
||||
need_flush = 1;
|
||||
rmap_remove(vcpu->kvm, sptep);
|
||||
if (is_large_pte(*sptep))
|
||||
--vcpu->kvm->stat.lpages;
|
||||
}
|
||||
set_shadow_pte(sptep, shadow_trap_nonpresent_pte);
|
||||
if (need_flush)
|
||||
kvm_flush_remote_tlbs(vcpu->kvm);
|
||||
return 1;
|
||||
}
|
||||
if (!is_shadow_present_pte(*sptep))
|
||||
|
||||
+29
-12
@@ -760,20 +760,37 @@ static void svm_get_segment(struct kvm_vcpu *vcpu,
|
||||
var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1;
|
||||
var->g = (s->attrib >> SVM_SELECTOR_G_SHIFT) & 1;
|
||||
|
||||
/*
|
||||
* SVM always stores 0 for the 'G' bit in the CS selector in
|
||||
* the VMCB on a VMEXIT. This hurts cross-vendor migration:
|
||||
* Intel's VMENTRY has a check on the 'G' bit.
|
||||
*/
|
||||
if (seg == VCPU_SREG_CS)
|
||||
switch (seg) {
|
||||
case VCPU_SREG_CS:
|
||||
/*
|
||||
* SVM always stores 0 for the 'G' bit in the CS selector in
|
||||
* the VMCB on a VMEXIT. This hurts cross-vendor migration:
|
||||
* Intel's VMENTRY has a check on the 'G' bit.
|
||||
*/
|
||||
var->g = s->limit > 0xfffff;
|
||||
|
||||
/*
|
||||
* Work around a bug where the busy flag in the tr selector
|
||||
* isn't exposed
|
||||
*/
|
||||
if (seg == VCPU_SREG_TR)
|
||||
break;
|
||||
case VCPU_SREG_TR:
|
||||
/*
|
||||
* Work around a bug where the busy flag in the tr selector
|
||||
* isn't exposed
|
||||
*/
|
||||
var->type |= 0x2;
|
||||
break;
|
||||
case VCPU_SREG_DS:
|
||||
case VCPU_SREG_ES:
|
||||
case VCPU_SREG_FS:
|
||||
case VCPU_SREG_GS:
|
||||
/*
|
||||
* The accessed bit must always be set in the segment
|
||||
* descriptor cache, although it can be cleared in the
|
||||
* descriptor, the cached bit always remains at 1. Since
|
||||
* Intel has a check on this, set it here to support
|
||||
* cross-vendor migration.
|
||||
*/
|
||||
if (!var->unusable)
|
||||
var->type |= 0x1;
|
||||
break;
|
||||
}
|
||||
|
||||
var->unusable = !var->present;
|
||||
}
|
||||
|
||||
+25
-31
@@ -928,11 +928,11 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
|
||||
int ret = 0;
|
||||
|
||||
switch (msr_index) {
|
||||
#ifdef CONFIG_X86_64
|
||||
case MSR_EFER:
|
||||
vmx_load_host_state(vmx);
|
||||
ret = kvm_set_msr_common(vcpu, msr_index, data);
|
||||
break;
|
||||
#ifdef CONFIG_X86_64
|
||||
case MSR_FS_BASE:
|
||||
vmcs_writel(GUEST_FS_BASE, data);
|
||||
break;
|
||||
@@ -1433,6 +1433,29 @@ continue_rmode:
|
||||
init_rmode(vcpu->kvm);
|
||||
}
|
||||
|
||||
static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
struct kvm_msr_entry *msr = find_msr_entry(vmx, MSR_EFER);
|
||||
|
||||
vcpu->arch.shadow_efer = efer;
|
||||
if (!msr)
|
||||
return;
|
||||
if (efer & EFER_LMA) {
|
||||
vmcs_write32(VM_ENTRY_CONTROLS,
|
||||
vmcs_read32(VM_ENTRY_CONTROLS) |
|
||||
VM_ENTRY_IA32E_MODE);
|
||||
msr->data = efer;
|
||||
} else {
|
||||
vmcs_write32(VM_ENTRY_CONTROLS,
|
||||
vmcs_read32(VM_ENTRY_CONTROLS) &
|
||||
~VM_ENTRY_IA32E_MODE);
|
||||
|
||||
msr->data = efer & ~EFER_LME;
|
||||
}
|
||||
setup_msrs(vmx);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
||||
static void enter_lmode(struct kvm_vcpu *vcpu)
|
||||
@@ -1447,13 +1470,8 @@ static void enter_lmode(struct kvm_vcpu *vcpu)
|
||||
(guest_tr_ar & ~AR_TYPE_MASK)
|
||||
| AR_TYPE_BUSY_64_TSS);
|
||||
}
|
||||
|
||||
vcpu->arch.shadow_efer |= EFER_LMA;
|
||||
|
||||
find_msr_entry(to_vmx(vcpu), MSR_EFER)->data |= EFER_LMA | EFER_LME;
|
||||
vmcs_write32(VM_ENTRY_CONTROLS,
|
||||
vmcs_read32(VM_ENTRY_CONTROLS)
|
||||
| VM_ENTRY_IA32E_MODE);
|
||||
vmx_set_efer(vcpu, vcpu->arch.shadow_efer);
|
||||
}
|
||||
|
||||
static void exit_lmode(struct kvm_vcpu *vcpu)
|
||||
@@ -1612,30 +1630,6 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
|
||||
vmcs_writel(GUEST_CR4, hw_cr4);
|
||||
}
|
||||
|
||||
static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
struct kvm_msr_entry *msr = find_msr_entry(vmx, MSR_EFER);
|
||||
|
||||
vcpu->arch.shadow_efer = efer;
|
||||
if (!msr)
|
||||
return;
|
||||
if (efer & EFER_LMA) {
|
||||
vmcs_write32(VM_ENTRY_CONTROLS,
|
||||
vmcs_read32(VM_ENTRY_CONTROLS) |
|
||||
VM_ENTRY_IA32E_MODE);
|
||||
msr->data = efer;
|
||||
|
||||
} else {
|
||||
vmcs_write32(VM_ENTRY_CONTROLS,
|
||||
vmcs_read32(VM_ENTRY_CONTROLS) &
|
||||
~VM_ENTRY_IA32E_MODE);
|
||||
|
||||
msr->data = efer & ~EFER_LME;
|
||||
}
|
||||
setup_msrs(vmx);
|
||||
}
|
||||
|
||||
static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
|
||||
{
|
||||
struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
|
||||
|
||||
@@ -485,11 +485,17 @@ static void lguest_write_cr4(unsigned long val)
|
||||
* into a process' address space. We set the entry then tell the Host the
|
||||
* toplevel and address this corresponds to. The Guest uses one pagetable per
|
||||
* process, so we need to tell the Host which one we're changing (mm->pgd). */
|
||||
static void lguest_pte_update(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep)
|
||||
{
|
||||
lazy_hcall(LHCALL_SET_PTE, __pa(mm->pgd), addr, ptep->pte_low);
|
||||
}
|
||||
|
||||
static void lguest_set_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep, pte_t pteval)
|
||||
{
|
||||
*ptep = pteval;
|
||||
lazy_hcall(LHCALL_SET_PTE, __pa(mm->pgd), addr, pteval.pte_low);
|
||||
lguest_pte_update(mm, addr, ptep);
|
||||
}
|
||||
|
||||
/* The Guest calls this to set a top-level entry. Again, we set the entry then
|
||||
@@ -1034,6 +1040,8 @@ __init void lguest_init(void)
|
||||
pv_mmu_ops.read_cr3 = lguest_read_cr3;
|
||||
pv_mmu_ops.lazy_mode.enter = paravirt_enter_lazy_mmu;
|
||||
pv_mmu_ops.lazy_mode.leave = lguest_leave_lazy_mode;
|
||||
pv_mmu_ops.pte_update = lguest_pte_update;
|
||||
pv_mmu_ops.pte_update_defer = lguest_pte_update;
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
/* apic read/write intercepts */
|
||||
|
||||
+22
-81
@@ -641,10 +641,11 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot,
|
||||
is_ram = pat_pagerange_is_ram(paddr, paddr + size);
|
||||
|
||||
/*
|
||||
* reserve_pfn_range() doesn't support RAM pages.
|
||||
* reserve_pfn_range() doesn't support RAM pages. Maintain the current
|
||||
* behavior with RAM pages by returning success.
|
||||
*/
|
||||
if (is_ram != 0)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
|
||||
ret = reserve_memtype(paddr, paddr + size, want_flags, &flags);
|
||||
if (ret)
|
||||
@@ -712,29 +713,28 @@ static void free_pfn_range(u64 paddr, unsigned long size)
|
||||
*
|
||||
* If the vma has a linear pfn mapping for the entire range, we get the prot
|
||||
* from pte and reserve the entire vma range with single reserve_pfn_range call.
|
||||
* Otherwise, we reserve the entire vma range, my ging through the PTEs page
|
||||
* by page to get physical address and protection.
|
||||
*/
|
||||
int track_pfn_vma_copy(struct vm_area_struct *vma)
|
||||
{
|
||||
int retval = 0;
|
||||
unsigned long i, j;
|
||||
resource_size_t paddr;
|
||||
unsigned long prot;
|
||||
unsigned long vma_start = vma->vm_start;
|
||||
unsigned long vma_end = vma->vm_end;
|
||||
unsigned long vma_size = vma_end - vma_start;
|
||||
unsigned long vma_size = vma->vm_end - vma->vm_start;
|
||||
pgprot_t pgprot;
|
||||
|
||||
if (!pat_enabled)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* For now, only handle remap_pfn_range() vmas where
|
||||
* is_linear_pfn_mapping() == TRUE. Handling of
|
||||
* vm_insert_pfn() is TBD.
|
||||
*/
|
||||
if (is_linear_pfn_mapping(vma)) {
|
||||
/*
|
||||
* reserve the whole chunk covered by vma. We need the
|
||||
* starting address and protection from pte.
|
||||
*/
|
||||
if (follow_phys(vma, vma_start, 0, &prot, &paddr)) {
|
||||
if (follow_phys(vma, vma->vm_start, 0, &prot, &paddr)) {
|
||||
WARN_ON_ONCE(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -742,28 +742,7 @@ int track_pfn_vma_copy(struct vm_area_struct *vma)
|
||||
return reserve_pfn_range(paddr, vma_size, &pgprot, 1);
|
||||
}
|
||||
|
||||
/* reserve entire vma page by page, using pfn and prot from pte */
|
||||
for (i = 0; i < vma_size; i += PAGE_SIZE) {
|
||||
if (follow_phys(vma, vma_start + i, 0, &prot, &paddr))
|
||||
continue;
|
||||
|
||||
pgprot = __pgprot(prot);
|
||||
retval = reserve_pfn_range(paddr, PAGE_SIZE, &pgprot, 1);
|
||||
if (retval)
|
||||
goto cleanup_ret;
|
||||
}
|
||||
return 0;
|
||||
|
||||
cleanup_ret:
|
||||
/* Reserve error: Cleanup partial reservation and return error */
|
||||
for (j = 0; j < i; j += PAGE_SIZE) {
|
||||
if (follow_phys(vma, vma_start + j, 0, &prot, &paddr))
|
||||
continue;
|
||||
|
||||
free_pfn_range(paddr, PAGE_SIZE);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -773,50 +752,28 @@ cleanup_ret:
|
||||
* prot is passed in as a parameter for the new mapping. If the vma has a
|
||||
* linear pfn mapping for the entire range reserve the entire vma range with
|
||||
* single reserve_pfn_range call.
|
||||
* Otherwise, we look t the pfn and size and reserve only the specified range
|
||||
* page by page.
|
||||
*
|
||||
* Note that this function can be called with caller trying to map only a
|
||||
* subrange/page inside the vma.
|
||||
*/
|
||||
int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot,
|
||||
unsigned long pfn, unsigned long size)
|
||||
{
|
||||
int retval = 0;
|
||||
unsigned long i, j;
|
||||
resource_size_t base_paddr;
|
||||
resource_size_t paddr;
|
||||
unsigned long vma_start = vma->vm_start;
|
||||
unsigned long vma_end = vma->vm_end;
|
||||
unsigned long vma_size = vma_end - vma_start;
|
||||
unsigned long vma_size = vma->vm_end - vma->vm_start;
|
||||
|
||||
if (!pat_enabled)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* For now, only handle remap_pfn_range() vmas where
|
||||
* is_linear_pfn_mapping() == TRUE. Handling of
|
||||
* vm_insert_pfn() is TBD.
|
||||
*/
|
||||
if (is_linear_pfn_mapping(vma)) {
|
||||
/* reserve the whole chunk starting from vm_pgoff */
|
||||
paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
|
||||
return reserve_pfn_range(paddr, vma_size, prot, 0);
|
||||
}
|
||||
|
||||
/* reserve page by page using pfn and size */
|
||||
base_paddr = (resource_size_t)pfn << PAGE_SHIFT;
|
||||
for (i = 0; i < size; i += PAGE_SIZE) {
|
||||
paddr = base_paddr + i;
|
||||
retval = reserve_pfn_range(paddr, PAGE_SIZE, prot, 0);
|
||||
if (retval)
|
||||
goto cleanup_ret;
|
||||
}
|
||||
return 0;
|
||||
|
||||
cleanup_ret:
|
||||
/* Reserve error: Cleanup partial reservation and return error */
|
||||
for (j = 0; j < i; j += PAGE_SIZE) {
|
||||
paddr = base_paddr + j;
|
||||
free_pfn_range(paddr, PAGE_SIZE);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -827,39 +784,23 @@ cleanup_ret:
|
||||
void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn,
|
||||
unsigned long size)
|
||||
{
|
||||
unsigned long i;
|
||||
resource_size_t paddr;
|
||||
unsigned long prot;
|
||||
unsigned long vma_start = vma->vm_start;
|
||||
unsigned long vma_end = vma->vm_end;
|
||||
unsigned long vma_size = vma_end - vma_start;
|
||||
unsigned long vma_size = vma->vm_end - vma->vm_start;
|
||||
|
||||
if (!pat_enabled)
|
||||
return;
|
||||
|
||||
/*
|
||||
* For now, only handle remap_pfn_range() vmas where
|
||||
* is_linear_pfn_mapping() == TRUE. Handling of
|
||||
* vm_insert_pfn() is TBD.
|
||||
*/
|
||||
if (is_linear_pfn_mapping(vma)) {
|
||||
/* free the whole chunk starting from vm_pgoff */
|
||||
paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
|
||||
free_pfn_range(paddr, vma_size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (size != 0 && size != vma_size) {
|
||||
/* free page by page, using pfn and size */
|
||||
paddr = (resource_size_t)pfn << PAGE_SHIFT;
|
||||
for (i = 0; i < size; i += PAGE_SIZE) {
|
||||
paddr = paddr + i;
|
||||
free_pfn_range(paddr, PAGE_SIZE);
|
||||
}
|
||||
} else {
|
||||
/* free entire vma, page by page, using the pfn from pte */
|
||||
for (i = 0; i < vma_size; i += PAGE_SIZE) {
|
||||
if (follow_phys(vma, vma_start + i, 0, &prot, &paddr))
|
||||
continue;
|
||||
|
||||
free_pfn_range(paddr, PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pgprot_t pgprot_writecombine(pgprot_t prot)
|
||||
|
||||
@@ -494,26 +494,6 @@ static void __devinit pci_siemens_interrupt_controller(struct pci_dev *dev)
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SIEMENS, 0x0015,
|
||||
pci_siemens_interrupt_controller);
|
||||
|
||||
/*
|
||||
* Regular PCI devices have 256 bytes, but AMD Family 10h/11h CPUs have
|
||||
* 4096 bytes configuration space for each function of their processor
|
||||
* configuration space.
|
||||
*/
|
||||
static void amd_cpu_pci_cfg_space_size(struct pci_dev *dev)
|
||||
{
|
||||
dev->cfg_size = pci_cfg_space_size_ext(dev);
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1200, amd_cpu_pci_cfg_space_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1201, amd_cpu_pci_cfg_space_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1202, amd_cpu_pci_cfg_space_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1203, amd_cpu_pci_cfg_space_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1204, amd_cpu_pci_cfg_space_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1300, amd_cpu_pci_cfg_space_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1301, amd_cpu_pci_cfg_space_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1302, amd_cpu_pci_cfg_space_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1303, amd_cpu_pci_cfg_space_size);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1304, amd_cpu_pci_cfg_space_size);
|
||||
|
||||
/*
|
||||
* SB600: Disable BAR1 on device 14.0 to avoid HPET resources from
|
||||
* confusing the PCI engine:
|
||||
|
||||
@@ -319,6 +319,9 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
return -EINVAL;
|
||||
}
|
||||
flags = new_flags;
|
||||
vma->vm_page_prot = __pgprot(
|
||||
(pgprot_val(vma->vm_page_prot) & ~_PAGE_CACHE_MASK) |
|
||||
flags);
|
||||
}
|
||||
|
||||
if (((vma->vm_pgoff < max_low_pfn_mapped) ||
|
||||
|
||||
@@ -82,6 +82,9 @@ static int shash_update_unaligned(struct shash_desc *desc, const u8 *data,
|
||||
u8 buf[shash_align_buffer_size(unaligned_len, alignmask)]
|
||||
__attribute__ ((aligned));
|
||||
|
||||
if (unaligned_len > len)
|
||||
unaligned_len = len;
|
||||
|
||||
memcpy(buf, data, unaligned_len);
|
||||
|
||||
return shash->update(desc, buf, unaligned_len) ?:
|
||||
|
||||
+2
-1
@@ -1146,9 +1146,10 @@ static int __init dock_init(void)
|
||||
static void __exit dock_exit(void)
|
||||
{
|
||||
struct dock_station *dock_station;
|
||||
struct dock_station *tmp;
|
||||
|
||||
unregister_acpi_bus_notifier(&dock_acpi_notifier);
|
||||
list_for_each_entry(dock_station, &dock_stations, sibiling)
|
||||
list_for_each_entry_safe(dock_station, tmp, &dock_stations, sibiling)
|
||||
dock_remove(dock_station);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
|
||||
* Portions Copyright (C) 2001 Sun Microsystems, Inc.
|
||||
* Portions Copyright (C) 2003 Red Hat Inc
|
||||
* Portions Copyright (C) 2005-2007 MontaVista Software, Inc.
|
||||
* Portions Copyright (C) 2005-2009 MontaVista Software, Inc.
|
||||
*
|
||||
* TODO
|
||||
* Look into engine reset on timeout errors. Should not be required.
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "pata_hpt37x"
|
||||
#define DRV_VERSION "0.6.11"
|
||||
#define DRV_VERSION "0.6.12"
|
||||
|
||||
struct hpt_clock {
|
||||
u8 xfer_speed;
|
||||
@@ -444,23 +444,6 @@ static void hpt370_set_dmamode(struct ata_port *ap, struct ata_device *adev)
|
||||
pci_write_config_dword(pdev, addr1, reg | mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* hpt370_bmdma_start - DMA engine begin
|
||||
* @qc: ATA command
|
||||
*
|
||||
* The 370 and 370A want us to reset the DMA engine each time we
|
||||
* use it. The 372 and later are fine.
|
||||
*/
|
||||
|
||||
static void hpt370_bmdma_start(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
struct pci_dev *pdev = to_pci_dev(ap->host->dev);
|
||||
pci_write_config_byte(pdev, 0x50 + 4 * ap->port_no, 0x37);
|
||||
udelay(10);
|
||||
ata_bmdma_start(qc);
|
||||
}
|
||||
|
||||
/**
|
||||
* hpt370_bmdma_end - DMA engine stop
|
||||
* @qc: ATA command
|
||||
@@ -598,7 +581,6 @@ static struct scsi_host_template hpt37x_sht = {
|
||||
static struct ata_port_operations hpt370_port_ops = {
|
||||
.inherits = &ata_bmdma_port_ops,
|
||||
|
||||
.bmdma_start = hpt370_bmdma_start,
|
||||
.bmdma_stop = hpt370_bmdma_stop,
|
||||
|
||||
.mode_filter = hpt370_filter,
|
||||
|
||||
@@ -1226,7 +1226,7 @@ int agp_generic_alloc_pages(struct agp_bridge_data *bridge, struct agp_memory *m
|
||||
int i, ret = -ENOMEM;
|
||||
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
page = alloc_page(GFP_KERNEL | GFP_DMA32);
|
||||
page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
|
||||
/* agp_free_memory() needs gart address */
|
||||
if (page == NULL)
|
||||
goto out;
|
||||
@@ -1257,7 +1257,7 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
|
||||
{
|
||||
struct page * page;
|
||||
|
||||
page = alloc_page(GFP_KERNEL | GFP_DMA32);
|
||||
page = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
|
||||
if (page == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ out1:
|
||||
blkdev_put(bdev, filp->f_mode);
|
||||
out:
|
||||
mutex_unlock(&raw_mutex);
|
||||
unlock_kernel();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -2271,7 +2271,7 @@ rescan_last_byte:
|
||||
continue; /* nothing to display */
|
||||
}
|
||||
/* Glyph not found */
|
||||
if ((!(vc->vc_utf && !vc->vc_disp_ctrl) && c < 128) && !(c & ~charmask)) {
|
||||
if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) {
|
||||
/* In legacy mode use the glyph we get by a 1:1 mapping.
|
||||
This would make absolutely no sense with Unicode in mind,
|
||||
but do this for ASCII characters since a font may lack
|
||||
|
||||
@@ -505,7 +505,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
struct drm_map *map = NULL;
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_hash_item *hash;
|
||||
unsigned long prot;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
@@ -538,11 +537,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
vma->vm_ops = obj->dev->driver->gem_vm_ops;
|
||||
vma->vm_private_data = map->handle;
|
||||
/* FIXME: use pgprot_writecombine when available */
|
||||
prot = pgprot_val(vma->vm_page_prot);
|
||||
#ifdef CONFIG_X86
|
||||
prot |= _PAGE_CACHE_WC;
|
||||
#endif
|
||||
vma->vm_page_prot = __pgprot(prot);
|
||||
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
|
||||
|
||||
/* Take a ref for this mapping of the object, so that the fault
|
||||
* handler can dereference the mmap offset's pointer to the object.
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
|
||||
drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
|
||||
u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
|
||||
u32 last_acthd = I915_READ(acthd_reg);
|
||||
@@ -58,8 +57,12 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
|
||||
if (ring->space >= n)
|
||||
return 0;
|
||||
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
|
||||
if (dev->primary->master) {
|
||||
struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
|
||||
if (master_priv->sarea_priv)
|
||||
master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
|
||||
}
|
||||
|
||||
|
||||
if (ring->head != last_head)
|
||||
i = 0;
|
||||
|
||||
@@ -603,6 +603,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
case -EAGAIN:
|
||||
return VM_FAULT_OOM;
|
||||
case -EFAULT:
|
||||
case -EINVAL:
|
||||
return VM_FAULT_SIGBUS;
|
||||
default:
|
||||
return VM_FAULT_NOPAGE;
|
||||
|
||||
@@ -96,16 +96,16 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
||||
*/
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_NONE;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
|
||||
} else if ((!IS_I965G(dev) && !IS_G33(dev)) || IS_I965GM(dev) ||
|
||||
IS_GM45(dev)) {
|
||||
} else if (IS_MOBILE(dev)) {
|
||||
uint32_t dcc;
|
||||
|
||||
/* On 915-945 and GM965, channel interleave by the CPU is
|
||||
* determined by DCC. The CPU will alternate based on bit 6
|
||||
* in interleaved mode, and the GPU will then also alternate
|
||||
* on bit 6, 9, and 10 for X, but the CPU may also optionally
|
||||
* alternate based on bit 17 (XOR not disabled and XOR
|
||||
* bit == 17).
|
||||
/* On mobile 9xx chipsets, channel interleave by the CPU is
|
||||
* determined by DCC. For single-channel, neither the CPU
|
||||
* nor the GPU do swizzling. For dual channel interleaved,
|
||||
* the GPU's interleave is bit 9 and 10 for X tiled, and bit
|
||||
* 9 for Y tiled. The CPU's interleave is independent, and
|
||||
* can be based on either bit 11 (haven't seen this yet) or
|
||||
* bit 17 (common).
|
||||
*/
|
||||
dcc = I915_READ(DCC);
|
||||
switch (dcc & DCC_ADDRESSING_MODE_MASK) {
|
||||
@@ -115,19 +115,18 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_NONE;
|
||||
break;
|
||||
case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
|
||||
if (IS_I915G(dev) || IS_I915GM(dev) ||
|
||||
dcc & DCC_CHANNEL_XOR_DISABLE) {
|
||||
if (dcc & DCC_CHANNEL_XOR_DISABLE) {
|
||||
/* This is the base swizzling by the GPU for
|
||||
* tiled buffers.
|
||||
*/
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_9_10;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_9;
|
||||
} else if ((IS_I965GM(dev) || IS_GM45(dev)) &&
|
||||
(dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
|
||||
/* GM965/GM45 does either bit 11 or bit 17
|
||||
* swizzling.
|
||||
*/
|
||||
} else if ((dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
|
||||
/* Bit 11 swizzling by the CPU in addition. */
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_9_11;
|
||||
} else {
|
||||
/* Bit 17 or perhaps other swizzling */
|
||||
/* Bit 17 swizzling by the CPU in addition. */
|
||||
swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -629,6 +629,22 @@
|
||||
#define TV_HOTPLUG_INT_EN (1 << 18)
|
||||
#define CRT_HOTPLUG_INT_EN (1 << 9)
|
||||
#define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
|
||||
#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8)
|
||||
/* must use period 64 on GM45 according to docs */
|
||||
#define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8)
|
||||
#define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7)
|
||||
#define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7)
|
||||
#define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5)
|
||||
#define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5)
|
||||
#define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5)
|
||||
#define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5)
|
||||
#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5)
|
||||
#define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4)
|
||||
#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4)
|
||||
#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2)
|
||||
#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
|
||||
#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */
|
||||
|
||||
|
||||
#define PORT_HOTPLUG_STAT 0x61114
|
||||
#define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
|
||||
|
||||
@@ -133,20 +133,39 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 temp;
|
||||
u32 hotplug_en;
|
||||
int i, tries = 0;
|
||||
/*
|
||||
* On 4 series desktop, CRT detect sequence need to be done twice
|
||||
* to get a reliable result.
|
||||
*/
|
||||
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
|
||||
if (IS_G4X(dev) && !IS_GM45(dev))
|
||||
tries = 2;
|
||||
else
|
||||
tries = 1;
|
||||
hotplug_en = I915_READ(PORT_HOTPLUG_EN);
|
||||
hotplug_en &= ~(CRT_HOTPLUG_MASK);
|
||||
hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
|
||||
|
||||
temp = I915_READ(PORT_HOTPLUG_EN);
|
||||
if (IS_GM45(dev))
|
||||
hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
|
||||
|
||||
I915_WRITE(PORT_HOTPLUG_EN,
|
||||
temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5));
|
||||
hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
|
||||
|
||||
do {
|
||||
if (!(I915_READ(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT))
|
||||
break;
|
||||
msleep(1);
|
||||
} while (time_after(timeout, jiffies));
|
||||
for (i = 0; i < tries ; i++) {
|
||||
unsigned long timeout;
|
||||
/* turn on the FORCE_DETECT */
|
||||
I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
|
||||
timeout = jiffies + msecs_to_jiffies(1000);
|
||||
/* wait for FORCE_DETECT to go off */
|
||||
do {
|
||||
if (!(I915_READ(PORT_HOTPLUG_EN) &
|
||||
CRT_HOTPLUG_FORCE_DETECT))
|
||||
break;
|
||||
msleep(1);
|
||||
} while (time_after(timeout, jiffies));
|
||||
}
|
||||
|
||||
if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
|
||||
CRT_HOTPLUG_MONITOR_COLOR)
|
||||
|
||||
@@ -1474,13 +1474,21 @@ static void intel_setup_outputs(struct drm_device *dev)
|
||||
|
||||
if (IS_I9XX(dev)) {
|
||||
int found;
|
||||
u32 reg;
|
||||
|
||||
if (I915_READ(SDVOB) & SDVO_DETECTED) {
|
||||
found = intel_sdvo_init(dev, SDVOB);
|
||||
if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
|
||||
intel_hdmi_init(dev, SDVOB);
|
||||
}
|
||||
if (!IS_G4X(dev) || (I915_READ(SDVOB) & SDVO_DETECTED)) {
|
||||
|
||||
/* Before G4X SDVOC doesn't have its own detect register */
|
||||
if (IS_G4X(dev))
|
||||
reg = SDVOC;
|
||||
else
|
||||
reg = SDVOB;
|
||||
|
||||
if (I915_READ(reg) & SDVO_DETECTED) {
|
||||
found = intel_sdvo_init(dev, SDVOC);
|
||||
if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
|
||||
intel_hdmi_init(dev, SDVOC);
|
||||
|
||||
@@ -1558,33 +1558,49 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct intel_output *intel_output = to_intel_output(connector);
|
||||
struct intel_tv_priv *tv_priv = intel_output->dev_priv;
|
||||
struct drm_encoder *encoder = &intel_output->enc;
|
||||
struct drm_crtc *crtc = encoder->crtc;
|
||||
int ret = 0;
|
||||
bool changed = false;
|
||||
|
||||
ret = drm_connector_property_set_value(connector, property, val);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (property == dev->mode_config.tv_left_margin_property)
|
||||
if (property == dev->mode_config.tv_left_margin_property &&
|
||||
tv_priv->margin[TV_MARGIN_LEFT] != val) {
|
||||
tv_priv->margin[TV_MARGIN_LEFT] = val;
|
||||
else if (property == dev->mode_config.tv_right_margin_property)
|
||||
changed = true;
|
||||
} else if (property == dev->mode_config.tv_right_margin_property &&
|
||||
tv_priv->margin[TV_MARGIN_RIGHT] != val) {
|
||||
tv_priv->margin[TV_MARGIN_RIGHT] = val;
|
||||
else if (property == dev->mode_config.tv_top_margin_property)
|
||||
changed = true;
|
||||
} else if (property == dev->mode_config.tv_top_margin_property &&
|
||||
tv_priv->margin[TV_MARGIN_TOP] != val) {
|
||||
tv_priv->margin[TV_MARGIN_TOP] = val;
|
||||
else if (property == dev->mode_config.tv_bottom_margin_property)
|
||||
changed = true;
|
||||
} else if (property == dev->mode_config.tv_bottom_margin_property &&
|
||||
tv_priv->margin[TV_MARGIN_BOTTOM] != val) {
|
||||
tv_priv->margin[TV_MARGIN_BOTTOM] = val;
|
||||
else if (property == dev->mode_config.tv_mode_property) {
|
||||
changed = true;
|
||||
} else if (property == dev->mode_config.tv_mode_property) {
|
||||
if (val >= NUM_TV_MODES) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!strcmp(tv_priv->tv_format, tv_modes[val].name))
|
||||
goto out;
|
||||
|
||||
tv_priv->tv_format = tv_modes[val].name;
|
||||
intel_tv_mode_set(&intel_output->enc, NULL, NULL);
|
||||
changed = true;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
intel_tv_mode_set(&intel_output->enc, NULL, NULL);
|
||||
if (changed && crtc)
|
||||
drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
|
||||
crtc->y, crtc->fb);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -114,6 +114,8 @@
|
||||
* the register setting lists into the table indexed by the clock selected
|
||||
* - set the correct hwif->ultra_mask for each individual chip
|
||||
* - add Ultra and MW DMA mode filtering for the HPT37[24] based SATA cards
|
||||
* - stop resetting HPT370's state machine before each DMA transfer as that has
|
||||
* caused more harm than good
|
||||
* Sergei Shtylyov, <sshtylyov@ru.mvista.com> or <source@mvista.com>
|
||||
*/
|
||||
|
||||
@@ -133,7 +135,7 @@
|
||||
#define DRV_NAME "hpt366"
|
||||
|
||||
/* various tuning parameters */
|
||||
#define HPT_RESET_STATE_ENGINE
|
||||
#undef HPT_RESET_STATE_ENGINE
|
||||
#undef HPT_DELAY_INTERRUPT
|
||||
|
||||
static const char *quirk_drives[] = {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ide.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -566,6 +568,10 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
|
||||
: ide_pc_intr),
|
||||
timeout, expiry);
|
||||
|
||||
/* Send the actual packet */
|
||||
if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)
|
||||
hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
|
||||
|
||||
/* Begin DMA, if necessary */
|
||||
if (dev_is_idecd(drive)) {
|
||||
if (drive->dma)
|
||||
@@ -577,10 +583,6 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
|
||||
}
|
||||
}
|
||||
|
||||
/* Send the actual packet */
|
||||
if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)
|
||||
hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
|
||||
|
||||
return ide_started;
|
||||
}
|
||||
|
||||
|
||||
@@ -736,11 +736,10 @@ repeat:
|
||||
prev_port = hwif->host->cur_port;
|
||||
hwif->rq = NULL;
|
||||
|
||||
if (drive->dev_flags & IDE_DFLAG_SLEEPING) {
|
||||
if (time_before(drive->sleep, jiffies)) {
|
||||
ide_unlock_port(hwif);
|
||||
goto plug_device;
|
||||
}
|
||||
if (drive->dev_flags & IDE_DFLAG_SLEEPING &&
|
||||
time_after(drive->sleep, jiffies)) {
|
||||
ide_unlock_port(hwif);
|
||||
goto plug_device;
|
||||
}
|
||||
|
||||
if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) &&
|
||||
|
||||
@@ -50,9 +50,8 @@ static LIST_HEAD(gameport_list);
|
||||
|
||||
static struct bus_type gameport_bus;
|
||||
|
||||
static void gameport_add_driver(struct gameport_driver *drv);
|
||||
static void gameport_add_port(struct gameport *gameport);
|
||||
static void gameport_destroy_port(struct gameport *gameport);
|
||||
static void gameport_attach_driver(struct gameport_driver *drv);
|
||||
static void gameport_reconnect_port(struct gameport *gameport);
|
||||
static void gameport_disconnect_port(struct gameport *gameport);
|
||||
|
||||
@@ -230,7 +229,6 @@ static void gameport_find_driver(struct gameport *gameport)
|
||||
|
||||
enum gameport_event_type {
|
||||
GAMEPORT_REGISTER_PORT,
|
||||
GAMEPORT_REGISTER_DRIVER,
|
||||
GAMEPORT_ATTACH_DRIVER,
|
||||
};
|
||||
|
||||
@@ -374,8 +372,8 @@ static void gameport_handle_event(void)
|
||||
gameport_add_port(event->object);
|
||||
break;
|
||||
|
||||
case GAMEPORT_REGISTER_DRIVER:
|
||||
gameport_add_driver(event->object);
|
||||
case GAMEPORT_ATTACH_DRIVER:
|
||||
gameport_attach_driver(event->object);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -706,14 +704,14 @@ static int gameport_driver_remove(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gameport_add_driver(struct gameport_driver *drv)
|
||||
static void gameport_attach_driver(struct gameport_driver *drv)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = driver_register(&drv->driver);
|
||||
error = driver_attach(&drv->driver);
|
||||
if (error)
|
||||
printk(KERN_ERR
|
||||
"gameport: driver_register() failed for %s, error: %d\n",
|
||||
"gameport: driver_attach() failed for %s, error: %d\n",
|
||||
drv->driver.name, error);
|
||||
}
|
||||
|
||||
|
||||
@@ -373,8 +373,10 @@ unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr)
|
||||
/* First step: get the top-level Guest page table entry. */
|
||||
gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t);
|
||||
/* Toplevel not present? We can't map it in. */
|
||||
if (!(pgd_flags(gpgd) & _PAGE_PRESENT))
|
||||
if (!(pgd_flags(gpgd) & _PAGE_PRESENT)) {
|
||||
kill_guest(cpu, "Bad address %#lx", vaddr);
|
||||
return -1UL;
|
||||
}
|
||||
|
||||
gpte = lgread(cpu, gpte_addr(gpgd, vaddr), pte_t);
|
||||
if (!(pte_flags(gpte) & _PAGE_PRESENT))
|
||||
|
||||
@@ -16,30 +16,56 @@
|
||||
* functions in this file help the target record and restore the
|
||||
* original bio state.
|
||||
*/
|
||||
|
||||
struct dm_bio_vec_details {
|
||||
#if PAGE_SIZE < 65536
|
||||
__u16 bv_len;
|
||||
__u16 bv_offset;
|
||||
#else
|
||||
unsigned bv_len;
|
||||
unsigned bv_offset;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct dm_bio_details {
|
||||
sector_t bi_sector;
|
||||
struct block_device *bi_bdev;
|
||||
unsigned int bi_size;
|
||||
unsigned short bi_idx;
|
||||
unsigned long bi_flags;
|
||||
struct dm_bio_vec_details bi_io_vec[BIO_MAX_PAGES];
|
||||
};
|
||||
|
||||
static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
bd->bi_sector = bio->bi_sector;
|
||||
bd->bi_bdev = bio->bi_bdev;
|
||||
bd->bi_size = bio->bi_size;
|
||||
bd->bi_idx = bio->bi_idx;
|
||||
bd->bi_flags = bio->bi_flags;
|
||||
|
||||
for (i = 0; i < bio->bi_vcnt; i++) {
|
||||
bd->bi_io_vec[i].bv_len = bio->bi_io_vec[i].bv_len;
|
||||
bd->bi_io_vec[i].bv_offset = bio->bi_io_vec[i].bv_offset;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
bio->bi_sector = bd->bi_sector;
|
||||
bio->bi_bdev = bd->bi_bdev;
|
||||
bio->bi_size = bd->bi_size;
|
||||
bio->bi_idx = bd->bi_idx;
|
||||
bio->bi_flags = bd->bi_flags;
|
||||
|
||||
for (i = 0; i < bio->bi_vcnt; i++) {
|
||||
bio->bi_io_vec[i].bv_len = bd->bi_io_vec[i].bv_len;
|
||||
bio->bi_io_vec[i].bv_offset = bd->bi_io_vec[i].bv_offset;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+1
-4
@@ -370,16 +370,13 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
|
||||
while (1) {
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
|
||||
if (!atomic_read(&io.count) || signal_pending(current))
|
||||
if (!atomic_read(&io.count))
|
||||
break;
|
||||
|
||||
io_schedule();
|
||||
}
|
||||
set_current_state(TASK_RUNNING);
|
||||
|
||||
if (atomic_read(&io.count))
|
||||
return -EINTR;
|
||||
|
||||
if (error_bits)
|
||||
*error_bits = io.error_bits;
|
||||
|
||||
|
||||
+15
-8
@@ -297,7 +297,8 @@ static int run_complete_job(struct kcopyd_job *job)
|
||||
dm_kcopyd_notify_fn fn = job->fn;
|
||||
struct dm_kcopyd_client *kc = job->kc;
|
||||
|
||||
kcopyd_put_pages(kc, job->pages);
|
||||
if (job->pages)
|
||||
kcopyd_put_pages(kc, job->pages);
|
||||
mempool_free(job, kc->job_pool);
|
||||
fn(read_err, write_err, context);
|
||||
|
||||
@@ -461,6 +462,7 @@ static void segment_complete(int read_err, unsigned long write_err,
|
||||
sector_t progress = 0;
|
||||
sector_t count = 0;
|
||||
struct kcopyd_job *job = (struct kcopyd_job *) context;
|
||||
struct dm_kcopyd_client *kc = job->kc;
|
||||
|
||||
mutex_lock(&job->lock);
|
||||
|
||||
@@ -490,7 +492,7 @@ static void segment_complete(int read_err, unsigned long write_err,
|
||||
|
||||
if (count) {
|
||||
int i;
|
||||
struct kcopyd_job *sub_job = mempool_alloc(job->kc->job_pool,
|
||||
struct kcopyd_job *sub_job = mempool_alloc(kc->job_pool,
|
||||
GFP_NOIO);
|
||||
|
||||
*sub_job = *job;
|
||||
@@ -509,13 +511,16 @@ static void segment_complete(int read_err, unsigned long write_err,
|
||||
} else if (atomic_dec_and_test(&job->sub_jobs)) {
|
||||
|
||||
/*
|
||||
* To avoid a race we must keep the job around
|
||||
* until after the notify function has completed.
|
||||
* Otherwise the client may try and stop the job
|
||||
* after we've completed.
|
||||
* Queue the completion callback to the kcopyd thread.
|
||||
*
|
||||
* Some callers assume that all the completions are called
|
||||
* from a single thread and don't race with each other.
|
||||
*
|
||||
* We must not call the callback directly here because this
|
||||
* code may not be executing in the thread.
|
||||
*/
|
||||
job->fn(read_err, write_err, job->context);
|
||||
mempool_free(job, job->kc->job_pool);
|
||||
push(&kc->complete_jobs, job);
|
||||
wake(kc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,6 +533,8 @@ static void split_job(struct kcopyd_job *job)
|
||||
{
|
||||
int i;
|
||||
|
||||
atomic_inc(&job->kc->nr_jobs);
|
||||
|
||||
atomic_set(&job->sub_jobs, SPLIT_COUNT);
|
||||
for (i = 0; i < SPLIT_COUNT; i++)
|
||||
segment_complete(0, 0u, job);
|
||||
|
||||
@@ -17,9 +17,7 @@
|
||||
|
||||
struct ps_internal {
|
||||
struct path_selector_type pst;
|
||||
|
||||
struct list_head list;
|
||||
long use;
|
||||
};
|
||||
|
||||
#define pst_to_psi(__pst) container_of((__pst), struct ps_internal, pst)
|
||||
@@ -45,12 +43,8 @@ static struct ps_internal *get_path_selector(const char *name)
|
||||
|
||||
down_read(&_ps_lock);
|
||||
psi = __find_path_selector_type(name);
|
||||
if (psi) {
|
||||
if ((psi->use == 0) && !try_module_get(psi->pst.module))
|
||||
psi = NULL;
|
||||
else
|
||||
psi->use++;
|
||||
}
|
||||
if (psi && !try_module_get(psi->pst.module))
|
||||
psi = NULL;
|
||||
up_read(&_ps_lock);
|
||||
|
||||
return psi;
|
||||
@@ -84,11 +78,7 @@ void dm_put_path_selector(struct path_selector_type *pst)
|
||||
if (!psi)
|
||||
goto out;
|
||||
|
||||
if (--psi->use == 0)
|
||||
module_put(psi->pst.module);
|
||||
|
||||
BUG_ON(psi->use < 0);
|
||||
|
||||
module_put(psi->pst.module);
|
||||
out:
|
||||
up_read(&_ps_lock);
|
||||
}
|
||||
@@ -136,11 +126,6 @@ int dm_unregister_path_selector(struct path_selector_type *pst)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (psi->use) {
|
||||
up_write(&_ps_lock);
|
||||
return -ETXTBSY;
|
||||
}
|
||||
|
||||
list_del(&psi->list);
|
||||
|
||||
up_write(&_ps_lock);
|
||||
|
||||
+23
-6
@@ -145,6 +145,8 @@ struct dm_raid1_read_record {
|
||||
struct dm_bio_details details;
|
||||
};
|
||||
|
||||
static struct kmem_cache *_dm_raid1_read_record_cache;
|
||||
|
||||
/*
|
||||
* Every mirror should look like this one.
|
||||
*/
|
||||
@@ -764,9 +766,9 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
|
||||
atomic_set(&ms->suspend, 0);
|
||||
atomic_set(&ms->default_mirror, DEFAULT_MIRROR);
|
||||
|
||||
len = sizeof(struct dm_raid1_read_record);
|
||||
ms->read_record_pool = mempool_create_kmalloc_pool(MIN_READ_RECORDS,
|
||||
len);
|
||||
ms->read_record_pool = mempool_create_slab_pool(MIN_READ_RECORDS,
|
||||
_dm_raid1_read_record_cache);
|
||||
|
||||
if (!ms->read_record_pool) {
|
||||
ti->error = "Error creating mirror read_record_pool";
|
||||
kfree(ms);
|
||||
@@ -1279,16 +1281,31 @@ static int __init dm_mirror_init(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = dm_register_target(&mirror_target);
|
||||
if (r < 0)
|
||||
DMERR("Failed to register mirror target");
|
||||
_dm_raid1_read_record_cache = KMEM_CACHE(dm_raid1_read_record, 0);
|
||||
if (!_dm_raid1_read_record_cache) {
|
||||
DMERR("Can't allocate dm_raid1_read_record cache");
|
||||
r = -ENOMEM;
|
||||
goto bad_cache;
|
||||
}
|
||||
|
||||
r = dm_register_target(&mirror_target);
|
||||
if (r < 0) {
|
||||
DMERR("Failed to register mirror target");
|
||||
goto bad_target;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
bad_target:
|
||||
kmem_cache_destroy(_dm_raid1_read_record_cache);
|
||||
bad_cache:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void __exit dm_mirror_exit(void)
|
||||
{
|
||||
dm_unregister_target(&mirror_target);
|
||||
kmem_cache_destroy(_dm_raid1_read_record_cache);
|
||||
}
|
||||
|
||||
/* Module hooks */
|
||||
|
||||
+62
-39
@@ -972,6 +972,17 @@ static void start_copy(struct dm_snap_pending_exception *pe)
|
||||
&src, 1, &dest, 0, copy_callback, pe);
|
||||
}
|
||||
|
||||
static struct dm_snap_pending_exception *
|
||||
__lookup_pending_exception(struct dm_snapshot *s, chunk_t chunk)
|
||||
{
|
||||
struct dm_snap_exception *e = lookup_exception(&s->pending, chunk);
|
||||
|
||||
if (!e)
|
||||
return NULL;
|
||||
|
||||
return container_of(e, struct dm_snap_pending_exception, e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Looks to see if this snapshot already has a pending exception
|
||||
* for this chunk, otherwise it allocates a new one and inserts
|
||||
@@ -981,40 +992,15 @@ static void start_copy(struct dm_snap_pending_exception *pe)
|
||||
* this.
|
||||
*/
|
||||
static struct dm_snap_pending_exception *
|
||||
__find_pending_exception(struct dm_snapshot *s, struct bio *bio)
|
||||
__find_pending_exception(struct dm_snapshot *s,
|
||||
struct dm_snap_pending_exception *pe, chunk_t chunk)
|
||||
{
|
||||
struct dm_snap_exception *e;
|
||||
struct dm_snap_pending_exception *pe;
|
||||
chunk_t chunk = sector_to_chunk(s, bio->bi_sector);
|
||||
struct dm_snap_pending_exception *pe2;
|
||||
|
||||
/*
|
||||
* Is there a pending exception for this already ?
|
||||
*/
|
||||
e = lookup_exception(&s->pending, chunk);
|
||||
if (e) {
|
||||
/* cast the exception to a pending exception */
|
||||
pe = container_of(e, struct dm_snap_pending_exception, e);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new pending exception, we don't want
|
||||
* to hold the lock while we do this.
|
||||
*/
|
||||
up_write(&s->lock);
|
||||
pe = alloc_pending_exception(s);
|
||||
down_write(&s->lock);
|
||||
|
||||
if (!s->valid) {
|
||||
pe2 = __lookup_pending_exception(s, chunk);
|
||||
if (pe2) {
|
||||
free_pending_exception(pe);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
e = lookup_exception(&s->pending, chunk);
|
||||
if (e) {
|
||||
free_pending_exception(pe);
|
||||
pe = container_of(e, struct dm_snap_pending_exception, e);
|
||||
goto out;
|
||||
return pe2;
|
||||
}
|
||||
|
||||
pe->e.old_chunk = chunk;
|
||||
@@ -1032,7 +1018,6 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
|
||||
get_pending_exception(pe);
|
||||
insert_exception(&s->pending, &pe->e);
|
||||
|
||||
out:
|
||||
return pe;
|
||||
}
|
||||
|
||||
@@ -1083,11 +1068,31 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
|
||||
* writeable.
|
||||
*/
|
||||
if (bio_rw(bio) == WRITE) {
|
||||
pe = __find_pending_exception(s, bio);
|
||||
pe = __lookup_pending_exception(s, chunk);
|
||||
if (!pe) {
|
||||
__invalidate_snapshot(s, -ENOMEM);
|
||||
r = -EIO;
|
||||
goto out_unlock;
|
||||
up_write(&s->lock);
|
||||
pe = alloc_pending_exception(s);
|
||||
down_write(&s->lock);
|
||||
|
||||
if (!s->valid) {
|
||||
free_pending_exception(pe);
|
||||
r = -EIO;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
e = lookup_exception(&s->complete, chunk);
|
||||
if (e) {
|
||||
free_pending_exception(pe);
|
||||
remap_exception(s, e, bio, chunk);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
pe = __find_pending_exception(s, pe, chunk);
|
||||
if (!pe) {
|
||||
__invalidate_snapshot(s, -ENOMEM);
|
||||
r = -EIO;
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
remap_exception(s, &pe->e, bio, chunk);
|
||||
@@ -1217,10 +1222,28 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio)
|
||||
if (e)
|
||||
goto next_snapshot;
|
||||
|
||||
pe = __find_pending_exception(snap, bio);
|
||||
pe = __lookup_pending_exception(snap, chunk);
|
||||
if (!pe) {
|
||||
__invalidate_snapshot(snap, -ENOMEM);
|
||||
goto next_snapshot;
|
||||
up_write(&snap->lock);
|
||||
pe = alloc_pending_exception(snap);
|
||||
down_write(&snap->lock);
|
||||
|
||||
if (!snap->valid) {
|
||||
free_pending_exception(pe);
|
||||
goto next_snapshot;
|
||||
}
|
||||
|
||||
e = lookup_exception(&snap->complete, chunk);
|
||||
if (e) {
|
||||
free_pending_exception(pe);
|
||||
goto next_snapshot;
|
||||
}
|
||||
|
||||
pe = __find_pending_exception(snap, pe, chunk);
|
||||
if (!pe) {
|
||||
__invalidate_snapshot(snap, -ENOMEM);
|
||||
goto next_snapshot;
|
||||
}
|
||||
}
|
||||
|
||||
if (!primary_pe) {
|
||||
|
||||
+14
-12
@@ -399,28 +399,30 @@ static int check_device_area(struct dm_dev_internal *dd, sector_t start,
|
||||
}
|
||||
|
||||
/*
|
||||
* This upgrades the mode on an already open dm_dev. Being
|
||||
* This upgrades the mode on an already open dm_dev, being
|
||||
* careful to leave things as they were if we fail to reopen the
|
||||
* device.
|
||||
* device and not to touch the existing bdev field in case
|
||||
* it is accessed concurrently inside dm_table_any_congested().
|
||||
*/
|
||||
static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode,
|
||||
struct mapped_device *md)
|
||||
{
|
||||
int r;
|
||||
struct dm_dev_internal dd_copy;
|
||||
dev_t dev = dd->dm_dev.bdev->bd_dev;
|
||||
struct dm_dev_internal dd_new, dd_old;
|
||||
|
||||
dd_copy = *dd;
|
||||
dd_new = dd_old = *dd;
|
||||
|
||||
dd_new.dm_dev.mode |= new_mode;
|
||||
dd_new.dm_dev.bdev = NULL;
|
||||
|
||||
r = open_dev(&dd_new, dd->dm_dev.bdev->bd_dev, md);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dd->dm_dev.mode |= new_mode;
|
||||
dd->dm_dev.bdev = NULL;
|
||||
r = open_dev(dd, dev, md);
|
||||
if (!r)
|
||||
close_dev(&dd_copy, md);
|
||||
else
|
||||
*dd = dd_copy;
|
||||
close_dev(&dd_old, md);
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+3
-17
@@ -18,7 +18,6 @@ struct tt_internal {
|
||||
struct target_type tt;
|
||||
|
||||
struct list_head list;
|
||||
long use;
|
||||
};
|
||||
|
||||
static LIST_HEAD(_targets);
|
||||
@@ -44,12 +43,8 @@ static struct tt_internal *get_target_type(const char *name)
|
||||
down_read(&_lock);
|
||||
|
||||
ti = __find_target_type(name);
|
||||
if (ti) {
|
||||
if ((ti->use == 0) && !try_module_get(ti->tt.module))
|
||||
ti = NULL;
|
||||
else
|
||||
ti->use++;
|
||||
}
|
||||
if (ti && !try_module_get(ti->tt.module))
|
||||
ti = NULL;
|
||||
|
||||
up_read(&_lock);
|
||||
return ti;
|
||||
@@ -77,10 +72,7 @@ void dm_put_target_type(struct target_type *t)
|
||||
struct tt_internal *ti = (struct tt_internal *) t;
|
||||
|
||||
down_read(&_lock);
|
||||
if (--ti->use == 0)
|
||||
module_put(ti->tt.module);
|
||||
|
||||
BUG_ON(ti->use < 0);
|
||||
module_put(ti->tt.module);
|
||||
up_read(&_lock);
|
||||
|
||||
return;
|
||||
@@ -140,12 +132,6 @@ void dm_unregister_target(struct target_type *t)
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (ti->use) {
|
||||
DMCRIT("Attempt to unregister target still in use: %s",
|
||||
t->name);
|
||||
BUG();
|
||||
}
|
||||
|
||||
list_del(&ti->list);
|
||||
kfree(ti);
|
||||
|
||||
|
||||
+4
-3
@@ -120,6 +120,7 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
|
||||
goto out_free_pages;
|
||||
|
||||
bio->bi_io_vec[i].bv_page = page;
|
||||
bio->bi_vcnt = i+1;
|
||||
}
|
||||
}
|
||||
/* If not user-requests, copy the page pointers to all bios */
|
||||
@@ -135,9 +136,9 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
|
||||
return r1_bio;
|
||||
|
||||
out_free_pages:
|
||||
for (i=0; i < RESYNC_PAGES ; i++)
|
||||
for (j=0 ; j < pi->raid_disks; j++)
|
||||
safe_put_page(r1_bio->bios[j]->bi_io_vec[i].bv_page);
|
||||
for (j=0 ; j < pi->raid_disks; j++)
|
||||
for (i=0; i < r1_bio->bios[j]->bi_vcnt ; i++)
|
||||
put_page(r1_bio->bios[j]->bi_io_vec[i].bv_page);
|
||||
j = -1;
|
||||
out_free_bio:
|
||||
while ( ++j < pi->raid_disks )
|
||||
|
||||
@@ -135,6 +135,7 @@ static const char *debug_fcp_opcode(unsigned int opcode,
|
||||
case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL: return "RegisterRC";
|
||||
case SFE_VENDOR_OPCODE_LNB_CONTROL: return "LNBControl";
|
||||
case SFE_VENDOR_OPCODE_TUNE_QPSK: return "TuneQPSK";
|
||||
case SFE_VENDOR_OPCODE_TUNE_QPSK2: return "TuneQPSK2";
|
||||
case SFE_VENDOR_OPCODE_HOST2CA: return "Host2CA";
|
||||
case SFE_VENDOR_OPCODE_CA2HOST: return "CA2Host";
|
||||
}
|
||||
@@ -266,7 +267,10 @@ static void avc_tuner_tuneqpsk(struct firedtv *fdtv,
|
||||
c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
|
||||
c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
|
||||
c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
|
||||
c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
|
||||
if (fdtv->type == FIREDTV_DVB_S2)
|
||||
c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK2;
|
||||
else
|
||||
c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
|
||||
|
||||
c->operand[4] = (params->frequency >> 24) & 0xff;
|
||||
c->operand[5] = (params->frequency >> 16) & 0xff;
|
||||
|
||||
@@ -48,8 +48,7 @@ struct cx88_IR {
|
||||
|
||||
/* poll external decoder */
|
||||
int polling;
|
||||
struct work_struct work;
|
||||
struct timer_list timer;
|
||||
struct delayed_work work;
|
||||
u32 gpio_addr;
|
||||
u32 last_gpio;
|
||||
u32 mask_keycode;
|
||||
@@ -143,27 +142,19 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
|
||||
}
|
||||
}
|
||||
|
||||
static void ir_timer(unsigned long data)
|
||||
{
|
||||
struct cx88_IR *ir = (struct cx88_IR *)data;
|
||||
|
||||
schedule_work(&ir->work);
|
||||
}
|
||||
|
||||
static void cx88_ir_work(struct work_struct *work)
|
||||
{
|
||||
struct cx88_IR *ir = container_of(work, struct cx88_IR, work);
|
||||
struct cx88_IR *ir = container_of(work, struct cx88_IR, work.work);
|
||||
|
||||
cx88_ir_handle_key(ir);
|
||||
mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
|
||||
schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
|
||||
}
|
||||
|
||||
void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir)
|
||||
{
|
||||
if (ir->polling) {
|
||||
setup_timer(&ir->timer, ir_timer, (unsigned long)ir);
|
||||
INIT_WORK(&ir->work, cx88_ir_work);
|
||||
schedule_work(&ir->work);
|
||||
INIT_DELAYED_WORK(&ir->work, cx88_ir_work);
|
||||
schedule_delayed_work(&ir->work, 0);
|
||||
}
|
||||
if (ir->sampling) {
|
||||
core->pci_irqmask |= PCI_INT_IR_SMPINT;
|
||||
@@ -179,10 +170,8 @@ void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir)
|
||||
core->pci_irqmask &= ~PCI_INT_IR_SMPINT;
|
||||
}
|
||||
|
||||
if (ir->polling) {
|
||||
del_timer_sync(&ir->timer);
|
||||
flush_scheduled_work();
|
||||
}
|
||||
if (ir->polling)
|
||||
cancel_delayed_work_sync(&ir->work);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
@@ -910,10 +910,10 @@ struct v4l2_subdev *v4l2_i2c_new_subdev(struct i2c_adapter *adapter,
|
||||
struct i2c_board_info info;
|
||||
|
||||
BUG_ON(!dev);
|
||||
#ifdef MODULE
|
||||
|
||||
if (module_name)
|
||||
request_module(module_name);
|
||||
#endif
|
||||
|
||||
/* Setup the i2c board info with the device type and
|
||||
the device address. */
|
||||
memset(&info, 0, sizeof(info));
|
||||
@@ -958,10 +958,10 @@ struct v4l2_subdev *v4l2_i2c_new_probed_subdev(struct i2c_adapter *adapter,
|
||||
struct i2c_board_info info;
|
||||
|
||||
BUG_ON(!dev);
|
||||
#ifdef MODULE
|
||||
|
||||
if (module_name)
|
||||
request_module(module_name);
|
||||
#endif
|
||||
|
||||
/* Setup the i2c board info with the device type and
|
||||
the device address. */
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
@@ -5934,7 +5934,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
|
||||
|
||||
/* Initalize the timer
|
||||
*/
|
||||
init_timer(&pCfg->timer);
|
||||
init_timer_on_stack(&pCfg->timer);
|
||||
pCfg->timer.data = (unsigned long) ioc;
|
||||
pCfg->timer.function = mpt_timer_expired;
|
||||
pCfg->wait_done = 0;
|
||||
|
||||
@@ -2565,7 +2565,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
|
||||
|
||||
for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
|
||||
if (!targets[i])
|
||||
continue;
|
||||
break;
|
||||
pr_debug("basa: target %x\n", targets[i]);
|
||||
if (list_empty(&bond->vlan_list)) {
|
||||
pr_debug("basa: empty vlan: arp_send\n");
|
||||
@@ -2672,7 +2672,6 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32
|
||||
int i;
|
||||
__be32 *targets = bond->params.arp_targets;
|
||||
|
||||
targets = bond->params.arp_targets;
|
||||
for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
|
||||
pr_debug("bva: sip %pI4 tip %pI4 t[%d] %pI4 bhti(tip) %d\n",
|
||||
&sip, &tip, i, &targets[i], bond_has_this_ip(bond, tip));
|
||||
@@ -3294,7 +3293,7 @@ static void bond_info_show_master(struct seq_file *seq)
|
||||
|
||||
for(i = 0; (i < BOND_MAX_ARP_TARGETS) ;i++) {
|
||||
if (!bond->params.arp_targets[i])
|
||||
continue;
|
||||
break;
|
||||
if (printed)
|
||||
seq_printf(seq, ",");
|
||||
seq_printf(seq, " %pI4", &bond->params.arp_targets[i]);
|
||||
|
||||
@@ -684,17 +684,15 @@ static ssize_t bonding_store_arp_targets(struct device *d,
|
||||
goto out;
|
||||
}
|
||||
/* look for an empty slot to put the target in, and check for dupes */
|
||||
for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
|
||||
for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) {
|
||||
if (targets[i] == newtarget) { /* duplicate */
|
||||
printk(KERN_ERR DRV_NAME
|
||||
": %s: ARP target %pI4 is already present\n",
|
||||
bond->dev->name, &newtarget);
|
||||
if (done)
|
||||
targets[i] = 0;
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (targets[i] == 0 && !done) {
|
||||
if (targets[i] == 0) {
|
||||
printk(KERN_INFO DRV_NAME
|
||||
": %s: adding ARP target %pI4.\n",
|
||||
bond->dev->name, &newtarget);
|
||||
@@ -720,12 +718,16 @@ static ssize_t bonding_store_arp_targets(struct device *d,
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
|
||||
for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) {
|
||||
if (targets[i] == newtarget) {
|
||||
int j;
|
||||
printk(KERN_INFO DRV_NAME
|
||||
": %s: removing ARP target %pI4.\n",
|
||||
bond->dev->name, &newtarget);
|
||||
targets[i] = 0;
|
||||
for (j = i; (j < (BOND_MAX_ARP_TARGETS-1)) && targets[j+1]; j++)
|
||||
targets[j] = targets[j+1];
|
||||
|
||||
targets[j] = 0;
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/version.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
@@ -691,9 +691,10 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
|
||||
struct ethtool_ringparam *ring)
|
||||
{
|
||||
struct ixgbe_adapter *adapter = netdev_priv(netdev);
|
||||
struct ixgbe_ring *temp_ring;
|
||||
struct ixgbe_ring *temp_tx_ring, *temp_rx_ring;
|
||||
int i, err;
|
||||
u32 new_rx_count, new_tx_count;
|
||||
bool need_update = false;
|
||||
|
||||
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
|
||||
return -EINVAL;
|
||||
@@ -712,80 +713,94 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
temp_ring = kcalloc(adapter->num_tx_queues,
|
||||
sizeof(struct ixgbe_ring), GFP_KERNEL);
|
||||
if (!temp_ring)
|
||||
return -ENOMEM;
|
||||
|
||||
while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
|
||||
msleep(1);
|
||||
|
||||
if (new_tx_count != adapter->tx_ring->count) {
|
||||
temp_tx_ring = kcalloc(adapter->num_tx_queues,
|
||||
sizeof(struct ixgbe_ring), GFP_KERNEL);
|
||||
if (!temp_tx_ring) {
|
||||
err = -ENOMEM;
|
||||
goto err_setup;
|
||||
}
|
||||
|
||||
if (new_tx_count != adapter->tx_ring_count) {
|
||||
memcpy(temp_tx_ring, adapter->tx_ring,
|
||||
adapter->num_tx_queues * sizeof(struct ixgbe_ring));
|
||||
for (i = 0; i < adapter->num_tx_queues; i++) {
|
||||
temp_ring[i].count = new_tx_count;
|
||||
err = ixgbe_setup_tx_resources(adapter, &temp_ring[i]);
|
||||
temp_tx_ring[i].count = new_tx_count;
|
||||
err = ixgbe_setup_tx_resources(adapter,
|
||||
&temp_tx_ring[i]);
|
||||
if (err) {
|
||||
while (i) {
|
||||
i--;
|
||||
ixgbe_free_tx_resources(adapter,
|
||||
&temp_ring[i]);
|
||||
&temp_tx_ring[i]);
|
||||
}
|
||||
goto err_setup;
|
||||
}
|
||||
temp_ring[i].v_idx = adapter->tx_ring[i].v_idx;
|
||||
temp_tx_ring[i].v_idx = adapter->tx_ring[i].v_idx;
|
||||
}
|
||||
if (netif_running(netdev))
|
||||
netdev->netdev_ops->ndo_stop(netdev);
|
||||
ixgbe_reset_interrupt_capability(adapter);
|
||||
ixgbe_napi_del_all(adapter);
|
||||
INIT_LIST_HEAD(&netdev->napi_list);
|
||||
kfree(adapter->tx_ring);
|
||||
adapter->tx_ring = temp_ring;
|
||||
temp_ring = NULL;
|
||||
adapter->tx_ring_count = new_tx_count;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
temp_ring = kcalloc(adapter->num_rx_queues,
|
||||
sizeof(struct ixgbe_ring), GFP_KERNEL);
|
||||
if (!temp_ring) {
|
||||
if (netif_running(netdev))
|
||||
netdev->netdev_ops->ndo_open(netdev);
|
||||
return -ENOMEM;
|
||||
temp_rx_ring = kcalloc(adapter->num_rx_queues,
|
||||
sizeof(struct ixgbe_ring), GFP_KERNEL);
|
||||
if ((!temp_rx_ring) && (need_update)) {
|
||||
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||
ixgbe_free_tx_resources(adapter, &temp_tx_ring[i]);
|
||||
kfree(temp_tx_ring);
|
||||
err = -ENOMEM;
|
||||
goto err_setup;
|
||||
}
|
||||
|
||||
if (new_rx_count != adapter->rx_ring->count) {
|
||||
if (new_rx_count != adapter->rx_ring_count) {
|
||||
memcpy(temp_rx_ring, adapter->rx_ring,
|
||||
adapter->num_rx_queues * sizeof(struct ixgbe_ring));
|
||||
for (i = 0; i < adapter->num_rx_queues; i++) {
|
||||
temp_ring[i].count = new_rx_count;
|
||||
err = ixgbe_setup_rx_resources(adapter, &temp_ring[i]);
|
||||
temp_rx_ring[i].count = new_rx_count;
|
||||
err = ixgbe_setup_rx_resources(adapter,
|
||||
&temp_rx_ring[i]);
|
||||
if (err) {
|
||||
while (i) {
|
||||
i--;
|
||||
ixgbe_free_rx_resources(adapter,
|
||||
&temp_ring[i]);
|
||||
&temp_rx_ring[i]);
|
||||
}
|
||||
goto err_setup;
|
||||
}
|
||||
temp_ring[i].v_idx = adapter->rx_ring[i].v_idx;
|
||||
temp_rx_ring[i].v_idx = adapter->rx_ring[i].v_idx;
|
||||
}
|
||||
if (netif_running(netdev))
|
||||
netdev->netdev_ops->ndo_stop(netdev);
|
||||
ixgbe_reset_interrupt_capability(adapter);
|
||||
ixgbe_napi_del_all(adapter);
|
||||
INIT_LIST_HEAD(&netdev->napi_list);
|
||||
kfree(adapter->rx_ring);
|
||||
adapter->rx_ring = temp_ring;
|
||||
temp_ring = NULL;
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
adapter->rx_ring_count = new_rx_count;
|
||||
/* if rings need to be updated, here's the place to do it in one shot */
|
||||
if (need_update) {
|
||||
if (netif_running(netdev))
|
||||
ixgbe_down(adapter);
|
||||
|
||||
/* tx */
|
||||
if (new_tx_count != adapter->tx_ring_count) {
|
||||
kfree(adapter->tx_ring);
|
||||
adapter->tx_ring = temp_tx_ring;
|
||||
temp_tx_ring = NULL;
|
||||
adapter->tx_ring_count = new_tx_count;
|
||||
}
|
||||
|
||||
/* rx */
|
||||
if (new_rx_count != adapter->rx_ring_count) {
|
||||
kfree(adapter->rx_ring);
|
||||
adapter->rx_ring = temp_rx_ring;
|
||||
temp_rx_ring = NULL;
|
||||
adapter->rx_ring_count = new_rx_count;
|
||||
}
|
||||
}
|
||||
|
||||
/* success! */
|
||||
err = 0;
|
||||
err_setup:
|
||||
ixgbe_init_interrupt_scheme(adapter);
|
||||
if (netif_running(netdev))
|
||||
netdev->netdev_ops->ndo_open(netdev);
|
||||
ixgbe_up(adapter);
|
||||
|
||||
err_setup:
|
||||
clear_bit(__IXGBE_RESETTING, &adapter->state);
|
||||
return err;
|
||||
}
|
||||
|
||||
+3
-2
@@ -2075,8 +2075,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (!tp->pcie_cap && netif_msg_probe(tp))
|
||||
dev_info(&pdev->dev, "no PCI Express capability\n");
|
||||
|
||||
/* Unneeded ? Don't mess with Mrs. Murphy. */
|
||||
rtl8169_irq_mask_and_ack(ioaddr);
|
||||
RTL_W16(IntrMask, 0x0000);
|
||||
|
||||
/* Soft reset the chip. */
|
||||
RTL_W8(ChipCmd, CmdReset);
|
||||
@@ -2088,6 +2087,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
msleep_interruptible(1);
|
||||
}
|
||||
|
||||
RTL_W16(IntrStatus, 0xffff);
|
||||
|
||||
/* Identify chip attached to board */
|
||||
rtl8169_get_mac_version(tp, ioaddr);
|
||||
|
||||
|
||||
@@ -424,10 +424,6 @@ static void efx_start_channel(struct efx_channel *channel)
|
||||
|
||||
EFX_LOG(channel->efx, "starting chan %d\n", channel->channel);
|
||||
|
||||
if (!(channel->efx->net_dev->flags & IFF_UP))
|
||||
netif_napi_add(channel->napi_dev, &channel->napi_str,
|
||||
efx_poll, napi_weight);
|
||||
|
||||
/* The interrupt handler for this channel may set work_pending
|
||||
* as soon as we enable it. Make sure it's cleared before
|
||||
* then. Similarly, make sure it sees the enabled flag set. */
|
||||
@@ -1273,6 +1269,8 @@ static int efx_init_napi(struct efx_nic *efx)
|
||||
|
||||
efx_for_each_channel(channel, efx) {
|
||||
channel->napi_dev = efx->net_dev;
|
||||
netif_napi_add(channel->napi_dev, &channel->napi_str,
|
||||
efx_poll, napi_weight);
|
||||
rc = efx_lro_init(&channel->lro_mgr, efx);
|
||||
if (rc)
|
||||
goto err;
|
||||
@@ -1289,6 +1287,8 @@ static void efx_fini_napi(struct efx_nic *efx)
|
||||
|
||||
efx_for_each_channel(channel, efx) {
|
||||
efx_lro_fini(&channel->lro_mgr);
|
||||
if (channel->napi_dev)
|
||||
netif_napi_del(&channel->napi_str);
|
||||
channel->napi_dev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -2674,7 +2674,7 @@ static int skge_down(struct net_device *dev)
|
||||
if (netif_msg_ifdown(skge))
|
||||
printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
|
||||
|
||||
netif_stop_queue(dev);
|
||||
netif_tx_disable(dev);
|
||||
|
||||
if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
|
||||
del_timer_sync(&skge->link_timer);
|
||||
@@ -2881,7 +2881,6 @@ static void skge_tx_clean(struct net_device *dev)
|
||||
}
|
||||
|
||||
skge->tx_ring.to_clean = e;
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
static void skge_tx_timeout(struct net_device *dev)
|
||||
@@ -2893,6 +2892,7 @@ static void skge_tx_timeout(struct net_device *dev)
|
||||
|
||||
skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_STOP);
|
||||
skge_tx_clean(dev);
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
static int skge_change_mtu(struct net_device *dev, int new_mtu)
|
||||
|
||||
@@ -1090,8 +1090,18 @@ ath5k_mode_setup(struct ath5k_softc *sc)
|
||||
static inline int
|
||||
ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
|
||||
{
|
||||
WARN_ON(hw_rix < 0 || hw_rix > AR5K_MAX_RATES);
|
||||
return sc->rate_idx[sc->curband->band][hw_rix];
|
||||
int rix;
|
||||
|
||||
/* return base rate on errors */
|
||||
if (WARN(hw_rix < 0 || hw_rix >= AR5K_MAX_RATES,
|
||||
"hw_rix out of bounds: %x\n", hw_rix))
|
||||
return 0;
|
||||
|
||||
rix = sc->rate_idx[sc->curband->band][hw_rix];
|
||||
if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix))
|
||||
rix = 0;
|
||||
|
||||
return rix;
|
||||
}
|
||||
|
||||
/***************\
|
||||
@@ -1668,7 +1678,6 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ath5k_tasklet_rx(unsigned long data)
|
||||
{
|
||||
@@ -2188,6 +2197,7 @@ static void
|
||||
ath5k_beacon_config(struct ath5k_softc *sc)
|
||||
{
|
||||
struct ath5k_hw *ah = sc->ah;
|
||||
unsigned long flags;
|
||||
|
||||
ath5k_hw_set_imr(ah, 0);
|
||||
sc->bmisscount = 0;
|
||||
@@ -2211,9 +2221,9 @@ ath5k_beacon_config(struct ath5k_softc *sc)
|
||||
|
||||
if (sc->opmode == NL80211_IFTYPE_ADHOC) {
|
||||
if (ath5k_hw_hasveol(ah)) {
|
||||
spin_lock(&sc->block);
|
||||
spin_lock_irqsave(&sc->block, flags);
|
||||
ath5k_beacon_send(sc);
|
||||
spin_unlock(&sc->block);
|
||||
spin_unlock_irqrestore(&sc->block, flags);
|
||||
}
|
||||
} else
|
||||
ath5k_beacon_update_timers(sc, -1);
|
||||
@@ -2259,7 +2269,7 @@ ath5k_init(struct ath5k_softc *sc, bool is_resume)
|
||||
sc->curband = &sc->sbands[sc->curchan->band];
|
||||
sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
|
||||
AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
|
||||
AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
|
||||
AR5K_INT_FATAL | AR5K_INT_GLOBAL;
|
||||
ret = ath5k_reset(sc, false, false);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
@@ -112,7 +112,7 @@ struct ath5k_softc {
|
||||
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
|
||||
struct ieee80211_channel channels[ATH_CHAN_MAX];
|
||||
struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
|
||||
u8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
|
||||
s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES];
|
||||
enum nl80211_iftype opmode;
|
||||
struct ath5k_hw *ah; /* Atheros HW */
|
||||
|
||||
|
||||
@@ -322,8 +322,13 @@ void ath_rx_cleanup(struct ath_softc *sc)
|
||||
|
||||
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
|
||||
skb = bf->bf_mpdu;
|
||||
if (skb)
|
||||
if (skb) {
|
||||
pci_unmap_single(sc->pdev,
|
||||
bf->bf_buf_addr,
|
||||
sc->rx.bufsize,
|
||||
DMA_FROM_DEVICE);
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
if (sc->rx.rxdma.dd_desc_len != 0)
|
||||
|
||||
@@ -2035,7 +2035,7 @@ struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
|
||||
|
||||
/* Try to avoid running out of descriptors */
|
||||
if (txq->axq_depth >= (ATH_TXBUF - 20)) {
|
||||
DPRINTF(sc, ATH_DBG_FATAL,
|
||||
DPRINTF(sc, ATH_DBG_XMIT,
|
||||
"TX queue: %d is full, depth: %d\n",
|
||||
qnum, txq->axq_depth);
|
||||
ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb));
|
||||
|
||||
@@ -50,7 +50,7 @@ static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
|
||||
}
|
||||
|
||||
/* Extract the bitrate index out of an OFDM PLCP header. */
|
||||
static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
|
||||
static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
|
||||
{
|
||||
int base = aphy ? 0 : 4;
|
||||
|
||||
|
||||
@@ -687,8 +687,7 @@ struct rt2x00_dev {
|
||||
*/
|
||||
#ifdef CONFIG_RT2X00_LIB_RFKILL
|
||||
unsigned long rfkill_state;
|
||||
#define RFKILL_STATE_ALLOCATED 1
|
||||
#define RFKILL_STATE_REGISTERED 2
|
||||
#define RFKILL_STATE_REGISTERED 1
|
||||
struct rfkill *rfkill;
|
||||
struct delayed_work rfkill_work;
|
||||
#endif /* CONFIG_RT2X00_LIB_RFKILL */
|
||||
|
||||
@@ -1105,7 +1105,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
|
||||
* Register extra components.
|
||||
*/
|
||||
rt2x00leds_register(rt2x00dev);
|
||||
rt2x00rfkill_allocate(rt2x00dev);
|
||||
rt2x00debug_register(rt2x00dev);
|
||||
|
||||
set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
|
||||
@@ -1137,7 +1136,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
|
||||
* Free extra components
|
||||
*/
|
||||
rt2x00debug_deregister(rt2x00dev);
|
||||
rt2x00rfkill_free(rt2x00dev);
|
||||
rt2x00leds_unregister(rt2x00dev);
|
||||
|
||||
/*
|
||||
|
||||
@@ -260,8 +260,6 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
|
||||
#ifdef CONFIG_RT2X00_LIB_RFKILL
|
||||
void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev);
|
||||
#else
|
||||
static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
@@ -270,14 +268,6 @@ static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
|
||||
static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_RT2X00_LIB_RFKILL */
|
||||
|
||||
/*
|
||||
|
||||
@@ -94,54 +94,13 @@ static void rt2x00rfkill_poll(struct work_struct *work)
|
||||
&rt2x00dev->rfkill_work, RFKILL_POLL_INTERVAL);
|
||||
}
|
||||
|
||||
void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state) ||
|
||||
test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
|
||||
return;
|
||||
|
||||
if (rfkill_register(rt2x00dev->rfkill)) {
|
||||
ERROR(rt2x00dev, "Failed to register rfkill handler.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
__set_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state);
|
||||
|
||||
/*
|
||||
* Force initial poll which will detect the initial device state,
|
||||
* and correctly sends the signal to the rfkill layer about this
|
||||
* state.
|
||||
*/
|
||||
rt2x00rfkill_poll(&rt2x00dev->rfkill_work.work);
|
||||
}
|
||||
|
||||
void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state) ||
|
||||
!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
|
||||
return;
|
||||
|
||||
cancel_delayed_work_sync(&rt2x00dev->rfkill_work);
|
||||
|
||||
rfkill_unregister(rt2x00dev->rfkill);
|
||||
|
||||
__clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state);
|
||||
}
|
||||
|
||||
void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
|
||||
static int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct device *dev = wiphy_dev(rt2x00dev->hw->wiphy);
|
||||
|
||||
if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
|
||||
return;
|
||||
|
||||
rt2x00dev->rfkill = rfkill_allocate(dev, RFKILL_TYPE_WLAN);
|
||||
if (!rt2x00dev->rfkill) {
|
||||
ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
__set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state);
|
||||
if (!rt2x00dev->rfkill)
|
||||
return -ENOMEM;
|
||||
|
||||
rt2x00dev->rfkill->name = rt2x00dev->ops->name;
|
||||
rt2x00dev->rfkill->data = rt2x00dev;
|
||||
@@ -157,16 +116,49 @@ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
|
||||
|
||||
INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll);
|
||||
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
|
||||
static void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state))
|
||||
rfkill_free(rt2x00dev->rfkill);
|
||||
rt2x00dev->rfkill = NULL;
|
||||
}
|
||||
|
||||
void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
|
||||
return;
|
||||
|
||||
if (rt2x00rfkill_allocate(rt2x00dev)) {
|
||||
ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (rfkill_register(rt2x00dev->rfkill)) {
|
||||
ERROR(rt2x00dev, "Failed to register rfkill handler.\n");
|
||||
rt2x00rfkill_free(rt2x00dev);
|
||||
return;
|
||||
}
|
||||
|
||||
__set_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state);
|
||||
|
||||
/*
|
||||
* Force initial poll which will detect the initial device state,
|
||||
* and correctly sends the signal to the rfkill layer about this
|
||||
* state.
|
||||
*/
|
||||
rt2x00rfkill_poll(&rt2x00dev->rfkill_work.work);
|
||||
}
|
||||
|
||||
void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state))
|
||||
return;
|
||||
|
||||
cancel_delayed_work_sync(&rt2x00dev->rfkill_work);
|
||||
|
||||
rfkill_free(rt2x00dev->rfkill);
|
||||
rt2x00dev->rfkill = NULL;
|
||||
rfkill_unregister(rt2x00dev->rfkill);
|
||||
|
||||
__clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state);
|
||||
}
|
||||
|
||||
+8
-1
@@ -847,6 +847,11 @@ int pci_cfg_space_size(struct pci_dev *dev)
|
||||
{
|
||||
int pos;
|
||||
u32 status;
|
||||
u16 class;
|
||||
|
||||
class = dev->class >> 8;
|
||||
if (class == PCI_CLASS_BRIDGE_HOST)
|
||||
return pci_cfg_space_size_ext(dev);
|
||||
|
||||
pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
|
||||
if (!pos) {
|
||||
@@ -936,7 +941,6 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
|
||||
dev->multifunction = !!(hdr_type & 0x80);
|
||||
dev->vendor = l & 0xffff;
|
||||
dev->device = (l >> 16) & 0xffff;
|
||||
dev->cfg_size = pci_cfg_space_size(dev);
|
||||
dev->error_state = pci_channel_io_normal;
|
||||
set_pcie_port_type(dev);
|
||||
|
||||
@@ -952,6 +956,9 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* need to have dev->class ready */
|
||||
dev->cfg_size = pci_cfg_space_size(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
@@ -225,6 +225,25 @@ static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
|
||||
.wireless = 2,
|
||||
};
|
||||
|
||||
/* The Aspire One has a dummy ACPI-WMI interface - disable it */
|
||||
static struct dmi_system_id __devinitdata acer_blacklist[] = {
|
||||
{
|
||||
.ident = "Acer Aspire One (SSD)",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Acer Aspire One (HDD)",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct dmi_system_id acer_quirks[] = {
|
||||
{
|
||||
.callback = dmi_matched,
|
||||
@@ -1254,6 +1273,12 @@ static int __init acer_wmi_init(void)
|
||||
|
||||
printk(ACER_INFO "Acer Laptop ACPI-WMI Extras\n");
|
||||
|
||||
if (dmi_check_system(acer_blacklist)) {
|
||||
printk(ACER_INFO "Blacklisted hardware detected - "
|
||||
"not loading\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
find_quirks();
|
||||
|
||||
/*
|
||||
|
||||
@@ -318,7 +318,7 @@ cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
|
||||
{
|
||||
int ret = length;
|
||||
|
||||
if (length >= 11 && strcmp(buffer, "CUMANASCSI2") == 0) {
|
||||
if (length >= 11 && strncmp(buffer, "CUMANASCSI2", 11) == 0) {
|
||||
buffer += 11;
|
||||
length -= 11;
|
||||
|
||||
|
||||
@@ -1944,12 +1944,14 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size)
|
||||
num_arrays++;
|
||||
q->pool = kzalloc(num_arrays * max * sizeof(void*), GFP_KERNEL);
|
||||
if (q->pool == NULL)
|
||||
goto enomem;
|
||||
return -ENOMEM;
|
||||
|
||||
q->queue = kfifo_init((void*)q->pool, max * sizeof(void*),
|
||||
GFP_KERNEL, NULL);
|
||||
if (q->queue == ERR_PTR(-ENOMEM))
|
||||
if (IS_ERR(q->queue)) {
|
||||
q->queue = NULL;
|
||||
goto enomem;
|
||||
}
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
q->pool[i] = kzalloc(item_size, GFP_KERNEL);
|
||||
@@ -1979,8 +1981,7 @@ void iscsi_pool_free(struct iscsi_pool *q)
|
||||
|
||||
for (i = 0; i < q->max; i++)
|
||||
kfree(q->pool[i]);
|
||||
if (q->pool)
|
||||
kfree(q->pool);
|
||||
kfree(q->pool);
|
||||
kfree(q->queue);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iscsi_pool_free);
|
||||
|
||||
+250
-245
@@ -101,6 +101,7 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ;
|
||||
#define SG_SECTOR_MSK (SG_SECTOR_SZ - 1)
|
||||
|
||||
static int sg_add(struct device *, struct class_interface *);
|
||||
static void sg_device_destroy(struct kref *kref);
|
||||
static void sg_remove(struct device *, struct class_interface *);
|
||||
|
||||
static DEFINE_IDR(sg_index_idr);
|
||||
@@ -137,6 +138,7 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */
|
||||
volatile char done; /* 0->before bh, 1->before read, 2->read */
|
||||
struct request *rq;
|
||||
struct bio *bio;
|
||||
struct execute_work ew;
|
||||
} Sg_request;
|
||||
|
||||
typedef struct sg_fd { /* holds the state of a file descriptor */
|
||||
@@ -158,6 +160,8 @@ typedef struct sg_fd { /* holds the state of a file descriptor */
|
||||
char next_cmd_len; /* 0 -> automatic (def), >0 -> use on next write() */
|
||||
char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */
|
||||
char mmap_called; /* 0 -> mmap() never called on this fd */
|
||||
struct kref f_ref;
|
||||
struct execute_work ew;
|
||||
} Sg_fd;
|
||||
|
||||
typedef struct sg_device { /* holds the state of each scsi generic device */
|
||||
@@ -171,6 +175,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
|
||||
char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */
|
||||
struct gendisk *disk;
|
||||
struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg<n>] */
|
||||
struct kref d_ref;
|
||||
} Sg_device;
|
||||
|
||||
static int sg_fasync(int fd, struct file *filp, int mode);
|
||||
@@ -185,7 +190,7 @@ static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
|
||||
Sg_request * srp);
|
||||
static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
|
||||
const char __user *buf, size_t count, int blocking,
|
||||
int read_only, Sg_request **o_srp);
|
||||
int read_only, int sg_io_owned, Sg_request **o_srp);
|
||||
static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
|
||||
unsigned char *cmnd, int timeout, int blocking);
|
||||
static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer);
|
||||
@@ -194,13 +199,14 @@ static void sg_build_reserve(Sg_fd * sfp, int req_size);
|
||||
static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size);
|
||||
static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp);
|
||||
static Sg_fd *sg_add_sfp(Sg_device * sdp, int dev);
|
||||
static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
|
||||
static void __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
|
||||
static void sg_remove_sfp(struct kref *);
|
||||
static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
|
||||
static Sg_request *sg_add_request(Sg_fd * sfp);
|
||||
static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
|
||||
static int sg_res_in_use(Sg_fd * sfp);
|
||||
static Sg_device *sg_lookup_dev(int dev);
|
||||
static Sg_device *sg_get_dev(int dev);
|
||||
static void sg_put_dev(Sg_device *sdp);
|
||||
#ifdef CONFIG_SCSI_PROC_FS
|
||||
static int sg_last_dev(void);
|
||||
#endif
|
||||
@@ -237,22 +243,17 @@ sg_open(struct inode *inode, struct file *filp)
|
||||
nonseekable_open(inode, filp);
|
||||
SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
|
||||
sdp = sg_get_dev(dev);
|
||||
if ((!sdp) || (!sdp->device)) {
|
||||
unlock_kernel();
|
||||
return -ENXIO;
|
||||
}
|
||||
if (sdp->detached) {
|
||||
unlock_kernel();
|
||||
return -ENODEV;
|
||||
if (IS_ERR(sdp)) {
|
||||
retval = PTR_ERR(sdp);
|
||||
sdp = NULL;
|
||||
goto sg_put;
|
||||
}
|
||||
|
||||
/* This driver's module count bumped by fops_get in <linux/fs.h> */
|
||||
/* Prevent the device driver from vanishing while we sleep */
|
||||
retval = scsi_device_get(sdp->device);
|
||||
if (retval) {
|
||||
unlock_kernel();
|
||||
return retval;
|
||||
}
|
||||
if (retval)
|
||||
goto sg_put;
|
||||
|
||||
if (!((flags & O_NONBLOCK) ||
|
||||
scsi_block_when_processing_errors(sdp->device))) {
|
||||
@@ -303,16 +304,20 @@ sg_open(struct inode *inode, struct file *filp)
|
||||
if ((sfp = sg_add_sfp(sdp, dev)))
|
||||
filp->private_data = sfp;
|
||||
else {
|
||||
if (flags & O_EXCL)
|
||||
if (flags & O_EXCL) {
|
||||
sdp->exclude = 0; /* undo if error */
|
||||
wake_up_interruptible(&sdp->o_excl_wait);
|
||||
}
|
||||
retval = -ENOMEM;
|
||||
goto error_out;
|
||||
}
|
||||
unlock_kernel();
|
||||
return 0;
|
||||
|
||||
error_out:
|
||||
scsi_device_put(sdp->device);
|
||||
retval = 0;
|
||||
error_out:
|
||||
if (retval)
|
||||
scsi_device_put(sdp->device);
|
||||
sg_put:
|
||||
if (sdp)
|
||||
sg_put_dev(sdp);
|
||||
unlock_kernel();
|
||||
return retval;
|
||||
}
|
||||
@@ -327,13 +332,13 @@ sg_release(struct inode *inode, struct file *filp)
|
||||
if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
|
||||
return -ENXIO;
|
||||
SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name));
|
||||
if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */
|
||||
if (!sdp->detached) {
|
||||
scsi_device_put(sdp->device);
|
||||
}
|
||||
sdp->exclude = 0;
|
||||
wake_up_interruptible(&sdp->o_excl_wait);
|
||||
}
|
||||
|
||||
sfp->closed = 1;
|
||||
|
||||
sdp->exclude = 0;
|
||||
wake_up_interruptible(&sdp->o_excl_wait);
|
||||
|
||||
kref_put(&sfp->f_ref, sg_remove_sfp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -557,7 +562,8 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
|
||||
return -EFAULT;
|
||||
blocking = !(filp->f_flags & O_NONBLOCK);
|
||||
if (old_hdr.reply_len < 0)
|
||||
return sg_new_write(sfp, filp, buf, count, blocking, 0, NULL);
|
||||
return sg_new_write(sfp, filp, buf, count,
|
||||
blocking, 0, 0, NULL);
|
||||
if (count < (SZ_SG_HEADER + 6))
|
||||
return -EIO; /* The minimum scsi command length is 6 bytes. */
|
||||
|
||||
@@ -638,7 +644,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
|
||||
|
||||
static ssize_t
|
||||
sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
|
||||
size_t count, int blocking, int read_only,
|
||||
size_t count, int blocking, int read_only, int sg_io_owned,
|
||||
Sg_request **o_srp)
|
||||
{
|
||||
int k;
|
||||
@@ -658,6 +664,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
|
||||
SCSI_LOG_TIMEOUT(1, printk("sg_new_write: queue full\n"));
|
||||
return -EDOM;
|
||||
}
|
||||
srp->sg_io_owned = sg_io_owned;
|
||||
hp = &srp->header;
|
||||
if (__copy_from_user(hp, buf, SZ_SG_IO_HDR)) {
|
||||
sg_remove_request(sfp, srp);
|
||||
@@ -755,23 +762,12 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
|
||||
hp->duration = jiffies_to_msecs(jiffies);
|
||||
|
||||
srp->rq->timeout = timeout;
|
||||
kref_get(&sfp->f_ref); /* sg_rq_end_io() does kref_put(). */
|
||||
blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk,
|
||||
srp->rq, 1, sg_rq_end_io);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
sg_srp_done(Sg_request *srp, Sg_fd *sfp)
|
||||
{
|
||||
unsigned long iflags;
|
||||
int done;
|
||||
|
||||
read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||
done = srp->done;
|
||||
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
||||
return done;
|
||||
}
|
||||
|
||||
static int
|
||||
sg_ioctl(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd_in, unsigned long arg)
|
||||
@@ -804,27 +800,26 @@ sg_ioctl(struct inode *inode, struct file *filp,
|
||||
return -EFAULT;
|
||||
result =
|
||||
sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
|
||||
blocking, read_only, &srp);
|
||||
blocking, read_only, 1, &srp);
|
||||
if (result < 0)
|
||||
return result;
|
||||
srp->sg_io_owned = 1;
|
||||
while (1) {
|
||||
result = 0; /* following macro to beat race condition */
|
||||
__wait_event_interruptible(sfp->read_wait,
|
||||
(sdp->detached || sfp->closed || sg_srp_done(srp, sfp)),
|
||||
result);
|
||||
(srp->done || sdp->detached),
|
||||
result);
|
||||
if (sdp->detached)
|
||||
return -ENODEV;
|
||||
if (sfp->closed)
|
||||
return 0; /* request packet dropped already */
|
||||
if (0 == result)
|
||||
write_lock_irq(&sfp->rq_list_lock);
|
||||
if (srp->done) {
|
||||
srp->done = 2;
|
||||
write_unlock_irq(&sfp->rq_list_lock);
|
||||
break;
|
||||
}
|
||||
srp->orphan = 1;
|
||||
write_unlock_irq(&sfp->rq_list_lock);
|
||||
return result; /* -ERESTARTSYS because signal hit process */
|
||||
}
|
||||
write_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||
srp->done = 2;
|
||||
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
||||
result = sg_new_read(sfp, p, SZ_SG_IO_HDR, srp);
|
||||
return (result < 0) ? result : 0;
|
||||
}
|
||||
@@ -1240,6 +1235,15 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sg_rq_end_io_usercontext(struct work_struct *work)
|
||||
{
|
||||
struct sg_request *srp = container_of(work, struct sg_request, ew.work);
|
||||
struct sg_fd *sfp = srp->parentfp;
|
||||
|
||||
sg_finish_rem_req(srp);
|
||||
kref_put(&sfp->f_ref, sg_remove_sfp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is a "bottom half" handler that is called by the mid
|
||||
* level when a command is completed (or has failed).
|
||||
@@ -1247,24 +1251,23 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
static void sg_rq_end_io(struct request *rq, int uptodate)
|
||||
{
|
||||
struct sg_request *srp = rq->end_io_data;
|
||||
Sg_device *sdp = NULL;
|
||||
Sg_device *sdp;
|
||||
Sg_fd *sfp;
|
||||
unsigned long iflags;
|
||||
unsigned int ms;
|
||||
char *sense;
|
||||
int result, resid;
|
||||
int result, resid, done = 1;
|
||||
|
||||
if (NULL == srp) {
|
||||
printk(KERN_ERR "sg_cmd_done: NULL request\n");
|
||||
if (WARN_ON(srp->done != 0))
|
||||
return;
|
||||
}
|
||||
|
||||
sfp = srp->parentfp;
|
||||
if (sfp)
|
||||
sdp = sfp->parentdp;
|
||||
if ((NULL == sdp) || sdp->detached) {
|
||||
printk(KERN_INFO "sg_cmd_done: device detached\n");
|
||||
if (WARN_ON(sfp == NULL))
|
||||
return;
|
||||
}
|
||||
|
||||
sdp = sfp->parentdp;
|
||||
if (unlikely(sdp->detached))
|
||||
printk(KERN_INFO "sg_rq_end_io: device detached\n");
|
||||
|
||||
sense = rq->sense;
|
||||
result = rq->errors;
|
||||
@@ -1303,32 +1306,26 @@ static void sg_rq_end_io(struct request *rq, int uptodate)
|
||||
}
|
||||
/* Rely on write phase to clean out srp status values, so no "else" */
|
||||
|
||||
if (sfp->closed) { /* whoops this fd already released, cleanup */
|
||||
SCSI_LOG_TIMEOUT(1, printk("sg_cmd_done: already closed, freeing ...\n"));
|
||||
sg_finish_rem_req(srp);
|
||||
srp = NULL;
|
||||
if (NULL == sfp->headrp) {
|
||||
SCSI_LOG_TIMEOUT(1, printk("sg_cmd_done: already closed, final cleanup\n"));
|
||||
if (0 == sg_remove_sfp(sdp, sfp)) { /* device still present */
|
||||
scsi_device_put(sdp->device);
|
||||
}
|
||||
sfp = NULL;
|
||||
}
|
||||
} else if (srp && srp->orphan) {
|
||||
write_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||
if (unlikely(srp->orphan)) {
|
||||
if (sfp->keep_orphan)
|
||||
srp->sg_io_owned = 0;
|
||||
else {
|
||||
sg_finish_rem_req(srp);
|
||||
srp = NULL;
|
||||
}
|
||||
else
|
||||
done = 0;
|
||||
}
|
||||
if (sfp && srp) {
|
||||
/* Now wake up any sg_read() that is waiting for this packet. */
|
||||
kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN);
|
||||
write_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||
srp->done = 1;
|
||||
srp->done = done;
|
||||
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
||||
|
||||
if (likely(done)) {
|
||||
/* Now wake up any sg_read() that is waiting for this
|
||||
* packet.
|
||||
*/
|
||||
wake_up_interruptible(&sfp->read_wait);
|
||||
write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
||||
kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN);
|
||||
kref_put(&sfp->f_ref, sg_remove_sfp);
|
||||
} else {
|
||||
INIT_WORK(&srp->ew.work, sg_rq_end_io_usercontext);
|
||||
schedule_work(&srp->ew.work);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1364,17 +1361,18 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
|
||||
printk(KERN_WARNING "kmalloc Sg_device failure\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
error = -ENOMEM;
|
||||
|
||||
if (!idr_pre_get(&sg_index_idr, GFP_KERNEL)) {
|
||||
printk(KERN_WARNING "idr expansion Sg_device failure\n");
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
write_lock_irqsave(&sg_index_lock, iflags);
|
||||
error = idr_get_new(&sg_index_idr, sdp, &k);
|
||||
write_unlock_irqrestore(&sg_index_lock, iflags);
|
||||
|
||||
error = idr_get_new(&sg_index_idr, sdp, &k);
|
||||
if (error) {
|
||||
write_unlock_irqrestore(&sg_index_lock, iflags);
|
||||
printk(KERN_WARNING "idr allocation Sg_device failure: %d\n",
|
||||
error);
|
||||
goto out;
|
||||
@@ -1391,6 +1389,9 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
|
||||
init_waitqueue_head(&sdp->o_excl_wait);
|
||||
sdp->sg_tablesize = min(q->max_hw_segments, q->max_phys_segments);
|
||||
sdp->index = k;
|
||||
kref_init(&sdp->d_ref);
|
||||
|
||||
write_unlock_irqrestore(&sg_index_lock, iflags);
|
||||
|
||||
error = 0;
|
||||
out:
|
||||
@@ -1401,6 +1402,8 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
|
||||
return sdp;
|
||||
|
||||
overflow:
|
||||
idr_remove(&sg_index_idr, k);
|
||||
write_unlock_irqrestore(&sg_index_lock, iflags);
|
||||
sdev_printk(KERN_WARNING, scsidp,
|
||||
"Unable to attach sg device type=%d, minor "
|
||||
"number exceeds %d\n", scsidp->type, SG_MAX_DEVS - 1);
|
||||
@@ -1488,49 +1491,46 @@ out:
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
sg_remove(struct device *cl_dev, struct class_interface *cl_intf)
|
||||
static void sg_device_destroy(struct kref *kref)
|
||||
{
|
||||
struct sg_device *sdp = container_of(kref, struct sg_device, d_ref);
|
||||
unsigned long flags;
|
||||
|
||||
/* CAUTION! Note that the device can still be found via idr_find()
|
||||
* even though the refcount is 0. Therefore, do idr_remove() BEFORE
|
||||
* any other cleanup.
|
||||
*/
|
||||
|
||||
write_lock_irqsave(&sg_index_lock, flags);
|
||||
idr_remove(&sg_index_idr, sdp->index);
|
||||
write_unlock_irqrestore(&sg_index_lock, flags);
|
||||
|
||||
SCSI_LOG_TIMEOUT(3,
|
||||
printk("sg_device_destroy: %s\n",
|
||||
sdp->disk->disk_name));
|
||||
|
||||
put_disk(sdp->disk);
|
||||
kfree(sdp);
|
||||
}
|
||||
|
||||
static void sg_remove(struct device *cl_dev, struct class_interface *cl_intf)
|
||||
{
|
||||
struct scsi_device *scsidp = to_scsi_device(cl_dev->parent);
|
||||
Sg_device *sdp = dev_get_drvdata(cl_dev);
|
||||
unsigned long iflags;
|
||||
Sg_fd *sfp;
|
||||
Sg_fd *tsfp;
|
||||
Sg_request *srp;
|
||||
Sg_request *tsrp;
|
||||
int delay;
|
||||
|
||||
if (!sdp)
|
||||
if (!sdp || sdp->detached)
|
||||
return;
|
||||
|
||||
delay = 0;
|
||||
SCSI_LOG_TIMEOUT(3, printk("sg_remove: %s\n", sdp->disk->disk_name));
|
||||
|
||||
/* Need a write lock to set sdp->detached. */
|
||||
write_lock_irqsave(&sg_index_lock, iflags);
|
||||
if (sdp->headfp) {
|
||||
sdp->detached = 1;
|
||||
for (sfp = sdp->headfp; sfp; sfp = tsfp) {
|
||||
tsfp = sfp->nextfp;
|
||||
for (srp = sfp->headrp; srp; srp = tsrp) {
|
||||
tsrp = srp->nextrp;
|
||||
if (sfp->closed || (0 == sg_srp_done(srp, sfp)))
|
||||
sg_finish_rem_req(srp);
|
||||
}
|
||||
if (sfp->closed) {
|
||||
scsi_device_put(sdp->device);
|
||||
__sg_remove_sfp(sdp, sfp);
|
||||
} else {
|
||||
delay = 1;
|
||||
wake_up_interruptible(&sfp->read_wait);
|
||||
kill_fasync(&sfp->async_qp, SIGPOLL,
|
||||
POLL_HUP);
|
||||
}
|
||||
}
|
||||
SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d, dirty\n", sdp->index));
|
||||
if (NULL == sdp->headfp) {
|
||||
idr_remove(&sg_index_idr, sdp->index);
|
||||
}
|
||||
} else { /* nothing active, simple case */
|
||||
SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d\n", sdp->index));
|
||||
idr_remove(&sg_index_idr, sdp->index);
|
||||
sdp->detached = 1;
|
||||
for (sfp = sdp->headfp; sfp; sfp = sfp->nextfp) {
|
||||
wake_up_interruptible(&sfp->read_wait);
|
||||
kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP);
|
||||
}
|
||||
write_unlock_irqrestore(&sg_index_lock, iflags);
|
||||
|
||||
@@ -1538,13 +1538,8 @@ sg_remove(struct device *cl_dev, struct class_interface *cl_intf)
|
||||
device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index));
|
||||
cdev_del(sdp->cdev);
|
||||
sdp->cdev = NULL;
|
||||
put_disk(sdp->disk);
|
||||
sdp->disk = NULL;
|
||||
if (NULL == sdp->headfp)
|
||||
kfree(sdp);
|
||||
|
||||
if (delay)
|
||||
msleep(10); /* dirty detach so delay device destruction */
|
||||
sg_put_dev(sdp);
|
||||
}
|
||||
|
||||
module_param_named(scatter_elem_sz, scatter_elem_sz, int, S_IRUGO | S_IWUSR);
|
||||
@@ -1673,10 +1668,30 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
|
||||
md->null_mapped = hp->dxferp ? 0 : 1;
|
||||
}
|
||||
|
||||
if (iov_count)
|
||||
res = blk_rq_map_user_iov(q, rq, md, hp->dxferp, iov_count,
|
||||
hp->dxfer_len, GFP_ATOMIC);
|
||||
else
|
||||
if (iov_count) {
|
||||
int len, size = sizeof(struct sg_iovec) * iov_count;
|
||||
struct iovec *iov;
|
||||
|
||||
iov = kmalloc(size, GFP_ATOMIC);
|
||||
if (!iov)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(iov, hp->dxferp, size)) {
|
||||
kfree(iov);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
len = iov_length(iov, iov_count);
|
||||
if (hp->dxfer_len < len) {
|
||||
iov_count = iov_shorten(iov, iov_count, hp->dxfer_len);
|
||||
len = hp->dxfer_len;
|
||||
}
|
||||
|
||||
res = blk_rq_map_user_iov(q, rq, md, (struct sg_iovec *)iov,
|
||||
iov_count,
|
||||
len, GFP_ATOMIC);
|
||||
kfree(iov);
|
||||
} else
|
||||
res = blk_rq_map_user(q, rq, md, hp->dxferp,
|
||||
hp->dxfer_len, GFP_ATOMIC);
|
||||
|
||||
@@ -1941,22 +1956,6 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id)
|
||||
return resp;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCSI_PROC_FS
|
||||
static Sg_request *
|
||||
sg_get_nth_request(Sg_fd * sfp, int nth)
|
||||
{
|
||||
Sg_request *resp;
|
||||
unsigned long iflags;
|
||||
int k;
|
||||
|
||||
read_lock_irqsave(&sfp->rq_list_lock, iflags);
|
||||
for (k = 0, resp = sfp->headrp; resp && (k < nth);
|
||||
++k, resp = resp->nextrp) ;
|
||||
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
|
||||
return resp;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* always adds to end of list */
|
||||
static Sg_request *
|
||||
sg_add_request(Sg_fd * sfp)
|
||||
@@ -2032,22 +2031,6 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp)
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCSI_PROC_FS
|
||||
static Sg_fd *
|
||||
sg_get_nth_sfp(Sg_device * sdp, int nth)
|
||||
{
|
||||
Sg_fd *resp;
|
||||
unsigned long iflags;
|
||||
int k;
|
||||
|
||||
read_lock_irqsave(&sg_index_lock, iflags);
|
||||
for (k = 0, resp = sdp->headfp; resp && (k < nth);
|
||||
++k, resp = resp->nextfp) ;
|
||||
read_unlock_irqrestore(&sg_index_lock, iflags);
|
||||
return resp;
|
||||
}
|
||||
#endif
|
||||
|
||||
static Sg_fd *
|
||||
sg_add_sfp(Sg_device * sdp, int dev)
|
||||
{
|
||||
@@ -2062,6 +2045,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
|
||||
init_waitqueue_head(&sfp->read_wait);
|
||||
rwlock_init(&sfp->rq_list_lock);
|
||||
|
||||
kref_init(&sfp->f_ref);
|
||||
sfp->timeout = SG_DEFAULT_TIMEOUT;
|
||||
sfp->timeout_user = SG_DEFAULT_TIMEOUT_USER;
|
||||
sfp->force_packid = SG_DEF_FORCE_PACK_ID;
|
||||
@@ -2089,15 +2073,54 @@ sg_add_sfp(Sg_device * sdp, int dev)
|
||||
sg_build_reserve(sfp, bufflen);
|
||||
SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: bufflen=%d, k_use_sg=%d\n",
|
||||
sfp->reserve.bufflen, sfp->reserve.k_use_sg));
|
||||
|
||||
kref_get(&sdp->d_ref);
|
||||
__module_get(THIS_MODULE);
|
||||
return sfp;
|
||||
}
|
||||
|
||||
static void
|
||||
__sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
|
||||
static void sg_remove_sfp_usercontext(struct work_struct *work)
|
||||
{
|
||||
struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
|
||||
struct sg_device *sdp = sfp->parentdp;
|
||||
|
||||
/* Cleanup any responses which were never read(). */
|
||||
while (sfp->headrp)
|
||||
sg_finish_rem_req(sfp->headrp);
|
||||
|
||||
if (sfp->reserve.bufflen > 0) {
|
||||
SCSI_LOG_TIMEOUT(6,
|
||||
printk("sg_remove_sfp: bufflen=%d, k_use_sg=%d\n",
|
||||
(int) sfp->reserve.bufflen,
|
||||
(int) sfp->reserve.k_use_sg));
|
||||
sg_remove_scat(&sfp->reserve);
|
||||
}
|
||||
|
||||
SCSI_LOG_TIMEOUT(6,
|
||||
printk("sg_remove_sfp: %s, sfp=0x%p\n",
|
||||
sdp->disk->disk_name,
|
||||
sfp));
|
||||
kfree(sfp);
|
||||
|
||||
scsi_device_put(sdp->device);
|
||||
sg_put_dev(sdp);
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
static void sg_remove_sfp(struct kref *kref)
|
||||
{
|
||||
struct sg_fd *sfp = container_of(kref, struct sg_fd, f_ref);
|
||||
struct sg_device *sdp = sfp->parentdp;
|
||||
Sg_fd *fp;
|
||||
Sg_fd *prev_fp;
|
||||
unsigned long iflags;
|
||||
|
||||
/* CAUTION! Note that sfp can still be found by walking sdp->headfp
|
||||
* even though the refcount is now 0. Therefore, unlink sfp from
|
||||
* sdp->headfp BEFORE doing any other cleanup.
|
||||
*/
|
||||
|
||||
write_lock_irqsave(&sg_index_lock, iflags);
|
||||
prev_fp = sdp->headfp;
|
||||
if (sfp == prev_fp)
|
||||
sdp->headfp = prev_fp->nextfp;
|
||||
@@ -2110,54 +2133,11 @@ __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
|
||||
prev_fp = fp;
|
||||
}
|
||||
}
|
||||
if (sfp->reserve.bufflen > 0) {
|
||||
SCSI_LOG_TIMEOUT(6,
|
||||
printk("__sg_remove_sfp: bufflen=%d, k_use_sg=%d\n",
|
||||
(int) sfp->reserve.bufflen, (int) sfp->reserve.k_use_sg));
|
||||
sg_remove_scat(&sfp->reserve);
|
||||
}
|
||||
sfp->parentdp = NULL;
|
||||
SCSI_LOG_TIMEOUT(6, printk("__sg_remove_sfp: sfp=0x%p\n", sfp));
|
||||
kfree(sfp);
|
||||
}
|
||||
write_unlock_irqrestore(&sg_index_lock, iflags);
|
||||
wake_up_interruptible(&sdp->o_excl_wait);
|
||||
|
||||
/* Returns 0 in normal case, 1 when detached and sdp object removed */
|
||||
static int
|
||||
sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
|
||||
{
|
||||
Sg_request *srp;
|
||||
Sg_request *tsrp;
|
||||
int dirty = 0;
|
||||
int res = 0;
|
||||
|
||||
for (srp = sfp->headrp; srp; srp = tsrp) {
|
||||
tsrp = srp->nextrp;
|
||||
if (sg_srp_done(srp, sfp))
|
||||
sg_finish_rem_req(srp);
|
||||
else
|
||||
++dirty;
|
||||
}
|
||||
if (0 == dirty) {
|
||||
unsigned long iflags;
|
||||
|
||||
write_lock_irqsave(&sg_index_lock, iflags);
|
||||
__sg_remove_sfp(sdp, sfp);
|
||||
if (sdp->detached && (NULL == sdp->headfp)) {
|
||||
idr_remove(&sg_index_idr, sdp->index);
|
||||
kfree(sdp);
|
||||
res = 1;
|
||||
}
|
||||
write_unlock_irqrestore(&sg_index_lock, iflags);
|
||||
} else {
|
||||
/* MOD_INC's to inhibit unloading sg and associated adapter driver */
|
||||
/* only bump the access_count if we actually succeeded in
|
||||
* throwing another counter on the host module */
|
||||
scsi_device_get(sdp->device); /* XXX: retval ignored? */
|
||||
sfp->closed = 1; /* flag dirty state on this fd */
|
||||
SCSI_LOG_TIMEOUT(1, printk("sg_remove_sfp: worrisome, %d writes pending\n",
|
||||
dirty));
|
||||
}
|
||||
return res;
|
||||
INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext);
|
||||
schedule_work(&sfp->ew.work);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -2199,19 +2179,38 @@ sg_last_dev(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static Sg_device *
|
||||
sg_get_dev(int dev)
|
||||
/* must be called with sg_index_lock held */
|
||||
static Sg_device *sg_lookup_dev(int dev)
|
||||
{
|
||||
Sg_device *sdp;
|
||||
unsigned long iflags;
|
||||
return idr_find(&sg_index_idr, dev);
|
||||
}
|
||||
|
||||
read_lock_irqsave(&sg_index_lock, iflags);
|
||||
sdp = idr_find(&sg_index_idr, dev);
|
||||
read_unlock_irqrestore(&sg_index_lock, iflags);
|
||||
static Sg_device *sg_get_dev(int dev)
|
||||
{
|
||||
struct sg_device *sdp;
|
||||
unsigned long flags;
|
||||
|
||||
read_lock_irqsave(&sg_index_lock, flags);
|
||||
sdp = sg_lookup_dev(dev);
|
||||
if (!sdp)
|
||||
sdp = ERR_PTR(-ENXIO);
|
||||
else if (sdp->detached) {
|
||||
/* If sdp->detached, then the refcount may already be 0, in
|
||||
* which case it would be a bug to do kref_get().
|
||||
*/
|
||||
sdp = ERR_PTR(-ENODEV);
|
||||
} else
|
||||
kref_get(&sdp->d_ref);
|
||||
read_unlock_irqrestore(&sg_index_lock, flags);
|
||||
|
||||
return sdp;
|
||||
}
|
||||
|
||||
static void sg_put_dev(struct sg_device *sdp)
|
||||
{
|
||||
kref_put(&sdp->d_ref, sg_device_destroy);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCSI_PROC_FS
|
||||
|
||||
static struct proc_dir_entry *sg_proc_sgp = NULL;
|
||||
@@ -2468,8 +2467,10 @@ static int sg_proc_seq_show_dev(struct seq_file *s, void *v)
|
||||
struct sg_proc_deviter * it = (struct sg_proc_deviter *) v;
|
||||
Sg_device *sdp;
|
||||
struct scsi_device *scsidp;
|
||||
unsigned long iflags;
|
||||
|
||||
sdp = it ? sg_get_dev(it->index) : NULL;
|
||||
read_lock_irqsave(&sg_index_lock, iflags);
|
||||
sdp = it ? sg_lookup_dev(it->index) : NULL;
|
||||
if (sdp && (scsidp = sdp->device) && (!sdp->detached))
|
||||
seq_printf(s, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
|
||||
scsidp->host->host_no, scsidp->channel,
|
||||
@@ -2480,6 +2481,7 @@ static int sg_proc_seq_show_dev(struct seq_file *s, void *v)
|
||||
(int) scsi_device_online(scsidp));
|
||||
else
|
||||
seq_printf(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n");
|
||||
read_unlock_irqrestore(&sg_index_lock, iflags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2493,16 +2495,20 @@ static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v)
|
||||
struct sg_proc_deviter * it = (struct sg_proc_deviter *) v;
|
||||
Sg_device *sdp;
|
||||
struct scsi_device *scsidp;
|
||||
unsigned long iflags;
|
||||
|
||||
sdp = it ? sg_get_dev(it->index) : NULL;
|
||||
read_lock_irqsave(&sg_index_lock, iflags);
|
||||
sdp = it ? sg_lookup_dev(it->index) : NULL;
|
||||
if (sdp && (scsidp = sdp->device) && (!sdp->detached))
|
||||
seq_printf(s, "%8.8s\t%16.16s\t%4.4s\n",
|
||||
scsidp->vendor, scsidp->model, scsidp->rev);
|
||||
else
|
||||
seq_printf(s, "<no active device>\n");
|
||||
read_unlock_irqrestore(&sg_index_lock, iflags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* must be called while holding sg_index_lock */
|
||||
static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
|
||||
{
|
||||
int k, m, new_interface, blen, usg;
|
||||
@@ -2512,7 +2518,8 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
|
||||
const char * cp;
|
||||
unsigned int ms;
|
||||
|
||||
for (k = 0; (fp = sg_get_nth_sfp(sdp, k)); ++k) {
|
||||
for (k = 0, fp = sdp->headfp; fp != NULL; ++k, fp = fp->nextfp) {
|
||||
read_lock(&fp->rq_list_lock); /* irqs already disabled */
|
||||
seq_printf(s, " FD(%d): timeout=%dms bufflen=%d "
|
||||
"(res)sgat=%d low_dma=%d\n", k + 1,
|
||||
jiffies_to_msecs(fp->timeout),
|
||||
@@ -2522,7 +2529,9 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
|
||||
seq_printf(s, " cmd_q=%d f_packid=%d k_orphan=%d closed=%d\n",
|
||||
(int) fp->cmd_q, (int) fp->force_packid,
|
||||
(int) fp->keep_orphan, (int) fp->closed);
|
||||
for (m = 0; (srp = sg_get_nth_request(fp, m)); ++m) {
|
||||
for (m = 0, srp = fp->headrp;
|
||||
srp != NULL;
|
||||
++m, srp = srp->nextrp) {
|
||||
hp = &srp->header;
|
||||
new_interface = (hp->interface_id == '\0') ? 0 : 1;
|
||||
if (srp->res_used) {
|
||||
@@ -2559,6 +2568,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
|
||||
}
|
||||
if (0 == m)
|
||||
seq_printf(s, " No requests active\n");
|
||||
read_unlock(&fp->rq_list_lock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2571,39 +2581,34 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v)
|
||||
{
|
||||
struct sg_proc_deviter * it = (struct sg_proc_deviter *) v;
|
||||
Sg_device *sdp;
|
||||
unsigned long iflags;
|
||||
|
||||
if (it && (0 == it->index)) {
|
||||
seq_printf(s, "max_active_device=%d(origin 1)\n",
|
||||
(int)it->max);
|
||||
seq_printf(s, " def_reserved_size=%d\n", sg_big_buff);
|
||||
}
|
||||
sdp = it ? sg_get_dev(it->index) : NULL;
|
||||
if (sdp) {
|
||||
|
||||
read_lock_irqsave(&sg_index_lock, iflags);
|
||||
sdp = it ? sg_lookup_dev(it->index) : NULL;
|
||||
if (sdp && sdp->headfp) {
|
||||
struct scsi_device *scsidp = sdp->device;
|
||||
|
||||
if (NULL == scsidp) {
|
||||
seq_printf(s, "device %d detached ??\n",
|
||||
(int)it->index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sg_get_nth_sfp(sdp, 0)) {
|
||||
seq_printf(s, " >>> device=%s ",
|
||||
sdp->disk->disk_name);
|
||||
if (sdp->detached)
|
||||
seq_printf(s, "detached pending close ");
|
||||
else
|
||||
seq_printf
|
||||
(s, "scsi%d chan=%d id=%d lun=%d em=%d",
|
||||
scsidp->host->host_no,
|
||||
scsidp->channel, scsidp->id,
|
||||
scsidp->lun,
|
||||
scsidp->host->hostt->emulated);
|
||||
seq_printf(s, " sg_tablesize=%d excl=%d\n",
|
||||
sdp->sg_tablesize, sdp->exclude);
|
||||
}
|
||||
seq_printf(s, " >>> device=%s ", sdp->disk->disk_name);
|
||||
if (sdp->detached)
|
||||
seq_printf(s, "detached pending close ");
|
||||
else
|
||||
seq_printf
|
||||
(s, "scsi%d chan=%d id=%d lun=%d em=%d",
|
||||
scsidp->host->host_no,
|
||||
scsidp->channel, scsidp->id,
|
||||
scsidp->lun,
|
||||
scsidp->host->hostt->emulated);
|
||||
seq_printf(s, " sg_tablesize=%d excl=%d\n",
|
||||
sdp->sg_tablesize, sdp->exclude);
|
||||
sg_proc_debug_helper(s, sdp);
|
||||
}
|
||||
read_unlock_irqrestore(&sg_index_lock, iflags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+14
-8
@@ -658,7 +658,7 @@ int spi_write_then_read(struct spi_device *spi,
|
||||
|
||||
int status;
|
||||
struct spi_message message;
|
||||
struct spi_transfer x;
|
||||
struct spi_transfer x[2];
|
||||
u8 *local_buf;
|
||||
|
||||
/* Use preallocated DMA-safe buffer. We can't avoid copying here,
|
||||
@@ -669,9 +669,15 @@ int spi_write_then_read(struct spi_device *spi,
|
||||
return -EINVAL;
|
||||
|
||||
spi_message_init(&message);
|
||||
memset(&x, 0, sizeof x);
|
||||
x.len = n_tx + n_rx;
|
||||
spi_message_add_tail(&x, &message);
|
||||
memset(x, 0, sizeof x);
|
||||
if (n_tx) {
|
||||
x[0].len = n_tx;
|
||||
spi_message_add_tail(&x[0], &message);
|
||||
}
|
||||
if (n_rx) {
|
||||
x[1].len = n_rx;
|
||||
spi_message_add_tail(&x[1], &message);
|
||||
}
|
||||
|
||||
/* ... unless someone else is using the pre-allocated buffer */
|
||||
if (!mutex_trylock(&lock)) {
|
||||
@@ -682,15 +688,15 @@ int spi_write_then_read(struct spi_device *spi,
|
||||
local_buf = buf;
|
||||
|
||||
memcpy(local_buf, txbuf, n_tx);
|
||||
x.tx_buf = local_buf;
|
||||
x.rx_buf = local_buf;
|
||||
x[0].tx_buf = local_buf;
|
||||
x[1].rx_buf = local_buf + n_tx;
|
||||
|
||||
/* do the i/o */
|
||||
status = spi_sync(spi, &message);
|
||||
if (status == 0)
|
||||
memcpy(rxbuf, x.rx_buf + n_tx, n_rx);
|
||||
memcpy(rxbuf, x[1].rx_buf, n_rx);
|
||||
|
||||
if (x.tx_buf == buf)
|
||||
if (x[0].tx_buf == buf)
|
||||
mutex_unlock(&lock);
|
||||
else
|
||||
kfree(local_buf);
|
||||
|
||||
@@ -652,7 +652,7 @@ next_desc:
|
||||
|
||||
iface = &intf->altsetting[0];
|
||||
ep = &iface->endpoint[0].desc;
|
||||
if (!usb_endpoint_is_int_in(ep)) {
|
||||
if (!ep || !usb_endpoint_is_int_in(ep)) {
|
||||
rv = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1719,7 +1719,8 @@ free_interfaces:
|
||||
}
|
||||
kfree(new_interfaces);
|
||||
|
||||
if (cp->string == NULL)
|
||||
if (cp->string == NULL &&
|
||||
!(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
|
||||
cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
|
||||
|
||||
/* Now that all the interfaces are set up, register them
|
||||
|
||||
@@ -54,6 +54,10 @@ static const struct usb_device_id usb_quirk_list[] = {
|
||||
{ USB_DEVICE(0x0638, 0x0a13), .driver_info =
|
||||
USB_QUIRK_STRING_FETCH_255 },
|
||||
|
||||
/* Saitek Cyborg Gold Joystick */
|
||||
{ USB_DEVICE(0x06a3, 0x0006), .driver_info =
|
||||
USB_QUIRK_CONFIG_INTF_STRINGS },
|
||||
|
||||
/* M-Systems Flash Disk Pioneers */
|
||||
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/quirks.h>
|
||||
#include "usb.h"
|
||||
|
||||
/* Active configuration fields */
|
||||
@@ -813,7 +814,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf)
|
||||
if (intf->sysfs_files_created || intf->unregistering)
|
||||
return 0;
|
||||
|
||||
if (alt->string == NULL)
|
||||
if (alt->string == NULL &&
|
||||
!(udev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
|
||||
alt->string = usb_cache_string(udev, alt->desc.iInterface);
|
||||
if (alt->string)
|
||||
retval = device_create_file(&intf->dev, &dev_attr_interface);
|
||||
|
||||
@@ -437,7 +437,7 @@ invalid:
|
||||
DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n",
|
||||
ctrl->bRequestType, ctrl->bRequest,
|
||||
w_value, w_index, w_length);
|
||||
req->zero = 0;
|
||||
req->zero = (value < w_length);
|
||||
req->length = value;
|
||||
value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
|
||||
if (value < 0)
|
||||
|
||||
@@ -175,12 +175,6 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p)
|
||||
strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info);
|
||||
}
|
||||
|
||||
static u32 eth_get_link(struct net_device *net)
|
||||
{
|
||||
struct eth_dev *dev = netdev_priv(net);
|
||||
return dev->gadget->speed != USB_SPEED_UNKNOWN;
|
||||
}
|
||||
|
||||
/* REVISIT can also support:
|
||||
* - WOL (by tracking suspends and issuing remote wakeup)
|
||||
* - msglevel (implies updated messaging)
|
||||
@@ -189,7 +183,7 @@ static u32 eth_get_link(struct net_device *net)
|
||||
|
||||
static struct ethtool_ops ops = {
|
||||
.get_drvinfo = eth_get_drvinfo,
|
||||
.get_link = eth_get_link
|
||||
.get_link = ethtool_op_get_link,
|
||||
};
|
||||
|
||||
static void defer_kevent(struct eth_dev *dev, int flag)
|
||||
|
||||
@@ -333,12 +333,40 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
token = hc32_to_cpu(ehci, qtd->hw_token);
|
||||
|
||||
/* always clean up qtds the hc de-activated */
|
||||
retry_xacterr:
|
||||
if ((token & QTD_STS_ACTIVE) == 0) {
|
||||
|
||||
/* on STALL, error, and short reads this urb must
|
||||
* complete and all its qtds must be recycled.
|
||||
*/
|
||||
if ((token & QTD_STS_HALT) != 0) {
|
||||
|
||||
/* retry transaction errors until we
|
||||
* reach the software xacterr limit
|
||||
*/
|
||||
if ((token & QTD_STS_XACT) &&
|
||||
QTD_CERR(token) == 0 &&
|
||||
--qh->xacterrs > 0 &&
|
||||
!urb->unlinked) {
|
||||
ehci_dbg(ehci,
|
||||
"detected XactErr len %d/%d retry %d\n",
|
||||
qtd->length - QTD_LENGTH(token), qtd->length,
|
||||
QH_XACTERR_MAX - qh->xacterrs);
|
||||
|
||||
/* reset the token in the qtd and the
|
||||
* qh overlay (which still contains
|
||||
* the qtd) so that we pick up from
|
||||
* where we left off
|
||||
*/
|
||||
token &= ~QTD_STS_HALT;
|
||||
token |= QTD_STS_ACTIVE |
|
||||
(EHCI_TUNE_CERR << 10);
|
||||
qtd->hw_token = cpu_to_hc32(ehci,
|
||||
token);
|
||||
wmb();
|
||||
qh->hw_token = cpu_to_hc32(ehci, token);
|
||||
goto retry_xacterr;
|
||||
}
|
||||
stopped = 1;
|
||||
|
||||
/* magic dummy for some short reads; qh won't advance.
|
||||
@@ -421,6 +449,9 @@ halt:
|
||||
/* remove qtd; it's recycled after possible urb completion */
|
||||
list_del (&qtd->qtd_list);
|
||||
last = qtd;
|
||||
|
||||
/* reinit the xacterr counter for the next qtd */
|
||||
qh->xacterrs = QH_XACTERR_MAX;
|
||||
}
|
||||
|
||||
/* last urb's completion might still need calling */
|
||||
@@ -862,6 +893,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
head->qh_next.qh = qh;
|
||||
head->hw_next = dma;
|
||||
|
||||
qh->xacterrs = QH_XACTERR_MAX;
|
||||
qh->qh_state = QH_STATE_LINKED;
|
||||
/* qtd completions reported later by interrupt */
|
||||
}
|
||||
|
||||
@@ -376,6 +376,9 @@ struct ehci_qh {
|
||||
#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */
|
||||
#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */
|
||||
|
||||
u8 xacterrs; /* XactErr retry counter */
|
||||
#define QH_XACTERR_MAX 32 /* XactErr retry limit */
|
||||
|
||||
/* periodic schedule info */
|
||||
u8 usecs; /* intr bandwidth */
|
||||
u8 gap_uf; /* uframes split/csplit gap */
|
||||
|
||||
@@ -668,6 +668,7 @@ static struct usb_device_id id_table_combined [] = {
|
||||
{ USB_DEVICE(DE_VID, WHT_PID) },
|
||||
{ USB_DEVICE(ADI_VID, ADI_GNICE_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
||||
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
|
||||
{ }, /* Optional parameter entry */
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
@@ -912,6 +912,13 @@
|
||||
#define ADI_VID 0x0456
|
||||
#define ADI_GNICE_PID 0xF000
|
||||
|
||||
/*
|
||||
* JETI SPECTROMETER SPECBOS 1201
|
||||
* http://www.jeti.com/products/sys/scb/scb1201.php
|
||||
*/
|
||||
#define JETI_VID 0x0c6c
|
||||
#define JETI_SPC1201_PID 0x04b2
|
||||
|
||||
/*
|
||||
* BmRequestType: 1100 0000b
|
||||
* bRequest: FTDI_E2_READ
|
||||
|
||||
@@ -1215,20 +1215,22 @@ static void ti_bulk_in_callback(struct urb *urb)
|
||||
}
|
||||
|
||||
tty = tty_port_tty_get(&port->port);
|
||||
if (tty && urb->actual_length) {
|
||||
usb_serial_debug_data(debug, dev, __func__,
|
||||
urb->actual_length, urb->transfer_buffer);
|
||||
if (tty) {
|
||||
if (urb->actual_length) {
|
||||
usb_serial_debug_data(debug, dev, __func__,
|
||||
urb->actual_length, urb->transfer_buffer);
|
||||
|
||||
if (!tport->tp_is_open)
|
||||
dbg("%s - port closed, dropping data", __func__);
|
||||
else
|
||||
ti_recv(&urb->dev->dev, tty,
|
||||
if (!tport->tp_is_open)
|
||||
dbg("%s - port closed, dropping data",
|
||||
__func__);
|
||||
else
|
||||
ti_recv(&urb->dev->dev, tty,
|
||||
urb->transfer_buffer,
|
||||
urb->actual_length);
|
||||
|
||||
spin_lock(&tport->tp_lock);
|
||||
tport->tp_icount.rx += urb->actual_length;
|
||||
spin_unlock(&tport->tp_lock);
|
||||
spin_lock(&tport->tp_lock);
|
||||
tport->tp_icount.rx += urb->actual_length;
|
||||
spin_unlock(&tport->tp_lock);
|
||||
}
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
|
||||
@@ -133,19 +133,18 @@ void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
|
||||
|
||||
/* build the command for
|
||||
* reading the ATA registers */
|
||||
scsi_eh_prep_cmnd(srb, &ses, NULL, 0, 0);
|
||||
srb->sdb.length = sizeof(regs);
|
||||
sg_init_one(&ses.sense_sgl, regs, srb->sdb.length);
|
||||
srb->sdb.table.sgl = &ses.sense_sgl;
|
||||
srb->sc_data_direction = DMA_FROM_DEVICE;
|
||||
srb->sdb.table.nents = 1;
|
||||
scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sizeof(regs));
|
||||
|
||||
/* we use the same command as before, but we set
|
||||
* the read taskfile bit, for not executing atacb command,
|
||||
* but reading register selected in srb->cmnd[4]
|
||||
*/
|
||||
srb->cmd_len = 16;
|
||||
srb->cmnd = ses.cmnd;
|
||||
srb->cmnd[2] = 1;
|
||||
|
||||
usb_stor_transparent_scsi_command(srb, us);
|
||||
memcpy(regs, srb->sense_buffer, sizeof(regs));
|
||||
tmp_result = srb->result;
|
||||
scsi_eh_restore_cmnd(srb, &ses);
|
||||
/* we fail to get registers, report invalid command */
|
||||
@@ -162,8 +161,8 @@ void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
|
||||
|
||||
/* XXX we should generate sk, asc, ascq from status and error
|
||||
* regs
|
||||
* (see 11.1 Error translation ATA device error to SCSI error map)
|
||||
* and ata_to_sense_error from libata.
|
||||
* (see 11.1 Error translation ATA device error to SCSI error
|
||||
* map, and ata_to_sense_error from libata.)
|
||||
*/
|
||||
|
||||
/* Sense data is current and format is descriptor. */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user