/* WMI command API */
int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len,
			 WMI_CMD_ID cmd_id)
{
	HTC_PACKET *pkt;
	A_STATUS status;
	void *vos_context;
	struct ol_softc *scn;
	A_UINT16 htc_tag = 0;

	if (wmi_get_runtime_pm_inprogress(wmi_handle))
		goto skip_suspend_check;

	if (adf_os_atomic_read(&wmi_handle->is_target_suspended) &&
			( (WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID != cmd_id) &&
			  (WMI_PDEV_RESUME_CMDID != cmd_id)) ) {
		pr_err("%s: Target is suspended  could not send WMI command: %d\n",
				__func__, cmd_id);
		VOS_ASSERT(0);
		return -EBUSY;
	} else
		goto dont_tag;

skip_suspend_check:
	switch(cmd_id) {
	case WMI_WOW_ENABLE_CMDID:
	case WMI_PDEV_SUSPEND_CMDID:
	case WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID:
	case WMI_WOW_ADD_WAKE_PATTERN_CMDID:
	case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID:
	case WMI_PDEV_RESUME_CMDID:
	case WMI_WOW_DEL_WAKE_PATTERN_CMDID:
#ifdef FEATURE_WLAN_D0WOW
	case WMI_D0_WOW_ENABLE_DISABLE_CMDID:
#endif
		htc_tag = HTC_TX_PACKET_TAG_AUTO_PM;
	default:
		break;
	}

dont_tag:
	/* Do sanity check on the TLV parameter structure */
	{
		void *buf_ptr = (void *) adf_nbuf_data(buf);

		if (wmitlv_check_command_tlv_params(NULL, buf_ptr, len, cmd_id) != 0)
		{
			adf_os_print("\nERROR: %s: Invalid WMI Parameter Buffer for Cmd:%d\n",
				     __func__, cmd_id);
			return -1;
		}
	}

	if (adf_nbuf_push_head(buf, sizeof(WMI_CMD_HDR)) == NULL) {
		pr_err("%s, Failed to send cmd %x, no memory\n",
		       __func__, cmd_id);
		return -ENOMEM;
	}

	WMI_SET_FIELD(adf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID, cmd_id);

	adf_os_atomic_inc(&wmi_handle->pending_cmds);
	if (adf_os_atomic_read(&wmi_handle->pending_cmds) >= WMI_MAX_CMDS) {
		vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL);
		scn = vos_get_context(VOS_MODULE_ID_HIF, vos_context);
		pr_err("\n%s: hostcredits = %d\n", __func__,
		       wmi_get_host_credits(wmi_handle));
		HTC_dump_counter_info(wmi_handle->htc_handle);
		//dump_CE_register(scn);
		//dump_CE_debug_register(scn->hif_sc);
		adf_os_atomic_dec(&wmi_handle->pending_cmds);
		pr_err("%s: MAX 1024 WMI Pending cmds reached.\n", __func__);
		vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE);
		schedule_work(&recovery_work);
		return -EBUSY;
	}

	pkt = adf_os_mem_alloc(NULL, sizeof(*pkt));
	if (!pkt) {
		adf_os_atomic_dec(&wmi_handle->pending_cmds);
		pr_err("%s, Failed to alloc htc packet %x, no memory\n",
		       __func__, cmd_id);
		return -ENOMEM;
	}

	SET_HTC_PACKET_INFO_TX(pkt,
			NULL,
			adf_nbuf_data(buf),
			len + sizeof(WMI_CMD_HDR),
			/* htt_host_data_dl_len(buf)+20 */
			wmi_handle->wmi_endpoint_id,
			htc_tag);

	SET_HTC_PACKET_NET_BUF_CONTEXT(pkt, buf);

	WMA_LOGD("Send WMI command:%s command_id:%d",
			get_wmi_cmd_string(cmd_id), cmd_id);

#ifdef WMI_INTERFACE_EVENT_LOGGING
	adf_os_spin_lock_bh(&wmi_handle->wmi_record_lock);
        /*Record 16 bytes of WMI cmd data - exclude TLV and WMI headers*/
        WMI_COMMAND_RECORD(cmd_id ,((u_int32_t *)adf_nbuf_data(buf) + 2));
	adf_os_spin_unlock_bh(&wmi_handle->wmi_record_lock);
