diff options
author | Franky Lin <franky.lin@broadcom.com> | 2016-04-11 11:35:25 +0200 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2016-04-14 15:57:50 +0300 |
commit | c56caa9db8abbbfb9e31325e0897705aa897db37 (patch) | |
tree | 6857c1874dcda08e811232d1e12303f2642c9227 /drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | |
parent | 2aec2c9d42aa9ac4b31583cf4e1c7774e040e57d (diff) |
brcmfmac: screening firmware event packet
Firmware uses asynchronized events as a communication method to the
host. The event packets are marked as ETH_P_LINK_CTL protocol type. For
SDIO and PCIe bus, this kind of packets are delivered through virtual
event channel not data channel. This patch adds a screening logic to
make sure the event handler only processes the events coming from the
correct channel.
Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
Signed-off-by: Franky Lin <franky.lin@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c')
-rw-r--r-- | drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 48d7467d270e..4252fa82b89c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -1294,6 +1294,17 @@ static inline u8 brcmf_sdio_getdatoffset(u8 *swheader) return (u8)((hdrvalue & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT); } +static inline bool brcmf_sdio_fromevntchan(u8 *swheader) +{ + u32 hdrvalue; + u8 ret; + + hdrvalue = *(u32 *)swheader; + ret = (u8)((hdrvalue & SDPCM_CHANNEL_MASK) >> SDPCM_CHANNEL_SHIFT); + + return (ret == SDPCM_EVENT_CHANNEL); +} + static int brcmf_sdio_hdparse(struct brcmf_sdio *bus, u8 *header, struct brcmf_sdio_hdrinfo *rd, enum brcmf_sdio_frmtype type) @@ -1641,7 +1652,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq) pfirst->len, pfirst->next, pfirst->prev); skb_unlink(pfirst, &bus->glom); - brcmf_rx_frame(bus->sdiodev->dev, pfirst); + if (brcmf_sdio_fromevntchan(pfirst->data)) + brcmf_rx_event(bus->sdiodev->dev, pfirst); + else + brcmf_rx_frame(bus->sdiodev->dev, pfirst, + false); bus->sdcnt.rxglompkts++; } @@ -1967,18 +1982,19 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) __skb_trim(pkt, rd->len); skb_pull(pkt, rd->dat_offset); + if (pkt->len == 0) + brcmu_pkt_buf_free_skb(pkt); + else if (rd->channel == SDPCM_EVENT_CHANNEL) + brcmf_rx_event(bus->sdiodev->dev, pkt); + else + brcmf_rx_frame(bus->sdiodev->dev, pkt, + false); + /* prepare the descriptor for the next read */ rd->len = rd->len_nxtfrm << 4; rd->len_nxtfrm = 0; /* treat all packet as event if we don't know */ rd->channel = SDPCM_EVENT_CHANNEL; - - if (pkt->len == 0) { - brcmu_pkt_buf_free_skb(pkt); - continue; - } - - brcmf_rx_frame(bus->sdiodev->dev, pkt); } rxcount = maxframes - rxleft; |