bus: mhi: core: Address pending BW requests for legacy mode

It cannot be guaranteed that certain legacy mode controllers stay
in M0 while a BW request is being processed. Ensure that those
pending BW requests are addressed when M0 entry occurs after a BW
request is processed but not responded to.

Change-Id: I6132116fae76fa10477aa7061c24f3ff5ac60a34
Signed-off-by: Bhaumik Bhatt <bbhatt@codeaurora.org>
This commit is contained in:
Bhaumik Bhatt 2020-12-28 13:27:10 -08:00
commit 85a71cb100
4 changed files with 36 additions and 9 deletions

View file

@ -797,6 +797,7 @@ int mhi_process_tsync_ev_ring(struct mhi_controller *mhi_cntrl,
struct mhi_event *mhi_event, u32 event_quota);
int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl,
struct mhi_event *mhi_event, u32 event_quota);
void mhi_special_dbs_pending(struct mhi_controller *mhi_cntrl);
int mhi_send_cmd(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
enum MHI_CMD cmd);
int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl);

View file

@ -1479,7 +1479,8 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl,
struct mhi_event_ctxt *er_ctxt =
&mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
struct mhi_link_info link_info, *cur_info = &mhi_cntrl->mhi_link_info;
int result, ret = 0;
u32 result = MHI_BW_SCALE_NACK;
int ret = 0;
spin_lock_bh(&mhi_event->lock);
dev_rp = mhi_to_virtual(ev_ring, er_ctxt->rp);
@ -1527,17 +1528,23 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl,
mutex_lock(&mhi_cntrl->pm_mutex);
ret = mhi_cntrl->bw_scale(mhi_cntrl, &link_info);
if (!ret)
if (!ret) {
*cur_info = link_info;
result = 0;
}
result = ret ? MHI_BW_SCALE_NACK : 0;
read_lock_bh(&mhi_cntrl->pm_lock);
if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl)))
write_lock_bh(&mhi_cntrl->pm_lock);
cur_info->last_response = MHI_BW_SCALE_RESULT(result,
link_info.sequence_num);
if (likely(MHI_DB_ACCESS_VALID(mhi_cntrl))) {
mhi_cntrl->write_reg(mhi_cntrl, mhi_cntrl->bw_scale_db, 0,
MHI_BW_SCALE_RESULT(result,
link_info.sequence_num));
read_unlock_bh(&mhi_cntrl->pm_lock);
cur_info->last_response);
cur_info->last_response = 0;
} else {
MHI_VERB("Cached response to BW_REQ seq: %d, ret: %d\n",
link_info.sequence_num, ret);
}
write_unlock_bh(&mhi_cntrl->pm_lock);
mhi_device_put(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS);
@ -1549,6 +1556,20 @@ exit_bw_scale_process:
return ret;
}
void mhi_special_dbs_pending(struct mhi_controller *mhi_cntrl)
{
struct mhi_link_info *link_info = &mhi_cntrl->mhi_link_info;
/* last_response cannot be empty as sequence numbers are non-zero */
if (mhi_cntrl->bw_scale && link_info->last_response) {
mhi_cntrl->write_reg(mhi_cntrl, mhi_cntrl->bw_scale_db, 0,
link_info->last_response);
MHI_VERB("Completed cached BW switch response: %d\n",
link_info->last_response);
link_info->last_response = 0;
}
}
void mhi_ev_task(unsigned long data)
{
struct mhi_event *mhi_event = (struct mhi_event *)data;

View file

@ -376,6 +376,9 @@ int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl)
if (mhi_cmd->ring.rp != mhi_cmd->ring.wp)
mhi_ring_cmd_db(mhi_cntrl, mhi_cmd);
spin_unlock_irq(&mhi_cmd->lock);
/* ring special doorbells for controllers in legacy mode */
mhi_special_dbs_pending(mhi_cntrl);
}
/* ring channel db registers */

View file

@ -132,11 +132,13 @@ enum mhi_dev_state {
* target_link_speed - as defined by TLS bits in LinkControl reg
* target_link_width - as defined by NLW bits in LinkStatus reg
* sequence_num - used by device to track bw requests sent to host
* last_response - used by host to cache response to the last bw switch request
*/
struct mhi_link_info {
unsigned int target_link_speed;
unsigned int target_link_width;
int sequence_num;
u32 last_response;
};
/**