summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWeilun Du <wdu@google.com>2020-09-15 12:08:52 -0700
committerWeilun Du <wdu@google.com>2020-09-15 14:37:49 -0700
commit3fe99b838d55cf996e9f668b71ce282bf61ed9a2 (patch)
treeeb6c6c67db4446ed8b8f040aaf033724c4122e24
parent6d2c2fb034e58e13326215c548950f3cf32899cb (diff)
downloadgoldfish-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.c27
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[] = {