#endif

	status = HTCSendPkt(wmi_handle->htc_handle, pkt);

	if (A_OK != status) {
		adf_os_atomic_dec(&wmi_handle->pending_cmds);
		pr_err("%s %d, HTCSendPkt failed\n", __func__, __LINE__);
	}


	return ((status == A_OK) ? EOK : -1);
}
Example #2
0
/* WMI command API */
int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len,
			 WMI_CMD_ID cmd_id)
{
	HTC_PACKET *pkt;
	A_STATUS status;
	struct ol_softc *scn;

	if (cdf_atomic_read(&wmi_handle->is_target_suspended) &&
	    ((WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID != cmd_id) &&
	     (WMI_PDEV_RESUME_CMDID != cmd_id))) {
		pr_err("%s: Target is suspended  could not send WMI command\n",
		       __func__);
		CDF_ASSERT(0);
		return -EBUSY;
	}

	/* Do sanity check on the TLV parameter structure */
	{
		void *buf_ptr = (void *)cdf_nbuf_data(buf);

		if (wmitlv_check_command_tlv_params(NULL, buf_ptr, len, cmd_id)
		    != 0) {
			cdf_print
				("\nERROR: %s: Invalid WMI Parameter Buffer for Cmd:%d\n",
				__func__, cmd_id);
			return -1;
		}
	}

	if (cdf_nbuf_push_head(buf, sizeof(WMI_CMD_HDR)) == NULL) {
		pr_err("%s, Failed to send cmd %x, no memory\n",
		       __func__, cmd_id);
		return -ENOMEM;
	}

	WMI_SET_FIELD(cdf_nbuf_data(buf), WMI_CMD_HDR, COMMANDID, cmd_id);

	cdf_atomic_inc(&wmi_handle->pending_cmds);
	if (cdf_atomic_read(&wmi_handle->pending_cmds) >= WMI_MAX_CMDS) {
		scn = cds_get_context(CDF_MODULE_ID_HIF);
		pr_err("\n%s: hostcredits = %d\n", __func__,
		       wmi_get_host_credits(wmi_handle));
		htc_dump_counter_info(wmi_handle->htc_handle);
		/* dump_ce_register(scn); */
		/* dump_ce_debug_register(scn->hif_sc); */
		cdf_atomic_dec(&wmi_handle->pending_cmds);
		pr_err("%s: MAX 1024 WMI Pending cmds reached.\n", __func__);
		CDF_BUG(0);
		return -EBUSY;
	}

	pkt = cdf_mem_malloc(sizeof(*pkt));
	if (!pkt) {
		cdf_atomic_dec(&wmi_handle->pending_cmds);
		pr_err("%s, Failed to alloc htc packet %x, no memory\n",
		       __func__, cmd_id);
		return -ENOMEM;
	}

	SET_HTC_PACKET_INFO_TX(pkt,
			       NULL,
			       cdf_nbuf_data(buf), len + sizeof(WMI_CMD_HDR),
	                       /* htt_host_data_dl_len(buf)+20 */
			       wmi_handle->wmi_endpoint_id, 0 /*htc_tag */ );

	SET_HTC_PACKET_NET_BUF_CONTEXT(pkt, buf);

	wma_log_cmd_id(cmd_id);

#ifdef WMI_INTERFACE_EVENT_LOGGING
	cdf_spin_lock_bh(&wmi_handle->wmi_record_lock);
	/*Record 16 bytes of WMI cmd data - exclude TLV and WMI headers */
	if (cmd_id == WMI_MGMT_TX_SEND_CMDID) {
		WMI_MGMT_COMMAND_RECORD(cmd_id,
					((uint32_t *)cdf_nbuf_data(buf) + 2));
	} else {
		WMI_COMMAND_RECORD(cmd_id, ((uint32_t *) cdf_nbuf_data(buf) +
					    2));
	}

	cdf_spin_unlock_bh(&wmi_handle->wmi_record_lock);
#endif

	status = htc_send_pkt(wmi_handle->htc_handle, pkt);

	if (A_OK != status) {
		cdf_atomic_dec(&wmi_handle->pending_cmds);
		pr_err("%s %d, htc_send_pkt failed\n", __func__, __LINE__);
	}

	return ((status == A_OK) ? EOK : -1);
}