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_sdio.c
index 35fc68be158d5b548e5c273ee85f7e3bf057a162..4ff2d3c52ee60bb2227b4f1dfdd322e05219b135 100644 (file)
@@ -94,6 +94,7 @@ struct rte_console {
 
 #include "dhd_bus.h"
 #include "dhd_dbg.h"
+#include "tracepoint.h"
 
 #define TXQLEN         2048    /* bulk tx queue length */
 #define TXHI           (TXQLEN - 256)  /* turn on flow control above TXHI */
@@ -675,7 +676,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
        u8 clkctl, clkreq, devctl;
        unsigned long timeout;
 
-       brcmf_dbg(TRACE, "Enter\n");
+       brcmf_dbg(SDIO, "Enter\n");
 
        clkctl = 0;
 
@@ -713,7 +714,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
                        devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
                        brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
                                         devctl, &err);
-                       brcmf_dbg(INFO, "CLKCTL: set PENDING\n");
+                       brcmf_dbg(SDIO, "CLKCTL: set PENDING\n");
                        bus->clkstate = CLK_PENDING;
 
                        return 0;
@@ -750,7 +751,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
 
                /* Mark clock available */
                bus->clkstate = CLK_AVAIL;
-               brcmf_dbg(INFO, "CLKCTL: turned ON\n");
+               brcmf_dbg(SDIO, "CLKCTL: turned ON\n");
 
 #if defined(DEBUG)
                if (!bus->alp_only) {
@@ -775,7 +776,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
                bus->clkstate = CLK_SDONLY;
                brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
                                 clkreq, &err);
-               brcmf_dbg(INFO, "CLKCTL: turned OFF\n");
+               brcmf_dbg(SDIO, "CLKCTL: turned OFF\n");
                if (err) {
                        brcmf_err("Failed access turning clock off: %d\n",
                                  err);
@@ -788,7 +789,7 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok)
 /* Change idle/active SD state */
 static int brcmf_sdbrcm_sdclk(struct brcmf_sdio *bus, bool on)
 {
-       brcmf_dbg(TRACE, "Enter\n");
+       brcmf_dbg(SDIO, "Enter\n");
 
        if (on)
                bus->clkstate = CLK_SDONLY;
@@ -805,7 +806,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
        uint oldstate = bus->clkstate;
 #endif                         /* DEBUG */
 
-       brcmf_dbg(TRACE, "Enter\n");
+       brcmf_dbg(SDIO, "Enter\n");
 
        /* Early exit if we're already there */
        if (bus->clkstate == target) {
@@ -849,7 +850,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok)
                break;
        }
 #ifdef DEBUG
-       brcmf_dbg(INFO, "%d -> %d\n", oldstate, bus->clkstate);
+       brcmf_dbg(SDIO, "%d -> %d\n", oldstate, bus->clkstate);
 #endif                         /* DEBUG */
 
        return 0;
@@ -862,7 +863,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
        u8 fcbits;
        int ret;
 
