aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/dma.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-11-18 13:55:32 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-18 13:55:32 -0500
commitdfef948ed2ba69cf041840b5e860d6b4e16fa0b1 (patch)
treeeab385cabe589346bcf19385c997ab8dabaef7bd /drivers/net/wireless/b43/dma.c
parentea31ba359c55e0734ff895692185d4c50cf0c537 (diff)
parentc85e9d7739fc8d879c4293ea020760926d6f87cd (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/b43/dma.c')
-rw-r--r--drivers/net/wireless/b43/dma.c48
1 files changed, 20 insertions, 28 deletions
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index de4e804bedf..b5cd7f57055 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1157,18 +1157,17 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
1157} 1157}
1158 1158
1159static int dma_tx_fragment(struct b43_dmaring *ring, 1159static int dma_tx_fragment(struct b43_dmaring *ring,
1160 struct sk_buff **in_skb) 1160 struct sk_buff *skb)
1161{ 1161{
1162 struct sk_buff *skb = *in_skb;
1163 const struct b43_dma_ops *ops = ring->ops; 1162 const struct b43_dma_ops *ops = ring->ops;
1164 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1163 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1164 struct b43_private_tx_info *priv_info = b43_get_priv_tx_info(info);
1165 u8 *header; 1165 u8 *header;
1166 int slot, old_top_slot, old_used_slots; 1166 int slot, old_top_slot, old_used_slots;
1167 int err; 1167 int err;
1168 struct b43_dmadesc_generic *desc; 1168 struct b43_dmadesc_generic *desc;
1169 struct b43_dmadesc_meta *meta; 1169 struct b43_dmadesc_meta *meta;
1170 struct b43_dmadesc_meta *meta_hdr; 1170 struct b43_dmadesc_meta *meta_hdr;
1171 struct sk_buff *bounce_skb;
1172 u16 cookie; 1171 u16 cookie;
1173 size_t hdrsize = b43_txhdr_size(ring->dev); 1172 size_t hdrsize = b43_txhdr_size(ring->dev);
1174 1173
@@ -1212,34 +1211,28 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
1212 1211
1213 meta->skb = skb; 1212 meta->skb = skb;
1214 meta->is_last_fragment = 1; 1213 meta->is_last_fragment = 1;
1214 priv_info->bouncebuffer = NULL;
1215 1215
1216 meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); 1216 meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
1217 /* create a bounce buffer in zone_dma on mapping failure. */ 1217 /* create a bounce buffer in zone_dma on mapping failure. */
1218 if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { 1218 if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
1219 bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); 1219 priv_info->bouncebuffer = kmalloc(skb->len, GFP_ATOMIC | GFP_DMA);
1220 if (!bounce_skb) { 1220 if (!priv_info->bouncebuffer) {
1221 ring->current_slot = old_top_slot; 1221 ring->current_slot = old_top_slot;
1222 ring->used_slots = old_used_slots; 1222 ring->used_slots = old_used_slots;
1223 err = -ENOMEM; 1223 err = -ENOMEM;
1224 goto out_unmap_hdr; 1224 goto out_unmap_hdr;
1225 } 1225 }
1226 memcpy(priv_info->bouncebuffer, skb->data, skb->len);
1226 1227
1227 memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len); 1228 meta->dmaaddr = map_descbuffer(ring, priv_info->bouncebuffer, skb->len, 1);
1228 memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb));
1229 bounce_skb->dev = skb->dev;
1230 skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb));
1231 info = IEEE80211_SKB_CB(bounce_skb);
1232
1233 dev_kfree_skb_any(skb);
1234 skb = bounce_skb;
1235 *in_skb = bounce_skb;
1236 meta->skb = skb;
1237 meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
1238 if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { 1229 if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
1230 kfree(priv_info->bouncebuffer);
1231 priv_info->bouncebuffer = NULL;
1239 ring->current_slot = old_top_slot; 1232 ring->current_slot = old_top_slot;
1240 ring->used_slots = old_used_slots; 1233 ring->used_slots = old_used_slots;
1241 err = -EIO; 1234 err = -EIO;
1242 goto out_free_bounce; 1235 goto out_unmap_hdr;
1243 } 1236 }
1244 } 1237 }
1245 1238
@@ -1256,8 +1249,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
1256 ops->poke_tx(ring, next_slot(ring, slot)); 1249 ops->poke_tx(ring, next_slot(ring, slot));
1257 return 0; 1250 return 0;
1258 1251
1259out_free_bounce:
1260 dev_kfree_skb_any(skb);
1261out_unmap_hdr: 1252out_unmap_hdr:
1262 unmap_descbuffer(ring, meta_hdr->dmaaddr, 1253 unmap_descbuffer(ring, meta_hdr->dmaaddr,
1263 hdrsize, 1); 1254 hdrsize, 1);
@@ -1362,11 +1353,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
1362 * static, so we don't need to store it per frame. */ 1353 * static, so we don't need to store it per frame. */
1363 ring->queue_prio = skb_get_queue_mapping(skb); 1354 ring->queue_prio = skb_get_queue_mapping(skb);
1364 1355
1365 /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing 1356 err = dma_tx_fragment(ring, skb);
1366 * into the skb data or cb now. */
1367 hdr = NULL;
1368 info = NULL;
1369 err = dma_tx_fragment(ring, &skb);
1370 if (unlikely(err == -ENOKEY)) { 1357 if (unlikely(err == -ENOKEY)) {
1371 /* Drop this packet, as we don't have the encryption key 1358 /* Drop this packet, as we don't have the encryption key
1372 * anymore and must not transmit it unencrypted. */ 1359 * anymore and must not transmit it unencrypted. */
@@ -1413,12 +1400,17 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
1413 B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); 1400 B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
1414 desc = ops->idx2desc(ring, slot, &meta); 1401 desc = ops->idx2desc(ring, slot, &meta);
1415 1402
1416 if (meta->skb) 1403 if (meta->skb) {
1417 unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1404 struct b43_private_tx_info *priv_info =
1418 1); 1405 b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
1419 else 1406
1407 unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
1408 kfree(priv_info->bouncebuffer);
1409 priv_info->bouncebuffer = NULL;
1410 } else {
1420 unmap_descbuffer(ring, meta->dmaaddr, 1411 unmap_descbuffer(ring, meta->dmaaddr,
1421 b43_txhdr_size(dev), 1); 1412 b43_txhdr_size(dev), 1);
1413 }
1422 1414
1423 if (meta->is_last_fragment) { 1415 if (meta->is_last_fragment) {
1424 struct ieee80211_tx_info *info; 1416 struct ieee80211_tx_info *info;