diff options
164 files changed, 2181 insertions, 1260 deletions
diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt index e65736c6b8bc..63e59b8847c5 100644 --- a/Documentation/cciss.txt +++ b/Documentation/cciss.txt @@ -21,6 +21,11 @@ This driver is known to work with the following cards: * SA E200 * SA E200i * SA E500 + * SA P212 + * SA P410 + * SA P410i + * SA P411 + * SA P812 Detecting drive failures: ------------------------- diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt index bf3256e04027..51a8021ee532 100644 --- a/Documentation/kobject.txt +++ b/Documentation/kobject.txt @@ -305,7 +305,7 @@ should not be manipulated by any other user. A kset keeps its children in a standard kernel linked list. Kobjects point back to their containing kset via their kset field. In almost all cases, -the kobjects belonging to a ket have that kset (or, strictly, its embedded +the kobjects belonging to a kset have that kset (or, strictly, its embedded kobject) in their parent. As a kset contains a kobject within it, it should always be dynamically diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 01c6c3d8a7e3..64b3f146e4b0 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -503,7 +503,7 @@ generate input device EV_KEY events. In addition to the EV_KEY events, thinkpad-acpi may also issue EV_SW events for switches: -SW_RADIO T60 and later hardare rfkill rocker switch +SW_RFKILL_ALL T60 and later hardare rfkill rocker switch SW_TABLET_MODE Tablet ThinkPads HKEY events 0x5009 and 0x500A Non hot-key ACPI HKEY event map: diff --git a/MAINTAINERS b/MAINTAINERS index e3560df4608e..88aac5f81e23 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -228,21 +228,21 @@ ACPI BATTERY DRIVERS P: Alexey Starikovskiy M: astarikovskiy@suse.de L: linux-acpi@vger.kernel.org -W: http://acpi.sourceforge.net/ +W: http://www.lesswatts.org/projects/acpi/ S: Supported ACPI EC DRIVER P: Alexey Starikovskiy M: astarikovskiy@suse.de L: linux-acpi@vger.kernel.org -W: http://acpi.sourceforge.net/ +W: http://www.lesswatts.org/projects/acpi/ S: Supported ACPI FAN DRIVER P: Len Brown M: len.brown@intel.com L: linux-acpi@vger.kernel.org -W: http://acpi.sourceforge.net/ +W: http://www.lesswatts.org/projects/acpi/ S: Supported ACPI PCI HOTPLUG DRIVER @@ -255,14 +255,14 @@ ACPI THERMAL DRIVER P: Len Brown M: len.brown@intel.com L: linux-acpi@vger.kernel.org -W: http://acpi.sourceforge.net/ +W: http://www.lesswatts.org/projects/acpi/ S: Supported ACPI VIDEO DRIVER P: Rui Zhang M: rui.zhang@intel.com L: linux-acpi@vger.kernel.org -W: http://acpi.sourceforge.net/ +W: http://www.lesswatts.org/projects/acpi/ S: Supported ACPI WMI DRIVER @@ -1202,6 +1202,7 @@ M: pj@sgi.com M: menage@google.com L: linux-kernel@vger.kernel.org W: http://www.bullopensource.org/cpuset/ +W: http://oss.sgi.com/projects/cpusets/ S: Supported CRAMFS FILESYSTEM @@ -3329,9 +3330,11 @@ L: video4linux-list@redhat.com W: http://www.isely.net/pvrusb2/ S: Maintained -PXA2xx SUPPORT -P: Nicolas Pitre -M: nico@cam.org +PXA2xx/PXA3xx SUPPORT +P: Eric Miao +M: eric.miao@marvell.com +P: Russell King +M: linux@arm.linux.org.uk L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 26 -EXTRAVERSION = -rc5 -NAME = Funky Weasel is Jiggy wit it +EXTRAVERSION = -rc6 +NAME = Rotary Wombat # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 853d1f11be00..43687cc60dfb 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -465,7 +465,6 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) printk(KERN_ERR "ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n", len, slit->header.length); - memset(numa_slit, 10, sizeof(numa_slit)); return; } slit_table = slit; @@ -574,8 +573,14 @@ void __init acpi_numa_arch_fixup(void) printk(KERN_INFO "Number of memory chunks in system = %d\n", num_node_memblks); - if (!slit_table) + if (!slit_table) { + for (i = 0; i < MAX_NUMNODES; i++) + for (j = 0; j < MAX_NUMNODES; j++) + node_distance(i, j) = i == j ? LOCAL_DISTANCE : + REMOTE_DISTANCE; return; + } + memset(numa_slit, -1, sizeof(numa_slit)); for (i = 0; i < slit_table->locality_count; i++) { if (!pxm_bit_test(i)) diff --git a/arch/ia64/kvm/mmio.c b/arch/ia64/kvm/mmio.c index 351bf70da463..7f1a858bc69f 100644 --- a/arch/ia64/kvm/mmio.c +++ b/arch/ia64/kvm/mmio.c @@ -159,7 +159,8 @@ static void mmio_access(struct kvm_vcpu *vcpu, u64 src_pa, u64 *dest, if (p->u.ioreq.state == STATE_IORESP_READY) { if (dir == IOREQ_READ) - *dest = p->u.ioreq.data; + /* it's necessary to ensure zero extending */ + *dest = p->u.ioreq.data & (~0UL >> (64-(s*8))); } else panic_vm(vcpu); out: diff --git a/arch/m68knommu/platform/coldfire/timers.c b/arch/m68knommu/platform/coldfire/timers.c index ba5a9f32ebd4..454f25493491 100644 --- a/arch/m68knommu/platform/coldfire/timers.c +++ b/arch/m68knommu/platform/coldfire/timers.c @@ -111,7 +111,13 @@ void hw_timer_init(void) __raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR)); mcftmr_cycles_per_jiffy = FREQ / HZ; - __raw_writetrr(mcftmr_cycles_per_jiffy, TA(MCFTIMER_TRR)); + /* + * The coldfire timer runs from 0 to TRR included, then 0 + * again and so on. It counts thus actually TRR + 1 steps + * for 1 tick, not TRR. So if you want n cycles, + * initialize TRR with n - 1. + */ + __raw_writetrr(mcftmr_cycles_per_jiffy - 1, TA(MCFTIMER_TRR)); __raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR)); diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index f5d7a5eab96e..75dff7cfa814 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c @@ -116,8 +116,6 @@ static void kvmppc_44x_shadow_release(struct kvm_vcpu *vcpu, struct tlbe *stlbe = &vcpu->arch.shadow_tlb[index]; struct page *page = vcpu->arch.shadow_pages[index]; - kunmap(vcpu->arch.shadow_pages[index]); - if (get_tlb_v(stlbe)) { if (kvmppc_44x_tlbe_is_writable(stlbe)) kvm_release_page_dirty(page); @@ -144,18 +142,19 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid, stlbe = &vcpu->arch.shadow_tlb[victim]; /* Get reference to new page. */ - down_write(¤t->mm->mmap_sem); + down_read(¤t->mm->mmap_sem); new_page = gfn_to_page(vcpu->kvm, gfn); if (is_error_page(new_page)) { - printk(KERN_ERR "Couldn't get guest page!\n"); + printk(KERN_ERR "Couldn't get guest page for gfn %lx!\n", gfn); kvm_release_page_clean(new_page); + up_read(¤t->mm->mmap_sem); return; } hpaddr = page_to_phys(new_page); /* Drop reference to old page. */ kvmppc_44x_shadow_release(vcpu, victim); - up_write(¤t->mm->mmap_sem); + up_read(¤t->mm->mmap_sem); vcpu->arch.shadow_pages[victim] = new_page; diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c index 712d89a28c46..9c8ad850c6e3 100644 --- a/arch/powerpc/kvm/booke_guest.c +++ b/arch/powerpc/kvm/booke_guest.c @@ -227,39 +227,6 @@ void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu) } } -static int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) -{ - enum emulation_result er; - int r; - - er = kvmppc_emulate_instruction(run, vcpu); - switch (er) { - case EMULATE_DONE: - /* Future optimization: only reload non-volatiles if they were - * actually modified. */ - r = RESUME_GUEST_NV; - break; - case EMULATE_DO_MMIO: - run->exit_reason = KVM_EXIT_MMIO; - /* We must reload nonvolatiles because "update" load/store - * instructions modify register state. */ - /* Future optimization: only reload non-volatiles if they were - * actually modified. */ - r = RESUME_HOST_NV; - break; - case EMULATE_FAIL: - /* XXX Deliver Program interrupt to guest. */ - printk(KERN_EMERG "%s: emulation failed (%08x)\n", __func__, - vcpu->arch.last_inst); - r = RESUME_HOST; - break; - default: - BUG(); - } - - return r; -} - /** * kvmppc_handle_exit * diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index a03fe0c80698..000097461283 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c @@ -246,6 +246,11 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) case 31: switch (get_xop(inst)) { + case 23: /* lwzx */ + rt = get_rt(inst); + emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); + break; + case 83: /* mfmsr */ rt = get_rt(inst); vcpu->arch.gpr[rt] = vcpu->arch.msr; @@ -267,6 +272,13 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]); break; + case 151: /* stwx */ + rs = get_rs(inst); + emulated = kvmppc_handle_store(run, vcpu, + vcpu->arch.gpr[rs], + 4, 1); + break; + case 163: /* wrteei */ vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE) | (inst & MSR_EE); diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index f639a152869f..a0775e1f08df 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c @@ -20,7 +20,7 @@ static int __diag_time_slice_end(struct kvm_vcpu *vcpu) VCPU_EVENT(vcpu, 5, "%s", "diag time slice end"); vcpu->stat.diagnose_44++; vcpu_put(vcpu); - schedule(); + yield(); vcpu_load(vcpu); return 0; } diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index fcd1ed8015c1..84a7fed4cd4e 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -339,6 +339,11 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) if (kvm_cpu_has_interrupt(vcpu)) return 0; + __set_cpu_idle(vcpu); + spin_lock_bh(&vcpu->arch.local_int.lock); + vcpu->arch.local_int.timer_due = 0; + spin_unlock_bh(&vcpu->arch.local_int.lock); + if (psw_interrupts_disabled(vcpu)) { VCPU_EVENT(vcpu, 3, "%s", "disabled wait"); __unset_cpu_idle(vcpu); @@ -366,8 +371,6 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) no_timer: spin_lock_bh(&vcpu->arch.local_int.float_int->lock); spin_lock_bh(&vcpu->arch.local_int.lock); - __set_cpu_idle(vcpu); - vcpu->arch.local_int.timer_due = 0; add_wait_queue(&vcpu->arch.local_int.wq, &wait); while (list_empty(&vcpu->arch.local_int.list) && list_empty(&vcpu->arch.local_int.float_int->list) && diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 0ac36a649eba..6558b09ff579 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -423,6 +423,8 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, return -EINVAL; /* not implemented yet */ } +extern void s390_handle_mcck(void); + static void __vcpu_run(struct kvm_vcpu *vcpu) { memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16); @@ -430,13 +432,21 @@ static void __vcpu_run(struct kvm_vcpu *vcpu) if (need_resched()) schedule(); + if (test_thread_flag(TIF_MCCK_PENDING)) + s390_handle_mcck(); + + kvm_s390_deliver_pending_interrupts(vcpu); + vcpu->arch.sie_block->icptcode = 0; local_irq_disable(); kvm_guest_enter(); local_irq_enable(); VCPU_EVENT(vcpu, 6, "entering sie flags %x", atomic_read(&vcpu->arch.sie_block->cpuflags)); - sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs); + if (sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs)) { + VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction"); + kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); + } VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", vcpu->arch.sie_block->icptcode); local_irq_disable(); @@ -475,7 +485,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) might_sleep(); do { - kvm_s390_deliver_pending_interrupts(vcpu); __vcpu_run(vcpu); rc = kvm_handle_sie_intercept(vcpu); } while (!signal_pending(current) && !rc); diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 5c1aea97cd12..3d98ba82ea67 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -254,36 +254,46 @@ void disable_noexec(struct mm_struct *mm, struct task_struct *tsk) int s390_enable_sie(void) { struct task_struct *tsk = current; - struct mm_struct *mm; - int rc; + struct mm_struct *mm, *old_mm; - task_lock(tsk); - - rc = 0; + /* Do we have pgstes? if yes, we are done */ if (tsk->mm->context.pgstes) - goto unlock; + return 0; - rc = -EINVAL; + /* lets check if we are allowed to replace the mm */ + task_lock(tsk); if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 || - tsk->mm != tsk->active_mm || tsk->mm->ioctx_list) - goto unlock; + tsk->mm != tsk->active_mm || tsk->mm->ioctx_list) { + task_unlock(tsk); + return -EINVAL; + } + task_unlock(tsk); - tsk->mm->context.pgstes = 1; /* dirty little tricks .. */ + /* we copy the mm with pgstes enabled */ + tsk->mm->context.pgstes = 1; mm = dup_mm(tsk); tsk->mm->context.pgstes = 0; - - rc = -ENOMEM; if (!mm) - goto unlock; - mmput(tsk->mm); + return -ENOMEM; + + /* Now lets check again if somebody attached ptrace etc */ + task_lock(tsk); + if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 || + tsk->mm != tsk->active_mm || tsk->mm->ioctx_list) { + mmput(mm); + task_unlock(tsk); + return -EINVAL; + } + + /* ok, we are alone. No ptrace, no threads, etc. */ + old_mm = tsk->mm; tsk->mm = tsk->active_mm = mm; preempt_disable(); update_mm(mm, tsk); cpu_set(smp_processor_id(), mm->cpu_vm_mask); preempt_enable(); - rc = 0; -unlock: task_unlock(tsk); - return rc; + mmput(old_mm); + return 0; } EXPORT_SYMBOL_GPL(s390_enable_sie); diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index b4b36e0f2e89..183db26d01bf 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -121,8 +121,10 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit) { int status, n, ret = 0; - if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) - fatal_perror("stop_ptraced_child : ptrace failed"); + if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) { + perror("stop_ptraced_child : ptrace failed"); + return -1; + } CATCH_EINTR(n = waitpid(pid, &status, 0)); if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { int exit_with = WEXITSTATUS(status); @@ -212,7 +214,7 @@ static void __init check_sysemu(void) if (n < 0) fatal_perror("check_sysemu : wait failed"); if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) - fatal("check_sysemu : expected SIGTRAP, got status = %d", + fatal("check_sysemu : expected SIGTRAP, got status = %d\n", status); if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) @@ -254,9 +256,11 @@ static void __init check_sysemu(void) if (WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))) { - if (!count) - fatal("check_ptrace : SYSEMU_SINGLESTEP " - "doesn't singlestep"); + if (!count) { + non_fatal("check_ptrace : SYSEMU_SINGLESTEP " + "doesn't singlestep"); + goto fail; + } n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); if (n < 0) @@ -266,9 +270,12 @@ static void __init check_sysemu(void) } else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) count++; - else - fatal("check_ptrace : expected SIGTRAP or " - "(SIGTRAP | 0x80), got status = %d", status); + else { + non_fatal("check_ptrace : expected SIGTRAP or " + "(SIGTRAP | 0x80), got status = %d\n", + status); + goto fail; + } } if (stop_ptraced_child(pid, 0, 0) < 0) goto fail_stopped; diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index b487cbead1bd..229f7a53d8da 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -6,7 +6,7 @@ #include <errno.h> #include <sys/ptrace.h> -#include <asm/user.h> +#include <sys/user.h> #include "kern_constants.h" #include "longjmp.h" #include "user.h" @@ -76,7 +76,7 @@ int put_fp_registers(int pid, unsigned long *regs) void arch_init_registers(int pid) { - struct user_fxsr_struct fpx_regs; + struct user_fpxregs_struct fpx_regs; int err; err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); diff --git a/arch/x86/boot/a20.c b/arch/x86/boot/a20.c index 90943f83e84d..e01aafd03bde 100644 --- a/arch/x86/boot/a20.c +++ b/arch/x86/boot/a20.c @@ -115,8 +115,6 @@ static void enable_a20_fast(void) int enable_a20(void) { - int loops = A20_ENABLE_LOOPS; - #if defined(CONFIG_X86_ELAN) /* Elan croaks if we try to touch the KBC */ enable_a20_fast(); @@ -128,6 +126,7 @@ int enable_a20(void) enable_a20_kbc(); return 0; #else + int loops = A20_ENABLE_LOOPS; while (loops--) { /* First, check to see if A20 is already enabled (legacy free, etc.) */ diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 2a609dc3271c..c778e4fa55a2 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -248,6 +248,7 @@ ENTRY(resume_userspace) DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret + TRACE_IRQS_OFF movl TI_flags(%ebp), %ecx andl $_TIF_WORK_MASK, %ecx # is there any work to be done on # int/exception return? diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index b2cc73768a9d..f7357cc0162c 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -189,7 +189,7 @@ default_entry: * this stage. */ -#define KPMDS ((0x100000000-__PAGE_OFFSET) >> 30) /* Number of kernel PMDs */ +#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */ xorl %ebx,%ebx /* %ebx is kept at zero */ diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index a40d54fc1fdd..4dc8600d9d20 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -2130,14 +2130,10 @@ static inline void __init check_timer(void) { int apic1, pin1, apic2, pin2; int vector; - unsigned int ver; unsigned long flags; local_irq_save(flags); - ver = apic_read(APIC_LVR); - ver = GET_APIC_VERSION(ver); - /* * get/set the timer IRQ vector: */ @@ -2150,15 +2146,11 @@ static inline void __init check_timer(void) * mode for the 8259A whenever interrupts are routed * through I/O APICs. Also IRQ0 has to be enabled in * the 8259A which implies the virtual wire has to be - * disabled in the local APIC. Finally timer interrupts - * need to be acknowledged manually in the 8259A for - * timer_interrupt() and for the i82489DX when using - * the NMI watchdog. + * disabled in the local APIC. */ apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); init_8259A(1); - timer_ack = !cpu_has_tsc; - timer_ack |= (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver)); + timer_ack = 1; if (timer_over_8254 > 0) enable_8259A_irq(0); diff --git a/arch/x86/kernel/mfgpt_32.c b/arch/x86/kernel/mfgpt_32.c index 3cad17fe026b..07c0f828f488 100644 --- a/arch/x86/kernel/mfgpt_32.c +++ b/arch/x86/kernel/mfgpt_32.c @@ -155,6 +155,7 @@ int geode_mfgpt_toggle_event(int timer, int cmp, int event, int enable) wrmsr(msr, value, dummy); return 0; } +EXPORT_SYMBOL_GPL(geode_mfgpt_toggle_event); int geode_mfgpt_set_irq(int timer, int cmp, int irq, int enable) { @@ -222,6 +223,7 @@ int geode_mfgpt_alloc_timer(int timer, int domain) /* No timers available - too bad */ return -1; } +EXPORT_SYMBOL_GPL(geode_mfgpt_alloc_timer); #ifdef CONFIG_GEODE_MFGPT_TIMER diff --git a/arch/x86/kernel/nmi_32.c b/arch/x86/kernel/nmi_32.c index 11b14bbaa61e..84160f74eeb0 100644 --- a/arch/x86/kernel/nmi_32.c +++ b/arch/x86/kernel/nmi_32.c @@ -26,7 +26,6 @@ #include <asm/smp.h> #include <asm/nmi.h> -#include <asm/timer.h> #include "mach_traps.h" @@ -82,7 +81,7 @@ int __init check_nmi_watchdog(void) prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL); if (!prev_nmi_count) - goto error; + return -1; printk(KERN_INFO "Testing NMI watchdog ... "); @@ -119,7 +118,7 @@ int __init check_nmi_watchdog(void) if (!atomic_read(&nmi_active)) { kfree(prev_nmi_count); atomic_set(&nmi_active, -1); - goto error; + return -1; } printk("OK.\n"); @@ -130,10 +129,6 @@ int __init check_nmi_watchdog(void) kfree(prev_nmi_count); return 0; -error: - timer_ack = !cpu_has_tsc; - - return -1; } static int __init setup_nmi_watchdog(char *str) diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c index 9615eee9b775..05191bbc68b8 100644 --- a/arch/x86/kernel/rtc.c +++ b/arch/x86/kernel/rtc.c @@ -4,6 +4,8 @@ #include <linux/acpi.h> #include <linux/bcd.h> #include <linux/mc146818rtc.h> +#include <linux/platform_device.h> +#include <linux/pnp.h> #include <asm/time.h> #include <asm/vsyscall.h> @@ -197,3 +199,35 @@ unsigned long long native_read_tsc(void) } EXPORT_SYMBOL(native_read_tsc); + +static struct resource rtc_resources[] = { + [0] = { + .start = RTC_PORT(0), + .end = RTC_PORT(1), + .flags = IORESOURCE_IO, + }, + [1] = { + .start = RTC_IRQ, + .end = RTC_IRQ, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device rtc_device = { + .name = "rtc_cmos", + .id = -1, + .resource = rtc_resources, + .num_resources = ARRAY_SIZE(rtc_resources), +}; + +static __init int add_rtc_cmos(void) +{ +#ifdef CONFIG_PNP + if (!pnp_platform_devices) + platform_device_register(&rtc_device); +#else + platform_device_register(&rtc_device); +#endif /* CONFIG_PNP */ + return 0; +} +device_initcall(add_rtc_cmos); diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index bde6f63e15d5..08d752de4eee 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c @@ -544,6 +544,7 @@ vm86_trap: #define DO_ERROR(trapnr, signr, str, name) \ void do_##name(struct pt_regs *regs, long error_code) \ { \ + trace_hardirqs_fixup(); \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ == NOTIFY_STOP) \ return; \ diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 7c077a9d9777..f2f5d260874e 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c @@ -200,7 +200,6 @@ int __pit_timer_fn(struct kvm_kpit_state *ps) atomic_inc(&pt->pending); smp_mb__after_atomic_inc(); - /* FIXME: handle case where the guest is in guest mode */ if (vcpu0 && waitqueue_active(&vcpu0->wq)) { vcpu0->arch.mp_state = KVM_MP_STATE_RUNNABLE; wake_up_interruptible(&vcpu0->wq); @@ -237,6 +236,19 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data) return HRTIMER_NORESTART; } +void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu) +{ + struct kvm_pit *pit = vcpu->kvm->arch.vpit; + struct hrtimer *timer; + + if (vcpu->vcpu_id != 0 || !pit) + return; + + timer = &pit->pit_state.pit_timer.timer; + if (hrtimer_cancel(timer)) + hrtimer_start(timer, timer->expires, HRTIMER_MODE_ABS); +} + static void destroy_pit_timer(struct kvm_kpit_timer *pt) { pr_debug("pit: execute del timer!\n"); diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c index ce1f583459b1..76d736b5f664 100644 --- a/arch/x86/kvm/irq.c +++ b/arch/x86/kvm/irq.c @@ -94,3 +94,9 @@ void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec) /* TODO: PIT, RTC etc. */ } EXPORT_SYMBOL_GPL(kvm_timer_intr_post); + +void __kvm_migrate_timers(struct kvm_vcpu *vcpu) +{ + __kvm_migrate_apic_timer(vcpu); + __kvm_migrate_pit_timer(vcpu); +} diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h index 1802134b836f..2a15be2275c0 100644 --- a/arch/x86/kvm/irq.h +++ b/arch/x86/kvm/irq.h @@ -84,6 +84,8 @@ void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec); void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu); void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu); void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu); +void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu); +void __kvm_migrate_timers(struct kvm_vcpu *vcpu); int pit_has_pending_timer(struct kvm_vcpu *vcpu); int apic_has_pending_timer(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 7246b60afb96..ee3f53098f0c 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -658,7 +658,7 @@ static int is_empty_shadow_page(u64 *spt) u64 *end; for (pos = spt, end = pos + PAGE_SIZE / sizeof(u64); pos != end; pos++) - if (*pos != shadow_trap_nonpresent_pte) { + if (is_shadow_present_pte(*pos)) { printk(KERN_ERR "%s: %p %llx\n", __func__, pos, *pos); return 0; @@ -1858,6 +1858,7 @@ static void free_mmu_pages(struct kvm_vcpu *vcpu) sp = container_of(vcpu->kvm->arch.active_mmu_pages.next, struct kvm_mmu_page, link); kvm_mmu_zap_page(vcpu->kvm, sp); + cond_resched(); } free_page((unsigned long)vcpu->arch.mmu.pae_root); } diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 156fe10288ae..934c7b619396 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h @@ -418,7 +418,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, /* mmio */ if (is_error_pfn(pfn)) { - pgprintk("gfn %x is mmio\n", walker.gfn); + pgprintk("gfn %lx is mmio\n", walker.gfn); kvm_release_pfn_clean(pfn); return 1; } diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index ab22615eee89..6b0d5fa5bab3 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -688,7 +688,7 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu) delta = vcpu->arch.host_tsc - tsc_this; svm->vmcb->control.tsc_offset += delta; vcpu->cpu = cpu; - kvm_migrate_apic_timer(vcpu); + kvm_migrate_timers(vcpu); } for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index bfe4db11989c..02efbe75f317 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -608,7 +608,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) if (vcpu->cpu != cpu) { vcpu_clear(vmx); - kvm_migrate_apic_timer(vcpu); + kvm_migrate_timers(vcpu); vpid_sync_vcpu_all(vmx); } @@ -1036,6 +1036,7 @@ static void hardware_enable(void *garbage) static void hardware_disable(void *garbage) { asm volatile (ASM_VMX_VMXOFF : : : "cc"); + write_cr4(read_cr4() & ~X86_CR4_VMXE); } static __init int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 21338bdb28ff..00acf1301a15 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2758,7 +2758,7 @@ again: if (vcpu->requests) { if (test_and_clear_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests)) - __kvm_migrate_apic_timer(vcpu); + __kvm_migrate_timers(vcpu); if (test_and_clear_bit(KVM_REQ_REPORT_TPR_ACCESS, &vcpu->requests)) { kvm_run->exit_reason = KVM_EXIT_TPR_ACCESS; diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index 8a96320ab071..932f216d890c 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c @@ -1727,7 +1727,8 @@ twobyte_insn: if (rc) goto done; - kvm_emulate_hypercall(ctxt->vcpu); + /* Let the processor re-execute the fixed hypercall */ + c->eip = ctxt->vcpu->arch.rip; /* Disable writeback. */ c->dst.type = OP_NONE; break; diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index fd7e1798c75a..8bcb6f40ccb6 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -497,6 +497,11 @@ static int vmalloc_fault(unsigned long address) unsigned long pgd_paddr; pmd_t *pmd_k; pte_t *pte_k; + + /* Make sure we are in vmalloc area */ + if (!(address >= VMALLOC_START && address < VMALLOC_END)) + return -1; + /* * Synchronize this task's top level page-table * with the 'reference' page table. diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 3890234e5b26..99649dccad28 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c @@ -97,36 +97,9 @@ static __init inline int srat_disabled(void) return numa_off || acpi_numa < 0; } -/* - * A lot of BIOS fill in 10 (= no distance) everywhere. This messes - * up the NUMA heuristics which wants the local node to have a smaller - * distance than the others. - * Do some quick checks here and only use the SLIT if it passes. - */ -static __init int slit_valid(struct acpi_table_slit *slit) -{ - int i, j; - int d = slit->locality_count; - for (i = 0; i < d; i++) { - for (j = 0; j < d; j++) { - u8 val = slit->entry[d*i + j]; - if (i == j) { - if (val != LOCAL_DISTANCE) - return 0; - } else if (val <= LOCAL_DISTANCE) - return 0; - } - } - return 1; -} - /* Callback for SLIT parsing */ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) { - if (!slit_valid(slit)) { - printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n"); - return; - } acpi_slit = slit; } diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index c39e1a5aa241..52b2e3856980 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -12,6 +12,7 @@ #include <linux/clocksource.h> #include <linux/clockchips.h> #include <linux/kernel_stat.h> +#include <linux/math64.h> #include <asm/xen/hypervisor.h> #include <asm/xen/hypercall.h> @@ -150,11 +151,7 @@ static void do_stolen_accounting(void) if (stolen < 0) stolen = 0; - ticks = 0; - while (stolen >= NS_PER_TICK) { - ticks++; - stolen -= NS_PER_TICK; - } + ticks = iter_div_u64_rem(stolen, NS_PER_TICK, &stolen); __get_cpu_var(residual_stolen) = stolen; account_steal_time(NULL, ticks); @@ -166,11 +163,7 @@ static void do_stolen_accounting(void) if (blocked < 0) blocked = 0; - ticks = 0; - while (blocked >= NS_PER_TICK) { - ticks++; - blocked -= NS_PER_TICK; - } + ticks = iter_div_u64_rem(blocked, NS_PER_TICK, &blocked); __get_cpu_var(residual_blocked) = blocked; account_steal_time(idle_task(smp_processor_id()), ticks); } diff --git a/block/blktrace.c b/block/blktrace.c index 7ae87cc4a163..8d3a27780260 100644 --- a/block/blktrace.c +++ b/block/blktrace.c @@ -79,16 +79,17 @@ void __trace_note_message(struct blk_trace *bt, const char *fmt, ...) { int n; va_list args; + unsigned long flags; char *buf; - preempt_disable(); + local_irq_save(flags); buf = per_cpu_ptr(bt->msg_data, smp_processor_id()); va_start(args, fmt); n = vscnprintf(buf, BLK_TN_MAX_MSG, fmt, args); va_end(args); trace_note(bt, 0, BLK_TN_MESSAGE, buf, n); - preempt_enable(); + local_irq_restore(flags); } EXPORT_SYMBOL_GPL(__trace_note_message); @@ -158,10 +159,7 @@ void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, /* * A word about the locking here - we disable interrupts to reserve * some space in the relay per-cpu buffer, to prevent an irq - * from coming in and stepping on our toes. Once reserved, it's - * enough to get preemption disabled to prevent read of this data - * before we are through filling it. get_cpu()/put_cpu() does this - * for us + * from coming in and stepping on our toes. */ local_irq_save(flags); diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index d2fc94161848..26038c2a2a71 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c @@ -301,16 +301,20 @@ static int bay_add(acpi_handle handle, int id) */ pdev->dev.uevent_suppress = 0; - if (acpi_bay_add_fs(new_bay)) { - platform_device_unregister(new_bay->pdev); - goto bay_add_err; - } - /* register for events on this device */ status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, bay_notify, new_bay); if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Error installing bay notify handler\n"); + printk(KERN_INFO PREFIX "Error installing bay notify handler\n"); + platform_device_unregister(new_bay->pdev); + goto bay_add_err; + } + + if (acpi_bay_add_fs(new_bay)) { + acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, + bay_notify); + platform_device_unregister(new_bay->pdev); + goto bay_add_err; } /* if we are on a dock station, we should register for dock diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index c78078315be9..f988a5e7d2b4 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c @@ -450,10 +450,6 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, return_ACPI_STATUS(AE_BAD_PARAMETER); } - if (!arg) { - return_ACPI_STATUS(AE_AML_NO_OPERAND); - } - /* Creating new namespace node(s), should not already exist */ flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | @@ -467,6 +463,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, /* * Walk the list of entries in the field_list + * Note: field_list can be of zero length. In this case, Arg will be NULL. */ while (arg) { /* diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index fa44fb96fc34..96c542f7fded 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -834,7 +834,7 @@ static int dock_add(acpi_handle handle) goto dock_add_err; } - printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_DESCRIPTION); + printk(KERN_INFO PREFIX "%s\n", ACPI_DOCK_DRIVER_DESCRIPTION); return 0; diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 0924992187e8..5622aee996b2 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -194,7 +194,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event)) return 0; - udelay(ACPI_EC_UDELAY); + msleep(1); } } pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 24da921d13e3..39d742190584 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c @@ -375,9 +375,15 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, goto cleanup; } + /* + * Add the table to the namespace. + * + * Note: We load the table objects relative to the root of the namespace. + * This appears to go against the ACPI specification, but we do it for + * compatibility with other ACPI implementations. + */ status = - acpi_ex_add_table(table_index, walk_state->scope_info->scope.node, - &ddb_handle); + acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); if (ACPI_FAILURE(status)) { /* On error, table_ptr was deallocated above */ diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 06f8634fe58b..2808dc60fd67 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -272,6 +272,12 @@ static u32 rtc_handler(void *context) static inline void rtc_wake_setup(void) { acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); + /* + * After the RTC handler is installed, the Fixed_RTC event should + * be disabled. Only when the RTC alarm is set will it be enabled. + */ + acpi_clear_event(ACPI_EVENT_RTC); + acpi_disable_event(ACPI_EVENT_RTC, 0); } static void rtc_wake_on(struct device *dev) diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index d9937e05ec6a..dba3cfbe8cba 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c @@ -223,15 +223,17 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) break; } - /* Set the system indicators to show the desired sleep state. */ - + /* + * Set the system indicators to show the desired sleep state. + * _SST is an optional method (return no error if not found) + */ status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { ACPI_EXCEPTION((AE_INFO, status, "While executing method _SST")); } - return_ACPI_STATUS(status); + return_ACPI_STATUS(AE_OK); } ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 5d59cb33b1a5..658e5f3abae0 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -140,19 +140,42 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) } } +/* + * A lot of BIOS fill in 10 (= no distance) everywhere. This messes + * up the NUMA heuristics which wants the local node to have a smaller + * distance than the others. + * Do some quick checks here and only use the SLIT if it passes. + */ +static __init int slit_valid(struct acpi_table_slit *slit) +{ + int i, j; + int d = slit->locality_count; + for (i = 0; i < d; i++) { + for (j = 0; j < d; j++) { + u8 val = slit->entry[d*i + j]; + if (i == j) { + if (val != LOCAL_DISTANCE) + return 0; + } else if (val <= LOCAL_DISTANCE) + return 0; + } + } + return 1; +} + static int __init acpi_parse_slit(struct acpi_table_header *table) { struct acpi_table_slit *slit; - u32 localities; if (!table) return -EINVAL; slit = (struct acpi_table_slit *)table; - /* downcast just for %llu vs %lu for i386/ia64 */ - localities = (u32) slit->locality_count; - + if (!slit_valid(slit)) { + printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n"); + return -EINVAL; + } acpi_numa_slit_init(slit); return 0; diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index f1e8bf65e24e..e94463778845 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c @@ -268,7 +268,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, */ if (ACPI_SUCCESS(status) && possible_method_call && (node->type == ACPI_TYPE_METHOD)) { - if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) { + if (walk_state->opcode == AML_UNLOAD_OP) { /* * acpi_ps_get_next_namestring has increased the AML pointer, * so we need to restore the saved AML pointer for method call. @@ -691,7 +691,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, /* To support super_name arg of Unload */ - if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) { + if (walk_state->opcode == AML_UNLOAD_OP) { status = acpi_ps_get_next_namepath(walk_state, parser_state, arg, diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 386e5aa48834..9dd0fa93b9e1 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -86,7 +86,6 @@ static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); static void acpi_processor_notify(acpi_handle handle, u32 event, void *data); static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); static int acpi_processor_handle_eject(struct acpi_processor *pr); -extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr); static const struct acpi_device_id processor_device_ids[] = { diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 2dd2c1f3a01c..556ee1585192 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1669,6 +1669,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) return -EINVAL; } + dev->cpu = pr->id; for (i = 0; i < CPUIDLE_STATE_MAX; i++) { dev->states[i].name[0] = '\0'; dev->states[i].desc[0] = '\0'; @@ -1738,7 +1739,7 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) int acpi_processor_cst_has_changed(struct acpi_processor *pr) { - int ret; + int ret = 0; if (boot_option_idle_override) return 0; @@ -1756,8 +1757,10 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) cpuidle_pause_and_lock(); cpuidle_disable_device(&pr->power.dev); acpi_processor_get_power_info(pr); - acpi_processor_setup_cpuidle(pr); - ret = cpuidle_enable_device(&pr->power.dev); + if (pr->flags.power) { + acpi_processor_setup_cpuidle(pr); + ret = cpuidle_enable_device(&pr->power.dev); + } cpuidle_resume_and_unlock(); return ret; @@ -1813,7 +1816,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, if (pr->flags.power) { #ifdef CONFIG_CPU_IDLE acpi_processor_setup_cpuidle(pr); - pr->power.dev.cpu = pr->id; if (cpuidle_register_device(&pr->power.dev)) return -EIO; #endif @@ -1850,8 +1852,7 @@ int acpi_processor_power_exit(struct acpi_processor *pr, return 0; #ifdef CONFIG_CPU_IDLE - if (pr->flags.power) - cpuidle_unregister_device(&pr->power.dev); + cpuidle_unregister_device(&pr->power.dev); #endif pr->flags.power_setup_done = 0; diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 8a5fe8710513..224c57c03381 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c @@ -495,6 +495,12 @@ static int __init acpi_sleep_proc_init(void) acpi_root_dir, &acpi_system_alarm_fops); acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); + /* + * Disable the RTC event after installing RTC handler. + * Only when RTC alarm is set will it be enabled. + */ + acpi_clear_event(ACPI_EVENT_RTC); + acpi_disable_event(ACPI_EVENT_RTC, 0); #endif /* HAVE_ACPI_LEGACY_ALARM */ /* 'wakeup device' [R/W] */ diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 769f24855eb6..5bd2dec9a7ac 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -77,7 +77,6 @@ static ssize_t acpi_table_show(struct kobject *kobj, container_of(bin_attr, struct acpi_table_attr, attr); struct acpi_table_header *table_header = NULL; acpi_status status; - ssize_t ret_count = count; status = acpi_get_table(table_attr->name, table_attr->instance, @@ -85,18 +84,8 @@ static ssize_t acpi_table_show(struct kobject *kobj, if (ACPI_FAILURE(status)) return -ENODEV; - if (offset >= table_header->length) { - ret_count = 0; - goto end; - } - - if (offset + ret_count > table_header->length) - ret_count = table_header->length - offset; - - memcpy(buf, ((char *)table_header) + offset, ret_count); - - end: - return ret_count; + return memory_read_from_buffer(buf, count, &offset, + table_header, table_header->length); } static void acpi_table_attr_init(struct acpi_table_attr *table_attr, diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 402f93e1ff20..5336ce88f89f 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -123,24 +123,13 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, } } - /* The table must be either an SSDT or a PSDT or an OEMx */ - - if (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)&& - !ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)&& - strncmp(table_desc->pointer->signature, "OEM", 3)) { - /* Check for a printable name */ - if (acpi_ut_valid_acpi_name( - *(u32 *) table_desc->pointer->signature)) { - ACPI_ERROR((AE_INFO, "Table has invalid signature " - "[%4.4s], must be SSDT or PSDT", - table_desc->pointer->signature)); - } else { - ACPI_ERROR((AE_INFO, "Table has invalid signature " - "(0x%8.8X), must be SSDT or PSDT", - *(u32 *) table_desc->pointer->signature)); - } - return_ACPI_STATUS(AE_BAD_SIGNATURE); - } + /* + * Originally, we checked the table signature for "SSDT" or "PSDT" here. + * Next, we added support for OEMx tables, signature "OEM". + * Valid tables were encountered with a null signature, so we've just + * given up on validating the signature, since it seems to be a waste + * of code. The original code was removed (05/2008). + */ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index fb57b93c2495..0e319604d3e7 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c @@ -540,7 +540,7 @@ static acpi_status acpi_tb_load_namespace(void) acpi_tb_print_table_header(0, table); if (no_auto_ssdt == 0) { - printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\""); + printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n"); } } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 504385b1f211..84c795fb9b1e 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -364,10 +364,17 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) if (flag & ACPI_TRIPS_CRITICAL) { status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tz->trips.critical.temperature); - if (ACPI_FAILURE(status)) { + /* + * Treat freezing temperatures as invalid as well; some + * BIOSes return really low values and cause reboots at startup. + * Below zero (Celcius) values clearly aren't right for sure.. + * ... so lets discard those as invalid. + */ + if (ACPI_FAILURE(status) || + tz->trips.critical.temperature <= 2732) { tz->trips.critical.flags.valid = 0; ACPI_EXCEPTION((AE_INFO, status, - "No critical threshold")); + "No or invalid critical threshold")); return -ENODEV; } else { tz->trips.critical.flags.valid = 1; diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index e4ba7192cd15..1f057b71db1a 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c @@ -1048,6 +1048,7 @@ acpi_ut_exception(char *module_name, va_start(args, format); acpi_os_vprintf(format, args); acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); + va_end(args); } EXPORT_SYMBOL(acpi_ut_exception); @@ -1063,7 +1064,6 @@ acpi_ut_warning(char *module_name, u32 line_number, char *format, ...) acpi_os_vprintf(format, args); acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); va_end(args); - va_end(args); } void ACPI_INTERNAL_VAR_XFACE diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h index d04fefb0841f..e4c9525e60b3 100644 --- a/drivers/atm/eni.h +++ b/drivers/atm/eni.h @@ -18,7 +18,6 @@ #include "midway.h" -#define KERNEL_OFFSET 0xC0000000 /* kernel 0x0 is at phys 0xC0000000 */ #define DEV_LABEL "eni" #define UBR_BUFFER (128*1024) /* UBR buffer size */ diff --git a/drivers/base/core.c b/drivers/base/core.c index 422cfcad486d..ee0a51a3a41d 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -762,6 +762,7 @@ static void device_remove_class_symlinks(struct device *dev) /** * dev_set_name - set a device name * @dev: device + * @fmt: format string for the device's name */ int dev_set_name(struct device *dev, const char *fmt, ...) { diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index e336b05fe4a7..5f1e1cc6165a 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -53,15 +53,16 @@ #include <linux/scatterlist.h> #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "HP CISS Driver (v 3.6.14)" -#define DRIVER_VERSION CCISS_DRIVER_VERSION(3,6,14) +#define DRIVER_NAME "HP CISS Driver (v 3.6.20)" +#define DRIVER_VERSION CCISS_DRIVER_VERSION(3, 6, 20) /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); -MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 3.6.14"); +MODULE_DESCRIPTION("Driver for HP Smart Array Controllers"); MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" - " SA6i P600 P800 P400 P400i E200 E200i E500"); -MODULE_VERSION("3.6.14"); + " SA6i P600 P800 P400 P400i E200 E200i E500 P700m" + " Smart Array G2 Series SAS/SATA Controllers"); +MODULE_VERSION("3.6.20"); MODULE_LICENSE("GPL"); #include "cciss_cmd.h" @@ -90,6 +91,11 @@ static const struct pci_device_id cciss_pci_device_id[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3237}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x323D}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3243}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, {0,} @@ -123,6 +129,11 @@ static struct board_type products[] = { {0x3215103C, "Smart Array E200i", &SA5_access, 120}, {0x3237103C, "Smart Array E500", &SA5_access, 512}, {0x323D103C, "Smart Array P700m", &SA5_access, 512}, + {0x3241103C, "Smart Array P212", &SA5_access, 384}, + {0x3243103C, "Smart Array P410", &SA5_access, 384}, + {0x3245103C, "Smart Array P410i", &SA5_access, 384}, + {0x3247103C, "Smart Array P411", &SA5_access, 384}, + {0x3249103C, "Smart Array P812", &SA5_access, 384}, {0xFFFF103C, "Unknown Smart Array", &SA5_access, 120}, }; diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index d307bf26af58..2d854bb9373e 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -749,7 +749,7 @@ config NVRAM if RTC_LIB=n config RTC - tristate "Enhanced Real Time Clock Support" + tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)" depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV \ && !ARM && !SUPERH && !S390 && !AVR32 ---help--- @@ -1036,9 +1036,9 @@ config HPET non-periodic and/or periodic. config HPET_RTC_IRQ - bool "HPET Control RTC IRQ" if !HPET_EMULATE_RTC - default n - depends on HPET + bool + default HPET_EMULATE_RTC + depends on RTC && HPET help If you say Y here, you will disable RTC_IRQ in drivers/char/rtc.c. It is assumed the platform called hpet_alloc with the RTC IRQ values for diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 55c97f623242..07b4d8ff56e5 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -458,6 +458,10 @@ static struct agp_device_ids ati_agp_device_ids[] __devinitdata = .chipset_name = "IGP9100/M", }, { + .device_id = PCI_DEVICE_ID_ATI_RS350_133, + .chipset_name = "IGP9000/M", + }, + { .device_id = PCI_DEVICE_ID_ATI_RS350_200, .chipset_name = "IGP9100/M", }, diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c index 2398e864c28d..a00869c650d5 100644 --- a/drivers/char/generic_nvram.c +++ b/drivers/char/generic_nvram.c @@ -133,7 +133,7 @@ static struct miscdevice nvram_dev = { int __init nvram_init(void) { - printk(KERN_INFO "Macintosh non-volatile memory driver v%s\n", + printk(KERN_INFO "Generic non-volatile memory driver v%s\n", NVRAM_VERSION); return misc_register(&nvram_dev); } diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 5cc651ef75eb..27fdc0866496 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -273,7 +273,7 @@ static int __init intel_rng_hw_init(void *_intel_rng_hw) if (mfc != INTEL_FWH_MANUFACTURER_CODE || (dvc != INTEL_FWH_DEVICE_CODE_8M && dvc != INTEL_FWH_DEVICE_CODE_4M)) { - printk(KERN_ERR PFX "FWH not detected\n"); + printk(KERN_NOTICE PFX "FWH not detected\n"); return -ENODEV; } diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 7f7e798c1384..d9a0a53c842d 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -677,12 +677,7 @@ static void k_deadunicode(struct vc_data *vc, unsigned int value, char up_flag) static void k_self(struct vc_data *vc, unsigned char value, char up_flag) { - unsigned int uni; - if (kbd->kbdmode == VC_UNICODE) - uni = value; - else - uni = conv_8bit_to_uni(value); - k_unicode(vc, uni, up_flag); + k_unicode(vc, conv_8bit_to_uni(value), up_flag); } static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag) diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fc555a90bb21..23554b676d6e 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -38,6 +38,8 @@ static void cpuidle_kick_cpus(void) static void cpuidle_kick_cpus(void) {} #endif +static int __cpuidle_register_device(struct cpuidle_device *dev); + /** * cpuidle_idle_call - the main idle loop * @@ -138,6 +140,12 @@ int cpuidle_enable_device(struct cpuidle_device *dev) if (!dev->state_count) return -EINVAL; + if (dev->registered == 0) { + ret = __cpuidle_register_device(dev); + if (ret) + return ret; + } + if ((ret = cpuidle_add_state_sysfs(dev))) return ret; @@ -232,10 +240,13 @@ static void poll_idle_init(struct cpuidle_device *dev) {} #endif /* CONFIG_ARCH_HAS_CPU_RELAX */ /** - * cpuidle_register_device - registers a CPU's idle PM feature + * __cpuidle_register_device - internal register function called before register + * and enable routines * @dev: the cpu + * + * cpuidle_lock mutex must be held before this is called */ -int cpuidle_register_device(struct cpuidle_device *dev) +static int __cpuidle_register_device(struct cpuidle_device *dev) { int ret; struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); @@ -247,18 +258,34 @@ int cpuidle_register_device(struct cpuidle_device *dev) init_completion(&dev->kobj_unregister); - mutex_lock(&cpuidle_lock); - poll_idle_init(dev); per_cpu(cpuidle_devices, dev->cpu) = dev; list_add(&dev->device_list, &cpuidle_detected_devices); if ((ret = cpuidle_add_sysfs(sys_dev))) { - mutex_unlock(&cpuidle_lock); module_put(cpuidle_curr_driver->owner); return ret; } + dev->registered = 1; + return 0; +} + +/** + * cpuidle_register_device - registers a CPU's idle PM feature + * @dev: the cpu + */ +int cpuidle_register_device(struct cpuidle_device *dev) +{ + int ret; + + mutex_lock(&cpuidle_lock); + + if ((ret = __cpuidle_register_device(dev))) { + mutex_unlock(&cpuidle_lock); + return ret; + } + cpuidle_enable_device(dev); cpuidle_install_idle_handler(); @@ -278,6 +305,9 @@ void cpuidle_unregister_device(struct cpuidle_device *dev) { struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); + if (dev->registered == 0) + return; + cpuidle_pause_and_lock(); cpuidle_disable_device(dev); diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c index 5fcbdccd7a53..16a874bb1561 100644 --- a/drivers/isdn/hardware/eicon/divasmain.c +++ b/drivers/isdn/hardware/eicon/divasmain.c @@ -806,7 +806,6 @@ static int DIVA_INIT_FUNCTION divas_init(void) if (!create_divas_proc()) { #ifdef MODULE - remove_divas_proc(); divas_unregister_chrdev(); divasfunc_exit(); #endif diff --git a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c index fae895828a17..040827288ec9 100644 --- a/drivers/isdn/hardware/eicon/divasproc.c +++ b/drivers/isdn/hardware/eicon/divasproc.c @@ -125,8 +125,8 @@ static const struct file_operations divas_fops = { int create_divas_proc(void) { - proc_create(divas_proc_name, S_IFREG | S_IRUGO, proc_net_eicon, - &divas_fops); + divas_proc_entry = proc_create(divas_proc_name, S_IFREG | S_IRUGO, + proc_net_eicon, &divas_fops); if (!divas_proc_entry) return (0); diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c index 15906d005b05..484299b031f8 100644 --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ b/drivers/isdn/hysdn/hysdn_procconf.c @@ -207,30 +207,17 @@ hysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t /* read conf file -> output card info data */ /*******************************************/ static ssize_t -hysdn_conf_read(struct file *file, char __user *buf, size_t count, loff_t * off) +hysdn_conf_read(struct file *file, char __user *buf, size_t count, loff_t *off) { char *cp; - int i; - if (file->f_mode & FMODE_READ) { - if (!(cp = file->private_data)) - return (-EFAULT); /* should never happen */ - i = strlen(cp); /* get total string length */ - if (*off < i) { - /* still bytes to transfer */ - cp += *off; /* point to desired data offset */ - i -= *off; /* remaining length */ - if (i > count) - i = count; /* limit length to transfer */ - if (copy_to_user(buf, cp, i)) - return (-EFAULT); /* copy error */ - *off += i; /* adjust offset */ - } else - return (0); - } else - return (-EPERM); /* no permission to read */ - - return (i); + if (!(file->f_mode & FMODE_READ)) + return -EPERM; /* no permission to read */ + + if (!(cp = file->private_data)) + return -EFAULT; /* should never happen */ + + return simple_read_from_buffer(buf, count, off, cp, strlen(cp)); } /* hysdn_conf_read */ /******************/ diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c index 7817d2244921..1081091bbfaf 100644 --- a/drivers/isdn/sc/ioctl.c +++ b/drivers/isdn/sc/ioctl.c @@ -226,6 +226,7 @@ int sc_ioctl(int card, scs_ioctl *data) */ if (copy_from_user(spid, data->dataptr, SCIOC_SPIDSIZE)) { kfree(rcvmsg); + kfree(spid); return -EFAULT; } diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index a0ce0b2fa03e..b5969298f3d3 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -1293,7 +1293,7 @@ static void tpacpi_input_send_radiosw(void) mutex_lock(&tpacpi_inputdev_send_mutex); input_report_switch(tpacpi_inputdev, - SW_RADIO, !!wlsw); + SW_RFKILL_ALL, !!wlsw); input_sync(tpacpi_inputdev); mutex_unlock(&tpacpi_inputdev_send_mutex); @@ -1921,6 +1921,29 @@ static struct attribute *hotkey_mask_attributes[] __initdata = { &dev_attr_hotkey_wakeup_hotunplug_complete.attr, }; +static void hotkey_exit(void) +{ +#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL + hotkey_poll_stop_sync(); +#endif + + if (hotkey_dev_attributes) + delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); + + kfree(hotkey_keycode_map); + + if (tp_features.hotkey) { + dbg_printk(TPACPI_DBG_EXIT, + "restoring original hot key mask\n"); + /* no short-circuit boolean operator below! */ + if ((hotkey_mask_set(hotkey_orig_mask) | + hotkey_status_set(hotkey_orig_status)) != 0) + printk(TPACPI_ERR + "failed to restore hot key mask " + "to BIOS defaults\n"); + } +} + static int __init hotkey_init(struct ibm_init_struct *iibm) { /* Requirements for changing the default keymaps: @@ -2060,226 +2083,220 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n", str_supported(tp_features.hotkey)); - if (tp_features.hotkey) { - hotkey_dev_attributes = create_attr_set(13, NULL); - if (!hotkey_dev_attributes) - return -ENOMEM; - res = add_many_to_attr_set(hotkey_dev_attributes, - hotkey_attributes, - ARRAY_SIZE(hotkey_attributes)); - if (res) - return res; + if (!tp_features.hotkey) + return 1; - /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, - A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking - for HKEY interface version 0x100 */ - if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { - if ((hkeyv >> 8) != 1) { - printk(TPACPI_ERR "unknown version of the " - "HKEY interface: 0x%x\n", hkeyv); - printk(TPACPI_ERR "please report this to %s\n", - TPACPI_MAIL); - } else { - /* - * MHKV 0x100 in A31, R40, R40e, - * T4x, X31, and later - */ - tp_features.hotkey_mask = 1; - } + hotkey_dev_attributes = create_attr_set(13, NULL); + if (!hotkey_dev_attributes) + return -ENOMEM; + res = add_many_to_attr_set(hotkey_dev_attributes, + hotkey_attributes, + ARRAY_SIZE(hotkey_attributes)); + if (res) + goto err_exit; + + /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, + A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking + for HKEY interface version 0x100 */ + if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { + if ((hkeyv >> 8) != 1) { + printk(TPACPI_ERR "unknown version of the " + "HKEY interface: 0x%x\n", hkeyv); + printk(TPACPI_ERR "please report this to %s\n", + TPACPI_MAIL); + } else { + /* + * MHKV 0x100 in A31, R40, R40e, + * T4x, X31, and later + */ + tp_features.hotkey_mask = 1; } + } - vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", - str_supported(tp_features.hotkey_mask)); + vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", + str_supported(tp_features.hotkey_mask)); - if (tp_features.hotkey_mask) { - if (!acpi_evalf(hkey_handle, &hotkey_all_mask, - "MHKA", "qd")) { - printk(TPACPI_ERR - "missing MHKA handler, " - "please report this to %s\n", - TPACPI_MAIL); - /* FN+F12, FN+F4, FN+F3 */ - hotkey_all_mask = 0x080cU; - } + if (tp_features.hotkey_mask) { + if (!acpi_evalf(hkey_handle, &hotkey_all_mask, + "MHKA", "qd")) { + printk(TPACPI_ERR + "missing MHKA handler, " + "please report this to %s\n", + TPACPI_MAIL); + /* FN+F12, FN+F4, FN+F3 */ + hotkey_all_mask = 0x080cU; } + } - /* hotkey_source_mask *must* be zero for - * the first hotkey_mask_get */ - res = hotkey_status_get(&hotkey_orig_status); - if (!res && tp_features.hotkey_mask) { - res = hotkey_mask_get(); - hotkey_orig_mask = hotkey_mask; - if (!res) { - res = add_many_to_attr_set( - hotkey_dev_attributes, - hotkey_mask_attributes, - ARRAY_SIZE(hotkey_mask_attributes)); - } - } + /* hotkey_source_mask *must* be zero for + * the first hotkey_mask_get */ + res = hotkey_status_get(&hotkey_orig_status); + if (res) + goto err_exit; + + if (tp_features.hotkey_mask) { + res = hotkey_mask_get(); + if (res) + goto err_exit; + + hotkey_orig_mask = hotkey_mask; + res = add_many_to_attr_set( + hotkey_dev_attributes, + hotkey_mask_attributes, + ARRAY_SIZE(hotkey_mask_attributes)); + if (res) + goto err_exit; + } #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - if (tp_features.hotkey_mask) { - hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK - & ~hotkey_all_mask; - } else { - hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; - } + if (tp_features.hotkey_mask) { + hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK + & ~hotkey_all_mask; + } else { + hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; + } - vdbg_printk(TPACPI_DBG_INIT, - "hotkey source mask 0x%08x, polling freq %d\n", - hotkey_source_mask, hotkey_poll_freq); + vdbg_printk(TPACPI_DBG_INIT, + "hotkey source mask 0x%08x, polling freq %d\n", + hotkey_source_mask, hotkey_poll_freq); #endif - /* Not all thinkpads have a hardware radio switch */ - if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { - tp_features.hotkey_wlsw = 1; - printk(TPACPI_INFO - "radio switch found; radios are %s\n", - enabled(status, 0)); - res = add_to_attr_set(hotkey_dev_attributes, - &dev_attr_hotkey_radio_sw.attr); - } + /* Not all thinkpads have a hardware radio switch */ + if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { + tp_features.hotkey_wlsw = 1; + printk(TPACPI_INFO + "radio switch found; radios are %s\n", + enabled(status, 0)); + res = add_to_attr_set(hotkey_dev_attributes, + &dev_attr_hotkey_radio_sw.attr); + } - /* For X41t, X60t, X61t Tablets... */ - if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { - tp_features.hotkey_tablet = 1; - printk(TPACPI_INFO - "possible tablet mode switch found; " - "ThinkPad in %s mode\n", - (status & TP_HOTKEY_TABLET_MASK)? - "tablet" : "laptop"); - res = add_to_attr_set(hotkey_dev_attributes, - &dev_attr_hotkey_tablet_mode.attr); - } + /* For X41t, X60t, X61t Tablets... */ + if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { + tp_features.hotkey_tablet = 1; + printk(TPACPI_INFO + "possible tablet mode switch found; " + "ThinkPad in %s mode\n", + (status & TP_HOTKEY_TABLET_MASK)? + "tablet" : "laptop"); + res = add_to_attr_set(hotkey_dev_attributes, + &dev_attr_hotkey_tablet_mode.attr); + } - if (!res) - res = register_attr_set_with_sysfs( - hotkey_dev_attributes, - &tpacpi_pdev->dev.kobj); - if (res) - return res; + if (!res) + res = register_attr_set_with_sysfs( + hotkey_dev_attributes, + &tpacpi_pdev->dev.kobj); + if (res) + goto err_exit; - /* Set up key map */ + /* Set up key map */ - hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, - GFP_KERNEL); - if (!hotkey_keycode_map) { - printk(TPACPI_ERR - "failed to allocate memory for key map\n"); - return -ENOMEM; - } + hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, + GFP_KERNEL); + if (!hotkey_keycode_map) { + printk(TPACPI_ERR + "failed to allocate memory for key map\n"); + res = -ENOMEM; + goto err_exit; + } - if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { - dbg_printk(TPACPI_DBG_INIT, - "using Lenovo default hot key map\n"); - memcpy(hotkey_keycode_map, &lenovo_keycode_map, - TPACPI_HOTKEY_MAP_SIZE); + if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { + dbg_printk(TPACPI_DBG_INIT, + "using Lenovo default hot key map\n"); + memcpy(hotkey_keycode_map, &lenovo_keycode_map, + TPACPI_HOTKEY_MAP_SIZE); + } else { + dbg_printk(TPACPI_DBG_INIT, + "using IBM default hot key map\n"); + memcpy(hotkey_keycode_map, &ibm_keycode_map, + TPACPI_HOTKEY_MAP_SIZE); + } + + set_bit(EV_KEY, tpacpi_inputdev->evbit); + set_bit(EV_MSC, tpacpi_inputdev->evbit); + set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); + tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; + tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; + tpacpi_inputdev->keycode = hotkey_keycode_map; + for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { + if (hotkey_keycode_map[i] != KEY_RESERVED) { + set_bit(hotkey_keycode_map[i], + tpacpi_inputdev->keybit); } else { - dbg_printk(TPACPI_DBG_INIT, - "using IBM default hot key map\n"); - memcpy(hotkey_keycode_map, &ibm_keycode_map, - TPACPI_HOTKEY_MAP_SIZE); - } - - set_bit(EV_KEY, tpacpi_inputdev->evbit); - set_bit(EV_MSC, tpacpi_inputdev->evbit); - set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); - tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; - tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; - tpacpi_inputdev->keycode = hotkey_keycode_map; - for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { - if (hotkey_keycode_map[i] != KEY_RESERVED) { - set_bit(hotkey_keycode_map[i], - tpacpi_inputdev->keybit); - } else { - if (i < sizeof(hotkey_reserved_mask)*8) - hotkey_reserved_mask |= 1 << i; - } - } - - if (tp_features.hotkey_wlsw) { - set_bit(EV_SW, tpacpi_inputdev->evbit); - set_bit(SW_RADIO, tpacpi_inputdev->swbit); - } - if (tp_features.hotkey_tablet) { - set_bit(EV_SW, tpacpi_inputdev->evbit); - set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); + if (i < sizeof(hotkey_reserved_mask)*8) + hotkey_reserved_mask |= 1 << i; } + } - /* Do not issue duplicate brightness change events to - * userspace */ - if (!tp_features.bright_acpimode) - /* update bright_acpimode... */ - tpacpi_check_std_acpi_brightness_support(); - - if (tp_features.bright_acpimode) { - printk(TPACPI_INFO - "This ThinkPad has standard ACPI backlight " - "brightness control, supported by the ACPI " - "video driver\n"); - printk(TPACPI_NOTICE - "Disabling thinkpad-acpi brightness events " - "by default...\n"); - - /* The hotkey_reserved_mask change below is not - * necessary while the keys are at KEY_RESERVED in the - * default map, but better safe than sorry, leave it - * here as a marker of what we have to do, especially - * when we finally become able to set this at runtime - * on response to X.org requests */ - hotkey_reserved_mask |= - (1 << TP_ACPI_HOTKEYSCAN_FNHOME) - | (1 << TP_ACPI_HOTKEYSCAN_FNEND); - } + if (tp_features.hotkey_wlsw) { + set_bit(EV_SW, tpacpi_inputdev->evbit); + set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit); + } + if (tp_features.hotkey_tablet) { + set_bit(EV_SW, tpacpi_inputdev->evbit); + set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); + } - dbg_printk(TPACPI_DBG_INIT, - "enabling hot key handling\n"); - res = hotkey_status_set(1); - if (res) - return res; - res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask) - & ~hotkey_reserved_mask) - | hotkey_orig_mask); - if (res < 0 && res != -ENXIO) - return res; + /* Do not issue duplicate brightness change events to + * userspace */ + if (!tp_features.bright_acpimode) + /* update bright_acpimode... */ + tpacpi_check_std_acpi_brightness_support(); - dbg_printk(TPACPI_DBG_INIT, - "legacy hot key reporting over procfs %s\n", - (hotkey_report_mode < 2) ? - "enabled" : "disabled"); + if (tp_features.bright_acpimode) { + printk(TPACPI_INFO + "This ThinkPad has standard ACPI backlight " + "brightness control, supported by the ACPI " + "video driver\n"); + printk(TPACPI_NOTICE + "Disabling thinkpad-acpi brightness events " + "by default...\n"); + + /* The hotkey_reserved_mask change below is not + * necessary while the keys are at KEY_RESERVED in the + * default map, but better safe than sorry, leave it + * here as a marker of what we have to do, especially + * when we finally become able to set this at runtime + * on response to X.org requests */ + hotkey_reserved_mask |= + (1 << TP_ACPI_HOTKEYSCAN_FNHOME) + | (1 << TP_ACPI_HOTKEYSCAN_FNEND); + } + + dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n"); + res = hotkey_status_set(1); + if (res) { + hotkey_exit(); + return res; + } + res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask) + & ~hotkey_reserved_mask) + | hotkey_orig_mask); + if (res < 0 && res != -ENXIO) { + hotkey_exit(); + return res; + } - tpacpi_inputdev->open = &hotkey_inputdev_open; - tpacpi_inputdev->close = &hotkey_inputdev_close; + dbg_printk(TPACPI_DBG_INIT, + "legacy hot key reporting over procfs %s\n", + (hotkey_report_mode < 2) ? + "enabled" : "disabled"); - hotkey_poll_setup_safe(1); - tpacpi_input_send_radiosw(); - tpacpi_input_send_tabletsw(); - } + tpacpi_inputdev->open = &hotkey_inputdev_open; + tpacpi_inputdev->close = &hotkey_inputdev_close; - return (tp_features.hotkey)? 0 : 1; -} + hotkey_poll_setup_safe(1); + tpacpi_input_send_radiosw(); + tpacpi_input_send_tabletsw(); -static void hotkey_exit(void) -{ -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - hotkey_poll_stop_sync(); -#endif + return 0; - if (tp_features.hotkey) { - dbg_printk(TPACPI_DBG_EXIT, - "restoring original hot key mask\n"); - /* no short-circuit boolean operator below! */ - if ((hotkey_mask_set(hotkey_orig_mask) | - hotkey_status_set(hotkey_orig_status)) != 0) - printk(TPACPI_ERR - "failed to restore hot key mask " - "to BIOS defaults\n"); - } +err_exit: + delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); + hotkey_dev_attributes = NULL; - if (hotkey_dev_attributes) { - delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); - hotkey_dev_attributes = NULL; - } + return (res < 0)? res : 1; } static void hotkey_notify(struct ibm_struct *ibm, u32 event) @@ -3319,7 +3336,7 @@ static struct tpacpi_led_classdev tpacpi_led_thinklight = { static int __init light_init(struct ibm_init_struct *iibm) { - int rc = 0; + int rc; vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); @@ -3337,20 +3354,23 @@ static int __init light_init(struct ibm_init_struct *iibm) tp_features.light_status = acpi_evalf(ec_handle, NULL, "KBLT", "qv"); - vdbg_printk(TPACPI_DBG_INIT, "light is %s\n", - str_supported(tp_features.light)); + vdbg_printk(TPACPI_DBG_INIT, "light is %s, light status is %s\n", + str_supported(tp_features.light), + str_supported(tp_features.light_status)); - if (tp_features.light) { - rc = led_classdev_register(&tpacpi_pdev->dev, - &tpacpi_led_thinklight.led_classdev); - } + if (!tp_features.light) + return 1; + + rc = led_classdev_register(&tpacpi_pdev->dev, + &tpacpi_led_thinklight.led_classdev); if (rc < 0) { tp_features.light = 0; tp_features.light_status = 0; - } else { - rc = (tp_features.light)? 0 : 1; + } else { + rc = 0; } + return rc; } @@ -3833,7 +3853,7 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { "tpacpi::standby", }; -static int led_get_status(unsigned int led) +static int led_get_status(const unsigned int led) { int status; enum led_status_t led_s; @@ -3857,41 +3877,42 @@ static int led_get_status(unsigned int led) /* not reached */ } -static int led_set_status(unsigned int led, enum led_status_t ledstatus) +static int led_set_status(const unsigned int led, + const enum led_status_t ledstatus) { /* off, on, blink. Index is led_status_t */ - static const int led_sled_arg1[] = { 0, 1, 3 }; - static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */ - static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */ - static const int led_led_arg1[] = { 0, 0x80, 0xc0 }; + static const unsigned int led_sled_arg1[] = { 0, 1, 3 }; + static const unsigned int led_led_arg1[] = { 0, 0x80, 0xc0 }; int rc = 0; switch (led_supported) { case TPACPI_LED_570: - /* 570 */ - led = 1 << led; - if (!acpi_evalf(led_handle, NULL, NULL, "vdd", - led, led_sled_arg1[ledstatus])) - rc = -EIO; - break; + /* 570 */ + if (led > 7) + return -EINVAL; + if (!acpi_evalf(led_handle, NULL, NULL, "vdd", + (1 << led), led_sled_arg1[ledstatus])) + rc = -EIO; + break; case TPACPI_LED_OLD: - /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ - led = 1 << led; - rc = ec_write(TPACPI_LED_EC_HLMS, led); - if (rc >= 0) - rc = ec_write(TPACPI_LED_EC_HLBL, - led * led_exp_hlbl[ledstatus]); - if (rc >= 0) - rc = ec_write(TPACPI_LED_EC_HLCL, - led * led_exp_hlcl[ledstatus]); - break; + /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ + if (led > 7) + return -EINVAL; + rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led)); + if (rc >= 0) + rc = ec_write(TPACPI_LED_EC_HLBL, + (ledstatus == TPACPI_LED_BLINK) << led); + if (rc >= 0) + rc = ec_write(TPACPI_LED_EC_HLCL, + (ledstatus != TPACPI_LED_OFF) << led); + break; case TPACPI_LED_NEW: - /* all others */ - if (!acpi_evalf(led_handle, NULL, NULL, "vdd", - led, led_led_arg1[ledstatus])) - rc = -EIO; - break; + /* all others */ + if (!acpi_evalf(led_handle, NULL, NULL, "vdd", + led, led_led_arg1[ledstatus])) + rc = -EIO; + break; default: rc = -ENXIO; } @@ -3978,7 +3999,6 @@ static void led_exit(void) } kfree(tpacpi_leds); - tpacpi_leds = NULL; } static int __init led_init(struct ibm_init_struct *iibm) @@ -4802,7 +4822,6 @@ static void brightness_exit(void) vdbg_printk(TPACPI_DBG_EXIT, "calling backlight_device_unregister()\n"); backlight_device_unregister(ibm_backlight_device); - ibm_backlight_device = NULL; } } @@ -5764,11 +5783,16 @@ static int __init fan_init(struct ibm_init_struct *iibm) fan_control_access_mode != TPACPI_FAN_WR_NONE) { rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, &fan_attr_group); - if (!(rc < 0)) - rc = driver_create_file(&tpacpi_hwmon_pdriver.driver, - &driver_attr_fan_watchdog); if (rc < 0) return rc; + + rc = driver_create_file(&tpacpi_hwmon_pdriver.driver, + &driver_attr_fan_watchdog); + if (rc < 0) { + sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, + &fan_attr_group); + return rc; + } return 0; } else return 1; diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index be624a049c67..c303e7f57ab4 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -1457,17 +1457,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq) int ret; /* - * Allocate interrupt. - */ - - ret = request_irq(irq, wbsd_irq, IRQF_SHARED, DRIVER_NAME, host); - if (ret) - return ret; - - host->irq = irq; - - /* - * Set up tasklets. + * Set up tasklets. Must be done before requesting interrupt. */ tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned long)host); @@ -1480,6 +1470,15 @@ static int __devinit wbsd_request_irq(struct wbsd_host *host, int irq) tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host); + /* + * Allocate interrupt. + */ + ret = request_irq(irq, wbsd_irq, IRQF_SHARED, DRIVER_NAME, host); + if (ret) + return ret; + + host->irq = irq; + return 0; } diff --git a/drivers/net/7990.c b/drivers/net/7990.c index 750a46f4bc58..ad6b8a5b6574 100644 --- a/drivers/net/7990.c +++ b/drivers/net/7990.c @@ -506,6 +506,7 @@ int lance_open (struct net_device *dev) return res; } +EXPORT_SYMBOL_GPL(lance_open); int lance_close (struct net_device *dev) { @@ -521,6 +522,7 @@ int lance_close (struct net_device *dev) return 0; } +EXPORT_SYMBOL_GPL(lance_close); void lance_tx_timeout(struct net_device *dev) { @@ -529,7 +531,7 @@ void lance_tx_timeout(struct net_device *dev) dev->trans_start = jiffies; netif_wake_queue (dev); } - +EXPORT_SYMBOL_GPL(lance_tx_timeout); int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) { @@ -586,6 +588,7 @@ int lance_start_xmit (struct sk_buff *skb, struct net_device *dev) return 0; } +EXPORT_SYMBOL_GPL(lance_start_xmit); /* taken from the depca driver via a2065.c */ static void lance_load_multicast (struct net_device *dev) @@ -654,6 +657,7 @@ void lance_set_multicast (struct net_device *dev) if (!stopped) netif_start_queue (dev); } +EXPORT_SYMBOL_GPL(lance_set_multicast); #ifdef CONFIG_NET_POLL_CONTROLLER void lance_poll(struct net_device *dev) diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 6ddc911e7d15..99e0b4cdc56f 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -637,22 +637,6 @@ static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw) } /* - * Force the PHY into power saving mode using vendor magic. - */ -#ifdef CONFIG_PM -static void atl1_phy_enter_power_saving(struct atl1_hw *hw) -{ - atl1_write_phy_reg(hw, MII_DBG_ADDR, 0); - atl1_write_phy_reg(hw, MII_DBG_DATA, 0x124E); - atl1_write_phy_reg(hw, MII_DBG_ADDR, 2); - atl1_write_phy_reg(hw, MII_DBG_DATA, 0x3000); - atl1_write_phy_reg(hw, MII_DBG_ADDR, 3); - atl1_write_phy_reg(hw, MII_DBG_DATA, 0); - -} -#endif - -/* * Resets the PHY and make all config validate * hw - Struct containing variables accessed by shared code * @@ -2860,7 +2844,6 @@ disable_wol: ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC); ioread32(hw->hw_addr + REG_PCIE_PHYMISC); - atl1_phy_enter_power_saving(hw); hw->phy_configured = false; pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); exit: diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 287a61918739..faae01dc1c4b 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -1766,16 +1766,20 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) mutex_lock(&ehea_bcmc_regs.lock); /* Deregister old MAC in pHYP */ - ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); - if (ret) - goto out_upregs; + if (port->state == EHEA_PORT_UP) { + ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC); + if (ret) + goto out_upregs; + } port->mac_addr = cb0->port_mac_addr << 16; /* Register new MAC in pHYP */ - ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); - if (ret) - goto out_upregs; + if (port->state == EHEA_PORT_UP) { + ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); + if (ret) + goto out_upregs; + } ret = 0; diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 9eca97fb0a54..2cb244763292 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -3273,6 +3273,20 @@ static void nv_link_irq(struct net_device *dev) dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name); } +static void nv_msi_workaround(struct fe_priv *np) +{ + + /* Need to toggle the msi irq mask within the ethernet device, + * otherwise, future interrupts will not be detected. + */ + if (np->msi_flags & NV_MSI_ENABLED) { + u8 __iomem *base = np->base; + + writel(0, base + NvRegMSIIrqMask); + writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); + } +} + static irqreturn_t nv_nic_irq(int foo, void *data) { struct net_device *dev = (struct net_device *) data; @@ -3295,6 +3309,8 @@ static irqreturn_t nv_nic_irq(int foo, void *data) if (!(events & np->irqmask)) break; + nv_msi_workaround(np); + spin_lock(&np->lock); nv_tx_done(dev); spin_unlock(&np->lock); @@ -3410,6 +3426,8 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) if (!(events & np->irqmask)) break; + nv_msi_workaround(np); + spin_lock(&np->lock); nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); spin_unlock(&np->lock); @@ -3750,6 +3768,8 @@ static irqreturn_t nv_nic_irq_test(int foo, void *data) if (!(events & NVREG_IRQ_TIMER)) return IRQ_RETVAL(0); + nv_msi_workaround(np); + spin_lock(&np->lock); np->intr_test = 1; spin_unlock(&np->lock); diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index ce816ba9c40d..e6317557a531 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -329,6 +329,7 @@ config PXA_FICP config MCS_FIR tristate "MosChip MCS7780 IrDA-USB dongle" depends on IRDA && USB && EXPERIMENTAL + select CRC32 help Say Y or M here if you want to build support for the MosChip MCS7780 IrDA-USB bridge device driver. diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 6321b059ce13..2f38e847e2cd 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -58,8 +58,8 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw); static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw) { - hw->mac.num_rx_queues = IXGBE_82598_MAX_TX_QUEUES; - hw->mac.num_tx_queues = IXGBE_82598_MAX_RX_QUEUES; + hw->mac.num_rx_queues = IXGBE_82598_MAX_RX_QUEUES; + hw->mac.num_tx_queues = IXGBE_82598_MAX_TX_QUEUES; hw->mac.num_rx_addrs = IXGBE_82598_RAR_ENTRIES; /* PHY ops are filled in by default properly for Fiber only */ diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 58a26a47af29..bafb69b6f7cb 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -341,12 +341,6 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) struct pppox_sock *relay_po; if (sk->sk_state & PPPOX_BOUND) { - struct pppoe_hdr *ph = pppoe_hdr(skb); - int len = ntohs(ph->length); - skb_pull_rcsum(skb, sizeof(struct pppoe_hdr)); - if (pskb_trim_rcsum(skb, len)) - goto abort_kfree; - ppp_input(&po->chan, skb); } else if (sk->sk_state & PPPOX_RELAY) { relay_po = get_item_by_addr(&po->pppoe_relay); @@ -357,7 +351,6 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) if ((sk_pppox(relay_po)->sk_state & PPPOX_CONNECTED) == 0) goto abort_put; - skb_pull(skb, sizeof(struct pppoe_hdr)); if (!__pppoe_xmit(sk_pppox(relay_po), skb)) goto abort_put; } else { @@ -388,6 +381,7 @@ static int pppoe_rcv(struct sk_buff *skb, { struct pppoe_hdr *ph; struct pppox_sock *po; + int len; if (!(skb = skb_share_check(skb, GFP_ATOMIC))) goto out; @@ -399,10 +393,21 @@ static int pppoe_rcv(struct sk_buff *skb, goto drop; ph = pppoe_hdr(skb); + len = ntohs(ph->length); + + skb_pull_rcsum(skb, sizeof(*ph)); + if (skb->len < len) + goto drop; po = get_item(ph->sid, eth_hdr(skb)->h_source, dev->ifindex); - if (po != NULL) - return sk_receive_skb(sk_pppox(po), skb, 0); + if (!po) + goto drop; + + if (pskb_trim_rcsum(skb, len)) + goto drop; + + return sk_receive_skb(sk_pppox(po), skb, 0); + drop: kfree_skb(skb); out: @@ -427,12 +432,12 @@ static int pppoe_disc_rcv(struct sk_buff *skb, if (dev_net(dev) != &init_net) goto abort; - if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) - goto abort; - if (!(skb = skb_share_check(skb, GFP_ATOMIC))) goto out; + if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) + goto abort; + ph = pppoe_hdr(skb); if (ph->code != PADT_CODE) goto abort; @@ -937,12 +942,10 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, m->msg_namelen = 0; if (skb) { - struct pppoe_hdr *ph = pppoe_hdr(skb); - const int len = ntohs(ph->length); - - error = memcpy_toiovec(m->msg_iov, (unsigned char *) &ph->tag[0], len); + total_len = min(total_len, skb->len); + error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len); if (error == 0) - error = len; + error = total_len; } kfree_skb(skb); diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 70cfdb46aa27..f9298827a76c 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -783,14 +783,18 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, err = 0; skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &err); - if (skb) { - err = memcpy_toiovec(msg->msg_iov, (unsigned char *) skb->data, - skb->len); - if (err < 0) - goto do_skb_free; - err = skb->len; - } -do_skb_free: + if (!skb) + goto end; + + if (len > skb->len) + len = skb->len; + else if (len < skb->len) + msg->msg_flags |= MSG_TRUNC; + + err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len); + if (likely(err == 0)) + err = len; + kfree_skb(skb); end: return err; diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index d3f749c72d41..790db89db345 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -733,8 +733,10 @@ void falcon_fini_rx(struct efx_rx_queue *rx_queue) continue; break; } - if (rc) + if (rc) { EFX_ERR(efx, "failed to flush rx queue %d\n", rx_queue->queue); + efx_schedule_reset(efx, RESET_TYPE_INVISIBLE); + } /* Remove RX descriptor ring from card */ EFX_ZERO_OWORD(rx_desc_ptr); diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 3bb60530d4d7..62436b3a18c6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -4404,7 +4404,9 @@ static int sky2_resume(struct pci_dev *pdev) if (err) { printk(KERN_ERR PFX "%s: could not up: %d\n", dev->name, err); + rtnl_lock(); dev_close(dev); + rtnl_unlock(); goto out; } } diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 69e97a1cb1c4..8606818653f8 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -93,14 +93,14 @@ #define SMC_insw(a, r, p, l) insw ((unsigned long *)((a) + (r)), p, l) # endif /* check if the mac in reg is valid */ -#define SMC_GET_MAC_ADDR(addr) \ +#define SMC_GET_MAC_ADDR(lp, addr) \ do { \ unsigned int __v; \ - __v = SMC_inw(ioaddr, ADDR0_REG); \ + __v = SMC_inw(ioaddr, ADDR0_REG(lp)); \ addr[0] = __v; addr[1] = __v >> 8; \ - __v = SMC_inw(ioaddr, ADDR1_REG); \ + __v = SMC_inw(ioaddr, ADDR1_REG(lp)); \ addr[2] = __v; addr[3] = __v >> 8; \ - __v = SMC_inw(ioaddr, ADDR2_REG); \ + __v = SMC_inw(ioaddr, ADDR2_REG(lp)); \ addr[4] = __v; addr[5] = __v >> 8; \ if (*(u32 *)(&addr[0]) == 0xFFFFFFFF) { \ random_ether_addr(addr); \ diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 07b3f77e7626..cc4bde852542 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.92" -#define DRV_MODULE_RELDATE "May 2, 2008" +#define DRV_MODULE_VERSION "3.92.1" +#define DRV_MODULE_RELDATE "June 9, 2008" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -1295,6 +1295,21 @@ static void tg3_frob_aux_power(struct tg3 *tp) GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT1), 100); + } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) { + /* The 5761 non-e device swaps GPIO 0 and GPIO 2. */ + u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OE1 | + GRC_LCLCTRL_GPIO_OE2 | + GRC_LCLCTRL_GPIO_OUTPUT0 | + GRC_LCLCTRL_GPIO_OUTPUT1 | + tp->grc_local_ctrl; + tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100); + + grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT2; + tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100); + + grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT0; + tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl, 100); } else { u32 no_gpio2; u32 grc_local_ctrl = 0; @@ -3168,8 +3183,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset) err |= tg3_readphy(tp, MII_BMCR, &bmcr); if ((tp->link_config.autoneg == AUTONEG_ENABLE) && !force_reset && - (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT) && - tp->link_config.flowctrl == tp->link_config.active_flowctrl) { + (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT)) { /* do nothing, just check for link up at the end */ } else if (tp->link_config.autoneg == AUTONEG_ENABLE) { u32 adv, new_adv; @@ -8599,7 +8613,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) (cmd->speed == SPEED_1000)) return -EINVAL; else if ((cmd->speed == SPEED_1000) && - (tp->tg3_flags2 & TG3_FLAG_10_100_ONLY)) + (tp->tg3_flags & TG3_FLAG_10_100_ONLY)) return -EINVAL; tg3_full_lock(tp, 0); @@ -11768,6 +11782,15 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; + if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) { + /* Turn off the debug UART. */ + tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL; + if (tp->tg3_flags2 & TG3_FLG2_IS_NIC) + /* Keep VMain power. */ + tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 | + GRC_LCLCTRL_GPIO_OUTPUT0; + } + /* Force the chip into D0. */ err = tg3_set_power_state(tp, PCI_D0); if (err) { diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 5450eac9e263..4452306d5328 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -44,11 +44,15 @@ struct virtnet_info /* The skb we couldn't send because buffers were full. */ struct sk_buff *last_xmit_skb; + /* If we need to free in a timer, this is it. */ + struct timer_list xmit_free_timer; + /* Number of input buffers, and max we've ever had. */ unsigned int num, max; /* For cleaning up after transmission. */ struct tasklet_struct tasklet; + bool free_in_tasklet; /* Receive & send queues. */ struct sk_buff_head recv; @@ -72,7 +76,7 @@ static void skb_xmit_done(struct virtqueue *svq) /* Suppress further interrupts. */ svq->vq_ops->disable_cb(svq); - /* We were waiting for more output buffers. */ + /* We were probably waiting for more output buffers. */ netif_wake_queue(vi->dev); /* Make sure we re-xmit last_xmit_skb: if there are no more packets @@ -94,9 +98,7 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, BUG_ON(len > MAX_PACKET_LEN); skb_trim(skb, len); - skb->protocol = eth_type_trans(skb, dev); - pr_debug("Receiving skb proto 0x%04x len %i type %i\n", - ntohs(skb->protocol), skb->len, skb->pkt_type); + dev->stats.rx_bytes += skb->len; dev->stats.rx_packets++; @@ -106,6 +108,10 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb, goto frame_err; } + skb->protocol = eth_type_trans(skb, dev); + pr_debug("Receiving skb proto 0x%04x len %i type %i\n", + ntohs(skb->protocol), skb->len, skb->pkt_type); + if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { pr_debug("GSO!\n"); switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { @@ -238,9 +244,25 @@ static void free_old_xmit_skbs(struct virtnet_info *vi) } } +/* If the virtio transport doesn't always notify us when all in-flight packets + * are consumed, we fall back to using this function on a timer to free them. */ +static void xmit_free(unsigned long data) +{ + struct virtnet_info *vi = (void *)data; + + netif_tx_lock(vi->dev); + + free_old_xmit_skbs(vi); + + if (!skb_queue_empty(&vi->send)) + mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10)); + + netif_tx_unlock(vi->dev); +} + static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) { - int num; + int num, err; struct scatterlist sg[2+MAX_SKB_FRAGS]; struct virtio_net_hdr *hdr; const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; @@ -283,7 +305,11 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) vnet_hdr_to_sg(sg, skb); num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; - return vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); + err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); + if (!err && !vi->free_in_tasklet) + mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10)); + + return err; } static void xmit_tasklet(unsigned long data) @@ -295,6 +321,8 @@ static void xmit_tasklet(unsigned long data) vi->svq->vq_ops->kick(vi->svq); vi->last_xmit_skb = NULL; } + if (vi->free_in_tasklet) + free_old_xmit_skbs(vi); netif_tx_unlock_bh(vi->dev); } @@ -435,6 +463,10 @@ static int virtnet_probe(struct virtio_device *vdev) vi->vdev = vdev; vdev->priv = vi; + /* If they give us a callback when all buffers are done, we don't need + * the timer. */ + vi->free_in_tasklet = virtio_has_feature(vdev,VIRTIO_F_NOTIFY_ON_EMPTY); + /* We expect two virtqueues, receive then send. */ vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done); if (IS_ERR(vi->rvq)) { @@ -454,6 +486,9 @@ static int virtnet_probe(struct virtio_device *vdev) tasklet_init(&vi->tasklet, xmit_tasklet, (unsigned long)vi); + if (!vi->free_in_tasklet) + setup_timer(&vi->xmit_free_timer, xmit_free, (unsigned long)vi); + err = register_netdev(dev); if (err) { pr_debug("virtio_net: registering device failed\n"); @@ -491,6 +526,9 @@ static void virtnet_remove(struct virtio_device *vdev) /* Stop all the virtqueues. */ vdev->config->reset(vdev); + if (!vi->free_in_tasklet) + del_timer_sync(&vi->xmit_free_timer); + /* Free our skbs in send and recv queues, if any. */ while ((skb = __skb_dequeue(&vi->recv)) != NULL) { kfree_skb(skb); @@ -514,7 +552,7 @@ static struct virtio_device_id id_table[] = { static unsigned int features[] = { VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, - VIRTIO_NET_F_HOST_ECN, + VIRTIO_NET_F_HOST_ECN, VIRTIO_F_NOTIFY_ON_EMPTY, }; static struct virtio_driver virtio_net = { diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 729336774828..6e704608947c 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -1753,6 +1753,8 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) if (priv->workqueue) { cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->request_direct_scan); + cancel_delayed_work(&priv->request_passive_scan); cancel_delayed_work(&priv->scan_event); } queue_work(priv->workqueue, &priv->down); @@ -2005,6 +2007,8 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) wake_up_interruptible(&priv->wait_command_queue); priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->request_direct_scan); + cancel_delayed_work(&priv->request_passive_scan); cancel_delayed_work(&priv->scan_event); schedule_work(&priv->link_down); queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); @@ -4712,6 +4716,12 @@ static void ipw_rx_notification(struct ipw_priv *priv, priv->status &= ~STATUS_SCAN_FORCED; #endif /* CONFIG_IPW2200_MONITOR */ + /* Do queued direct scans first */ + if (priv->status & STATUS_DIRECT_SCAN_PENDING) { + queue_delayed_work(priv->workqueue, + &priv->request_direct_scan, 0); + } + if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING | STATUS_ROAMING | @@ -6267,7 +6277,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv, } } -static int ipw_request_scan_helper(struct ipw_priv *priv, int type) +static int ipw_request_scan_helper(struct ipw_priv *priv, int type, int direct) { struct ipw_scan_request_ext scan; int err = 0, scan_type; @@ -6278,22 +6288,31 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type) mutex_lock(&priv->mutex); + if (direct && (priv->direct_scan_ssid_len == 0)) { + IPW_DEBUG_HC("Direct scan requested but no SSID to scan for\n"); + priv->status &= ~STATUS_DIRECT_SCAN_PENDING; + goto done; + } + if (priv->status & STATUS_SCANNING) { - IPW_DEBUG_HC("Concurrent scan requested. Ignoring.\n"); - priv->status |= STATUS_SCAN_PENDING; + IPW_DEBUG_HC("Concurrent scan requested. Queuing.\n"); + priv->status |= direct ? STATUS_DIRECT_SCAN_PENDING : + STATUS_SCAN_PENDING; goto done; } if (!(priv->status & STATUS_SCAN_FORCED) && priv->status & STATUS_SCAN_ABORTING) { IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n"); - priv->status |= STATUS_SCAN_PENDING; + priv->status |= direct ? STATUS_DIRECT_SCAN_PENDING : + STATUS_SCAN_PENDING; goto done; } if (priv->status & STATUS_RF_KILL_MASK) { - IPW_DEBUG_HC("Aborting scan due to RF Kill activation\n"); - priv->status |= STATUS_SCAN_PENDING; + IPW_DEBUG_HC("Queuing scan due to RF Kill activation\n"); + priv->status |= direct ? STATUS_DIRECT_SCAN_PENDING : + STATUS_SCAN_PENDING; goto done; } @@ -6321,6 +6340,7 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type) cpu_to_le16(20); scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120); + scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20); #ifdef CONFIG_IPW2200_MONITOR if (priv->ieee->iw_mode == IW_MODE_MONITOR) { @@ -6360,13 +6380,23 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type) cpu_to_le16(2000); } else { #endif /* CONFIG_IPW2200_MONITOR */ - /* If we are roaming, then make this a directed scan for the - * current network. Otherwise, ensure that every other scan - * is a fast channel hop scan */ - if ((priv->status & STATUS_ROAMING) - || (!(priv->status & STATUS_ASSOCIATED) - && (priv->config & CFG_STATIC_ESSID) - && (le32_to_cpu(scan.full_scan_index) % 2))) { + /* Honor direct scans first, otherwise if we are roaming make + * this a direct scan for the current network. Finally, + * ensure that every other scan is a fast channel hop scan */ + if (direct) { + err = ipw_send_ssid(priv, priv->direct_scan_ssid, + priv->direct_scan_ssid_len); + if (err) { + IPW_DEBUG_HC("Attempt to send SSID command " + "failed\n"); + goto done; + } + + scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; + } else if ((priv->status & STATUS_ROAMING) + || (!(priv->status & STATUS_ASSOCIATED) + && (priv->config & CFG_STATIC_ESSID) + && (le32_to_cpu(scan.full_scan_index) % 2))) { err = ipw_send_ssid(priv, priv->essid, priv->essid_len); if (err) { IPW_DEBUG_HC("Attempt to send SSID command " @@ -6391,7 +6421,12 @@ send_request: } priv->status |= STATUS_SCANNING; - priv->status &= ~STATUS_SCAN_PENDING; + if (direct) { + priv->status &= ~STATUS_DIRECT_SCAN_PENDING; + priv->direct_scan_ssid_len = 0; + } else + priv->status &= ~STATUS_SCAN_PENDING; + queue_delayed_work(priv->workqueue, &priv->scan_check, IPW_SCAN_CHECK_WATCHDOG); done: @@ -6402,15 +6437,22 @@ done: static void ipw_request_passive_scan(struct work_struct *work) { struct ipw_priv *priv = - container_of(work, struct ipw_priv, request_passive_scan); - ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE); + container_of(work, struct ipw_priv, request_passive_scan.work); + ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE, 0); } static void ipw_request_scan(struct work_struct *work) { struct ipw_priv *priv = container_of(work, struct ipw_priv, request_scan.work); - ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE); + ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE, 0); +} + +static void ipw_request_direct_scan(struct work_struct *work) +{ + struct ipw_priv *priv = + container_of(work, struct ipw_priv, request_direct_scan.work); + ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE, 1); } static void ipw_bg_abort_scan(struct work_struct *work) @@ -9477,99 +9519,38 @@ static int ipw_wx_get_retry(struct net_device *dev, return 0; } -static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid, - int essid_len) -{ - struct ipw_scan_request_ext scan; - int err = 0, scan_type; - - if (!(priv->status & STATUS_INIT) || - (priv->status & STATUS_EXIT_PENDING)) - return 0; - - mutex_lock(&priv->mutex); - - if (priv->status & STATUS_RF_KILL_MASK) { - IPW_DEBUG_HC("Aborting scan due to RF kill activation\n"); - priv->status |= STATUS_SCAN_PENDING; - goto done; - } - - IPW_DEBUG_HC("starting request direct scan!\n"); - - if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) { - /* We should not sleep here; otherwise we will block most - * of the system (for instance, we hold rtnl_lock when we - * get here). - */ - err = -EAGAIN; - goto done; - } - memset(&scan, 0, sizeof(scan)); - - if (priv->config & CFG_SPEED_SCAN) - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = - cpu_to_le16(30); - else - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = - cpu_to_le16(20); - - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = - cpu_to_le16(20); - scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120); - scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20); - - scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); - - err = ipw_send_ssid(priv, essid, essid_len); - if (err) { - IPW_DEBUG_HC("Attempt to send SSID command failed\n"); - goto done; - } - scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; - - ipw_add_scan_channels(priv, &scan, scan_type); - - err = ipw_send_scan_request_ext(priv, &scan); - if (err) { - IPW_DEBUG_HC("Sending scan command failed: %08X\n", err); - goto done; - } - - priv->status |= STATUS_SCANNING; - - done: - mutex_unlock(&priv->mutex); - return err; -} - static int ipw_wx_set_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_priv(dev); struct iw_scan_req *req = (struct iw_scan_req *)extra; + struct delayed_work *work = NULL; mutex_lock(&priv->mutex); + priv->user_requested_scan = 1; - mutex_unlock(&priv->mutex); if (wrqu->data.length == sizeof(struct iw_scan_req)) { if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { - ipw_request_direct_scan(priv, req->essid, - req->essid_len); - return 0; - } - if (req->scan_type == IW_SCAN_TYPE_PASSIVE) { - queue_work(priv->workqueue, - &priv->request_passive_scan); - return 0; + int len = min((int)req->essid_len, + (int)sizeof(priv->direct_scan_ssid)); + memcpy(priv->direct_scan_ssid, req->essid, len); + priv->direct_scan_ssid_len = len; + work = &priv->request_direct_scan; + } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) { + work = &priv->request_passive_scan; } + } else { + /* Normal active broadcast scan */ + work = &priv->request_scan; } + mutex_unlock(&priv->mutex); + IPW_DEBUG_WX("Start scan\n"); - queue_delayed_work(priv->workqueue, &priv->request_scan, 0); + queue_delayed_work(priv->workqueue, work, 0); return 0; } @@ -10731,6 +10712,8 @@ static void ipw_link_up(struct ipw_priv *priv) } cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->request_direct_scan); + cancel_delayed_work(&priv->request_passive_scan); cancel_delayed_work(&priv->scan_event); ipw_reset_stats(priv); /* Ensure the rate is updated immediately */ @@ -10761,6 +10744,8 @@ static void ipw_link_down(struct ipw_priv *priv) /* Cancel any queued work ... */ cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->request_direct_scan); + cancel_delayed_work(&priv->request_passive_scan); cancel_delayed_work(&priv->adhoc_check); cancel_delayed_work(&priv->gather_stats); @@ -10800,8 +10785,9 @@ static int __devinit ipw_setup_deferred_work(struct ipw_priv *priv) INIT_WORK(&priv->up, ipw_bg_up); INIT_WORK(&priv->down, ipw_bg_down); INIT_DELAYED_WORK(&priv->request_scan, ipw_request_scan); + INIT_DELAYED_WORK(&priv->request_direct_scan, ipw_request_direct_scan); + INIT_DELAYED_WORK(&priv->request_passive_scan, ipw_request_passive_scan); INIT_DELAYED_WORK(&priv->scan_event, ipw_scan_event); - INIT_WORK(&priv->request_passive_scan, ipw_request_passive_scan); INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats); INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan); INIT_WORK(&priv->roam, ipw_bg_roam); @@ -11835,6 +11821,8 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev) cancel_delayed_work(&priv->adhoc_check); cancel_delayed_work(&priv->gather_stats); cancel_delayed_work(&priv->request_scan); + cancel_delayed_work(&priv->request_direct_scan); + cancel_delayed_work(&priv->request_passive_scan); cancel_delayed_work(&priv->scan_event); cancel_delayed_work(&priv->rf_kill); cancel_delayed_work(&priv->scan_check); diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index cd3295b66dd6..d4ab28b73b32 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -1037,6 +1037,7 @@ struct ipw_cmd { /* XXX */ #define STATUS_DISASSOC_PENDING (1<<12) #define STATUS_STATE_PENDING (1<<13) +#define STATUS_DIRECT_SCAN_PENDING (1<<19) #define STATUS_SCAN_PENDING (1<<20) #define STATUS_SCANNING (1<<21) #define STATUS_SCAN_ABORTING (1<<22) @@ -1292,6 +1293,8 @@ struct ipw_priv { struct iw_public_data wireless_data; int user_requested_scan; + u8 direct_scan_ssid[IW_ESSID_MAX_SIZE]; + u8 direct_scan_ssid_len; struct workqueue_struct *workqueue; @@ -1301,8 +1304,9 @@ struct ipw_priv { struct work_struct system_config; struct work_struct rx_replenish; struct delayed_work request_scan; + struct delayed_work request_direct_scan; + struct delayed_work request_passive_scan; struct delayed_work scan_event; - struct work_struct request_passive_scan; struct work_struct adapter_restart; struct delayed_work rf_kill; struct work_struct up; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index d200d08fb086..8b1528e52d43 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -229,14 +229,15 @@ static int iwl3945_led_register_led(struct iwl3945_priv *priv, led->led_dev.brightness_set = iwl3945_led_brightness_set; led->led_dev.default_trigger = trigger; + led->priv = priv; + led->type = type; + ret = led_classdev_register(device, &led->led_dev); if (ret) { IWL_ERROR("Error: failed to register led handler.\n"); return ret; } - led->priv = priv; - led->type = type; led->registered = 1; if (set_led && led->led_on) diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 6328b9593877..8124fd9b1353 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1842,6 +1842,9 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) spin_lock_irqsave(&priv->driver_lock, flags); + /* We don't get a response on the sleep-confirmation */ + priv->dnld_sent = DNLD_RES_RECEIVED; + /* If nothing to do, go back to sleep (?) */ if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx]) priv->psstate = PS_STATE_SLEEP; @@ -1904,12 +1907,12 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_HOST); + spin_lock_irqsave(&priv->driver_lock, flags); if (priv->dnld_sent) { allowed = 0; lbs_deb_host("dnld_sent was set\n"); } - spin_lock_irqsave(&priv->driver_lock, flags); /* In-progress command? */ if (priv->cur_cmd) { allowed = 0; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index e1f066068590..acfc4bfcc262 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -732,8 +732,8 @@ static int lbs_thread(void *data) lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n", priv->currenttxskb, priv->dnld_sent); - spin_lock_irq(&priv->driver_lock); /* Process any pending command response */ + spin_lock_irq(&priv->driver_lock); resp_idx = priv->resp_idx; if (priv->resp_len[resp_idx]) { spin_unlock_irq(&priv->driver_lock); diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 6424e5a2c83d..418606ac1c3b 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -719,7 +719,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) fc = le16_to_cpu(*((__le16 *) buffer)); is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_QOS_DATA); + (fc & IEEE80211_STYPE_QOS_DATA); is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); need_padding = is_qos ^ is_4addr; diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 0201c8adfda7..46c791adb894 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -50,15 +50,17 @@ static int irq_flags(int triggering, int polarity, int shareable) flags = IORESOURCE_IRQ_HIGHEDGE; } - if (shareable) + if (shareable == ACPI_SHARED) flags |= IORESOURCE_IRQ_SHAREABLE; return flags; } -static void decode_irq_flags(int flag, int *triggering, int *polarity) +static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering, + int *polarity, int *shareable) { - switch (flag) { + switch (flags & (IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL | + IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE)) { case IORESOURCE_IRQ_LOWLEVEL: *triggering = ACPI_LEVEL_SENSITIVE; *polarity = ACPI_ACTIVE_LOW; @@ -75,7 +77,18 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity) *triggering = ACPI_EDGE_SENSITIVE; *polarity = ACPI_ACTIVE_HIGH; break; + default: + dev_err(&dev->dev, "can't encode invalid IRQ mode %#x\n", + flags); + *triggering = ACPI_EDGE_SENSITIVE; + *polarity = ACPI_ACTIVE_HIGH; + break; } + + if (flags & IORESOURCE_IRQ_SHAREABLE) + *shareable = ACPI_SHARED; + else + *shareable = ACPI_EXCLUSIVE; } static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, @@ -742,6 +755,9 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data) if (pnpacpi_supported_resource(res)) { (*resource)->type = res->type; (*resource)->length = sizeof(struct acpi_resource); + if (res->type == ACPI_RESOURCE_TYPE_IRQ) + (*resource)->data.irq.descriptor_length = + res->data.irq.descriptor_length; (*resource)++; } @@ -788,22 +804,21 @@ static void pnpacpi_encode_irq(struct pnp_dev *dev, struct resource *p) { struct acpi_resource_irq *irq = &resource->data.irq; - int triggering, polarity; + int triggering, polarity, shareable; - decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); + decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); irq->triggering = triggering; irq->polarity = polarity; - if (triggering == ACPI_EDGE_SENSITIVE) - irq->sharable = ACPI_EXCLUSIVE; - else - irq->sharable = ACPI_SHARED; + irq->sharable = shareable; irq->interrupt_count = 1; irq->interrupts[0] = p->start; - dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start, + dev_dbg(&dev->dev, " encode irq %d %s %s %s (%d-byte descriptor)\n", + (int) p->start, triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge", polarity == ACPI_ACTIVE_LOW ? "low" : "high", - irq->sharable == ACPI_SHARED ? "shared" : "exclusive"); + irq->sharable == ACPI_SHARED ? "shared" : "exclusive", + irq->descriptor_length); } static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, @@ -811,16 +826,13 @@ static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, struct resource *p) { struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; - int triggering, polarity; + int triggering, polarity, shareable; - decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); + decode_irq_flags(dev, p->flags, &triggering, &polarity, &shareable); extended_irq->producer_consumer = ACPI_CONSUMER; extended_irq->triggering = triggering; extended_irq->polarity = polarity; - if (triggering == ACPI_EDGE_SENSITIVE) - extended_irq->sharable = ACPI_EXCLUSIVE; - else - extended_irq->sharable = ACPI_SHARED; + extended_irq->sharable = shareable; extended_irq->interrupt_count = 1; extended_irq->interrupts[0] = p->start; diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 60f8afc7a56e..4949dc4859be 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -256,6 +256,17 @@ config RTC_DRV_S35390A This driver can also be built as a module. If so the module will be called rtc-s35390a. +config RTC_DRV_FM3130 + tristate "Ramtron FM3130" + help + If you say Y here you will get support for the + Ramtron FM3130 RTC chips. + Ramtron FM3130 is a chip with two separate devices inside, + RTC clock and FRAM. This driver provides only RTC functionality. + + This driver can also be built as a module. If so the module + will be called rtc-fm3130. + endif # I2C comment "SPI RTC drivers" diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index ebe871cf16c1..b6e14d51670b 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o +obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o @@ -41,6 +42,7 @@ obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o +obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o @@ -54,4 +56,3 @@ obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o -obj-$(CONFIG_RTC_DRV_PPC) += rtc-ppc.o diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c index 42244f14b41c..2ef8cdfda4a7 100644 --- a/drivers/rtc/rtc-at32ap700x.c +++ b/drivers/rtc/rtc-at32ap700x.c @@ -94,8 +94,11 @@ static int at32_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); + spin_lock_irq(&rtc->lock); rtc_time_to_tm(rtc->alarm_time, &alrm->time); - alrm->pending = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0; + alrm->enabled = rtc_readl(rtc, IMR) & RTC_BIT(IMR_TOPI) ? 1 : 0; + alrm->pending = rtc_readl(rtc, ISR) & RTC_BIT(ISR_TOPI) ? 1 : 0; + spin_unlock_irq(&rtc->lock); return 0; } @@ -119,7 +122,7 @@ static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) spin_lock_irq(&rtc->lock); rtc->alarm_time = alarm_unix_time; rtc_writel(rtc, TOP, rtc->alarm_time); - if (alrm->pending) + if (alrm->enabled) rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) | RTC_BIT(CTRL_TOPEN)); else diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index d060a06ce05b..d7bb9bac71df 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -905,19 +905,7 @@ static struct pnp_driver cmos_pnp_driver = { .resume = cmos_pnp_resume, }; -static int __init cmos_init(void) -{ - return pnp_register_driver(&cmos_pnp_driver); -} -module_init(cmos_init); - -static void __exit cmos_exit(void) -{ - pnp_unregister_driver(&cmos_pnp_driver); -} -module_exit(cmos_exit); - -#else /* no PNP */ +#endif /* CONFIG_PNP */ /*----------------------------------------------------------------*/ @@ -958,20 +946,33 @@ static struct platform_driver cmos_platform_driver = { static int __init cmos_init(void) { +#ifdef CONFIG_PNP + if (pnp_platform_devices) + return pnp_register_driver(&cmos_pnp_driver); + else + return platform_driver_probe(&cmos_platform_driver, + cmos_platform_probe); +#else return platform_driver_probe(&cmos_platform_driver, cmos_platform_probe); +#endif /* CONFIG_PNP */ } module_init(cmos_init); static void __exit cmos_exit(void) { +#ifdef CONFIG_PNP + if (pnp_platform_devices) + pnp_unregister_driver(&cmos_pnp_driver); + else + platform_driver_unregister(&cmos_platform_driver); +#else platform_driver_unregister(&cmos_platform_driver); +#endif /* CONFIG_PNP */ } module_exit(cmos_exit); -#endif /* !PNP */ - MODULE_AUTHOR("David Brownell"); MODULE_DESCRIPTION("Driver for PC-style 'CMOS' RTCs"); MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c new file mode 100644 index 000000000000..11644c8fca82 --- /dev/null +++ b/drivers/rtc/rtc-fm3130.c @@ -0,0 +1,501 @@ +/* + * rtc-fm3130.c - RTC driver for Ramtron FM3130 I2C chip. + * + * Copyright (C) 2008 Sergey Lapin + * Based on ds1307 driver by James Chapman and David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/rtc.h> +#include <linux/bcd.h> + +#define FM3130_RTC_CONTROL (0x0) +#define FM3130_CAL_CONTROL (0x1) +#define FM3130_RTC_SECONDS (0x2) +#define FM3130_RTC_MINUTES (0x3) +#define FM3130_RTC_HOURS (0x4) +#define FM3130_RTC_DAY (0x5) +#define FM3130_RTC_DATE (0x6) +#define FM3130_RTC_MONTHS (0x7) +#define FM3130_RTC_YEARS (0x8) + +#define FM3130_ALARM_SECONDS (0x9) +#define FM3130_ALARM_MINUTES (0xa) +#define FM3130_ALARM_HOURS (0xb) +#define FM3130_ALARM_DATE (0xc) +#define FM3130_ALARM_MONTHS (0xd) +#define FM3130_ALARM_WP_CONTROL (0xe) + +#define FM3130_CAL_CONTROL_BIT_nOSCEN (1 << 7) /* Osciallator enabled */ +#define FM3130_RTC_CONTROL_BIT_LB (1 << 7) /* Low battery */ +#define FM3130_RTC_CONTROL_BIT_AF (1 << 6) /* Alarm flag */ +#define FM3130_RTC_CONTROL_BIT_CF (1 << 5) /* Century overflow */ +#define FM3130_RTC_CONTROL_BIT_POR (1 << 4) /* Power on reset */ +#define FM3130_RTC_CONTROL_BIT_AEN (1 << 3) /* Alarm enable */ +#define FM3130_RTC_CONTROL_BIT_CAL (1 << 2) /* Calibration mode */ +#define FM3130_RTC_CONTROL_BIT_WRITE (1 << 1) /* W=1 -> write mode W=0 normal */ +#define FM3130_RTC_CONTROL_BIT_READ (1 << 0) /* R=1 -> read mode R=0 normal */ + +#define FM3130_CLOCK_REGS 7 +#define FM3130_ALARM_REGS 5 + +struct fm3130 { + u8 reg_addr_time; + u8 reg_addr_alarm; + u8 regs[15]; + struct i2c_msg msg[4]; + struct i2c_client *client; + struct rtc_device *rtc; + int data_valid; + int alarm; +}; +static const struct i2c_device_id fm3130_id[] = { + { "fm3130-rtc", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, fm3130_id); + +#define FM3130_MODE_NORMAL 0 +#define FM3130_MODE_WRITE 1 +#define FM3130_MODE_READ 2 + +static void fm3130_rtc_mode(struct device *dev, int mode) +{ + struct fm3130 *fm3130 = dev_get_drvdata(dev); + + fm3130->regs[FM3130_RTC_CONTROL] = + i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); + switch (mode) { + case FM3130_MODE_NORMAL: + fm3130->regs[FM3130_RTC_CONTROL] &= + ~(FM3130_RTC_CONTROL_BIT_WRITE | + FM3130_RTC_CONTROL_BIT_READ); + break; + case FM3130_MODE_WRITE: + fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_WRITE; + break; + case FM3130_MODE_READ: + fm3130->regs[FM3130_RTC_CONTROL] |= FM3130_RTC_CONTROL_BIT_READ; + break; + default: + dev_dbg(dev, "invalid mode %d\n", mode); + break; + } + /* Checking for alarm */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { + fm3130->alarm = 1; + fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; + } + i2c_smbus_write_byte_data(fm3130->client, + FM3130_RTC_CONTROL, fm3130->regs[FM3130_RTC_CONTROL]); +} + +static int fm3130_get_time(struct device *dev, struct rtc_time *t) +{ + struct fm3130 *fm3130 = dev_get_drvdata(dev); + int tmp; + + if (!fm3130->data_valid) { + /* We have invalid data in RTC, probably due + to battery faults or other problems. Return EIO + for now, it will allow us to set data later insted + of error during probing which disables device */ + return -EIO; + } + fm3130_rtc_mode(dev, FM3130_MODE_READ); + + /* read the RTC date and time registers all at once */ + tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), + fm3130->msg, 2); + if (tmp != 2) { + dev_err(dev, "%s error %d\n", "read", tmp); + return -EIO; + } + + fm3130_rtc_mode(dev, FM3130_MODE_NORMAL); + + dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x" + "%02x %02x %02x %02x %02x %02x %02x\n", + "read", + fm3130->regs[0], fm3130->regs[1], + fm3130->regs[2], fm3130->regs[3], + fm3130->regs[4], fm3130->regs[5], + fm3130->regs[6], fm3130->regs[7], + fm3130->regs[8], fm3130->regs[9], + fm3130->regs[0xa], fm3130->regs[0xb], + fm3130->regs[0xc], fm3130->regs[0xd], + fm3130->regs[0xe]); + + t->tm_sec = BCD2BIN(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f); + t->tm_min = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); + tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f; + t->tm_hour = BCD2BIN(tmp); + t->tm_wday = BCD2BIN(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1; + t->tm_mday = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f); + tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f; + t->tm_mon = BCD2BIN(tmp) - 1; + + /* assume 20YY not 19YY, and ignore CF bit */ + t->tm_year = BCD2BIN(fm3130->regs[FM3130_RTC_YEARS]) + 100; + + dev_dbg(dev, "%s secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + "read", t->tm_sec, t->tm_min, + t->tm_hour, t->tm_mday, + t->tm_mon, t->tm_year, t->tm_wday); + + /* initial clock setting can be undefined */ + return rtc_valid_tm(t); +} + + +static int fm3130_set_time(struct device *dev, struct rtc_time *t) +{ + struct fm3130 *fm3130 = dev_get_drvdata(dev); + int tmp, i; + u8 *buf = fm3130->regs; + + dev_dbg(dev, "%s secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + "write", t->tm_sec, t->tm_min, + t->tm_hour, t->tm_mday, + t->tm_mon, t->tm_year, t->tm_wday); + + /* first register addr */ + buf[FM3130_RTC_SECONDS] = BIN2BCD(t->tm_sec); + buf[FM3130_RTC_MINUTES] = BIN2BCD(t->tm_min); + buf[FM3130_RTC_HOURS] = BIN2BCD(t->tm_hour); + buf[FM3130_RTC_DAY] = BIN2BCD(t->tm_wday + 1); + buf[FM3130_RTC_DATE] = BIN2BCD(t->tm_mday); + buf[FM3130_RTC_MONTHS] = BIN2BCD(t->tm_mon + 1); + + /* assume 20YY not 19YY */ + tmp = t->tm_year - 100; + buf[FM3130_RTC_YEARS] = BIN2BCD(tmp); + + dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x" + "%02x %02x %02x %02x %02x %02x %02x %02x\n", + "write", buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7], + buf[8], buf[9], buf[0xa], buf[0xb], + buf[0xc], buf[0xd], buf[0xe]); + + fm3130_rtc_mode(dev, FM3130_MODE_WRITE); + + /* Writing time registers, we don't support multibyte transfers */ + for (i = 0; i < FM3130_CLOCK_REGS; i++) { + i2c_smbus_write_byte_data(fm3130->client, + FM3130_RTC_SECONDS + i, + fm3130->regs[FM3130_RTC_SECONDS + i]); + } + + fm3130_rtc_mode(dev, FM3130_MODE_NORMAL); + + /* We assume here that data are valid once written */ + if (!fm3130->data_valid) + fm3130->data_valid = 1; + return 0; +} + +static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct fm3130 *fm3130 = dev_get_drvdata(dev); + int tmp; + struct rtc_time *tm = &alrm->time; + /* read the RTC alarm registers all at once */ + tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), + &fm3130->msg[2], 2); + if (tmp != 2) { + dev_err(dev, "%s error %d\n", "read", tmp); + return -EIO; + } + dev_dbg(dev, "alarm read %02x %02x %02x %02x %02x\n", + fm3130->regs[FM3130_ALARM_SECONDS], + fm3130->regs[FM3130_ALARM_MINUTES], + fm3130->regs[FM3130_ALARM_HOURS], + fm3130->regs[FM3130_ALARM_DATE], + fm3130->regs[FM3130_ALARM_MONTHS]); + + + tm->tm_sec = BCD2BIN(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F); + tm->tm_min = BCD2BIN(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F); + tm->tm_hour = BCD2BIN(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F); + tm->tm_mday = BCD2BIN(fm3130->regs[FM3130_ALARM_DATE] & 0x3F); + tm->tm_mon = BCD2BIN(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F); + if (tm->tm_mon > 0) + tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */ + dev_dbg(dev, "%s secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + "read alarm", tm->tm_sec, tm->tm_min, + tm->tm_hour, tm->tm_mday, + tm->tm_mon, tm->tm_year, tm->tm_wday); + + return 0; +} + +static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct fm3130 *fm3130 = dev_get_drvdata(dev); + struct rtc_time *tm = &alrm->time; + int i; + + dev_dbg(dev, "%s secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + "write alarm", tm->tm_sec, tm->tm_min, + tm->tm_hour, tm->tm_mday, + tm->tm_mon, tm->tm_year, tm->tm_wday); + + if (tm->tm_sec != -1) + fm3130->regs[FM3130_ALARM_SECONDS] = + BIN2BCD(tm->tm_sec) | 0x80; + + if (tm->tm_min != -1) + fm3130->regs[FM3130_ALARM_MINUTES] = + BIN2BCD(tm->tm_min) | 0x80; + + if (tm->tm_hour != -1) + fm3130->regs[FM3130_ALARM_HOURS] = + BIN2BCD(tm->tm_hour) | 0x80; + + if (tm->tm_mday != -1) + fm3130->regs[FM3130_ALARM_DATE] = + BIN2BCD(tm->tm_mday) | 0x80; + + if (tm->tm_mon != -1) + fm3130->regs[FM3130_ALARM_MONTHS] = + BIN2BCD(tm->tm_mon + 1) | 0x80; + + dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n", + fm3130->regs[FM3130_ALARM_SECONDS], + fm3130->regs[FM3130_ALARM_MINUTES], + fm3130->regs[FM3130_ALARM_HOURS], + fm3130->regs[FM3130_ALARM_DATE], + fm3130->regs[FM3130_ALARM_MONTHS]); + /* Writing time registers, we don't support multibyte transfers */ + for (i = 0; i < FM3130_ALARM_REGS; i++) { + i2c_smbus_write_byte_data(fm3130->client, + FM3130_ALARM_SECONDS + i, + fm3130->regs[FM3130_ALARM_SECONDS + i]); + } + fm3130->regs[FM3130_RTC_CONTROL] = + i2c_smbus_read_byte_data(fm3130->client, FM3130_RTC_CONTROL); + /* Checking for alarm */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { + fm3130->alarm = 1; + fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; + } + if (alrm->enabled) { + i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, + (fm3130->regs[FM3130_RTC_CONTROL] & + ~(FM3130_RTC_CONTROL_BIT_CAL)) | + FM3130_RTC_CONTROL_BIT_AEN); + } else { + i2c_smbus_write_byte_data(fm3130->client, FM3130_RTC_CONTROL, + fm3130->regs[FM3130_RTC_CONTROL] & + ~(FM3130_RTC_CONTROL_BIT_AEN)); + } + return 0; +} + +static const struct rtc_class_ops fm3130_rtc_ops = { + .read_time = fm3130_get_time, + .set_time = fm3130_set_time, + .read_alarm = fm3130_read_alarm, + .set_alarm = fm3130_set_alarm, +}; + +static struct i2c_driver fm3130_driver; + +static int __devinit fm3130_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct fm3130 *fm3130; + int err = -ENODEV; + int tmp; + struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + + if (!i2c_check_functionality(adapter, + I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) + return -EIO; + + fm3130 = kzalloc(sizeof(struct fm3130), GFP_KERNEL); + + if (!fm3130) + return -ENOMEM; + + fm3130->client = client; + i2c_set_clientdata(client, fm3130); + fm3130->reg_addr_time = FM3130_RTC_SECONDS; + fm3130->reg_addr_alarm = FM3130_ALARM_SECONDS; + + /* Messages to read time */ + fm3130->msg[0].addr = client->addr; + fm3130->msg[0].flags = 0; + fm3130->msg[0].len = 1; + fm3130->msg[0].buf = &fm3130->reg_addr_time; + + fm3130->msg[1].addr = client->addr; + fm3130->msg[1].flags = I2C_M_RD; + fm3130->msg[1].len = FM3130_CLOCK_REGS; + fm3130->msg[1].buf = &fm3130->regs[FM3130_RTC_SECONDS]; + + /* Messages to read alarm */ + fm3130->msg[2].addr = client->addr; + fm3130->msg[2].flags = 0; + fm3130->msg[2].len = 1; + fm3130->msg[2].buf = &fm3130->reg_addr_alarm; + + fm3130->msg[3].addr = client->addr; + fm3130->msg[3].flags = I2C_M_RD; + fm3130->msg[3].len = FM3130_ALARM_REGS; + fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS]; + + fm3130->data_valid = 0; + + tmp = i2c_transfer(adapter, fm3130->msg, 4); + if (tmp != 4) { + pr_debug("read error %d\n", tmp); + err = -EIO; + goto exit_free; + } + + fm3130->regs[FM3130_RTC_CONTROL] = + i2c_smbus_read_byte_data(client, FM3130_RTC_CONTROL); + fm3130->regs[FM3130_CAL_CONTROL] = + i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL); + + /* Checking for alarm */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_AF) { + fm3130->alarm = 1; + fm3130->regs[FM3130_RTC_CONTROL] &= ~FM3130_RTC_CONTROL_BIT_AF; + } + + /* Disabling calibration mode */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) + i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, + fm3130->regs[FM3130_RTC_CONTROL] & + ~(FM3130_RTC_CONTROL_BIT_CAL)); + dev_warn(&client->dev, "Disabling calibration mode!\n"); + + /* Disabling read and write modes */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE || + fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) + i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, + fm3130->regs[FM3130_RTC_CONTROL] & + ~(FM3130_RTC_CONTROL_BIT_READ | + FM3130_RTC_CONTROL_BIT_WRITE)); + dev_warn(&client->dev, "Disabling READ or WRITE mode!\n"); + + /* oscillator off? turn it on, so clock can tick. */ + if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN) + i2c_smbus_write_byte_data(client, FM3130_CAL_CONTROL, + fm3130->regs[FM3130_CAL_CONTROL] & + ~(FM3130_CAL_CONTROL_BIT_nOSCEN)); + + /* oscillator fault? clear flag, and warn */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) + dev_warn(&client->dev, "Low battery!\n"); + + /* oscillator fault? clear flag, and warn */ + if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) { + i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL, + fm3130->regs[FM3130_RTC_CONTROL] & + ~FM3130_RTC_CONTROL_BIT_POR); + dev_warn(&client->dev, "SET TIME!\n"); + } + /* ACS is controlled by alarm */ + i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80); + + /* TODO */ + /* TODO need to sanity check alarm */ + tmp = fm3130->regs[FM3130_RTC_SECONDS]; + tmp = BCD2BIN(tmp & 0x7f); + if (tmp > 60) + goto exit_bad; + tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f); + if (tmp > 60) + goto exit_bad; + + tmp = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f); + if (tmp == 0 || tmp > 31) + goto exit_bad; + + tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f); + if (tmp == 0 || tmp > 12) + goto exit_bad; + + tmp = fm3130->regs[FM3130_RTC_HOURS]; + + fm3130->data_valid = 1; + +exit_bad: + if (!fm3130->data_valid) + dev_dbg(&client->dev, + "%s: %02x %02x %02x %02x %02x %02x %02x %02x" + "%02x %02x %02x %02x %02x %02x %02x\n", + "bogus registers", + fm3130->regs[0], fm3130->regs[1], + fm3130->regs[2], fm3130->regs[3], + fm3130->regs[4], fm3130->regs[5], + fm3130->regs[6], fm3130->regs[7], + fm3130->regs[8], fm3130->regs[9], + fm3130->regs[0xa], fm3130->regs[0xb], + fm3130->regs[0xc], fm3130->regs[0xd], + fm3130->regs[0xe]); + + /* We won't bail out here because we just got invalid data. + Time setting from u-boot doesn't work anyway */ + fm3130->rtc = rtc_device_register(client->name, &client->dev, + &fm3130_rtc_ops, THIS_MODULE); + if (IS_ERR(fm3130->rtc)) { + err = PTR_ERR(fm3130->rtc); + dev_err(&client->dev, + "unable to register the class device\n"); + goto exit_free; + } + return 0; +exit_free: + kfree(fm3130); + return err; +} + +static int __devexit fm3130_remove(struct i2c_client *client) +{ + struct fm3130 *fm3130 = i2c_get_clientdata(client); + + rtc_device_unregister(fm3130->rtc); + kfree(fm3130); + return 0; +} + +static struct i2c_driver fm3130_driver = { + .driver = { + .name = "rtc-fm3130", + .owner = THIS_MODULE, + }, + .probe = fm3130_probe, + .remove = __devexit_p(fm3130_remove), + .id_table = fm3130_id, +}; + +static int __init fm3130_init(void) +{ + return i2c_add_driver(&fm3130_driver); +} +module_init(fm3130_init); + +static void __exit fm3130_exit(void) +{ + i2c_del_driver(&fm3130_driver); +} +module_exit(fm3130_exit); + +MODULE_DESCRIPTION("RTC driver for FM3130"); +MODULE_AUTHOR("Sergey Lapin <slapin@ossfans.org>"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 436bf1f6d4a6..9a71dae223e8 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -290,9 +290,6 @@ int qeth_set_large_send(struct qeth_card *card, card->dev->features |= NETIF_F_TSO | NETIF_F_SG | NETIF_F_HW_CSUM; } else { - PRINT_WARN("TSO not supported on %s. " - "large_send set to 'no'.\n", - card->dev->name); card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_HW_CSUM); card->options.large_send = QETH_LARGE_SEND_NO; @@ -1407,12 +1404,6 @@ static void qeth_init_func_level(struct qeth_card *card) } } -static inline __u16 qeth_raw_devno_from_bus_id(char *id) -{ - id += (strlen(id) - 4); - return (__u16) simple_strtoul(id, &id, 16); -} - static int qeth_idx_activate_get_answer(struct qeth_channel *channel, void (*idx_reply_cb)(struct qeth_channel *, struct qeth_cmd_buffer *)) @@ -1439,7 +1430,7 @@ static int qeth_idx_activate_get_answer(struct qeth_channel *channel, spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); if (rc) { - PRINT_ERR("Error2 in activating channel rc=%d\n", rc); + QETH_DBF_MESSAGE(2, "Error2 in activating channel rc=%d\n", rc); QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); atomic_set(&channel->irq_pending, 0); wake_up(&card->wait_q); @@ -1468,6 +1459,7 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel, __u16 temp; __u8 tmp; int rc; + struct ccw_dev_id temp_devid; card = CARD_FROM_CDEV(channel->ccwdev); @@ -1494,8 +1486,8 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel, &card->token.issuer_rm_w, QETH_MPC_TOKEN_LENGTH); memcpy(QETH_IDX_ACT_FUNC_LEVEL(iob->data), &card->info.func_level, sizeof(__u16)); - temp = qeth_raw_devno_from_bus_id(CARD_DDEV_ID(card)); - memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(iob->data), &temp, 2); + ccw_device_get_id(CARD_DDEV(card), &temp_devid); + memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(iob->data), &temp_devid.devno, 2); temp = (card->info.cula << 8) + card->info.unit_addr2; memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2); @@ -1508,7 +1500,8 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel, spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); if (rc) { - PRINT_ERR("Error1 in activating channel. rc=%d\n", rc); + QETH_DBF_MESSAGE(2, "Error1 in activating channel. rc=%d\n", + rc); QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); atomic_set(&channel->irq_pending, 0); wake_up(&card->wait_q); @@ -1658,7 +1651,6 @@ int qeth_send_control_data(struct qeth_card *card, int len, reply = qeth_alloc_reply(card); if (!reply) { - PRINT_WARN("Could not alloc qeth_reply!\n"); return -ENOMEM; } reply->callback = reply_cb; @@ -2612,15 +2604,9 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index) if (newcount < count) { /* we are in memory shortage so we switch back to traditional skb allocation and drop packages */ - if (!atomic_read(&card->force_alloc_skb) && - net_ratelimit()) - PRINT_WARN("Switch to alloc skb\n"); atomic_set(&card->force_alloc_skb, 3); count = newcount; } else { - if ((atomic_read(&card->force_alloc_skb) == 1) && - net_ratelimit()) - PRINT_WARN("Switch to sg\n"); atomic_add_unless(&card->force_alloc_skb, -1, 0); } @@ -3034,7 +3020,7 @@ int qeth_get_elements_no(struct qeth_card *card, void *hdr, elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) + skb->len) >> PAGE_SHIFT); if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { - PRINT_ERR("Invalid size of IP packet " + QETH_DBF_MESSAGE(2, "Invalid size of IP packet " "(Number=%d / Length=%d). Discarded.\n", (elements_needed+elems), skb->len); return 0; @@ -3247,8 +3233,6 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, * free buffers) to handle eddp context */ if (qeth_eddp_check_buffers_for_context(queue, ctx) < 0) { - if (net_ratelimit()) - PRINT_WARN("eddp tx_dropped 1\n"); rc = -EBUSY; goto out; } @@ -3260,7 +3244,6 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, tmp = qeth_eddp_fill_buffer(queue, ctx, queue->next_buf_to_fill); if (tmp < 0) { - PRINT_ERR("eddp tx_dropped 2\n"); rc = -EBUSY; goto out; } @@ -3602,8 +3585,6 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) if ((!qeth_adp_supported(card, IPA_SETADP_SET_SNMP_CONTROL)) && (!card->options.layer2)) { - PRINT_WARN("SNMP Query MIBS not supported " - "on %s!\n", QETH_CARD_IFNAME(card)); return -EOPNOTSUPP; } /* skip 4 bytes (data_len struct member) to get req_len */ @@ -3634,7 +3615,7 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len, qeth_snmp_command_cb, (void *)&qinfo); if (rc) - PRINT_WARN("SNMP command failed on %s: (0x%x)\n", + QETH_DBF_MESSAGE(2, "SNMP command failed on %s: (0x%x)\n", QETH_CARD_IFNAME(card), rc); else { if (copy_to_user(udata, qinfo.udata, qinfo.udata_len)) @@ -3807,8 +3788,8 @@ retry: if (mpno) mpno = min(mpno - 1, QETH_MAX_PORTNO); if (card->info.portno > mpno) { - PRINT_ERR("Device %s does not offer port number %d \n.", - CARD_BUS_ID(card), card->info.portno); + QETH_DBF_MESSAGE(2, "Device %s does not offer port number %d" + "\n.", CARD_BUS_ID(card), card->info.portno); rc = -ENODEV; goto out; } @@ -3985,8 +3966,6 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, return skb; no_mem: if (net_ratelimit()) { - PRINT_WARN("No memory for packet received on %s.\n", - QETH_CARD_IFNAME(card)); QETH_DBF_TEXT(TRACE, 2, "noskbmem"); QETH_DBF_TEXT_(TRACE, 2, "%s", CARD_BUS_ID(card)); } @@ -4004,15 +3983,17 @@ static void qeth_unregister_dbf_views(void) } } -void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...) +void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *fmt, ...) { char dbf_txt_buf[32]; + va_list args; if (level > (qeth_dbf[dbf_nix].id)->level) return; - snprintf(dbf_txt_buf, sizeof(dbf_txt_buf), text); + va_start(args, fmt); + vsnprintf(dbf_txt_buf, sizeof(dbf_txt_buf), fmt, args); + va_end(args); debug_text_event(qeth_dbf[dbf_nix].id, level, dbf_txt_buf); - } EXPORT_SYMBOL_GPL(qeth_dbf_longtext); diff --git a/drivers/s390/net/qeth_core_offl.c b/drivers/s390/net/qeth_core_offl.c index 822df8362856..452874e89740 100644 --- a/drivers/s390/net/qeth_core_offl.c +++ b/drivers/s390/net/qeth_core_offl.c @@ -122,8 +122,8 @@ int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue, if (element == 0) return -EBUSY; else { - PRINT_WARN("could only partially fill eddp " - "buffer!\n"); + QETH_DBF_MESSAGE(2, "could only partially fill" + "eddp buffer!\n"); goto out; } } @@ -143,8 +143,6 @@ int qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue, if (must_refcnt) { must_refcnt = 0; if (qeth_eddp_buf_ref_context(buf, ctx)) { - PRINT_WARN("no memory to create eddp context " - "reference\n"); goto out_check; } } diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 08a50f057284..c26e842ad905 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -129,7 +129,6 @@ static ssize_t qeth_dev_portno_store(struct device *dev, portno = simple_strtoul(buf, &tmp, 16); if (portno > QETH_MAX_PORTNO) { - PRINT_WARN("portno 0x%X is out of range\n", portno); return -EINVAL; } @@ -223,8 +222,6 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev, * if though we have to permit priority queueing */ if (card->qdio.no_out_queues == 1) { - PRINT_WARN("Priority queueing disabled due " - "to hardware limitations!\n"); card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT; return -EPERM; } @@ -250,7 +247,6 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev, card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING; card->qdio.default_out_queue = QETH_DEFAULT_QUEUE; } else { - PRINT_WARN("Unknown queueing type '%s'\n", tmp); return -EINVAL; } return count; @@ -291,9 +287,6 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev, ((cnt > QETH_IN_BUF_COUNT_MAX) ? QETH_IN_BUF_COUNT_MAX : cnt); if (old_cnt != cnt) { rc = qeth_realloc_buffer_pool(card, cnt); - if (rc) - PRINT_WARN("Error (%d) while setting " - "buffer count.\n", rc); } return count; } @@ -355,7 +348,6 @@ static ssize_t qeth_dev_performance_stats_store(struct device *dev, card->perf_stats.initial_rx_packets = card->stats.rx_packets; card->perf_stats.initial_tx_packets = card->stats.tx_packets; } else { - PRINT_WARN("performance_stats: write 0 or 1 to this file!\n"); return -EINVAL; } return count; @@ -399,7 +391,6 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, newdis = QETH_DISCIPLINE_LAYER2; break; default: - PRINT_WARN("layer2: write 0 or 1 to this file!\n"); return -EINVAL; } @@ -463,7 +454,6 @@ static ssize_t qeth_dev_large_send_store(struct device *dev, } else if (!strcmp(tmp, "TSO")) { type = QETH_LARGE_SEND_TSO; } else { - PRINT_WARN("large_send: invalid mode %s!\n", tmp); return -EINVAL; } if (card->options.large_send == type) @@ -503,8 +493,6 @@ static ssize_t qeth_dev_blkt_store(struct qeth_card *card, if (i <= max_value) { *value = i; } else { - PRINT_WARN("blkt total time: write values between" - " 0 and %d to this file!\n", max_value); return -EINVAL; } return count; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 86ec50ddae13..f682f7b14480 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -101,19 +101,16 @@ static struct net_device *qeth_l2_netdev_by_devno(unsigned char *read_dev_no) { struct qeth_card *card; struct net_device *ndev; - unsigned char *readno; - __u16 temp_dev_no, card_dev_no; - char *endp; + __u16 temp_dev_no; unsigned long flags; + struct ccw_dev_id read_devid; ndev = NULL; memcpy(&temp_dev_no, read_dev_no, 2); read_lock_irqsave(&qeth_core_card_list.rwlock, flags); list_for_each_entry(card, &qeth_core_card_list.list, list) { - readno = CARD_RDEV_ID(card); - readno += (strlen(readno) - 4); - card_dev_no = simple_strtoul(readno, &endp, 16); - if (card_dev_no == temp_dev_no) { + ccw_device_get_id(CARD_RDEV(card), &read_devid); + if (read_devid.devno == temp_dev_no) { ndev = card->dev; break; } @@ -134,14 +131,14 @@ static int qeth_l2_send_setgroupmac_cb(struct qeth_card *card, mac = &cmd->data.setdelmac.mac[0]; /* MAC already registered, needed in couple/uncouple case */ if (cmd->hdr.return_code == 0x2005) { - PRINT_WARN("Group MAC %02x:%02x:%02x:%02x:%02x:%02x " \ + QETH_DBF_MESSAGE(2, "Group MAC %02x:%02x:%02x:%02x:%02x:%02x " "already existing on %s \n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], QETH_CARD_IFNAME(card)); cmd->hdr.return_code = 0; } if (cmd->hdr.return_code) - PRINT_ERR("Could not set group MAC " \ + QETH_DBF_MESSAGE(2, "Could not set group MAC " "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], QETH_CARD_IFNAME(card), cmd->hdr.return_code); @@ -166,7 +163,7 @@ static int qeth_l2_send_delgroupmac_cb(struct qeth_card *card, cmd = (struct qeth_ipa_cmd *) data; mac = &cmd->data.setdelmac.mac[0]; if (cmd->hdr.return_code) - PRINT_ERR("Could not delete group MAC " \ + QETH_DBF_MESSAGE(2, "Could not delete group MAC " "%02x:%02x:%02x:%02x:%02x:%02x on %s: %x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], QETH_CARD_IFNAME(card), cmd->hdr.return_code); @@ -186,10 +183,8 @@ static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac) mc = kmalloc(sizeof(struct qeth_mc_mac), GFP_ATOMIC); - if (!mc) { - PRINT_ERR("no mem vor mc mac address\n"); + if (!mc) return; - } memcpy(mc->mc_addr, mac, OSA_ADDR_LEN); mc->mc_addrlen = OSA_ADDR_LEN; @@ -280,7 +275,7 @@ static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card, QETH_DBF_TEXT(TRACE, 2, "L2sdvcb"); cmd = (struct qeth_ipa_cmd *) data; if (cmd->hdr.return_code) { - PRINT_ERR("Error in processing VLAN %i on %s: 0x%x. " + QETH_DBF_MESSAGE(2, "Error in processing VLAN %i on %s: 0x%x. " "Continuing\n", cmd->data.setdelvlan.vlan_id, QETH_CARD_IFNAME(card), cmd->hdr.return_code); QETH_DBF_TEXT_(TRACE, 2, "L2VL%4x", cmd->hdr.command); @@ -333,8 +328,6 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) spin_lock_bh(&card->vlanlock); list_add_tail(&id->list, &card->vid_list); spin_unlock_bh(&card->vlanlock); - } else { - PRINT_ERR("no memory for vid\n"); } } @@ -550,16 +543,15 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) rc = qeth_query_setadapterparms(card); if (rc) { - PRINT_WARN("could not query adapter parameters on device %s: " - "x%x\n", CARD_BUS_ID(card), rc); + QETH_DBF_MESSAGE(2, "could not query adapter parameters on " + "device %s: x%x\n", CARD_BUS_ID(card), rc); } if (card->info.guestlan) { rc = qeth_setadpparms_change_macaddr(card); if (rc) { - PRINT_WARN("couldn't get MAC address on " - "device %s: x%x\n", - CARD_BUS_ID(card), rc); + QETH_DBF_MESSAGE(2, "couldn't get MAC address on " + "device %s: x%x\n", CARD_BUS_ID(card), rc); QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); return rc; } @@ -585,8 +577,6 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) } if (card->info.type == QETH_CARD_TYPE_OSN) { - PRINT_WARN("Setting MAC address on %s is not supported.\n", - dev->name); QETH_DBF_TEXT(TRACE, 3, "setmcOSN"); return -EOPNOTSUPP; } @@ -666,7 +656,7 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ctx = qeth_eddp_create_context(card, new_skb, hdr, skb->sk->sk_protocol); if (ctx == NULL) { - PRINT_WARN("could not create eddp context\n"); + QETH_DBF_MESSAGE(2, "could not create eddp context\n"); goto tx_drop; } } else { @@ -731,6 +721,7 @@ tx_drop: if ((new_skb != skb) && new_skb) dev_kfree_skb_any(new_skb); dev_kfree_skb_any(skb); + netif_wake_queue(dev); return NETDEV_TX_OK; } @@ -1155,7 +1146,7 @@ static int qeth_osn_send_control_data(struct qeth_card *card, int len, (addr_t) iob, 0, 0); spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags); if (rc) { - PRINT_WARN("qeth_osn_send_control_data: " + QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: " "ccw_device_start rc = %i\n", rc); QETH_DBF_TEXT_(TRACE, 2, " err%d", rc); qeth_release_buffer(iob->channel, iob); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 94a8ead64ed4..999552c83bbe 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -311,7 +311,6 @@ static struct qeth_ipaddr *qeth_l3_get_addr_buffer( addr = kzalloc(sizeof(struct qeth_ipaddr), GFP_ATOMIC); if (addr == NULL) { - PRINT_WARN("Not enough memory to add address\n"); return NULL; } addr->type = QETH_IP_TYPE_NORMAL; @@ -649,15 +648,6 @@ static void qeth_l3_correct_routing_type(struct qeth_card *card, } } out_inval: - PRINT_WARN("Routing type '%s' not supported for interface %s.\n" - "Router status set to 'no router'.\n", - ((*type == PRIMARY_ROUTER)? "primary router" : - (*type == SECONDARY_ROUTER)? "secondary router" : - (*type == PRIMARY_CONNECTOR)? "primary connector" : - (*type == SECONDARY_CONNECTOR)? "secondary connector" : - (*type == MULTICAST_ROUTER)? "multicast router" : - "unknown"), - card->dev->name); *type = NO_ROUTER; } @@ -674,9 +664,9 @@ int qeth_l3_setrouting_v4(struct qeth_card *card) QETH_PROT_IPV4); if (rc) { card->options.route4.type = NO_ROUTER; - PRINT_WARN("Error (0x%04x) while setting routing type on %s. " - "Type set to 'no router'.\n", - rc, QETH_CARD_IFNAME(card)); + QETH_DBF_MESSAGE(2, "Error (0x%04x) while setting routing type" + " on %s. Type set to 'no router'.\n", rc, + QETH_CARD_IFNAME(card)); } return rc; } @@ -697,9 +687,9 @@ int qeth_l3_setrouting_v6(struct qeth_card *card) QETH_PROT_IPV6); if (rc) { card->options.route6.type = NO_ROUTER; - PRINT_WARN("Error (0x%04x) while setting routing type on %s. " - "Type set to 'no router'.\n", - rc, QETH_CARD_IFNAME(card)); + QETH_DBF_MESSAGE(2, "Error (0x%04x) while setting routing type" + " on %s. Type set to 'no router'.\n", rc, + QETH_CARD_IFNAME(card)); } #endif return rc; @@ -737,7 +727,6 @@ int qeth_l3_add_ipato_entry(struct qeth_card *card, if (!memcmp(ipatoe->addr, new->addr, (ipatoe->proto == QETH_PROT_IPV4)? 4:16) && (ipatoe->mask_bits == new->mask_bits)) { - PRINT_WARN("ipato entry already exists!\n"); rc = -EEXIST; break; } @@ -802,7 +791,6 @@ int qeth_l3_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto, rc = -EEXIST; spin_unlock_irqrestore(&card->ip_lock, flags); if (rc) { - PRINT_WARN("Cannot add VIPA. Address already exists!\n"); return rc; } if (!qeth_l3_add_ip(card, ipaddr)) @@ -867,7 +855,6 @@ int qeth_l3_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto, rc = -EEXIST; spin_unlock_irqrestore(&card->ip_lock, flags); if (rc) { - PRINT_WARN("Cannot add RXIP. Address already exists!\n"); return rc; } if (!qeth_l3_add_ip(card, ipaddr)) @@ -1020,23 +1007,23 @@ static int qeth_l3_setadapter_hstr(struct qeth_card *card) IPA_SETADP_SET_BROADCAST_MODE, card->options.broadcast_mode); if (rc) - PRINT_WARN("couldn't set broadcast mode on " + QETH_DBF_MESSAGE(2, "couldn't set broadcast mode on " "device %s: x%x\n", CARD_BUS_ID(card), rc); rc = qeth_l3_send_setadp_mode(card, IPA_SETADP_ALTER_MAC_ADDRESS, card->options.macaddr_mode); if (rc) - PRINT_WARN("couldn't set macaddr mode on " + QETH_DBF_MESSAGE(2, "couldn't set macaddr mode on " "device %s: x%x\n", CARD_BUS_ID(card), rc); return rc; } if (card->options.broadcast_mode == QETH_TR_BROADCAST_LOCAL) - PRINT_WARN("set adapter parameters not available " + QETH_DBF_MESSAGE(2, "set adapter parameters not available " "to set broadcast mode, using ALLRINGS " "on device %s:\n", CARD_BUS_ID(card)); if (card->options.macaddr_mode == QETH_TR_MACADDR_CANONICAL) - PRINT_WARN("set adapter parameters not available " + QETH_DBF_MESSAGE(2, "set adapter parameters not available " "to set macaddr mode, using NONCANONICAL " "on device %s:\n", CARD_BUS_ID(card)); return 0; @@ -2070,7 +2057,7 @@ static struct qeth_card *qeth_l3_get_card_from_dev(struct net_device *dev) card = netdev_priv(dev); else if (rc == QETH_VLAN_CARD) card = netdev_priv(vlan_dev_info(dev)->real_dev); - if (card->options.layer2) + if (card && card->options.layer2) card = NULL; QETH_DBF_TEXT_(TRACE, 4, "%d", rc); return card ; @@ -2182,8 +2169,6 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries) if (card->info.guestlan) return -EOPNOTSUPP; if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) { - PRINT_WARN("ARP processing not supported " - "on %s!\n", QETH_CARD_IFNAME(card)); return -EOPNOTSUPP; } rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING, @@ -2191,8 +2176,8 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries) no_entries); if (rc) { tmp = rc; - PRINT_WARN("Could not set number of ARP entries on %s: " - "%s (0x%x/%d)\n", QETH_CARD_IFNAME(card), + QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on " + "%s: %s (0x%x/%d)\n", QETH_CARD_IFNAME(card), qeth_l3_arp_get_error_cause(&rc), tmp, tmp); } return rc; @@ -2260,9 +2245,6 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card, qdata->no_entries * uentry_size){ QETH_DBF_TEXT_(TRACE, 4, "qaer3%i", -ENOMEM); cmd->hdr.return_code = -ENOMEM; - PRINT_WARN("query ARP user space buffer is too small for " - "the returned number of ARP entries. " - "Aborting query!\n"); goto out_error; } QETH_DBF_TEXT_(TRACE, 4, "anore%i", @@ -2324,8 +2306,6 @@ static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ IPA_ARP_PROCESSING)) { - PRINT_WARN("ARP processing not supported " - "on %s!\n", QETH_CARD_IFNAME(card)); return -EOPNOTSUPP; } /* get size of userspace buffer and mask_bits -> 6 bytes */ @@ -2344,7 +2324,7 @@ static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) qeth_l3_arp_query_cb, (void *)&qinfo); if (rc) { tmp = rc; - PRINT_WARN("Error while querying ARP cache on %s: %s " + QETH_DBF_MESSAGE(2, "Error while querying ARP cache on %s: %s " "(0x%x/%d)\n", QETH_CARD_IFNAME(card), qeth_l3_arp_get_error_cause(&rc), tmp, tmp); if (copy_to_user(udata, qinfo.udata, 4)) @@ -2375,8 +2355,6 @@ static int qeth_l3_arp_add_entry(struct qeth_card *card, if (card->info.guestlan) return -EOPNOTSUPP; if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) { - PRINT_WARN("ARP processing not supported " - "on %s!\n", QETH_CARD_IFNAME(card)); return -EOPNOTSUPP; } @@ -2391,10 +2369,9 @@ static int qeth_l3_arp_add_entry(struct qeth_card *card, if (rc) { tmp = rc; qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf); - PRINT_WARN("Could not add ARP entry for address %s on %s: " - "%s (0x%x/%d)\n", - buf, QETH_CARD_IFNAME(card), - qeth_l3_arp_get_error_cause(&rc), tmp, tmp); + QETH_DBF_MESSAGE(2, "Could not add ARP entry for address %s " + "on %s: %s (0x%x/%d)\n", buf, QETH_CARD_IFNAME(card), + qeth_l3_arp_get_error_cause(&rc), tmp, tmp); } return rc; } @@ -2417,8 +2394,6 @@ static int qeth_l3_arp_remove_entry(struct qeth_card *card, if (card->info.guestlan) return -EOPNOTSUPP; if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) { - PRINT_WARN("ARP processing not supported " - "on %s!\n", QETH_CARD_IFNAME(card)); return -EOPNOTSUPP; } memcpy(buf, entry, 12); @@ -2433,10 +2408,9 @@ static int qeth_l3_arp_remove_entry(struct qeth_card *card, tmp = rc; memset(buf, 0, 16); qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf); - PRINT_WARN("Could not delete ARP entry for address %s on %s: " - "%s (0x%x/%d)\n", - buf, QETH_CARD_IFNAME(card), - qeth_l3_arp_get_error_cause(&rc), tmp, tmp); + QETH_DBF_MESSAGE(2, "Could not delete ARP entry for address %s" + " on %s: %s (0x%x/%d)\n", buf, QETH_CARD_IFNAME(card), + qeth_l3_arp_get_error_cause(&rc), tmp, tmp); } return rc; } @@ -2456,16 +2430,14 @@ static int qeth_l3_arp_flush_cache(struct qeth_card *card) if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD)) return -EOPNOTSUPP; if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) { - PRINT_WARN("ARP processing not supported " - "on %s!\n", QETH_CARD_IFNAME(card)); return -EOPNOTSUPP; } rc = qeth_l3_send_simple_setassparms(card, IPA_ARP_PROCESSING, IPA_CMD_ASS_ARP_FLUSH_CACHE, 0); if (rc) { tmp = rc; - PRINT_WARN("Could not flush ARP cache on %s: %s (0x%x/%d)\n", - QETH_CARD_IFNAME(card), + QETH_DBF_MESSAGE(2, "Could not flush ARP cache on %s: %s " + "(0x%x/%d)\n", QETH_CARD_IFNAME(card), qeth_l3_arp_get_error_cause(&rc), tmp, tmp); } return rc; @@ -2724,7 +2696,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ctx = qeth_eddp_create_context(card, new_skb, hdr, skb->sk->sk_protocol); if (ctx == NULL) { - PRINT_WARN("could not create eddp context\n"); + QETH_DBF_MESSAGE(2, "could not create eddp context\n"); goto tx_drop; } } else { @@ -2792,6 +2764,7 @@ tx_drop: if ((new_skb != skb) && new_skb) dev_kfree_skb_any(new_skb); dev_kfree_skb_any(skb); + netif_wake_queue(dev); return NETDEV_TX_OK; } diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index 08f51fd902c4..ac1993708ae9 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -85,7 +85,6 @@ static ssize_t qeth_l3_dev_route_store(struct qeth_card *card, } else if (!strcmp(tmp, "multicast_router")) { route->type = MULTICAST_ROUTER; } else { - PRINT_WARN("Invalid routing type '%s'.\n", tmp); return -EINVAL; } if (((card->state == CARD_STATE_SOFTSETUP) || @@ -137,9 +136,6 @@ static ssize_t qeth_l3_dev_route6_store(struct device *dev, return -EINVAL; if (!qeth_is_supported(card, IPA_IPV6)) { - PRINT_WARN("IPv6 not supported for interface %s.\n" - "Routing status no changed.\n", - QETH_CARD_IFNAME(card)); return -ENOTSUPP; } @@ -179,7 +175,6 @@ static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev, if ((i == 0) || (i == 1)) card->options.fake_broadcast = i; else { - PRINT_WARN("fake_broadcast: write 0 or 1 to this file!\n"); return -EINVAL; } return count; @@ -220,7 +215,6 @@ static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev, if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) { - PRINT_WARN("Device is not a tokenring device!\n"); return -EINVAL; } @@ -233,8 +227,6 @@ static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev, card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS; return count; } else { - PRINT_WARN("broadcast_mode: invalid mode %s!\n", - tmp); return -EINVAL; } return count; @@ -275,7 +267,6 @@ static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev, if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) { - PRINT_WARN("Device is not a tokenring device!\n"); return -EINVAL; } @@ -285,7 +276,6 @@ static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev, QETH_TR_MACADDR_CANONICAL : QETH_TR_MACADDR_NONCANONICAL; else { - PRINT_WARN("canonical_macaddr: write 0 or 1 to this file!\n"); return -EINVAL; } return count; @@ -327,7 +317,6 @@ static ssize_t qeth_l3_dev_checksum_store(struct device *dev, else if (!strcmp(tmp, "no_checksumming")) card->options.checksum_type = NO_CHECKSUMMING; else { - PRINT_WARN("Unknown checksumming type '%s'\n", tmp); return -EINVAL; } return count; @@ -382,8 +371,6 @@ static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev, } else if (!strcmp(tmp, "0")) { card->ipato.enabled = 0; } else { - PRINT_WARN("ipato_enable: write 0, 1 or 'toggle' to " - "this file\n"); return -EINVAL; } return count; @@ -422,8 +409,6 @@ static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev, } else if (!strcmp(tmp, "0")) { card->ipato.invert4 = 0; } else { - PRINT_WARN("ipato_invert4: write 0, 1 or 'toggle' to " - "this file\n"); return -EINVAL; } return count; @@ -486,13 +471,10 @@ static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto, /* get address string */ end = strchr(start, '/'); if (!end || (end - start >= 40)) { - PRINT_WARN("Invalid format for ipato_addx/delx. " - "Use <ip addr>/<mask bits>\n"); return -EINVAL; } strncpy(buffer, start, end - start); if (qeth_l3_string_to_ipaddr(buffer, proto, addr)) { - PRINT_WARN("Invalid IP address format!\n"); return -EINVAL; } start = end + 1; @@ -500,7 +482,6 @@ static int qeth_l3_parse_ipatoe(const char *buf, enum qeth_prot_versions proto, if (!strlen(start) || (tmp == start) || (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) { - PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n"); return -EINVAL; } return 0; @@ -520,7 +501,6 @@ static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count, ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL); if (!ipatoe) { - PRINT_WARN("No memory to allocate ipato entry\n"); return -ENOMEM; } ipatoe->proto = proto; @@ -609,8 +589,6 @@ static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev, } else if (!strcmp(tmp, "0")) { card->ipato.invert6 = 0; } else { - PRINT_WARN("ipato_invert6: write 0, 1 or 'toggle' to " - "this file\n"); return -EINVAL; } return count; @@ -724,7 +702,6 @@ static int qeth_l3_parse_vipae(const char *buf, enum qeth_prot_versions proto, u8 *addr) { if (qeth_l3_string_to_ipaddr(buf, proto, addr)) { - PRINT_WARN("Invalid IP address format!\n"); return -EINVAL; } return 0; @@ -891,7 +868,6 @@ static int qeth_l3_parse_rxipe(const char *buf, enum qeth_prot_versions proto, u8 *addr) { if (qeth_l3_string_to_ipaddr(buf, proto, addr)) { - PRINT_WARN("Invalid IP address format!\n"); return -EINVAL; } return 0; diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index 5080f343ad74..5bfbe7659830 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c @@ -207,6 +207,7 @@ s390_handle_mcck(void) do_exit(SIGSEGV); } } +EXPORT_SYMBOL_GPL(s390_handle_mcck); /* * returns 0 if all registers could be validated diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8eb4da332f56..94789be54ca3 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -644,6 +644,48 @@ static void hub_stop(struct usb_hub *hub) #ifdef CONFIG_PM +/* Try to identify which devices need USB-PERSIST handling */ +static int persistent_device(struct usb_device *udev) +{ + int i; + int retval; + struct usb_host_config *actconfig; + + /* Explicitly not marked persistent? */ + if (!udev->persist_enabled) + return 0; + + /* No active config? */ + actconfig = udev->actconfig; + if (!actconfig) + return 0; + + /* FIXME! We should check whether it's open here or not! */ + + /* + * Check that all the interface drivers have a + * 'reset_resume' entrypoint + */ + retval = 0; + for (i = 0; i < actconfig->desc.bNumInterfaces; i++) { + struct usb_interface *intf; + struct usb_driver *driver; + + intf = actconfig->interface[i]; + if (!intf->dev.driver) + continue; + driver = to_usb_driver(intf->dev.driver); + if (!driver->reset_resume) + return 0; + /* + * We have at least one driver, and that one + * has a reset_resume method. + */ + retval = 1; + } + return retval; +} + static void hub_restart(struct usb_hub *hub, int type) { struct usb_device *hdev = hub->hdev; @@ -689,8 +731,8 @@ static void hub_restart(struct usb_hub *hub, int type) * turn off the various status changes to prevent * khubd from disconnecting it later. */ - if (udev->persist_enabled && status == 0 && - !(portstatus & USB_PORT_STAT_ENABLE)) { + if (status == 0 && !(portstatus & USB_PORT_STAT_ENABLE) && + persistent_device(udev)) { if (portchange & USB_PORT_STAT_C_ENABLE) clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_ENABLE); diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index c9cec8738261..65aa5ecf569a 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2207,14 +2207,14 @@ struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, goto err_put; } - ret = usb_add_hcd(hcd, irq, irqflags); - if (ret) - goto err_unmap; - hcd->irq = irq; hcd->rsrc_start = res_start; hcd->rsrc_len = res_len; + ret = usb_add_hcd(hcd, irq, irqflags); + if (ret) + goto err_unmap; + return hcd; err_unmap: diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index eb6c06979f3b..001789c9a11a 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -272,6 +272,7 @@ config USB_TEST config USB_ISIGHTFW tristate "iSight firmware loading support" depends on USB + select FW_LOADER help This driver loads firmware for USB Apple iSight cameras, allowing them to be driven by the USB video class driver available at diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c index 390e04885536..9f30aa1f8a5d 100644 --- a/drivers/usb/misc/isight_firmware.c +++ b/drivers/usb/misc/isight_firmware.c @@ -39,9 +39,12 @@ static int isight_firmware_load(struct usb_interface *intf, struct usb_device *dev = interface_to_usbdev(intf); int llen, len, req, ret = 0; const struct firmware *firmware; - unsigned char *buf; + unsigned char *buf = kmalloc(50, GFP_KERNEL); unsigned char data[4]; - char *ptr; + u8 *ptr; + + if (!buf) + return -ENOMEM; if (request_firmware(&firmware, "isight.fw", &dev->dev) != 0) { printk(KERN_ERR "Unable to load isight firmware\n"); @@ -59,7 +62,7 @@ static int isight_firmware_load(struct usb_interface *intf, goto out; } - while (1) { + while (ptr+4 <= firmware->data+firmware->size) { memcpy(data, ptr, 4); len = (data[0] << 8 | data[1]); req = (data[2] << 8 | data[3]); @@ -71,10 +74,14 @@ static int isight_firmware_load(struct usb_interface *intf, continue; for (; len > 0; req += 50) { - llen = len > 50 ? 50 : len; + llen = min(len, 50); len -= llen; - - buf = kmalloc(llen, GFP_KERNEL); + if (ptr+llen > firmware->data+firmware->size) { + printk(KERN_ERR + "Malformed isight firmware"); + ret = -ENODEV; + goto out; + } memcpy(buf, ptr, llen); ptr += llen; @@ -89,16 +96,18 @@ static int isight_firmware_load(struct usb_interface *intf, goto out; } - kfree(buf); } } + if (usb_control_msg (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1, 300) != 1) { printk(KERN_ERR "isight firmware loading completion failed\n"); ret = -ENODEV; } + out: + kfree(buf); release_firmware(firmware); return ret; } diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 35ac9d956b3d..c14b2435d23e 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -2432,9 +2432,9 @@ static int cirrusfb_pci_register(struct pci_dev *pdev, info->screen_size = board_size; cinfo->unmap = cirrusfb_pci_unmap; - printk(KERN_INFO " RAM (%lu kB) at 0xx%lx, ", - info->screen_size >> 10, board_addr); - printk(KERN_INFO "Cirrus Logic chipset on PCI bus\n"); + printk(KERN_INFO "RAM (%lu kB) at 0x%lx, Cirrus " + "Logic chipset on PCI bus\n", + info->screen_size >> 10, board_addr); pci_set_drvdata(pdev, info); ret = cirrusfb_register(info); diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index b50bb03cb5ab..0a2785361ca3 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -1320,7 +1320,7 @@ static void free_irq_local(int irq) * Power management hooks. Note that we won't be called from IRQ context, * unlike the blank functions above, so we may sleep. */ -static int fsl_diu_suspend(struct of_device *dev, pm_message_t state) +static int fsl_diu_suspend(struct of_device *ofdev, pm_message_t state) { struct fsl_diu_data *machine_data; @@ -1330,7 +1330,7 @@ static int fsl_diu_suspend(struct of_device *dev, pm_message_t state) return 0; } -static int fsl_diu_resume(struct of_device *dev) +static int fsl_diu_resume(struct of_device *ofdev) { struct fsl_diu_data *machine_data; diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index fb9e67228543..c18880d9db1f 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c @@ -279,7 +279,7 @@ static void hga_blank(int blank_mode) static int __init hga_card_detect(void) { - int count=0; + int count = 0; void __iomem *p, *q; unsigned short p_save, q_save; @@ -303,20 +303,18 @@ static int __init hga_card_detect(void) writew(0x55aa, p); if (readw(p) == 0x55aa) count++; writew(p_save, p); - if (count != 2) { - return 0; - } + if (count != 2) + goto error; /* Ok, there is definitely a card registering at the correct * memory location, so now we do an I/O port test. */ - if (!test_hga_b(0x66, 0x0f)) { /* cursor low register */ - return 0; - } - if (!test_hga_b(0x99, 0x0f)) { /* cursor low register */ - return 0; - } + if (!test_hga_b(0x66, 0x0f)) /* cursor low register */ + goto error; + + if (!test_hga_b(0x99, 0x0f)) /* cursor low register */ + goto error; /* See if the card is a Hercules, by checking whether the vsync * bit of the status register is changing. This test lasts for @@ -331,7 +329,7 @@ static int __init hga_card_detect(void) } if (p_save == q_save) - return 0; + goto error; switch (inb_p(HGA_STATUS_PORT) & 0x70) { case 0x10: @@ -348,6 +346,12 @@ static int __init hga_card_detect(void) break; } return 1; +error: + if (release_io_ports) + release_region(0x3b0, 12); + if (release_io_port) + release_region(0x3bf, 1); + return 0; } /** diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 28e3d5c5fcac..1f3465201fdf 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -2,6 +2,11 @@ Version 1.53 ------------ DFS support added (Microsoft Distributed File System client support needed for referrals which enable a hierarchical name space among servers). +Disable temporary caching of mode bits to servers which do not support +storing of mode (e.g. Windows servers, when client mounts without cifsacl +mount option) and add new "dynperm" mount option to enable temporary caching +of mode (enable old behavior). Fix hang on mount caused when server crashes +tcp session during negotiate protocol. Version 1.52 ------------ diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5df93fd6303f..86b4d5f405ae 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -97,9 +97,6 @@ cifs_read_super(struct super_block *sb, void *data, { struct inode *inode; struct cifs_sb_info *cifs_sb; -#ifdef CONFIG_CIFS_DFS_UPCALL - int len; -#endif int rc = 0; /* BB should we make this contingent on mount parm? */ @@ -117,15 +114,17 @@ cifs_read_super(struct super_block *sb, void *data, * complex operation (mount), and in case of fail * just exit instead of doing mount and attempting * undo it if this copy fails?*/ - len = strlen(data); - cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); - if (cifs_sb->mountdata == NULL) { - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; - return -ENOMEM; + if (data) { + int len = strlen(data); + cifs_sb->mountdata = kzalloc(len + 1, GFP_KERNEL); + if (cifs_sb->mountdata == NULL) { + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + return -ENOMEM; + } + strncpy(cifs_sb->mountdata, data, len + 1); + cifs_sb->mountdata[len] = '\0'; } - strncpy(cifs_sb->mountdata, data, len + 1); - cifs_sb->mountdata[len] = '\0'; #endif rc = cifs_mount(sb, cifs_sb, data, devname); diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 08914053242b..9cfcf326ead3 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -333,7 +333,6 @@ struct cifsFileInfo { bool messageMode:1; /* for pipes: message vs byte mode */ atomic_t wrtPending; /* handle in use - defer close */ struct semaphore fh_sem; /* prevents reopen race after dead ses*/ - char *search_resume_name; /* BB removeme BB */ struct cifs_search_info srch_inf; }; @@ -626,7 +625,7 @@ GLOBAL_EXTERN atomic_t tcpSesAllocCount; GLOBAL_EXTERN atomic_t tcpSesReconnectCount; GLOBAL_EXTERN atomic_t tconInfoReconnectCount; -/* Various Debug counters to remove someday (BB) */ +/* Various Debug counters */ GLOBAL_EXTERN atomic_t bufAllocCount; /* current number allocated */ #ifdef CONFIG_CIFS_STATS2 GLOBAL_EXTERN atomic_t totBufAllocCount; /* total allocated over all time */ diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 65d58b4e6a61..0f327c224da3 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -79,6 +79,19 @@ #define TRANS2_GET_DFS_REFERRAL 0x10 #define TRANS2_REPORT_DFS_INCOSISTENCY 0x11 +/* SMB Transact (Named Pipe) subcommand codes */ +#define TRANS_SET_NMPIPE_STATE 0x0001 +#define TRANS_RAW_READ_NMPIPE 0x0011 +#define TRANS_QUERY_NMPIPE_STATE 0x0021 +#define TRANS_QUERY_NMPIPE_INFO 0x0022 +#define TRANS_PEEK_NMPIPE 0x0023 +#define TRANS_TRANSACT_NMPIPE 0x0026 +#define TRANS_RAW_WRITE_NMPIPE 0x0031 +#define TRANS_READ_NMPIPE 0x0036 +#define TRANS_WRITE_NMPIPE 0x0037 +#define TRANS_WAIT_NMPIPE 0x0053 +#define TRANS_CALL_NMPIPE 0x0054 + /* NT Transact subcommand codes */ #define NT_TRANSACT_CREATE 0x01 #define NT_TRANSACT_IOCTL 0x02 @@ -328,12 +341,13 @@ #define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */ #define CREATE_NO_EA_KNOWLEDGE 0x00000200 #define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete - open for recovery flag - should - be zero */ + "open for recovery" flag - should + be zero in any case */ +#define CREATE_OPEN_FOR_RECOVERY 0x00000400 #define CREATE_RANDOM_ACCESS 0x00000800 #define CREATE_DELETE_ON_CLOSE 0x00001000 #define CREATE_OPEN_BY_ID 0x00002000 -#define CREATE_OPEN_BACKUP_INTN 0x00004000 +#define CREATE_OPEN_BACKUP_INTENT 0x00004000 #define CREATE_NO_COMPRESSION 0x00008000 #define CREATE_RESERVE_OPFILTER 0x00100000 /* should be zero */ #define OPEN_REPARSE_POINT 0x00200000 @@ -722,7 +736,6 @@ typedef struct smb_com_tconx_rsp_ext { #define SMB_CSC_CACHE_AUTO_REINT 0x0004 #define SMB_CSC_CACHE_VDO 0x0008 #define SMB_CSC_NO_CACHING 0x000C - #define SMB_UNIQUE_FILE_NAME 0x0010 #define SMB_EXTENDED_SIGNATURES 0x0020 @@ -806,7 +819,7 @@ typedef struct smb_com_findclose_req { #define ICOUNT_MASK 0x00FF #define PIPE_READ_MODE 0x0100 #define NAMED_PIPE_TYPE 0x0400 -#define PIPE_END_POINT 0x0800 +#define PIPE_END_POINT 0x4000 #define BLOCKING_NAMED_PIPE 0x8000 typedef struct smb_com_open_req { /* also handles create */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index fb655b4593c6..4511b708f0f3 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1728,7 +1728,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, { int rc = 0; LOCK_REQ *pSMB = NULL; - LOCK_RSP *pSMBr = NULL; +/* LOCK_RSP *pSMBr = NULL; */ /* No response data other than rc to parse */ int bytes_returned; int timeout = 0; __u16 count; @@ -1739,8 +1739,6 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, if (rc) return rc; - pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ - if (lockType == LOCKING_ANDX_OPLOCK_RELEASE) { timeout = CIFS_ASYNC_OP; /* no response expected */ pSMB->Timeout = 0; @@ -1774,7 +1772,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, if (waitFlag) { rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned); + (struct smb_hdr *) pSMB, &bytes_returned); cifs_small_buf_release(pSMB); } else { rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 023434f72c15..e8fa46c7cff2 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -653,6 +653,7 @@ multi_t2_fnd: spin_lock(&GlobalMid_Lock); server->tcpStatus = CifsExiting; spin_unlock(&GlobalMid_Lock); + wake_up_all(&server->response_q); /* don't exit until kthread_stop is called */ set_current_state(TASK_UNINTERRUPTIBLE); @@ -2120,6 +2121,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; } + if ((volume_info.cifs_acl) && (volume_info.dynperm)) + cERROR(1, ("mount option dynperm ignored if cifsacl " + "mount option supported")); + tcon = find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, volume_info.username); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index f0b5b5f3dd2e..fb69c1fa85c9 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -260,7 +260,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, buf, inode->i_sb, xid, &fileHandle); if (newinode) { - newinode->i_mode = mode; + if (cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_DYNPERM) + newinode->i_mode = mode; if ((oplock & CIFS_CREATE_ACTION) && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 8636cec2642c..0aac824371a5 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -546,7 +546,6 @@ int cifs_close(struct inode *inode, struct file *file) msleep(timeout); timeout *= 8; } - kfree(pSMBFile->search_resume_name); kfree(file->private_data); file->private_data = NULL; } else @@ -605,12 +604,6 @@ int cifs_closedir(struct inode *inode, struct file *file) else cifs_buf_release(ptmp); } - ptmp = pCFileStruct->search_resume_name; - if (ptmp) { - cFYI(1, ("closedir free resume name")); - pCFileStruct->search_resume_name = NULL; - kfree(ptmp); - } kfree(file->private_data); file->private_data = NULL; } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 129dbfe4dca7..722be543ceec 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -418,6 +418,7 @@ int cifs_get_inode_info(struct inode **pinode, char *buf = NULL; bool adjustTZ = false; bool is_dfs_referral = false; + umode_t default_mode; pTcon = cifs_sb->tcon; cFYI(1, ("Getting info on %s", full_path)); @@ -530,47 +531,42 @@ int cifs_get_inode_info(struct inode **pinode, inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; } - /* set default mode. will override for dirs below */ - if (atomic_read(&cifsInfo->inUse) == 0) - /* new inode, can safely set these fields */ - inode->i_mode = cifs_sb->mnt_file_mode; - else /* since we set the inode type below we need to mask off - to avoid strange results if type changes and both - get orred in */ - inode->i_mode &= ~S_IFMT; -/* if (attr & ATTR_REPARSE) */ - /* We no longer handle these as symlinks because we could not - follow them due to the absolute path with drive letter */ - if (attr & ATTR_DIRECTORY) { - /* override default perms since we do not do byte range locking - on dirs */ - inode->i_mode = cifs_sb->mnt_dir_mode; - inode->i_mode |= S_IFDIR; - } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && - (cifsInfo->cifsAttrs & ATTR_SYSTEM) && - /* No need to le64 convert size of zero */ - (pfindData->EndOfFile == 0)) { - inode->i_mode = cifs_sb->mnt_file_mode; - inode->i_mode |= S_IFIFO; -/* BB Finish for SFU style symlinks and devices */ - } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && - (cifsInfo->cifsAttrs & ATTR_SYSTEM)) { - if (decode_sfu_inode(inode, le64_to_cpu(pfindData->EndOfFile), - full_path, cifs_sb, xid)) - cFYI(1, ("Unrecognized sfu inode type")); - - cFYI(1, ("sfu mode 0%o", inode->i_mode)); + /* get default inode mode */ + if (attr & ATTR_DIRECTORY) + default_mode = cifs_sb->mnt_dir_mode; + else + default_mode = cifs_sb->mnt_file_mode; + + /* set permission bits */ + if (atomic_read(&cifsInfo->inUse) == 0 || + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) + inode->i_mode = default_mode; + else { + /* just reenable write bits if !ATTR_READONLY */ + if ((inode->i_mode & S_IWUGO) == 0 && + (attr & ATTR_READONLY) == 0) + inode->i_mode |= (S_IWUGO & default_mode); + inode->i_mode &= ~S_IFMT; + } + /* clear write bits if ATTR_READONLY is set */ + if (attr & ATTR_READONLY) + inode->i_mode &= ~S_IWUGO; + + /* set inode type */ + if ((attr & ATTR_SYSTEM) && + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { + /* no need to fix endianness on 0 */ + if (pfindData->EndOfFile == 0) + inode->i_mode |= S_IFIFO; + else if (decode_sfu_inode(inode, + le64_to_cpu(pfindData->EndOfFile), + full_path, cifs_sb, xid)) + cFYI(1, ("unknown SFU file type\n")); } else { - inode->i_mode |= S_IFREG; - /* treat dos attribute of read-only as read-only mode eg 555 */ - if (cifsInfo->cifsAttrs & ATTR_READONLY) - inode->i_mode &= ~(S_IWUGO); - else if ((inode->i_mode & S_IWUGO) == 0) - /* the ATTR_READONLY flag may have been */ - /* changed on server -- set any w bits */ - /* allowed by mnt_file_mode */ - inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); - /* BB add code to validate if device or weird share or device type? */ + if (attr & ATTR_DIRECTORY) + inode->i_mode |= S_IFDIR; + else + inode->i_mode |= S_IFREG; } spin_lock(&inode->i_lock); @@ -1019,8 +1015,11 @@ mkdir_get_info: CIFS_MOUNT_MAP_SPECIAL_CHR); } if (direntry->d_inode) { - direntry->d_inode->i_mode = mode; - direntry->d_inode->i_mode |= S_IFDIR; + if (cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_DYNPERM) + direntry->d_inode->i_mode = + (mode | S_IFDIR); + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { direntry->d_inode->i_uid = @@ -1547,13 +1546,26 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) } else goto cifs_setattr_exit; } - if (attrs->ia_valid & ATTR_UID) { - cFYI(1, ("UID changed to %d", attrs->ia_uid)); - uid = attrs->ia_uid; - } - if (attrs->ia_valid & ATTR_GID) { - cFYI(1, ("GID changed to %d", attrs->ia_gid)); - gid = attrs->ia_gid; + + /* + * Without unix extensions we can't send ownership changes to the + * server, so silently ignore them. This is consistent with how + * local DOS/Windows filesystems behave (VFAT, NTFS, etc). With + * CIFSACL support + proper Windows to Unix idmapping, we may be + * able to support this in the future. + */ + if (!pTcon->unix_ext && + !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { + attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); + } else { + if (attrs->ia_valid & ATTR_UID) { + cFYI(1, ("UID changed to %d", attrs->ia_uid)); + uid = attrs->ia_uid; + } + if (attrs->ia_valid & ATTR_GID) { + cFYI(1, ("GID changed to %d", attrs->ia_gid)); + gid = attrs->ia_gid; + } } time_buf.Attributes = 0; @@ -1563,7 +1575,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) attrs->ia_valid &= ~ATTR_MODE; if (attrs->ia_valid & ATTR_MODE) { - cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode)); + cFYI(1, ("Mode changed to 0%o", attrs->ia_mode)); mode = attrs->ia_mode; } @@ -1578,18 +1590,18 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) #ifdef CONFIG_CIFS_EXPERIMENTAL if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) rc = mode_to_acl(inode, full_path, mode); - else if ((mode & S_IWUGO) == 0) { -#else - if ((mode & S_IWUGO) == 0) { + else #endif - /* not writeable */ - if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) { - set_dosattr = true; - time_buf.Attributes = - cpu_to_le32(cifsInode->cifsAttrs | - ATTR_READONLY); - } - } else if (cifsInode->cifsAttrs & ATTR_READONLY) { + if (((mode & S_IWUGO) == 0) && + (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { + set_dosattr = true; + time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs | + ATTR_READONLY); + /* fix up mode if we're not using dynperm */ + if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) + attrs->ia_mode = inode->i_mode & ~S_IWUGO; + } else if ((mode & S_IWUGO) && + (cifsInode->cifsAttrs & ATTR_READONLY)) { /* If file is readonly on server, we would not be able to write to it - so if any write bit is enabled for user or group or other we @@ -1600,6 +1612,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) /* Windows ignores set to zero */ if (time_buf.Attributes == 0) time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); + + /* reset local inode permissions to normal */ + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { + attrs->ia_mode &= ~(S_IALLUGO); + if (S_ISDIR(inode->i_mode)) + attrs->ia_mode |= + cifs_sb->mnt_dir_mode; + else + attrs->ia_mode |= + cifs_sb->mnt_file_mode; + } + } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { + /* ignore mode change - ATTR_READONLY hasn't changed */ + attrs->ia_valid &= ~ATTR_MODE; } } diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 1d69b8014e0b..4b17f8fe3157 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -519,8 +519,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) pnotify = (struct file_notify_information *) ((char *)&pSMBr->hdr.Protocol + data_offset); cFYI(1, ("dnotify on %s Action: 0x%x", - pnotify->FileName, - pnotify->Action)); /* BB removeme BB */ + pnotify->FileName, pnotify->Action)); /* cifs_dump_mem("Rcvd notify Data: ",buf, sizeof(struct smb_hdr)+60); */ return true; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 713c25110197..83f306954883 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -132,6 +132,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, __u32 attr; __u64 allocation_size; __u64 end_of_file; + umode_t default_mode; /* save mtime and size */ local_mtime = tmp_inode->i_mtime; @@ -187,48 +188,54 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, if (atomic_read(&cifsInfo->inUse) == 0) { tmp_inode->i_uid = cifs_sb->mnt_uid; tmp_inode->i_gid = cifs_sb->mnt_gid; - /* set default mode. will override for dirs below */ - tmp_inode->i_mode = cifs_sb->mnt_file_mode; - } else { - /* mask off the type bits since it gets set - below and we do not want to get two type - bits set */ + } + + if (attr & ATTR_DIRECTORY) + default_mode = cifs_sb->mnt_dir_mode; + else + default_mode = cifs_sb->mnt_file_mode; + + /* set initial permissions */ + if ((atomic_read(&cifsInfo->inUse) == 0) || + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) + tmp_inode->i_mode = default_mode; + else { + /* just reenable write bits if !ATTR_READONLY */ + if ((tmp_inode->i_mode & S_IWUGO) == 0 && + (attr & ATTR_READONLY) == 0) + tmp_inode->i_mode |= (S_IWUGO & default_mode); + tmp_inode->i_mode &= ~S_IFMT; } - if (attr & ATTR_DIRECTORY) { - *pobject_type = DT_DIR; - /* override default perms since we do not lock dirs */ - if (atomic_read(&cifsInfo->inUse) == 0) - tmp_inode->i_mode = cifs_sb->mnt_dir_mode; - tmp_inode->i_mode |= S_IFDIR; - } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && - (attr & ATTR_SYSTEM)) { + /* clear write bits if ATTR_READONLY is set */ + if (attr & ATTR_READONLY) + tmp_inode->i_mode &= ~S_IWUGO; + + /* set inode type */ + if ((attr & ATTR_SYSTEM) && + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { if (end_of_file == 0) { - *pobject_type = DT_FIFO; tmp_inode->i_mode |= S_IFIFO; + *pobject_type = DT_FIFO; } else { - /* rather than get the type here, we mark the - inode as needing revalidate and get the real type - (blk vs chr vs. symlink) later ie in lookup */ - *pobject_type = DT_REG; + /* + * trying to get the type can be slow, so just call + * this a regular file for now, and mark for reval + */ tmp_inode->i_mode |= S_IFREG; + *pobject_type = DT_REG; cifsInfo->time = 0; } -/* we no longer mark these because we could not follow them */ -/* } else if (attr & ATTR_REPARSE) { - *pobject_type = DT_LNK; - tmp_inode->i_mode |= S_IFLNK; */ } else { - *pobject_type = DT_REG; - tmp_inode->i_mode |= S_IFREG; - if (attr & ATTR_READONLY) - tmp_inode->i_mode &= ~(S_IWUGO); - else if ((tmp_inode->i_mode & S_IWUGO) == 0) - /* the ATTR_READONLY flag may have been changed on */ - /* server -- set any w bits allowed by mnt_file_mode */ - tmp_inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode); - } /* could add code here - to validate if device or weird share type? */ + if (attr & ATTR_DIRECTORY) { + tmp_inode->i_mode |= S_IFDIR; + *pobject_type = DT_DIR; + } else { + tmp_inode->i_mode |= S_IFREG; + *pobject_type = DT_REG; + } + } /* can not fill in nlink here as in qpathinfo version and Unx search */ if (atomic_read(&cifsInfo->inUse) == 0) @@ -675,8 +682,6 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, cifsFile->invalidHandle = true; CIFSFindClose(xid, pTcon, cifsFile->netfid); } - kfree(cifsFile->search_resume_name); - cifsFile->search_resume_name = NULL; if (cifsFile->srch_inf.ntwrk_buf_start) { cFYI(1, ("freeing SMB ff cache buf on search rewind")); if (cifsFile->srch_inf.smallBuf) @@ -1043,9 +1048,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) } /* else { cifsFile->invalidHandle = true; CIFSFindClose(xid, pTcon, cifsFile->netfid); - } - kfree(cifsFile->search_resume_name); - cifsFile->search_resume_name = NULL; */ + } */ rc = find_cifs_entry(xid, pTcon, file, ¤t_entry, &num_to_fill); diff --git a/fs/fat/file.c b/fs/fat/file.c index 27cc1164ec36..771326b8047e 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -257,26 +257,34 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) } EXPORT_SYMBOL_GPL(fat_getattr); -static int fat_check_mode(const struct msdos_sb_info *sbi, struct inode *inode, - mode_t mode) +static int fat_sanitize_mode(const struct msdos_sb_info *sbi, + struct inode *inode, umode_t *mode_ptr) { - mode_t mask, req = mode & ~S_IFMT; + mode_t mask, perm; - if (S_ISREG(mode)) + /* + * Note, the basic check is already done by a caller of + * (attr->ia_mode & ~MSDOS_VALID_MODE) + */ + + if (S_ISREG(inode->i_mode)) mask = sbi->options.fs_fmask; else mask = sbi->options.fs_dmask; + perm = *mode_ptr & ~(S_IFMT | mask); + /* * Of the r and x bits, all (subject to umask) must be present. Of the * w bits, either all (subject to umask) or none must be present. */ - req &= ~mask; - if ((req & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO))) + if ((perm & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO))) return -EPERM; - if ((req & S_IWUGO) && ((req & S_IWUGO) != (S_IWUGO & ~mask))) + if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask))) return -EPERM; + *mode_ptr &= S_IFMT | perm; + return 0; } @@ -299,7 +307,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) { struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); struct inode *inode = dentry->d_inode; - int mask, error = 0; + int error = 0; unsigned int ia_valid; lock_kernel(); @@ -332,12 +340,13 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) error = 0; goto out; } + if (((attr->ia_valid & ATTR_UID) && (attr->ia_uid != sbi->options.fs_uid)) || ((attr->ia_valid & ATTR_GID) && (attr->ia_gid != sbi->options.fs_gid)) || ((attr->ia_valid & ATTR_MODE) && - fat_check_mode(sbi, inode, attr->ia_mode) < 0)) + (attr->ia_mode & ~MSDOS_VALID_MODE))) error = -EPERM; if (error) { @@ -346,15 +355,16 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) goto out; } - error = inode_setattr(inode, attr); - if (error) - goto out; + /* + * We don't return -EPERM here. Yes, strange, but this is too + * old behavior. + */ + if (attr->ia_valid & ATTR_MODE) { + if (fat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0) + attr->ia_valid &= ~ATTR_MODE; + } - if (S_ISDIR(inode->i_mode)) - mask = sbi->options.fs_dmask; - else - mask = sbi->options.fs_fmask; - inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask); + error = inode_setattr(inode, attr); out: unlock_kernel(); return error; diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 17403629e330..ab8ccc9d14ff 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -315,9 +315,9 @@ struct mem_size_stats { }; static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, - void *private) + struct mm_walk *walk) { - struct mem_size_stats *mss = private; + struct mem_size_stats *mss = walk->private; struct vm_area_struct *vma = mss->vma; pte_t *pte, ptent; spinlock_t *ptl; @@ -365,19 +365,21 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, return 0; } -static struct mm_walk smaps_walk = { .pmd_entry = smaps_pte_range }; - static int show_smap(struct seq_file *m, void *v) { struct vm_area_struct *vma = v; struct mem_size_stats mss; int ret; + struct mm_walk smaps_walk = { + .pmd_entry = smaps_pte_range, + .mm = vma->vm_mm, + .private = &mss, + }; memset(&mss, 0, sizeof mss); mss.vma = vma; if (vma->vm_mm && !is_vm_hugetlb_page(vma)) - walk_page_range(vma->vm_mm, vma->vm_start, vma->vm_end, - &smaps_walk, &mss); + walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); ret = show_map(m, v); if (ret) @@ -426,9 +428,9 @@ const struct file_operations proc_smaps_operations = { }; static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, - unsigned long end, void *private) + unsigned long end, struct mm_walk *walk) { - struct vm_area_struct *vma = private; + struct vm_area_struct *vma = walk->private; pte_t *pte, ptent; spinlock_t *ptl; struct page *page; @@ -452,8 +454,6 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, return 0; } -static struct mm_walk clear_refs_walk = { .pmd_entry = clear_refs_pte_range }; - static ssize_t clear_refs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { @@ -476,11 +476,17 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf, return -ESRCH; mm = get_task_mm(task); if (mm) { + static struct mm_walk clear_refs_walk; + memset(&clear_refs_walk, 0, sizeof(clear_refs_walk)); + clear_refs_walk.pmd_entry = clear_refs_pte_range; + clear_refs_walk.mm = mm; down_read(&mm->mmap_sem); - for (vma = mm->mmap; vma; vma = vma->vm_next) + for (vma = mm->mmap; vma; vma = vma->vm_next) { + clear_refs_walk.private = vma; if (!is_vm_hugetlb_page(vma)) - walk_page_range(mm, vma->vm_start, vma->vm_end, - &clear_refs_walk, vma); + walk_page_range(vma->vm_start, vma->vm_end, + &clear_refs_walk); + } flush_tlb_mm(mm); up_read(&mm->mmap_sem); mmput(mm); @@ -528,9 +534,9 @@ static int add_to_pagemap(unsigned long addr, u64 pfn, } static int pagemap_pte_hole(unsigned long start, unsigned long end, - void *private) + struct mm_walk *walk) { - struct pagemapread *pm = private; + struct pagemapread *pm = walk->private; unsigned long addr; int err = 0; for (addr = start; addr < end; addr += PAGE_SIZE) { @@ -547,24 +553,45 @@ static u64 swap_pte_to_pagemap_entry(pte_t pte) return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT); } +static unsigned long pte_to_pagemap_entry(pte_t pte) +{ + unsigned long pme = 0; + if (is_swap_pte(pte)) + pme = PM_PFRAME(swap_pte_to_pagemap_entry(pte)) + | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP; + else if (pte_present(pte)) + pme = PM_PFRAME(pte_pfn(pte)) + | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT; + return pme; +} + static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, - void *private) + struct mm_walk *walk) { - struct pagemapread *pm = private; + struct vm_area_struct *vma; + struct pagemapread *pm = walk->private; pte_t *pte; int err = 0; + /* find the first VMA at or above 'addr' */ + vma = find_vma(walk->mm, addr); for (; addr != end; addr += PAGE_SIZE) { u64 pfn = PM_NOT_PRESENT; - pte = pte_offset_map(pmd, addr); - if (is_swap_pte(*pte)) - pfn = PM_PFRAME(swap_pte_to_pagemap_entry(*pte)) - | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP; - else if (pte_present(*pte)) - pfn = PM_PFRAME(pte_pfn(*pte)) - | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT; - /* unmap so we're not in atomic when we copy to userspace */ - pte_unmap(pte); + + /* check to see if we've left 'vma' behind + * and need a new, higher one */ + if (vma && (addr >= vma->vm_end)) + vma = find_vma(walk->mm, addr); + + /* check that 'vma' actually covers this address, + * and that it isn't a huge page vma */ + if (vma && (vma->vm_start <= addr) && + !is_vm_hugetlb_page(vma)) { + pte = pte_offset_map(pmd, addr); + pfn = pte_to_pagemap_entry(*pte); + /* unmap before userspace copy */ + pte_unmap(pte); + } err = add_to_pagemap(addr, pfn, pm); if (err) return err; @@ -675,8 +702,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, * user buffer is tracked in "pm", and the walk * will stop when we hit the end of the buffer. */ - ret = walk_page_range(mm, start_vaddr, end_vaddr, - &pagemap_walk, &pm); + ret = walk_page_range(start_vaddr, end_vaddr, + &pagemap_walk); if (ret == PM_END_OF_BUFFER) ret = 0; /* don't need mmap_sem for these, but this looks cleaner */ diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 06480bcabfdc..06ebb6ef72aa 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -319,6 +319,7 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) #endif /* CONFIG_CPU_FREQ */ /* in processor_throttling.c */ +int acpi_processor_tstate_has_changed(struct acpi_processor *pr); int acpi_processor_get_throttling_info(struct acpi_processor *pr); extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state); extern struct file_operations acpi_processor_throttling_fops; diff --git a/include/asm-m68k/bitops.h b/include/asm-m68k/bitops.h index 83d1f286230b..3e8106442d5a 100644 --- a/include/asm-m68k/bitops.h +++ b/include/asm-m68k/bitops.h @@ -410,8 +410,49 @@ static inline int ext2_find_next_zero_bit(const void *vaddr, unsigned size, res = ext2_find_first_zero_bit (p, size - 32 * (p - addr)); return (p - addr) * 32 + res; } -#define ext2_find_next_bit(addr, size, off) \ - generic_find_next_le_bit((unsigned long *)(addr), (size), (off)) + +static inline int ext2_find_first_bit(const void *vaddr, unsigned size) +{ + const unsigned long *p = vaddr, *addr = vaddr; + int res; + + if (!size) + return 0; + + size = (size >> 5) + ((size & 31) > 0); + while (*p++ == 0UL) { + if (--size == 0) + return (p - addr) << 5; + } + + --p; + for (res = 0; res < 32; res++) + if (ext2_test_bit(res, p)) + break; + return (p - addr) * 32 + res; +} + +static inline int ext2_find_next_bit(const void *vaddr, unsigned size, + unsigned offset) +{ + const unsigned long *addr = vaddr; + const unsigned long *p = addr + (offset >> 5); + int bit = offset & 31UL, res; + + if (offset >= size) + return size; + + if (bit) { + /* Look for one in first longword */ + for (res = bit; res < 32; res++) + if (ext2_test_bit(res, p)) + return (p - addr) * 32 + res; + p++; + } + /* No set bit yet, search remaining full bytes for a set bit */ + res = ext2_find_first_bit(p, size - 32 * (p - addr)); + return (p - addr) * 32 + res; +} #endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/kvm_ppc.h b/include/asm-powerpc/kvm_ppc.h index b35a7e3ef978..5a21115228af 100644 --- a/include/asm-powerpc/kvm_ppc.h +++ b/include/asm-powerpc/kvm_ppc.h @@ -57,6 +57,7 @@ extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, extern int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu); +extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu); extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid, u32 flags); diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 51e6b1e520e6..dcf77fa826b5 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -82,6 +82,7 @@ struct cpuidle_state_kobj { }; struct cpuidle_device { + unsigned int registered:1; unsigned int enabled:1; unsigned int cpu; diff --git a/include/linux/ioport.h b/include/linux/ioport.h index d5d40a9f7929..c6801bffe76d 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -53,14 +53,14 @@ struct resource_list { #define IORESOURCE_AUTO 0x40000000 #define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */ -/* ISA PnP IRQ specific bits (IORESOURCE_BITS) */ +/* PnP IRQ specific bits (IORESOURCE_BITS) */ #define IORESOURCE_IRQ_HIGHEDGE (1<<0) #define IORESOURCE_IRQ_LOWEDGE (1<<1) #define IORESOURCE_IRQ_HIGHLEVEL (1<<2) #define IORESOURCE_IRQ_LOWLEVEL (1<<3) #define IORESOURCE_IRQ_SHAREABLE (1<<4) -/* ISA PnP DMA specific bits (IORESOURCE_BITS) */ +/* PnP DMA specific bits (IORESOURCE_BITS) */ #define IORESOURCE_DMA_TYPE_MASK (3<<0) #define IORESOURCE_DMA_8BIT (0<<0) #define IORESOURCE_DMA_8AND16BIT (1<<0) @@ -76,7 +76,7 @@ struct resource_list { #define IORESOURCE_DMA_TYPEB (2<<6) #define IORESOURCE_DMA_TYPEF (3<<6) -/* ISA PnP memory I/O specific bits (IORESOURCE_BITS) */ +/* PnP memory I/O specific bits (IORESOURCE_BITS) */ #define IORESOURCE_MEM_WRITEABLE (1<<0) /* dup: IORESOURCE_READONLY */ #define IORESOURCE_MEM_CACHEABLE (1<<1) /* dup: IORESOURCE_CACHEABLE */ #define IORESOURCE_MEM_RANGELENGTH (1<<2) /* dup: IORESOURCE_RANGELENGTH */ diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 10b666b61add..cde056e08181 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -396,8 +396,10 @@ static inline struct request_sock *inet6_reqsk_alloc(struct request_sock_ops *op { struct request_sock *req = reqsk_alloc(ops); - if (req != NULL) + if (req != NULL) { inet_rsk(req)->inet6_rsk_offset = inet6_rsk_offset(req); + inet6_rsk(req)->pktopts = NULL; + } return req; } diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 398978972b7a..092b1b25291d 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -297,7 +297,7 @@ static inline gpa_t gfn_to_gpa(gfn_t gfn) return (gpa_t)gfn << PAGE_SHIFT; } -static inline void kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) +static inline void kvm_migrate_timers(struct kvm_vcpu *vcpu) { set_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests); } diff --git a/include/linux/math64.h b/include/linux/math64.h index c1a5f81501ff..c87f1528703a 100644 --- a/include/linux/math64.h +++ b/include/linux/math64.h @@ -81,4 +81,25 @@ static inline s64 div_s64(s64 dividend, s32 divisor) } #endif +u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder); + +static __always_inline u32 +__iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder) +{ + u32 ret = 0; + + while (dividend >= divisor) { + /* The following asm() prevents the compiler from + optimising this loop into a modulo operation. */ + asm("" : "+rm"(dividend)); + + dividend -= divisor; + ret++; + } + + *remainder = dividend; + + return ret; +} + #endif /* _LINUX_MATH64_H */ diff --git a/include/linux/mm.h b/include/linux/mm.h index c31a9cd2a30e..586a943cab01 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -760,16 +760,17 @@ unsigned long unmap_vmas(struct mmu_gather **tlb, * (see walk_page_range for more details) */ struct mm_walk { - int (*pgd_entry)(pgd_t *, unsigned long, unsigned long, void *); - int (*pud_entry)(pud_t *, unsigned long, unsigned long, void *); - int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, void *); - int (*pte_entry)(pte_t *, unsigned long, unsigned long, void *); - int (*pte_hole)(unsigned long, unsigned long, void *); + int (*pgd_entry)(pgd_t *, unsigned long, unsigned long, struct mm_walk *); + int (*pud_entry)(pud_t *, unsigned long, unsigned long, struct mm_walk *); + int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, struct mm_walk *); + int (*pte_entry)(pte_t *, unsigned long, unsigned long, struct mm_walk *); + int (*pte_hole)(unsigned long, unsigned long, struct mm_walk *); + struct mm_struct *mm; + void *private; }; -int walk_page_range(const struct mm_struct *, unsigned long addr, - unsigned long end, const struct mm_walk *walk, - void *private); +int walk_page_range(unsigned long addr, unsigned long end, + struct mm_walk *walk); void free_pgd_range(struct mmu_gather **tlb, unsigned long addr, unsigned long end, unsigned long floor, unsigned long ceiling); void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *start_vma, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 9b940e644179..eafc9d6d2b35 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -716,6 +716,7 @@ #define PCI_DEVICE_ID_HP_CISSA 0x3220 #define PCI_DEVICE_ID_HP_CISSC 0x3230 #define PCI_DEVICE_ID_HP_CISSD 0x3238 +#define PCI_DEVICE_ID_HP_CISSE 0x323a #define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031 #define PCI_VENDOR_ID_PCTECH 0x1042 diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 9883bc942262..fff1d27ddb4c 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -9,6 +9,8 @@ struct net; struct completion; +struct mm_struct; + /* * The proc filesystem constants/structures */ @@ -101,8 +103,6 @@ extern spinlock_t proc_subdir_lock; extern void proc_root_init(void); extern void proc_misc_init(void); -struct mm_struct; - void proc_flush_task(struct task_struct *task); struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *); int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir); diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index a2aec2c0cfb5..b358c704d102 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -246,6 +246,7 @@ enum rt_class_t { RT_TABLE_UNSPEC=0, /* User defined values */ + RT_TABLE_COMPAT=252, RT_TABLE_DEFAULT=253, RT_TABLE_MAIN=254, RT_TABLE_LOCAL=255, diff --git a/include/linux/sched.h b/include/linux/sched.h index ae0be3c62375..c5d3f847ca8d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2026,6 +2026,19 @@ static inline int fatal_signal_pending(struct task_struct *p) return signal_pending(p) && __fatal_signal_pending(p); } +static inline int signal_pending_state(long state, struct task_struct *p) +{ + if (!(state & (TASK_INTERRUPTIBLE | TASK_WAKEKILL))) + return 0; + if (!signal_pending(p)) + return 0; + + if (state & (__TASK_STOPPED | __TASK_TRACED)) + return 0; + + return (state & TASK_INTERRUPTIBLE) || __fatal_signal_pending(p); +} + static inline int need_resched(void) { return unlikely(test_thread_flag(TIF_NEED_RESCHED)); diff --git a/include/linux/ssb/ssb_driver_gige.h b/include/linux/ssb/ssb_driver_gige.h index 01fbdf5fef22..942e38736901 100644 --- a/include/linux/ssb/ssb_driver_gige.h +++ b/include/linux/ssb/ssb_driver_gige.h @@ -100,7 +100,7 @@ extern char * nvram_get(const char *name); /* Get the device MAC address */ static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr) { -#ifdef CONFIG_BCM947XX +#ifdef CONFIG_BCM47XX char *res = nvram_get("et0macaddr"); if (res) memcpy(macaddr, res, 6); diff --git a/include/linux/time.h b/include/linux/time.h index d32ef0ad4c0a..e15206a7e82e 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -6,6 +6,7 @@ #ifdef __KERNEL__ # include <linux/cache.h> # include <linux/seqlock.h> +# include <linux/math64.h> #endif #ifndef _STRUCT_TIMESPEC @@ -169,18 +170,13 @@ extern struct timeval ns_to_timeval(const s64 nsec); * timespec_add_ns - Adds nanoseconds to a timespec * @a: pointer to timespec to be incremented * @ns: unsigned nanoseconds value to be added + * + * This must always be inlined because its used from the x86-64 vdso, + * which cannot call other kernel functions. */ -static inline void timespec_add_ns(struct timespec *a, u64 ns) +static __always_inline void timespec_add_ns(struct timespec *a, u64 ns) { - ns += a->tv_nsec; - while(unlikely(ns >= NSEC_PER_SEC)) { - /* The following asm() prevents the compiler from - * optimising this loop into a modulo operation. */ - asm("" : "+r"(ns)); - - ns -= NSEC_PER_SEC; - a->tv_sec++; - } + a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns); a->tv_nsec = ns; } #endif /* __KERNEL__ */ diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 9405aa6cdf26..38c0571820fb 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -38,7 +38,7 @@ struct virtio_net_hdr #define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set __u8 gso_type; __u16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ - __u16 gso_size; /* Bytes to append to gso_hdr_len per frame */ + __u16 gso_size; /* Bytes to append to hdr_len per frame */ __u16 csum_start; /* Position to start checksumming from */ __u16 csum_offset; /* Offset after that to place checksum */ }; diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index a42cd63d241a..9fabe5b38912 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -197,4 +197,14 @@ static inline int inet_iif(const struct sk_buff *skb) return skb->rtable->rt_iif; } +static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops) +{ + struct request_sock *req = reqsk_alloc(ops); + + if (req != NULL) + inet_rsk(req)->opt = NULL; + + return req; +} + #endif /* _INET_SOCK_H */ diff --git a/include/net/tcp.h b/include/net/tcp.h index 633147cb6bbc..d448310c82c1 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -433,7 +433,6 @@ extern struct sk_buff * tcp_make_synack(struct sock *sk, extern int tcp_disconnect(struct sock *sk, int flags); -extern void tcp_unhash(struct sock *sk); /* From syncookies.c */ extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; diff --git a/ipc/shm.c b/ipc/shm.c index d05f6b564998..790240cd067f 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -1058,16 +1058,16 @@ asmlinkage long sys_shmdt(char __user *shmaddr) static int sysvipc_shm_proc_show(struct seq_file *s, void *it) { struct shmid_kernel *shp = it; - char *format; -#define SMALL_STRING "%10d %10d %4o %10u %5u %5u %5d %5u %5u %5u %5u %10lu %10lu %10lu\n" -#define BIG_STRING "%10d %10d %4o %21u %5u %5u %5d %5u %5u %5u %5u %10lu %10lu %10lu\n" +#if BITS_PER_LONG <= 32 +#define SIZE_SPEC "%10lu" +#else +#define SIZE_SPEC "%21lu" +#endif - if (sizeof(size_t) <= sizeof(int)) - format = SMALL_STRING; - else - format = BIG_STRING; - return seq_printf(s, format, + return seq_printf(s, + "%10d %10d %4o " SIZE_SPEC " %5u %5u " + "%5lu %5u %5u %5u %5u %10lu %10lu %10lu\n", shp->shm_perm.key, shp->shm_perm.id, shp->shm_perm.mode, diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 1e0250cb9486..d4998f81e229 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -699,8 +699,9 @@ static int __register_kprobes(struct kprobe **kps, int num, return -EINVAL; for (i = 0; i < num; i++) { ret = __register_kprobe(kps[i], called_from); - if (ret < 0 && i > 0) { - unregister_kprobes(kps, i); + if (ret < 0) { + if (i > 0) + unregister_kprobes(kps, i); break; } } @@ -776,8 +777,9 @@ static int __register_jprobes(struct jprobe **jps, int num, jp->kp.break_handler = longjmp_break_handler; ret = __register_kprobe(&jp->kp, called_from); } - if (ret < 0 && i > 0) { - unregister_jprobes(jps, i); + if (ret < 0) { + if (i > 0) + unregister_jprobes(jps, i); break; } } @@ -920,8 +922,9 @@ static int __register_kretprobes(struct kretprobe **rps, int num, return -EINVAL; for (i = 0; i < num; i++) { ret = __register_kretprobe(rps[i], called_from); - if (ret < 0 && i > 0) { - unregister_kretprobes(rps, i); + if (ret < 0) { + if (i > 0) + unregister_kretprobes(rps, i); break; } } diff --git a/kernel/sched.c b/kernel/sched.c index bfb8ad8ed171..eaf6751e7612 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -312,12 +312,15 @@ static DEFINE_SPINLOCK(task_group_lock); #endif /* - * A weight of 0, 1 or ULONG_MAX can cause arithmetics problems. + * A weight of 0 or 1 can cause arithmetics problems. + * A weight of a cfs_rq is the sum of weights of which entities + * are queued on this cfs_rq, so a weight of a entity should not be + * too large, so as the shares value of a task group. * (The default weight is 1024 - so there's no practical * limitation from this.) */ #define MIN_SHARES 2 -#define MAX_SHARES (ULONG_MAX - 1) +#define MAX_SHARES (1UL << 18) static int init_task_group_load = INIT_TASK_GROUP_LOAD; #endif @@ -1337,8 +1340,13 @@ calc_delta_mine(unsigned long delta_exec, unsigned long weight, { u64 tmp; - if (!lw->inv_weight) - lw->inv_weight = 1 + (WMULT_CONST-lw->weight/2)/(lw->weight+1); + if (!lw->inv_weight) { + if (BITS_PER_LONG > 32 && unlikely(lw->weight >= WMULT_CONST)) + lw->inv_weight = 1; + else + lw->inv_weight = 1 + (WMULT_CONST-lw->weight/2) + / (lw->weight+1); + } tmp = (u64)delta_exec * weight; /* @@ -4159,12 +4167,10 @@ need_resched_nonpreemptible: clear_tsk_need_resched(prev); if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { - if (unlikely((prev->state & TASK_INTERRUPTIBLE) && - signal_pending(prev))) { + if (unlikely(signal_pending_state(prev->state, prev))) prev->state = TASK_RUNNING; - } else { + else deactivate_task(rq, prev, 1); - } switch_count = &prev->nvcsw; } diff --git a/lib/div64.c b/lib/div64.c index bb5bd0c0f030..a111eb8de9cf 100644 --- a/lib/div64.c +++ b/lib/div64.c @@ -98,3 +98,13 @@ EXPORT_SYMBOL(div64_u64); #endif #endif /* BITS_PER_LONG == 32 */ + +/* + * Iterative div/mod for use when dividend is not expected to be much + * bigger than divisor. + */ +u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder) +{ + return __iter_div_u64_rem(dividend, divisor, remainder); +} +EXPORT_SYMBOL(iter_div_u64_rem); diff --git a/lib/radix-tree.c b/lib/radix-tree.c index bd521716ab1a..169a2f8dabcc 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -88,6 +88,57 @@ static inline gfp_t root_gfp_mask(struct radix_tree_root *root) return root->gfp_mask & __GFP_BITS_MASK; } +static inline void tag_set(struct radix_tree_node *node, unsigned int tag, + int offset) +{ + __set_bit(offset, node->tags[tag]); +} + +static inline void tag_clear(struct radix_tree_node *node, unsigned int tag, + int offset) +{ + __clear_bit(offset, node->tags[tag]); +} + +static inline int tag_get(struct radix_tree_node *node, unsigned int tag, + int offset) +{ + return test_bit(offset, node->tags[tag]); +} + +static inline void root_tag_set(struct radix_tree_root *root, unsigned int tag) +{ + root->gfp_mask |= (__force gfp_t)(1 << (tag + __GFP_BITS_SHIFT)); +} + +static inline void root_tag_clear(struct radix_tree_root *root, unsigned int tag) +{ + root->gfp_mask &= (__force gfp_t)~(1 << (tag + __GFP_BITS_SHIFT)); +} + +static inline void root_tag_clear_all(struct radix_tree_root *root) +{ + root->gfp_mask &= __GFP_BITS_MASK; +} + +static inline int root_tag_get(struct radix_tree_root *root, unsigned int tag) +{ + return (__force unsigned)root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT)); +} + +/* + * Returns 1 if any slot in the node has this tag set. + * Otherwise returns 0. + */ +static inline int any_tag_set(struct radix_tree_node *node, unsigned int tag) +{ + int idx; + for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) { + if (node->tags[tag][idx]) + return 1; + } + return 0; +} /* * This assumes that the caller has performed appropriate preallocation, and * that the caller has pinned this thread of control to the current CPU. @@ -124,6 +175,17 @@ static void radix_tree_node_rcu_free(struct rcu_head *head) { struct radix_tree_node *node = container_of(head, struct radix_tree_node, rcu_head); + + /* + * must only free zeroed nodes into the slab. radix_tree_shrink + * can leave us with a non-NULL entry in the first slot, so clear + * that here to make sure. + */ + tag_clear(node, 0, 0); + tag_clear(node, 1, 0); + node->slots[0] = NULL; + node->count = 0; + kmem_cache_free(radix_tree_node_cachep, node); } @@ -165,59 +227,6 @@ out: } EXPORT_SYMBOL(radix_tree_preload); -static inline void tag_set(struct radix_tree_node *node, unsigned int tag, - int offset) -{ - __set_bit(offset, node->tags[tag]); -} - -static inline void tag_clear(struct radix_tree_node *node, unsigned int tag, - int offset) -{ - __clear_bit(offset, node->tags[tag]); -} - -static inline int tag_get(struct radix_tree_node *node, unsigned int tag, - int offset) -{ - return test_bit(offset, node->tags[tag]); -} - -static inline void root_tag_set(struct radix_tree_root *root, unsigned int tag) -{ - root->gfp_mask |= (__force gfp_t)(1 << (tag + __GFP_BITS_SHIFT)); -} - - -static inline void root_tag_clear(struct radix_tree_root *root, unsigned int tag) -{ - root->gfp_mask &= (__force gfp_t)~(1 << (tag + __GFP_BITS_SHIFT)); -} - -static inline void root_tag_clear_all(struct radix_tree_root *root) -{ - root->gfp_mask &= __GFP_BITS_MASK; -} - -static inline int root_tag_get(struct radix_tree_root *root, unsigned int tag) -{ - return (__force unsigned)root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT)); -} - -/* - * Returns 1 if any slot in the node has this tag set. - * Otherwise returns 0. - */ -static inline int any_tag_set(struct radix_tree_node *node, unsigned int tag) -{ - int idx; - for (idx = 0; idx < RADIX_TREE_TAG_LONGS; idx++) { - if (node->tags[tag][idx]) - return 1; - } - return 0; -} - /* * Return the maximum key which can be store into a * radix tree with height HEIGHT. @@ -930,11 +939,6 @@ static inline void radix_tree_shrink(struct radix_tree_root *root) newptr = radix_tree_ptr_to_indirect(newptr); root->rnode = newptr; root->height--; - /* must only free zeroed nodes into the slab */ - tag_clear(to_free, 0, 0); - tag_clear(to_free, 1, 0); - to_free->slots[0] = NULL; - to_free->count = 0; radix_tree_node_free(to_free); } } diff --git a/mm/nommu.c b/mm/nommu.c index 3abd0845bda4..4462b6a3fcb9 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -104,21 +104,15 @@ EXPORT_SYMBOL(vmtruncate); unsigned int kobjsize(const void *objp) { struct page *page; - int order = 0; /* * If the object we have should not have ksize performed on it, * return size of 0 */ - if (!objp) - return 0; - - if ((unsigned long)objp >= memory_end) + if (!objp || !virt_addr_valid(objp)) return 0; page = virt_to_head_page(objp); - if (!page) - return 0; /* * If the allocator sets PageSlab, we know the pointer came from @@ -129,18 +123,9 @@ unsigned int kobjsize(const void *objp) /* * The ksize() function is only guaranteed to work for pointers - * returned by kmalloc(). So handle arbitrary pointers, that we expect - * always to be compound pages, here. - */ - if (PageCompound(page)) - order = compound_order(page); - - /* - * Finally, handle arbitrary pointers that don't set PageSlab. - * Default to 0-order in the case when we're unable to ksize() - * the object. + * returned by kmalloc(). So handle arbitrary pointers here. */ - return PAGE_SIZE << order; + return PAGE_SIZE << compound_order(page); } /* diff --git a/mm/pagewalk.c b/mm/pagewalk.c index 0afd2387e507..d5878bed7841 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c @@ -3,14 +3,14 @@ #include <linux/sched.h> static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, - const struct mm_walk *walk, void *private) + struct mm_walk *walk) { pte_t *pte; int err = 0; pte = pte_offset_map(pmd, addr); for (;;) { - err = walk->pte_entry(pte, addr, addr + PAGE_SIZE, private); + err = walk->pte_entry(pte, addr, addr + PAGE_SIZE, walk); if (err) break; addr += PAGE_SIZE; @@ -24,7 +24,7 @@ static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, } static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end, - const struct mm_walk *walk, void *private) + struct mm_walk *walk) { pmd_t *pmd; unsigned long next; @@ -35,15 +35,15 @@ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end, next = pmd_addr_end(addr, end); if (pmd_none_or_clear_bad(pmd)) { if (walk->pte_hole) - err = walk->pte_hole(addr, next, private); + err = walk->pte_hole(addr, next, walk); if (err) break; continue; } if (walk->pmd_entry) - err = walk->pmd_entry(pmd, addr, next, private); + err = walk->pmd_entry(pmd, addr, next, walk); if (!err && walk->pte_entry) - err = walk_pte_range(pmd, addr, next, walk, private); + err = walk_pte_range(pmd, addr, next, walk); if (err) break; } while (pmd++, addr = next, addr != end); @@ -52,7 +52,7 @@ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end, } static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end, - const struct mm_walk *walk, void *private) + struct mm_walk *walk) { pud_t *pud; unsigned long next; @@ -63,15 +63,15 @@ static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end, next = pud_addr_end(addr, end); if (pud_none_or_clear_bad(pud)) { if (walk->pte_hole) - err = walk->pte_hole(addr, next, private); + err = walk->pte_hole(addr, next, walk); if (err) break; continue; } if (walk->pud_entry) - err = walk->pud_entry(pud, addr, next, private); + err = walk->pud_entry(pud, addr, next, walk); if (!err && (walk->pmd_entry || walk->pte_entry)) - err = walk_pmd_range(pud, addr, next, walk, private); + err = walk_pmd_range(pud, addr, next, walk); if (err) break; } while (pud++, addr = next, addr != end); @@ -85,15 +85,15 @@ static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end, * @addr: starting address * @end: ending address * @walk: set of callbacks to invoke for each level of the tree - * @private: private data passed to the callback function * * Recursively walk the page table for the memory area in a VMA, * calling supplied callbacks. Callbacks are called in-order (first * PGD, first PUD, first PMD, first PTE, second PTE... second PMD, * etc.). If lower-level callbacks are omitted, walking depth is reduced. * - * Each callback receives an entry pointer, the start and end of the - * associated range, and a caller-supplied private data pointer. + * Each callback receives an entry pointer and the start and end of the + * associated range, and a copy of the original mm_walk for access to + * the ->private or ->mm fields. * * No locks are taken, but the bottom level iterator will map PTE * directories from highmem if necessary. @@ -101,9 +101,8 @@ static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end, * If any callback returns a non-zero value, the walk is aborted and * the return value is propagated back to the caller. Otherwise 0 is returned. */ -int walk_page_range(const struct mm_struct *mm, - unsigned long addr, unsigned long end, - const struct mm_walk *walk, void *private) +int walk_page_range(unsigned long addr, unsigned long end, + struct mm_walk *walk) { pgd_t *pgd; unsigned long next; @@ -112,21 +111,24 @@ int walk_page_range(const struct mm_struct *mm, if (addr >= end) return err; - pgd = pgd_offset(mm, addr); + if (!walk->mm) + return -EINVAL; + + pgd = pgd_offset(walk->mm, addr); do { next = pgd_addr_end(addr, end); if (pgd_none_or_clear_bad(pgd)) { if (walk->pte_hole) - err = walk->pte_hole(addr, next, private); + err = walk->pte_hole(addr, next, walk); if (err) break; continue; } if (walk->pgd_entry) - err = walk->pgd_entry(pgd, addr, next, private); + err = walk->pgd_entry(pgd, addr, next, walk); if (!err && (walk->pud_entry || walk->pmd_entry || walk->pte_entry)) - err = walk_pud_range(pgd, addr, next, walk, private); + err = walk_pud_range(pgd, addr, next, walk); if (err) break; } while (pgd++, addr = next, addr != end); diff --git a/mm/vmscan.c b/mm/vmscan.c index 9a29901ad3b3..967d30ccd92b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1307,7 +1307,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, struct scan_control *sc) { int priority; - int ret = 0; + unsigned long ret = 0; unsigned long total_scanned = 0; unsigned long nr_reclaimed = 0; struct reclaim_state *reclaim_state = current->reclaim_state; diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index c22a3780c14e..37d27bcb361f 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -589,7 +589,7 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) goto drop; - req = reqsk_alloc(&dccp_request_sock_ops); + req = inet_reqsk_alloc(&dccp_request_sock_ops); if (req == NULL) goto drop; @@ -605,7 +605,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ireq = inet_rsk(req); ireq->loc_addr = ip_hdr(skb)->daddr; ireq->rmt_addr = ip_hdr(skb)->saddr; - ireq->opt = NULL; /* * Step 3: Process LISTEN state diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 9b1129bb7ece..f7fe2a572d7b 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -421,7 +421,6 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) ireq6 = inet6_rsk(req); ipv6_addr_copy(&ireq6->rmt_addr, &ipv6_hdr(skb)->saddr); ipv6_addr_copy(&ireq6->loc_addr, &ipv6_hdr(skb)->daddr); - ireq6->pktopts = NULL; if (ipv6_opt_accepted(sk, skb) || np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 3b83c34019fc..0d4d72827e4b 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -960,7 +960,10 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, rtm->rtm_dst_len = dst_len; rtm->rtm_src_len = 0; rtm->rtm_tos = tos; - rtm->rtm_table = tb_id; + if (tb_id < 256) + rtm->rtm_table = tb_id; + else + rtm->rtm_table = RT_TABLE_COMPAT; NLA_PUT_U32(skb, RTA_TABLE, tb_id); rtm->rtm_type = type; rtm->rtm_flags = fi->fib_flags; diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 73ba98921d64..d182a2a26291 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -285,7 +285,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, cookie_check_timestamp(&tcp_opt); ret = NULL; - req = reqsk_alloc(&tcp_request_sock_ops); /* for safety */ + req = inet_reqsk_alloc(&tcp_request_sock_ops); /* for safety */ if (!req) goto out; @@ -301,7 +301,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, ireq->rmt_port = th->source; ireq->loc_addr = ip_hdr(skb)->daddr; ireq->rmt_addr = ip_hdr(skb)->saddr; - ireq->opt = NULL; ireq->snd_wscale = tcp_opt.snd_wscale; ireq->rcv_wscale = tcp_opt.rcv_wscale; ireq->sack_ok = tcp_opt.sack_ok; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index cd601a866c2f..4f8485c67d1a 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1285,7 +1285,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) goto drop; - req = reqsk_alloc(&tcp_request_sock_ops); + req = inet_reqsk_alloc(&tcp_request_sock_ops); if (!req) goto drop; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3c6aafb02183..e84b3fd17fb4 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -191,7 +191,7 @@ lookup_protocol: np->mcast_hops = -1; np->mc_loop = 1; np->pmtudisc = IPV6_PMTUDISC_WANT; - np->ipv6only = init_net.ipv6.sysctl.bindv6only; + np->ipv6only = net->ipv6.sysctl.bindv6only; /* Init the ipv4 part of the socket since we can have sockets * using v6 API for ipv4. diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 938ce4ecde55..3ecc1157994e 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -198,7 +198,6 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) ireq = inet_rsk(req); ireq6 = inet6_rsk(req); treq = tcp_rsk(req); - ireq6->pktopts = NULL; if (security_inet_conn_request(sk, skb, req)) { reqsk_free(req); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 715965f0fac0..cb46749d4c32 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1299,7 +1299,6 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) treq = inet6_rsk(req); ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); - treq->pktopts = NULL; if (!want_cookie) TCP_ECN_create_request(req, tcp_hdr(skb)); diff --git a/net/key/af_key.c b/net/key/af_key.c index 9bba7ac5fee0..7470e367272b 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3030,6 +3030,9 @@ static int key_notify_sa_expire(struct xfrm_state *x, struct km_event *c) static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c) { + if (atomic_read(&pfkey_socks_nr) == 0) + return 0; + switch (c->event) { case XFRM_MSG_EXPIRE: return key_notify_sa_expire(x, c); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c7314bf4bec2..006486b26726 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -899,7 +899,7 @@ extern const struct iw_handler_def ieee80211_iw_handler_def; /* ieee80211_ioctl.c */ -int ieee80211_set_freq(struct ieee80211_local *local, int freq); +int ieee80211_set_freq(struct net_device *dev, int freq); /* ieee80211_sta.c */ void ieee80211_sta_timer(unsigned long data); void ieee80211_sta_work(struct work_struct *work); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5c876450b14c..98c0b5e56ecc 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -511,6 +511,7 @@ static int ieee80211_stop(struct net_device *dev) case IEEE80211_IF_TYPE_STA: case IEEE80211_IF_TYPE_IBSS: sdata->u.sta.state = IEEE80211_DISABLED; + memset(sdata->u.sta.bssid, 0, ETH_ALEN); del_timer_sync(&sdata->u.sta.timer); /* * When we get here, the interface is marked down. diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 841278f1df8e..4d2b582dd055 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -44,7 +44,7 @@ #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) #define IEEE80211_SCAN_INTERVAL (2 * HZ) #define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ) -#define IEEE80211_IBSS_JOIN_TIMEOUT (20 * HZ) +#define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ) #define IEEE80211_PROBE_DELAY (HZ / 33) #define IEEE80211_CHANNEL_TIME (HZ / 33) @@ -2336,6 +2336,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, u8 *pos; struct ieee80211_sub_if_data *sdata; struct ieee80211_supported_band *sband; + union iwreq_data wrqu; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; @@ -2358,13 +2359,10 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, sdata->drop_unencrypted = bss->capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - res = ieee80211_set_freq(local, bss->freq); + res = ieee80211_set_freq(dev, bss->freq); - if (local->oper_channel->flags & IEEE80211_CHAN_NO_IBSS) { - printk(KERN_DEBUG "%s: IBSS not allowed on frequency " - "%d MHz\n", dev->name, local->oper_channel->center_freq); - return -1; - } + if (res) + return res; /* Set beacon template */ skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); @@ -2479,6 +2477,10 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, ifsta->state = IEEE80211_IBSS_JOINED; mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); + memset(&wrqu, 0, sizeof(wrqu)); + memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); + wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); + return res; } @@ -3486,7 +3488,7 @@ static int ieee80211_sta_config_auth(struct net_device *dev, spin_unlock_bh(&local->sta_bss_lock); if (selected) { - ieee80211_set_freq(local, selected->freq); + ieee80211_set_freq(dev, selected->freq); if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) ieee80211_sta_set_ssid(dev, selected->ssid, selected->ssid_len); diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 8311bb24f9f3..a8bb8e31b1ec 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -290,14 +290,22 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev, return 0; } -int ieee80211_set_freq(struct ieee80211_local *local, int freqMHz) +int ieee80211_set_freq(struct net_device *dev, int freqMHz) { int ret = -EINVAL; struct ieee80211_channel *chan; + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { + if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && + chan->flags & IEEE80211_CHAN_NO_IBSS) { + printk(KERN_DEBUG "%s: IBSS not allowed on frequency " + "%d MHz\n", dev->name, chan->center_freq); + return ret; + } local->oper_channel = chan; if (local->sta_sw_scanning || local->sta_hw_scanning) @@ -315,7 +323,6 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra) { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (sdata->vif.type == IEEE80211_IF_TYPE_STA) @@ -329,14 +336,14 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, IEEE80211_STA_AUTO_CHANNEL_SEL; return 0; } else - return ieee80211_set_freq(local, + return ieee80211_set_freq(dev, ieee80211_channel_to_frequency(freq->m)); } else { int i, div = 1000000; for (i = 0; i < freq->e; i++) div /= 10; if (div > 0) - return ieee80211_set_freq(local, freq->m / div); + return ieee80211_set_freq(dev, freq->m / div); else return -EINVAL; } diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 508c5895c680..a07f91aac920 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -467,6 +467,25 @@ static void parse_elf_finish(struct elf_info *info) release_file(info->hdr, info->size); } +static int ignore_undef_symbol(struct elf_info *info, const char *symname) +{ + /* ignore __this_module, it will be resolved shortly */ + if (strcmp(symname, MODULE_SYMBOL_PREFIX "__this_module") == 0) + return 1; + /* ignore global offset table */ + if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0) + return 1; + if (info->hdr->e_machine == EM_PPC) + /* Special register function linked on all modules during final link of .ko */ + if (strncmp(symname, "_restgpr_", sizeof("_restgpr_") - 1) == 0 || + strncmp(symname, "_savegpr_", sizeof("_savegpr_") - 1) == 0 || + strncmp(symname, "_rest32gpr_", sizeof("_rest32gpr_") - 1) == 0 || + strncmp(symname, "_save32gpr_", sizeof("_save32gpr_") - 1) == 0) + return 1; + /* Do not ignore this symbol */ + return 0; +} + #define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_" #define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_" @@ -493,11 +512,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info, if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL && ELF_ST_BIND(sym->st_info) != STB_WEAK) break; - /* ignore global offset table */ - if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0) - break; - /* ignore __this_module, it will be resolved shortly */ - if (strcmp(symname, MODULE_SYMBOL_PREFIX "__this_module") == 0) + if (ignore_undef_symbol(info, symname)) break; /* cope with newer glibc (2.3.4 or higher) STT_ definition in elf.h */ #if defined(STT_REGISTER) || defined(STT_SPARC_REGISTER) diff --git a/security/dummy.c b/security/dummy.c index f50c6c3c32c9..b8916883b77f 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -27,6 +27,8 @@ #include <linux/hugetlb.h> #include <linux/ptrace.h> #include <linux/file.h> +#include <linux/prctl.h> +#include <linux/securebits.h> static int dummy_ptrace (struct task_struct *parent, struct task_struct *child) { @@ -607,7 +609,27 @@ static int dummy_task_kill (struct task_struct *p, struct siginfo *info, static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, long *rc_p) { - return 0; + switch (option) { + case PR_CAPBSET_READ: + *rc_p = (cap_valid(arg2) ? 1 : -EINVAL); + break; + case PR_GET_KEEPCAPS: + *rc_p = issecure(SECURE_KEEP_CAPS); + break; + case PR_SET_KEEPCAPS: + if (arg2 > 1) + *rc_p = -EINVAL; + else if (arg2) + current->securebits |= issecure_mask(SECURE_KEEP_CAPS); + else + current->securebits &= + ~issecure_mask(SECURE_KEEP_CAPS); + break; + default: + return 0; + } + + return 1; } static void dummy_task_reparent_to_init (struct task_struct *p) diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 4232fd75dd20..98778cb69c6e 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c @@ -45,7 +45,7 @@ #else #define ioapic_debug(fmt, arg...) #endif -static void ioapic_deliver(struct kvm_ioapic *vioapic, int irq); +static int ioapic_deliver(struct kvm_ioapic *vioapic, int irq); static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, unsigned long addr, @@ -89,8 +89,8 @@ static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) pent = &ioapic->redirtbl[idx]; if (!pent->fields.mask) { - ioapic_deliver(ioapic, idx); - if (pent->fields.trig_mode == IOAPIC_LEVEL_TRIG) + int injected = ioapic_deliver(ioapic, idx); + if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG) pent->fields.remote_irr = 1; } if (!pent->fields.trig_mode) @@ -133,7 +133,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) } } -static void ioapic_inj_irq(struct kvm_ioapic *ioapic, +static int ioapic_inj_irq(struct kvm_ioapic *ioapic, struct kvm_vcpu *vcpu, u8 vector, u8 trig_mode, u8 delivery_mode) { @@ -143,7 +143,7 @@ static void ioapic_inj_irq(struct kvm_ioapic *ioapic, ASSERT((delivery_mode == IOAPIC_FIXED) || (delivery_mode == IOAPIC_LOWEST_PRIORITY)); - kvm_apic_set_irq(vcpu, vector, trig_mode); + return kvm_apic_set_irq(vcpu, vector, trig_mode); } static u32 ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest, @@ -186,7 +186,7 @@ static u32 ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest, return mask; } -static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq) +static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) { u8 dest = ioapic->redirtbl[irq].fields.dest_id; u8 dest_mode = ioapic->redirtbl[irq].fields.dest_mode; @@ -195,7 +195,7 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq) u8 trig_mode = ioapic->redirtbl[irq].fields.trig_mode; u32 deliver_bitmask; struct kvm_vcpu *vcpu; - int vcpu_id; + int vcpu_id, r = 0; ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " "vector=%x trig_mode=%x\n", @@ -204,7 +204,7 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq) deliver_bitmask = ioapic_get_delivery_bitmask(ioapic, dest, dest_mode); if (!deliver_bitmask) { ioapic_debug("no target on destination\n"); - return; + return 0; } switch (delivery_mode) { @@ -216,7 +216,7 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq) vcpu = ioapic->kvm->vcpus[0]; #endif if (vcpu != NULL) - ioapic_inj_irq(ioapic, vcpu, vector, + r = ioapic_inj_irq(ioapic, vcpu, vector, trig_mode, delivery_mode); else ioapic_debug("null lowest prio vcpu: " @@ -234,7 +234,7 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq) deliver_bitmask &= ~(1 << vcpu_id); vcpu = ioapic->kvm->vcpus[vcpu_id]; if (vcpu) { - ioapic_inj_irq(ioapic, vcpu, vector, + r = ioapic_inj_irq(ioapic, vcpu, vector, trig_mode, delivery_mode); } } @@ -246,6 +246,7 @@ static void ioapic_deliver(struct kvm_ioapic *ioapic, int irq) delivery_mode); break; } + return r; } void kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) |