[RFC] mac80211: fix A-MSDU outer SA/DA

2016-10-07 Thread Michael Braun
According to IEEE 802.11-2012 section 8.3.2 table 8-19, the outer SA/DA
of A-MSDU frames need to be changed depending on FromDS/ToDS values.

Signed-off-by: Michael Braun 
---
 net/mac80211/tx.c | 24 +++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 5023966..87670b7 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3050,7 +3050,7 @@ static bool ieee80211_amsdu_prepare_head(struct 
ieee80211_sub_if_data *sdata,
int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header);
int subframe_len = skb->len - hdr_len;
void *data;
-   u8 *qc;
+   u8 *qc, *bssid;
 
if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
return false;
@@ -3062,10 +3062,32 @@ static bool ieee80211_amsdu_prepare_head(struct 
ieee80211_sub_if_data *sdata,
 &subframe_len))
return false;
 
+   switch (sdata->vif.type) {
+   case NL80211_IFTYPE_STATION:
+   bssid = sdata->u.mgd.bssid;
+   break;
+   case NL80211_IFTYPE_AP:
+   case NL80211_IFTYPE_AP_VLAN:
+   bssid = sdata->vif.addr;
+   break;
+   default:
+   bssid = NULL;
+   }
+
amsdu_hdr.h_proto = cpu_to_be16(subframe_len);
memcpy(amsdu_hdr.h_source, skb->data + fast_tx->sa_offs, ETH_ALEN);
memcpy(amsdu_hdr.h_dest, skb->data + fast_tx->da_offs, ETH_ALEN);
 
+   /* according to IEEE 802.11-2012 8.3.2 table 8-19, the outer SA/DA
+* fields needs to be changed to BSSID for A-MSDU frames depending
+* on FromDS/ToDS values.
+*/
+   hdr = data;
+   if (bssid && (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FROMDS)))
+   memcpy(amsdu_hdr.h_source, bssid, ETH_ALEN);
+   if (bssid && (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_TODS)))
+   memcpy(amsdu_hdr.h_dest, bssid, ETH_ALEN);
+
data = skb_push(skb, sizeof(amsdu_hdr));
memmove(data, data + sizeof(amsdu_hdr), hdr_len);
memcpy(data + hdr_len, &amsdu_hdr, sizeof(amsdu_hdr));
-- 
2.1.4



[PATCH] mac80211: enable to inject a-msdu frames using monitor interface

2016-10-07 Thread Michael Braun
Problem: When injecting an A-MSDU using a PF_PACKET socket, the qos flag
IEEE80211_QOS_CTL_A_MSDU_PRESENT is cleared.

How to reproduce: Inject a frame on a mac80211 hwsim monitor interface and
have tshark sniffing on this monitor interface.
You'll see the packet twice: Once with correct flag and once with flag
cleared. On hwsim0, you'll only see the packet with a cleared flag.

I guess the same is needed for packets with IEEE80211_TX_CTRL_AMSDU set.

Signed-off-by: Michael Braun 
---
 net/mac80211/wme.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 9eb0aee..3faa972 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -248,6 +248,13 @@ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data 
*sdata,
/* preserve EOSP bit */
ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
 
+   /* preserve A-MSDU bit for MONITOR interfaces to allow injecting
+* A-MSDU frames
+*/
+   if (info->flags & IEEE80211_TX_CTL_INJECTED ||
+   info->control.flags & IEEE80211_TX_CTRL_AMSDU)
+   ack_policy |= *p & IEEE80211_QOS_CTL_A_MSDU_PRESENT;
+
if (is_multicast_ether_addr(hdr->addr1) ||
sdata->noack_map & BIT(tid)) {
ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
-- 
2.1.4



[PATCH v5 3/4] cfg80211: configure multicast to unicast for AP interfaces

2016-10-07 Thread Michael Braun
This add a userspace toggle to configure multicast to unicast.

Signed-off-by: Michael Braun 
---
 include/net/cfg80211.h   |  6 ++
 include/uapi/linux/nl80211.h | 10 ++
 net/wireless/nl80211.c   | 36 
 net/wireless/rdev-ops.h  | 12 
 net/wireless/trace.h | 19 +++
 5 files changed, 83 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7ce6223..7b0941d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2460,6 +2460,8 @@ struct cfg80211_qos_map {
  *
  * @set_wds_peer: set the WDS peer for a WDS interface
  *
+ * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
+ *
  * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting
  * functions to adjust rfkill hw state
  *
@@ -2722,6 +2724,10 @@ struct cfg80211_ops {
int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
const u8 *addr);
 
+   int (*set_multicast_to_unicast)(struct wiphy *wiphy,
+   struct net_device *dev,
+   const bool enabled);
+
void(*rfkill_poll)(struct wiphy *wiphy);
 
 #ifdef CONFIG_NL80211_TESTMODE
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 2206941..1b9e87b 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -599,6 +599,9 @@
  *
  * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS 
interface.
  *
+ * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if AP interface should
+ *  perform multicast to unicast conversion (per-BSS).
+ *
  * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial
  * mesh config parameters may be given.
  * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the
@@ -1026,6 +1029,8 @@ enum nl80211_commands {
 
NL80211_CMD_ABORT_SCAN,
 
+   NL80211_CMD_SET_MULTICAST_TO_UNICAST,
+
/* add new commands above here */
 
/* used to define NL80211_CMD_MAX below */
@@ -1867,6 +1872,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_MESH_PEER_AID: Association ID for the mesh peer (u16). This is
  * used to pull the stored data for mesh peer in power save state.
  *
+ * @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Multicast packets should be
+ *  send out as unicast to all stations.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2261,6 +2269,8 @@ enum nl80211_attrs {
 
NL80211_ATTR_MESH_PEER_AID,
 
+   NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED,
+
/* add attributes here, update the policy in nl80211.c */
 
__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f02653a..57b5d70 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -409,6 +409,7 @@ static const struct nla_policy 
nl80211_policy[NUM_NL80211_ATTR] = {
.len = VHT_MUMIMO_GROUPS_DATA_LEN
},
[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN },
+   [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_U8, },
 };
 
 /* policy for the key attributes */
@@ -1538,6 +1539,7 @@ static int nl80211_send_wiphy(struct 
cfg80211_registered_device *rdev,
goto nla_put_failure;
}
CMD(set_wds_peer, SET_WDS_PEER);
+   CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
CMD(tdls_mgmt, TDLS_MGMT);
CMD(tdls_oper, TDLS_OPER);
@@ -2164,6 +2166,32 @@ static int nl80211_set_wds_peer(struct sk_buff *skb, 
struct genl_info *info)
return rdev_set_wds_peer(rdev, dev, bssid);
 }
 
+static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
+   struct genl_info *info)
+{
+   struct cfg80211_registered_device *rdev = info->user_ptr[0];
+   struct net_device *dev = info->user_ptr[1];
+   struct wireless_dev *wdev = dev->ieee80211_ptr;
+   const struct nlattr *nla;
+   bool enabled;
+
+   if (!info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED])
+   return -EINVAL;
+
+   if (netif_running(dev))
+   return -EBUSY;
+
+   if (!rdev->ops->set_multicast_to_unicast)
+   return -EOPNOTSUPP;
+
+   if (wdev->iftype != NL80211_IFTYPE_AP)
+   return -EOPNOTSUPP;
+
+   nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
+   enabled = nla_get_flag(nla);
+   return rdev_set_multicast_to_unicast(rdev, dev, enabled);
+}
+
 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 {
str

[PATCH v5 2/4] mac80211: filter multicast data packets on AP / AP_VLAN

2016-10-07 Thread Michael Braun
This patch adds filtering for multicast data packets on AP_VLAN interfaces
that have no authorized station connected and changes filtering on AP
interfaces to not count stations assigned to AP_VLAN interfaces.

This saves airtime and avoids waking up other stations currently authorized
in this BSS. When using WPA, the packets dropped could not be decrypted by
any station.

The behaviour when there are no AP_VLAN interfaces is left unchanged.
When there are AP_VLAN interfaces, this patch
1. adds filtering multicast data packets sent on AP_VLAN interfaces that
   have no authorized station connected.
   No filtering happens on 4addr AP_VLAN interfaces.
2. makes filtering of multicast data packets sent on AP interfaces depend
   on the number of authorized stations in this bss not assigned to an
   AP_VLAN interface.

Therefore, a new num_mcast_sta counter is added for AP_VLAN interfaces.
The existing one for AP interfaces is altered to not track stations
assigned to an AP_VLAN interface.

The new counter is exposed in debugfs.

Signed-off-by: Michael Braun 

--
v4:
 - update description
v3:
 - reuse existing num_mcast_sta
v2:
 - use separate function to inc/dec mcast_sta counters
 - do not filter in 4addr mode
 - change description
 - change filtering on AP interface (do not count AP_VLAN sta)
 - use new counters regardless of 4addr or not
 - simplify cfg.c:change_station
 - remove no-op change in __cleanup_single_sta
---
 net/mac80211/cfg.c| 20 ++--
 net/mac80211/debugfs_netdev.c | 11 +++
 net/mac80211/ieee80211_i.h| 33 +
 net/mac80211/rx.c |  5 +++--
 net/mac80211/sta_info.c   | 10 ++
 net/mac80211/tx.c |  5 ++---
 6 files changed, 57 insertions(+), 27 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 24133f5..1edb017 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1357,9 +1357,6 @@ static int ieee80211_change_station(struct wiphy *wiphy,
goto out_err;
 
if (params->vlan && params->vlan != sta->sdata->dev) {
-   bool prev_4addr = false;
-   bool new_4addr = false;
-
vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
 
if (params->vlan->ieee80211_ptr->use_4addr) {
@@ -1369,26 +1366,21 @@ static int ieee80211_change_station(struct wiphy *wiphy,
}
 
rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
-   new_4addr = true;
__ieee80211_check_fast_rx_iface(vlansdata);
}
 
if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-   sta->sdata->u.vlan.sta) {
+   sta->sdata->u.vlan.sta)
RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL);
-   prev_4addr = true;
-   }
+
+   if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+   ieee80211_vif_dec_num_mcast(sta->sdata);
 
