Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8bd73803 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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.
parents 6339204e 1af0b2fc
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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)
+20 −0
Original line number Diff line number Diff line
@@ -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:
+7 −1
Original line number Diff line number Diff line
@@ -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)
	!
+29 −12
Original line number Diff line number Diff line
@@ -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) {