/****************************************************************************** * * Name: HandleRxReadyEvent() * * Description: Rx ready event handler * * Arguments: PMRVDRV_ADAPTER Adapter * * Return Value: * * Notes: * *****************************************************************************/ VOID HandleRxReadyEvent( IN PMRVDRV_ADAPTER Adapter ) { int IsRxOK = 0; PRxPD pRxPDCurrent; PNDIS_PACKET pPacket; NDIS_STATUS pStatus; DBGPRINT(DBG_RX | DBG_HELP,(L"+HandleRxReadyEvent()\n")); pRxPDCurrent = (PRxPD)(Adapter->pRxPD1); //lykao, 060905, begin if (pRxPDCurrent->Status & MRVDRV_RXPD_STATUS_OK) { Adapter->RcvOK++; Adapter->DirectedFramesRcvOK++; wlan_compute_rssi(Adapter,pRxPDCurrent); } else { DBGPRINT(DBG_RX | DBG_WARNING,(L"WARNING: frame received with bad status\n")); //dralee++ 09212005 for error handling pPacket = Adapter->pRxCurPkt; Adapter->pRxCurPkt = NULL; if ( pPacket ) ReturnRxPacketDesc(Adapter,pPacket); return; } pPacket = Adapter->pRxCurPkt; Adapter->pRxCurPkt = NULL; if (Adapter->MediaConnectStatus == NdisMediaStateConnected) { Adapter->ulRxByteInLastPeriod += Adapter->ulRxSize; NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_SUCCESS); NdisMIndicateReceivePacket(Adapter->MrvDrvAdapterHdl, &pPacket, 1); pStatus = NDIS_GET_PACKET_STATUS(pPacket); if ((pStatus == NDIS_STATUS_RESOURCES) || (pStatus == NDIS_STATUS_SUCCESS)) { // return packet DBGPRINT(DBG_RX|DBG_HELP, (L"Packet returned success or resources...\n")); ReturnRxPacketDesc(Adapter,pPacket); } else { DBGPRINT(DBG_RX|DBG_ERROR, (L"Packet returned pending...\n")); } } else { ///pmkcache: bug#16956 ++ if (Adapter->bIsReconnectAssociation == TRUE) { Adapter->isPktPending = TRUE; if ( Adapter->pPendedRxPkt ) { NKDbgPrintfW( L"ERROR, a pended RX packet has not been process!!\r\n" ); } Adapter->pPendedRxPkt = pPacket; return; } ///pmkcache: bug#16956 -- DBGPRINT(DBG_RX|DBG_ERROR, (L"Not connected, packet was dropped...\n")); ReturnRxPacketDesc(Adapter,pPacket); } return; }
/** * @brief This function processes a received 802.11 packet and forwards it * to kernel/upper layer * * @param priv A pointer to wlan_private * @param skb A pointer to skb which includes the received packet * @return 0 or -1 */ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb) { wlan_adapter *adapter = priv->adapter; int ret = 0; struct rx80211packethdr *p_rx_pkt; struct rxpd *prxpd; struct rx_radiotap_hdr radiotap_hdr; struct rx_radiotap_hdr *pradiotap_hdr; lbs_deb_enter(LBS_DEB_RX); p_rx_pkt = (struct rx80211packethdr *) skb->data; prxpd = &p_rx_pkt->rx_pd; // lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100)); if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { lbs_deb_rx("rx err: frame received wit bad length\n"); priv->stats.rx_length_errors++; ret = 0; goto done; } /* * Check rxpd status and update 802.3 stat, */ if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) { //lbs_deb_rx("rx err: frame received with bad status\n"); priv->stats.rx_errors++; } lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); /* create the exported radio header */ if(priv->adapter->monitormode == WLAN_MONITOR_OFF) { /* no radio header */ /* chop the rxpd */ skb_pull(skb, sizeof(struct rxpd)); } else { /* radiotap header */ radiotap_hdr.hdr.it_version = 0; /* XXX must check this value for pad */ radiotap_hdr.hdr.it_pad = 0; radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr)); radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT); /* unknown values */ radiotap_hdr.flags = 0; radiotap_hdr.chan_freq = 0; radiotap_hdr.chan_flags = 0; radiotap_hdr.antenna = 0; /* known values */ radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate); /* XXX must check no carryout */ radiotap_hdr.antsignal = prxpd->snr + prxpd->nf; radiotap_hdr.rx_flags = 0; if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS; //memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18); /* chop the rxpd */ skb_pull(skb, sizeof(struct rxpd)); /* add space for the new radio header */ if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) && pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) { lbs_pr_alert("%s: couldn't pskb_expand_head\n", __func__); } pradiotap_hdr = (struct rx_radiotap_hdr *)skb_push(skb, sizeof(struct rx_radiotap_hdr)); memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr)); } /* Take the data rate from the rxpd structure * only if the rate is auto */ if (adapter->auto_rate) adapter->cur_rate = libertas_fw_index_to_data_rate(prxpd->rx_rate); wlan_compute_rssi(priv, prxpd); lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); priv->stats.rx_bytes += skb->len; priv->stats.rx_packets++; libertas_upload_rx_packet(priv, skb); ret = 0; done: lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret); return ret; }
/** * @brief This function processes received packet and forwards it * to kernel/upper layer * * @param priv A pointer to wlan_private * @param skb A pointer to skb which includes the received packet * @return WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE */ int ProcessRxedPacket(wlan_private * priv, struct sk_buff *skb) { #ifdef WPRM_DRV wlan_adapter *Adapter = priv->adapter; #endif int ret = WLAN_STATUS_SUCCESS; RxPacketHdr_t *pRxPkt; RxPD *pRxPD; int hdrChop; EthII_Hdr_t *pEthHdr; u32 u32SkbLen = skb->len; const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; ENTER(); pRxPkt = (RxPacketHdr_t *) skb->data; pRxPD = &pRxPkt->rx_pd; DBG_HEXDUMP(DAT_D, "Rx", skb->data, MIN(skb->len, MAX_DATA_DUMP_LEN)); if (skb->len < (ETH_HLEN + 8 + sizeof(RxPD))) { PRINTM(ERROR, "RX Error: FRAME RECEIVED WITH BAD LENGTH\n"); priv->stats.rx_length_errors++; ret = WLAN_STATUS_SUCCESS; kfree_skb(skb); goto done; } PRINTM(INFO, "RX Data: skb->len - sizeof(RxPd) = %d - %d = %d\n", skb->len, sizeof(RxPD), skb->len - sizeof(RxPD)); HEXDUMP("RX Data: Dest", pRxPkt->eth803_hdr.dest_addr, sizeof(pRxPkt->eth803_hdr.dest_addr)); HEXDUMP("RX Data: Src", pRxPkt->eth803_hdr.src_addr, sizeof(pRxPkt->eth803_hdr.src_addr)); if (memcmp(&pRxPkt->rfc1042_hdr, rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) { /* * Replace the 803 header and rfc1042 header (llc/snap) with an * EthernetII header, keep the src/dst and snap_type (ethertype) * * The firmware only passes up SNAP frames converting * all RX Data from 802.11 to 802.2/LLC/SNAP frames. * * To create the Ethernet II, just move the src, dst address right * before the snap_type. */ pEthHdr = (EthII_Hdr_t *) ((u8 *) & pRxPkt->eth803_hdr + sizeof(pRxPkt->eth803_hdr) + sizeof(pRxPkt->rfc1042_hdr) - sizeof(pRxPkt->eth803_hdr.dest_addr) - sizeof(pRxPkt->eth803_hdr.src_addr) - sizeof(pRxPkt->rfc1042_hdr.snap_type)); memcpy(pEthHdr->src_addr, pRxPkt->eth803_hdr.src_addr, sizeof(pEthHdr->src_addr)); memcpy(pEthHdr->dest_addr, pRxPkt->eth803_hdr.dest_addr, sizeof(pEthHdr->dest_addr)); /* Chop off the RxPD + the excess memory from the 802.2/llc/snap header * that was removed */ hdrChop = (u8 *) pEthHdr - (u8 *) pRxPkt; } else { HEXDUMP("RX Data: LLC/SNAP", (u8 *) & pRxPkt->rfc1042_hdr, sizeof(pRxPkt->rfc1042_hdr)); /* Chop off the RxPD */ hdrChop = (u8 *) & pRxPkt->eth803_hdr - (u8 *) pRxPkt; } /* Chop off the leading header bytes so the skb points to the start of * either the reconstructed EthII frame or the 802.2/llc/snap frame */ skb_pull(skb, hdrChop); u32SkbLen = skb->len; wlan_compute_rssi(priv, pRxPD); if (os_upload_rx_packet(priv, skb)) { PRINTM(ERROR, "RX Error: os_upload_rx_packet" " returns failure\n"); ret = WLAN_STATUS_FAILURE; goto done; } priv->stats.rx_bytes += u32SkbLen; priv->stats.rx_packets++; PRINTM(DATA, "Data => kernel\n"); #ifdef WPRM_DRV WPRM_DRV_TRACING_PRINT(); /* increase traffic meter rx counter and call measurement function to see if we need to change FW power mode. */ wprm_rx_packet_cnt++; wprm_traffic_measurement(priv, Adapter, FALSE); #endif ret = WLAN_STATUS_SUCCESS; done: LEAVE(); return (ret); }
/** * @brief This function processes received packet and forwards it * to kernel/upper layer * * @param priv A pointer to wlan_private * @param skb A pointer to skb which includes the received packet * @return 0 or -1 */ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb) { wlan_adapter *adapter = priv->adapter; int ret = 0; struct rxpackethdr *p_rx_pkt; struct rxpd *p_rx_pd; int hdrchop; struct ethhdr *p_ethhdr; const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; lbs_deb_enter(LBS_DEB_RX); if (priv->adapter->monitormode != WLAN_MONITOR_OFF) return process_rxed_802_11_packet(priv, skb); p_rx_pkt = (struct rxpackethdr *) skb->data; p_rx_pd = &p_rx_pkt->rx_pd; if (p_rx_pd->rx_control & RxPD_MESH_FRAME) SET_MESH_FRAME(skb); else UNSET_MESH_FRAME(skb); lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min_t(unsigned int, skb->len, 100)); if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { lbs_deb_rx("rx err: frame received with bad length\n"); priv->stats.rx_length_errors++; ret = 0; goto done; } /* * Check rxpd status and update 802.3 stat, */ if (!(p_rx_pd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) { lbs_deb_rx("rx err: frame received with bad status\n"); lbs_pr_alert("rxpd not ok\n"); priv->stats.rx_errors++; ret = 0; goto done; } lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr, sizeof(p_rx_pkt->eth803_hdr.dest_addr)); lbs_deb_hex(LBS_DEB_RX, "RX Data: Src", p_rx_pkt->eth803_hdr.src_addr, sizeof(p_rx_pkt->eth803_hdr.src_addr)); if (memcmp(&p_rx_pkt->rfc1042_hdr, rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) { /* * Replace the 803 header and rfc1042 header (llc/snap) with an * EthernetII header, keep the src/dst and snap_type (ethertype) * * The firmware only passes up SNAP frames converting * all RX Data from 802.11 to 802.2/LLC/SNAP frames. * * To create the Ethernet II, just move the src, dst address right * before the snap_type. */ p_ethhdr = (struct ethhdr *) ((u8 *) & p_rx_pkt->eth803_hdr + sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr) - sizeof(p_rx_pkt->eth803_hdr.dest_addr) - sizeof(p_rx_pkt->eth803_hdr.src_addr) - sizeof(p_rx_pkt->rfc1042_hdr.snap_type)); memcpy(p_ethhdr->h_source, p_rx_pkt->eth803_hdr.src_addr, sizeof(p_ethhdr->h_source)); memcpy(p_ethhdr->h_dest, p_rx_pkt->eth803_hdr.dest_addr, sizeof(p_ethhdr->h_dest)); /* Chop off the rxpd + the excess memory from the 802.2/llc/snap header * that was removed */ hdrchop = (u8 *) p_ethhdr - (u8 *) p_rx_pkt; } else { lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP", (u8 *) & p_rx_pkt->rfc1042_hdr, sizeof(p_rx_pkt->rfc1042_hdr)); /* Chop off the rxpd */ hdrchop = (u8 *) & p_rx_pkt->eth803_hdr - (u8 *) p_rx_pkt; } /* Chop off the leading header bytes so the skb points to the start of * either the reconstructed EthII frame or the 802.2/llc/snap frame */ skb_pull(skb, hdrchop); /* Take the data rate from the rxpd structure * only if the rate is auto */ if (adapter->auto_rate) adapter->cur_rate = libertas_fw_index_to_data_rate(p_rx_pd->rx_rate); wlan_compute_rssi(priv, p_rx_pd); lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); priv->stats.rx_bytes += skb->len; priv->stats.rx_packets++; libertas_upload_rx_packet(priv, skb); ret = 0; done: lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret); return ret; }