From 78f1bef7e5c36957377fe874e0381948597f92a2 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Fri, 13 May 2016 15:26:50 -0700 Subject: mhi: core: Protect DB register when handling DB MODE Possibility exist when handling a DB MODE event another core to queue a TRE to same channel. During that time CC ctxt WP may get updated, however DB MODE event thread still be using a stale WP. Add a lock to synchronize DB MODE event thread and queue TRE thread. CRs-Fixed: 1005752 Change-Id: I7f285da8751a867a1c3d651466537368799eb657 Signed-off-by: Sujeev Dias --- drivers/platform/msm/mhi/mhi_main.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/msm/mhi/mhi_main.c b/drivers/platform/msm/mhi/mhi_main.c index c949745f5af7..a061d4ab50cb 100644 --- a/drivers/platform/msm/mhi/mhi_main.c +++ b/drivers/platform/msm/mhi/mhi_main.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1166,6 +1166,7 @@ int parse_xfer_event(struct mhi_device_ctxt *ctxt, { struct mhi_ring *chan_ctxt = NULL; u64 db_value = 0; + unsigned long flags; mhi_dev_ctxt->flags.uldl_enabled = 1; chan = MHI_EV_READ_CHID(EV_CHID, event); @@ -1173,6 +1174,8 @@ int parse_xfer_event(struct mhi_device_ctxt *ctxt, chan_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; mhi_log(MHI_MSG_INFO, "DB_MODE/OOB Detected chan %d.\n", chan); + spin_lock_irqsave(&mhi_dev_ctxt->db_write_lock[chan], + flags); if (chan_ctxt->wp != chan_ctxt->rp) { db_value = mhi_v2p_addr(mhi_dev_ctxt, MHI_RING_TYPE_XFER_RING, chan, @@ -1182,8 +1185,10 @@ int parse_xfer_event(struct mhi_device_ctxt *ctxt, db_value); } client_handle = mhi_dev_ctxt->client_handle_list[chan]; - if (NULL != client_handle) - result->transaction_status = -ENOTCONN; + if (client_handle) + result->transaction_status = -ENOTCONN; + spin_unlock_irqrestore(&mhi_dev_ctxt->db_write_lock[chan], + flags); break; } case MHI_EVENT_CC_BAD_TRE: -- cgit v1.2.3 From fc63288a51cdf39b1bf147bdf26f5311518a77d2 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Mon, 16 May 2016 16:05:52 -0700 Subject: mhi: core: change logs to print MHI_STATEs in text Instead of printing enum index convert MHI_STATE enum to text representation for easier interpretation of debug logs. CRs-Fixed: 1012249 Change-Id: I97a9a7ff293c739531d8197334a0f0a35bf20419 Signed-off-by: Sujeev Dias --- drivers/platform/msm/mhi/mhi_main.c | 13 +++-- drivers/platform/msm/mhi/mhi_pm.c | 11 ++-- drivers/platform/msm/mhi/mhi_states.c | 98 ++++++++++++++++++++++------------- drivers/platform/msm/mhi/mhi_sys.c | 15 +++++- drivers/platform/msm/mhi/mhi_sys.h | 4 ++ 5 files changed, 92 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/msm/mhi/mhi_main.c b/drivers/platform/msm/mhi/mhi_main.c index a061d4ab50cb..a8da2f9ef9fb 100644 --- a/drivers/platform/msm/mhi/mhi_main.c +++ b/drivers/platform/msm/mhi/mhi_main.c @@ -520,9 +520,9 @@ static inline int mhi_queue_tre(struct mhi_device_ctxt } } else { mhi_log(MHI_MSG_VERBOSE, - "Wakeup, pending data state %d chan state %d\n", - mhi_dev_ctxt->mhi_state, - chan_ctxt->mhi_chan_state); + "Wakeup, pending data state %s chan state %d\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), + chan_ctxt->mhi_chan_state); ret_val = 0; } return ret_val; @@ -766,10 +766,9 @@ int mhi_send_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, } mhi_log(MHI_MSG_INFO, - "Entered, MHI state %d dev_exec_env %d chan %d cmd %d\n", - mhi_dev_ctxt->mhi_state, - mhi_dev_ctxt->dev_exec_env, - chan, cmd); + "Entered, MHI state %s dev_exec_env %d chan %d cmd %d\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), + mhi_dev_ctxt->dev_exec_env, chan, cmd); mhi_log(MHI_MSG_INFO, "Getting Reference %d", chan); pm_runtime_get(&mhi_dev_ctxt->dev_info->pcie_device->dev); /* diff --git a/drivers/platform/msm/mhi/mhi_pm.c b/drivers/platform/msm/mhi/mhi_pm.c index a928c05b805a..d62d4189d3f3 100644 --- a/drivers/platform/msm/mhi/mhi_pm.c +++ b/drivers/platform/msm/mhi/mhi_pm.c @@ -46,8 +46,8 @@ int mhi_pci_suspend(struct device *dev) if (NULL == mhi_dev_ctxt) return -EINVAL; - mhi_log(MHI_MSG_INFO, "Entered, MHI state %d\n", - mhi_dev_ctxt->mhi_state); + mhi_log(MHI_MSG_INFO, "Entered, MHI state %s\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); atomic_set(&mhi_dev_ctxt->flags.pending_resume, 1); r = mhi_initiate_m3(mhi_dev_ctxt); @@ -115,7 +115,8 @@ int mhi_pci_resume(struct device *dev) break; default: mhi_log(MHI_MSG_INFO, - "Wait complete state: %d\n", mhi_dev_ctxt->mhi_state); + "Wait complete state: %s\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); r = 0; } exit: @@ -181,8 +182,8 @@ ssize_t sysfs_init_m0(struct device *dev, struct device_attribute *attr, } mhi_initiate_m0(mhi_dev_ctxt); mhi_log(MHI_MSG_CRITICAL, - "Current mhi_state = 0x%x\n", - mhi_dev_ctxt->mhi_state); + "Current mhi_state = %s\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); return count; } diff --git a/drivers/platform/msm/mhi/mhi_states.c b/drivers/platform/msm/mhi/mhi_states.c index ca4520a3c57d..63007a991d4c 100644 --- a/drivers/platform/msm/mhi/mhi_states.c +++ b/drivers/platform/msm/mhi/mhi_states.c @@ -17,6 +17,29 @@ #include #include +static const char *state_transition_str(enum STATE_TRANSITION state) +{ + static const char * const mhi_states_transition_str[] = { + "RESET", + "READY", + "M0", + "M1", + "M2", + "M3", + "BHI", + "SBL", + "AMSS", + "LINK_DOWN", + "WAKE" + }; + + if (state == STATE_TRANSITION_SYS_ERR) + return "SYS_ERR"; + + return (state <= STATE_TRANSITION_WAKE) ? + mhi_states_transition_str[state] : "Invalid"; +} + static inline void mhi_set_m_state(struct mhi_device_ctxt *mhi_dev_ctxt, enum MHI_STATE new_state) { @@ -150,8 +173,9 @@ static int process_m0_transition( "Transitioning from M1.\n"); } else { mhi_log(MHI_MSG_INFO, - "MHI State %d link state %d. Quitting\n", - mhi_dev_ctxt->mhi_state, mhi_dev_ctxt->flags.link_up); + "MHI State %s link state %d. Quitting\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), + mhi_dev_ctxt->flags.link_up); } read_lock_irqsave(&mhi_dev_ctxt->xfer_lock, flags); @@ -196,8 +220,8 @@ static int process_m1_transition( int r = 0; mhi_log(MHI_MSG_INFO, - "Processing M1 state transition from state %d\n", - mhi_dev_ctxt->mhi_state); + "Processing M1 state transition from state %s\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); write_lock_irqsave(&mhi_dev_ctxt->xfer_lock, flags); if (!mhi_dev_ctxt->flags.pending_M3) { @@ -444,8 +468,8 @@ static int process_reset_transition( STATE_TRANSITION_RESET); if (0 != r) mhi_log(MHI_MSG_CRITICAL, - "Failed to initiate 0x%x state trans\n", - STATE_TRANSITION_RESET); + "Failed to initiate %s state trans\n", + state_transition_str(STATE_TRANSITION_RESET)); break; default: mhi_log(MHI_MSG_CRITICAL, @@ -475,8 +499,8 @@ static int process_reset_transition( STATE_TRANSITION_READY); if (0 != r) mhi_log(MHI_MSG_CRITICAL, - "Failed to initiate 0x%x state trans\n", - STATE_TRANSITION_READY); + "Failed to initiate %s state trans\n", + state_transition_str(STATE_TRANSITION_READY)); return r; } @@ -636,8 +660,8 @@ int mhi_trigger_reset(struct mhi_device_ctxt *mhi_dev_ctxt) STATE_TRANSITION_RESET); if (0 != r) mhi_log(MHI_MSG_CRITICAL, - "Failed to initiate 0x%x state trans ret %d\n", - STATE_TRANSITION_RESET, r); + "Failed to initiate %s state trans ret %d\n", + state_transition_str(STATE_TRANSITION_RESET), r); mhi_log(MHI_MSG_INFO, "Exiting\n"); return r; } @@ -648,8 +672,8 @@ static int process_stt_work_item( { int r = 0; - mhi_log(MHI_MSG_INFO, "Transitioning to %d\n", - (int)cur_work_item); + mhi_log(MHI_MSG_INFO, "Transitioning to %s\n", + state_transition_str(cur_work_item)); trace_mhi_state(cur_work_item); switch (cur_work_item) { case STATE_TRANSITION_BHI: @@ -689,7 +713,8 @@ static int process_stt_work_item( break; default: mhi_log(MHI_MSG_ERROR, - "Unrecongized state: %d\n", cur_work_item); + "Unrecongized state: %s\n", + state_transition_str(cur_work_item)); break; } return r; @@ -762,8 +787,8 @@ int mhi_init_state_transition(struct mhi_device_ctxt *mhi_dev_ctxt, BUG_ON(nr_avail_work_items <= 0); mhi_log(MHI_MSG_VERBOSE, - "Processing state transition %x\n", - new_state); + "Processing state transition %s\n", + state_transition_str(new_state)); *(enum STATE_TRANSITION *)stt_ring->wp = new_state; r = ctxt_add_element(stt_ring, (void **)&cur_work_item); BUG_ON(r); @@ -778,13 +803,14 @@ int mhi_initiate_m0(struct mhi_device_ctxt *mhi_dev_ctxt) unsigned long flags; mhi_log(MHI_MSG_INFO, - "Entered MHI state %d, Pending M0 %d Pending M3 %d\n", - mhi_dev_ctxt->mhi_state, mhi_dev_ctxt->flags.pending_M0, - mhi_dev_ctxt->flags.pending_M3); + "Entered MHI state %s, Pending M0 %d Pending M3 %d\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), + mhi_dev_ctxt->flags.pending_M0, + mhi_dev_ctxt->flags.pending_M3); mutex_lock(&mhi_dev_ctxt->pm_lock); mhi_log(MHI_MSG_INFO, - "Waiting for M0 M1 or M3. Currently %d...\n", - mhi_dev_ctxt->mhi_state); + "Waiting for M0 M1 or M3. Currently %s...\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); r = wait_event_interruptible_timeout(*mhi_dev_ctxt->mhi_ev_wq.m3_event, mhi_dev_ctxt->mhi_state == MHI_STATE_M3 || @@ -794,9 +820,9 @@ int mhi_initiate_m0(struct mhi_device_ctxt *mhi_dev_ctxt) switch (r) { case 0: mhi_log(MHI_MSG_CRITICAL, - "Timeout: State %d after %d ms\n", - mhi_dev_ctxt->mhi_state, - MHI_MAX_SUSPEND_TIMEOUT); + "Timeout: State %s after %d ms\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), + MHI_MAX_SUSPEND_TIMEOUT); mhi_dev_ctxt->counters.m0_event_timeouts++; r = -ETIME; goto exit; @@ -806,7 +832,8 @@ int mhi_initiate_m0(struct mhi_device_ctxt *mhi_dev_ctxt) goto exit; default: mhi_log(MHI_MSG_INFO, - "Wait complete state: %d\n", mhi_dev_ctxt->mhi_state); + "Wait complete state: %s\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); r = 0; break; } @@ -814,8 +841,8 @@ int mhi_initiate_m0(struct mhi_device_ctxt *mhi_dev_ctxt) mhi_dev_ctxt->mhi_state == MHI_STATE_M1) { mhi_assert_device_wake(mhi_dev_ctxt); mhi_log(MHI_MSG_INFO, - "MHI state %d, done\n", - mhi_dev_ctxt->mhi_state); + "MHI state %s, done\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state)); goto exit; } else { if (0 != mhi_turn_on_pcie_link(mhi_dev_ctxt)) { @@ -864,9 +891,10 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt) int r = 0, abort_m3 = 0; mhi_log(MHI_MSG_INFO, - "Entered MHI state %d, Pending M0 %d Pending M3 %d\n", - mhi_dev_ctxt->mhi_state, mhi_dev_ctxt->flags.pending_M0, - mhi_dev_ctxt->flags.pending_M3); + "Entered MHI state %s, Pending M0 %d Pending M3 %d\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), + mhi_dev_ctxt->flags.pending_M0, + mhi_dev_ctxt->flags.pending_M3); mutex_lock(&mhi_dev_ctxt->pm_lock); switch (mhi_dev_ctxt->mhi_state) { case MHI_STATE_RESET: @@ -906,9 +934,9 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt) break; case MHI_STATE_M3: mhi_log(MHI_MSG_INFO, - "MHI state %d, link state %d.\n", - mhi_dev_ctxt->mhi_state, - mhi_dev_ctxt->flags.link_up); + "MHI state %s, link state %d.\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), + mhi_dev_ctxt->flags.link_up); if (mhi_dev_ctxt->flags.link_up) r = -EAGAIN; else @@ -916,9 +944,9 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt) goto exit; default: mhi_log(MHI_MSG_INFO, - "MHI state %d, link state %d.\n", - mhi_dev_ctxt->mhi_state, - mhi_dev_ctxt->flags.link_up); + "MHI state %s, link state %d.\n", + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), + mhi_dev_ctxt->flags.link_up); break; } while (atomic_read(&mhi_dev_ctxt->counters.outbound_acks)) { diff --git a/drivers/platform/msm/mhi/mhi_sys.c b/drivers/platform/msm/mhi/mhi_sys.c index b8652770275e..3a13e6a51609 100644 --- a/drivers/platform/msm/mhi/mhi_sys.c +++ b/drivers/platform/msm/mhi/mhi_sys.c @@ -34,6 +34,17 @@ MODULE_PARM_DESC(mhi_msg_lvl, "dbg lvl"); module_param(mhi_ipc_log_lvl, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(mhi_ipc_log_lvl, "dbg lvl"); +const char * const mhi_states_str[MHI_STATE_LIMIT] = { + "RESET", + "READY", + "M0", + "M1", + "M2", + "M3", + "BHI", + "SYS_ERR", +}; + static ssize_t mhi_dbgfs_chan_read(struct file *fp, char __user *buf, size_t count, loff_t *offp) { @@ -225,9 +236,9 @@ static ssize_t mhi_dbgfs_state_read(struct file *fp, char __user *buf, amnt_copied = scnprintf(mhi_dev_ctxt->chan_info, MHI_LOG_SIZE, - "%s %u %s %d %s %d %s %d %s %d %s %d %s %d %s %d %s %d %s %d %s %d, %s, %d, %s %d\n", + "%s %s %s %d %s %d %s %d %s %d %s %d %s %d %s %d %s %d %s %d %s %d, %s, %d, %s %d\n", "Our State:", - mhi_dev_ctxt->mhi_state, + TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), "M0->M1:", mhi_dev_ctxt->counters.m0_m1, "M0<-M1:", diff --git a/drivers/platform/msm/mhi/mhi_sys.h b/drivers/platform/msm/mhi/mhi_sys.h index 765fd46ef2dd..a948a2354de7 100644 --- a/drivers/platform/msm/mhi/mhi_sys.h +++ b/drivers/platform/msm/mhi/mhi_sys.h @@ -46,6 +46,10 @@ extern void *mhi_ipc_log; "[%s] " _msg, __func__, ##__VA_ARGS__); \ } while (0) +extern const char * const mhi_states_str[MHI_STATE_LIMIT]; +#define TO_MHI_STATE_STR(state) (((state) >= MHI_STATE_LIMIT) ? \ + "INVALID_STATE" : mhi_states_str[state]) + irqreturn_t mhi_msi_handlr(int msi_number, void *dev_id); struct mhi_meminfo { -- cgit v1.2.3 From 667012017d56d7edea10d33b68d95f7f5876e788 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Sun, 1 May 2016 14:45:56 -0700 Subject: msm: mhi: fix error handling Validate the channel prior to proceeding further. Unlock spin lock before jumping to error handler. CRs-Fixed: 1016969 Change-Id: Ie3328f878b582a333ae15f3b950c258ec42fd768 Signed-off-by: Sujeev Dias --- drivers/net/ethernet/msm/msm_rmnet_mhi.c | 4 +++- drivers/platform/msm/mhi/mhi_main.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ethernet/msm/msm_rmnet_mhi.c b/drivers/net/ethernet/msm/msm_rmnet_mhi.c index a55a26be4273..50d8e72a96c8 100644 --- a/drivers/net/ethernet/msm/msm_rmnet_mhi.c +++ b/drivers/net/ethernet/msm/msm_rmnet_mhi.c @@ -625,6 +625,9 @@ static int rmnet_mhi_xmit(struct sk_buff *skb, struct net_device *dev) tx_ring_full_count[rmnet_mhi_ptr->dev_index]++; netif_stop_queue(dev); rmnet_log(MSG_VERBOSE, "Stopping Queue\n"); + write_unlock_irqrestore( + &rmnet_mhi_ptr->out_chan_full_lock, + flags); goto rmnet_mhi_xmit_error_cleanup; } else { retry = 1; @@ -652,7 +655,6 @@ static int rmnet_mhi_xmit(struct sk_buff *skb, struct net_device *dev) rmnet_mhi_xmit_error_cleanup: rmnet_log(MSG_VERBOSE, "Ring full\n"); - write_unlock_irqrestore(&rmnet_mhi_ptr->out_chan_full_lock, flags); return NETDEV_TX_BUSY; } diff --git a/drivers/platform/msm/mhi/mhi_main.c b/drivers/platform/msm/mhi/mhi_main.c index a8da2f9ef9fb..a1d6dfd4be4d 100644 --- a/drivers/platform/msm/mhi/mhi_main.c +++ b/drivers/platform/msm/mhi/mhi_main.c @@ -1397,8 +1397,10 @@ static int start_chan_cmd(struct mhi_device_ctxt *mhi_dev_ctxt, u32 chan; MHI_TRB_GET_INFO(CMD_TRB_CHID, cmd_pkt, chan); - if (!VALID_CHAN_NR(chan)) + if (!VALID_CHAN_NR(chan)) { mhi_log(MHI_MSG_ERROR, "Bad chan: 0x%x\n", chan); + return -EINVAL; + } mhi_dev_ctxt->mhi_chan_pend_cmd_ack[chan] = MHI_CMD_NOT_PENDING; mhi_log(MHI_MSG_INFO, "Processed START CMD chan %d\n", chan); -- cgit v1.2.3 From ac489269bb2aa1daaaa59b58f2133a2ea096397f Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Thu, 24 Mar 2016 13:54:37 -0700 Subject: mhi: core: add memory barrier after ring operations There are instances when MHI channel context read pointer can be accessed simultaneously by different CPU cores. To make sure read pointer updates visible to all cores, add a memory barrier after completion of MHI ring operation. CRs-Fixed: 966338 Change-Id: Ifc8c4cd7595fed9049009c42420a665fb170079f Signed-off-by: Sujeev Dias --- drivers/platform/msm/mhi/mhi_ring_ops.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/msm/mhi/mhi_ring_ops.c b/drivers/platform/msm/mhi/mhi_ring_ops.c index e5a6dd51f51a..7063053ca841 100644 --- a/drivers/platform/msm/mhi/mhi_ring_ops.c +++ b/drivers/platform/msm/mhi/mhi_ring_ops.c @@ -48,6 +48,9 @@ static int add_element(struct mhi_ring *ring, void **rp, *assigned_addr = (char *)ring->wp; *wp = (void *)(((d_wp + 1) % ring_size) * ring->el_size + (uintptr_t)ring->base); + + /* force update visible to other cores */ + smp_wmb(); return 0; } @@ -101,6 +104,9 @@ int delete_element(struct mhi_ring *ring, void **rp, *rp = (void *)(((d_rp + 1) % ring_size) * ring->el_size + (uintptr_t)ring->base); + + /* force update visible to other cores */ + smp_wmb(); return 0; } -- cgit v1.2.3 From 683cb7801ea873103b09008db6c13c73adec2829 Mon Sep 17 00:00:00 2001 From: Tony Truong Date: Mon, 28 Mar 2016 18:30:44 -0700 Subject: mhi: core: Lock MHI_M3 state transition To avoid any race conditions between MHI_M2 state transition and MHI_M3 state transition lock the entire MHI_M3 transition using xfer_lock. CRs-Fixed: 972390 Change-Id: I7c2e1b7b3966dc5fb8bf2f91bce734bbc58c6fd7 Signed-off-by: Tony Truong Signed-off-by: Sujeev Dias --- drivers/platform/msm/mhi/mhi_states.c | 48 ++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/msm/mhi/mhi_states.c b/drivers/platform/msm/mhi/mhi_states.c index 63007a991d4c..b841d51d1f1d 100644 --- a/drivers/platform/msm/mhi/mhi_states.c +++ b/drivers/platform/msm/mhi/mhi_states.c @@ -909,27 +909,31 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt) case MHI_STATE_M0: case MHI_STATE_M1: case MHI_STATE_M2: + write_lock_irqsave(&mhi_dev_ctxt->xfer_lock, flags); mhi_log(MHI_MSG_INFO, "Triggering wake out of M2\n"); - write_lock_irqsave(&mhi_dev_ctxt->xfer_lock, flags); mhi_dev_ctxt->flags.pending_M3 = 1; if ((atomic_read(&mhi_dev_ctxt->flags.m2_transition)) == 0) { mhi_log(MHI_MSG_INFO, "M2 transition not set\n"); mhi_assert_device_wake(mhi_dev_ctxt); } - write_unlock_irqrestore(&mhi_dev_ctxt->xfer_lock, flags); - r = wait_event_interruptible_timeout( + + if (mhi_dev_ctxt->mhi_state == MHI_STATE_M2) { + write_unlock_irqrestore(&mhi_dev_ctxt->xfer_lock, + flags); + r = wait_event_interruptible_timeout( *mhi_dev_ctxt->mhi_ev_wq.m0_event, - mhi_dev_ctxt->mhi_state == MHI_STATE_M0 || - mhi_dev_ctxt->mhi_state == MHI_STATE_M1, + mhi_dev_ctxt->mhi_state == MHI_STATE_M0, msecs_to_jiffies(MHI_MAX_RESUME_TIMEOUT)); - if (0 == r || -ERESTARTSYS == r) { - mhi_log(MHI_MSG_CRITICAL, - "MDM failed to come out of M2.\n"); - mhi_dev_ctxt->counters.m2_event_timeouts++; - r = -EAGAIN; - goto exit; + write_lock_irqsave(&mhi_dev_ctxt->xfer_lock, flags); + if (0 == r || -ERESTARTSYS == r) { + mhi_log(MHI_MSG_CRITICAL, + "MDM failed to come out of M2.\n"); + mhi_dev_ctxt->counters.m2_event_timeouts++; + r = -EAGAIN; + goto unlock; + } } break; case MHI_STATE_M3: @@ -943,13 +947,15 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt) r = 0; goto exit; default: + write_lock_irqsave(&mhi_dev_ctxt->xfer_lock, flags); mhi_log(MHI_MSG_INFO, "MHI state %s, link state %d.\n", TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), mhi_dev_ctxt->flags.link_up); break; } - while (atomic_read(&mhi_dev_ctxt->counters.outbound_acks)) { + + if (atomic_read(&mhi_dev_ctxt->counters.outbound_acks)) { mhi_log(MHI_MSG_INFO, "There are still %d acks pending from device\n", atomic_read(&mhi_dev_ctxt->counters.outbound_acks)); @@ -957,25 +963,23 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt) __pm_relax(&mhi_dev_ctxt->w_lock); abort_m3 = 1; r = -EAGAIN; - goto exit; + goto unlock; } if (atomic_read(&mhi_dev_ctxt->flags.data_pending)) { abort_m3 = 1; r = -EAGAIN; - goto exit; + goto unlock; } - 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); r = -EAGAIN; - goto exit; + goto unlock; } mhi_dev_ctxt->flags.pending_M3 = 1; mhi_set_m_state(mhi_dev_ctxt, MHI_STATE_M3); write_unlock_irqrestore(&mhi_dev_ctxt->xfer_lock, flags); - mhi_log(MHI_MSG_INFO, "Waiting for M3 completion.\n"); r = wait_event_interruptible_timeout(*mhi_dev_ctxt->mhi_ev_wq.m3_event, @@ -998,16 +1002,20 @@ int mhi_initiate_m3(struct mhi_device_ctxt *mhi_dev_ctxt) r = mhi_set_bus_request(mhi_dev_ctxt, 0); if (r) mhi_log(MHI_MSG_INFO, "Failed to set bus freq ret %d\n", r); -exit: + goto exit; +unlock: + mhi_dev_ctxt->flags.pending_M3 = 0; if (abort_m3) { - write_lock_irqsave(&mhi_dev_ctxt->xfer_lock, flags); atomic_inc(&mhi_dev_ctxt->flags.data_pending); write_unlock_irqrestore(&mhi_dev_ctxt->xfer_lock, flags); ring_all_chan_dbs(mhi_dev_ctxt); ring_all_cmd_dbs(mhi_dev_ctxt); atomic_dec(&mhi_dev_ctxt->flags.data_pending); mhi_deassert_device_wake(mhi_dev_ctxt); + } else { + write_unlock_irqrestore(&mhi_dev_ctxt->xfer_lock, flags); } +exit: mhi_dev_ctxt->flags.pending_M3 = 0; mutex_unlock(&mhi_dev_ctxt->pm_lock); return r; -- cgit v1.2.3 From 8526dcd42590d3d4d87b4141996e03b25023d1fc Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Wed, 1 Jun 2016 17:06:57 -0700 Subject: mhi: core: Do not reset doorbell mode during MHI_M3 abort In order to avoid being out of sync between MHI client and MHI host, host shall not reset the doorbell modes for hardware channels during MHI_M3 state transition abort. CRs-Fixed: 1023725 Change-Id: I6c742fc968fd57d71a86039bf1f3f65b1362bc90 Signed-off-by: Sujeev Dias --- drivers/platform/msm/mhi/mhi_states.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/msm/mhi/mhi_states.c b/drivers/platform/msm/mhi/mhi_states.c index b841d51d1f1d..5dca3b65e38d 100644 --- a/drivers/platform/msm/mhi/mhi_states.c +++ b/drivers/platform/msm/mhi/mhi_states.c @@ -80,7 +80,8 @@ static void conditional_chan_db_write( spin_unlock_irqrestore(&mhi_dev_ctxt->db_write_lock[chan], flags); } -static void ring_all_chan_dbs(struct mhi_device_ctxt *mhi_dev_ctxt) +static void ring_all_chan_dbs(struct mhi_device_ctxt *mhi_dev_ctxt, + bool reset_db_mode) { u32 i = 0; struct mhi_ring *local_ctxt = NULL; @@ -89,7 +90,7 @@ static void ring_all_chan_dbs(struct mhi_device_ctxt *mhi_dev_ctxt) for (i = 0; i < MHI_MAX_CHANNELS; ++i) if (VALID_CHAN_NR(i)) { local_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[i]; - if (IS_HARDWARE_CHANNEL(i)) + if (IS_HARDWARE_CHANNEL(i) && reset_db_mode) mhi_dev_ctxt->flags.db_mode[i] = 1; if ((local_ctxt->wp != local_ctxt->rp) || ((local_ctxt->wp != local_ctxt->rp) && @@ -186,7 +187,7 @@ static int process_m0_transition( if (mhi_dev_ctxt->flags.mhi_initialized) { ring_all_ev_dbs(mhi_dev_ctxt); - ring_all_chan_dbs(mhi_dev_ctxt); + ring_all_chan_dbs(mhi_dev_ctxt, true); ring_all_cmd_dbs(mhi_dev_ctxt); } atomic_dec(&mhi_dev_ctxt->flags.data_pending); @@ -618,7 +619,7 @@ static int process_amss_transition( "Failed to set local chan state ret %d\n", r); return r; } - ring_all_chan_dbs(mhi_dev_ctxt); + ring_all_chan_dbs(mhi_dev_ctxt, true); mhi_log(MHI_MSG_INFO, "Notifying clients that MHI is enabled\n"); enable_clients(mhi_dev_ctxt, mhi_dev_ctxt->dev_exec_env); @@ -632,7 +633,7 @@ static int process_amss_transition( i, r); return r; } - ring_all_chan_dbs(mhi_dev_ctxt); + ring_all_chan_dbs(mhi_dev_ctxt, true); } ring_all_ev_dbs(mhi_dev_ctxt); atomic_dec(&mhi_dev_ctxt->flags.data_pending); @@ -1008,7 +1009,7 @@ unlock: if (abort_m3) { atomic_inc(&mhi_dev_ctxt->flags.data_pending); write_unlock_irqrestore(&mhi_dev_ctxt->xfer_lock, flags); - ring_all_chan_dbs(mhi_dev_ctxt); + ring_all_chan_dbs(mhi_dev_ctxt, false); ring_all_cmd_dbs(mhi_dev_ctxt); atomic_dec(&mhi_dev_ctxt->flags.data_pending); mhi_deassert_device_wake(mhi_dev_ctxt); -- cgit v1.2.3 From 4267834dd4fac5c576f650a5c3d0f4bf937de562 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Tue, 31 May 2016 19:07:48 -0700 Subject: mhi: core: Preserve DB Mode state during lpm When exiting low power modes (M3) do not reset the DB Mode state if DB mode preserve flag is set for channel. CRs-Fixed: 1022868 Change-Id: I6557d28afe9d0ac11b76c683ffba76d7d6ffd377 Signed-off-by: Sujeev Dias --- drivers/platform/msm/mhi/mhi.h | 11 +++++++++-- drivers/platform/msm/mhi/mhi_init.c | 28 ++++++++++++++++------------ drivers/platform/msm/mhi/mhi_macros.h | 4 ++++ drivers/platform/msm/mhi/mhi_main.c | 25 +++++++++++++++---------- drivers/platform/msm/mhi/mhi_states.c | 12 +++++++----- 5 files changed, 51 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/msm/mhi/mhi.h b/drivers/platform/msm/mhi/mhi.h index c6fa39d6e0e2..3ecc7ce5df1e 100644 --- a/drivers/platform/msm/mhi/mhi.h +++ b/drivers/platform/msm/mhi/mhi.h @@ -261,6 +261,12 @@ enum MHI_EVENT_CCS { MHI_EVENT_CC_BAD_TRE = 0x11, }; +struct db_mode { + /* if set do not reset DB_Mode during M0 resume */ + u32 preserve_db_state : 1; + u32 db_mode : 1; +}; + struct mhi_ring { void *base; void *wp; @@ -270,6 +276,7 @@ struct mhi_ring { uintptr_t el_size; u32 overwrite_en; enum MHI_CHAN_DIR dir; + struct db_mode db_mode; }; enum MHI_CMD_STATUS { @@ -414,7 +421,6 @@ struct mhi_flags { u32 ev_thread_stopped; u32 st_thread_stopped; u32 uldl_enabled; - u32 db_mode[MHI_MAX_CHANNELS]; }; struct mhi_wait_queues { @@ -577,7 +583,8 @@ int mhi_init_chan_ctxt(struct mhi_chan_ctxt *cc_list, enum MHI_CHAN_DIR chan_type, u32 event_ring, struct mhi_ring *ring, - enum MHI_CHAN_STATE chan_state); + enum MHI_CHAN_STATE chan_state, + bool preserve_db_state); int mhi_populate_event_cfg(struct mhi_device_ctxt *mhi_dev_ctxt); int mhi_get_event_ring_for_channel(struct mhi_device_ctxt *mhi_dev_ctxt, u32 chan); diff --git a/drivers/platform/msm/mhi/mhi_init.c b/drivers/platform/msm/mhi/mhi_init.c index 93c3de35473b..2982bd0831c7 100644 --- a/drivers/platform/msm/mhi/mhi_init.c +++ b/drivers/platform/msm/mhi/mhi_init.c @@ -585,21 +585,23 @@ error_during_props: /** * @brief Initialize the channel context and shadow context * - * @cc_list: Context to initialize - * @trb_list_phy: Physical base address for the TRE ring - * @trb_list_virt: Virtual base address for the TRE ring - * @el_per_ring: Number of TREs this ring will contain - * @chan_type: Type of channel IN/OUT - * @event_ring: Event ring to be mapped to this channel context - * @ring: Shadow context to be initialized alongside - * + * @cc_list: Context to initialize + * @trb_list_phy: Physical base address for the TRE ring + * @trb_list_virt: Virtual base address for the TRE ring + * @el_per_ring: Number of TREs this ring will contain + * @chan_type: Type of channel IN/OUT + * @event_ring: Event ring to be mapped to this channel context + * @ring: Shadow context to be initialized alongside + * @chan_state: Channel state + * @preserve_db_state: Do not reset DB state during resume * @Return errno */ int mhi_init_chan_ctxt(struct mhi_chan_ctxt *cc_list, - uintptr_t trb_list_phy, uintptr_t trb_list_virt, - u64 el_per_ring, enum MHI_CHAN_DIR chan_type, - u32 event_ring, struct mhi_ring *ring, - enum MHI_CHAN_STATE chan_state) + uintptr_t trb_list_phy, uintptr_t trb_list_virt, + u64 el_per_ring, enum MHI_CHAN_DIR chan_type, + u32 event_ring, struct mhi_ring *ring, + enum MHI_CHAN_STATE chan_state, + bool preserve_db_state) { cc_list->mhi_chan_state = chan_state; cc_list->mhi_chan_type = chan_type; @@ -617,6 +619,8 @@ int mhi_init_chan_ctxt(struct mhi_chan_ctxt *cc_list, ring->el_size = sizeof(struct mhi_tx_pkt); ring->overwrite_en = 0; ring->dir = chan_type; + ring->db_mode.db_mode = 1; + ring->db_mode.preserve_db_state = (preserve_db_state) ? 1 : 0; /* Flush writes to MMIO */ wmb(); return 0; diff --git a/drivers/platform/msm/mhi/mhi_macros.h b/drivers/platform/msm/mhi/mhi_macros.h index bb47f53e244d..6701f3761aaa 100644 --- a/drivers/platform/msm/mhi/mhi_macros.h +++ b/drivers/platform/msm/mhi/mhi_macros.h @@ -244,6 +244,10 @@ #define MHI_CHAN_TYPE__MASK (3) #define MHI_CHAN_TYPE__SHIFT (6) +#define PRESERVE_DB_STATE +#define MHI_PRESERVE_DB_STATE__MASK (1) +#define MHI_PRESERVE_DB_STATE__SHIFT (8) + #define GET_CHAN_PROPS(_FIELD, _VAL) \ (((_VAL) >> MHI_##_FIELD ## __SHIFT) & MHI_##_FIELD ## __MASK) diff --git a/drivers/platform/msm/mhi/mhi_main.c b/drivers/platform/msm/mhi/mhi_main.c index a1d6dfd4be4d..bc5f305e580b 100644 --- a/drivers/platform/msm/mhi/mhi_main.c +++ b/drivers/platform/msm/mhi/mhi_main.c @@ -212,7 +212,7 @@ int mhi_release_chan_ctxt(struct mhi_device_ctxt *mhi_dev_ctxt, ring->len, ring->base, cc_list->mhi_trb_ring_base_addr); mhi_init_chan_ctxt(cc_list, 0, 0, 0, 0, 0, ring, - MHI_CHAN_STATE_DISABLED); + MHI_CHAN_STATE_DISABLED, false); return 0; } @@ -259,7 +259,9 @@ static int populate_tre_ring(struct mhi_client_handle *client_handle) client_handle->chan_info.flags), client_handle->chan_info.ev_ring, &mhi_dev_ctxt->mhi_local_chan_ctxt[chan], - MHI_CHAN_STATE_ENABLED); + MHI_CHAN_STATE_ENABLED, + GET_CHAN_PROPS(PRESERVE_DB_STATE, + client_handle->chan_info.flags)); mhi_log(MHI_MSG_INFO, "Exited\n"); return 0; } @@ -654,6 +656,7 @@ static int mhi_queue_dma_xfer( MHI_ASSERT(VALID_BUF(buf, buf_len, mhi_dev_ctxt), "Client buffer is of invalid length\n"); chan = client_handle->chan_info.chan_nr; + mhi_log(MHI_MSG_INFO, "Getting Reference %d", chan); pm_runtime_get(&mhi_dev_ctxt->dev_info->pcie_device->dev); @@ -698,6 +701,7 @@ static int mhi_queue_dma_xfer( error: pm_runtime_mark_last_busy(&mhi_dev_ctxt->dev_info->pcie_device->dev); + mhi_log(MHI_MSG_INFO, "Putting Reference %d", chan); pm_runtime_put_noidle(&mhi_dev_ctxt->dev_info->pcie_device->dev); return ret_val; @@ -1169,12 +1173,13 @@ int parse_xfer_event(struct mhi_device_ctxt *ctxt, mhi_dev_ctxt->flags.uldl_enabled = 1; chan = MHI_EV_READ_CHID(EV_CHID, event); - mhi_dev_ctxt->flags.db_mode[chan] = 1; chan_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; + mhi_log(MHI_MSG_INFO, "DB_MODE/OOB Detected chan %d.\n", chan); spin_lock_irqsave(&mhi_dev_ctxt->db_write_lock[chan], flags); + chan_ctxt->db_mode.db_mode = 1; if (chan_ctxt->wp != chan_ctxt->rp) { db_value = mhi_v2p_addr(mhi_dev_ctxt, MHI_RING_TYPE_XFER_RING, chan, @@ -1658,6 +1663,8 @@ void mhi_process_db(struct mhi_device_ctxt *mhi_dev_ctxt, void __iomem *io_addr, uintptr_t chan, u32 val) { + struct mhi_ring *chan_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan]; + mhi_log(MHI_MSG_VERBOSE, "db.set addr: %p io_offset 0x%lx val:0x%x\n", io_addr, chan, val); @@ -1668,14 +1675,14 @@ void mhi_process_db(struct mhi_device_ctxt *mhi_dev_ctxt, if (io_addr == mhi_dev_ctxt->mmio_info.chan_db_addr) { if (!(IS_HARDWARE_CHANNEL(chan) && mhi_dev_ctxt->flags.uldl_enabled && - !mhi_dev_ctxt->flags.db_mode[chan])) { + !chan_ctxt->db_mode.db_mode)) { mhi_write_db(mhi_dev_ctxt, io_addr, chan, val); - mhi_dev_ctxt->flags.db_mode[chan] = 0; + chan_ctxt->db_mode.db_mode = 0; } else { mhi_log(MHI_MSG_INFO, - "Not ringing xfer db, chan %ld, ul_dl %d db_mode %d\n", - chan, mhi_dev_ctxt->flags.uldl_enabled, - mhi_dev_ctxt->flags.db_mode[chan]); + "Not ringing xfer db, chan %ld, ul_dl %d db_mode %d\n", + chan, mhi_dev_ctxt->flags.uldl_enabled, + chan_ctxt->db_mode.db_mode); } /* Event Doorbell and Polling mode Disabled */ } else if (io_addr == mhi_dev_ctxt->mmio_info.event_db_addr) { @@ -1683,11 +1690,9 @@ void mhi_process_db(struct mhi_device_ctxt *mhi_dev_ctxt, if (IS_SW_EV_RING(mhi_dev_ctxt, chan) || !mhi_dev_ctxt->flags.uldl_enabled) { mhi_write_db(mhi_dev_ctxt, io_addr, chan, val); - mhi_dev_ctxt->flags.db_mode[chan] = 0; } } else { mhi_write_db(mhi_dev_ctxt, io_addr, chan, val); - mhi_dev_ctxt->flags.db_mode[chan] = 0; } } diff --git a/drivers/platform/msm/mhi/mhi_states.c b/drivers/platform/msm/mhi/mhi_states.c index 5dca3b65e38d..f0404da98cf7 100644 --- a/drivers/platform/msm/mhi/mhi_states.c +++ b/drivers/platform/msm/mhi/mhi_states.c @@ -90,11 +90,13 @@ static void ring_all_chan_dbs(struct mhi_device_ctxt *mhi_dev_ctxt, for (i = 0; i < MHI_MAX_CHANNELS; ++i) if (VALID_CHAN_NR(i)) { local_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[i]; - if (IS_HARDWARE_CHANNEL(i) && reset_db_mode) - mhi_dev_ctxt->flags.db_mode[i] = 1; - if ((local_ctxt->wp != local_ctxt->rp) || - ((local_ctxt->wp != local_ctxt->rp) && - (local_ctxt->dir == MHI_IN))) + + /* Reset the DB Mode state to DB Mode */ + if (local_ctxt->db_mode.preserve_db_state == 0 + && reset_db_mode) + local_ctxt->db_mode.db_mode = 1; + + if (local_ctxt->wp != local_ctxt->rp) conditional_chan_db_write(mhi_dev_ctxt, i); } } -- cgit v1.2.3 From 3d25629c67df204e768d90c047eebc0ae0793239 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Thu, 7 Jul 2016 13:10:08 -0700 Subject: mhi: core: add missing MHI state Add missing state MHI_STATE_RESERVE to MHI states look up table. CRs-Fixed: 1049595 Change-Id: I9a6bd2750f81f6cabc1e7b5aff488b4a01f7897d Signed-off-by: Sujeev Dias --- drivers/platform/msm/mhi/mhi_sys.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/platform/msm/mhi/mhi_sys.c b/drivers/platform/msm/mhi/mhi_sys.c index 3a13e6a51609..e38e82beef88 100644 --- a/drivers/platform/msm/mhi/mhi_sys.c +++ b/drivers/platform/msm/mhi/mhi_sys.c @@ -41,6 +41,7 @@ const char * const mhi_states_str[MHI_STATE_LIMIT] = { "M1", "M2", "M3", + "Reserved: 0x06", "BHI", "SYS_ERR", }; -- cgit v1.2.3 From 0f889f7e46e6451f82efe66d599fee7cb8acf971 Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Mon, 29 Aug 2016 18:56:30 -0700 Subject: msm: mhi: Check bb ring and transfer ring when checking for space When checking for available spaces, check available spaces on both bounce buffer ring and transfer ring and return min. Change-Id: I9208b46c32821de3f5d9e3d828087d7bc29b9546 CRs-Fixed: 1055681 Signed-off-by: Sujeev Dias --- drivers/platform/msm/mhi/mhi_ring_ops.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/msm/mhi/mhi_ring_ops.c b/drivers/platform/msm/mhi/mhi_ring_ops.c index 7063053ca841..07d0098a1b61 100644 --- a/drivers/platform/msm/mhi/mhi_ring_ops.c +++ b/drivers/platform/msm/mhi/mhi_ring_ops.c @@ -114,6 +114,7 @@ int mhi_get_free_desc(struct mhi_client_handle *client_handle) { u32 chan; struct mhi_device_ctxt *ctxt; + int bb_ring, ch_ring; if (!client_handle || MHI_HANDLE_MAGIC != client_handle->magic || !client_handle->mhi_dev_ctxt) @@ -121,7 +122,10 @@ int mhi_get_free_desc(struct mhi_client_handle *client_handle) ctxt = client_handle->mhi_dev_ctxt; chan = client_handle->chan_info.chan_nr; - return get_nr_avail_ring_elements(&ctxt->mhi_local_chan_ctxt[chan]); + bb_ring = get_nr_avail_ring_elements(&ctxt->chan_bb_list[chan]); + ch_ring = get_nr_avail_ring_elements(&ctxt->mhi_local_chan_ctxt[chan]); + + return min(bb_ring, ch_ring); } EXPORT_SYMBOL(mhi_get_free_desc); -- cgit v1.2.3 From 219eb1102331910ed033033fae7b4793fb4f0f7e Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Tue, 27 Sep 2016 11:52:29 -0700 Subject: mhi: core: Do not clear transaction status MHI transaction status stores the OVERFLOW status received from device. MHI clients uses this status to determine overflow buffers, do not clear the status. CRs-Fixed: 1042516 Change-Id: Iaaff06c1c39775d6a33ca17851f1e1579b2a2ecb Signed-off-by: Sujeev Dias --- drivers/platform/msm/mhi/mhi_main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/msm/mhi/mhi_main.c b/drivers/platform/msm/mhi/mhi_main.c index bc5f305e580b..6da133ce8e04 100644 --- a/drivers/platform/msm/mhi/mhi_main.c +++ b/drivers/platform/msm/mhi/mhi_main.c @@ -873,7 +873,6 @@ static void parse_inbound_bb(struct mhi_device_ctxt *mhi_dev_ctxt, result->buf_addr = bb->client_buf; result->bytes_xferd = bb->filled_size; - result->transaction_status = 0; /* At this point the bounce buffer is no longer necessary * Whatever was received from the device was copied back to the -- cgit v1.2.3 From fcfe80f8cc31bcb80e6cb201b3ab89ba94ebae4e Mon Sep 17 00:00:00 2001 From: Sujeev Dias Date: Tue, 13 Sep 2016 16:55:01 -0700 Subject: mhi: core: Add support for new MHI hardware channel Add support for new MHI hardware channel 102 to be use by MHI clients as ADPL channel. CRs-Fixed: 1027069 Change-Id: Ib3c2019fc269064d097bb7f40f01d4580e63a603 Signed-off-by: Sujeev Dias --- drivers/platform/msm/mhi/mhi.h | 10 ++-------- drivers/platform/msm/mhi/mhi_hwio.h | 18 +++++++++--------- drivers/platform/msm/mhi/mhi_isr.c | 26 ++++++++++++++------------ drivers/platform/msm/mhi/mhi_macros.h | 1 - drivers/platform/msm/mhi/mhi_mmio_ops.c | 5 +++++ drivers/platform/msm/mhi/mhi_sys.c | 6 +----- include/linux/msm_mhi.h | 5 +++-- 7 files changed, 34 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/msm/mhi/mhi.h b/drivers/platform/msm/mhi/mhi.h index 3ecc7ce5df1e..6919a97116ab 100644 --- a/drivers/platform/msm/mhi/mhi.h +++ b/drivers/platform/msm/mhi/mhi.h @@ -277,6 +277,8 @@ struct mhi_ring { u32 overwrite_en; enum MHI_CHAN_DIR dir; struct db_mode db_mode; + u32 msi_disable_cntr; + u32 msi_enable_cntr; }; enum MHI_CMD_STATUS { @@ -351,12 +353,6 @@ struct mhi_client_handle { int event_ring_index; }; -enum MHI_EVENT_POLLING { - MHI_EVENT_POLLING_DISABLED = 0x0, - MHI_EVENT_POLLING_ENABLED = 0x1, - MHI_EVENT_POLLING_reserved = 0x80000000 -}; - enum MHI_TYPE_EVENT_RING { MHI_ER_DATA_TYPE = 0x1, MHI_ER_CTRL_TYPE = 0x2, @@ -393,8 +389,6 @@ struct mhi_counters { u32 m3_event_timeouts; u32 m0_event_timeouts; u32 m2_event_timeouts; - u32 msi_disable_cntr; - u32 msi_enable_cntr; u32 nr_irq_migrations; u32 *msi_counter; u32 *ev_counter; diff --git a/drivers/platform/msm/mhi/mhi_hwio.h b/drivers/platform/msm/mhi/mhi_hwio.h index 370ee0ebab7e..88a6a74566e6 100644 --- a/drivers/platform/msm/mhi/mhi_hwio.h +++ b/drivers/platform/msm/mhi/mhi_hwio.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -23,14 +23,14 @@ #define MHICFG (0x10) -#define MHICFG_RESERVED_BITS31_24_MASK 0xff000000 -#define MHICFG_RESERVED_BITS31_24_SHIFT 0x18 -#define MHICFG_NER_MASK 0xff0000 -#define MHICFG_NER_SHIFT 0x10 -#define MHICFG_RESERVED_BITS15_8_MASK 0xff00 -#define MHICFG_RESERVED_BITS15_8_SHIFT 0x8 -#define MHICFG_NCH_MASK 0xff -#define MHICFG_NCH_SHIFT 0x0 +#define MHICFG_NHWER_MASK (0xff000000) +#define MHICFG_NHWER_SHIFT (24) +#define MHICFG_NER_MASK (0xff0000) +#define MHICFG_NER_SHIFT (16) +#define MHICFG_NHWCH_MASK (0xff00) +#define MHICFG_NHWCH_SHIFT (8) +#define MHICFG_NCH_MASK (0xff) +#define MHICFG_NCH_SHIFT (0) #define CHDBOFF (0x18) diff --git a/drivers/platform/msm/mhi/mhi_isr.c b/drivers/platform/msm/mhi/mhi_isr.c index 5336b9ff0c11..04778a360289 100644 --- a/drivers/platform/msm/mhi/mhi_isr.c +++ b/drivers/platform/msm/mhi/mhi_isr.c @@ -277,20 +277,22 @@ struct mhi_result *mhi_poll(struct mhi_client_handle *client_handle) void mhi_mask_irq(struct mhi_client_handle *client_handle) { - disable_irq_nosync(MSI_TO_IRQ(client_handle->mhi_dev_ctxt, - client_handle->msi_vec)); - client_handle->mhi_dev_ctxt->counters.msi_disable_cntr++; - if (client_handle->mhi_dev_ctxt->counters.msi_disable_cntr > - (client_handle->mhi_dev_ctxt->counters.msi_enable_cntr + 1)) - mhi_log(MHI_MSG_INFO, "No nested IRQ disable Allowed\n"); + struct mhi_device_ctxt *mhi_dev_ctxt = + client_handle->mhi_dev_ctxt; + struct mhi_ring *ev_ring = &mhi_dev_ctxt-> + mhi_local_event_ctxt[client_handle->event_ring_index]; + + disable_irq_nosync(MSI_TO_IRQ(mhi_dev_ctxt, client_handle->msi_vec)); + ev_ring->msi_disable_cntr++; } void mhi_unmask_irq(struct mhi_client_handle *client_handle) { - client_handle->mhi_dev_ctxt->counters.msi_enable_cntr++; - enable_irq(MSI_TO_IRQ(client_handle->mhi_dev_ctxt, - client_handle->msi_vec)); - if (client_handle->mhi_dev_ctxt->counters.msi_enable_cntr > - client_handle->mhi_dev_ctxt->counters.msi_disable_cntr) - mhi_log(MHI_MSG_INFO, "No nested IRQ enable Allowed\n"); + struct mhi_device_ctxt *mhi_dev_ctxt = + client_handle->mhi_dev_ctxt; + struct mhi_ring *ev_ring = &mhi_dev_ctxt-> + mhi_local_event_ctxt[client_handle->event_ring_index]; + + ev_ring->msi_enable_cntr++; + enable_irq(MSI_TO_IRQ(mhi_dev_ctxt, client_handle->msi_vec)); } diff --git a/drivers/platform/msm/mhi/mhi_macros.h b/drivers/platform/msm/mhi/mhi_macros.h index 6701f3761aaa..6f9ed293e6dd 100644 --- a/drivers/platform/msm/mhi/mhi_macros.h +++ b/drivers/platform/msm/mhi/mhi_macros.h @@ -96,7 +96,6 @@ ((_mhi_dev_ctxt)->mmio_info.nr_event_rings - \ ((_mhi_dev_ctxt)->mmio_info.nr_hw_event_rings))) - /* MHI Transfer Ring Elements 7.4.1*/ #define TX_TRB_LEN #define MHI_TX_TRB_LEN__SHIFT (0) diff --git a/drivers/platform/msm/mhi/mhi_mmio_ops.c b/drivers/platform/msm/mhi/mhi_mmio_ops.c index ddf18e466cd3..6f56587a172b 100644 --- a/drivers/platform/msm/mhi/mhi_mmio_ops.c +++ b/drivers/platform/msm/mhi/mhi_mmio_ops.c @@ -144,6 +144,11 @@ int mhi_init_mmio(struct mhi_device_ctxt *mhi_dev_ctxt) MHICFG, MHICFG_NER_MASK, MHICFG_NER_SHIFT, mhi_dev_ctxt->mmio_info.nr_event_rings); + mhi_reg_write_field(mhi_dev_ctxt, mhi_dev_ctxt->mmio_info.mmio_addr, + MHICFG, + MHICFG_NHWER_MASK, + MHICFG_NHWER_SHIFT, + mhi_dev_ctxt->mmio_info.nr_hw_event_rings); pcie_dword_val = mhi_dev_ctxt->dev_space.ring_ctxt.dma_cc_list; pcie_word_val = HIGH_WORD(pcie_dword_val); diff --git a/drivers/platform/msm/mhi/mhi_sys.c b/drivers/platform/msm/mhi/mhi_sys.c index e38e82beef88..3316b2694896 100644 --- a/drivers/platform/msm/mhi/mhi_sys.c +++ b/drivers/platform/msm/mhi/mhi_sys.c @@ -237,7 +237,7 @@ static ssize_t mhi_dbgfs_state_read(struct file *fp, char __user *buf, amnt_copied = scnprintf(mhi_dev_ctxt->chan_info, MHI_LOG_SIZE, - "%s %s %s %d %s %d %s %d %s %d %s %d %s %d %s %d %s %d %s %d %s %d, %s, %d, %s %d\n", + "%s %s %s %d %s %d %s %d %s %d %s %d %s %d %s %d %s %d %s %d %s %d\n", "Our State:", TO_MHI_STATE_STR(mhi_dev_ctxt->mhi_state), "M0->M1:", @@ -256,10 +256,6 @@ static ssize_t mhi_dbgfs_state_read(struct file *fp, char __user *buf, mhi_dev_ctxt->counters.m3_event_timeouts, "M0_ev_TO:", mhi_dev_ctxt->counters.m0_event_timeouts, - "MSI_d:", - mhi_dev_ctxt->counters.msi_disable_cntr, - "MSI_e:", - mhi_dev_ctxt->counters.msi_enable_cntr, "outstanding_acks:", atomic_read(&mhi_dev_ctxt->counters.outbound_acks), "LPM:", diff --git a/include/linux/msm_mhi.h b/include/linux/msm_mhi.h index b8b2226940a4..263b8bba9e2c 100644 --- a/include/linux/msm_mhi.h +++ b/include/linux/msm_mhi.h @@ -63,9 +63,10 @@ enum MHI_CLIENT_CHANNEL { MHI_CLIENT_RESERVED_1_UPPER = 99, MHI_CLIENT_IP_HW_0_OUT = 100, MHI_CLIENT_IP_HW_0_IN = 101, - MHI_CLIENT_RESERVED_2_LOWER = 102, + MHI_CLIENT_IP_HW_ADPL_IN = 102, + MHI_CLIENT_RESERVED_2_LOWER = 103, MHI_CLIENT_RESERVED_2_UPPER = 127, - MHI_MAX_CHANNELS = 102 + MHI_MAX_CHANNELS = 103 }; enum MHI_CB_REASON { -- cgit v1.2.3