Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / brcm80211 / brcmfmac / dhd_cdc.c
index a2354d951dd7b5ae823a25b1dcd046afa9c617f8..59c77aa3b9597894385a9b8c4c8d72aa5f6db84f 100644 (file)
@@ -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;