Loading drivers/bus/mhi/core/mhi_init.c +3 −0 Original line number Diff line number Diff line Loading @@ -346,6 +346,9 @@ void mhi_destroy_sysfs(struct mhi_controller *mhi_cntrl) } spin_unlock(&mhi_tsync->lock); if (mhi_tsync->db_response_pending) complete(&mhi_tsync->db_completion); kfree(mhi_cntrl->mhi_tsync); mhi_cntrl->mhi_tsync = NULL; mutex_unlock(&mhi_cntrl->tsync_mutex); Loading drivers/bus/mhi/core/mhi_internal.h +2 −0 Original line number Diff line number Diff line Loading @@ -727,8 +727,10 @@ struct mhi_timesync { void __iomem *time_reg; u32 int_sequence; u64 local_time; u64 remote_time; bool db_support; bool db_response_pending; struct completion db_completion; spinlock_t lock; /* list protection */ struct list_head head; }; Loading drivers/bus/mhi/core/mhi_main.c +49 −21 Original line number Diff line number Diff line Loading @@ -1402,6 +1402,10 @@ int mhi_process_tsync_ev_ring(struct mhi_controller *mhi_cntrl, if (unlikely(mhi_tsync->int_sequence != sequence)) { MHI_ASSERT(1, "Unexpected response:0x%llx Expected:0x%llx\n", sequence, mhi_tsync->int_sequence); mhi_device_put(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); mutex_unlock(&mhi_cntrl->tsync_mutex); goto exit_tsync_process; } Loading @@ -1427,6 +1431,11 @@ int mhi_process_tsync_ev_ring(struct mhi_controller *mhi_cntrl, } while (true); mhi_tsync->db_response_pending = false; mhi_tsync->remote_time = remote_time; complete(&mhi_tsync->db_completion); mhi_device_put(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); mutex_unlock(&mhi_cntrl->tsync_mutex); exit_tsync_process: Loading Loading @@ -1484,13 +1493,10 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl, read_unlock_bh(&mhi_cntrl->pm_lock); spin_unlock_bh(&mhi_event->lock); atomic_inc(&mhi_cntrl->pending_pkts); ret = mhi_device_get_sync(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); if (ret) { atomic_dec(&mhi_cntrl->pending_pkts); if (ret) goto exit_bw_scale_process; } mutex_lock(&mhi_cntrl->pm_mutex); Loading @@ -1508,7 +1514,6 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl, read_unlock_bh(&mhi_cntrl->pm_lock); mhi_device_put(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); atomic_dec(&mhi_cntrl->pending_pkts); mutex_unlock(&mhi_cntrl->pm_mutex); Loading Loading @@ -2502,13 +2507,37 @@ int mhi_get_remote_time_sync(struct mhi_device *mhi_dev, { struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; struct mhi_timesync *mhi_tsync = mhi_cntrl->mhi_tsync; u64 local_time; int ret; mutex_lock(&mhi_cntrl->tsync_mutex); /* not all devices support time features */ if (!mhi_tsync) { ret = -EIO; goto error_unlock; if (!mhi_tsync) return -EINVAL; if (unlikely(MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))) { MHI_ERR("MHI is not in active state, pm_state:%s\n", to_mhi_pm_state_str(mhi_cntrl->pm_state)); return -EIO; } mutex_lock(&mhi_cntrl->tsync_mutex); /* return times from last async request completion */ if (mhi_tsync->db_response_pending) { local_time = mhi_tsync->local_time; mutex_unlock(&mhi_cntrl->tsync_mutex); ret = wait_for_completion_timeout(&mhi_tsync->db_completion, msecs_to_jiffies(mhi_cntrl->timeout_ms)); if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) || !ret) { MHI_ERR("Pending DB request did not complete, abort\n"); return -EAGAIN; } *t_host = local_time; *t_dev = mhi_tsync->remote_time; return 0; } /* bring to M0 state */ Loading Loading @@ -2581,14 +2610,13 @@ int mhi_get_remote_time(struct mhi_device *mhi_dev, int ret = 0; /* not all devices support all time features */ if (!mhi_tsync || !mhi_tsync->db_support) return -EINVAL; mutex_lock(&mhi_cntrl->tsync_mutex); if (!mhi_tsync || !mhi_tsync->db_support) { ret = -EIO; goto error_unlock; } /* tsync db can only be rung in M0 state */ ret = __mhi_device_get_sync(mhi_cntrl); ret = mhi_device_get_sync(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); if (ret) goto error_unlock; Loading Loading @@ -2656,21 +2684,21 @@ int mhi_get_remote_time(struct mhi_device *mhi_dev, MHI_VERB("time DB request with seq:0x%llx\n", mhi_tsync->int_sequence); mhi_tsync->db_response_pending = true; init_completion(&mhi_tsync->db_completion); skip_tsync_db: spin_lock(&mhi_tsync->lock); list_add_tail(&tsync_node->node, &mhi_tsync->head); spin_unlock(&mhi_tsync->lock); ret = 0; mutex_unlock(&mhi_cntrl->tsync_mutex); return 0; error_invalid_state: if (ret) kfree(tsync_node); error_no_mem: read_lock_bh(&mhi_cntrl->pm_lock); mhi_cntrl->wake_put(mhi_cntrl, false); read_unlock_bh(&mhi_cntrl->pm_lock); mhi_device_put(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); error_unlock: mutex_unlock(&mhi_cntrl->tsync_mutex); return ret; Loading drivers/bus/mhi/core/mhi_pm.c +5 −2 Original line number Diff line number Diff line Loading @@ -1241,6 +1241,7 @@ int mhi_pm_fast_suspend(struct mhi_controller *mhi_cntrl, bool notify_client) int ret; enum MHI_PM_STATE new_state; struct mhi_chan *itr, *tmp; struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev; read_lock_bh(&mhi_cntrl->pm_lock); if (mhi_cntrl->pm_state == MHI_PM_DISABLE) { Loading @@ -1255,7 +1256,8 @@ int mhi_pm_fast_suspend(struct mhi_controller *mhi_cntrl, bool notify_client) read_unlock_bh(&mhi_cntrl->pm_lock); /* do a quick check to see if any pending votes to keep us busy */ if (atomic_read(&mhi_cntrl->pending_pkts)) { if (atomic_read(&mhi_cntrl->pending_pkts) || atomic_read(&mhi_dev->bus_vote)) { MHI_VERB("Busy, aborting M3\n"); return -EBUSY; } Loading @@ -1274,7 +1276,8 @@ int mhi_pm_fast_suspend(struct mhi_controller *mhi_cntrl, bool notify_client) * Check the votes once more to see if we should abort * suspend. */ if (atomic_read(&mhi_cntrl->pending_pkts)) { if (atomic_read(&mhi_cntrl->pending_pkts) || atomic_read(&mhi_dev->bus_vote)) { MHI_VERB("Busy, aborting M3\n"); ret = -EBUSY; goto error_suspend; Loading Loading
drivers/bus/mhi/core/mhi_init.c +3 −0 Original line number Diff line number Diff line Loading @@ -346,6 +346,9 @@ void mhi_destroy_sysfs(struct mhi_controller *mhi_cntrl) } spin_unlock(&mhi_tsync->lock); if (mhi_tsync->db_response_pending) complete(&mhi_tsync->db_completion); kfree(mhi_cntrl->mhi_tsync); mhi_cntrl->mhi_tsync = NULL; mutex_unlock(&mhi_cntrl->tsync_mutex); Loading
drivers/bus/mhi/core/mhi_internal.h +2 −0 Original line number Diff line number Diff line Loading @@ -727,8 +727,10 @@ struct mhi_timesync { void __iomem *time_reg; u32 int_sequence; u64 local_time; u64 remote_time; bool db_support; bool db_response_pending; struct completion db_completion; spinlock_t lock; /* list protection */ struct list_head head; }; Loading
drivers/bus/mhi/core/mhi_main.c +49 −21 Original line number Diff line number Diff line Loading @@ -1402,6 +1402,10 @@ int mhi_process_tsync_ev_ring(struct mhi_controller *mhi_cntrl, if (unlikely(mhi_tsync->int_sequence != sequence)) { MHI_ASSERT(1, "Unexpected response:0x%llx Expected:0x%llx\n", sequence, mhi_tsync->int_sequence); mhi_device_put(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); mutex_unlock(&mhi_cntrl->tsync_mutex); goto exit_tsync_process; } Loading @@ -1427,6 +1431,11 @@ int mhi_process_tsync_ev_ring(struct mhi_controller *mhi_cntrl, } while (true); mhi_tsync->db_response_pending = false; mhi_tsync->remote_time = remote_time; complete(&mhi_tsync->db_completion); mhi_device_put(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); mutex_unlock(&mhi_cntrl->tsync_mutex); exit_tsync_process: Loading Loading @@ -1484,13 +1493,10 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl, read_unlock_bh(&mhi_cntrl->pm_lock); spin_unlock_bh(&mhi_event->lock); atomic_inc(&mhi_cntrl->pending_pkts); ret = mhi_device_get_sync(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); if (ret) { atomic_dec(&mhi_cntrl->pending_pkts); if (ret) goto exit_bw_scale_process; } mutex_lock(&mhi_cntrl->pm_mutex); Loading @@ -1508,7 +1514,6 @@ int mhi_process_bw_scale_ev_ring(struct mhi_controller *mhi_cntrl, read_unlock_bh(&mhi_cntrl->pm_lock); mhi_device_put(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); atomic_dec(&mhi_cntrl->pending_pkts); mutex_unlock(&mhi_cntrl->pm_mutex); Loading Loading @@ -2502,13 +2507,37 @@ int mhi_get_remote_time_sync(struct mhi_device *mhi_dev, { struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; struct mhi_timesync *mhi_tsync = mhi_cntrl->mhi_tsync; u64 local_time; int ret; mutex_lock(&mhi_cntrl->tsync_mutex); /* not all devices support time features */ if (!mhi_tsync) { ret = -EIO; goto error_unlock; if (!mhi_tsync) return -EINVAL; if (unlikely(MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))) { MHI_ERR("MHI is not in active state, pm_state:%s\n", to_mhi_pm_state_str(mhi_cntrl->pm_state)); return -EIO; } mutex_lock(&mhi_cntrl->tsync_mutex); /* return times from last async request completion */ if (mhi_tsync->db_response_pending) { local_time = mhi_tsync->local_time; mutex_unlock(&mhi_cntrl->tsync_mutex); ret = wait_for_completion_timeout(&mhi_tsync->db_completion, msecs_to_jiffies(mhi_cntrl->timeout_ms)); if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) || !ret) { MHI_ERR("Pending DB request did not complete, abort\n"); return -EAGAIN; } *t_host = local_time; *t_dev = mhi_tsync->remote_time; return 0; } /* bring to M0 state */ Loading Loading @@ -2581,14 +2610,13 @@ int mhi_get_remote_time(struct mhi_device *mhi_dev, int ret = 0; /* not all devices support all time features */ if (!mhi_tsync || !mhi_tsync->db_support) return -EINVAL; mutex_lock(&mhi_cntrl->tsync_mutex); if (!mhi_tsync || !mhi_tsync->db_support) { ret = -EIO; goto error_unlock; } /* tsync db can only be rung in M0 state */ ret = __mhi_device_get_sync(mhi_cntrl); ret = mhi_device_get_sync(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); if (ret) goto error_unlock; Loading Loading @@ -2656,21 +2684,21 @@ int mhi_get_remote_time(struct mhi_device *mhi_dev, MHI_VERB("time DB request with seq:0x%llx\n", mhi_tsync->int_sequence); mhi_tsync->db_response_pending = true; init_completion(&mhi_tsync->db_completion); skip_tsync_db: spin_lock(&mhi_tsync->lock); list_add_tail(&tsync_node->node, &mhi_tsync->head); spin_unlock(&mhi_tsync->lock); ret = 0; mutex_unlock(&mhi_cntrl->tsync_mutex); return 0; error_invalid_state: if (ret) kfree(tsync_node); error_no_mem: read_lock_bh(&mhi_cntrl->pm_lock); mhi_cntrl->wake_put(mhi_cntrl, false); read_unlock_bh(&mhi_cntrl->pm_lock); mhi_device_put(mhi_cntrl->mhi_dev, MHI_VOTE_DEVICE | MHI_VOTE_BUS); error_unlock: mutex_unlock(&mhi_cntrl->tsync_mutex); return ret; Loading
drivers/bus/mhi/core/mhi_pm.c +5 −2 Original line number Diff line number Diff line Loading @@ -1241,6 +1241,7 @@ int mhi_pm_fast_suspend(struct mhi_controller *mhi_cntrl, bool notify_client) int ret; enum MHI_PM_STATE new_state; struct mhi_chan *itr, *tmp; struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev; read_lock_bh(&mhi_cntrl->pm_lock); if (mhi_cntrl->pm_state == MHI_PM_DISABLE) { Loading @@ -1255,7 +1256,8 @@ int mhi_pm_fast_suspend(struct mhi_controller *mhi_cntrl, bool notify_client) read_unlock_bh(&mhi_cntrl->pm_lock); /* do a quick check to see if any pending votes to keep us busy */ if (atomic_read(&mhi_cntrl->pending_pkts)) { if (atomic_read(&mhi_cntrl->pending_pkts) || atomic_read(&mhi_dev->bus_vote)) { MHI_VERB("Busy, aborting M3\n"); return -EBUSY; } Loading @@ -1274,7 +1276,8 @@ int mhi_pm_fast_suspend(struct mhi_controller *mhi_cntrl, bool notify_client) * Check the votes once more to see if we should abort * suspend. */ if (atomic_read(&mhi_cntrl->pending_pkts)) { if (atomic_read(&mhi_cntrl->pending_pkts) || atomic_read(&mhi_dev->bus_vote)) { MHI_VERB("Busy, aborting M3\n"); ret = -EBUSY; goto error_suspend; Loading