aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorArend van Spriel <arend@broadcom.com>2013-04-03 06:40:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-04-03 15:07:03 -0400
commitaeecc574a428a116936cadcea06b47cffad16ba1 (patch)
treeb29bc67392aa023f03ff3e36af0a25f15f3c00b8 /drivers
parenta04278096c14922bf7c701afe5c0c648d427a14d (diff)
brcmfmac: use skb_cow() in brcmf_sdbrcm_txpkt() to assure alignment
In brcmf_sdbrcm_txpkt() a new packet is allocated and used to transmit to firmware freeing up the original packet. However, that packet is still referenced in firmware-signalling so this would result in a double free. Using skb_cow() avoids this as the packet reference is unchanged. Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Piotr Haber <phaber@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c25
1 files changed, 6 insertions, 19 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 4fa19b9fd8d4..f5f04ba65e8c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -1781,7 +1781,6 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
1781 u8 *frame; 1781 u8 *frame;
1782 u16 len, pad = 0; 1782 u16 len, pad = 0;
1783 u32 swheader; 1783 u32 swheader;
1784 struct sk_buff *new;
1785 int i; 1784 int i;
1786 1785
1787 brcmf_dbg(TRACE, "Enter\n"); 1786 brcmf_dbg(TRACE, "Enter\n");
@@ -1795,26 +1794,14 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
1795 brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n", 1794 brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n",
1796 skb_headroom(pkt), pad); 1795 skb_headroom(pkt), pad);
1797 bus->sdiodev->bus_if->tx_realloc++; 1796 bus->sdiodev->bus_if->tx_realloc++;
1798 new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN); 1797 ret = skb_cow(pkt, BRCMF_SDALIGN);
1799 if (!new) { 1798 if (ret)
1800 brcmf_err("couldn't allocate new %d-byte packet\n",
1801 pkt->len + BRCMF_SDALIGN);
1802 ret = -ENOMEM;
1803 goto done; 1799 goto done;
1804 } 1800 pad = ((unsigned long)frame % BRCMF_SDALIGN);
1805
1806 pkt_align(new, pkt->len, BRCMF_SDALIGN);
1807 memcpy(new->data, pkt->data, pkt->len);
1808 brcmu_pkt_buf_free_skb(pkt);
1809 pkt = new;
1810 frame = (u8 *) (pkt->data);
1811 /* precondition: (frame % BRCMF_SDALIGN) == 0) */
1812 pad = 0;
1813 } else {
1814 skb_push(pkt, pad);
1815 frame = (u8 *) (pkt->data);
1816 memset(frame + SDPCM_HDRLEN, 0, pad);
1817 } 1801 }
1802 skb_push(pkt, pad);
1803 frame = (u8 *) (pkt->data);
1804 memset(frame, 0, pad + SDPCM_HDRLEN);
1818 } 1805 }
1819 /* precondition: pad < BRCMF_SDALIGN */ 1806 /* precondition: pad < BRCMF_SDALIGN */
1820 1807