dmaengine fixes for v6.1
Driver fixes for: - Pile of at_hdmac driver rework which fixes many long standing issues for this driver. - couple of stm32 driver fixes for clearing structure and race fix - idxd fixes for RO device state and batch size - ti driver mem leak fix - apple fix for grabbing channels in xlate - resource leak fix in mv xor -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+vs47OPLdNbVcHzyfBQHDyUjg0cFAmNt7eYACgkQfBQHDyUj g0dx3A/+NiVgApGZO1nvRCOFeBXSggZIzPYSDqS/ZqaYai63MoIB/em6CR36cYNm xztCv/5MfpH8xcztoDBA4TwxcKzHo6/QxvHli3T+gMa0Imz/JSr8wxz2wfMnJStL dcdCTQTRtUhdh8rlxAcGD4gWdhoZTrVoNSGQK3MgQC7GrcCET5K6hZB8JWOg9nd+ gxpZu5a4DirWAWW/MFdtfhfHjff4SDhLpRi+kWknA8UHQb9jlsidqvVjRQNWAy4u QGhM4dxXsO+vSFxHcRZoxQjMQHoJ9v65Jh6cvADDpwa3/BbKFnljpCDA775hK2aL SLqdUXtV9KeGpMVs6D8tradc2MqFgs+UfbNApZM+NY7UPpV0fQZh4wF8SQcS3lAq 1SIz5myxp1XLuac+TFR/nSlisdtEB/eVFcJKibJpc+RrEBZKIG0XzcBjTI1TrFz5 7p//84SE2EKd7MGKVUGZ1gWRG46VYGTsvQQpZ1YDaXdd9JKBl6jzgAPEoLIPEUC/ Pg60TIDXzM0pNtQUDIp6g4LPf6Q88poL8WxejsN2OS0Kxy+isYsY6S8GZIQB39Tw 9Q0JuN0AkQv+wSx5GGbVEaosZhoR/Vk8DJiq22H9joTUSVjrMGFlT+/Kw3X+H6gF Pi3GcqIJeUbN+UPOMekR+UXS1U36/cB1Dh/ksLyEt3vAbm3U2NQ= =UR0f -----END PGP SIGNATURE----- Merge tag 'dmaengine-fix-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine Pull dmaengine fixes from Vinod Koul: "Misc minor driver fixes and a big pile of at_hdmac driver fixes. More work on this driver is done and sitting in next: - Pile of at_hdmac driver rework which fixes many long standing issues for this driver. - couple of stm32 driver fixes for clearing structure and race fix - idxd fixes for RO device state and batch size - ti driver mem leak fix - apple fix for grabbing channels in xlate - resource leak fix in mv xor" * tag 'dmaengine-fix-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (24 commits) dmaengine: at_hdmac: Check return code of dma_async_device_register dmaengine: at_hdmac: Fix impossible condition dmaengine: at_hdmac: Don't allow CPU to reorder channel enable dmaengine: at_hdmac: Fix completion of unissued descriptor in case of errors dmaengine: at_hdmac: Fix descriptor handling when issuing it to hardware dmaengine: at_hdmac: Fix concurrency over the active list dmaengine: at_hdmac: Free the memset buf without holding the chan lock dmaengine: at_hdmac: Fix concurrency over descriptor dmaengine: at_hdmac: Fix concurrency problems by removing atc_complete_all() dmaengine: at_hdmac: Protect atchan->status with the channel lock dmaengine: at_hdmac: Do not call the complete callback on device_terminate_all dmaengine: at_hdmac: Fix premature completion of desc in issue_pending dmaengine: at_hdmac: Start transfer for cyclic channels in issue_pending dmaengine: at_hdmac: Don't start transactions at tx_submit level dmaengine: at_hdmac: Fix at_lli struct definition dmaengine: stm32-dma: fix potential race between pause and resume dmaengine: ti: k3-udma-glue: fix memory leak when register device fail dmaengine: mv_xor_v2: Fix a resource leak in mv_xor_v2_remove() dmaengine: apple-admac: Fix grabbing of channels in of_xlate dmaengine: idxd: fix RO device state error after been disabled/reset ...
This commit is contained in:
Коммит
91c77a6ec4
|
@ -493,7 +493,7 @@ static struct dma_chan *admac_dma_of_xlate(struct of_phandle_args *dma_spec,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return &ad->channels[index].chan;
|
||||
return dma_get_slave_channel(&ad->channels[index].chan);
|
||||
}
|
||||
|
||||
static int admac_drain_reports(struct admac_data *ad, int channo)
|
||||
|
|
|
@ -256,6 +256,8 @@ static void atc_dostart(struct at_dma_chan *atchan, struct at_desc *first)
|
|||
ATC_SPIP_BOUNDARY(first->boundary));
|
||||
channel_writel(atchan, DPIP, ATC_DPIP_HOLE(first->dst_hole) |
|
||||
ATC_DPIP_BOUNDARY(first->boundary));
|
||||
/* Don't allow CPU to reorder channel enable. */
|
||||
wmb();
|
||||
dma_writel(atdma, CHER, atchan->mask);
|
||||
|
||||
vdbg_dump_regs(atchan);
|
||||
|
@ -316,7 +318,8 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie)
|
|||
struct at_desc *desc_first = atc_first_active(atchan);
|
||||
struct at_desc *desc;
|
||||
int ret;
|
||||
u32 ctrla, dscr, trials;
|
||||
u32 ctrla, dscr;
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* If the cookie doesn't match to the currently running transfer then
|
||||
|
@ -386,7 +389,7 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie)
|
|||
dscr = channel_readl(atchan, DSCR);
|
||||
rmb(); /* ensure DSCR is read before CTRLA */
|
||||
ctrla = channel_readl(atchan, CTRLA);
|
||||
for (trials = 0; trials < ATC_MAX_DSCR_TRIALS; ++trials) {
|
||||
for (i = 0; i < ATC_MAX_DSCR_TRIALS; ++i) {
|
||||
u32 new_dscr;
|
||||
|
||||
rmb(); /* ensure DSCR is read after CTRLA */
|
||||
|
@ -412,7 +415,7 @@ static int atc_get_bytes_left(struct dma_chan *chan, dma_cookie_t cookie)
|
|||
rmb(); /* ensure DSCR is read before CTRLA */
|
||||
ctrla = channel_readl(atchan, CTRLA);
|
||||
}
|
||||
if (unlikely(trials >= ATC_MAX_DSCR_TRIALS))
|
||||
if (unlikely(i == ATC_MAX_DSCR_TRIALS))
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* for the first descriptor we can be more accurate */
|
||||
|
@ -462,18 +465,6 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
|
|||
if (!atc_chan_is_cyclic(atchan))
|
||||
dma_cookie_complete(txd);
|
||||
|
||||
/* If the transfer was a memset, free our temporary buffer */
|
||||
if (desc->memset_buffer) {
|
||||
dma_pool_free(atdma->memset_pool, desc->memset_vaddr,
|
||||
desc->memset_paddr);
|
||||
desc->memset_buffer = false;
|
||||
}
|
||||
|
||||
/* move children to free_list */
|
||||
list_splice_init(&desc->tx_list, &atchan->free_list);
|
||||
/* move myself to free_list */
|
||||
list_move(&desc->desc_node, &atchan->free_list);
|
||||
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
|
||||
dma_descriptor_unmap(txd);
|
||||
|
@ -483,42 +474,20 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
|
|||
dmaengine_desc_get_callback_invoke(txd, NULL);
|
||||
|
||||
dma_run_dependencies(txd);
|
||||
}
|
||||
|
||||
/**
|
||||
* atc_complete_all - finish work for all transactions
|
||||
* @atchan: channel to complete transactions for
|
||||
*
|
||||
* Eventually submit queued descriptors if any
|
||||
*
|
||||
* Assume channel is idle while calling this function
|
||||
* Called with atchan->lock held and bh disabled
|
||||
*/
|
||||
static void atc_complete_all(struct at_dma_chan *atchan)
|
||||
{
|
||||
struct at_desc *desc, *_desc;
|
||||
LIST_HEAD(list);
|
||||
unsigned long flags;
|
||||
|
||||
dev_vdbg(chan2dev(&atchan->chan_common), "complete all\n");
|
||||
|
||||
spin_lock_irqsave(&atchan->lock, flags);
|
||||
|
||||
/*
|
||||
* Submit queued descriptors ASAP, i.e. before we go through
|
||||
* the completed ones.
|
||||
*/
|
||||
if (!list_empty(&atchan->queue))
|
||||
atc_dostart(atchan, atc_first_queued(atchan));
|
||||
/* empty active_list now it is completed */
|
||||
list_splice_init(&atchan->active_list, &list);
|
||||
/* empty queue list by moving descriptors (if any) to active_list */
|
||||
list_splice_init(&atchan->queue, &atchan->active_list);
|
||||
|
||||
/* move children to free_list */
|
||||
list_splice_init(&desc->tx_list, &atchan->free_list);
|
||||
/* add myself to free_list */
|
||||
list_add(&desc->desc_node, &atchan->free_list);
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
|
||||
list_for_each_entry_safe(desc, _desc, &list, desc_node)
|
||||
atc_chain_complete(atchan, desc);
|
||||
/* If the transfer was a memset, free our temporary buffer */
|
||||
if (desc->memset_buffer) {
|
||||
dma_pool_free(atdma->memset_pool, desc->memset_vaddr,
|
||||
desc->memset_paddr);
|
||||
desc->memset_buffer = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -527,26 +496,28 @@ static void atc_complete_all(struct at_dma_chan *atchan)
|
|||
*/
|
||||
static void atc_advance_work(struct at_dma_chan *atchan)
|
||||
{
|
||||
struct at_desc *desc;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
dev_vdbg(chan2dev(&atchan->chan_common), "advance_work\n");
|
||||
|
||||
spin_lock_irqsave(&atchan->lock, flags);
|
||||
ret = atc_chan_is_enabled(atchan);
|
||||
if (atc_chan_is_enabled(atchan) || list_empty(&atchan->active_list))
|
||||
return spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
|
||||
desc = atc_first_active(atchan);
|
||||
/* Remove the transfer node from the active list. */
|
||||
list_del_init(&desc->desc_node);
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
if (list_empty(&atchan->active_list) ||
|
||||
list_is_singular(&atchan->active_list))
|
||||
return atc_complete_all(atchan);
|
||||
|
||||
atc_chain_complete(atchan, atc_first_active(atchan));
|
||||
atc_chain_complete(atchan, desc);
|
||||
|
||||
/* advance work */
|
||||
spin_lock_irqsave(&atchan->lock, flags);
|
||||
atc_dostart(atchan, atc_first_active(atchan));
|
||||
if (!list_empty(&atchan->active_list)) {
|
||||
desc = atc_first_queued(atchan);
|
||||
list_move_tail(&desc->desc_node, &atchan->active_list);
|
||||
atc_dostart(atchan, desc);
|
||||
}
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
}
|
||||
|
||||
|
@ -558,6 +529,7 @@ static void atc_advance_work(struct at_dma_chan *atchan)
|
|||
static void atc_handle_error(struct at_dma_chan *atchan)
|
||||
{
|
||||
struct at_desc *bad_desc;
|
||||
struct at_desc *desc;
|
||||
struct at_desc *child;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -570,13 +542,12 @@ static void atc_handle_error(struct at_dma_chan *atchan)
|
|||
bad_desc = atc_first_active(atchan);
|
||||
list_del_init(&bad_desc->desc_node);
|
||||
|
||||
/* As we are stopped, take advantage to push queued descriptors
|
||||
* in active_list */
|
||||
list_splice_init(&atchan->queue, atchan->active_list.prev);
|
||||
|
||||
/* Try to restart the controller */
|
||||
if (!list_empty(&atchan->active_list))
|
||||
atc_dostart(atchan, atc_first_active(atchan));
|
||||
if (!list_empty(&atchan->active_list)) {
|
||||
desc = atc_first_queued(atchan);
|
||||
list_move_tail(&desc->desc_node, &atchan->active_list);
|
||||
atc_dostart(atchan, desc);
|
||||
}
|
||||
|
||||
/*
|
||||
* KERN_CRITICAL may seem harsh, but since this only happens
|
||||
|
@ -691,19 +662,11 @@ static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx)
|
|||
spin_lock_irqsave(&atchan->lock, flags);
|
||||
cookie = dma_cookie_assign(tx);
|
||||
|
||||
if (list_empty(&atchan->active_list)) {
|
||||
dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n",
|
||||
desc->txd.cookie);
|
||||
atc_dostart(atchan, desc);
|
||||
list_add_tail(&desc->desc_node, &atchan->active_list);
|
||||
} else {
|
||||
dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n",
|
||||
desc->txd.cookie);
|
||||
list_add_tail(&desc->desc_node, &atchan->queue);
|
||||
}
|
||||
|
||||
list_add_tail(&desc->desc_node, &atchan->queue);
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
|
||||
dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n",
|
||||
desc->txd.cookie);
|
||||
return cookie;
|
||||
}
|
||||
|
||||
|
@ -1445,11 +1408,8 @@ static int atc_terminate_all(struct dma_chan *chan)
|
|||
struct at_dma_chan *atchan = to_at_dma_chan(chan);
|
||||
struct at_dma *atdma = to_at_dma(chan->device);
|
||||
int chan_id = atchan->chan_common.chan_id;
|
||||
struct at_desc *desc, *_desc;
|
||||
unsigned long flags;
|
||||
|
||||
LIST_HEAD(list);
|
||||
|
||||
dev_vdbg(chan2dev(chan), "%s\n", __func__);
|
||||
|
||||
/*
|
||||
|
@ -1468,19 +1428,15 @@ static int atc_terminate_all(struct dma_chan *chan)
|
|||
cpu_relax();
|
||||
|
||||
/* active_list entries will end up before queued entries */
|
||||
list_splice_init(&atchan->queue, &list);
|
||||
list_splice_init(&atchan->active_list, &list);
|
||||
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
|
||||
/* Flush all pending and queued descriptors */
|
||||
list_for_each_entry_safe(desc, _desc, &list, desc_node)
|
||||
atc_chain_complete(atchan, desc);
|
||||
list_splice_tail_init(&atchan->queue, &atchan->free_list);
|
||||
list_splice_tail_init(&atchan->active_list, &atchan->free_list);
|
||||
|
||||
clear_bit(ATC_IS_PAUSED, &atchan->status);
|
||||
/* if channel dedicated to cyclic operations, free it */
|
||||
clear_bit(ATC_IS_CYCLIC, &atchan->status);
|
||||
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1535,20 +1491,26 @@ atc_tx_status(struct dma_chan *chan,
|
|||
}
|
||||
|
||||
/**
|
||||
* atc_issue_pending - try to finish work
|
||||
* atc_issue_pending - takes the first transaction descriptor in the pending
|
||||
* queue and starts the transfer.
|
||||
* @chan: target DMA channel
|
||||
*/
|
||||
static void atc_issue_pending(struct dma_chan *chan)
|
||||
{
|
||||
struct at_dma_chan *atchan = to_at_dma_chan(chan);
|
||||
struct at_dma_chan *atchan = to_at_dma_chan(chan);
|
||||
struct at_desc *desc;
|
||||
unsigned long flags;
|
||||
|
||||
dev_vdbg(chan2dev(chan), "issue_pending\n");
|
||||
|
||||
/* Not needed for cyclic transfers */
|
||||
if (atc_chan_is_cyclic(atchan))
|
||||
return;
|
||||
spin_lock_irqsave(&atchan->lock, flags);
|
||||
if (atc_chan_is_enabled(atchan) || list_empty(&atchan->queue))
|
||||
return spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
|
||||
atc_advance_work(atchan);
|
||||
desc = atc_first_queued(atchan);
|
||||
list_move_tail(&desc->desc_node, &atchan->active_list);
|
||||
atc_dostart(atchan, desc);
|
||||
spin_unlock_irqrestore(&atchan->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1966,7 +1928,11 @@ static int __init at_dma_probe(struct platform_device *pdev)
|
|||
dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask) ? "slave " : "",
|
||||
plat_dat->nr_channels);
|
||||
|
||||
dma_async_device_register(&atdma->dma_common);
|
||||
err = dma_async_device_register(&atdma->dma_common);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Unable to register: %d.\n", err);
|
||||
goto err_dma_async_device_register;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not return an error if the dmac node is not present in order to
|
||||
|
@ -1986,6 +1952,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
|
|||
|
||||
err_of_dma_controller_register:
|
||||
dma_async_device_unregister(&atdma->dma_common);
|
||||
err_dma_async_device_register:
|
||||
dma_pool_destroy(atdma->memset_pool);
|
||||
err_memset_pool_create:
|
||||
dma_pool_destroy(atdma->dma_desc_pool);
|
||||
|
|
|
@ -186,13 +186,13 @@
|
|||
/* LLI == Linked List Item; aka DMA buffer descriptor */
|
||||
struct at_lli {
|
||||
/* values that are not changed by hardware */
|
||||
dma_addr_t saddr;
|
||||
dma_addr_t daddr;
|
||||
u32 saddr;
|
||||
u32 daddr;
|
||||
/* value that may get written back: */
|
||||
u32 ctrla;
|
||||
u32 ctrla;
|
||||
/* more values that are not changed by hardware */
|
||||
u32 ctrlb;
|
||||
dma_addr_t dscr; /* chain to next lli */
|
||||
u32 ctrlb;
|
||||
u32 dscr; /* chain to next lli */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -312,6 +312,24 @@ static int idxd_user_drv_probe(struct idxd_dev *idxd_dev)
|
|||
if (idxd->state != IDXD_DEV_ENABLED)
|
||||
return -ENXIO;
|
||||
|
||||
/*
|
||||
* User type WQ is enabled only when SVA is enabled for two reasons:
|
||||
* - If no IOMMU or IOMMU Passthrough without SVA, userspace
|
||||
* can directly access physical address through the WQ.
|
||||
* - The IDXD cdev driver does not provide any ways to pin
|
||||
* user pages and translate the address from user VA to IOVA or
|
||||
* PA without IOMMU SVA. Therefore the application has no way
|
||||
* to instruct the device to perform DMA function. This makes
|
||||
* the cdev not usable for normal application usage.
|
||||
*/
|
||||
if (!device_user_pasid_enabled(idxd)) {
|
||||
idxd->cmd_status = IDXD_SCMD_WQ_USER_NO_IOMMU;
|
||||
dev_dbg(&idxd->pdev->dev,
|
||||
"User type WQ cannot be enabled without SVA.\n");
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_lock(&wq->wq_lock);
|
||||
wq->type = IDXD_WQT_USER;
|
||||
rc = drv_enable_wq(wq);
|
||||
|
|
|
@ -390,7 +390,7 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq)
|
|||
clear_bit(WQ_FLAG_ATS_DISABLE, &wq->flags);
|
||||
memset(wq->name, 0, WQ_NAME_SIZE);
|
||||
wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER;
|
||||
wq->max_batch_size = WQ_DEFAULT_MAX_BATCH;
|
||||
idxd_wq_set_max_batch_size(idxd->data->type, wq, WQ_DEFAULT_MAX_BATCH);
|
||||
if (wq->opcap_bmap)
|
||||
bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS);
|
||||
}
|
||||
|
@ -730,13 +730,21 @@ static void idxd_device_wqs_clear_state(struct idxd_device *idxd)
|
|||
|
||||
void idxd_device_clear_state(struct idxd_device *idxd)
|
||||
{
|
||||
if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
|
||||
return;
|
||||
/* IDXD is always disabled. Other states are cleared only when IDXD is configurable. */
|
||||
if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) {
|
||||
/*
|
||||
* Clearing wq state is protected by wq lock.
|
||||
* So no need to be protected by device lock.
|
||||
*/
|
||||
idxd_device_wqs_clear_state(idxd);
|
||||
|
||||
spin_lock(&idxd->dev_lock);
|
||||
idxd_groups_clear_state(idxd);
|
||||
idxd_engines_clear_state(idxd);
|
||||
} else {
|
||||
spin_lock(&idxd->dev_lock);
|
||||
}
|
||||
|
||||
idxd_device_wqs_clear_state(idxd);
|
||||
spin_lock(&idxd->dev_lock);
|
||||
idxd_groups_clear_state(idxd);
|
||||
idxd_engines_clear_state(idxd);
|
||||
idxd->state = IDXD_DEV_DISABLED;
|
||||
spin_unlock(&idxd->dev_lock);
|
||||
}
|
||||
|
@ -869,7 +877,7 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
|
|||
|
||||
/* bytes 12-15 */
|
||||
wq->wqcfg->max_xfer_shift = ilog2(wq->max_xfer_bytes);
|
||||
wq->wqcfg->max_batch_shift = ilog2(wq->max_batch_size);
|
||||
idxd_wqcfg_set_max_batch_shift(idxd->data->type, wq->wqcfg, ilog2(wq->max_batch_size));
|
||||
|
||||
/* bytes 32-63 */
|
||||
if (idxd->hw.wq_cap.op_config && wq->opcap_bmap) {
|
||||
|
@ -1051,7 +1059,7 @@ static int idxd_wq_load_config(struct idxd_wq *wq)
|
|||
wq->priority = wq->wqcfg->priority;
|
||||
|
||||
wq->max_xfer_bytes = 1ULL << wq->wqcfg->max_xfer_shift;
|
||||
wq->max_batch_size = 1ULL << wq->wqcfg->max_batch_shift;
|
||||
idxd_wq_set_max_batch_size(idxd->data->type, wq, 1U << wq->wqcfg->max_batch_shift);
|
||||
|
||||
for (i = 0; i < WQCFG_STRIDES(idxd); i++) {
|
||||
wqcfg_offset = WQCFG_OFFSET(idxd, wq->id, i);
|
||||
|
|
|
@ -548,6 +548,38 @@ static inline int idxd_wq_refcount(struct idxd_wq *wq)
|
|||
return wq->client_count;
|
||||
};
|
||||
|
||||
/*
|
||||
* Intel IAA does not support batch processing.
|
||||
* The max batch size of device, max batch size of wq and
|
||||
* max batch shift of wqcfg should be always 0 on IAA.
|
||||
*/
|
||||
static inline void idxd_set_max_batch_size(int idxd_type, struct idxd_device *idxd,
|
||||
u32 max_batch_size)
|
||||
{
|
||||
if (idxd_type == IDXD_TYPE_IAX)
|
||||
idxd->max_batch_size = 0;
|
||||
else
|
||||
idxd->max_batch_size = max_batch_size;
|
||||
}
|
||||
|
||||
static inline void idxd_wq_set_max_batch_size(int idxd_type, struct idxd_wq *wq,
|
||||
u32 max_batch_size)
|
||||
{
|
||||
if (idxd_type == IDXD_TYPE_IAX)
|
||||
wq->max_batch_size = 0;
|
||||
else
|
||||
wq->max_batch_size = max_batch_size;
|
||||
}
|
||||
|
||||
static inline void idxd_wqcfg_set_max_batch_shift(int idxd_type, union wqcfg *wqcfg,
|
||||
u32 max_batch_shift)
|
||||
{
|
||||
if (idxd_type == IDXD_TYPE_IAX)
|
||||
wqcfg->max_batch_shift = 0;
|
||||
else
|
||||
wqcfg->max_batch_shift = max_batch_shift;
|
||||
}
|
||||
|
||||
int __must_check __idxd_driver_register(struct idxd_device_driver *idxd_drv,
|
||||
struct module *module, const char *mod_name);
|
||||
#define idxd_driver_register(driver) \
|
||||
|
|
|
@ -183,7 +183,7 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
|
|||
init_completion(&wq->wq_dead);
|
||||
init_completion(&wq->wq_resurrect);
|
||||
wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER;
|
||||
wq->max_batch_size = WQ_DEFAULT_MAX_BATCH;
|
||||
idxd_wq_set_max_batch_size(idxd->data->type, wq, WQ_DEFAULT_MAX_BATCH);
|
||||
wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
|
||||
wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev));
|
||||
if (!wq->wqcfg) {
|
||||
|
@ -418,7 +418,7 @@ static void idxd_read_caps(struct idxd_device *idxd)
|
|||
|
||||
idxd->max_xfer_bytes = 1ULL << idxd->hw.gen_cap.max_xfer_shift;
|
||||
dev_dbg(dev, "max xfer size: %llu bytes\n", idxd->max_xfer_bytes);
|
||||
idxd->max_batch_size = 1U << idxd->hw.gen_cap.max_batch_shift;
|
||||
idxd_set_max_batch_size(idxd->data->type, idxd, 1U << idxd->hw.gen_cap.max_batch_shift);
|
||||
dev_dbg(dev, "max batch size: %u\n", idxd->max_batch_size);
|
||||
if (idxd->hw.gen_cap.config_en)
|
||||
set_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags);
|
||||
|
|
|
@ -1046,7 +1046,7 @@ static ssize_t wq_max_batch_size_store(struct device *dev, struct device_attribu
|
|||
if (batch_size > idxd->max_batch_size)
|
||||
return -EINVAL;
|
||||
|
||||
wq->max_batch_size = (u32)batch_size;
|
||||
idxd_wq_set_max_batch_size(idxd->data->type, wq, (u32)batch_size);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -893,6 +893,7 @@ static int mv_xor_v2_remove(struct platform_device *pdev)
|
|||
tasklet_kill(&xor_dev->irq_tasklet);
|
||||
|
||||
clk_disable_unprepare(xor_dev->clk);
|
||||
clk_disable_unprepare(xor_dev->reg_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1247,14 +1247,14 @@ static int pxad_init_phys(struct platform_device *op,
|
|||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < nb_phy_chans; i++)
|
||||
if (platform_get_irq(op, i) > 0)
|
||||
if (platform_get_irq_optional(op, i) > 0)
|
||||
nr_irq++;
|
||||
|
||||
for (i = 0; i < nb_phy_chans; i++) {
|
||||
phy = &pdev->phys[i];
|
||||
phy->base = pdev->base;
|
||||
phy->idx = i;
|
||||
irq = platform_get_irq(op, i);
|
||||
irq = platform_get_irq_optional(op, i);
|
||||
if ((nr_irq > 1) && (irq > 0))
|
||||
ret = devm_request_irq(&op->dev, irq,
|
||||
pxad_chan_handler,
|
||||
|
|
|
@ -675,6 +675,8 @@ static void stm32_dma_handle_chan_paused(struct stm32_dma_chan *chan)
|
|||
|
||||
chan->chan_reg.dma_sndtr = stm32_dma_read(dmadev, STM32_DMA_SNDTR(chan->id));
|
||||
|
||||
chan->status = DMA_PAUSED;
|
||||
|
||||
dev_dbg(chan2dev(chan), "vchan %pK: paused\n", &chan->vchan);
|
||||
}
|
||||
|
||||
|
@ -789,9 +791,7 @@ static irqreturn_t stm32_dma_chan_irq(int irq, void *devid)
|
|||
if (status & STM32_DMA_TCI) {
|
||||
stm32_dma_irq_clear(chan, STM32_DMA_TCI);
|
||||
if (scr & STM32_DMA_SCR_TCIE) {
|
||||
if (chan->status == DMA_PAUSED && !(scr & STM32_DMA_SCR_EN))
|
||||
stm32_dma_handle_chan_paused(chan);
|
||||
else
|
||||
if (chan->status != DMA_PAUSED)
|
||||
stm32_dma_handle_chan_done(chan, scr);
|
||||
}
|
||||
status &= ~STM32_DMA_TCI;
|
||||
|
@ -838,13 +838,11 @@ static int stm32_dma_pause(struct dma_chan *c)
|
|||
return -EPERM;
|
||||
|
||||
spin_lock_irqsave(&chan->vchan.lock, flags);
|
||||
|
||||
ret = stm32_dma_disable_chan(chan);
|
||||
/*
|
||||
* A transfer complete flag is set to indicate the end of transfer due to the stream
|
||||
* interruption, so wait for interrupt
|
||||
*/
|
||||
if (!ret)
|
||||
chan->status = DMA_PAUSED;
|
||||
stm32_dma_handle_chan_paused(chan);
|
||||
|
||||
spin_unlock_irqrestore(&chan->vchan.lock, flags);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -1539,6 +1539,7 @@ static struct dma_chan *stm32_mdma_of_xlate(struct of_phandle_args *dma_spec,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.request = dma_spec->args[0];
|
||||
config.priority_level = dma_spec->args[1];
|
||||
config.transfer_config = dma_spec->args[2];
|
||||
|
|
|
@ -299,6 +299,7 @@ struct k3_udma_glue_tx_channel *k3_udma_glue_request_tx_chn(struct device *dev,
|
|||
ret = device_register(&tx_chn->common.chan_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Channel Device registration failed %d\n", ret);
|
||||
put_device(&tx_chn->common.chan_dev);
|
||||
tx_chn->common.chan_dev.parent = NULL;
|
||||
goto err;
|
||||
}
|
||||
|
@ -917,6 +918,7 @@ k3_udma_glue_request_rx_chn_priv(struct device *dev, const char *name,
|
|||
ret = device_register(&rx_chn->common.chan_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Channel Device registration failed %d\n", ret);
|
||||
put_device(&rx_chn->common.chan_dev);
|
||||
rx_chn->common.chan_dev.parent = NULL;
|
||||
goto err;
|
||||
}
|
||||
|
@ -1048,6 +1050,7 @@ k3_udma_glue_request_remote_rx_chn(struct device *dev, const char *name,
|
|||
ret = device_register(&rx_chn->common.chan_dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Channel Device registration failed %d\n", ret);
|
||||
put_device(&rx_chn->common.chan_dev);
|
||||
rx_chn->common.chan_dev.parent = NULL;
|
||||
goto err;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ enum idxd_scmd_stat {
|
|||
IDXD_SCMD_WQ_NO_SIZE = 0x800e0000,
|
||||
IDXD_SCMD_WQ_NO_PRIV = 0x800f0000,
|
||||
IDXD_SCMD_WQ_IRQ_ERR = 0x80100000,
|
||||
IDXD_SCMD_WQ_USER_NO_IOMMU = 0x80110000,
|
||||
};
|
||||
|
||||
#define IDXD_SCMD_SOFTERR_MASK 0x80000000
|
||||
|
|
Загрузка…
Ссылка в новой задаче