Merge tag 'regmap-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 9 May 2012 18:25:45 +0000 (11:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 9 May 2012 18:25:45 +0000 (11:25 -0700)
Pull last minute regman bug fix from Mark Brown:
 "This is a last minute bug fix that was only just noticed since the
  code path that's being exercised here is one that is fairly rarely
  used.  The changelog for the change itself is extremely clear and the
  code itself is obvious to inspection so should be pretty safe."

* tag 'regmap-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap:
  regmap: fix possible memory corruption in regmap_bulk_read()

26 files changed:
arch/arm/kernel/ptrace.c
arch/arm/kernel/smp.c
arch/arm/kernel/sys_arm.c
arch/ia64/kvm/kvm-ia64.c
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/traps.c
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/kvm/book3s_hv.c
arch/x86/kernel/kvm.c
arch/x86/kernel/process_64.c
arch/x86/kernel/setup_percpu.c
arch/x86/kvm/x86.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/nouveau/nouveau_i2c.c
drivers/gpu/drm/nouveau/nouveau_i2c.h
drivers/regulator/core.c
drivers/regulator/max8997.c
drivers/video/xen-fbfront.c
drivers/xen/Kconfig
mm/percpu.c

index 80abafb..9650c14 100644 (file)
@@ -906,27 +906,14 @@ long arch_ptrace(struct task_struct *child, long request,
        return ret;
 }
 
