diff options
Diffstat (limited to 'drivers/net/wireless/b43/dma.c')
-rw-r--r-- | drivers/net/wireless/b43/dma.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 3e73d2a523aa..8a708b77925d 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -1114,7 +1114,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1114 | { | 1114 | { |
1115 | const struct b43_dma_ops *ops = ring->ops; | 1115 | const struct b43_dma_ops *ops = ring->ops; |
1116 | u8 *header; | 1116 | u8 *header; |
1117 | int slot; | 1117 | int slot, old_top_slot, old_used_slots; |
1118 | int err; | 1118 | int err; |
1119 | struct b43_dmadesc_generic *desc; | 1119 | struct b43_dmadesc_generic *desc; |
1120 | struct b43_dmadesc_meta *meta; | 1120 | struct b43_dmadesc_meta *meta; |
@@ -1126,6 +1126,9 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1126 | #define SLOTS_PER_PACKET 2 | 1126 | #define SLOTS_PER_PACKET 2 |
1127 | B43_WARN_ON(skb_shinfo(skb)->nr_frags); | 1127 | B43_WARN_ON(skb_shinfo(skb)->nr_frags); |
1128 | 1128 | ||
1129 | old_top_slot = ring->current_slot; | ||
1130 | old_used_slots = ring->used_slots; | ||
1131 | |||
1129 | /* Get a slot for the header. */ | 1132 | /* Get a slot for the header. */ |
1130 | slot = request_slot(ring); | 1133 | slot = request_slot(ring); |
1131 | desc = ops->idx2desc(ring, slot, &meta_hdr); | 1134 | desc = ops->idx2desc(ring, slot, &meta_hdr); |
@@ -1133,13 +1136,21 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1133 | 1136 | ||
1134 | header = &(ring->txhdr_cache[slot * hdrsize]); | 1137 | header = &(ring->txhdr_cache[slot * hdrsize]); |
1135 | cookie = generate_cookie(ring, slot); | 1138 | cookie = generate_cookie(ring, slot); |
1136 | b43_generate_txhdr(ring->dev, header, | 1139 | err = b43_generate_txhdr(ring->dev, header, |
1137 | skb->data, skb->len, ctl, cookie); | 1140 | skb->data, skb->len, ctl, cookie); |
1141 | if (unlikely(err)) { | ||
1142 | ring->current_slot = old_top_slot; | ||
1143 | ring->used_slots = old_used_slots; | ||
1144 | return err; | ||
1145 | } | ||
1138 | 1146 | ||
1139 | meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, | 1147 | meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, |
1140 | hdrsize, 1); | 1148 | hdrsize, 1); |
1141 | if (dma_mapping_error(meta_hdr->dmaaddr)) | 1149 | if (dma_mapping_error(meta_hdr->dmaaddr)) { |
1150 | ring->current_slot = old_top_slot; | ||
1151 | ring->used_slots = old_used_slots; | ||
1142 | return -EIO; | 1152 | return -EIO; |
1153 | } | ||
1143 | ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, | 1154 | ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, |
1144 | hdrsize, 1, 0, 0); | 1155 | hdrsize, 1, 0, 0); |
1145 | 1156 | ||
@@ -1157,6 +1168,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1157 | if (dma_mapping_error(meta->dmaaddr)) { | 1168 | if (dma_mapping_error(meta->dmaaddr)) { |
1158 | bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); | 1169 | bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); |
1159 | if (!bounce_skb) { | 1170 | if (!bounce_skb) { |
1171 | ring->current_slot = old_top_slot; | ||
1172 | ring->used_slots = old_used_slots; | ||
1160 | err = -ENOMEM; | 1173 | err = -ENOMEM; |
1161 | goto out_unmap_hdr; | 1174 | goto out_unmap_hdr; |
1162 | } | 1175 | } |
@@ -1167,6 +1180,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1167 | meta->skb = skb; | 1180 | meta->skb = skb; |
1168 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); | 1181 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); |
1169 | if (dma_mapping_error(meta->dmaaddr)) { | 1182 | if (dma_mapping_error(meta->dmaaddr)) { |
1183 | ring->current_slot = old_top_slot; | ||
1184 | ring->used_slots = old_used_slots; | ||
1170 | err = -EIO; | 1185 | err = -EIO; |
1171 | goto out_free_bounce; | 1186 | goto out_free_bounce; |
1172 | } | 1187 | } |
@@ -1252,6 +1267,13 @@ int b43_dma_tx(struct b43_wldev *dev, | |||
1252 | B43_WARN_ON(ring->stopped); | 1267 | B43_WARN_ON(ring->stopped); |
1253 | 1268 | ||
1254 | err = dma_tx_fragment(ring, skb, ctl); | 1269 | err = dma_tx_fragment(ring, skb, ctl); |
1270 | if (unlikely(err == -ENOKEY)) { | ||
1271 | /* Drop this packet, as we don't have the encryption key | ||
1272 | * anymore and must not transmit it unencrypted. */ | ||
1273 | dev_kfree_skb_any(skb); | ||
1274 | err = 0; | ||
1275 | goto out_unlock; | ||
1276 | } | ||
1255 | if (unlikely(err)) { | 1277 | if (unlikely(err)) { |
1256 | b43err(dev->wl, "DMA tx mapping failure\n"); | 1278 | b43err(dev->wl, "DMA tx mapping failure\n"); |
1257 | goto out_unlock; | 1279 | goto out_unlock; |