aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2014-07-30 20:34:05 -0400
committerVinod Koul <vinod.koul@intel.com>2014-07-31 07:45:45 -0400
commitc091ff51b4d2543b828d53ce47f66905dee870fd (patch)
tree1354b1abdf40d4f83e0824a51b0be634ddc5a16e /drivers/dma
parent9f2c2bb31258e11b1ebaf73bdf2a88f8afaa2dd2 (diff)
dmaengine: shdma: Make channel filter ignore unrelated devices
The shdma_chan_filter() function relies on the DMA channel being embedded in an shdma_chan structure. If this assumption isn't true, for instance when the system contains DMA channels supported by an unrelated driver, the function will crash. Avoid this by returning false directly when the channel belongs to an unrelated device. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Simon Horman <horms+renesas@verge.net.au> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/sh/shdma-base.c84
1 files changed, 45 insertions, 39 deletions
diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index b35007e21e6b..94b6bde6c86a 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -206,45 +206,6 @@ static int shdma_setup_slave(struct shdma_chan *schan, int slave_id,
206 return 0; 206 return 0;
207} 207}
208 208
209/*
210 * This is the standard shdma filter function to be used as a replacement to the
211 * "old" method, using the .private pointer. If for some reason you allocate a
212 * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter
213 * parameter. If this filter is used, the slave driver, after calling
214 * dma_request_channel(), will also have to call dmaengine_slave_config() with
215 * .slave_id, .direction, and either .src_addr or .dst_addr set.
216 * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE
217 * capability! If this becomes a requirement, hardware glue drivers, using this
218 * services would have to provide their own filters, which first would check
219 * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do
220 * this, and only then, in case of a match, call this common filter.
221 * NOTE 2: This filter function is also used in the DT case by shdma_of_xlate().
222 * In that case the MID-RID value is used for slave channel filtering and is
223 * passed to this function in the "arg" parameter.
224 */
225bool shdma_chan_filter(struct dma_chan *chan, void *arg)
226{
227 struct shdma_chan *schan = to_shdma_chan(chan);
228 struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
229 const struct shdma_ops *ops = sdev->ops;
230 int match = (long)arg;
231 int ret;
232
233 if (match < 0)
234 /* No slave requested - arbitrary channel */
235 return true;
236
237 if (!schan->dev->of_node && match >= slave_num)
238 return false;
239
240 ret = ops->set_slave(schan, match, 0, true);
241 if (ret < 0)
242 return false;
243
244 return true;
245}
246EXPORT_SYMBOL(shdma_chan_filter);
247
248static int shdma_alloc_chan_resources(struct dma_chan *chan) 209static int shdma_alloc_chan_resources(struct dma_chan *chan)
249{ 210{
250 struct shdma_chan *schan = to_shdma_chan(chan); 211 struct shdma_chan *schan = to_shdma_chan(chan);
@@ -295,6 +256,51 @@ esetslave:
295 return ret; 256 return ret;
296} 257}
297 258
259/*
260 * This is the standard shdma filter function to be used as a replacement to the
261 * "old" method, using the .private pointer. If for some reason you allocate a
262 * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter
263 * parameter. If this filter is used, the slave driver, after calling
264 * dma_request_channel(), will also have to call dmaengine_slave_config() with
265 * .slave_id, .direction, and either .src_addr or .dst_addr set.
266 * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE
267 * capability! If this becomes a requirement, hardware glue drivers, using this
268 * services would have to provide their own filters, which first would check
269 * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do
270 * this, and only then, in case of a match, call this common filter.
271 * NOTE 2: This filter function is also used in the DT case by shdma_of_xlate().
272 * In that case the MID-RID value is used for slave channel filtering and is
273 * passed to this function in the "arg" parameter.
274 */
275bool shdma_chan_filter(struct dma_chan *chan, void *arg)
276{
277 struct shdma_chan *schan;
278 struct shdma_dev *sdev;
279 int match = (long)arg;
280 int ret;
281
282 /* Only support channels handled by this driver. */
283 if (chan->device->device_alloc_chan_resources !=
284 shdma_alloc_chan_resources)
285 return false;
286
287 if (match < 0)
288 /* No slave requested - arbitrary channel */
289 return true;
290
291 schan = to_shdma_chan(chan);
292 if (!schan->dev->of_node && match >= slave_num)
293 return false;
294
295 sdev = to_shdma_dev(schan->dma_chan.device);
296 ret = sdev->ops->set_slave(schan, match, 0, true);
297 if (ret < 0)
298 return false;
299
300 return true;
301}
302EXPORT_SYMBOL(shdma_chan_filter);
303
298static dma_async_tx_callback __ld_cleanup(struct shdma_chan *schan, bool all) 304static dma_async_tx_callback __ld_cleanup(struct shdma_chan *schan, bool all)
299{ 305{
300 struct shdma_desc *desc, *_desc; 306 struct shdma_desc *desc, *_desc;