-#ifdef __ARMEB__
-#define AUDIT_ARCH_NR AUDIT_ARCH_ARMEB
-#else
-#define AUDIT_ARCH_NR AUDIT_ARCH_ARM
-#endif
-
 asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
 {
        unsigned long ip;
 
-       /*
-        * Save IP.  IP is used to denote syscall entry/exit:
-        *  IP = 0 -> entry, = 1 -> exit
-        */
-       ip = regs->ARM_ip;
-       regs->ARM_ip = why;
-
-       if (!ip)
+       if (why)
                audit_syscall_exit(regs);
        else
-               audit_syscall_entry(AUDIT_ARCH_NR, scno, regs->ARM_r0,
+               audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0,
                                    regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
 
        if (!test_thread_flag(TIF_SYSCALL_TRACE))
@@ -936,6 +923,13 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
 
        current_thread_info()->syscall = scno;
 
+       /*
+        * IP is used to denote syscall entry/exit:
+        * IP = 0 -> entry, =1 -> exit
+        */
+       ip = regs->ARM_ip;
+       regs->ARM_ip = why;
+
        /* the 0x80 provides a way for the tracing parent to distinguish
           between a syscall stop and SIGTRAP delivery */
        ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
index f6a4d32..8f46446 100644 (file)
@@ -251,8 +251,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
        struct mm_struct *mm = &init_mm;
        unsigned int cpu = smp_processor_id();
 
-       printk("CPU%u: Booted secondary processor\n", cpu);
-
        /*
         * All kernel threads share the same mm context; grab a
         * reference and switch to it.
@@ -264,6 +262,8 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
        enter_lazy_tlb(mm, current);
        local_flush_tlb_all();
 
+       printk("CPU%u: Booted secondary processor\n", cpu);
+
        cpu_init();
        preempt_disable();
        trace_hardirqs_off();
index d2b1779..76cbb05 100644 (file)
@@ -115,7 +115,7 @@ int kernel_execve(const char *filename,
                  "Ir" (THREAD_START_SP - sizeof(regs)),
                  "r" (&regs),
                  "Ir" (sizeof(regs))
-               : "r0", "r1", "r2", "r3", "ip", "lr", "memory");
+               : "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory");
 
  out:
        return ret;
index f5104b7..463fb3b 100644 (file)
@@ -1174,7 +1174,7 @@ out:
 
 bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
 {
-       return irqchip_in_kernel(vcpu->kcm) == (vcpu->arch.apic != NULL);
+       return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL);
 }
 
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
index 548da3a..d58fc4e 100644 (file)
@@ -288,13 +288,6 @@ label##_hv:                                                                \
 /* Exception addition: Hard disable interrupts */
 #define DISABLE_INTS   SOFT_DISABLE_INTS(r10,r11)
 
-/* Exception addition: Keep interrupt state */
-#define ENABLE_INTS                            \
-       ld      r11,PACAKMSR(r13);              \
-       ld      r12,_MSR(r1);                   \
-       rlwimi  r11,r12,0,MSR_EE;               \
-       mtmsrd  r11,1
-
 #define ADD_NVGPRS                             \
        bl      .save_nvgprs
 
index f8a7a1a..fc60150 100644 (file)
@@ -767,16 +767,6 @@ do_work:
        SOFT_DISABLE_INTS(r3,r4)
 1:     bl      .preempt_schedule_irq
 
-       /* Hard-disable interrupts again (and update PACA) */
-#ifdef CONFIG_PPC_BOOK3E
-       wrteei  0
-#else
-       ld      r10,PACAKMSR(r13) /* Get kernel MSR without EE */
-       mtmsrd  r10,1
-#endif /* CONFIG_PPC_BOOK3E */
-       li      r0,PACA_IRQ_HARD_DIS
-       stb     r0,PACAIRQHAPPENED(r13)
-
        /* Re-test flags and eventually loop */
        clrrdi  r9,r1,THREAD_SHIFT
        ld      r4,TI_FLAGS(r9)
@@ -787,14 +777,6 @@ do_work:
 user_work:
 #endif /* CONFIG_PREEMPT */
 
-       /* Enable interrupts */
-#ifdef CONFIG_PPC_BOOK3E
-       wrteei  1
-#else
-       ori     r10,r10,MSR_EE
-       mtmsrd  r10,1
-#endif /* CONFIG_PPC_BOOK3E */
-
        andi.   r0,r4,_TIF_NEED_RESCHED
        beq     1f
        bl      .restore_interrupts
index cb705fd..8f880bc 100644 (file)
@@ -768,8 +768,8 @@ alignment_common:
        std     r3,_DAR(r1)
        std     r4,_DSISR(r1)
        bl      .save_nvgprs
+       DISABLE_INTS
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       ENABLE_INTS
        bl      .alignment_exception
        b       .ret_from_except
 
index 43eb74f..c6c6f3b 100644 (file)
@@ -260,11 +260,17 @@ EXPORT_SYMBOL(arch_local_irq_restore);
  * if they are currently disabled. This is typically called before
  * schedule() or do_signal() when returning to userspace. We do it
  * in C to avoid the burden of dealing with lockdep etc...
+ *
+ * NOTE: This is called with interrupts hard disabled but not marked
+ * as such in paca->irq_happened, so we need to resync this.
  */
 void restore_interrupts(void)
 {
-       if (irqs_disabled())
+       if (irqs_disabled()) {
+               local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
                local_irq_enable();
+       } else
+               __hard_irq_enable();
 }
 
 #endif /* CONFIG_PPC64 */
index 6aa0c66..1589723 100644 (file)
@@ -248,7 +248,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
                                   addr, regs->nip, regs->link, code);
        }
 
-       if (!arch_irq_disabled_regs(regs))
+       if (arch_irqs_disabled() && !arch_irq_disabled_regs(regs))
                local_irq_enable();
 
        memset(&info, 0, sizeof(info));
@@ -1019,7 +1019,9 @@ void __kprobes program_check_exception(struct pt_regs *regs)
                return;
        }
 
-       local_irq_enable();
+       /* We restore the interrupt state now */
+       if (!arch_irq_disabled_regs(regs))
+               local_irq_enable();
 
 #ifdef CONFIG_MATH_EMULATION
        /* (reason & REASON_ILLEGAL) would be the obvious thing here,
@@ -1069,6 +1071,10 @@ void alignment_exception(struct pt_regs *regs)
 {
        int sig, code, fixed = 0;
 
+       /* We restore the interrupt state now */
+       if (!arch_irq_disabled_regs(regs))
+               local_irq_enable();
+
        /* we don't implement logging of alignment exceptions */
        if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
                fixed = fix_alignment(regs);
