Search Linux Wireless

Re: [RFC PATCH 03/10] mac80211: A-MPDU Tx adding basic functionality

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> +	sta = sta_info_get(local, ra);
> +	if (!sta) {
> +		printk(KERN_ERR "Could not find the station\n");
> +		return -ENOENT;
> +	}
> +
> +	spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
> +
> +	/* we have tried too many times, reciever does not want A-MPDU */

typo: "receiver"

> +	if (sta->ampdu_mlme.tid_tx[tid].addba_req_num >	HT_AGG_MAX_RETRIES) {
> +		ret = -EBUSY;
> +		goto start_ba_exit;

Can this counter reset somehow? Or do we only implicitly reset it when
the station disassociates and associates again?

> +	/* FIXME: need a better way to ensure that TX flow won't interrupt us*/
> +	/* until the end of the call to requeue function */
> +	spin_lock_bh(&local->mdev->queue_lock);

Hm. I think the queue lock here is pretty much the only way. On the
other hand, maybe here's the point where we should talk about
multi-queue ethernet devices?

> +	if (local->ops->ampdu_action)
> +		ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
> +						ra, tid, &start_seq_num);
> +
> +	if (ret) {
> +		/* No need to requeue the packets in the agg queue, since we
> +		 * held the tx lock: no packet could be enqueued to the newly
> +		 * allocated queue */
> +		ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
> +#ifdef CONFIG_MAC80211_HT_DEBUG
> +		printk(KERN_DEBUG "BA request denied - HW or queue unavailable"
> +				" for tid %d\n", tid);
> +#endif /* CONFIG_MAC80211_HT_DEBUG */
> +		spin_unlock_bh(&local->mdev->queue_lock);
> +		*state = HT_AGG_STATE_IDLE;
> +		goto start_ba_exit;
> +	}
> +
> +	/* Will put all the packets in the new SW queue */
> +	ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
> +	spin_unlock_bh(&local->mdev->queue_lock);
> +
> +	/* We have most probably almost emptied the legacy queue */
> +	ieee80211_wake_queue(local_to_hw(local), ieee802_1d_to_ac[tid]);
> +
> +	/* send an addBA request */
> +	sta->ampdu_mlme.dialog_token_allocator++;
> +	sta->ampdu_mlme.tid_tx[tid].dialog_token =
> +			sta->ampdu_mlme.dialog_token_allocator;
> +	sta->ampdu_mlme.tid_tx[tid].ssn = start_seq_num;
> +
> +	ieee80211_send_addba_request(sta->dev, ra, tid,
> +			 sta->ampdu_mlme.tid_tx[tid].dialog_token,
> +			 sta->ampdu_mlme.tid_tx[tid].ssn,
> +			 0x40, 5000);
> +
> +	/* activate the timer for the recipient's addBA response */
> +	sta->ampdu_mlme.tid_tx[tid].addba_resp_timer.expires =
> +				jiffies + ADDBA_RESP_INTERVAL;
> +	add_timer(&sta->ampdu_mlme.tid_tx[tid].addba_resp_timer);
> +	printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
> +
> +start_ba_exit:
> +	spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
> +	sta_info_put(sta);
> +	return ret;
> +}
> +EXPORT_SYMBOL(ieee80211_start_tx_ba_session);

Why is this exported? I thought this is the first step of enabling
aggregation?


> +	/* check if the TID is in aggregation */
> +	state = &sta->ampdu_mlme.tid_tx[tid].state;
> +	spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
> +
> +	if (*state != HT_AGG_STATE_OPERATIONAL) {
> +		printk(KERN_ERR "Call to %s, whith AGG non operational\n",
> +								__func__);
> +		ret = -ENOENT;
> +		goto stop_BA_exit;

I dislike the __func__ usage here, why not just say "tried to disable TX
aggregation while not operational" or something? Typo: "with".

> +	/* Tell the driver to stop its HW queue */
> +	if (local->ops->ampdu_action)
> +		ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP,
> +						ra, tid, NULL);

Does it really stop the hw queue? Isn't that more like "stop
aggregation"? Does the hardware actually have queues for each of these?
Hm. I'm familiar enough with this I think.

> +	/* case HW denied going back to legacy */
> +	if (ret) {
> +		printk(KERN_ERR "Driver could not stop aggregations\n");
> +		*state = HT_AGG_STATE_OPERATIONAL;
> +		ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
> +		goto stop_BA_exit;

Is there really a use case for a driver denying this? IOW, can you think
of a good reason why a driver would deny it?

> +EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);

Again, why export this?

> +	if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
> +		printk(KERN_ERR "%s, state not HT_ADDBA_REQUESTED_MSK: %d\n",
> +			__func__, *state);

Please just write the message w/o the function name.

> +	if (*state & HT_ADDBA_DRV_READY_MSK)
> +		printk(KERN_ERR "driver already prepared for aggregation\n");

That's a bit odd. Shouldn't it rather be a WARN_ON() because the driver
did something weird?

> +	*state |= HT_ADDBA_DRV_READY_MSK;
> +
> +	if (*state == HT_AGG_STATE_OPERATIONAL) {
> +		printk(KERN_ERR "%s. OPERATIONNAL\n", __func__);

typo, weird message :)

> +	/* avoid ordering issues: we are the only one that can modify
> +	 * the content of the qdiscs */
> +	spin_lock_bh(&local->mdev->queue_lock);
> +	/* remove the queue for this aggregation */
> +	ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
> +	spin_unlock_bh(&local->mdev->queue_lock);
> +
> +	/* Not scheduling the device leads to a stall in the TX when qdisc */
> +	/* contains more than ~220 packets... */
> +	netif_schedule(local->mdev);

This seems a bit weird, can you explain a bit more?

> +	hdr = (struct ieee80211_hdr *) skb_put(skb,
> +					sizeof(struct ieee80211_hdr));
> +	memcpy(&hdr->addr1, ra, ETH_ALEN);
> +	hdr->frame_control = tid;

Hrm. This is just strange and hard to understand imho. Can't we just use
some other structure instead of and ieee80211_hdr and push that onto the
queue? Then we shouldn't be using an skb queue any more I guess if we're
going to use it like this. For the skbs we can use skb->cb for our own
list structure, and here we just use another structure that embeds our
list structure...

> +	/* not an elegant detour, but there is no choice as the timer passes
> +	 * only one argument, and verious sta_info are needed here, so init

typo: various, but I think it should read something like "both the
sta_info and the TID are needed here"?

> +	/* check if the TID waits for addBA response */
> +	spin_lock_bh(&sta->ampdu_mlme.ampdu_tx);
> +	if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
> +		spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx);
> +		*state = HT_AGG_STATE_IDLE;
> +		printk(KERN_DEBUG "timer expired on tid %d but we are not "
> +				"expecting addBA response there", tid);
> +		goto timer_expired_exit;
> +	}

Couldn't this also happen when the response was just received while the
timer expires but the response grabs the ampdu_tx spinlock before the
timer does? Seems that should be in a comment and not worry about a
printk.

johannes

Attachment: signature.asc
Description: This is a digitally signed message part


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux