Search Linux Wireless

Re: [PATCH 2/2] mac80211: implement multi-interface CSA

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

 



On Mon, 2014-01-20 at 15:27 +0100, Michal Kazior wrote:

> This implements a fairly simple multi-interface
> CSA. It doesn't support multiple channel
> contexts so it doesn't support multi-channel.

For not implementing chanctx support, I think it changes an awful lot in
the implementation there...

> A new worker is introduced: csa_complete_work
> which is used to account per-interface countdowns
> and issue the actual channel switch after last
> interface completes its CSA.

Not sure I understand this part, don't they all have the same countdown,
and should finish at the same time?
 
>  	/* abort any running channel switch */
>  	mutex_lock(&local->mtx);
> -	sdata->vif.csa_active = false;
> -	kfree(sdata->u.ap.next_beacon);
> -	sdata->u.ap.next_beacon = NULL;
> +	ieee80211_csa_clear(sdata);
> +	ieee80211_csa_free(sdata);
>  	mutex_unlock(&local->mtx);

Maybe that kind of refactoring would be better in a separate patch?
 
> +static int ieee80211_ap_beacon_presp_backup(struct ieee80211_sub_if_data *sdata)

I'm beginning to think it's time to create a new file
net/mac80211/ap.c :-)

What's the backup/restore used for anyway?

> -int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata,
> -				 u32 *changed)
> +const struct cfg80211_chan_def *
> +ieee80211_get_csa_chandef(struct ieee80211_local *local)
>  {
> -	struct ieee80211_local *local = sdata->local;
> -	struct ieee80211_chanctx_conf *conf;
> -	struct ieee80211_chanctx *ctx;
> -	const struct cfg80211_chan_def *chandef = &sdata->csa_chandef;
> -	int ret;
> -	u32 chanctx_changed = 0;
> +	struct ieee80211_sub_if_data *sdata;
> +	const struct cfg80211_chan_def *chandef = NULL;
>  
>  	lockdep_assert_held(&local->mtx);
> +	lockdep_assert_held(&local->chanctx_mtx);
>  
> -	/* should never be called if not performing a channel switch. */
> -	if (WARN_ON(!sdata->vif.csa_active))
> -		return -EINVAL;
> +	list_for_each_entry_rcu(sdata, &local->interfaces, list) {

_rcu doesn't seem right.

But then again this whole function, iterating interfaces rather than
channel contexts etc. is terrible IMHO. This seems to pretty much turn
chanctx support upside down, making the channel context structures not
be the first-class citizens I think we want them to be.

I'd say Luca's approach has more future, as it makes channel context
support native. With this, I don't even see how you *could* later add
real channel context support. A function like this, that essentially
assumes exactly a single chanctx that might be doing CSA and similar
seems to make that rather difficult.

> +struct ieee80211_chanctx *
> +ieee80211_get_csa_chanctx(struct ieee80211_local *local)
> +{
> +	struct ieee80211_chanctx *chanctx = NULL, *ctx;
> +	int num_chanctx = 0;
> +
> +	lockdep_assert_held(&local->chanctx_mtx);
> +
> +	list_for_each_entry(ctx, &local->chanctx_list, list) {
> +		chanctx = ctx;
> +		num_chanctx++;
>  	}
>  
> -	sdata->vif.bss_conf.chandef = *chandef;
> -	ctx->conf.def = *chandef;
> +	/* multi-channel is not supported, multi-vif is */
> +	if (num_chanctx > 1)
> +		return NULL;

This is essentially the same thing, but written as a chanctx function?

> +	if (!chandef) {
> +		rcu_read_unlock();
> +		return -EINVAL;
> +	}
> +
> +	if (!cfg80211_chandef_usable(local->hw.wiphy, chandef,
> +				     IEEE80211_CHAN_DISABLED)) {
> +		rcu_read_unlock();
> +		return -EINVAL;
> +	}
> +
> +	ieee80211_use_csa_chandef(local);
> +	rcu_read_unlock();

A function that changes something but is under rcu_read_lock()? can't
this call into the driver, which is likely not allowed?


> +++ b/net/mac80211/tx.c
> @@ -2427,13 +2427,16 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
>  	if (WARN_ON(counter_offset_beacon >= beacon_data_len))
>  		return;
>  
> -	/* Warn if the driver did not check for/react to csa
> -	 * completeness.  A beacon with CSA counter set to 0 should
> -	 * never occur, because a counter of 1 means switch just
> -	 * before the next beacon.
> -	 */
> -	if (WARN_ON(beacon_data[counter_offset_beacon] == 1))
> +	if (beacon_data[counter_offset_beacon] == 1) {
> +		/* Warn if the driver did not check for/react to csa
> +		 * completeness. A beacon with CSA counter set to 0 should
> +		 * never occur, because a counter of 1 means switch just before
> +		 * the next beacon. Multi-interface CSA may need to wait for
> +		 * other interfaces to complete their counter so don't warn
> +		 * unless driver actually didn't notify us. */

Err, that doesn't seem right either ... multi-interface CSA should all
be switching at the same time, so you *still* shouldn't be running into
this and transmitting beacons with CSA count==1. If you do, your driver
is likely not behaving as it should.


In any case, unless I'm missing some bigger picture this seems like a
really hacky way to add things, basically ignoring all the channel
context work. Since I care more about channel contexts, maybe we should
merge support for channel context CSA before we try to do the multi
thing.

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux