diff options
author | Takashi Iwai <tiwai@suse.de> | 2020-09-09 18:26:07 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2020-09-09 18:26:48 +0200 |
commit | 9ddb236f13594b34a12dacf69a5adca7a1aef35e (patch) | |
tree | 1dc1f6e54962a2e3ad3d56c894522cb4b1ddce93 /drivers/staging/wfx/data_tx.c | |
parent | ALSA: vx: vx_pcm: remove redundant assignment (diff) | |
parent | ALSA: hda/realtek - The Mic on a RedmiBook doesn't work (diff) | |
download | linux-dev-9ddb236f13594b34a12dacf69a5adca7a1aef35e.tar.xz linux-dev-9ddb236f13594b34a12dacf69a5adca7a1aef35e.zip |
Merge branch 'for-linus' into for-next
Back-merge to apply the tasklet conversion patches that are based
on the already applied tasklet API changes on 5.9-rc4.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'drivers/staging/wfx/data_tx.c')
-rw-r--r-- | drivers/staging/wfx/data_tx.c | 127 |
1 files changed, 47 insertions, 80 deletions
diff --git a/drivers/staging/wfx/data_tx.c b/drivers/staging/wfx/data_tx.c index f042ef36b408..3acf4eb0214d 100644 --- a/drivers/staging/wfx/data_tx.c +++ b/drivers/staging/wfx/data_tx.c @@ -213,23 +213,6 @@ static bool ieee80211_is_action_back(struct ieee80211_hdr *hdr) return true; } -static void wfx_tx_manage_pm(struct wfx_vif *wvif, struct ieee80211_hdr *hdr, - struct wfx_tx_priv *tx_priv, - struct ieee80211_sta *sta) -{ - struct wfx_sta_priv *sta_priv; - int tid = ieee80211_get_tid(hdr); - - if (sta) { - tx_priv->has_sta = true; - sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; - spin_lock_bh(&sta_priv->lock); - sta_priv->buffered[tid]++; - ieee80211_sta_set_buffered(sta, tid, true); - spin_unlock_bh(&sta_priv->lock); - } -} - static u8 wfx_tx_get_link_id(struct wfx_vif *wvif, struct ieee80211_sta *sta, struct ieee80211_hdr *hdr) { @@ -407,8 +390,7 @@ static int wfx_tx_inner(struct wfx_vif *wvif, struct ieee80211_sta *sta, req->tx_flags.retry_policy_index = wfx_tx_get_rate_id(wvif, tx_info); // Auxiliary operations - wfx_tx_manage_pm(wvif, hdr, tx_priv, sta); - wfx_tx_queues_put(wvif->wdev, skb); + wfx_tx_queues_put(wvif, skb); if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) schedule_work(&wvif->update_tim_work); wfx_bh_request_tx(wvif->wdev); @@ -436,7 +418,8 @@ void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, wvif = wvif_iterate(wdev, NULL); if (WARN_ON(!wvif)) goto drop; - // FIXME: why? + // Because of TX_AMPDU_SETUP_IN_HW, mac80211 does not try to send any + // BlockAck session management frame. The check below exist just in case. if (ieee80211_is_action_back(hdr)) { dev_info(wdev->dev, "drop BA action\n"); goto drop; @@ -450,37 +433,6 @@ drop: ieee80211_tx_status_irqsafe(wdev->hw, skb); } -static struct ieee80211_hdr *wfx_skb_hdr80211(struct sk_buff *skb) -{ - struct hif_msg *hif = (struct hif_msg *)skb->data; - struct hif_req_tx *req = (struct hif_req_tx *)hif->body; - - return (struct ieee80211_hdr *)(req->frame + req->data_flags.fc_offset); -} - -static void wfx_tx_update_sta(struct wfx_vif *wvif, struct ieee80211_hdr *hdr) -{ - int tid = ieee80211_get_tid(hdr); - struct wfx_sta_priv *sta_priv; - struct ieee80211_sta *sta; - - rcu_read_lock(); // protect sta - sta = ieee80211_find_sta(wvif->vif, hdr->addr1); - if (sta) { - sta_priv = (struct wfx_sta_priv *)&sta->drv_priv; - spin_lock_bh(&sta_priv->lock); - WARN(!sta_priv->buffered[tid], "inconsistent notification"); - sta_priv->buffered[tid]--; - if (!sta_priv->buffered[tid]) - ieee80211_sta_set_buffered(sta, tid, false); - spin_unlock_bh(&sta_priv->lock); - } else { - dev_dbg(wvif->wdev->dev, "%s: sta does not exist anymore\n", - __func__); - } - rcu_read_unlock(); -} - static void wfx_skb_dtor(struct wfx_vif *wvif, struct sk_buff *skb) { struct hif_msg *hif = (struct hif_msg *)skb->data; @@ -533,27 +485,29 @@ static void wfx_tx_fill_rates(struct wfx_dev *wdev, dev_dbg(wdev->dev, "%d more retries than expected\n", tx_count); } -void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg) +void wfx_tx_confirm_cb(struct wfx_dev *wdev, const struct hif_cnf_tx *arg) { struct ieee80211_tx_info *tx_info; const struct wfx_tx_priv *tx_priv; + struct wfx_vif *wvif; struct sk_buff *skb; - skb = wfx_pending_get(wvif->wdev, arg->packet_id); + skb = wfx_pending_get(wdev, arg->packet_id); if (!skb) { - dev_warn(wvif->wdev->dev, "received unknown packet_id (%#.8x) from chip\n", + dev_warn(wdev->dev, "received unknown packet_id (%#.8x) from chip\n", arg->packet_id); return; } + wvif = wdev_to_wvif(wdev, ((struct hif_msg *)skb->data)->interface); + WARN_ON(!wvif); + if (!wvif) + return; tx_info = IEEE80211_SKB_CB(skb); tx_priv = wfx_skb_tx_priv(skb); - _trace_tx_stats(arg, skb, - wfx_pending_get_pkt_us_delay(wvif->wdev, skb)); + _trace_tx_stats(arg, skb, wfx_pending_get_pkt_us_delay(wdev, skb)); // You can touch to tx_priv, but don't touch to tx_info->status. - wfx_tx_fill_rates(wvif->wdev, tx_info, arg); - if (tx_priv->has_sta) - wfx_tx_update_sta(wvif, wfx_skb_hdr80211(skb)); + wfx_tx_fill_rates(wdev, tx_info, arg); skb_trim(skb, skb->len - wfx_tx_get_icv_len(tx_priv->hw_key)); // From now, you can touch to tx_info->status, but do not touch to @@ -582,45 +536,58 @@ void wfx_tx_confirm_cb(struct wfx_vif *wvif, const struct hif_cnf_tx *arg) wfx_skb_dtor(wvif, skb); } -void wfx_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u32 queues, bool drop) +static void wfx_flush_vif(struct wfx_vif *wvif, u32 queues, + struct sk_buff_head *dropped) { - struct wfx_dev *wdev = hw->priv; - struct sk_buff_head dropped; struct wfx_queue *queue; - struct wfx_vif *wvif; - struct hif_msg *hif; - 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) + queue = &wvif->tx_queue[i]; + if (dropped) + wfx_tx_queue_drop(wvif, queue, dropped); + } + if (wvif->wdev->chip_frozen) + return; + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + if (!(BIT(i) & queues)) continue; - if (wait_event_timeout(wdev->tx_dequeue, - wfx_tx_queue_empty(wdev, queue, vif_id), + queue = &wvif->tx_queue[i]; + if (wait_event_timeout(wvif->wdev->tx_dequeue, + wfx_tx_queue_empty(wvif, queue), msecs_to_jiffies(1000)) <= 0) - dev_warn(wdev->dev, + dev_warn(wvif->wdev->dev, "frames queued while flushing tx queues?"); } +} + +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_vif *wvif; + struct hif_msg *hif; + struct sk_buff *skb; + + skb_queue_head_init(&dropped); + if (vif) { + wvif = (struct wfx_vif *)vif->drv_priv; + wfx_flush_vif(wvif, queues, drop ? &dropped : NULL); + } else { + wvif = NULL; + while ((wvif = wvif_iterate(wdev, wvif)) != NULL) + wfx_flush_vif(wvif, queues, drop ? &dropped : NULL); + } wfx_tx_flush(wdev); if (wdev->chip_frozen) wfx_pending_drop(wdev, &dropped); while ((skb = skb_dequeue(&dropped)) != NULL) { hif = (struct hif_msg *)skb->data; wvif = wdev_to_wvif(wdev, hif->interface); - if (wfx_skb_tx_priv(skb)->has_sta) - wfx_tx_update_sta(wvif, wfx_skb_hdr80211(skb)); ieee80211_tx_info_clear_status(IEEE80211_SKB_CB(skb)); wfx_skb_dtor(wvif, skb); } } - |