/** * @brief Reset for a single MHI channel * * @param device [IN ] context * @param chan_id [IN ] channel id of the channel to reset * * @return MHI_STATUS */ MHI_STATUS mhi_reset_channel(mhi_client_handle *client_handle) { MHI_STATUS ret_val; mhi_chan_ctxt *cur_ctxt = NULL; mhi_device_ctxt *mhi_dev_ctxt = NULL; u32 chan_id = 0; mhi_ring *cur_ring = NULL; chan_id = client_handle->chan; mhi_dev_ctxt = client_handle->mhi_dev_ctxt; if (chan_id > (MHI_MAX_CHANNELS - 1) || NULL == mhi_dev_ctxt) { mhi_log(MHI_MSG_ERROR, "Bad input parameters\n"); return MHI_STATUS_ERROR; } mutex_lock(&mhi_dev_ctxt->mhi_chan_mutex[chan_id]); /* We need to reset the channel completley, we will assume that our * base is correct*/ cur_ctxt = &mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list[chan_id]; cur_ring = &mhi_dev_ctxt->mhi_local_event_ctxt[chan_id]; memset(cur_ring->base, 0, sizeof(char)*cur_ring->len); if (IS_HARDWARE_CHANNEL(chan_id)) { ret_val = mhi_init_chan_ctxt(cur_ctxt, mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)cur_ring->base), (uintptr_t)cur_ring->base, MAX_NR_TRBS_PER_HARD_CHAN, (chan_id % 2) ? MHI_IN : MHI_OUT, (chan_id % 2) ? IPA_IN_EV_RING : IPA_OUT_EV_RING, cur_ring); } else { ret_val = mhi_init_chan_ctxt(cur_ctxt, mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)cur_ring->base), (uintptr_t)cur_ring->base, MAX_NR_TRBS_PER_SOFT_CHAN, (chan_id % 2) ? MHI_IN : MHI_OUT, SOFTWARE_EV_RING, cur_ring); } if (MHI_STATUS_SUCCESS != ret_val) mhi_log(MHI_MSG_ERROR, "Failed to reset chan ctxt\n"); mutex_unlock(&mhi_dev_ctxt->mhi_chan_mutex[chan_id]); return ret_val; }
static enum MHI_STATUS mhi_init_contexts(struct mhi_device_ctxt *mhi_dev_ctxt) { u32 i = 0; struct mhi_control_seg *mhi_ctrl = mhi_dev_ctxt->mhi_ctrl_seg; struct mhi_event_ctxt *event_ctxt = NULL; u32 event_ring_index = 0; union mhi_xfer_pkt *trb_list = NULL; struct mhi_chan_ctxt *chan_ctxt = NULL; struct mhi_ring *local_event_ctxt = NULL; u32 msi_vec = 0; u32 intmod_t = 0; uintptr_t ev_ring_addr; for (i = 0; i < EVENT_RINGS_ALLOCATED; ++i) { MHI_GET_EVENT_RING_INFO(EVENT_RING_MSI_VEC, mhi_dev_ctxt->ev_ring_props[i], msi_vec); switch (i) { case IPA_OUT_EV_RING: intmod_t = 10; break; case IPA_IN_EV_RING: intmod_t = 6; break; } event_ring_index = mhi_dev_ctxt->alloced_ev_rings[i]; event_ctxt = &mhi_ctrl->mhi_ec_list[event_ring_index]; local_event_ctxt = &mhi_dev_ctxt->mhi_local_event_ctxt[event_ring_index]; ev_ring_addr = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_ctrl->ev_trb_list[i]); mhi_log(MHI_MSG_VERBOSE, "Setting msi_vec 0x%x, for ev ring ctxt 0x%x\n", msi_vec, event_ring_index); mhi_event_ring_init(event_ctxt, ev_ring_addr, (uintptr_t)mhi_ctrl->ev_trb_list[i], EV_EL_PER_RING, local_event_ctxt, intmod_t, msi_vec); } /* Init Command Ring */ mhi_cmd_ring_init(&mhi_ctrl->mhi_cmd_ctxt_list[PRIMARY_CMD_RING], mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_ctrl->cmd_trb_list[PRIMARY_CMD_RING]), (uintptr_t)mhi_ctrl->cmd_trb_list[PRIMARY_CMD_RING], CMD_EL_PER_RING, &mhi_dev_ctxt->mhi_local_cmd_ctxt[PRIMARY_CMD_RING]); mhi_log(MHI_MSG_INFO, "Initializing contexts\n"); /* Initialize Channel Contexts */ for (i = 0; i < MHI_MAX_CHANNELS; ++i) { trb_list = mhi_dev_ctxt->mhi_ctrl_seg->xfer_trb_list[i]; chan_ctxt = &mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list[i]; if (IS_SOFTWARE_CHANNEL(i)) { mhi_init_chan_ctxt(chan_ctxt, mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)trb_list), (uintptr_t)trb_list, MAX_NR_TRBS_PER_SOFT_CHAN, (i % 2) ? MHI_IN : MHI_OUT, 0, &mhi_dev_ctxt->mhi_local_chan_ctxt[i]); } else if (IS_HARDWARE_CHANNEL(i)) { mhi_init_chan_ctxt(chan_ctxt, mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)trb_list), (uintptr_t)trb_list, MAX_NR_TRBS_PER_HARD_CHAN, (i % 2) ? MHI_IN : MHI_OUT, i, &mhi_dev_ctxt->mhi_local_chan_ctxt[i]); } } mhi_dev_ctxt->mhi_state = MHI_STATE_RESET; return MHI_STATUS_SUCCESS; }