sta->sdata = vlansdata;
ieee80211_check_fast_xmit(sta);
 
-   if (sta->sta_state == IEEE80211_STA_AUTHORIZED &&
-   prev_4addr != new_4addr) {
-   if (new_4addr)
-   atomic_dec(&sta->sdata->bss->num_mcast_sta);
-   else
-   atomic_inc(&sta->sdata->bss->num_mcast_sta);
-   }
+   if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+   ieee80211_vif_inc_num_mcast(sta->sdata);
 
ieee80211_send_layer2_update(sta);
}
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index a5ba739..ed7bff4 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -477,6 +477,7 @@ IEEE80211_IF_FILE_RW(tdls_wider_bw);
 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(num_mcast_sta_vlan, 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)
@@ -643,6 +644,13 @@ 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)
+{
+   /* add num_mcast_sta_vlan using name num_mcast_sta */
+   debugfs_create_file("num_mcast_sta", 0400, sdata->vif.debugfs_dir,
+   sdata, &num_mcast_sta_vlan_ops);
+}
+
 static void add_ibss_files(struct ieee80211_sub_if_data *sdata)
 {
DEBUGFS_ADD_MODE(tsf, 0600);
@@ -746,6 +754,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
case NL80211_IFTYPE_AP:
add_ap_files(sdata);
break;
+   c

[PATCH v5 4/4] mac80211: multicast to unicast conversion

2016-10-07 Thread Michael Braun
This patch adds support for sending multicast data packets with ARP, IPv4
and IPv6 payload (possible 802.1q tagged) as 802.11 unicast frames to all
stations.

IEEE 802.11 multicast has well known issues, among them:
 1. packets are not acked and hence not retransmitted, resulting in
decreased reliablity
 2. packets are send at low rate, increasing time required on air

When used with AP_VLAN, there is another disadvantage:
 3. all stations in the BSS are woken up, regardsless of their AP_VLAN
assignment.

By doing multicast to unicast conversion, all three issus are solved.

IEEE802.11-2012 proposes directed multicast service (DMS) using A-MSDU
frames and a station initiated control protocol. It has the advantage that
the station can recover the destination multicast mac address, but it is
not backward compatible with non QOS stations and does not enable the
administrator of a BSS to force this mode of operation within a BSS.
Additionally, it would require both the ap and the station to implement
the control protocol, which is optional on both ends. Furthermore, I've
seen a few mobile phone stations locally that indicate qos support but
won't complete DHCP if their broadcasts are encapsulated as A-MSDU. Though
they work fine with this series approach.

This patch therefore does not opt to implement DMS but instead just
replicates the packet and changes the destination address. As this works
fine with ARP, IPv4 and IPv6, it is limited to these protocols and normal
802.11 multicast frames are send out for all other payload protocols.

There is a runtime toggle to enable multicast conversion in a per-bss
fashion.

When there is only a single station assigned to the AP_VLAN interface, no
packet replication will occur. 4addr mode of operation is unchanged.

This change opts for iterating all BSS stations for finding the stations
assigned to this AP/AP_VLAN interface, as there currently is no per
AP_VLAN list to iterate and multicast packets are expected to be few.
If needed, such a list could be added later.

Signed-off-by: Michael Braun 

--
v5:
  - rename bss->unicast to bss->multicast_to_unicast
  - access sdata->bss only after checking iftype
v4:
  - rename MULTICAST_TO_UNICAST to MULTICAST_TO_UNICAST
v3: fix compile error for trace.h
v2: add nl80211 toggle
rename tx_dnat to change_da
change int to bool unicast
---
 net/mac80211/cfg.c|  15 +++
 net/mac80211/debugfs_netdev.c |   3 ++
 net/mac80211/ieee80211_i.h|   1 +
 net/mac80211/tx.c | 101 ++
 4 files changed, 120 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1edb017..1db4c3e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2242,6 +2242,20 @@ static int ieee80211_set_wds_peer(struct wiphy *wiphy, 
struct net_device *dev,
return 0;
 }
 
+static int ieee80211_set_multicast_to_unicast(struct wiphy *wiphy,
+ struct net_device *dev,
+ const bool enabled)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+   if (sdata->vif.type != NL80211_IFTYPE_AP)
+   return -1;
+
+   sdata->u.ap.multicast_to_unicast = enabled;
+
+   return 0;
+}
+
 static void ieee80211_rfkill_poll(struct wiphy *wiphy)
 {
struct ieee80211_local *local = wiphy_priv(wiphy);
@@ -3400,6 +3414,7 @@ const struct cfg80211_ops mac80211_config_ops = {
.set_tx_power = ieee80211_set_tx_power,
.get_tx_power = ieee80211_get_tx_power,
.set_wds_peer = ieee80211_set_wds_peer,
+   .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
.rfkill_poll = ieee80211_rfkill_poll,
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump)
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index ed7bff4..509c6c3 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -487,6 +487,8 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast(
 }
 IEEE80211_IF_FILE_R(num_buffered_multicast);
 
+IEEE80211_IF_FILE(multicast_to_unicast, u.ap.multicast_to_unicast, HEX);
+
 /* IBSS attributes */
 static ssize_t ieee80211_if_fmt_tsf(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
@@ -642,6 +644,7 @@ static void add_ap_files(struct ieee80211_sub_if_data 
*sdata)
DEBUGFS_ADD(dtim_count);
DEBUGFS_ADD(num_buffered_multicast);
DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
+   DEBUGFS_ADD_MODE(multicast_to_unicast, 0600);
 }
 
 static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 70c0963..84374ed 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -293,6 +293,7 @@ struct ieee80211_if_ap {
 driver_smps_mode; /* smps mode request */

[PATCH v5 1/4] mac80211: remove unnecessary num_mcast_sta user

2016-10-07 Thread Michael Braun
Checking for num_mcast_sta in __ieee80211_request_smps_ap() is unnecessary,
as sta list will be empty in this case anyway, so list_for_each_entry(sta,
...) will exit immediately.

Signed-off-by: Michael Braun 
---
 net/mac80211/cfg.c | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 543b1d4..24133f5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2313,13 +2313,6 @@ int __ieee80211_request_smps_ap(struct 
ieee80211_sub_if_data *sdata,
smps_mode == IEEE80211_SMPS_AUTOMATIC)
return 0;
 
-/* If no associated stations, there's no need to do anything */
-   if (!atomic_read(&sdata->u.ap.num_mcast_sta)) {
-   sdata->smps_mode = smps_mode;
-   ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps);
-   return 0;
-   }
-
ht_dbg(sdata,
   "SMPS %d requested in AP mode, sending Action frame to %d 
stations\n",
   smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta));
