void ol_rx_err( ol_pdev_handle pdev, u_int8_t vdev_id, u_int8_t *peer_mac_addr, int tid, u_int32_t tsf32, enum ol_rx_err_type err_type, adf_nbuf_t rx_frame) { struct ieee80211_frame wh; struct ether_header *eh; struct ol_ath_softc_net80211 *scn ; struct ieee80211vap *vap; enum ieee80211_opmode opmode; A_BOOL notify = TRUE; eh = (struct ether_header *)adf_nbuf_data(rx_frame); scn = (struct ol_ath_softc_net80211 *)pdev; vap = ol_ath_vap_get(scn, vdev_id); if(vap == NULL) { printk("%s: vap is NULL \n", __func__); return; } opmode = ieee80211_vap_get_opmode(vap); if (err_type == OL_RX_ERR_TKIP_MIC) { /*TODO: Reconstructing the WLAN header for now from ether header * since WLAN header is not available for HL case. */ wh.i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_DATA; wh.i_dur[0] = wh.i_dur[1] = 0; wh.i_seq[0] = wh.i_seq[1] = 0; adf_os_mem_copy(&wh.i_addr1, &vap->iv_myaddr, IEEE80211_ADDR_LEN); adf_os_mem_copy(&wh.i_addr2, peer_mac_addr, IEEE80211_ADDR_LEN); if (opmode == IEEE80211_M_HOSTAP || opmode == IEEE80211_M_WDS) { wh.i_fc[1] = IEEE80211_FC1_DIR_TODS; adf_os_mem_copy(&wh.i_addr3, &eh->ether_dhost , IEEE80211_ADDR_LEN); } else if (opmode == IEEE80211_M_STA) { wh.i_fc[1] = IEEE80211_FC1_DIR_FROMDS; adf_os_mem_copy(&wh.i_addr3, &eh->ether_shost , IEEE80211_ADDR_LEN); } else { /*TODO: Handle other cases*/ notify = FALSE; } if (notify) { printk("%s: TKIP MIC failure \n",__func__); ieee80211_notify_michael_failure(vap,(const struct ieee80211_frame *)&wh,0); } } }
static inline void ol_rx_decap_to_native_wifi( struct ol_txrx_vdev_t *vdev, adf_nbuf_t msdu, struct ol_rx_decap_info_t *info, struct ethernet_hdr_t *ethr_hdr) { struct ieee80211_frame_addr4 *wh; u_int16_t hdsize; /* * we need to remove Qos control field and HT control. * MSFT: http://msdn.microsoft.com/en-us/library/windows/hardware/ff552608(v=vs.85).aspx */ wh = (struct ieee80211_frame_addr4 *)info->hdr; if ( (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) { hdsize = sizeof(struct ieee80211_frame_addr4); } else { hdsize = sizeof(struct ieee80211_frame); } wh = (struct ieee80211_frame_addr4 *) adf_nbuf_push_head(msdu, hdsize); TXRX_ASSERT2(wh != NULL); TXRX_ASSERT2(hdsize <= info->hdr_len); adf_os_mem_copy ((u_int8_t *)wh, info->hdr, hdsize); /* amsdu subfrm handling if ethr_hdr is not NULL */ if (ethr_hdr != NULL) { switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { case IEEE80211_FC1_DIR_NODS: adf_os_mem_copy(wh->i_addr1, ethr_hdr->dest_addr, ETHERNET_ADDR_LEN); adf_os_mem_copy(wh->i_addr2, ethr_hdr->src_addr, ETHERNET_ADDR_LEN); break; case IEEE80211_FC1_DIR_TODS: adf_os_mem_copy(wh->i_addr2, ethr_hdr->src_addr, ETHERNET_ADDR_LEN); adf_os_mem_copy(wh->i_addr3, ethr_hdr->dest_addr, ETHERNET_ADDR_LEN); break; case IEEE80211_FC1_DIR_FROMDS: adf_os_mem_copy(wh->i_addr1, ethr_hdr->dest_addr, ETHERNET_ADDR_LEN); adf_os_mem_copy(wh->i_addr3, ethr_hdr->src_addr, ETHERNET_ADDR_LEN); break; case IEEE80211_FC1_DIR_DSTODS: adf_os_mem_copy(wh->i_addr3, ethr_hdr->dest_addr, ETHERNET_ADDR_LEN); adf_os_mem_copy(wh->i_addr4, ethr_hdr->src_addr, ETHERNET_ADDR_LEN); break; } } if (IEEE80211_QOS_HAS_SEQ(wh) ) { if (wh->i_fc[1] & IEEE80211_FC1_ORDER) { wh->i_fc[1] &= ~IEEE80211_FC1_ORDER; } wh->i_fc[0] &= ~IEEE80211_FC0_SUBTYPE_QOS; } }
int wmi_send_node_rate_sched(struct ol_ath_softc_net80211 *scn, wmi_peer_rate_retry_sched_cmd *cmd_buf) { wmi_unified_t wmi_handle = scn->wmi_handle; wmi_peer_rate_retry_sched_cmd *cmd; wmi_buf_t buf; int len = sizeof(wmi_peer_rate_retry_sched_cmd); buf = wmi_buf_alloc(wmi_handle, len); if(!buf) { printk("%s: wmi_buf_alloc failed\n", __func__); return ENOMEM; } cmd = (wmi_peer_rate_retry_sched_cmd *)wmi_buf_data(buf); adf_os_mem_copy(cmd, cmd_buf, len); return (wmi_unified_cmd_send( wmi_handle, buf, len, WMI_PEER_RATE_RETRY_SCHED_CMDID)); }
a_status_t fwd_send_next(fwd_softc_t *sc) { a_uint32_t len, alloclen; adf_nbuf_t nbuf; fwd_cmd_t *h; a_uint8_t *pld; a_uint32_t target_jmp_loc; len = fwd_chunk_len(sc); alloclen = sizeof(fwd_cmd_t) + len; if (fwd_is_first(sc) || fwd_is_last(sc)) alloclen += 4; nbuf = adf_nbuf_alloc(NULL,alloclen + 20, 20, 0); if (!nbuf) { adf_os_print("FWD: packet allocation failed. \n"); return A_STATUS_ENOMEM; } h = (fwd_cmd_t *)adf_nbuf_put_tail(nbuf, alloclen); h->more_data = adf_os_htons(!fwd_is_last(sc)); h->len = adf_os_htons(len); h->offset = adf_os_htonl(sc->offset); pld = (a_uint8_t *)(h + 1); if (fwd_is_first(sc)) { *(a_uint32_t *)pld = adf_os_htonl(sc->target_upload_addr); pld += 4; } adf_os_mem_copy(pld, &sc->image[sc->offset], len); if(h->more_data == 0) { target_jmp_loc = adf_os_htonl(fw_exec_addr); adf_os_mem_copy(pld+len, (a_uint8_t *)&target_jmp_loc, 4); } HIFSend(sc->hif_handle, sc->tx_pipe, NULL, nbuf); /*adf_os_timer_start(&sc->tmr, FWD_TIMEOUT_MSECS);*/ return A_STATUS_OK; }
void __adf_nbuf_trace_update(struct sk_buff *buf, char *event_string) { char string_buf[NBUF_PKT_TRAC_MAX_STRING]; if ((!trace_update_cb) || (!event_string)) { return; } if (!adf_nbuf_trace_get_proto_type(buf)) { return; } /* Buffer over flow */ if (NBUF_PKT_TRAC_MAX_STRING <= (adf_os_str_len(event_string) + NBUF_PKT_TRAC_PROTO_STRING)) { return; } adf_os_mem_zero(string_buf, NBUF_PKT_TRAC_MAX_STRING); adf_os_mem_copy(string_buf, event_string, adf_os_str_len(event_string)); if (NBUF_PKT_TRAC_TYPE_EAPOL & adf_nbuf_trace_get_proto_type(buf)) { adf_os_mem_copy(string_buf + adf_os_str_len(event_string), "EPL", NBUF_PKT_TRAC_PROTO_STRING); } else if (NBUF_PKT_TRAC_TYPE_DHCP & adf_nbuf_trace_get_proto_type(buf)) { adf_os_mem_copy(string_buf + adf_os_str_len(event_string), "DHC", NBUF_PKT_TRAC_PROTO_STRING); } else if (NBUF_PKT_TRAC_TYPE_MGMT_ACTION & adf_nbuf_trace_get_proto_type(buf)) { adf_os_mem_copy(string_buf + adf_os_str_len(event_string), "MACT", NBUF_PKT_TRAC_PROTO_STRING); } trace_update_cb(string_buf); return; }
/** * adf_dp_add_record() - add dp trace record * @code: dptrace code * @data: data pointer * @size: size of buffer * @print: print it in kmsg * * Return: none */ void adf_dp_add_record(enum ADF_DP_TRACE_ID code, uint8_t *data, uint8_t size, bool print) { struct adf_dp_trace_record_s *rec = NULL; int index; spin_lock_bh(&l_dp_trace_lock); g_adf_dp_trace_data.num++; if (g_adf_dp_trace_data.num > MAX_ADF_DP_TRACE_RECORDS) g_adf_dp_trace_data.num = MAX_ADF_DP_TRACE_RECORDS; if (INVALID_ADF_DP_TRACE_ADDR == g_adf_dp_trace_data.head) { /* first record */ g_adf_dp_trace_data.head = 0; g_adf_dp_trace_data.tail = 0; } else { /* queue is not empty */ g_adf_dp_trace_data.tail++; if (MAX_ADF_DP_TRACE_RECORDS == g_adf_dp_trace_data.tail) g_adf_dp_trace_data.tail = 0; if (g_adf_dp_trace_data.head == g_adf_dp_trace_data.tail) { /* full */ if (MAX_ADF_DP_TRACE_RECORDS == ++g_adf_dp_trace_data.head) g_adf_dp_trace_data.head = 0; } } rec = &g_adf_dp_trace_tbl[g_adf_dp_trace_data.tail]; index = g_adf_dp_trace_data.tail; rec->code = code; rec->size = 0; if (data != NULL && size > 0) { if (size > ADF_DP_TRACE_RECORD_SIZE) size = ADF_DP_TRACE_RECORD_SIZE; rec->size = size; adf_os_mem_copy(rec->data, data, size); } rec->time = adf_os_gettimestamp(); rec->pid = (in_interrupt() ? 0 : current->pid); spin_unlock_bh(&l_dp_trace_lock); if ((g_adf_dp_trace_data.live_mode || print == true) && (rec->code < ADF_DP_TRACE_MAX)) adf_dp_trace_cb_table[rec->code] (rec, index); }
adf_nbuf_t RxSgToSingleNetbuf(HTC_TARGET *target) { adf_nbuf_t skb; a_uint8_t *anbdata; a_uint8_t *anbdata_new; a_uint32_t anblen; adf_nbuf_t new_skb = NULL; a_uint32_t sg_queue_len; adf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue; sg_queue_len = adf_nbuf_queue_len(rx_sg_queue); if (sg_queue_len <= 1) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("RxSgToSingleNetbuf: invalid sg queue len %u\n")); goto _failed; } new_skb = adf_nbuf_alloc(target->ExpRxSgTotalLen, 0, 4, FALSE); if (new_skb == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("RxSgToSingleNetbuf: can't allocate %u size netbuf\n", target->ExpRxSgTotalLen)); goto _failed; } adf_nbuf_peek_header(new_skb, &anbdata_new, &anblen); skb = adf_nbuf_queue_remove(rx_sg_queue); do { adf_nbuf_peek_header(skb, &anbdata, &anblen); adf_os_mem_copy(anbdata_new, anbdata, adf_nbuf_len(skb)); adf_nbuf_put_tail(new_skb, adf_nbuf_len(skb)); anbdata_new += adf_nbuf_len(skb); adf_nbuf_free(skb); skb = adf_nbuf_queue_remove(rx_sg_queue); } while(skb != NULL); RESET_RX_SG_CONFIG(target); return new_skb; _failed: while ((skb = adf_nbuf_queue_remove(rx_sg_queue)) != NULL) { adf_nbuf_free(skb); } RESET_RX_SG_CONFIG(target); return NULL; }
/** * @brief * * @param sc * @param data * * @return */ static a_status_t acfg_iwevent_leave_ap(__adf_softc_t *sc, acfg_ev_data_t *data) { union iwreq_data wreq = {{0}}; wreq.addr.sa_family = ARPHRD_ETHER; adf_os_mem_copy(wreq.addr.sa_data, data->leave_ap.mac, ETH_ALEN); adf_trace(ADF_DEBUG_FUNCTRACE, "ADF_EVENT: LEAVE AP\n"); wireless_send_event(hdl_to_netdev(sc), IWEVEXPIRED, &wreq, NULL); return A_STATUS_OK; }
/** * adf_dp_trace_ptr() - record dptrace * @code: dptrace code * @data: data * @size: size of data * @msdu_id: msdu_id * @status: return status * * Return: none */ void adf_dp_trace_ptr(adf_nbuf_t nbuf, enum ADF_DP_TRACE_ID code, uint8_t *data, uint8_t size, uint16_t msdu_id, uint16_t status) { struct adf_dp_trace_ptr_buf buf; int buf_size = sizeof(struct adf_dp_trace_ptr_buf); if (adf_dp_enable_check(nbuf, code, ADF_TX) == false) return; if (buf_size > ADF_DP_TRACE_RECORD_SIZE) ADF_BUG(0); adf_os_mem_copy(&buf.cookie, data, size); buf.msdu_id = msdu_id; buf.status = status; adf_dp_add_record(code, (uint8_t *)&buf, buf_size, false); }
static inline A_STATUS ol_tx_copy_native_wifi_header( adf_nbuf_t msdu, u_int8_t *hdsize, u_int8_t *localbuf) { struct ieee80211_frame *wh = (struct ieee80211_frame*)adf_nbuf_data(msdu); if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) { *hdsize = sizeof(struct ieee80211_frame_addr4); } else { *hdsize = sizeof(struct ieee80211_frame); } if (adf_nbuf_len(msdu) < *hdsize) { return A_ERROR; } adf_os_mem_copy(localbuf, wh, *hdsize); return A_OK; }
void _wmi_cmd_rsp(void *pContext, WMI_COMMAND_ID cmd_id, A_UINT16 SeqNo, A_UINT8 *buffer, int Length) { adf_nbuf_t netbuf = ADF_NBUF_NULL; A_UINT8 *pData; netbuf = WMI_AllocEvent(pContext, WMI_EVT_CLASS_CMD_REPLY, sizeof(WMI_CMD_HDR) + Length); if (netbuf == ADF_NBUF_NULL) { adf_os_print("%s: buffer allocation for event_id %x failed!\n", __FUNCTION__, cmd_id); adf_os_assert(0); return; } if (Length != 0 && buffer != NULL) { pData = (A_UINT8 *)adf_nbuf_put_tail(netbuf, Length); adf_os_mem_copy(pData, buffer, Length); } WMI_SendEvent(pContext, netbuf, cmd_id, SeqNo, Length); }
static inline A_STATUS ol_tx_encap_from_native_wifi ( struct ol_txrx_vdev_t *vdev, struct ol_tx_desc_t *tx_desc, adf_nbuf_t msdu, struct ol_txrx_msdu_info_t *tx_msdu_info ) { u_int8_t localbuf[sizeof(struct ieee80211_qosframe_htc_addr4)]; struct ieee80211_frame *wh; u_int8_t hdsize, new_hdsize; struct ieee80211_qoscntl *qos_cntl; struct ol_txrx_peer_t *peer; if (tx_msdu_info->htt.info.frame_type != htt_frm_type_data) { return A_OK; } peer = tx_msdu_info->peer; /* * for unicast,the peer should not be NULL. * for multicast, the peer is AP. */ if (tx_msdu_info->htt.info.is_unicast && peer->qos_capable) { if (A_OK != ol_tx_copy_native_wifi_header(msdu, &hdsize, localbuf)) return A_ERROR; wh = (struct ieee80211_frame*)localbuf; /*add qos cntl*/ qos_cntl = (struct ieee80211_qoscntl*)(localbuf + hdsize); qos_cntl->i_qos[0] = tx_msdu_info->htt.info.ext_tid & IEEE80211_QOS_TID; #if 0 if ( wmmParam[ac].wmep_noackPolicy ) { qos_cntl->i_qos[0]|= 1 << IEEE80211_QOS_ACKPOLICY_S; } #endif qos_cntl->i_qos[1] = 0; wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS; /* count for qos field */ new_hdsize = hdsize + sizeof(struct ieee80211_qosframe) - sizeof(struct ieee80211_frame); /*add ht control field if needed */ /* copy new hd to bd */ adf_os_mem_copy( (void*)htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, new_hdsize), localbuf, new_hdsize); adf_nbuf_pull_head(msdu, hdsize); tx_msdu_info->htt.info.l3_hdr_offset = new_hdsize; tx_desc->orig_l2_hdr_bytes = hdsize; } /* Set Protected Frame bit in MAC header */ if (vdev->pdev->sw_pf_proc_enable && tx_msdu_info->htt.action.do_encrypt) { if (tx_desc->orig_l2_hdr_bytes) { wh = (struct ieee80211_frame*)htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, tx_msdu_info->htt.info.l3_hdr_offset); } else { if (A_OK != ol_tx_copy_native_wifi_header(msdu, &hdsize, localbuf)) return A_ERROR; wh = (struct ieee80211_frame*)htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc, hdsize); adf_os_mem_copy((void*)wh, localbuf, hdsize); adf_nbuf_pull_head(msdu, hdsize); tx_msdu_info->htt.info.l3_hdr_offset = hdsize; tx_desc->orig_l2_hdr_bytes = hdsize; } wh->i_fc[1] |= IEEE80211_FC1_WEP; } return A_OK; }
void * __ahdecl ath_hal_memcpy(void *dst, const void *src, adf_os_size_t n) { adf_os_mem_copy(dst, src, n); return 0; }
/* 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); }
void ieee80211_add_vap_target(struct ieee80211vap *vap) { struct ieee80211com *ic = vap->iv_ic; struct ieee80211vap_target vt; int i; u_int8_t vapindex = 0; #if 0 /* Dump mac address */ printk("%s, mac: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", __FUNCTION__, vap->iv_myaddr[0], vap->iv_myaddr[1], vap->iv_myaddr[2], vap->iv_myaddr[3], vap->iv_myaddr[4], vap->iv_myaddr[5]); #endif for (i = 0; i < HTC_MAX_VAP_NUM; i++) { /* avoid upper layer add the same vap twice */ if (IEEE80211_ADDR_EQ(ic->target_vap_bitmap[i].vap_macaddr, vap->iv_myaddr)) { printk("%s: add the same vap twice\n", __FUNCTION__); return; } if (ic->target_vap_bitmap[i].vap_valid == 0) { printk("%s: target_vap_bitmap(%d) is invalid\n", __FUNCTION__, i); IEEE80211_ADDR_COPY(ic->target_vap_bitmap[i].vap_macaddr, vap->iv_myaddr); ic->target_vap_bitmap[i].vap_valid = 1; vapindex = i; break; } else { #if 0 printk("%s: target_vap_bitmap(%d) vap_valid = %d\n", __FUNCTION__, i, ic->target_vap_bitmap[i].vap_valid); #endif } } printk("%s: vap index: %d\n", __FUNCTION__, vapindex); /* If we can't find any suitable vap entry */ if (i == HTC_MAX_VAP_NUM) { printk("%s: exceed maximum vap number\n", __FUNCTION__); return; } vt.iv_create_flags = cpu_to_be32(vap->iv_create_flags); vt.iv_vapindex = vapindex; vt.iv_opmode = cpu_to_be32(vap->iv_opmode); vt.iv_mcast_rate = 0; vt.iv_rtsthreshold = cpu_to_be16(2304); adf_os_mem_copy(&vt.iv_myaddr, &(vap->iv_myaddr), IEEE80211_ADDR_LEN); #if ENCAP_OFFLOAD adf_os_mem_copy(&vt.iv_myaddr, &(vap->iv_myaddr), IEEE80211_ADDR_LEN); #endif /* save information to vap target */ ic->target_vap_bitmap[vapindex].iv_vapindex = vapindex; ic->target_vap_bitmap[vapindex].iv_opmode = vap->iv_opmode; ic->target_vap_bitmap[vapindex].iv_mcast_rate = vap->iv_mcast_rate; ic->target_vap_bitmap[vapindex].iv_rtsthreshold = 2304; ic->ic_add_vap_target(ic, &vt, sizeof(vt)); //printk("%s Exit \n", __FUNCTION__); }
static inline A_STATUS ol_tx_encap_from_8023 ( struct ol_txrx_vdev_t *vdev, struct ol_tx_desc_t *tx_desc, adf_nbuf_t msdu, struct ol_txrx_msdu_info_t *tx_msdu_info ) { u_int8_t localbuf[ sizeof(struct ieee80211_qosframe_htc_addr4) \ + sizeof(struct llc_snap_hdr_t)]; struct llc_snap_hdr_t *llc_hdr; struct ethernet_hdr_t *eth_hdr; struct ieee80211_frame *wh; u_int8_t hdsize, new_l2_hdsize, new_hdsize; struct ieee80211_qoscntl *qos_cntl; const u_int8_t ethernet_II_llc_snap_header_prefix[] = \ { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; struct ol_txrx_peer_t *peer; u_int16_t ether_type; if (tx_msdu_info->htt.info.frame_type != htt_frm_type_data) return A_OK; /* * for unicast,the peer should not be NULL. * for multicast, the peer is AP. */ peer = tx_msdu_info->peer; eth_hdr = (struct ethernet_hdr_t *)adf_nbuf_data(msdu); hdsize = sizeof(struct ethernet_hdr_t); wh = (struct ieee80211_frame *)localbuf; wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA; *(u_int16_t *)wh->i_dur = 0; new_hdsize = 0; switch (vdev->opmode) { case wlan_op_mode_ap: /* DA , BSSID , SA*/ adf_os_mem_copy(wh->i_addr1, eth_hdr->dest_addr, IEEE80211_ADDR_LEN); adf_os_mem_copy(wh->i_addr2, &vdev->mac_addr.raw, IEEE80211_ADDR_LEN); adf_os_mem_copy(wh->i_addr3, eth_hdr->src_addr, IEEE80211_ADDR_LEN); wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS; new_hdsize = sizeof(struct ieee80211_frame); break; case wlan_op_mode_ibss: /* DA, SA, BSSID */ adf_os_mem_copy(wh->i_addr1, eth_hdr->dest_addr, IEEE80211_ADDR_LEN); adf_os_mem_copy(wh->i_addr2, eth_hdr->src_addr, IEEE80211_ADDR_LEN); /* need to check the bssid behaviour for IBSS vdev */ adf_os_mem_copy(wh->i_addr3, &vdev->mac_addr.raw, IEEE80211_ADDR_LEN); wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; new_hdsize = sizeof(struct ieee80211_frame); break; case wlan_op_mode_sta: /* BSSID, SA , DA*/ adf_os_mem_copy(wh->i_addr1, &peer->mac_addr.raw, IEEE80211_ADDR_LEN); adf_os_mem_copy(wh->i_addr2, eth_hdr->src_addr, IEEE80211_ADDR_LEN); adf_os_mem_copy(wh->i_addr3, eth_hdr->dest_addr, IEEE80211_ADDR_LEN); wh->i_fc[1] = IEEE80211_FC1_DIR_TODS; new_hdsize = sizeof(struct ieee80211_frame); break; case wlan_op_mode_monitor: default: return A_ERROR; } /*add qos cntl*/ if (tx_msdu_info->htt.info.is_unicast && peer->qos_capable ) { qos_cntl = (struct ieee80211_qoscntl*)(localbuf + new_hdsize); qos_cntl->i_qos[0] = tx_msdu_info->htt.info.ext_tid & IEEE80211_QOS_TID; wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS; #if 0 if ( wmmParam[ac].wmep_noackPolicy ) { qos_cntl->i_qos[0]|= 1 << IEEE80211_QOS_ACKPOLICY_S; } #endif qos_cntl->i_qos[1] = 0; new_hdsize += sizeof(struct ieee80211_qoscntl); /*add ht control field if needed */ } /* Set Protected Frame bit in MAC header */ if (vdev->pdev->sw_pf_proc_enable && tx_msdu_info->htt.action.do_encrypt) { wh->i_fc[1] |= IEEE80211_FC1_WEP; } new_l2_hdsize = new_hdsize; /* add llc snap if needed */ if (vdev->pdev->sw_tx_llc_proc_enable) { llc_hdr = (struct llc_snap_hdr_t *) (localbuf + new_hdsize); ether_type = (eth_hdr->ethertype[0]<<8) |(eth_hdr->ethertype[1]); if ( ether_type >= IEEE8023_MAX_LEN ) { adf_os_mem_copy(llc_hdr, ethernet_II_llc_snap_header_prefix, sizeof(ethernet_II_llc_snap_header_prefix)); if ( ether_type == ETHERTYPE_AARP || ether_type == ETHERTYPE_IPX) { llc_hdr->org_code[2] = BTEP_SNAP_ORGCODE_2;// 0xf8; bridge tunnel header } llc_hdr->ethertype[0] = eth_hdr->ethertype[0]; llc_hdr->ethertype[1] = eth_hdr->ethertype[1]; new_hdsize += sizeof(struct llc_snap_hdr_t); } else { /*llc ready, and it's in payload pdu, do we need to move to BD pdu?*/ } } adf_os_mem_copy( (void*)htt_tx_desc_mpdu_header(tx_desc->htt_tx_desc,new_l2_hdsize), localbuf, new_hdsize); adf_nbuf_pull_head(msdu,hdsize); tx_msdu_info->htt.info.l3_hdr_offset = new_l2_hdsize; tx_desc->orig_l2_hdr_bytes = hdsize; return A_OK; }
static inline void ol_rx_decap_to_8023 ( struct ol_txrx_vdev_t *vdev, adf_nbuf_t msdu, struct ol_rx_decap_info_t *info, struct ethernet_hdr_t *ethr_hdr) { struct llc_snap_hdr_t *llc_hdr; u_int16_t ether_type; u_int16_t l2_hdr_space; struct ieee80211_frame_addr4 *wh; u_int8_t local_buf[ETHERNET_HDR_LEN]; u_int8_t *buf; /* * populate Ethernet header, * if ethr_hdr is null, rx frame is 802.11 format(HW ft disabled) * if ethr_hdr is not null, rx frame is "subfrm of amsdu". */ buf = (u_int8_t *)adf_nbuf_data(msdu); llc_hdr = (struct llc_snap_hdr_t *)buf; ether_type = (llc_hdr->ethertype[0] << 8)|llc_hdr->ethertype[1]; /* do llc remove if needed */ l2_hdr_space = 0; if (IS_SNAP(llc_hdr)) { if (IS_BTEP(llc_hdr)) { /* remove llc*/ l2_hdr_space += sizeof(struct llc_snap_hdr_t); llc_hdr = NULL; } else if (IS_RFC1042(llc_hdr)) { if ( !(ether_type == ETHERTYPE_AARP || ether_type == ETHERTYPE_IPX) ) { /* remove llc*/ l2_hdr_space += sizeof(struct llc_snap_hdr_t); llc_hdr = NULL; } } } if (l2_hdr_space > ETHERNET_HDR_LEN) { buf = adf_nbuf_pull_head(msdu, l2_hdr_space - ETHERNET_HDR_LEN); } else if (l2_hdr_space < ETHERNET_HDR_LEN) { buf = adf_nbuf_push_head(msdu, ETHERNET_HDR_LEN - l2_hdr_space); } /* normal msdu(non-subfrm of A-MSDU) if ethr_hdr is null */ if (ethr_hdr == NULL) { /* mpdu hdr should be present in info,re-create ethr_hdr based on mpdu hdr*/ TXRX_ASSERT2(info->hdr_len != 0); wh = (struct ieee80211_frame_addr4 *)info->hdr; ethr_hdr = (struct ethernet_hdr_t *)local_buf; switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { case IEEE80211_FC1_DIR_NODS: adf_os_mem_copy(ethr_hdr->dest_addr, wh->i_addr1, ETHERNET_ADDR_LEN); adf_os_mem_copy(ethr_hdr->src_addr, wh->i_addr2, ETHERNET_ADDR_LEN); break; case IEEE80211_FC1_DIR_TODS: adf_os_mem_copy(ethr_hdr->dest_addr, wh->i_addr3, ETHERNET_ADDR_LEN); adf_os_mem_copy(ethr_hdr->src_addr, wh->i_addr2, ETHERNET_ADDR_LEN); break; case IEEE80211_FC1_DIR_FROMDS: adf_os_mem_copy(ethr_hdr->dest_addr, wh->i_addr1, ETHERNET_ADDR_LEN); adf_os_mem_copy(ethr_hdr->src_addr, wh->i_addr3, ETHERNET_ADDR_LEN); break; case IEEE80211_FC1_DIR_DSTODS: adf_os_mem_copy(ethr_hdr->dest_addr, wh->i_addr3, ETHERNET_ADDR_LEN); adf_os_mem_copy(ethr_hdr->src_addr, wh->i_addr4, ETHERNET_ADDR_LEN); break; } } if (llc_hdr == NULL) { ethr_hdr->ethertype[0] = (ether_type >> 8) & 0xff; ethr_hdr->ethertype[1] = (ether_type) & 0xff; }
static void usb_hif_usb_recv_bundle_complete(struct urb *urb) { HIF_URB_CONTEXT *urb_context = (HIF_URB_CONTEXT *) urb->context; A_STATUS status = A_OK; adf_nbuf_t buf = NULL; HIF_USB_PIPE *pipe = urb_context->pipe; A_UINT8 *netdata, *netdata_new; A_UINT32 netlen, netlen_new; HTC_FRAME_HDR *HtcHdr; A_UINT16 payloadLen; adf_nbuf_t new_skb = NULL; AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ( "+%s: recv pipe: %d, stat:%d,len:%d urb:0x%p\n", __func__, pipe->logical_pipe_num, urb->status, urb->actual_length, urb)); /* this urb is not pending anymore */ usb_hif_remove_pending_transfer(urb_context); do { if (urb->status != 0) { status = A_ECOMM; switch (urb->status) { case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* NOTE: no need to spew these errors when * device is removed * or urb is killed due to driver shutdown */ status = A_ECANCELED; break; default: AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( "%s recv pipe: %d (ep:0x%2.2X), failed:%d\n", __func__, pipe->logical_pipe_num, pipe->ep_address, urb->status)); break; } break; } if (urb->actual_length == 0) break; buf = urb_context->buf; if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) { A_UINT8 *data; A_UINT32 len; adf_nbuf_peek_header(buf, &data, &len); DebugDumpBytes(data, len, "hif recv data"); } adf_nbuf_peek_header(buf, &netdata, &netlen); netlen = urb->actual_length; do { #if defined(AR6004_1_0_ALIGN_WAR) A_UINT8 extra_pad; A_UINT16 act_frame_len; #endif A_UINT16 frame_len; /* Hack into HTC header for bundle processing */ HtcHdr = (HTC_FRAME_HDR *) netdata; if (HtcHdr->EndpointID >= ENDPOINT_MAX) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("athusb: Rx: invalid EndpointID=%d\n", HtcHdr->EndpointID)); break; } payloadLen = HtcHdr->PayloadLen; payloadLen = A_LE2CPU16(payloadLen); #if defined(AR6004_1_0_ALIGN_WAR) act_frame_len = (HTC_HDR_LENGTH + payloadLen); if (HtcHdr->EndpointID == 0 || HtcHdr->EndpointID == 1) { /* assumption: target won't pad on HTC endpoint * 0 & 1. */ extra_pad = 0; } else { extra_pad = A_GET_UINT8_FIELD((A_UINT8 *) HtcHdr, HTC_FRAME_HDR, ControlBytes[1]); } #endif if (payloadLen > HIF_USB_RX_BUFFER_SIZE) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("athusb: payloadLen too long %u\n", payloadLen)); break; } #if defined(AR6004_1_0_ALIGN_WAR) frame_len = (act_frame_len + extra_pad); #else frame_len = (HTC_HDR_LENGTH + payloadLen); #endif if (netlen >= frame_len) { /* allocate a new skb and copy */ #if defined(AR6004_1_0_ALIGN_WAR) new_skb = adf_nbuf_alloc(NULL, act_frame_len, 0, 4, FALSE); if (new_skb == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( "athusb: allocate skb (len=%u) failed\n", act_frame_len)); break; } adf_nbuf_peek_header(new_skb, &netdata_new, &netlen_new); adf_os_mem_copy(netdata_new, netdata, act_frame_len); adf_nbuf_put_tail(new_skb, act_frame_len); #else new_skb = adf_nbuf_alloc(NULL, frame_len, 0, 4, FALSE); if (new_skb == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( "athusb: allocate skb (len=%u) failed\n", frame_len)); break; } adf_nbuf_peek_header(new_skb, &netdata_new, &netlen_new); adf_os_mem_copy(netdata_new, netdata, frame_len); adf_nbuf_put_tail(new_skb, frame_len); #endif skb_queue_tail(&pipe->io_comp_queue, new_skb); new_skb = NULL; netdata += frame_len; netlen -= frame_len; } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ( "athusb: subframe length %d not fitted into bundle packet length %d\n" , netlen, frame_len)); break; } } while (netlen); schedule_work(&pipe->io_complete_work); } while (FALSE); if (urb_context->buf == NULL) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("athusb: buffer in urb_context is NULL\n")); } /* reset urb_context->buf ==> seems not necessary */ usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context); if (A_SUCCESS(status)) { if (pipe->urb_cnt >= pipe->urb_cnt_thresh) { /* our free urbs are piling up, post more transfers */ usb_hif_post_recv_bundle_transfers(pipe, 0 /* pass zero for not allocating urb-buffer again */ ); } } AR_DEBUG_PRINTF(USB_HIF_DEBUG_BULK_IN, ("-%s\n", __func__)); }