index ddc485a..c3beaee 100644 (file)
@@ -258,6 +258,8 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
                            !(memslot->userspace_addr & (s - 1))) {
                                start &= ~(s - 1);
                                pgsize = s;
+                               get_page(hpage);
+                               put_page(page);
                                page = hpage;
                        }
                }
@@ -281,11 +283,8 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
        err = 0;
 
  out:
-       if (got) {
-               if (PageHuge(page))
-                       page = compound_head(page);
+       if (got)
                put_page(page);
-       }
        return err;
 
  up_err:
@@ -678,8 +677,15 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
                SetPageDirty(page);
 
  out_put:
-       if (page)
-               put_page(page);
+       if (page) {
+               /*
+                * We drop pages[0] here, not page because page might
+                * have been set to the head page of a compound, but
+                * we have to drop the reference on the correct tail
+                * page to match the get inside gup()
+                */
+               put_page(pages[0]);
+       }
        return ret;
 
  out_unlock:
@@ -979,6 +985,7 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
                        pa = *physp;
                }
                page = pfn_to_page(pa >> PAGE_SHIFT);
+               get_page(page);
        } else {
                hva = gfn_to_hva_memslot(memslot, gfn);
                npages = get_user_pages_fast(hva, 1, 1, pages);
@@ -991,8 +998,6 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
                page = compound_head(page);
                psize <<= compound_order(page);
        }
-       if (!kvm->arch.using_mmu_notifiers)
-               get_page(page);
        offset = gpa & (psize - 1);
        if (nb_ret)
                *nb_ret = psize - offset;
@@ -1003,7 +1008,6 @@ void kvmppc_unpin_guest_page(struct kvm *kvm, void *va)
 {
        struct page *page = virt_to_page(va);
 
-       page = compound_head(page);
        put_page(page);
 }
 
index 01294a5..108d1f5 100644 (file)
@@ -1192,8 +1192,6 @@ static void unpin_slot(struct kvm *kvm, int slot_id)
                                continue;
                        pfn = physp[j] >> PAGE_SHIFT;
                        page = pfn_to_page(pfn);
-                       if (PageHuge(page))
-                               page = compound_head(page);
                        SetPageDirty(page);
                        put_page(page);
                }