-- 
2.1.4



[PATCH] wlcore: Allow scans when in AP mode

2016-10-07 Thread Xander Huff
From: James Minor 

When in AP mode, scans can be done without changing firmware to
the multi-role firmware. Allow the interface to scan if forced
in the scan request.

Signed-off-by: James Minor 
Signed-off-by: Xander Huff 
Reviewed-by: Ben Shelton 
Reviewed-by: Jaeden Amero 
---
 drivers/net/wireless/ti/wlcore/main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/ti/wlcore/main.c 
b/drivers/net/wireless/ti/wlcore/main.c
index 471521a..01ca370 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -6120,6 +6120,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
WIPHY_FLAG_SUPPORTS_SCHED_SCAN |
WIPHY_FLAG_HAS_CHANNEL_SWITCH;
 
+   wl->hw->wiphy->features |= NL80211_FEATURE_AP_SCAN;
+
/* make sure all our channels fit in the scanned_ch bitmask */
BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) +
 ARRAY_SIZE(wl1271_channels_5ghz) >
-- 
1.9.1



[PATCH 2/2] ath10k: add support for per sta tx bitrate

2016-10-07 Thread akolli
From: Anilkumar Kolli 

Per STA tx bitrate info is filled from peer stats.
Export per sta txrate info to cfg80211/nl80211

Signed-off-by: Anilkumar Kolli 
---
 drivers/net/wireless/ath/ath10k/debugfs_sta.c |   13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c 
b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
index 9955fea0802a..7daf9927a1ef 100644
--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
@@ -77,6 +77,19 @@ void ath10k_sta_statistics(struct ieee80211_hw *hw, struct 
ieee80211_vif *vif,
 
sinfo->rx_duration = arsta->rx_duration;
sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION;
+
+   if (!arsta->txrate.legacy && !arsta->txrate.nss)
+   return;
+
+   if(arsta->txrate.legacy) {
+   sinfo->txrate.legacy = arsta->txrate.legacy;
+   } else {
+   sinfo->txrate.mcs = arsta->txrate.mcs;
+   sinfo->txrate.nss = arsta->txrate.nss;
+   sinfo->txrate.bw = arsta->txrate.bw;
+   }
+   sinfo->txrate.flags = arsta->txrate.flags;
+   sinfo->filled |= 1ULL << NL80211_STA_INFO_TX_BITRATE;
 }
 
 static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
-- 
1.7.9.5



[PATCH 1/2] ath10k: add per peer htt tx stats support for 10.4

2016-10-07 Thread akolli
From: Anilkumar Kolli 

Per peer tx stats are part of 'HTT_10_4_T2H_MSG_TYPE_PEER_STATS'
event, Firmware sends one HTT event for every four PPDUs.
HTT payload has success pkts/bytes, failed pkts/bytes, retry
pkts/bytes and rate info per ppdu.
Peer stats are enabled through 'WMI_SERVICE_PEER_STATS',
which are nowadays enabled by default.

Parse peer stats and update the tx rate information per STA.

tx rate, Peer stats are tested on QCA4019 with Firmware version
10.4-3.2.1-00028.

Signed-off-by: Anilkumar Kolli 
---
 drivers/net/wireless/ath/ath10k/core.h   |   17 
 drivers/net/wireless/ath/ath10k/htt.c|2 +
 drivers/net/wireless/ath/ath10k/htt.h|   25 ++
 drivers/net/wireless/ath/ath10k/htt_rx.c |  125 ++
 drivers/net/wireless/ath/ath10k/wmi.h|   10 ++-
 5 files changed, 178 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h 
b/drivers/net/wireless/ath/ath10k/core.h
index dda49af1eb74..fc3d3bded265 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -337,6 +337,7 @@ struct ath10k_sta {
u32 nss;
u32 smps;
u16 peer_id;
+   struct rate_info txrate;
 
struct work_struct update_wk;
 
@@ -694,6 +695,21 @@ struct ath10k_fw_components {
struct ath10k_fw_file fw_file;
 };
 
+struct ath10k_per_peer_tx_stats {
+   u32 succ_bytes;
+   u32 retry_bytes;
+   u32 failed_bytes;
+   u8  ratecode;
+   u8  flags;
+   u16 peer_id;
+   u16 succ_pkts;
+   u16 retry_pkts;
+   u16 failed_pkts;
+   u16 duration;
+   u32 reserved1;
+   u32 reserved2;
+};
+
 struct ath10k {
struct ath_common ath_common;
struct ieee80211_hw *hw;
@@ -906,6 +922,7 @@ struct ath10k {
 
struct ath10k_thermal thermal;
struct ath10k_wow wow;
+   struct ath10k_per_peer_tx_stats peer_tx_stats;
 
/* NAPI */
struct net_device napi_dev;
diff --git a/drivers/net/wireless/ath/ath10k/htt.c 
b/drivers/net/wireless/ath/ath10k/htt.c
index 130cd9502021..cd160b16db1e 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -137,6 +137,8 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] 
= {
HTT_T2H_MSG_TYPE_STATS_NOUPLOAD,
[HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND] =
HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND,
+   [HTT_10_4_T2H_MSG_TYPE_PEER_STATS] =
+   HTT_T2H_MSG_TYPE_PEER_STATS,
 };
 
 int ath10k_htt_connect(struct ath10k_htt *htt)
diff --git a/drivers/net/wireless/ath/ath10k/htt.h 
b/drivers/net/wireless/ath/ath10k/htt.h
index 0d2ed09f202b..164eb3a10566 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -419,6 +419,7 @@ enum htt_10_4_t2h_msg_type {
HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD = 0x18,
/* 0x19 to 0x2f are reserved */
HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND = 0x30,
+   HTT_10_4_T2H_MSG_TYPE_PEER_STATS = 0x31,
/* keep this last */
HTT_10_4_T2H_NUM_MSGS
 };
@@ -453,6 +454,7 @@ enum htt_t2h_msg_type {
HTT_T2H_MSG_TYPE_TX_FETCH_IND,
HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM,
HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND,
+   HTT_T2H_MSG_TYPE_PEER_STATS,
/* keep this last */
HTT_T2H_NUM_MSGS
 };
@@ -1470,6 +1472,28 @@ struct htt_channel_change {
__le32 phymode;
 } __packed;
 
+struct htt_per_peer_tx_stats_ind {
+   __le32  succ_bytes;
+   __le32  retry_bytes;
+   __le32  failed_bytes;
+   u8  ratecode;
+   u8  flags;
+   __le16  peer_id;
+   __le16  succ_pkts;
+   __le16  retry_pkts;
+   __le16  failed_pkts;
+   __le16  tx_duration;
+   __le32  reserved1;
+   __le32  reserved2;
+} __packed;
+
+struct htt_peer_tx_stats {
+   u8 num_ppdu;
+   u8 ppdu_len;
+   u8 version;
+   u8 payload[0];
+} __packed;
+
 union htt_rx_pn_t {
/* WEP: 24-bit PN */
u32 pn24;
@@ -1521,6 +1545,7 @@ struct htt_resp {
struct htt_tx_fetch_confirm tx_fetch_confirm;
struct htt_tx_mode_switch_ind tx_mode_switch_ind;
struct htt_channel_change chan_change;
+   struct htt_peer_tx_stats peer_tx_stats;
};
 } __packed;
 
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c 
b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 0b4c1562420f..eab719d9729b 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -2194,6 +2194,128 @@ void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, 
struct sk_buff *skb)
dev_kfree_skb_any(skb);
 }
 
