Re: [PATCH v6 5/6] ARM: dts: add wl12xx/wl18xx bindings
that would be great. thanks. i'll try posting the updated patchset (v7, some minor changes) tomorrow. Eliad. On Mon, Mar 16, 2015 at 3:08 PM, Pau Pajuel wrote: > Hi, > > 2015-03-13 9:17 GMT+01:00 Enric Balletbo Serra : >> >> Hello, >> >> 2015-03-13 9:01 GMT+01:00 Javier Martinez Canillas : >> > Hello Eliad, >> > >> > On Thu, Mar 12, 2015 at 1:09 PM, Eliad Peller wrote: >> >> Replace all the pdata-quirks for setting wl12xx/wl18xx >> >> platform data with proper DT definitions. >> >> >> >> The patch was compile-tested only. >> >> >> >> Signed-off-by: Eliad Peller >> >> --- >> > >> > I wanted to test your series but I realized that the IGEPv2 I've >> > access is the old revision that has another SDIO wlan module instead >> > of a Wilink8. >> > >> > Maybe Enric have the new revision? I also added to Pau Pajuel as cc >> > who still works in the company manufacturing these boards so he should >> > be able to test it. >> > >> >> Sorry, now I only have an old revision too, so I can't test, cc'ing >> Agustí that has access to the hardware, maybe he can test it or he can >> provide to us a board ;) >> >> > But in any case, your patch looks good to me so for the >> > arch/arm/boot/dts/omap3-igep00* changes: >> > >> > Acked-by: Javier Martinez Canillas >> > >> >> For my part also looks good. >> >> Acked-by: Enric Balletbo i Serra >> >> Best regards, >>Enric >> >> > Best regards, >> > Javier > > > I'm gonna test it this week. I added Eduard Gavin as cc too. > > Cheers! -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 03/10] mac80211: add new Minstrel statistic output via csv
On 2015-02-13 15:57, Thomas Huehn wrote: > This patch adds a new debugfs file "rc_stats_csv" to output Minstrels > statistics in a common csv format that is easy to parse. > > Signed-off-by: Thomas Huehn > Signed-off-by: Stefan Venz > --- > net/mac80211/rc80211_minstrel.h| 6 +- > net/mac80211/rc80211_minstrel_debugfs.c| 95 > ++ > net/mac80211/rc80211_minstrel_ht_debugfs.c | 2 +- > 3 files changed, 88 insertions(+), 15 deletions(-) > > diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c > b/net/mac80211/rc80211_minstrel_ht_debugfs.c > index 7fc690f..b300513 100644 > --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c > +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c > @@ -112,7 +112,7 @@ minstrel_ht_stats_open(struct inode *inode, struct file > *file) > > if (!msp->is_ht) { > inode->i_private = &msp->legacy; > - ret = minstrel_stats_open(inode, file); > + ret = minstrel_stats_csv_open(inode, file); That does not look right to me. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 04/10] mac80211: add new Minstrel-HT statistic output via csv
On 2015-02-13 15:57, Thomas Huehn wrote: > This patch adds a new debugfs file "rc_stats_csv" to output > Minstrel-HTs statistics in a common csv format that is easy > to parse. > > Signed-off-by: Thomas Huehn > Signed-off-by: Stefan Venz > --- > --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c > +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c > +static int > +minstrel_ht_stats_csv_open(struct inode *inode, struct file *file) > +{ > + struct minstrel_ht_sta_priv *msp = inode->i_private; > + struct minstrel_ht_sta *mi = &msp->ht; > + struct minstrel_debugfs_info *ms; > + struct timeval tv; > + unsigned int i; > + int ret; > + char *p; > + > + do_gettimeofday(&tv); > + > + if (!msp->is_ht) { > + inode->i_private = &msp->legacy; > + ret = minstrel_stats_open(inode, file); Should be minstrel_stats_csv_open here? - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 07/10] mac80211: restructure per-rate throughput calculation into function
On 2015-02-13 15:57, Thomas Huehn wrote: > This patch moves Minstrels and Minstrel-HTs per-rate throughput > calculation (EWMA(thr)) into a dedicated function to be called. > Therefore the variable "unsigned int cur_tp" within struct > "minstrel_rate_stats" becomes obsolete. and is removed to free > up its space. > > Signed-off-by: Thomas Huehn > --- > net/mac80211/rc80211_minstrel.c| 46 +++-- > net/mac80211/rc80211_minstrel.h| 4 +- > net/mac80211/rc80211_minstrel_debugfs.c| 12 ++--- > net/mac80211/rc80211_minstrel_ht.c | 79 > ++ > net/mac80211/rc80211_minstrel_ht.h | 1 + > net/mac80211/rc80211_minstrel_ht_debugfs.c | 12 ++--- > 6 files changed, 94 insertions(+), 60 deletions(-) > > diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c > index 89db6cf..28de2f7a 100644 > --- a/net/mac80211/rc80211_minstrel.c > +++ b/net/mac80211/rc80211_minstrel.c > @@ -69,13 +69,34 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) > return i; > } > > +/* return current EMWA throughput */ > +int minstrel_get_tp_avg(struct minstrel_rate *mr) > +{ > + int tp_avg, usecs; > + > + usecs = mr->perfect_tx_time; > + if (!usecs) > + usecs = 100; > + > + /* reset thr. below 10% success */ > + if (mr->stats.prob_ewma < MINSTREL_FRAC(10, 100)) > + tp_avg = 0; You don't really need a variable, you can just do return 0 here and reduce indentation of the line below. > + else > + tp_avg = MINSTREL_TRUNC(mr->stats.prob_ewma * (10 / usecs)); > + > + return tp_avg; > +} > + > + > + > /* find & sort topmost throughput rates */ > static inline void > minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) > { > int j = MAX_THR_RATES; > > - while (j > 0 && mi->r[i].stats.cur_tp > mi->r[tp_list[j - > 1]].stats.cur_tp) > + while (j > 0 && (minstrel_get_tp_avg(&mi->r[i]) > > + minstrel_get_tp_avg(&mi->r[tp_list[j - 1]]))) Indentation seems off. > j--; > if (j < MAX_THR_RATES - 1) > memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); > @@ -158,8 +179,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct > minstrel_sta_info *mi) > { > u8 tmp_tp_rate[MAX_THR_RATES]; > u8 tmp_prob_rate = 0; > - u32 usecs; > - int i; > + int i, tmp_cur_tp, tmp_prob_tp; > > for (i = 0; i < MAX_THR_RATES; i++) > tmp_tp_rate[i] = 0; > diff --git a/net/mac80211/rc80211_minstrel_ht.c > b/net/mac80211/rc80211_minstrel_ht.c > index 6b07686..2a55f63 100644 > --- a/net/mac80211/rc80211_minstrel_ht.c > +++ b/net/mac80211/rc80211_minstrel_ht.c > @@ -312,23 +312,23 @@ minstrel_get_ratestats(struct minstrel_ht_sta *mi, int > index) > } > > /* > - * Calculate throughput based on the average A-MPDU length, taking into > account > - * the expected number of retransmissions and their expected length > + * Return current throughput based on the average A-MPDU length, taking into > + * account the expected number of retransmissions and their expected length > */ > -static void > -minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate) > +int > +minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate) > { > struct minstrel_rate_stats *mrs; > unsigned int nsecs = 0; > - unsigned int tmp_prob_ewma; > + unsigned int tmp_prob_ewma, tp_avg; > > mrs = &mi->groups[group].rates[rate]; > tmp_prob_ewma = mrs->prob_ewma; > > /* do not account throughput if sucess prob is below 10% */ > if (mrs->prob_ewma < MINSTREL_FRAC(10, 100)) { > - mrs->cur_tp = 0; > - return; > + tp_avg = 0; > + return tp_avg; No need for the tp_avg variable. > } > > /* > @@ -344,7 +344,9 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int > group, int rate) > nsecs += minstrel_mcs_groups[group].duration[rate]; > > /* prob is scaled - see MINSTREL_FRAC above */ > - mrs->cur_tp = MINSTREL_TRUNC(100 * ((tmp_prob_ewma * 1000) / > nsecs)); > + tp_avg = MINSTREL_TRUNC(10 * ((tmp_prob_ewma * 1000) / nsecs)); > + > + return tp_avg; > } > > /* -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 08/10] mac80211: add max. lossless throughput per rate to rc_stats
On 2015-02-13 15:57, Thomas Huehn wrote: > This patch adds the new statistic "maximum possible lossless > throughput" to Minstrels and Minstrel-HTs rc_stats (in debugfs). This > enables comprehensive comparison between current per-rate throughput > and max. achievable per-rate throughput. > > Signed-off-by: Thomas Huehn > --- > net/mac80211/rc80211_minstrel.c| 12 > net/mac80211/rc80211_minstrel.h| 1 + > net/mac80211/rc80211_minstrel_debugfs.c| 18 +++--- > net/mac80211/rc80211_minstrel_ht.c | 19 +++ > net/mac80211/rc80211_minstrel_ht.h | 1 + > net/mac80211/rc80211_minstrel_ht_debugfs.c | 20 > 6 files changed, 56 insertions(+), 15 deletions(-) > > diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c > index 28de2f7a..42dfef8 100644 > --- a/net/mac80211/rc80211_minstrel.c > +++ b/net/mac80211/rc80211_minstrel.c > @@ -87,7 +87,19 @@ int minstrel_get_tp_avg(struct minstrel_rate *mr) > return tp_avg; > } > > +/* return max. potential lossless throughput */ > +int minstrel_get_tp_max(struct minstrel_rate *mr) > +{ > + int tp_max, usecs; > > + usecs = mr->perfect_tx_time; > + if (!usecs) > + usecs = 100; > + > + tp_max = 10 / usecs; > + > + return tp_max; > +} This should probably be an inline function, and you can remove the tp_max variable as well. By the way, in the case of !usecs, the result (10 / 100) will be 0, so you can simplify the logic. > /* find & sort topmost throughput rates */ > static inline void > diff --git a/net/mac80211/rc80211_minstrel_ht.c > b/net/mac80211/rc80211_minstrel_ht.c > index 2a55f63..b62b04e 100644 > --- a/net/mac80211/rc80211_minstrel_ht.c > +++ b/net/mac80211/rc80211_minstrel_ht.c > @@ -350,6 +350,25 @@ minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int > group, int rate) > } > > /* > + * Return max. potential lossless throughput based on the average A-MPDU > + */ > +int > +minstrel_ht_get_tp_max(struct minstrel_ht_sta *mi, int group, int rate) > +{ > + unsigned int nsecs = 0; > + unsigned int tp_max; > + > + if (group != MINSTREL_CCK_GROUP) > + nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len); > + > + nsecs += minstrel_mcs_groups[group].duration[rate]; > + tp_max = 1 / nsecs; > + > + return tp_max; > +} I don't like duplication of the throughput metric - gets annoying if we ever decide to tweak it. How about unifying this with minstrel_ht_get_tp_avg by passing in the prob value as a parameter. - Felix -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [1/3] rt2x00usb: initialize the read value in case of failure
* Sebastian Andrzej Siewior | 2015-03-16 17:41:00 [+0100]: Just an update: … >|ieee80211 phy0: rt2800usb_write_firmware: Info - Firmware loading not >required - NIC in AutoRun mode >|IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready >|IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready >switch to AP mode done. > >And this should be where it switches back to managed mode >|ieee80211 phy0: rt2x00usb_vendor_request: Error - Vendor Request 0x06 failed >for offset 0x3200 with error -110 val: 0 type 40 >|ieee80211 phy0: rt2800usb_write_firmware: Info - Firmware is written. so the difference is that I don't see "NIC in AutoRun mode". So rt2800usb_autorun_detect() does not return 1 for some reason but 0 instead and whatever comes next kills the stick. Maybe it was tired of of the wpa <-> hostapd mode switch for no reason. So I told rt2800usb_autorun_detect() to always return 1 and not to care what the stick says. The stick now runs for 12.5h in test without a problem (that means it is able to connect to the AP and hostapd does not complain, too). After around 11h I saw the message that it would write the firmware (but it got ignored instead). So the workaround seems to work. I have no idea what AutoRun mode is (it seems that the stick already has a firmware and is happy with it) and I have no clue why the firmware decides to lie about it. I looked at the vendor driver I found at github (which seems to be from 2012-10-22, DPO_RT5572_LinuxSTA_2.6.1.3) and well, I look again if someone says it is worth looking… They seem to do some kind "firmware is comming" magic which might be already done in the current driver at a different spot but I think the main question is why request is answered wrong. I *think* the vendor driver sends the USB_MODE_AUTORUN request only once but it is hard to tell… >>Kalle Valo Sebastian -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Connection issues with BW Tracking in mac80211
On Thu, 2015-03-12 at 14:47 +0530, Krishna Chaitanya wrote: > 1. Make the directed probe mandatory: > a. Check for successful probe resp without depending on > proberesp_ies. > b. remove the proberesp_ies from the auth_data to trigger > directed probe. > > 2. Timestamps for proberesp and beacons and update the latest one to "ies". > > 3. while update "ies" check only for beacon as its supposed to have latest > information (This will trigger #1 automatically). > > As a quick and minimal impact solution i am thinking 1-b. Huh? No, that'd be one of the worst possible solution IMHO since it would make the system behave differently *all the time* just because of a very uncommon scenario. Is this really a "real world" use case? I can't really think of any way this would happen in practice. The least impact would probably have #2. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] mac80211: initialize rate control earlier for tdls station
On Sun, 2015-03-08 at 18:04 +0200, Arik Nemtsov wrote: > From: Marek Puzyniak > > Currently when TDLS station in driver goes from authorized from authenticated > to associated state it can not use rate control parameters > because rate control is not initialized yet. Some drivers > require parameters already initialized by rate control when > entering associated state. It can be done by initializing > rate control after station transition to associated state > but before notifying driver about that. Applied, with the minor fix in the commit log above and the comment in the code. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3] mac80211: Get IV len from key conf and not cipher scheme
On Wed, 2015-03-11 at 16:29 +, Cedric Izoard wrote: > When a key is installed using a cipher scheme, a new flag > IEE80211_KEY_FLAG_CIPHER_SCHEME is set. Should this flag really be visible to the driver? The driver should better know if it's a CS key anyway, no? And then we could use an internal key flag (see net/mac80211/key.h) and avoid increasing the size of the flags field. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] cfg80211: Process all pending regulatory requests/hints
On Thu, 2015-03-12 at 09:37 -0400, Ilan Peer wrote: > From: Ben > > It is possible that there are several regulatory requests > pending, but the processing of the last one does not call > CRDA, and thus the other requests are not handled. > > Fix this by rescheduling the work until all requests have been > processed. Applied. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] mac80211: minstrel_ht: fix rounding issue in MCS duration calculation
On Fri, 2015-03-13 at 10:54 +0100, Felix Fietkau wrote: > On very high MCS bitrates, the calculated duration of rates that are > next to each other can be very imprecise, due to the small packet size > used as reference (1200 bytes). > This is most visible in VHT80 nss=2 MCS8/9, for which minstrel shows the > same throughput when the probability is also the same. This leads to a > bad rate selection for such rates. > > Fix this issue by introducing an average A-MPDU size factor into the > calculation. Applied. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv2 1/3] mac80211: IBSS fix scan request
On Mon, 2015-03-09 at 07:58 +0100, Janusz Dziedzic wrote: > In case of wide bandwidth scan all channels we have > in chandef. For example in case of 80MHz bandwidth > we have four possible control channels. I think you misunderstood - this doesn't really say *why* either. It should probably say something like If channels wider than 20 MHz are used by IBSS, scan all channels in the chandef to be able to find neighboring IBSS networks that use the same overall channel but a different control channel. no? johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv2 2/3] mac80211: ibss refactor ieee80211_rx_bss_info
On Mon, 2015-03-09 at 07:58 +0100, Janusz Dziedzic wrote: > Put station specific code in ieee80211_update_sta_info > function. Applied. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv2 3/3] mac80211: add VHT support for IBSS
On Mon, 2015-03-09 at 07:58 +0100, Janusz Dziedzic wrote: > Add VHT support for IBSS. Drivers could activate > this feature by setting NL80211_EXT_FEATURE_VHT_IBSS > flag. I'm assuming this needs patch 1 to go in first, so am not applying this. If I'm wrong let me know, or just resend with the changed patch 1. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] iw: display allowable channel bandwidth information
On Wed, 2015-03-04 at 12:34 +0530, Ashok Raj Nagarajan wrote: > We already have allowable channel bandwidth information at userspace. > Display this information with 'iw list'. Excerpt of iw list command > > Frequencies: > * 5180 MHz [36] (17.0 dBm) > (10MHZ, 20MHZ, HT40+, VHT80, VHT160) > * 5200 MHz [40] (17.0 dBm) > (10MHZ, 20MHZ, HT40-, HT40+, VHT80, VHT160) > > Signed-off-by: Ashok Raj Nagarajan > --- > v2: > Display channel bw information in separate line (Johannes) > Updated commit log to reflect above change. Thanks for the changes. I was going to apply this, but then I realized that the above example is probably incorrect, since I'm guessing it was done on a driver that doesn't actually support 10 MHz? And if it was then it probably also supported 5 MHz... Now, the annoying thing is that to display the possible bandwidth we need to parse a lot more information - i.e. the "supports 5 MHz" and "supports 10 MHz" flags, along with the HT/VHT information. The even more annoying thing is that we get that information only in later nl80211 messages while printing this, so we can no longer parse things in the right order. One technical alternative would be to print exactly the attributes, i.e. "no 5 MHz", "no 10 MHz", etc. instead of inverting and printing what's supported, but that's perhaps a little too unfriendly for users? I guess we can first collect all messages and print all the data later, parsing them first for the capabilities and then the channels, but that seems like a pretty big code change? Additionally, the channel display information in "iw list" is getting pretty big these days. Perhaps we should have a separate command that prints the channel list with all the detail information, and then that command can do all of the above? johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH iw 2/2] iw: add a delay option to net-detect
On Fri, 2015-03-13 at 14:17 +0200, Luca Coelho wrote: > From: Luciano Coelho > > Add an option that allows the initial net-detect scan to be delayed by > the specified number of seconds. Applied. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3] mac80211: add an intermediate software queue implementation
This allows drivers to request per-vif and per-sta-tid queues from which they can pull frames. This makes it easier to keep the hardware queues short, and to improve fairness between clients and vifs. The task of scheduling packet transmission is left up to the driver - queueing is controlled by mac80211. Drivers can only dequeue packets by calling ieee80211_tx_dequeue. This makes it possible to add active queue management later without changing drivers using this code. This can also be used as a starting point to implement A-MSDU aggregation in a way that does not add artificially induced latency. Signed-off-by: Felix Fietkau --- include/net/mac80211.h | 77 ++ net/mac80211/driver-ops.h | 17 ++ net/mac80211/ieee80211_i.h | 14 net/mac80211/iface.c | 26 +++ net/mac80211/main.c| 3 ++ net/mac80211/rx.c | 15 + net/mac80211/sta_info.c| 83 +- net/mac80211/sta_info.h| 3 ++ net/mac80211/trace.h | 34 +++ net/mac80211/tx.c | 72 ++-- net/mac80211/util.c| 38 + 11 files changed, 370 insertions(+), 12 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a1db2ea..724e133 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -84,6 +84,33 @@ * */ +/** + * DOC: mac80211 software tx queueing + * + * mac80211 provides an optional intermediate queueing implementation designed + * to allow the driver to keep hardware queues short and provide some fairness + * between different stations/interfaces. + * In this model, the driver pulls data frames from the mac80211 queue instead + * of letting mac80211 push them via drv_tx(). Management frames are still sent + * via drv_tx(). + * + * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with a + * single per-vif queue for multicast data frames. + * + * The driver is expected to initialize its private per-queue data for stations + * and interfaces in the .add_interface and .sta_add ops. + * + * The driver can not access the queue directly. To dequeue a frame, it calls + * ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a queue, it + * calls the .wake_tx_queue driver op. + * + * For AP powersave TIM handling, the driver only needs to indicate if it has + * buffered packets in the driver specific data structures. For frames buffered + * in the ieee80211_txq struct, mac80211 sets TIM and the driver is expected + * to dequeue and transmit packets on demand via the .release_buffered_frames + * op. + */ + struct device; /** @@ -1257,6 +1284,8 @@ struct ieee80211_vif { u8 cab_queue; u8 hw_queue[IEEE80211_NUM_ACS]; + struct ieee80211_txq *txq; + struct ieee80211_chanctx_conf __rcu *chanctx_conf; u32 driver_flags; @@ -1519,6 +1548,8 @@ struct ieee80211_sta { bool tdls_initiator; bool mfp; + struct ieee80211_txq *txq[IEEE80211_NUM_TIDS]; + /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; @@ -1547,6 +1578,27 @@ struct ieee80211_tx_control { }; /** + * struct ieee80211_txq - Software intermediate tx queue + * + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @sta: station table entry, may be NULL for per-vif queue + * @tid: the TID for this queue (unset for per-vif queue) + * @ac: the AC for this queue + * + * The driver can obtain packets from this queue by calling + * ieee80211_tx_dequeue(). + */ +struct ieee80211_txq { + struct ieee80211_vif *vif; + struct ieee80211_sta *sta; + u8 tid; + u8 ac; + + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); +}; + +/** * enum ieee80211_hw_flags - hardware flags * * These flags are used to indicate hardware capabilities to @@ -1770,6 +1822,8 @@ enum ieee80211_hw_flags { * within &struct ieee80211_sta. * @chanctx_data_size: size (in bytes) of the drv_priv data area * within &struct ieee80211_chanctx_conf. + * @txq_data_size: size (in bytes) of the drv_priv data area + * within @struct ieee80211_txq. * * @max_rates: maximum number of alternate rate retry stages the hw * can handle. @@ -1818,6 +1872,9 @@ enum ieee80211_hw_flags { * @n_cipher_schemes: a size of an array of cipher schemes definitions. * @cipher_schemes: a pointer to an array of cipher scheme definitions * supported by HW. + * + * @txq_ac_max_pending: maximum number of frames per AC pending in all txq + * entries for a vif. */ struct ieee80211_hw { struct ieee80211_conf conf; @@ -1830,6 +1887,7 @@ struct ieee80211_hw { int vif_data_size; int sta_data_size; int chanctx_data_size; + int txq_data_size; u16 queues; u16 max_listen_interval; s8 max_signal; @@ -1846,6 +
Re: [PATCH iw 0/4] iw: add scheduled scan support
On Fri, 2015-03-13 at 22:27 +0200, Luca Coelho wrote: > From: Luciano Coelho > > This series adds scheduled scan support to the iw tool (finally! ;). It doesn't apply though, at least not on top of your delay patch :) johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4] mac80211: Get IV len from key conf and not cipher scheme
When a key is installed using a cipher scheme, a new internal flag KEY_FLAG_CIPHER_SCHEME is set. This flag is used on TX path to test for "cipher scheme" key, instead of testing for sta->cipher_scheme as sta is NULL for bcast/mcast messages. For cipher scheme key, security header length is then read from key->conf.iv_len initialized with cs->hdr_len. Signed-off-by: Cedric Izoard --- net/mac80211/key.c | 1 + net/mac80211/key.h | 1 + net/mac80211/wpa.c | 13 ++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 0825d76..2291cd7 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -492,6 +492,7 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, for (j = 0; j < len; j++) key->u.gen.rx_pn[i][j] = seq[len - j - 1]; + key->flags |= KEY_FLAG_CIPHER_SCHEME; } } memcpy(key->conf.key, key_data, key_len); diff --git a/net/mac80211/key.h b/net/mac80211/key.h index d57a9915..2fe2e2b 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -34,6 +34,7 @@ struct sta_info; enum ieee80211_internal_key_flags { KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), KEY_FLAG_TAINTED= BIT(1), + KEY_FLAG_CIPHER_SCHEME = BIT(2), }; enum ieee80211_internal_tkip_state { diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 75de6fa..9d63d93 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -780,9 +780,8 @@ ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_key *key = tx->key; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - const struct ieee80211_cipher_scheme *cs = key->sta->cipher_scheme; int hdrlen; - u8 *pos; + u8 *pos, iv_len = key->conf.iv_len; if (info->control.hw_key && !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) { @@ -790,14 +789,14 @@ ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx, return TX_CONTINUE; } - if (unlikely(skb_headroom(skb) < cs->hdr_len && -pskb_expand_head(skb, cs->hdr_len, 0, GFP_ATOMIC))) + if (unlikely(skb_headroom(skb) < iv_len && +pskb_expand_head(skb, iv_len, 0, GFP_ATOMIC))) return TX_DROP; hdrlen = ieee80211_hdrlen(hdr->frame_control); - pos = skb_push(skb, cs->hdr_len); - memmove(pos, pos + cs->hdr_len, hdrlen); + pos = skb_push(skb, iv_len); + memmove(pos, pos + iv_len, hdrlen); return TX_CONTINUE; } @@ -1217,7 +1216,7 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx) if (!info->control.hw_key) return TX_DROP; - if (tx->key->sta->cipher_scheme) { + if (tx->key->flags & KEY_FLAG_CIPHER_SCHEME) { res = ieee80211_crypto_cs_encrypt(tx, skb); if (res != TX_CONTINUE) return res; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Mesh mode in ath10k
On Sat, Mar 14, 2015 at 08:09:27PM +0100, Dani Camps wrote: > Dear all, > > Has anyone tested mesh mode (802.11s) with ath10k? Any feedback about > potential problems encountered and hints to resolve them is > appreciated. Hi Dani, I've spent a little bit of time on it (on the order of an hour or two), so far without success. I can get the device to beacon with mesh beacons but have some sort of issue adding stations and haven't had a chance to debug it. You will at least need the raw mode patches from here: http://lists.infradead.org/pipermail/ath10k/2014-September/003206.html -- Bob Copeland %% http://bobcopeland.com/ -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3] mac80211: add an intermediate software queue implementation
On Tue, 2015-03-17 at 11:21 +0100, Felix Fietkau wrote: > +/** > + * DOC: mac80211 software tx queueing > + * > + * mac80211 provides an optional intermediate queueing implementation > designed > + * to allow the driver to keep hardware queues short and provide some > fairness > + * between different stations/interfaces. > + * In this model, the driver pulls data frames from the mac80211 queue > instead > + * of letting mac80211 push them via drv_tx(). Management frames are still > sent > + * via drv_tx(). IIRC there were some other frames - perhaps it should read "Some frames (e.g. management) are still sent via drv_tx()."? Also, I wonder if this is really correct, since bufferable management frames are probably *not* desired to go through that? > + * For AP powersave TIM handling, the driver only needs to indicate if it has > + * buffered packets in the driver specific data structures. Maybe you should say how to indicate it. > For frames buffered > + * in the ieee80211_txq struct, mac80211 sets TIM and the driver is expected > + * to dequeue and transmit packets on demand via the .release_buffered_frames > + * op. > + */ "via" reads odd here to me, perhaps say "to dequeue and transmit packets on demand as requested by the .release_buffered_frames op"? > @@ -1257,6 +1284,8 @@ struct ieee80211_vif { > u8 cab_queue; > u8 hw_queue[IEEE80211_NUM_ACS]; > > + struct ieee80211_txq *txq; This is just one txq, the mcast one? Perhaps that should be cab_txq then? Or is it multiple, then perhaps it should be "txqs"? > + struct ieee80211_txq *txq[IEEE80211_NUM_TIDS]; I wonder if there's a way to make this a single pointer here only? But I guess with variable-sized driver data this would be really difficult. > /** > + * struct ieee80211_txq - Software intermediate tx queue > + * > + * @vif: &struct ieee80211_vif pointer from the add_interface callback. > + * @sta: station table entry, may be NULL for per-vif queue > + * @tid: the TID for this queue (unset for per-vif queue) "unset" is probably not really true (and it's 0) - "unused" might be better? > @@ -1818,6 +1872,9 @@ enum ieee80211_hw_flags { > * @n_cipher_schemes: a size of an array of cipher schemes definitions. > * @cipher_schemes: a pointer to an array of cipher scheme definitions > * supported by HW. > + * > + * @txq_ac_max_pending: maximum number of frames per AC pending in all txq > + * entries for a vif. I think you should give some guidance on how to best set this value, like max aggregation size or something? I'm not really sure :) > +static inline void drv_wake_tx_queue(struct ieee80211_local *local, > + struct txq_info *txq) > +{ > + struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif); > + > + if (!check_sdata_in_driver(sdata)) > + return; > + > + if (txq->txq.sta) > + trace_drv_wake_sta_tx_queue(local, sdata, txq->txq.sta, > + txq->txq.tid); > + else > + trace_drv_wake_vif_tx_queue(local, sdata); Having separate tracepoints seems a bit strange - can't we unify them and have any necessary if inside the fast_assign() part of the macro? That way we stub out everything if tracing isn't enabled. > if (ndev) { > + struct txq_info *txqi = NULL; > + > + if (local->ops->wake_tx_queue) { > + txqi = kzalloc(sizeof(*txqi) + > + local->hw.txq_data_size, GFP_KERNEL); > + if (txqi) > + ieee80211_init_tx_queue(sdata, NULL, txqi, 0); Might be worth wrapping that into a single alloc_and_init() function? Or really just alloc() since the init could be implied? > void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) > { > + struct txq_info *txqi; > ASSERT_RTNL(); > > mutex_lock(&sdata->local->iflist_mtx); > @@ -1790,6 +1804,11 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data > *sdata) > > synchronize_rcu(); > > + if (sdata->vif.txq) { > + txqi = container_of(sdata->vif.txq, struct txq_info, txq); you could move the variable here > @@ -1831,6 +1851,12 @@ void ieee80211_remove_interfaces(struct > ieee80211_local *local) > list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { > list_del(&sdata->list); > > + if (sdata->vif.txq) { > + txqi = container_of(sdata->vif.txq, struct txq_info, > +txq); similar here > @@ -1197,6 +1198,20 @@ static void sta_ps_start(struct sta_info *sta) > drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); > ps_dbg(sdata, "STA %pM aid %d enters power save mode\n", > sta->sta.addr, sta->sta.aid); > + > + if (!sta->txqi) > + return; > + > + for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) { > +
RE: [PATCH 1/3] mwifiex: add cfg80211 set_default_mgmt_key handler
> -Original Message- > From: Johannes Berg [mailto:johan...@sipsolutions.net] > Sent: Friday, February 13, 2015 11:37 PM > To: Avinash Patil > Cc: linux-wireless@vger.kernel.org; Amitkumar Karwar; Cathy Luo; Xinming Hu; > Li Long > Subject: Re: [PATCH 1/3] mwifiex: add cfg80211 set_default_mgmt_key handler > > On Thu, 2015-02-12 at 23:45 +0530, Avinash Patil wrote: > > From: Xinming Hu > > > > It is observed that hostapd failed to setup with management frame > > protection mode enabled when using mwifiex. > > > > This is because hostapd will try to install IGTK using > > cfg80211 set_default_mgmt_key handler. > > > > we have already support IGTK install in set_key handler, so just work > > around this issue by add an empty cfg80211_set_default_mgmt_key handler. > > I believe that this is incorrect since the key should only be installed for TX > after this handler, not in the set_key handler. This should make a difference > in the case of rekeying? Perhaps hostapd doesn't actually program the key > until rekeying with all stations finishes though. I believe that set_defualt_mgmt_key and corresponding changes in hostapd & cfg80211 are designed with focus on mac80211. Our design is a bit different in a way all PMF is handled in FW; also we don't support two pair of GTK/IGTKs. We already have installed IGTK to FW in add_key handler. > johannes
Re: [PATCH v4] mac80211: Get IV len from key conf and not cipher scheme
On Tue, 2015-03-17 at 10:47 +, Cedric Izoard wrote: > When a key is installed using a cipher scheme, a new internal > flag KEY_FLAG_CIPHER_SCHEME is set. > This flag is used on TX path to test for "cipher scheme" > key, instead of testing for sta->cipher_scheme as sta > is NULL for bcast/mcast messages. > For cipher scheme key, security header length is then > read from key->conf.iv_len initialized with cs->hdr_len. Applied. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3] mac80211: add an intermediate software queue implementation
On 2015-03-17 12:24, Johannes Berg wrote: > On Tue, 2015-03-17 at 11:21 +0100, Felix Fietkau wrote: >> @@ -1257,6 +1284,8 @@ struct ieee80211_vif { >> u8 cab_queue; >> u8 hw_queue[IEEE80211_NUM_ACS]; >> >> +struct ieee80211_txq *txq; > > This is just one txq, the mcast one? Perhaps that should be cab_txq > then? That would be misleading, since this queue is only used when CAB isn't (i.e. no sta in PS). > Or is it multiple, then perhaps it should be "txqs"? > >> +struct ieee80211_txq *txq[IEEE80211_NUM_TIDS]; > > I wonder if there's a way to make this a single pointer here only? But I > guess with variable-sized driver data this would be really difficult. Maybe a potential optimization for later - I'd like to keep it simple for now... >> @@ -1818,6 +1872,9 @@ enum ieee80211_hw_flags { >> * @n_cipher_schemes: a size of an array of cipher schemes definitions. >> * @cipher_schemes: a pointer to an array of cipher scheme definitions >> * supported by HW. >> + * >> + * @txq_ac_max_pending: maximum number of frames per AC pending in all txq >> + * entries for a vif. > > I think you should give some guidance on how to best set this value, > like max aggregation size or something? I'm not really sure :) I don't have any guidance for tuning this in the driver just yet. For devices with software aggregation, it should just be left at the default value. >> +if (sta_prepare_rate_control(local, sta, gfp)) >> +goto free_txq; > > Does it even have to come before rate control? It doesn't have to, but I figured cleanup is simpler that way. >> @@ -1090,10 +1119,25 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info >> *sta) >> >> BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); >> sta->driver_buffered_tids = 0; >> +sta->txq_buffered_tids = 0; >> >> if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) >> drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); >> >> +if (sta->txqi) { >> +for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { >> +struct txq_info *txqi; >> + >> +txqi = container_of(sta->sta.txq[i], struct txq_info, >> +txq); >> + >> +if (!skb_queue_len(&txqi->queue)) >> +continue; >> + >> +drv_wake_tx_queue(local, txqi); >> +} >> +} > > This could be an interesting race. If you wake the queue, and then the > station goes to sleep again before the driver had a chance to pull > frames, what happens? Should the driver be responsible for this? But you > don't have "unwake_tx_queue", so maybe you should not return any frame > from the dequeue in such a case? The driver is responsible for making sure that any queue of a sleeping sta is not scheduled. >> @@ -1447,6 +1493,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, >> >> sta_info_recalc_tim(sta); >> } else { >> +unsigned long tids = sta->txq_buffered_tids & >> driver_release_tids; > > I'm not sure I understand this. Are you treating txq_buffered_tids as > driver-buffered? Yes. As explained in the DOC section, PS delivery of txq buffered frames goes through drv_release_buffered_frames. Maybe I could change the wording a bit to make it more clear. >> @@ -368,6 +369,8 @@ struct sta_info { >> struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; >> struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; >> unsigned long driver_buffered_tids; >> +unsigned long txq_buffered_tids; >> +struct txq_info *txqi; > > Hm, so, internally you allocate one big thing and externally to the > driver you have a per-TID array. > > Why not just remove this pointer, and keep only the per-TID array? You'd > have to do a bit more container_of() but I don't think that's a big > deal? Plus you can't really use this anyway since you can't index it, > i.e. you cannot say sta->txqi[t] since the size doesn't match up. Will do >> +static void ieee80211_drv_tx(struct ieee80211_local *local, >> + struct ieee80211_vif *vif, >> + struct ieee80211_sta *pubsta, >> + struct sk_buff *skb) >> +{ >> +struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; >> +struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); >> +struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); >> +struct ieee80211_tx_control control = { >> +.sta = pubsta >> +}; >> +struct ieee80211_txq *txq = NULL; >> +struct txq_info *txqi; >> +u8 ac; >> + >> +if (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE) >> +goto tx_normal; >> + >> +if (ieee80211_is_mgmt(hdr->frame_control) || >> +ieee80211_is_ctl(hdr->frame_control)) >> +goto tx_normal; > > Doesn't this become awkward with powersave handling for bufferable mgmt > frames? They'd be st
[PATCH] brcmfmac: cfg80211: use msecs_to_jiffies for time conversion
Converting milliseconds to jiffies by "val * HZ / 1000" is technically OK but msecs_to_jiffies(val) is the cleaner solution and handles all corner cases correctly. This is a minor API consolidation only and should make things more readable. Patch was compile tested with x86_64_defconfig + CONFIG_BRCMFMAC=m Patch is agianst 4.0-rc4 (localversion-next is -next-20150317) Signed-off-by: Nicholas Mc Guire --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 9b805c9..1996dc2 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -1110,7 +1110,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif, /* Arm scan timeout timer */ mod_timer(&cfg->escan_timeout, jiffies + - WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000); + msecs_to_jiffies(WL_ESCAN_TIMER_INTERVAL_MS)); return 0; -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 0/7] ath10k: add multi-channel support
New qca6174 with wmi-tlv firmware supports multi-channel operation. To make use of it ath10k needs a few changes: implement mac80211's chanctx API and rework tx queue control a bit. Changes since RFC: * I've sent `ath10k: defer AP self-peer removal wait` separately now because it's not really required for multi-channel per se v2: * fix null deref after rebasing * fix commit log typo v3: * remove some duplication wrt mac80211 [Johannes] * small fixes v4: * rebased * fix STA CSA * drop ar->arvifs data_lock protection patch * drop ar->arvifs for vif iteration in favour of ieee80211_iterate_active_interfaces() * small refactor in monitor recalc * add a patch to fix fw resource allocation for multi-vif/chan Michal Kazior (7): ath10k: allow empty ssid vdev config ath10k: implement chanctx API ath10k: implement adaptive qcs command ath10k: rework tx queue locking ath10k: implement tx pause wmi event ath10k: enable multi-channel on supported devices ath10k: allocate fw resources for iface combinations drivers/net/wireless/ath/ath10k/core.h| 18 + drivers/net/wireless/ath/ath10k/htt_rx.c | 102 +++- drivers/net/wireless/ath/ath10k/htt_tx.c | 4 +- drivers/net/wireless/ath/ath10k/hw.h | 6 +- drivers/net/wireless/ath/ath10k/mac.c | 940 ++ drivers/net/wireless/ath/ath10k/mac.h | 24 + drivers/net/wireless/ath/ath10k/wmi-ops.h | 16 + drivers/net/wireless/ath/ath10k/wmi-tlv.c | 88 ++- drivers/net/wireless/ath/ath10k/wmi-tlv.h | 46 ++ drivers/net/wireless/ath/ath10k/wmi.c | 18 +- drivers/net/wireless/ath/ath10k/wmi.h | 1 + 11 files changed, 1125 insertions(+), 138 deletions(-) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 2/7] ath10k: implement chanctx API
The chanctx API will allow ath10k to support multi-channel operation. Signed-off-by: Michal Kazior --- Notes: v2: * prevent null deref in ath10k_peer_assoc_h_vht() after rebasing to latest master branch v3: * remove chanctx internal ath10k list [Johannes] (I still keep local chandef copy) * remove arvif->arctx and use vif->chanctx_conf directly * remove ar->chandef * fix typo sanity check (arvif->arctx was checked twice in rx_h_peer_channel; arvif itself should be checked too) * skip presp template setup for IBSS v4; * fix CSA * refactor monitor recalc code a bit drivers/net/wireless/ath/ath10k/core.h | 10 + drivers/net/wireless/ath/ath10k/htt_rx.c | 102 - drivers/net/wireless/ath/ath10k/mac.c| 683 +-- drivers/net/wireless/ath/ath10k/mac.h| 11 + drivers/net/wireless/ath/ath10k/wmi.c| 13 +- 5 files changed, 697 insertions(+), 122 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index c1f43b0..d54e12d 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -281,6 +281,15 @@ struct ath10k_sta { #endif }; +struct ath10k_chanctx { + /* Used to story copy of chanctx_conf to avoid inconsistencies. Ideally +* mac80211 should allow some sort of explicit locking to guarantee +* that the publicly available chanctx_conf can be accessed safely at +* all times. +*/ + struct ieee80211_chanctx_conf conf; +}; + #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ) enum ath10k_beacon_state { @@ -596,6 +605,7 @@ struct ath10k { struct cfg80211_chan_def chandef; unsigned long long free_vdev_map; + struct ath10k_vif *monitor_arvif; bool monitor; int monitor_vdev_id; bool monitor_started; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 01a2b38..daf9d2f 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -773,8 +773,89 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, } } +static struct ieee80211_channel * +ath10k_htt_rx_h_peer_channel(struct ath10k *ar, struct htt_rx_desc *rxd) +{ + struct ath10k_peer *peer; + struct ath10k_vif *arvif; + struct ath10k_chanctx *arctx; + u16 peer_id; + + lockdep_assert_held(&ar->data_lock); + + if (!rxd) + return NULL; + + if (rxd->attention.flags & + __cpu_to_le32(RX_ATTENTION_FLAGS_PEER_IDX_INVALID)) + return NULL; + + if (!(rxd->msdu_end.info0 & + __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU))) + return NULL; + + peer_id = MS(__le32_to_cpu(rxd->mpdu_start.info0), +RX_MPDU_START_INFO0_PEER_IDX); + + peer = ath10k_peer_find_by_id(ar, peer_id); + if (!peer) + return NULL; + + arvif = ath10k_get_arvif(ar, peer->vdev_id); + if (WARN_ON_ONCE(!arvif)) + return NULL; + + arctx = ath10k_mac_vif_ctx(arvif); + if (WARN_ON_ONCE(!arctx)) + return NULL; + + return arctx->conf.def.chan; +} + +static struct ieee80211_channel * +ath10k_htt_rx_h_vdev_channel(struct ath10k *ar, u32 vdev_id) +{ + struct ath10k_vif *arvif; + struct ath10k_chanctx *arctx; + + lockdep_assert_held(&ar->data_lock); + + list_for_each_entry(arvif, &ar->arvifs, list) { + arctx = ath10k_mac_vif_ctx(arvif); + + if (arvif->vdev_id == vdev_id && arctx) + return arctx->conf.def.chan; + } + + return NULL; +} + +static void +ath10k_htt_rx_h_any_chan_iter(struct ieee80211_hw *hw, + struct ieee80211_chanctx_conf *conf, + void *data) +{ + struct cfg80211_chan_def *def = data; + + *def = conf->def; +} + +static struct ieee80211_channel * +ath10k_htt_rx_h_any_channel(struct ath10k *ar) +{ + struct cfg80211_chan_def def = {}; + + ieee80211_iter_chan_contexts_atomic(ar->hw, + ath10k_htt_rx_h_any_chan_iter, + &def); + + return def.chan; +} + static bool ath10k_htt_rx_h_channel(struct ath10k *ar, - struct ieee80211_rx_status *status) + struct ieee80211_rx_status *status, + struct htt_rx_desc *rxd, + u32 vdev_id) { struct ieee80211_channel *ch; @@ -782,6 +863,12 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar, ch = ar->scan_channel; if (!ch) ch = ar->rx_channel; + if (!ch) + ch = ath10k_htt_rx_h_peer_channel(ar, rxd); + if (
[PATCH v4 3/7] ath10k: implement adaptive qcs command
This command will be used to configure multi-channel scheduler in firmware. Signed-off-by: Michal Kazior --- drivers/net/wireless/ath/ath10k/wmi-ops.h | 16 drivers/net/wireless/ath/ath10k/wmi-tlv.c | 30 ++ drivers/net/wireless/ath/ath10k/wmi-tlv.h | 4 drivers/net/wireless/ath/ath10k/wmi.c | 3 +++ drivers/net/wireless/ath/ath10k/wmi.h | 1 + 5 files changed, 54 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index f0a8b8d..3c8325c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -150,6 +150,7 @@ struct wmi_ops { u32 num_ac); struct sk_buff *(*gen_sta_keepalive)(struct ath10k *ar, const struct wmi_sta_keepalive_arg *arg); + struct sk_buff *(*gen_adaptive_qcs)(struct ath10k *ar, bool enable); }; int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); @@ -1072,4 +1073,19 @@ ath10k_wmi_sta_keepalive(struct ath10k *ar, return ath10k_wmi_cmd_send(ar, skb, cmd_id); } +static inline int +ath10k_wmi_adaptive_qcs(struct ath10k *ar, bool enable) +{ + struct sk_buff *skb; + + if (!ar->wmi.ops->gen_adaptive_qcs) + return -EOPNOTSUPP; + + skb = ar->wmi.ops->gen_adaptive_qcs(ar, enable); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->adaptive_qcs_cmdid); +} + #endif diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index fa3eb1b..a359a7e 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -2561,6 +2561,34 @@ ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie(struct ath10k *ar, u32 vdev_id, return skb; } +static struct sk_buff * +ath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k *ar, bool enable) +{ + struct wmi_tlv_adaptive_qcs *cmd; + struct wmi_tlv *tlv; + struct sk_buff *skb; + void *ptr; + size_t len; + + len = sizeof(*tlv) + sizeof(*cmd); + skb = ath10k_wmi_alloc_skb(ar, len); + if (!skb) + return ERR_PTR(-ENOMEM); + + ptr = (void *)skb->data; + tlv = ptr; + tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_RESMGR_ADAPTIVE_OCS_CMD); + tlv->len = __cpu_to_le16(sizeof(*cmd)); + cmd = (void *)tlv->value; + cmd->enable = __cpu_to_le32(enable ? 1 : 0); + + ptr += sizeof(*tlv); + ptr += sizeof(*cmd); + + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv adaptive qcs %d\n", enable); + return skb; +} + // /* TLV mappings */ // @@ -2685,6 +2713,7 @@ static struct wmi_cmd_map wmi_tlv_cmd_map = { .gpio_output_cmdid = WMI_TLV_GPIO_OUTPUT_CMDID, .pdev_get_temperature_cmdid = WMI_TLV_CMD_UNSUPPORTED, .vdev_set_wmm_params_cmdid = WMI_TLV_VDEV_SET_WMM_PARAMS_CMDID, + .adaptive_qcs_cmdid = WMI_TLV_RESMGR_ADAPTIVE_OCS_CMDID, }; static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = { @@ -2858,6 +2887,7 @@ static const struct wmi_ops wmi_tlv_ops = { .gen_p2p_go_bcn_ie = ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie, .gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd, .gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive, + .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs, }; // diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index 06b37b2..1b373f2 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -1464,6 +1464,10 @@ struct wmi_tlv_roam_ev { __le32 rssi; } __packed; +struct wmi_tlv_adaptive_qcs { + __le32 enable; +} __packed; + void ath10k_wmi_tlv_attach(struct ath10k *ar); #endif diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index eb66fc4..34412ee 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -5249,6 +5249,7 @@ static const struct wmi_ops wmi_ops = { /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ + /* .gen_adaptive_qcs not implemented */ }; static const struct wmi_ops wmi_10_1_ops = { @@ -5312,6 +5313,7 @@ static const struct wmi_ops wmi_10_1_ops = { /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_go_bcn_ie not implemented */ + /* .gen_adaptive_qcs not implemented */ }; static const struct wmi_ops wmi_10_2_ops = { @@ -5436,6 +5438,7 @@ static const struct wmi_ops wmi_10_2_4_ops = { /* .gen_bcn_tmpl not implemented */ /* .gen_prb_tmpl not implemented */ /* .gen_p2p_g
[PATCH v4 1/7] ath10k: allow empty ssid vdev config
It doesn't make much sense to reject a valid firmware configuration combination. Since SSID isn't known early on it might make sense to allow driver to start vdev without SSID and restart it later. Signed-off-by: Michal Kazior --- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 -- drivers/net/wireless/ath/ath10k/wmi.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 3eec042..fa3eb1b 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1486,8 +1486,6 @@ ath10k_wmi_tlv_op_gen_vdev_start(struct ath10k *ar, void *ptr; u32 flags = 0; - if (WARN_ON(arg->ssid && arg->ssid_len == 0)) - return ERR_PTR(-EINVAL); if (WARN_ON(arg->hidden_ssid && !arg->ssid)) return ERR_PTR(-EINVAL); if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 54430a1..7b3e6ca 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -4286,8 +4286,6 @@ ath10k_wmi_op_gen_vdev_start(struct ath10k *ar, const char *cmdname; u32 flags = 0; - if (WARN_ON(arg->ssid && arg->ssid_len == 0)) - return ERR_PTR(-EINVAL); if (WARN_ON(arg->hidden_ssid && !arg->ssid)) return ERR_PTR(-EINVAL); if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 7/7] ath10k: allocate fw resources for iface combinations
The number of 3 vdevs wasn't enough to handle the worst case for interface combinations in practice. wpa_supplicant may need up to 4 vifs to have 2 vifs actually connected, i.e. p2pdev + client + 2x p2p (either p2p client or p2p go). This fixes worst case warning: Free vdev map is empty, no more interfaces allowed. This keeps the ability to associate 32 stations in AP mode at the cost of not being able to guarantee that under all circumstances, i.e. some combinations may consume additional fw peer entries for internal purposes leaving less resource for stations in AP mode. Signed-off-by: Michal Kazior --- drivers/net/wireless/ath/ath10k/hw.h | 6 ++ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 8 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 7f04645..904ce48 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -256,11 +256,9 @@ struct ath10k_pktlog_hdr { #define TARGET_10_2_DMA_BURST_SIZE 1 /* Target specific defines for WMI-TLV firmware */ -#define TARGET_TLV_NUM_VDEVS 3 +#define TARGET_TLV_NUM_VDEVS 4 #define TARGET_TLV_NUM_STATIONS32 -#define TARGET_TLV_NUM_PEERS ((TARGET_TLV_NUM_STATIONS) + \ -(TARGET_TLV_NUM_VDEVS) + \ -2) +#define TARGET_TLV_NUM_PEERS 35 #define TARGET_TLV_NUM_TIDS((TARGET_TLV_NUM_PEERS) * 2) #define TARGET_TLV_NUM_MSDU_DESC (1024 + 32) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 45f8431..d92fedf 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1286,8 +1286,8 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS); if (test_bit(WMI_SERVICE_RX_FULL_REORDER, ar->wmi.svc_map)) { - cfg->num_offload_peers = __cpu_to_le32(3); - cfg->num_offload_reorder_bufs = __cpu_to_le32(3); + cfg->num_offload_peers = __cpu_to_le32(TARGET_TLV_NUM_VDEVS); + cfg->num_offload_reorder_bufs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS); } else { cfg->num_offload_peers = __cpu_to_le32(0); cfg->num_offload_reorder_bufs = __cpu_to_le32(0); @@ -1304,8 +1304,8 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) cfg->rx_timeout_pri[3] = __cpu_to_le32(0x28); cfg->rx_decap_mode = __cpu_to_le32(1); cfg->scan_max_pending_reqs = __cpu_to_le32(4); - cfg->bmiss_offload_max_vdev = __cpu_to_le32(3); - cfg->roam_offload_max_vdev = __cpu_to_le32(3); + cfg->bmiss_offload_max_vdev = __cpu_to_le32(TARGET_TLV_NUM_VDEVS); + cfg->roam_offload_max_vdev = __cpu_to_le32(TARGET_TLV_NUM_VDEVS); cfg->roam_offload_max_ap_profiles = __cpu_to_le32(8); cfg->num_mcast_groups = __cpu_to_le32(0); cfg->num_mcast_table_elems = __cpu_to_le32(0); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 5/7] ath10k: implement tx pause wmi event
qca6174 wmi-tlv firmware defines a new wmi event for host tx pausing (i.e. stop/wake tx queues). Map these events to ath10k/mac80211 tx queue control. This is important for multi-channel throughput performance. Signed-off-by: Michal Kazior --- Notes: v2: * s/thourghput/throughput/ in commit log v4: * use ieee80211_iterate_active_interfaces_atomic() instead of ar->arvifs drivers/net/wireless/ath/ath10k/mac.c | 90 +++ drivers/net/wireless/ath/ath10k/mac.h | 8 +++ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 48 + drivers/net/wireless/ath/ath10k/wmi-tlv.h | 42 +++ 4 files changed, 188 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 185be19..e6b0746 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -28,6 +28,7 @@ #include "txrx.h" #include "testmode.h" #include "wmi.h" +#include "wmi-tlv.h" #include "wmi-ops.h" /**/ @@ -2773,6 +2774,83 @@ void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason) ieee80211_wake_queue(ar->hw, arvif->vdev_id); } +static void ath10k_mac_vif_handle_tx_pause(struct ath10k_vif *arvif, + enum wmi_tlv_tx_pause_id pause_id, + enum wmi_tlv_tx_pause_action action) +{ + struct ath10k *ar = arvif->ar; + + lockdep_assert_held(&ar->htt.tx_lock); + + switch (pause_id) { + case WMI_TLV_TX_PAUSE_ID_MCC: + case WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA: + case WMI_TLV_TX_PAUSE_ID_P2P_GO_PS: + case WMI_TLV_TX_PAUSE_ID_AP_PS: + case WMI_TLV_TX_PAUSE_ID_IBSS_PS: + switch (action) { + case WMI_TLV_TX_PAUSE_ACTION_STOP: + ath10k_mac_vif_tx_lock(arvif, pause_id); + break; + case WMI_TLV_TX_PAUSE_ACTION_WAKE: + ath10k_mac_vif_tx_unlock(arvif, pause_id); + break; + default: + ath10k_warn(ar, "received unknown tx pause action %d on vdev %i, ignoring\n", + action, arvif->vdev_id); + break; + } + break; + case WMI_TLV_TX_PAUSE_ID_AP_PEER_PS: + case WMI_TLV_TX_PAUSE_ID_AP_PEER_UAPSD: + case WMI_TLV_TX_PAUSE_ID_STA_ADD_BA: + case WMI_TLV_TX_PAUSE_ID_HOST: + default: + /* FIXME: Some pause_ids aren't vdev specific. Instead they +* target peer_id and tid. Implementing these could improve +* traffic scheduling fairness across multiple connected +* stations in AP/IBSS modes. +*/ + ath10k_dbg(ar, ATH10K_DBG_MAC, + "mac ignoring unsupported tx pause vdev %i id %d\n", + arvif->vdev_id, pause_id); + break; + } +} + +struct ath10k_mac_tx_pause { + u32 vdev_id; + enum wmi_tlv_tx_pause_id pause_id; + enum wmi_tlv_tx_pause_action action; +}; + +static void ath10k_mac_handle_tx_pause_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_mac_tx_pause *arg = data; + + ath10k_mac_vif_handle_tx_pause(arvif, arg->pause_id, arg->action); +} + +void ath10k_mac_handle_tx_pause(struct ath10k *ar, u32 vdev_id, + enum wmi_tlv_tx_pause_id pause_id, + enum wmi_tlv_tx_pause_action action) +{ + struct ath10k_mac_tx_pause arg = { + .vdev_id = vdev_id, + .pause_id = pause_id, + .action = action, + }; + + spin_lock_bh(&ar->htt.tx_lock); + ieee80211_iterate_active_interfaces_atomic(ar->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + ath10k_mac_handle_tx_pause_iter, + &arg); + spin_unlock_bh(&ar->htt.tx_lock); +} + static u8 ath10k_tx_h_get_tid(struct ieee80211_hdr *hdr) { if (ieee80211_is_mgmt(hdr->frame_control)) @@ -3920,6 +3998,14 @@ err: return ret; } +static void ath10k_mac_vif_tx_unlock_all(struct ath10k_vif *arvif) +{ + int i; + + for (i = 0; i < BITS_PER_LONG; i++) + ath10k_mac_vif_tx_unlock(arvif, i); +} + static void ath10k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { @@ -3986,6 +4072,10 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, ath10k_warn(ar, "failed to recalc monitor: %d\n", ret); } + spin_lock_bh(&ar->htt.tx_lock); + ath10k_mac_vif_tx_un
[PATCH v4 6/7] ath10k: enable multi-channel on supported devices
This effectively enables multi-channel operation on qca6174 WLAN.RM.2.0-00073 (and possibly any newer firmware release for qca6174). This adds appopriate interface combinations and initializes firmware channel scheduler. Signed-off-by: Michal Kazior --- drivers/net/wireless/ath/ath10k/mac.c | 81 ++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index e6b0746..dc51c80 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3492,6 +3492,15 @@ static int ath10k_start(struct ieee80211_hw *hw) goto err_core_stop; } + if (test_bit(WMI_SERVICE_ADAPTIVE_OCS, ar->wmi.svc_map)) { + ret = ath10k_wmi_adaptive_qcs(ar, true); + if (ret) { + ath10k_warn(ar, "failed to enable adaptive qcs: %d\n", + ret); + goto err_core_stop; + } + } + if (ar->cfg_tx_chainmask) __ath10k_set_antenna(ar, ar->cfg_tx_chainmask, ar->cfg_rx_chainmask); @@ -6205,6 +6214,64 @@ static const struct ieee80211_iface_combination ath10k_10x_if_comb[] = { }, }; +static const struct ieee80211_iface_limit ath10k_tlv_if_limit[] = { + { + .max = 2, + .types = BIT(NL80211_IFTYPE_STATION) | +BIT(NL80211_IFTYPE_AP) | +BIT(NL80211_IFTYPE_P2P_CLIENT) | +BIT(NL80211_IFTYPE_P2P_GO), + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_DEVICE), + }, +}; + +static const struct ieee80211_iface_limit ath10k_tlv_if_limit_ibss[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_STATION), + }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_ADHOC), + }, +}; + +/* FIXME: This is not thouroughly tested. These combinations may over- or + * underestimate hw/fw capabilities. + */ +static struct ieee80211_iface_combination ath10k_tlv_if_comb[] = { + { + .limits = ath10k_tlv_if_limit, + .num_different_channels = 1, + .max_interfaces = 2, + .n_limits = ARRAY_SIZE(ath10k_tlv_if_limit), + }, + { + .limits = ath10k_tlv_if_limit_ibss, + .num_different_channels = 1, + .max_interfaces = 2, + .n_limits = ARRAY_SIZE(ath10k_tlv_if_limit_ibss), + }, +}; + +static struct ieee80211_iface_combination ath10k_tlv_qcs_if_comb[] = { + { + .limits = ath10k_tlv_if_limit, + .num_different_channels = 2, + .max_interfaces = 2, + .n_limits = ARRAY_SIZE(ath10k_tlv_if_limit), + }, + { + .limits = ath10k_tlv_if_limit_ibss, + .num_different_channels = 1, + .max_interfaces = 2, + .n_limits = ARRAY_SIZE(ath10k_tlv_if_limit_ibss), + }, +}; + static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) { struct ieee80211_sta_vht_cap vht_cap = {0}; @@ -6484,12 +6551,24 @@ int ath10k_mac_register(struct ath10k *ar) switch (ar->wmi.op_version) { case ATH10K_FW_WMI_OP_VERSION_MAIN: - case ATH10K_FW_WMI_OP_VERSION_TLV: ar->hw->wiphy->iface_combinations = ath10k_if_comb; ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ath10k_if_comb); ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); break; + case ATH10K_FW_WMI_OP_VERSION_TLV: + if (test_bit(WMI_SERVICE_ADAPTIVE_OCS, ar->wmi.svc_map)) { + ar->hw->wiphy->iface_combinations = + ath10k_tlv_qcs_if_comb; + ar->hw->wiphy->n_iface_combinations = + ARRAY_SIZE(ath10k_tlv_qcs_if_comb); + } else { + ar->hw->wiphy->iface_combinations = ath10k_tlv_if_comb; + ar->hw->wiphy->n_iface_combinations = + ARRAY_SIZE(ath10k_tlv_if_comb); + } + ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); + break; case ATH10K_FW_WMI_OP_VERSION_10_1: case ATH10K_FW_WMI_OP_VERSION_10_2: case ATH10K_FW_WMI_OP_VERSION_10_2_4: -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 4/7] ath10k: rework tx queue locking
Tx queue locking was very simple until now. Multi-channel support will require a more flexible and fine grained control. This introduces a per-hw and per-vif (each with a bitmask of reasons) tx queue locking. Signed-off-by: Michal Kazior --- Notes: v4: * use ieee80211_iterate_active_interfaces_atomic() instead of ar->arvifs drivers/net/wireless/ath/ath10k/core.h | 8 +++ drivers/net/wireless/ath/ath10k/htt_tx.c | 4 +- drivers/net/wireless/ath/ath10k/mac.c| 88 +++- drivers/net/wireless/ath/ath10k/mac.h| 5 ++ 4 files changed, 101 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index d54e12d..b99871a 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -311,6 +311,7 @@ struct ath10k_vif { enum ath10k_beacon_state beacon_state; void *beacon_buf; dma_addr_t beacon_paddr; + unsigned long tx_paused; /* arbitrary values defined by target */ struct ath10k *ar; struct ieee80211_vif *vif; @@ -510,6 +511,11 @@ static inline const char *ath10k_scan_state_str(enum ath10k_scan_state state) return "unknown"; } +enum ath10k_tx_pause_reason { + ATH10K_TX_PAUSE_Q_FULL, + ATH10K_TX_PAUSE_MAX, +}; + struct ath10k { struct ath_common ath_common; struct ieee80211_hw *hw; @@ -668,6 +674,8 @@ struct ath10k { struct dfs_pattern_detector *dfs_detector; + unsigned long tx_paused; /* see ATH10K_TX_PAUSE_ */ + #ifdef CONFIG_ATH10K_DEBUGFS struct ath10k_debug debug; #endif diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index cbd2bc9..c67b385 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -26,7 +26,7 @@ void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) { htt->num_pending_tx--; if (htt->num_pending_tx == htt->max_num_pending_tx - 1) - ieee80211_wake_queues(htt->ar->hw); + ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); } static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt) @@ -49,7 +49,7 @@ static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) htt->num_pending_tx++; if (htt->num_pending_tx == htt->max_num_pending_tx) - ieee80211_stop_queues(htt->ar->hw); + ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); exit: spin_unlock_bh(&htt->tx_lock); diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 8b64313..185be19 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -2707,6 +2707,72 @@ static void ath10k_reg_notifier(struct wiphy *wiphy, /* TX handlers */ /***/ +void ath10k_mac_tx_lock(struct ath10k *ar, int reason) +{ + lockdep_assert_held(&ar->htt.tx_lock); + + WARN_ON(reason >= ATH10K_TX_PAUSE_MAX); + ar->tx_paused |= BIT(reason); + ieee80211_stop_queues(ar->hw); +} + +static void ath10k_mac_tx_unlock_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct ath10k *ar = data; + struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + + if (arvif->tx_paused) + return; + + ieee80211_wake_queue(ar->hw, arvif->vdev_id); +} + +void ath10k_mac_tx_unlock(struct ath10k *ar, int reason) +{ + lockdep_assert_held(&ar->htt.tx_lock); + + WARN_ON(reason >= ATH10K_TX_PAUSE_MAX); + ar->tx_paused &= ~BIT(reason); + + if (ar->tx_paused) + return; + + ieee80211_iterate_active_interfaces_atomic(ar->hw, + IEEE80211_IFACE_ITER_RESUME_ALL, + ath10k_mac_tx_unlock_iter, + ar); +} + +void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason) +{ + struct ath10k *ar = arvif->ar; + + lockdep_assert_held(&ar->htt.tx_lock); + + WARN_ON(reason >= BITS_PER_LONG); + arvif->tx_paused |= BIT(reason); + ieee80211_stop_queue(ar->hw, arvif->vdev_id); +} + +void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason) +{ + struct ath10k *ar = arvif->ar; + + lockdep_assert_held(&ar->htt.tx_lock); + + WARN_ON(reason >= BITS_PER_LONG); + arvif->tx_paused &= ~BIT(reason); + + if (ar->tx_paused) + return; + + if (arvif->tx_paused) + return; + + ieee80211_wake_queue(ar->hw, arvif->vdev_id); +} + static u8 ath10k_tx_h_get_tid(struct ieee80211_hdr *hdr) { if (ieee80211_is_mgmt(hdr->frame_control)) @@ -3200,6 +3266,7 @@ void ath10k_halt(struct ath10k *ar) ath10k_monitor_stop(ar); ar->monitor_started = false;
Re: [PATCH v3] mac80211: add an intermediate software queue implementation
On Tue, 2015-03-17 at 13:04 +0100, Felix Fietkau wrote: > >> @@ -1090,10 +1119,25 @@ void ieee80211_sta_ps_deliver_wakeup(struct > >> sta_info *sta) [...] > >> + drv_wake_tx_queue(local, txqi); > >> + } > >> + } > > > > This could be an interesting race. If you wake the queue, and then the > > station goes to sleep again before the driver had a chance to pull > > frames, what happens? Should the driver be responsible for this? But you > > don't have "unwake_tx_queue", so maybe you should not return any frame > > from the dequeue in such a case? > The driver is responsible for making sure that any queue of a sleeping > sta is not scheduled. Right but you're asking it to wake up the queue here, and if it goes to sleep again quickly the driver might not have realized soon enough? I guess the device would filter the frames though so it's probably not a big deal, but could be interesting. > >> + struct txq_info *txqi; > > > > Hm, so, internally you allocate one big thing and externally to the > > driver you have a per-TID array. > > > > Why not just remove this pointer, and keep only the per-TID array? You'd > > have to do a bit more container_of() but I don't think that's a big > > deal? Plus you can't really use this anyway since you can't index it, > > i.e. you cannot say sta->txqi[t] since the size doesn't match up. > Will do Actually freeing it might be interesting then? OTOH, you could just allocate each one separately as well, there's little to be gained from doing a bigger allocation for all of them. > > Doesn't this become awkward with powersave handling for bufferable mgmt > > frames? They'd be stored on the per-station non-txq queues, but then the > > wakeup handling needs to see which ones to take first? Having these on > > the txqs might make that part easier? > I guess I'll change it to throw bufferable mgmt frames in the txq as well. > > > OTOH, I guess it would make building A-MPDUs or even A-MSDUs far more > > complicated, so I guess it's a reasonable tradeoff. Yeah I'm not so sure it's a great idea though since it's certainly easier to do other things like A-MSDU/A-MPDU with only (QoS-)data frames here. Since, as you mentioned on IRC, you're also thinking about a sort of fastpath I think then we should restrict that to only data frames and not worry about any mgmt frames for such a fastpath. > >> + atomic_dec(&sdata->txqs_len[ac]); > >> + if (__netif_subqueue_stopped(sdata->dev, ac)) > >> + ieee80211_propagate_queue_wake(local, sdata->vif.hw_queue[ac]); > > > > Do you really want to do that unconditionally? There could be a lot of > > frames on the queue still, or even on other station queues? > Unconditionally? ieee80211_propagate_queue_wake checks the per-sdata txq > limit. Oh, right, I missed that part. > > Anyway - overall I think this looks pretty good. What we discussed in > > Ottawa was that we should perhaps forego the whole qdisc and netdev > > queue start/stop and just do something like the qdisc would do in the > > layer of these queues, although then we'd have to first convert every > > driver or make this layer mandatory in some other way. That's something > > we should explore here I think. > I agree. Figuring out what tx queue scheduling should look like for > devices with firmware based aggregation is going to be interesting > though... Yeah, though we're possibly also going to be moving in the direction of having hardware queues managed closer to the stations, so that the firmware could do better fairness between stations. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH iw v2 1/4] iw: move generic sched scan parsing code out of net detect
From: Luciano Coelho The scheduled scan structure is pretty much the same as the net-detect WoWLAN trigger's. Move the bulk of the command line parsing code to a generic function so we can reuse it for sched_scan. Signed-off-by: Luciano Coelho --- iw.h | 4 ++ scan.c | 170 + wowlan.c | 174 +++ 3 files changed, 181 insertions(+), 167 deletions(-) diff --git a/iw.h b/iw.h index db88a86..efc21d6 100644 --- a/iw.h +++ b/iw.h @@ -173,6 +173,10 @@ void print_ies(unsigned char *ie, int ielen, bool unknown, void parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen); void iw_hexdump(const char *prefix, const __u8 *data, size_t len); +#define SCHED_SCAN_OPTIONS "interval [delay ] " \ + "[freqs +] [matches [ssid ]+]]" +int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv); + DECLARE_SECTION(set); DECLARE_SECTION(get); diff --git a/scan.c b/scan.c index 538b30e..d1c3bf2 100644 --- a/scan.c +++ b/scan.c @@ -99,6 +99,176 @@ static int parse_random_mac_addr(struct nl_msg *msg, char *arg) return -ENOBUFS; } +int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv) +{ + struct nl_msg *matchset = NULL, *freqs = NULL; + struct nlattr *match = NULL; + enum { + ND_TOPLEVEL, + ND_MATCH, + ND_FREQS, + } parse_state = ND_TOPLEVEL; + int c = *argc; + char *end, **v = *argv; + int err = 0, i = 0; + unsigned int freq, interval = 0, delay = 0; + bool have_matchset = false, have_freqs = false; + + matchset = nlmsg_alloc(); + if (!matchset) { + err = -ENOBUFS; + goto out; + } + + freqs = nlmsg_alloc(); + if (!freqs) { + err = -ENOBUFS; + goto out; + } + + while (c) { + switch (parse_state) { + case ND_TOPLEVEL: + if (!strcmp(v[0], "interval")) { + c--; v++; + if (c == 0) { + err = -EINVAL; + goto nla_put_failure; + } + + if (interval) { + err = -EINVAL; + goto nla_put_failure; + } + interval = strtoul(v[0], &end, 10); + if (*end || !interval) { + err = -EINVAL; + goto nla_put_failure; + } + NLA_PUT_U32(msg, + NL80211_ATTR_SCHED_SCAN_INTERVAL, + interval); + } else if (!strcmp(v[0], "delay")) { + c--; v++; + if (c == 0) { + err = -EINVAL; + goto nla_put_failure; + } + + if (delay) { + err = -EINVAL; + goto nla_put_failure; + } + delay = strtoul(v[0], &end, 10); + if (*end) { + err = -EINVAL; + goto nla_put_failure; + } + NLA_PUT_U32(msg, + NL80211_ATTR_SCHED_SCAN_DELAY, + delay); + } else if (!strcmp(v[0], "matches")) { + parse_state = ND_MATCH; + if (have_matchset) { + err = -EINVAL; + goto nla_put_failure; + } + + i = 0; + } else if (!strcmp(v[0], "freqs")) { + parse_state = ND_FREQS; + if (have_freqs) { + err = -EINVAL; + goto nla_put_failure; + } + + have_freqs = true; + i = 0; + } else { + /* this element is not for us, so +* return to continue parsing. +*/ + goto nla_put_failure; + } + c--;
[PATCH iw v2 0/4] iw: add scheduled scan support
From: Luciano Coelho This series adds scheduled scan support to the iw tool (finally! ;). In v2, just rebased. Luciano Coelho (4): iw: move generic sched scan parsing code out of net detect iw: implement scheduled scan iw: add support for active scheduled scan iw: add randomise option for sched_scan event.c | 9 +++ info.c | 6 ++ iw.h | 4 + scan.c | 266 +++ wowlan.c | 174 ++--- 5 files changed, 292 insertions(+), 167 deletions(-) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH iw v2 2/4] iw: implement scheduled scan
From: Luciano Coelho Add sched_start, sched_stop and events parsing for scheduled scan. For now, only passive scans are supported. Signed-off-by: Luciano Coelho --- event.c | 9 + info.c | 6 ++ scan.c | 29 + 3 files changed, 44 insertions(+) diff --git a/event.c b/event.c index 71ab7f7..929854b 100644 --- a/event.c +++ b/event.c @@ -359,6 +359,15 @@ static int print_event(struct nl_msg *msg, void *arg) } printf("\n"); break; + case NL80211_CMD_START_SCHED_SCAN: + printf("scheduled scan started\n"); + break; + case NL80211_CMD_SCHED_SCAN_STOPPED: + printf("sched scan stopped\n"); + break; + case NL80211_CMD_SCHED_SCAN_RESULTS: + printf("got scheduled scan results\n"); + break; case NL80211_CMD_REG_CHANGE: printf("regulatory domain change: "); diff --git a/info.c b/info.c index 1df503f..66887e3 100644 --- a/info.c +++ b/info.c @@ -232,6 +232,12 @@ next: if (tb_msg[NL80211_ATTR_MAX_SCAN_IE_LEN]) printf("\tmax scan IEs length: %d bytes\n", nla_get_u16(tb_msg[NL80211_ATTR_MAX_SCAN_IE_LEN])); + if (tb_msg[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]) + printf("\tmax # sched scan SSIDs: %d\n", + nla_get_u8(tb_msg[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS])); + if (tb_msg[NL80211_ATTR_MAX_MATCH_SETS]) + printf("\tmax # match sets: %d\n", + nla_get_u8(tb_msg[NL80211_ATTR_MAX_MATCH_SETS])); if (tb_msg[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) { unsigned int frag; diff --git a/scan.c b/scan.c index d1c3bf2..e534fd4 100644 --- a/scan.c +++ b/scan.c @@ -1980,3 +1980,32 @@ COMMAND(scan, trigger, "[freq *] [ies ] [meshid ] NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan, "Trigger a scan on the given frequencies with probing for the given\n" "SSIDs (or wildcard if not given) unless passive scanning is requested."); + + +static int handle_start_sched_scan(struct nl80211_state *state, + struct nl_cb *cb, struct nl_msg *msg, + int argc, char **argv, enum id_input id) +{ + return parse_sched_scan(msg, &argc, &argv); +} + +static int handle_stop_sched_scan(struct nl80211_state *state, struct nl_cb *cb, + struct nl_msg *msg, int argc, char **argv, + enum id_input id) +{ + if (argc != 0) + return 1; + + return 0; +} + +COMMAND(scan, sched_start, + SCHED_SCAN_OPTIONS, + NL80211_CMD_START_SCHED_SCAN, 0, CIB_NETDEV, handle_start_sched_scan, + "Start a scheduled scan at the specified interval on the given frequencies\n" + "with probing for the given SSIDs (or wildcard if not given) unless passive\n" + "scanning is requested. If matches are specified, only matching results\n" + "will be returned."); +COMMAND(scan, sched_stop, "", + NL80211_CMD_STOP_SCHED_SCAN, 0, CIB_NETDEV, handle_stop_sched_scan, + "Stop an ongoing scheduled scan."); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH iw v2 3/4] iw: add support for active scheduled scan
From: Luciano Coelho Add options to explicitly use active or passive scans on schedule scans (and net-detect). If neither active nor passive parameters are passed, the default is to do active scans with the wildcard SSID. Signed-off-by: Luciano Coelho --- iw.h | 2 +- scan.c | 60 ++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/iw.h b/iw.h index efc21d6..fc20838 100644 --- a/iw.h +++ b/iw.h @@ -174,7 +174,7 @@ void parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen); void iw_hexdump(const char *prefix, const __u8 *data, size_t len); #define SCHED_SCAN_OPTIONS "interval [delay ] " \ - "[freqs +] [matches [ssid ]+]]" + "[freqs +] [matches [ssid ]+]] [active [ssid ]+|passive] " int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv); DECLARE_SECTION(set); diff --git a/scan.c b/scan.c index e534fd4..7ff04ec 100644 --- a/scan.c +++ b/scan.c @@ -101,18 +101,20 @@ static int parse_random_mac_addr(struct nl_msg *msg, char *arg) int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv) { - struct nl_msg *matchset = NULL, *freqs = NULL; + struct nl_msg *matchset = NULL, *freqs = NULL, *ssids = NULL; struct nlattr *match = NULL; enum { ND_TOPLEVEL, ND_MATCH, ND_FREQS, + ND_ACTIVE, } parse_state = ND_TOPLEVEL; int c = *argc; char *end, **v = *argv; int err = 0, i = 0; unsigned int freq, interval = 0, delay = 0; - bool have_matchset = false, have_freqs = false; + bool have_matchset = false, have_freqs = false, have_ssids = false; + bool have_active = false, have_passive = false; matchset = nlmsg_alloc(); if (!matchset) { @@ -126,6 +128,12 @@ int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv) goto out; } + ssids = nlmsg_alloc(); + if (!ssids) { + err = -ENOMEM; + goto out; + } + while (c) { switch (parse_state) { case ND_TOPLEVEL: @@ -184,6 +192,22 @@ int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv) have_freqs = true; i = 0; + } else if (!strcmp(v[0], "active")) { + parse_state = ND_ACTIVE; + if (have_active || have_passive) { + err = -EINVAL; + goto nla_put_failure; + } + + have_active = true; + i = 0; + } else if (!strcmp(v[0], "passive")) { + if (have_active || have_passive) { + err = -EINVAL; + goto nla_put_failure; + } + + have_passive = true; } else { /* this element is not for us, so * return to continue parsing. @@ -249,9 +273,41 @@ int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv) c--; v++; } break; + case ND_ACTIVE: + if (!strcmp(v[0], "ssid")) { + c--; v++; + if (c == 0) { + err = -EINVAL; + goto nla_put_failure; + } + + NLA_PUT(ssids, + NL80211_SCHED_SCAN_MATCH_ATTR_SSID, + strlen(v[0]), v[0]); + + have_ssids = true; + i++; + c--; v++; + } else { + /* other element that cannot be part +* of a match indicates the end of the +* active set. */ + /* need at least one item in the set */ + if (i == 0) { + err = -EINVAL; + goto nla_put_failure; + } + + parse_state = ND_TOPLEVEL; + } + break; } } + if (!have_ssids) + NLA_PUT(ssids, 1, 0, ""); + if (!have_passive) + nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids); if (have_freqs) nla_put_nested(msg, NL80211_ATT
[PATCH iw v2 4/4] iw: add randomise option for sched_scan
From: Luciano Coelho Like with normal scans, we can randomise the MAC address sent out in active scheduled scans. Add the randomise option to sched_scan (and net-detect) parsing code. Signed-off-by: Luciano Coelho --- iw.h | 2 +- scan.c | 11 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/iw.h b/iw.h index fc20838..78195ea 100644 --- a/iw.h +++ b/iw.h @@ -174,7 +174,7 @@ void parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen); void iw_hexdump(const char *prefix, const __u8 *data, size_t len); #define SCHED_SCAN_OPTIONS "interval [delay ] " \ - "[freqs +] [matches [ssid ]+]] [active [ssid ]+|passive] " + "[freqs +] [matches [ssid ]+]] [active [ssid ]+|passive] [randomise[=/]]" int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv); DECLARE_SECTION(set); diff --git a/scan.c b/scan.c index 7ff04ec..e959c1b 100644 --- a/scan.c +++ b/scan.c @@ -115,6 +115,7 @@ int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv) unsigned int freq, interval = 0, delay = 0; bool have_matchset = false, have_freqs = false, have_ssids = false; bool have_active = false, have_passive = false; + uint32_t flags = 0; matchset = nlmsg_alloc(); if (!matchset) { @@ -208,6 +209,14 @@ int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv) } have_passive = true; + } else if (!strncmp(v[0], "randomise", 9) || + !strncmp(v[0], "randomize", 9)) { + flags |= NL80211_SCAN_FLAG_RANDOM_ADDR; + if (c > 0) { + err = parse_random_mac_addr(msg, v[0]); + if (err) + goto nla_put_failure; + } } else { /* this element is not for us, so * return to continue parsing. @@ -312,6 +321,8 @@ int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv) nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs); if (have_matchset) nla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH, matchset); + if (flags) + NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS, flags); nla_put_failure: if (match) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] nl80211: add net-detect delay to wowlan info
From: Luciano Coelho Pass the initial net-detect delay (NL80211_ATTR_SCHED_SCAN_DELAY) attribute in the WoWLAN info response. Additionally, remove a bogus TODO comment. Signed-off-by: Luciano Coelho Reviewed-by: Emmanuel Grumbach --- net/wireless/nl80211.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 9f14e32..7561338 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -1099,8 +1099,6 @@ static int nl80211_send_wowlan(struct sk_buff *msg, if (large && nl80211_send_wowlan_tcp_caps(rdev, msg)) return -ENOBUFS; - /* TODO: send wowlan net detect */ - nla_nest_end(msg, nl_wowlan); return 0; @@ -8831,6 +8829,9 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg, if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, req->interval)) return -ENOBUFS; + if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_DELAY, req->delay)) + return -ENOBUFS; + freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES); if (!freqs) return -ENOBUFS; -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: ARP dropped during WPA handshake
> > > During the initial WPA handshake the connection is not fully set up, > > > and so no general traffic can (nor should) pass between the STA and AP. > > > That includes ARP and any L2/L3+ protocols, except for EAP and wifi > > > management packets. > > > > > > The interface itself must be IFF_UP before it can pass traffic, > > > including the WPA handshake traffic. IFF_UP only means that the > > > interface can be configured at the L2 level and the hardware is > > > active, it does *not* mean the interface can pass traffic. > > > > > > Whatever is causing the ARPs shouldn't be doing that yet, and should > > > be fixed to use the interface's "operstate" or IFF_LOWER_UP instead > > > of IFF_UP. Only when the supplicant changes the interface's > > > operstate to IF_OPER_UP is the interface *actually* ready to pass > traffic. IFF_UP is not sufficient. > > > > > > > Thanks for your reply. > > > > It seems wpa_supplicant set the operstate to IF_OPER_DORMANT when he > received the ASSOCIATED Event from the driver (through netlink). And set the > operstate to IF_OPER_UP in case of wpa handshake success. > > > > Is it normal the local ip stack send arp when netdev it is on > IF_OPER_DORMANT state? > > I'm not sure the kernel stack cares much as long as the device is up. > It is requesting the ARP because some application is attempting to > communicate with that IP address. That application should probably be > waiting until the interface is actually ready to communicate, which means > IF_OPER_UP. > > But if this is the first WPA handshake with the AP during the initial > connection, the wifi device shouldn't even have an IP address yet, so nothing > should be doing ARP on the interface yet. Perhaps whatever is assigning the > IP address to the interface is doing it too early, before the interface is > IF_OPER_UP? > It is not the initial connection. My sta is connected on AP1 and the communication is established (in my test the communication it is iperf from STA to computer behind the APs). I looking for a solution to enable the communication for wpa_supplicant, but block the L3 communication while the WPA handshake is not finished. Have you any idea? Cedric. -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH iw v2 0/4] iw: add scheduled scan support
On Tue, 2015-03-17 at 16:11 +0200, Luca Coelho wrote: > From: Luciano Coelho > > This series adds scheduled scan support to the iw tool (finally! ;). > > In v2, just rebased. Great, thanks; all applied. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] brcmfmac: cfg80211: use msecs_to_jiffies for time conversion
On 03/17/15 13:06, Nicholas Mc Guire wrote: Converting milliseconds to jiffies by "val * HZ / 1000" is technically OK but msecs_to_jiffies(val) is the cleaner solution and handles all corner cases correctly. This is a minor API consolidation only and should make things more readable. Patch was compile tested with x86_64_defconfig + CONFIG_BRCMFMAC=m Patch is agianst 4.0-rc4 (localversion-next is -next-20150317) It applies to wireless-drivers-next/master as well so Acked-by: Arend van Spriel Signed-off-by: Nicholas Mc Guire --- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 9b805c9..1996dc2 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -1110,7 +1110,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif, /* Arm scan timeout timer */ mod_timer(&cfg->escan_timeout, jiffies + - WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000); + msecs_to_jiffies(WL_ESCAN_TIMER_INTERVAL_MS)); return 0; -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: ARP dropped during WPA handshake
On Tue, 2015-03-17 at 16:02 +0100, voncken wrote: > > > > > During the initial WPA handshake the connection is not fully set up, > > > > and so no general traffic can (nor should) pass between the STA and AP. > > > > That includes ARP and any L2/L3+ protocols, except for EAP and wifi > > > > management packets. > > > > > > > > The interface itself must be IFF_UP before it can pass traffic, > > > > including the WPA handshake traffic. IFF_UP only means that the > > > > interface can be configured at the L2 level and the hardware is > > > > active, it does *not* mean the interface can pass traffic. > > > > > > > > Whatever is causing the ARPs shouldn't be doing that yet, and should > > > > be fixed to use the interface's "operstate" or IFF_LOWER_UP instead > > > > of IFF_UP. Only when the supplicant changes the interface's > > > > operstate to IF_OPER_UP is the interface *actually* ready to pass > > traffic. IFF_UP is not sufficient. > > > > > > > > > > Thanks for your reply. > > > > > > It seems wpa_supplicant set the operstate to IF_OPER_DORMANT when he > > received the ASSOCIATED Event from the driver (through netlink). And set the > > operstate to IF_OPER_UP in case of wpa handshake success. > > > > > > Is it normal the local ip stack send arp when netdev it is on > > IF_OPER_DORMANT state? > > > > I'm not sure the kernel stack cares much as long as the device is up. > > It is requesting the ARP because some application is attempting to > > communicate with that IP address. That application should probably be > > waiting until the interface is actually ready to communicate, which means > > IF_OPER_UP. > > > > But if this is the first WPA handshake with the AP during the initial > > connection, the wifi device shouldn't even have an IP address yet, so > > nothing > > should be doing ARP on the interface yet. Perhaps whatever is assigning the > > IP address to the interface is doing it too early, before the interface is > > IF_OPER_UP? > > > It is not the initial connection. My sta is connected on AP1 and the > communication is established (in my test the communication it is iperf from > STA to computer behind the APs). > > I looking for a solution to enable the communication for wpa_supplicant, but > block the L3 communication while the WPA handshake is not finished. Yeah, I saw your mail to netdev. In my opinion (which may not count for much) I don't think the kernel should be doing any ARP when the interface is not IF_OPER_UP. wpa_supplicant is doing the right thing if it is setting the interface IF_OPER_DORMANT when doing the rekeying and then setting the interface to IF_OPER_UP when it has successfully installed the new keys. There's only a few places where ARPs get triggered in the kernel, and perhaps those need to be modified to defer the ARP until IF_OPER_UP or something like that. In any case, I think this is best followed up on netdev since I don't think the supplicant is doing anything wrong here. Dan -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4] mac80211: add an intermediate software queue implementation
This allows drivers to request per-vif and per-sta-tid queues from which they can pull frames. This makes it easier to keep the hardware queues short, and to improve fairness between clients and vifs. The task of scheduling packet transmission is left up to the driver - queueing is controlled by mac80211. Drivers can only dequeue packets by calling ieee80211_tx_dequeue. This makes it possible to add active queue management later without changing drivers using this code. This can also be used as a starting point to implement A-MSDU aggregation in a way that does not add artificially induced latency. Signed-off-by: Felix Fietkau --- include/net/mac80211.h | 78 ++ net/mac80211/agg-tx.c | 42 + net/mac80211/driver-ops.h | 12 + net/mac80211/ieee80211_i.h | 24 ++ net/mac80211/iface.c | 19 net/mac80211/main.c| 3 ++ net/mac80211/rx.c | 13 + net/mac80211/sta_info.c| 78 ++ net/mac80211/sta_info.h| 2 + net/mac80211/trace.h | 28 +++ net/mac80211/tx.c | 115 + net/mac80211/util.c| 38 +++ 12 files changed, 433 insertions(+), 19 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a1db2ea..aafa5eb 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -84,6 +84,34 @@ * */ +/** + * DOC: mac80211 software tx queueing + * + * mac80211 provides an optional intermediate queueing implementation designed + * to allow the driver to keep hardware queues short and provide some fairness + * between different stations/interfaces. + * In this model, the driver pulls data frames from the mac80211 queue instead + * of letting mac80211 push them via drv_tx(). + * Other frames (e.g. control or management) are still pushed using drv_tx(). + * + * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with a + * single per-vif queue for multicast data frames. + * + * The driver is expected to initialize its private per-queue data for stations + * and interfaces in the .add_interface and .sta_add ops. + * + * The driver can not access the queue directly. To dequeue a frame, it calls + * ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a queue, it + * calls the .wake_tx_queue driver op. + * + * For AP powersave TIM handling, the driver only needs to indicate if it has + * buffered packets in the driver specific data structures by calling + * ieee80211_sta_set_buffered(). For frames buffered in the ieee80211_txq + * struct, mac80211 sets TIM and calls .release_buffered_frames(). + * The driver is expected to release its own buffered frames and also call + * ieee80211_tx_dequeue() within that callback. + */ + struct device; /** @@ -1257,6 +1285,8 @@ struct ieee80211_vif { u8 cab_queue; u8 hw_queue[IEEE80211_NUM_ACS]; + struct ieee80211_txq *txq; + struct ieee80211_chanctx_conf __rcu *chanctx_conf; u32 driver_flags; @@ -1519,6 +1549,8 @@ struct ieee80211_sta { bool tdls_initiator; bool mfp; + struct ieee80211_txq *txq[IEEE80211_NUM_TIDS]; + /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; @@ -1547,6 +1579,27 @@ struct ieee80211_tx_control { }; /** + * struct ieee80211_txq - Software intermediate tx queue + * + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @sta: station table entry, may be NULL for per-vif queue + * @tid: the TID for this queue (unused for per-vif queue) + * @ac: the AC for this queue + * + * The driver can obtain packets from this queue by calling + * ieee80211_tx_dequeue(). + */ +struct ieee80211_txq { + struct ieee80211_vif *vif; + struct ieee80211_sta *sta; + u8 tid; + u8 ac; + + /* must be last */ + u8 drv_priv[0] __aligned(sizeof(void *)); +}; + +/** * enum ieee80211_hw_flags - hardware flags * * These flags are used to indicate hardware capabilities to @@ -1770,6 +1823,8 @@ enum ieee80211_hw_flags { * within &struct ieee80211_sta. * @chanctx_data_size: size (in bytes) of the drv_priv data area * within &struct ieee80211_chanctx_conf. + * @txq_data_size: size (in bytes) of the drv_priv data area + * within @struct ieee80211_txq. * * @max_rates: maximum number of alternate rate retry stages the hw * can handle. @@ -1818,6 +1873,9 @@ enum ieee80211_hw_flags { * @n_cipher_schemes: a size of an array of cipher schemes definitions. * @cipher_schemes: a pointer to an array of cipher scheme definitions * supported by HW. + * + * @txq_ac_max_pending: maximum number of frames per AC pending in all txq + * entries for a vif. */ struct ieee80211_hw { struct ieee80211_conf conf; @@ -1830,6 +1888,7 @@ struct ieee80211_hw { int vif_data_size; int sta_data_size; int c
[PATCH v3 01/10] mac80211: enhance readability of Minstrels rc_stats output
This patch restructures the rc_stats debugfs table of Minstrel in order to achieve better human readability. A new layout of the statistics and a new header is added. In addition to the old layout there are two new columns of information added: idx - representing the rate index of each rate in mac80211 which can be used to set specific rates as fixed rate via debugfs airtime - the tx-time in micro seconds that a 1200 Byte packet takes to be transmitted over the air at the given rate The old layout of rc_stats: rate tpt eprob *prob ret *ok(*cum)ok( cum) DP 1 0.9 93.5 100.0 10( 0) 2(2) 2 0.4 40.0 100.0 00( 0) 4(10) 5.50.0 0.0 0.0 00( 0) 0(0) ... is changed into this new layout: best ___rate___statistics__last___ __sum-of rate [name idx tx-time] [ ø(tp) ø(prob)] [prob.|retry|suc|att] [#success | #attempts] DP 1 0 9738 0.993.5 100.0 1 1 1 2 2 2 1 4922 0.440.0 100.0 1 0 0 4 10 5.5 2 1858 0.0 0.0 0.0 2 0 0 0 0 ... Signed-off-by: Thomas Huehn Signed-off-by: Stefan Venz --- net/mac80211/rc80211_minstrel_debugfs.c | 18 +- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index 2acab1b..2d70081 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c @@ -68,8 +68,12 @@ minstrel_stats_open(struct inode *inode, struct file *file) file->private_data = ms; p = ms->buf; - p += sprintf(p, "rate tpt eprob *prob" - " *ok(*cum)ok( cum)\n"); + p += sprintf(p, "\n"); + p += sprintf(p, "best ___rate___statistics__" + "last_____sum-of\n"); + p += sprintf(p, "rate [name idx airtime] [ ø(tp) ø(prob)] " + "[prob.|retry|suc|att] [#success | #attempts]\n"); + for (i = 0; i < mi->n_rates; i++) { struct minstrel_rate *mr = &mi->r[i]; struct minstrel_rate_stats *mrs = &mi->r[i].stats; @@ -79,18 +83,22 @@ minstrel_stats_open(struct inode *inode, struct file *file) *(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' '; *(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' '; *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; - p += sprintf(p, "%3u%s", mr->bitrate / 2, + + p += sprintf(p, " %3u%s ", mr->bitrate / 2, (mr->bitrate & 1 ? ".5" : " ")); + p += sprintf(p, "%3u ", i); + p += sprintf(p, "%6u ", mr->perfect_tx_time); tp = MINSTREL_TRUNC(mrs->cur_tp / 10); prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); eprob = MINSTREL_TRUNC(mrs->probability * 1000); - p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u" - " %4u(%4u) %9llu(%9llu)\n", + p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u %3u" + " %3u %-3u %9llu %-9llu\n", tp / 10, tp % 10, eprob / 10, eprob % 10, prob / 10, prob % 10, + mrs->retry_count, mrs->last_success, mrs->last_attempts, (unsigned long long)mrs->succ_hist, -- 2.3.0 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 08/10] mac80211: add max. lossless throughput per rate to rc_stats
This patch adds the new statistic "maximum possible lossless throughput" to Minstrels and Minstrel-HTs rc_stats (in debugfs). This enables comprehensive comparison between current per-rate throughput and max. achievable per-rate throughput. Signed-off-by: Thomas Huehn --- net/mac80211/rc80211_minstrel.c| 10 net/mac80211/rc80211_minstrel.h| 1 + net/mac80211/rc80211_minstrel_debugfs.c| 18 --- net/mac80211/rc80211_minstrel_ht.c | 84 -- net/mac80211/rc80211_minstrel_ht.h | 4 +- net/mac80211/rc80211_minstrel_ht_debugfs.c | 24 + 6 files changed, 83 insertions(+), 58 deletions(-) diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index d985227..c2afe51 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -85,6 +85,16 @@ int minstrel_get_tp_avg(struct minstrel_rate *mr) return MINSTREL_TRUNC(mr->stats.prob_ewma * (10 / usecs)); } +/* return max. potential lossless throughput */ +inline int +minstrel_get_tp_max(struct minstrel_rate *mr) +{ + if (!mr->perfect_tx_time) + return 0; + + return 10 / mr->perfect_tx_time; +} + /* find & sort topmost throughput rates */ static inline void minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 490df3b..6693d8d 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -135,6 +135,7 @@ void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); /* Recalculate success probabilities and counters for a given rate using EWMA */ void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs); int minstrel_get_tp_avg(struct minstrel_rate *mr); +int minstrel_get_tp_max(struct minstrel_rate *mr); /* debugfs */ int minstrel_stats_open(struct inode *inode, struct file *file); diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index 4d6eeef..3ed69ef 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c @@ -75,7 +75,7 @@ minstrel_stats_open(struct inode *inode, struct file *file) { struct minstrel_sta_info *mi = inode->i_private; struct minstrel_debugfs_info *ms; - unsigned int i, tp_avg, prob, eprob; + unsigned int i, tp_max, tp_avg, prob, eprob; char *p; ms = kmalloc(2048, GFP_KERNEL); @@ -85,9 +85,9 @@ minstrel_stats_open(struct inode *inode, struct file *file) file->private_data = ms; p = ms->buf; p += sprintf(p, "\n"); - p += sprintf(p, "best ___rate___statistics__" + p += sprintf(p, "best __rate___statistics__" "last_____sum-of\n"); - p += sprintf(p, "rate [name idx airtime] [ ø(tp) ø(prob)] " + p += sprintf(p, "rate [name idx airtime max_tp] [ ø(tp) ø(prob)] " "[prob.|retry|suc|att] [#success | #attempts]\n"); for (i = 0; i < mi->n_rates; i++) { @@ -103,14 +103,16 @@ minstrel_stats_open(struct inode *inode, struct file *file) p += sprintf(p, " %3u%s ", mr->bitrate / 2, (mr->bitrate & 1 ? ".5" : " ")); p += sprintf(p, "%3u ", i); - p += sprintf(p, "%6u ", mr->perfect_tx_time); + p += sprintf(p, "%6u ", mr->perfect_tx_time); + tp_max = minstrel_get_tp_max(mr); tp_avg = minstrel_get_tp_avg(mr); prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); eprob = MINSTREL_TRUNC(mrs->prob_ewma * 1000); - p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u %3u" + p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u %3u.%1u %3u" " %3u %-3u %9llu %-9llu\n", + tp_max / 10, tp_max % 10, tp_avg / 10, tp_avg % 10, eprob / 10, eprob % 10, prob / 10, prob % 10, @@ -145,7 +147,7 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file) struct minstrel_sta_info *mi = inode->i_private; struct minstrel_debugfs_info *ms; struct timeval tv; - unsigned int i, tp_avg, prob, eprob; + unsigned int i, tp_max, tp_avg, prob, eprob; char *p; ms = kmalloc(2048, GFP_KERNEL); @@ -173,12 +175,14 @@ minstrel_stats_csv_open(struct inode *inode, struct file *file) p += sprintf(p, "%u,", i); p += sprintf(p, "%u,",mr->perfect_tx_time); + tp_max = minstrel_get_tp_max(mr); tp_avg = minstrel_get_tp_avg(mr); prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); eprob = MINSTR
[PATCH v3 09/10] mac80211: reduce calculation costs of EWMA
This patch reduces the calculation costs of the EWMA macro from "2x multiplication and 1 addition" down to "1x multiplication and 2x additions". This slightly improves performance depending on the CPU architecture. Signed-off-by: Thomas Huehn --- net/mac80211/rc80211_minstrel.h | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 6693d8d..38158b0 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -27,7 +27,12 @@ static inline int minstrel_ewma(int old, int new, int weight) { - return (new * (EWMA_DIV - weight) + old * weight) / EWMA_DIV; + int diff, incr; + + diff = new - old; + incr = (EWMA_DIV - weight) * diff / EWMA_DIV; + + return old + incr; } struct minstrel_rate_stats { -- 2.3.0 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 03/10] mac80211: add new Minstrel statistic output via csv
This patch adds a new debugfs file "rc_stats_csv" to output Minstrels statistics in a common csv format that is easy to parse. Signed-off-by: Thomas Huehn Signed-off-by: Stefan Venz --- net/mac80211/rc80211_minstrel.h | 6 +-- net/mac80211/rc80211_minstrel_debugfs.c | 95 + 2 files changed, 87 insertions(+), 14 deletions(-) diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 410efe6..9613e73 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -13,7 +13,6 @@ #define EWMA_DIV 128 #define SAMPLE_COLUMNS 10 /* number of columns in sample table */ - /* scaled fraction values */ #define MINSTREL_SCALE 16 #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) @@ -24,7 +23,7 @@ /* * Perform EWMA (Exponentially Weighted Moving Average) calculation - */ + */ static inline int minstrel_ewma(int old, int new, int weight) { @@ -95,6 +94,7 @@ struct minstrel_sta_info { #ifdef CONFIG_MAC80211_DEBUGFS struct dentry *dbg_stats; + struct dentry *dbg_stats_csv; #endif }; @@ -121,7 +121,6 @@ struct minstrel_priv { u32 fixed_rate_idx; struct dentry *dbg_fixed_rate; #endif - }; struct minstrel_debugfs_info { @@ -135,6 +134,7 @@ void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); /* debugfs */ int minstrel_stats_open(struct inode *inode, struct file *file); +int minstrel_stats_csv_open(struct inode *inode, struct file *file); ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos); int minstrel_stats_release(struct inode *inode, struct file *file); diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index 2d70081..8c35402 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c @@ -54,6 +54,22 @@ #include #include "rc80211_minstrel.h" +ssize_t +minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) +{ + struct minstrel_debugfs_info *ms; + + ms = file->private_data; + return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); +} + +int +minstrel_stats_release(struct inode *inode, struct file *file) +{ + kfree(file->private_data); + return 0; +} + int minstrel_stats_open(struct inode *inode, struct file *file) { @@ -115,25 +131,76 @@ minstrel_stats_open(struct inode *inode, struct file *file) return 0; } -ssize_t -minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) +static const struct file_operations minstrel_stat_fops = { + .owner = THIS_MODULE, + .open = minstrel_stats_open, + .read = minstrel_stats_read, + .release = minstrel_stats_release, + .llseek = default_llseek, +}; + +int +minstrel_stats_csv_open(struct inode *inode, struct file *file) { + struct minstrel_sta_info *mi = inode->i_private; struct minstrel_debugfs_info *ms; + struct timeval tv; + unsigned int i, tp, prob, eprob; + char *p; - ms = file->private_data; - return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len); -} + ms = kmalloc(2048, GFP_KERNEL); + if (!ms) + return -ENOMEM; + + file->private_data = ms; + p = ms->buf; + + do_gettimeofday(&tv); + + for (i = 0; i < mi->n_rates; i++) { + struct minstrel_rate *mr = &mi->r[i]; + struct minstrel_rate_stats *mrs = &mi->r[i].stats; + + p += sprintf(p, "%ld.%.6ld,", tv.tv_sec, tv.tv_usec); + p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : "")); + p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B" : "")); + p += sprintf(p, "%s" ,((i == mi->max_tp_rate[2]) ? "C" : "")); + p += sprintf(p, "%s" ,((i == mi->max_tp_rate[3]) ? "D" : "")); + p += sprintf(p, "%s" ,((i == mi->max_prob_rate) ? "P" : "")); + + p += sprintf(p, ",%u%s", mr->bitrate / 2, + (mr->bitrate & 1 ? ".5," : ",")); + p += sprintf(p, "%u,", i); + p += sprintf(p, "%u,",mr->perfect_tx_time); + + tp = MINSTREL_TRUNC(mrs->cur_tp / 10); + prob = MINSTREL_TRUNC(mrs->cur_prob * 1000); + eprob = MINSTREL_TRUNC(mrs->probability * 1000); + + p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u," + "%llu,%llu,%d,%d\n", + tp / 10, tp % 10, + eprob / 10, eprob % 10, + prob / 10, prob % 10, + mrs->retry_count, + mrs->last_success, + mrs->last_attempts, + (unsigned long long)mrs->succ_hist, +
[PATCH v3 02/10] mac80211: enhance readability of Minstrel-HTs rc_stats output
This patch restructures the rc_stats debugfs table of Minstrel-HT in order to achieve better human readability. A new layout of the statistics and a new header is added. In addition to the old layout there are two new columns of information added: idx - representing the rate index of each rate in mac80211 which can be used to set specific rates as fixed rate via debugfs airtime - the tx-time in micro seconds that a 1200 Byte packet takes to be transmitted over the air at the given rate The old layout of rc_stats: type rate tpt eprob *prob ret *ok(*cum)ok( cum) HT20/LGI MCS0 5.6 100.0 100.0 10( 0) 1(1) HT20/LGI B MCS1 10.5 100.0 100.0 00( 0) 1(1) HT20/LGI AMCS2 14.8 100.0 100.0 00( 0) 1(1) ... is changed into this new layout: best rate____statistics__last___ __sum-of mode guard # rate [name idx airtime] [ ø(tp) ø(prob)] [prob.|retry|suc|att] [#success | #attempts] HT20 LGI 1 MCS0 01480 0.0 0.0 0.0 1 0 0 0 0 HT20 LGI 1 B MCS1 1 740 10.5100.0100.0 0 0 0 1 1 HT20 LGI 1AMCS2 2 496 14.8100.0100.0 0 0 0 1 1 ... Signed-off-by: Thomas Huehn Signed-off-by: Stefan Venz --- net/mac80211/rc80211_minstrel_ht_debugfs.c | 49 +- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c index 20c676b..7fc690f 100644 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c @@ -19,7 +19,7 @@ static char * minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) { const struct mcs_group *mg; - unsigned int j, tp, prob, eprob; + unsigned int j, tp, prob, eprob, tx_time; char htmode = '2'; char gimode = 'L'; u32 gflags; @@ -45,12 +45,19 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) if (!(mi->groups[i].supported & BIT(j))) continue; - if (gflags & IEEE80211_TX_RC_MCS) - p += sprintf(p, " HT%c0/%cGI ", htmode, gimode); - else if (gflags & IEEE80211_TX_RC_VHT_MCS) - p += sprintf(p, "VHT%c0/%cGI ", htmode, gimode); - else - p += sprintf(p, " CCK/%cP ", j < 4 ? 'L' : 'S'); + if (gflags & IEEE80211_TX_RC_MCS) { + p += sprintf(p, "HT%c0 ", htmode); + p += sprintf(p, "%cGI ", gimode); + p += sprintf(p, "%d ", mg->streams); + } else if (gflags & IEEE80211_TX_RC_VHT_MCS) { + p += sprintf(p, "VHT%c0 ", htmode); + p += sprintf(p, "%cGI ", gimode); + p += sprintf(p, "%d ", mg->streams); + } else { + p += sprintf(p, "CCK"); + p += sprintf(p, "%cP ", j < 4 ? 'L' : 'S'); + p += sprintf(p, "1 "); + } *(p++) = (idx == mi->max_tp_rate[0]) ? 'A' : ' '; *(p++) = (idx == mi->max_tp_rate[1]) ? 'B' : ' '; @@ -59,21 +66,27 @@ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p) *(p++) = (idx == mi->max_prob_rate) ? 'P' : ' '; if (gflags & IEEE80211_TX_RC_MCS) { - p += sprintf(p, " MCS%-2u ", (mg->streams - 1) * 8 + j); + p += sprintf(p, " MCS%-2u", (mg->streams - 1) * 8 + j); } else if (gflags & IEEE80211_TX_RC_VHT_MCS) { - p += sprintf(p, " MCS%-1u/%1u", j, mg->streams); + p += sprintf(p, " MCS%-1u/%1u", j, mg->streams); } else { int r = bitrates[j % 4]; - p += sprintf(p, " %2u.%1uM ", r / 10, r % 10); + p += sprintf(p, " %2u.%1uM", r / 10, r % 10); } + p += sprintf(p, " %3u ", idx); + + /* tx_time[rate(i)] in usec */ + tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000); + p += sprintf(p, "%6u ", tx_time); + tp = mr->cur_tp / 10; prob = MINSTREL_TRUNC(mr->cur_prob * 1000); eprob = MINSTREL_TRUNC(mr->probability * 1000); - p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u " - "%3u %4u(%4u) %9llu(%9llu)\n", + p += sprintf(p, "%4u.%1u %3u.%1u %3u.%1u " + "%3u %3u %-3u %9llu %-9llu\n", tp / 10, tp % 10,
[PATCH v3 04/10] mac80211: add new Minstrel-HT statistic output via csv
This patch adds a new debugfs file "rc_stats_csv" to output Minstrel-HTs statistics in a common csv format that is easy to parse. Signed-off-by: Thomas Huehn Signed-off-by: Stefan Venz --- net/mac80211/rc80211_minstrel_ht.h | 1 + net/mac80211/rc80211_minstrel_ht_debugfs.c | 145 - 2 files changed, 144 insertions(+), 2 deletions(-) diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h index f2217d6..3cc30e8 100644 --- a/net/mac80211/rc80211_minstrel_ht.h +++ b/net/mac80211/rc80211_minstrel_ht.h @@ -112,6 +112,7 @@ struct minstrel_ht_sta_priv { }; #ifdef CONFIG_MAC80211_DEBUGFS struct dentry *dbg_stats; + struct dentry *dbg_stats_csv; #endif void *ratelist; void *sample_table; diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c index 7fc690f..133d7b6 100644 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c @@ -107,8 +107,8 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) struct minstrel_ht_sta *mi = &msp->ht; struct minstrel_debugfs_info *ms; unsigned int i; - char *p; int ret; + char *p; if (!msp->is_ht) { inode->i_private = &msp->legacy; @@ -146,7 +146,6 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) MINSTREL_TRUNC(mi->avg_ampdu_len), MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10); ms->len = p - ms->buf; - WARN_ON(ms->len + sizeof(*ms) > 32768); return nonseekable_open(inode, file); @@ -160,6 +159,145 @@ static const struct file_operations minstrel_ht_stat_fops = { .llseek = no_llseek, }; +static char * +minstrel_ht_stats_csv_dump(struct minstrel_ht_sta *mi, int i, char *p, + struct timeval tv) +{ + const struct mcs_group *mg; + unsigned int j, tp, prob, eprob, tx_time; + char htmode = '2'; + char gimode = 'L'; + u32 gflags; + + if (!mi->groups[i].supported) + return p; + + mg = &minstrel_mcs_groups[i]; + gflags = mg->flags; + + if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) + htmode = '4'; + else if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH) + htmode = '8'; + if (gflags & IEEE80211_TX_RC_SHORT_GI) + gimode = 'S'; + + for (j = 0; j < MCS_GROUP_RATES; j++) { + struct minstrel_rate_stats *mr = &mi->groups[i].rates[j]; + static const int bitrates[4] = { 10, 20, 55, 110 }; + int idx = i * MCS_GROUP_RATES + j; + + if (!(mi->groups[i].supported & BIT(j))) + continue; + + p += sprintf(p, "%ld.%.6ld,", tv.tv_sec, tv.tv_usec); + + if (gflags & IEEE80211_TX_RC_MCS) { + p += sprintf(p, "HT%c0,", htmode); + p += sprintf(p, "%cGI,", gimode); + p += sprintf(p, "%d,", mg->streams); + } else if (gflags & IEEE80211_TX_RC_VHT_MCS) { + p += sprintf(p, "VHT%c0,", htmode); + p += sprintf(p, "%cGI,", gimode); + p += sprintf(p, "%d,", mg->streams); + } else { + p += sprintf(p, "CCK,"); + p += sprintf(p, "%cP,", j < 4 ? 'L' : 'S'); + p += sprintf(p, "1,"); + } + + p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[0]) ? "A" : "")); + p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[1]) ? "B" : "")); + p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[2]) ? "C" : "")); + p += sprintf(p, "%s" ,((idx == mi->max_tp_rate[3]) ? "D" : "")); + p += sprintf(p, "%s" ,((idx == mi->max_prob_rate) ? "P" : "")); + + if (gflags & IEEE80211_TX_RC_MCS) { + p += sprintf(p, ",MCS%-2u,", (mg->streams - 1) * 8 + j); + } else if (gflags & IEEE80211_TX_RC_VHT_MCS) { + p += sprintf(p, ",MCS%-1u/%1u,", j, mg->streams); + } else { + int r = bitrates[j % 4]; + p += sprintf(p, ",%2u.%1uM,", r / 10, r % 10); + } + + p += sprintf(p, "%u,", idx); + tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000); + p += sprintf(p, "%u,", tx_time); + + tp = mr->cur_tp / 10; + prob = MINSTREL_TRUNC(mr->cur_prob * 1000); + eprob = MINSTREL_TRUNC(mr->probability * 1000); + + p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u,%llu,%llu,", + tp / 10, tp % 10, + eprob / 10, eprob % 10, + prob / 10, prob % 10, +
[PATCH v3 10/10] mac80211: add standard deviation to Minstrels throughput statistic
This patch adds the statistical descriptor "standard deviation" to better describe the current properties of Minstrel and Minstrel-HTs success probability distribution. The standard deviation (SD) is calculated as exponential weighted moving standard deviation (EWMSD) and its current value is added as new column in all rc_stats (in debugfs). Signed-off-by: Thomas Huehn --- net/mac80211/rc80211_minstrel.c| 19 ++- net/mac80211/rc80211_minstrel.h| 22 +- net/mac80211/rc80211_minstrel_debugfs.c| 19 --- net/mac80211/rc80211_minstrel_ht_debugfs.c | 14 +- 4 files changed, 56 insertions(+), 18 deletions(-) diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index c2afe51..30512d0 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -156,7 +156,7 @@ minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi) } /* -* Recalculate success probabilities and counters for a given rate using EWMA +* Recalculate statistics and counters of a given rate */ void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) @@ -164,11 +164,20 @@ minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) if (unlikely(mrs->attempts > 0)) { mrs->sample_skipped = 0; mrs->cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); - if (unlikely(!mrs->att_hist)) + if (unlikely(!mrs->att_hist)) { mrs->prob_ewma = mrs->cur_prob; - else + } else { + /* update exponential weighted moving variance */ + mrs->prob_ewmsd = minstrel_ewmsd(mrs->prob_ewmsd, +mrs->cur_prob, +mrs->prob_ewma, +EWMA_LEVEL); + + /*update exponential weighted moving avarage */ mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma, -mrs->cur_prob, EWMA_LEVEL); + mrs->cur_prob, + EWMA_LEVEL); + } mrs->att_hist += mrs->attempts; mrs->succ_hist += mrs->success; } else { @@ -195,7 +204,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) struct minstrel_rate *mr = &mi->r[i]; struct minstrel_rate_stats *mrs = &mi->r[i].stats; - /* Update success probabilities per rate */ + /* Update statistics of success probability per rate */ minstrel_calc_rate_stats(mrs); /* Sample less often below the 10% chance of success. diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 38158b0..713c81e 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -35,6 +35,24 @@ minstrel_ewma(int old, int new, int weight) return old + incr; } +/* + * Perform EWMSD (Exponentially Weighted Moving Standard Deviation) calculation + */ +static inline int +minstrel_ewmsd(int old_ewmsd, int cur_prob, int prob_ewma, int weight) +{ + int diff, incr, tmp_var; + + /* calculate exponential weighted moving variance */ + diff = MINSTREL_TRUNC((cur_prob - prob_ewma) * 100); + incr = (EWMA_DIV - weight) * diff / EWMA_DIV; + tmp_var = old_ewmsd * old_ewmsd; + tmp_var = weight * (tmp_var + diff * incr / 100) / EWMA_DIV; + + /* return standard deviation */ + return (u16) int_sqrt(tmp_var); +} + struct minstrel_rate_stats { /* current / last sampling period attempts/success counters */ u16 attempts, last_attempts; @@ -45,9 +63,11 @@ struct minstrel_rate_stats { /* statistis of packet delivery probability * cur_prob - current prob within last update intervall -* prob_ewma - exponential weighted moving average of prob */ +* prob_ewma - exponential weighted moving average of prob +* prob_ewmsd - exp. weighted moving standard deviation of prob */ unsigned int cur_prob; unsigned int prob_ewma; + u16 prob_ewmsd; /* maximum retry counts */ u8 retry_count; diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c index 3ed69ef..0a60bac 100644 --- a/net/mac80211/rc80211_minstrel_debugfs.c +++ b/net/mac80211/rc80211_minstrel_debugfs.c @@ -85,10 +85,12 @@ minstrel_stats_open(struct inode *inode, struct file *file) file->private_data = ms; p = ms->buf; p += sprintf(p, "\n"); - p += sprintf(p, "best __rate___statistics__" -
[PATCH v3 05/10] mac80211: unify Minstrel & Minstrel-HTs calculation of rate statistics
This patch unifies the calculation of Minstrels and Minstrel-HTs per-rate statistic. The new common function minstrel_calc_rate_stats() is called when a statistic update is performed. Signed-off-by: Thomas Huehn --- net/mac80211/rc80211_minstrel.c| 44 -- net/mac80211/rc80211_minstrel.h| 3 +++ net/mac80211/rc80211_minstrel_ht.c | 28 +--- 3 files changed, 32 insertions(+), 43 deletions(-) diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 7c86a00..4858e67 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -127,6 +127,32 @@ minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi) rate_control_set_rates(mp->hw, mi->sta, ratetbl); } +/* +* Recalculate success probabilities and counters for a given rate using EWMA +*/ +void +minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) +{ + if (unlikely(mrs->attempts > 0)) { + mrs->sample_skipped = 0; + mrs->cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); + if (unlikely(!mrs->att_hist)) + mrs->probability = mrs->cur_prob; + else + mrs->probability = minstrel_ewma(mrs->probability, +mrs->cur_prob, EWMA_LEVEL); + mrs->att_hist += mrs->attempts; + mrs->succ_hist += mrs->success; + } else { + mrs->sample_skipped++; + } + + mrs->last_success = mrs->success; + mrs->last_attempts = mrs->attempts; + mrs->success = 0; + mrs->attempts = 0; +} + static void minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) { @@ -146,22 +172,8 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) if (!usecs) usecs = 100; - if (unlikely(mrs->attempts > 0)) { - mrs->sample_skipped = 0; - mrs->cur_prob = MINSTREL_FRAC(mrs->success, - mrs->attempts); - mrs->succ_hist += mrs->success; - mrs->att_hist += mrs->attempts; - mrs->probability = minstrel_ewma(mrs->probability, -mrs->cur_prob, -EWMA_LEVEL); - } else - mrs->sample_skipped++; - - mrs->last_success = mrs->success; - mrs->last_attempts = mrs->attempts; - mrs->success = 0; - mrs->attempts = 0; + /* Update success probabilities per rate */ + minstrel_calc_rate_stats(mrs); /* Update throughput per rate, reset thr. below 10% success */ if (mrs->probability < MINSTREL_FRAC(10, 100)) diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 9613e73..728144c 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -132,6 +132,9 @@ extern const struct rate_control_ops mac80211_minstrel; void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); +/* Recalculate success probabilities and counters for a given rate using EWMA */ +void minstrel_calc_rate_stats(struct minstrel_rate_stats *mr); + /* debugfs */ int minstrel_stats_open(struct inode *inode, struct file *file); int minstrel_stats_csv_open(struct inode *inode, struct file *file); diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 60698fc..7afa562 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -313,32 +313,6 @@ minstrel_get_ratestats(struct minstrel_ht_sta *mi, int index) return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES]; } - -/* - * Recalculate success probabilities and counters for a rate using EWMA - */ -static void -minstrel_calc_rate_ewma(struct minstrel_rate_stats *mr) -{ - if (unlikely(mr->attempts > 0)) { - mr->sample_skipped = 0; - mr->cur_prob = MINSTREL_FRAC(mr->success, mr->attempts); - if (!mr->att_hist) - mr->probability = mr->cur_prob; - else - mr->probability = minstrel_ewma(mr->probability, - mr->cur_prob, EWMA_LEVEL); - mr->att_hist += mr->attempts; - mr->succ_hist += mr->success; - } else { - mr->sample_skipped++; - } - mr->last_success = mr->success; - mr->last_attempts = mr->attempts; - mr->success = 0; - mr->attempts = 0; -} - /* * Calculate throughput b
[PATCH v3 07/10] mac80211: restructure per-rate throughput calculation into function
This patch moves Minstrels and Minstrel-HTs per-rate throughput calculation (EWMA(thr)) into a dedicated function to be called. Therefore the variable "unsigned int cur_tp" within struct "minstrel_rate_stats" becomes obsolete. and is removed to free up its space. Signed-off-by: Thomas Huehn --- net/mac80211/rc80211_minstrel.c| 43 +++-- net/mac80211/rc80211_minstrel.h| 4 +- net/mac80211/rc80211_minstrel_debugfs.c| 12 ++--- net/mac80211/rc80211_minstrel_ht.c | 77 ++ net/mac80211/rc80211_minstrel_ht.h | 1 + net/mac80211/rc80211_minstrel_ht_debugfs.c | 12 ++--- 6 files changed, 88 insertions(+), 61 deletions(-) diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 89db6cf..d985227 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -69,14 +69,32 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) return i; } +/* return current EMWA throughput */ +int minstrel_get_tp_avg(struct minstrel_rate *mr) +{ + int usecs; + + usecs = mr->perfect_tx_time; + if (!usecs) + usecs = 100; + + /* reset thr. below 10% success */ + if (mr->stats.prob_ewma < MINSTREL_FRAC(10, 100)) + return 0; + else + return MINSTREL_TRUNC(mr->stats.prob_ewma * (10 / usecs)); +} + /* find & sort topmost throughput rates */ static inline void minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) { int j = MAX_THR_RATES; - while (j > 0 && mi->r[i].stats.cur_tp > mi->r[tp_list[j - 1]].stats.cur_tp) + while (j > 0 && (minstrel_get_tp_avg(&mi->r[i]) > + minstrel_get_tp_avg(&mi->r[tp_list[j - 1]]))) j--; + if (j < MAX_THR_RATES - 1) memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); if (j < MAX_THR_RATES) @@ -158,8 +176,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) { u8 tmp_tp_rate[MAX_THR_RATES]; u8 tmp_prob_rate = 0; - u32 usecs; - int i; + int i, tmp_cur_tp, tmp_prob_tp; for (i = 0; i < MAX_THR_RATES; i++) tmp_tp_rate[i] = 0; @@ -168,19 +185,9 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) struct minstrel_rate *mr = &mi->r[i]; struct minstrel_rate_stats *mrs = &mi->r[i].stats; - usecs = mr->perfect_tx_time; - if (!usecs) - usecs = 100; - /* Update success probabilities per rate */ minstrel_calc_rate_stats(mrs); - /* Update throughput per rate, reset thr. below 10% success */ - if (mrs->prob_ewma < MINSTREL_FRAC(10, 100)) - mrs->cur_tp = 0; - else - mrs->cur_tp = mrs->prob_ewma * (100 / usecs); - /* Sample less often below the 10% chance of success. * Sample less often above the 95% chance of success. */ if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) || @@ -205,7 +212,9 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) * (2) if all success probabilities < 95%, the rate with * highest success probability is chosen as max_prob_rate */ if (mrs->prob_ewma >= MINSTREL_FRAC(95, 100)) { - if (mrs->cur_tp >= mi->r[tmp_prob_rate].stats.cur_tp) + tmp_cur_tp = minstrel_get_tp_avg(mr); + tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate]); + if (tmp_cur_tp >= tmp_prob_tp) tmp_prob_rate = i; } else { if (mrs->prob_ewma >= mi->r[tmp_prob_rate].stats.prob_ewma) @@ -676,11 +685,15 @@ static u32 minstrel_get_expected_throughput(void *priv_sta) { struct minstrel_sta_info *mi = priv_sta; int idx = mi->max_tp_rate[0]; + int tmp_cur_tp; /* convert pkt per sec in kbps (1200 is the average pkt size used for * computing cur_tp */ - return MINSTREL_TRUNC(mi->r[idx].stats.cur_tp) * 1200 * 8 / 1024; + tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx]); + tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024; + + return tmp_cur_tp; } const struct rate_control_ops mac80211_minstrel = { diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index 58f2870..490df3b 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -38,9 +38,6 @@ struct minstrel_rate_stats { /* total attempts/success counters */ u64 att_hist, succ_hist; - /* current EWMA of rate throughput */ - unsigned int cur_tp; - /* statistis of packet delivery probabi
[PATCH v3 06/10] mac80211: improve Minstrel variable & function naming
This patch ensures a consistent usage of variable names for type "minstrel_rate_stats" to be used as "mrs" and from type minstrel_rate as "mr" across both Minstrel & Minstrel-HT. In addition some variable and function names got changed to more meaningful ones. Signed-off-by: Thomas Huehn --- net/mac80211/rc80211_minstrel.c| 26 +++ net/mac80211/rc80211_minstrel.h| 13 ++-- net/mac80211/rc80211_minstrel_debugfs.c| 4 +- net/mac80211/rc80211_minstrel_ht.c | 112 ++--- net/mac80211/rc80211_minstrel_ht.h | 2 +- net/mac80211/rc80211_minstrel_ht_debugfs.c | 36 +- 6 files changed, 98 insertions(+), 95 deletions(-) diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 4858e67..89db6cf 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -137,9 +137,9 @@ minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs) mrs->sample_skipped = 0; mrs->cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); if (unlikely(!mrs->att_hist)) - mrs->probability = mrs->cur_prob; + mrs->prob_ewma = mrs->cur_prob; else - mrs->probability = minstrel_ewma(mrs->probability, + mrs->prob_ewma = minstrel_ewma(mrs->prob_ewma, mrs->cur_prob, EWMA_LEVEL); mrs->att_hist += mrs->attempts; mrs->succ_hist += mrs->success; @@ -176,15 +176,15 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) minstrel_calc_rate_stats(mrs); /* Update throughput per rate, reset thr. below 10% success */ - if (mrs->probability < MINSTREL_FRAC(10, 100)) + if (mrs->prob_ewma < MINSTREL_FRAC(10, 100)) mrs->cur_tp = 0; else - mrs->cur_tp = mrs->probability * (100 / usecs); + mrs->cur_tp = mrs->prob_ewma * (100 / usecs); /* Sample less often below the 10% chance of success. * Sample less often above the 95% chance of success. */ - if (mrs->probability > MINSTREL_FRAC(95, 100) || - mrs->probability < MINSTREL_FRAC(10, 100)) { + if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) || + mrs->prob_ewma < MINSTREL_FRAC(10, 100)) { mr->adjusted_retry_count = mrs->retry_count >> 1; if (mr->adjusted_retry_count > 2) mr->adjusted_retry_count = 2; @@ -204,11 +204,11 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) * choose the maximum throughput rate as max_prob_rate * (2) if all success probabilities < 95%, the rate with * highest success probability is chosen as max_prob_rate */ - if (mrs->probability >= MINSTREL_FRAC(95, 100)) { + if (mrs->prob_ewma >= MINSTREL_FRAC(95, 100)) { if (mrs->cur_tp >= mi->r[tmp_prob_rate].stats.cur_tp) tmp_prob_rate = i; } else { - if (mrs->probability >= mi->r[tmp_prob_rate].stats.probability) + if (mrs->prob_ewma >= mi->r[tmp_prob_rate].stats.prob_ewma) tmp_prob_rate = i; } } @@ -227,7 +227,7 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) #endif /* Reset update timer */ - mi->stats_update = jiffies; + mi->last_stats_update = jiffies; minstrel_update_rates(mp, mi); } @@ -265,7 +265,7 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, if (mi->sample_deferred > 0) mi->sample_deferred--; - if (time_after(jiffies, mi->stats_update + + if (time_after(jiffies, mi->last_stats_update + (mp->update_interval * HZ) / 1000)) minstrel_update_stats(mp, mi); } @@ -397,7 +397,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, * has a probability of >95%, we shouldn't be attempting * to use it, as this only wastes precious airtime */ if (!mrr_capable && - (mi->r[ndx].stats.probability > MINSTREL_FRAC(95, 100))) + (mi->r[ndx].stats.prob_ewma > MINSTREL_FRAC(95, 100))) return; mi->prev_sample = true; @@ -531,7 +531,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, } mi->n_rates = n; - mi->stats_update = jiffies; + mi->last_stats_update = jiffies; init_sample_table(mi); minstrel_update_rates(mp, mi); @@ -565,7 +565,7 @@ minstrel
[PATCH] mac80211: stop scan before connection
From: David Spinadel Stop scan before authentication or association to make sure that nothing interferes with connection flow. Currently mac80211 defers RX auth and assoc packets (among other ones) until after the scan is complete, so auth during scan is likely to fail if scan took too much time. Signed-off-by: David Spinadel Reviewed-by: Luciano Coelho --- net/mac80211/mlme.c | 4 1 file changed, 4 insertions(+) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d77150d..3f3ac3e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -4458,6 +4458,10 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, } else WARN_ON_ONCE(!ether_addr_equal(ifmgd->bssid, cbss->bssid)); + /* Cancel scan to ensure that nothing interferes with connection */ + if (local->scanning) + ieee80211_scan_cancel(local); + return 0; } -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 10/16 linux-next] orinoco: constify of_device_id array
of_device_id is always used as const. (See driver.of_match_table and open firmware functions) Signed-off-by: Fabian Frederick --- drivers/net/wireless/orinoco/airport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c index 0ca8b14..77e6c53 100644 --- a/drivers/net/wireless/orinoco/airport.c +++ b/drivers/net/wireless/orinoco/airport.c @@ -228,7 +228,7 @@ MODULE_AUTHOR("Benjamin Herrenschmidt "); MODULE_DESCRIPTION("Driver for the Apple Airport wireless card."); MODULE_LICENSE("Dual MPL/GPL"); -static struct of_device_id airport_match[] = { +static const struct of_device_id airport_match[] = { { .name = "radio", }, -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 00/16 linux-next] drivers/net: constify of_device_id array
This small patchset adds const to of_device_id arrays in drivers/net branch. Fabian Frederick (16): net: netcp: constify of_device_id array Altera TSE: constify of_device_id array net/fsl: constify of_device_id array net: ethoc: constify of_device_id array drivers: net: xgene: constify of_device_id array net: ethernet: apple: constify of_device_id array netdev: octeon_mgmt: constify of_device_id array net: greth: constify of_device_id array net: xilinx: constify of_device_id array orinoco: constify of_device_id array net: phy: constify of_device_id array can: constify of_device_id array IBM-EMAC: constify of_device_id array ehea: constify of_device_id array net: via-rhine: constify of_device_id array via-velocity: constify of_device_id array drivers/net/can/cc770/cc770_platform.c| 2 +- drivers/net/can/grcan.c | 2 +- drivers/net/can/mscan/mpc5xxx_can.c | 2 +- drivers/net/can/sja1000/sja1000_platform.c| 2 +- drivers/net/can/xilinx_can.c | 2 +- drivers/net/ethernet/aeroflex/greth.c | 2 +- drivers/net/ethernet/altera/altera_tse_main.c | 4 ++-- drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 2 +- drivers/net/ethernet/apple/bmac.c | 2 +- drivers/net/ethernet/apple/mace.c | 2 +- drivers/net/ethernet/ethoc.c | 2 +- drivers/net/ethernet/freescale/fec_mpc52xx.c | 2 +- drivers/net/ethernet/freescale/fec_mpc52xx_phy.c | 2 +- drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c | 4 ++-- drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c | 2 +- drivers/net/ethernet/freescale/fs_enet/mii-fec.c | 4 ++-- drivers/net/ethernet/freescale/fsl_pq_mdio.c | 2 +- drivers/net/ethernet/freescale/gianfar.c | 2 +- drivers/net/ethernet/freescale/gianfar_ptp.c | 2 +- drivers/net/ethernet/freescale/ucc_geth.c | 2 +- drivers/net/ethernet/freescale/xgmac_mdio.c | 2 +- drivers/net/ethernet/ibm/ehea/ehea_main.c | 4 ++-- drivers/net/ethernet/ibm/emac/core.c | 2 +- drivers/net/ethernet/ibm/emac/mal.c | 2 +- drivers/net/ethernet/ibm/emac/rgmii.c | 2 +- drivers/net/ethernet/ibm/emac/tah.c | 2 +- drivers/net/ethernet/ibm/emac/zmii.c | 2 +- drivers/net/ethernet/octeon/octeon_mgmt.c | 2 +- drivers/net/ethernet/ti/netcp_core.c | 2 +- drivers/net/ethernet/via/via-rhine.c | 2 +- drivers/net/ethernet/via/via-velocity.c | 2 +- drivers/net/ethernet/xilinx/ll_temac_main.c | 2 +- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 2 +- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 2 +- drivers/net/phy/mdio-bcm-unimac.c | 2 +- drivers/net/phy/mdio-gpio.c | 2 +- drivers/net/phy/mdio-mux-gpio.c | 2 +- drivers/net/phy/mdio-mux-mmioreg.c| 2 +- drivers/net/phy/mdio-octeon.c | 2 +- drivers/net/wireless/orinoco/airport.c| 2 +- 40 files changed, 44 insertions(+), 44 deletions(-) -- 2.1.0 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 00/16 linux-next] drivers/net: constify of_device_id array
From: Fabian Frederick Date: Tue, 17 Mar 2015 19:37:31 +0100 > This small patchset adds const to of_device_id arrays in > drivers/net branch. Series applied, thanks. -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] mac80211: filter multicast data packets on AP_VLAN interfaces w/o sta
Currently, multicast data packets are dropped on AP interfaces if there are no authorized stations connected. This avoids superflous data packets to be transmitted on air. But when using AP_VLAN, this does not happen, as the current check does not apply to AP_VLAN interfaces. Though, there can easily be more AP_VLAN interfaces on an AP resulting in more multicast data frames. This is especially true since hostapd does not remove no-longer-used AP_VLAN interfaces and bridges. In order to filter on AP_VLAN interfaces, a per AP_VLAN interface counter is required (in constrast to the counter on the AP interface counting the stations on all related AP_VLAN interfaces as well). If there are multicast data frames on the AP interface and authorized stations only on the related AP_VLAN interfaces, these multicast data frames on the AP interface still won't be filtered. This is just left unchanged by this patch. Signed-off-by: Michael Braun --- net/mac80211/cfg.c| 12 net/mac80211/debugfs_netdev.c | 9 + net/mac80211/ieee80211_i.h| 1 + net/mac80211/sta_info.c | 17 + net/mac80211/tx.c | 8 5 files changed, 47 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 74f509c..53db0c3 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1360,6 +1360,18 @@ static int ieee80211_change_station(struct wiphy *wiphy, prev_4addr = true; } + if (sta->sta_state == IEEE80211_STA_AUTHORIZED && + sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && + !sta->sdata->u.vlan.sta && + sta->sdata != vlansdata) + atomic_dec(&sta->sdata->u.vlan.num_mcast_sta); + + if (sta->sta_state == IEEE80211_STA_AUTHORIZED && + vlansdata->vif.type == NL80211_IFTYPE_AP_VLAN && + !vlansdata->u.vlan.sta && + sta->sdata != vlansdata) + atomic_inc(&vlansdata->u.vlan.num_mcast_sta); + sta->sdata = vlansdata; if (sta->sta_state == IEEE80211_STA_AUTHORIZED && diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index c68896a..71b71e2 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -428,6 +428,7 @@ IEEE80211_IF_FILE_RW(uapsd_max_sp_len); IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC); IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC); IEEE80211_IF_FILE(dtim_count, u.ap.ps.dtim_count, DEC); +IEEE80211_IF_FILE(vlan_num_mcast_sta, u.vlan.num_mcast_sta, ATOMIC); static ssize_t ieee80211_if_fmt_num_buffered_multicast( const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) @@ -594,6 +595,11 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD_MODE(tkip_mic_test, 0200); } +static void add_vlan_files(struct ieee80211_sub_if_data *sdata) +{ + DEBUGFS_ADD(vlan_num_mcast_sta); +} + static void add_ibss_files(struct ieee80211_sub_if_data *sdata) { DEBUGFS_ADD_MODE(tsf, 0600); @@ -697,6 +703,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata) case NL80211_IFTYPE_AP: add_ap_files(sdata); break; + case NL80211_IFTYPE_AP_VLAN: + add_vlan_files(sdata); + break; case NL80211_IFTYPE_WDS: add_wds_files(sdata); break; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8d53d65..722ad28 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -305,6 +305,7 @@ struct ieee80211_if_vlan { /* used for all tx if the VLAN is configured to 4-addr mode */ struct sta_info __rcu *sta; + atomic_t num_mcast_sta; /* number of stations receiving multicast */ }; struct mesh_stats { diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 00ca8dc..68f9d2b 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -143,6 +143,17 @@ static void __cleanup_single_sta(struct sta_info *sta) ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); kfree(tid_tx); } + + if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { + if (sta->sdata->vif.type == NL80211_IFTYPE_AP || + (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && +!sta->sdata->u.vlan.sta)) + atomic_dec(&sta->sdata->bss->num_mcast_sta); + if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && +!sta->sdata->u.vlan.sta) + atomic_dec(&sta->sdata->u.vlan.num_mcast_sta); + clear_sta_flag(sta, WLAN_STA_AUTHORIZED); + } } static void cleanup_single_sta(struct sta_info *sta) @@ -1694,6 +1705,9 @@ int sta_info_move_state(struct sta_info *st
[PATCH] mac80211: fix typo in debug output
--- net/mac80211/cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 74f509c..62007ca 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2297,7 +2297,7 @@ int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata, } ht_dbg(sdata, - "SMSP %d requested in AP mode, sending Action frame to %d stations\n", + "SMPS %d requested in AP mode, sending Action frame to %d stations\n", smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta)); mutex_lock(&sdata->local->sta_mtx); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Broadcom 43340
Arend van Spriel writes: > > On 03/15/15 21:38, Jürgen Bausa wrote: > > > > would be nice, if you could make it clear. > > > > Maybe you need to mount it. This is what I found [1]: > > $ sudo mount -t efivarfs none /sys/firmware/efi/efivars > Thanks, that worked. Now I have firmware and nvram-file and the driver seems to load ok. At least I have an interface wlan0. However, I am not able to connect.Network-manager just says "interface is being set up ..." forever. I have no idea howto debug this. In the other post you said that the nl80211 driver should be used instead of wext. I found that nl80211 is the default for network-manager. So, whats going wrong here? JuergenN�r��yb�X��ǧv�^�){.n�+{��*ޕ�,�{ay�ʇڙ�,j��f���h���z��w��� ���j:+v���w�j�mzZ+�ݢj"��!�i
Re: [PATCH] mac80211: fix typo in debug output
Please resend with signed-off-by. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] iw: Print OSEN element for HotSpot 2.0 IE.
From: Ben Greear Re-uses most of the print-rsn logic since only the header differs. Example output: ... HotSpot 2.0 OSEN: * Group cipher: NO-GROUP * Pairwise ciphers: CCMP * Authentication suites: OSEN * Capabilities: 16-PTKSA-RC 1-GTKSA-RC (0x000c) Signed-off-by: Ben Greear --- scan.c | 51 +++ 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/scan.c b/scan.c index 538b30e..f01921a 100644 --- a/scan.c +++ b/scan.c @@ -410,6 +410,9 @@ static void print_cipher(const uint8_t *data) case 6: printf("AES-128-CMAC"); break; + case 7: + printf("NO-GROUP"); + break; case 8: printf("GCMP"); break; @@ -466,24 +469,37 @@ static void print_auth(const uint8_t *data) data[0], data[1] ,data[2], data[3]); break; } + } else if (memcmp(data, wfa_oui, 3) == 0) { + switch (data[3]) { + case 1: + printf("OSEN"); + break; + default: + printf("%.02x-%.02x-%.02x:%d", + data[0], data[1] ,data[2], data[3]); + break; + } } else printf("%.02x-%.02x-%.02x:%d", data[0], data[1] ,data[2], data[3]); } -static void print_rsn_ie(const char *defcipher, const char *defauth, -uint8_t len, const uint8_t *data) +static void _print_rsn_ie(const char *defcipher, const char *defauth, + uint8_t len, const uint8_t *data, int is_osen) { bool first = true; - __u16 version, count, capa; + __u16 count, capa; int i; - version = data[0] + (data[1] << 8); - tab_on_first(&first); - printf("\t * Version: %d\n", version); + if (!is_osen) { + __u16 version; + version = data[0] + (data[1] << 8); + tab_on_first(&first); + printf("\t * Version: %d\n", version); - data += 2; - len -= 2; + data += 2; + len -= 2; + } if (len < 4) { tab_on_first(&first); @@ -627,6 +643,19 @@ static void print_rsn_ie(const char *defcipher, const char *defauth, } } +static void print_rsn_ie(const char *defcipher, const char *defauth, +uint8_t len, const uint8_t *data) +{ + _print_rsn_ie(defcipher, defauth, len, data, 0); +} + +static void print_osen_ie(const char *defcipher, const char *defauth, + uint8_t len, const uint8_t *data) +{ + printf("\n\t"); + _print_rsn_ie(defcipher, defauth, len, data, 1); +} + static void print_rsn(const uint8_t type, uint8_t len, const uint8_t *data) { print_rsn_ie("CCMP", "IEEE 802.1X", len, data); @@ -1076,6 +1105,11 @@ static void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data) print_rsn_ie("TKIP", "IEEE 802.1X", len, data); } +static void print_wifi_osen(const uint8_t type, uint8_t len, const uint8_t *data) +{ + print_osen_ie("OSEN", "OSEN", len, data); +} + static bool print_wifi_wmm_param(const uint8_t *data, uint8_t len) { int i; @@ -1429,6 +1463,7 @@ static inline void print_hs20_ind(const uint8_t type, uint8_t len, const uint8_t static const struct ie_print wfa_printers[] = { [9] = { "P2P", print_p2p, 2, 255, BIT(PRINT_SCAN), }, [16] = { "HotSpot 2.0 Indication", print_hs20_ind, 1, 255, BIT(PRINT_SCAN), }, + [18] = { "HotSpot 2.0 OSEN", print_wifi_osen, 1, 255, BIT(PRINT_SCAN), }, }; static void print_vendor(unsigned char len, unsigned char *data, -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Broadcom 43340
On 03/17/15 22:01, Jürgen Bausa wrote: Arend van Spriel writes: On 03/15/15 21:38, Jürgen Bausa wrote: would be nice, if you could make it clear. Maybe you need to mount it. This is what I found [1]: $ sudo mount -t efivarfs none /sys/firmware/efi/efivars Thanks, that worked. Now I have firmware and nvram-file and the driver seems to load ok. At least I have an interface wlan0. However, I am not able to connect.Network-manager just says "interface is being set up ..." forever. I have no idea howto debug this. In the other post you said that the nl80211 driver should be used instead of wext. I found that nl80211 is the default for network-manager. So, whats going wrong here? Could you provide output of these: $ iw dev $ iw list $ ifconfig -a Regards, Arend -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] brcmfmac: cfg80211: use msecs_to_jiffies for time conversion
On Tue, 2015-03-17 at 08:06 -0400, Nicholas Mc Guire wrote: > Converting milliseconds to jiffies by "val * HZ / 1000" is technically > OK but msecs_to_jiffies(val) is the cleaner solution and handles all > corner cases correctly. This is a minor API consolidation only and > should make things more readable. Hi Nicholas These API consolidation changes now always have a function call when the compiler may have previously been able to optimize out the "constant * HZ / 1000" calculation. Perhaps the [um]secs_to_jiffies calls should be indirected with yet another static inline with a __builtin_constant_p() test so that the function calls can again be avoided when possible. (and a trivial style note) > diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c > b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c [] > @@ -1110,7 +1110,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct > brcmf_cfg80211_vif *vif, > > /* Arm scan timeout timer */ > mod_timer(&cfg->escan_timeout, jiffies + > - WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000); > + msecs_to_jiffies(WL_ESCAN_TIMER_INTERVAL_MS)); It may be nicer to keep the arithmetic on one line mod_timer(&cfg->escan_timeout, jiffies + msecs_to_jiffies(WL_ESCAN_TIMER_INTERVAL_MS)); -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Broadcom 43340
On Tue, 2015-03-17 at 21:01 +, Jürgen Bausa wrote: > Arend van Spriel writes: > > > > > On 03/15/15 21:38, Jürgen Bausa wrote: > > > > > > would be nice, if you could make it clear. > > > > > > > Maybe you need to mount it. This is what I found [1]: > > > > $ sudo mount -t efivarfs none /sys/firmware/efi/efivars > > > > Thanks, that worked. Now I have firmware and nvram-file and the driver seems > to load ok. At least I have an interface wlan0. > > However, I am not able to connect.Network-manager just says "interface is > being set up ..." forever. I have no idea howto debug this. In the other > post you said that the nl80211 driver should be used instead of wext. I > found that nl80211 is the default for network-manager. So, whats going wrong > here? Could you provide more NetworkManager logs? They should look like this; where do your logs stop? NetworkManager[1949]: (wlan0): Activation: starting connection 'my wifi' NetworkManager[1949]: (wlan0): Activation: Stage 1 of 5 (Device Prepare) scheduled... NetworkManager[1949]: (wlan0): Activation: Stage 1 of 5 (Device Prepare) started... NetworkManager[1949]: (wlan0): device state change: disconnected -> prepare (reason 'none') [30 40 0] NetworkManager[1949]: (wlan0): Activation: Stage 2 of 5 (Device Configure) scheduled... NetworkManager[1949]: (wlan0): Activation: Stage 1 of 5 (Device Prepare) complete. NetworkManager[1949]: (wlan0): Activation: Stage 2 of 5 (Device Configure) starting... NetworkManager[1949]: (wlan0): device state change: prepare -> config (reason 'none') [40 50 0] NetworkManager[1949]: (wlan0): Activation: (wifi) connection 'my wifi' has security, and secrets exist. No new secrets needed. NetworkManager[1949]: Config: added 'ssid' value 'my wifi' NetworkManager[1949]: Config: added 'scan_ssid' value '1' NetworkManager[1949]: Config: added 'key_mgmt' value 'WPA-PSK' NetworkManager[1949]: Config: added 'psk' value '' NetworkManager[1949]: Config: added 'proto' value 'WPA RSN' NetworkManager[1949]: (wlan0): Activation: Stage 2 of 5 (Device Configure) complete. NetworkManager[1949]: Config: set interface ap_scan to 1 NetworkManager[1949]: (wlan0): supplicant interface state: inactive -> scanning NetworkManager[1949]: (wlan0): supplicant interface state: scanning -> authenticating NetworkManager[1949]: (wlan0): supplicant interface state: authenticating -> associating NetworkManager[1949]: (wlan0): supplicant interface state: associating -> associated NetworkManager[1949]: (wlan0): supplicant interface state: associated -> 4-way handshake NetworkManager[1949]: (wlan0): supplicant interface state: 4-way handshake -> completed Dan -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] mac80211: fix typo in debug output
Signed-off-by: Michael Braun --- net/mac80211/cfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 74f509c..62007ca 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2297,7 +2297,7 @@ int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata, } ht_dbg(sdata, - "SMSP %d requested in AP mode, sending Action frame to %d stations\n", + "SMPS %d requested in AP mode, sending Action frame to %d stations\n", smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta)); mutex_lock(&sdata->local->sta_mtx); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] brcmfmac: cfg80211: use msecs_to_jiffies for time conversion
On Tue, 17 Mar 2015, Joe Perches wrote: > On Tue, 2015-03-17 at 08:06 -0400, Nicholas Mc Guire wrote: > > Converting milliseconds to jiffies by "val * HZ / 1000" is technically > > OK but msecs_to_jiffies(val) is the cleaner solution and handles all > > corner cases correctly. This is a minor API consolidation only and > > should make things more readable. > > Hi Nicholas > > These API consolidation changes now always have a function > call when the compiler may have previously been able to > optimize out the "constant * HZ / 1000" calculation. > > Perhaps the [um]secs_to_jiffies calls should be indirected > with yet another static inline with a __builtin_constant_p() > test so that the function calls can again be avoided when > possible. will give it a try > > (and a trivial style note) > > > diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c > > b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c > [] > > @@ -1110,7 +1110,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct > > brcmf_cfg80211_vif *vif, > > > > /* Arm scan timeout timer */ > > mod_timer(&cfg->escan_timeout, jiffies + > > - WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000); > > + msecs_to_jiffies(WL_ESCAN_TIMER_INTERVAL_MS)); > > It may be nicer to keep the arithmetic on one line sorry that was plain carelessness afer it went over 80 char. > > mod_timer(&cfg->escan_timeout, > jiffies + msecs_to_jiffies(WL_ESCAN_TIMER_INTERVAL_MS)); > thx! hofrat -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] cfg/mac80211: add regulatory classes IE during TDLS setup
From: Arik Nemtsov Seems Broadcom TDLS peers (Nexus 5, Xperia Z3) refuse to allow TDLS connection when channel-switching is supported but the regulatory classes IE is missing from the setup request. Add a chandef to reg-class translation function to cfg80211 and use it to add the required IE during setup. For now add only the current regulatory class as supported - it is enough to resolve the compatibility issue. Signed-off-by: Arik Nemtsov Signed-off-by: Emmanuel Grumbach --- include/net/cfg80211.h | 11 + net/mac80211/tdls.c| 21 net/wireless/util.c| 129 + 3 files changed, 161 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 12a6121..c4d873b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4903,6 +4903,17 @@ void cfg80211_ch_switch_started_notify(struct net_device *dev, bool ieee80211_operating_class_to_band(u8 operating_class, enum ieee80211_band *band); +/** + * ieee80211_chandef_to_operating_class - convert chandef to operation class + * + * @chandef: the chandef to convert + * @op_class: a pointer to the resulting operating class + * + * Returns %true if the conversion was successful, %false otherwise. + */ +bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, + u8 *op_class); + /* * cfg80211_tdls_oper_request - request userspace to perform TDLS operation * @dev: the device on which the operation is requested diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index bc7e404..79ed59a 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c @@ -136,6 +136,24 @@ ieee80211_tdls_add_supp_channels(struct ieee80211_sub_if_data *sdata, *pos = 2 * subband_cnt; } +static void ieee80211_tdls_add_oper_classes(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) +{ + u8 *pos; + u8 op_class; + + if (!ieee80211_chandef_to_operating_class(&sdata->vif.bss_conf.chandef, + &op_class)) + return; + + pos = skb_put(skb, 4); + *pos++ = WLAN_EID_SUPPORTED_REGULATORY_CLASSES; + *pos++ = 2; /* len */ + + *pos++ = op_class; + *pos++ = op_class; /* give current operating class as alternate too */ +} + static void ieee80211_tdls_add_bss_coex_ie(struct sk_buff *skb) { u8 *pos = (void *)skb_put(skb, 3); @@ -350,6 +368,8 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata, } } + ieee80211_tdls_add_oper_classes(sdata, skb); + /* * with TDLS we can switch channels, and HT-caps are not necessarily * the same on all bands. The specification limits the setup to a @@ -786,6 +806,7 @@ ieee80211_tdls_build_mgmt_packet_data(struct ieee80211_sub_if_data *sdata, 50 + /* supported channels */ 3 + /* 40/20 BSS coex */ 4 + /* AID */ + 4 + /* oper classes */ extra_ies_len + sizeof(struct ieee80211_tdls_lnkie)); if (!skb) diff --git a/net/wireless/util.c b/net/wireless/util.c index f7b3598..f218b15 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1314,6 +1314,135 @@ bool ieee80211_operating_class_to_band(u8 operating_class, } EXPORT_SYMBOL(ieee80211_operating_class_to_band); +bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef, + u8 *op_class) +{ + u8 vht_opclass; + u16 freq = chandef->center_freq1; + + if (freq >= 2412 && freq <= 2472) { + if (chandef->width > NL80211_CHAN_WIDTH_40) + return false; + + /* 2.407 GHz, channels 1..13 */ + if (chandef->width == NL80211_CHAN_WIDTH_40) { + if (freq > chandef->chan->center_freq) + *op_class = 83; /* HT40+ */ + else + *op_class = 84; /* HT40- */ + } else { + *op_class = 81; + } + + return true; + } + + if (freq == 2484) { + if (chandef->width > NL80211_CHAN_WIDTH_40) + return false; + + *op_class = 82; /* channel 14 */ + return true; + } + + switch (chandef->width) { + case NL80211_CHAN_WIDTH_80: + vht_opclass = 128; + break; + case NL80211_CHAN_WIDTH_160: + vht_opclass = 129; + break; + case NL80211_CHAN_WIDTH_80P80: + vht_opclass = 130; + break; + case NL80211_CHAN_WIDTH_10: + case NL802