static void mhi_move_interrupts(mhi_device_ctxt *mhi_dev_ctxt, u32 cpu) { u32 irq_to_affin = 0; MHI_GET_EVENT_RING_INFO(EVENT_RING_MSI_VEC, mhi_dev_ctxt->ev_ring_props[IPA_IN_EV_RING], irq_to_affin); irq_to_affin += mhi_dev_ctxt->dev_props->irq_base; irq_set_affinity(irq_to_affin, get_cpu_mask(cpu)); MHI_GET_EVENT_RING_INFO(EVENT_RING_MSI_VEC, mhi_dev_ctxt->ev_ring_props[IPA_OUT_EV_RING], irq_to_affin); irq_to_affin += mhi_dev_ctxt->dev_props->irq_base; irq_set_affinity(irq_to_affin, get_cpu_mask(cpu)); }
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; }
/** * @brief Add elements to event ring for the device to use * * @param mhi device context * * @return MHI_STATUS */ MHI_STATUS mhi_add_elements_to_event_rings(mhi_device_ctxt *mhi_dev_ctxt, STATE_TRANSITION new_state) { MHI_STATUS ret_val = MHI_STATUS_SUCCESS; MHI_EVENT_RING_STATE event_ring_state = MHI_EVENT_RING_UINIT; switch (new_state) { case STATE_TRANSITION_READY: MHI_GET_EVENT_RING_INFO(EVENT_RING_STATE_FIELD, mhi_dev_ctxt->ev_ring_props[PRIMARY_EVENT_RING], event_ring_state); if (MHI_EVENT_RING_UINIT == event_ring_state) { ret_val = mhi_init_event_ring(mhi_dev_ctxt, EV_EL_PER_RING, mhi_dev_ctxt->alloced_ev_rings[PRIMARY_EVENT_RING]); if (MHI_STATUS_SUCCESS != ret_val) { mhi_log(MHI_MSG_ERROR, "Failed to add ev el on event ring\n"); return MHI_STATUS_ERROR; } MHI_SET_EVENT_RING_INFO(EVENT_RING_STATE_FIELD, mhi_dev_ctxt->ev_ring_props[PRIMARY_EVENT_RING], MHI_EVENT_RING_INIT); } mhi_log(MHI_MSG_ERROR, "Event ring initialized ringing, EV DB to resume\n"); ring_ev_db(mhi_dev_ctxt, mhi_dev_ctxt->alloced_ev_rings[PRIMARY_EVENT_RING]); break; case STATE_TRANSITION_AMSS: MHI_GET_EVENT_RING_INFO(EVENT_RING_STATE_FIELD, mhi_dev_ctxt->ev_ring_props[IPA_OUT_EV_RING], event_ring_state); if (MHI_EVENT_RING_UINIT == event_ring_state) { ret_val = mhi_init_event_ring(mhi_dev_ctxt, EV_EL_PER_RING, mhi_dev_ctxt->alloced_ev_rings[IPA_OUT_EV_RING]); if (MHI_STATUS_SUCCESS != ret_val) { mhi_log(MHI_MSG_ERROR, "Failed to add ev el on event ring\n"); return MHI_STATUS_ERROR; } ret_val = mhi_init_event_ring(mhi_dev_ctxt, EV_EL_PER_RING, mhi_dev_ctxt->alloced_ev_rings[IPA_IN_EV_RING]); if (MHI_STATUS_SUCCESS != ret_val) { mhi_log(MHI_MSG_ERROR, "Failed to add ev el on event ring\n"); return MHI_STATUS_ERROR; } MHI_SET_EVENT_RING_INFO(EVENT_RING_STATE_FIELD, mhi_dev_ctxt->ev_ring_props[IPA_OUT_EV_RING], MHI_EVENT_RING_INIT); MHI_SET_EVENT_RING_INFO(EVENT_RING_STATE_FIELD, mhi_dev_ctxt->ev_ring_props[IPA_IN_EV_RING], MHI_EVENT_RING_INIT); } ring_ev_db(mhi_dev_ctxt, mhi_dev_ctxt->alloced_ev_rings[SOFTWARE_EV_RING]); ring_ev_db(mhi_dev_ctxt, mhi_dev_ctxt->alloced_ev_rings[IPA_OUT_EV_RING]); ring_ev_db(mhi_dev_ctxt, mhi_dev_ctxt->alloced_ev_rings[IPA_IN_EV_RING]); break; default: mhi_log(MHI_MSG_ERROR, "Unrecognized event stage, %d\n", new_state); ret_val = MHI_STATUS_ERROR; break; } return ret_val; }