From dd59b8537f6cb53ab863fafad86a5828f1e889a2 Mon Sep 17 00:00:00 2001 From: Yuri Tikhonov Date: Mon, 12 Jan 2009 15:17:20 -0700 Subject: dmaengine: fix dependency chaining In dmaengine we track the dependencies between the descriptors using the 'next' pointers of the structure. These pointers are set to NULL as soon as the corresponding descriptor has been submitted to the channel (in dma_run_dependencies()). But, the first 'next' in chain is still remaining set, regardless the fact, that tx->next has been already submitted. This may lead to multiple submissions of the same descriptor. This patch fixes this. Actually, some previous implementation of the xxx_run_dependencies() function already had this fix in place. The fdb..0eaf3 commit, beside the correct things, broke this. Cc: Signed-off-by: Yuri Tikhonov Signed-off-by: Dan Williams --- drivers/dma/dmaengine.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/dma/dmaengine.c') diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 403dbe781122..6df144a65fef 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -961,6 +961,8 @@ void dma_run_dependencies(struct dma_async_tx_descriptor *tx) if (!dep) return; + /* we'll submit tx->next now, so clear the link */ + tx->next = NULL; chan = dep->chan; /* keep submitting up until a channel switch is detected -- cgit v1.2.3 From 83436a0560e9ef8af2f0796264dde4bed1415359 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 19 Jan 2009 14:39:10 -0700 Subject: dmaengine: kill some dubious WARN_ONCEs dma_find_channel and dma_issue_pending_all are good places to warn about improper api usage. However, warning correctly means synchronizing with dma_list_mutex, i.e. too much overhead for these fast-path calls. Reported-by: Ingo Molnar Signed-off-by: Dan Williams --- drivers/dma/dmaengine.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/dma/dmaengine.c') diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 6df144a65fef..a58993011edb 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -329,9 +329,6 @@ struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type) struct dma_chan *chan; int cpu; - WARN_ONCE(dmaengine_ref_count == 0, - "client called %s without a reference", __func__); - cpu = get_cpu(); chan = per_cpu_ptr(channel_table[tx_type], cpu)->chan; put_cpu(); @@ -348,9 +345,6 @@ void dma_issue_pending_all(void) struct dma_device *device; struct dma_chan *chan; - WARN_ONCE(dmaengine_ref_count == 0, - "client called %s without a reference", __func__); - rcu_read_lock(); list_for_each_entry_rcu(device, &dma_device_list, global_node) { if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) -- cgit v1.2.3 From 287d859222e0adbc67666a6154aaf42d7d5bbb54 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 18 Feb 2009 14:48:26 -0800 Subject: atmel-mci: fix initialization of dma slave data The conversion of atmel-mci to dma_request_channel missed the initialization of the channel dma_slave information. The filter_fn passed to dma_request_channel is responsible for initializing the channel's private data. This implementation has the additional benefit of enabling a generic client-channel data passing mechanism. Reviewed-by: Atsushi Nemoto Signed-off-by: Dan Williams Acked-by: Haavard Skinnemoen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/dma/dmaengine.c | 2 ++ drivers/dma/dw_dmac.c | 5 ++--- drivers/dma/dw_dmac_regs.h | 2 -- drivers/mmc/host/atmel-mci.c | 5 +++-- include/linux/dmaengine.h | 2 ++ 5 files changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/dma/dmaengine.c') diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index a58993011edb..280a9d263eb3 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -518,6 +518,7 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v dma_chan_name(chan), err); else break; + chan->private = NULL; chan = NULL; } } @@ -536,6 +537,7 @@ void dma_release_channel(struct dma_chan *chan) WARN_ONCE(chan->client_count != 1, "chan reference count %d != 1\n", chan->client_count); dma_chan_put(chan); + chan->private = NULL; mutex_unlock(&dma_list_mutex); } EXPORT_SYMBOL_GPL(dma_release_channel); diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 6b702cc46b3d..a97c07eef7ec 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -560,7 +560,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned long flags) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); - struct dw_dma_slave *dws = dwc->dws; + struct dw_dma_slave *dws = chan->private; struct dw_desc *prev; struct dw_desc *first; u32 ctllo; @@ -790,7 +790,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) cfghi = DWC_CFGH_FIFO_MODE; cfglo = 0; - dws = dwc->dws; + dws = chan->private; if (dws) { /* * We need controller-specific data to set up slave @@ -866,7 +866,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan) spin_lock_bh(&dwc->lock); list_splice_init(&dwc->free_list, &list); dwc->descs_allocated = 0; - dwc->dws = NULL; /* Disable interrupts */ channel_clear_bit(dw, MASK.XFER, dwc->mask); diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index 00fdd187bb0c..b252b202c5cf 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h @@ -139,8 +139,6 @@ struct dw_dma_chan { struct list_head queue; struct list_head free_list; - struct dw_dma_slave *dws; - unsigned int descs_allocated; }; diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 76bfe16c09b1..2b1196e6142c 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1548,9 +1548,10 @@ static bool filter(struct dma_chan *chan, void *slave) { struct dw_dma_slave *dws = slave; - if (dws->dma_dev == chan->device->dev) + if (dws->dma_dev == chan->device->dev) { + chan->private = dws; return true; - else + } else return false; } #endif diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 3e68469c1885..f0413845f20e 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -121,6 +121,7 @@ struct dma_chan_percpu { * @local: per-cpu pointer to a struct dma_chan_percpu * @client-count: how many clients are using this channel * @table_count: number of appearances in the mem-to-mem allocation table + * @private: private data for certain client-channel associations */ struct dma_chan { struct dma_device *device; @@ -134,6 +135,7 @@ struct dma_chan { struct dma_chan_percpu *local; int client_count; int table_count; + void *private; }; /** -- cgit v1.2.3