diff options
author | Jérôme Pouiller <jerome.pouiller@silabs.com> | 2020-07-01 17:06:57 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-07-03 10:33:07 +0200 |
commit | 70a37a09db9c8187e94108d875513c18000bb8d9 (patch) | |
tree | d67f6e31ac700915d74100b400b5be1e4ae606f3 /drivers/staging/wfx/queue.c | |
parent | staging: wfx: check the vif ID of the Tx confirmations (diff) | |
download | linux-dev-70a37a09db9c8187e94108d875513c18000bb8d9.tar.xz linux-dev-70a37a09db9c8187e94108d875513c18000bb8d9.zip |
staging: wfx: correctly retrieve vif ID from Tx confirmation
The device is able to send multiple Tx confirmations in the one reply.
In this case, there is only one vif identifier for all the
confirmations.
Unfortunately, to generate this kind of messages the device squashes all
the confirmations whatever their vif ID and use the vif ID of the first
confirmation. So, the driver cannot rely on the vif ID mentioned in the
header. Fortunately, using the packet_id, the driver can retrieve the Tx
request and the associated vif.
Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200701150707.222985-4-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/wfx/queue.c')
-rw-r--r-- | drivers/staging/wfx/queue.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/drivers/staging/wfx/queue.c b/drivers/staging/wfx/queue.c index 6069143369f3..678f62263909 100644 --- a/drivers/staging/wfx/queue.c +++ b/drivers/staging/wfx/queue.c @@ -138,30 +138,32 @@ void wfx_pending_drop(struct wfx_dev *wdev, struct sk_buff_head *dropped) } } -struct sk_buff *wfx_pending_get(struct wfx_vif *wvif, u32 packet_id) +struct sk_buff *wfx_pending_get(struct wfx_dev *wdev, u32 packet_id) { struct wfx_queue *queue; struct hif_req_tx *req; + struct wfx_vif *wvif; struct hif_msg *hif; struct sk_buff *skb; - spin_lock_bh(&wvif->wdev->tx_pending.lock); - skb_queue_walk(&wvif->wdev->tx_pending, skb) { + spin_lock_bh(&wdev->tx_pending.lock); + skb_queue_walk(&wdev->tx_pending, skb) { hif = (struct hif_msg *)skb->data; req = (struct hif_req_tx *)hif->body; - if (req->packet_id == packet_id) { - spin_unlock_bh(&wvif->wdev->tx_pending.lock); + if (req->packet_id != packet_id) + continue; + spin_unlock_bh(&wdev->tx_pending.lock); + wvif = wdev_to_wvif(wdev, hif->interface); + if (wvif) { queue = &wvif->tx_queue[skb_get_queue_mapping(skb)]; - WARN(hif->interface != wvif->id, "sent frame %08x on vif %d, but get reply on vif %d", - req->packet_id, hif->interface, wvif->id); WARN_ON(skb_get_queue_mapping(skb) > 3); WARN_ON(!atomic_read(&queue->pending_frames)); atomic_dec(&queue->pending_frames); - skb_unlink(skb, &wvif->wdev->tx_pending); - return skb; } + skb_unlink(skb, &wdev->tx_pending); + return skb; } - spin_unlock_bh(&wvif->wdev->tx_pending.lock); + spin_unlock_bh(&wdev->tx_pending.lock); WARN(1, "cannot find packet in pending queue"); return NULL; } |