diff --git a/drivers/dma/qcom/msm_gpi.c b/drivers/dma/qcom/msm_gpi.c index a728e20655a8..18d69ed0f969 100644 --- a/drivers/dma/qcom/msm_gpi.c +++ b/drivers/dma/qcom/msm_gpi.c @@ -1772,11 +1772,40 @@ int gpi_terminate_channel(struct gpii_chan *gpii_chan) return ret; } +/* + * geni_gsi_connect_doorbell() - function to connect gsi doorbell + * @chan: gsi channel handle + * + * This function uses asynchronous channel command 48 to connect + * io_6 input from GSI interrupt input. + * + * Return: Returns success or failure + */ +int geni_gsi_connect_doorbell(struct dma_chan *chan) +{ + struct gpii_chan *gpii_chan = to_gpii_chan(chan); + struct gpii *gpii = gpii_chan->gpii; + int ret = 0; + + GPII_VERB(gpii, gpii_chan->chid, "Enter\n"); + ret = gpi_send_cmd(gpii, gpii_chan, GPI_CH_CMD_ENABLE_HID); + if (ret) { + GPII_ERR(gpii, gpii_chan->chid, "Error enable Chan:%d HID interrupt\n", ret); + gpi_dump_debug_reg(gpii); + } + + return ret; +} +EXPORT_SYMBOL_GPL(geni_gsi_connect_doorbell); + /* * geni_gsi_disconnect_doorbell_stop_ch() - function to disconnect gsi doorbell and stop channel * @chan: gsi channel handle * @stop_ch: stop channel if set to true * + * This function uses asynchronous channel command 49 to dis-connect + * io_6 input from GSI interrupt input. + * * Return: Returns success or failure */ int geni_gsi_disconnect_doorbell_stop_ch(struct dma_chan *chan, bool stop_ch) @@ -1786,10 +1815,6 @@ int geni_gsi_disconnect_doorbell_stop_ch(struct dma_chan *chan, bool stop_ch) int ret = 0; bool error = false; - /* - * Use asynchronous channel command 49 (see section 3.10.7) to dis-connect - * io_6 input from GSI interrupt input. - */ GPII_VERB(gpii, gpii_chan->chid, "Enter\n"); ret = gpi_send_cmd(gpii, gpii_chan, GPI_CH_CMD_DISABLE_HID); if (ret) { diff --git a/drivers/spi/q2spi-gsi.c b/drivers/spi/q2spi-gsi.c index ee4a9b225b2c..7f7e4a1630b1 100644 --- a/drivers/spi/q2spi-gsi.c +++ b/drivers/spi/q2spi-gsi.c @@ -708,6 +708,7 @@ void q2spi_gsi_ch_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb, void * case MSM_GPI_QUP_CR_HEADER: /* Update last access time of a device for autosuspend */ pm_runtime_mark_last_busy(q2spi->dev); + q2spi->gsi->qup_gsi_err = false; q2spi_cr_hdr_event = &cb->q2spi_cr_header_event; num_crs = q2spi_cr_hdr_event->byte0_len; if (q2spi_cr_hdr_event->code == Q2SPI_CR_HEADER_LEN_ZERO || @@ -744,6 +745,11 @@ void q2spi_gsi_ch_ev_cb(struct dma_chan *ch, struct msm_gpi_cb const *cb, void * if (cb->cb_event == MSM_GPI_QUP_ERROR) q2spi->gsi->qup_gsi_global_err = true; + if (cb->cb_event == MSM_GPI_QUP_FW_ERROR) { + q2spi_geni_se_dump_regs(q2spi); + gpi_dump_for_geni(q2spi->gsi->tx_c); + } + if (q2spi->gsi->qup_gsi_err) Q2SPI_DEBUG(q2spi, "%s set qup_gsi_err\n", __func__); } diff --git a/drivers/spi/q2spi-msm-geni.c b/drivers/spi/q2spi-msm-geni.c index dc8b1613cd3d..adaceda5c111 100644 --- a/drivers/spi/q2spi-msm-geni.c +++ b/drivers/spi/q2spi-msm-geni.c @@ -1977,15 +1977,16 @@ static int q2spi_transfer_with_retries(struct q2spi_geni *q2spi, struct q2spi_re return ret; } else if (ret == -ETIMEDOUT) { /* Upon transfer failure's retry here */ - Q2SPI_DEBUG(q2spi, "%s ret:%d retry_count:%d retrying cur_q2spi_pkt:%p\n", - __func__, ret, i + 1, cur_q2spi_pkt); + Q2SPI_DEBUG(q2spi, "%s ret:%d retry_count:%d q2spi_pkt:%p db_pending:%d\n", + __func__, ret, i + 1, cur_q2spi_pkt, + atomic_read(&q2spi->doorbell_pending)); if (q2spi->gsi->qup_gsi_global_err) { Q2SPI_DEBUG(q2spi, "%s GSI global error, No retry\n", __func__); ret = -EIO; goto transfer_exit; } - if (i == 0) { + if (i == 0 && !atomic_read(&q2spi->doorbell_pending)) { ret = q2spi_wakeup_hw_from_sleep(q2spi); if (ret) { Q2SPI_DEBUG(q2spi, "%s Err q2spi_wakeup_hw_from_sleep\n", @@ -2212,7 +2213,7 @@ static ssize_t q2spi_transfer(struct file *filp, const char __user *buf, size_t return -EINVAL; } q2spi = filp->private_data; - Q2SPI_DEBUG(q2spi, "%s Enter PID=%d\n", __func__, current->pid); + Q2SPI_DEBUG(q2spi, "In %s Enter PID=%d\n", __func__, current->pid); mutex_lock(&q2spi->port_lock); ret = q2spi_transfer_check(q2spi, &q2spi_req, buf, len); @@ -2784,9 +2785,6 @@ static int q2spi_gsi_submit(struct q2spi_packet *q2spi_pkt) if (ret) { Q2SPI_DEBUG(q2spi, "%s Err q2spi_setup_gsi_xfer failed: %d\n", __func__, ret); atomic_set(&q2spi->sma_wr_pending, 0); - atomic_set(&q2spi->doorbell_pending, 0); - q2spi_geni_se_dump_regs(q2spi); - gpi_dump_for_geni(q2spi->gsi->tx_c); del_timer_sync(&q2spi->slave_sleep_timer); goto unmap_buf; } @@ -2797,9 +2795,6 @@ static int q2spi_gsi_submit(struct q2spi_packet *q2spi_pkt) Q2SPI_DEBUG(q2spi, "%s PID:%d Err completion timeout: %d\n", __func__, current->pid, ret); atomic_set(&q2spi->sma_wr_pending, 0); - atomic_set(&q2spi->doorbell_pending, 0); - q2spi_geni_se_dump_regs(q2spi); - gpi_dump_for_geni(q2spi->gsi->tx_c); del_timer_sync(&q2spi->slave_sleep_timer); goto unmap_buf; } @@ -3102,14 +3097,11 @@ int __q2spi_send_messages(struct q2spi_geni *q2spi, void *ptr) q2spi_pkt->var5_pkt->flow_id); } } - if (!cm_flow_pkt && atomic_read(&q2spi->doorbell_pending)) { - atomic_inc(&q2spi->retry); - Q2SPI_DEBUG(q2spi, "%s doorbell pending retry\n", __func__); - complete_all(&q2spi_pkt->bulk_wait); - q2spi_unmap_var_bufs(q2spi, q2spi_pkt); - ret = -EAGAIN; - goto send_msg_exit; - } + + if (!cm_flow_pkt && atomic_read(&q2spi->doorbell_pending)) + Q2SPI_DEBUG(q2spi, "%s cm_flow_pkt:%d doorbell_pending:%d\n", + __func__, cm_flow_pkt, atomic_read(&q2spi->doorbell_pending)); + ret = q2spi_gsi_submit(q2spi_pkt); if (ret) { Q2SPI_DEBUG(q2spi, "%s Err q2spi_gsi_submit failed: %d\n", __func__, ret); @@ -4619,7 +4611,7 @@ int q2spi_wakeup_slave_through_gpio(struct q2spi_geni *q2spi) return ret; } geni_gsi_ch_start(q2spi->gsi->tx_c); - + geni_gsi_connect_doorbell(q2spi->gsi->tx_c); ret = q2spi_map_doorbell_rx_buf(q2spi); return ret; } @@ -4769,6 +4761,7 @@ static int q2spi_geni_runtime_resume(struct device *dev) Q2SPI_DEBUG(q2spi, "%s Failed to set IRQ wake\n", __func__); geni_gsi_ch_start(q2spi->gsi->tx_c); + geni_gsi_connect_doorbell(q2spi->gsi->tx_c); /* Clear is_suspend to map doorbell buffers */ atomic_set(&q2spi->is_suspend, 0); diff --git a/include/linux/msm_gpi.h b/include/linux/msm_gpi.h index dac16f3d4157..1f64a2ed1e8f 100644 --- a/include/linux/msm_gpi.h +++ b/include/linux/msm_gpi.h @@ -470,6 +470,14 @@ int gsi_common_tx_tre_optimization(struct gsi_common *gsi, u32 num_xfers, u32 nu */ int geni_gsi_ch_start(struct dma_chan *chan); +/** + * geni_gsi_connect_doorbell() - function to connect gsi doorbell + * @chan: dma channel handle + * + * Return: Returns success or failure + */ +int geni_gsi_connect_doorbell(struct dma_chan *chan); + /** * geni_gsi_disconnect_doorbell_stop_ch() - function to disconnect gsi doorbell and stop channel * @chan: dma channel handle