summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c12
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c34
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h1
3 files changed, 33 insertions, 14 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 0299ab6731b2..d37620e93e61 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -388,11 +388,13 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
- /* await txstatus signal for firmware is active */
- if (success && brcmf_fws_fc_active(drvr->fws))
- return;
-
- brcmf_txfinalize(drvr, txp, success);
+ /* await txstatus signal for firmware if active */
+ if (brcmf_fws_fc_active(drvr->fws)) {
+ if (!success)
+ brcmf_fws_bustxfail(drvr->fws, txp);
+ } else {
+ brcmf_txfinalize(drvr, txp, success);
+ }
}
static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 9389bf7b7696..eb63419cece0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -810,20 +810,12 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
}
static int
-brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
+brcmf_fws_txstatus_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot)
{
- u8 flags;
- u32 status;
- u32 hslot;
int ret;
struct sk_buff *skb;
struct brcmf_fws_mac_descriptor *entry = NULL;
- status = le32_to_cpu(*(__le32 *)data);
- flags = brcmf_txstatus_get_field(status, FLAGS);
- hslot = brcmf_txstatus_get_field(status, HSLOT);
- fws->stats.txs_indicate++;
-
brcmf_dbg(TRACE, "status: flags=0x%X, hslot=%d\n",
flags, hslot);
@@ -854,6 +846,20 @@ done:
return ret;
}
+static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
+{
+ u32 status;
+ u32 hslot;
+ u8 flags;
+
+ fws->stats.txs_indicate++;
+ status = le32_to_cpu(*(__le32 *)data);
+ flags = brcmf_txstatus_get_field(status, FLAGS);
+ hslot = brcmf_txstatus_get_field(status, HSLOT);
+
+ return brcmf_fws_txstatus_process(fws, flags, hslot);
+}
+
static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
{
__le32 timestamp;
@@ -1289,3 +1295,13 @@ bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
brcmf_dbg(TRACE, "enter: mode=%d\n", fws->fcmode);
return fws->fcmode != BRCMF_FWS_FCMODE_NONE;
}
+
+void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
+{
+ ulong flags;
+
+ brcmf_fws_lock(fws->drvr, flags);
+ brcmf_fws_txstatus_process(fws, BRCMF_FWS_TXSTATUS_FW_TOSSED,
+ brcmf_skb_htod_tag_get_field(skb, HSLOT));
+ brcmf_fws_unlock(fws->drvr, flags);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
index 7778e02d7581..fbe483d23752 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h
@@ -28,5 +28,6 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb);
void brcmf_fws_reset_interface(struct brcmf_if *ifp);
void brcmf_fws_add_interface(struct brcmf_if *ifp);
void brcmf_fws_del_interface(struct brcmf_if *ifp);
+void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb);
#endif /* FWSIGNAL_H_ */
OpenPOWER on IntegriCloud