mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
mhi: core: Handle RSC minimum credit requirement
After getting OOB driver checks for transfer ring empty condition and rings the channel ring doorbell without making sure if there are minimum 8 TREs queued for GSI to perform DMA. Otherwise there is a possibility of Host ringing doorbell after OOB with same write pointer which was already processed in polling mode. Change-Id: Idda28aadbd1af9b5857db71d98237ef4761427bd Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
This commit is contained in:
parent
855fb63bd5
commit
10f4c14b87
2 changed files with 33 additions and 2 deletions
|
|
@ -362,6 +362,8 @@ enum mhi_cmd_type {
|
|||
#define MHI_RSCTRE_DATA_DWORD0(cookie) (cookie)
|
||||
#define MHI_RSCTRE_DATA_DWORD1 (MHI_PKT_TYPE_COALESCING << 16)
|
||||
|
||||
#define MHI_RSC_MIN_CREDITS (8)
|
||||
|
||||
enum MHI_CMD {
|
||||
MHI_CMD_RESET_CHAN,
|
||||
MHI_CMD_START_CHAN,
|
||||
|
|
|
|||
|
|
@ -499,6 +499,8 @@ int mhi_queue_dma(struct mhi_device *mhi_dev,
|
|||
struct mhi_ring *buf_ring = &mhi_chan->buf_ring;
|
||||
struct mhi_buf_info *buf_info;
|
||||
struct mhi_tre *mhi_tre;
|
||||
bool ring_db = true;
|
||||
int n_free_tre, n_queued_tre;
|
||||
|
||||
if (mhi_is_ring_full(mhi_cntrl, tre_ring))
|
||||
return -ENOMEM;
|
||||
|
|
@ -538,6 +540,18 @@ int mhi_queue_dma(struct mhi_device *mhi_dev,
|
|||
mhi_tre->dword[0] =
|
||||
MHI_RSCTRE_DATA_DWORD0(buf_ring->wp - buf_ring->base);
|
||||
mhi_tre->dword[1] = MHI_RSCTRE_DATA_DWORD1;
|
||||
/*
|
||||
* on RSC channel IPA HW has a minimum credit requirement before
|
||||
* switching to DB mode
|
||||
*/
|
||||
n_free_tre = mhi_get_no_free_descriptors(mhi_dev,
|
||||
DMA_FROM_DEVICE);
|
||||
n_queued_tre = tre_ring->elements - n_free_tre;
|
||||
read_lock_bh(&mhi_chan->lock);
|
||||
if (mhi_chan->db_cfg.db_mode &&
|
||||
n_queued_tre < MHI_RSC_MIN_CREDITS)
|
||||
ring_db = false;
|
||||
read_unlock_bh(&mhi_chan->lock);
|
||||
} else {
|
||||
mhi_tre->ptr = MHI_TRE_DATA_PTR(buf_info->p_addr);
|
||||
mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(buf_info->len);
|
||||
|
|
@ -555,7 +569,7 @@ int mhi_queue_dma(struct mhi_device *mhi_dev,
|
|||
if (mhi_chan->dir == DMA_TO_DEVICE)
|
||||
atomic_inc(&mhi_cntrl->pending_pkts);
|
||||
|
||||
if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl))) {
|
||||
if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl)) && ring_db) {
|
||||
read_lock_bh(&mhi_chan->lock);
|
||||
mhi_ring_chan_db(mhi_cntrl, mhi_chan);
|
||||
read_unlock_bh(&mhi_chan->lock);
|
||||
|
|
@ -972,6 +986,8 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
|
|||
u32 ev_code;
|
||||
struct mhi_result result;
|
||||
unsigned long flags = 0;
|
||||
bool ring_db = true;
|
||||
int n_free_tre, n_queued_tre;
|
||||
|
||||
ev_code = MHI_TRE_GET_EV_CODE(event);
|
||||
buf_ring = &mhi_chan->buf_ring;
|
||||
|
|
@ -1067,9 +1083,22 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
|
|||
|
||||
MHI_VERB("DB_MODE/OOB Detected chan %d.\n", mhi_chan->chan);
|
||||
mhi_chan->db_cfg.db_mode = true;
|
||||
|
||||
/*
|
||||
* on RSC channel IPA HW has a minimum credit requirement before
|
||||
* switching to DB mode
|
||||
*/
|
||||
if (mhi_chan->xfer_type == MHI_XFER_RSC_DMA) {
|
||||
n_free_tre = mhi_get_no_free_descriptors(
|
||||
mhi_chan->mhi_dev, DMA_FROM_DEVICE);
|
||||
n_queued_tre = tre_ring->elements - n_free_tre;
|
||||
if (n_queued_tre < MHI_RSC_MIN_CREDITS)
|
||||
ring_db = false;
|
||||
}
|
||||
|
||||
read_lock_irqsave(&mhi_cntrl->pm_lock, flags);
|
||||
if (tre_ring->wp != tre_ring->rp &&
|
||||
MHI_DB_ACCESS_VALID(mhi_cntrl)) {
|
||||
MHI_DB_ACCESS_VALID(mhi_cntrl) && ring_db) {
|
||||
mhi_ring_chan_db(mhi_cntrl, mhi_chan);
|
||||
}
|
||||
read_unlock_irqrestore(&mhi_cntrl->pm_lock, flags);
|
||||
|
|
|
|||
Loading…
Reference in a new issue