Skip to content

Commit

Permalink
Merge branch 'topic/slave_caps_device_control_fix_rebased' into for-l…
Browse files Browse the repository at this point in the history
…inus
  • Loading branch information
Vinod Koul committed Feb 3, 2015
2 parents c914570 + 5cf5aec commit 2cd6f79
Show file tree
Hide file tree
Showing 50 changed files with 1,647 additions and 1,829 deletions.
97 changes: 55 additions & 42 deletions Documentation/dmaengine/provider.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,31 @@ need to initialize a few fields in there:
* channels: should be initialized as a list using the
INIT_LIST_HEAD macro for example

* src_addr_widths:
- should contain a bitmask of the supported source transfer width

* dst_addr_widths:
- should contain a bitmask of the supported destination transfer
width

* directions:
- should contain a bitmask of the supported slave directions
(i.e. excluding mem2mem transfers)

* residue_granularity:
- Granularity of the transfer residue reported to dma_set_residue.
- This can be either:
+ Descriptor
-> Your device doesn't support any kind of residue
reporting. The framework will only know that a particular
transaction descriptor is done.
+ Segment
-> Your device is able to report which chunks have been
transferred
+ Burst
-> Your device is able to report which burst have been
transferred

* dev: should hold the pointer to the struct device associated
to your current driver instance.

Expand Down Expand Up @@ -274,48 +299,36 @@ supported.
account the current period.
- This function can be called in an interrupt context.

* device_control
- Used by client drivers to control and configure the channel it
has a handle on.
- Called with a command and an argument
+ The command is one of the values listed by the enum
dma_ctrl_cmd. The valid commands are:
+ DMA_PAUSE
+ Pauses a transfer on the channel
+ This command should operate synchronously on the channel,
pausing right away the work of the given channel
+ DMA_RESUME
+ Restarts a transfer on the channel
+ This command should operate synchronously on the channel,
resuming right away the work of the given channel
+ DMA_TERMINATE_ALL
+ Aborts all the pending and ongoing transfers on the
channel
+ This command should operate synchronously on the channel,
terminating right away all the channels
+ DMA_SLAVE_CONFIG
+ Reconfigures the channel with passed configuration
+ This command should NOT perform synchronously, or on any
currently queued transfers, but only on subsequent ones
+ In this case, the function will receive a
dma_slave_config structure pointer as an argument, that
will detail which configuration to use.
+ Even though that structure contains a direction field,
this field is deprecated in favor of the direction
argument given to the prep_* functions
+ FSLDMA_EXTERNAL_START
+ TODO: Why does that even exist?
+ The argument is an opaque unsigned long. This actually is a
pointer to a struct dma_slave_config that should be used only
in the DMA_SLAVE_CONFIG.

* device_slave_caps
- Called through the framework by client drivers in order to have
an idea of what are the properties of the channel allocated to
them.
- Such properties are the buswidth, available directions, etc.
- Required for every generic layer doing DMA transfers, such as
ASoC.
* device_config
- Reconfigures the channel with the configuration given as
argument
- This command should NOT perform synchronously, or on any
currently queued transfers, but only on subsequent ones
- In this case, the function will receive a dma_slave_config
structure pointer as an argument, that will detail which
configuration to use.
- Even though that structure contains a direction field, this
field is deprecated in favor of the direction argument given to
the prep_* functions
- This call is mandatory for slave operations only. This should NOT be
set or expected to be set for memcpy operations.
If a driver support both, it should use this call for slave
operations only and not for memcpy ones.

* device_pause
- Pauses a transfer on the channel
- This command should operate synchronously on the channel,
pausing right away the work of the given channel

* device_resume
- Resumes a transfer on the channel
- This command should operate synchronously on the channel,
pausing right away the work of the given channel

* device_terminate_all
- Aborts all the pending and ongoing transfers on the channel
- This command should operate synchronously on the channel,
terminating right away all the channels