+static inline bool is_valid_legacy_rate(u8 rate)
+{
+   static const u8 legacy_rates[] = {1, 2, 5, 11, 6, 9, 12,
+   

[PATCH 0/2] ath10k: add support for tx bitrate

2016-10-07 Thread akolli
From: Anilkumar Kolli 

This patch series adds support for tx bitrate using 
.sta_statistics callback.

tx bitrate tested on QCA4019 using iw.

Anilkumar Kolli (2):
  ath10k: add per peer htt tx stats support for 10.4
  ath10k: add support for per sta tx bitrate

 drivers/net/wireless/ath/ath10k/core.h|   17 
 drivers/net/wireless/ath/ath10k/debugfs_sta.c |   13 +++
 drivers/net/wireless/ath/ath10k/htt.c |2 +
 drivers/net/wireless/ath/ath10k/htt.h |   25 +
 drivers/net/wireless/ath/ath10k/htt_rx.c  |  125 +
 drivers/net/wireless/ath/ath10k/wmi.h |   10 +-
 6 files changed, 191 insertions(+), 1 deletion(-)

-- 
1.7.9.5



Re: bcmdhd: Strange Power Save messages

2016-10-07 Thread Gucea Doru
On Thu, Oct 6, 2016 at 10:25 AM, Arend Van Spriel
 wrote:
> On 6-10-2016 10:07, Gucea Doru wrote:
>> On Wed, Oct 5, 2016 at 11:12 AM, Arend Van Spriel
>>  wrote:
>>> On 4-10-2016 13:39, Gucea Doru wrote:
 On Sat, Oct 1, 2016 at 2:52 PM, Arend van Spriel
>  wrote:
>>
>>
>> On 29-09-16 13:32, Gucea Doru wrote:
>>> On Tue, Sep 27, 2016 at 12:03 PM, Gucea Doru  
>>> wrote:
 What is the decision triggering the exit from the PS mode immediately
 after the ping request? I am asking this because 802.11 PS legacy
 specifies that the client should wait for a beacon with TIM set in
 order to wake up: in my case, there is no beacon between the ping
 request message and the Null frame that announces the exit from the PS
 mode.
>>>
>>>
>>> Any help would be highly appreciated :)
>>
>> Actually though I already sent you are reply, but alas here it is.
>>
>> bcmdhd is our aosp driver. I am maintaining the upstream brcm80211
>> drivers. Regardless your question is more for firmware running on the
>> device. So like the same behavior would be observed when using brcmfmac
>> with same firmware.
>>
>>> IEEE Std 802.11-2012, section 10.2.1.8 specifies that "when the STA
>>> detects that the bit corresponding to its AID is 1 i the TIM, the STA
>>> shall issue a PS Poll". In my capture there are cases when the STA
>>> exits the PS mode without waiting for a beacon.
>>
>> It is a bit tricky, but the standard does not explicitly say the STA
>> should be in power-save at any other time. So it is difficult to say
>> what event occurred on the STA side to exit PS mode. Also STA means
>> P2P-Client as you say. That means that you have multiple interfaces:
>> regular STA and P2P-Client. So is the STA connected to some other AP or
>> just not connected. wpa_supplicant will do intermittent scan or initiate
>> scheduled scan by which firmware will scan at a certain interval. That
>> is just some things I can come up with and I am sure there are more.

 I agree that there may be some events belonging to the regular STA
 interface that could trigger the Null Frame (which includes the exit
 from PS Mode). However, I would expect to see some management frames
 in the air before/after the Null Packet (e.g.: a Probe request in case
 of a scheduled scan). But in my case the trigger for the Null frame
 seems to be the ping request packet, the scenario is the same every
 time: ping request -> Block ACK -> Null Frame (Wireshark trace
 confirms this behavior).

 I thought that you had a power save optimization algorithm that keeps
 the card on a few milliseconds just to see if we can have a fast reply
 from the peer. Does this ring a bell? :)
>>>
>>> It does not. That would be implemented in firmware. As said I am working
>>> on brcmfmac/brcmsmac. So bcmdhd and firmware are not my expertise.
>>>
>>
>> Arend, could you please redirect me to a Broadcom firmware maintainer?
>
> Can you please elaborate on your platform, broadcom chipset, and what
> version of bcmdhd you are using.
>

Platform: Nexus 5 running CM13 (Android 6.0.1)
Broadcom chipset: BCM4339 Wi-Fi Chipset
bcmdhd version:Dongle Host Driver, version 1.88.45 (r)

Do you need more information?

Thank you,
Doru


[PATCH v4 4/4] mac80211: multicast to unicast conversion

2016-10-07 Thread Michael Braun
This patch adds support for sending multicast data packets with ARP, IPv4
and IPv6 payload (possible 802.1q tagged) as 802.11 unicast frames to all
stations.

IEEE 802.11 multicast has well known issues, among them:
 1. packets are not acked and hence not retransmitted, resulting in
decreased reliablity
 2. packets are send at low rate, increasing time required on air

When used with AP_VLAN, there is another disadvantage:
 3. all stations in the BSS are woken up, regardsless of their AP_VLAN
assignment.

By doing multicast to unicast conversion, all three issus are solved.

IEEE802.11-2012 proposes directed multicast service (DMS) using A-MSDU
frames and a station initiated control protocol. It has the advantage that
the station can recover the destination multicast mac address, but it is
not backward compatible with non QOS stations and does not enable the
administrator of a BSS to force this mode of operation within a BSS.
Additionally, it would require both the ap and the station to implement
the control protocol, which is optional on both ends. Furthermore, I've
seen a few mobile phone stations locally that indicate qos support but
won't complete DHCP if their broadcasts are encapsulated as A-MSDU. Though
they work fine with this series approach.

This patch therefore does not opt to implement DMS but instead just
replicates the packet and changes the destination address. As this works
fine with ARP, IPv4 and IPv6, it is limited to these protocols and normal
802.11 multicast frames are send out for all other payload protocols.

There is a runtime toggle to enable multicast conversion in a per-bss
fashion.

When there is only a single station assigned to the AP_VLAN interface, no
packet replication will occur. 4addr mode of operation is unchanged.

This change opts for iterating all BSS stations for finding the stations
assigned to this AP/AP_VLAN interface, as there currently is no per
AP_VLAN list to iterate and multicast packets are expected to be few.
If needed, such a list could be added later.

Signed-off-by: Michael Braun 

--
v4:
  - rename MULTICAST_TO_UNICAST to MULTICAST_TO_UNICAST
