diff options
| author | Andrei Danaila <adanaila@codeaurora.org> | 2014-12-17 12:27:03 -0800 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 21:11:14 -0700 |
| commit | 9c1b21c4e3ff4e3f2beda0dd0bf140dad8cd0d86 (patch) | |
| tree | fbb771b54b3115d84cac5114a93b74ac9fe85089 | |
| parent | c84885de9a53d2335ec9a60156b23adb95a324aa (diff) | |
mhi: core: Enable runtime PM
Enable runtime PM in the MHI driver to increase transparency
between kernel and device driver and synchronize runtime PM
actions with system wide power states.
Change-Id: I8b87c2ed7b0be8a4cf9568ac1fb772eebe416dc6
Signed-off-by: Andrei Danaila <adanaila@codeaurora.org>
| -rw-r--r-- | drivers/platform/msm/mhi/mhi.h | 12 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_iface.c | 10 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_init.c | 8 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_macros.h | 1 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_main.c | 111 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_pm.c | 31 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_states.c | 98 | ||||
| -rw-r--r-- | drivers/platform/msm/mhi/mhi_sys.c | 3 |
8 files changed, 120 insertions, 154 deletions
diff --git a/drivers/platform/msm/mhi/mhi.h b/drivers/platform/msm/mhi/mhi.h index 9db159b6d8c1..907eb5413e55 100644 --- a/drivers/platform/msm/mhi/mhi.h +++ b/drivers/platform/msm/mhi/mhi.h @@ -392,8 +392,6 @@ struct mhi_flags { u32 kill_threads; atomic_t data_pending; atomic_t events_pending; - atomic_t m0_work_enabled; - atomic_t m3_work_enabled; atomic_t pending_resume; atomic_t pending_ssr; atomic_t pending_powerup; @@ -460,10 +458,7 @@ struct mhi_device_ctxt { rwlock_t xfer_lock; struct hrtimer m1_timer; ktime_t m1_timeout; - struct delayed_work m3_work; - struct work_struct m0_work; - - struct workqueue_struct *work_queue; + ktime_t ul_acc_tmr_timeout; struct mhi_chan_counters mhi_chan_cntr[MHI_MAX_CHANNELS]; u32 ev_counter[MHI_MAX_CHANNELS]; u32 bus_client; @@ -574,8 +569,6 @@ int mhi_cpu_notifier_cb(struct notifier_block *nfb, unsigned long action, enum MHI_STATUS init_mhi_base_state(struct mhi_device_ctxt *mhi_dev_ctxt); enum MHI_STATUS mhi_turn_off_pcie_link(struct mhi_device_ctxt *mhi_dev_ctxt); enum MHI_STATUS mhi_turn_on_pcie_link(struct mhi_device_ctxt *mhi_dev_ctxt); -void delayed_m3(struct work_struct *work); -void m0_work(struct work_struct *work); int mhi_initiate_m0(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_set_bus_request(struct mhi_device_ctxt *mhi_dev_ctxt, @@ -592,5 +585,8 @@ void mhi_reg_write(struct mhi_device_ctxt *mhi_dev_ctxt, u32 mhi_reg_read(void __iomem *io_addr, uintptr_t io_offset); u32 mhi_reg_read_field(void __iomem *io_addr, uintptr_t io_offset, u32 mask, u32 shift); +void mhi_exit_m2(struct mhi_device_ctxt *mhi_dev_ctxt); +int mhi_runtime_suspend(struct device *dev); +int mhi_runtime_resume(struct device *dev); #endif diff --git a/drivers/platform/msm/mhi/mhi_iface.c b/drivers/platform/msm/mhi/mhi_iface.c index 4fb1c2547612..662f5c68be4a 100644 --- a/drivers/platform/msm/mhi/mhi_iface.c +++ b/drivers/platform/msm/mhi/mhi_iface.c @@ -18,6 +18,7 @@ #include <linux/msm-bus.h> #include <linux/delay.h> #include <linux/debugfs.h> +#include <linux/pm_runtime.h> #define CREATE_TRACE_POINTS #include "mhi_trace.h" @@ -157,6 +158,8 @@ int mhi_ctxt_init(struct mhi_pcie_dev_info *mhi_pcie_dev) mhi_pcie_dev->mhi_ctxt.mmio_addr = mhi_pcie_dev->core.bar0_base; pcie_device->dev.platform_data = &mhi_pcie_dev->mhi_ctxt; + mhi_pcie_dev->mhi_ctxt.dev_info->plat_dev->dev.platform_data = + &mhi_pcie_dev->mhi_ctxt; if (mhi_pcie_dev->mhi_ctxt.base_state == STATE_TRANSITION_BHI) { ret_val = bhi_probe(mhi_pcie_dev); if (ret_val) { @@ -189,6 +192,12 @@ msi_config_err: return ret_val; } +static const struct dev_pm_ops pm_ops = { + .runtime_suspend = mhi_runtime_suspend, + .runtime_resume = mhi_runtime_resume, + .runtime_idle = NULL, +}; + static struct pci_driver mhi_pcie_driver = { .name = "mhi_pcie_drv", .id_table = mhi_pcie_device_id, @@ -247,6 +256,7 @@ static struct platform_driver mhi_plat_driver = { .name = "mhi", .owner = THIS_MODULE, .of_match_table = mhi_plat_match, + .pm = &pm_ops, }, }; diff --git a/drivers/platform/msm/mhi/mhi_init.c b/drivers/platform/msm/mhi/mhi_init.c index 0b9fb890e8c5..c11ac2faeeaa 100644 --- a/drivers/platform/msm/mhi/mhi_init.c +++ b/drivers/platform/msm/mhi/mhi_init.c @@ -473,14 +473,6 @@ static enum MHI_STATUS mhi_init_contexts(struct mhi_device_ctxt *mhi_dev_ctxt) static enum MHI_STATUS mhi_init_work_queues( struct mhi_device_ctxt *mhi_dev_ctxt) { - mhi_dev_ctxt->work_queue = create_singlethread_workqueue("mhi"); - if (NULL == mhi_dev_ctxt->work_queue) { - mhi_log(MHI_MSG_CRITICAL | MHI_DBG_POWER, - "Failed to create MHI work queue.\n"); - return MHI_STATUS_ERROR; - } - INIT_DELAYED_WORK(&mhi_dev_ctxt->m3_work, delayed_m3); - INIT_WORK(&mhi_dev_ctxt->m0_work, m0_work); return MHI_STATUS_SUCCESS; } diff --git a/drivers/platform/msm/mhi/mhi_macros.h b/drivers/platform/msm/mhi/mhi_macros.h index 791f8a484464..8b8505bd3563 100644 --- a/drivers/platform/msm/mhi/mhi_macros.h +++ b/drivers/platform/msm/mhi/mhi_macros.h @@ -28,6 +28,7 @@ #define MHI_MAX_RESUME_TIMEOUT 5000 #define MHI_MAX_SUSPEND_TIMEOUT 5000 #define MHI_MAX_CMD_TIMEOUT 500 +#define MHI_RPM_AUTOSUSPEND_TMR_VAL_MS 1000 #define MAX_NR_MSI 4 diff --git a/drivers/platform/msm/mhi/mhi_main.c b/drivers/platform/msm/mhi/mhi_main.c index faf066b482b5..f9459125e1ee 100644 --- a/drivers/platform/msm/mhi/mhi_main.c +++ b/drivers/platform/msm/mhi/mhi_main.c @@ -21,6 +21,7 @@ #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/completion.h> +#include <linux/pm_runtime.h> #include "mhi_sys.h" #include "mhi.h" @@ -234,6 +235,7 @@ enum MHI_STATUS mhi_open_channel(struct mhi_client_handle *client_handle) chan = client_handle->chan; mhi_log(MHI_MSG_INFO, "Entered: Client opening chan 0x%x\n", chan); + init_completion(&client_handle->chan_open_complete); mhi_dev_ctxt = client_handle->mhi_dev_ctxt; switch (mhi_dev_ctxt->dev_exec_env) { case MHI_EXEC_ENV_PBL: @@ -314,9 +316,6 @@ enum MHI_STATUS mhi_register_channel(struct mhi_client_handle **client_handle, (*client_handle)->user_data = UserData; - init_completion(&(*client_handle)->chan_reset_complete); - init_completion(&(*client_handle)->chan_open_complete); - (*client_handle)->cb_mod = 1; (*client_handle)->chan_status = 0; (*client_handle)->magic = MHI_HANDLE_MAGIC; @@ -353,6 +352,7 @@ void mhi_close_channel(struct mhi_client_handle *mhi_handle) return; chan = mhi_handle->chan; mhi_log(MHI_MSG_INFO, "Client attempting to close chan 0x%x\n", chan); + init_completion(&mhi_handle->chan_reset_complete); index = mhi_handle->device_index; if (!atomic_read(&mhi_handle->mhi_dev_ctxt->flags.pending_ssr)) { ret_val = mhi_send_cmd(mhi_handle->mhi_dev_ctxt, @@ -362,15 +362,14 @@ void mhi_close_channel(struct mhi_client_handle *mhi_handle) "Failed to send reset cmd for chan %d ret %d\n", chan, ret_val); } - r = wait_for_completion_interruptible_timeout( + r = wait_for_completion_timeout( &mhi_handle->chan_reset_complete, msecs_to_jiffies(MHI_MAX_CMD_TIMEOUT)); - if (0 == r || -ERESTARTSYS == r) { + if (!r) mhi_log(MHI_MSG_ERROR, "Failed to reset chan %d ret %d\n", chan, r); - } } else { /* * Assumption: Device is not playing with our @@ -473,87 +472,62 @@ enum MHI_STATUS mhi_add_elements_to_event_rings( return ret_val; } -static enum MHI_STATUS mhi_wake_dev_from_m3( - struct mhi_device_ctxt *mhi_dev_ctxt) +void mhi_update_chan_db(struct mhi_device_ctxt *mhi_dev_ctxt, + u32 chan) { - int r = 0; - if (!atomic_cmpxchg(&mhi_dev_ctxt->flags.m0_work_enabled, 0, 1)) { - mhi_log(MHI_MSG_INFO, - "Initiating M0 work...\n"); - if (atomic_read(&mhi_dev_ctxt->flags.pending_resume)) { - mhi_log(MHI_MSG_INFO, - "Resume is pending, quitting ...\n"); - atomic_set(&mhi_dev_ctxt->flags.m0_work_enabled, 0); - __pm_stay_awake(&mhi_dev_ctxt->w_lock); - __pm_relax(&mhi_dev_ctxt->w_lock); - return MHI_STATUS_SUCCESS; + u64 db_value = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, + (uintptr_t)mhi_dev_ctxt->mhi_local_chan_ctxt[chan].wp); + mhi_dev_ctxt->mhi_chan_db_order[chan]++; + if (IS_HARDWARE_CHANNEL(chan) && (chan % 2)) { + if (unlikely(mhi_xfer_db_interval != 0)) { + if ((mhi_dev_ctxt-> + mhi_chan_cntr[chan].pkts_xferd % + mhi_xfer_db_interval) == 0) + mhi_process_db(mhi_dev_ctxt, + mhi_dev_ctxt->channel_db_addr, + chan, db_value); + } else { + if ((mhi_dev_ctxt-> + mhi_chan_cntr[chan].pkts_xferd % + MHI_XFER_DB_INTERVAL) == 0) + mhi_process_db(mhi_dev_ctxt, + mhi_dev_ctxt->channel_db_addr, + chan, db_value); } - r = queue_work(mhi_dev_ctxt->work_queue, - &mhi_dev_ctxt->m0_work); - if (!r) - mhi_log(MHI_MSG_CRITICAL, - "Failed to start M0 work.\n"); } else { - mhi_log(MHI_MSG_VERBOSE, - "M0 work pending.\n"); + mhi_process_db(mhi_dev_ctxt, + mhi_dev_ctxt->channel_db_addr, + chan, db_value); } - return MHI_STATUS_SUCCESS; } static enum MHI_STATUS mhi_notify_device( struct mhi_device_ctxt *mhi_dev_ctxt, u32 chan) { unsigned long flags = 0; - u64 db_value; struct mhi_chan_ctxt *chan_ctxt; + enum MHI_STATUS ret_val = MHI_STATUS_SUCCESS; chan_ctxt = &mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list[chan]; + spin_lock_irqsave(&mhi_dev_ctxt->db_write_lock[chan], flags); if (likely(((MHI_STATE_M0 == mhi_dev_ctxt->mhi_state) || (MHI_STATE_M1 == mhi_dev_ctxt->mhi_state)) && (chan_ctxt->mhi_chan_state != MHI_CHAN_STATE_ERROR) && !mhi_dev_ctxt->flags.pending_M3)) { - - mhi_dev_ctxt->mhi_chan_db_order[chan]++; - db_value = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, - (uintptr_t)mhi_dev_ctxt->mhi_local_chan_ctxt[chan].wp); - if (IS_HARDWARE_CHANNEL(chan) && (chan % 2)) { - if (unlikely(mhi_xfer_db_interval != 0)) { - if ((mhi_dev_ctxt-> - mhi_chan_cntr[chan].pkts_xferd % - mhi_xfer_db_interval) == 0) { - mhi_process_db(mhi_dev_ctxt, - mhi_dev_ctxt->channel_db_addr, - chan, db_value); - } - } else { - if ((mhi_dev_ctxt-> - mhi_chan_cntr[chan].pkts_xferd % - MHI_XFER_DB_INTERVAL) == 0) { - mhi_process_db(mhi_dev_ctxt, - mhi_dev_ctxt->channel_db_addr, - chan, db_value); - } - } - } else { - mhi_process_db(mhi_dev_ctxt, - mhi_dev_ctxt->channel_db_addr, - chan, db_value); - } + mhi_update_chan_db(mhi_dev_ctxt, chan); } else { mhi_log(MHI_MSG_VERBOSE, - "Wakeup, pending data MHI state %d, chan state %d\n", - mhi_dev_ctxt->mhi_state, chan_ctxt->mhi_chan_state); - if (mhi_dev_ctxt->flags.pending_M3 || - mhi_dev_ctxt->mhi_state == MHI_STATE_M3) { - mhi_wake_dev_from_m3(mhi_dev_ctxt); - } + "Wakeup, pending data state %d chan state %d\n", + mhi_dev_ctxt->mhi_state, + chan_ctxt->mhi_chan_state); + ret_val = MHI_STATUS_SUCCESS; } spin_unlock_irqrestore(&mhi_dev_ctxt->db_write_lock[chan], flags); /* * If there are no clients still sending we can trigger our * inactivity timer */ - return MHI_STATUS_SUCCESS; + return ret_val; } enum MHI_STATUS mhi_queue_xfer(struct mhi_client_handle *client_handle, @@ -574,6 +548,7 @@ enum MHI_STATUS mhi_queue_xfer(struct mhi_client_handle *client_handle, "Client buffer is of invalid length\n"); mhi_dev_ctxt = client_handle->mhi_dev_ctxt; chan = client_handle->chan; + pm_runtime_get(&mhi_dev_ctxt->dev_info->plat_dev->dev); /* Bump up the vote for pending data */ read_lock_irqsave(&mhi_dev_ctxt->xfer_lock, flags); @@ -617,10 +592,10 @@ enum MHI_STATUS mhi_queue_xfer(struct mhi_client_handle *client_handle, } mhi_notify_device(mhi_dev_ctxt, chan); - atomic_dec(&mhi_dev_ctxt->flags.data_pending); - return MHI_STATUS_SUCCESS; error: atomic_dec(&mhi_dev_ctxt->flags.data_pending); + pm_runtime_mark_last_busy(&mhi_dev_ctxt->dev_info->plat_dev->dev); + pm_runtime_put_noidle(&mhi_dev_ctxt->dev_info->plat_dev->dev); return ret_val; } EXPORT_SYMBOL(mhi_queue_xfer); @@ -649,6 +624,7 @@ enum MHI_STATUS mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, chan, cmd); mhi_assert_device_wake(mhi_dev_ctxt); + pm_runtime_get(&mhi_dev_ctxt->dev_info->plat_dev->dev); /* * If there is a cmd pending a struct device confirmation, * do not send anymore for this channel @@ -725,16 +701,13 @@ enum MHI_STATUS mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, mhi_dev_ctxt->cmd_ring_order++; mhi_process_db(mhi_dev_ctxt, mhi_dev_ctxt->cmd_db_addr, 0, db_value); - } else { - mhi_log(MHI_MSG_INFO, - "Waking dev from M3 for cmd %d on chan %d\n", - cmd, chan); - mhi_wake_dev_from_m3(mhi_dev_ctxt); } mhi_log(MHI_MSG_VERBOSE, "Sent command 0x%x for chan %d\n", cmd, chan); mutex_unlock(&mhi_dev_ctxt->mhi_cmd_mutex_list[PRIMARY_CMD_RING]); + pm_runtime_mark_last_busy(&mhi_dev_ctxt->dev_info->plat_dev->dev); + pm_runtime_put_noidle(&mhi_dev_ctxt->dev_info->plat_dev->dev); mhi_log(MHI_MSG_INFO, "Exited.\n"); return MHI_STATUS_SUCCESS; diff --git a/drivers/platform/msm/mhi/mhi_pm.c b/drivers/platform/msm/mhi/mhi_pm.c index a12bdef7a8fa..6878b5dd7af8 100644 --- a/drivers/platform/msm/mhi/mhi_pm.c +++ b/drivers/platform/msm/mhi/mhi_pm.c @@ -15,6 +15,7 @@ #include <linux/pm.h> #include <linux/fs.h> #include <linux/hrtimer.h> +#include <linux/pm_runtime.h> #include "mhi_sys.h" #include "mhi.h" @@ -46,11 +47,6 @@ int mhi_pci_suspend(struct pci_dev *pcie_dev, pm_message_t state) mhi_log(MHI_MSG_INFO, "Entered, sys state %d, MHI state %d\n", state.event, mhi_dev_ctxt->mhi_state); atomic_set(&mhi_dev_ctxt->flags.pending_resume, 1); - r = cancel_work_sync(&mhi_dev_ctxt->m0_work); - if (!r) { - atomic_set(&mhi_dev_ctxt->flags.m0_work_enabled, 0); - mhi_log(MHI_MSG_INFO, "M0 work cancelled\n"); - } r = mhi_initiate_m3(mhi_dev_ctxt); @@ -58,8 +54,29 @@ int mhi_pci_suspend(struct pci_dev *pcie_dev, pm_message_t state) return r; atomic_set(&mhi_dev_ctxt->flags.pending_resume, 0); - mhi_log(MHI_MSG_ERROR, "Failing suspend sequence ret: %d\n", - r); + mhi_log(MHI_MSG_INFO, "Exited, ret %d\n", r); + return r; +} + +int mhi_runtime_suspend(struct device *dev) +{ + int r = 0; + struct mhi_device_ctxt *mhi_dev_ctxt = dev->platform_data; + mhi_log(MHI_MSG_INFO, "Runtime Suspend - Entered\n"); + r = mhi_initiate_m3(mhi_dev_ctxt); + pm_runtime_mark_last_busy(dev); + mhi_log(MHI_MSG_INFO, "Runtime Suspend - Exited\n"); + return r; +} + +int mhi_runtime_resume(struct device *dev) +{ + int r = 0; + struct mhi_device_ctxt *mhi_dev_ctxt = dev->platform_data; + mhi_log(MHI_MSG_INFO, "Runtime Resume - Entered\n"); + r = mhi_initiate_m0(mhi_dev_ctxt); + pm_runtime_mark_last_busy(dev); + mhi_log(MHI_MSG_INFO, "Runtime Resume - Exited\n"); return r; } diff --git a/drivers/platform/msm/mhi/mhi_states.c b/drivers/platform/msm/mhi/mhi_states.c index 4d4b81873340..65cbe88754b6 100644 --- a/drivers/platform/msm/mhi/mhi_states.c +++ b/drivers/platform/msm/mhi/mhi_states.c @@ -14,6 +14,9 @@ #include "mhi_hwio.h" #include "mhi_trace.h" +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> + static void conditional_chan_db_write( struct mhi_device_ctxt *mhi_dev_ctxt, u32 chan) { @@ -111,14 +114,7 @@ static enum MHI_STATUS process_m0_transition( unsigned long flags; int ret_val; mhi_log(MHI_MSG_INFO, "Entered\n"); - ret_val = cancel_delayed_work(&mhi_dev_ctxt->m3_work); - if (ret_val) { - atomic_set(&mhi_dev_ctxt->flags.m3_work_enabled, 0); - mhi_log(MHI_MSG_INFO, "M3 work was cancelled\n"); - } else { - mhi_log(MHI_MSG_INFO, - "M3 work NOT cancelled, either running or never started\n"); - } + if (mhi_dev_ctxt->mhi_state == MHI_STATE_M2) { mhi_dev_ctxt->counters.m2_m0++; } else if (mhi_dev_ctxt->mhi_state == MHI_STATE_M3) { @@ -175,6 +171,7 @@ static enum MHI_STATUS process_m1_transition( { unsigned long flags = 0; int ret_val = 0; + int r = 0; mhi_log(MHI_MSG_INFO, "Processing M1 state transition from state %d\n", mhi_dev_ctxt->mhi_state); @@ -213,15 +210,20 @@ static enum MHI_STATUS process_m1_transition( 0); if (ret_val) mhi_log(MHI_MSG_INFO, "Failed to update bus request\n"); - if (!atomic_cmpxchg(&mhi_dev_ctxt->flags.m3_work_enabled, 0, 1)) { - mhi_log(MHI_MSG_INFO, "Starting M3 deferred work\n"); - ret_val = queue_delayed_work(mhi_dev_ctxt->work_queue, - &mhi_dev_ctxt->m3_work, - msecs_to_jiffies(m3_timer_val_ms)); - if (ret_val == 0) - mhi_log(MHI_MSG_CRITICAL, - "Failed to start M3 delayed work.\n"); + + mhi_log(MHI_MSG_INFO, "Start Deferred Suspend usage_count: %d\n", + atomic_read( + &mhi_dev_ctxt->dev_info->plat_dev->dev.power.usage_count)); + + pm_runtime_mark_last_busy(&mhi_dev_ctxt->dev_info->plat_dev->dev); + r = pm_request_autosuspend(&mhi_dev_ctxt->dev_info->plat_dev->dev); + if (r) { + mhi_log(MHI_MSG_ERROR, "Failed to remove counter ret %d\n", r); + mhi_log(MHI_MSG_ERROR, "Usage counter is %d\n", + atomic_read( + &mhi_dev_ctxt->dev_info->plat_dev->dev.power.usage_count)); } + return MHI_STATUS_SUCCESS; } @@ -269,17 +271,7 @@ static enum MHI_STATUS mhi_process_link_down( mhi_deassert_device_wake(mhi_dev_ctxt); write_unlock_irqrestore(&mhi_dev_ctxt->xfer_lock, flags); - r = cancel_delayed_work_sync(&mhi_dev_ctxt->m3_work); - if (r) { - atomic_set(&mhi_dev_ctxt->flags.m3_work_enabled, 0); - mhi_log(MHI_MSG_INFO, "M3 work cancelled\n"); - } - r = cancel_work_sync(&mhi_dev_ctxt->m0_work); - if (r) { - atomic_set(&mhi_dev_ctxt->flags.m0_work_enabled, 0); - mhi_log(MHI_MSG_INFO, "M0 work cancelled\n"); - } mhi_dev_ctxt->flags.stop_threads = 1; while (!mhi_dev_ctxt->ev_thread_stopped) { @@ -541,10 +533,10 @@ enum MHI_STATUS start_chan_sync(struct mhi_client_handle *client_handle) MHI_CLIENT_SAHARA_OUT, ret_val); return ret_val; } - r = wait_for_completion_interruptible_timeout( + r = wait_for_completion_timeout( &client_handle->chan_open_complete, msecs_to_jiffies(MHI_MAX_CMD_TIMEOUT)); - if (0 == r || -ERESTARTSYS == r) { + if (!r) { mhi_log(MHI_MSG_ERROR, "Failed to start chan %d ret %d\n", client_handle->chan, r); @@ -600,7 +592,19 @@ static enum MHI_STATUS process_sbl_transition( struct mhi_device_ctxt *mhi_dev_ctxt, enum STATE_TRANSITION cur_work_item) { + int r; mhi_log(MHI_MSG_INFO, "Processing SBL state transition\n"); + + pm_runtime_set_autosuspend_delay(&mhi_dev_ctxt->dev_info->plat_dev->dev, + MHI_RPM_AUTOSUSPEND_TMR_VAL_MS); + pm_runtime_use_autosuspend(&mhi_dev_ctxt->dev_info->plat_dev->dev); + r = pm_runtime_set_active(&mhi_dev_ctxt->dev_info->plat_dev->dev); + if (r) { + mhi_log(MHI_MSG_ERROR, + "Failed to activate runtime pm ret %d\n", r); + } + pm_runtime_enable(&mhi_dev_ctxt->dev_info->plat_dev->dev); + mhi_log(MHI_MSG_INFO, "Enabled runtime pm\n"); mhi_dev_ctxt->dev_exec_env = MHI_EXEC_ENV_SBL; wmb(); enable_clients(mhi_dev_ctxt, mhi_dev_ctxt->dev_exec_env); @@ -612,6 +616,7 @@ static enum MHI_STATUS process_amss_transition( enum STATE_TRANSITION cur_work_item) { enum MHI_STATUS ret_val; + mhi_log(MHI_MSG_INFO, "Processing AMSS state transition\n"); mhi_dev_ctxt->dev_exec_env = MHI_EXEC_ENV_AMSS; atomic_inc(&mhi_dev_ctxt->flags.data_pending); @@ -843,30 +848,6 @@ enum MHI_STATUS mhi_init_state_transition(struct mhi_device_ctxt *mhi_dev_ctxt, return ret_val; } -void delayed_m3(struct work_struct *work) -{ - int r; - struct delayed_work *del_work = to_delayed_work(work); - struct mhi_device_ctxt *mhi_dev_ctxt = container_of(del_work, - struct mhi_device_ctxt, m3_work); - r = mhi_initiate_m3(mhi_dev_ctxt); - if (r) - mhi_log(MHI_MSG_INFO, "Failed to initiate M3 ret: %d\n", r); - -} - -void m0_work(struct work_struct *work) -{ - struct mhi_device_ctxt *mhi_dev_ctxt = - container_of(work, struct mhi_device_ctxt, m0_work); - if (!atomic_read(&mhi_dev_ctxt->flags.pending_resume)) { - mhi_log(MHI_MSG_INFO, "No pending resume, initiating M0.\n"); - mhi_initiate_m0(mhi_dev_ctxt); - } else { - mhi_log(MHI_MSG_INFO, "Pending resume, quitting.\n"); - } -} - int mhi_initiate_m0(struct mhi_device_ctxt *mhi_dev_ctxt) { int r = 0; @@ -939,7 +920,6 @@ int mhi_initiate_m0(struct mhi_device_ctxt *mhi_dev_ctxt) write_unlock_irqrestore(&mhi_dev_ctxt->xfer_lock, flags); } exit: - atomic_set(&mhi_dev_ctxt->flags.m0_work_enabled, 0); mutex_unlock(&mhi_dev_ctxt->pm_lock); mhi_log(MHI_MSG_INFO, "Exited...\n"); return r; @@ -949,7 +929,7 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt) { unsigned long flags; - int r; + int r = 0; int abort_m3 = 0; mhi_log(MHI_MSG_INFO, @@ -982,6 +962,7 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt) if (0 == r || -ERESTARTSYS == r) { mhi_log(MHI_MSG_INFO, "MDM failed to come out of M2.\n"); + r = -EAGAIN; goto exit; } break; @@ -991,7 +972,7 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_dev_ctxt->mhi_state, mhi_dev_ctxt->flags.link_up); if (mhi_dev_ctxt->flags.link_up) - r = -EPERM; + r = -EAGAIN; else r = 0; goto exit; @@ -1009,11 +990,13 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt) __pm_stay_awake(&mhi_dev_ctxt->w_lock); __pm_relax(&mhi_dev_ctxt->w_lock); abort_m3 = 1; + r = -EAGAIN; goto exit; } if (atomic_read(&mhi_dev_ctxt->flags.data_pending)) { abort_m3 = 1; + r = -EAGAIN; goto exit; } r = hrtimer_cancel(&mhi_dev_ctxt->m1_timer); @@ -1025,9 +1008,7 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt) write_lock_irqsave(&mhi_dev_ctxt->xfer_lock, flags); if (mhi_dev_ctxt->flags.pending_M0) { write_unlock_irqrestore(&mhi_dev_ctxt->xfer_lock, flags); - mhi_log(MHI_MSG_INFO, - "Pending M0 detected, aborting M3 procedure\n"); - r = -EPERM; + r = -EAGAIN; goto exit; } mhi_dev_ctxt->flags.pending_M3 = 1; @@ -1072,7 +1053,6 @@ exit: ring_all_chan_dbs(mhi_dev_ctxt); atomic_dec(&mhi_dev_ctxt->flags.data_pending); } - atomic_set(&mhi_dev_ctxt->flags.m3_work_enabled, 0); mhi_dev_ctxt->flags.pending_M3 = 0; mutex_unlock(&mhi_dev_ctxt->pm_lock); return r; diff --git a/drivers/platform/msm/mhi/mhi_sys.c b/drivers/platform/msm/mhi/mhi_sys.c index 07cd5f8b03c6..53cdc8828b92 100644 --- a/drivers/platform/msm/mhi/mhi_sys.c +++ b/drivers/platform/msm/mhi/mhi_sys.c @@ -39,9 +39,6 @@ MODULE_PARM_DESC(mhi_ipc_log_lvl, "dbg lvl"); module_param(mhi_msg_class , uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(mhi_msg_class, "dbg class"); -u32 m3_timer_val_ms = 1000; -module_param(m3_timer_val_ms, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(m3_timer_val_ms, "timer val"); static ssize_t mhi_dbgfs_chan_read(struct file *fp, char __user *buf, size_t count, loff_t *offp) |
