diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/mwl8k.c | 46 |
1 files changed, 31 insertions, 15 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 0251b6144f57..6b12d81ba94b 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -84,7 +84,8 @@ struct rxd_ops { | |||
84 | int rxd_size; | 84 | int rxd_size; |
85 | void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr); | 85 | void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr); |
86 | void (*rxd_refill)(void *rxd, dma_addr_t addr, int len); | 86 | void (*rxd_refill)(void *rxd, dma_addr_t addr, int len); |
87 | int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status); | 87 | int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status, |
88 | __le16 *qos); | ||
88 | }; | 89 | }; |
89 | 90 | ||
90 | struct mwl8k_device_info { | 91 | struct mwl8k_device_info { |
@@ -699,21 +700,29 @@ static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len) | |||
699 | struct mwl8k_dma_data { | 700 | struct mwl8k_dma_data { |
700 | __le16 fwlen; | 701 | __le16 fwlen; |
701 | struct ieee80211_hdr wh; | 702 | struct ieee80211_hdr wh; |
703 | char data[0]; | ||
702 | } __attribute__((packed)); | 704 | } __attribute__((packed)); |
703 | 705 | ||
704 | /* Routines to add/remove DMA header from skb. */ | 706 | /* Routines to add/remove DMA header from skb. */ |
705 | static inline void mwl8k_remove_dma_header(struct sk_buff *skb) | 707 | static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos) |
706 | { | 708 | { |
707 | struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)skb->data; | 709 | struct mwl8k_dma_data *tr; |
708 | void *dst, *src = &tr->wh; | 710 | int hdrlen; |
709 | int hdrlen = ieee80211_hdrlen(tr->wh.frame_control); | 711 | |
710 | u16 space = sizeof(struct mwl8k_dma_data) - hdrlen; | 712 | tr = (struct mwl8k_dma_data *)skb->data; |
713 | hdrlen = ieee80211_hdrlen(tr->wh.frame_control); | ||
711 | 714 | ||
712 | dst = (void *)tr + space; | 715 | if (hdrlen != sizeof(tr->wh)) { |
713 | if (dst != src) { | 716 | if (ieee80211_is_data_qos(tr->wh.frame_control)) { |
714 | memmove(dst, src, hdrlen); | 717 | memmove(tr->data - hdrlen, &tr->wh, hdrlen - 2); |
715 | skb_pull(skb, space); | 718 | *((__le16 *)(tr->data - 2)) = qos; |
719 | } else { | ||
720 | memmove(tr->data - hdrlen, &tr->wh, hdrlen); | ||
721 | } | ||
716 | } | 722 | } |
723 | |||
724 | if (hdrlen != sizeof(*tr)) | ||
725 | skb_pull(skb, sizeof(*tr) - hdrlen); | ||
717 | } | 726 | } |
718 | 727 | ||
719 | static inline void mwl8k_add_dma_header(struct sk_buff *skb) | 728 | static inline void mwl8k_add_dma_header(struct sk_buff *skb) |
@@ -793,7 +802,8 @@ static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len) | |||
793 | } | 802 | } |
794 | 803 | ||
795 | static int | 804 | static int |
796 | mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status) | 805 | mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, |
806 | __le16 *qos) | ||
797 | { | 807 | { |
798 | struct mwl8k_rxd_8366 *rxd = _rxd; | 808 | struct mwl8k_rxd_8366 *rxd = _rxd; |
799 | 809 | ||
@@ -823,6 +833,8 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status) | |||
823 | status->band = IEEE80211_BAND_2GHZ; | 833 | status->band = IEEE80211_BAND_2GHZ; |
824 | status->freq = ieee80211_channel_to_frequency(rxd->channel); | 834 | status->freq = ieee80211_channel_to_frequency(rxd->channel); |
825 | 835 | ||
836 | *qos = rxd->qos_control; | ||
837 | |||
826 | return le16_to_cpu(rxd->pkt_len); | 838 | return le16_to_cpu(rxd->pkt_len); |
827 | } | 839 | } |
828 | 840 | ||
@@ -881,7 +893,8 @@ static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len) | |||
881 | } | 893 | } |
882 | 894 | ||
883 | static int | 895 | static int |
884 | mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status) | 896 | mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, |
897 | __le16 *qos) | ||
885 | { | 898 | { |
886 | struct mwl8k_rxd_8687 *rxd = _rxd; | 899 | struct mwl8k_rxd_8687 *rxd = _rxd; |
887 | u16 rate_info; | 900 | u16 rate_info; |
@@ -912,6 +925,8 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status) | |||
912 | status->band = IEEE80211_BAND_2GHZ; | 925 | status->band = IEEE80211_BAND_2GHZ; |
913 | status->freq = ieee80211_channel_to_frequency(rxd->channel); | 926 | status->freq = ieee80211_channel_to_frequency(rxd->channel); |
914 | 927 | ||
928 | *qos = rxd->qos_control; | ||
929 | |||
915 | return le16_to_cpu(rxd->pkt_len); | 930 | return le16_to_cpu(rxd->pkt_len); |
916 | } | 931 | } |
917 | 932 | ||
@@ -1083,6 +1098,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | |||
1083 | void *rxd; | 1098 | void *rxd; |
1084 | int pkt_len; | 1099 | int pkt_len; |
1085 | struct ieee80211_rx_status status; | 1100 | struct ieee80211_rx_status status; |
1101 | __le16 qos; | ||
1086 | 1102 | ||
1087 | skb = rxq->buf[rxq->head].skb; | 1103 | skb = rxq->buf[rxq->head].skb; |
1088 | if (skb == NULL) | 1104 | if (skb == NULL) |
@@ -1090,7 +1106,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | |||
1090 | 1106 | ||
1091 | rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size); | 1107 | rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size); |
1092 | 1108 | ||
1093 | pkt_len = priv->rxd_ops->rxd_process(rxd, &status); | 1109 | pkt_len = priv->rxd_ops->rxd_process(rxd, &status, &qos); |
1094 | if (pkt_len < 0) | 1110 | if (pkt_len < 0) |
1095 | break; | 1111 | break; |
1096 | 1112 | ||
@@ -1108,7 +1124,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | |||
1108 | rxq->rxd_count--; | 1124 | rxq->rxd_count--; |
1109 | 1125 | ||
1110 | skb_put(skb, pkt_len); | 1126 | skb_put(skb, pkt_len); |
1111 | mwl8k_remove_dma_header(skb); | 1127 | mwl8k_remove_dma_header(skb, qos); |
1112 | 1128 | ||
1113 | /* | 1129 | /* |
1114 | * Check for a pending join operation. Save a | 1130 | * Check for a pending join operation. Save a |
@@ -1354,7 +1370,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) | |||
1354 | BUG_ON(skb == NULL); | 1370 | BUG_ON(skb == NULL); |
1355 | pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); | 1371 | pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); |
1356 | 1372 | ||
1357 | mwl8k_remove_dma_header(skb); | 1373 | mwl8k_remove_dma_header(skb, tx_desc->qos_control); |
1358 | 1374 | ||
1359 | /* Mark descriptor as unused */ | 1375 | /* Mark descriptor as unused */ |
1360 | tx_desc->pkt_phys_addr = 0; | 1376 | tx_desc->pkt_phys_addr = 0; |