v3: fix compile error for trace.h
v2: add nl80211 toggle
rename tx_dnat to change_da
change int to bool unicast
---
 net/mac80211/cfg.c|  15 +++
 net/mac80211/debugfs_netdev.c |   3 ++
 net/mac80211/ieee80211_i.h|   1 +
 net/mac80211/tx.c | 101 ++
 4 files changed, 120 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1edb017..23f711a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2242,6 +2242,20 @@ static int ieee80211_set_wds_peer(struct wiphy *wiphy, 
struct net_device *dev,
return 0;
 }
 
+static int ieee80211_set_multicast_to_unicast(struct wiphy *wiphy,
+ struct net_device *dev,
+ const bool enabled)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+   if (sdata->vif.type != NL80211_IFTYPE_AP)
+   return -1;
+
+   sdata->u.ap.unicast = enabled;
+
+   return 0;
+}
+
 static void ieee80211_rfkill_poll(struct wiphy *wiphy)
 {
struct ieee80211_local *local = wiphy_priv(wiphy);
@@ -3400,6 +3414,7 @@ const struct cfg80211_ops mac80211_config_ops = {
.set_tx_power = ieee80211_set_tx_power,
.get_tx_power = ieee80211_get_tx_power,
.set_wds_peer = ieee80211_set_wds_peer,
+   .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
.rfkill_poll = ieee80211_rfkill_poll,
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump)
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index ed7bff4..a5554cc 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -487,6 +487,8 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast(
 }
 IEEE80211_IF_FILE_R(num_buffered_multicast);
 
+IEEE80211_IF_FILE(multicast_to_unicast, u.ap.unicast, HEX);
+
 /* IBSS attributes */
 static ssize_t ieee80211_if_fmt_tsf(
const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
@@ -642,6 +644,7 @@ static void add_ap_files(struct ieee80211_sub_if_data 
*sdata)
DEBUGFS_ADD(dtim_count);
DEBUGFS_ADD(num_buffered_multicast);
DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
+   DEBUGFS_ADD_MODE(multicast_to_unicast, 0600);
 }
 
 static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 70c0963..b23bc21 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -293,6 +293,7 @@ struct ieee80211_if_ap {
 driver_smps_mode; /* smps mode request */
 
struct work_struct request_smps_work;
+   bool unicast;
 };
 
 struct ieee80211_if_wds {
diff --git a/net/mac80211/tx.

[PATCH v4 3/4] cfg80211: configure multicast to unicast for AP interfaces

2016-10-07 Thread Michael Braun
This add a userspace toggle to configure multicast to unicast.

Signed-off-by: Michael Braun 
---
 include/net/cfg80211.h   |  6 ++
 include/uapi/linux/nl80211.h | 10 ++
 net/wireless/nl80211.c   | 36 
 net/wireless/rdev-ops.h  | 12 
 net/wireless/trace.h | 19 +++
 5 files changed, 83 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b550314..6ab8940 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2460,6 +2460,8 @@ struct cfg80211_qos_map {
  *
  * @set_wds_peer: set the WDS peer for a WDS interface
  *
+ * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
+ *
  * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting
  * functions to adjust rfkill hw state
  *
@@ -2722,6 +2724,10 @@ struct cfg80211_ops {
int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
const u8 *addr);
 
+   int (*set_multicast_to_unicast)(struct wiphy *wiphy,
+   struct net_device *dev,
+   const bool enabled);
+
void(*rfkill_poll)(struct wiphy *wiphy);
 
 #ifdef CONFIG_NL80211_TESTMODE
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 2206941..1b9e87b 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -599,6 +599,9 @@
  *
  * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS 
interface.
  *
+ * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if AP interface should
+ *  perform multicast to unicast conversion (per-BSS).
+ *
  * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial
  * mesh config parameters may be given.
  * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the
@@ -1026,6 +1029,8 @@ enum nl80211_commands {
 
NL80211_CMD_ABORT_SCAN,
 
+   NL80211_CMD_SET_MULTICAST_TO_UNICAST,
+
/* add new commands above here */
 
/* used to define NL80211_CMD_MAX below */
@@ -1867,6 +1872,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_MESH_PEER_AID: Association ID for the mesh peer (u16). This is
  * used to pull the stored data for mesh peer in power save state.
  *
+ * @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Multicast packets should be
+ *  send out as unicast to all stations.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2261,6 +2269,8 @@ enum nl80211_attrs {
 
NL80211_ATTR_MESH_PEER_AID,
 
+   NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED,
+
/* add attributes here, update the policy in nl80211.c */
 
__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f02653a..57b5d70 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -409,6 +409,7 @@ static const struct nla_policy 
nl80211_policy[NUM_NL80211_ATTR] = {
.len = VHT_MUMIMO_GROUPS_DATA_LEN
},
[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN },
+   [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_U8, },
 };
 
 /* policy for the key attributes */
@@ -1538,6 +1539,7 @@ static int nl80211_send_wiphy(struct 
cfg80211_registered_device *rdev,
goto nla_put_failure;
}
CMD(set_wds_peer, SET_WDS_PEER);
+   CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST);
if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
CMD(tdls_mgmt, TDLS_MGMT);
CMD(tdls_oper, TDLS_OPER);
@@ -2164,6 +2166,32 @@ static int nl80211_set_wds_peer(struct sk_buff *skb, 
struct genl_info *info)
return rdev_set_wds_peer(rdev, dev, bssid);
 }
 
+static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
+   struct genl_info *info)
+{
+   struct cfg80211_registered_device *rdev = info->user_ptr[0];
+   struct net_device *dev = info->user_ptr[1];
+   struct wireless_dev *wdev = dev->ieee80211_ptr;
+   const struct nlattr *nla;
+   bool enabled;
+
+   if (!info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED])
+   return -EINVAL;
+
+   if (netif_running(dev))
+   return -EBUSY;
+
+   if (!rdev->ops->set_multicast_to_unicast)
+   return -EOPNOTSUPP;
+
+   if (wdev->iftype != NL80211_IFTYPE_AP)
+   return -EOPNOTSUPP;
+
+   nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED];
+   enabled = nla_get_flag(nla);
+   return rdev_set_multicast_to_unicast(rdev, dev, enabled);
+}
+
 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 {
str

[PATCH v4 2/4] mac80211: filter multicast data packets on AP / AP_VLAN

2016-10-07 Thread Michael Braun
This patch adds filtering for multicast data packets on AP_VLAN interfaces
that have no authorized station connected and changes filtering on AP
interfaces to not count stations assigned to AP_VLAN interfaces.

This saves airtime and avoids waking up other stations currently authorized
in this BSS. When using WPA, the packets dropped could not be decrypted by
any station.

The behaviour when there are no AP_VLAN interfaces is left unchanged.
When there are AP_VLAN interfaces, this patch
1. adds filtering multicast data packets sent on AP_VLAN interfaces that
   have no authorized station connected.
   No filtering happens on 4addr AP_VLAN interfaces.
2. makes filtering of multicast data packets sent on AP interfaces depend
   on the number of authorized stations in this bss not assigned to an
   AP_VLAN interface.

Therefore, a new num_mcast_sta counter is added for AP_VLAN interfaces.
The existing one for AP interfaces is altered to not track stations
assigned to an AP_VLAN interface.

The new counter is exposed in debugfs.

Signed-off-by: Michael Braun 

--
v4:
 - update description
v3:
 - reuse existing num_mcast_sta
v2:
 - use separate function to inc/dec mcast_sta counters
 - do not filter in 4addr mode
 - change description
 - change filtering on AP interface (do not count AP_VLAN sta)
 - use new counters regardless of 4addr or not
 - simplify cfg.c:change_station
 - remove no-op change in __cleanup_single_sta
---
 net/mac80211/cfg.c| 20 ++--
 net/mac80211/debugfs_netdev.c | 11 +++
 net/mac80211/ieee80211_i.h| 33 +
 net/mac80211/rx.c |  5 +++--
 net/mac80211/sta_info.c   | 10 ++
 net/mac80211/tx.c |  5 ++---
 6 files changed, 57 insertions(+), 27 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 24133f5..1edb017 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1357,9 +1357,6 @@ static int ieee80211_change_station(struct wiphy *wiphy,
goto out_err;
 
if (params->vlan && params->vlan != sta->sdata->dev) {
-   bool prev_4addr = false;
-   bool new_4addr = false;
-
vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
 
if (params->vlan->ieee80211_ptr->use_4addr) {
@@ -1369,26 +1366,21 @@ static int ieee80211_change_station(struct wiphy *wiphy,
}
 
rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
-   new_4addr = true;
__ieee80211_check_fast_rx_iface(vlansdata);
}
 
if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-   sta->sdata->u.vlan.sta) {
+   sta->sdata->u.vlan.sta)
RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL);
-   prev_4addr = true;
-   }
+
+   if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+   ieee80211_vif_dec_num_mcast(sta->sdata);
 
