diff options
author | David S. Miller <davem@davemloft.net> | 2009-11-18 13:55:32 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-18 13:55:32 -0500 |
commit | dfef948ed2ba69cf041840b5e860d6b4e16fa0b1 (patch) | |
tree | eab385cabe589346bcf19385c997ab8dabaef7bd /drivers/net/wireless/b43/dma.c | |
parent | ea31ba359c55e0734ff895692185d4c50cf0c537 (diff) | |
parent | c85e9d7739fc8d879c4293ea020760926d6f87cd (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.c | 48 |
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 | ||
1159 | static int dma_tx_fragment(struct b43_dmaring *ring, | 1159 | static 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 | ||
1259 | out_free_bounce: | ||
1260 | dev_kfree_skb_any(skb); | ||
1261 | out_unmap_hdr: | 1252 | out_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; |