mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-30 02:29:01 +00:00
ea91ee13a7
This patch fixes the dw_dmac dma engine which is used by the SATA controllers in the MyBook Live Series and WNDR4700. The code was backported from the upstream kernel. It can be dropped completely on 4.7+. Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
144 lines
4.3 KiB
Diff
144 lines
4.3 KiB
Diff
From 7bd903c5ca47fde5ad52370a47776491813c772e Mon Sep 17 00:00:00 2001
|
|
From: Peter Ujfalusi <peter.ujfalusi@ti.com>
|
|
Date: Mon, 14 Dec 2015 22:47:39 +0200
|
|
Subject: [PATCH 1/3] dmaengine: core: Move and merge the code paths using
|
|
private_candidate
|
|
|
|
Channel matching with private_candidate() is used in two paths, the error
|
|
checking is slightly different in them and they are duplicating code also.
|
|
Move the code under find_candidate() to provide consistent execution and
|
|
going to allow us to reuse this mode of channel lookup later.
|
|
|
|
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
|
|
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
|
|
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
|
|
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
|
|
---
|
|
drivers/dma/dmaengine.c | 81 +++++++++++++++++++++++++------------------------
|
|
1 file changed, 42 insertions(+), 39 deletions(-)
|
|
|
|
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
|
|
index f2cbff9..81a36fc 100644
|
|
--- a/drivers/dma/dmaengine.c
|
|
+++ b/drivers/dma/dmaengine.c
|
|
@@ -542,6 +542,42 @@ static struct dma_chan *private_candidate(const dma_cap_mask_t *mask,
|
|
return NULL;
|
|
}
|
|
|
|
+static struct dma_chan *find_candidate(struct dma_device *device,
|
|
+ const dma_cap_mask_t *mask,
|
|
+ dma_filter_fn fn, void *fn_param)
|
|
+{
|
|
+ struct dma_chan *chan = private_candidate(mask, device, fn, fn_param);
|
|
+ int err;
|
|
+
|
|
+ if (chan) {
|
|
+ /* Found a suitable channel, try to grab, prep, and return it.
|
|
+ * We first set DMA_PRIVATE to disable balance_ref_count as this
|
|
+ * channel will not be published in the general-purpose
|
|
+ * allocator
|
|
+ */
|
|
+ dma_cap_set(DMA_PRIVATE, device->cap_mask);
|
|
+ device->privatecnt++;
|
|
+ err = dma_chan_get(chan);
|
|
+
|
|
+ if (err) {
|
|
+ if (err == -ENODEV) {
|
|
+ pr_debug("%s: %s module removed\n", __func__,
|
|
+ dma_chan_name(chan));
|
|
+ list_del_rcu(&device->global_node);
|
|
+ } else
|
|
+ pr_debug("%s: failed to get %s: (%d)\n",
|
|
+ __func__, dma_chan_name(chan), err);
|
|
+
|
|
+ if (--device->privatecnt == 0)
|
|
+ dma_cap_clear(DMA_PRIVATE, device->cap_mask);
|
|
+
|
|
+ chan = ERR_PTR(err);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return chan ? chan : ERR_PTR(-EPROBE_DEFER);
|
|
+}
|
|
+
|
|
/**
|
|
* dma_get_slave_channel - try to get specific channel exclusively
|
|
* @chan: target channel
|
|
@@ -580,7 +616,6 @@ struct dma_chan *dma_get_any_slave_channel(struct dma_device *device)
|
|
{
|
|
dma_cap_mask_t mask;
|
|
struct dma_chan *chan;
|
|
- int err;
|
|
|
|
dma_cap_zero(mask);
|
|
dma_cap_set(DMA_SLAVE, mask);
|
|
@@ -588,23 +623,11 @@ struct dma_chan *dma_get_any_slave_channel(struct dma_device *device)
|
|
/* lock against __dma_request_channel */
|
|
mutex_lock(&dma_list_mutex);
|
|
|
|
- chan = private_candidate(&mask, device, NULL, NULL);
|
|
- if (chan) {
|
|
- dma_cap_set(DMA_PRIVATE, device->cap_mask);
|
|
- device->privatecnt++;
|
|
- err = dma_chan_get(chan);
|
|
- if (err) {
|
|
- pr_debug("%s: failed to get %s: (%d)\n",
|
|
- __func__, dma_chan_name(chan), err);
|
|
- chan = NULL;
|
|
- if (--device->privatecnt == 0)
|
|
- dma_cap_clear(DMA_PRIVATE, device->cap_mask);
|
|
- }
|
|
- }
|
|
+ chan = find_candidate(device, &mask, NULL, NULL);
|
|
|
|
mutex_unlock(&dma_list_mutex);
|
|
|
|
- return chan;
|
|
+ return IS_ERR(chan) ? NULL : chan;
|
|
}
|
|
EXPORT_SYMBOL_GPL(dma_get_any_slave_channel);
|
|
|
|
@@ -621,35 +644,15 @@ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
|
|
{
|
|
struct dma_device *device, *_d;
|
|
struct dma_chan *chan = NULL;
|
|
- int err;
|
|
|
|
/* Find a channel */
|
|
mutex_lock(&dma_list_mutex);
|
|
list_for_each_entry_safe(device, _d, &dma_device_list, global_node) {
|
|
- chan = private_candidate(mask, device, fn, fn_param);
|
|
- if (chan) {
|
|
- /* Found a suitable channel, try to grab, prep, and
|
|
- * return it. We first set DMA_PRIVATE to disable
|
|
- * balance_ref_count as this channel will not be
|
|
- * published in the general-purpose allocator
|
|
- */
|
|
- dma_cap_set(DMA_PRIVATE, device->cap_mask);
|
|
- device->privatecnt++;
|
|
- err = dma_chan_get(chan);
|
|
+ chan = find_candidate(device, mask, fn, fn_param);
|
|
+ if (!IS_ERR(chan))
|
|
+ break;
|
|
|
|
- if (err == -ENODEV) {
|
|
- pr_debug("%s: %s module removed\n",
|
|
- __func__, dma_chan_name(chan));
|
|
- list_del_rcu(&device->global_node);
|
|
- } else if (err)
|
|
- pr_debug("%s: failed to get %s: (%d)\n",
|
|
- __func__, dma_chan_name(chan), err);
|
|
- else
|
|
- break;
|
|
- if (--device->privatecnt == 0)
|
|
- dma_cap_clear(DMA_PRIVATE, device->cap_mask);
|
|
- chan = NULL;
|
|
- }
|
|
+ chan = NULL;
|
|
}
|
|
mutex_unlock(&dma_list_mutex);
|
|
|
|
--
|
|
2.8.1
|
|
|