You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'topic/err_reporting' into for-linus
Signed-off-by: Vinod Koul <vinod.koul@intel.com> Conflicts: drivers/dma/cppi41.c
This commit is contained in:
@@ -282,6 +282,17 @@ supported.
|
||||
that is supposed to push the current
|
||||
transaction descriptor to a pending queue, waiting
|
||||
for issue_pending to be called.
|
||||
- In this structure the function pointer callback_result can be
|
||||
initialized in order for the submitter to be notified that a
|
||||
transaction has completed. In the earlier code the function pointer
|
||||
callback has been used. However it does not provide any status to the
|
||||
transaction and will be deprecated. The result structure defined as
|
||||
dmaengine_result that is passed in to callback_result has two fields:
|
||||
+ result: This provides the transfer result defined by
|
||||
dmaengine_tx_result. Either success or some error
|
||||
condition.
|
||||
+ residue: Provides the residue bytes of the transfer for those that
|
||||
support residue.
|
||||
|
||||
* device_issue_pending
|
||||
- Takes the first transaction descriptor in the pending queue,
|
||||
|
||||
@@ -473,15 +473,11 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
|
||||
/* for cyclic transfers,
|
||||
* no need to replay callback function while stopping */
|
||||
if (!atc_chan_is_cyclic(atchan)) {
|
||||
dma_async_tx_callback callback = txd->callback;
|
||||
void *param = txd->callback_param;
|
||||
|
||||
/*
|
||||
* The API requires that no submissions are done from a
|
||||
* callback, so we don't need to drop the lock here
|
||||
*/
|
||||
if (callback)
|
||||
callback(param);
|
||||
dmaengine_desc_get_callback_invoke(txd, NULL);
|
||||
}
|
||||
|
||||
dma_run_dependencies(txd);
|
||||
@@ -598,15 +594,12 @@ static void atc_handle_cyclic(struct at_dma_chan *atchan)
|
||||
{
|
||||
struct at_desc *first = atc_first_active(atchan);
|
||||
struct dma_async_tx_descriptor *txd = &first->txd;
|
||||
dma_async_tx_callback callback = txd->callback;
|
||||
void *param = txd->callback_param;
|
||||
|
||||
dev_vdbg(chan2dev(&atchan->chan_common),
|
||||
"new cyclic period llp 0x%08x\n",
|
||||
channel_readl(atchan, DSCR));
|
||||
|
||||
if (callback)
|
||||
callback(param);
|
||||
dmaengine_desc_get_callback_invoke(txd, NULL);
|
||||
}
|
||||
|
||||
/*-- IRQ & Tasklet ---------------------------------------------------*/
|
||||
|
||||
@@ -1572,8 +1572,8 @@ static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan)
|
||||
desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, xfer_node);
|
||||
txd = &desc->tx_dma_desc;
|
||||
|
||||
if (txd->callback && (txd->flags & DMA_PREP_INTERRUPT))
|
||||
txd->callback(txd->callback_param);
|
||||
if (txd->flags & DMA_PREP_INTERRUPT)
|
||||
dmaengine_desc_get_callback_invoke(txd, NULL);
|
||||
}
|
||||
|
||||
static void at_xdmac_tasklet(unsigned long data)
|
||||
@@ -1616,8 +1616,8 @@ static void at_xdmac_tasklet(unsigned long data)
|
||||
|
||||
if (!at_xdmac_chan_is_cyclic(atchan)) {
|
||||
dma_cookie_complete(txd);
|
||||
if (txd->callback && (txd->flags & DMA_PREP_INTERRUPT))
|
||||
txd->callback(txd->callback_param);
|
||||
if (txd->flags & DMA_PREP_INTERRUPT)
|
||||
dmaengine_desc_get_callback_invoke(txd, NULL);
|
||||
}
|
||||
|
||||
dma_run_dependencies(txd);
|
||||
|
||||
@@ -1875,8 +1875,7 @@ static void dma_tasklet(unsigned long data)
|
||||
struct coh901318_chan *cohc = (struct coh901318_chan *) data;
|
||||
struct coh901318_desc *cohd_fin;
|
||||
unsigned long flags;
|
||||
dma_async_tx_callback callback;
|
||||
void *callback_param;
|
||||
struct dmaengine_desc_callback cb;
|
||||
|
||||
dev_vdbg(COHC_2_DEV(cohc), "[%s] chan_id %d"
|
||||
" nbr_active_done %ld\n", __func__,
|
||||
@@ -1891,8 +1890,7 @@ static void dma_tasklet(unsigned long data)
|
||||
goto err;
|
||||
|
||||
/* locate callback to client */
|
||||
callback = cohd_fin->desc.callback;
|
||||
callback_param = cohd_fin->desc.callback_param;
|
||||
dmaengine_desc_get_callback(&cohd_fin->desc, &cb);
|
||||
|
||||
/* sign this job as completed on the channel */
|
||||
dma_cookie_complete(&cohd_fin->desc);
|
||||
@@ -1907,8 +1905,7 @@ static void dma_tasklet(unsigned long data)
|
||||
spin_unlock_irqrestore(&cohc->lock, flags);
|
||||
|
||||
/* Call the callback when we're done */
|
||||
if (callback)
|
||||
callback(callback_param);
|
||||
dmaengine_desc_callback_invoke(&cb, NULL);
|
||||
|
||||
spin_lock_irqsave(&cohc->lock, flags);
|
||||
|
||||
|
||||
@@ -336,7 +336,7 @@ static irqreturn_t cppi41_irq(int irq, void *data)
|
||||
|
||||
c->residue = pd_trans_len(c->desc->pd6) - len;
|
||||
dma_cookie_complete(&c->txd);
|
||||
c->txd.callback(c->txd.callback_param);
|
||||
dmaengine_desc_get_callback_invoke(&c->txd, NULL);
|
||||
|
||||
/* Paired with cppi41_dma_issue_pending */
|
||||
pm_runtime_mark_last_busy(cdd->ddev.dev);
|
||||
|
||||
@@ -86,4 +86,88 @@ static inline void dma_set_residue(struct dma_tx_state *state, u32 residue)
|
||||
state->residue = residue;
|
||||
}
|
||||
|
||||
struct dmaengine_desc_callback {
|
||||
dma_async_tx_callback callback;
|
||||
dma_async_tx_callback_result callback_result;
|
||||
void *callback_param;
|
||||
};
|
||||
|
||||
/**
|
||||
* dmaengine_desc_get_callback - get the passed in callback function
|
||||
* @tx: tx descriptor
|
||||
* @cb: temp struct to hold the callback info
|
||||
*
|
||||
* Fill the passed in cb struct with what's available in the passed in
|
||||
* tx descriptor struct
|
||||
* No locking is required.
|
||||
*/
|
||||
static inline void
|
||||
dmaengine_desc_get_callback(struct dma_async_tx_descriptor *tx,
|
||||
struct dmaengine_desc_callback *cb)
|
||||
{
|
||||
cb->callback = tx->callback;
|
||||
cb->callback_result = tx->callback_result;
|
||||
cb->callback_param = tx->callback_param;
|
||||
}
|
||||
|
||||
/**
|
||||
* dmaengine_desc_callback_invoke - call the callback function in cb struct
|
||||
* @cb: temp struct that is holding the callback info
|
||||
* @result: transaction result
|
||||
*
|
||||
* Call the callback function provided in the cb struct with the parameter
|
||||
* in the cb struct.
|
||||
* Locking is dependent on the driver.
|
||||
*/
|
||||
static inline void
|
||||
dmaengine_desc_callback_invoke(struct dmaengine_desc_callback *cb,
|
||||
const struct dmaengine_result *result)
|
||||
{
|
||||
struct dmaengine_result dummy_result = {
|
||||
.result = DMA_TRANS_NOERROR,
|
||||
.residue = 0
|
||||
};
|
||||
|
||||
if (cb->callback_result) {
|
||||
if (!result)
|
||||
result = &dummy_result;
|
||||
cb->callback_result(cb->callback_param, result);
|
||||
} else if (cb->callback) {
|
||||
cb->callback(cb->callback_param);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dmaengine_desc_get_callback_invoke - get the callback in tx descriptor and
|
||||
* then immediately call the callback.
|
||||
* @tx: dma async tx descriptor
|
||||
* @result: transaction result
|
||||
*
|
||||
* Call dmaengine_desc_get_callback() and dmaengine_desc_callback_invoke()
|
||||
* in a single function since no work is necessary in between for the driver.
|
||||
* Locking is dependent on the driver.
|
||||
*/
|
||||
static inline void
|
||||
dmaengine_desc_get_callback_invoke(struct dma_async_tx_descriptor *tx,
|
||||
const struct dmaengine_result *result)
|
||||
{
|
||||
struct dmaengine_desc_callback cb;
|
||||
|
||||
dmaengine_desc_get_callback(tx, &cb);
|
||||
dmaengine_desc_callback_invoke(&cb, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* dmaengine_desc_callback_valid - verify the callback is valid in cb
|
||||
* @cb: callback info struct
|
||||
*
|
||||
* Return a bool that verifies whether callback in cb is valid or not.
|
||||
* No locking is required.
|
||||
*/
|
||||
static inline bool
|
||||
dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb)
|
||||
{
|
||||
return (cb->callback) ? true : false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -270,20 +270,19 @@ static void
|
||||
dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc,
|
||||
bool callback_required)
|
||||
{
|
||||
dma_async_tx_callback callback = NULL;
|
||||
void *param = NULL;
|
||||
struct dma_async_tx_descriptor *txd = &desc->txd;
|
||||
struct dw_desc *child;
|
||||
unsigned long flags;
|
||||
struct dmaengine_desc_callback cb;
|
||||
|
||||
dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie);
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
dma_cookie_complete(txd);
|
||||
if (callback_required) {
|
||||
callback = txd->callback;
|
||||
param = txd->callback_param;
|
||||
}
|
||||
if (callback_required)
|
||||
dmaengine_desc_get_callback(txd, &cb);
|
||||
else
|
||||
memset(&cb, 0, sizeof(cb));
|
||||
|
||||
/* async_tx_ack */
|
||||
list_for_each_entry(child, &desc->tx_list, desc_node)
|
||||
@@ -292,8 +291,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc,
|
||||
dwc_desc_put(dwc, desc);
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
if (callback)
|
||||
callback(param);
|
||||
dmaengine_desc_callback_invoke(&cb, NULL);
|
||||
}
|
||||
|
||||
static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc)
|
||||
|
||||
@@ -737,10 +737,10 @@ static void ep93xx_dma_tasklet(unsigned long data)
|
||||
{
|
||||
struct ep93xx_dma_chan *edmac = (struct ep93xx_dma_chan *)data;
|
||||
struct ep93xx_dma_desc *desc, *d;
|
||||
dma_async_tx_callback callback = NULL;
|
||||
void *callback_param = NULL;
|
||||
struct dmaengine_desc_callback cb;
|
||||
LIST_HEAD(list);
|
||||
|
||||
memset(&cb, 0, sizeof(cb));
|
||||
spin_lock_irq(&edmac->lock);
|
||||
/*
|
||||
* If dma_terminate_all() was called before we get to run, the active
|
||||
@@ -755,8 +755,7 @@ static void ep93xx_dma_tasklet(unsigned long data)
|
||||
dma_cookie_complete(&desc->txd);
|
||||
list_splice_init(&edmac->active, &list);
|
||||
}
|
||||
callback = desc->txd.callback;
|
||||
callback_param = desc->txd.callback_param;
|
||||
dmaengine_desc_get_callback(&desc->txd, &cb);
|
||||
}
|
||||
spin_unlock_irq(&edmac->lock);
|
||||
|
||||
@@ -769,8 +768,7 @@ static void ep93xx_dma_tasklet(unsigned long data)
|
||||
ep93xx_dma_desc_put(edmac, desc);
|
||||
}
|
||||
|
||||
if (callback)
|
||||
callback(callback_param);
|
||||
dmaengine_desc_callback_invoke(&cb, NULL);
|
||||
}
|
||||
|
||||
static irqreturn_t ep93xx_dma_interrupt(int irq, void *dev_id)
|
||||
|
||||
@@ -134,16 +134,8 @@ static void fsl_re_issue_pending(struct dma_chan *chan)
|
||||
|
||||
static void fsl_re_desc_done(struct fsl_re_desc *desc)
|
||||
{
|
||||
dma_async_tx_callback callback;
|
||||
void *callback_param;
|
||||
|
||||
dma_cookie_complete(&desc->async_tx);
|
||||
|
||||
callback = desc->async_tx.callback;
|
||||
callback_param = desc->async_tx.callback_param;
|
||||
if (callback)
|
||||
callback(callback_param);
|
||||
|
||||
dmaengine_desc_get_callback_invoke(&desc->async_tx, NULL);
|
||||
dma_descriptor_unmap(&desc->async_tx);
|
||||
}
|
||||
|
||||
|
||||
@@ -517,11 +517,7 @@ static dma_cookie_t fsldma_run_tx_complete_actions(struct fsldma_chan *chan,
|
||||
ret = txd->cookie;
|
||||
|
||||
/* Run the link descriptor callback function */
|
||||
if (txd->callback) {
|
||||
chan_dbg(chan, "LD %p callback\n", desc);
|
||||
txd->callback(txd->callback_param);
|
||||
}
|
||||
|
||||
dmaengine_desc_get_callback_invoke(txd, NULL);
|
||||
dma_descriptor_unmap(txd);
|
||||
}
|
||||
|
||||
|
||||
@@ -663,9 +663,7 @@ static void imxdma_tasklet(unsigned long data)
|
||||
out:
|
||||
spin_unlock_irqrestore(&imxdma->lock, flags);
|
||||
|
||||
if (desc->desc.callback)
|
||||
desc->desc.callback(desc->desc.callback_param);
|
||||
|
||||
dmaengine_desc_get_callback_invoke(&desc->desc, NULL);
|
||||
}
|
||||
|
||||
static int imxdma_terminate_all(struct dma_chan *chan)
|
||||
|
||||
@@ -650,8 +650,7 @@ static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event)
|
||||
|
||||
static void sdma_handle_channel_loop(struct sdma_channel *sdmac)
|
||||
{
|
||||
if (sdmac->desc.callback)
|
||||
sdmac->desc.callback(sdmac->desc.callback_param);
|
||||
dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
|
||||
}
|
||||
|
||||
static void sdma_update_channel_loop(struct sdma_channel *sdmac)
|
||||
@@ -701,8 +700,8 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
|
||||
sdmac->status = DMA_COMPLETE;
|
||||
|
||||
dma_cookie_complete(&sdmac->desc);
|
||||
if (sdmac->desc.callback)
|
||||
sdmac->desc.callback(sdmac->desc.callback_param);
|
||||
|
||||
dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
|
||||
}
|
||||
|
||||
static void sdma_tasklet(unsigned long data)
|
||||
|
||||
+187
-26
@@ -38,8 +38,54 @@
|
||||
|
||||
#include "../dmaengine.h"
|
||||
|
||||
static char *chanerr_str[] = {
|
||||
"DMA Transfer Destination Address Error",
|
||||
"Next Descriptor Address Error",
|
||||
"Descriptor Error",
|
||||
"Chan Address Value Error",
|
||||
"CHANCMD Error",
|
||||
"Chipset Uncorrectable Data Integrity Error",
|
||||
"DMA Uncorrectable Data Integrity Error",
|
||||
"Read Data Error",
|
||||
"Write Data Error",
|
||||
"Descriptor Control Error",
|
||||
"Descriptor Transfer Size Error",
|
||||
"Completion Address Error",
|
||||
"Interrupt Configuration Error",
|
||||
"Super extended descriptor Address Error",
|
||||
"Unaffiliated Error",
|
||||
"CRC or XOR P Error",
|
||||
"XOR Q Error",
|
||||
"Descriptor Count Error",
|
||||
"DIF All F detect Error",
|
||||
"Guard Tag verification Error",
|
||||
"Application Tag verification Error",
|
||||
"Reference Tag verification Error",
|
||||
"Bundle Bit Error",
|
||||
"Result DIF All F detect Error",
|
||||
"Result Guard Tag verification Error",
|
||||
"Result Application Tag verification Error",
|
||||
"Result Reference Tag verification Error",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void ioat_eh(struct ioatdma_chan *ioat_chan);
|
||||
|
||||
static void ioat_print_chanerrs(struct ioatdma_chan *ioat_chan, u32 chanerr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
if ((chanerr >> i) & 1) {
|
||||
if (chanerr_str[i]) {
|
||||
dev_err(to_dev(ioat_chan), "Err(%d): %s\n",
|
||||
i, chanerr_str[i]);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ioat_dma_do_interrupt - handler used for single vector interrupt mode
|
||||
* @irq: interrupt id
|
||||
@@ -568,12 +614,14 @@ static void __cleanup(struct ioatdma_chan *ioat_chan, dma_addr_t phys_complete)
|
||||
|
||||
tx = &desc->txd;
|
||||
if (tx->cookie) {
|
||||
struct dmaengine_result res;
|
||||
|
||||
dma_cookie_complete(tx);
|
||||
dma_descriptor_unmap(tx);
|
||||
if (tx->callback) {
|
||||
tx->callback(tx->callback_param);
|
||||
tx->callback = NULL;
|
||||
}
|
||||
res.result = DMA_TRANS_NOERROR;
|
||||
dmaengine_desc_get_callback_invoke(tx, NULL);
|
||||
tx->callback = NULL;
|
||||
tx->callback_result = NULL;
|
||||
}
|
||||
|
||||
if (tx->phys == phys_complete)
|
||||
@@ -622,7 +670,8 @@ static void ioat_cleanup(struct ioatdma_chan *ioat_chan)
|
||||
if (is_ioat_halted(*ioat_chan->completion)) {
|
||||
u32 chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
|
||||
|
||||
if (chanerr & IOAT_CHANERR_HANDLE_MASK) {
|
||||
if (chanerr &
|
||||
(IOAT_CHANERR_HANDLE_MASK | IOAT_CHANERR_RECOVER_MASK)) {
|
||||
mod_timer(&ioat_chan->timer, jiffies + IDLE_TIMEOUT);
|
||||
ioat_eh(ioat_chan);
|
||||
}
|
||||
@@ -652,6 +701,61 @@ static void ioat_restart_channel(struct ioatdma_chan *ioat_chan)
|
||||
__ioat_restart_chan(ioat_chan);
|
||||
}
|
||||
|
||||
|
||||
static void ioat_abort_descs(struct ioatdma_chan *ioat_chan)
|
||||
{
|
||||
struct ioatdma_device *ioat_dma = ioat_chan->ioat_dma;
|
||||
struct ioat_ring_ent *desc;
|
||||
u16 active;
|
||||
int idx = ioat_chan->tail, i;
|
||||
|
||||
/*
|
||||
* We assume that the failed descriptor has been processed.
|
||||
* Now we are just returning all the remaining submitted
|
||||
* descriptors to abort.
|
||||
*/
|
||||
active = ioat_ring_active(ioat_chan);
|
||||
|
||||
/* we skip the failed descriptor that tail points to */
|
||||
for (i = 1; i < active; i++) {
|
||||
struct dma_async_tx_descriptor *tx;
|
||||
|
||||
smp_read_barrier_depends();
|
||||
prefetch(ioat_get_ring_ent(ioat_chan, idx + i + 1));
|
||||
desc = ioat_get_ring_ent(ioat_chan, idx + i);
|
||||
|
||||
tx = &desc->txd;
|
||||
if (tx->cookie) {
|
||||
struct dmaengine_result res;
|
||||
|
||||
dma_cookie_complete(tx);
|
||||
dma_descriptor_unmap(tx);
|
||||
res.result = DMA_TRANS_ABORTED;
|
||||
dmaengine_desc_get_callback_invoke(tx, &res);
|
||||
tx->callback = NULL;
|
||||
tx->callback_result = NULL;
|
||||
}
|
||||
|
||||
/* skip extended descriptors */
|
||||
if (desc_has_ext(desc)) {
|
||||
WARN_ON(i + 1 >= active);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* cleanup super extended descriptors */
|
||||
if (desc->sed) {
|
||||
ioat_free_sed(ioat_dma, desc->sed);
|
||||
desc->sed = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
smp_mb(); /* finish all descriptor reads before incrementing tail */
|
||||
ioat_chan->tail = idx + active;
|
||||
|
||||
desc = ioat_get_ring_ent(ioat_chan, ioat_chan->tail);
|
||||
ioat_chan->last_completion = *ioat_chan->completion = desc->txd.phys;
|
||||
}
|
||||
|
||||
static void ioat_eh(struct ioatdma_chan *ioat_chan)
|
||||
{
|
||||
struct pci_dev *pdev = to_pdev(ioat_chan);
|
||||
@@ -662,6 +766,8 @@ static void ioat_eh(struct ioatdma_chan *ioat_chan)
|
||||
u32 err_handled = 0;
|
||||
u32 chanerr_int;
|
||||
u32 chanerr;
|
||||
bool abort = false;
|
||||
struct dmaengine_result res;
|
||||
|
||||
/* cleanup so tail points to descriptor that caused the error */
|
||||
if (ioat_cleanup_preamble(ioat_chan, &phys_complete))
|
||||
@@ -697,30 +803,55 @@ static void ioat_eh(struct ioatdma_chan *ioat_chan)
|
||||
break;
|
||||
}
|
||||
|
||||
if (chanerr & IOAT_CHANERR_RECOVER_MASK) {
|
||||
if (chanerr & IOAT_CHANERR_READ_DATA_ERR) {
|
||||
res.result = DMA_TRANS_READ_FAILED;
|
||||
err_handled |= IOAT_CHANERR_READ_DATA_ERR;
|
||||
} else if (chanerr & IOAT_CHANERR_WRITE_DATA_ERR) {
|
||||
res.result = DMA_TRANS_WRITE_FAILED;
|
||||
err_handled |= IOAT_CHANERR_WRITE_DATA_ERR;
|
||||
}
|
||||
|
||||
abort = true;
|
||||
} else
|
||||
res.result = DMA_TRANS_NOERROR;
|
||||
|
||||
/* fault on unhandled error or spurious halt */
|
||||
if (chanerr ^ err_handled || chanerr == 0) {
|
||||
dev_err(to_dev(ioat_chan), "%s: fatal error (%x:%x)\n",
|
||||
__func__, chanerr, err_handled);
|
||||
dev_err(to_dev(ioat_chan), "Errors handled:\n");
|
||||
ioat_print_chanerrs(ioat_chan, err_handled);
|
||||
dev_err(to_dev(ioat_chan), "Errors not handled:\n");
|
||||
ioat_print_chanerrs(ioat_chan, (chanerr & ~err_handled));
|
||||
|
||||
BUG();
|
||||
} else { /* cleanup the faulty descriptor */
|
||||
tx = &desc->txd;
|
||||
if (tx->cookie) {
|
||||
dma_cookie_complete(tx);
|
||||
dma_descriptor_unmap(tx);
|
||||
if (tx->callback) {
|
||||
tx->callback(tx->callback_param);
|
||||
tx->callback = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
|
||||
pci_write_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, chanerr_int);
|
||||
/* cleanup the faulty descriptor since we are continuing */
|
||||
tx = &desc->txd;
|
||||
if (tx->cookie) {
|
||||
dma_cookie_complete(tx);
|
||||
dma_descriptor_unmap(tx);
|
||||
dmaengine_desc_get_callback_invoke(tx, &res);
|
||||
tx->callback = NULL;
|
||||
tx->callback_result = NULL;
|
||||
}
|
||||
|
||||
/* mark faulting descriptor as complete */
|
||||
*ioat_chan->completion = desc->txd.phys;
|
||||
|
||||
spin_lock_bh(&ioat_chan->prep_lock);
|
||||
/* we need abort all descriptors */
|
||||
if (abort) {
|
||||
ioat_abort_descs(ioat_chan);
|
||||
/* clean up the channel, we could be in weird state */
|
||||
ioat_reset_hw(ioat_chan);
|
||||
}
|
||||
|
||||
writel(chanerr, ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
|
||||
pci_write_config_dword(pdev, IOAT_PCI_CHANERR_INT_OFFSET, chanerr_int);
|
||||
|
||||
ioat_restart_channel(ioat_chan);
|
||||
spin_unlock_bh(&ioat_chan->prep_lock);
|
||||
}
|
||||
@@ -753,10 +884,28 @@ void ioat_timer_event(unsigned long data)
|
||||
chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
|
||||
dev_err(to_dev(ioat_chan), "%s: Channel halted (%x)\n",
|
||||
__func__, chanerr);
|
||||
if (test_bit(IOAT_RUN, &ioat_chan->state))
|
||||
BUG_ON(is_ioat_bug(chanerr));
|
||||
else /* we never got off the ground */
|
||||
return;
|
||||
dev_err(to_dev(ioat_chan), "Errors:\n");
|
||||
ioat_print_chanerrs(ioat_chan, chanerr);
|
||||
|
||||
if (test_bit(IOAT_RUN, &ioat_chan->state)) {
|
||||
spin_lock_bh(&ioat_chan->cleanup_lock);
|
||||
spin_lock_bh(&ioat_chan->prep_lock);
|
||||
set_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
|
||||
spin_unlock_bh(&ioat_chan->prep_lock);
|
||||
|
||||
ioat_abort_descs(ioat_chan);
|
||||
dev_warn(to_dev(ioat_chan), "Reset channel...\n");
|
||||
ioat_reset_hw(ioat_chan);
|
||||
dev_warn(to_dev(ioat_chan), "Restart channel...\n");
|
||||
ioat_restart_channel(ioat_chan);
|
||||
|
||||
spin_lock_bh(&ioat_chan->prep_lock);
|
||||
clear_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
|
||||
spin_unlock_bh(&ioat_chan->prep_lock);
|
||||
spin_unlock_bh(&ioat_chan->cleanup_lock);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ioat_chan->cleanup_lock);
|
||||
@@ -780,14 +929,26 @@ void ioat_timer_event(unsigned long data)
|
||||
u32 chanerr;
|
||||
|
||||
chanerr = readl(ioat_chan->reg_base + IOAT_CHANERR_OFFSET);
|
||||
dev_warn(to_dev(ioat_chan), "Restarting channel...\n");
|
||||
dev_warn(to_dev(ioat_chan), "CHANSTS: %#Lx CHANERR: %#x\n",
|
||||
status, chanerr);
|
||||
dev_warn(to_dev(ioat_chan), "Active descriptors: %d\n",
|
||||
ioat_ring_active(ioat_chan));
|
||||
dev_err(to_dev(ioat_chan), "CHANSTS: %#Lx CHANERR: %#x\n",
|
||||
status, chanerr);
|
||||
dev_err(to_dev(ioat_chan), "Errors:\n");
|
||||
ioat_print_chanerrs(ioat_chan, chanerr);
|
||||
|
||||
dev_dbg(to_dev(ioat_chan), "Active descriptors: %d\n",
|
||||
ioat_ring_active(ioat_chan));
|
||||
|
||||
spin_lock_bh(&ioat_chan->prep_lock);
|
||||
set_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
|
||||
spin_unlock_bh(&ioat_chan->prep_lock);
|
||||
|
||||
ioat_abort_descs(ioat_chan);
|
||||
dev_warn(to_dev(ioat_chan), "Resetting channel...\n");
|
||||
ioat_reset_hw(ioat_chan);
|
||||
dev_warn(to_dev(ioat_chan), "Restarting channel...\n");
|
||||
ioat_restart_channel(ioat_chan);
|
||||
|
||||
spin_lock_bh(&ioat_chan->prep_lock);
|
||||
clear_bit(IOAT_CHAN_DOWN, &ioat_chan->state);
|
||||
spin_unlock_bh(&ioat_chan->prep_lock);
|
||||
spin_unlock_bh(&ioat_chan->cleanup_lock);
|
||||
return;
|
||||
|
||||
@@ -240,6 +240,8 @@
|
||||
#define IOAT_CHANERR_DESCRIPTOR_COUNT_ERR 0x40000
|
||||
|
||||
#define IOAT_CHANERR_HANDLE_MASK (IOAT_CHANERR_XOR_P_OR_CRC_ERR | IOAT_CHANERR_XOR_Q_ERR)
|
||||
#define IOAT_CHANERR_RECOVER_MASK (IOAT_CHANERR_READ_DATA_ERR | \
|
||||
IOAT_CHANERR_WRITE_DATA_ERR)
|
||||
|
||||
#define IOAT_CHANERR_MASK_OFFSET 0x2C /* 32-bit Channel Error Register */
|
||||
|
||||
|
||||
@@ -71,8 +71,7 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
|
||||
/* call the callback (must not sleep or submit new
|
||||
* operations to this channel)
|
||||
*/
|
||||
if (tx->callback)
|
||||
tx->callback(tx->callback_param);
|
||||
dmaengine_desc_get_callback_invoke(tx, NULL);
|
||||
|
||||
dma_descriptor_unmap(tx);
|
||||
if (desc->group_head)
|
||||
|
||||
@@ -1160,11 +1160,10 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id)
|
||||
struct scatterlist **sg, *sgnext, *sgnew = NULL;
|
||||
/* Next transfer descriptor */
|
||||
struct idmac_tx_desc *desc, *descnew;
|
||||
dma_async_tx_callback callback;
|
||||
void *callback_param;
|
||||
bool done = false;
|
||||
u32 ready0, ready1, curbuf, err;
|
||||
unsigned long flags;
|
||||
struct dmaengine_desc_callback cb;
|
||||
|
||||
/* IDMAC has cleared the respective BUFx_RDY bit, we manage the buffer */
|
||||
|
||||
@@ -1278,12 +1277,12 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id)
|
||||
|
||||
if (likely(sgnew) &&
|
||||
ipu_submit_buffer(ichan, descnew, sgnew, ichan->active_buffer) < 0) {
|
||||
callback = descnew->txd.callback;
|
||||
callback_param = descnew->txd.callback_param;
|
||||
dmaengine_desc_get_callback(&descnew->txd, &cb);
|
||||
|
||||
list_del_init(&descnew->list);
|
||||
spin_unlock(&ichan->lock);
|
||||
if (callback)
|
||||
callback(callback_param);
|
||||
|
||||
dmaengine_desc_callback_invoke(&cb, NULL);
|
||||
spin_lock(&ichan->lock);
|
||||
}
|
||||
|
||||
@@ -1292,13 +1291,12 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id)
|
||||
if (done)
|
||||
dma_cookie_complete(&desc->txd);
|
||||
|
||||
callback = desc->txd.callback;
|
||||
callback_param = desc->txd.callback_param;
|
||||
dmaengine_desc_get_callback(&desc->txd, &cb);
|
||||
|
||||
spin_unlock(&ichan->lock);
|
||||
|
||||
if (done && (desc->txd.flags & DMA_PREP_INTERRUPT) && callback)
|
||||
callback(callback_param);
|
||||
if (done && (desc->txd.flags & DMA_PREP_INTERRUPT))
|
||||
dmaengine_desc_callback_invoke(&cb, NULL);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -104,10 +104,8 @@ static void mic_dma_cleanup(struct mic_dma_chan *ch)
|
||||
tx = &ch->tx_array[last_tail];
|
||||
if (tx->cookie) {
|
||||
dma_cookie_complete(tx);
|
||||
if (tx->callback) {
|
||||
tx->callback(tx->callback_param);
|
||||
tx->callback = NULL;
|
||||
}
|
||||
dmaengine_desc_get_callback_invoke(tx, NULL);
|
||||
tx->callback = NULL;
|
||||
}
|
||||
last_tail = mic_dma_hw_ring_inc(last_tail);
|
||||
}
|
||||
|
||||
@@ -864,19 +864,15 @@ static void dma_do_tasklet(unsigned long data)
|
||||
struct mmp_pdma_desc_sw *desc, *_desc;
|
||||
LIST_HEAD(chain_cleanup);
|
||||
unsigned long flags;
|
||||
struct dmaengine_desc_callback cb;
|
||||
|
||||
if (chan->cyclic_first) {
|
||||
dma_async_tx_callback cb = NULL;
|
||||
void *cb_data = NULL;
|
||||
|
||||
spin_lock_irqsave(&chan->desc_lock, flags);
|
||||
desc = chan->cyclic_first;
|
||||
cb = desc->async_tx.callback;
|
||||
cb_data = desc->async_tx.callback_param;
|
||||
dmaengine_desc_get_callback(&desc->async_tx, &cb);
|
||||
spin_unlock_irqrestore(&chan->desc_lock, flags);
|
||||
|
||||
if (cb)
|
||||
cb(cb_data);
|
||||
dmaengine_desc_callback_invoke(&cb, NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -921,8 +917,8 @@ static void dma_do_tasklet(unsigned long data)
|
||||
/* Remove from the list of transactions */
|
||||
list_del(&desc->node);
|
||||
/* Run the link descriptor callback function */
|
||||
if (txd->callback)
|
||||
txd->callback(txd->callback_param);
|
||||
dmaengine_desc_get_callback(txd, &cb);
|
||||
dmaengine_desc_callback_invoke(&cb, NULL);
|
||||
|
||||
dma_pool_free(chan->desc_pool, desc, txd->phys);
|
||||
}
|
||||
|
||||
@@ -349,9 +349,7 @@ static void dma_do_tasklet(unsigned long data)
|
||||
{
|
||||
struct mmp_tdma_chan *tdmac = (struct mmp_tdma_chan *)data;
|
||||
|
||||
if (tdmac->desc.callback)
|
||||
tdmac->desc.callback(tdmac->desc.callback_param);
|
||||
|
||||
dmaengine_desc_get_callback_invoke(&tdmac->desc, NULL);
|
||||
}
|
||||
|
||||
static void mmp_tdma_free_descriptor(struct mmp_tdma_chan *tdmac)
|
||||
|
||||
@@ -411,8 +411,7 @@ static void mpc_dma_process_completed(struct mpc_dma *mdma)
|
||||
list_for_each_entry(mdesc, &list, node) {
|
||||
desc = &mdesc->desc;
|
||||
|
||||
if (desc->callback)
|
||||
desc->callback(desc->callback_param);
|
||||
dmaengine_desc_get_callback_invoke(desc, NULL);
|
||||
|
||||
last_cookie = desc->cookie;
|
||||
dma_run_dependencies(desc);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user