brcmfmac: Make FWS queueing configurable.
authorHante Meuleman <meuleman@broadcom.com>
Mon, 12 May 2014 08:47:30 +0000 (10:47 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 13 May 2014 19:56:46 +0000 (15:56 -0400)
FWS is always queuing frames and using a worker for de-queueing,
this is not always efficient for all bus layer. For example SDIO
has an internal queue and worker making the queueing of FWS
unnecessary. Make it possible to bypass the worker if fws mode
is none using a bus interface configuration. For USB bus layer
this configuration is set true to have fws provide queueing
regardless the fws mode.

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: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
drivers/net/wireless/brcm80211/brcmfmac/usb.c

index c4535616064e8389125b238a50fcc74d3c6d47da..c5dcd82e884bf74a8bebb862519219870cc0f38d 100644 (file)
@@ -99,6 +99,7 @@ struct brcmf_bus {
        unsigned long tx_realloc;
        u32 chip;
        u32 chiprev;
+       bool always_use_fws_queue;
 
        struct brcmf_bus_ops *ops;
 };
index b58a97aa659a644d622c581f9201a531bb66f0e5..699908de314a94ff3f382f62536756b3f4a5eed2 100644 (file)
@@ -476,6 +476,7 @@ struct brcmf_fws_info {
        bool bus_flow_blocked;
        bool creditmap_received;
        u8 mode;
+       bool avoid_queueing;
 };
 
 /*
@@ -1872,6 +1873,13 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
 
        drvr->tx_multicast += !!multicast;
 
+       if (fws->avoid_queueing) {
+               rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
+               if (rc < 0)
+                       brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
+               return rc;
+       }
+
        /* set control buffer information */
        skcb->if_flags = 0;
        skcb->state = BRCMF_FWS_SKBSTATE_NEW;
@@ -2030,6 +2038,13 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
        fws->drvr = drvr;
        fws->fcmode = fcmode;
 
+       if ((drvr->bus_if->always_use_fws_queue == false) &&
+           (fcmode == BRCMF_FWS_FCMODE_NONE)) {
+               fws->avoid_queueing = true;
+               brcmf_dbg(INFO, "FWS queueing will be avoided\n");
+               return 0;
+       }
+
        fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq");
        if (fws->fws_wq == NULL) {
                brcmf_err("workqueue creation failed\n");
index 24f65cd538595a84e6c66b62b8698bbc97456288..3ce0e7cfd0271513a13fa8897ecb27e42fcbb8d7 100644 (file)
@@ -1254,6 +1254,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
        bus->chip = bus_pub->devid;
        bus->chiprev = bus_pub->chiprev;
        bus->proto_type = BRCMF_PROTO_BCDC;
+       bus->always_use_fws_queue = true;
 
        /* Attach to the common driver interface */
        ret = brcmf_attach(dev);