Skip to content

Commit

Permalink
usb: musb: musb_cppi41: Handle ISOCH differently and not use the hrti…
Browse files Browse the repository at this point in the history
…mer.

In case of ISOCH transfers the hrtimer workaround for the hardware issue
is not very reliable. Instead of checking musb_is_tx_fifo_empty() in hrtimer
routine, schedule a completion work and check the same in completion work.

Signed-off-by: George Cherian <george.cherian@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
  • Loading branch information
George Cherian authored and Felipe Balbi committed Feb 18, 2014
1 parent f82503f commit 1af54b7
Showing 1 changed file with 53 additions and 0 deletions.
53 changes: 53 additions & 0 deletions drivers/usb/musb/musb_cppi41.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct cppi41_dma_channel {
u32 transferred;
u32 packet_sz;
struct list_head tx_check;
struct work_struct dma_completion;
};

#define MUSB_DMA_NUM_CHANNELS 15
Expand Down Expand Up @@ -112,6 +113,18 @@ static bool musb_is_tx_fifo_empty(struct musb_hw_ep *hw_ep)
return true;
}

static bool is_isoc(struct musb_hw_ep *hw_ep, bool in)
{
if (in && hw_ep->in_qh) {
if (hw_ep->in_qh->type == USB_ENDPOINT_XFER_ISOC)
return true;
} else if (hw_ep->out_qh) {
if (hw_ep->out_qh->type == USB_ENDPOINT_XFER_ISOC)
return true;
}
return false;
}

static void cppi41_dma_callback(void *private_data);

static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
Expand Down Expand Up @@ -165,6 +178,32 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
}
}

static void cppi_trans_done_work(struct work_struct *work)
{
unsigned long flags;
struct cppi41_dma_channel *cppi41_channel =
container_of(work, struct cppi41_dma_channel, dma_completion);
struct cppi41_dma_controller *controller = cppi41_channel->controller;
struct musb *musb = controller->musb;
struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
bool empty;

if (!cppi41_channel->is_tx && is_isoc(hw_ep, 1)) {
spin_lock_irqsave(&musb->lock, flags);
cppi41_trans_done(cppi41_channel);
spin_unlock_irqrestore(&musb->lock, flags);
} else {
empty = musb_is_tx_fifo_empty(hw_ep);
if (empty) {
spin_lock_irqsave(&musb->lock, flags);
cppi41_trans_done(cppi41_channel);
spin_unlock_irqrestore(&musb->lock, flags);
} else {
schedule_work(&cppi41_channel->dma_completion);
}
}
}

static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
{
struct cppi41_dma_controller *controller;
Expand Down Expand Up @@ -228,6 +267,14 @@ static void cppi41_dma_callback(void *private_data)
transferred < cppi41_channel->packet_sz)
cppi41_channel->prog_len = 0;

if (!cppi41_channel->is_tx) {
if (is_isoc(hw_ep, 1))
schedule_work(&cppi41_channel->dma_completion);
else
cppi41_trans_done(cppi41_channel);
goto out;
}

empty = musb_is_tx_fifo_empty(hw_ep);
if (empty) {
cppi41_trans_done(cppi41_channel);
Expand Down Expand Up @@ -264,6 +311,10 @@ static void cppi41_dma_callback(void *private_data)
goto out;
}
}
if (is_isoc(hw_ep, 0)) {
schedule_work(&cppi41_channel->dma_completion);
goto out;
}
list_add_tail(&cppi41_channel->tx_check,
&controller->early_tx_list);
if (!hrtimer_active(&controller->early_tx)) {
Expand Down Expand Up @@ -620,6 +671,8 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller)
cppi41_channel->port_num = port;
cppi41_channel->is_tx = is_tx;
INIT_LIST_HEAD(&cppi41_channel->tx_check);
INIT_WORK(&cppi41_channel->dma_completion,
cppi_trans_done_work);

musb_dma = &cppi41_channel->channel;
musb_dma->private_data = cppi41_channel;
Expand Down

0 comments on commit 1af54b7

Please sign in to comment.