diff options
Diffstat (limited to 'drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c')
-rw-r--r-- | drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c | 205 |
1 files changed, 130 insertions, 75 deletions
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c index d9a4567ca721..5d5cd4d01156 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c @@ -18,7 +18,6 @@ #include <rtw_debug.h> #include <rtl8723b_hal.h> - static s32 initrecvbuf(struct recv_buf *precvbuf, struct adapter *padapter) { INIT_LIST_HEAD(&precvbuf->list); @@ -29,9 +28,9 @@ static s32 initrecvbuf(struct recv_buf *precvbuf, struct adapter *padapter) return _SUCCESS; } -static void update_recvframe_attrib( - struct adapter *padapter, union recv_frame *precvframe, struct recv_stat *prxstat -) +static void update_recvframe_attrib(struct adapter *padapter, + union recv_frame *precvframe, + struct recv_stat *prxstat) { struct rx_pkt_attrib *pattrib; struct recv_stat report; @@ -48,7 +47,7 @@ static void update_recvframe_attrib( memset(pattrib, 0, sizeof(struct rx_pkt_attrib)); /* update rx report to recv_frame attribute */ - pattrib->pkt_rpt_type = prxreport->c2h_ind?C2H_PACKET:NORMAL_RX; + pattrib->pkt_rpt_type = prxreport->c2h_ind ? C2H_PACKET : NORMAL_RX; /* DBG_871X("%s: pkt_rpt_type =%d\n", __func__, pattrib->pkt_rpt_type); */ if (pattrib->pkt_rpt_type == NORMAL_RX) { @@ -75,8 +74,9 @@ static void update_recvframe_attrib( pattrib->mdata = (u8)prxreport->md; pattrib->data_rate = (u8)prxreport->rx_rate; - } else + } else { pattrib->pkt_len = (u16)prxreport->pktlen; + } } /* @@ -84,75 +84,92 @@ static void update_recvframe_attrib( *Before calling this function, *precvframe->u.hdr.rx_data should be ready! */ -static void update_recvframe_phyinfo( - union recv_frame *precvframe, struct phy_stat *pphy_status -) +static void update_recvframe_phyinfo(union recv_frame *precvframe, + struct phy_stat *pphy_status) { struct adapter *padapter = precvframe->u.hdr.adapter; struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib; - struct hal_com_data *pHalData = GET_HAL_DATA(padapter); - PODM_PHY_INFO_T pPHYInfo = (PODM_PHY_INFO_T)(&pattrib->phy_info); + struct hal_com_data *p_hal_data = GET_HAL_DATA(padapter); + struct odm_phy_info *p_phy_info = + (struct odm_phy_info *)(&pattrib->phy_info); u8 *wlanhdr; - ODM_PACKET_INFO_T pkt_info; + u8 *my_bssid; + u8 *rx_bssid; + u8 *rx_ra; + u8 *my_hwaddr; u8 *sa = NULL; + + struct odm_packet_info pkt_info = { + .data_rate = 0x00, + .station_id = 0x00, + .bssid_match = false, + .to_self = false, + .is_beacon = false, + }; + /* _irqL irqL; */ struct sta_priv *pstapriv; struct sta_info *psta; - pkt_info.bPacketMatchBSSID = false; - pkt_info.bPacketToSelf = false; - pkt_info.bPacketBeacon = false; - - wlanhdr = get_recvframe_data(precvframe); + my_bssid = get_bssid(&padapter->mlmepriv); + rx_bssid = get_hdr_bssid(wlanhdr); + pkt_info.bssid_match = ((!IsFrameTypeCtrl(wlanhdr)) && + !pattrib->icv_err && !pattrib->crc_err && + !ether_addr_equal(rx_bssid, my_bssid)); - pkt_info.bPacketMatchBSSID = ((!IsFrameTypeCtrl(wlanhdr)) && - !pattrib->icv_err && !pattrib->crc_err && - !memcmp(get_hdr_bssid(wlanhdr), get_bssid(&padapter->mlmepriv), ETH_ALEN)); + rx_ra = get_ra(wlanhdr); + my_hwaddr = myid(&padapter->eeprompriv); + pkt_info.to_self = pkt_info.bssid_match && + !ether_addr_equal(rx_ra, my_hwaddr); - pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID && (!memcmp(get_ra(wlanhdr), myid(&padapter->eeprompriv), ETH_ALEN)); - pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID && (GetFrameSubType(wlanhdr) == WIFI_BEACON); + pkt_info.is_beacon = pkt_info.bssid_match && + (GetFrameSubType(wlanhdr) == WIFI_BEACON); sa = get_ta(wlanhdr); - pkt_info.StationID = 0xFF; + pkt_info.station_id = 0xFF; pstapriv = &padapter->stapriv; psta = rtw_get_stainfo(pstapriv, sa); if (psta) { - pkt_info.StationID = psta->mac_id; - /* DBG_8192C("%s ==> StationID(%d)\n", __func__, pkt_info.StationID); */ + pkt_info.station_id = psta->mac_id; + /* DBG_8192C("%s ==> StationID(%d)\n", + * __func__, pkt_info.station_id); */ } - pkt_info.DataRate = pattrib->data_rate; + pkt_info.data_rate = pattrib->data_rate; /* rtl8723b_query_rx_phy_status(precvframe, pphy_status); */ - /* spin_lock_bh(&pHalData->odm_stainfo_lock); */ - ODM_PhyStatusQuery(&pHalData->odmpriv, pPHYInfo, (u8 *)pphy_status, &(pkt_info)); + /* spin_lock_bh(&p_hal_data->odm_stainfo_lock); */ + ODM_PhyStatusQuery(&p_hal_data->odmpriv, p_phy_info, + (u8 *)pphy_status, &(pkt_info)); if (psta) psta->rssi = pattrib->phy_info.RecvSignalPower; - /* spin_unlock_bh(&pHalData->odm_stainfo_lock); */ + /* spin_unlock_bh(&p_hal_data->odm_stainfo_lock); */ precvframe->u.hdr.psta = NULL; if ( - pkt_info.bPacketMatchBSSID && + pkt_info.bssid_match && (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true) ) { if (psta) { precvframe->u.hdr.psta = psta; rtl8723b_process_phy_info(padapter, precvframe); } - } else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) { - if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == true) + } else if (pkt_info.to_self || pkt_info.is_beacon) { + u32 adhoc_state = WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE; + if (check_fwstate(&padapter->mlmepriv, adhoc_state)) if (psta) precvframe->u.hdr.psta = psta; rtl8723b_process_phy_info(padapter, precvframe); } } -static void rtl8723bs_c2h_packet_handler(struct adapter *padapter, u8 *pbuf, u16 length) +static void rtl8723bs_c2h_packet_handler(struct adapter *padapter, + u8 *pbuf, u16 length) { - u8 *tmpBuf = NULL; + u8 *tmp = NULL; u8 res = false; if (length == 0) @@ -160,85 +177,127 @@ static void rtl8723bs_c2h_packet_handler(struct adapter *padapter, u8 *pbuf, u16 /* DBG_871X("+%s() length =%d\n", __func__, length); */ - tmpBuf = rtw_zmalloc(length); - if (tmpBuf == NULL) + tmp = rtw_zmalloc(length); + if (tmp == NULL) return; - memcpy(tmpBuf, pbuf, length); + memcpy(tmp, pbuf, length); - res = rtw_c2h_packet_wk_cmd(padapter, tmpBuf, length); + res = rtw_c2h_packet_wk_cmd(padapter, tmp, length); if (res == false) - kfree(tmpBuf); + kfree(tmp); /* DBG_871X("-%s res(%d)\n", __func__, res); */ return; } +static inline union recv_frame *try_alloc_recvframe(struct recv_priv *precvpriv, + struct recv_buf *precvbuf) +{ + union recv_frame *precvframe; + + precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue); + if (!precvframe) { + DBG_8192C("%s: no enough recv frame!\n", __func__); + rtw_enqueue_recvbuf_to_head(precvbuf, + &precvpriv->recv_buf_pending_queue); + + /* The case of can't allocte recvframe should be temporary, */ + /* schedule again and hope recvframe is available next time. */ + tasklet_schedule(&precvpriv->recv_tasklet); + } + + return precvframe; +} + +static inline bool rx_crc_err(struct recv_priv *precvpriv, + struct hal_com_data *p_hal_data, + struct rx_pkt_attrib *pattrib, + union recv_frame *precvframe) +{ + /* fix Hardware RX data error, drop whole recv_buffer */ + if ((!(p_hal_data->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) { + DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", + __func__, __LINE__); + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + return true; + } + + return false; +} + +static inline bool pkt_exceeds_tail(struct recv_priv *precvpriv, + u8 *end, u8 *tail, + union recv_frame *precvframe) +{ + if (end > tail) { + DBG_8192C("%s()-%d: : next pkt len(%p,%d) exceed ptail(%p)!\n", + __func__, __LINE__, ptr, pkt_offset, precvbuf->ptail); + rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + return true; + } + + return false; +} + static void rtl8723bs_recv_tasklet(void *priv) { struct adapter *padapter; - struct hal_com_data *pHalData; + struct hal_com_data *p_hal_data; struct recv_priv *precvpriv; struct recv_buf *precvbuf; union recv_frame *precvframe; struct rx_pkt_attrib *pattrib; + struct __queue *recv_buf_queue; u8 *ptr; u32 pkt_offset, skb_len, alloc_sz; _pkt *pkt_copy = NULL; u8 shift_sz = 0, rx_report_sz = 0; - padapter = priv; - pHalData = GET_HAL_DATA(padapter); + p_hal_data = GET_HAL_DATA(padapter); precvpriv = &padapter->recvpriv; + recv_buf_queue = &precvpriv->recv_buf_pending_queue; do { - precvbuf = rtw_dequeue_recvbuf(&precvpriv->recv_buf_pending_queue); - if (NULL == precvbuf) + precvbuf = rtw_dequeue_recvbuf(recv_buf_queue); + if (!precvbuf) break; ptr = precvbuf->pdata; while (ptr < precvbuf->ptail) { - precvframe = rtw_alloc_recvframe(&precvpriv->free_recv_queue); - if (precvframe == NULL) { - DBG_8192C("%s: no enough recv frame!\n", __func__); - rtw_enqueue_recvbuf_to_head(precvbuf, &precvpriv->recv_buf_pending_queue); - - /* The case of can't allocte recvframe should be temporary, */ - /* schedule again and hope recvframe is available next time. */ - tasklet_schedule(&precvpriv->recv_tasklet); + precvframe = try_alloc_recvframe(precvpriv, precvbuf); + if(!precvframe) return; - } /* rx desc parsing */ - update_recvframe_attrib(padapter, precvframe, (struct recv_stat *)ptr); + update_recvframe_attrib(padapter, precvframe, + (struct recv_stat *)ptr); pattrib = &precvframe->u.hdr.attrib; - /* fix Hardware RX data error, drop whole recv_buffer */ - if ((!(pHalData->ReceiveConfig & RCR_ACRC32)) && pattrib->crc_err) { - DBG_8192C("%s()-%d: RX Warning! rx CRC ERROR !!\n", __func__, __LINE__); - rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + if(rx_crc_err(precvpriv, p_hal_data, + pattrib, precvframe)) break; - } rx_report_sz = RXDESC_SIZE + pattrib->drvinfo_sz; - pkt_offset = rx_report_sz + pattrib->shift_sz + pattrib->pkt_len; + pkt_offset = rx_report_sz + + pattrib->shift_sz + + pattrib->pkt_len; - if ((ptr + pkt_offset) > precvbuf->ptail) { - DBG_8192C("%s()-%d: : next pkt len(%p,%d) exceed ptail(%p)!\n", __func__, __LINE__, ptr, pkt_offset, precvbuf->ptail); - rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + if(pkt_exceeds_tail(precvpriv, ptr + pkt_offset, + precvbuf->ptail, precvframe)) break; - } if ((pattrib->crc_err) || (pattrib->icv_err)) { - { - DBG_8192C("%s: crc_err =%d icv_err =%d, skip!\n", __func__, pattrib->crc_err, pattrib->icv_err); - } - rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); + DBG_8192C("%s: crc_err =%d icv_err =%d, skip!\n", + __func__, pattrib->crc_err, + pattrib->icv_err); + rtw_free_recvframe(precvframe, + &precvpriv->free_recv_queue); } else { /* Modified by Albert 20101213 */ /* For 8 bytes IP header alignment. */ @@ -289,7 +348,7 @@ static void rtl8723bs_recv_tasklet(void *priv) skb_reset_tail_pointer(pkt_clone); precvframe->u.hdr.rx_head = precvframe->u.hdr.rx_data = precvframe->u.hdr.rx_tail = pkt_clone->data; - precvframe->u.hdr.rx_end = pkt_clone->data + skb_len; + precvframe->u.hdr.rx_end = pkt_clone->data + skb_len; } else { DBG_8192C("%s: rtw_skb_clone fail\n", __func__); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); @@ -300,14 +359,14 @@ static void rtl8723bs_recv_tasklet(void *priv) recvframe_put(precvframe, skb_len); /* recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE); */ - if (pHalData->ReceiveConfig & RCR_APPFCS) + if (p_hal_data->ReceiveConfig & RCR_APPFCS) recvframe_pull_tail(precvframe, IEEE80211_FCS_LEN); /* move to drv info position */ ptr += RXDESC_SIZE; /* update drv info */ - if (pHalData->ReceiveConfig & RCR_APP_BA_SSN) { + if (p_hal_data->ReceiveConfig & RCR_APP_BA_SSN) { /* rtl8723s_update_bassn(padapter, pdrvinfo); */ ptr += 4; } @@ -337,7 +396,6 @@ static void rtl8723bs_recv_tasklet(void *priv) rtl8723bs_c2h_packet_handler(padapter, precvframe->u.hdr.rx_data, pattrib->pkt_len); rtw_free_recvframe(precvframe, &precvpriv->free_recv_queue); - } } @@ -350,7 +408,6 @@ static void rtl8723bs_recv_tasklet(void *priv) rtw_enqueue_recvbuf(precvbuf, &precvpriv->free_recv_buf_queue); } while (1); - } /* @@ -366,7 +423,6 @@ s32 rtl8723bs_init_recv_priv(struct adapter *padapter) struct recv_priv *precvpriv; struct recv_buf *precvbuf; - res = _SUCCESS; precvpriv = &padapter->recvpriv; @@ -463,7 +519,6 @@ void rtl8723bs_free_recv_priv(struct adapter *padapter) struct recv_priv *precvpriv; struct recv_buf *precvbuf; - precvpriv = &padapter->recvpriv; /* 3 1. kill tasklet */ |