void htt_h2t_send_complete(void *context, HTC_PACKET *htc_pkt) { void (*send_complete_part2)( void *pdev, A_STATUS status, adf_nbuf_t msdu, u_int16_t msdu_id); struct htt_pdev_t *pdev = (struct htt_pdev_t *) context; struct htt_htc_pkt *htt_pkt; adf_nbuf_t netbuf; send_complete_part2 = htc_pkt->pPktContext; htt_pkt = container_of(htc_pkt, struct htt_htc_pkt, htc_pkt); /* process (free or keep) the netbuf that held the message */ netbuf = (adf_nbuf_t) htc_pkt->pNetBufContext; if (send_complete_part2 != NULL) { send_complete_part2( htt_pkt->pdev_ctxt, htc_pkt->Status, netbuf, htt_pkt->msdu_id); } if (pdev->cfg.is_high_latency && !pdev->cfg.default_tx_comp_req) { int32_t credit_delta; adf_os_atomic_add(1, &pdev->htt_tx_credit.bus_delta); credit_delta = htt_tx_credit_update(pdev); if (credit_delta) { ol_tx_credit_completion_handler(pdev->txrx_pdev, credit_delta); } } /* free the htt_htc_pkt / HTC_PACKET object */ htt_htc_pkt_free(pdev, htt_pkt); }
/* Target to host Msg/event handler for low priority messages*/ void htt_t2h_lp_msg_handler(void *context, adf_nbuf_t htt_t2h_msg ) { struct htt_pdev_t *pdev = (struct htt_pdev_t *) context; u_int32_t *msg_word; enum htt_t2h_msg_type msg_type; msg_word = (u_int32_t *) adf_nbuf_data(htt_t2h_msg); msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word); switch (msg_type) { case HTT_T2H_MSG_TYPE_VERSION_CONF: { htc_pm_runtime_put(pdev->htc_pdev); pdev->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word); pdev->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word); adf_os_print("target uses HTT version %d.%d; host uses %d.%d\n", pdev->tgt_ver.major, pdev->tgt_ver.minor, HTT_CURRENT_VERSION_MAJOR, HTT_CURRENT_VERSION_MINOR); if (pdev->tgt_ver.major != HTT_CURRENT_VERSION_MAJOR) { adf_os_print("*** Incompatible host/target HTT versions!\n"); } /* abort if the target is incompatible with the host */ adf_os_assert(pdev->tgt_ver.major == HTT_CURRENT_VERSION_MAJOR); if (pdev->tgt_ver.minor != HTT_CURRENT_VERSION_MINOR) { adf_os_print( "*** Warning: host/target HTT versions are different, " "though compatible!\n"); } break; } case HTT_T2H_MSG_TYPE_RX_FLUSH: { u_int16_t peer_id; u_int8_t tid; int seq_num_start, seq_num_end; enum htt_rx_flush_action action; peer_id = HTT_RX_FLUSH_PEER_ID_GET(*msg_word); tid = HTT_RX_FLUSH_TID_GET(*msg_word); seq_num_start = HTT_RX_FLUSH_SEQ_NUM_START_GET(*(msg_word+1)); seq_num_end = HTT_RX_FLUSH_SEQ_NUM_END_GET(*(msg_word+1)); action = HTT_RX_FLUSH_MPDU_STATUS_GET(*(msg_word+1)) == 1 ? htt_rx_flush_release : htt_rx_flush_discard; ol_rx_flush_handler( pdev->txrx_pdev, peer_id, tid, seq_num_start, seq_num_end, action); break; } case HTT_T2H_MSG_TYPE_RX_OFFLOAD_DELIVER_IND: { int msdu_cnt; msdu_cnt = HTT_RX_OFFLOAD_DELIVER_IND_MSDU_CNT_GET(*msg_word); ol_rx_offload_deliver_ind_handler( pdev->txrx_pdev, htt_t2h_msg, msdu_cnt); break; } case HTT_T2H_MSG_TYPE_RX_FRAG_IND: { u_int16_t peer_id; u_int8_t tid; peer_id = HTT_RX_FRAG_IND_PEER_ID_GET(*msg_word); tid = HTT_RX_FRAG_IND_EXT_TID_GET(*msg_word); HTT_RX_FRAG_SET_LAST_MSDU(pdev, htt_t2h_msg); ol_rx_frag_indication_handler( pdev->txrx_pdev, htt_t2h_msg, peer_id, tid); break; } case HTT_T2H_MSG_TYPE_RX_ADDBA: { u_int16_t peer_id; u_int8_t tid; u_int8_t win_sz; u_int16_t start_seq_num; /* * FOR NOW, the host doesn't need to know the initial * sequence number for rx aggregation. * Thus, any value will do - specify 0. */ start_seq_num = 0; peer_id = HTT_RX_ADDBA_PEER_ID_GET(*msg_word); tid = HTT_RX_ADDBA_TID_GET(*msg_word); win_sz = HTT_RX_ADDBA_WIN_SIZE_GET(*msg_word); ol_rx_addba_handler( pdev->txrx_pdev, peer_id, tid, win_sz, start_seq_num, 0 /* success */); break; } case HTT_T2H_MSG_TYPE_RX_DELBA: { u_int16_t peer_id; u_int8_t tid; peer_id = HTT_RX_DELBA_PEER_ID_GET(*msg_word); tid = HTT_RX_DELBA_TID_GET(*msg_word); ol_rx_delba_handler(pdev->txrx_pdev, peer_id, tid); break; } case HTT_T2H_MSG_TYPE_PEER_MAP: { u_int8_t mac_addr_deswizzle_buf[HTT_MAC_ADDR_LEN]; u_int8_t *peer_mac_addr; u_int16_t peer_id; u_int8_t vdev_id; peer_id = HTT_RX_PEER_MAP_PEER_ID_GET(*msg_word); vdev_id = HTT_RX_PEER_MAP_VDEV_ID_GET(*msg_word); peer_mac_addr = htt_t2h_mac_addr_deswizzle( (u_int8_t *) (msg_word+1), &mac_addr_deswizzle_buf[0]); ol_rx_peer_map_handler( pdev->txrx_pdev, peer_id, vdev_id, peer_mac_addr, 1/*can tx*/); break; } case HTT_T2H_MSG_TYPE_PEER_UNMAP: { u_int16_t peer_id; peer_id = HTT_RX_PEER_UNMAP_PEER_ID_GET(*msg_word); ol_rx_peer_unmap_handler(pdev->txrx_pdev, peer_id); break; } case HTT_T2H_MSG_TYPE_SEC_IND: { u_int16_t peer_id; enum htt_sec_type sec_type; int is_unicast; peer_id = HTT_SEC_IND_PEER_ID_GET(*msg_word); sec_type = HTT_SEC_IND_SEC_TYPE_GET(*msg_word); is_unicast = HTT_SEC_IND_UNICAST_GET(*msg_word); msg_word++; /* point to the first part of the Michael key */ ol_rx_sec_ind_handler( pdev->txrx_pdev, peer_id, sec_type, is_unicast, msg_word, msg_word+2); break; } case HTT_T2H_MSG_TYPE_MGMT_TX_COMPL_IND: { struct htt_mgmt_tx_compl_ind *compl_msg; compl_msg = (struct htt_mgmt_tx_compl_ind *)(msg_word + 1); if (pdev->cfg.is_high_latency) { ol_tx_target_credit_update(pdev->txrx_pdev, 1); } ol_tx_single_completion_handler( pdev->txrx_pdev, compl_msg->status, compl_msg->desc_id); htc_pm_runtime_put(pdev->htc_pdev); HTT_TX_SCHED(pdev); break; } #if TXRX_STATS_LEVEL != TXRX_STATS_LEVEL_OFF case HTT_T2H_MSG_TYPE_STATS_CONF: { u_int64_t cookie; u_int8_t *stats_info_list; cookie = *(msg_word + 1); cookie |= ((u_int64_t) (*(msg_word + 2))) << 32; stats_info_list = (u_int8_t *) (msg_word + 3); htc_pm_runtime_put(pdev->htc_pdev); ol_txrx_fw_stats_handler(pdev->txrx_pdev, cookie, stats_info_list); break; } #endif #ifndef REMOVE_PKT_LOG case HTT_T2H_MSG_TYPE_PKTLOG: { u_int32_t *pl_hdr; u_int32_t log_type; pl_hdr = (msg_word + 1); log_type = (*(pl_hdr + 1) & ATH_PKTLOG_HDR_LOG_TYPE_MASK) >> ATH_PKTLOG_HDR_LOG_TYPE_SHIFT; if (log_type == PKTLOG_TYPE_TX_CTRL || (log_type) == PKTLOG_TYPE_TX_STAT || (log_type) == PKTLOG_TYPE_TX_MSDU_ID || (log_type) == PKTLOG_TYPE_TX_FRM_HDR || (log_type) == PKTLOG_TYPE_TX_VIRT_ADDR) { wdi_event_handler(WDI_EVENT_TX_STATUS, pdev->txrx_pdev, pl_hdr); } else if ((log_type) == PKTLOG_TYPE_RC_FIND) { wdi_event_handler(WDI_EVENT_RATE_FIND, pdev->txrx_pdev, pl_hdr); } else if ((log_type) == PKTLOG_TYPE_RC_UPDATE) { wdi_event_handler( WDI_EVENT_RATE_UPDATE, pdev->txrx_pdev, pl_hdr); } else if ((log_type) == PKTLOG_TYPE_RX_STAT) { wdi_event_handler(WDI_EVENT_RX_DESC, pdev->txrx_pdev, pl_hdr); } break; } #endif case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND: { u_int32_t htt_credit_delta_abs; int32_t htt_credit_delta; int sign; htt_credit_delta_abs = HTT_TX_CREDIT_DELTA_ABS_GET(*msg_word); sign = HTT_TX_CREDIT_SIGN_BIT_GET(*msg_word) ? -1 : 1; htt_credit_delta = sign * htt_credit_delta_abs; ol_tx_credit_completion_handler(pdev->txrx_pdev, htt_credit_delta); break; } #ifdef IPA_UC_OFFLOAD case HTT_T2H_MSG_TYPE_WDI_IPA_OP_RESPONSE: { u_int8_t op_code; u_int16_t len; u_int8_t *op_msg_buffer; u_int8_t *msg_start_ptr; htc_pm_runtime_put(pdev->htc_pdev); msg_start_ptr = (u_int8_t *)msg_word; op_code = HTT_WDI_IPA_OP_RESPONSE_OP_CODE_GET(*msg_word); msg_word++; len = HTT_WDI_IPA_OP_RESPONSE_RSP_LEN_GET(*msg_word); op_msg_buffer = adf_os_mem_alloc(NULL, sizeof(struct htt_wdi_ipa_op_response_t) + len); if (!op_msg_buffer) { adf_os_print("OPCODE messsage buffer alloc fail"); break; } adf_os_mem_copy(op_msg_buffer, msg_start_ptr, sizeof(struct htt_wdi_ipa_op_response_t) + len); ol_txrx_ipa_uc_op_response(pdev->txrx_pdev, op_msg_buffer); break; } #endif /* IPA_UC_OFFLOAD */ default: break; }; /* Free the indication buffer */ adf_nbuf_free(htt_t2h_msg); }