sta->sdata = vlansdata;
ieee80211_check_fast_xmit(sta);
 
-   if (sta->sta_state == IEEE80211_STA_AUTHORIZED &&
-   prev_4addr != new_4addr) {
-   if (new_4addr)
-   atomic_dec(&sta->sdata->bss->num_mcast_sta);
-   else
-   atomic_inc(&sta->sdata->bss->num_mcast_sta);
-   }
+   if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+   ieee80211_vif_inc_num_mcast(sta->sdata);
 
ieee80211_send_layer2_update(sta);
}
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index a5ba739..ed7bff4 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -477,6 +477,7 @@ IEEE80211_IF_FILE_RW(tdls_wider_bw);
 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(num_mcast_sta_vlan, 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)
@@ -643,6 +644,13 @@ 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)
+{
+   /* add num_mcast_sta_vlan using name num_mcast_sta */
+   debugfs_create_file("num_mcast_sta", 0400, sdata->vif.debugfs_dir,
+   sdata, &num_mcast_sta_vlan_ops);
+}
+
 static void add_ibss_files(struct ieee80211_sub_if_data *sdata)
 {
DEBUGFS_ADD_MODE(tsf, 0600);
@@ -746,6 +754,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
case NL80211_IFTYPE_AP:
add_ap_files(sdata);
break;
+   c

[PATCH v4 1/4] mac80211: remove unnecessary num_mcast_sta user

2016-10-07 Thread Michael Braun
Checking for num_mcast_sta in __ieee80211_request_smps_ap() is unnecessary,
as sta list will be empty in this case anyway, so list_for_each_entry(sta,
...) will exit immediately.

Signed-off-by: Michael Braun 
---
 net/mac80211/cfg.c | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 543b1d4..24133f5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2313,13 +2313,6 @@ int __ieee80211_request_smps_ap(struct 
ieee80211_sub_if_data *sdata,
smps_mode == IEEE80211_SMPS_AUTOMATIC)
return 0;
 
-/* If no associated stations, there's no need to do anything */
-   if (!atomic_read(&sdata->u.ap.num_mcast_sta)) {
-   sdata->smps_mode = smps_mode;
-   ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps);
-   return 0;
-   }
-
ht_dbg(sdata,
   "SMPS %d requested in AP mode, sending Action frame to %d 
stations\n",
   smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta));
-- 
2.1.4



Re: [v7, 1/3] Documentation: dt: net: add ath9k wireless device binding

2016-10-07 Thread Kalle Valo
Martin Blumenstingl  wrote:
> Add documentation how devicetree can be used to configure ath9k based
> devices.
> 
> Signed-off-by: Martin Blumenstingl 

Looks good to me but missing the ack from DT maintainers, will wait for
that.

3 patches set to Deferred.

9359805 [v7,1/3] Documentation: dt: net: add ath9k wireless device binding
9359801 [v7,2/3] ath9k: add a helper to get the string representation of 
ath_bus_type
9359803 [v7,3/3] ath9k: parse the device configuration from an OF node

-- 
https://patchwork.kernel.org/patch/9359805/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches



Re: [v5] ath9k: Switch to using mac80211 intermediate software queues.

2016-10-07 Thread Kalle Valo
Toke Høiland-Jørgensen wrote:
> This switches ath9k over to using the mac80211 intermediate software
> queueing mechanism for data packets. It removes the queueing inside the
> driver, except for the retry queue, and instead pulls from mac80211 when
> a packet is needed. The retry queue is used to store a packet that was
> pulled but can't be sent immediately.
> 
> The old code path in ath_tx_start that would queue packets has been
> removed completely, as has the qlen limit tunables (since there's no
> longer a queue in the driver to limit).
> 
> Based on Tim's original patch set, but reworked quite thoroughly.
> 
> Cc: Tim Shepard 
> Cc: Felix Fietkau 
> Signed-off-by: Toke Høiland-Jørgensen 
> Signed-off-by: Felix Fietkau 

Depends on:

bb42f2d13ffc mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue

Patch set to Awaiting Upstream.

-- 
https://patchwork.kernel.org/patch/9311037/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches



Re: [1/2] rtl8xxxu: Fix rtl8723bu driver reload issue

2016-10-07 Thread Kalle Valo
Jes Sorensen  wrote:
> From: Jes Sorensen 
> 
> The generic disable_rf() function clears bits 22 and 23 in
> REG_RX_WAIT_CCA, however we did not re-enable them again in
> rtl8723b_enable_rf()
> 
> This resolves the problem for me with 8723bu devices not working again
> after reloading the driver.
> 
> Signed-off-by: Jes Sorensen 
> Cc: sta...@vger.kernel.org # 4.7+

2 patches applied to wireless-drivers.git, thanks.

ab05e5ec81c7 rtl8xxxu: Fix rtl8723bu driver reload issue
29d5e6fbd65b rtl8xxxu: Fix rtl8192eu driver reload issue

-- 
https://patchwork.kernel.org/patch/9359015/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches



Re: [1/2] rtl8xxxu: Fix memory leak in handling rxdesc16 packets

2016-10-07 Thread Kalle Valo
Jes Sorensen  wrote:
> From: Jes Sorensen 
> 
> A device running without RX package aggregation could return more data
> in the USB packet than the actual network packet. In this case we
> could would clone the skb but then determine that that there was no
> packet to handle and exit without freeing the cloned skb first.
> 
> This has so far only been observed with 8188eu devices, but could
> affect others.
> 
> Signed-off-by: Jes Sorensen 
> Cc: sta...@vger.kernel.org # 4.8+

2 patches applied to wireless-drivers.git, thanks.

1e54134ccad0 rtl8xxxu: Fix memory leak in handling rxdesc16 packets
8a55698f2f29 rtl8xxxu: Fix big-endian problem reporting mactime

-- 
https://patchwork.kernel.org/patch/9356961/

Documentation about submitting wireless patches and checking status
from patchwork:

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches



[PATCH 3/3] mac80211: validate DA/SA during A-MSDU decapsulation

2016-10-07 Thread Johannes Berg
From: Johannes Berg 

As pointed out by Michael Braun, we don't check inner L2 addresses
during A-MSDU decapsulation, leading to the possibility that, for
example, a station associated to an AP sends frames as though they
came from somewhere else.

Fix this problem by letting cfg80211 validate the addresses, as
indicated by passing in the ones that need to be validated.

Reported-by: Michael Braun 
Signed-off-by: Johannes Berg 
---
 net/mac80211/rx.c | 20 +++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index cf53fe1a0aa2..a47bbc973f2d 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2299,6 +2299,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
struct sk_buff_head frame_list;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
struct ethhdr ethhdr;
+   const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
 
