in ti/k3-ringacc.c [768:869]
int k3_ringacc_ring_cfg(struct k3_ring *ring, struct k3_ring_cfg *cfg)
{
struct k3_ringacc *ringacc;
int ret = 0;
if (!ring || !cfg)
return -EINVAL;
ringacc = ring->parent;
if (ringacc->dma_rings)
return k3_dmaring_cfg(ring, cfg);
if (cfg->elm_size > K3_RINGACC_RING_ELSIZE_256 ||
cfg->mode >= K3_RINGACC_RING_MODE_INVALID ||
cfg->size & ~K3_RINGACC_CFG_RING_SIZE_ELCNT_MASK ||
!test_bit(ring->ring_id, ringacc->rings_inuse))
return -EINVAL;
if (cfg->mode == K3_RINGACC_RING_MODE_MESSAGE &&
ring->proxy_id == K3_RINGACC_PROXY_NOT_USED &&
cfg->elm_size > K3_RINGACC_RING_ELSIZE_8) {
dev_err(ringacc->dev,
"Message mode must use proxy for %u element size\n",
4 << ring->elm_size);
return -EINVAL;
}
/*
* In case of shared ring only the first user (master user) can
* configure the ring. The sequence should be by the client:
* ring = k3_ringacc_request_ring(ringacc, ring_id, 0); # master user
* k3_ringacc_ring_cfg(ring, cfg); # master configuration
* k3_ringacc_request_ring(ringacc, ring_id, K3_RING_FLAG_SHARED);
* k3_ringacc_request_ring(ringacc, ring_id, K3_RING_FLAG_SHARED);
*/
if (ring->use_count != 1)
return 0;
ring->size = cfg->size;
ring->elm_size = cfg->elm_size;
ring->mode = cfg->mode;
memset(&ring->state, 0, sizeof(ring->state));
if (ring->proxy_id != K3_RINGACC_PROXY_NOT_USED)
ring->proxy = ringacc->proxy_target_base +
ring->proxy_id * K3_RINGACC_PROXY_TARGET_STEP;
switch (ring->mode) {
case K3_RINGACC_RING_MODE_RING:
ring->ops = &k3_ring_mode_ring_ops;
ring->dma_dev = cfg->dma_dev;
if (!ring->dma_dev)
ring->dma_dev = ringacc->dev;
break;
case K3_RINGACC_RING_MODE_MESSAGE:
ring->dma_dev = ringacc->dev;
if (ring->proxy)
ring->ops = &k3_ring_mode_proxy_ops;
else
ring->ops = &k3_ring_mode_msg_ops;
break;
default:
ring->ops = NULL;
ret = -EINVAL;
goto err_free_proxy;
}
ring->ring_mem_virt = dma_alloc_coherent(ring->dma_dev,
ring->size * (4 << ring->elm_size),
&ring->ring_mem_dma, GFP_KERNEL);
if (!ring->ring_mem_virt) {
dev_err(ringacc->dev, "Failed to alloc ring mem\n");
ret = -ENOMEM;
goto err_free_ops;
}
ret = k3_ringacc_ring_cfg_sci(ring);
if (ret)
goto err_free_mem;
ring->flags |= K3_RING_FLAG_BUSY;
ring->flags |= (cfg->flags & K3_RINGACC_RING_SHARED) ?
K3_RING_FLAG_SHARED : 0;
k3_ringacc_ring_dump(ring);
return 0;
err_free_mem:
dma_free_coherent(ring->dma_dev,
ring->size * (4 << ring->elm_size),
ring->ring_mem_virt,
ring->ring_mem_dma);
err_free_ops:
ring->ops = NULL;
ring->dma_dev = NULL;
err_free_proxy:
ring->proxy = NULL;
return ret;
}