Commit 1eb43018 authored by Arend van Spriel's avatar Arend van Spriel Committed by John W. Linville

brcmfmac: fix txglomming scatter-gather packet transfers

The driver concatenates multiple packets in one MMC transfer. For
scatter-gather to work the total length need to be multiple of 512
bytes. A pre-allocated buffer was used to add padding to accomplish
that. However, the length was not properly set and it was freed after
the first transfer causing a crash.
Reviewed-by: default avatarDaniel (Deognyoun) Kim <dekim@broadcom.com>
Reviewed-by: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarFranky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 21f8aaee
...@@ -457,7 +457,6 @@ struct brcmf_sdio { ...@@ -457,7 +457,6 @@ struct brcmf_sdio {
u8 tx_hdrlen; /* sdio bus header length for tx packet */ u8 tx_hdrlen; /* sdio bus header length for tx packet */
bool txglom; /* host tx glomming enable flag */ bool txglom; /* host tx glomming enable flag */
struct sk_buff *txglom_sgpad; /* scatter-gather padding buffer */
u16 head_align; /* buffer pointer alignment */ u16 head_align; /* buffer pointer alignment */
u16 sgentry_align; /* scatter-gather buffer alignment */ u16 sgentry_align; /* scatter-gather buffer alignment */
}; };
...@@ -1944,9 +1943,8 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus, ...@@ -1944,9 +1943,8 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus,
if (lastfrm && chain_pad) if (lastfrm && chain_pad)
tail_pad += blksize - chain_pad; tail_pad += blksize - chain_pad;
if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) { if (skb_tailroom(pkt) < tail_pad && pkt->len > blksize) {
pkt_pad = bus->txglom_sgpad; pkt_pad = brcmu_pkt_buf_get_skb(tail_pad + tail_chop +
if (pkt_pad == NULL) bus->head_align);
brcmu_pkt_buf_get_skb(tail_pad + tail_chop);
if (pkt_pad == NULL) if (pkt_pad == NULL)
return -ENOMEM; return -ENOMEM;
ret = brcmf_sdio_txpkt_hdalign(bus, pkt_pad); ret = brcmf_sdio_txpkt_hdalign(bus, pkt_pad);
...@@ -1957,6 +1955,7 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus, ...@@ -1957,6 +1955,7 @@ static int brcmf_sdio_txpkt_prep_sg(struct brcmf_sdio *bus,
tail_chop); tail_chop);
*(u32 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop; *(u32 *)(pkt_pad->cb) = ALIGN_SKB_FLAG + tail_chop;
skb_trim(pkt, pkt->len - tail_chop); skb_trim(pkt, pkt->len - tail_chop);
skb_trim(pkt_pad, tail_pad + tail_chop);
__skb_queue_after(pktq, pkt, pkt_pad); __skb_queue_after(pktq, pkt, pkt_pad);
} else { } else {
ntail = pkt->data_len + tail_pad - ntail = pkt->data_len + tail_pad -
...@@ -2011,7 +2010,7 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq, ...@@ -2011,7 +2010,7 @@ brcmf_sdio_txpkt_prep(struct brcmf_sdio *bus, struct sk_buff_head *pktq,
return ret; return ret;
head_pad = (u16)ret; head_pad = (u16)ret;
if (head_pad) if (head_pad)
memset(pkt_next->data, 0, head_pad + bus->tx_hdrlen); memset(pkt_next->data + bus->tx_hdrlen, 0, head_pad);
total_len += pkt_next->len; total_len += pkt_next->len;
...@@ -3486,10 +3485,6 @@ static int brcmf_sdio_bus_preinit(struct device *dev) ...@@ -3486,10 +3485,6 @@ static int brcmf_sdio_bus_preinit(struct device *dev)
bus->txglom = false; bus->txglom = false;
value = 1; value = 1;
pad_size = bus->sdiodev->func[2]->cur_blksize << 1; pad_size = bus->sdiodev->func[2]->cur_blksize << 1;
bus->txglom_sgpad = brcmu_pkt_buf_get_skb(pad_size);
if (!bus->txglom_sgpad)
brcmf_err("allocating txglom padding skb failed, reduced performance\n");
err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom", err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom",
&value, sizeof(u32)); &value, sizeof(u32));
if (err < 0) { if (err < 0) {
...@@ -4053,7 +4048,6 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) ...@@ -4053,7 +4048,6 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
brcmf_sdio_chip_detach(&bus->ci); brcmf_sdio_chip_detach(&bus->ci);
} }
brcmu_pkt_buf_free_skb(bus->txglom_sgpad);
kfree(bus->rxbuf); kfree(bus->rxbuf);
kfree(bus->hdrbuf); kfree(bus->hdrbuf);
kfree(bus); kfree(bus);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment