aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/mwl8k.c46
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
90struct mwl8k_device_info { 91struct mwl8k_device_info {
@@ -699,21 +700,29 @@ static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len)
699struct mwl8k_dma_data { 700struct 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. */
705static inline void mwl8k_remove_dma_header(struct sk_buff *skb) 707static 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
719static inline void mwl8k_add_dma_header(struct sk_buff *skb) 728static 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
795static int 804static int
796mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status) 805mwl8k_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
883static int 895static int
884mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status) 896mwl8k_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;