lkml.org 
[lkml]   [2016]   [May]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.5 027/200] dmaengine: dw: fix master selection
    Date
    4.5-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

    commit 3fe6409c23e2bee4b2b1b6d671d2da8daa15271c upstream.

    The commit 895005202987 ("dmaengine: dw: apply both HS interfaces and remove
    slave_id usage") cleaned up the code to avoid usage of depricated slave_id
    member of generic slave configuration.

    Meanwhile it broke the master selection by removing important call to
    dwc_set_masters() in ->device_alloc_chan_resources() which copied masters from
    custom slave configuration to the internal channel structure.

    Everything works until now since there is no customized connection of
    DesignWare DMA IP to the bus, i.e. one bus and one or more masters are in use.
    The configurations where 2 masters are connected to the different masters are
    not working anymore. We are expecting one user of such configuration and need
    to select masters properly. Besides that it is obviously a performance
    regression since only one master is in use in multi-master configuration.

    Select masters in accordance with what user asked for. Keep this patch in a form
    more suitable for back porting.

    We are safe to take necessary data in ->device_alloc_chan_resources() because
    we don't support generic slave configuration embedded into custom one, and thus
    the only way to provide such is to use the parameter to a filter function which
    is called exactly before channel resource allocation.

    While here, replase BUG_ON to less noisy dev_warn() and prevent channel
    allocation in case of error.

    Fixes: 895005202987 ("dmaengine: dw: apply both HS interfaces and remove slave_id usage")
    Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
    Signed-off-by: Vinod Koul <vinod.koul@intel.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/dma/dw/core.c | 34 +++++++++++++++++++---------------
    1 file changed, 19 insertions(+), 15 deletions(-)

    --- a/drivers/dma/dw/core.c
    +++ b/drivers/dma/dw/core.c
    @@ -130,26 +130,14 @@ static void dwc_desc_put(struct dw_dma_c
    static void dwc_initialize(struct dw_dma_chan *dwc)
    {
    struct dw_dma *dw = to_dw_dma(dwc->chan.device);
    - struct dw_dma_slave *dws = dwc->chan.private;
    u32 cfghi = DWC_CFGH_FIFO_MODE;
    u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority);

    if (dwc->initialized == true)
    return;

    - if (dws) {
    - /*
    - * We need controller-specific data to set up slave
    - * transfers.
    - */
    - BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev);
    -
    - cfghi |= DWC_CFGH_DST_PER(dws->dst_id);
    - cfghi |= DWC_CFGH_SRC_PER(dws->src_id);
    - } else {
    - cfghi |= DWC_CFGH_DST_PER(dwc->dst_id);
    - cfghi |= DWC_CFGH_SRC_PER(dwc->src_id);
    - }
    + cfghi |= DWC_CFGH_DST_PER(dwc->dst_id);
    + cfghi |= DWC_CFGH_SRC_PER(dwc->src_id);

    channel_writel(dwc, CFG_LO, cfglo);
    channel_writel(dwc, CFG_HI, cfghi);
    @@ -941,7 +929,7 @@ bool dw_dma_filter(struct dma_chan *chan
    struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
    struct dw_dma_slave *dws = param;

    - if (!dws || dws->dma_dev != chan->device->dev)
    + if (dws->dma_dev != chan->device->dev)
    return false;

    /* We have to copy data since dws can be temporary storage */
    @@ -1165,6 +1153,14 @@ static int dwc_alloc_chan_resources(stru
    * doesn't mean what you think it means), and status writeback.
    */

    + /*
    + * We need controller-specific data to set up slave transfers.
    + */
    + if (chan->private && !dw_dma_filter(chan, chan->private)) {
    + dev_warn(chan2dev(chan), "Wrong controller-specific data\n");
    + return -EINVAL;
    + }
    +
    /* Enable controller here if needed */
    if (!dw->in_use)
    dw_dma_on(dw);
    @@ -1226,6 +1222,14 @@ static void dwc_free_chan_resources(stru
    spin_lock_irqsave(&dwc->lock, flags);
    list_splice_init(&dwc->free_list, &list);
    dwc->descs_allocated = 0;
    +
    + /* Clear custom channel configuration */
    + dwc->src_id = 0;
    + dwc->dst_id = 0;
    +
    + dwc->src_master = 0;
    + dwc->dst_master = 0;
    +
    dwc->initialized = false;

    /* Disable interrupts */

    \
     
     \ /
      Last update: 2016-05-03 03:41    [W:4.165 / U:0.104 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site