index b8ba6e4..e554e5a 100644 (file)
@@ -79,7 +79,6 @@ struct kvm_task_sleep_node {
        u32 token;
        int cpu;
        bool halted;
-       struct mm_struct *mm;
 };
 
 static struct kvm_task_sleep_head {
@@ -126,9 +125,7 @@ void kvm_async_pf_task_wait(u32 token)
 
        n.token = token;
        n.cpu = smp_processor_id();
-       n.mm = current->active_mm;
        n.halted = idle || preempt_count() > 1;
-       atomic_inc(&n.mm->mm_count);
        init_waitqueue_head(&n.wq);
        hlist_add_head(&n.link, &b->list);
        spin_unlock(&b->lock);
@@ -161,9 +158,6 @@ EXPORT_SYMBOL_GPL(kvm_async_pf_task_wait);
 static void apf_task_wake_one(struct kvm_task_sleep_node *n)
 {
        hlist_del_init(&n->link);
-       if (!n->mm)
-               return;
-       mmdrop(n->mm);
        if (n->halted)
                smp_send_reschedule(n->cpu);
        else if (waitqueue_active(&n->wq))
@@ -207,7 +201,7 @@ again:
                 * async PF was not yet handled.
                 * Add dummy entry for the token.
                 */
-               n = kmalloc(sizeof(*n), GFP_ATOMIC);
+               n = kzalloc(sizeof(*n), GFP_ATOMIC);
                if (!n) {
                        /*
                         * Allocation failed! Busy wait while other cpu
@@ -219,7 +213,6 @@ again:
                }
                n->token = token;
                n->cpu = smp_processor_id();
-               n->mm = NULL;
                init_waitqueue_head(&n->wq);
                hlist_add_head(&n->link, &b->list);
        } else
index 733ca39..43d8b48 100644 (file)
@@ -423,6 +423,7 @@ void set_personality_ia32(bool x32)
                current_thread_info()->status |= TS_COMPAT;
        }
 }
+EXPORT_SYMBOL_GPL(set_personality_ia32);
 
 unsigned long get_wchan(struct task_struct *p)
 {
index 71f4727..5a98aa2 100644 (file)
@@ -185,10 +185,22 @@ void __init setup_per_cpu_areas(void)
 #endif
        rc = -EINVAL;
        if (pcpu_chosen_fc != PCPU_FC_PAGE) {
-               const size_t atom_size = cpu_has_pse ? PMD_SIZE : PAGE_SIZE;
                const size_t dyn_size = PERCPU_MODULE_RESERVE +
                        PERCPU_DYNAMIC_RESERVE - PERCPU_FIRST_CHUNK_RESERVE;
+               size_t atom_size;
 
+               /*
+                * On 64bit, use PMD_SIZE for atom_size so that embedded
+                * percpu areas are aligned to PMD.  This, in the future,
+                * can also allow using PMD mappings in vmalloc area.  Use
+                * PAGE_SIZE on 32bit as vmalloc space is highly contended
+                * and large vmalloc area allocs can easily fail.
+                */
+#ifdef CONFIG_X86_64
+               atom_size = PMD_SIZE;
+#else
+               atom_size = PAGE_SIZE;
+#endif
                rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE,
                                            dyn_size, atom_size,
                                            pcpu_cpu_distance,
index 91a5e98..185a2b8 100644 (file)
@@ -6581,6 +6581,7 @@ void kvm_arch_async_page_present(struct kvm_vcpu *vcpu,
                kvm_inject_page_fault(vcpu, &fault);
        }
        vcpu->arch.apf.halted = false;
+       vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
 }
 
 bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu)
index a8f8844..95dccce 100644 (file)
@@ -63,6 +63,7 @@
 #include <asm/stackprotector.h>
 #include <asm/hypervisor.h>
 #include <asm/mwait.h>
+#include <asm/pci_x86.h>
 
 #ifdef CONFIG_ACPI
 #include <linux/acpi.h>
@@ -809,9 +810,40 @@ static void xen_io_delay(void)
 }
 
 #ifdef CONFIG_X86_LOCAL_APIC
+static unsigned long xen_set_apic_id(unsigned int x)
+{
+       WARN_ON(1);
+       return x;
+}
+static unsigned int xen_get_apic_id(unsigned long x)
+{
+       return ((x)>>24) & 0xFFu;
+}
 static u32 xen_apic_read(u32 reg)
 {
-       return 0;
+       struct xen_platform_op op = {
+               .cmd = XENPF_get_cpuinfo,
+               .interface_version = XENPF_INTERFACE_VERSION,
+               .u.pcpu_info.xen_cpuid = 0,
+       };
+       int ret = 0;
+
+       /* Shouldn't need this as APIC is turned off for PV, and we only
+        * get called on the bootup processor. But just in case. */
+       if (!xen_initial_domain() || smp_processor_id())
+               return 0;
+
+       if (reg == APIC_LVR)
+               return 0x10;
+
+       if (reg != APIC_ID)
+               return 0;
+
+       ret = HYPERVISOR_dom0_op(&op);
+       if (ret)
+               return 0;
+
+       return op.u.pcpu_info.apic_id << 24;
 }
 
 static void xen_apic_write(u32 reg, u32 val)
@@ -849,6 +881,8 @@ static void set_xen_basic_apic_ops(void)
        apic->icr_write = xen_apic_icr_write;
        apic->wait_icr_idle = xen_apic_wait_icr_idle;
        apic->safe_wait_icr_idle = xen_safe_apic_wait_icr_idle;
+       apic->set_apic_id = xen_set_apic_id;
+       apic->get_apic_id = xen_get_apic_id;
 }
 
 #endif
