mirror of
https://github.com/torvalds/linux.git
synced 2026-07-30 19:21:28 +02:00
bus: mhi: host: Add support for processing of sleepable events
Processing of some events requires the use of a sleeping function. In order to handle those events, work is queued using high priority workqueue. Sleepable events also require use of a dedicated event ring. Replaced 'TO_MHI_STATE_STR' with 'mhi_state_str' to aid in compilation. Change-Id: I3c42bc5b33b179de79911f8ec21b9a351116a112 Signed-off-by: Hemant Kumar <hemantk@codeaurora.org> Signed-off-by: Lazarus Motha <quic_lmotha@quicinc.com>
This commit is contained in:
parent
93258369b2
commit
04d4e7ae5c
|
|
@ -946,11 +946,13 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
|
|||
|
||||
mhi_event->mhi_cntrl = mhi_cntrl;
|
||||
spin_lock_init(&mhi_event->lock);
|
||||
if (mhi_event->data_type == MHI_ER_CTRL)
|
||||
tasklet_init(&mhi_event->task, mhi_ctrl_ev_task,
|
||||
(ulong)mhi_event);
|
||||
|
||||
if (mhi_event->priority == MHI_ER_PRIORITY_HI_SLEEP)
|
||||
INIT_WORK(&mhi_event->work, mhi_process_ev_work);
|
||||
else
|
||||
tasklet_init(&mhi_event->task, mhi_ev_task,
|
||||
tasklet_init(&mhi_event->task,
|
||||
(mhi_event->data_type == MHI_ER_CTRL) ?
|
||||
mhi_ctrl_ev_task : mhi_ev_task,
|
||||
(ulong)mhi_event);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ struct mhi_event {
|
|||
struct mhi_ring ring;
|
||||
struct db_cfg db_cfg;
|
||||
struct tasklet_struct task;
|
||||
struct work_struct work;
|
||||
spinlock_t lock;
|
||||
int (*process_event)(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_event *mhi_event,
|
||||
|
|
@ -359,6 +360,8 @@ void mhi_reset_chan(struct mhi_controller *mhi_cntrl,
|
|||
/* Event processing methods */
|
||||
void mhi_ctrl_ev_task(unsigned long data);
|
||||
void mhi_ev_task(unsigned long data);
|
||||
void mhi_process_ev_work(struct work_struct *work);
|
||||
void mhi_process_sleeping_events(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_event *mhi_event, u32 event_quota);
|
||||
int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,
|
||||
|
|
|
|||
|
|
@ -426,6 +426,30 @@ void mhi_create_devices(struct mhi_controller *mhi_cntrl)
|
|||
}
|
||||
}
|
||||
|
||||
void mhi_process_sleeping_events(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_event *mhi_event;
|
||||
struct mhi_event_ctxt *er_ctxt;
|
||||
struct mhi_ring *ev_ring;
|
||||
int i;
|
||||
|
||||
mhi_event = mhi_cntrl->mhi_event;
|
||||
for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) {
|
||||
if (mhi_event->offload_ev || mhi_event->priority !=
|
||||
MHI_ER_PRIORITY_HI_SLEEP)
|
||||
continue;
|
||||
|
||||
er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
|
||||
ev_ring = &mhi_event->ring;
|
||||
|
||||
/* Only proceed if event ring has pending events */
|
||||
if (ev_ring->rp == mhi_to_virtual(ev_ring, er_ctxt->rp))
|
||||
continue;
|
||||
|
||||
queue_work(mhi_cntrl->hiprio_wq, &mhi_event->work);
|
||||
}
|
||||
}
|
||||
|
||||
irqreturn_t mhi_irq_handler(int irq_number, void *priv)
|
||||
{
|
||||
struct mhi_event *mhi_event = priv;
|
||||
|
|
@ -467,6 +491,9 @@ irqreturn_t mhi_irq_handler(int irq_number, void *priv)
|
|||
case MHI_ER_PRIORITY_DEFAULT_NOSLEEP:
|
||||
tasklet_schedule(&mhi_event->task);
|
||||
break;
|
||||
case MHI_ER_PRIORITY_HI_SLEEP:
|
||||
queue_work(mhi_cntrl->hiprio_wq, &mhi_event->work);
|
||||
break;
|
||||
default:
|
||||
dev_dbg(dev, "skip unknown priority event\n");
|
||||
break;
|
||||
|
|
@ -1095,6 +1122,24 @@ void mhi_ctrl_ev_task(unsigned long data)
|
|||
}
|
||||
}
|
||||
|
||||
void mhi_process_ev_work(struct work_struct *work)
|
||||
{
|
||||
struct mhi_event *mhi_event = container_of(work, struct mhi_event,
|
||||
work);
|
||||
struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl;
|
||||
struct device *dev = mhi_cntrl->cntrl_dev;
|
||||
|
||||
dev_dbg(dev, "Enter with pm_state:%s MHI_STATE:%s ee:%s\n",
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state),
|
||||
mhi_state_str(mhi_cntrl->dev_state),
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee));
|
||||
|
||||
if (unlikely(MHI_EVENT_ACCESS_INVALID(mhi_cntrl->pm_state)))
|
||||
return;
|
||||
|
||||
mhi_event->process_event(mhi_cntrl, mhi_event, U32_MAX);
|
||||
}
|
||||
|
||||
static bool mhi_is_ring_full(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_ring *ring)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -432,6 +432,8 @@ static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl)
|
|||
|
||||
read_unlock_bh(&mhi_cntrl->pm_lock);
|
||||
|
||||
mhi_process_sleeping_events(mhi_cntrl);
|
||||
|
||||
/*
|
||||
* The MHI devices are only created when the client device switches its
|
||||
* Execution Environment (EE) to either SBL or AMSS states
|
||||
|
|
@ -497,7 +499,10 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl)
|
|||
if (mhi_event->offload_ev)
|
||||
continue;
|
||||
disable_irq(mhi_cntrl->irq[mhi_event->irq]);
|
||||
tasklet_kill(&mhi_event->task);
|
||||
if (mhi_event->priority == MHI_ER_PRIORITY_HI_SLEEP)
|
||||
cancel_work_sync(&mhi_event->work);
|
||||
else
|
||||
tasklet_kill(&mhi_event->task);
|
||||
}
|
||||
|
||||
/* Release lock and wait for all pending threads to complete */
|
||||
|
|
@ -630,7 +635,10 @@ static void mhi_pm_sys_error_transition(struct mhi_controller *mhi_cntrl)
|
|||
for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) {
|
||||
if (mhi_event->offload_ev)
|
||||
continue;
|
||||
tasklet_kill(&mhi_event->task);
|
||||
if (mhi_event->priority == MHI_ER_PRIORITY_HI_SLEEP)
|
||||
cancel_work_sync(&mhi_event->work);
|
||||
else
|
||||
tasklet_kill(&mhi_event->task);
|
||||
}
|
||||
|
||||
/* Release lock and wait for all pending threads to complete */
|
||||
|
|
@ -766,6 +774,9 @@ void mhi_pm_st_worker(struct work_struct *work)
|
|||
write_lock_irq(&mhi_cntrl->pm_lock);
|
||||
mhi_cntrl->ee = MHI_EE_SBL;
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
|
||||
mhi_process_sleeping_events(mhi_cntrl);
|
||||
|
||||
/*
|
||||
* The MHI devices are only created when the client
|
||||
* device switches its Execution Environment (EE) to
|
||||
|
|
|
|||
|
|
@ -202,10 +202,12 @@ enum mhi_er_data_type {
|
|||
* enum mhi_er_priority - Event ring processing priority
|
||||
* @MHI_ER_PRIORITY_DEFAULT_NOSLEEP: processed by tasklet
|
||||
* @MHI_ER_PRIORITY_HI_NOSLEEP: processed by hi-priority tasklet
|
||||
* @MHI_ER_PRIORITY_HI_SLEEP: processed by hi-priority wq
|
||||
*/
|
||||
enum mhi_er_priority {
|
||||
MHI_ER_PRIORITY_DEFAULT_NOSLEEP,
|
||||
MHI_ER_PRIORITY_HI_NOSLEEP,
|
||||
MHI_ER_PRIORITY_HI_SLEEP,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user