diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index a2354d951dd7..59c77aa3b959 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c @@ -28,6 +28,7 @@ #include "dhd.h" #include "dhd_proto.h" #include "dhd_bus.h" +#include "fwsignal.h" #include "dhd_dbg.h" struct brcmf_proto_cdc_dcmd { @@ -71,13 +72,26 @@ struct brcmf_proto_cdc_dcmd { ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ ((idx) << BDC_FLAG2_IF_SHIFT))) +/** + * struct brcmf_proto_bdc_header - BDC header format + * + * @flags: flags contain protocol and checksum info. + * @priority: 802.1d priority and USB flow control info (bit 4:7). + * @flags2: additional flags containing dongle interface index. + * @data_offset: start of packet data. header is following by firmware signals. + */ struct brcmf_proto_bdc_header { u8 flags; - u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */ + u8 priority; u8 flags2; u8 data_offset; }; +/* + * maximum length of firmware signal data between + * the BDC header and packet data in the tx path. + */ +#define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES 12 #define RETRIES 2 /* # of retries to retrieve matching dcmd response */ #define BUS_HEADER_LEN (16+64) /* Must be atleast SDPCM_RESERVE @@ -258,7 +272,7 @@ static void pkt_set_sum_good(struct sk_buff *skb, bool x) skb->ip_summed = (x ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE); } -void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, +void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset, struct sk_buff *pktbuf) { struct brcmf_proto_bdc_header *h; @@ -266,7 +280,6 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, brcmf_dbg(CDC, "Enter\n"); /* Push BDC header used to convey priority for buses that don't */ - skb_push(pktbuf, BDC_HEADER_LEN); h = (struct brcmf_proto_bdc_header *)(pktbuf->data); @@ -277,11 +290,11 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); h->flags2 = 0; - h->data_offset = 0; + h->data_offset = offset; BDC_SET_IF_IDX(h, ifidx); } -int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, +int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, struct sk_buff *pktbuf) { struct brcmf_proto_bdc_header *h; @@ -290,8 +303,8 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, /* Pop BDC header used to convey priority for buses that don't */ - if (pktbuf->len < BDC_HEADER_LEN) { - brcmf_err("rx data too short (%d < %d)\n", + if (pktbuf->len <= BDC_HEADER_LEN) { + brcmf_dbg(INFO, "rx data too short (%d <= %d)\n", pktbuf->len, BDC_HEADER_LEN); return -EBADE; } @@ -328,7 +341,10 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, pktbuf->priority = h->priority & BDC_PRIORITY_MASK; skb_pull(pktbuf, BDC_HEADER_LEN); - skb_pull(pktbuf, h->data_offset << 2); + if (do_fws) + brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); + else + skb_pull(pktbuf, h->data_offset << 2); if (pktbuf->len == 0) return -ENODATA; @@ -350,7 +366,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr) } drvr->prot = cdc; - drvr->hdrlen += BDC_HEADER_LEN; + drvr->hdrlen += BDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN + sizeof(struct brcmf_proto_cdc_dcmd) + ROUND_UP_MARGIN; return 0; |