mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
Merge branch 'fixes' into next
This brings in the rz-dmac fixes which are in fixes
This commit is contained in:
@@ -954,6 +954,7 @@ static int dw_edma_irq_request(struct dw_edma *dw,
|
||||
{
|
||||
struct dw_edma_chip *chip = dw->chip;
|
||||
struct device *dev = dw->chip->dev;
|
||||
struct msi_desc *msi_desc;
|
||||
u32 wr_mask = 1;
|
||||
u32 rd_mask = 1;
|
||||
int i, err = 0;
|
||||
@@ -1005,9 +1006,12 @@ static int dw_edma_irq_request(struct dw_edma *dw,
|
||||
&dw->irq[i]);
|
||||
if (err)
|
||||
goto err_irq_free;
|
||||
|
||||
if (irq_get_msi_desc(irq))
|
||||
msi_desc = irq_get_msi_desc(irq);
|
||||
if (msi_desc) {
|
||||
get_cached_msi_msg(irq, &dw->irq[i].msi);
|
||||
if (!msi_desc->pci.msi_attrib.is_msix)
|
||||
dw->irq[i].msi.data = dw->irq[0].msi.data + i;
|
||||
}
|
||||
}
|
||||
|
||||
dw->nr_irqs = i;
|
||||
|
||||
@@ -252,10 +252,10 @@ static void dw_hdma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
|
||||
lower_32_bits(chunk->ll_region.paddr));
|
||||
SET_CH_32(dw, chan->dir, chan->id, llp.msb,
|
||||
upper_32_bits(chunk->ll_region.paddr));
|
||||
/* Set consumer cycle */
|
||||
SET_CH_32(dw, chan->dir, chan->id, cycle_sync,
|
||||
HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT);
|
||||
}
|
||||
/* Set consumer cycle */
|
||||
SET_CH_32(dw, chan->dir, chan->id, cycle_sync,
|
||||
HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT);
|
||||
|
||||
dw_hdma_v0_sync_ll_data(chunk);
|
||||
|
||||
|
||||
@@ -317,10 +317,8 @@ static struct dma_chan *fsl_edma3_xlate(struct of_phandle_args *dma_spec,
|
||||
return NULL;
|
||||
i = fsl_chan - fsl_edma->chans;
|
||||
|
||||
fsl_chan->priority = dma_spec->args[1];
|
||||
fsl_chan->is_rxchan = dma_spec->args[2] & FSL_EDMA_RX;
|
||||
fsl_chan->is_remote = dma_spec->args[2] & FSL_EDMA_REMOTE;
|
||||
fsl_chan->is_multi_fifo = dma_spec->args[2] & FSL_EDMA_MULTI_FIFO;
|
||||
if (!b_chmux && i != dma_spec->args[0])
|
||||
continue;
|
||||
|
||||
if ((dma_spec->args[2] & FSL_EDMA_EVEN_CH) && (i & 0x1))
|
||||
continue;
|
||||
@@ -328,17 +326,15 @@ static struct dma_chan *fsl_edma3_xlate(struct of_phandle_args *dma_spec,
|
||||
if ((dma_spec->args[2] & FSL_EDMA_ODD_CH) && !(i & 0x1))
|
||||
continue;
|
||||
|
||||
if (!b_chmux && i == dma_spec->args[0]) {
|
||||
chan = dma_get_slave_channel(chan);
|
||||
chan->device->privatecnt++;
|
||||
return chan;
|
||||
} else if (b_chmux && !fsl_chan->srcid) {
|
||||
/* if controller support channel mux, choose a free channel */
|
||||
chan = dma_get_slave_channel(chan);
|
||||
chan->device->privatecnt++;
|
||||
fsl_chan->srcid = dma_spec->args[0];
|
||||
return chan;
|
||||
}
|
||||
fsl_chan->srcid = dma_spec->args[0];
|
||||
fsl_chan->priority = dma_spec->args[1];
|
||||
fsl_chan->is_rxchan = dma_spec->args[2] & FSL_EDMA_RX;
|
||||
fsl_chan->is_remote = dma_spec->args[2] & FSL_EDMA_REMOTE;
|
||||
fsl_chan->is_multi_fifo = dma_spec->args[2] & FSL_EDMA_MULTI_FIFO;
|
||||
|
||||
chan = dma_get_slave_channel(chan);
|
||||
chan->device->privatecnt++;
|
||||
return chan;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -158,11 +158,7 @@ static const struct device_type idxd_cdev_file_type = {
|
||||
static void idxd_cdev_dev_release(struct device *dev)
|
||||
{
|
||||
struct idxd_cdev *idxd_cdev = dev_to_cdev(dev);
|
||||
struct idxd_cdev_context *cdev_ctx;
|
||||
struct idxd_wq *wq = idxd_cdev->wq;
|
||||
|
||||
cdev_ctx = &ictx[wq->idxd->data->type];
|
||||
ida_free(&cdev_ctx->minor_ida, idxd_cdev->minor);
|
||||
kfree(idxd_cdev);
|
||||
}
|
||||
|
||||
@@ -582,11 +578,15 @@ int idxd_wq_add_cdev(struct idxd_wq *wq)
|
||||
|
||||
void idxd_wq_del_cdev(struct idxd_wq *wq)
|
||||
{
|
||||
struct idxd_cdev_context *cdev_ctx;
|
||||
struct idxd_cdev *idxd_cdev;
|
||||
|
||||
idxd_cdev = wq->idxd_cdev;
|
||||
wq->idxd_cdev = NULL;
|
||||
cdev_device_del(&idxd_cdev->cdev, cdev_dev(idxd_cdev));
|
||||
|
||||
cdev_ctx = &ictx[wq->idxd->data->type];
|
||||
ida_free(&cdev_ctx->minor_ida, idxd_cdev->minor);
|
||||
put_device(cdev_dev(idxd_cdev));
|
||||
}
|
||||
|
||||
|
||||
@@ -175,6 +175,7 @@ void idxd_wq_free_resources(struct idxd_wq *wq)
|
||||
free_descs(wq);
|
||||
dma_free_coherent(dev, wq->compls_size, wq->compls, wq->compls_addr);
|
||||
sbitmap_queue_free(&wq->sbq);
|
||||
wq->type = IDXD_WQT_NONE;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(idxd_wq_free_resources, "IDXD");
|
||||
|
||||
@@ -382,7 +383,6 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq)
|
||||
lockdep_assert_held(&wq->wq_lock);
|
||||
wq->state = IDXD_WQ_DISABLED;
|
||||
memset(wq->wqcfg, 0, idxd->wqcfg_size);
|
||||
wq->type = IDXD_WQT_NONE;
|
||||
wq->threshold = 0;
|
||||
wq->priority = 0;
|
||||
wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
|
||||
@@ -831,8 +831,7 @@ static void idxd_device_evl_free(struct idxd_device *idxd)
|
||||
struct device *dev = &idxd->pdev->dev;
|
||||
struct idxd_evl *evl = idxd->evl;
|
||||
|
||||
gencfg.bits = ioread32(idxd->reg_base + IDXD_GENCFG_OFFSET);
|
||||
if (!gencfg.evl_en)
|
||||
if (!evl)
|
||||
return;
|
||||
|
||||
mutex_lock(&evl->lock);
|
||||
@@ -1125,7 +1124,11 @@ int idxd_device_config(struct idxd_device *idxd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
lockdep_assert_held(&idxd->dev_lock);
|
||||
guard(spinlock)(&idxd->dev_lock);
|
||||
|
||||
if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
|
||||
return 0;
|
||||
|
||||
rc = idxd_wqs_setup(idxd);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
@@ -1332,6 +1335,11 @@ void idxd_wq_free_irq(struct idxd_wq *wq)
|
||||
|
||||
free_irq(ie->vector, ie);
|
||||
idxd_flush_pending_descs(ie);
|
||||
|
||||
/* The interrupt might have been already released by FLR */
|
||||
if (ie->int_handle == INVALID_INT_HANDLE)
|
||||
return;
|
||||
|
||||
if (idxd->request_int_handles)
|
||||
idxd_device_release_int_handle(idxd, ie->int_handle, IDXD_IRQ_MSIX);
|
||||
idxd_device_clear_perm_entry(idxd, ie);
|
||||
@@ -1340,6 +1348,23 @@ void idxd_wq_free_irq(struct idxd_wq *wq)
|
||||
ie->pasid = IOMMU_PASID_INVALID;
|
||||
}
|
||||
|
||||
void idxd_wq_flush_descs(struct idxd_wq *wq)
|
||||
{
|
||||
struct idxd_irq_entry *ie = &wq->ie;
|
||||
struct idxd_device *idxd = wq->idxd;
|
||||
|
||||
guard(mutex)(&wq->wq_lock);
|
||||
|
||||
if (wq->state != IDXD_WQ_ENABLED || wq->type != IDXD_WQT_KERNEL)
|
||||
return;
|
||||
|
||||
idxd_flush_pending_descs(ie);
|
||||
if (idxd->request_int_handles)
|
||||
idxd_device_release_int_handle(idxd, ie->int_handle, IDXD_IRQ_MSIX);
|
||||
idxd_device_clear_perm_entry(idxd, ie);
|
||||
ie->int_handle = INVALID_INT_HANDLE;
|
||||
}
|
||||
|
||||
int idxd_wq_request_irq(struct idxd_wq *wq)
|
||||
{
|
||||
struct idxd_device *idxd = wq->idxd;
|
||||
@@ -1454,11 +1479,7 @@ int idxd_drv_enable_wq(struct idxd_wq *wq)
|
||||
}
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
spin_lock(&idxd->dev_lock);
|
||||
if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
|
||||
rc = idxd_device_config(idxd);
|
||||
spin_unlock(&idxd->dev_lock);
|
||||
rc = idxd_device_config(idxd);
|
||||
if (rc < 0) {
|
||||
dev_dbg(dev, "Writing wq %d config failed: %d\n", wq->id, rc);
|
||||
goto err;
|
||||
@@ -1533,7 +1554,6 @@ void idxd_drv_disable_wq(struct idxd_wq *wq)
|
||||
idxd_wq_reset(wq);
|
||||
idxd_wq_free_resources(wq);
|
||||
percpu_ref_exit(&wq->wq_active);
|
||||
wq->type = IDXD_WQT_NONE;
|
||||
wq->client_count = 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(idxd_drv_disable_wq, "IDXD");
|
||||
@@ -1554,10 +1574,7 @@ int idxd_device_drv_probe(struct idxd_dev *idxd_dev)
|
||||
}
|
||||
|
||||
/* Device configuration */
|
||||
spin_lock(&idxd->dev_lock);
|
||||
if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
|
||||
rc = idxd_device_config(idxd);
|
||||
spin_unlock(&idxd->dev_lock);
|
||||
rc = idxd_device_config(idxd);
|
||||
if (rc < 0)
|
||||
return -ENXIO;
|
||||
|
||||
|
||||
@@ -194,6 +194,22 @@ static void idxd_dma_release(struct dma_device *device)
|
||||
kfree(idxd_dma);
|
||||
}
|
||||
|
||||
static int idxd_dma_terminate_all(struct dma_chan *c)
|
||||
{
|
||||
struct idxd_wq *wq = to_idxd_wq(c);
|
||||
|
||||
idxd_wq_flush_descs(wq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void idxd_dma_synchronize(struct dma_chan *c)
|
||||
{
|
||||
struct idxd_wq *wq = to_idxd_wq(c);
|
||||
|
||||
idxd_wq_drain(wq);
|
||||
}
|
||||
|
||||
int idxd_register_dma_device(struct idxd_device *idxd)
|
||||
{
|
||||
struct idxd_dma_dev *idxd_dma;
|
||||
@@ -224,6 +240,8 @@ int idxd_register_dma_device(struct idxd_device *idxd)
|
||||
dma->device_issue_pending = idxd_dma_issue_pending;
|
||||
dma->device_alloc_chan_resources = idxd_dma_alloc_chan_resources;
|
||||
dma->device_free_chan_resources = idxd_dma_free_chan_resources;
|
||||
dma->device_terminate_all = idxd_dma_terminate_all;
|
||||
dma->device_synchronize = idxd_dma_synchronize;
|
||||
|
||||
rc = dma_async_device_register(dma);
|
||||
if (rc < 0) {
|
||||
|
||||
@@ -803,6 +803,7 @@ void idxd_wq_quiesce(struct idxd_wq *wq);
|
||||
int idxd_wq_init_percpu_ref(struct idxd_wq *wq);
|
||||
void idxd_wq_free_irq(struct idxd_wq *wq);
|
||||
int idxd_wq_request_irq(struct idxd_wq *wq);
|
||||
void idxd_wq_flush_descs(struct idxd_wq *wq);
|
||||
|
||||
/* submission */
|
||||
int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc);
|
||||
|
||||
@@ -973,7 +973,8 @@ static void idxd_device_config_restore(struct idxd_device *idxd,
|
||||
|
||||
idxd->rdbuf_limit = idxd_saved->saved_idxd.rdbuf_limit;
|
||||
|
||||
idxd->evl->size = saved_evl->size;
|
||||
if (idxd->evl)
|
||||
idxd->evl->size = saved_evl->size;
|
||||
|
||||
for (i = 0; i < idxd->max_groups; i++) {
|
||||
struct idxd_group *saved_group, *group;
|
||||
@@ -1104,12 +1105,10 @@ static void idxd_reset_done(struct pci_dev *pdev)
|
||||
idxd_device_config_restore(idxd, idxd->idxd_saved);
|
||||
|
||||
/* Re-configure IDXD device if allowed. */
|
||||
if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) {
|
||||
rc = idxd_device_config(idxd);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "HALT: %s config fails\n", idxd_name);
|
||||
goto out;
|
||||
}
|
||||
rc = idxd_device_config(idxd);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "HALT: %s config fails\n", idxd_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Bind IDXD device to driver. */
|
||||
@@ -1147,6 +1146,7 @@ static void idxd_reset_done(struct pci_dev *pdev)
|
||||
}
|
||||
out:
|
||||
kfree(idxd->idxd_saved);
|
||||
idxd->idxd_saved = NULL;
|
||||
}
|
||||
|
||||
static const struct pci_error_handlers idxd_error_handler = {
|
||||
|
||||
@@ -397,6 +397,17 @@ static void idxd_device_flr(struct work_struct *work)
|
||||
dev_err(&idxd->pdev->dev, "FLR failed\n");
|
||||
}
|
||||
|
||||
static void idxd_wqs_flush_descs(struct idxd_device *idxd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < idxd->max_wqs; i++) {
|
||||
struct idxd_wq *wq = idxd->wqs[i];
|
||||
|
||||
idxd_wq_flush_descs(wq);
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t idxd_halt(struct idxd_device *idxd)
|
||||
{
|
||||
union gensts_reg gensts;
|
||||
@@ -415,6 +426,11 @@ static irqreturn_t idxd_halt(struct idxd_device *idxd)
|
||||
} else if (gensts.reset_type == IDXD_DEVICE_RESET_FLR) {
|
||||
idxd->state = IDXD_DEV_HALTED;
|
||||
idxd_mask_error_interrupts(idxd);
|
||||
/* Flush all pending descriptors, and disable
|
||||
* interrupts, they will be re-enabled when FLR
|
||||
* concludes.
|
||||
*/
|
||||
idxd_wqs_flush_descs(idxd);
|
||||
dev_dbg(&idxd->pdev->dev,
|
||||
"idxd halted, doing FLR. After FLR, configs are restored\n");
|
||||
INIT_WORK(&idxd->work, idxd_device_flr);
|
||||
|
||||
@@ -138,7 +138,7 @@ static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie,
|
||||
*/
|
||||
list_for_each_entry_safe(d, t, &flist, list) {
|
||||
list_del_init(&d->list);
|
||||
idxd_dma_complete_txd(found, IDXD_COMPLETE_ABORT, true,
|
||||
idxd_dma_complete_txd(d, IDXD_COMPLETE_ABORT, true,
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1836,6 +1836,7 @@ static void idxd_conf_device_release(struct device *dev)
|
||||
{
|
||||
struct idxd_device *idxd = confdev_to_idxd(dev);
|
||||
|
||||
destroy_workqueue(idxd->wq);
|
||||
kfree(idxd->groups);
|
||||
bitmap_free(idxd->wq_enable_map);
|
||||
kfree(idxd->wqs);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/interrupt.h>
|
||||
@@ -302,13 +303,10 @@ static void rz_dmac_disable_hw(struct rz_dmac_chan *channel)
|
||||
{
|
||||
struct dma_chan *chan = &channel->vc.chan;
|
||||
struct rz_dmac *dmac = to_rz_dmac(chan->device);
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(dmac->dev, "%s channel %d\n", __func__, channel->index);
|
||||
|
||||
local_irq_save(flags);
|
||||
rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void rz_dmac_set_dmars_register(struct rz_dmac *dmac, int nr, u32 dmars)
|
||||
@@ -452,6 +450,7 @@ static int rz_dmac_alloc_chan_resources(struct dma_chan *chan)
|
||||
if (!desc)
|
||||
break;
|
||||
|
||||
/* No need to lock. This is called only for the 1st client. */
|
||||
list_add_tail(&desc->node, &channel->ld_free);
|
||||
channel->descs_allocated++;
|
||||
}
|
||||
@@ -507,18 +506,21 @@ rz_dmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
|
||||
dev_dbg(dmac->dev, "%s channel: %d src=0x%pad dst=0x%pad len=%zu\n",
|
||||
__func__, channel->index, &src, &dest, len);
|
||||
|
||||
if (list_empty(&channel->ld_free))
|
||||
return NULL;
|
||||
scoped_guard(spinlock_irqsave, &channel->vc.lock) {
|
||||
if (list_empty(&channel->ld_free))
|
||||
return NULL;
|
||||
|
||||
desc = list_first_entry(&channel->ld_free, struct rz_dmac_desc, node);
|
||||
desc = list_first_entry(&channel->ld_free, struct rz_dmac_desc, node);
|
||||
|
||||
desc->type = RZ_DMAC_DESC_MEMCPY;
|
||||
desc->src = src;
|
||||
desc->dest = dest;
|
||||
desc->len = len;
|
||||
desc->direction = DMA_MEM_TO_MEM;
|
||||
desc->type = RZ_DMAC_DESC_MEMCPY;
|
||||
desc->src = src;
|
||||
desc->dest = dest;
|
||||
desc->len = len;
|
||||
desc->direction = DMA_MEM_TO_MEM;
|
||||
|
||||
list_move_tail(channel->ld_free.next, &channel->ld_queue);
|
||||
}
|
||||
|
||||
list_move_tail(channel->ld_free.next, &channel->ld_queue);
|
||||
return vchan_tx_prep(&channel->vc, &desc->vd, flags);
|
||||
}
|
||||
|
||||
@@ -534,27 +536,29 @@ rz_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
||||
int dma_length = 0;
|
||||
int i = 0;
|
||||
|
||||
if (list_empty(&channel->ld_free))
|
||||
return NULL;
|
||||
scoped_guard(spinlock_irqsave, &channel->vc.lock) {
|
||||
if (list_empty(&channel->ld_free))
|
||||
return NULL;
|
||||
|
||||
desc = list_first_entry(&channel->ld_free, struct rz_dmac_desc, node);
|
||||
desc = list_first_entry(&channel->ld_free, struct rz_dmac_desc, node);
|
||||
|
||||
for_each_sg(sgl, sg, sg_len, i) {
|
||||
dma_length += sg_dma_len(sg);
|
||||
for_each_sg(sgl, sg, sg_len, i)
|
||||
dma_length += sg_dma_len(sg);
|
||||
|
||||
desc->type = RZ_DMAC_DESC_SLAVE_SG;
|
||||
desc->sg = sgl;
|
||||
desc->sgcount = sg_len;
|
||||
desc->len = dma_length;
|
||||
desc->direction = direction;
|
||||
|
||||
if (direction == DMA_DEV_TO_MEM)
|
||||
desc->src = channel->src_per_address;
|
||||
else
|
||||
desc->dest = channel->dst_per_address;
|
||||
|
||||
list_move_tail(channel->ld_free.next, &channel->ld_queue);
|
||||
}
|
||||
|
||||
desc->type = RZ_DMAC_DESC_SLAVE_SG;
|
||||
desc->sg = sgl;
|
||||
desc->sgcount = sg_len;
|
||||
desc->len = dma_length;
|
||||
desc->direction = direction;
|
||||
|
||||
if (direction == DMA_DEV_TO_MEM)
|
||||
desc->src = channel->src_per_address;
|
||||
else
|
||||
desc->dest = channel->dst_per_address;
|
||||
|
||||
list_move_tail(channel->ld_free.next, &channel->ld_queue);
|
||||
return vchan_tx_prep(&channel->vc, &desc->vd, flags);
|
||||
}
|
||||
|
||||
@@ -566,8 +570,8 @@ static int rz_dmac_terminate_all(struct dma_chan *chan)
|
||||
unsigned int i;
|
||||
LIST_HEAD(head);
|
||||
|
||||
rz_dmac_disable_hw(channel);
|
||||
spin_lock_irqsave(&channel->vc.lock, flags);
|
||||
rz_dmac_disable_hw(channel);
|
||||
for (i = 0; i < DMAC_NR_LMDESC; i++)
|
||||
lmdesc[i].header = 0;
|
||||
|
||||
@@ -698,7 +702,9 @@ static void rz_dmac_irq_handle_channel(struct rz_dmac_chan *channel)
|
||||
if (chstat & CHSTAT_ER) {
|
||||
dev_err(dmac->dev, "DMAC err CHSTAT_%d = %08X\n",
|
||||
channel->index, chstat);
|
||||
rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1);
|
||||
|
||||
scoped_guard(spinlock_irqsave, &channel->vc.lock)
|
||||
rz_dmac_ch_writel(channel, CHCTRL_DEFAULT, CHCTRL, 1);
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
@@ -1236,8 +1236,8 @@ static int xdma_probe(struct platform_device *pdev)
|
||||
|
||||
xdev->rmap = devm_regmap_init_mmio(&pdev->dev, reg_base,
|
||||
&xdma_regmap_config);
|
||||
if (!xdev->rmap) {
|
||||
xdma_err(xdev, "config regmap failed: %d", ret);
|
||||
if (IS_ERR(xdev->rmap)) {
|
||||
xdma_err(xdev, "config regmap failed: %pe", xdev->rmap);
|
||||
goto failed;
|
||||
}
|
||||
INIT_LIST_HEAD(&xdev->dma_dev.channels);
|
||||
|
||||
Reference in New Issue
Block a user