@@ -1365,8 +1399,10 @@ asmlinkage void __init xen_start_kernel(void)
                /* Make sure ACS will be enabled */
                pci_request_acs();
        }
-               
-
+#ifdef CONFIG_PCI
+       /* PCI BIOS service won't work from a PV guest. */
+       pci_probe &= ~PCI_PROBE_BIOS;
+#endif
        xen_raw_console_write("about to get started...\n");
 
        xen_setup_runstate_info(0);
index b8e2794..69f5857 100644 (file)
@@ -353,8 +353,13 @@ static pteval_t pte_mfn_to_pfn(pteval_t val)
 {
        if (val & _PAGE_PRESENT) {
                unsigned long mfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
+               unsigned long pfn = mfn_to_pfn(mfn);
+
                pteval_t flags = val & PTE_FLAGS_MASK;
-               val = ((pteval_t)mfn_to_pfn(mfn) << PAGE_SHIFT) | flags;
+               if (unlikely(pfn == ~0))
+                       val = flags & ~_PAGE_PRESENT;
+               else
+                       val = ((pteval_t)pfn << PAGE_SHIFT) | flags;
        }
 
        return val;
index 80fce51..62892a8 100644 (file)
@@ -398,10 +398,8 @@ static int init_render_ring(struct intel_ring_buffer *ring)
                        return ret;
        }
 
-       if (INTEL_INFO(dev)->gen >= 6) {
-               I915_WRITE(INSTPM,
-                          INSTPM_FORCE_ORDERING << 16 | INSTPM_FORCE_ORDERING);
 
+       if (IS_GEN6(dev)) {
                /* From the Sandybridge PRM, volume 1 part 3, page 24:
                 * "If this bit is set, STCunit will have LRA as replacement
                 *  policy. [...] This bit must be reset.  LRA replacement
@@ -411,6 +409,11 @@ static int init_render_ring(struct intel_ring_buffer *ring)
                           CM0_STC_EVICT_DISABLE_LRA_SNB << CM0_MASK_SHIFT);
        }
 
+       if (INTEL_INFO(dev)->gen >= 6) {
+               I915_WRITE(INSTPM,
+                          INSTPM_FORCE_ORDERING << 16 | INSTPM_FORCE_ORDERING);
+       }
+
        return ret;
 }
 
index 232d77d..ae5e748 100644 (file)
@@ -1220,8 +1220,14 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in
 
 static int intel_sdvo_supports_hotplug(struct intel_sdvo *intel_sdvo)
 {
+       struct drm_device *dev = intel_sdvo->base.base.dev;
        u8 response[2];
 
+       /* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise
+        * on the line. */
+       if (IS_I945G(dev) || IS_I945GM(dev))
+               return false;
+
        return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT,
                                    &response, 2) && response[0];
 }
index e2be95a..77e5646 100644 (file)
 #include "nouveau_i2c.h"
 #include "nouveau_hw.h"
 
-#define T_TIMEOUT  2200000
-#define T_RISEFALL 1000
-#define T_HOLD     5000
-
 static void
 i2c_drive_scl(void *data, int state)
 {
@@ -113,175 +109,6 @@ i2c_sense_sda(void *data)
        return 0;
 }
 
