[PATCH iw] phy: Allow set netns by fd
From: Vadim Kochan Added possibility to change network namespace for phy device by network namespace name from /var/run/netns or by absolute file path: iw phy XXX set netns name iw tries to open fd of given nsname from /var/run/netns or by absoute path if nsname contains "/". Signed-off-by: Vadim Kochan --- phy.c | 55 ++- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/phy.c b/phy.c index aab462d..271c9d9 100644 --- a/phy.c +++ b/phy.c @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include #include #include @@ -296,6 +299,24 @@ COMMAND(set, retry, "[short ] [long ]", NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_retry, "Set retry limit."); +#ifndef NETNS_RUN_DIR +#define NETNS_RUN_DIR "/var/run/netns" +#endif +int netns_get_fd(const char *name) +{ + char pathbuf[MAXPATHLEN]; + const char *path, *ptr; + + path = name; + ptr = strchr(name, '/'); + if (!ptr) { + snprintf(pathbuf, sizeof(pathbuf), "%s/%s", + NETNS_RUN_DIR, name ); + path = pathbuf; + } + return open(path, O_RDONLY); +} + static int handle_netns(struct nl80211_state *state, struct nl_cb *cb, struct nl_msg *msg, @@ -303,26 +324,42 @@ static int handle_netns(struct nl80211_state *state, enum id_input id) { char *end; + int fd; - if (argc != 1) + if (argc < 1 || !*argv[0]) return 1; - if (!*argv[0]) + if (argc == 1) { + NLA_PUT_U32(msg, NL80211_ATTR_PID, + strtoul(argv[0], &end, 10)); + if (*end != '\0') { + printf("Invalid parameter: pid(%s)\n", argv[0]); + return 1; + } + return 0; + } + + if (argc != 2 || strcmp(argv[0], "name")) return 1; - NLA_PUT_U32(msg, NL80211_ATTR_PID, - strtoul(argv[0], &end, 10)); + if ((fd = netns_get_fd(argv[1])) >= 0) { + NLA_PUT_U32(msg, NL80211_ATTR_NETNS_FD, fd); + return 0; + } else { + printf("Invalid parameter: nsname(%s)\n", argv[0]); + } - if (*end != '\0') - return 1; + return 1; - return 0; nla_put_failure: return -ENOBUFS; } -COMMAND(set, netns, "", +COMMAND(set, netns, "{ | name }", NL80211_CMD_SET_WIPHY_NETNS, 0, CIB_PHY, handle_netns, - "Put this wireless device into a different network namespace"); + "Put this wireless device into a different network namespace:\n" + "- change network namespace by process id\n" + " - change network namespace by name from "NETNS_RUN_DIR"\n" + " or by absolute path (man ip-netns)\n"); static int handle_coverage(struct nl80211_state *state, struct nl_cb *cb, -- 2.2.2 -- 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: Fwd: Kernel 3.6.0 works, newer doesn't
On 02/13/2015 09:58 PM, Tim-Hinnerk Heuer wrote: Hi can someone here help with this issue, please? I'm willing to give more info if necessary or help out otherwise. I am a programmer but haven't done much with Linux drivers yet. First key is probably defining 'not working'. Second key is likely to be a dmesg output of it 'not working'. Third detail that is likely to help is what distribution you're running and how how you're attempting to manage the wifi device(networkmanager/wicd/etc). Hi there, Sorry, I'm new to this list, so excuse my newbie question. I have Linux 3.6.0-030600-generic #201209302035 SMP Mon Oct 1 00:36:01 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux installed and it works great. My WLAN driver works with this version, but not with any newer version of the kernel. Am I right that backports can help me with that? Can I somehow upgrade to a newer version of the kernel and keep my WIFI USB driver and maybe even upgrade to newer kernels? Or even better, does someone here have the capacity to fix the problem in newer kernels? My Wifi USB Card is the Asus USB N13 ``` lsusb Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 004: ID 0b05:1784 ASUSTek Computer, Inc. USB-N13 802.11n Network Adapter (rev. A1) [Ralink RT3072] Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub sudo lsmod|grep rt xt_addrtype12713 2 x_tables 29846 6 ip_tables,ipt_MASQUERADE,xt_conntrack,iptable_filter,xt_addrtype,iptable_nat rt2800usb 26998 0 rt2x00usb 20762 1 rt2800usb rt2800lib 63557 1 rt2800usb rt2x00lib 55527 3 rt2x00usb,rt2800lib,rt2800usb mac80211 564631 3 rt2x00lib,rt2x00usb,rt2800lib cfg80211 212917 2 mac80211,rt2x00lib crc_ccitt 12667 1 rt2800lib parport_pc 32866 0 parport46562 3 lp,ppdev,parport_pc ``` Running Ubuntu 14.04. Thanks for your patience. Tim -- Forwarded message -- From: Greg KH Date: 14 February 2015 at 04:19 Subject: Re: Kernel 3.6.0 works, newer doesn't To: Tim-Hinnerk Heuer Cc: linux-...@vger.kernel.org On Fri, Feb 13, 2015 at 11:20:33PM +1300, Tim-Hinnerk Heuer wrote: Hi there, Sorry, I'm new to this list, so excuse my newbie question. I have Linux 3.6.0-030600-generic #201209302035 SMP Mon Oct 1 00:36:01 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux installed and it works great. My WLAN driver works with this version, but not with any newer version of the kernel. Am I right that backports can help me with that? I suggest working with the driver authors of that driver to fix it to work with the latest kernel version. It is merged into the main kernel.org repo, right? Which one is it? The networking mailing list should be able to help you out the best, try sending this to the linux-wireless@vger.kernel.org hope this helps, greg k-h -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- 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 -- 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
Fwd: Kernel 3.6.0 works, newer doesn't
Hi can someone here help with this issue, please? I'm willing to give more info if necessary or help out otherwise. I am a programmer but haven't done much with Linux drivers yet. Hi there, Sorry, I'm new to this list, so excuse my newbie question. I have Linux 3.6.0-030600-generic #201209302035 SMP Mon Oct 1 00:36:01 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux installed and it works great. My WLAN driver works with this version, but not with any newer version of the kernel. Am I right that backports can help me with that? Can I somehow upgrade to a newer version of the kernel and keep my WIFI USB driver and maybe even upgrade to newer kernels? Or even better, does someone here have the capacity to fix the problem in newer kernels? My Wifi USB Card is the Asus USB N13 ``` lsusb Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 004: ID 0b05:1784 ASUSTek Computer, Inc. USB-N13 802.11n Network Adapter (rev. A1) [Ralink RT3072] Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub sudo lsmod|grep rt xt_addrtype12713 2 x_tables 29846 6 ip_tables,ipt_MASQUERADE,xt_conntrack,iptable_filter,xt_addrtype,iptable_nat rt2800usb 26998 0 rt2x00usb 20762 1 rt2800usb rt2800lib 63557 1 rt2800usb rt2x00lib 55527 3 rt2x00usb,rt2800lib,rt2800usb mac80211 564631 3 rt2x00lib,rt2x00usb,rt2800lib cfg80211 212917 2 mac80211,rt2x00lib crc_ccitt 12667 1 rt2800lib parport_pc 32866 0 parport46562 3 lp,ppdev,parport_pc ``` Running Ubuntu 14.04. Thanks for your patience. Tim -- Forwarded message -- From: Greg KH Date: 14 February 2015 at 04:19 Subject: Re: Kernel 3.6.0 works, newer doesn't To: Tim-Hinnerk Heuer Cc: linux-...@vger.kernel.org On Fri, Feb 13, 2015 at 11:20:33PM +1300, Tim-Hinnerk Heuer wrote: > Hi there, > > Sorry, I'm new to this list, so excuse my newbie question. > > I have Linux 3.6.0-030600-generic #201209302035 SMP Mon Oct 1 00:36:01 > UTC 2012 x86_64 x86_64 x86_64 GNU/Linux installed and it works great. > My WLAN driver works with this version, but not with any newer version > of the kernel. Am I right that backports can help me with that? I suggest working with the driver authors of that driver to fix it to work with the latest kernel version. It is merged into the main kernel.org repo, right? Which one is it? The networking mailing list should be able to help you out the best, try sending this to the linux-wireless@vger.kernel.org hope this helps, greg k-h -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- 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: [RFC] mac80211: use rhashtable for station table
2015-02-14 0:47 GMT+03:00 Johannes Berg : > We currently have a hand-rolled table with 256 entries and are > using the last byte of the MAC address as the hash. This hash > is obviously very fast, but collisions are easily created and > we waste a lot of space in the common case of just connecting > as a client to an AP where we just have a single station. The > other common case of an AP is also suboptimal due to the size > of the hash table and the ease of causing collisions. > > Convert all of this to use rhashtable with jhash, which gives > us the advantage of a far better hash function (with random > perturbation to avoid hash collision attacks) and of course > that the hash table grows and shrinks dynamically with chain > length, improving both cases above. > A nice change! Couple of years ago I did some tests with real sets of MACs and jhash gives a better distribution than usage of a last octet. BTW, why do you use full address and generic jhash? Hashing of two least significant words could be faster. Isn't it? -- Sergey -- 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: [RFC] mac80211: use rhashtable for station table
On 02/13/2015 01:47 PM, Johannes Berg wrote: > From: Johannes Berg > > We currently have a hand-rolled table with 256 entries and are > using the last byte of the MAC address as the hash. This hash > is obviously very fast, but collisions are easily created and > we waste a lot of space in the common case of just connecting > as a client to an AP where we just have a single station. The > other common case of an AP is also suboptimal due to the size > of the hash table and the ease of causing collisions. > > Convert all of this to use rhashtable with jhash, which gives > us the advantage of a far better hash function (with random > perturbation to avoid hash collision attacks) and of course > that the hash table grows and shrinks dynamically with chain > length, improving both cases above. Oooh, maybe finally time to mix local addr with peer addr to make lots of vifs connected to same AP hash well too? :) Thanks, Ben -- Ben Greear Candela Technologies Inc http://www.candelatech.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
[RFC] mac80211: use rhashtable for station table
From: Johannes Berg We currently have a hand-rolled table with 256 entries and are using the last byte of the MAC address as the hash. This hash is obviously very fast, but collisions are easily created and we waste a lot of space in the common case of just connecting as a client to an AP where we just have a single station. The other common case of an AP is also suboptimal due to the size of the hash table and the ease of causing collisions. Convert all of this to use rhashtable with jhash, which gives us the advantage of a far better hash function (with random perturbation to avoid hash collision attacks) and of course that the hash table grows and shrinks dynamically with chain length, improving both cases above. Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 3 +- net/mac80211/main.c| 9 +++-- net/mac80211/rx.c | 4 +-- net/mac80211/sta_info.c| 87 -- net/mac80211/sta_info.h| 37 ++-- net/mac80211/status.c | 4 +-- 6 files changed, 59 insertions(+), 85 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 3afe36824703..798392398ab5 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1195,7 +1196,7 @@ struct ieee80211_local { spinlock_t tim_lock; unsigned long num_sta; struct list_head sta_list; - struct sta_info __rcu *sta_hash[STA_HASH_SIZE]; + struct rhashtable sta_hash; struct timer_list sta_cleanup; int sta_generation; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5e09d354c5a5..95d59d24b271 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -557,6 +557,9 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, local = wiphy_priv(wiphy); + if (sta_info_init(local)) + goto err_free; + local->hw.wiphy = wiphy; local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); @@ -629,8 +632,6 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, spin_lock_init(&local->ack_status_lock); idr_init(&local->ack_status_frames); - sta_info_init(local); - for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { skb_queue_head_init(&local->pending[i]); atomic_set(&local->agg_queue_stop[i], 0); @@ -650,6 +651,9 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, ieee80211_roc_setup(local); return &local->hw; + err_free: + wiphy_free(wiphy); + return NULL; } EXPORT_SYMBOL(ieee80211_alloc_hw_nm); @@ -1173,7 +1177,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) destroy_workqueue(local->workqueue); wiphy_unregister(local->hw.wiphy); - sta_info_stop(local); ieee80211_wep_free(local); ieee80211_led_exit(local); kfree(local->int_scan_req); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index ed38d8302659..aa238a66ae2e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3417,7 +3417,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, __le16 fc; struct ieee80211_rx_data rx; struct ieee80211_sub_if_data *prev; - struct sta_info *sta, *tmp, *prev_sta; + struct sta_info *sta, *prev_sta; int err = 0; fc = ((struct ieee80211_hdr *)skb->data)->frame_control; @@ -3454,7 +3454,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, if (ieee80211_is_data(fc)) { prev_sta = NULL; - for_each_sta_info(local, hdr->addr2, sta, tmp) { + for_each_sta_info(local, hdr->addr2, sta) { if (!prev_sta) { prev_sta = sta; continue; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 00ca8dcc2bcf..0535bf89e115 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -68,28 +68,7 @@ static int sta_info_hash_del(struct ieee80211_local *local, struct sta_info *sta) { - struct sta_info *s; - - s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)], - lockdep_is_held(&local->sta_mtx)); - if (!s) - return -ENOENT; - if (s == sta) { - rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], - s->hnext); - return 0; - } - - while (rcu_access_pointer(s->hnext) && - rcu_access_pointer(s->hnext) != sta) - s = rcu_dereference_protected(s->hnext, - lockdep_is_held(&local->sta_mtx)); - if (rcu_access_pointer(s->hnext)) { - rcu_assign_
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. 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 v2] ath10k: Increase AST table SKID length limit
The current SKID length configuration causes firmware to reject peer creation for not able to allocate AST entries for peers. This issue is observed when least significant 3 bytes are used ramdomly to create client MAC addresses. AST table SKID length configuration is increased to maximum value to fix this issue. Signed-off-by: SenthilKumar Jegadeesan --- drivers/net/wireless/ath/ath10k/hw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 460771f..7f04645 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -223,7 +223,7 @@ struct ath10k_pktlog_hdr { #define TARGET_10X_NUM_WDS_ENTRIES 32 #define TARGET_10X_DMA_BURST_SIZE 0 #define TARGET_10X_MAC_AGGR_DELIM 0 -#define TARGET_10X_AST_SKID_LIMIT 16 +#define TARGET_10X_AST_SKID_LIMIT 128 #define TARGET_10X_NUM_STATIONS128 #define TARGET_10X_NUM_PEERS ((TARGET_10X_NUM_STATIONS) + \ (TARGET_10X_NUM_VDEVS)) -- 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 v2 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 42dfef8..c108f03 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -161,7 +161,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) @@ -169,11 +169,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 { @@ -200,7 +209,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 182d552..a217a2c 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 v2 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.2.2 -- 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 v2 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 v2 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 ++ net/mac80211/rc80211_minstrel_ht_debugfs.c | 2 +- 3 files changed, 88 insertions(+), 15 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..ab15ca6 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, + (uns
[PATCH v2 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 v2 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| 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; + 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]]))) 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; @@ -168,19 +188,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 +215,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 +688,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
[PATCH v2 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 80452cf..381d089 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -311,32 +311,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 v2 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| 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; +} /* find & sort topmost throughput rates */ static inline void 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 d8ccef7..182d552 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 = MINSTREL_TRUNC(mrs->prob_ewma * 1000); -
[PATCH v2 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 b300513..ae05780 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 v2 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.2.2 -- 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 v2 0/10] Improve Minstrels & Minstrel-HTs common code base & statistics
This patch series adds several improvements to the readability, the output format of rc_stats and the calculated statistics of Minstrel and Minstrel-HT. Variable names got more consistent and functions got unified between both rate control algorithms. Greetings Thomas --- Changes in v2: - fix define MACRO from CPTCFG_* into CONFIG_* - change standard deviation symbol sigma into "sd" [PATCH v2 01/10] mac80211: enhance readability of Minstrels rc_stats [PATCH v2 02/10] mac80211: enhance readability of Minstrel-HTs [PATCH v2 03/10] mac80211: add new Minstrel statistic output via csv [PATCH v2 04/10] mac80211: add new Minstrel-HT statistic output via [PATCH v2 05/10] mac80211: unify Minstrel & Minstrel-HTs calculation [PATCH v2 06/10] mac80211: improve Minstrel variable & function [PATCH v2 07/10] mac80211: restructure per-rate throughput [PATCH v2 08/10] mac80211: add max. lossless throughput per rate to [PATCH v2 09/10] mac80211: reduce calculation costs of EWMA [PATCH v2 10/10] mac80211: add standard deviation to Minstrels -- 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] ath10k: Increase AST table SKID length limit
On Thu, Feb 12, 2015 at 05:13:21AM -0800, Ben Greear wrote: > > > On 02/12/2015 01:28 AM, SenthilKumar Jegadeesan wrote: > >The current SKID length configuration causes firmware > >to reject peer creation for not able to allocate > >AST entries for peers. This issue is observed when > >least significant 3 bytes are used ramdomly to create > >client MAC addresses. > > > >AST table SKID length configuration is increased to > >maximum value to fix this issue. > > If your firmware is like 10.1, then probably AST length should > really be same as config.num_peers? > > 10.1 firmware definitely has same or similar issue in it's > AST table handling, for what that is worth. > > Thanks, > Ben I agree. New patch will address this case. Thanks, Senthil J -- 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 1/2] ath10k: workaround qca6174 sta powersave issue
qca6184 WLAN.RM.2.0-00073 has a bug in sta powersave state machine and requires peer param to be poked to enable the powersave. Calling this unconditionally should be safe for other chips/firmwares. Signed-off-by: Michal Kazior --- drivers/net/wireless/ath/ath10k/mac.c | 12 drivers/net/wireless/ath/ath10k/wmi.h | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index d6d2f0f..8ed0ba6 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1853,6 +1853,18 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, } arvif->is_up = true; + + /* Workaround: Some firmware revisions (tested with qca6174 +* WLAN.RM.2.0-00073) have buggy powersave state machine and must be +* poked with peer param command. +*/ + ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, arvif->bssid, + WMI_PEER_DUMMY_VAR, 1); + if (ret) { + ath10k_warn(ar, "failed to poke peer %pM param for ps workaround on vdev %i: %d\n", + arvif->bssid, arvif->vdev_id, ret); + return; + } } static void ath10k_bss_disassoc(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 20ce360..c56de92 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4436,7 +4436,8 @@ enum wmi_peer_param { WMI_PEER_AUTHORIZE = 0x3, WMI_PEER_CHAN_WIDTH = 0x4, WMI_PEER_NSS= 0x5, - WMI_PEER_USE_4ADDR = 0x6 + WMI_PEER_USE_4ADDR = 0x6, + WMI_PEER_DUMMY_VAR = 0xff, /* dummy parameter for STA PS workaround */ }; struct wmi_peer_set_param_cmd { -- 1.8.5.3 -- 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 2/2] ath10k: disable multi-vif ps by default
Not all firmware revisions have a proper multi-interface client powersaving implementation, e.g. qca6174 WLAN.RM.2.0-00073. Signed-off-by: Michal Kazior --- @Kalle: 999.999.0.636 seems to work okay with multi-vif PS so you might want to bump it with the MULTI_VIF_PS_SUPPORT feature flag set. drivers/net/wireless/ath/ath10k/core.h | 7 +++ drivers/net/wireless/ath/ath10k/mac.c | 31 +-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index d60e46f..c900ef2 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -288,6 +288,7 @@ struct ath10k_vif { bool is_started; bool is_up; bool spectral_enabled; + bool ps; u32 aid; u8 bssid[ETH_ALEN]; @@ -413,6 +414,12 @@ enum ath10k_fw_features { */ ATH10K_FW_FEATURE_WMI_10_2 = 4, + /* Some firmware revisions lack proper multi-interface client powersave +* implementation. Enabling PS could result in connection drops, +* traffic stalls, etc. +*/ + ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT = 5, + /* keep last */ ATH10K_FW_FEATURE_COUNT, }; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 8ed0ba6..bab8adc 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1253,6 +1253,20 @@ static int ath10k_mac_vif_recalc_ps_poll_count(struct ath10k_vif *arvif) return 0; } +static int ath10k_mac_ps_vif_count(struct ath10k *ar) +{ + struct ath10k_vif *arvif; + int num = 0; + + lockdep_assert_held(&ar->conf_mutex); + + list_for_each_entry(arvif, &ar->arvifs, list) + if (arvif->ps) + num++; + + return num; +} + static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif) { struct ath10k *ar = arvif->ar; @@ -1262,13 +1276,24 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif) enum wmi_sta_ps_mode psmode; int ret; int ps_timeout; + bool enable_ps; lockdep_assert_held(&arvif->ar->conf_mutex); if (arvif->vif->type != NL80211_IFTYPE_STATION) return 0; - if (vif->bss_conf.ps) { + enable_ps = arvif->ps; + + if (enable_ps && ath10k_mac_ps_vif_count(ar) > 1 && + !test_bit(ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT, + ar->fw_features)) { + ath10k_warn(ar, "refusing to enable ps on vdev %i: not supported by fw\n", + arvif->vdev_id); + enable_ps = false; + } + + if (enable_ps) { psmode = WMI_STA_PS_MODE_ENABLED; param = WMI_STA_PS_PARAM_INACTIVITY_TIME; @@ -3546,7 +3571,9 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, } if (changed & BSS_CHANGED_PS) { - ret = ath10k_mac_vif_setup_ps(arvif); + arvif->ps = vif->bss_conf.ps; + + ret = ath10k_config_ps(ar); if (ret) ath10k_warn(ar, "failed to setup ps on vdev %i: %d\n", arvif->vdev_id, ret); -- 1.8.5.3 -- 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] iwl4965: Enable checking of format strings
On Fri, Feb 13 2015, David Laight wrote: > From: Rasmus Villemoes >> Well, probably the linker is allowed to overlap "anonymous" objects >> (string literals) with whatever const char[] (or indeed any const) >> object it finds containing the appropriate byte sequence. But I think >> language lawyers would insist that for >> >> const char foo[] = "a string"; >> const char bar[] = "a string"; > > A quick test shows those are separate strings. > But 'const char *foo = "xxx";' will share. Yes, of course, because in that case you are actually creating two objects, "xxx" which the linker will find some place to put, and foo which is initialized to the address of whereever "xxx" was/will be put. So one is wasting sizeof(const char*). Also, passing foo to a function means the compiler has to load the value of foo and use that, instead of simply passing the compile-time (well, link-time) constant address of "xxx". > You also need -O1 to get the strings into .rodata.str.n so that the linker > can merge them. Sure, optimization has to be turned on, but isn't the kernel always compiled with -O2? ISTR that there are some things which won't even work/compile with -O0. Rasmus -- 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] iwl4965: Enable checking of format strings
From: Rasmus Villemoes > Well, probably the linker is allowed to overlap "anonymous" objects > (string literals) with whatever const char[] (or indeed any const) > object it finds containing the appropriate byte sequence. But I think > language lawyers would insist that for > > const char foo[] = "a string"; > const char bar[] = "a string"; A quick test shows those are separate strings. But 'const char *foo = "xxx";' will share. You also need -O1 to get the strings into .rodata.str.n so that the linker can merge them. David -- 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
rtl8192cu beacon fix unreliable
When using hostapd and an rtl8192cu Wireless USB adaptor the beacon doesn't start sometimes. This was tested with the kernel/git/davem/net-next.git repository and 3423eb92315865d76cb8d488513bfef6ab9251d0 This behaviour is apparently random. If the beacon starts OK then it continues. If a beacon isn't generated then it never starts. Repeating cycles of hostapd stop/start may or may not generate a beacon. There are no specific error messages displayed either on console or in syslog. I have repeated hostapd stop/start a number of consecutive times and received a beacon each time, however I have also done this a number of times and never generated a beacon. We have succesfully used the pvaret-rtl8192cu driver which is based on the vendor driver and used that in conjunction with the modified hostapd code that requires use of the rtl871xdrv driver interface and as far as we have seen it always generates a beacon. Platform is a custom designed Atmel-ARM CPU (AT91SAM9G25) with a D-Link DWA-121. -- 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] iwl4965: Enable checking of format strings
On Fri, Feb 13 2015, Mark Rustad wrote: > On 2/12/15 2:20 AM, Rasmus Villemoes wrote: >> Rather weak arguments, but I have three of them :-) > > Yes, weak. All three. > >> (1) If I'm reading some code and spot a non-constant format >> argument, I sometimes track back to see how e.g. fmt_value is >> defined. If I then see it's a macro, I immediately think "ok, the >> compiler is doing type-checking". If it is a const char[], I have >> to remember that gcc also does it in that case (as opposed to for >> example const char*const). > > GCC should check in both cases. The case you are replacing was not > const char * const, but only const char *. Still, the compiler really > should check either form, even though theoretically the pointer in the > latter case could be changed, but the initial const value should be a > good indication of what the parameters are expected to be. No real > reason for the compiler not to check it. I agree with all of that - just wanted to point out what gcc currently does and doesn't, and changing to const char[] would indeed enable checking. >> (2) The names of these variables themselves may end up wasting a >> few bytes in the image. > > Maybe in a debug image, but they should be stripped from any normal > image. Really not a factor. Sure, that was by far the weakest, and let's ignore that. >> (3) gcc/the linker doesn't merge identical const char[] arrays >> across translation units. It also doesn't consider their tails for >> merging with string literals. So although these specific strings >> are unlikely to appear elsewhere, a string such as "%10u\n" or >> "max\n" couldn't be merged with one of the above. > > I haven't checked, but there is no theoretical reason that const char > [] items could not be merged exactly as the literals are. Considering > the boundaries the compiler guys push on optimization, doing such > merging would be tame by comparison (speculative stores make me crazy). Well, probably the linker is allowed to overlap "anonymous" objects (string literals) with whatever const char[] (or indeed any const) object it finds containing the appropriate byte sequence. But I think language lawyers would insist that for const char foo[] = "a string"; const char bar[] = "a string"; foo and bar have different addresses, whether they are defined in the same or different TUs. One could then argue that if their address is never taken explicitly it should be ok, but since passing foo to a printf function effectively makes the address of foo escape the TU (even though one is formally passing pointer to first element), I can certainly see why compiler people would be reluctant to do merging of such objects. Rasmus -- 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] mwifiex: fix usb tx data payload offset issue
From: Zhaoyang Liu Commit 84b313b35f8158d7 ("mwifiex: make tx packet 64 byte DMA aligned") induced payload offset issue for USB interface. There is no USB interface header for tx packets, so there's no need to pull interface length while processing tx skb. This patch fixes this issue. Signed-off-by: Zhaoyang Liu Signed-off-by: Amitkumar Karwar Signed-off-by: Avinash Patil --- drivers/net/wireless/mwifiex/txrx.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index ac93557..ea4549f 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -80,11 +80,13 @@ EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, struct mwifiex_tx_param *tx_param) { - int ret = -1; + int hroom, ret = -1; struct mwifiex_adapter *adapter = priv->adapter; u8 *head_ptr; struct txpd *local_tx_pd = NULL; + hroom = (adapter->iface_type == MWIFIEX_USB) ? 0 : INTF_HEADER_LEN; + if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) head_ptr = mwifiex_process_uap_txpd(priv, skb); else @@ -92,11 +94,9 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, if (head_ptr) { if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) - local_tx_pd = - (struct txpd *) (head_ptr + INTF_HEADER_LEN); + local_tx_pd = (struct txpd *)(head_ptr + hroom); if (adapter->iface_type == MWIFIEX_USB) { adapter->data_sent = true; - skb_pull(skb, INTF_HEADER_LEN); ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_USB_EP_DATA, skb, NULL); -- 1.8.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