MHI_STATUS mhi_process_event_ring(mhi_device_ctxt *mhi_dev_ctxt, u32 ev_index, u32 event_quota) { mhi_event_pkt *local_rp = NULL; mhi_event_pkt *device_rp = NULL; mhi_event_pkt event_to_process; mhi_event_ctxt *ev_ctxt = NULL; mhi_ring *local_ev_ctxt = &mhi_dev_ctxt->mhi_local_event_ctxt[ev_index]; ev_ctxt = &mhi_dev_ctxt->mhi_ctrl_seg->mhi_ec_list[ev_index]; device_rp = (mhi_event_pkt *)mhi_p2v_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, ev_ctxt->mhi_event_read_ptr); local_rp = (mhi_event_pkt *)local_ev_ctxt->rp; if (unlikely(MHI_STATUS_SUCCESS != validate_ev_el_addr(local_ev_ctxt, (uintptr_t)device_rp))) mhi_log(MHI_MSG_ERROR, "Failed to validate event ring element 0x%p\n", device_rp); while ((local_rp != device_rp) && (event_quota > 0) && (device_rp != NULL) && (local_rp != NULL)) { event_to_process = *local_rp; if (unlikely(MHI_STATUS_SUCCESS != recycle_trb_and_ring(mhi_dev_ctxt, local_ev_ctxt, MHI_RING_TYPE_EVENT_RING, ev_index))) mhi_log(MHI_MSG_ERROR, "Failed to recycle ev pkt\n"); switch (MHI_TRB_READ_INFO(EV_TRB_TYPE, (&event_to_process))) { case MHI_PKT_TYPE_CMD_COMPLETION_EVENT: mhi_log(MHI_MSG_INFO, "MHI CCE received ring 0x%x\n", ev_index); __pm_stay_awake(&mhi_dev_ctxt->wake_lock); __pm_relax(&mhi_dev_ctxt->wake_lock); parse_cmd_event(mhi_dev_ctxt, &event_to_process); break; case MHI_PKT_TYPE_TX_EVENT: { u32 chan = MHI_EV_READ_CHID(EV_CHID, &event_to_process); if (((MHI_EV_READ_CODE(EV_TRB_CODE, &event_to_process) == MHI_EVENT_CC_OOB) || (MHI_EV_READ_CODE(EV_TRB_CODE, &event_to_process) == MHI_EVENT_CC_DB_MODE)) && (chan == MHI_CLIENT_IP_HW_0_OUT) && (mhi_dev_ctxt->mhi_local_chan_ctxt[chan].rp == mhi_dev_ctxt->mhi_local_chan_ctxt[chan].wp)) { mhi_log(MHI_MSG_VERBOSE, "Empty OOB chan %d\n", chan); parse_xfer_event(mhi_dev_ctxt, &event_to_process); } else { __pm_stay_awake(&mhi_dev_ctxt->wake_lock); parse_xfer_event(mhi_dev_ctxt, &event_to_process); __pm_relax(&mhi_dev_ctxt->wake_lock); } } break; case MHI_PKT_TYPE_STATE_CHANGE_EVENT: { STATE_TRANSITION new_state; new_state = MHI_READ_STATE(&event_to_process); mhi_log(MHI_MSG_INFO, "MHI STE received ring 0x%x\n", ev_index); mhi_init_state_transition(mhi_dev_ctxt, new_state); break; } case MHI_PKT_TYPE_EE_EVENT: { STATE_TRANSITION new_state; mhi_log(MHI_MSG_INFO, "MHI EEE received ring 0x%x\n", ev_index); __pm_stay_awake(&mhi_dev_ctxt->wake_lock); __pm_relax(&mhi_dev_ctxt->wake_lock); switch(MHI_READ_EXEC_ENV(&event_to_process)) { case MHI_EXEC_ENV_SBL: new_state = STATE_TRANSITION_SBL; mhi_init_state_transition(mhi_dev_ctxt, new_state); break; case MHI_EXEC_ENV_AMSS: new_state = STATE_TRANSITION_AMSS; mhi_init_state_transition(mhi_dev_ctxt, new_state); break; } break; } default: mhi_log(MHI_MSG_ERROR, "Unsupported packet type code 0x%x\n", MHI_TRB_READ_INFO(EV_TRB_TYPE, &event_to_process)); break; } local_rp = (mhi_event_pkt *)local_ev_ctxt->rp; device_rp = (mhi_event_pkt *)mhi_p2v_addr( mhi_dev_ctxt->mhi_ctrl_seg_info, (u64)ev_ctxt->mhi_event_read_ptr); --event_quota; } return MHI_STATUS_SUCCESS; }
MHI_STATUS parse_cmd_event(mhi_device_ctxt *mhi_dev_ctxt, mhi_event_pkt *ev_pkt) { MHI_STATUS ret_val = MHI_STATUS_SUCCESS; mhi_cmd_pkt *cmd_pkt = NULL; uintptr_t phy_trb_loc = 0; if (NULL != ev_pkt) phy_trb_loc = (uintptr_t)MHI_EV_READ_PTR(EV_PTR, ev_pkt); else return MHI_STATUS_ERROR; cmd_pkt = (mhi_cmd_pkt *)mhi_p2v_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, phy_trb_loc); mhi_log(MHI_MSG_INFO, "Received CMD completion event\n"); switch (MHI_EV_READ_CODE(EV_TRB_CODE, ev_pkt)) { /* Command completion was successful */ case MHI_EVENT_CC_SUCCESS: { u32 chan; MHI_TRB_GET_INFO(CMD_TRB_CHID, cmd_pkt, chan); switch (MHI_TRB_READ_INFO(CMD_TRB_TYPE, cmd_pkt)) { case MHI_PKT_TYPE_NOOP_CMD: mhi_log(MHI_MSG_INFO, "Processed NOOP cmd event\n"); break; case MHI_PKT_TYPE_RESET_CHAN_CMD: if (MHI_STATUS_SUCCESS != reset_chan_cmd(mhi_dev_ctxt, cmd_pkt)) mhi_log(MHI_MSG_INFO, "Failed to process reset cmd\n"); break; case MHI_PKT_TYPE_STOP_CHAN_CMD: { mhi_log(MHI_MSG_INFO, "Processed cmd stop event\n"); if (MHI_STATUS_SUCCESS != ret_val) { mhi_log(MHI_MSG_INFO, "Failed to set chan state\n"); return MHI_STATUS_ERROR; } break; } case MHI_PKT_TYPE_START_CHAN_CMD: { if (MHI_STATUS_SUCCESS != start_chan_cmd(mhi_dev_ctxt, cmd_pkt)) mhi_log(MHI_MSG_INFO, "Failed to process reset cmd\n"); atomic_dec(&mhi_dev_ctxt->start_cmd_pending_ack); wake_up_interruptible(mhi_dev_ctxt->chan_start_complete); break; } default: mhi_log(MHI_MSG_INFO, "Bad cmd type 0x%x\n", MHI_TRB_READ_INFO(CMD_TRB_TYPE, cmd_pkt)); break; } mhi_log(MHI_MSG_INFO, "CMD completion indicated successful\n"); mhi_dev_ctxt->mhi_chan_pend_cmd_ack[chan] = MHI_CMD_NOT_PENDING; break; } default: mhi_log(MHI_MSG_INFO, "Unhandled mhi completion code\n"); break; } mhi_log(MHI_MSG_INFO, "Recycling cmd event\n"); ctxt_del_element(mhi_dev_ctxt->mhi_local_cmd_ctxt, NULL); return MHI_STATUS_SUCCESS; }