-static void
-i2c_delay(struct nouveau_i2c_chan *port, u32 nsec)
-{
-       udelay((nsec + 500) / 1000);
-}
-
-static bool
-i2c_raise_scl(struct nouveau_i2c_chan *port)
-{
-       u32 timeout = T_TIMEOUT / T_RISEFALL;
-
-       i2c_drive_scl(port, 1);
-       do {
-               i2c_delay(port, T_RISEFALL);
-       } while (!i2c_sense_scl(port) && --timeout);
-
-       return timeout != 0;
-}
-
-static int
-i2c_start(struct nouveau_i2c_chan *port)
-{
-       int ret = 0;
-
-       port->state  = i2c_sense_scl(port);
-       port->state |= i2c_sense_sda(port) << 1;
-       if (port->state != 3) {
-               i2c_drive_scl(port, 0);
-               i2c_drive_sda(port, 1);
-               if (!i2c_raise_scl(port))
-                       ret = -EBUSY;
-       }
-
-       i2c_drive_sda(port, 0);
-       i2c_delay(port, T_HOLD);
-       i2c_drive_scl(port, 0);
-       i2c_delay(port, T_HOLD);
-       return ret;
-}
-
-static void
-i2c_stop(struct nouveau_i2c_chan *port)
-{
-       i2c_drive_scl(port, 0);
-       i2c_drive_sda(port, 0);
-       i2c_delay(port, T_RISEFALL);
-
-       i2c_drive_scl(port, 1);
-       i2c_delay(port, T_HOLD);
-       i2c_drive_sda(port, 1);
-       i2c_delay(port, T_HOLD);
-}
-
-static int
-i2c_bitw(struct nouveau_i2c_chan *port, int sda)
-{
-       i2c_drive_sda(port, sda);
-       i2c_delay(port, T_RISEFALL);
-
-       if (!i2c_raise_scl(port))
-               return -ETIMEDOUT;
-       i2c_delay(port, T_HOLD);
-
-       i2c_drive_scl(port, 0);
-       i2c_delay(port, T_HOLD);
-       return 0;
-}
-
-static int
-i2c_bitr(struct nouveau_i2c_chan *port)
-{
-       int sda;
-
-       i2c_drive_sda(port, 1);
-       i2c_delay(port, T_RISEFALL);
-
-       if (!i2c_raise_scl(port))
-               return -ETIMEDOUT;
-       i2c_delay(port, T_HOLD);
-
-       sda = i2c_sense_sda(port);
-
-       i2c_drive_scl(port, 0);
-       i2c_delay(port, T_HOLD);
-       return sda;
-}
-
-static int
-i2c_get_byte(struct nouveau_i2c_chan *port, u8 *byte, bool last)
-{
-       int i, bit;
-
-       *byte = 0;
-       for (i = 7; i >= 0; i--) {
-               bit = i2c_bitr(port);
-               if (bit < 0)
-                       return bit;
-               *byte |= bit << i;
-       }
-
-       return i2c_bitw(port, last ? 1 : 0);
-}
-
-static int
-i2c_put_byte(struct nouveau_i2c_chan *port, u8 byte)
-{
-       int i, ret;
-       for (i = 7; i >= 0; i--) {
-               ret = i2c_bitw(port, !!(byte & (1 << i)));
-               if (ret < 0)
-                       return ret;
-       }
-
-       ret = i2c_bitr(port);
-       if (ret == 1) /* nack */
-               ret = -EIO;
-       return ret;
-}
-
-static int
-i2c_addr(struct nouveau_i2c_chan *port, struct i2c_msg *msg)
-{
-       u32 addr = msg->addr << 1;
-       if (msg->flags & I2C_M_RD)
-               addr |= 1;
-       return i2c_put_byte(port, addr);
-}
-
-static int
-i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
-{
-       struct nouveau_i2c_chan *port = (struct nouveau_i2c_chan *)adap;
-       struct i2c_msg *msg = msgs;
-       int ret = 0, mcnt = num;
-
-       while (!ret && mcnt--) {
-               u8 remaining = msg->len;
-               u8 *ptr = msg->buf;
-
-               ret = i2c_start(port);
-               if (ret == 0)
-                       ret = i2c_addr(port, msg);
-
-               if (msg->flags & I2C_M_RD) {
-                       while (!ret && remaining--)
-                               ret = i2c_get_byte(port, ptr++, !remaining);
-               } else {
-                       while (!ret && remaining--)
-                               ret = i2c_put_byte(port, *ptr++);
-               }
-
-               msg++;
-       }
-
-       i2c_stop(port);
-       return (ret < 0) ? ret : num;
-}
-
-static u32
-i2c_bit_func(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-const struct i2c_algorithm nouveau_i2c_bit_algo = {
-       .master_xfer = i2c_bit_xfer,
-       .functionality = i2c_bit_func
-};
-
 static const uint32_t nv50_i2c_port[] = {
        0x00e138, 0x00e150, 0x00e168, 0x00e180,
        0x00e254, 0x00e274, 0x00e764, 0x00e780,
@@ -384,12 +211,10 @@ nouveau_i2c_init(struct drm_device *dev)
                case 0: /* NV04:NV50 */
                        port->drive = entry[0];
                        port->sense = entry[1];
-                       port->adapter.algo = &nouveau_i2c_bit_algo;
                        break;
                case 4: /* NV4E */
                        port->drive = 0x600800 + entry[1];
                        port->sense = port->drive;
-                       port->adapter.algo = &nouveau_i2c_bit_algo;
                        break;
                case 5: /* NV50- */
                        port->drive = entry[0] & 0x0f;
@@ -402,7 +227,6 @@ nouveau_i2c_init(struct drm_device *dev)
                                port->drive = 0x00d014 + (port->drive * 0x20);
                                port->sense = port->drive;
                        }
-                       port->adapter.algo = &nouveau_i2c_bit_algo;
                        break;
                case 6: /* NV50- DP AUX */
                        port->drive = entry[0];
@@ -413,7 +237,7 @@ nouveau_i2c_init(struct drm_device *dev)
                        break;
                }
 
