提交 8bd73803 编写于 作者: L Linus Torvalds

Merge branch 'sh/for-2.6.33' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6

* 'sh/for-2.6.33' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6:
  sh: Remove superfluous setup_frame_reg call
  sh: Don't continue unwinding across interrupts
  sh: Setup frame pointer in handle_exception path
  sh: Correct the offset of the return address in ret_from_exception
  usb: r8a66597-hcd: Fix up spinlock recursion in root hub polling.
  usb: r8a66597-hcd: Flush the D-cache for the pipe-in transfer buffers.
...@@ -132,7 +132,6 @@ ENTRY(tlb_protection_violation_store) ...@@ -132,7 +132,6 @@ ENTRY(tlb_protection_violation_store)
mov #1, r5 mov #1, r5
call_handle_tlbmiss: call_handle_tlbmiss:
setup_frame_reg
mov.l 1f, r0 mov.l 1f, r0
mov r5, r8 mov r5, r8
mov.l @r0, r6 mov.l @r0, r6
...@@ -365,6 +364,8 @@ handle_exception: ...@@ -365,6 +364,8 @@ handle_exception:
mov.l @k2, k2 ! read out vector and keep in k2 mov.l @k2, k2 ! read out vector and keep in k2
handle_exception_special: handle_exception_special:
setup_frame_reg
! Setup return address and jump to exception handler ! Setup return address and jump to exception handler
mov.l 7f, r9 ! fetch return address mov.l 7f, r9 ! fetch return address
stc r2_bank, r0 ! k2 (vector) stc r2_bank, r0 ! k2 (vector)
......
...@@ -540,6 +540,8 @@ void dwarf_free_frame(struct dwarf_frame *frame) ...@@ -540,6 +540,8 @@ void dwarf_free_frame(struct dwarf_frame *frame)
mempool_free(frame, dwarf_frame_pool); mempool_free(frame, dwarf_frame_pool);
} }
extern void ret_from_irq(void);
/** /**
* dwarf_unwind_stack - unwind the stack * dwarf_unwind_stack - unwind the stack
* *
...@@ -678,6 +680,24 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, ...@@ -678,6 +680,24 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc,
addr = frame->cfa + reg->addr; addr = frame->cfa + reg->addr;
frame->return_addr = __raw_readl(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; return frame;
bail: bail:
......
...@@ -70,8 +70,14 @@ ret_from_exception: ...@@ -70,8 +70,14 @@ ret_from_exception:
CFI_STARTPROC simple CFI_STARTPROC simple
CFI_DEF_CFA r14, 0 CFI_DEF_CFA r14, 0
CFI_REL_OFFSET 17, 64 CFI_REL_OFFSET 17, 64
CFI_REL_OFFSET 15, 0 CFI_REL_OFFSET 15, 60
CFI_REL_OFFSET 14, 56 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() preempt_stop()
ENTRY(ret_from_irq) ENTRY(ret_from_irq)
! !
......
...@@ -35,7 +35,9 @@ ...@@ -35,7 +35,9 @@
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mm.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <asm/cacheflush.h>
#include "../core/hcd.h" #include "../core/hcd.h"
#include "r8a66597.h" #include "r8a66597.h"
...@@ -820,6 +822,26 @@ static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb, ...@@ -820,6 +822,26 @@ static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb,
enable_r8a66597_pipe_dma(r8a66597, dev, pipe, 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 */ /* this function must be called with interrupt disabled */
static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) 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) ...@@ -838,15 +860,9 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address)
list_del(&td->queue); list_del(&td->queue);
kfree(td); kfree(td);
if (urb) { if (urb)
usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), r8a66597_urb_done(r8a66597, urb, -ENODEV);
urb);
spin_unlock(&r8a66597->lock);
usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb,
-ENODEV);
spin_lock(&r8a66597->lock);
}
break; break;
} }
} }
...@@ -1006,6 +1022,8 @@ static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port, ...@@ -1006,6 +1022,8 @@ static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port,
/* this function must be called with interrupt disabled */ /* this function must be called with interrupt disabled */
static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
u16 syssts) u16 syssts)
__releases(r8a66597->lock)
__acquires(r8a66597->lock)
{ {
if (syssts == SE0) { if (syssts == SE0) {
r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port)); r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
...@@ -1023,7 +1041,9 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, ...@@ -1023,7 +1041,9 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
} }
spin_unlock(&r8a66597->lock);
usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597)); usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597));
spin_lock(&r8a66597->lock);
} }
/* this function must be called with interrupt disabled */ /* this function must be called with interrupt disabled */
...@@ -1283,10 +1303,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock) ...@@ -1283,10 +1303,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock)
if (usb_pipeisoc(urb->pipe)) if (usb_pipeisoc(urb->pipe))
urb->start_frame = r8a66597_get_frame(hcd); urb->start_frame = r8a66597_get_frame(hcd);
usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb); r8a66597_urb_done(r8a66597, urb, status);
spin_unlock(&r8a66597->lock);
usb_hcd_giveback_urb(hcd, urb, status);
spin_lock(&r8a66597->lock);
} }
if (restart) { if (restart) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册