brcmfmac: SDIO: avoid using bus state for private states.
authorHante Meuleman <meuleman@broadcom.com>
Sun, 25 Jan 2015 19:31:35 +0000 (20:31 +0100)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 29 Jan 2015 07:59:03 +0000 (09:59 +0200)
Each bus driver is maintaing an exported bus state indicating
if upper layers can or cannot send data. SDIO is using this state
also for more private states. This makes handling the states and
state changes complex. This patch minimises the exposed states
and makes SDIO keep track of an internal state where necessary.

Reviewed-by: Arend Van Spriel <arend@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Daniel (Deognyoun) Kim <dekim@broadcom.com>
Signed-off-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/brcm80211/brcmfmac/bus.h
drivers/net/wireless/brcm80211/brcmfmac/core.c
drivers/net/wireless/brcm80211/brcmfmac/fwil.c
drivers/net/wireless/brcm80211/brcmfmac/pcie.c
drivers/net/wireless/brcm80211/brcmfmac/sdio.c
drivers/net/wireless/brcm80211/brcmfmac/sdio.h
drivers/net/wireless/brcm80211/brcmfmac/usb.c

index 9afaeb6d2af5df6821ecd74aa74d270f4866df63..7944224e3fc90140deb61ae061f4296a555ac526 100644 (file)
@@ -269,6 +269,12 @@ static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn,
        return ret;
 }
 
+static void brcmf_sdiod_nomedium_state(struct brcmf_sdio_dev *sdiodev)
+{
+       sdiodev->state = BRCMF_STATE_NOMEDIUM;
+       brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_DOWN);
+}
+
 static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
                                   u8 regsz, void *data, bool write)
 {
@@ -276,7 +282,7 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
        s32 retry = 0;
        int ret;
 
-       if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM)
+       if (sdiodev->state == BRCMF_STATE_NOMEDIUM)
                return -ENOMEDIUM;
 
        /*
@@ -302,7 +308,7 @@ static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
                 retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
 
        if (ret == -ENOMEDIUM)
-               brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM);
+               brcmf_sdiod_nomedium_state(sdiodev);
        else if (ret != 0) {
                /*
                 * SleepCSR register access can fail when
@@ -325,7 +331,7 @@ brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
        int err = 0, i;
        u8 addr[3];
 
-       if (sdiodev->bus_if->state == BRCMF_BUS_NOMEDIUM)
+       if (sdiodev->state == BRCMF_STATE_NOMEDIUM)
                return -ENOMEDIUM;
 
        addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK;
@@ -454,7 +460,7 @@ static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
                err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr,
                                  req_sz);
        if (err == -ENOMEDIUM)
-               brcmf_bus_change_state(sdiodev->bus_if, BRCMF_BUS_NOMEDIUM);
+               brcmf_sdiod_nomedium_state(sdiodev);
        return err;
 }
 
@@ -589,8 +595,7 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
 
                ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
                if (ret == -ENOMEDIUM) {
-                       brcmf_bus_change_state(sdiodev->bus_if,
-                                              BRCMF_BUS_NOMEDIUM);
+                       brcmf_sdiod_nomedium_state(sdiodev);
                        break;
                } else if (ret != 0) {
                        brcmf_err("CMD53 sg block %s failed %d\n",
index ef344e47218a3ab153f86fba35f510c6dc6cd809..55d36ff5439d91a3b085a028dde1ce94cc82f97c 100644 (file)
 
 /* The level of bus communication with the dongle */
 enum brcmf_bus_state {
-       BRCMF_BUS_UNKNOWN,      /* Not determined yet */
-       BRCMF_BUS_NOMEDIUM,     /* No medium access to dongle */
        BRCMF_BUS_DOWN,         /* Not ready for frame transfers */
-       BRCMF_BUS_LOAD,         /* Download access only (CPU reset) */
-       BRCMF_BUS_DATA          /* Ready for frame transfers */
+       BRCMF_BUS_UP            /* Ready for frame transfers */
 };
 
 /* The level of bus communication with the dongle */
@@ -188,18 +185,9 @@ void brcmf_bus_wowl_config(struct brcmf_bus *bus, bool enabled)
                bus->ops->wowl_config(bus->dev, enabled);
 }
 
-static inline bool brcmf_bus_ready(struct brcmf_bus *bus)
-{
-       return bus->state == BRCMF_BUS_LOAD || bus->state == BRCMF_BUS_DATA;
-}
-
 static inline void brcmf_bus_change_state(struct brcmf_bus *bus,
                                          enum brcmf_bus_state new_state)
 {
-       /* NOMEDIUM is permanent */
-       if (bus->state == BRCMF_BUS_NOMEDIUM)
-               return;
-
        brcmf_dbg(TRACE, "%d -> %d\n", bus->state, new_state);
        bus->state = new_state;
 }