if (unlikely(!ieee80211_is_data(fc)))
return RX_CONTINUE;
@@ -2322,6 +2323,23 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
default:
return RX_DROP_UNUSABLE;
}
+   check_da = NULL;
+   check_sa = NULL;
+   } else switch (rx->sdata->vif.type) {
+   case NL80211_IFTYPE_AP:
+   case NL80211_IFTYPE_AP_VLAN:
+   check_da = NULL;
+   break;
+   case NL80211_IFTYPE_STATION:
+   if (!rx->sta ||
+   !test_sta_flag(rx->sta, WLAN_STA_TDLS_PEER))
+   check_sa = NULL;
+   break;
+   case NL80211_IFTYPE_MESH_POINT:
+   check_sa = NULL;
+   break;
+   default:
+   break;
}
 
if (is_multicast_ether_addr(hdr->addr1))
@@ -2338,7 +2356,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
 rx->sdata->vif.type,
 rx->local->hw.extra_tx_headroom,
-NULL, NULL);
+check_da, check_sa);
 
while (!skb_queue_empty(&frame_list)) {
rx->skb = __skb_dequeue(&frame_list);
-- 
2.8.1



[PATCH 2/3] cfg80211: add ability to check DA/SA in A-MSDU decapsulation

2016-10-07 Thread Johannes Berg
From: Johannes Berg 

We should not accept arbitrary DA/SA inside A-MSDUs, it could be used
to circumvent protections, like allowing a station to send frames and
make them seem to come from somewhere else.

Add the necessary infrastructure in cfg80211 to allow such checks, in
further patches we'll start using them.

Signed-off-by: Johannes Berg 
---
 drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c |  2 +-
 include/net/cfg80211.h   |  5 -
 net/mac80211/rx.c|  3 ++-
 net/wireless/util.c  | 14 --
 4 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c 
b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
index e9f462e3730b..274dd5a1574a 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -45,7 +45,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct 
mwifiex_private *priv,
skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
 
ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
-priv->wdev.iftype, 0);
+priv->wdev.iftype, 0, NULL, NULL);
 
while (!skb_queue_empty(&list)) {
struct rx_packet_hdr *rx_hdr;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f372eadd1963..7df600c463eb 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4090,10 +4090,13 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const 
u8 *addr,
  * @addr: The device MAC address.
  * @iftype: The device interface type.
  * @extra_headroom: The hardware extra headroom for SKBs in the @list.
+ * @check_da: DA to check in the inner ethernet header, or NULL
+ * @check_sa: SA to check in the inner ethernet header, or NULL
  */
 void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
  const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom);
+ const unsigned int extra_headroom,
+ const u8 *check_da, const u8 *check_sa);
 
 /**
  * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index de2d75fa5c51..cf53fe1a0aa2 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2337,7 +2337,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
 
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
 rx->sdata->vif.type,
-rx->local->hw.extra_tx_headroom);
+rx->local->hw.extra_tx_headroom,
+NULL, NULL);
 
while (!skb_queue_empty(&frame_list)) {
rx->skb = __skb_dequeue(&frame_list);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index e36ede840b88..5ea12afc7706 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -739,7 +739,8 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int 
hlen,
 
 void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
  const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom)
+ const unsigned int extra_headroom,
+ const u8 *check_da, const u8 *check_sa)
 {
unsigned int hlen = ALIGN(extra_headroom, 4);
struct sk_buff *frame = NULL;
@@ -767,8 +768,17 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct 
sk_buff_head *list,
goto purge;
 
offset += sizeof(struct ethhdr);
-   /* reuse skb for the last subframe */
last = remaining <= subframe_len + padding;
+
+   /* FIXME: should we really accept multicast DA? */
+   if ((check_da && !is_multicast_ether_addr(eth.h_dest) &&
+!ether_addr_equal(check_da, eth.h_dest)) ||
+   (check_sa && !ether_addr_equal(check_sa, eth.h_source))) {
+   offset += len + padding;
+   continue;
+   }
+
+   /* reuse skb for the last subframe */
if (!skb_is_nonlinear(skb) && !reuse_frag && last) {
skb_pull(skb, offset);
frame = skb;
-- 
2.8.1



[PATCH 1/3] cfg80211: let ieee80211_amsdu_to_8023s() take only header-less SKB

2016-10-07 Thread Johannes Berg
From: Johannes Berg 

There's only a single case where has_80211_header is passed as true,
which is in mac80211. Given that there's only simple code that needs
to be done before calling it, export that function from cfg80211
instead and let mac80211 call it itself.

Signed-off-by: Johannes Berg 
---
 .../net/wireless/marvell/mwifiex/11n_rxreorder.c   |  2 +-
 include/net/cfg80211.h | 31 +++---
 net/mac80211/rx.c  |  8 +-
 net/wireless/util.c| 24 -
 4 files changed, 35 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c 
b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
index 94480123efa3..e9f462e3730b 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -45,7 +45,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct 
mwifiex_private *priv,
skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));
 
ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
-priv->wdev.iftype, 0, false);
+priv->wdev.iftype, 0);
 
while (!skb_queue_empty(&list)) {
struct rx_packet_hdr *rx_hdr;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fe78f02a242e..f372eadd1963 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4040,14 +4040,29 @@ unsigned int ieee80211_get_mesh_hdrlen(struct 
ieee80211s_hdr *meshhdr);
  */
 
 /**
+ * ieee80211_data_to_8023_exthdr - convert an 802.11 data frame to 802.3
+ * @skb: the 802.11 data frame
+ * @ehdr: pointer to a &struct ethhdr that will get the header, instead
+ * of it being pushed into the SKB
+ * @addr: the device MAC address
+ * @iftype: the virtual interface type
+ * Return: 0 on success. Non-zero on error.
+ */
+int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
+ const u8 *addr, enum nl80211_iftype iftype);
+
+/**
  * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
  * @skb: the 802.11 data frame
  * @addr: the device MAC address
  * @iftype: the virtual interface type
  * Return: 0 on success. Non-zero on error.
  */
-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
-  enum nl80211_iftype iftype);
+static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
+enum nl80211_iftype iftype)
+{
+   return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype);
+}
 
 /**
  * ieee80211_data_from_8023 - convert an 802.3 frame to 802.11
@@ -4065,22 +4080,20 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const 
u8 *addr,
 /**
  * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame
  *
- * Decode an IEEE 802.11n A-MSDU frame and convert it to a list of
- * 802.3 frames. The @list will be empty if the decode fails. The
- * @skb is consumed after the function returns.
+ * Decode an IEEE 802.11 A-MSDU and convert it to a list of 802.3 frames.
+ * The @list will be empty if the decode fails. The @skb must be fully
+ * header-less before being passed in here; it is freed in this function.
  *
- * @skb: The input IEEE 802.11n A-MSDU frame.
+ * @skb: The input A-MSDU frame without any headers.
  * @list: The output list of 802.3 frames. It must be allocated and
  * initialized by by the caller.
  * @addr: The device MAC address.
  * @iftype: The device interface type.
  * @extra_headroom: The hardware extra headroom for SKBs in the @list.
- * @has_80211_header: Set it true if SKB is with IEEE 802.11 header.
  */
 void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
  const u8 *addr, enum nl80211_iftype iftype,
