Example #1
0
MHI_STATUS parse_inbound(mhi_device_ctxt *mhi_dev_ctxt, u32 chan,
			mhi_xfer_pkt *local_ev_trb_loc, u16 xfer_len)
{
	mhi_client_handle *client_handle;
	mhi_ring *local_chan_ctxt;
	mhi_result *result;
	mhi_cb_info cb_info;

	client_handle = mhi_dev_ctxt->client_handle_list[chan];
	local_chan_ctxt = &mhi_dev_ctxt->mhi_local_chan_ctxt[chan];

	if (unlikely(mhi_dev_ctxt->mhi_local_chan_ctxt[chan].rp ==
	    mhi_dev_ctxt->mhi_local_chan_ctxt[chan].wp)) {
		mhi_dev_ctxt->mhi_chan_cntr[chan].empty_ring_removal++;
		mhi_wait_for_mdm(mhi_dev_ctxt);
		return mhi_send_cmd(mhi_dev_ctxt,
				    MHI_COMMAND_RESET_CHAN,
				    chan);
	}

	if (NULL != mhi_dev_ctxt->client_handle_list[chan])
		result = &mhi_dev_ctxt->client_handle_list[chan]->result;

	/* If a client is registered */
	if (unlikely(IS_SOFTWARE_CHANNEL(chan))) {
		MHI_TX_TRB_SET_LEN(TX_TRB_LEN,
		local_ev_trb_loc,
		xfer_len);
		ctxt_del_element(local_chan_ctxt, NULL);
		if (NULL != client_handle->client_info.mhi_client_cb &&
		   (0 == (client_handle->pkt_count % client_handle->cb_mod))) {
			cb_info.cb_reason = MHI_CB_XFER_SUCCESS;
			cb_info.result = &client_handle->result;
			cb_info.result->transaction_status =
					MHI_STATUS_SUCCESS;
			client_handle->client_info.mhi_client_cb(&cb_info);
		}
	} else  {
		/* IN Hardware channel with no client
		 * registered, we are done with this TRB*/
		if (likely(NULL != client_handle)) {
			ctxt_del_element(local_chan_ctxt, NULL);
		/* A client is not registred for this IN channel */
		} else  {/* Hardware Channel, no client registerered,
				drop data */
			recycle_trb_and_ring(mhi_dev_ctxt,
				 &mhi_dev_ctxt->mhi_local_chan_ctxt[chan],
				 MHI_RING_TYPE_XFER_RING,
				 chan);
		}
	}
	return MHI_STATUS_SUCCESS;
}
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;
}