Commit 76c33d27 authored by Sascha Hauer's avatar Sascha Hauer Committed by Vinod Koul

dmaengine: imx-sdma: factor out a struct sdma_desc from struct sdma_channel

This is a preparation step to make the adding of virt-dma easier.
We create a struct sdma_desc, move some fields from struct sdma_channel
there and add a pointer from the former to the latter. For now we
allocate the data statically in struct sdma_channel, but with
virt-dma support it will be dynamically allocated.
Signed-off-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: default avatarRobin Gong <yibin.gong@nxp.com>
Reviewed-by: default avatarSascha Hauer <s.hauer@pengutronix.de>
Tested-by: default avatarLucas Stach <l.stach@pengutronix.de>
Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent ce397d21
...@@ -288,6 +288,30 @@ struct sdma_context_data { ...@@ -288,6 +288,30 @@ struct sdma_context_data {
struct sdma_engine; struct sdma_engine;
/**
* struct sdma_desc - descriptor structor for one transfer
* @vd descriptor for virt dma
* @num_bd max NUM_BD. number of descriptors currently handling
* @buf_tail ID of the buffer that was processed
* @buf_ptail ID of the previous buffer that was processed
* @period_len period length, used in cyclic.
* @chn_real_count the real count updated from bd->mode.count
* @chn_count the transfer count setuped
* @sdmac sdma_channel pointer
* @bd pointer of alloced bd
*/
struct sdma_desc {
unsigned int num_bd;
dma_addr_t bd_phys;
unsigned int buf_tail;
unsigned int buf_ptail;
unsigned int period_len;
unsigned int chn_real_count;
unsigned int chn_count;
struct sdma_channel *sdmac;
struct sdma_buffer_descriptor *bd;
};
/** /**
* struct sdma_channel - housekeeping for a SDMA channel * struct sdma_channel - housekeeping for a SDMA channel
* *
...@@ -298,11 +322,10 @@ struct sdma_engine; ...@@ -298,11 +322,10 @@ struct sdma_engine;
* @event_id0 aka dma request line * @event_id0 aka dma request line
* @event_id1 for channels that use 2 events * @event_id1 for channels that use 2 events
* @word_size peripheral access size * @word_size peripheral access size
* @buf_tail ID of the buffer that was processed
* @buf_ptail ID of the previous buffer that was processed
* @num_bd max NUM_BD. number of descriptors currently handling
*/ */
struct sdma_channel { struct sdma_channel {
struct sdma_desc *desc;
struct sdma_desc _desc;
struct sdma_engine *sdma; struct sdma_engine *sdma;
unsigned int channel; unsigned int channel;
enum dma_transfer_direction direction; enum dma_transfer_direction direction;
...@@ -310,12 +333,6 @@ struct sdma_channel { ...@@ -310,12 +333,6 @@ struct sdma_channel {
unsigned int event_id0; unsigned int event_id0;
unsigned int event_id1; unsigned int event_id1;
enum dma_slave_buswidth word_size; enum dma_slave_buswidth word_size;
unsigned int buf_tail;
unsigned int buf_ptail;
unsigned int num_bd;
unsigned int period_len;
struct sdma_buffer_descriptor *bd;
dma_addr_t bd_phys;
unsigned int pc_from_device, pc_to_device; unsigned int pc_from_device, pc_to_device;
unsigned int device_to_device; unsigned int device_to_device;
unsigned long flags; unsigned long flags;
...@@ -325,10 +342,8 @@ struct sdma_channel { ...@@ -325,10 +342,8 @@ struct sdma_channel {
u32 shp_addr, per_addr; u32 shp_addr, per_addr;
struct dma_chan chan; struct dma_chan chan;
spinlock_t lock; spinlock_t lock;
struct dma_async_tx_descriptor desc; struct dma_async_tx_descriptor txdesc;
enum dma_status status; enum dma_status status;
unsigned int chn_count;
unsigned int chn_real_count;
struct tasklet_struct tasklet; struct tasklet_struct tasklet;
struct imx_dma_data data; struct imx_dma_data data;
bool enabled; bool enabled;
...@@ -391,6 +406,8 @@ struct sdma_engine { ...@@ -391,6 +406,8 @@ struct sdma_engine {
u32 spba_start_addr; u32 spba_start_addr;
u32 spba_end_addr; u32 spba_end_addr;
unsigned int irq; unsigned int irq;
dma_addr_t bd0_phys;
struct sdma_buffer_descriptor *bd0;
}; };
static struct sdma_driver_data sdma_imx31 = { static struct sdma_driver_data sdma_imx31 = {
...@@ -625,7 +642,7 @@ static int sdma_run_channel0(struct sdma_engine *sdma) ...@@ -625,7 +642,7 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size, static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
u32 address) u32 address)
{ {
struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd; struct sdma_buffer_descriptor *bd0 = sdma->bd0;
void *buf_virt; void *buf_virt;
dma_addr_t buf_phys; dma_addr_t buf_phys;
int ret; int ret;
...@@ -700,7 +717,9 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac) ...@@ -700,7 +717,9 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* call callback function. * call callback function.
*/ */
while (1) { while (1) {
bd = &sdmac->bd[sdmac->buf_tail]; struct sdma_desc *desc = sdmac->desc;
bd = &desc->bd[desc->buf_tail];
if (bd->mode.status & BD_DONE) if (bd->mode.status & BD_DONE)
break; break;
...@@ -716,11 +735,11 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac) ...@@ -716,11 +735,11 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* the number of bytes present in the current buffer descriptor. * the number of bytes present in the current buffer descriptor.
*/ */
sdmac->chn_real_count = bd->mode.count; desc->chn_real_count = bd->mode.count;
bd->mode.status |= BD_DONE; bd->mode.status |= BD_DONE;
bd->mode.count = sdmac->period_len; bd->mode.count = desc->period_len;
sdmac->buf_ptail = sdmac->buf_tail; desc->buf_ptail = desc->buf_tail;
sdmac->buf_tail = (sdmac->buf_tail + 1) % sdmac->num_bd; desc->buf_tail = (desc->buf_tail + 1) % desc->num_bd;
/* /*
* The callback is called from the interrupt context in order * The callback is called from the interrupt context in order
...@@ -729,7 +748,7 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac) ...@@ -729,7 +748,7 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* executed. * executed.
*/ */
dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL); dmaengine_desc_get_callback_invoke(&sdmac->txdesc, NULL);
if (error) if (error)
sdmac->status = old_status; sdmac->status = old_status;
...@@ -742,17 +761,17 @@ static void mxc_sdma_handle_channel_normal(unsigned long data) ...@@ -742,17 +761,17 @@ static void mxc_sdma_handle_channel_normal(unsigned long data)
struct sdma_buffer_descriptor *bd; struct sdma_buffer_descriptor *bd;
int i, error = 0; int i, error = 0;
sdmac->chn_real_count = 0; sdmac->desc->chn_real_count = 0;
/* /*
* non loop mode. Iterate over all descriptors, collect * non loop mode. Iterate over all descriptors, collect
* errors and call callback function * errors and call callback function
*/ */
for (i = 0; i < sdmac->num_bd; i++) { for (i = 0; i < sdmac->desc->num_bd; i++) {
bd = &sdmac->bd[i]; bd = &sdmac->desc->bd[i];
if (bd->mode.status & (BD_DONE | BD_RROR)) if (bd->mode.status & (BD_DONE | BD_RROR))
error = -EIO; error = -EIO;
sdmac->chn_real_count += bd->mode.count; sdmac->desc->chn_real_count += bd->mode.count;
} }
if (error) if (error)
...@@ -760,9 +779,9 @@ static void mxc_sdma_handle_channel_normal(unsigned long data) ...@@ -760,9 +779,9 @@ static void mxc_sdma_handle_channel_normal(unsigned long data)
else else
sdmac->status = DMA_COMPLETE; sdmac->status = DMA_COMPLETE;
dma_cookie_complete(&sdmac->desc); dma_cookie_complete(&sdmac->txdesc);
dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL); dmaengine_desc_get_callback_invoke(&sdmac->txdesc, NULL);
} }
static irqreturn_t sdma_int_handler(int irq, void *dev_id) static irqreturn_t sdma_int_handler(int irq, void *dev_id)
...@@ -890,7 +909,7 @@ static int sdma_load_context(struct sdma_channel *sdmac) ...@@ -890,7 +909,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int channel = sdmac->channel; int channel = sdmac->channel;
int load_address; int load_address;
struct sdma_context_data *context = sdma->context; struct sdma_context_data *context = sdma->context;
struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd; struct sdma_buffer_descriptor *bd0 = sdma->bd0;
int ret; int ret;
unsigned long flags; unsigned long flags;
...@@ -1093,18 +1112,22 @@ static int sdma_set_channel_priority(struct sdma_channel *sdmac, ...@@ -1093,18 +1112,22 @@ static int sdma_set_channel_priority(struct sdma_channel *sdmac,
static int sdma_request_channel(struct sdma_channel *sdmac) static int sdma_request_channel(struct sdma_channel *sdmac)
{ {
struct sdma_engine *sdma = sdmac->sdma; struct sdma_engine *sdma = sdmac->sdma;
struct sdma_desc *desc;
int channel = sdmac->channel; int channel = sdmac->channel;
int ret = -EBUSY; int ret = -EBUSY;
sdmac->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys, sdmac->desc = &sdmac->_desc;
desc = sdmac->desc;
desc->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &desc->bd_phys,
GFP_KERNEL); GFP_KERNEL);
if (!sdmac->bd) { if (!desc->bd) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
sdma->channel_control[channel].base_bd_ptr = sdmac->bd_phys; sdma->channel_control[channel].base_bd_ptr = desc->bd_phys;
sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys; sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
sdma_set_channel_priority(sdmac, MXC_SDMA_DEFAULT_PRIORITY); sdma_set_channel_priority(sdmac, MXC_SDMA_DEFAULT_PRIORITY);
return 0; return 0;
...@@ -1169,10 +1192,10 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan) ...@@ -1169,10 +1192,10 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
if (ret) if (ret)
goto disable_clk_ahb; goto disable_clk_ahb;
dma_async_tx_descriptor_init(&sdmac->desc, chan); dma_async_tx_descriptor_init(&sdmac->txdesc, chan);
sdmac->desc.tx_submit = sdma_tx_submit; sdmac->txdesc.tx_submit = sdma_tx_submit;
/* txd.flags will be overwritten in prep funcs */ /* txd.flags will be overwritten in prep funcs */
sdmac->desc.flags = DMA_CTRL_ACK; sdmac->txdesc.flags = DMA_CTRL_ACK;
return 0; return 0;
...@@ -1187,6 +1210,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan) ...@@ -1187,6 +1210,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
{ {
struct sdma_channel *sdmac = to_sdma_chan(chan); struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma; struct sdma_engine *sdma = sdmac->sdma;
struct sdma_desc *desc = sdmac->desc;
sdma_disable_channel(chan); sdma_disable_channel(chan);
...@@ -1200,7 +1224,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan) ...@@ -1200,7 +1224,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
sdma_set_channel_priority(sdmac, 0); sdma_set_channel_priority(sdmac, 0);
dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys); dma_free_coherent(NULL, PAGE_SIZE, desc->bd, desc->bd_phys);
clk_disable(sdma->clk_ipg); clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb); clk_disable(sdma->clk_ahb);
...@@ -1216,6 +1240,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( ...@@ -1216,6 +1240,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
int ret, i, count; int ret, i, count;
int channel = sdmac->channel; int channel = sdmac->channel;
struct scatterlist *sg; struct scatterlist *sg;
struct sdma_desc *desc = sdmac->desc;
if (sdmac->status == DMA_IN_PROGRESS) if (sdmac->status == DMA_IN_PROGRESS)
return NULL; return NULL;
...@@ -1223,9 +1248,9 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( ...@@ -1223,9 +1248,9 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
sdmac->flags = 0; sdmac->flags = 0;
sdmac->buf_tail = 0; desc->buf_tail = 0;
sdmac->buf_ptail = 0; desc->buf_ptail = 0;
sdmac->chn_real_count = 0; desc->chn_real_count = 0;
dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n", dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
sg_len, channel); sg_len, channel);
...@@ -1242,9 +1267,9 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( ...@@ -1242,9 +1267,9 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
goto err_out; goto err_out;
} }
sdmac->chn_count = 0; desc->chn_count = 0;
for_each_sg(sgl, sg, sg_len, i) { for_each_sg(sgl, sg, sg_len, i) {
struct sdma_buffer_descriptor *bd = &sdmac->bd[i]; struct sdma_buffer_descriptor *bd = &desc->bd[i];
int param; int param;
bd->buffer_addr = sg->dma_address; bd->buffer_addr = sg->dma_address;
...@@ -1259,7 +1284,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( ...@@ -1259,7 +1284,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
} }
bd->mode.count = count; bd->mode.count = count;
sdmac->chn_count += count; desc->chn_count += count;
if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) { if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
ret = -EINVAL; ret = -EINVAL;
...@@ -1300,10 +1325,10 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( ...@@ -1300,10 +1325,10 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
bd->mode.status = param; bd->mode.status = param;
} }
sdmac->num_bd = sg_len; desc->num_bd = sg_len;
sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys; sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
return &sdmac->desc; return &sdmac->txdesc;
err_out: err_out:
sdmac->status = DMA_ERROR; sdmac->status = DMA_ERROR;
return NULL; return NULL;
...@@ -1319,6 +1344,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( ...@@ -1319,6 +1344,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
int num_periods = buf_len / period_len; int num_periods = buf_len / period_len;
int channel = sdmac->channel; int channel = sdmac->channel;
int ret, i = 0, buf = 0; int ret, i = 0, buf = 0;
struct sdma_desc *desc = sdmac->desc;
dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel); dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
...@@ -1327,10 +1353,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( ...@@ -1327,10 +1353,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
sdmac->status = DMA_IN_PROGRESS; sdmac->status = DMA_IN_PROGRESS;
sdmac->buf_tail = 0; desc->buf_tail = 0;
sdmac->buf_ptail = 0; desc->buf_ptail = 0;
sdmac->chn_real_count = 0; desc->chn_real_count = 0;
sdmac->period_len = period_len; desc->period_len = period_len;
sdmac->flags |= IMX_DMA_SG_LOOP; sdmac->flags |= IMX_DMA_SG_LOOP;
sdmac->direction = direction; sdmac->direction = direction;
...@@ -1351,7 +1377,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( ...@@ -1351,7 +1377,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
} }
while (buf < buf_len) { while (buf < buf_len) {
struct sdma_buffer_descriptor *bd = &sdmac->bd[i]; struct sdma_buffer_descriptor *bd = &desc->bd[i];
int param; int param;
bd->buffer_addr = dma_addr; bd->buffer_addr = dma_addr;
...@@ -1382,10 +1408,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( ...@@ -1382,10 +1408,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
i++; i++;
} }
sdmac->num_bd = num_periods; desc->num_bd = num_periods;
sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys; sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
return &sdmac->desc; return &sdmac->txdesc;
err_out: err_out:
sdmac->status = DMA_ERROR; sdmac->status = DMA_ERROR;
return NULL; return NULL;
...@@ -1424,13 +1450,14 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan, ...@@ -1424,13 +1450,14 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
struct dma_tx_state *txstate) struct dma_tx_state *txstate)
{ {
struct sdma_channel *sdmac = to_sdma_chan(chan); struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_desc *desc = sdmac->desc;
u32 residue; u32 residue;
if (sdmac->flags & IMX_DMA_SG_LOOP) if (sdmac->flags & IMX_DMA_SG_LOOP)
residue = (sdmac->num_bd - sdmac->buf_ptail) * residue = (desc->num_bd - desc->buf_ptail) *
sdmac->period_len - sdmac->chn_real_count; desc->period_len - desc->chn_real_count;
else else
residue = sdmac->chn_count - sdmac->chn_real_count; residue = desc->chn_count - desc->chn_real_count;
dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie, dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
residue); residue);
...@@ -1654,6 +1681,8 @@ static int sdma_init(struct sdma_engine *sdma) ...@@ -1654,6 +1681,8 @@ static int sdma_init(struct sdma_engine *sdma)
if (ret) if (ret)
goto err_dma_alloc; goto err_dma_alloc;
sdma->bd0 = sdma->channel[0].desc->bd;
sdma_config_ownership(&sdma->channel[0], false, true, false); sdma_config_ownership(&sdma->channel[0], false, true, false);
/* Set Command Channel (Channel Zero) */ /* Set Command Channel (Channel Zero) */
......
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