mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 13:41:51 +00:00
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.
This commit is contained in:
commit
8bd73803e1
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
!
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user