Misc notes (stuff that should be documented, but don't really know
where to put them)
Expand Down
4 changes: 2 additions & 2 deletions drivers/crypto/ux500/cryp/cryp_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,12 +606,12 @@ static void cryp_dma_done(struct cryp_ctx *ctx)
dev_dbg(ctx->device->dev, "[%s]: ", __func__);

chan = ctx->device->dma.chan_mem2cryp;
dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0);
dmaengine_terminate_all(chan);
dma_unmap_sg(chan->device->dev, ctx->device->dma.sg_src,
ctx->device->dma.sg_src_len, DMA_TO_DEVICE);

chan = ctx->device->dma.chan_cryp2mem;
dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0);
dmaengine_terminate_all(chan);
dma_unmap_sg(chan->device->dev, ctx->device->dma.sg_dst,
ctx->device->dma.sg_dst_len, DMA_FROM_DEVICE);
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/crypto/ux500/hash/hash_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ static void hash_dma_done(struct hash_ctx *ctx)
struct dma_chan *chan;

chan = ctx->device->dma.chan_mem2hash;
dmaengine_device_control(chan, DMA_TERMINATE_ALL, 0);
dmaengine_terminate_all(chan);
dma_unmap_sg(chan->device->dev, ctx->device->dma.sg,
ctx->device->dma.sg_len, DMA_TO_DEVICE);
}
Expand Down
156 changes: 90 additions & 66 deletions drivers/dma/amba-pl08x.c
Original file line number Diff line number Diff line change
Expand Up @@ -1386,32 +1386,6 @@ static u32 pl08x_get_cctl(struct pl08x_dma_chan *plchan,
return pl08x_cctl(cctl);
}

