aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/wfx/data_tx.c
diff options
context:
space:
mode:
authorJérôme Pouiller <jerome.pouiller@silabs.com>2020-04-01 13:04:01 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-04-13 08:55:37 +0200
commit4c6b3837c6dc0d9e5f9ec910da2e36349beea733 (patch)
tree7298ea6c467be03e12cc55377c59ecf7b92f1297 /drivers/staging/wfx/data_tx.c
parentstaging: wfx: relocate wfx_skb_dtor() prior its callers (diff)
downloadlinux-dev-4c6b3837c6dc0d9e5f9ec910da2e36349beea733.tar.xz
linux-dev-4c6b3837c6dc0d9e5f9ec910da2e36349beea733.zip
staging: wfx: repair wfx_flush()
Until now, wfx_flush() flushed queue for while device instead of only the queue of the intended vif. It sometime failed with a timeout, but this error was not reported. Moreover, if the device was frozen, wfx_flush didn't do anything and it results a potential warning (and maybe a resource leak) when the frozen device was unregistered. We can also notice that wfx_tx_queues_wait_empty_vif() did only exist to work around the broken feature of wfx_flush(). This patch repair wfx_flush() and therefore drop wfx_tx_queues_wait_empty_vif(). Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com> Link: https://lore.kernel.org/r/20200401110405.80282-29-Jerome.Pouiller@silabs.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/wfx/data_tx.c')
-rw-r--r--drivers/staging/wfx/data_tx.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c
index ec95518c9167..1d9a8089f3d3 100644
--- a/drivers/staging/wfx/data_tx.c
+++ b/drivers/staging/wfx/data_tx.c
@@ -524,7 +524,7 @@ static void wfx_notify_buffered_tx(struct wfx_vif *wvif, struct sk_buff *skb)
rcu_read_unlock();
}
-void wfx_skb_dtor(struct wfx_dev *wdev, struct sk_buff *skb)
+static void wfx_skb_dtor(struct wfx_dev *wdev, struct sk_buff *skb)
{
struct hif_msg *hif = (struct hif_msg *)skb->data;
struct hif_req_tx *req = (struct hif_req_tx *)hif->body;
@@ -626,4 +626,36 @@ void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg)
wfx_skb_dtor(wvif->wdev, skb);
}
+void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u32 queues, bool drop)
+{
+ struct wfx_dev *wdev = hw->priv;
+ struct sk_buff_head dropped;
+ struct wfx_queue *queue;
+ struct sk_buff *skb;
+ int vif_id = -1;
+ int i;
+
+ if (vif)
+ vif_id = ((struct wfx_vif *)vif->drv_priv)->id;
+ skb_queue_head_init(&dropped);
+ for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+ if (!(BIT(i) & queues))
+ continue;
+ queue = &wdev->tx_queue[i];
+ if (drop)
+ wfx_tx_queue_drop(wdev, queue, vif_id, &dropped);
+ if (wdev->chip_frozen)
+ continue;
+ if (wait_event_timeout(wdev->tx_dequeue,
+ wfx_tx_queue_empty(wdev, queue, vif_id),
+ msecs_to_jiffies(1000)) <= 0)
+ dev_warn(wdev->dev, "frames queued while flushing tx queues?");
+ }
+ wfx_tx_flush(wdev);
+ if (wdev->chip_frozen)
+ wfx_pending_drop(wdev, &dropped);
+ while ((skb = skb_dequeue(&dropped)) != NULL)
+ wfx_skb_dtor(wdev, skb);
+}