summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/mwifiex/main.h1
-rw-r--r--drivers/net/wireless/mwifiex/pcie.c32
-rw-r--r--drivers/net/wireless/mwifiex/pcie.h13
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c2
4 files changed, 48 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index ef02a5bf57b1..51044e3ea89b 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -602,6 +602,7 @@ struct mwifiex_if_ops {
int (*init_fw_port) (struct mwifiex_adapter *);
int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
void (*card_reset) (struct mwifiex_adapter *);
+ int (*clean_pcie_ring) (struct mwifiex_adapter *adapter);
};
struct mwifiex_adapter {
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index ac20bc4bc1a0..19b5a83f4e7f 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -764,6 +764,37 @@ static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter)
return 0;
}
+/* This function flushes the TX buffer descriptor ring
+ * This function defined as handler is also called while cleaning TXRX
+ * during disconnect/ bss stop.
+ */
+static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter)
+{
+ struct pcie_service_card *card = adapter->card;
+ u32 rdptr;
+
+ /* Read the TX ring read pointer set by firmware */
+ if (mwifiex_read_reg(adapter, REG_TXBD_RDPTR, &rdptr)) {
+ dev_err(adapter->dev,
+ "Flush TXBD: failed to read REG_TXBD_RDPTR\n");
+ return -1;
+ }
+
+ if (!mwifiex_pcie_txbd_empty(card, rdptr)) {
+ card->txbd_flush = 1;
+ /* write pointer already set at last send
+ * send dnld-rdy intr again, wait for completion.
+ */
+ if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT,
+ CPU_INTR_DNLD_RDY)) {
+ dev_err(adapter->dev,
+ "failed to assert dnld-rdy interrupt.\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
/*
* This function sends data buffer to device
*/
@@ -1995,6 +2026,7 @@ static struct mwifiex_if_ops pcie_ops = {
.update_mp_end_port = NULL,
.cleanup_mpa_buf = NULL,
.init_fw_port = mwifiex_pcie_init_fw_port,
+ .clean_pcie_ring = mwifiex_clean_pcie_ring_buf,
};
/*
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h
index 87201f554d2e..24a39b32a222 100644
--- a/drivers/net/wireless/mwifiex/pcie.h
+++ b/drivers/net/wireless/mwifiex/pcie.h
@@ -114,6 +114,7 @@ struct pcie_service_card {
struct pci_dev *dev;
struct mwifiex_adapter *adapter;
+ u8 txbd_flush;
u32 txbd_wrptr;
u32 txbd_rdptr;
u32 txbd_ring_size;
@@ -146,4 +147,16 @@ struct pcie_service_card {
void __iomem *pci_mmap1;
};
+static inline int
+mwifiex_pcie_txbd_empty(struct pcie_service_card *card, u32 rdptr)
+{
+ if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) ==
+ (rdptr & MWIFIEX_TXBD_MASK)) &&
+ ((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) !=
+ (rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND)))
+ return 1;
+
+ return 0;
+}
+
#endif /* _MWIFIEX_PCIE_H */
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 818f871ae987..6d641cbce726 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -568,6 +568,8 @@ mwifiex_clean_txrx(struct mwifiex_private *priv)
mwifiex_wmm_delete_all_ralist(priv);
memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid));
+ if (priv->adapter->if_ops.clean_pcie_ring)
+ priv->adapter->if_ops.clean_pcie_ring(priv->adapter);
spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
}