From 29e04ae31ddb08794afbbef3cb72249d3804f47e Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Wed, 3 Apr 2013 12:40:34 +0200 Subject: [PATCH] brcmfmac: allow stopping netif queue for different reasons Currently, the netif queue is only stopped when the bus interface is giving a push back. This will change soon so prepare the driver by adding a stop reason and stop/resume the queue accordingly. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Hante Meuleman Reviewed-by: Piotr Haber Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 17 +++++++++++ .../wireless/brcm80211/brcmfmac/dhd_linux.c | 29 ++++++++++++++----- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 64006edeb430..af307c101c94 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -554,6 +554,19 @@ struct brcmf_if_event { struct brcmf_cfg80211_vif; struct brcmf_fws_mac_descriptor; +/** + * enum brcmf_netif_stop_reason - reason for stopping netif queue. + * + * @BRCMF_NETIF_STOP_REASON_FWS_FC: + * netif stopped due to firmware signalling flow control. + * @BRCMF_NETIF_STOP_REASON_BLOCK_BUS: + * netif stopped due to bus blocking. + */ +enum brcmf_netif_stop_reason { + BRCMF_NETIF_STOP_REASON_FWS_FC = 1, + BRCMF_NETIF_STOP_REASON_BLOCK_BUS = 2 +}; + /** * struct brcmf_if - interface control information. * @@ -567,6 +580,7 @@ struct brcmf_fws_mac_descriptor; * @ifidx: interface index in device firmware. * @bssidx: index of bss associated with this interface. * @mac_addr: assigned mac address. + * @netif_stop: bitmap indicates reason why netif queues are stopped. * @pend_8021x_cnt: tracks outstanding number of 802.1x frames. * @pend_8021x_wait: used for signalling change in count. */ @@ -581,6 +595,7 @@ struct brcmf_if { int ifidx; s32 bssidx; u8 mac_addr[ETH_ALEN]; + u8 netif_stop; atomic_t pend_8021x_cnt; wait_queue_head_t pend_8021x_wait; }; @@ -605,6 +620,8 @@ extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, char *name, u8 *mac_addr); extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); +void brcmf_txflowblock_if(struct brcmf_if *ifp, + enum brcmf_netif_stop_reason reason, bool state); extern u32 brcmf_get_chip_info(struct brcmf_if *ifp); #endif /* _BRCMF_H_ */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index a08db02537fc..3ba9e1049f3b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -248,9 +248,27 @@ done: return NETDEV_TX_OK; } +void brcmf_txflowblock_if(struct brcmf_if *ifp, + enum brcmf_netif_stop_reason reason, bool state) +{ + if (!ifp) + return; + + brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n", + ifp->bssidx, ifp->netif_stop, reason, state); + if (state) { + if (!ifp->netif_stop) + netif_stop_queue(ifp->ndev); + ifp->netif_stop |= reason; + } else { + ifp->netif_stop &= ~reason; + if (!ifp->netif_stop) + netif_wake_queue(ifp->ndev); + } +} + void brcmf_txflowblock(struct device *dev, bool state) { - struct net_device *ndev; struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; int i; @@ -258,13 +276,8 @@ void brcmf_txflowblock(struct device *dev, bool state) brcmf_dbg(TRACE, "Enter\n"); for (i = 0; i < BRCMF_MAX_IFS; i++) - if (drvr->iflist[i]) { - ndev = drvr->iflist[i]->ndev; - if (state) - netif_stop_queue(ndev); - else - netif_wake_queue(ndev); - } + brcmf_txflowblock_if(drvr->iflist[i], + BRCMF_NETIF_STOP_REASON_BLOCK_BUS, state); } void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)