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

Commit 33476c9a authored by Gidon Studinski's avatar Gidon Studinski Committed by Alexei Avshalom Lazar
Browse files

wigig_sensing: enable data read in non-burst sizes



Data read over SPI was guaranteed to be in a full burst size. This change
enables FW to raise the Data Ready DRI earlier, before the full burst is
ready. The driver must handle the case where data size reported by the HW
is less than a full burst, and then execute another iteration until the
whole burst is read.

This change causes a performance optimization, since the FW can raise the
Data Ready DRI earlier. The whole burst data is usually in place when the
driver handles it.

Change-Id: I98966ec5c1ef614c3c145e99bb3327febe1ebe74
Signed-off-by: default avatarGidon Studinski <gidons@codeaurora.org>
Signed-off-by: default avatarAlexei Avshalom Lazar <ailizaro@codeaurora.org>
parent cec1c1c8
Loading
Loading
Loading
Loading
+87 −57
Original line number Diff line number Diff line
@@ -978,71 +978,32 @@ static int wigig_sensing_handle_fifo_ready_dri(struct wigig_sensing_ctx *ctx)
	return rc;
}

static int wigig_sensing_chip_data_ready(struct wigig_sensing_ctx *ctx,
					 u16 fill_level, u32 burst_size)
static int wigig_sensing_chip_data_ready_internal(struct wigig_sensing_ctx *ctx,
						  u16 fill_level, u32 *offset)
{
	int rc = 0;
	enum wigig_sensing_stm_e stm_state = ctx->stm.state;
	struct spi_fifo *spi_fifo = &ctx->spi_fifo;
	struct cir_data *d = &ctx->cir_data;
	struct circ_buf local;
	u32 bytes_to_read;
	u32 idx = 0;
	u32 spi_transaction_size;
	u32 available_space_to_end;
	u32 orig_head;

	if (stm_state == WIGIG_SENSING_STATE_INITIALIZED ||
	    stm_state == WIGIG_SENSING_STATE_READY_STOPPED ||
	    stm_state == WIGIG_SENSING_STATE_SYS_ASSERT) {
		pr_err("Received data ready interrupt in an unexpected stm_state, disregarding\n");
		return 0;
	}

	if (!ctx->cir_data.b.buf)
		return -EFAULT;

	/*
	 * Read data from FIFO over SPI
	 * Disregard the lowest 2 bits of fill_level as SPI can read in 32 bit
	 * units. Additionally, HW reports the fill_level as one more than
	 * there is actually (1 when the FIFO is empty)
	 * Make sure that fill_level is in 32 bit units
	 */
	if (fill_level == 0 || fill_level == 1) {
		pr_err("Wrong fill_level received\n");
		return -EFAULT;
	}
	fill_level = (fill_level - 1) & ~0x3;

	if (fill_level > burst_size) {
		pr_err("FIFO fill level too large, fill_level = %u, burst_size = %u\n",
		       fill_level, burst_size);
		return -EFAULT;
	}

	/*
	 * In case there is not enough space in the buffer, discard an old
	 * burst
	 */
	if (circ_space(&d->b, d->size_bytes) < fill_level) {
		mutex_lock(&d->lock);
		if (circ_space(&d->b, d->size_bytes) < fill_level) {
			pr_debug("Buffer full, dropping burst\n");
			d->b.tail = (d->b.tail + burst_size) &
				(d->size_bytes - 1);
			ctx->dropped_bursts++;
		}
		mutex_unlock(&d->lock);
	}
	fill_level = fill_level & ~0x3;

	spi_transaction_size =
		calc_spi_transaction_size(fill_level, SPI_MAX_TRANSACTION_SIZE);
	local = d->b;
	local.head = (local.head + *offset) & (d->size_bytes - 1);
	orig_head = local.head;
	mutex_lock(&ctx->spi_lock);
	while (fill_level > 0) {
		if (ctx->stm.change_mode_in_progress) {
			local.head = orig_head;
			rc = -EFAULT;
			break;
		}

@@ -1050,28 +1011,30 @@ static int wigig_sensing_chip_data_ready(struct wigig_sensing_ctx *ctx,
			fill_level : spi_transaction_size;
		available_space_to_end =
			circ_space_to_end(&local, d->size_bytes);
		pr_debug("fill_level=%u, bytes_to_read=%u, idx=%u, available_space_to_end = %u\n",
			 fill_level, bytes_to_read, idx,
		pr_debug("fill_level=%u, bytes_to_read=%u, offset=%u, available_space_to_end = %u\n",
			 fill_level, bytes_to_read, *offset,
			 available_space_to_end);
		/* Determine transaction type */
		if (available_space_to_end >= bytes_to_read) {
			rc = spis_block_read_mem(ctx->spi_dev,
						 spi_fifo->base_addr + idx,
						 spi_fifo->base_addr + *offset,
						 &d->b.buf[local.head],
						 bytes_to_read,
						 ctx->last_read_length
			);
						 ctx->last_read_length);
			if (rc)
				break;
		} else {
			/*
			 * There is not enough place in the CIR buffer, copy to
			 * a temporay buffer and then split
			 */
			rc = spis_block_read_mem(ctx->spi_dev,
						 spi_fifo->base_addr + idx,
						 spi_fifo->base_addr + *offset,
						 ctx->temp_buffer,
						 bytes_to_read,
						 ctx->last_read_length
			);
						 ctx->last_read_length);
			if (rc)
				break;
			memcpy(&d->b.buf[local.head], ctx->temp_buffer,
			       available_space_to_end);
			memcpy(&d->b.buf[0],
@@ -1080,14 +1043,82 @@ static int wigig_sensing_chip_data_ready(struct wigig_sensing_ctx *ctx,
		}

		fill_level -= bytes_to_read;
		idx += bytes_to_read;
		*offset += bytes_to_read;
		local.head = (local.head + bytes_to_read) & (d->size_bytes - 1);
	}
	mutex_unlock(&ctx->spi_lock);

	return rc;
}

static int wigig_sensing_chip_data_ready(struct wigig_sensing_ctx *ctx,
					 u16 fill_level,
					 u32 burst_size)
{
	int rc = 0;
	u32 read_bytes = 0;
	enum wigig_sensing_stm_e stm_state = ctx->stm.state;
	struct cir_data *d = &ctx->cir_data;
	union user_rgf_spi_status spi_status;

	if (stm_state == WIGIG_SENSING_STATE_INITIALIZED ||
	    stm_state == WIGIG_SENSING_STATE_READY_STOPPED ||
	    stm_state == WIGIG_SENSING_STATE_SYS_ASSERT) {
		pr_err("Received data ready interrupt in an unexpected state, disregarding\n");
		return 0;
	}

	if (!ctx->cir_data.b.buf)
		return -EFAULT;

	/*
	 * In case there is not enough space in the buffer, discard an old
	 * burst
	 */
	if (circ_space(&d->b, d->size_bytes) < burst_size) {
		mutex_lock(&d->lock);
		if (circ_space(&d->b, d->size_bytes) < burst_size) {
			pr_debug("Buffer full, dropping burst\n");
			d->b.tail = (d->b.tail + burst_size) &
				(d->size_bytes - 1);
			ctx->dropped_bursts++;
		}
		mutex_unlock(&d->lock);
	}

	while (read_bytes < burst_size) {
		rc = wigig_sensing_chip_data_ready_internal(ctx, fill_level,
							    &read_bytes);
		if (rc) {
			if (ctx->stm.change_mode_in_progress)
				pr_err("change_mode_in_progress, aborting SPI transactions\n");
			else
				pr_err("wigig_sensing_chip_data_ready_internal failed, err %d\n",
				       rc);
			return rc;
		}

		if (read_bytes == burst_size)
			break;

		/* Read fill_level again */
		pr_debug("Reading RGF_USER_SPI_SPI_MBOX_FILL_STATUS register\n");
		mutex_lock(&ctx->spi_lock);
		rc = spis_read_reg(ctx->spi_dev,
				   RGF_USER_SPI_SPI_MBOX_FILL_STATUS,
				   &spi_status.v);
		mutex_unlock(&ctx->spi_lock);
		if (rc) {
			pr_err("Fail to read RGF_USER_SPI_SPI_MBOX_FILL_STATUS, err %d\n",
			       rc);
			return rc;
		}
		fill_level = spi_status.b.fill_level;
	}

	/* Increment destination rd_ptr */
	mutex_lock(&d->lock);
	d->b.head = local.head;
	d->b.head = (d->b.head + read_bytes) & (d->size_bytes - 1);
	pr_debug("head=%u, tail=%u\n", d->b.head, d->b.tail);
	mutex_unlock(&d->lock);

@@ -1287,8 +1318,7 @@ static irqreturn_t wigig_sensing_dri_isr_thread(int irq, void *cookie)
		pr_debug("DATA READY INTERRUPT\n");
		if (!ctx->stm.change_mode_in_progress)
			wigig_sensing_chip_data_ready(ctx,
						      spi_status.b.fill_level,
						      ctx->stm.burst_size);
				spi_status.b.fill_level, ctx->stm.burst_size);
		else
			pr_debug("Change mode in progress, aborting data processing\n");
		spi_status.v &= ~INT_DATA_READY;