index e2a9e33f71ab0fbf360dbc2f959c7cb03352a526..ff8c97ba4bc5ddd326038fbf08196a36e796df7b 100644 (file)
@@ -197,7 +197,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
        brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx);
 
        /* Can the device send data? */
-       if (drvr->bus_if->state != BRCMF_BUS_DATA) {
+       if (drvr->bus_if->state != BRCMF_BUS_UP) {
                brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state);
                netif_stop_queue(ndev);
                dev_kfree_skb(skb);
@@ -637,7 +637,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
        brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
 
        /* If bus is not ready, can't continue */
-       if (bus_if->state != BRCMF_BUS_DATA) {
+       if (bus_if->state != BRCMF_BUS_UP) {
                brcmf_err("failed bus is not ready\n");
                return -EAGAIN;
        }
@@ -964,7 +964,7 @@ int brcmf_bus_start(struct device *dev)
                p2p_ifp = NULL;
 
        /* signal bus ready */
-       brcmf_bus_change_state(bus_if, BRCMF_BUS_DATA);
+       brcmf_bus_change_state(bus_if, BRCMF_BUS_UP);
 
        /* Bus is ready, do any initialization */
        ret = brcmf_c_preinit_dcmds(ifp);
index 03f2c406a17bb034f9e7078f8c5c65344f316a9b..dcfa0bb149ce8eb778c68f7071f1b45c11899be2 100644 (file)
@@ -109,7 +109,7 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
        struct brcmf_pub *drvr = ifp->drvr;
        s32 err;
 
-       if (drvr->bus_if->state != BRCMF_BUS_DATA) {
+       if (drvr->bus_if->state != BRCMF_BUS_UP) {
                brcmf_err("bus is down. we have nothing to do.\n");
                return -EIO;
        }
index e91fa9a2c8855e37a315698d4a86c062edbfdffa..61c053a729be01b752101dab3db55cf1e6728e9b 100644 (file)
@@ -1828,7 +1828,7 @@ static int brcmf_pcie_resume(struct pci_dev *pdev)
                                goto cleanup;
                        brcmf_dbg(PCIE, "Hot resume, continue....\n");
                        brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
-                       brcmf_bus_change_state(bus, BRCMF_BUS_DATA);
+                       brcmf_bus_change_state(bus, BRCMF_BUS_UP);
                        brcmf_pcie_intr_enable(devinfo);
                        return 0;
                }
index 488a0f648e185376601573d48e37a9e02754a87c..5e9d20853bbb8d569d03f231276c99f2d95833c2 100644 (file)
@@ -1909,7 +1909,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
        bus->rxpending = true;
 
        for (rd->seq_num = bus->rx_seq, rxleft = maxframes;
-            !bus->rxskip && rxleft && brcmf_bus_ready(bus->sdiodev->bus_if);
+            !bus->rxskip && rxleft && bus->sdiodev->state == BRCMF_STATE_DATA;
             rd->seq_num++, rxleft--) {
 
                /* Handle glomming separately */
@@ -2415,7 +2415,7 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes)
        }
 
        /* Deflow-control stack if needed */
-       if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) &&
+       if ((bus->sdiodev->state == BRCMF_STATE_DATA) &&
            bus->txoff && (pktq_len(&bus->txq) < TXLOW)) {
                bus->txoff = false;
                brcmf_txflowblock(bus->sdiodev->dev, false);
@@ -2503,7 +2503,7 @@ static void brcmf_sdio_bus_stop(struct device *dev)
                bus->watchdog_tsk = NULL;
        }
 
-       if (bus_if->state == BRCMF_BUS_DOWN) {
+       if (sdiodev->state != BRCMF_STATE_NOMEDIUM) {
                sdio_claim_host(sdiodev->func[1]);
 
                /* Enable clock for device interrupts */
@@ -2756,7 +2756,7 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
                brcmf_sdio_sendfromq(bus, framecnt);
        }
 
-       if (!brcmf_bus_ready(bus->sdiodev->bus_if) || (err != 0)) {
+       if ((bus->sdiodev->state != BRCMF_STATE_DATA) || (err != 0)) {
                brcmf_err("failed backplane access over SDIO, halting operation\n");
                atomic_set(&bus->intstatus, 0);
        } else if (atomic_read(&bus->intstatus) ||
@@ -3411,8 +3411,8 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
                goto err;
        }
 
-       /* Allow HT Clock now that the ARM is running. */
-       brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_LOAD);
+       /* Allow full data communication using DPC from now on. */
+       bus->sdiodev->state = BRCMF_STATE_DATA;
        bcmerror = 0;
 
 err:
@@ -3558,7 +3558,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus)
                return;
        }
 
