Commit be18a251 authored by Per Forlin's avatar Per Forlin Committed by Felipe Balbi

usb: musb: ux500: optimize DMA callback routine

Skip the use of work queue and call musb_dma_completion() directly from
DMA callback context.

Here follows measurements on a Snowball board with ondemand governor active.

Performance using work queue:
(105 MB) copied, 6.23758 s, 16.8 MB/s
(105 MB) copied, 5.7151 s, 18.3 MB/s
(105 MB) copied, 5.83583 s, 18.0 MB/s
(105 MB) copied, 5.93611 s, 17.7 MB/s

Performance without work queue
(105 MB) copied, 5.62173 s, 18.7 MB/s
(105 MB) copied, 5.61811 s, 18.7 MB/s
(105 MB) copied, 5.57817 s, 18.8 MB/s
(105 MB) copied, 5.58549 s, 18.8 MB/s
Signed-off-by: default avatarPer Forlin <per.forlin@linaro.org>
Acked-by: default avatarMian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent dc47ce90
...@@ -37,7 +37,6 @@ struct ux500_dma_channel { ...@@ -37,7 +37,6 @@ struct ux500_dma_channel {
struct dma_channel channel; struct dma_channel channel;
struct ux500_dma_controller *controller; struct ux500_dma_controller *controller;
struct musb_hw_ep *hw_ep; struct musb_hw_ep *hw_ep;
struct work_struct channel_work;
struct dma_chan *dma_chan; struct dma_chan *dma_chan;
unsigned int cur_len; unsigned int cur_len;
dma_cookie_t cookie; dma_cookie_t cookie;
...@@ -56,31 +55,11 @@ struct ux500_dma_controller { ...@@ -56,31 +55,11 @@ struct ux500_dma_controller {
dma_addr_t phy_base; dma_addr_t phy_base;
}; };
/* Work function invoked from DMA callback to handle tx transfers. */
static void ux500_tx_work(struct work_struct *data)
{
struct ux500_dma_channel *ux500_channel = container_of(data,
struct ux500_dma_channel, channel_work);
struct musb_hw_ep *hw_ep = ux500_channel->hw_ep;
struct musb *musb = hw_ep->musb;
unsigned long flags;
dev_dbg(musb->controller, "DMA tx transfer done on hw_ep=%d\n",
hw_ep->epnum);
spin_lock_irqsave(&musb->lock, flags);
ux500_channel->channel.actual_len = ux500_channel->cur_len;
ux500_channel->channel.status = MUSB_DMA_STATUS_FREE;
musb_dma_completion(musb, hw_ep->epnum,
ux500_channel->is_tx);
spin_unlock_irqrestore(&musb->lock, flags);
}
/* Work function invoked from DMA callback to handle rx transfers. */ /* Work function invoked from DMA callback to handle rx transfers. */
static void ux500_rx_work(struct work_struct *data) void ux500_dma_callback(void *private_data)
{ {
struct ux500_dma_channel *ux500_channel = container_of(data, struct dma_channel *channel = private_data;
struct ux500_dma_channel, channel_work); struct ux500_dma_channel *ux500_channel = channel->private_data;
struct musb_hw_ep *hw_ep = ux500_channel->hw_ep; struct musb_hw_ep *hw_ep = ux500_channel->hw_ep;
struct musb *musb = hw_ep->musb; struct musb *musb = hw_ep->musb;
unsigned long flags; unsigned long flags;
...@@ -94,14 +73,7 @@ static void ux500_rx_work(struct work_struct *data) ...@@ -94,14 +73,7 @@ static void ux500_rx_work(struct work_struct *data)
musb_dma_completion(musb, hw_ep->epnum, musb_dma_completion(musb, hw_ep->epnum,
ux500_channel->is_tx); ux500_channel->is_tx);
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
}
void ux500_dma_callback(void *private_data)
{
struct dma_channel *channel = (struct dma_channel *)private_data;
struct ux500_dma_channel *ux500_channel = channel->private_data;
schedule_work(&ux500_channel->channel_work);
} }
static bool ux500_configure_channel(struct dma_channel *channel, static bool ux500_configure_channel(struct dma_channel *channel,
...@@ -330,7 +302,6 @@ static int ux500_dma_controller_start(struct dma_controller *c) ...@@ -330,7 +302,6 @@ static int ux500_dma_controller_start(struct dma_controller *c)
void **param_array; void **param_array;
struct ux500_dma_channel *channel_array; struct ux500_dma_channel *channel_array;
u32 ch_count; u32 ch_count;
void (*musb_channel_work)(struct work_struct *);
dma_cap_mask_t mask; dma_cap_mask_t mask;
if ((data->num_rx_channels > UX500_MUSB_DMA_NUM_RX_CHANNELS) || if ((data->num_rx_channels > UX500_MUSB_DMA_NUM_RX_CHANNELS) ||
...@@ -347,7 +318,6 @@ static int ux500_dma_controller_start(struct dma_controller *c) ...@@ -347,7 +318,6 @@ static int ux500_dma_controller_start(struct dma_controller *c)
channel_array = controller->rx_channel; channel_array = controller->rx_channel;
ch_count = data->num_rx_channels; ch_count = data->num_rx_channels;
param_array = data->dma_rx_param_array; param_array = data->dma_rx_param_array;
musb_channel_work = ux500_rx_work;
for (dir = 0; dir < 2; dir++) { for (dir = 0; dir < 2; dir++) {
for (ch_num = 0; ch_num < ch_count; ch_num++) { for (ch_num = 0; ch_num < ch_count; ch_num++) {
...@@ -374,15 +344,12 @@ static int ux500_dma_controller_start(struct dma_controller *c) ...@@ -374,15 +344,12 @@ static int ux500_dma_controller_start(struct dma_controller *c)
return -EBUSY; return -EBUSY;
} }
INIT_WORK(&ux500_channel->channel_work,
musb_channel_work);
} }
/* Prepare the loop for TX channels */ /* Prepare the loop for TX channels */
channel_array = controller->tx_channel; channel_array = controller->tx_channel;
ch_count = data->num_tx_channels; ch_count = data->num_tx_channels;
param_array = data->dma_tx_param_array; param_array = data->dma_tx_param_array;
musb_channel_work = ux500_tx_work;
is_tx = 1; is_tx = 1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment