aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwl8k.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r--drivers/net/wireless/mwl8k.c83
1 files changed, 13 insertions, 70 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 301d2a20d42b..5aa80420c0d1 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -111,17 +111,6 @@ struct mwl8k_rx_queue {
111 struct sk_buff **rx_skb; 111 struct sk_buff **rx_skb;
112}; 112};
113 113
114struct mwl8k_skb {
115 /*
116 * The DMA engine requires a modification to the payload.
117 * If the skbuff is shared/cloned, it needs to be unshared.
118 * This method is used to ensure the stack always gets back
119 * the skbuff it sent for transmission.
120 */
121 struct sk_buff *clone;
122 struct sk_buff *skb;
123};
124
125struct mwl8k_tx_queue { 114struct mwl8k_tx_queue {
126 /* hw transmits here */ 115 /* hw transmits here */
127 int tx_head; 116 int tx_head;
@@ -132,7 +121,7 @@ struct mwl8k_tx_queue {
132 struct ieee80211_tx_queue_stats tx_stats; 121 struct ieee80211_tx_queue_stats tx_stats;
133 struct mwl8k_tx_desc *tx_desc_area; 122 struct mwl8k_tx_desc *tx_desc_area;
134 dma_addr_t tx_desc_dma; 123 dma_addr_t tx_desc_dma;
135 struct mwl8k_skb *tx_skb; 124 struct sk_buff **tx_skb;
136}; 125};
137 126
138/* Pointers to the firmware data and meta information about it. */ 127/* Pointers to the firmware data and meta information about it. */
@@ -714,12 +703,11 @@ struct mwl8k_dma_data {
714} __attribute__((packed)); 703} __attribute__((packed));
715 704
716/* Routines to add/remove DMA header from skb. */ 705/* Routines to add/remove DMA header from skb. */
717static inline int mwl8k_remove_dma_header(struct sk_buff *skb) 706static inline void mwl8k_remove_dma_header(struct sk_buff *skb)
718{ 707{
719 struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)(skb->data); 708 struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)skb->data;
720 void *dst, *src = &tr->wh; 709 void *dst, *src = &tr->wh;
721 __le16 fc = tr->wh.frame_control; 710 int hdrlen = ieee80211_hdrlen(tr->wh.frame_control);
722 int hdrlen = ieee80211_hdrlen(fc);
723 u16 space = sizeof(struct mwl8k_dma_data) - hdrlen; 711 u16 space = sizeof(struct mwl8k_dma_data) - hdrlen;
724 712
725 dst = (void *)tr + space; 713 dst = (void *)tr + space;
@@ -727,11 +715,9 @@ static inline int mwl8k_remove_dma_header(struct sk_buff *skb)
727 memmove(dst, src, hdrlen); 715 memmove(dst, src, hdrlen);
728 skb_pull(skb, space); 716 skb_pull(skb, space);
729 } 717 }
730
731 return 0;
732} 718}
733 719
734static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb) 720static inline void mwl8k_add_dma_header(struct sk_buff *skb)
735{ 721{
736 struct ieee80211_hdr *wh; 722 struct ieee80211_hdr *wh;
737 u32 hdrlen, pktlen; 723 u32 hdrlen, pktlen;
@@ -763,8 +749,6 @@ static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb)
763 * This includes all crypto material including the MIC. 749 * This includes all crypto material including the MIC.
764 */ 750 */
765 tr->fwlen = cpu_to_le16(pktlen - hdrlen); 751 tr->fwlen = cpu_to_le16(pktlen - hdrlen);
766
767 return skb;
768} 752}
769 753
770 754
@@ -967,10 +951,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
967 MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); 951 MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
968 952
969 skb_put(skb, le16_to_cpu(rx_desc->pkt_len)); 953 skb_put(skb, le16_to_cpu(rx_desc->pkt_len));
970 if (mwl8k_remove_dma_header(skb)) { 954 mwl8k_remove_dma_header(skb);
971 dev_kfree_skb(skb);
972 continue;
973 }
974 955
975 wh = (struct ieee80211_hdr *)skb->data; 956 wh = (struct ieee80211_hdr *)skb->data;
976 957
@@ -1224,7 +1205,6 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
1224 1205
1225 while (txq->tx_stats.len > 0) { 1206 while (txq->tx_stats.len > 0) {
1226 int tx; 1207 int tx;
1227 int rc;
1228 struct mwl8k_tx_desc *tx_desc; 1208 struct mwl8k_tx_desc *tx_desc;
1229 unsigned long addr; 1209 unsigned long addr;
1230 int size; 1210 int size;
@@ -1232,7 +1212,6 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
1232 struct ieee80211_tx_info *info; 1212 struct ieee80211_tx_info *info;
1233 u32 status; 1213 u32 status;
1234 1214
1235 rc = 0;
1236 tx = txq->tx_head; 1215 tx = txq->tx_head;
1237 tx_desc = txq->tx_desc_area + tx; 1216 tx_desc = txq->tx_desc_area + tx;
1238 1217
@@ -1252,40 +1231,18 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
1252 1231
1253 addr = le32_to_cpu(tx_desc->pkt_phys_addr); 1232 addr = le32_to_cpu(tx_desc->pkt_phys_addr);
1254 size = le16_to_cpu(tx_desc->pkt_len); 1233 size = le16_to_cpu(tx_desc->pkt_len);
1255 skb = txq->tx_skb[tx].skb; 1234 skb = txq->tx_skb[tx];
1256 txq->tx_skb[tx].skb = NULL; 1235 txq->tx_skb[tx] = NULL;
1257 1236
1258 BUG_ON(skb == NULL); 1237 BUG_ON(skb == NULL);
1259 pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); 1238 pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE);
1260 1239
1261 rc = mwl8k_remove_dma_header(skb); 1240 mwl8k_remove_dma_header(skb);
1262 1241
1263 /* Mark descriptor as unused */ 1242 /* Mark descriptor as unused */
1264 tx_desc->pkt_phys_addr = 0; 1243 tx_desc->pkt_phys_addr = 0;
1265 tx_desc->pkt_len = 0; 1244 tx_desc->pkt_len = 0;
1266 1245
1267 if (txq->tx_skb[tx].clone) {
1268 /* Replace with original skb
1269 * before returning to stack
1270 * as buffer has been cloned
1271 */
1272 dev_kfree_skb(skb);
1273 skb = txq->tx_skb[tx].clone;
1274 txq->tx_skb[tx].clone = NULL;
1275 }
1276
1277 if (rc) {
1278 /* Something has gone wrong here.
1279 * Failed to remove DMA header.
1280 * Print error message and drop packet.
1281 */
1282 printk(KERN_ERR "%s: Error removing DMA header from "
1283 "tx skb 0x%p.\n", priv->name, skb);
1284
1285 dev_kfree_skb(skb);
1286 continue;
1287 }
1288
1289 info = IEEE80211_SKB_CB(skb); 1246 info = IEEE80211_SKB_CB(skb);
1290 ieee80211_tx_info_clear_status(info); 1247 ieee80211_tx_info_clear_status(info);
1291 if (MWL8K_TXD_SUCCESS(status)) 1248 if (MWL8K_TXD_SUCCESS(status))
@@ -1327,7 +1284,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1327 struct mwl8k_tx_desc *tx; 1284 struct mwl8k_tx_desc *tx;
1328 struct mwl8k_dma_data *tr; 1285 struct mwl8k_dma_data *tr;
1329 struct mwl8k_vif *mwl8k_vif; 1286 struct mwl8k_vif *mwl8k_vif;
1330 struct sk_buff *org_skb = skb;
1331 dma_addr_t dma; 1287 dma_addr_t dma;
1332 u16 qos = 0; 1288 u16 qos = 0;
1333 bool qosframe = false, ampduframe = false; 1289 bool qosframe = false, ampduframe = false;
@@ -1338,21 +1294,12 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1338 txq = priv->txq + index; 1294 txq = priv->txq + index;
1339 tx = txq->tx_desc_area + txq->tx_tail; 1295 tx = txq->tx_desc_area + txq->tx_tail;
1340 1296
1341 BUG_ON(txq->tx_skb[txq->tx_tail].skb != NULL); 1297 BUG_ON(txq->tx_skb[txq->tx_tail] != NULL);
1342 1298
1343 /* 1299 /*
1344 * Append HW DMA header to start of packet. Drop packet if 1300 * Append HW DMA header to start of packet.
1345 * there is not enough space or a failure to unshare/unclone
1346 * the skb.
1347 */ 1301 */
1348 skb = mwl8k_add_dma_header(skb); 1302 mwl8k_add_dma_header(skb);
1349
1350 if (skb == NULL) {
1351 printk(KERN_DEBUG "%s: failed to prepend HW DMA "
1352 "header, dropping TX frame.\n", priv->name);
1353 dev_kfree_skb(org_skb);
1354 return NETDEV_TX_OK;
1355 }
1356 1303
1357 tx_info = IEEE80211_SKB_CB(skb); 1304 tx_info = IEEE80211_SKB_CB(skb);
1358 mwl8k_vif = MWL8K_VIF(tx_info->control.vif); 1305 mwl8k_vif = MWL8K_VIF(tx_info->control.vif);
@@ -1380,8 +1327,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1380 printk(KERN_DEBUG "%s: failed to dma map skb, " 1327 printk(KERN_DEBUG "%s: failed to dma map skb, "
1381 "dropping TX frame.\n", priv->name); 1328 "dropping TX frame.\n", priv->name);
1382 1329
1383 if (org_skb != NULL)
1384 dev_kfree_skb(org_skb);
1385 if (skb != NULL) 1330 if (skb != NULL)
1386 dev_kfree_skb(skb); 1331 dev_kfree_skb(skb);
1387 return NETDEV_TX_OK; 1332 return NETDEV_TX_OK;
@@ -1437,9 +1382,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1437 tx->pkt_phys_addr = cpu_to_le32(dma); 1382 tx->pkt_phys_addr = cpu_to_le32(dma);
1438 tx->pkt_len = cpu_to_le16(skb->len); 1383 tx->pkt_len = cpu_to_le16(skb->len);
1439 1384
1440 txq->tx_skb[txq->tx_tail].skb = skb; 1385 txq->tx_skb[txq->tx_tail] = skb;
1441 txq->tx_skb[txq->tx_tail].clone =
1442 skb == org_skb ? NULL : org_skb;
1443 1386
1444 spin_lock_bh(&priv->tx_lock); 1387 spin_lock_bh(&priv->tx_lock);
1445 1388