-       brcmf_dbg(TRACE, "Enter\n");
+       brcmf_dbg(SDIO, "Enter\n");
 
        /* Read mailbox data and ack that we did so */
        ret = r_sdreg32(bus, &hmb_data,
@@ -875,7 +876,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
 
        /* Dongle recomposed rx frames, accept them again */
        if (hmb_data & HMB_DATA_NAKHANDLED) {
-               brcmf_dbg(INFO, "Dongle reports NAK handled, expect rtx of %d\n",
+               brcmf_dbg(SDIO, "Dongle reports NAK handled, expect rtx of %d\n",
                          bus->rx_seq);
                if (!bus->rxskip)
                        brcmf_err("unexpected NAKHANDLED!\n");
@@ -896,7 +897,7 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus)
                                  "expecting %d\n",
                                  bus->sdpcm_ver, SDPCM_PROT_VERSION);
                else
-                       brcmf_dbg(INFO, "Dongle ready, protocol version %d\n",
+                       brcmf_dbg(SDIO, "Dongle ready, protocol version %d\n",
                                  bus->sdpcm_ver);
        }
 
@@ -970,7 +971,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
        if (!retries)
                brcmf_err("count never zeroed: last 0x%04x\n", lastrbc);
        else
-               brcmf_dbg(INFO, "flush took %d iterations\n", 0xffff - retries);
+               brcmf_dbg(SDIO, "flush took %d iterations\n", 0xffff - retries);
 
        if (rtx) {
                bus->sdcnt.rxrtx++;
@@ -1173,7 +1174,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
        /* If packets, issue read(s) and send up packet chain */
        /* Return sequence numbers consumed? */
 
-       brcmf_dbg(TRACE, "start: glomd %p glom %p\n",
+       brcmf_dbg(SDIO, "start: glomd %p glom %p\n",
                  bus->glomd, skb_peek(&bus->glom));
 
        /* If there's a descriptor, generate the packet chain */
@@ -1546,7 +1547,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
        struct sk_buff_head pktlist;    /* needed for bus interface */
        u16 pad;                /* Number of pad bytes to read */
        uint rxleft = 0;        /* Remaining number of frames allowed */
-       int sdret;              /* Return code from calls */
+       int ret;                /* Return code from calls */
        uint rxcount = 0;       /* Total frames read */
        struct brcmf_sdio_read *rd = &bus->cur_read, rd_new;
        u8 head_read = 0;
@@ -1577,15 +1578,15 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                /* read header first for unknow frame length */
                sdio_claim_host(bus->sdiodev->func[1]);
                if (!rd->len) {
-                       sdret = brcmf_sdcard_recv_buf(bus->sdiodev,
+                       ret = brcmf_sdcard_recv_buf(bus->sdiodev,
                                                      bus->sdiodev->sbwad,
                                                      SDIO_FUNC_2, F2SYNC,
                                                      bus->rxhdr,
                                                      BRCMF_FIRSTREAD);
                        bus->sdcnt.f2rxhdrs++;
-                       if (sdret < 0) {
+                       if (ret < 0) {
                                brcmf_err("RXHEADER FAILED: %d\n",
-                                         sdret);
+                                         ret);
                                bus->sdcnt.rx_hdrfail++;
                                brcmf_sdbrcm_rxfail(bus, true, true);
                                sdio_release_host(bus->sdiodev->func[1]);
@@ -1637,14 +1638,14 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
                skb_pull(pkt, head_read);
                pkt_align(pkt, rd->len_left, BRCMF_SDALIGN);
 
-               sdret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
+               ret = brcmf_sdcard_recv_pkt(bus->sdiodev, bus->sdiodev->sbwad,
                                              SDIO_FUNC_2, F2SYNC, pkt);
                bus->sdcnt.f2rxdata++;
                sdio_release_host(bus->sdiodev->func[1]);
 
-               if (sdret < 0) {
+               if (ret < 0) {
                        brcmf_err("read %d bytes from channel %d failed: %d\n",
-                                 rd->len, rd->channel, sdret);
+                                 rd->len, rd->channel, ret);
                        brcmu_pkt_buf_free_skb(pkt);
                        sdio_claim_host(bus->sdiodev->func[1]);
                        brcmf_sdbrcm_rxfail(bus, true,
@@ -1775,13 +1776,12 @@ brcmf_sdbrcm_wait_event_wakeup(struct brcmf_sdio *bus)
 /* Writes a HW/SW header into the packet and sends it. */
 /* Assumes: (a) header space already there, (b) caller holds lock */
 static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
-                             uint chan, bool free_pkt)
+                             uint chan)
 {
        int ret;
        u8 *frame;
        u16 len, pad = 0;
        u32 swheader;
-       struct sk_buff *new;
        int i;
 
        brcmf_dbg(TRACE, "Enter\n");
@@ -1795,30 +1795,14 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
                        brcmf_dbg(INFO, "insufficient headroom %d for %d pad\n",
                                  skb_headroom(pkt), pad);
                        bus->sdiodev->bus_if->tx_realloc++;
-                       new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN);
-                       if (!new) {
-                               brcmf_err("couldn't allocate new %d-byte packet\n",
-                                         pkt->len + BRCMF_SDALIGN);
-                               ret = -ENOMEM;
+                       ret = skb_cow(pkt, BRCMF_SDALIGN);
+                       if (ret)
                                goto done;
-                       }
-
-                       pkt_align(new, pkt->len, BRCMF_SDALIGN);
-                       memcpy(new->data, pkt->data, pkt->len);
-                       if (free_pkt)
-                               brcmu_pkt_buf_free_skb(pkt);
-                       /* free the pkt if canned one is not used */
-                       free_pkt = true;
-                       pkt = new;
-                       frame = (u8 *) (pkt->data);
-                       /* precondition: (frame % BRCMF_SDALIGN) == 0) */
-                       pad = 0;
-               } else {
-                       skb_push(pkt, pad);
-                       frame = (u8 *) (pkt->data);
-                       /* precondition: pad + SDPCM_HDRLEN <= pkt->len */
-                       memset(frame, 0, pad + SDPCM_HDRLEN);
+                       pad = ((unsigned long)frame % BRCMF_SDALIGN);
                }
+               skb_push(pkt, pad);
+               frame = (u8 *) (pkt->data);
+               memset(frame, 0, pad + SDPCM_HDRLEN);
        }
        /* precondition: pad < BRCMF_SDALIGN */
 
@@ -1833,8 +1817,8 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
            (((pad +
               SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
 
-       put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
-       put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+       *(((__le32 *) frame) + 1) = cpu_to_le32(swheader);
+       *(((__le32 *) frame) + 2) = 0;
 
 #ifdef DEBUG
        tx_packets[pkt->priority]++;
@@ -1900,11 +1884,7 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt,
 done:
        /* restore pkt buffer pointer before calling tx complete routine */
        skb_pull(pkt, SDPCM_HDRLEN + pad);
-       brcmf_txcomplete(bus->sdiodev->dev, pkt, ret != 0);
-
-       if (free_pkt)
-               brcmu_pkt_buf_free_skb(pkt);
-
+       brcmf_txcomplete(bus->sdiodev->dev, pkt, ret == 0);
        return ret;
 }
 
@@ -1932,7 +1912,7 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes)
                spin_unlock_bh(&bus->txqlock);
                datalen = pkt->len - SDPCM_HDRLEN;
 
-               ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true);
+               ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL);
 
                /* In poll mode, need to check for other events */
                if (!bus->intr && cnt) {
@@ -2138,7 +2118,7 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
                        bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN;
                }
 
-               brcmf_dbg(INFO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
+               brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
                          devctl, clkctl);
 
                if (SBSDIO_HTAV(clkctl)) {
@@ -2314,6 +2294,15 @@ static void brcmf_sdbrcm_dpc(struct brcmf_sdio *bus)
        }
 }
 
+static struct pktq *brcmf_sdbrcm_bus_gettxq(struct device *dev)
+{
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+       struct brcmf_sdio *bus = sdiodev->bus;
+
+       return &bus->txq;
+}
+
 static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
 {
        int ret = -EBADE;
@@ -2343,7 +2332,6 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
        if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) {
                skb_pull(pkt, SDPCM_HDRLEN);
                brcmf_txcomplete(bus->sdiodev->dev, pkt, false);
-               brcmu_pkt_buf_free_skb(pkt);
                brcmf_err("out of bus->txq !!!\n");
                ret = -ENOSR;
        } else {
@@ -2400,7 +2388,7 @@ brcmf_sdbrcm_membytes(struct brcmf_sdio *bus, bool write, u32 address, u8 *data,
 
        /* Do the transfer(s) */
        while (size) {
-               brcmf_dbg(INFO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
+               brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
                          write ? "write" : "read", dsize,
                          sdaddr, address & SBSDIO_SBWINDOW_MASK);
                bcmerror = brcmf_sdcard_rwdata(bus->sdiodev, write,
@@ -2633,10 +2621,10 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
                                                 msecs_to_jiffies(2000));
 
                if (!bus->ctrl_frame_stat) {
-                       brcmf_dbg(INFO, "ctrl_frame_stat == false\n");
+                       brcmf_dbg(SDIO, "ctrl_frame_stat == false\n");
                        ret = 0;
                } else {
-                       brcmf_dbg(INFO, "ctrl_frame_stat == true\n");
+                       brcmf_dbg(SDIO, "ctrl_frame_stat == true\n");
                        ret = -1;
                }
        }
@@ -2707,7 +2695,7 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
 
        addr = le32_to_cpu(addr_le);
 
-       brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr);
+       brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr);
 
        /*
         * Check if addr is valid.
@@ -2734,8 +2722,8 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus,
        sh->console_addr = le32_to_cpu(sh_le.console_addr);
        sh->msgtrace_addr = le32_to_cpu(sh_le.msgtrace_addr);
 
-       if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
-               brcmf_err("sdpcm_shared version mismatch: dhd %d dongle %d\n",
+       if ((sh->flags & SDPCM_SHARED_VERSION_MASK) > SDPCM_SHARED_VERSION) {
+               brcmf_err("sdpcm shared version unsupported: dhd %d dongle %d\n",
                          SDPCM_SHARED_VERSION,
                          sh->flags & SDPCM_SHARED_VERSION_MASK);
                return -EPROTO;
@@ -2817,21 +2805,18 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
        int error, res;
        char buf[350];
        struct brcmf_trap_info tr;
-       int nbytes;
        loff_t pos = 0;
 
-       if ((sh->flags & SDPCM_SHARED_TRAP) == 0)
+       if ((sh->flags & SDPCM_SHARED_TRAP) == 0) {
+               brcmf_dbg(INFO, "no trap in firmware\n");
                return 0;
+       }
 
        error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr,
                                      sizeof(struct brcmf_trap_info));
        if (error < 0)
                return error;
 
-       nbytes = brcmf_sdio_dump_console(bus, sh, data, count);
-       if (nbytes < 0)
-               return nbytes;
-
        res = scnprintf(buf, sizeof(buf),
                        "dongle trap info: type 0x%x @ epc 0x%08x\n"
                        "  cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
@@ -2847,12 +2832,7 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
                        le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
                        le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
 
-       error = simple_read_from_buffer(data+nbytes, count, &pos, buf, res);
-       if (error < 0)
-               return error;
-
-       nbytes += error;
-       return nbytes;
+       return simple_read_from_buffer(data, count, &pos, buf, res);
 }
 
 static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
@@ -2934,14 +2914,20 @@ static int brcmf_sdbrcm_died_dump(struct brcmf_sdio *bus, char __user *data,
        error = brcmf_sdio_assert_info(bus, &sh, data, count);
        if (error < 0)
                goto done;
-
        nbytes = error;
-       error = brcmf_sdio_trap_info(bus, &sh, data, count);
+
+       error = brcmf_sdio_trap_info(bus, &sh, data+nbytes, count);
+       if (error < 0)
+               goto done;
+       nbytes += error;
+
+       error = brcmf_sdio_dump_console(bus, &sh, data+nbytes, count);
        if (error < 0)
                goto done;
+       nbytes += error;
 
-       error += nbytes;
-       *ppos += error;
+       error = nbytes;
+       *ppos += nbytes;
 done:
        return error;
 }
@@ -3856,6 +3842,7 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
        .txdata = brcmf_sdbrcm_bus_txdata,
        .txctl = brcmf_sdbrcm_bus_txctl,
        .rxctl = brcmf_sdbrcm_bus_rxctl,
+       .gettxq = brcmf_sdbrcm_bus_gettxq,
 };
 
 void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev)