summaryrefslogtreecommitdiff
path: root/drivers/usb/musb/musb_cppi41.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-04-20 11:32:26 +1000
committerDave Airlie <airlied@redhat.com>2015-04-20 13:05:20 +1000
commit2c33ce009ca2389dbf0535d0672214d09738e35e (patch)
tree6186a6458c3c160385d794a23eaf07c786a9e61b /drivers/usb/musb/musb_cppi41.c
parentcec32a47010647e8b0603726ebb75b990a4057a4 (diff)
parent09d51602cf84a1264946711dd4ea0dddbac599a1 (diff)
Merge Linus master into drm-next
The merge is clean, but the arm build fails afterwards, due to API changes in the regulator tree. I've included the patch into the merge to fix the build. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/usb/musb/musb_cppi41.c')
-rw-r--r--drivers/usb/musb/musb_cppi41.c84
1 files changed, 42 insertions, 42 deletions
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index be84562d021b..8bd8c5e26921 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -225,10 +225,12 @@ static void cppi41_dma_callback(void *private_data)
struct dma_channel *channel = private_data;
struct cppi41_dma_channel *cppi41_channel = channel->private_data;
struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
+ struct cppi41_dma_controller *controller;
struct musb *musb = hw_ep->musb;
unsigned long flags;
struct dma_tx_state txstate;
u32 transferred;
+ int is_hs = 0;
bool empty;
spin_lock_irqsave(&musb->lock, flags);
@@ -248,61 +250,59 @@ static void cppi41_dma_callback(void *private_data)
transferred < cppi41_channel->packet_sz)
cppi41_channel->prog_len = 0;
- empty = musb_is_tx_fifo_empty(hw_ep);
- if (empty) {
+ if (cppi41_channel->is_tx)
+ empty = musb_is_tx_fifo_empty(hw_ep);
+
+ if (!cppi41_channel->is_tx || empty) {
cppi41_trans_done(cppi41_channel);
- } else {
- struct cppi41_dma_controller *controller;
- int is_hs = 0;
- /*
- * On AM335x it has been observed that the TX interrupt fires
- * too early that means the TXFIFO is not yet empty but the DMA
- * engine says that it is done with the transfer. We don't
- * receive a FIFO empty interrupt so the only thing we can do is
- * to poll for the bit. On HS it usually takes 2us, on FS around
- * 110us - 150us depending on the transfer size.
- * We spin on HS (no longer than than 25us and setup a timer on
- * FS to check for the bit and complete the transfer.
- */
- controller = cppi41_channel->controller;
+ goto out;
+ }
- if (is_host_active(musb)) {
- if (musb->port1_status & USB_PORT_STAT_HIGH_SPEED)
- is_hs = 1;
- } else {
- if (musb->g.speed == USB_SPEED_HIGH)
- is_hs = 1;
- }
- if (is_hs) {
- unsigned wait = 25;
-
- do {
- empty = musb_is_tx_fifo_empty(hw_ep);
- if (empty)
- break;
- wait--;
- if (!wait)
- break;
- udelay(1);
- } while (1);
+ /*
+ * On AM335x it has been observed that the TX interrupt fires
+ * too early that means the TXFIFO is not yet empty but the DMA
+ * engine says that it is done with the transfer. We don't
+ * receive a FIFO empty interrupt so the only thing we can do is
+ * to poll for the bit. On HS it usually takes 2us, on FS around
+ * 110us - 150us depending on the transfer size.
+ * We spin on HS (no longer than than 25us and setup a timer on
+ * FS to check for the bit and complete the transfer.
+ */
+ controller = cppi41_channel->controller;
+
+ if (is_host_active(musb)) {
+ if (musb->port1_status & USB_PORT_STAT_HIGH_SPEED)
+ is_hs = 1;
+ } else {
+ if (musb->g.speed == USB_SPEED_HIGH)
+ is_hs = 1;
+ }
+ if (is_hs) {
+ unsigned wait = 25;
+ do {
empty = musb_is_tx_fifo_empty(hw_ep);
if (empty) {
cppi41_trans_done(cppi41_channel);
goto out;
}
- }
- list_add_tail(&cppi41_channel->tx_check,
- &controller->early_tx_list);
- if (!hrtimer_is_queued(&controller->early_tx)) {
- unsigned long usecs = cppi41_channel->total_len / 10;
+ wait--;
+ if (!wait)
+ break;
+ cpu_relax();
+ } while (1);
+ }
+ list_add_tail(&cppi41_channel->tx_check,
+ &controller->early_tx_list);
+ if (!hrtimer_is_queued(&controller->early_tx)) {
+ unsigned long usecs = cppi41_channel->total_len / 10;
- hrtimer_start_range_ns(&controller->early_tx,
+ hrtimer_start_range_ns(&controller->early_tx,
ktime_set(0, usecs * NSEC_PER_USEC),
20 * NSEC_PER_USEC,
HRTIMER_MODE_REL);
- }
}
+
out:
spin_unlock_irqrestore(&musb->lock, flags);
}