void mt76_remove_hdr_pad(struct sk_buff *skb) { int len = ieee80211_get_hdrlen_from_skb(skb); memmove(skb->data + 2, skb->data, len); skb_pull(skb, 2); }
static void mt76x02u_remove_dma_hdr(struct sk_buff *skb) { int hdr_len; skb_pull(skb, sizeof(struct mt76x02_txwi) + MT_DMA_HDR_LEN); hdr_len = ieee80211_get_hdrlen_from_skb(skb); if (hdr_len % 4) mt76x02_remove_hdr_pad(skb, 2); }
static int mt7601u_skb_rooms(struct mt7601u_dev *dev, struct sk_buff *skb) { int hdr_len = ieee80211_get_hdrlen_from_skb(skb); u32 need_head; need_head = sizeof(struct mt76_txwi) + 4; if (hdr_len % 4) need_head += 2; return skb_cow(skb, need_head); }
void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len) { int hdrlen; if (!len) return; hdrlen = ieee80211_get_hdrlen_from_skb(skb); memmove(skb->data + len, skb->data, hdrlen); skb_pull(skb, len); }
void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb); if (unlikely(!iv_len)) return; /* Copy IV/EIV data */ memcpy(skbdesc->iv, skb->data + header_length, iv_len); }
static void mt7601u_tx_skb_remove_dma_overhead(struct sk_buff *skb, struct ieee80211_tx_info *info) { int pkt_len = (unsigned long)info->status.status_driver_data[0]; skb_pull(skb, sizeof(struct mt76_txwi) + 4); if (ieee80211_get_hdrlen_from_skb(skb) % 4) mt76_remove_hdr_pad(skb); skb_trim(skb, pkt_len); }
int mt76x02_insert_hdr_pad(struct sk_buff *skb) { int len = ieee80211_get_hdrlen_from_skb(skb); if (len % 4 == 0) return 0; skb_push(skb, 2); memmove(skb->data, skb->data + 2, len); skb->data[len] = 0; skb->data[len + 1] = 0; return 2; }
void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, struct sk_buff *skb, struct ath_rx_status *rx_stats, struct ieee80211_rx_status *rxs, bool decrypt_error) { struct ath_hw *ah = common->ah; struct ieee80211_hdr *hdr; int hdrlen, padpos, padsize; u8 keyix; __le16 fc; /* see if any padding is done by the hw and remove it */ hdr = (struct ieee80211_hdr *) skb->data; hdrlen = ieee80211_get_hdrlen_from_skb(skb); fc = hdr->frame_control; padpos = ieee80211_hdrlen(fc); /* The MAC header is padded to have 32-bit boundary if the * packet payload is non-zero. The general calculation for * padsize would take into account odd header lengths: * padsize = (4 - padpos % 4) % 4; However, since only * even-length headers are used, padding can only be 0 or 2 * bytes and we can optimize this a bit. In addition, we must * not try to remove padding from short control frames that do * not have payload. */ padsize = padpos & 3; if (padsize && skb->len>=padpos+padsize+FCS_LEN) { memmove(skb->data + padsize, skb->data, padpos); skb_pull(skb, padsize); } keyix = rx_stats->rs_keyix; if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && ieee80211_has_protected(fc)) { rxs->flag |= RX_FLAG_DECRYPTED; } else if (ieee80211_has_protected(fc) && !decrypt_error && skb->len >= hdrlen + 4) { keyix = skb->data[hdrlen + 3] >> 6; if (test_bit(keyix, common->keymap)) rxs->flag |= RX_FLAG_DECRYPTED; }
int mt76_insert_hdr_pad(struct sk_buff *skb) { int len = ieee80211_get_hdrlen_from_skb(skb); int ret; if (len % 4 == 0) return 0; if (skb_headroom(skb) < 2 && (ret = pskb_expand_head(skb, 2, 0, GFP_ATOMIC)) != 0) return ret; skb_push(skb, 2); memmove(skb->data, skb->data + 2, len); skb->data[len] = 0; skb->data[len + 1] = 0; return 2; }
void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb); if (unlikely(!iv_len)) return; /* Copy IV/EIV data */ memcpy(skbdesc->iv, skb->data + header_length, iv_len); /* Move ieee80211 header */ memmove(skb->data + iv_len, skb->data, header_length); /* Pull buffer to correct size */ skb_pull(skb, iv_len); /* IV/EIV data has officially be stripped */ skbdesc->flags |= FRAME_DESC_IV_STRIPPED; }
void rt2x00crypto_tx_insert_iv(struct sk_buff *skb) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb); const unsigned int iv_len = ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4); if (!(skbdesc->flags & FRAME_DESC_IV_STRIPPED)) return; skb_push(skb, iv_len); /* Move ieee80211 header */ memmove(skb->data, skb->data + iv_len, header_length); /* Copy IV/EIV data */ memcpy(skb->data + header_length, skbdesc->iv, iv_len); /* IV/EIV data has returned into the frame */ skbdesc->flags &= ~FRAME_DESC_IV_STRIPPED; }
void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, struct txentry_desc *txdesc) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); txdesc->cipher = rt2x00crypto_key_to_cipher(hw_key); if (hw_key->flags & IEEE80211_KEY_FLAG_PAIRWISE) __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags); txdesc->key_idx = hw_key->hw_key_idx; txdesc->iv_offset = ieee80211_get_hdrlen_from_skb(entry->skb); if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags); if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) __set_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags); }
/*should call before software enc*/ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); __le16 fc = rtl_get_fc(skb); u16 ether_type; u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); const struct iphdr *ip; if (!ieee80211_is_data(fc)) return false; ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len + SNAP_SIZE + PROTOC_TYPE_SIZE); ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE); /* ether_type = ntohs(ether_type); */ if (ETH_P_IP == ether_type) { if (IPPROTO_UDP == ip->protocol) { struct udphdr *udp = (struct udphdr *)((u8 *) ip + (ip->ihl << 2)); if (((((u8 *) udp)[1] == 68) && (((u8 *) udp)[3] == 67)) || ((((u8 *) udp)[1] == 67) && (((u8 *) udp)[3] == 68))) { /* * 68 : UDP BOOTP client * 67 : UDP BOOTP server */ RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, "dhcp %s !!\n", is_tx ? "Tx" : "Rx"); if (is_tx) { schedule_work(&rtlpriv-> works.lps_leave_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } return true; } } } else if (ETH_P_ARP == ether_type) { if (is_tx) { schedule_work(&rtlpriv->works.lps_leave_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } return true; } else if (ETH_P_PAE == ether_type) { RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); if (is_tx) { schedule_work(&rtlpriv->works.lps_leave_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } return true; } else if (ETH_P_IPV6 == ether_type) { /* IPv6 */ return true; } return false; }
void rt2x00lib_rxdone(struct queue_entry *entry) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct rxdone_entry_desc rxdesc; struct sk_buff *skb; struct ieee80211_rx_status *rx_status; unsigned int header_length; int rate_idx; if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) goto submit_entry; if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) goto submit_entry; /* * Allocate a new sk_buffer. If no new buffer available, drop the * received frame and reuse the existing buffer. */ skb = rt2x00queue_alloc_rxskb(entry); if (!skb) goto submit_entry; /* * Unmap the skb. */ rt2x00queue_unmap_skb(entry); /* * Extract the RXD details. */ memset(&rxdesc, 0, sizeof(rxdesc)); rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); /* * Check for valid size in case we get corrupted descriptor from * hardware. */ if (unlikely(rxdesc.size == 0 || rxdesc.size > entry->queue->data_size)) { WARNING(rt2x00dev, "Wrong frame size %d max %d.\n", rxdesc.size, entry->queue->data_size); dev_kfree_skb(entry->skb); goto renew_skb; } /* * The data behind the ieee80211 header must be * aligned on a 4 byte boundary. */ header_length = ieee80211_get_hdrlen_from_skb(entry->skb); /* * Hardware might have stripped the IV/EIV/ICV data, * in that case it is possible that the data was * provided separately (through hardware descriptor) * in which case we should reinsert the data into the frame. */ if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) && (rxdesc.flags & RX_FLAG_IV_STRIPPED)) rt2x00crypto_rx_insert_iv(entry->skb, header_length, &rxdesc); else if (header_length && (rxdesc.size > header_length) && (rxdesc.dev_flags & RXDONE_L2PAD)) rt2x00queue_remove_l2pad(entry->skb, header_length); /* Trim buffer to correct size */ skb_trim(entry->skb, rxdesc.size); /* * Translate the signal to the correct bitrate index. */ rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc); if (rxdesc.rate_mode == RATE_MODE_HT_MIX || rxdesc.rate_mode == RATE_MODE_HT_GREENFIELD) rxdesc.flags |= RX_FLAG_HT; /* * Check if this is a beacon, and more frames have been * buffered while we were in powersaving mode. */ rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc); /* * Update extra components */ rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); rt2x00debug_update_crypto(rt2x00dev, &rxdesc); rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); /* * Initialize RX status information, and send frame * to mac80211. */ rx_status = IEEE80211_SKB_RXCB(entry->skb); rx_status->mactime = rxdesc.timestamp; rx_status->band = rt2x00dev->curr_band; rx_status->freq = rt2x00dev->curr_freq; rx_status->rate_idx = rate_idx; rx_status->signal = rxdesc.rssi; rx_status->flag = rxdesc.flags; rx_status->antenna = rt2x00dev->link.ant.active.rx; ieee80211_rx_ni(rt2x00dev->hw, entry->skb); renew_skb: /* * Replace the skb with the freshly allocated one. */ entry->skb = skb; submit_entry: entry->flags = 0; rt2x00queue_index_inc(entry, Q_INDEX_DONE); if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) rt2x00dev->ops->lib->clear_entry(entry); }
void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); unsigned int header_length, i; u8 rate_idx, rate_flags, retry_rates; u8 skbdesc_flags = skbdesc->flags; bool success; /* * Unmap the skb. */ rt2x00queue_unmap_skb(entry); /* * Remove the extra tx headroom from the skb. */ skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom); /* * Signal that the TX descriptor is no longer in the skb. */ skbdesc->flags &= ~SKBDESC_DESC_IN_SKB; /* * Determine the length of 802.11 header. */ header_length = ieee80211_get_hdrlen_from_skb(entry->skb); /* * Remove L2 padding which was added during */ if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags)) rt2x00queue_remove_l2pad(entry->skb, header_length); /* * If the IV/EIV data was stripped from the frame before it was * passed to the hardware, we should now reinsert it again because * mac80211 will expect the same data to be present it the * frame as it was passed to us. */ if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) rt2x00crypto_tx_insert_iv(entry->skb, header_length); /* * Send frame to debugfs immediately, after this call is completed * we are going to overwrite the skb->cb array. */ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb); /* * Determine if the frame has been successfully transmitted. */ success = test_bit(TXDONE_SUCCESS, &txdesc->flags) || test_bit(TXDONE_UNKNOWN, &txdesc->flags); /* * Update TX statistics. */ rt2x00dev->link.qual.tx_success += success; rt2x00dev->link.qual.tx_failed += !success; rate_idx = skbdesc->tx_rate_idx; rate_flags = skbdesc->tx_rate_flags; retry_rates = test_bit(TXDONE_FALLBACK, &txdesc->flags) ? (txdesc->retry + 1) : 1; /* * Initialize TX status */ memset(&tx_info->status, 0, sizeof(tx_info->status)); tx_info->status.ack_signal = 0; /* * Frame was send with retries, hardware tried * different rates to send out the frame, at each * retry it lowered the rate 1 step except when the * lowest rate was used. */ for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) { tx_info->status.rates[i].idx = rate_idx - i; tx_info->status.rates[i].flags = rate_flags; if (rate_idx - i == 0) { /* * The lowest rate (index 0) was used until the * number of max retries was reached. */ tx_info->status.rates[i].count = retry_rates - i; i++; break; } tx_info->status.rates[i].count = 1; } if (i < (IEEE80211_TX_MAX_RATES - 1)) tx_info->status.rates[i].idx = -1; /* terminate */ if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { if (success) tx_info->flags |= IEEE80211_TX_STAT_ACK; else rt2x00dev->low_level_stats.dot11ACKFailureCount++; } /* * Every single frame has it's own tx status, hence report * every frame as ampdu of size 1. * * TODO: if we can find out how many frames were aggregated * by the hw we could provide the real ampdu_len to mac80211 * which would allow the rc algorithm to better decide on * which rates are suitable. */ if (test_bit(TXDONE_AMPDU, &txdesc->flags) || tx_info->flags & IEEE80211_TX_CTL_AMPDU) { tx_info->flags |= IEEE80211_TX_STAT_AMPDU; tx_info->status.ampdu_len = 1; tx_info->status.ampdu_ack_len = success ? 1 : 0; if (!success) tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; } if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { if (success) rt2x00dev->low_level_stats.dot11RTSSuccessCount++; else rt2x00dev->low_level_stats.dot11RTSFailureCount++; } /* * Only send the status report to mac80211 when it's a frame * that originated in mac80211. If this was a extra frame coming * through a mac80211 library call (RTS/CTS) then we should not * send the status report back. */ if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) { if (test_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags)) ieee80211_tx_status(rt2x00dev->hw, entry->skb); else ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb); } else dev_kfree_skb_any(entry->skb); /* * Make this entry available for reuse. */ entry->skb = NULL; entry->flags = 0; rt2x00dev->ops->lib->clear_entry(entry); rt2x00queue_index_inc(entry, Q_INDEX_DONE); /* * If the data queue was below the threshold before the txdone * handler we must make sure the packet queue in the mac80211 stack * is reenabled when the txdone handler has finished. This has to be * serialized with rt2x00mac_tx(), otherwise we can wake up queue * before it was stopped. */ spin_lock_bh(&entry->queue->tx_lock); if (!rt2x00queue_threshold(entry->queue)) rt2x00queue_unpause_queue(entry->queue); spin_unlock_bh(&entry->queue->tx_lock); }
void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry) { struct rxdone_entry_desc rxdesc; struct sk_buff *skb; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; unsigned int header_length; int rate_idx; /* * Allocate a new sk_buffer. If no new buffer available, drop the * received frame and reuse the existing buffer. */ skb = rt2x00queue_alloc_rxskb(rt2x00dev, entry); if (!skb) return; /* * Unmap the skb. */ rt2x00queue_unmap_skb(rt2x00dev, entry->skb); /* * Extract the RXD details. */ memset(&rxdesc, 0, sizeof(rxdesc)); rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); /* Trim buffer to correct size */ skb_trim(entry->skb, rxdesc.size); /* * The data behind the ieee80211 header must be * aligned on a 4 byte boundary. */ header_length = ieee80211_get_hdrlen_from_skb(entry->skb); /* * Hardware might have stripped the IV/EIV/ICV data, * in that case it is possible that the data was * provided seperately (through hardware descriptor) * in which case we should reinsert the data into the frame. */ if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) && (rxdesc.flags & RX_FLAG_IV_STRIPPED)) rt2x00crypto_rx_insert_iv(entry->skb, header_length, &rxdesc); else if (rxdesc.dev_flags & RXDONE_L2PAD) rt2x00queue_remove_l2pad(entry->skb, header_length); else rt2x00queue_align_payload(entry->skb, header_length); /* * Check if the frame was received using HT. In that case, * the rate is the MCS index and should be passed to mac80211 * directly. Otherwise we need to translate the signal to * the correct bitrate index. */ if (rxdesc.rate_mode == RATE_MODE_CCK || rxdesc.rate_mode == RATE_MODE_OFDM) { rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc); } else { rxdesc.flags |= RX_FLAG_HT; rate_idx = rxdesc.signal; } /* * Update extra components */ rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); rt2x00debug_update_crypto(rt2x00dev, &rxdesc); rx_status->mactime = rxdesc.timestamp; rx_status->rate_idx = rate_idx; rx_status->signal = rxdesc.rssi; rx_status->noise = rxdesc.noise; rx_status->flag = rxdesc.flags; rx_status->antenna = rt2x00dev->link.ant.active.rx; /* * Send frame to mac80211 & debugfs. * mac80211 will clean up the skb structure. */ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status)); ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb); /* * Replace the skb with the freshly allocated one. */ entry->skb = skb; entry->flags = 0; rt2x00dev->ops->lib->clear_entry(entry); rt2x00queue_index_inc(entry->queue, Q_INDEX); }
void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); u8 rate_idx, rate_flags, retry_rates; u8 skbdesc_flags = skbdesc->flags; unsigned int i; bool success; /* * Unmap the skb. */ rt2x00queue_unmap_skb(rt2x00dev, entry->skb); /* * Remove L2 padding which was added during */ if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) rt2x00queue_remove_l2pad(entry->skb, header_length); /* * If the IV/EIV data was stripped from the frame before it was * passed to the hardware, we should now reinsert it again because * mac80211 will expect the the same data to be present it the * frame as it was passed to us. */ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) rt2x00crypto_tx_insert_iv(entry->skb, header_length); /* * Send frame to debugfs immediately, after this call is completed * we are going to overwrite the skb->cb array. */ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb); /* * Determine if the frame has been successfully transmitted. */ success = test_bit(TXDONE_SUCCESS, &txdesc->flags) || test_bit(TXDONE_UNKNOWN, &txdesc->flags) || test_bit(TXDONE_FALLBACK, &txdesc->flags); /* * Update TX statistics. */ rt2x00dev->link.qual.tx_success += success; rt2x00dev->link.qual.tx_failed += !success; rate_idx = skbdesc->tx_rate_idx; rate_flags = skbdesc->tx_rate_flags; retry_rates = test_bit(TXDONE_FALLBACK, &txdesc->flags) ? (txdesc->retry + 1) : 1; /* * Initialize TX status */ memset(&tx_info->status, 0, sizeof(tx_info->status)); tx_info->status.ack_signal = 0; /* * Frame was send with retries, hardware tried * different rates to send out the frame, at each * retry it lowered the rate 1 step. */ for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) { tx_info->status.rates[i].idx = rate_idx - i; tx_info->status.rates[i].flags = rate_flags; tx_info->status.rates[i].count = 1; } if (i < (IEEE80211_TX_MAX_RATES - 1)) tx_info->status.rates[i].idx = -1; /* terminate */ if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { if (success) tx_info->flags |= IEEE80211_TX_STAT_ACK; else rt2x00dev->low_level_stats.dot11ACKFailureCount++; } if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { if (success) rt2x00dev->low_level_stats.dot11RTSSuccessCount++; else rt2x00dev->low_level_stats.dot11RTSFailureCount++; } /* * Only send the status report to mac80211 when it's a frame * that originated in mac80211. If this was a extra frame coming * through a mac80211 library call (RTS/CTS) then we should not * send the status report back. */ if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); else dev_kfree_skb_irq(entry->skb); /* * Make this entry available for reuse. */ entry->skb = NULL; entry->flags = 0; rt2x00dev->ops->lib->clear_entry(entry); clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); /* * If the data queue was below the threshold before the txdone * handler we must make sure the packet queue in the mac80211 stack * is reenabled when the txdone handler has finished. */ if (!rt2x00queue_threshold(entry->queue)) ieee80211_wake_queue(rt2x00dev->hw, qid); }
int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx, struct vnt_tx_desc *head_td, struct sk_buff *skb) { struct vnt_td_info *td_info = head_td->td_info; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_rate *tx_rate = &info->control.rates[0]; struct ieee80211_rate *rate; struct ieee80211_key_conf *tx_key; struct ieee80211_hdr *hdr; struct vnt_tx_fifo_head *tx_buffer_head = (struct vnt_tx_fifo_head *)td_info->buf; u16 tx_body_size = skb->len, current_rate; u8 pkt_type; bool is_pspoll = false; memset(tx_buffer_head, 0, sizeof(*tx_buffer_head)); hdr = (struct ieee80211_hdr *)(skb->data); rate = ieee80211_get_tx_rate(priv->hw, info); current_rate = rate->hw_value; if (priv->wCurrentRate != current_rate && !(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { priv->wCurrentRate = current_rate; RFbSetPower(priv, priv->wCurrentRate, priv->hw->conf.chandef.chan->hw_value); } if (current_rate > RATE_11M) { if (info->band == NL80211_BAND_5GHZ) { pkt_type = PK_TYPE_11A; } else { if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) pkt_type = PK_TYPE_11GB; else pkt_type = PK_TYPE_11GA; } } else { pkt_type = PK_TYPE_11B; } /*Set fifo controls */ if (pkt_type == PK_TYPE_11A) tx_buffer_head->fifo_ctl = 0; else if (pkt_type == PK_TYPE_11B) tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11B); else if (pkt_type == PK_TYPE_11GB) tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GB); else if (pkt_type == PK_TYPE_11GA) tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GA); /* generate interrupt */ tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT); if (!ieee80211_is_data(hdr->frame_control)) { tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_TMOEN); tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_ISDMA0); tx_buffer_head->time_stamp = cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us); } else { tx_buffer_head->time_stamp = cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us); } if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_NEEDACK); if (ieee80211_has_retry(hdr->frame_control)) tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LRETRY); if (tx_rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) priv->byPreambleType = PREAMBLE_SHORT; else priv->byPreambleType = PREAMBLE_LONG; if (tx_rate->flags & IEEE80211_TX_RC_USE_RTS_CTS) tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_RTS); if (ieee80211_has_a4(hdr->frame_control)) { tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LHEAD); priv->bLongHeader = true; } if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER) is_pspoll = true; tx_buffer_head->frag_ctl = cpu_to_le16(ieee80211_get_hdrlen_from_skb(skb) << 10); if (info->control.hw_key) { tx_key = info->control.hw_key; switch (info->control.hw_key->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_LEGACY); break; case WLAN_CIPHER_SUITE_TKIP: tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_TKIP); break; case WLAN_CIPHER_SUITE_CCMP: tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_AES); default: break; } } tx_buffer_head->current_rate = cpu_to_le16(current_rate); /* legacy rates TODO use ieee80211_tx_rate */ if (current_rate >= RATE_18M && ieee80211_is_data(hdr->frame_control)) { if (priv->byAutoFBCtrl == AUTO_FB_0) tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_AUTO_FB_0); else if (priv->byAutoFBCtrl == AUTO_FB_1) tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_AUTO_FB_1); } tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG); s_cbFillTxBufHead(priv, pkt_type, (u8 *)tx_buffer_head, dma_idx, head_td, is_pspoll); if (info->control.hw_key) { tx_key = info->control.hw_key; if (tx_key->keylen > 0) vnt_fill_txkey(hdr, tx_buffer_head->tx_key, tx_key, skb, tx_body_size, td_info->mic_hdr); } return 0; }
static void vnt_fill_txkey(struct ieee80211_hdr *hdr, u8 *key_buffer, struct ieee80211_key_conf *tx_key, struct sk_buff *skb, u16 payload_len, struct vnt_mic_hdr *mic_hdr) { u64 pn64; u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb)); /* strip header and icv len from payload */ payload_len -= ieee80211_get_hdrlen_from_skb(skb); payload_len -= tx_key->icv_len; switch (tx_key->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: memcpy(key_buffer, iv, 3); memcpy(key_buffer + 3, tx_key->key, tx_key->keylen); if (tx_key->keylen == WLAN_KEY_LEN_WEP40) { memcpy(key_buffer + 8, iv, 3); memcpy(key_buffer + 11, tx_key->key, WLAN_KEY_LEN_WEP40); } break; case WLAN_CIPHER_SUITE_TKIP: ieee80211_get_tkip_p2k(tx_key, skb, key_buffer); break; case WLAN_CIPHER_SUITE_CCMP: if (!mic_hdr) return; mic_hdr->id = 0x59; mic_hdr->payload_len = cpu_to_be16(payload_len); ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2); pn64 = atomic64_read(&tx_key->tx_pn); mic_hdr->ccmp_pn[5] = pn64; mic_hdr->ccmp_pn[4] = pn64 >> 8; mic_hdr->ccmp_pn[3] = pn64 >> 16; mic_hdr->ccmp_pn[2] = pn64 >> 24; mic_hdr->ccmp_pn[1] = pn64 >> 32; mic_hdr->ccmp_pn[0] = pn64 >> 40; if (ieee80211_has_a4(hdr->frame_control)) mic_hdr->hlen = cpu_to_be16(28); else mic_hdr->hlen = cpu_to_be16(22); ether_addr_copy(mic_hdr->addr1, hdr->addr1); ether_addr_copy(mic_hdr->addr2, hdr->addr2); ether_addr_copy(mic_hdr->addr3, hdr->addr3); mic_hdr->frame_control = cpu_to_le16( le16_to_cpu(hdr->frame_control) & 0xc78f); mic_hdr->seq_ctrl = cpu_to_le16( le16_to_cpu(hdr->seq_ctrl) & 0xf); if (ieee80211_has_a4(hdr->frame_control)) ether_addr_copy(mic_hdr->addr4, hdr->addr4); memcpy(key_buffer, tx_key->key, WLAN_KEY_LEN_CCMP); break; default: break; } }
static unsigned int s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType, unsigned char *pbyTxBufferAddr, unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD, unsigned int is_pspoll) { struct vnt_td_info *td_info = pHeadTD->td_info; struct sk_buff *skb = td_info->skb; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct vnt_tx_fifo_head *tx_buffer_head = (struct vnt_tx_fifo_head *)td_info->buf; u16 fifo_ctl = le16_to_cpu(tx_buffer_head->fifo_ctl); unsigned int cbFrameSize; __le16 uDuration; unsigned char *pbyBuffer; unsigned int uLength = 0; unsigned int cbMICHDR = 0; unsigned int uMACfragNum = 1; unsigned int uPadding = 0; unsigned int cbReqCount = 0; bool bNeedACK = (bool)(fifo_ctl & FIFOCTL_NEEDACK); bool bRTS = (bool)(fifo_ctl & FIFOCTL_RTS); struct vnt_tx_desc *ptdCurr; unsigned int cbHeaderLength = 0; void *pvRrvTime; struct vnt_mic_hdr *pMICHDR; void *pvRTS; void *pvCTS; void *pvTxDataHd; unsigned short wTxBufSize; /* FFinfo size */ unsigned char byFBOption = AUTO_FB_NONE; pvRrvTime = pMICHDR = pvRTS = pvCTS = pvTxDataHd = NULL; cbFrameSize = skb->len + 4; if (info->control.hw_key) { switch (info->control.hw_key->cipher) { case WLAN_CIPHER_SUITE_CCMP: cbMICHDR = sizeof(struct vnt_mic_hdr); default: break; } cbFrameSize += info->control.hw_key->icv_len; if (pDevice->byLocalID > REV_ID_VT3253_A1) { /* MAC Header should be padding 0 to DW alignment. */ uPadding = 4 - (ieee80211_get_hdrlen_from_skb(skb) % 4); uPadding %= 4; } } /* * Use for AUTO FALL BACK */ if (fifo_ctl & FIFOCTL_AUTO_FB_0) byFBOption = AUTO_FB_0; else if (fifo_ctl & FIFOCTL_AUTO_FB_1) byFBOption = AUTO_FB_1; /* Set RrvTime/RTS/CTS Buffer */ wTxBufSize = sizeof(struct vnt_tx_fifo_head); if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {/* 802.11g packet */ if (byFBOption == AUTO_FB_NONE) { if (bRTS) {/* RTS_need */ pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts)); pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR); pvCTS = NULL; pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR + sizeof(struct vnt_rts_g)); cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR + sizeof(struct vnt_rts_g) + sizeof(struct vnt_tx_datahead_g); } else { /* RTS_needless */ pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts)); pvRTS = NULL; pvCTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR); pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR + sizeof(struct vnt_cts)); cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR + sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g); } } else { /* Auto Fall Back */ if (bRTS) {/* RTS_need */ pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts)); pvRTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR); pvCTS = NULL; pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR + sizeof(struct vnt_rts_g_fb)); cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR + sizeof(struct vnt_rts_g_fb) + sizeof(struct vnt_tx_datahead_g_fb); } else { /* RTS_needless */ pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts)); pvRTS = NULL; pvCTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR); pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR + sizeof(struct vnt_cts_fb)); cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR + sizeof(struct vnt_cts_fb) + sizeof(struct vnt_tx_datahead_g_fb); } } /* Auto Fall Back */ } else {/* 802.11a/b packet */ if (byFBOption == AUTO_FB_NONE) { if (bRTS) { pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab)); pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR); pvCTS = NULL; pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_ab)); cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_ab) + sizeof(struct vnt_tx_datahead_ab); } else { /* RTS_needless, need MICHDR */ pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab)); pvRTS = NULL; pvCTS = NULL; pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR); cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_tx_datahead_ab); } } else { /* Auto Fall Back */ if (bRTS) { /* RTS_need */ pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); pMICHDR = (struct vnt_mic_hdr *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab)); pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR); pvCTS = NULL; pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_a_fb)); cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_a_fb) + sizeof(struct vnt_tx_datahead_a_fb); } else { /* RTS_needless */ pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize); pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab)); pvRTS = NULL; pvCTS = NULL; pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR); cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_tx_datahead_a_fb); } } /* Auto Fall Back */ } td_info->mic_hdr = pMICHDR; memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderLength - wTxBufSize)); /* Fill FIFO,RrvTime,RTS,and CTS */ s_vGenerateTxParameter(pDevice, byPktType, tx_buffer_head, pvRrvTime, pvRTS, pvCTS, cbFrameSize, bNeedACK, uDMAIdx, hdr, pDevice->wCurrentRate); /* Fill DataHead */ uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK, 0, 0, uMACfragNum, byFBOption, pDevice->wCurrentRate, is_pspoll); hdr->duration_id = uDuration; cbReqCount = cbHeaderLength + uPadding + skb->len; pbyBuffer = (unsigned char *)pHeadTD->td_info->buf; uLength = cbHeaderLength + uPadding; /* Copy the Packet into a tx Buffer */ memcpy((pbyBuffer + uLength), skb->data, skb->len); ptdCurr = pHeadTD; ptdCurr->td_info->req_count = (u16)cbReqCount; return cbHeaderLength; }
void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry) { struct rxdone_entry_desc rxdesc; struct sk_buff *skb; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; struct ieee80211_supported_band *sband; struct ieee80211_hdr *hdr; const struct rt2x00_rate *rate; unsigned int header_size; unsigned int align; unsigned int i; int idx = -1; /* * Allocate a new sk_buffer. If no new buffer available, drop the * received frame and reuse the existing buffer. */ skb = rt2x00queue_alloc_rxskb(rt2x00dev, entry); if (!skb) return; /* * Unmap the skb. */ rt2x00queue_unmap_skb(rt2x00dev, entry->skb); /* * Extract the RXD details. */ memset(&rxdesc, 0, sizeof(rxdesc)); rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); /* * The data behind the ieee80211 header must be * aligned on a 4 byte boundary. */ header_size = ieee80211_get_hdrlen_from_skb(entry->skb); align = ((unsigned long)(entry->skb->data + header_size)) & 3; if (align) { skb_push(entry->skb, align); /* Move entire frame in 1 command */ memmove(entry->skb->data, entry->skb->data + align, rxdesc.size); } /* Update data pointers, trim buffer to correct size */ skb_trim(entry->skb, rxdesc.size); /* * Update RX statistics. */ sband = &rt2x00dev->bands[rt2x00dev->curr_band]; for (i = 0; i < sband->n_bitrates; i++) { rate = rt2x00_get_rate(sband->bitrates[i].hw_value); if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && (rate->plcp == rxdesc.signal)) || (!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && (rate->bitrate == rxdesc.signal))) { idx = i; break; } } if (idx < 0) { WARNING(rt2x00dev, "Frame received with unrecognized signal," "signal=0x%.2x, plcp=%d.\n", rxdesc.signal, !!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP)); idx = 0; } /* * Only update link status if this is a beacon frame carrying our bssid. */ hdr = (struct ieee80211_hdr *)entry->skb->data; if (ieee80211_is_beacon(hdr->frame_control) && (rxdesc.dev_flags & RXDONE_MY_BSS)) rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc.rssi); rt2x00dev->link.qual.rx_success++; rx_status->mactime = rxdesc.timestamp; rx_status->rate_idx = idx; rx_status->qual = rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi); rx_status->signal = rxdesc.rssi; rx_status->flag = rxdesc.flags; rx_status->antenna = rt2x00dev->link.ant.active.rx; /* * Send frame to mac80211 & debugfs. * mac80211 will clean up the skb structure. */ rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status); /* * Replace the skb with the freshly allocated one. */ entry->skb = skb; entry->flags = 0; rt2x00dev->ops->lib->init_rxentry(rt2x00dev, entry); rt2x00queue_index_inc(entry->queue, Q_INDEX); }
static void ar5523_data_rx_cb(struct urb *urb) { struct ar5523_rx_data *data = urb->context; struct ar5523 *ar = data->ar; struct ar5523_rx_desc *desc; struct ar5523_chunk *chunk; struct ieee80211_hw *hw = ar->hw; struct ieee80211_rx_status *rx_status; u32 rxlen; int usblen = urb->actual_length; int hdrlen, pad; ar5523_dbg(ar, "%s\n", __func__); /* sync/async unlink faults aren't errors */ if (urb->status) { if (urb->status != -ESHUTDOWN) ar5523_err(ar, "%s: USB err: %d\n", __func__, urb->status); goto skip; } if (usblen < AR5523_MIN_RXBUFSZ) { ar5523_err(ar, "RX: wrong xfer size (usblen=%d)\n", usblen); goto skip; } chunk = (struct ar5523_chunk *) data->skb->data; if (((chunk->flags & UATH_CFLAGS_FINAL) == 0) || chunk->seqnum != 0) { ar5523_dbg(ar, "RX: No final flag. s: %d f: %02x l: %d\n", chunk->seqnum, chunk->flags, be16_to_cpu(chunk->length)); goto skip; } /* Rx descriptor is located at the end, 32-bit aligned */ desc = (struct ar5523_rx_desc *) (data->skb->data + usblen - sizeof(struct ar5523_rx_desc)); rxlen = be32_to_cpu(desc->len); if (rxlen > ar->rxbufsz) { ar5523_dbg(ar, "RX: Bad descriptor (len=%d)\n", be32_to_cpu(desc->len)); goto skip; } if (!rxlen) { ar5523_dbg(ar, "RX: rxlen is 0\n"); goto skip; } if (be32_to_cpu(desc->status) != 0) { ar5523_dbg(ar, "Bad RX status (0x%x len = %d). Skip\n", be32_to_cpu(desc->status), be32_to_cpu(desc->len)); goto skip; } skb_reserve(data->skb, sizeof(*chunk)); skb_put(data->skb, rxlen - sizeof(struct ar5523_rx_desc)); hdrlen = ieee80211_get_hdrlen_from_skb(data->skb); if (!IS_ALIGNED(hdrlen, 4)) { ar5523_dbg(ar, "eek, alignment workaround activated\n"); pad = ALIGN(hdrlen, 4) - hdrlen; memmove(data->skb->data + pad, data->skb->data, hdrlen); skb_pull(data->skb, pad); skb_put(data->skb, pad); } rx_status = IEEE80211_SKB_RXCB(data->skb); memset(rx_status, 0, sizeof(*rx_status)); rx_status->freq = be32_to_cpu(desc->channel); rx_status->band = hw->conf.chandef.chan->band; rx_status->signal = -95 + be32_to_cpu(desc->rssi); ieee80211_rx_irqsafe(hw, data->skb); data->skb = NULL; skip: if (data->skb) { dev_kfree_skb_irq(data->skb); data->skb = NULL; } ar5523_rx_data_put(ar, data); if (atomic_inc_return(&ar->rx_data_free_cnt) >= AR5523_RX_DATA_REFILL_COUNT && test_bit(AR5523_HW_UP, &ar->flags)) queue_work(ar->wq, &ar->rx_refill_work); }
static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, struct ath9k_htc_rxbuf *rxbuf, struct ieee80211_rx_status *rx_status) { struct ieee80211_hdr *hdr; struct ieee80211_hw *hw = priv->hw; struct sk_buff *skb = rxbuf->skb; struct ath_common *common = ath9k_hw_common(priv->ah); struct ath_htc_rx_status *rxstatus; int hdrlen, padpos, padsize; int last_rssi = ATH_RSSI_DUMMY_MARKER; __le16 fc; if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) { ath_print(common, ATH_DBG_FATAL, "Corrupted RX frame, dropping\n"); goto rx_next; } rxstatus = (struct ath_htc_rx_status *)skb->data; if (be16_to_cpu(rxstatus->rs_datalen) - (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) { ath_print(common, ATH_DBG_FATAL, "Corrupted RX data len, dropping " "(dlen: %d, skblen: %d)\n", rxstatus->rs_datalen, skb->len); goto rx_next; } /* Get the RX status information */ memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); hdr = (struct ieee80211_hdr *)skb->data; fc = hdr->frame_control; hdrlen = ieee80211_get_hdrlen_from_skb(skb); padpos = ath9k_cmn_padpos(fc); padsize = padpos & 3; if (padsize && skb->len >= padpos+padsize+FCS_LEN) { memmove(skb->data + padsize, skb->data, padpos); skb_pull(skb, padsize); } memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); if (rxbuf->rxstatus.rs_status != 0) { if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_CRC) rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_PHY) goto rx_next; if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT) { /* FIXME */ } else if (rxbuf->rxstatus.rs_status & ATH9K_RXERR_MIC) { if (ieee80211_is_ctl(fc)) /* * Sometimes, we get invalid * MIC failures on valid control frames. * Remove these mic errors. */ rxbuf->rxstatus.rs_status &= ~ATH9K_RXERR_MIC; else rx_status->flag |= RX_FLAG_MMIC_ERROR; } /* * Reject error frames with the exception of * decryption and MIC failures. For monitor mode, * we also ignore the CRC error. */ if (priv->ah->opmode == NL80211_IFTYPE_MONITOR) { if (rxbuf->rxstatus.rs_status & ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | ATH9K_RXERR_CRC)) goto rx_next; } else { if (rxbuf->rxstatus.rs_status & ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { goto rx_next; } } } if (!(rxbuf->rxstatus.rs_status & ATH9K_RXERR_DECRYPT)) { u8 keyix; keyix = rxbuf->rxstatus.rs_keyix; if (keyix != ATH9K_RXKEYIX_INVALID) { rx_status->flag |= RX_FLAG_DECRYPTED; } else if (ieee80211_has_protected(fc) && skb->len >= hdrlen + 4) { keyix = skb->data[hdrlen + 3] >> 6; if (test_bit(keyix, common->keymap)) rx_status->flag |= RX_FLAG_DECRYPTED; }
static void rt2x00usb_interrupt_rxdone(struct urb *urb) { struct queue_entry *entry = (struct queue_entry *)urb->context; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct sk_buff *skb; struct skb_frame_desc *skbdesc; struct rxdone_entry_desc rxdesc; int header_size; if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; /* * Check if the received data is simply too small * to be actually valid, or if the urb is signaling * a problem. */ if (urb->actual_length < entry->queue->desc_size || urb->status) goto skip_entry; /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(entry->skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->entry = entry; memset(&rxdesc, 0, sizeof(rxdesc)); rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); /* * The data behind the ieee80211 header must be * aligned on a 4 byte boundary. */ header_size = ieee80211_get_hdrlen_from_skb(entry->skb); if (header_size % 4 == 0) { skb_push(entry->skb, 2); memmove(entry->skb->data, entry->skb->data + 2, entry->skb->len - 2); skbdesc->data = entry->skb->data; skb_trim(entry->skb,entry->skb->len - 2); } /* * Allocate a new sk buffer to replace the current one. * If allocation fails, we should drop the current frame * so we can recycle the existing sk buffer for the new frame. */ skb = rt2x00usb_alloc_rxskb(entry->queue); if (!skb) goto skip_entry; /* * Send the frame to rt2x00lib for further processing. */ rt2x00lib_rxdone(entry, &rxdesc); /* * Replace current entry's skb with the newly allocated one, * and reinitialize the urb. */ entry->skb = skb; urb->transfer_buffer = entry->skb->data; urb->transfer_buffer_length = entry->skb->len; skip_entry: if (test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) { __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); usb_submit_urb(urb, GFP_ATOMIC); } rt2x00queue_index_inc(entry->queue, Q_INDEX); }
/*should call before software enc*/ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); u16 fc = le16_to_cpu(hdr->frame_control); u16 ether_type; u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb); const struct iphdr *ip; if (!ieee80211_is_data(fc)) goto end; if (ieee80211_is_nullfunc(fc)) return true; ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len + SNAP_SIZE + PROTOC_TYPE_SIZE); ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE); ether_type = ntohs(ether_type); if (ETH_P_IP == ether_type) { if (IPPROTO_UDP == ip->protocol) { struct udphdr *udp = (struct udphdr *)((u8 *) ip + (ip->ihl << 2)); if (((((u8 *) udp)[1] == 68) && (((u8 *) udp)[3] == 67)) || ((((u8 *) udp)[1] == 67) && (((u8 *) udp)[3] == 68))) { /* * 68 : UDP BOOTP client * 67 : UDP BOOTP server */ RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, ("dhcp %s !!\n", (is_tx) ? "Tx" : "Rx")); if (is_tx) { rtl_lps_leave(hw); ppsc->last_delaylps_stamp_jiffies = jiffies; } return true; } } } else if (ETH_P_ARP == ether_type) { if (is_tx) { rtl_lps_leave(hw); ppsc->last_delaylps_stamp_jiffies = jiffies; } return true; } else if (ETH_P_PAE == ether_type) { RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, ("802.1X %s EAPOL pkt!!\n", (is_tx) ? "Tx" : "Rx")); if (is_tx) { rtl_lps_leave(hw); ppsc->last_delaylps_stamp_jiffies = jiffies; } return true; } else if (0x86DD == ether_type) { return true; } end: return false; }
static void wl18xx_tx_complete_packet(struct wl1271 *wl, u8 tx_stat_byte) { struct ieee80211_tx_info *info; struct sk_buff *skb; int id = tx_stat_byte & WL18XX_TX_STATUS_DESC_ID_MASK; bool tx_success; /* check for id legality */ if (unlikely(id >= wl->num_tx_desc || wl->tx_frames[id] == NULL)) { wl1271_warning("illegal id in tx completion: %d", id); return; } /* a zero bit indicates Tx success */ tx_success = !(tx_stat_byte & BIT(WL18XX_TX_STATUS_STAT_BIT_IDX)); skb = wl->tx_frames[id]; info = IEEE80211_SKB_CB(skb); if (wl12xx_is_dummy_packet(wl, skb)) { wl1271_free_tx_id(wl, id); return; } /* update the TX status info */ if (tx_success && !(info->flags & IEEE80211_TX_CTL_NO_ACK)) info->flags |= IEEE80211_TX_STAT_ACK; /* * first pass info->control.vif while it's valid, and then fill out * the info->status structures */ wl18xx_get_last_tx_rate(wl, info->control.vif, &info->status.rates[0]); info->status.rates[0].count = 1; /* no data about retries */ info->status.ack_signal = -1; if (!tx_success) wl->stats.retry_count++; /* * TODO: update sequence number for encryption? seems to be * unsupported for now. needed for recovery with encryption. */ /* remove private header from packet */ skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); /* remove TKIP header space if present */ if ((wl->quirks & WLCORE_QUIRK_TKIP_HEADER_SPACE) && info->control.hw_key && info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { int hdrlen = ieee80211_get_hdrlen_from_skb(skb); memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data, hdrlen); skb_pull(skb, WL1271_EXTRA_SPACE_TKIP); } wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p success %d", id, skb, tx_success); /* return the packet to the stack */ skb_queue_tail(&wl->deferred_tx_queue, skb); queue_work(wl->freezable_wq, &wl->netstack_work); wl1271_free_tx_id(wl, id); }