diff options
author | Weilun Du <wdu@google.com> | 2020-09-15 12:08:52 -0700 |
---|---|---|
committer | Weilun Du <wdu@google.com> | 2020-09-15 14:37:49 -0700 |
commit | 3fe99b838d55cf996e9f668b71ce282bf61ed9a2 (patch) | |
tree | eb6c6c67db4446ed8b8f040aaf033724c4122e24 | |
parent | 6d2c2fb034e58e13326215c548950f3cf32899cb (diff) | |
download | goldfish-modules-3fe99b838d55cf996e9f668b71ce282bf61ed9a2.tar.gz |
[Virtio Wifi] Fix beacon TX crash and add support for tx_status
1, Each packet needs to be acked for transmission. We can save the round
trip between guest and host and the number of items in virtqueue by
direectly calling ieee80211_status_tx for each pakcket in
virtio_wifi_tx(). This would require a copy of the sk_buff because
ieee80211_tx_status() will free the sk_buff.
2, Fixed crash in beacon tx timer.
BUG: 148080973
BUG: 166501213
Signed-off-by: Weilun Du <wdu@google.com>
Change-Id: Ie38ed4038cc8ba2f927a4a31be0042c27b5e7597
-rw-r--r-- | virtio_wifi.c | 27 |
1 files changed, 13 insertions, 14 deletions
diff --git a/virtio_wifi.c b/virtio_wifi.c index 27d494b..ef23947 100644 --- a/virtio_wifi.c +++ b/virtio_wifi.c @@ -212,6 +212,7 @@ static void virtio_wifi_tx(struct ieee80211_hw *hw, struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb); struct ieee80211_channel *channel; int err; + struct sk_buff* copy; struct send_queue *sq; bool kick = !netdev_xmit_more(); @@ -236,9 +237,10 @@ static void virtio_wifi_tx(struct ieee80211_hw *hw, else sq = vi->sq_p2p; free_old_xmit_skbs(sq); - err = xmit_skb(sq, skb); + copy = skb_copy(skb, GFP_ATOMIC); + err = xmit_skb(sq, copy); if (unlikely(err)) { - dev_kfree_skb_any(skb); + dev_kfree_skb_any(copy); return; } ieee80211_tx_info_clear_status(txi); @@ -247,9 +249,9 @@ static void virtio_wifi_tx(struct ieee80211_hw *hw, txi->control.rates[1].idx = -1; // Always assume that tx is acked. txi->flags |= IEEE80211_TX_STAT_ACK; - ieee80211_tx_status_noskb(hw, control->sta, txi); - skb_orphan(skb); - nf_reset_ct(skb); + ieee80211_tx_status_ni(hw, skb); + skb_orphan(copy); + nf_reset_ct(copy); /* * If running out of space, stop queue to avoid getting packets that we @@ -413,7 +415,7 @@ static void virtio_wifi_bss_info_changed(struct ieee80211_hw *hw, bcn_int = vi->beacon_int; until_tbtt = bcn_int - do_div(tsf, bcn_int); hrtimer_start(&vi->beacon_timer, ns_to_ktime( - until_tbtt * 1000), HRTIMER_MODE_REL); + until_tbtt * 1000), HRTIMER_MODE_REL_SOFT); } } } @@ -532,8 +534,7 @@ static int receive_buf(struct virtio_wifi_info *vi, return 0; } - if (skb->len >= IEEE80211_HEADER_LEN && - ieee80211_is_probe_resp(hdr->frame_control)) { + if (ieee80211_is_probe_resp(hdr->frame_control)) { struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; @@ -759,16 +760,14 @@ static enum hrtimer_restart virtio_wifi_beacon(struct hrtimer *timer) ktime_t next_bcn; if (!vi->started) - goto out; + return HRTIMER_NORESTART; ieee80211_iterate_active_interfaces_atomic( hw, IEEE80211_IFACE_ITER_NORMAL, virtio_wifi_beacon_tx, vi); - next_bcn = ktime_add(hrtimer_get_expires(timer), - ns_to_ktime(bcn_int * 5000)); - hrtimer_start(&vi->beacon_timer, next_bcn, HRTIMER_MODE_ABS); -out: - return HRTIMER_NORESTART; + hrtimer_forward(&vi->beacon_timer, hrtimer_get_expires(timer), + ns_to_ktime(bcn_int * 5000)); + return HRTIMER_RESTART; } static const struct ieee80211_iface_limit virtio_wifi_if_limit[] = { |