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

Commit fe5d837a authored by Shrey Vijay's avatar Shrey Vijay Committed by Alok Chauhan
Browse files

i2c-qcom-geni: Handle corner cases in GSI transfer



Add check to handle if the IOMMU buffer mapping fails,
also make sure to unmap buffer in case of prep_slave_sg failure.

Change-Id: I926a6ce5b10a3c7f29210cba5179cc795ec0c1b4
Signed-off-by: default avatarShrey Vijay <shreyv@codeaurora.org>
parent 1d62eb3a
Loading
Loading
Loading
Loading
+31 −12
Original line number Original line Diff line number Diff line
@@ -526,8 +526,16 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],


		if (msgs[i].flags & I2C_M_RD) {
		if (msgs[i].flags & I2C_M_RD) {
			sg_init_table(&gi2c->rx_sg, 1);
			sg_init_table(&gi2c->rx_sg, 1);
			geni_se_iommu_map_buf(rx_dev, &gi2c->rx_ph, msgs[i].buf,
			ret = geni_se_iommu_map_buf(rx_dev, &gi2c->rx_ph,
						msgs[i].len, DMA_FROM_DEVICE);
						msgs[i].buf, msgs[i].len,
						DMA_FROM_DEVICE);
			if (ret) {
				GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
					    "geni_se_iommu_map_buf for rx failed :%d\n",
					    ret);
				goto geni_i2c_gsi_xfer_out;

			}
			gi2c->rx_t.dword[0] =
			gi2c->rx_t.dword[0] =
				MSM_GPI_DMA_W_BUFFER_TRE_DWORD0(gi2c->rx_ph);
				MSM_GPI_DMA_W_BUFFER_TRE_DWORD0(gi2c->rx_ph);
			gi2c->rx_t.dword[1] =
			gi2c->rx_t.dword[1] =
@@ -548,7 +556,7 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
				GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
				GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
					    "prep_slave_sg for rx failed\n");
					    "prep_slave_sg for rx failed\n");
				gi2c->err = -ENOMEM;
				gi2c->err = -ENOMEM;
				goto geni_i2c_gsi_xfer_out;
				goto geni_i2c_err_prep_sg;
			}
			}
			gi2c->rx_desc->callback = gi2c_gsi_rx_cb;
			gi2c->rx_desc->callback = gi2c_gsi_rx_cb;
			gi2c->rx_desc->callback_param = &gi2c->rx_cb;
			gi2c->rx_desc->callback_param = &gi2c->rx_cb;
@@ -557,8 +565,16 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
			rx_cookie = dmaengine_submit(gi2c->rx_desc);
			rx_cookie = dmaengine_submit(gi2c->rx_desc);
			dma_async_issue_pending(gi2c->rx_c);
			dma_async_issue_pending(gi2c->rx_c);
		} else {
		} else {
			geni_se_iommu_map_buf(tx_dev, &gi2c->tx_ph, msgs[i].buf,
			ret = geni_se_iommu_map_buf(tx_dev, &gi2c->tx_ph,
						msgs[i].len, DMA_TO_DEVICE);
						msgs[i].buf, msgs[i].len,
						DMA_TO_DEVICE);
			if (ret) {
				GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
					    "geni_se_iommu_map_buf for tx failed :%d\n",
					    ret);
				goto geni_i2c_gsi_xfer_out;

			}
			gi2c->tx_t.dword[0] =
			gi2c->tx_t.dword[0] =
				MSM_GPI_DMA_W_BUFFER_TRE_DWORD0(gi2c->tx_ph);
				MSM_GPI_DMA_W_BUFFER_TRE_DWORD0(gi2c->tx_ph);
			gi2c->tx_t.dword[1] =
			gi2c->tx_t.dword[1] =
@@ -580,7 +596,7 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
			GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
			GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
				    "prep_slave_sg for tx failed\n");
				    "prep_slave_sg for tx failed\n");
			gi2c->err = -ENOMEM;
			gi2c->err = -ENOMEM;
			goto geni_i2c_gsi_xfer_out;
			goto geni_i2c_err_prep_sg;
		}
		}
		gi2c->tx_desc->callback = gi2c_gsi_tx_cb;
		gi2c->tx_desc->callback = gi2c_gsi_tx_cb;
		gi2c->tx_desc->callback_param = &gi2c->tx_cb;
		gi2c->tx_desc->callback_param = &gi2c->tx_cb;
@@ -591,12 +607,6 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],


		timeout = wait_for_completion_timeout(&gi2c->xfer,
		timeout = wait_for_completion_timeout(&gi2c->xfer,
						gi2c->xfer_timeout);
						gi2c->xfer_timeout);
		if (msgs[i].flags & I2C_M_RD)
			geni_se_iommu_unmap_buf(rx_dev, &gi2c->rx_ph,
				msgs[i].len, DMA_FROM_DEVICE);
		else
			geni_se_iommu_unmap_buf(tx_dev, &gi2c->tx_ph,
				msgs[i].len, DMA_TO_DEVICE);


		if (!timeout) {
		if (!timeout) {
			GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
			GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
@@ -604,12 +614,21 @@ static int geni_i2c_gsi_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
					gi2c->xfer_timeout, gi2c->cur->len);
					gi2c->xfer_timeout, gi2c->cur->len);
			gi2c->err = -ETIMEDOUT;
			gi2c->err = -ETIMEDOUT;
		}
		}
geni_i2c_err_prep_sg:
		if (msgs[i].flags & I2C_M_RD)
			geni_se_iommu_unmap_buf(rx_dev, &gi2c->rx_ph,
				msgs[i].len, DMA_FROM_DEVICE);
		else
			geni_se_iommu_unmap_buf(tx_dev, &gi2c->tx_ph,
				msgs[i].len, DMA_TO_DEVICE);

		if (gi2c->err) {
		if (gi2c->err) {
			dmaengine_terminate_all(gi2c->tx_c);
			dmaengine_terminate_all(gi2c->tx_c);
			gi2c->cfg_sent = 0;
			gi2c->cfg_sent = 0;
			goto geni_i2c_gsi_xfer_out;
			goto geni_i2c_gsi_xfer_out;
		}
		}
	}
	}

geni_i2c_gsi_xfer_out:
geni_i2c_gsi_xfer_out:
	if (!ret && gi2c->err)
	if (!ret && gi2c->err)
		ret = gi2c->err;
		ret = gi2c->err;