-       if (!brcmf_bus_ready(bus->sdiodev->bus_if)) {
+       if (bus->sdiodev->state != BRCMF_STATE_DATA) {
                brcmf_err("bus is down. we have nothing to do\n");
                return;
        }
@@ -3581,10 +3581,6 @@ void brcmf_sdio_isr(struct brcmf_sdio *bus)
 
 static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
 {
-#ifdef DEBUG
-       struct brcmf_bus *bus_if = dev_get_drvdata(bus->sdiodev->dev);
-#endif /* DEBUG */
-
        brcmf_dbg(TIMER, "Enter\n");
 
        /* Poll period: check device if appropriate. */
@@ -3628,7 +3624,7 @@ static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus)
        }
 #ifdef DEBUG
        /* Poll for console output periodically */
-       if (bus_if && bus_if->state == BRCMF_BUS_DATA &&
+       if (bus->sdiodev->state == BRCMF_STATE_DATA &&
            bus->console_interval != 0) {
                bus->console.count += BRCMF_WD_POLL_MS;
                if (bus->console.count >= bus->console_interval) {
@@ -3869,11 +3865,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdio *bus)
                goto fail;
        }
 
-       /* SDIO register access works so moving
-        * state from UNKNOWN to DOWN.
-        */
-       brcmf_bus_change_state(bus->sdiodev->bus_if, BRCMF_BUS_DOWN);
-
        bus->ci = brcmf_chip_attach(bus->sdiodev, &brcmf_sdio_buscore_ops);
        if (IS_ERR(bus->ci)) {
                brcmf_err("brcmf_chip_attach failed!\n");
@@ -4007,18 +3998,16 @@ static void brcmf_sdio_firmware_callback(struct device *dev,
 
        brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev));
 
-       /* try to download image and nvram to the dongle */
-       if (bus_if->state == BRCMF_BUS_DOWN) {
-               bus->alp_only = true;
-               err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
-               if (err)
-                       goto fail;
-               bus->alp_only = false;
-       }
-
        if (!bus_if->drvr)
                return;
 
+       /* try to download image and nvram to the dongle */
+       bus->alp_only = true;
+       err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
+       if (err)
+               goto fail;
+       bus->alp_only = false;
+
        /* Start the watchdog timer */
        bus->sdcnt.tickcnt = 0;
        brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
@@ -4254,7 +4243,7 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
                        destroy_workqueue(bus->brcmf_wq);
 
                if (bus->ci) {
-                       if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
+                       if (bus->sdiodev->state != BRCMF_STATE_NOMEDIUM) {
                                sdio_claim_host(bus->sdiodev->func[1]);
                                brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
                                /* Leave the device in state where it is
@@ -4289,7 +4278,7 @@ void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick)
        }
 
        /* don't start the wd until fw is loaded */
-       if (bus->sdiodev->bus_if->state != BRCMF_BUS_DATA)
+       if (bus->sdiodev->state != BRCMF_STATE_DATA)
                return;
 
        if (wdtick) {
index 9c5d42d20b4891e3eec059a092ad7118af344587..ec2586a8425cf31d4f84bc053afb0e4a2c3ab5ea 100644 (file)
 /* watchdog polling interval in ms */
 #define BRCMF_WD_POLL_MS       10
 
+/* The state of the bus */
+enum brcmf_sdio_state {
+       BRCMF_STATE_DOWN,       /* Device available, still initialising */
+       BRCMF_STATE_DATA,       /* Ready for data transfers, DPC enabled */
+       BRCMF_STATE_NOMEDIUM    /* No medium access to dongle possible */
+};
+
 struct brcmf_sdreg {
        int func;
        int offset;
@@ -187,6 +194,7 @@ struct brcmf_sdio_dev {
        char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
        char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
        bool wowl_enabled;
+       enum brcmf_sdio_state state;
 };
 
 /* sdio core registers */
index 4572defc280fa42e7100115540a32581912bf2e2..7e0c9e2fa7f6498058cb7a5ce9feb165afb04dfb 100644 (file)
@@ -576,7 +576,7 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
                brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DOWN);
        } else if (state == BRCMFMAC_USB_STATE_UP) {
                brcmf_dbg(USB, "DBUS is up\n");
-               brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DATA);
+               brcmf_bus_change_state(bcmf_bus, BRCMF_BUS_UP);
        } else {
                brcmf_dbg(USB, "DBUS current state=%d\n", state);
        }