Merge branch 'for-linus' of git://git.monstr.eu/linux-2.6-microblaze
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 8 Feb 2010 18:10:36 +0000 (10:10 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 8 Feb 2010 18:10:36 +0000 (10:10 -0800)
* 'for-linus' of git://git.monstr.eu/linux-2.6-microblaze:
  microblaze: Invalidate dcache before enabling it

arch/powerpc/platforms/pseries/xics.c
arch/sh/kernel/cpu/sh3/entry.S
arch/sh/kernel/dwarf.c
arch/sh/kernel/entry-common.S
drivers/usb/host/r8a66597-hcd.c

index 1ee66db003bec6809b8446e8b46b89602d032550..f5f79196721c5d9b540ddee8eaade847d0026094 100644 (file)
@@ -784,9 +784,13 @@ static void xics_set_cpu_priority(unsigned char cppr)
 {
        struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
 
-       BUG_ON(os_cppr->index != 0);
+       /*
+        * we only really want to set the priority when there's
+        * just one cppr value on the stack
+        */
+       WARN_ON(os_cppr->index != 0);
 
-       os_cppr->stack[os_cppr->index] = cppr;
+       os_cppr->stack[0] = cppr;
 
        if (firmware_has_feature(FW_FEATURE_LPAR))
                lpar_cppr_info(cppr);
@@ -821,8 +825,14 @@ void xics_setup_cpu(void)
 
 void xics_teardown_cpu(void)
 {
+       struct xics_cppr *os_cppr = &__get_cpu_var(xics_cppr);
        int cpu = smp_processor_id();
 
+       /*
+        * we have to reset the cppr index to 0 because we're
+        * not going to return from the IPI
+        */
+       os_cppr->index = 0;
        xics_set_cpu_priority(0);
 
        /* Clear any pending IPI request */
index 3f7e2a22c7c2a6bd1d4303ac5427b5461ff43d6c..f6a389c996cbbb16ce9b8cf5daaf45b34db16188 100644 (file)
@@ -132,7 +132,6 @@ ENTRY(tlb_protection_violation_store)
         mov    #1, r5
 
 call_handle_tlbmiss:
-       setup_frame_reg
        mov.l   1f, r0
        mov     r5, r8
        mov.l   @r0, r6
@@ -365,6 +364,8 @@ handle_exception:
         mov.l  @k2, k2         ! read out vector and keep in k2
 
 handle_exception_special:
+       setup_frame_reg
+
        ! Setup return address and jump to exception handler
        mov.l   7f, r9          ! fetch return address
        stc     r2_bank, r0     ! k2 (vector)
index 88d28ec3780a621ecfcb4dba2ea9f670fda86f3a..e51168064e5669b114d903f6917979e3f2786d4e 100644 (file)
@@ -540,6 +540,8 @@ void dwarf_free_frame(struct dwarf_frame *frame)
        mempool_free(frame, dwarf_frame_pool);
 }
 
+extern void ret_from_irq(void);
+
 /**
  *     dwarf_unwind_stack - unwind the stack
  *
@@ -678,6 +680,24 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc,
        addr = frame->cfa + reg->addr;
        frame->return_addr = __raw_readl(addr);
 
+       /*
+        * Ah, the joys of unwinding through interrupts.
+        *
+        * Interrupts are tricky - the DWARF info needs to be _really_
+        * accurate and unfortunately I'm seeing a lot of bogus DWARF
+        * info. For example, I've seen interrupts occur in epilogues
+        * just after the frame pointer (r14) had been restored. The
+        * problem was that the DWARF info claimed that the CFA could be
+        * reached by using the value of the frame pointer before it was
+        * restored.
+        *
+        * So until the compiler can be trusted to produce reliable
+        * DWARF info when it really matters, let's stop unwinding once
+        * we've calculated the function that was interrupted.
+        */
+       if (prev && prev->pc == (unsigned long)ret_from_irq)
+               frame->return_addr = 0;
+
        return frame;
 
 bail:
index f0abd58c3a69c4c439e485653f3b86a4e66b94fe..2b15ae60c3a0257ed1ea48b34da0044c6a4bfaf6 100644 (file)
@@ -70,8 +70,14 @@ ret_from_exception:
        CFI_STARTPROC simple
        CFI_DEF_CFA r14, 0
        CFI_REL_OFFSET 17, 64
-       CFI_REL_OFFSET 15, 0
+       CFI_REL_OFFSET 15, 60
        CFI_REL_OFFSET 14, 56
+       CFI_REL_OFFSET 13, 52
+       CFI_REL_OFFSET 12, 48
+       CFI_REL_OFFSET 11, 44
+       CFI_REL_OFFSET 10, 40
+       CFI_REL_OFFSET 9, 36
+       CFI_REL_OFFSET 8, 32
        preempt_stop()
 ENTRY(ret_from_irq)
        !
index 0ceec123ddfd09928c86cc55fca0ef522937afae..bee558aed42778ce153b5a1db9c4c55376575431 100644 (file)
@@ -35,7 +35,9 @@
 #include <linux/usb.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/mm.h>
 #include <linux/irq.h>
+#include <asm/cacheflush.h>
 
 #include "../core/hcd.h"
 #include "r8a66597.h"
@@ -820,6 +822,26 @@ static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb,
        enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb);
 }
 
+static void r8a66597_urb_done(struct r8a66597 *r8a66597, struct urb *urb,
+                             int status)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
+{
+       if (usb_pipein(urb->pipe) && usb_pipetype(urb->pipe) != PIPE_CONTROL) {
+               void *ptr;
+
+               for (ptr = urb->transfer_buffer;
+                    ptr < urb->transfer_buffer + urb->transfer_buffer_length;
+                    ptr += PAGE_SIZE)
+                       flush_dcache_page(virt_to_page(ptr));
+       }
+
+       usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);
+       spin_unlock(&r8a66597->lock);
+       usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb, status);
+       spin_lock(&r8a66597->lock);
+}
+
 /* this function must be called with interrupt disabled */
 static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
 {
@@ -838,15 +860,9 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
                list_del(&td->queue);
                kfree(td);
 
-               if (urb) {
-                       usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597),
-                                       urb);
+               if (urb)
+                       r8a66597_urb_done(r8a66597, urb, -ENODEV);
 
-                       spin_unlock(&r8a66597->lock);
-                       usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb,
-                                       -ENODEV);
-                       spin_lock(&r8a66597->lock);
-               }
                break;
        }
 }
@@ -1006,6 +1022,8 @@ static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port,
 /* this function must be called with interrupt disabled */
 static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
                                        u16 syssts)
+__releases(r8a66597->lock)
+__acquires(r8a66597->lock)
 {
        if (syssts == SE0) {
                r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
@@ -1023,7 +1041,9 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
                        usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
        }
 
+       spin_unlock(&r8a66597->lock);
        usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597));
+       spin_lock(&r8a66597->lock);
 }
 
 /* this function must be called with interrupt disabled */
@@ -1283,10 +1303,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock)
                if (usb_pipeisoc(urb->pipe))
                        urb->start_frame = r8a66597_get_frame(hcd);
 
-               usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb);
-               spin_unlock(&r8a66597->lock);
-               usb_hcd_giveback_urb(hcd, urb, status);
-               spin_lock(&r8a66597->lock);
+               r8a66597_urb_done(r8a66597, urb, status);
        }
 
        if (restart) {