- const unsigned int extra_headroom,
- bool has_80211_header);
+ const unsigned int extra_headroom);
 
 /**
  * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 3ac2f1cba317..de2d75fa5c51 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2298,6 +2298,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
__le16 fc = hdr->frame_control;
struct sk_buff_head frame_list;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+   struct ethhdr ethhdr;
 
if (unlikely(!ieee80211_is_data(fc)))
return RX_CONTINUE;
@@ -2329,9 +2330,14 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
skb->dev = dev;
__skb_queue_head_init(&frame_list);
 
+   if (ieee80211_data_to_8023_exthdr(skb, ðhdr,
+ rx->sdata->vif.addr,
+ 

Re: [PATCH v8] cfg80211: Provision to allow the support for different beacon intervals

2016-10-07 Thread Johannes Berg
On Fri, 2016-10-07 at 07:42 +, Kushwaha, Purushottam wrote:
> > 
> > However, it seems pretty easy to solve by passing another bool that
> > indicates "all the same"?
> Yes . Thanks . 
> We are planning to get the following changes in 2 commits . Let me
> know your consent . 
> 1. cfg80211: Provision to allow the support for different beacon
> intervals. ( Would like to go with this in a separate commit as the
> current infrastructure also does not support the validation of
> radar_detect / num_different_channel ) . 
> 2. cfg80211 : Check radar_detect and num_different_channels with
> beacon interface combinations.
> 
Seems fine, no driver will be able to advertise the different BIs
inbetween the two patches anyway.

I think we might want to add another patch before or inbetween, that
converts the far-too-long argument list of the combination
iter/validation functions to a structure?

johannes


RE: [PATCH v8] cfg80211: Provision to allow the support for different beacon intervals

2016-10-07 Thread Kushwaha, Purushottam
> However, it seems pretty easy to solve by passing another bool that indicates 
> "all the same"?
Yes . Thanks . 
We are planning to get the following changes in 2 commits . Let me know your 
consent . 
1. cfg80211: Provision to allow the support for different beacon intervals. ( 
Would like to go with this in a separate commit as the current infrastructure 
also does not support the validation of radar_detect / num_different_channel ) 
. 
2. cfg80211 : Check radar_detect and num_different_channels with beacon 
interface combinations.

Regards,
Purushottam


-Original Message-
From: Johannes Berg [mailto:johan...@sipsolutions.net] 
Sent: Wednesday, September 28, 2016 4:51 PM
To: Undekari, Sunil Dutt ; Kushwaha, Purushottam 

Cc: linux-wireless@vger.kernel.org; Malinen, Jouni ; 
Hullur Subramanyam, Amarnath 
Subject: Re: [PATCH v8] cfg80211: Provision to allow the support for different 
beacon intervals

Hi,

> In PATCH v8 , cfg80211_validate_beacon_int -> 
> cfg80211_iter_combinations carries the argument iftype_num , which 
> also considers the "new interface" that is getting added.

Ah, right, I remember now, sorry.

> Thus , in the example you have quoted above , the iftype_num shall 
> represent 2 ( AP + AP ) , and thus the min_gcd obtained out of 
> cfg80211_iter_combinations (cfg80211_get_beacon_int_min_gcd) shall be
> 50 for the example 1 and 200 for the example 2 . Thus , considering 
> the two examples mentioned above , the second AP should succeed for 
> "example 1" vs failure for "example 2" with patch
> V8 , isn't ?

Yeah, I tried to simplify and did so too much. I believe you are, for this 
purpose, ignoring for example radar detection.

Since you're passing 0 for num_different_channels and radar_detect, you might 
find a combination isn't actually currently usable, but that allows the new 
beacon interval configuration.

So I think overall this will only work right if it's done with all necessary 
information, no?

Trying to construct another example ... let's say permitted combinations are

 * go = 3, channels = 1, min_bcn_gcd = 50
 * go = 3, channels = 2, min_bcn_gcd = 100

(which isn't actually all that far-fetched, since channel hopping takes
time)

For simplification, say you already have two GOs active on different channels 
(with BI 100), and want to add another one - with beacon interval 50 - this 
isn't possible, but I don't think your code would detect it?

Or, perhaps I'm reading this wrong, if your code *does* detect it then changing 
the scenario a bit to have just a single channel, your code would prevent it 
even though it's allowed?


> The current behavior of the kernel is to not allow the configuration 
> of different beacon intervals and our expectation is that this new 
> patch should be backward compatible with the existing behavior.

Correct, and I agree, we shouldn't break that.

> Now , if we go with this approach of "introducing a new argument to 
> cfg80211_iter_combinations which shall be the GCD of all the existing 
> combinations to check against the respective 
> "diff_beacon_int_gcd_min"" ,  consider the case ( same one which is 
> mentioned above ) that we have a single AP interface ( beacon interval 
> = 300 ) , and a new AP is getting added ( beacon interval =
> 150 ),  with the following allowed combinations:
> 
> 1) * ap = 2
> diff_beacon_int_gcd_min = 0 ( rather not specified )
> 2)  * ap = 2
>   diff_beacon_int_gcd_min = 100
> 
> The GCD calculated is 150 . cfg80211_iter_combinations shall return 
> success for both the scenarios ( 1 and 2 ) (The intention here is to 
> compare with only the nonzero " diff_beacon_int_gcd_min" )
> 
> This success from "cfg80211_iter_combinations" does not represent if 
> the GCD passed is compared against a 0 / non zero 
> "diff_beacon_int_gcd_min" , isn't ?
> 
> Thus , we are trying to solve this problem , by getting the 
> "diff_beacon_int_gcd_min" for the respective interface combination , 
> before comparing it with the calculated GCD.

Oh. I think I finally understand your concern - good point!

Let me see if I understand correctly - you're saying that if I first calculate 

  g = GCD(all BIs, including the new one)

and then do

  cfg80211_iter_combinations(... existing variables ..., g)

then I cannot accurately determine whether or not I can use a combination that 
doesn't specify a min_beacon_interval_gcd, you can't know if the "all BIs" were 
the same, or not.

That's actually a very good point.

However, it seems pretty easy to solve by passing another bool that indicates 
"all the same"?

johannes


Re: [PATCH] wl18xx: Handle kfree() in better way when kzalloc fails

2016-10-07 Thread souptick joarder
On Fri, Oct 7, 2016 at 12:36 PM, Johannes Berg
 wrote:
>
> On Fri, 2016-10-07 at 12:19 +0530, Souptick Joarder wrote:
> > This patch is added to handle kfree and return error in a better way
>
> What's "better" about this?
>
> kfree(NULL) is perfectly valid, adding another label makes the code
> harder to read,

I agree with you.

when kzalloc(sizeof(*cmd), GFP_KERNEL) fails, try to avoid extra
kfree(cmd_channel) function call,
cause anyway it will call kfree with NULL.

I thought from that point of view.

>
> > - struct wl18xx_cmd_scan_params *cmd;
> > + struct wl18xx_cmd_scan_params *cmd = NULL;
>
> that new initialization is actually *completely* pointless since it's
> overwritten immediately here:
>
> >   struct wlcore_scan_channels *cmd_channels = NULL;
> >   int ret;
> >
> >   cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
> >   if (!cmd) {
> > - ret = -ENOMEM;
> > - goto out;
> > + return -ENOMEM;
> >   }
> >
> ...
>
> what gives?
>

> johannes

Ok, I will drop this patch.

-Souptick


Re: [PATCH] wl18xx: Handle kfree() in better way when kzalloc fails

2016-10-07 Thread Johannes Berg
On Fri, 2016-10-07 at 12:19 +0530, Souptick Joarder wrote:
> This patch is added to handle kfree and return error in a better way

What's "better" about this?

kfree(NULL) is perfectly valid, adding another label makes the code
harder to read,

> - struct wl18xx_cmd_scan_params *cmd;
> + struct wl18xx_cmd_scan_params *cmd = NULL;

that new initialization is actually *completely* pointless since it's
overwritten immediately here:

>   struct wlcore_scan_channels *cmd_channels = NULL;
>   int ret;
>  
>   cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
>   if (!cmd) {
> - ret = -ENOMEM;
> - goto out;
> + return -ENOMEM;
>   }
> 
...

what gives?

johannes