A_STATUS htt_h2t_sync_msg(struct htt_pdev_t *pdev, u_int8_t sync_cnt) { struct htt_htc_pkt *pkt; adf_nbuf_t msg; u_int32_t *msg_word; pkt = htt_htc_pkt_alloc(pdev); if (!pkt) { return A_NO_MEMORY; } /* show that this is not a tx frame download (not required, but helpful) */ pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; pkt->pdev_ctxt = NULL; /* not used during send-done callback */ msg = adf_nbuf_alloc( pdev->osdev, HTT_MSG_BUF_SIZE(HTT_H2T_SYNC_MSG_SZ), /* reserve room for HTC header */ HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, FALSE); if (!msg) { htt_htc_pkt_free(pdev, pkt); return A_NO_MEMORY; } /* set the length of the message */ adf_nbuf_put_tail(msg, HTT_H2T_SYNC_MSG_SZ); /* fill in the message contents */ msg_word = (u_int32_t *) adf_nbuf_data(msg); /* rewind beyond alignment pad to get to the HTC header reserved area */ adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); *msg_word = 0; HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_SYNC); HTT_H2T_SYNC_COUNT_SET(*msg_word, sync_cnt); SET_HTC_PACKET_INFO_TX( &pkt->htc_pkt, htt_h2t_send_complete_free_netbuf, adf_nbuf_data(msg), adf_nbuf_len(msg), pdev->htc_endpoint, HTC_TX_PACKET_TAG_RUNTIME_PUT); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); #ifdef ATH_11AC_TXCOMPACT if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) htt_htc_misc_pkt_list_add(pdev, pkt); #else HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); #endif if ((pdev->cfg.is_high_latency) && (!pdev->cfg.default_tx_comp_req)) { ol_tx_target_credit_update(pdev->txrx_pdev, -1); } return A_OK; }
static int SendHCICommand(struct ar3k_config_info *pConfig, u8 *pBuffer, int Length) { struct htc_packet *pPacket = NULL; int status = 0; do { pPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet)); if (NULL == pPacket) { status = A_NO_MEMORY; break; } A_MEMZERO(pPacket,sizeof(struct htc_packet)); SET_HTC_PACKET_INFO_TX(pPacket, NULL, pBuffer, Length, HCI_COMMAND_TYPE, AR6K_CONTROL_PKT_TAG); /* issue synchronously */ status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,true); } while (false); if (pPacket != NULL) { kfree(pPacket); } return status; }
static A_STATUS SendHCICommand(AR3K_CONFIG_INFO *pConfig, A_UINT8 *pBuffer, int Length) { HTC_PACKET *pPacket = NULL; A_STATUS status = A_OK; do { pPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET)); if (NULL == pPacket) { status = A_NO_MEMORY; break; } A_MEMZERO(pPacket,sizeof(HTC_PACKET)); SET_HTC_PACKET_INFO_TX(pPacket, NULL, pBuffer, Length, HCI_COMMAND_TYPE, AR6K_CONTROL_PKT_TAG); /* issue synchronously */ status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,TRUE); } while (FALSE); if (pPacket != NULL) { A_FREE(pPacket); } return status; }
/* WMI command API */ int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len, WMI_CMD_ID cmd_id) { A_STATUS status; struct cookie *cookie; if (wbuf_push(buf, sizeof(WMI_CMD_HDR)) == NULL) { return -ENOMEM; } WMI_SET_FIELD(wbuf_header(buf), WMI_CMD_HDR, COMMANDID, cmd_id); //WMI_CMD_HDR_SET_DEVID(cmd_hdr, 0); // unused cookie = ol_alloc_cookie(wmi_handle); if (!cookie) { return -ENOMEM; } cookie->PacketContext = buf; SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, cookie, wbuf_header(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(&cookie->HtcPkt, buf); status = HTCSendPkt(wmi_handle->htc_handle, &cookie->HtcPkt); return ((status == A_OK) ? EOK : -1); }
static inline int htt_tx_send_base( htt_pdev_handle pdev, adf_nbuf_t msdu, u_int16_t msdu_id, int download_len, u_int8_t more_data) { struct htt_host_tx_desc_t *htt_host_tx_desc; struct htt_htc_pkt *pkt; int packet_len; HTC_ENDPOINT_ID ep_id; /* * The HTT tx descriptor was attached as the prefix fragment to the * msdu netbuf during the call to htt_tx_desc_init. * Retrieve it so we can provide its HTC header space to HTC. */ htt_host_tx_desc = (struct htt_host_tx_desc_t *) adf_nbuf_get_frag_vaddr(msdu, 0); pkt = htt_htc_pkt_alloc(pdev); if (!pkt) { return 1; /* failure */ } pkt->msdu_id = msdu_id; pkt->pdev_ctxt = pdev->txrx_pdev; /* packet length includes HTT tx desc frag added above */ packet_len = adf_nbuf_len(msdu); if (packet_len < download_len) { /* * This case of packet length being less than the nominal download * length can happen for a couple reasons: * In HL, the nominal download length is a large artificial value. * In LL, the frame may not have the optional header fields * accounted for in the nominal download size (LLC/SNAP header, * IPv4 or IPv6 header). */ download_len = packet_len; } ep_id = htt_tx_htt2_get_ep_id(pdev, msdu); SET_HTC_PACKET_INFO_TX( &pkt->htc_pkt, pdev->tx_send_complete_part2, (unsigned char *) htt_host_tx_desc, download_len - HTC_HDR_LENGTH, ep_id, 1); /* tag - not relevant here */ SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msdu); adf_nbuf_trace_update(msdu, "HT:T:"); HTCSendDataPkt(pdev->htc_pdev, &pkt->htc_pkt, more_data); return 0; /* success */ }
A_STATUS HTCStart(HTC_HANDLE HTCHandle) { adf_nbuf_t netbuf; A_STATUS status = A_OK; HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_SETUP_COMPLETE_EX_MSG *pSetupComp; HTC_PACKET *pSendPacket; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); do { HTCConfigTargetHIFPipe(target); /* allocate a buffer to send */ pSendPacket = HTCAllocControlTxPacket(target); if (NULL == pSendPacket) { AR_DEBUG_ASSERT(FALSE); adf_os_print("%s: allocControlTxPacket failed\n",__func__); status = A_NO_MEMORY; break; } netbuf = (adf_nbuf_t)GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket); /* assemble setup complete message */ adf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); pSetupComp = (HTC_SETUP_COMPLETE_EX_MSG *) adf_nbuf_data(netbuf); A_MEMZERO(pSetupComp,sizeof(HTC_SETUP_COMPLETE_EX_MSG)); HTC_SET_FIELD(pSetupComp, HTC_SETUP_COMPLETE_EX_MSG, MESSAGEID, HTC_MSG_SETUP_COMPLETE_EX_ID); //if (!htc_credit_flow) { if (0) { AR_DEBUG_PRINTF(ATH_DEBUG_INIT, ("HTC will not use TX credit flow control\n")); pSetupComp->SetupFlags |= HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW; } else { AR_DEBUG_PRINTF(ATH_DEBUG_INIT, ("HTC using TX credit flow control\n")); } SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pSetupComp, sizeof(HTC_SETUP_COMPLETE_EX_MSG), ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); status = HTCSendPkt((HTC_HANDLE)target,pSendPacket); if (A_FAILED(status)) { break; } } while (FALSE); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); return status; }
int htt_h2t_ipa_uc_get_stats(struct htt_pdev_t *pdev) { struct htt_htc_pkt *pkt = NULL; adf_nbuf_t msg = NULL; u_int32_t *msg_word; /* New buffer alloc send */ pkt = htt_htc_pkt_alloc(pdev); if (!pkt) { return A_NO_MEMORY; } /* show that this is not a tx frame download (not required, * but helpful) */ pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; pkt->pdev_ctxt = NULL; /* not used during send-done callback */ msg = adf_nbuf_alloc( pdev->osdev, HTT_MSG_BUF_SIZE(HTT_WDI_IPA_OP_REQUEST_SZ), /* reserve room for HTC header */ HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, FALSE); if (!msg) { htt_htc_pkt_free(pdev, pkt); return A_NO_MEMORY; } /* set the length of the message */ adf_nbuf_put_tail(msg, HTT_WDI_IPA_OP_REQUEST_SZ); /* rewind beyond alignment pad to get to the HTC header reserved area */ adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); /* fill in the message contents */ msg_word = (u_int32_t *) adf_nbuf_data(msg); *msg_word = 0; HTT_WDI_IPA_OP_REQUEST_OP_CODE_SET(*msg_word, HTT_WDI_IPA_OPCODE_DBG_STATS); HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_WDI_IPA_OP_REQ); SET_HTC_PACKET_INFO_TX( &pkt->htc_pkt, htt_h2t_send_complete_free_netbuf, adf_nbuf_data(msg), adf_nbuf_len(msg), pdev->htc_endpoint, 1); /* tag - not relevant here */ SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); #ifdef ATH_11AC_TXCOMPACT if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) htt_htc_misc_pkt_list_add(pdev, pkt); #else HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); #endif return A_OK; }
void epping_tx_dup_pkt(epping_adapter_t *pAdapter, HTC_ENDPOINT_ID eid, adf_nbuf_t skb) { struct epping_cookie * cookie = NULL; int skb_len, ret; adf_nbuf_t new_skb; cookie = epping_alloc_cookie(pAdapter->pEpping_ctx); if (cookie == NULL) { EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: epping_alloc_cookie returns no resource\n", __func__); return; } new_skb = adf_nbuf_copy(skb); if (!new_skb) { EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: adf_nbuf_copy returns no resource\n", __func__); epping_free_cookie(pAdapter->pEpping_ctx, cookie); return; } SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, cookie, adf_nbuf_data(skb), adf_nbuf_len(new_skb), eid, 0); SET_HTC_PACKET_NET_BUF_CONTEXT(&cookie->HtcPkt, new_skb); skb_len = (int)adf_nbuf_len(new_skb); /* send the packet */ ret = HTCSendPkt(pAdapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt); if (ret != A_OK) { EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: HTCSendPkt failed, ret = %d\n", __func__, ret); epping_free_cookie(pAdapter->pEpping_ctx, cookie); adf_nbuf_free(new_skb); return; } pAdapter->stats.tx_bytes += skb_len; ++pAdapter->stats.tx_packets; if (((pAdapter->stats.tx_packets + pAdapter->stats.tx_dropped) % EPPING_STATS_LOG_COUNT) == 0 && (pAdapter->stats.tx_packets || pAdapter->stats.tx_dropped)) { epping_log_stats(pAdapter, __func__); } }
A_STATUS HTCSendSetupComplete(HTC_TARGET *target) { HTC_PACKET *pSendPacket = NULL; A_STATUS status; HTC_SETUP_COMPLETE_MSG *pSetupComplete; do { /* allocate a packet to send to the target */ pSendPacket = HTC_ALLOC_CONTROL_TX(target); if (NULL == pSendPacket) { status = A_NO_MEMORY; break; } /* assemble setup complete message */ pSetupComplete = (HTC_SETUP_COMPLETE_MSG *)pSendPacket->pBuffer; A_MEMZERO(pSetupComplete,sizeof(HTC_SETUP_COMPLETE_MSG)); pSetupComplete->MessageID = HTC_MSG_SETUP_COMPLETE_ID; SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pSetupComplete, sizeof(HTC_SETUP_COMPLETE_MSG), ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); /* we want synchronous operation */ pSendPacket->Completion = NULL; /* send the message */ status = HTCIssueSend(target,pSendPacket,0); } while (FALSE); if (pSendPacket != NULL) { HTC_FREE_CONTROL_TX(target,pSendPacket); } return status; }
A_STATUS CAR6KMini::WMISendControlPacket( IN PVOID osbuf, HTC_ENDPOINT_ID Endpoint) { A_STATUS status; ndis_mini_buf_t *pNb; pNb = (ndis_mini_buf_t *)osbuf; SET_HTC_PACKET_INFO_TX(&pNb->HtcPacket, osbuf, a_netbuf_to_data(osbuf), a_netbuf_to_len(osbuf), Endpoint, AR6K_CONTROL_PKT_TAG); status = HTCSendPkt(m_pHTCTarget, &pNb->HtcPacket); if (A_OK != status && A_PENDING != status && m_ControlEp != Endpoint) NdisInterlockedDecrement(&m_TxPending); return status; }
A_STATUS HTCSendSetupComplete(HTC_TARGET *target) { HTC_PACKET *pSendPacket = NULL; A_STATUS status; do { /* allocate a packet to send to the target */ pSendPacket = HTC_ALLOC_CONTROL_TX(target); if (NULL == pSendPacket) { status = A_NO_MEMORY; break; } if (target->HTCTargetVersion >= HTC_VERSION_2P1) { HTC_SETUP_COMPLETE_EX_MSG *pSetupCompleteEx; A_UINT32 setupFlags = 0; pSetupCompleteEx = (HTC_SETUP_COMPLETE_EX_MSG *)pSendPacket->pBuffer; A_MEMZERO(pSetupCompleteEx, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); pSetupCompleteEx->MessageID = HTC_MSG_SETUP_COMPLETE_EX_ID; if (target->MaxMsgPerBundle > 0) { /* host can do HTC bundling, indicate this to the target */ setupFlags |= HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV; pSetupCompleteEx->MaxMsgsPerBundledRecv = target->MaxMsgPerBundle; } A_MEMCPY(&pSetupCompleteEx->SetupFlags, &setupFlags, sizeof(pSetupCompleteEx->SetupFlags)); SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pSetupCompleteEx, sizeof(HTC_SETUP_COMPLETE_EX_MSG), ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); } else { HTC_SETUP_COMPLETE_MSG *pSetupComplete; /* assemble setup complete message */ pSetupComplete = (HTC_SETUP_COMPLETE_MSG *)pSendPacket->pBuffer; A_MEMZERO(pSetupComplete, sizeof(HTC_SETUP_COMPLETE_MSG)); pSetupComplete->MessageID = HTC_MSG_SETUP_COMPLETE_ID; SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pSetupComplete, sizeof(HTC_SETUP_COMPLETE_MSG), ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); } /* we want synchronous operation */ pSendPacket->Completion = NULL; HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0); /* send the message */ status = HTCIssueSend(target,pSendPacket); } while (FALSE); if (pSendPacket != NULL) { HTC_FREE_CONTROL_TX(target,pSendPacket); } return status; }
A_STATUS htt_h2t_rx_ring_cfg_msg_ll(struct htt_pdev_t *pdev) { struct htt_htc_pkt *pkt; adf_nbuf_t msg; u_int32_t *msg_word; int enable_ctrl_data, enable_mgmt_data, enable_null_data, enable_phy_data, enable_hdr, enable_ppdu_start, enable_ppdu_end; pkt = htt_htc_pkt_alloc(pdev); if (!pkt) { return A_ERROR; /* failure */ } /* show that this is not a tx frame download (not required, but helpful) */ pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; pkt->pdev_ctxt = NULL; /* not used during send-done callback */ msg = adf_nbuf_alloc( pdev->osdev, HTT_MSG_BUF_SIZE(HTT_RX_RING_CFG_BYTES(1)), /* reserve room for the HTC header */ HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE); if (!msg) { htt_htc_pkt_free(pdev, pkt); return A_ERROR; /* failure */ } /* * Set the length of the message. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added * separately during the below call to adf_nbuf_push_head. * The contribution from the HTC header is added separately inside HTC. */ adf_nbuf_put_tail(msg, HTT_RX_RING_CFG_BYTES(1)); /* fill in the message contents */ msg_word = (u_int32_t *) adf_nbuf_data(msg); /* rewind beyond alignment pad to get to the HTC header reserved area */ adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); *msg_word = 0; HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_RING_CFG); HTT_RX_RING_CFG_NUM_RINGS_SET(*msg_word, 1); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_SET( *msg_word, pdev->rx_ring.alloc_idx.paddr); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_BASE_PADDR_SET(*msg_word, pdev->rx_ring.base_paddr); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_LEN_SET(*msg_word, pdev->rx_ring.size); HTT_RX_RING_CFG_BUF_SZ_SET(*msg_word, HTT_RX_BUF_SIZE); /* FIX THIS: if the FW creates a complete translated rx descriptor, then the MAC DMA of the HW rx descriptor should be disabled. */ msg_word++; *msg_word = 0; #ifndef REMOVE_PKT_LOG if (ol_cfg_is_packet_log_enabled(pdev->ctrl_pdev)) { enable_ctrl_data = 1; enable_mgmt_data = 1; enable_null_data = 1; enable_phy_data = 1; enable_hdr = 1; enable_ppdu_start= 1; enable_ppdu_end = 1; /* Disable ASPM when pkt log is enabled */ adf_os_print("Pkt log is enabled\n"); htt_htc_disable_aspm(); } else { adf_os_print("Pkt log is disabled\n"); enable_ctrl_data = 0; enable_mgmt_data = 0; enable_null_data = 0; enable_phy_data = 0; enable_hdr = 0; enable_ppdu_start= 0; enable_ppdu_end = 0; } #else enable_ctrl_data = 0; enable_mgmt_data = 0; enable_null_data = 0; enable_phy_data = 0; enable_hdr = 0; enable_ppdu_start= 0; enable_ppdu_end = 0; #endif HTT_RX_RING_CFG_ENABLED_802_11_HDR_SET(*msg_word, enable_hdr); HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_SET(*msg_word, 1); HTT_RX_RING_CFG_ENABLED_PPDU_START_SET(*msg_word, enable_ppdu_start); HTT_RX_RING_CFG_ENABLED_PPDU_END_SET(*msg_word, enable_ppdu_end); HTT_RX_RING_CFG_ENABLED_MPDU_START_SET(*msg_word, 1); HTT_RX_RING_CFG_ENABLED_MPDU_END_SET(*msg_word, 1); HTT_RX_RING_CFG_ENABLED_MSDU_START_SET(*msg_word, 1); HTT_RX_RING_CFG_ENABLED_MSDU_END_SET(*msg_word, 1); HTT_RX_RING_CFG_ENABLED_RX_ATTN_SET(*msg_word, 1); HTT_RX_RING_CFG_ENABLED_FRAG_INFO_SET(*msg_word, 1); /* always present? */ HTT_RX_RING_CFG_ENABLED_UCAST_SET(*msg_word, 1); HTT_RX_RING_CFG_ENABLED_MCAST_SET(*msg_word, 1); /* Must change to dynamic enable at run time * rather than at compile time */ HTT_RX_RING_CFG_ENABLED_CTRL_SET(*msg_word, enable_ctrl_data); HTT_RX_RING_CFG_ENABLED_MGMT_SET(*msg_word, enable_mgmt_data); HTT_RX_RING_CFG_ENABLED_NULL_SET(*msg_word, enable_null_data); HTT_RX_RING_CFG_ENABLED_PHY_SET(*msg_word, enable_phy_data); HTT_RX_RING_CFG_IDX_INIT_VAL_SET(*msg_word, *pdev->rx_ring.alloc_idx.vaddr); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_OFFSET_802_11_HDR_SET(*msg_word, RX_STD_DESC_HDR_STATUS_OFFSET_DWORD); HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD_SET(*msg_word, HTT_RX_STD_DESC_RESERVATION_DWORD); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_OFFSET_PPDU_START_SET(*msg_word, RX_STD_DESC_PPDU_START_OFFSET_DWORD); HTT_RX_RING_CFG_OFFSET_PPDU_END_SET(*msg_word, RX_STD_DESC_PPDU_END_OFFSET_DWORD); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_OFFSET_MPDU_START_SET(*msg_word, RX_STD_DESC_MPDU_START_OFFSET_DWORD); HTT_RX_RING_CFG_OFFSET_MPDU_END_SET(*msg_word, RX_STD_DESC_MPDU_END_OFFSET_DWORD); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_OFFSET_MSDU_START_SET(*msg_word, RX_STD_DESC_MSDU_START_OFFSET_DWORD); HTT_RX_RING_CFG_OFFSET_MSDU_END_SET(*msg_word, RX_STD_DESC_MSDU_END_OFFSET_DWORD); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_OFFSET_RX_ATTN_SET(*msg_word, RX_STD_DESC_ATTN_OFFSET_DWORD); HTT_RX_RING_CFG_OFFSET_FRAG_INFO_SET(*msg_word, RX_STD_DESC_FRAG_INFO_OFFSET_DWORD); SET_HTC_PACKET_INFO_TX( &pkt->htc_pkt, htt_h2t_send_complete_free_netbuf, adf_nbuf_data(msg), adf_nbuf_len(msg), pdev->htc_endpoint, HTC_TX_PACKET_TAG_RUNTIME_PUT); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); #ifdef ATH_11AC_TXCOMPACT if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) htt_htc_misc_pkt_list_add(pdev, pkt); #else HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); #endif return A_OK; }
A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, HTC_SERVICE_CONNECT_REQ *pConnectReq, HTC_SERVICE_CONNECT_RESP *pConnectResp) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); A_STATUS status = A_OK; HTC_PACKET *pRecvPacket = NULL; HTC_PACKET *pSendPacket = NULL; HTC_CONNECT_SERVICE_RESPONSE_MSG *pResponseMsg; HTC_CONNECT_SERVICE_MSG *pConnectMsg; HTC_ENDPOINT_ID assignedEndpoint = ENDPOINT_MAX; HTC_ENDPOINT *pEndpoint; unsigned int maxMsgSize = 0; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:0x%X SvcID:0x%X \n", (A_UINT32)target, pConnectReq->ServiceID)); do { AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0); if (HTC_CTRL_RSVD_SVC == pConnectReq->ServiceID) { /* special case for pseudo control service */ assignedEndpoint = ENDPOINT_0; maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH; } else { /* allocate a packet to send to the target */ pSendPacket = HTC_ALLOC_CONTROL_TX(target); if (NULL == pSendPacket) { AR_DEBUG_ASSERT(FALSE); status = A_NO_MEMORY; break; } /* assemble connect service message */ pConnectMsg = (HTC_CONNECT_SERVICE_MSG *)pSendPacket->pBuffer; AR_DEBUG_ASSERT(pConnectMsg != NULL); A_MEMZERO(pConnectMsg,sizeof(HTC_CONNECT_SERVICE_MSG)); pConnectMsg->MessageID = HTC_MSG_CONNECT_SERVICE_ID; pConnectMsg->ServiceID = pConnectReq->ServiceID; pConnectMsg->ConnectionFlags = pConnectReq->ConnectionFlags; /* check caller if it wants to transfer meta data */ if ((pConnectReq->pMetaData != NULL) && (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { /* copy meta data into message buffer (after header ) */ A_MEMCPY((A_UINT8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG), pConnectReq->pMetaData, pConnectReq->MetaDataLength); pConnectMsg->ServiceMetaLength = pConnectReq->MetaDataLength; } SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pConnectMsg, sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectMsg->ServiceMetaLength, ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); /* we want synchronous operation */ pSendPacket->Completion = NULL; HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0); status = HTCIssueSend(target,pSendPacket); if (A_FAILED(status)) { break; } /* wait for response */ status = HTCWaitforControlMessage(target, &pRecvPacket); if (A_FAILED(status)) { break; } /* we controlled the buffer creation so it has to be properly aligned */ pResponseMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)pRecvPacket->pBuffer; if ((pResponseMsg->MessageID != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) || (pRecvPacket->ActualLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) { /* this message is not valid */ AR_DEBUG_ASSERT(FALSE); status = A_EPROTO; break; } pConnectResp->ConnectRespCode = pResponseMsg->Status; /* check response status */ if (pResponseMsg->Status != HTC_SERVICE_SUCCESS) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target failed service 0x%X connect request (status:%d)\n", pResponseMsg->ServiceID, pResponseMsg->Status)); status = A_EPROTO; break; } assignedEndpoint = (HTC_ENDPOINT_ID) pResponseMsg->EndpointID; maxMsgSize = pResponseMsg->MaxMsgSize; if ((pConnectResp->pMetaData != NULL) && (pResponseMsg->ServiceMetaLength > 0) && (pResponseMsg->ServiceMetaLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { /* caller supplied a buffer and the target responded with data */ int copyLength = min((int)pConnectResp->BufferLength, (int)pResponseMsg->ServiceMetaLength); /* copy the meta data */ A_MEMCPY(pConnectResp->pMetaData, ((A_UINT8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG), copyLength); pConnectResp->ActualLength = copyLength; } } /* the rest of these are parameter checks so set the error status */ status = A_EPROTO; if (assignedEndpoint >= ENDPOINT_MAX) { AR_DEBUG_ASSERT(FALSE); break; } if (0 == maxMsgSize) { AR_DEBUG_ASSERT(FALSE); break; } pEndpoint = &target->EndPoint[assignedEndpoint]; pEndpoint->Id = assignedEndpoint; if (pEndpoint->ServiceID != 0) { /* endpoint already in use! */ AR_DEBUG_ASSERT(FALSE); break; } /* return assigned endpoint to caller */ pConnectResp->Endpoint = assignedEndpoint; pConnectResp->MaxMsgLength = maxMsgSize; /* setup the endpoint */ pEndpoint->ServiceID = pConnectReq->ServiceID; /* this marks the endpoint in use */ pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth; pEndpoint->MaxMsgLength = maxMsgSize; /* copy all the callbacks */ pEndpoint->EpCallBacks = pConnectReq->EpCallbacks; /* set the credit distribution info for this endpoint, this information is * passed back to the credit distribution callback function */ pEndpoint->CreditDist.ServiceID = pConnectReq->ServiceID; pEndpoint->CreditDist.pHTCReserved = pEndpoint; pEndpoint->CreditDist.Endpoint = assignedEndpoint; pEndpoint->CreditDist.TxCreditSize = target->TargetCreditSize; if (pConnectReq->MaxSendMsgSize != 0) { /* override TxCreditsPerMaxMsg calculation, this optimizes the credit-low indications * since the host will actually issue smaller messages in the Send path */ if (pConnectReq->MaxSendMsgSize > maxMsgSize) { /* can't be larger than the maximum the target can support */ AR_DEBUG_ASSERT(FALSE); break; } pEndpoint->CreditDist.TxCreditsPerMaxMsg = pConnectReq->MaxSendMsgSize / target->TargetCreditSize; } else { pEndpoint->CreditDist.TxCreditsPerMaxMsg = maxMsgSize / target->TargetCreditSize; } if (0 == pEndpoint->CreditDist.TxCreditsPerMaxMsg) { pEndpoint->CreditDist.TxCreditsPerMaxMsg = 1; } /* save local connection flags */ pEndpoint->LocalConnectionFlags = pConnectReq->LocalConnectionFlags; status = A_OK; } while (FALSE); if (pSendPacket != NULL) { HTC_FREE_CONTROL_TX(target,pSendPacket); } if (pRecvPacket != NULL) { HTC_FREE_CONTROL_RX(target,pRecvPacket); } AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCConnectService \n")); return status; }
/* 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); }
ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID, char __user *buffer, size_t length) { int writePtr; raw_htc_buffer *free; AR_RAW_HTC_T *arRaw = ar->arRawHtc; if (arRawStream2EndpointID(ar,StreamID) == 0) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("StreamID(%d) not connected! \n", StreamID)); return -EFAULT; } if (down_interruptible(&arRaw->raw_htc_write_sem[StreamID])) { return -ERESTARTSYS; } /* Search for a free buffer */ free = get_free_buffer(ar,StreamID); /* Check if there is space to write else wait */ while (!arRaw->write_buffer_available[StreamID]) { up(&arRaw->raw_htc_write_sem[StreamID]); /* Wait for buffer to become free */ AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("Sleeping StreamID(%d) write process\n", StreamID)); if (wait_event_interruptible(arRaw->raw_htc_write_queue[StreamID], arRaw->write_buffer_available[StreamID])) { return -EINTR; } if (down_interruptible(&arRaw->raw_htc_write_sem[StreamID])) { return -ERESTARTSYS; } free = get_free_buffer(ar,StreamID); } /* Send the data */ writePtr = HTC_HEADER_LEN; if (length > (HTC_RAW_BUFFER_SIZE - HTC_HEADER_LEN)) { length = HTC_RAW_BUFFER_SIZE - HTC_HEADER_LEN; } if (copy_from_user(&free->data[writePtr], buffer, length)) { up(&arRaw->raw_htc_read_sem[StreamID]); return -EFAULT; } free->length = length; SET_HTC_PACKET_INFO_TX(&free->HTCPacket, free, &free->data[writePtr], length, arRawStream2EndpointID(ar,StreamID), AR6K_DATA_PKT_TAG); HTCSendPkt(ar->arHtcTarget,&free->HTCPacket); arRaw->write_buffer_available[StreamID] = FALSE; up(&arRaw->raw_htc_write_sem[StreamID]); return length; }
int htt_h2t_dbg_stats_get( struct htt_pdev_t *pdev, u_int32_t stats_type_upload_mask, u_int32_t stats_type_reset_mask, u_int8_t cfg_stat_type, u_int32_t cfg_val, u_int64_t cookie) { struct htt_htc_pkt *pkt; adf_nbuf_t msg; u_int32_t *msg_word; uint16_t htc_tag = 1; pkt = htt_htc_pkt_alloc(pdev); if (!pkt) { return -1; /* failure */ } if (stats_type_upload_mask >= 1 << HTT_DBG_NUM_STATS || stats_type_reset_mask >= 1 << HTT_DBG_NUM_STATS) { /* FIX THIS - add more details? */ adf_os_print("%#x %#x stats not supported\n", stats_type_upload_mask, stats_type_reset_mask); return -1; /* failure */ } if (stats_type_reset_mask) htc_tag = HTC_TX_PACKET_TAG_RUNTIME_PUT; /* show that this is not a tx frame download (not required, but helpful) */ pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; pkt->pdev_ctxt = NULL; /* not used during send-done callback */ msg = adf_nbuf_alloc( pdev->osdev, HTT_MSG_BUF_SIZE(HTT_H2T_STATS_REQ_MSG_SZ), /* reserve room for HTC header */ HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, FALSE); if (!msg) { htt_htc_pkt_free(pdev, pkt); return -1; /* failure */ } /* set the length of the message */ adf_nbuf_put_tail(msg, HTT_H2T_STATS_REQ_MSG_SZ); /* fill in the message contents */ msg_word = (u_int32_t *) adf_nbuf_data(msg); /* rewind beyond alignment pad to get to the HTC header reserved area */ adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); *msg_word = 0; HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_STATS_REQ); HTT_H2T_STATS_REQ_UPLOAD_TYPES_SET(*msg_word, stats_type_upload_mask); msg_word++; *msg_word = 0; HTT_H2T_STATS_REQ_RESET_TYPES_SET(*msg_word, stats_type_reset_mask); msg_word++; *msg_word = 0; HTT_H2T_STATS_REQ_CFG_VAL_SET(*msg_word, cfg_val); HTT_H2T_STATS_REQ_CFG_STAT_TYPE_SET(*msg_word, cfg_stat_type); /* cookie LSBs */ msg_word++; *msg_word = cookie & 0xffffffff; /* cookie MSBs */ msg_word++; *msg_word = cookie >> 32; SET_HTC_PACKET_INFO_TX( &pkt->htc_pkt, htt_h2t_send_complete_free_netbuf, adf_nbuf_data(msg), adf_nbuf_len(msg), pdev->htc_endpoint, htc_tag); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); #ifdef ATH_11AC_TXCOMPACT if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) { htt_htc_misc_pkt_list_add(pdev, pkt); } #else HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); #endif if ((pdev->cfg.is_high_latency) && (!pdev->cfg.default_tx_comp_req)) { ol_tx_target_credit_update(pdev->txrx_pdev, -1); } return 0; }
A_STATUS htt_h2t_rx_ring_cfg_msg_hl(struct htt_pdev_t *pdev) { struct htt_htc_pkt *pkt; adf_nbuf_t msg; u_int32_t *msg_word; pkt = htt_htc_pkt_alloc(pdev); if (!pkt) { return A_ERROR; /* failure */ } /* show that this is not a tx frame download (not required, but helpful) */ pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; pkt->pdev_ctxt = NULL; /* not used during send-done callback */ msg = adf_nbuf_alloc( pdev->osdev, HTT_MSG_BUF_SIZE(HTT_RX_RING_CFG_BYTES(1)), /* reserve room for the HTC header */ HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE); if (!msg) { htt_htc_pkt_free(pdev, pkt); return A_ERROR; /* failure */ } /* * Set the length of the message. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added * separately during the below call to adf_nbuf_push_head. * The contribution from the HTC header is added separately inside HTC. */ adf_nbuf_put_tail(msg, HTT_RX_RING_CFG_BYTES(1)); /* fill in the message contents */ msg_word = (u_int32_t *) adf_nbuf_data(msg); /* rewind beyond alignment pad to get to the HTC header reserved area */ adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); *msg_word = 0; HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_RING_CFG); HTT_RX_RING_CFG_NUM_RINGS_SET(*msg_word, 1); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_IDX_SHADOW_REG_PADDR_SET( *msg_word, pdev->rx_ring.alloc_idx.paddr); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_BASE_PADDR_SET(*msg_word, pdev->rx_ring.base_paddr); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_LEN_SET(*msg_word, pdev->rx_ring.size); HTT_RX_RING_CFG_BUF_SZ_SET(*msg_word, HTT_RX_BUF_SIZE); /* FIX THIS: if the FW creates a complete translated rx descriptor, then the MAC DMA of the HW rx descriptor should be disabled. */ msg_word++; *msg_word = 0; HTT_RX_RING_CFG_ENABLED_802_11_HDR_SET(*msg_word, 0); HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_SET(*msg_word, 1); HTT_RX_RING_CFG_ENABLED_PPDU_START_SET(*msg_word, 0); HTT_RX_RING_CFG_ENABLED_PPDU_END_SET(*msg_word, 0); HTT_RX_RING_CFG_ENABLED_MPDU_START_SET(*msg_word, 0); HTT_RX_RING_CFG_ENABLED_MPDU_END_SET(*msg_word, 0); HTT_RX_RING_CFG_ENABLED_MSDU_START_SET(*msg_word, 0); HTT_RX_RING_CFG_ENABLED_MSDU_END_SET(*msg_word, 0); HTT_RX_RING_CFG_ENABLED_RX_ATTN_SET(*msg_word, 0); HTT_RX_RING_CFG_ENABLED_FRAG_INFO_SET(*msg_word, 0); /* always present? */ HTT_RX_RING_CFG_ENABLED_UCAST_SET(*msg_word, 1); HTT_RX_RING_CFG_ENABLED_MCAST_SET(*msg_word, 1); /* Must change to dynamic enable at run time * rather than at compile time */ HTT_RX_RING_CFG_ENABLED_CTRL_SET(*msg_word, 0); HTT_RX_RING_CFG_ENABLED_MGMT_SET(*msg_word, 0); HTT_RX_RING_CFG_ENABLED_NULL_SET(*msg_word, 0); HTT_RX_RING_CFG_ENABLED_PHY_SET(*msg_word, 0); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_OFFSET_802_11_HDR_SET(*msg_word, 0); HTT_RX_RING_CFG_OFFSET_MSDU_PAYLD_SET(*msg_word, 0); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_OFFSET_PPDU_START_SET(*msg_word, 0); HTT_RX_RING_CFG_OFFSET_PPDU_END_SET(*msg_word, 0); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_OFFSET_MPDU_START_SET(*msg_word, 0); HTT_RX_RING_CFG_OFFSET_MPDU_END_SET(*msg_word, 0); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_OFFSET_MSDU_START_SET(*msg_word, 0); HTT_RX_RING_CFG_OFFSET_MSDU_END_SET(*msg_word, 0); msg_word++; *msg_word = 0; HTT_RX_RING_CFG_OFFSET_RX_ATTN_SET(*msg_word, 0); HTT_RX_RING_CFG_OFFSET_FRAG_INFO_SET(*msg_word, 0); SET_HTC_PACKET_INFO_TX( &pkt->htc_pkt, htt_h2t_send_complete_free_netbuf, adf_nbuf_data(msg), adf_nbuf_len(msg), pdev->htc_endpoint, 1); /* tag - not relevant here */ SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); #ifdef ATH_11AC_TXCOMPACT if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) { htt_htc_misc_pkt_list_add(pdev, pkt); } #else HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); #endif if (!pdev->cfg.default_tx_comp_req) { ol_tx_target_credit_update(pdev->txrx_pdev, -1); } return A_OK; }
int htt_h2t_ipa_uc_rsc_cfg_msg(struct htt_pdev_t *pdev) { struct htt_htc_pkt *pkt; adf_nbuf_t msg; u_int32_t *msg_word; pkt = htt_htc_pkt_alloc(pdev); if (!pkt) { return A_NO_MEMORY; } /* show that this is not a tx frame download (not required, but helpful) */ pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; pkt->pdev_ctxt = NULL; /* not used during send-done callback */ msg = adf_nbuf_alloc( pdev->osdev, HTT_MSG_BUF_SIZE(HTT_WDI_IPA_CFG_SZ), /* reserve room for HTC header */ HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, FALSE); if (!msg) { htt_htc_pkt_free(pdev, pkt); return A_NO_MEMORY; } /* set the length of the message */ adf_nbuf_put_tail(msg, HTT_WDI_IPA_CFG_SZ); /* fill in the message contents */ msg_word = (u_int32_t *) adf_nbuf_data(msg); /* rewind beyond alignment pad to get to the HTC header reserved area */ adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); *msg_word = 0; HTT_WDI_IPA_CFG_TX_PKT_POOL_SIZE_SET(*msg_word, pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt); HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_WDI_IPA_CFG); msg_word++; *msg_word = 0; HTT_WDI_IPA_CFG_TX_COMP_RING_BASE_ADDR_SET(*msg_word, (unsigned int)pdev->ipa_uc_tx_rsc.tx_comp_base.paddr); msg_word++; *msg_word = 0; HTT_WDI_IPA_CFG_TX_COMP_RING_SIZE_SET(*msg_word, (unsigned int)ol_cfg_ipa_uc_tx_max_buf_cnt(pdev->ctrl_pdev)); msg_word++; *msg_word = 0; HTT_WDI_IPA_CFG_TX_COMP_WR_IDX_ADDR_SET(*msg_word, (unsigned int)pdev->ipa_uc_tx_rsc.tx_comp_idx_paddr); msg_word++; *msg_word = 0; HTT_WDI_IPA_CFG_TX_CE_WR_IDX_ADDR_SET(*msg_word, (unsigned int)pdev->ipa_uc_tx_rsc.tx_ce_idx.paddr); msg_word++; *msg_word = 0; HTT_WDI_IPA_CFG_RX_IND_RING_BASE_ADDR_SET(*msg_word, (unsigned int)pdev->ipa_uc_rx_rsc.rx_ind_ring_base.paddr); msg_word++; *msg_word = 0; HTT_WDI_IPA_CFG_RX_IND_RING_SIZE_SET(*msg_word, (unsigned int)ol_cfg_ipa_uc_rx_ind_ring_size(pdev->ctrl_pdev)); msg_word++; *msg_word = 0; HTT_WDI_IPA_CFG_RX_IND_RD_IDX_ADDR_SET(*msg_word, (unsigned int)pdev->ipa_uc_rx_rsc.rx_ipa_prc_done_idx.paddr); msg_word++; *msg_word = 0; HTT_WDI_IPA_CFG_RX_IND_WR_IDX_ADDR_SET(*msg_word, (unsigned int)pdev->ipa_uc_rx_rsc.rx_rdy_idx_paddr); SET_HTC_PACKET_INFO_TX( &pkt->htc_pkt, htt_h2t_send_complete_free_netbuf, adf_nbuf_data(msg), adf_nbuf_len(msg), pdev->htc_endpoint, HTC_TX_PACKET_TAG_RUNTIME_PUT); SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); #ifdef ATH_11AC_TXCOMPACT if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) htt_htc_misc_pkt_list_add(pdev, pkt); #else HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); #endif return A_OK; }
static int epping_tx_send_int(adf_nbuf_t skb, epping_adapter_t *pAdapter) { EPPING_HEADER *eppingHdr = (EPPING_HEADER *)adf_nbuf_data(skb); HTC_ENDPOINT_ID eid = ENDPOINT_UNUSED; struct epping_cookie * cookie = NULL; A_UINT8 ac = 0; A_STATUS ret = A_OK; int skb_len; EPPING_HEADER tmpHdr = *eppingHdr; /* allocate resource for this packet */ cookie = epping_alloc_cookie(pAdapter->pEpping_ctx); /* no resource */ if (cookie == NULL) { EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: epping_alloc_cookie returns no resource\n", __func__); return -1; } if (enb_tx_dump) epping_hex_dump((void *)eppingHdr, skb->len, __func__); /* * a quirk of linux, the payload of the frame is 32-bit aligned and thus * the addition of the HTC header will mis-align the start of the HTC * frame, so we add some padding which will be stripped off in the target */ if (EPPING_ALIGNMENT_PAD > 0) { A_NETBUF_PUSH(skb, EPPING_ALIGNMENT_PAD); } /* prepare ep/HTC information */ ac = eppingHdr->StreamNo_h; eid = pAdapter->pEpping_ctx->EppingEndpoint[ac]; if (eid < 0 || eid >= EPPING_MAX_NUM_EPIDS) { EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: invalid eid = %d, ac = %d\n", __func__, eid, ac); return -1; } if (tmpHdr.Cmd_h == EPPING_CMD_RESET_RECV_CNT || tmpHdr.Cmd_h == EPPING_CMD_CONT_RX_START) { epping_set_kperf_flag(pAdapter, eid, tmpHdr.CmdBuffer_t[0]); } if (pAdapter->pEpping_ctx->kperf[eid]) { switch (tmpHdr.Cmd_h) { case EPPING_CMD_NO_ECHO: #ifdef HIF_PCI epping_tx_copier_schedule(pAdapter->pEpping_ctx, eid, skb); #endif /* HIF_PCI */ break; default: break; } } if (pAdapter->pEpping_ctx->kperf[eid] && tmpHdr.Cmd_h == EPPING_CMD_NO_ECHO) { epping_tx_dup_pkt(pAdapter, eid, skb); } SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, cookie, adf_nbuf_data(skb), adf_nbuf_len(skb), eid, 0); SET_HTC_PACKET_NET_BUF_CONTEXT(&cookie->HtcPkt, skb); skb_len = skb->len; /* send the packet */ ret = HTCSendPkt(pAdapter->pEpping_ctx->HTCHandle, &cookie->HtcPkt); epping_log_packet(pAdapter, &tmpHdr, ret, __func__); if (ret != A_OK) { EPPING_LOG(VOS_TRACE_LEVEL_FATAL, "%s: HTCSendPkt failed, status = %d\n", __func__, ret); epping_free_cookie(pAdapter->pEpping_ctx, cookie); return -1; } pAdapter->stats.tx_bytes += skb_len; ++pAdapter->stats.tx_packets; if (((pAdapter->stats.tx_packets + pAdapter->stats.tx_dropped) % EPPING_STATS_LOG_COUNT) == 0 && (pAdapter->stats.tx_packets || pAdapter->stats.tx_dropped)) { epping_log_stats(pAdapter, __func__); } return 0; }
A_STATUS hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb) #endif { int status = A_OK; int length; EPPING_HEADER *pHeader; HTC_PACKET *pPacket; HTC_TX_TAG htc_tag = AR6K_DATA_PKT_TAG; #ifdef EXPORT_HCI_BRIDGE_INTERFACE AR6K_HCI_BRIDGE_INFO *pHcidevInfo = g_pHcidevInfo; #else AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)ar->hcidev_info; #endif do { if (NULL == pHcidevInfo) { status = A_ERROR; break; } if (NULL == pHcidevInfo->pHCIDev) { status = A_ERROR; break; } if (pHcidevInfo->HciNormalMode) { /* this interface cannot run when normal WMI is running */ status = A_ERROR; break; } pHeader = (EPPING_HEADER *)A_NETBUF_DATA(skb); if (!IS_EPPING_PACKET(pHeader)) { status = A_EINVAL; break; } if (IS_EPING_PACKET_NO_DROP(pHeader)) { htc_tag = AR6K_CONTROL_PKT_TAG; } length = sizeof(EPPING_HEADER) + pHeader->DataLength; pPacket = AllocHTCStruct(pHcidevInfo); if (NULL == pPacket) { status = A_NO_MEMORY; break; } SET_HTC_PACKET_INFO_TX(pPacket, skb, A_NETBUF_DATA(skb), length, HCI_ACL_TYPE, /* send every thing out as ACL */ htc_tag); HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,FALSE); pPacket = NULL; } while (FALSE); return status; }
A_STATUS htc_start(HTC_HANDLE HTCHandle) { cdf_nbuf_t netbuf; A_STATUS status = A_OK; HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); HTC_SETUP_COMPLETE_EX_MSG *pSetupComp; HTC_PACKET *pSendPacket; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Enter\n")); do { htc_config_target_hif_pipe(target); /* allocate a buffer to send */ pSendPacket = htc_alloc_control_tx_packet(target); if (NULL == pSendPacket) { AR_DEBUG_ASSERT(false); cdf_print("%s: allocControlTxPacket failed\n", __func__); status = A_NO_MEMORY; break; } netbuf = (cdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket); /* assemble setup complete message */ cdf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); pSetupComp = (HTC_SETUP_COMPLETE_EX_MSG *) cdf_nbuf_data(netbuf); A_MEMZERO(pSetupComp, sizeof(HTC_SETUP_COMPLETE_EX_MSG)); HTC_SET_FIELD(pSetupComp, HTC_SETUP_COMPLETE_EX_MSG, MESSAGEID, HTC_MSG_SETUP_COMPLETE_EX_ID); if (!htc_credit_flow) { AR_DEBUG_PRINTF(ATH_DEBUG_INIT, ("HTC will not use TX credit flow control\n")); pSetupComp->SetupFlags |= HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW; } else { AR_DEBUG_PRINTF(ATH_DEBUG_INIT, ("HTC using TX credit flow control\n")); } #ifdef HIF_SDIO #if ENABLE_BUNDLE_RX if (HTC_ENABLE_BUNDLE(target)) pSetupComp->SetupFlags |= HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV; #endif /* ENABLE_BUNDLE_RX */ #endif /* HIF_SDIO */ SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *) pSetupComp, sizeof(HTC_SETUP_COMPLETE_EX_MSG), ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); status = htc_send_pkt((HTC_HANDLE) target, pSendPacket); if (A_FAILED(status)) { break; } } while (false); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Exit\n")); return status; }
A_STATUS htt_h2t_ver_req_msg(struct htt_pdev_t *pdev) { struct htt_htc_pkt *pkt; adf_nbuf_t msg; u_int32_t *msg_word; u_int32_t msg_size; u_int32_t max_tx_group; pkt = htt_htc_pkt_alloc(pdev); if (!pkt) { return A_ERROR; /* failure */ } max_tx_group = OL_TX_GET_MAX_GROUPS(pdev->txrx_pdev); if (max_tx_group) { msg_size = HTT_VER_REQ_BYTES + sizeof(struct htt_option_tlv_mac_tx_queue_groups_t); } else { msg_size = HTT_VER_REQ_BYTES; } /* show that this is not a tx frame download (not required, but helpful) */ pkt->msdu_id = HTT_TX_COMPL_INV_MSDU_ID; pkt->pdev_ctxt = NULL; /* not used during send-done callback */ msg = adf_nbuf_alloc( pdev->osdev, HTT_MSG_BUF_SIZE(msg_size), /* reserve room for the HTC header */ HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE); if (!msg) { htt_htc_pkt_free(pdev, pkt); return A_ERROR; /* failure */ } /* * Set the length of the message. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added * separately during the below call to adf_nbuf_push_head. * The contribution from the HTC header is added separately inside HTC. */ adf_nbuf_put_tail(msg, msg_size); /* fill in the message contents */ msg_word = (u_int32_t *) adf_nbuf_data(msg); /* rewind beyond alignment pad to get to the HTC header reserved area */ adf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING); *msg_word = 0; HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_VERSION_REQ); if (max_tx_group) { *(msg_word + 1) = 0; /* Fill Group Info */ HTT_OPTION_TLV_TAG_SET(*(msg_word+1), HTT_OPTION_TLV_TAG_MAX_TX_QUEUE_GROUPS); HTT_OPTION_TLV_LENGTH_SET(*(msg_word+1), (sizeof(struct htt_option_tlv_mac_tx_queue_groups_t)/ sizeof(u_int32_t))); HTT_OPTION_TLV_VALUE0_SET(*(msg_word+1), max_tx_group); } SET_HTC_PACKET_INFO_TX( &pkt->htc_pkt, htt_h2t_send_complete_free_netbuf, adf_nbuf_data(msg), adf_nbuf_len(msg), pdev->htc_endpoint, 1); /* tag - not relevant here */ SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg); #ifdef ATH_11AC_TXCOMPACT if (HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt) == A_OK) { htt_htc_misc_pkt_list_add(pdev, pkt); } #else HTCSendPkt(pdev->htc_pdev, &pkt->htc_pkt); #endif if ((pdev->cfg.is_high_latency) && (!pdev->cfg.default_tx_comp_req)) { ol_tx_target_credit_update(pdev->txrx_pdev, -1); } return A_OK; }
/* 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); }
A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, HTC_SERVICE_CONNECT_REQ *pConnectReq, HTC_SERVICE_CONNECT_RESP *pConnectResp) { HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); A_STATUS status = A_OK; HTC_PACKET *pSendPacket = NULL; HTC_CONNECT_SERVICE_RESPONSE_MSG *pResponseMsg; HTC_CONNECT_SERVICE_MSG *pConnectMsg; HTC_ENDPOINT_ID assignedEndpoint = ENDPOINT_MAX; HTC_ENDPOINT *pEndpoint; unsigned int maxMsgSize = 0; adf_nbuf_t netbuf; A_UINT8 txAlloc; int length; A_BOOL disableCreditFlowCtrl = FALSE; A_UINT16 conn_flags; A_UINT16 rsp_msg_id, rsp_msg_serv_id, rsp_msg_max_msg_size; A_UINT8 rsp_msg_status, rsp_msg_end_id, rsp_msg_serv_meta_len; AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:%p SvcID:0x%X \n", target, pConnectReq->ServiceID)); do { AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0); if (HTC_CTRL_RSVD_SVC == pConnectReq->ServiceID) { /* special case for pseudo control service */ assignedEndpoint = ENDPOINT_0; maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH; txAlloc = 0; } else { txAlloc = HTCGetCreditAllocation(target,pConnectReq->ServiceID); if (!txAlloc) { AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("Service %d does not allocate target credits!\n", pConnectReq->ServiceID)); } /* allocate a packet to send to the target */ pSendPacket = HTCAllocControlTxPacket(target); if (NULL == pSendPacket) { AR_DEBUG_ASSERT(FALSE); status = A_NO_MEMORY; break; } netbuf = (adf_nbuf_t)GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket); length = sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectReq->MetaDataLength; /* assemble connect service message */ adf_nbuf_put_tail(netbuf, length); pConnectMsg = (HTC_CONNECT_SERVICE_MSG *)adf_nbuf_data(netbuf); AR_DEBUG_ASSERT(pConnectMsg != NULL); A_MEMZERO(pConnectMsg,sizeof(HTC_CONNECT_SERVICE_MSG)); conn_flags = (pConnectReq->ConnectionFlags & ~HTC_SET_RECV_ALLOC_MASK) | HTC_CONNECT_FLAGS_SET_RECV_ALLOCATION(txAlloc); HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG, MESSAGEID, HTC_MSG_CONNECT_SERVICE_ID); HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG, SERVICE_ID, pConnectReq->ServiceID); HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG, CONNECTIONFLAGS, conn_flags); if (pConnectReq->ConnectionFlags & HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL) { disableCreditFlowCtrl = TRUE; } /* * EV #134248 BUG Fix : Credit miss happens resulting in failure to create * VAP. Disable Credit for WMI endpoint too. */ if (!htc_credit_flow ) { disableCreditFlowCtrl = TRUE; } /* check caller if it wants to transfer meta data */ if ((pConnectReq->pMetaData != NULL) && (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { /* copy meta data into message buffer (after header ) */ A_MEMCPY((A_UINT8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG), pConnectReq->pMetaData, pConnectReq->MetaDataLength); HTC_SET_FIELD(pConnectMsg, HTC_CONNECT_SERVICE_MSG, SERVICEMETALENGTH, pConnectReq->MetaDataLength); } SET_HTC_PACKET_INFO_TX(pSendPacket, NULL, (A_UINT8 *)pConnectMsg, length, ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); status = HTCSendPkt((HTC_HANDLE)target,pSendPacket); /* we don't own it anymore */ pSendPacket = NULL; if (A_FAILED(status)) { break; } /* wait for response */ status = HTCWaitRecvCtrlMessage(target); if (A_FAILED(status)) { break; } /* we controlled the buffer creation so it has to be properly aligned */ pResponseMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)target->CtrlResponseBuffer; rsp_msg_id = HTC_GET_FIELD(pResponseMsg, HTC_CONNECT_SERVICE_RESPONSE_MSG, MESSAGEID); rsp_msg_serv_id = HTC_GET_FIELD(pResponseMsg, HTC_CONNECT_SERVICE_RESPONSE_MSG, SERVICEID); rsp_msg_status = HTC_GET_FIELD(pResponseMsg, HTC_CONNECT_SERVICE_RESPONSE_MSG, STATUS); rsp_msg_end_id = HTC_GET_FIELD(pResponseMsg, HTC_CONNECT_SERVICE_RESPONSE_MSG, ENDPOINTID); rsp_msg_max_msg_size = HTC_GET_FIELD(pResponseMsg, HTC_CONNECT_SERVICE_RESPONSE_MSG, MAXMSGSIZE); rsp_msg_serv_meta_len = HTC_GET_FIELD(pResponseMsg, HTC_CONNECT_SERVICE_RESPONSE_MSG, SERVICEMETALENGTH); if ((rsp_msg_id != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) || (target->CtrlResponseLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) { /* this message is not valid */ AR_DEBUG_ASSERT(FALSE); status = A_EPROTO; break; } AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCConnectService, service 0x%X connect response from target status:%d, assigned ep: %d\n", rsp_msg_serv_id, rsp_msg_status, rsp_msg_end_id)); pConnectResp->ConnectRespCode = rsp_msg_status; /* check response status */ if (rsp_msg_status != HTC_SERVICE_SUCCESS) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target failed service 0x%X connect request (status:%d)\n", rsp_msg_serv_id, rsp_msg_status)); status = A_EPROTO; break; } assignedEndpoint = (HTC_ENDPOINT_ID)rsp_msg_end_id; maxMsgSize = rsp_msg_max_msg_size; if ((pConnectResp->pMetaData != NULL) && (rsp_msg_serv_meta_len > 0) && (rsp_msg_serv_meta_len <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { /* caller supplied a buffer and the target responded with data */ int copyLength = min((int)pConnectResp->BufferLength, (int)rsp_msg_serv_meta_len); /* copy the meta data */ A_MEMCPY(pConnectResp->pMetaData, ((A_UINT8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG), copyLength); pConnectResp->ActualLength = copyLength; } /* done processing response buffer */ target->CtrlResponseProcessing = FALSE; } /* the rest of these are parameter checks so set the error status */ status = A_EPROTO; if (assignedEndpoint >= ENDPOINT_MAX) { AR_DEBUG_ASSERT(FALSE); break; } if (0 == maxMsgSize) { AR_DEBUG_ASSERT(FALSE); break; } pEndpoint = &target->EndPoint[assignedEndpoint]; pEndpoint->Id = assignedEndpoint; if (pEndpoint->ServiceID != 0) { /* endpoint already in use! */ AR_DEBUG_ASSERT(FALSE); break; } /* return assigned endpoint to caller */ pConnectResp->Endpoint = assignedEndpoint; pConnectResp->MaxMsgLength = maxMsgSize; /* setup the endpoint */ pEndpoint->ServiceID = pConnectReq->ServiceID; /* this marks the endpoint in use */ pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth; pEndpoint->MaxMsgLength = maxMsgSize; pEndpoint->TxCredits = txAlloc; pEndpoint->TxCreditSize = target->TargetCreditSize; pEndpoint->TxCreditsPerMaxMsg = maxMsgSize / target->TargetCreditSize; if (maxMsgSize % target->TargetCreditSize) { pEndpoint->TxCreditsPerMaxMsg++; } /* copy all the callbacks */ pEndpoint->EpCallBacks = pConnectReq->EpCallbacks; status = HIFMapServiceToPipe(target->hif_dev, pEndpoint->ServiceID, &pEndpoint->UL_PipeID, &pEndpoint->DL_PipeID, &pEndpoint->ul_is_polled, &pEndpoint->dl_is_polled); if (A_FAILED(status)) { break; } adf_os_assert(!pEndpoint->dl_is_polled); /* not currently supported */ if (pEndpoint->ul_is_polled) { adf_os_timer_init( target->osdev, &pEndpoint->ul_poll_timer, HTCSendCompleteCheckCleanup, pEndpoint); } AR_DEBUG_PRINTF(ATH_DEBUG_SETUP, ("HTC Service:0x%4.4X, ULpipe:%d DLpipe:%d id:%d Ready\n", pEndpoint->ServiceID,pEndpoint->UL_PipeID,pEndpoint->DL_PipeID,pEndpoint->Id)); if (disableCreditFlowCtrl && pEndpoint->TxCreditFlowEnabled) { pEndpoint->TxCreditFlowEnabled = FALSE; AR_DEBUG_PRINTF(ATH_DEBUG_WARN,("HTC Service:0x%4.4X ep:%d TX flow control disabled\n", pEndpoint->ServiceID, assignedEndpoint)); } } while (FALSE); AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCConnectService \n")); return status; }