* [PATCH 0/4] async_tx: fix dependency handling and related cleanups
@ 2008-02-13 7:02 Dan Williams
2008-02-13 7:02 ` [PATCH 1/4] async_tx: checkpatch says s/__FUNCTION__/__func__/g Dan Williams
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Dan Williams @ 2008-02-13 7:02 UTC (permalink / raw)
To: linux-kernel; +Cc: hskinnemoen, shannon.nelson, olof, yur
Injecting channel-switch-interrupts has been broken for a while now. It
has not been a problem in practice because the only in-tree driver that
relied on this functionality was the iop3xx version of iop-adma, and it
had a bug-masking local workaround. Three side benefits arise from this
fix:
1/ dma_async_tx_descriptor sheds two list_heads
2/ Locking is made sane in that dma drivers no longer need to directly
touch dma_async_tx_descriptor.lock
3/ dma_device.device_dependency_added is no longer needed
Testing shows that iop-adma now gets by without the 'watchdog'
workaround.
---
Dan Williams (4):
iop-adma: remove the workaround for missed interrupts on iop3xx
async_tx: kill ->device_dependency_added
async_tx: fix multiple dependency submission
async_tx: checkpatch says s/__FUNCTION__/__func__/g
crypto/async_tx/async_memcpy.c | 6 -
crypto/async_tx/async_memset.c | 6 -
crypto/async_tx/async_tx.c | 203 ++++++++++++++++++++++++++------
crypto/async_tx/async_xor.c | 12 +-
drivers/dma/dmaengine.c | 3
drivers/dma/ioat_dma.c | 12 --
drivers/dma/iop-adma.c | 21 +--
include/asm-arm/arch-iop13xx/adma.h | 5 -
include/asm-arm/hardware/iop3xx-adma.h | 8 -
include/asm-arm/hardware/iop_adma.h | 2
include/linux/dmaengine.h | 11 --
11 files changed, 185 insertions(+), 104 deletions(-)
--
Dan
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/4] async_tx: checkpatch says s/__FUNCTION__/__func__/g
2008-02-13 7:02 [PATCH 0/4] async_tx: fix dependency handling and related cleanups Dan Williams
@ 2008-02-13 7:02 ` Dan Williams
2008-02-13 7:03 ` [PATCH 2/4] async_tx: fix multiple dependency submission Dan Williams
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Dan Williams @ 2008-02-13 7:02 UTC (permalink / raw)
To: linux-kernel; +Cc: hskinnemoen, shannon.nelson, olof, yur
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
crypto/async_tx/async_memcpy.c | 6 +++---
crypto/async_tx/async_memset.c | 6 +++---
crypto/async_tx/async_tx.c | 6 +++---
crypto/async_tx/async_xor.c | 12 ++++++------
4 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
index 0f62822..84caa4e 100644
--- a/crypto/async_tx/async_memcpy.c
+++ b/crypto/async_tx/async_memcpy.c
@@ -66,11 +66,11 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
}
if (tx) {
- pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+ pr_debug("%s: (async) len: %zu\n", __func__, len);
async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
} else {
void *dest_buf, *src_buf;
- pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+ pr_debug("%s: (sync) len: %zu\n", __func__, len);
/* wait for any prerequisite operations */
if (depend_tx) {
@@ -80,7 +80,7 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
BUG_ON(depend_tx->ack);
if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
panic("%s: DMA_ERROR waiting for depend_tx\n",
- __FUNCTION__);
+ __func__);
}
dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
diff --git a/crypto/async_tx/async_memset.c b/crypto/async_tx/async_memset.c
index 09c0e83..f5ff390 100644
--- a/crypto/async_tx/async_memset.c
+++ b/crypto/async_tx/async_memset.c
@@ -63,11 +63,11 @@ async_memset(struct page *dest, int val, unsigned int offset,
}
if (tx) {
- pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+ pr_debug("%s: (async) len: %zu\n", __func__, len);
async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
} else { /* run the memset synchronously */
void *dest_buf;
- pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+ pr_debug("%s: (sync) len: %zu\n", __func__, len);
dest_buf = (void *) (((char *) page_address(dest)) + offset);
@@ -79,7 +79,7 @@ async_memset(struct page *dest, int val, unsigned int offset,
BUG_ON(depend_tx->ack);
if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
panic("%s: DMA_ERROR waiting for depend_tx\n",
- __FUNCTION__);
+ __func__);
}
memset(dest_buf, val, len);
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
index 5628821..2be3bae 100644
--- a/crypto/async_tx/async_tx.c
+++ b/crypto/async_tx/async_tx.c
@@ -472,11 +472,11 @@ async_trigger_callback(enum async_tx_flags flags,
tx = NULL;
if (tx) {
- pr_debug("%s: (async)\n", __FUNCTION__);
+ pr_debug("%s: (async)\n", __func__);
async_tx_submit(chan, tx, flags, depend_tx, cb_fn, cb_param);
} else {
- pr_debug("%s: (sync)\n", __FUNCTION__);
+ pr_debug("%s: (sync)\n", __func__);
/* wait for any prerequisite operations */
if (depend_tx) {
@@ -486,7 +486,7 @@ async_trigger_callback(enum async_tx_flags flags,
BUG_ON(depend_tx->ack);
if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
panic("%s: DMA_ERROR waiting for depend_tx\n",
- __FUNCTION__);
+ __func__);
}
async_tx_sync_epilog(flags, depend_tx, cb_fn, cb_param);
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index 2259a4f..7a9db35 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -47,7 +47,7 @@ do_async_xor(struct dma_device *device,
int i;
unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;
- pr_debug("%s: len: %zu\n", __FUNCTION__, len);
+ pr_debug("%s: len: %zu\n", __func__, len);
dma_dest = dma_map_page(device->dev, dest, offset, len,
DMA_FROM_DEVICE);
@@ -86,7 +86,7 @@ do_sync_xor(struct page *dest, struct page **src_list, unsigned int offset,
void *_dest;
int i;
- pr_debug("%s: len: %zu\n", __FUNCTION__, len);
+ pr_debug("%s: len: %zu\n", __func__, len);
/* reuse the 'src_list' array to convert to buffer pointers */
for (i = 0; i < src_cnt; i++)
@@ -196,7 +196,7 @@ async_xor(struct page *dest, struct page **src_list, unsigned int offset,
DMA_ERROR)
panic("%s: DMA_ERROR waiting for "
"depend_tx\n",
- __FUNCTION__);
+ __func__);
}
do_sync_xor(dest, &src_list[src_off], offset,
@@ -276,7 +276,7 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,
unsigned long dma_prep_flags = cb_fn ? DMA_PREP_INTERRUPT : 0;
int i;
- pr_debug("%s: (async) len: %zu\n", __FUNCTION__, len);
+ pr_debug("%s: (async) len: %zu\n", __func__, len);
for (i = 0; i < src_cnt; i++)
dma_src[i] = dma_map_page(device->dev, src_list[i],
@@ -299,7 +299,7 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,
} else {
unsigned long xor_flags = flags;
- pr_debug("%s: (sync) len: %zu\n", __FUNCTION__, len);
+ pr_debug("%s: (sync) len: %zu\n", __func__, len);
xor_flags |= ASYNC_TX_XOR_DROP_DST;
xor_flags &= ~ASYNC_TX_ACK;
@@ -310,7 +310,7 @@ async_xor_zero_sum(struct page *dest, struct page **src_list,
if (tx) {
if (dma_wait_for_async_tx(tx) == DMA_ERROR)
panic("%s: DMA_ERROR waiting for tx\n",
- __FUNCTION__);
+ __func__);
async_tx_ack(tx);
}
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/4] async_tx: fix multiple dependency submission
2008-02-13 7:02 [PATCH 0/4] async_tx: fix dependency handling and related cleanups Dan Williams
2008-02-13 7:02 ` [PATCH 1/4] async_tx: checkpatch says s/__FUNCTION__/__func__/g Dan Williams
@ 2008-02-13 7:03 ` Dan Williams
2008-02-13 16:10 ` Nelson, Shannon
2008-02-13 7:03 ` [PATCH 3/4] async_tx: kill ->device_dependency_added Dan Williams
` (2 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Dan Williams @ 2008-02-13 7:03 UTC (permalink / raw)
To: linux-kernel; +Cc: hskinnemoen, shannon.nelson, olof, yur
Shrink struct dma_async_tx_descriptor and introduce
async_tx_channel_switch to properly inject a channel switch interrupt in
the descriptor stream. This simplifies the locking model as drivers no
longer need to handle dma_async_tx_descriptor.lock.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
crypto/async_tx/async_tx.c | 197 ++++++++++++++++++++++++++++++++++++--------
drivers/dma/dmaengine.c | 2
drivers/dma/iop-adma.c | 9 +-
include/linux/dmaengine.h | 9 +-
4 files changed, 170 insertions(+), 47 deletions(-)
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
index 2be3bae..6975616 100644
--- a/crypto/async_tx/async_tx.c
+++ b/crypto/async_tx/async_tx.c
@@ -89,13 +89,19 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
iter = tx;
/* find the root of the unsubmitted dependency chain */
- while (iter->cookie == -EBUSY) {
+ do {
parent = iter->parent;
- if (parent && parent->cookie == -EBUSY)
- iter = iter->parent;
- else
+ if (!parent)
break;
- }
+ else
+ iter = parent;
+ } while (parent);
+
+ /* there is a small window for ->parent == NULL and
+ * ->cookie == -EBUSY
+ */
+ while (iter->cookie == -EBUSY)
+ cpu_relax();
status = dma_sync_wait(iter->chan, iter->cookie);
} while (status == DMA_IN_PROGRESS || (iter != tx));
@@ -111,24 +117,33 @@ EXPORT_SYMBOL_GPL(dma_wait_for_async_tx);
void
async_tx_run_dependencies(struct dma_async_tx_descriptor *tx)
{
- struct dma_async_tx_descriptor *dep_tx, *_dep_tx;
- struct dma_device *dev;
+ struct dma_async_tx_descriptor *next = tx->next;
struct dma_chan *chan;
- list_for_each_entry_safe(dep_tx, _dep_tx, &tx->depend_list,
- depend_node) {
- chan = dep_tx->chan;
- dev = chan->device;
- /* we can't depend on ourselves */
- BUG_ON(chan == tx->chan);
- list_del(&dep_tx->depend_node);
- tx->tx_submit(dep_tx);
-
- /* we need to poke the engine as client code does not
- * know about dependency submission events
- */
- dev->device_issue_pending(chan);
+ if (!next)
+ return;
+
+ tx->next = NULL;
+ chan = next->chan;
+
+ /* keep submitting up until a channel switch is detected
+ * in that case we will be called again as a result of
+ * processing the interrupt from async_tx_channel_switch
+ */
+ while (next && next->chan == chan) {
+ struct dma_async_tx_descriptor *_next;
+
+ spin_lock_bh(&next->lock);
+ next->parent = NULL;
+ _next = next->next;
+ next->next = NULL;
+ spin_unlock_bh(&next->lock);
+
+ next->tx_submit(next);
+ next = _next;
}
+
+ chan->device->device_issue_pending(chan);
}
EXPORT_SYMBOL_GPL(async_tx_run_dependencies);
@@ -397,6 +412,92 @@ static void __exit async_tx_exit(void)
}
#endif
+
+/**
+ * async_tx_channel_switch - queue an interrupt descriptor with a dependency
+ * pre-attached.
+ * @depend_tx: the operation that must finish before the new operation runs
+ * @tx: the new operation
+ */
+static void
+async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx,
+ struct dma_async_tx_descriptor *tx)
+{
+ struct dma_chan *chan;
+ struct dma_device *device;
+ struct dma_async_tx_descriptor *intr_tx = (void *) ~0;
+
+ /* first check to see if we can still append to depend_tx */
+ spin_lock_bh(&depend_tx->lock);
+ if (depend_tx->parent && depend_tx->chan == tx->chan) {
+ tx->parent = depend_tx;
+ depend_tx->next = tx;
+ intr_tx = NULL;
+ }
+ spin_unlock_bh(&depend_tx->lock);
+
+ if (!intr_tx)
+ return;
+
+ chan = depend_tx->chan;
+ device = chan->device;
+
+ /* see if we can schedule an interrupt
+ * otherwise poll for completion
+ */
+ if (dma_has_cap(DMA_INTERRUPT, device->cap_mask))
+ intr_tx = device->device_prep_dma_interrupt(chan);
+ else
+ intr_tx = NULL;
+
+ if (intr_tx) {
+ intr_tx->callback = NULL;
+ intr_tx->callback_param = NULL;
+ tx->parent = intr_tx;
+ /* safe to set ->next outside the lock since we know we are
+ * not submitted yet
+ */
+ intr_tx->next = tx;
+
+ /* check if we need to append */
+ spin_lock_bh(&depend_tx->lock);
+ if (depend_tx->parent) {
+ intr_tx->parent = depend_tx;
+ depend_tx->next = intr_tx;
+ async_tx_ack(intr_tx);
+ intr_tx = NULL;
+ }
+ spin_unlock_bh(&depend_tx->lock);
+
+ if (intr_tx) {
+ intr_tx->parent = NULL;
+ intr_tx->tx_submit(intr_tx);
+ async_tx_ack(intr_tx);
+ }
+ } else {
+ if (dma_wait_for_async_tx(depend_tx) == DMA_ERROR)
+ panic("%s: DMA_ERROR waiting for depend_tx\n",
+ __func__);
+ tx->tx_submit(tx);
+ }
+}
+
+
+/**
+ * submit_disposition - while holding depend_tx->lock we must avoid submitting
+ * new operations to prevent a circular locking dependency with
+ * drivers that already hold a channel lock when calling
+ * async_tx_run_dependencies.
+ * @ASYNC_TX_SUBMITTED: we were able to append the new operation under the lock
+ * @ASYNC_TX_CHANNEL_SWITCH: when the lock is dropped schedule a channel switch
+ * @ASYNC_TX_DIRECT_SUBMIT: when the lock is dropped submit directly
+ */
+enum submit_disposition {
+ ASYNC_TX_SUBMITTED,
+ ASYNC_TX_CHANNEL_SWITCH,
+ ASYNC_TX_DIRECT_SUBMIT,
+};
+
void
async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
enum async_tx_flags flags, struct dma_async_tx_descriptor *depend_tx,
@@ -405,28 +506,54 @@ async_tx_submit(struct dma_chan *chan, struct dma_async_tx_descriptor *tx,
tx->callback = cb_fn;
tx->callback_param = cb_param;
- /* set this new tx to run after depend_tx if:
- * 1/ a dependency exists (depend_tx is !NULL)
- * 2/ the tx can not be submitted to the current channel
- */
- if (depend_tx && depend_tx->chan != chan) {
- /* if ack is already set then we cannot be sure
+ if (depend_tx) {
+ enum submit_disposition s;
+
+ /* sanity check the dependency chain:
+ * 1/ if ack is already set then we cannot be sure
* we are referring to the correct operation
+ * 2/ dependencies are 1:1 i.e. two transactions can
+ * not depend on the same parent
*/
- BUG_ON(depend_tx->ack);
+ BUG_ON(depend_tx->ack || depend_tx->next || tx->parent);
- tx->parent = depend_tx;
+ /* the lock prevents async_tx_run_dependencies from missing
+ * the setting of ->next when ->parent != NULL
+ */
spin_lock_bh(&depend_tx->lock);
- list_add_tail(&tx->depend_node, &depend_tx->depend_list);
- if (depend_tx->cookie == 0) {
- struct dma_chan *dep_chan = depend_tx->chan;
- struct dma_device *dep_dev = dep_chan->device;
- dep_dev->device_dependency_added(dep_chan);
+ if (depend_tx->parent) {
+ /* we have a parent so we can not submit directly
+ * if we are staying on the same channel: append
+ * else: channel switch
+ */
+ if (depend_tx->chan == chan) {
+ tx->parent = depend_tx;
+ depend_tx->next = tx;
+ s = ASYNC_TX_SUBMITTED;
+ } else
+ s = ASYNC_TX_CHANNEL_SWITCH;
+ } else {
+ /* we do not have a parent so we may be able to submit
+ * directly if we are staying on the same channel
+ */
+ if (depend_tx->chan == chan)
+ s = ASYNC_TX_DIRECT_SUBMIT;
+ else
+ s = ASYNC_TX_CHANNEL_SWITCH;
}
spin_unlock_bh(&depend_tx->lock);
- /* schedule an interrupt to trigger the channel switch */
- async_trigger_callback(ASYNC_TX_ACK, depend_tx, NULL, NULL);
+ switch (s) {
+ case ASYNC_TX_SUBMITTED:
+ break;
+ case ASYNC_TX_CHANNEL_SWITCH:
+ async_tx_channel_switch(depend_tx, tx);
+ break;
+ case ASYNC_TX_DIRECT_SUBMIT:
+ tx->parent = NULL;
+ tx->tx_submit(tx);
+ break;
+ }
} else {
tx->parent = NULL;
tx->tx_submit(tx);
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 2996523..9369781 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -600,8 +600,6 @@ void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
{
tx->chan = chan;
spin_lock_init(&tx->lock);
- INIT_LIST_HEAD(&tx->depend_node);
- INIT_LIST_HEAD(&tx->depend_list);
}
EXPORT_SYMBOL(dma_async_tx_descriptor_init);
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 3986d54..a6171da 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -63,7 +63,6 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
struct iop_adma_chan *iop_chan, dma_cookie_t cookie)
{
BUG_ON(desc->async_tx.cookie < 0);
- spin_lock_bh(&desc->async_tx.lock);
if (desc->async_tx.cookie > 0) {
cookie = desc->async_tx.cookie;
desc->async_tx.cookie = 0;
@@ -101,7 +100,6 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
/* run dependent operations */
async_tx_run_dependencies(&desc->async_tx);
- spin_unlock_bh(&desc->async_tx.lock);
return cookie;
}
@@ -275,8 +273,11 @@ iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
static void iop_adma_tasklet(unsigned long data)
{
- struct iop_adma_chan *chan = (struct iop_adma_chan *) data;
- __iop_adma_slot_cleanup(chan);
+ struct iop_adma_chan *iop_chan = (struct iop_adma_chan *) data;
+
+ spin_lock(&iop_chan->lock);
+ __iop_adma_slot_cleanup(iop_chan);
+ spin_unlock(&iop_chan->lock);
}
static struct iop_adma_desc_slot *
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index acbb364..d04b169 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -221,11 +221,9 @@ typedef void (*dma_async_tx_callback)(void *dma_async_param);
* @callback: routine to call after this operation is complete
* @callback_param: general parameter to pass to the callback routine
* ---async_tx api specific fields---
- * @depend_list: at completion this list of transactions are submitted
- * @depend_node: allow this transaction to be executed after another
- * transaction has completed, possibly on another channel
+ * @next: at completion submit this descriptor
* @parent: pointer to the next level up in the dependency chain
- * @lock: protect the dependency list
+ * @lock: protect the parent and next pointers
*/
struct dma_async_tx_descriptor {
dma_cookie_t cookie;
@@ -236,8 +234,7 @@ struct dma_async_tx_descriptor {
dma_cookie_t (*tx_submit)(struct dma_async_tx_descriptor *tx);
dma_async_tx_callback callback;
void *callback_param;
- struct list_head depend_list;
- struct list_head depend_node;
+ struct dma_async_tx_descriptor *next;
struct dma_async_tx_descriptor *parent;
spinlock_t lock;
};
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/4] async_tx: kill ->device_dependency_added
2008-02-13 7:02 [PATCH 0/4] async_tx: fix dependency handling and related cleanups Dan Williams
2008-02-13 7:02 ` [PATCH 1/4] async_tx: checkpatch says s/__FUNCTION__/__func__/g Dan Williams
2008-02-13 7:03 ` [PATCH 2/4] async_tx: fix multiple dependency submission Dan Williams
@ 2008-02-13 7:03 ` Dan Williams
2008-02-13 16:05 ` Nelson, Shannon
2008-02-13 7:03 ` [PATCH 4/4] iop-adma: remove the workaround for missed interrupts on iop3xx Dan Williams
2008-02-15 8:38 ` [PATCH 0/4] async_tx: fix dependency handling and related cleanups Haavard Skinnemoen
4 siblings, 1 reply; 8+ messages in thread
From: Dan Williams @ 2008-02-13 7:03 UTC (permalink / raw)
To: linux-kernel; +Cc: hskinnemoen, shannon.nelson, olof, yur
DMA drivers no longer need to be notified of depdency submission events as
async_tx_run_dependencies and async_tx_channel_switch will handle the
scheduling and execution of dependent operations.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/dma/dmaengine.c | 1 -
drivers/dma/ioat_dma.c | 12 ------------
drivers/dma/iop-adma.c | 7 -------
include/linux/dmaengine.h | 2 --
4 files changed, 0 insertions(+), 22 deletions(-)
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 9369781..5ca0d94 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -362,7 +362,6 @@ int dma_async_device_register(struct dma_device *device)
BUG_ON(!device->device_alloc_chan_resources);
BUG_ON(!device->device_free_chan_resources);
- BUG_ON(!device->device_dependency_added);
BUG_ON(!device->device_is_tx_complete);
BUG_ON(!device->device_issue_pending);
BUG_ON(!device->dev);
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index dff38ac..05ace54 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -922,17 +922,6 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
spin_unlock_bh(&ioat_chan->cleanup_lock);
}
-static void ioat_dma_dependency_added(struct dma_chan *chan)
-{
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
- spin_lock_bh(&ioat_chan->desc_lock);
- if (ioat_chan->pending == 0) {
- spin_unlock_bh(&ioat_chan->desc_lock);
- ioat_dma_memcpy_cleanup(ioat_chan);
- } else
- spin_unlock_bh(&ioat_chan->desc_lock);
-}
-
/**
* ioat_dma_is_complete - poll the status of a IOAT DMA transaction
* @chan: IOAT DMA channel handle
@@ -1314,7 +1303,6 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev,
dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
device->common.device_is_tx_complete = ioat_dma_is_complete;
- device->common.device_dependency_added = ioat_dma_dependency_added;
switch (device->version) {
case IOAT_VER_1_2:
device->common.device_prep_dma_memcpy = ioat1_dma_prep_memcpy;
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index a6171da..1cb4284 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -672,12 +672,6 @@ iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src,
return sw_desc ? &sw_desc->async_tx : NULL;
}
-static void iop_adma_dependency_added(struct dma_chan *chan)
-{
- struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
- tasklet_schedule(&iop_chan->irq_tasklet);
-}
-
static void iop_adma_free_chan_resources(struct dma_chan *chan)
{
struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
@@ -1178,7 +1172,6 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
dma_dev->device_free_chan_resources = iop_adma_free_chan_resources;
dma_dev->device_is_tx_complete = iop_adma_is_complete;
dma_dev->device_issue_pending = iop_adma_issue_pending;
- dma_dev->device_dependency_added = iop_adma_dependency_added;
dma_dev->dev = &pdev->dev;
/* set prep routines based on capability */
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index d04b169..e2538b4 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -258,7 +258,6 @@ struct dma_async_tx_descriptor {
* @device_prep_dma_zero_sum: prepares a zero_sum operation
* @device_prep_dma_memset: prepares a memset operation
* @device_prep_dma_interrupt: prepares an end of chain interrupt operation
- * @device_dependency_added: async_tx notifies the channel about new deps
* @device_issue_pending: push pending transactions to hardware
*/
struct dma_device {
@@ -293,7 +292,6 @@ struct dma_device {
struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
struct dma_chan *chan);
- void (*device_dependency_added)(struct dma_chan *chan);
enum dma_status (*device_is_tx_complete)(struct dma_chan *chan,
dma_cookie_t cookie, dma_cookie_t *last,
dma_cookie_t *used);
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/4] iop-adma: remove the workaround for missed interrupts on iop3xx
2008-02-13 7:02 [PATCH 0/4] async_tx: fix dependency handling and related cleanups Dan Williams
` (2 preceding siblings ...)
2008-02-13 7:03 ` [PATCH 3/4] async_tx: kill ->device_dependency_added Dan Williams
@ 2008-02-13 7:03 ` Dan Williams
2008-02-15 8:38 ` [PATCH 0/4] async_tx: fix dependency handling and related cleanups Haavard Skinnemoen
4 siblings, 0 replies; 8+ messages in thread
From: Dan Williams @ 2008-02-13 7:03 UTC (permalink / raw)
To: linux-kernel; +Cc: hskinnemoen, shannon.nelson, olof, yur
This workaround was covering the dependency submission bug in async_tx.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/dma/iop-adma.c | 5 -----
include/asm-arm/arch-iop13xx/adma.h | 5 -----
include/asm-arm/hardware/iop3xx-adma.h | 8 --------
include/asm-arm/hardware/iop_adma.h | 2 --
4 files changed, 0 insertions(+), 20 deletions(-)
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index 1cb4284..821bd17 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -255,8 +255,6 @@ static void __iop_adma_slot_cleanup(struct iop_adma_chan *iop_chan)
BUG_ON(!seen_current);
- iop_chan_idle(busy, iop_chan);
-
if (cookie > 0) {
iop_chan->completed_cookie = cookie;
pr_debug("\tcompleted cookie %d\n", cookie);
@@ -1226,9 +1224,6 @@ static int __devinit iop_adma_probe(struct platform_device *pdev)
}
spin_lock_init(&iop_chan->lock);
- init_timer(&iop_chan->cleanup_watchdog);
- iop_chan->cleanup_watchdog.data = (unsigned long) iop_chan;
- iop_chan->cleanup_watchdog.function = iop_adma_tasklet;
INIT_LIST_HEAD(&iop_chan->chain);
INIT_LIST_HEAD(&iop_chan->all_slots);
INIT_RCU_HEAD(&iop_chan->common.rcu);
diff --git a/include/asm-arm/arch-iop13xx/adma.h b/include/asm-arm/arch-iop13xx/adma.h
index efd9a5e..90d14ee 100644
--- a/include/asm-arm/arch-iop13xx/adma.h
+++ b/include/asm-arm/arch-iop13xx/adma.h
@@ -454,11 +454,6 @@ static inline void iop_chan_append(struct iop_adma_chan *chan)
__raw_writel(adma_accr, ADMA_ACCR(chan));
}
-static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
-{
- do { } while (0);
-}
-
static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
{
return __raw_readl(ADMA_ACSR(chan));
diff --git a/include/asm-arm/hardware/iop3xx-adma.h b/include/asm-arm/hardware/iop3xx-adma.h
index 5c529e6..84d635b 100644
--- a/include/asm-arm/hardware/iop3xx-adma.h
+++ b/include/asm-arm/hardware/iop3xx-adma.h
@@ -767,20 +767,12 @@ static inline int iop_desc_get_zero_result(struct iop_adma_desc_slot *desc)
static inline void iop_chan_append(struct iop_adma_chan *chan)
{
u32 dma_chan_ctrl;
- /* workaround dropped interrupts on 3xx */
- mod_timer(&chan->cleanup_watchdog, jiffies + msecs_to_jiffies(3));
dma_chan_ctrl = __raw_readl(DMA_CCR(chan));
dma_chan_ctrl |= 0x2;
__raw_writel(dma_chan_ctrl, DMA_CCR(chan));
}
-static inline void iop_chan_idle(int busy, struct iop_adma_chan *chan)
-{
- if (!busy)
- del_timer(&chan->cleanup_watchdog);
-}
-
static inline u32 iop_chan_get_status(struct iop_adma_chan *chan)
{
return __raw_readl(DMA_CSR(chan));
diff --git a/include/asm-arm/hardware/iop_adma.h b/include/asm-arm/hardware/iop_adma.h
index ca8e71f..cb7e361 100644
--- a/include/asm-arm/hardware/iop_adma.h
+++ b/include/asm-arm/hardware/iop_adma.h
@@ -51,7 +51,6 @@ struct iop_adma_device {
* @common: common dmaengine channel object members
* @last_used: place holder for allocation to continue from where it left off
* @all_slots: complete domain of slots usable by the channel
- * @cleanup_watchdog: workaround missed interrupts on iop3xx
* @slots_allocated: records the actual size of the descriptor slot pool
* @irq_tasklet: bottom half where iop_adma_slot_cleanup runs
*/
@@ -65,7 +64,6 @@ struct iop_adma_chan {
struct dma_chan common;
struct iop_adma_desc_slot *last_used;
struct list_head all_slots;
- struct timer_list cleanup_watchdog;
int slots_allocated;
struct tasklet_struct irq_tasklet;
};
^ permalink raw reply related [flat|nested] 8+ messages in thread
* RE: [PATCH 3/4] async_tx: kill ->device_dependency_added
2008-02-13 7:03 ` [PATCH 3/4] async_tx: kill ->device_dependency_added Dan Williams
@ 2008-02-13 16:05 ` Nelson, Shannon
0 siblings, 0 replies; 8+ messages in thread
From: Nelson, Shannon @ 2008-02-13 16:05 UTC (permalink / raw)
To: Williams, Dan J, linux-kernel; +Cc: hskinnemoen, olof, yur, Sosnowski, Maciej
>-----Original Message-----
>From: Williams, Dan J
>Sent: Tuesday, February 12, 2008 11:03 PM
>To: linux-kernel@vger.kernel.org
>Cc: hskinnemoen@atmel.com; Nelson, Shannon; olof@lixom.net;
>yur@emcraft.com
>Subject: [PATCH 3/4] async_tx: kill ->device_dependency_added
>
>DMA drivers no longer need to be notified of depdency
>submission events as
>async_tx_run_dependencies and async_tx_channel_switch will handle the
>scheduling and execution of dependent operations.
>
>Signed-off-by: Dan Williams <dan.j.williams@intel.com>
>---
>
> drivers/dma/dmaengine.c | 1 -
> drivers/dma/ioat_dma.c | 12 ------------
> drivers/dma/iop-adma.c | 7 -------
> include/linux/dmaengine.h | 2 --
> 4 files changed, 0 insertions(+), 22 deletions(-)
>
>
>diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
>index 9369781..5ca0d94 100644
>--- a/drivers/dma/dmaengine.c
>+++ b/drivers/dma/dmaengine.c
>@@ -362,7 +362,6 @@ int dma_async_device_register(struct
>dma_device *device)
>
> BUG_ON(!device->device_alloc_chan_resources);
> BUG_ON(!device->device_free_chan_resources);
>- BUG_ON(!device->device_dependency_added);
> BUG_ON(!device->device_is_tx_complete);
> BUG_ON(!device->device_issue_pending);
> BUG_ON(!device->dev);
>diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
>index dff38ac..05ace54 100644
>--- a/drivers/dma/ioat_dma.c
>+++ b/drivers/dma/ioat_dma.c
>@@ -922,17 +922,6 @@ static void
>ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan)
> spin_unlock_bh(&ioat_chan->cleanup_lock);
> }
>
>-static void ioat_dma_dependency_added(struct dma_chan *chan)
>-{
>- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
>- spin_lock_bh(&ioat_chan->desc_lock);
>- if (ioat_chan->pending == 0) {
>- spin_unlock_bh(&ioat_chan->desc_lock);
>- ioat_dma_memcpy_cleanup(ioat_chan);
>- } else
>- spin_unlock_bh(&ioat_chan->desc_lock);
>-}
>-
> /**
> * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
> * @chan: IOAT DMA channel handle
>@@ -1314,7 +1303,6 @@ struct ioatdma_device
>*ioat_dma_probe(struct pci_dev *pdev,
>
> dma_cap_set(DMA_MEMCPY, device->common.cap_mask);
> device->common.device_is_tx_complete = ioat_dma_is_complete;
>- device->common.device_dependency_added =
>ioat_dma_dependency_added;
> switch (device->version) {
> case IOAT_VER_1_2:
> device->common.device_prep_dma_memcpy =
>ioat1_dma_prep_memcpy;
>diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
>index a6171da..1cb4284 100644
>--- a/drivers/dma/iop-adma.c
>+++ b/drivers/dma/iop-adma.c
>@@ -672,12 +672,6 @@ iop_adma_prep_dma_zero_sum(struct
>dma_chan *chan, dma_addr_t *dma_src,
> return sw_desc ? &sw_desc->async_tx : NULL;
> }
>
>-static void iop_adma_dependency_added(struct dma_chan *chan)
>-{
>- struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
>- tasklet_schedule(&iop_chan->irq_tasklet);
>-}
>-
> static void iop_adma_free_chan_resources(struct dma_chan *chan)
> {
> struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan);
>@@ -1178,7 +1172,6 @@ static int __devinit
>iop_adma_probe(struct platform_device *pdev)
> dma_dev->device_free_chan_resources =
>iop_adma_free_chan_resources;
> dma_dev->device_is_tx_complete = iop_adma_is_complete;
> dma_dev->device_issue_pending = iop_adma_issue_pending;
>- dma_dev->device_dependency_added = iop_adma_dependency_added;
> dma_dev->dev = &pdev->dev;
>
> /* set prep routines based on capability */
>diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
>index d04b169..e2538b4 100644
>--- a/include/linux/dmaengine.h
>+++ b/include/linux/dmaengine.h
>@@ -258,7 +258,6 @@ struct dma_async_tx_descriptor {
> * @device_prep_dma_zero_sum: prepares a zero_sum operation
> * @device_prep_dma_memset: prepares a memset operation
> * @device_prep_dma_interrupt: prepares an end of chain
>interrupt operation
>- * @device_dependency_added: async_tx notifies the channel
>about new deps
> * @device_issue_pending: push pending transactions to hardware
> */
> struct dma_device {
>@@ -293,7 +292,6 @@ struct dma_device {
> struct dma_async_tx_descriptor *(*device_prep_dma_interrupt)(
> struct dma_chan *chan);
>
>- void (*device_dependency_added)(struct dma_chan *chan);
> enum dma_status (*device_is_tx_complete)(struct dma_chan *chan,
> dma_cookie_t cookie, dma_cookie_t *last,
> dma_cookie_t *used);
>
>
Acked-by: Shannon Nelson <shannon.nelson@intel.com>
^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH 2/4] async_tx: fix multiple dependency submission
2008-02-13 7:03 ` [PATCH 2/4] async_tx: fix multiple dependency submission Dan Williams
@ 2008-02-13 16:10 ` Nelson, Shannon
0 siblings, 0 replies; 8+ messages in thread
From: Nelson, Shannon @ 2008-02-13 16:10 UTC (permalink / raw)
To: Williams, Dan J, linux-kernel; +Cc: hskinnemoen, olof, yur, Sosnowski, Maciej
>-----Original Message-----
>From: Williams, Dan J
>Sent: Tuesday, February 12, 2008 11:03 PM
>To: linux-kernel@vger.kernel.org
>Cc: hskinnemoen@atmel.com; Nelson, Shannon; olof@lixom.net;
>yur@emcraft.com
>Subject: [PATCH 2/4] async_tx: fix multiple dependency submission
>
>Shrink struct dma_async_tx_descriptor and introduce
>async_tx_channel_switch to properly inject a channel switch
>interrupt in
>the descriptor stream. This simplifies the locking model as drivers no
>longer need to handle dma_async_tx_descriptor.lock.
>
>Signed-off-by: Dan Williams <dan.j.williams@intel.com>
>---
>
> crypto/async_tx/async_tx.c | 197
>++++++++++++++++++++++++++++++++++++--------
> drivers/dma/dmaengine.c | 2
> drivers/dma/iop-adma.c | 9 +-
> include/linux/dmaengine.h | 9 +-
> 4 files changed, 170 insertions(+), 47 deletions(-)
>
>
Acked-by: Shannon Nelson <shannon.nelson@intel.com>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/4] async_tx: fix dependency handling and related cleanups
2008-02-13 7:02 [PATCH 0/4] async_tx: fix dependency handling and related cleanups Dan Williams
` (3 preceding siblings ...)
2008-02-13 7:03 ` [PATCH 4/4] iop-adma: remove the workaround for missed interrupts on iop3xx Dan Williams
@ 2008-02-15 8:38 ` Haavard Skinnemoen
4 siblings, 0 replies; 8+ messages in thread
From: Haavard Skinnemoen @ 2008-02-15 8:38 UTC (permalink / raw)
To: Dan Williams; +Cc: linux-kernel, shannon.nelson, olof, yur
On Wed, 13 Feb 2008 00:02:52 -0700
Dan Williams <dan.j.williams@intel.com> wrote:
> Dan Williams (4):
> iop-adma: remove the workaround for missed interrupts on iop3xx
> async_tx: kill ->device_dependency_added
> async_tx: fix multiple dependency submission
> async_tx: checkpatch says s/__FUNCTION__/__func__/g
All of the above changes are fine with me. I'll rebase my dmaslave
patches on top of them; that will probably allow me to get rid of the
dma_slave_descriptor struct.
Haavard
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2008-02-15 8:39 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-13 7:02 [PATCH 0/4] async_tx: fix dependency handling and related cleanups Dan Williams
2008-02-13 7:02 ` [PATCH 1/4] async_tx: checkpatch says s/__FUNCTION__/__func__/g Dan Williams
2008-02-13 7:03 ` [PATCH 2/4] async_tx: fix multiple dependency submission Dan Williams
2008-02-13 16:10 ` Nelson, Shannon
2008-02-13 7:03 ` [PATCH 3/4] async_tx: kill ->device_dependency_added Dan Williams
2008-02-13 16:05 ` Nelson, Shannon
2008-02-13 7:03 ` [PATCH 4/4] iop-adma: remove the workaround for missed interrupts on iop3xx Dan Williams
2008-02-15 8:38 ` [PATCH 0/4] async_tx: fix dependency handling and related cleanups Haavard Skinnemoen
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.