diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/htc_drv_txrx.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 59 |
1 files changed, 34 insertions, 25 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 2c3c51007dd3..28abc7d5e909 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -244,16 +244,25 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, | |||
244 | enum htc_endpoint_id ep_id, bool txok) | 244 | enum htc_endpoint_id ep_id, bool txok) |
245 | { | 245 | { |
246 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; | 246 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; |
247 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
247 | struct ieee80211_tx_info *tx_info; | 248 | struct ieee80211_tx_info *tx_info; |
248 | 249 | ||
249 | if (!skb) | 250 | if (!skb) |
250 | return; | 251 | return; |
251 | 252 | ||
252 | if (ep_id == priv->mgmt_ep) | 253 | if (ep_id == priv->mgmt_ep) { |
253 | skb_pull(skb, sizeof(struct tx_mgmt_hdr)); | 254 | skb_pull(skb, sizeof(struct tx_mgmt_hdr)); |
254 | else | 255 | } else if ((ep_id == priv->data_bk_ep) || |
255 | /* TODO: Check for cab/uapsd/data */ | 256 | (ep_id == priv->data_be_ep) || |
257 | (ep_id == priv->data_vi_ep) || | ||
258 | (ep_id == priv->data_vo_ep)) { | ||
256 | skb_pull(skb, sizeof(struct tx_frame_hdr)); | 259 | skb_pull(skb, sizeof(struct tx_frame_hdr)); |
260 | } else { | ||
261 | ath_print(common, ATH_DBG_FATAL, | ||
262 | "Unsupported TX EPID: %d\n", ep_id); | ||
263 | dev_kfree_skb_any(skb); | ||
264 | return; | ||
265 | } | ||
257 | 266 | ||
258 | tx_info = IEEE80211_SKB_CB(skb); | 267 | tx_info = IEEE80211_SKB_CB(skb); |
259 | 268 | ||
@@ -439,10 +448,32 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
439 | struct ieee80211_hw *hw = priv->hw; | 448 | struct ieee80211_hw *hw = priv->hw; |
440 | struct sk_buff *skb = rxbuf->skb; | 449 | struct sk_buff *skb = rxbuf->skb; |
441 | struct ath_common *common = ath9k_hw_common(priv->ah); | 450 | struct ath_common *common = ath9k_hw_common(priv->ah); |
451 | struct ath_htc_rx_status *rxstatus; | ||
442 | int hdrlen, padpos, padsize; | 452 | int hdrlen, padpos, padsize; |
443 | int last_rssi = ATH_RSSI_DUMMY_MARKER; | 453 | int last_rssi = ATH_RSSI_DUMMY_MARKER; |
444 | __le16 fc; | 454 | __le16 fc; |
445 | 455 | ||
456 | if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) { | ||
457 | ath_print(common, ATH_DBG_FATAL, | ||
458 | "Corrupted RX frame, dropping\n"); | ||
459 | goto rx_next; | ||
460 | } | ||
461 | |||
462 | rxstatus = (struct ath_htc_rx_status *)skb->data; | ||
463 | |||
464 | if (be16_to_cpu(rxstatus->rs_datalen) - | ||
465 | (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) { | ||
466 | ath_print(common, ATH_DBG_FATAL, | ||
467 | "Corrupted RX data len, dropping " | ||
468 | "(dlen: %d, skblen: %d)\n", | ||
469 | rxstatus->rs_datalen, skb->len); | ||
470 | goto rx_next; | ||
471 | } | ||
472 | |||
473 | /* Get the RX status information */ | ||
474 | memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); | ||
475 | skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); | ||
476 | |||
446 | hdr = (struct ieee80211_hdr *)skb->data; | 477 | hdr = (struct ieee80211_hdr *)skb->data; |
447 | fc = hdr->frame_control; | 478 | fc = hdr->frame_control; |
448 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 479 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
@@ -607,8 +638,6 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, | |||
607 | struct ath_hw *ah = priv->ah; | 638 | struct ath_hw *ah = priv->ah; |
608 | struct ath_common *common = ath9k_hw_common(ah); | 639 | struct ath_common *common = ath9k_hw_common(ah); |
609 | struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; | 640 | struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL; |
610 | struct ath_htc_rx_status *rxstatus; | ||
611 | u32 len = 0; | ||
612 | 641 | ||
613 | spin_lock(&priv->rx.rxbuflock); | 642 | spin_lock(&priv->rx.rxbuflock); |
614 | list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { | 643 | list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) { |
@@ -625,27 +654,7 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, | |||
625 | goto err; | 654 | goto err; |
626 | } | 655 | } |
627 | 656 | ||
628 | len = skb->len; | ||
629 | if (len <= HTC_RX_FRAME_HEADER_SIZE) { | ||
630 | ath_print(common, ATH_DBG_FATAL, | ||
631 | "Corrupted RX frame, dropping\n"); | ||
632 | goto err; | ||
633 | } | ||
634 | |||
635 | rxstatus = (struct ath_htc_rx_status *)skb->data; | ||
636 | |||
637 | if (be16_to_cpu(rxstatus->rs_datalen) - | ||
638 | (len - HTC_RX_FRAME_HEADER_SIZE) != 0) { | ||
639 | ath_print(common, ATH_DBG_FATAL, | ||
640 | "Corrupted RX data len, dropping " | ||
641 | "(epid: %d, dlen: %d, skblen: %d)\n", | ||
642 | ep_id, rxstatus->rs_datalen, len); | ||
643 | goto err; | ||
644 | } | ||
645 | |||
646 | spin_lock(&priv->rx.rxbuflock); | 657 | spin_lock(&priv->rx.rxbuflock); |
647 | memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); | ||
648 | skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); | ||
649 | rxbuf->skb = skb; | 658 | rxbuf->skb = skb; |
650 | rxbuf->in_process = true; | 659 | rxbuf->in_process = true; |
651 | spin_unlock(&priv->rx.rxbuflock); | 660 | spin_unlock(&priv->rx.rxbuflock); |