static int dma_set_runtime_config(struct dma_chan *chan,
struct dma_slave_config *config)
{
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
struct pl08x_driver_data *pl08x = plchan->host;

if (!plchan->slave)
return -EINVAL;

/* Reject definitely invalid configurations */
if (config->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES ||
config->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
return -EINVAL;

if (config->device_fc && pl08x->vd->pl080s) {
dev_err(&pl08x->adev->dev,
"%s: PL080S does not support peripheral flow control\n",
__func__);
return -EINVAL;
}

plchan->cfg = *config;

return 0;
}

/*
* Slave transactions callback to the slave device to allow
* synchronization of slave DMA signals with the DMAC enable
Expand Down Expand Up @@ -1693,20 +1667,71 @@ static struct dma_async_tx_descriptor *pl08x_prep_dma_cyclic(
return vchan_tx_prep(&plchan->vc, &txd->vd, flags);
}

static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
unsigned long arg)
static int pl08x_config(struct dma_chan *chan,
struct dma_slave_config *config)
{
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
struct pl08x_driver_data *pl08x = plchan->host;

if (!plchan->slave)
return -EINVAL;

/* Reject definitely invalid configurations */
if (config->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES ||
config->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
return -EINVAL;

if (config->device_fc && pl08x->vd->pl080s) {
dev_err(&pl08x->adev->dev,
"%s: PL080S does not support peripheral flow control\n",
__func__);
return -EINVAL;
}

plchan->cfg = *config;

return 0;
}

static int pl08x_terminate_all(struct dma_chan *chan)
{
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
struct pl08x_driver_data *pl08x = plchan->host;
unsigned long flags;
int ret = 0;

/* Controls applicable to inactive channels */
if (cmd == DMA_SLAVE_CONFIG) {
return dma_set_runtime_config(chan,
(struct dma_slave_config *)arg);
spin_lock_irqsave(&plchan->vc.lock, flags);
if (!plchan->phychan && !plchan->at) {
spin_unlock_irqrestore(&plchan->vc.lock, flags);
return 0;
}

plchan->state = PL08X_CHAN_IDLE;

if (plchan->phychan) {
/*
* Mark physical channel as free and free any slave
* signal
*/
pl08x_phy_free(plchan);
}
/* Dequeue jobs and free LLIs */
if (plchan->at) {
pl08x_desc_free(&plchan->at->vd);
plchan->at = NULL;
}
/* Dequeue jobs not yet fired as well */
pl08x_free_txd_list(pl08x, plchan);

spin_unlock_irqrestore(&plchan->vc.lock, flags);

return 0;
}

static int pl08x_pause(struct dma_chan *chan)
{
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
unsigned long flags;

/*
* Anything succeeds on channels with no physical allocation and
* no queued transfers.
Expand All @@ -1717,42 +1742,35 @@ static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
return 0;
}

switch (cmd) {
case DMA_TERMINATE_ALL:
plchan->state = PL08X_CHAN_IDLE;
pl08x_pause_phy_chan(plchan->phychan);
plchan->state = PL08X_CHAN_PAUSED;

if (plchan->phychan) {
/*
* Mark physical channel as free and free any slave
* signal
*/
pl08x_phy_free(plchan);
}
/* Dequeue jobs and free LLIs */
if (plchan->at) {
pl08x_desc_free(&plchan->at->vd);
plchan->at = NULL;
}
/* Dequeue jobs not yet fired as well */
pl08x_free_txd_list(pl08x, plchan);
break;
case DMA_PAUSE:
pl08x_pause_phy_chan(plchan->phychan);
plchan->state = PL08X_CHAN_PAUSED;
break;
case DMA_RESUME:
pl08x_resume_phy_chan(plchan->phychan);
plchan->state = PL08X_CHAN_RUNNING;
break;
default:
/* Unknown command */
ret = -ENXIO;
break;
spin_unlock_irqrestore(&plchan->vc.lock, flags);

return 0;
}

static int pl08x_resume(struct dma_chan *chan)
{
struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
unsigned long flags;

/*
* Anything succeeds on channels with no physical allocation and
* no queued transfers.
*/
spin_lock_irqsave(&plchan->vc.lock, flags);
if (!plchan->phychan && !plchan->at) {
spin_unlock_irqrestore(&plchan->vc.lock, flags);
return 0;
}

pl08x_resume_phy_chan(plchan->phychan);
plchan->state = PL08X_CHAN_RUNNING;

spin_unlock_irqrestore(&plchan->vc.lock, flags);

return ret;
return 0;
}

bool pl08x_filter_id(struct dma_chan *chan, void *chan_id)
Expand Down Expand Up @@ -2048,7 +2066,10 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
pl08x->memcpy.device_prep_dma_interrupt = pl08x_prep_dma_interrupt;
pl08x->memcpy.device_tx_status = pl08x_dma_tx_status;
pl08x->memcpy.device_issue_pending = pl08x_issue_pending;
pl08x->memcpy.device_control = pl08x_control;
pl08x->memcpy.device_config = pl08x_config;
pl08x->memcpy.device_pause = pl08x_pause;
pl08x->memcpy.device_resume = pl08x_resume;
pl08x->memcpy.device_terminate_all = pl08x_terminate_all;

/* Initialize slave engine */
dma_cap_set(DMA_SLAVE, pl08x->slave.cap_mask);
Expand All @@ -2061,7 +2082,10 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
pl08x->slave.device_issue_pending = pl08x_issue_pending;
pl08x->slave.device_prep_slave_sg = pl08x_prep_slave_sg;
pl08x->slave.device_prep_dma_cyclic = pl08x_prep_dma_cyclic;
pl08x->slave.device_control = pl08x_control;
pl08x->slave.device_config = pl08x_config;
pl08x->slave.device_pause = pl08x_pause;
pl08x->slave.device_resume = pl08x_resume;
pl08x->slave.device_terminate_all = pl08x_terminate_all;

/* Get the platform data */
pl08x->pd = dev_get_platdata(&adev->dev);
Expand Down
Loading

0 comments on commit 2cd6f79

Please sign in to comment.