From patchwork Sun Nov 1 15:28:34 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Buesch X-Patchwork-Id: 56876 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nA1FU7Xc010437 for ; Sun, 1 Nov 2009 15:30:07 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752805AbZKAPaA (ORCPT ); Sun, 1 Nov 2009 10:30:00 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752778AbZKAPaA (ORCPT ); Sun, 1 Nov 2009 10:30:00 -0500 Received: from bu3sch.de ([62.75.166.246]:54084 "EHLO vs166246.vserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752740AbZKAP37 (ORCPT ); Sun, 1 Nov 2009 10:29:59 -0500 Received: by vs166246.vserver.de with esmtpa (Exim 4.69) id 1N4cNX-0002Vk-8a; Sun, 01 Nov 2009 15:30:03 +0000 From: Michael Buesch To: Christian Casteyde Subject: Re: 2.6.32-rc5-git3: Reported regressions from 2.6.31 Date: Sun, 1 Nov 2009 16:28:34 +0100 User-Agent: KMail/1.9.9 Cc: "John W. Linville" , linux-wireless@vger.kernel.org, Johannes Berg References: <20091028190547.GA2856@tuxdriver.com> <200910282138.37401.casteyde.christian@free.fr> In-Reply-To: <200910282138.37401.casteyde.christian@free.fr> MIME-Version: 1.0 Content-Disposition: inline Message-Id: <200911011628.34535.mb@bu3sch.de> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Index: wireless-testing/drivers/net/wireless/b43/dma.c =================================================================== --- wireless-testing.orig/drivers/net/wireless/b43/dma.c 2009-11-01 15:10:48.000000000 +0100 +++ wireless-testing/drivers/net/wireless/b43/dma.c 2009-11-01 16:26:00.000000000 +0100 @@ -1157,18 +1157,17 @@ struct b43_dmaring *parse_cookie(struct } static int dma_tx_fragment(struct b43_dmaring *ring, - struct sk_buff **in_skb) + struct sk_buff *skb) { - struct sk_buff *skb = *in_skb; const struct b43_dma_ops *ops = ring->ops; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct b43_private_tx_info *priv_info = b43_get_priv_tx_info(info); u8 *header; int slot, old_top_slot, old_used_slots; int err; struct b43_dmadesc_generic *desc; struct b43_dmadesc_meta *meta; struct b43_dmadesc_meta *meta_hdr; - struct sk_buff *bounce_skb; u16 cookie; size_t hdrsize = b43_txhdr_size(ring->dev); @@ -1212,34 +1211,34 @@ static int dma_tx_fragment(struct b43_dm meta->skb = skb; meta->is_last_fragment = 1; + priv_info->bouncebuffer = NULL; meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); /* create a bounce buffer in zone_dma on mapping failure. */ if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { - bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); - if (!bounce_skb) { + +{ +static unsigned int count; +if (count++ < 10) + printk(KERN_DEBUG "Allocated bounce buffer\n"); +} + priv_info->bouncebuffer = kmalloc(skb->len, GFP_ATOMIC | GFP_DMA); + if (!priv_info->bouncebuffer) { ring->current_slot = old_top_slot; ring->used_slots = old_used_slots; err = -ENOMEM; goto out_unmap_hdr; } + memcpy(priv_info->bouncebuffer, skb->data, skb->len); - memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len); - memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb)); - bounce_skb->dev = skb->dev; - skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb)); - info = IEEE80211_SKB_CB(bounce_skb); - - dev_kfree_skb_any(skb); - skb = bounce_skb; - *in_skb = bounce_skb; - meta->skb = skb; - meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); + meta->dmaaddr = map_descbuffer(ring, priv_info->bouncebuffer, skb->len, 1); if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { + kfree(priv_info->bouncebuffer); + priv_info->bouncebuffer = NULL; ring->current_slot = old_top_slot; ring->used_slots = old_used_slots; err = -EIO; - goto out_free_bounce; + goto out_unmap_hdr; } } @@ -1256,8 +1255,6 @@ static int dma_tx_fragment(struct b43_dm ops->poke_tx(ring, next_slot(ring, slot)); return 0; -out_free_bounce: - dev_kfree_skb_any(skb); out_unmap_hdr: unmap_descbuffer(ring, meta_hdr->dmaaddr, hdrsize, 1); @@ -1362,11 +1359,7 @@ int b43_dma_tx(struct b43_wldev *dev, st * static, so we don't need to store it per frame. */ ring->queue_prio = skb_get_queue_mapping(skb); - /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing - * into the skb data or cb now. */ - hdr = NULL; - info = NULL; - err = dma_tx_fragment(ring, &skb); + err = dma_tx_fragment(ring, skb); if (unlikely(err == -ENOKEY)) { /* Drop this packet, as we don't have the encryption key * anymore and must not transmit it unencrypted. */ @@ -1413,12 +1406,17 @@ void b43_dma_handle_txstatus(struct b43_ B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); desc = ops->idx2desc(ring, slot, &meta); - if (meta->skb) - unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, - 1); - else + if (meta->skb) { + struct b43_private_tx_info *priv_info = + b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb)); + + unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1); + kfree(priv_info->bouncebuffer); + priv_info->bouncebuffer = NULL; + } else { unmap_descbuffer(ring, meta->dmaaddr, b43_txhdr_size(dev), 1); + } if (meta->is_last_fragment) { struct ieee80211_tx_info *info; Index: wireless-testing/drivers/net/wireless/b43/xmit.h =================================================================== --- wireless-testing.orig/drivers/net/wireless/b43/xmit.h 2009-10-09 19:50:15.000000000 +0200 +++ wireless-testing/drivers/net/wireless/b43/xmit.h 2009-11-01 16:05:46.000000000 +0100 @@ -2,6 +2,8 @@ #define B43_XMIT_H_ #include "main.h" +#include + #define _b43_declare_plcp_hdr(size) \ struct b43_plcp_hdr##size { \ @@ -332,4 +334,21 @@ static inline u8 b43_kidx_to_raw(struct return raw_kidx; } +/* struct b43_private_tx_info - TX info private to b43. + * The structure is placed in (struct ieee80211_tx_info *)->rate_driver_data + * + * @bouncebuffer: DMA Bouncebuffer (if used) + */ +struct b43_private_tx_info { + void *bouncebuffer; +}; + +static inline struct b43_private_tx_info * +b43_get_priv_tx_info(struct ieee80211_tx_info *info) +{ + BUILD_BUG_ON(sizeof(struct b43_private_tx_info) > + sizeof(info->rate_driver_data)); + return (struct b43_private_tx_info *)info->rate_driver_data; +} + #endif /* B43_XMIT_H_ */