Skip to content

Commit 3fe6409

Browse files
andy-shevVinod Koul
authored andcommitted
dmaengine: dw: fix master selection
The commit 8950052 ("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: 8950052 ("dmaengine: dw: apply both HS interfaces and remove slave_id usage") Cc: stable@vger.kernel.org Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
1 parent f55532a commit 3fe6409

File tree

1 file changed

+19
-15
lines changed

1 file changed

+19
-15
lines changed

drivers/dma/dw/core.c

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -130,26 +130,14 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc)
130130
static void dwc_initialize(struct dw_dma_chan *dwc)
131131
{
132132
struct dw_dma *dw = to_dw_dma(dwc->chan.device);
133-
struct dw_dma_slave *dws = dwc->chan.private;
134133
u32 cfghi = DWC_CFGH_FIFO_MODE;
135134
u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority);
136135

137136
if (dwc->initialized == true)
138137
return;
139138

140-
if (dws) {
141-
/*
142-
* We need controller-specific data to set up slave
143-
* transfers.
144-
*/
145-
BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev);
146-
147-
cfghi |= DWC_CFGH_DST_PER(dws->dst_id);
148-
cfghi |= DWC_CFGH_SRC_PER(dws->src_id);
149-
} else {
150-
cfghi |= DWC_CFGH_DST_PER(dwc->dst_id);
151-
cfghi |= DWC_CFGH_SRC_PER(dwc->src_id);
152-
}
139+
cfghi |= DWC_CFGH_DST_PER(dwc->dst_id);
140+
cfghi |= DWC_CFGH_SRC_PER(dwc->src_id);
153141

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

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

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

1156+
/*
1157+
* We need controller-specific data to set up slave transfers.
1158+
*/
1159+
if (chan->private && !dw_dma_filter(chan, chan->private)) {
1160+
dev_warn(chan2dev(chan), "Wrong controller-specific data\n");
1161+
return -EINVAL;
1162+
}
1163+
11681164
/* Enable controller here if needed */
11691165
if (!dw->in_use)
11701166
dw_dma_on(dw);
@@ -1226,6 +1222,14 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
12261222
spin_lock_irqsave(&dwc->lock, flags);
12271223
list_splice_init(&dwc->free_list, &list);
12281224
dwc->descs_allocated = 0;
1225+
1226+
/* Clear custom channel configuration */
1227+
dwc->src_id = 0;
1228+
dwc->dst_id = 0;
1229+
1230+
dwc->src_master = 0;
1231+
dwc->dst_master = 0;
1232+
12291233
dwc->initialized = false;
12301234

12311235
/* Disable interrupts */

0 commit comments

Comments
 (0)