Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c39a75b0 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "qcom-sps-dma: Avoid re-allocation of pre-allocated resources"

parents 2e33a42b d23fd79a
Loading
Loading
Loading
Loading
+30 −9
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#define QBAM_OF_MANAGE_LOCAL	"qcom,managed-locally"
#define QBAM_OF_SUM_THRESHOLD	"qcom,summing-threshold"
#define QBAM_MAX_DESCRIPTORS	(0x100)
#define QBAM_MAX_CHANNELS	(32)

/*
 * qbam_xfer_buf - a single buffer transfer.
@@ -74,6 +75,7 @@ struct qbam_async_tx_descriptor {
#define DMA_TO_QBAM_ASYNC_DESC(dma_async_desc) \
	container_of(dma_async_desc, struct qbam_async_tx_descriptor, dma_desc)

struct qbam_channel;
/*
 * qbam_device - top level device of current driver
 * @handle bam sps handle.
@@ -84,6 +86,8 @@ struct qbam_async_tx_descriptor {
 * @manage is bame managed locally or remotely,
 * @summing_threshold event threshold.
 * @irq bam interrupt line.
 * @channels has the same channels as qbam_dev->dma_dev.channels but
 *   supports fast access by pipe index.
 */
struct qbam_device {
	struct dma_device		dma_dev;
@@ -94,6 +98,7 @@ struct qbam_device {
	u32				summing_threshold;
	u32				manage;
	int				irq;
	struct qbam_channel		*channels[QBAM_MAX_CHANNELS];
};

/* qbam_pipe: aggregate of bam pipe related entries of qbam_channel */
@@ -161,24 +166,20 @@ static void qbam_free_chan(struct dma_chan *chan)
{
	struct qbam_channel *qbam_chan = DMA_TO_QBAM_CHAN(chan);
	struct qbam_device  *qbam_dev  = qbam_chan->qbam_dev;
	struct sps_connect  *pipe_cfg  = &qbam_chan->bam_pipe.cfg;


	mutex_lock(&qbam_chan->lock);
	if (qbam_disconnect_chan(qbam_chan))
		qbam_err(qbam_dev,
			"error free_chan() faild to disconnect(pipe:%d)\n",
			qbam_chan->bam_pipe.index);

	dma_free_coherent(qbam_dev->dma_dev.dev, pipe_cfg->desc.size,
			 pipe_cfg->desc.base, pipe_cfg->desc.phys_base);

	if (qbam_chan->pending_desc) {
		kfree(qbam_chan->pending_desc->xfer_bufs);
		kfree(qbam_chan->pending_desc);
		qbam_chan->pending_desc = NULL;
	}

	sps_free_endpoint(qbam_chan->bam_pipe.handle);
	qbam_chan->bam_pipe.handle = NULL;
	mutex_unlock(&qbam_chan->lock);
}

static struct dma_chan *qbam_dma_xlate(struct of_phandle_args *dma_spec,
@@ -198,6 +199,19 @@ static struct dma_chan *qbam_dma_xlate(struct of_phandle_args *dma_spec,

	channel_index = dma_spec->args[0];

	if (channel_index >= QBAM_MAX_CHANNELS) {
		qbam_err(qbam_dev,
			"error: channel_index:%d out of bounds",
			channel_index);
		return NULL;
	}
	qbam_chan = qbam_dev->channels[channel_index];
	 /* return qbam_chan if exists, or create one */
	if (qbam_chan) {
		qbam_chan->chan.client_count = 1;
		return &qbam_chan->chan;
	}

	num_descriptors = dma_spec->args[1];
	if (!num_descriptors || (num_descriptors > QBAM_MAX_DESCRIPTORS)) {
		qbam_err(qbam_dev,
@@ -236,6 +250,7 @@ static struct dma_chan *qbam_dma_xlate(struct of_phandle_args *dma_spec,

	/* add to dma_device list of channels */
	list_add(&qbam_chan->chan.device_node, &qbam_dev->dma_dev.channels);
	qbam_dev->channels[channel_index] = qbam_chan;

	return &qbam_chan->chan;
}
@@ -417,6 +432,9 @@ static int qbam_slave_cfg(struct qbam_channel *qbam_chan,
			return ret;
	}

	if (qbam_chan->bam_pipe.cfg.desc.base)
		goto cfg_done;

	ret = sps_get_config(qbam_chan->bam_pipe.handle,
						&qbam_chan->bam_pipe.cfg);
	if (ret) {
@@ -454,10 +472,10 @@ static int qbam_slave_cfg(struct qbam_channel *qbam_chan,
			qbam_chan->bam_pipe.num_descriptors);
		return -ENOMEM;
	}

cfg_done:
	ret = qbam_connect_chan(qbam_chan);
	if (ret)
		dma_free_coherent(qbam_dev->dma_dev.dev, pipe_cfg->desc.size,
		dmam_free_coherent(qbam_dev->dma_dev.dev, pipe_cfg->desc.size,
				 pipe_cfg->desc.base, pipe_cfg->desc.phys_base);

	return ret;
@@ -663,8 +681,11 @@ static void qbam_pipes_free(struct qbam_device *qbam_dev)

	list_for_each_entry_safe(qbam_chan_cur, qbam_chan_next,
			&qbam_dev->dma_dev.channels, chan.device_node) {
		mutex_lock(&qbam_chan_cur->lock);
		qbam_free_chan(&qbam_chan_cur->chan);
		sps_free_endpoint(qbam_chan_cur->bam_pipe.handle);
		list_del(&qbam_chan_cur->chan.device_node);
		mutex_unlock(&qbam_chan_cur->lock);
		kfree(qbam_chan_cur);
	}
}