static enum MHI_STATUS process_reset_transition( struct mhi_device_ctxt *mhi_dev_ctxt, enum STATE_TRANSITION cur_work_item) { u32 i = 0; enum MHI_STATUS ret_val = MHI_STATUS_SUCCESS; unsigned long flags = 0; mhi_log(MHI_MSG_INFO, "Processing RESET state transition\n"); write_lock_irqsave(&mhi_dev_ctxt->xfer_lock, flags); mhi_dev_ctxt->mhi_state = MHI_STATE_RESET; write_unlock_irqrestore(&mhi_dev_ctxt->xfer_lock, flags); mhi_dev_ctxt->counters.mhi_reset_cntr++; mhi_dev_ctxt->dev_exec_env = MHI_EXEC_ENV_PBL; ret_val = mhi_test_for_device_reset(mhi_dev_ctxt); ret_val = mhi_test_for_device_ready(mhi_dev_ctxt); switch (ret_val) { case MHI_STATUS_SUCCESS: break; case MHI_STATUS_LINK_DOWN: mhi_log(MHI_MSG_CRITICAL, "Link down detected\n"); break; case MHI_STATUS_DEVICE_NOT_READY: ret_val = mhi_init_state_transition(mhi_dev_ctxt, STATE_TRANSITION_RESET); if (MHI_STATUS_SUCCESS != ret_val) mhi_log(MHI_MSG_CRITICAL, "Failed to initiate 0x%x state trans\n", STATE_TRANSITION_RESET); break; default: mhi_log(MHI_MSG_CRITICAL, "Unexpected ret code detected for\n"); break; } for (i = 0; i < NR_OF_CMD_RINGS; ++i) { mhi_dev_ctxt->mhi_local_cmd_ctxt[i].rp = mhi_dev_ctxt->mhi_local_cmd_ctxt[i].base; mhi_dev_ctxt->mhi_local_cmd_ctxt[i].wp = mhi_dev_ctxt->mhi_local_cmd_ctxt[i].base; mhi_dev_ctxt->mhi_ctrl_seg->mhi_cmd_ctxt_list[i]. mhi_cmd_ring_read_ptr = virt_to_dma(NULL, mhi_dev_ctxt->mhi_local_cmd_ctxt[i].rp); } for (i = 0; i < mhi_dev_ctxt->mmio_info.nr_event_rings; ++i) mhi_reset_ev_ctxt(mhi_dev_ctxt, i); for (i = 0; i < MHI_MAX_CHANNELS; ++i) { if (VALID_CHAN_NR(i)) mhi_reset_chan_ctxt(mhi_dev_ctxt, i); } ret_val = mhi_init_state_transition(mhi_dev_ctxt, STATE_TRANSITION_READY); if (MHI_STATUS_SUCCESS != ret_val) mhi_log(MHI_MSG_CRITICAL, "Failed to initiate 0x%x state trans\n", STATE_TRANSITION_READY); return ret_val; }
MHI_STATUS process_RESET_transition(mhi_device_ctxt *mhi_dev_ctxt, STATE_TRANSITION cur_work_item) { u32 i = 0; u32 ev_ring_index; MHI_STATUS ret_val = MHI_STATUS_SUCCESS; mhi_log(MHI_MSG_INFO, "Processing RESET state transition\n"); mhi_dev_ctxt->counters.mhi_reset_cntr++; if (mhi_dev_ctxt->counters.mhi_reset_cntr >= 10) { panic("CP Crash: need CP dump"); } ret_val = mhi_test_for_device_ready(mhi_dev_ctxt); switch (ret_val) { case MHI_STATUS_SUCCESS: mhi_dev_ctxt->counters.mhi_reset_cntr = 0; mhi_dev_ctxt->mhi_state = MHI_STATE_READY; ret_val = mhi_init_state_transition(mhi_dev_ctxt, STATE_TRANSITION_READY); if (MHI_STATUS_SUCCESS != ret_val) mhi_log(MHI_MSG_CRITICAL, "Failed to initiate 0x%x state trans\n", STATE_TRANSITION_READY); break; case MHI_STATUS_LINK_DOWN: mhi_log(MHI_MSG_CRITICAL, "Link down detected\n"); break; case MHI_STATUS_DEVICE_NOT_READY: ret_val = mhi_init_state_transition(mhi_dev_ctxt, STATE_TRANSITION_RESET); if (MHI_STATUS_SUCCESS != ret_val) mhi_log(MHI_MSG_CRITICAL, "Failed to initiate 0x%x state trans\n", STATE_TRANSITION_RESET); break; default: mhi_log(MHI_MSG_CRITICAL, "Unexpected ret code detected for\n"); break; } /* Synchronise the local rp/wp with the ctxt rp/wp This will enable the device to pick up exactly where it left off, should this be an SSR recovery */ for (i = 0; i < NR_OF_CMD_RINGS; ++i) { mhi_dev_ctxt->mhi_local_cmd_ctxt[i].rp = mhi_dev_ctxt->mhi_local_cmd_ctxt[i].base; mhi_dev_ctxt->mhi_local_cmd_ctxt[i].wp = mhi_dev_ctxt->mhi_local_cmd_ctxt[i].base; mhi_dev_ctxt->mhi_ctrl_seg->mhi_cmd_ctxt_list[i].mhi_cmd_ring_read_ptr = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_dev_ctxt->mhi_local_cmd_ctxt[i].rp); } for (i = 0; i < EVENT_RINGS_ALLOCATED; ++i) { ev_ring_index = mhi_dev_ctxt->alloced_ev_rings[i]; mhi_dev_ctxt->mhi_ctrl_seg->mhi_ec_list[ev_ring_index].mhi_event_read_ptr = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_dev_ctxt->mhi_local_event_ctxt[ev_ring_index].rp); } for (i = 0; i < MHI_MAX_CHANNELS; ++i) { if (VALID_CHAN_NR(i)) { mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list[i].mhi_trb_read_ptr = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_dev_ctxt->mhi_local_chan_ctxt[i].rp); mhi_dev_ctxt->mhi_ctrl_seg->mhi_cc_list[i].mhi_trb_write_ptr = mhi_v2p_addr(mhi_dev_ctxt->mhi_ctrl_seg_info, (uintptr_t)mhi_dev_ctxt->mhi_local_chan_ctxt[i].wp); } } /* reset outbound_ack count */ atomic_set(&mhi_dev_ctxt->counters.outbound_acks, 0); return ret_val; }