-               if (!port->adapter.algo) {
+               if (!port->adapter.algo && !port->drive) {
                        NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n",
                                 i, port->type, port->drive, port->sense);
                        kfree(port);
@@ -429,7 +253,26 @@ nouveau_i2c_init(struct drm_device *dev)
                port->dcb = ROM32(entry[0]);
                i2c_set_adapdata(&port->adapter, i2c);
 
-               ret = i2c_add_adapter(&port->adapter);
+               if (port->adapter.algo != &nouveau_dp_i2c_algo) {
+                       port->adapter.algo_data = &port->bit;
+                       port->bit.udelay = 10;
+                       port->bit.timeout = usecs_to_jiffies(2200);
+                       port->bit.data = port;
+                       port->bit.setsda = i2c_drive_sda;
+                       port->bit.setscl = i2c_drive_scl;
+                       port->bit.getsda = i2c_sense_sda;
+                       port->bit.getscl = i2c_sense_scl;
+
+                       i2c_drive_scl(port, 0);
+                       i2c_drive_sda(port, 1);
+                       i2c_drive_scl(port, 1);
+
+                       ret = i2c_bit_add_bus(&port->adapter);
+               } else {
+                       port->adapter.algo = &nouveau_dp_i2c_algo;
+                       ret = i2c_add_adapter(&port->adapter);
+               }
+
                if (ret) {
                        NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret);
                        kfree(port);
index 4d2e4e9..1d08389 100644 (file)
@@ -34,6 +34,7 @@
 struct nouveau_i2c_chan {
        struct i2c_adapter adapter;
        struct drm_device *dev;
+       struct i2c_algo_bit_data bit;
        struct list_head head;
        u8  index;
        u8  type;
index e70dd38..046fb1b 100644 (file)
@@ -1431,7 +1431,10 @@ void devm_regulator_put(struct regulator *regulator)
 
        rc = devres_destroy(regulator->dev, devm_regulator_release,
                            devm_regulator_match, regulator);
-       WARN_ON(rc);
+       if (rc == 0)
+               regulator_put(regulator);
+       else
+               WARN_ON(rc);
 }
 EXPORT_SYMBOL_GPL(devm_regulator_put);
 
index 9657929..17a58c5 100644 (file)
@@ -684,7 +684,7 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev,
                }
 
                new_val++;
-       } while (desc->min + desc->step + new_val <= desc->max);
+       } while (desc->min + desc->step * new_val <= desc->max);
 
        new_idx = tmp_idx;
        new_val = tmp_val;
index cb4529c..b7f5173 100644 (file)
@@ -365,7 +365,7 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
        struct fb_info *fb_info;
        int fb_size;
        int val;
