Merge "dmaengine: msm_gpi: fix gpi terminate sequence issue"
This commit is contained in:
commit
984a99ba02
@ -676,6 +676,7 @@ static int gpi_start_chan(struct gpii_chan *gpii_chan);
|
||||
static void gpi_free_chan_desc(struct gpii_chan *gpii_chan);
|
||||
static int gpi_deep_sleep_exit_config(struct dma_chan *chan,
|
||||
struct dma_slave_config *config);
|
||||
static void gpi_noop_tre(struct gpii_chan *gpii_chan);
|
||||
|
||||
static inline struct gpii_chan *to_gpii_chan(struct dma_chan *dma_chan)
|
||||
{
|
||||
@ -2223,6 +2224,14 @@ static void gpi_process_imed_data_event(struct gpii_chan *gpii_chan,
|
||||
struct msm_gpi_tre *gpi_tre;
|
||||
|
||||
spin_unlock_irqrestore(&gpii_chan->vc.lock, flags);
|
||||
/*
|
||||
* RP pointed by Event is to last TRE processed,
|
||||
* we need to update ring rp to tre + 1
|
||||
*/
|
||||
tre += ch_ring->el_size;
|
||||
if (tre >= (ch_ring->base + ch_ring->len))
|
||||
tre = ch_ring->base;
|
||||
ch_ring->rp = tre;
|
||||
GPII_ERR(gpii, gpii_chan->chid,
|
||||
"event without a pending descriptor!\n");
|
||||
gpi_ere = (struct gpi_ere *)imed_event;
|
||||
@ -2345,6 +2354,14 @@ static void gpi_process_xfer_compl_event(struct gpii_chan *gpii_chan,
|
||||
struct gpi_ere *gpi_ere;
|
||||
|
||||
spin_unlock_irqrestore(&gpii_chan->vc.lock, flags);
|
||||
/*
|
||||
* RP pointed by Event is to last TRE processed,
|
||||
* we need to update ring rp to ev_rp + 1
|
||||
*/
|
||||
ev_rp += ch_ring->el_size;
|
||||
if (ev_rp >= (ch_ring->base + ch_ring->len))
|
||||
ev_rp = ch_ring->base;
|
||||
ch_ring->rp = ev_rp;
|
||||
GPII_ERR(gpii, gpii_chan->chid,
|
||||
"Event without a pending descriptor!\n");
|
||||
gpi_ere = (struct gpi_ere *)compl_event;
|
||||
@ -3095,6 +3112,88 @@ int gpi_terminate_all(struct dma_chan *chan)
|
||||
GPII_INFO(gpii, gpii_chan->chid, "Enter\n");
|
||||
mutex_lock(&gpii->ctrl_lock);
|
||||
|
||||
/*
|
||||
* treat both channels as a group if its protocol is not UART
|
||||
* STOP, RESET, or START needs to be in lockstep
|
||||
*/
|
||||
schid = (gpii->protocol == SE_PROTOCOL_UART) ? gpii_chan->chid : 0;
|
||||
echid = (gpii->protocol == SE_PROTOCOL_UART) ? schid + 1 :
|
||||
MAX_CHANNELS_PER_GPII;
|
||||
|
||||
/* stop the channel */
|
||||
for (i = schid; i < echid; i++) {
|
||||
gpii_chan = &gpii->gpii_chan[i];
|
||||
|
||||
/* disable ch state so no more TRE processing */
|
||||
write_lock_irq(&gpii->pm_lock);
|
||||
gpii_chan->pm_state = PREPARE_TERMINATE;
|
||||
write_unlock_irq(&gpii->pm_lock);
|
||||
|
||||
/* send command to Stop the channel */
|
||||
ret = gpi_send_cmd(gpii, gpii_chan, GPI_CH_CMD_STOP);
|
||||
if (ret)
|
||||
GPII_ERR(gpii, gpii_chan->chid,
|
||||
"Error Stopping Chan:%d resetting\n", ret);
|
||||
}
|
||||
|
||||
/* reset the channels (clears any pending tre) */
|
||||
for (i = schid; i < echid; i++) {
|
||||
gpii_chan = &gpii->gpii_chan[i];
|
||||
|
||||
ret = gpi_reset_chan(gpii_chan, GPI_CH_CMD_RESET);
|
||||
if (ret) {
|
||||
GPII_ERR(gpii, gpii_chan->chid,
|
||||
"Error resetting channel ret:%d\n", ret);
|
||||
if (!gpii->reg_table_dump) {
|
||||
gpi_dump_debug_reg(gpii);
|
||||
gpii->reg_table_dump = true;
|
||||
}
|
||||
goto terminate_exit;
|
||||
}
|
||||
|
||||
/* reprogram channel CNTXT */
|
||||
ret = gpi_alloc_chan(gpii_chan, false);
|
||||
if (ret) {
|
||||
GPII_ERR(gpii, gpii_chan->chid,
|
||||
"Error alloc_channel ret:%d\n", ret);
|
||||
goto terminate_exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* restart the channels */
|
||||
for (i = schid; i < echid; i++) {
|
||||
gpii_chan = &gpii->gpii_chan[i];
|
||||
|
||||
ret = gpi_start_chan(gpii_chan);
|
||||
if (ret) {
|
||||
GPII_ERR(gpii, gpii_chan->chid,
|
||||
"Error Starting Channel ret:%d\n", ret);
|
||||
goto terminate_exit;
|
||||
}
|
||||
}
|
||||
|
||||
terminate_exit:
|
||||
mutex_unlock(&gpii->ctrl_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gpi_q2spi_terminate_all() - function to stop and restart the channels
|
||||
* @chan: gsi dma channel handle
|
||||
*
|
||||
* Return: Returns success or failure
|
||||
*/
|
||||
int gpi_q2spi_terminate_all(struct dma_chan *chan)
|
||||
{
|
||||
struct gpii_chan *gpii_chan = to_gpii_chan(chan);
|
||||
struct gpii *gpii = gpii_chan->gpii;
|
||||
int schid, echid, i;
|
||||
int ret = 0;
|
||||
bool stop_cmd_failed = false;
|
||||
|
||||
GPII_INFO(gpii, gpii_chan->chid, "Enter\n");
|
||||
mutex_lock(&gpii->ctrl_lock);
|
||||
|
||||
/*
|
||||
* treat both channels as a group if its protocol is not UART
|
||||
* STOP, RESET if STOP fails, and RE-START needs to be in lockstep
|
||||
@ -3117,6 +3216,14 @@ int gpi_terminate_all(struct dma_chan *chan)
|
||||
if (ret) {
|
||||
GPII_ERR(gpii, gpii_chan->chid,
|
||||
"Error Stopping Chan:%d resetting\n", ret);
|
||||
stop_cmd_failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset both TX and RX channel if stop cmd fails */
|
||||
if (stop_cmd_failed) {
|
||||
for (i = schid; i < echid; i++) {
|
||||
gpii_chan = &gpii->gpii_chan[i];
|
||||
ret = gpi_reset_chan(gpii_chan, GPI_CH_CMD_RESET);
|
||||
if (ret) {
|
||||
GPII_ERR(gpii, gpii_chan->chid,
|
||||
@ -3127,6 +3234,14 @@ int gpi_terminate_all(struct dma_chan *chan)
|
||||
}
|
||||
goto terminate_exit;
|
||||
}
|
||||
|
||||
/* reprogram channel CNTXT */
|
||||
ret = gpi_alloc_chan(gpii_chan, false);
|
||||
if (ret) {
|
||||
GPII_ERR(gpii, gpii_chan->chid,
|
||||
"Error alloc_channel ret:%d\n", ret);
|
||||
goto terminate_exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3146,6 +3261,7 @@ int gpi_terminate_all(struct dma_chan *chan)
|
||||
mutex_unlock(&gpii->ctrl_lock);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpi_q2spi_terminate_all);
|
||||
|
||||
static void gpi_noop_tre(struct gpii_chan *gpii_chan)
|
||||
{
|
||||
|
@ -1106,7 +1106,20 @@ static void gi2c_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb_str,
|
||||
static void gi2c_gsi_cb_err(struct msm_gpi_dma_async_tx_cb_param *cb,
|
||||
char *xfer)
|
||||
{
|
||||
struct geni_i2c_dev *gi2c = cb->userdata;
|
||||
struct geni_i2c_dev *gi2c;
|
||||
|
||||
if (!cb || !cb->userdata) {
|
||||
pr_err("%s: Invalid gsi_cb\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
gi2c = cb->userdata;
|
||||
|
||||
if (!gi2c->cur) {
|
||||
geni_i2c_err(gi2c, GENI_SPURIOUS_IRQ);
|
||||
I2C_LOG_DBG(gi2c->ipcl, false, gi2c->dev, "%s: Invalid gi2c dev\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cb->status & DM_I2C_CB_ERR) {
|
||||
I2C_LOG_DBG(gi2c->ipcl, false, gi2c->dev,
|
||||
|
@ -450,7 +450,7 @@ int check_gsi_transfer_completion_db_rx(struct q2spi_geni *q2spi)
|
||||
Q2SPI_DEBUG(q2spi, "%s Err QUP GSI Error\n", __func__);
|
||||
q2spi->gsi->qup_gsi_err = false;
|
||||
q2spi->setup_config0 = false;
|
||||
dmaengine_terminate_all(q2spi->gsi->tx_c);
|
||||
gpi_q2spi_terminate_all(q2spi->gsi->tx_c);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -492,7 +492,7 @@ int check_gsi_transfer_completion(struct q2spi_geni *q2spi)
|
||||
Q2SPI_DEBUG(q2spi, "%s Err QUP Gsi Error\n", __func__);
|
||||
q2spi->gsi->qup_gsi_err = false;
|
||||
q2spi->setup_config0 = false;
|
||||
dmaengine_terminate_all(q2spi->gsi->tx_c);
|
||||
gpi_q2spi_terminate_all(q2spi->gsi->tx_c);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -593,7 +593,7 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
|
||||
if (dma_submit_error(q2spi->gsi->tx_cookie)) {
|
||||
Q2SPI_DEBUG(q2spi, "%s Err dmaengine_submit failed (%d)\n",
|
||||
__func__, q2spi->gsi->tx_cookie);
|
||||
dmaengine_terminate_all(q2spi->gsi->tx_c);
|
||||
gpi_q2spi_terminate_all(q2spi->gsi->tx_c);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -622,7 +622,7 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
|
||||
if (dma_submit_error(q2spi->gsi->rx_cookie)) {
|
||||
Q2SPI_DEBUG(q2spi, "%s Err dmaengine_submit failed (%d)\n",
|
||||
__func__, q2spi->gsi->rx_cookie);
|
||||
dmaengine_terminate_all(q2spi->gsi->rx_c);
|
||||
gpi_q2spi_terminate_all(q2spi->gsi->rx_c);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (cmd == Q2SPI_RX_ONLY) {
|
||||
@ -650,7 +650,7 @@ int q2spi_setup_gsi_xfer(struct q2spi_packet *q2spi_pkt)
|
||||
if (dma_submit_error(q2spi->gsi->rx_cookie)) {
|
||||
Q2SPI_DEBUG(q2spi, "%s Err dmaengine_submit failed (%d)\n",
|
||||
__func__, q2spi->gsi->rx_cookie);
|
||||
dmaengine_terminate_all(q2spi->gsi->rx_c);
|
||||
gpi_q2spi_terminate_all(q2spi->gsi->rx_c);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -413,6 +413,14 @@ struct gsi_common {
|
||||
*/
|
||||
void gpi_dump_for_geni(struct dma_chan *chan);
|
||||
|
||||
/**
|
||||
* gpi_q2spi_terminate_all() - function to stop and restart the channels
|
||||
* @chan: gsi dma channel handle
|
||||
*
|
||||
* Return: Returns success or failure
|
||||
*/
|
||||
int gpi_q2spi_terminate_all(struct dma_chan *chan);
|
||||
|
||||
/**
|
||||
* gpi_update_multi_desc_flag() - update multi descriptor flag and num of msgs for
|
||||
* multi descriptor mode handling.
|
||||
|
Loading…
Reference in New Issue
Block a user