[Make-wifi-fast] [PATCH 1/2] mac80211: Implement Airtime-based Queue Limit (AQL)
Johannes Berg
johannes at sipsolutions.net
Fri Oct 4 08:30:24 EDT 2019
Just took a very brief look so I can think about it while offline ;-)
But some (editorial) comments:
> +/**
> + * ieee80211_sta_register_pending_airtime - register the estimated airtime for
> + * the frames pending in lower layer (firmware/hardware) txq.
That doesn't work - the short description must be on a single line.
> + * Update the total pending airtime of the frames released to firmware. The
> + * pending airtime is used by AQL to control queue size in the lower layer.
What does "released to firmware" mean? I guess it should either be
something like "transmitted by the device" or "sitting on the hardware
queues" - I'm guessing the latter?
> + * The airtime is estimated using frame length and the last reported data
> + * rate. The pending airtime for a txq is increased by the estimated
> + * airtime when the frame is relased to the lower layer, and decreased by the
> + * same amount at the tx completion event.
> + *
> + * @pubsta: the station
> + * @tid: the TID to register airtime for
> + * @tx_airtime: the estimated airtime (in usec)
> + * @tx_commpleted: true if called from the tx completion event.
> + */
> +void ieee80211_sta_register_pending_airtime(struct ieee80211_sta *pubsta,
> + u8 tid, u32 tx_airtime,
> + bool tx_completed);
The "bool tx_completed" is a bit confusing IMHO.
Probably better to do something like this:
void ieee80211_sta_update_pending_airtime(sta, tid, *s32* airtime);
static inline void ieee80211_sta_register_pending_airtime(...)
{
ieee80211_sta_update_pending_airtime(..., airtime);
}
static inline void ieee80211_sta_release_pending_airtime(...)
{
ieee8021
1_sta_update_pending_airtime(..., -airtime);
}
or something like that?
> +/**
> + * ieee80211_txq_aritme_check - check if the airtime limit of AQL (Airtime based
> + * queue limit) has been reached.
same comment as above - and there's a typo
> + * @hw: pointer obtained from ieee80211_alloc_hw()
> + * @txq: pointer obtained from station or virtual interface
> + * Retrun
typo
> true if the queue limit has not been reached and txq can continue to
> + * release packets to the lower layer.
> + * Return false if the queue limit has been reached and the txq should not
> + * release more frames to the lower layer.
> + */
> +bool
> +ieee80211_txq_airtime_check(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
Why is it necessary to call this, vs. just returning NULL when an SKB is
requested?
> +static ssize_t aql_txq_limit_read(struct file *file,
> + char __user *user_buf,
> + size_t count,
> + loff_t *ppos)
> +{
> + struct ieee80211_local *local = file->private_data;
> + char buf[400];
> + int len = 0;
> +
> + rcu_read_lock();
> + len = scnprintf(buf, sizeof(buf),
> + "AC AQL limit low AQL limit high\n"
> + "0 %u %u\n"
> + "1 %u %u\n"
> + "2 %u %u\n"
> + "3 %u %u\n",
> + local->aql_txq_limit_low[0],
> + local->aql_txq_limit_high[0],
> + local->aql_txq_limit_low[1],
> + local->aql_txq_limit_high[1],
> + local->aql_txq_limit_low[2],
> + local->aql_txq_limit_high[2],
> + local->aql_txq_limit_low[3],
> + local->aql_txq_limit_high[3]);
> + rcu_read_unlock();
I don't understand the RCI critical section here, you do nothing that
would require it.
> + return simple_read_from_buffer(user_buf, count, ppos,
> + buf, len);
> +}
> +
> +static ssize_t aql_txq_limit_write(struct file *file,
> + const char __user *user_buf,
> + size_t count,
> + loff_t *ppos)
> +{
> + struct ieee80211_local *local = file->private_data;
> + char buf[100];
> + size_t len;
> + u32 ac, q_limit_low, q_limit_high;
> + struct sta_info *sta;
> +
> + if (count > sizeof(buf))
> + return -EINVAL;
> +
> + if (copy_from_user(buf, user_buf, count))
> + return -EFAULT;
> +
> + buf[sizeof(buf) - 1] = '\0';
> + len = strlen(buf);
> + if (len > 0 && buf[len - 1] == '\n')
> + buf[len - 1] = 0;
> +
> + if (sscanf(buf, "%u %u %u", &ac, &q_limit_low, &q_limit_high) == 3) {
> + if (ac < IEEE80211_NUM_ACS) {
The double indentation is a bit odd here - why not return -EINVAL
immediately if any of the checks doesn't work?
if (sscanf(...) != 3)
return -EINVAL;
if (ac >= NUM_ACS)
return -EINVAL;
[...]
> + buf[sizeof(_buf) - 1] = '\0';
> + if (sscanf(buf, "queue limit %u %u %u", &ac, &q_limit_l, &q_limit_h)
> + == 3) {
> + if (ac < IEEE80211_NUM_ACS) {
same here
> @@ -245,8 +266,8 @@ static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf,
> sta->airtime[ac].deficit = sta->airtime_weight;
> spin_unlock_bh(&local->active_txq_lock[ac]);
> }
> -
> return count;
> +
> }
spurious change
> +void ieee80211_sta_register_pending_airtime(struct ieee80211_sta *pubsta,
> + u8 tid, u32 tx_airtime,
> + bool tx_completed)
> +{
> + u8 ac = ieee80211_ac_from_tid(tid);
> + struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
> + struct ieee80211_local *local = sta->local;
> +
> + spin_lock_bh(&local->active_txq_lock[ac]);
> + if (tx_completed) {
> + sta->airtime[ac].aql_tx_pending -= tx_airtime;
> + local->aql_total_pending_airtime -= tx_airtime;
maybe this should check for underflow, just in case the driver has some
symmetry bug?
> +bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
> + struct ieee80211_txq *txq)
> +{
> + struct sta_info *sta;
> + struct ieee80211_local *local = hw_to_local(hw);
> +
> +
please remove one blank line
> bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
> struct ieee80211_txq *txq)
> {
> @@ -3748,10 +3784,13 @@ bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
> struct sta_info *sta;
> u8 ac = txq->ac;
>
> - spin_lock_bh(&local->active_txq_lock[ac]);
> -
> if (!txqi->txq.sta)
> - goto out;
> + return true;
> +
> + if (!(local->airtime_flags & AIRTIME_USE_TX))
> + return true;
> +
> + spin_lock_bh(&local->active_txq_lock[ac]);
>
> if (list_empty(&txqi->schedule_order))
> goto out;
> @@ -3773,10 +3812,11 @@ bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
> }
>
> sta = container_of(txqi->txq.sta, struct sta_info, sta);
> - if (sta->airtime[ac].deficit >= 0)
> + if (ieee80211_txq_airtime_check(hw, &txqi->txq))
> goto out;
OK, so you *do* call it here, but then why are you exporting it too?
> - sta->airtime[ac].deficit += sta->airtime_weight;
> + if (sta->airtime[ac].deficit < 0)
> + sta->airtime[ac].deficit += sta->airtime_weight;
something seems wrong with indentation here (spaces instead of tabs?)
Anyway, like I said - very cursory and mostly editorial view.
Thanks,
johannes
More information about the Make-wifi-fast
mailing list