diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-08 13:09:55 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-08 13:09:55 -0500 |
| commit | 8bd73803e18354add19b050d05770b646ecbffd0 (patch) | |
| tree | c2aa0467418491890b972177dfc64f7fe8e47d9b | |
| parent | 6339204ecc2aa2067a99595522de0403f0854bb8 (diff) | |
| parent | 1af0b2fc676009d9b5b71a82ea6a3c2b20b7ea56 (diff) | |
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.
| -rw-r--r-- | arch/sh/kernel/cpu/sh3/entry.S | 3 | ||||
| -rw-r--r-- | arch/sh/kernel/dwarf.c | 20 | ||||
| -rw-r--r-- | arch/sh/kernel/entry-common.S | 8 | ||||
| -rw-r--r-- | drivers/usb/host/r8a66597-hcd.c | 41 |
4 files changed, 58 insertions, 14 deletions
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index 3f7e2a22c7c2..f6a389c996cb 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S | |||
| @@ -132,7 +132,6 @@ ENTRY(tlb_protection_violation_store) | |||
| 132 | mov #1, r5 | 132 | mov #1, r5 |
| 133 | 133 | ||
| 134 | call_handle_tlbmiss: | 134 | call_handle_tlbmiss: |
| 135 | setup_frame_reg | ||
| 136 | mov.l 1f, r0 | 135 | mov.l 1f, r0 |
| 137 | mov r5, r8 | 136 | mov r5, r8 |
| 138 | mov.l @r0, r6 | 137 | mov.l @r0, r6 |
| @@ -365,6 +364,8 @@ handle_exception: | |||
| 365 | mov.l @k2, k2 ! read out vector and keep in k2 | 364 | mov.l @k2, k2 ! read out vector and keep in k2 |
| 366 | 365 | ||
| 367 | handle_exception_special: | 366 | handle_exception_special: |
| 367 | setup_frame_reg | ||
| 368 | |||
| 368 | ! Setup return address and jump to exception handler | 369 | ! Setup return address and jump to exception handler |
| 369 | mov.l 7f, r9 ! fetch return address | 370 | mov.l 7f, r9 ! fetch return address |
| 370 | stc r2_bank, r0 ! k2 (vector) | 371 | stc r2_bank, r0 ! k2 (vector) |
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c index 88d28ec3780a..e51168064e56 100644 --- a/arch/sh/kernel/dwarf.c +++ b/arch/sh/kernel/dwarf.c | |||
| @@ -540,6 +540,8 @@ void dwarf_free_frame(struct dwarf_frame *frame) | |||
| 540 | mempool_free(frame, dwarf_frame_pool); | 540 | mempool_free(frame, dwarf_frame_pool); |
| 541 | } | 541 | } |
| 542 | 542 | ||
| 543 | extern void ret_from_irq(void); | ||
| 544 | |||
| 543 | /** | 545 | /** |
| 544 | * dwarf_unwind_stack - unwind the stack | 546 | * dwarf_unwind_stack - unwind the stack |
| 545 | * | 547 | * |
| @@ -678,6 +680,24 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, | |||
| 678 | addr = frame->cfa + reg->addr; | 680 | addr = frame->cfa + reg->addr; |
| 679 | frame->return_addr = __raw_readl(addr); | 681 | frame->return_addr = __raw_readl(addr); |
| 680 | 682 | ||
| 683 | /* | ||
| 684 | * Ah, the joys of unwinding through interrupts. | ||
| 685 | * | ||
| 686 | * Interrupts are tricky - the DWARF info needs to be _really_ | ||
| 687 | * accurate and unfortunately I'm seeing a lot of bogus DWARF | ||
| 688 | * info. For example, I've seen interrupts occur in epilogues | ||
| 689 | * just after the frame pointer (r14) had been restored. The | ||
| 690 | * problem was that the DWARF info claimed that the CFA could be | ||
| 691 | * reached by using the value of the frame pointer before it was | ||
| 692 | * restored. | ||
| 693 | * | ||
| 694 | * So until the compiler can be trusted to produce reliable | ||
| 695 | * DWARF info when it really matters, let's stop unwinding once | ||
| 696 | * we've calculated the function that was interrupted. | ||
| 697 | */ | ||
| 698 | if (prev && prev->pc == (unsigned long)ret_from_irq) | ||
| 699 | frame->return_addr = 0; | ||
| 700 | |||
| 681 | return frame; | 701 | return frame; |
| 682 | 702 | ||
| 683 | bail: | 703 | bail: |
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index f0abd58c3a69..2b15ae60c3a0 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S | |||
| @@ -70,8 +70,14 @@ ret_from_exception: | |||
| 70 | CFI_STARTPROC simple | 70 | CFI_STARTPROC simple |
| 71 | CFI_DEF_CFA r14, 0 | 71 | CFI_DEF_CFA r14, 0 |
| 72 | CFI_REL_OFFSET 17, 64 | 72 | CFI_REL_OFFSET 17, 64 |
| 73 | CFI_REL_OFFSET 15, 0 | 73 | CFI_REL_OFFSET 15, 60 |
| 74 | CFI_REL_OFFSET 14, 56 | 74 | CFI_REL_OFFSET 14, 56 |
| 75 | CFI_REL_OFFSET 13, 52 | ||
| 76 | CFI_REL_OFFSET 12, 48 | ||
| 77 | CFI_REL_OFFSET 11, 44 | ||
| 78 | CFI_REL_OFFSET 10, 40 | ||
| 79 | CFI_REL_OFFSET 9, 36 | ||
| 80 | CFI_REL_OFFSET 8, 32 | ||
| 75 | preempt_stop() | 81 | preempt_stop() |
| 76 | ENTRY(ret_from_irq) | 82 | ENTRY(ret_from_irq) |
| 77 | ! | 83 | ! |
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 0ceec123ddfd..bee558aed427 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
| @@ -35,7 +35,9 @@ | |||
| 35 | #include <linux/usb.h> | 35 | #include <linux/usb.h> |
| 36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
| 37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
| 38 | #include <linux/mm.h> | ||
| 38 | #include <linux/irq.h> | 39 | #include <linux/irq.h> |
| 40 | #include <asm/cacheflush.h> | ||
| 39 | 41 | ||
| 40 | #include "../core/hcd.h" | 42 | #include "../core/hcd.h" |
| 41 | #include "r8a66597.h" | 43 | #include "r8a66597.h" |
| @@ -820,6 +822,26 @@ static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb, | |||
| 820 | enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb); | 822 | enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb); |
| 821 | } | 823 | } |
| 822 | 824 | ||
| 825 | static void r8a66597_urb_done(struct r8a66597 *r8a66597, struct urb *urb, | ||
| 826 | int status) | ||
| 827 | __releases(r8a66597->lock) | ||
| 828 | __acquires(r8a66597->lock) | ||
| 829 | { | ||
| 830 | if (usb_pipein(urb->pipe) && usb_pipetype(urb->pipe) != PIPE_CONTROL) { | ||
| 831 | void *ptr; | ||
| 832 | |||
| 833 | for (ptr = urb->transfer_buffer; | ||
| 834 | ptr < urb->transfer_buffer + urb->transfer_buffer_length; | ||
| 835 | ptr += PAGE_SIZE) | ||
| 836 | flush_dcache_page(virt_to_page(ptr)); | ||
| 837 | } | ||
| 838 | |||
| 839 | usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb); | ||
| 840 | spin_unlock(&r8a66597->lock); | ||
| 841 | usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb, status); | ||
| 842 | spin_lock(&r8a66597->lock); | ||
| 843 | } | ||
| 844 | |||
| 823 | /* this function must be called with interrupt disabled */ | 845 | /* this function must be called with interrupt disabled */ |
| 824 | static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) | 846 | static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) |
| 825 | { | 847 | { |
| @@ -838,15 +860,9 @@ static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) | |||
| 838 | list_del(&td->queue); | 860 | list_del(&td->queue); |
| 839 | kfree(td); | 861 | kfree(td); |
| 840 | 862 | ||
| 841 | if (urb) { | 863 | if (urb) |
| 842 | usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), | 864 | r8a66597_urb_done(r8a66597, urb, -ENODEV); |
| 843 | urb); | ||
| 844 | 865 | ||
| 845 | spin_unlock(&r8a66597->lock); | ||
| 846 | usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb, | ||
| 847 | -ENODEV); | ||
| 848 | spin_lock(&r8a66597->lock); | ||
| 849 | } | ||
| 850 | break; | 866 | break; |
| 851 | } | 867 | } |
| 852 | } | 868 | } |
| @@ -1006,6 +1022,8 @@ static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port, | |||
| 1006 | /* this function must be called with interrupt disabled */ | 1022 | /* this function must be called with interrupt disabled */ |
| 1007 | static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, | 1023 | static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, |
| 1008 | u16 syssts) | 1024 | u16 syssts) |
| 1025 | __releases(r8a66597->lock) | ||
| 1026 | __acquires(r8a66597->lock) | ||
| 1009 | { | 1027 | { |
| 1010 | if (syssts == SE0) { | 1028 | if (syssts == SE0) { |
| 1011 | r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port)); | 1029 | r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port)); |
| @@ -1023,7 +1041,9 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, | |||
| 1023 | usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); | 1041 | usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); |
| 1024 | } | 1042 | } |
| 1025 | 1043 | ||
| 1044 | spin_unlock(&r8a66597->lock); | ||
| 1026 | usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597)); | 1045 | usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597)); |
| 1046 | spin_lock(&r8a66597->lock); | ||
| 1027 | } | 1047 | } |
| 1028 | 1048 | ||
| 1029 | /* this function must be called with interrupt disabled */ | 1049 | /* this function must be called with interrupt disabled */ |
| @@ -1283,10 +1303,7 @@ __releases(r8a66597->lock) __acquires(r8a66597->lock) | |||
| 1283 | if (usb_pipeisoc(urb->pipe)) | 1303 | if (usb_pipeisoc(urb->pipe)) |
| 1284 | urb->start_frame = r8a66597_get_frame(hcd); | 1304 | urb->start_frame = r8a66597_get_frame(hcd); |
| 1285 | 1305 | ||
| 1286 | usb_hcd_unlink_urb_from_ep(r8a66597_to_hcd(r8a66597), urb); | 1306 | r8a66597_urb_done(r8a66597, urb, status); |
| 1287 | spin_unlock(&r8a66597->lock); | ||
| 1288 | usb_hcd_giveback_urb(hcd, urb, status); | ||
| 1289 | spin_lock(&r8a66597->lock); | ||
| 1290 | } | 1307 | } |
| 1291 | 1308 | ||
| 1292 | if (restart) { | 1309 | if (restart) { |