-       int ret;
+       int ret = 0;
 
        info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (info == NULL) {
@@ -458,26 +458,31 @@ static int __devinit xenfb_probe(struct xenbus_device *dev,
        xenfb_init_shared_page(info, fb_info);
 
        ret = xenfb_connect_backend(dev, info);
-       if (ret < 0)
-               goto error;
+       if (ret < 0) {
+               xenbus_dev_fatal(dev, ret, "xenfb_connect_backend");
+               goto error_fb;
+       }
 
        ret = register_framebuffer(fb_info);
        if (ret) {
-               fb_deferred_io_cleanup(fb_info);
-               fb_dealloc_cmap(&fb_info->cmap);
-               framebuffer_release(fb_info);
                xenbus_dev_fatal(dev, ret, "register_framebuffer");
-               goto error;
+               goto error_fb;
        }
        info->fb_info = fb_info;
 
        xenfb_make_preferred_console();
        return 0;
 
- error_nomem:
-       ret = -ENOMEM;
-       xenbus_dev_fatal(dev, ret, "allocating device memory");
- error:
+error_fb:
+       fb_deferred_io_cleanup(fb_info);
+       fb_dealloc_cmap(&fb_info->cmap);
+       framebuffer_release(fb_info);
+error_nomem:
+       if (!ret) {
+               ret = -ENOMEM;
+               xenbus_dev_fatal(dev, ret, "allocating device memory");
+       }
+error:
        xenfb_remove(dev);
        return ret;
 }
index 9424313..ea20c51 100644 (file)
@@ -183,15 +183,17 @@ config XEN_ACPI_PROCESSOR
        depends on XEN && X86 && ACPI_PROCESSOR && CPU_FREQ
        default m
        help
-          This ACPI processor uploads Power Management information to the Xen hypervisor.
-
-         To do that the driver parses the Power Management data and uploads said
-         information to the Xen hypervisor. Then the Xen hypervisor can select the
-          proper Cx and Pxx states. It also registers itslef as the SMM so that
-          other drivers (such as ACPI cpufreq scaling driver) will not load.
-
-          To compile this driver as a module, choose M here: the
-          module will be called xen_acpi_processor  If you do not know what to choose,
-          select M here. If the CPUFREQ drivers are built in, select Y here.
+          This ACPI processor uploads Power Management information to the Xen
+         hypervisor.
+
+         To do that the driver parses the Power Management data and uploads
+         said information to the Xen hypervisor. Then the Xen hypervisor can
+         select the proper Cx and Pxx states. It also registers itslef as the
+         SMM so that other drivers (such as ACPI cpufreq scaling driver) will
+         not load.
+
+          To compile this driver as a module, choose M here: the module will be
+         called xen_acpi_processor  If you do not know what to choose, select
+         M here. If the CPUFREQ drivers are built in, select Y here.
 
 endmenu
index f47af91..f921fdf 100644 (file)
@@ -1132,20 +1132,20 @@ static void pcpu_dump_alloc_info(const char *lvl,
                for (alloc_end += gi->nr_units / upa;
                     alloc < alloc_end; alloc++) {
                        if (!(alloc % apl)) {
-                               printk("\n");
+                               printk(KERN_CONT "\n");
                                printk("%spcpu-alloc: ", lvl);
                        }
-                       printk("[%0*d] ", group_width, group);
+                       printk(KERN_CONT "[%0*d] ", group_width, group);
 
                        for (unit_end += upa; unit < unit_end; unit++)
                                if (gi->cpu_map[unit] != NR_CPUS)
-                                       printk("%0*d ", cpu_width,
+                                       printk(KERN_CONT "%0*d ", cpu_width,
                                               gi->cpu_map[unit]);
                                else
-                                       printk("%s ", empty_str);
+                                       printk(KERN_CONT "%s ", empty_str);
                }
        }
-       printk("\n");
+       printk(KERN_CONT "\n");
 }
 
 /**