Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 3.10 3/8] iwlwifi: mvm: properly tell the fw that a STA is awake
From: Emmanuel Grumbach @ 2013-08-21  6:04 UTC (permalink / raw)
  To: Greg KH; +Cc: stable, linux-wireless, Emmanuel Grumbach, Johannes Berg
In-Reply-To: <1377065066-13030-1-git-send-email-emmanuel.grumbach@intel.com>

commit 5af01772ee1d6e96849adf728ff837bd71b119c0 upstream.

The firmware API wasn't being used correctly, fix that.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/iwlwifi/mvm/sta.c |    8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 736b50b..35c8ed5 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -1296,17 +1296,11 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
 	struct iwl_mvm_add_sta_cmd cmd = {
 		.add_modify = STA_MODE_MODIFY,
 		.sta_id = mvmsta->sta_id,
-		.modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT,
-		.sleep_state_flags = cpu_to_le16(STA_SLEEP_STATE_AWAKE),
+		.station_flags_msk = cpu_to_le32(STA_FLG_PS),
 		.mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
 	};
 	int ret;
 
-	/*
-	 * Same modify mask for sleep_tx_count and sleep_state_flags but this
-	 * should be fine since if we set the STA as "awake", then
-	 * sleep_tx_count is not relevant.
-	 */
 	ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA, CMD_ASYNC, sizeof(cmd), &cmd);
 	if (ret)
 		IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 3.10 2/8] iwlwifi: mvm: fix MCAST in AP mode
From: Emmanuel Grumbach @ 2013-08-21  6:04 UTC (permalink / raw)
  To: Greg KH; +Cc: stable, linux-wireless, Emmanuel Grumbach, Johannes Berg
In-Reply-To: <1377065066-13030-1-git-send-email-emmanuel.grumbach@intel.com>

commit 9116a3683902583a302ac5dcb283416d504d9bb4 upstream.

In multicast, there is no retries nor RTS since there is no
specific recipient that can ACK or send CTS. This means
that we must not use the rate scale table for multicast
frames.
This true for any frame that doesn't have a valid
ieee80211_sta pointer.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/iwlwifi/mvm/tx.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 48c1891..b9ba4e7 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -175,7 +175,7 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
 	 * table is controlled by LINK_QUALITY commands
 	 */
 
-	if (ieee80211_is_data(fc)) {
+	if (ieee80211_is_data(fc) && sta) {
 		tx_cmd->initial_rate_index = 0;
 		tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
 		return;
-- 
1.7.10.4


^ permalink raw reply related

* [PATCH 3.10 1/8] iwlwifi: mvm: correctly configure MCAST in AP mode
From: Emmanuel Grumbach @ 2013-08-21  6:04 UTC (permalink / raw)
  To: Greg KH; +Cc: stable, linux-wireless, Emmanuel Grumbach, Johannes Berg

commit 86a91ec757338edbce51de5dabd7afb0366f485c upstream.

The AP mode needs to use the MCAST fifo for the MCAST
frames sent after the DTIM. This fifo needs to be
configured with the same parameters as the VOICE FIFO.

A separate SCD queue is mapped to this fifo - the cab_queue
(cab stands for Content After Beacon). This queue isn't
connected to any station, but rather to the MAC context.
This queue should (and is already) be set as the MCAST
queue - this is part of the of MAC context command.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Reviewed-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h |    8 +++++++-
 drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c   |    6 +++++-
 drivers/net/wireless/iwlwifi/mvm/mvm.h        |    1 +
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h
index d68640e..98b1feb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-mac.h
@@ -71,7 +71,13 @@
 #define MAC_INDEX_MIN_DRIVER	0
 #define NUM_MAC_INDEX_DRIVER	MAC_INDEX_AUX
 
-#define AC_NUM	4 /* Number of access categories */
+enum iwl_ac {
+	AC_BK,
+	AC_BE,
+	AC_VI,
+	AC_VO,
+	AC_NUM,
+};
 
 /**
  * enum iwl_mac_protection_flags - MAC context flags
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index b2cc3d9..3b69045 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -362,7 +362,7 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 		break;
 	case NL80211_IFTYPE_AP:
 		iwl_trans_ac_txq_enable(mvm->trans, vif->cab_queue,
-					IWL_MVM_TX_FIFO_VO);
+					IWL_MVM_TX_FIFO_MCAST);
 		/* fall through */
 	default:
 		for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
@@ -550,6 +550,10 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
 		cmd->ac[i].fifos_mask = BIT(iwl_mvm_ac_to_tx_fifo[i]);
 	}
 
+	/* in AP mode, the MCAST FIFO takes the EDCA params from VO */
+	if (vif->type == NL80211_IFTYPE_AP)
+		cmd->ac[AC_VO].fifos_mask |= BIT(IWL_MVM_TX_FIFO_MCAST);
+
 	if (vif->bss_conf.qos)
 		cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
 
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 9f46b23..8086231 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -88,6 +88,7 @@ enum iwl_mvm_tx_fifo {
 	IWL_MVM_TX_FIFO_BE,
 	IWL_MVM_TX_FIFO_VI,
 	IWL_MVM_TX_FIFO_VO,
+	IWL_MVM_TX_FIFO_MCAST = 5,
 };
 
 extern struct ieee80211_ops iwl_mvm_hw_ops;
-- 
1.7.10.4


^ permalink raw reply related

* [RFC v2 2/2] mac80211: implement SMPS for AP
From: Emmanuel Grumbach @ 2013-08-21  5:54 UTC (permalink / raw)
  To: linux-wireless; +Cc: Emmanuel Grumbach
In-Reply-To: <1377064482-2944-1-git-send-email-emmanuel.grumbach@intel.com>

When the driver requests to move to STATIC or DYNAMIC SMPS,
we send an action frame to each associated station and
reconfigure the channel context / driver.
Of course, non-MIMO stations are ignored.

The beacon isn't updated. The association response will
include the original capabilities. Stations that associate
while in non-OFF SMPS mode will get an action frame right
after association to inform them about our current state.
Note that we wait until the end of the EAPOL. Sending an
action frame before the EAPOL is finished can be an issue
for a few clients. Clients aren't likely to send EAPOL
frames in MIMO anyway.

When the SMPS configuration gets more permissive (e.g.
STATIC -> OFF), we don't wake up stations that are asleep
We remember that they don't know about the change and send
the action frame when they wake up.

When the SMPS configuration gets more restrictive (e.g.
OFF -> STATIC), we set the TIM bit for every sleeping STA.
uAPSD stations might send MIMO until they poll the action
frame, but this is for a short period of time.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
v2:
	* send Action frames to authorized stations only
	* add a WARN_ON on AUTOMATIC in AP mode
---
 net/mac80211/cfg.c            |   91 +++++++++++++++++++++++++++++++++++++++++
 net/mac80211/debugfs_netdev.c |    1 +
 net/mac80211/ht.c             |    3 ++
 net/mac80211/ieee80211_i.h    |    2 +
 net/mac80211/sta_info.c       |   71 ++++++++++++++++++++++++++++++++
 net/mac80211/sta_info.h       |    5 +++
 net/mac80211/status.c         |   15 ++++---
 net/mac80211/util.c           |   25 +++++++++++
 8 files changed, 208 insertions(+), 5 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 34298f5..9672b8a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1554,6 +1554,19 @@ static int ieee80211_change_station(struct wiphy *wiphy,
 
 	mutex_unlock(&local->sta_mtx);
 
+	if (sdata->vif.type == NL80211_IFTYPE_AP &&
+	    sta->known_smps_mode != sta->sdata->smps_mode &&
+	    test_sta_flag(sta, WLAN_STA_AUTHORIZED) &&
+	    sta_info_tx_streams(sta) != 1) {
+		ht_dbg(sta->sdata,
+		       "%pM just authorized and MIMO capable - update SMPS\n",
+		       sta->sta.addr);
+		ieee80211_send_smps_action(sta->sdata,
+			sta->sdata->u.ap.req_smps,
+			sta->sta.addr,
+			sta->sdata->vif.bss_conf.bssid);
+	}
+
 	if (sdata->vif.type == NL80211_IFTYPE_STATION &&
 	    params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
 		ieee80211_recalc_ps(local, -1);
@@ -2341,6 +2354,84 @@ static int ieee80211_testmode_dump(struct wiphy *wiphy,
 int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
 				enum ieee80211_smps_mode smps_mode)
 {
+	struct sta_info *sta;
+	enum ieee80211_smps_mode old_req;
+	int i;
+
+	if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP))
+		return -EINVAL;
+
+	if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
+		return 0;
+
+	old_req = sdata->u.ap.req_smps;
+	sdata->u.ap.req_smps = smps_mode;
+
+	/* AUTOMATIC doesn't mean much for AP - don't allow it */
+	if (old_req == smps_mode ||
+	    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,
+	       "SMSP %d requested in AP mode, sending Action frame to %d stations\n",
+	       smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta));
+
+	mutex_lock(&sdata->local->sta_mtx);
+	for (i = 0; i < STA_HASH_SIZE; i++) {
+		for (sta = rcu_dereference_protected(sdata->local->sta_hash[i],
+				lockdep_is_held(&sdata->local->sta_mtx));
+		     sta;
+		     sta = rcu_dereference_protected(sta->hnext,
+				lockdep_is_held(&sdata->local->sta_mtx))) {
+			if (sta->sdata != sdata)
+				continue;
+
+			/* This station doesn't support MIMO - skip it */
+			if (sta_info_tx_streams(sta) == 1) {
+				ht_dbg(sdata,
+				       "Won't send SMPS to non-MIMO capable STA %pM\n",
+				       sta->sta.addr);
+				continue;
+			}
+
+			/*
+			 * Don't wake up a STA just to send the action frame
+			 * unless we are getting more restrictive.
+			 */
+			if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
+			    !ieee80211_smps_is_restrictive(sta->known_smps_mode,
+							   smps_mode)) {
+				ht_dbg(sdata,
+				       "Won't send SMPS to sleeping STA %pM\n",
+				       sta->sta.addr);
+				continue;
+			}
+
+			/*
+			 * If the STA is not authorized, wait until it gets
+			 * authorized and the action frame will be sent then.
+			 */
+			if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+				continue;
+
+			ht_dbg(sdata, "Sending SMPS to %pM\n", sta->sta.addr);
+			ieee80211_send_smps_action(sdata, smps_mode,
+						   sta->sta.addr,
+						   sdata->vif.bss_conf.bssid);
+		}
+	}
+	mutex_unlock(&sdata->local->sta_mtx);
+
+	sdata->smps_mode = smps_mode;
+	ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps);
+
 	return 0;
 }
 
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index ef9c9ec..3287764 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -569,6 +569,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
 static void add_ap_files(struct ieee80211_sub_if_data *sdata)
 {
 	DEBUGFS_ADD(num_mcast_sta);
+	DEBUGFS_ADD_MODE(smps, 0600);
 	DEBUGFS_ADD(num_sta_ps);
 	DEBUGFS_ADD(dtim_count);
 	DEBUGFS_ADD(num_buffered_multicast);
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 2c85b96..9a8be8f 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -489,6 +489,9 @@ void ieee80211_request_smps(struct ieee80211_vif *vif,
 		ieee80211_queue_work(&sdata->local->hw,
 				     &sdata->u.mgd.request_smps_work);
 	} else {
+		/* AUTOMATIC is meaningless in AP mode */
+		if (WARN_ON_ONCE(smps_mode == IEEE80211_SMPS_AUTOMATIC))
+			return;
 		if (sdata->u.ap.driver_smps_mode == smps_mode)
 			return;
 		sdata->u.ap.driver_smps_mode = smps_mode;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 7c68eac..e9da9b4 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1445,6 +1445,8 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
 			       const u8 *bssid);
 void ieee80211_request_smps_ap_work(struct work_struct *work);
 void ieee80211_request_smps_mgd_work(struct work_struct *work);
+bool ieee80211_smps_is_restrictive(enum ieee80211_smps_mode smps_mode_old,
+				   enum ieee80211_smps_mode smps_mode_new);
 
 void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
 				     u16 initiator, u16 reason, bool stop);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 9c97237..e5ab630 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -385,6 +385,27 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 		sta->last_seq_ctrl[i] = cpu_to_le16(USHRT_MAX);
 
 	sta->sta.smps_mode = IEEE80211_SMPS_OFF;
+	if (sdata->vif.type == NL80211_IFTYPE_AP) {
+
+		struct ieee80211_supported_band *sband =
+			local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
+		u8 smps = (sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >>
+				IEEE80211_HT_CAP_SM_PS_SHIFT;
+
+		switch (smps) {
+		case WLAN_HT_SMPS_CONTROL_DISABLED:
+			sta->known_smps_mode = IEEE80211_SMPS_OFF;
+			break;
+		case WLAN_HT_SMPS_CONTROL_STATIC:
+			sta->known_smps_mode = IEEE80211_SMPS_STATIC;
+			break;
+		case WLAN_HT_SMPS_CONTROL_DYNAMIC:
+			sta->known_smps_mode = IEEE80211_SMPS_DYNAMIC;
+			break;
+		default:
+			WARN_ON(1);
+		}
+	}
 
 	sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr);
 
@@ -1069,6 +1090,19 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
 
 	ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta);
 
+	/* This station just woke up and isn't aware of our SMPS state */
+	if (!ieee80211_smps_is_restrictive(sta->known_smps_mode,
+					   sdata->smps_mode) &&
+	    sta->known_smps_mode != sdata->smps_mode &&
+	    sta_info_tx_streams(sta) != 1) {
+		ht_dbg(sdata,
+		       "%pM just woke up and MIMO capable - update SMPS\n",
+		       sta->sta.addr);
+		ieee80211_send_smps_action(sdata, sdata->smps_mode,
+					   sta->sta.addr,
+					   sdata->vif.bss_conf.bssid);
+	}
+
 	local->total_ps_buffered -= buffered;
 
 	sta_info_recalc_tim(sta);
@@ -1520,3 +1554,40 @@ int sta_info_move_state(struct sta_info *sta,
 
 	return 0;
 }
+
+u8 sta_info_tx_streams(struct sta_info *sta)
+{
+	struct ieee80211_sta_ht_cap *ht_cap = &sta->sta.ht_cap;
+	u8 rx_streams;
+
+	if (!sta->sta.ht_cap.ht_supported)
+		return 1;
+
+	if (!sta->sta.vht_cap.vht_supported) {
+		int i;
+		u16 tx_mcs_map =
+			le16_to_cpu(sta->sta.vht_cap.vht_mcs.tx_mcs_map);
+
+		for (i = 7; i <= 0; i--)
+			if ((tx_mcs_map & (0x3 << (i * 2))) !=
+			    IEEE80211_VHT_MCS_NOT_SUPPORTED)
+				return i + 1;
+		WARN_ON(1);
+		return 1;
+	}
+
+	if (ht_cap->mcs.rx_mask[3])
+		rx_streams = 4;
+	else if (ht_cap->mcs.rx_mask[2])
+		rx_streams = 3;
+	else if (ht_cap->mcs.rx_mask[1])
+		rx_streams = 2;
+	else
+		rx_streams = 1;
+
+	if (!(ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_RX_DIFF))
+		return rx_streams;
+
+	return ((ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
+			>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1;
+}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 9013969..390d249 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -301,6 +301,8 @@ struct sta_ampdu_mlme {
  * @chains: chains ever used for RX from this station
  * @chain_signal_last: last signal (per chain)
  * @chain_signal_avg: signal average (per chain)
+ * @known_smps_mode: the smps_mode the client thinks we are in. Relevant for
+ *	AP only.
  */
 struct sta_info {
 	/* General information, mostly static */
@@ -411,6 +413,8 @@ struct sta_info {
 	unsigned int lost_packets;
 	unsigned int beacon_loss_count;
 
+	enum ieee80211_smps_mode known_smps_mode;
+
 	/* keep last! */
 	struct ieee80211_sta sta;
 };
@@ -613,6 +617,7 @@ void sta_set_rate_info_rx(struct sta_info *sta,
 			  struct rate_info *rinfo);
 void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
 			  unsigned long exp_time);
+u8 sta_info_tx_streams(struct sta_info *sta);
 
 void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
 void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 368837f..7746cd0 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -191,8 +191,8 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
 	if (ieee80211_is_action(mgmt->frame_control) &&
 	    mgmt->u.action.category == WLAN_CATEGORY_HT &&
 	    mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS &&
-	    sdata->vif.type == NL80211_IFTYPE_STATION &&
 	    ieee80211_sdata_running(sdata)) {
+		enum ieee80211_smps_mode smps_mode;
 		/*
 		 * This update looks racy, but isn't -- if we come
 		 * here we've definitely got a station that we're
@@ -202,18 +202,23 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
 		 */
 		switch (mgmt->u.action.u.ht_smps.smps_control) {
 		case WLAN_HT_SMPS_CONTROL_DYNAMIC:
-			sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
+			smps_mode = IEEE80211_SMPS_DYNAMIC;
 			break;
 		case WLAN_HT_SMPS_CONTROL_STATIC:
-			sdata->smps_mode = IEEE80211_SMPS_STATIC;
+			smps_mode = IEEE80211_SMPS_STATIC;
 			break;
 		case WLAN_HT_SMPS_CONTROL_DISABLED:
 		default: /* shouldn't happen since we don't send that */
-			sdata->smps_mode = IEEE80211_SMPS_OFF;
+			smps_mode = IEEE80211_SMPS_OFF;
 			break;
 		}
 
-		ieee80211_queue_work(&local->hw, &sdata->recalc_smps);
+		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+			sdata->smps_mode = smps_mode;
+			ieee80211_queue_work(&local->hw, &sdata->recalc_smps);
+		} else if (sdata->vif.type == NL80211_IFTYPE_AP) {
+			sta->known_smps_mode = smps_mode;
+		}
 	}
 }
 
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index d23c5a7..dad8262 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2295,3 +2295,28 @@ void ieee80211_radar_detected(struct ieee80211_hw *hw)
 	ieee80211_queue_work(hw, &local->radar_detected_work);
 }
 EXPORT_SYMBOL(ieee80211_radar_detected);
+
+/*
+ * Returns true if smps_mode_new is strictly more restrictive than
+ * smps_mode_old.
+ */
+bool ieee80211_smps_is_restrictive(enum ieee80211_smps_mode smps_mode_old,
+				   enum ieee80211_smps_mode smps_mode_new)
+{
+	if (WARN_ON_ONCE(smps_mode_old == IEEE80211_SMPS_AUTOMATIC ||
+			 smps_mode_new == IEEE80211_SMPS_AUTOMATIC))
+		return false;
+
+	switch (smps_mode_old) {
+	case IEEE80211_SMPS_STATIC:
+		return false;
+	case IEEE80211_SMPS_DYNAMIC:
+		return smps_mode_new == IEEE80211_SMPS_STATIC;
+	case IEEE80211_SMPS_OFF:
+		return smps_mode_new != IEEE80211_SMPS_OFF;
+	default:
+		WARN_ON(1);
+	}
+
+	return false;
+}
-- 
1.7.10.4


^ permalink raw reply related

* [RFC v2 1/2] mac80211: allow APs to send SMPS frames
From: Emmanuel Grumbach @ 2013-08-21  5:54 UTC (permalink / raw)
  To: linux-wireless; +Cc: Emmanuel Grumbach

SMPS code checks all over the place that the vif is
BSS. Remove that constraint and allow SMPS for AP too.

Provide dummy implementation that will be used for
further patches.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---
v2:
	* fix return value s/-EINVAL/-EOPNOTSUPP/
	* cancel sdata->u.ap.request_smps_work
---
 net/mac80211/cfg.c            |   16 +++++++++++++---
 net/mac80211/debugfs_netdev.c |   24 +++++++++++++++---------
 net/mac80211/ht.c             |   38 ++++++++++++++++++++++++++++----------
 net/mac80211/ieee80211_i.h    |   13 ++++++++++---
 net/mac80211/iface.c          |    2 ++
 net/mac80211/mlme.c           |    2 +-
 6 files changed, 69 insertions(+), 26 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 4cc81c3..34298f5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1059,6 +1059,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
 	/* abort any running channel switch */
 	sdata->vif.csa_active = false;
 	cancel_work_sync(&sdata->csa_finalize_work);
+	cancel_work_sync(&sdata->u.ap.request_smps_work);
 
 	/* turn off carrier for this interface and dependent VLANs */
 	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
@@ -2337,8 +2338,14 @@ static int ieee80211_testmode_dump(struct wiphy *wiphy,
 }
 #endif
 
-int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
-			     enum ieee80211_smps_mode smps_mode)
+int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
+				enum ieee80211_smps_mode smps_mode)
+{
+	return 0;
+}
+
+int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
+				 enum ieee80211_smps_mode smps_mode)
 {
 	const u8 *ap;
 	enum ieee80211_smps_mode old_req;
@@ -2346,6 +2353,9 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
 
 	lockdep_assert_held(&sdata->wdev.mtx);
 
+	if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION))
+		return -EINVAL;
+
 	old_req = sdata->u.mgd.req_smps;
 	sdata->u.mgd.req_smps = smps_mode;
 
@@ -2402,7 +2412,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 
 	/* no change, but if automatic follow powersave */
 	sdata_lock(sdata);
-	__ieee80211_request_smps(sdata, sdata->u.mgd.req_smps);
+	__ieee80211_request_smps_mgd(sdata, sdata->u.mgd.req_smps);
 	sdata_unlock(sdata);
 
 	if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index e601c9f..ef9c9ec 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -224,12 +224,15 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
 	     smps_mode == IEEE80211_SMPS_AUTOMATIC))
 		return -EINVAL;
 
-	/* supported only on managed interfaces for now */
-	if (sdata->vif.type != NL80211_IFTYPE_STATION)
+	if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+	    sdata->vif.type != NL80211_IFTYPE_AP)
 		return -EOPNOTSUPP;
 
 	sdata_lock(sdata);
-	err = __ieee80211_request_smps(sdata, smps_mode);
+	if (sdata->vif.type == NL80211_IFTYPE_STATION)
+		err = __ieee80211_request_smps_mgd(sdata, smps_mode);
+	else
+		err = __ieee80211_request_smps_ap(sdata, smps_mode);
 	sdata_unlock(sdata);
 
 	return err;
@@ -245,12 +248,15 @@ static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
 static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
 				     char *buf, int buflen)
 {
-	if (sdata->vif.type != NL80211_IFTYPE_STATION)
-		return -EOPNOTSUPP;
-
-	return snprintf(buf, buflen, "request: %s\nused: %s\n",
-			smps_modes[sdata->u.mgd.req_smps],
-			smps_modes[sdata->smps_mode]);
+	if (sdata->vif.type == NL80211_IFTYPE_STATION)
+		return snprintf(buf, buflen, "request: %s\nused: %s\n",
+				smps_modes[sdata->u.mgd.req_smps],
+				smps_modes[sdata->smps_mode]);
+	if (sdata->vif.type == NL80211_IFTYPE_AP)
+		return snprintf(buf, buflen, "request: %s\nused: %s\n",
+				smps_modes[sdata->u.ap.req_smps],
+				smps_modes[sdata->smps_mode]);
+	return -EOPNOTSUPP;
 }
 
 static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 529bf58..2c85b96 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -448,14 +448,25 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
 	return 0;
 }
 
-void ieee80211_request_smps_work(struct work_struct *work)
+void ieee80211_request_smps_mgd_work(struct work_struct *work)
 {
 	struct ieee80211_sub_if_data *sdata =
 		container_of(work, struct ieee80211_sub_if_data,
 			     u.mgd.request_smps_work);
 
 	sdata_lock(sdata);
-	__ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode);
+	__ieee80211_request_smps_mgd(sdata, sdata->u.mgd.driver_smps_mode);
+	sdata_unlock(sdata);
+}
+
+void ieee80211_request_smps_ap_work(struct work_struct *work)
+{
+	struct ieee80211_sub_if_data *sdata =
+		container_of(work, struct ieee80211_sub_if_data,
+			     u.ap.request_smps_work);
+
+	sdata_lock(sdata);
+	__ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode);
 	sdata_unlock(sdata);
 }
 
@@ -464,19 +475,26 @@ void ieee80211_request_smps(struct ieee80211_vif *vif,
 {
 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 
-	if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
+	if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION &&
+			 vif->type != NL80211_IFTYPE_AP))
 		return;
 
 	if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF))
 		smps_mode = IEEE80211_SMPS_AUTOMATIC;
 
-	if (sdata->u.mgd.driver_smps_mode == smps_mode)
-		return;
-
-	sdata->u.mgd.driver_smps_mode = smps_mode;
-
-	ieee80211_queue_work(&sdata->local->hw,
-			     &sdata->u.mgd.request_smps_work);
+	if (vif->type == NL80211_IFTYPE_STATION) {
+		if (sdata->u.mgd.driver_smps_mode == smps_mode)
+			return;
+		sdata->u.mgd.driver_smps_mode = smps_mode;
+		ieee80211_queue_work(&sdata->local->hw,
+				     &sdata->u.mgd.request_smps_work);
+	} else {
+		if (sdata->u.ap.driver_smps_mode == smps_mode)
+			return;
+		sdata->u.ap.driver_smps_mode = smps_mode;
+		ieee80211_queue_work(&sdata->local->hw,
+				     &sdata->u.ap.request_smps_work);
+	}
 }
 /* this might change ... don't want non-open drivers using it */
 EXPORT_SYMBOL_GPL(ieee80211_request_smps);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 47cf62e..7c68eac 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -265,6 +265,10 @@ struct ieee80211_if_ap {
 
 	struct ps_data ps;
 	atomic_t num_mcast_sta; /* number of stations receiving multicast */
+	enum ieee80211_smps_mode req_smps, /* requested smps mode */
+			 driver_smps_mode; /* smps mode request */
+
+	struct work_struct request_smps_work;
 };
 
 struct ieee80211_if_wds {
@@ -1439,7 +1443,8 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
 int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
 			       enum ieee80211_smps_mode smps, const u8 *da,
 			       const u8 *bssid);
-void ieee80211_request_smps_work(struct work_struct *work);
+void ieee80211_request_smps_ap_work(struct work_struct *work);
+void ieee80211_request_smps_mgd_work(struct work_struct *work);
 
 void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
 				     u16 initiator, u16 reason, bool stop);
@@ -1634,8 +1639,10 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
 u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
 			    struct ieee802_11_elems *elems,
 			    enum ieee80211_band band, u32 *basic_rates);
-int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
-			     enum ieee80211_smps_mode smps_mode);
+int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
+				 enum ieee80211_smps_mode smps_mode);
+int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
+				enum ieee80211_smps_mode smps_mode);
 void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
 
 size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index cc0c4be..913ef15 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1301,6 +1301,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
 	case NL80211_IFTYPE_AP:
 		skb_queue_head_init(&sdata->u.ap.ps.bc_buf);
 		INIT_LIST_HEAD(&sdata->u.ap.vlans);
+		INIT_WORK(&sdata->u.ap.request_smps_work,
+			  ieee80211_request_smps_ap_work);
 		sdata->vif.bss_conf.bssid = sdata->vif.addr;
 		break;
 	case NL80211_IFTYPE_P2P_CLIENT:
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 21bccd8..89e6f28 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3693,7 +3693,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
 		  ieee80211_beacon_connection_loss_work);
 	INIT_WORK(&ifmgd->csa_connection_drop_work,
 		  ieee80211_csa_connection_drop_work);
-	INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_work);
+	INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work);
 	setup_timer(&ifmgd->timer, ieee80211_sta_timer,
 		    (unsigned long) sdata);
 	setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer,
-- 
1.7.10.4


^ permalink raw reply related

* RE: [PATCH 3.10 0/3] Enable 7000 device family on 3.10
From: Grumbach, Emmanuel @ 2013-08-21  5:46 UTC (permalink / raw)
  To: Greg KH, Emmanuel Grumbach
  Cc: Johannes Berg, stable@vger.kernel.org, linux-wireless
In-Reply-To: <20130820212524.GA9902@kroah.com>

> On Tue, Aug 20, 2013 at 11:22:21PM +0300, Emmanuel Grumbach wrote:
> > On Tue, Aug 6, 2013 at 4:42 PM, Greg KH <greg@kroah.com> wrote:
> > > On Tue, Aug 06, 2013 at 02:39:39PM +0200, Johannes Berg wrote:
> > >> [Emmanuel is on vacation, I'll cover for him]
> > >>
> > >> On Fri, 2013-08-02 at 17:02 +0800, Greg KH wrote:
> > >> > On Mon, Jul 15, 2013 at 02:44:57PM +0300, Emmanuel Grumbach
> wrote:
> > >> > > This small patch series enables 7260 and 3160 devices on 3.10
> > >> > > kernel. Three patches are already in linux.git (3.11-rc1).
> > >> > > One patch is 3.10 specific and disables configuration that is
> > >> > > not supported in 3.10.
> > >> >
> > >> > I need the git commit id of these patches in Linus's tree before
> > >> > I can apply them.  Please resend them with that information.
> > >>
> > >> The second and third patch does have it, and the first patch is
> > >> only relevant for 3.10 since 3.11 will have more device types
> > >> enabled, we just didn't get all the code in. This seems to be
> > >> described in the commit log, do you want more details?
> > >
> > > Yes, please resend them with those details.  For me to take a patch
> > > that is not in Linus's tree is a big deal, I need a whole lot of
> > > justification for it.
> > >
> >
> > Just got back. Sorry for the delay.
> > I guess I will just drop that patch that is not in Linus's tree.
> > This patch disables a feature that is not likely to be used but we
> > *know* it is buggy.
> > So people who want more than just associating to their router will see
> > a bug in 3.10.
> > I guess we can leave with that since I was suggesting to disable the
> > feature anyway.
> 
> Why would this patch not go to Linus's tree?  If it's broken, fix it, and I can
> take the backported patch into the 3.10 tree.

It is actually a few patches and they are already in Linus's tree.
Sending them to you.

> 
> > So - do you want to resend, or you can apply the 2 patches I sent as is?
> 
> Please resend.
> 

On the way.

^ permalink raw reply

* Re: [RFC 1/2] mac80211: allow APs to send SMPS frames
From: Emmanuel Grumbach @ 2013-08-21  4:59 UTC (permalink / raw)
  To: Julian Calaby; +Cc: Emmanuel Grumbach, linux-wireless
In-Reply-To: <CAGRGNgVdMKmd6fPi7ugrWUVaSZeU54K+jyT=gLY2tnxvyBPogQ@mail.gmail.com>

Hi Julian,

Thanks for the review.

> On Tue, Aug 20, 2013 at 9:12 PM, Emmanuel Grumbach
> <emmanuel.grumbach@intel.com> wrote:
>> SMPS code checks all over the place that the vif is
>> BSS. Remove that constraint and allow SMPS for AP too.
>>
>> Provide dummy implementation that will be used for
>> further patches.
>>
>> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
>> ---
>>  net/mac80211/cfg.c            |   15 ++++++++++++---
>>  net/mac80211/debugfs_netdev.c |   24 +++++++++++++++---------
>>  net/mac80211/ht.c             |   38 ++++++++++++++++++++++++++++----------
>>  net/mac80211/ieee80211_i.h    |   13 ++++++++++---
>>  net/mac80211/iface.c          |    2 ++
>>  net/mac80211/mlme.c           |    2 +-
>>  6 files changed, 68 insertions(+), 26 deletions(-)
>>
>> diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
>> index e601c9f..7609e47 100644
>> --- a/net/mac80211/debugfs_netdev.c
>> +++ b/net/mac80211/debugfs_netdev.c
>> @@ -245,12 +248,15 @@ static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
>>  static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
>>                                      char *buf, int buflen)
>>  {
>> -       if (sdata->vif.type != NL80211_IFTYPE_STATION)
>> -               return -EOPNOTSUPP;
>> -
>> -       return snprintf(buf, buflen, "request: %s\nused: %s\n",
>> -                       smps_modes[sdata->u.mgd.req_smps],
>> -                       smps_modes[sdata->smps_mode]);
>> +       if (sdata->vif.type == NL80211_IFTYPE_STATION)
>> +               return snprintf(buf, buflen, "request: %s\nused: %s\n",
>> +                               smps_modes[sdata->u.mgd.req_smps],
>> +                               smps_modes[sdata->smps_mode]);
>> +       if (sdata->vif.type == NL80211_IFTYPE_AP)
>> +               return snprintf(buf, buflen, "request: %s\nused: %s\n",
>> +                               smps_modes[sdata->u.ap.req_smps],
>> +                               smps_modes[sdata->smps_mode]);
>> +       return -EINVAL;
>
> Do you intend to change the return value for this function when we
> can't do SMPS from -EOPNOTSUPP to -EINVAL?

You are right - v2 on the way with other comments I got internally.

^ permalink raw reply

* Re: [RFC 1/2] mac80211: allow APs to send SMPS frames
From: Julian Calaby @ 2013-08-21  0:57 UTC (permalink / raw)
  To: Emmanuel Grumbach; +Cc: linux-wireless
In-Reply-To: <1376997139-6228-1-git-send-email-emmanuel.grumbach@intel.com>

Hi Emmanuel,

One minor thing I noticed:

On Tue, Aug 20, 2013 at 9:12 PM, Emmanuel Grumbach
<emmanuel.grumbach@intel.com> wrote:
> SMPS code checks all over the place that the vif is
> BSS. Remove that constraint and allow SMPS for AP too.
>
> Provide dummy implementation that will be used for
> further patches.
>
> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
> ---
>  net/mac80211/cfg.c            |   15 ++++++++++++---
>  net/mac80211/debugfs_netdev.c |   24 +++++++++++++++---------
>  net/mac80211/ht.c             |   38 ++++++++++++++++++++++++++++----------
>  net/mac80211/ieee80211_i.h    |   13 ++++++++++---
>  net/mac80211/iface.c          |    2 ++
>  net/mac80211/mlme.c           |    2 +-
>  6 files changed, 68 insertions(+), 26 deletions(-)
>
> diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
> index e601c9f..7609e47 100644
> --- a/net/mac80211/debugfs_netdev.c
> +++ b/net/mac80211/debugfs_netdev.c
> @@ -245,12 +248,15 @@ static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = {
>  static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata,
>                                      char *buf, int buflen)
>  {
> -       if (sdata->vif.type != NL80211_IFTYPE_STATION)
> -               return -EOPNOTSUPP;
> -
> -       return snprintf(buf, buflen, "request: %s\nused: %s\n",
> -                       smps_modes[sdata->u.mgd.req_smps],
> -                       smps_modes[sdata->smps_mode]);
> +       if (sdata->vif.type == NL80211_IFTYPE_STATION)
> +               return snprintf(buf, buflen, "request: %s\nused: %s\n",
> +                               smps_modes[sdata->u.mgd.req_smps],
> +                               smps_modes[sdata->smps_mode]);
> +       if (sdata->vif.type == NL80211_IFTYPE_AP)
> +               return snprintf(buf, buflen, "request: %s\nused: %s\n",
> +                               smps_modes[sdata->u.ap.req_smps],
> +                               smps_modes[sdata->smps_mode]);
> +       return -EINVAL;

Do you intend to change the return value for this function when we
can't do SMPS from -EOPNOTSUPP to -EINVAL?

You've also included a couple of other cases where you return -EINVAL.
I'm assuming those are correct.

Thanks,

-- 
Julian Calaby

Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/
.Plan: http://sites.google.com/site/juliancalaby/

^ permalink raw reply

* Re: pull request: wireless 2013-08-19
From: David Miller @ 2013-08-21  0:26 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20130819185940.GE30753@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Mon, 19 Aug 2013 14:59:40 -0400

> This is a batch of fixes intended for the 3.11 stream...
> 
> Regarding the iwlwifi bits, Johannes says:
> 
> "We revert an rfkill bugfix that unfortunately caused more bugs, shuffle
> some code to avoid touching the PCIe device before it's enabled and
> disconnect if firmware fails to do our bidding. I also have Stanislaw's
> fix to not crash in some channel switch scenarios."
> 
> As for the mac80211 bits, Johannes says:
> 
> "This time, I have one fix from Dan Carpenter for users of
> nl80211hdr_put(), and one fix from myself fixing a regression with the
> libertas driver."
> 
> Along with the above...
> 
> Dan Carpenter fixes some incorrectly placed "address of" operators
> in hostap that caused copying of junk data.
> 
> Jussi Kivilinna corrects zd1201 to use an allocated buffer rather
> than the stack for a URB operation.
> 
> Please let me know if there are problems!

Pulled, thanks John.

^ permalink raw reply

* Re: [REGRESSION] 3.10.{6,7} crashes on network activity
From: Josh Boyer @ 2013-08-21  0:11 UTC (permalink / raw)
  To: Arend van Spriel
  Cc: Felix Fietkau, Greg Kroah-Hartman, Tom Gundersen,
	stable@vger.kernel.org, Linux Wireless List, LKML, Johannes Berg
In-Reply-To: <52132589.5000306@broadcom.com>

On Tue, Aug 20, 2013 at 4:15 AM, Arend van Spriel <arend@broadcom.com> wrote:
> On 08/20/2013 06:56 AM, Felix Fietkau wrote:
>>
>> On 2013-08-20 2:28 AM, Greg Kroah-Hartman wrote:
>>>
>>> On Tue, Aug 20, 2013 at 08:26:11AM +0800, Tom Gundersen wrote:
>>>>
>>>> On Tue, Aug 20, 2013 at 8:03 AM, Greg Kroah-Hartman
>>>> <gregkh@linuxfoundation.org> wrote:
>>>>>
>>>>> On Tue, Aug 20, 2013 at 07:59:47AM +0800, Tom Gundersen wrote:
>>>>>>
>>>>>> Hi guys,
>>>>>>
>>>>>> Starting with 3.10.6 (and still present in .7) I get an oops on
>>>>>> connecting to the network.
>>>>>>
>>>>>> The attached picture shows the oops. In case it does not reach the ML,
>>>>>> the top of the call trace reads:
>>>>>>
>>>>>> brcms_c_compute_rtscts_dur
>>>>>> brcms_c_ampdu_finalize
>>>>>> ampdu_finalize
>>>>>> dma_txfast
>>>>>> brcms_c_txfifo
>>>>>> brcms_c_sendpkt_mac80211
>>>>>> brcms_ops_tx
>>>>>> __ieee80211_tx
>>>>>>
>>>>>> I bisected the problem and the first bad commit is
>>>>>>
>>>>>> commit ef47a5e4f1aaf1d0e2e6875e34b2c9595897bef6
>>>>>> Author: Felix Fietkau <nbd@openwrt.org>
>>>>>> Date:   Fri Jun 28 21:04:35 2013 +0200
>>>>>>
>>>>>>      mac80211/minstrel_ht: fix cck rate sampling
>>>>>>
>>>>>>      commit 1cd158573951f737fbc878a35cb5eb47bf9af3d5 upstream.
>>>>>>
>>>>>> Reverting it on top of .7 fixes the problem.
>>>>>>
>>>>>> I had the same (I suppose) problem on mainline some time ago, but I
>>>>>> have not bisected it, verified that the problem still occurs there, or
>>>>>> checked if reverting the upstream patch fixes it. I'd be happy to do
>>>>>> that if it would help though.
>>>>>>
>>>>>> Let me know if you need any more information.
>>>>>
>>>>>
>>>>> Do you have this same problem with 3.11-rc6 as well?
>>>>
>>>>
>>>> Yes, I just confirmed. I also confirmed that reverting the mainline
>>>> commit on top of -rc6 fixes the problem.
>>>
>>>
>>> Great, thanks.
>>>
>>> Felix and Johannes, any chance we can get this reverted in Linus tree
>>> soon, and push that revert back to the 3.10 stable tree as well?
>>
>> I'd like to avoid a revert, since that will simply replace one set of
>> issues with another. Let's limit the use of the feature that brcmsmac
>> can't handle to drivers that are known to work with it. Tom, Please
>> test this patch to see if it fixes your issue.
>
>
> Hi Felix,
>
> I have been diving into root causing why brcmsmac can not handle cck
> fallback rates, because it should. Maybe it is better to flag no cck support
> and only change brcmsmac.

We have a number of users hitting this in Fedora 18 and 19 now.  We're
tracking it with https://bugzilla.redhat.com/show_bug.cgi?id=998080
and I'm sure we can find people to test easily.

If you have a patch disabling cck in brcmsmac, I'd be happy to build a
kernel for people.  If that's going to be some time coming, perhaps
it's better to grab Felix's patch on a temporary basis?

josh

^ permalink raw reply

* [PATCH 2/2] staging: vt6656: baseband.c BBvCalculateParameter create structure for pwPhyLen, pbyPhySrv and pbyPhySgn
From: Malcolm Priestley @ 2013-08-20 21:52 UTC (permalink / raw)
  To: gregkh; +Cc: linux-wireless

Create single packed structure vnt_phy_field for rxtx.h structures.

In card.c CARDvSetRSPINF a vnt_phy_field replaces abyServ,
abySignal, awLen variables.

In rxtx.c point BBvCalculateParameter to relevant field.

Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
 drivers/staging/vt6656/baseband.c | 70 ++++++++++++++--------------
 drivers/staging/vt6656/baseband.h | 10 +++-
 drivers/staging/vt6656/card.c     | 68 +++++++++------------------
 drivers/staging/vt6656/rxtx.c     | 97 +++++++++++++++------------------------
 drivers/staging/vt6656/rxtx.h     | 57 ++++++-----------------
 5 files changed, 117 insertions(+), 185 deletions(-)

diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c
index 7d34403..1e8b841 100644
--- a/drivers/staging/vt6656/baseband.c
+++ b/drivers/staging/vt6656/baseband.c
@@ -723,16 +723,16 @@ BBuGetFrameTime(
  *      cbFrameLength   - Tx Frame Length
  *      wRate           - Tx Rate
  *  Out:
- *      pwPhyLen        - pointer to Phy Length field
- *      pbyPhySrv       - pointer to Phy Service field
- *      pbyPhySgn       - pointer to Phy Signal field
+ *	struct vnt_phy_field *phy
+ * 			- pointer to Phy Length field
+ *			- pointer to Phy Service field
+ * 			- pointer to Phy Signal field
  *
  * Return Value: none
  *
  */
 void BBvCalculateParameter(struct vnt_private *pDevice, u32 cbFrameLength,
-	u16 wRate, u8 byPacketType, u16 *pwPhyLen, u8 *pbyPhySrv,
-		u8 *pbyPhySgn)
+	u16 wRate, u8 byPacketType, struct vnt_phy_field *phy)
 {
 	u32 cbBitCount;
 	u32 cbUsCount = 0;
@@ -747,15 +747,15 @@ void BBvCalculateParameter(struct vnt_private *pDevice, u32 cbFrameLength,
     switch (wRate) {
     case RATE_1M :
         cbUsCount = cbBitCount;
-        *pbyPhySgn = 0x00;
+	phy->signal = 0x00;
         break;
 
     case RATE_2M :
         cbUsCount = cbBitCount / 2;
         if (byPreambleType == 1)
-            *pbyPhySgn = 0x09;
+		phy->signal = 0x09;
         else // long preamble
-            *pbyPhySgn = 0x01;
+		phy->signal = 0x01;
         break;
 
     case RATE_5M :
@@ -766,9 +766,9 @@ void BBvCalculateParameter(struct vnt_private *pDevice, u32 cbFrameLength,
         if (cbTmp != cbBitCount)
             cbUsCount ++;
         if (byPreambleType == 1)
-            *pbyPhySgn = 0x0a;
+		phy->signal = 0x0a;
         else // long preamble
-            *pbyPhySgn = 0x02;
+		phy->signal = 0x02;
         break;
 
     case RATE_11M :
@@ -783,101 +783,101 @@ void BBvCalculateParameter(struct vnt_private *pDevice, u32 cbFrameLength,
                 bExtBit = true;
         }
         if (byPreambleType == 1)
-            *pbyPhySgn = 0x0b;
+		phy->signal = 0x0b;
         else // long preamble
-            *pbyPhySgn = 0x03;
+		phy->signal = 0x03;
         break;
 
     case RATE_6M :
         if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9B; //1001 1011
+		phy->signal = 0x9b;
         }
         else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8B; //1000 1011
+		phy->signal = 0x8b;
         }
         break;
 
     case RATE_9M :
         if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9F; //1001 1111
+		phy->signal = 0x9f;
         }
         else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8F; //1000 1111
+		phy->signal = 0x8f;
         }
         break;
 
     case RATE_12M :
         if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9A; //1001 1010
+		phy->signal = 0x9a;
         }
         else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8A; //1000 1010
+		phy->signal = 0x8a;
         }
         break;
 
     case RATE_18M :
         if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9E; //1001 1110
+		phy->signal = 0x9e;
         }
         else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8E; //1000 1110
+		phy->signal = 0x8e;
         }
         break;
 
     case RATE_24M :
         if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x99; //1001 1001
+		phy->signal = 0x99;
         }
         else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x89; //1000 1001
+		phy->signal = 0x89;
         }
         break;
 
     case RATE_36M :
         if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9D; //1001 1101
+		phy->signal = 0x9d;
         }
         else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8D; //1000 1101
+		phy->signal = 0x8d;
         }
         break;
 
     case RATE_48M :
         if(byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x98; //1001 1000
+		phy->signal = 0x98;
         }
         else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x88; //1000 1000
+		phy->signal = 0x88;
         }
         break;
 
     case RATE_54M :
         if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9C; //1001 1100
+		phy->signal = 0x9c;
         }
         else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8C; //1000 1100
+		phy->signal = 0x8c;
         }
         break;
 
     default :
         if (byPacketType == PK_TYPE_11A) {//11a, 5GHZ
-            *pbyPhySgn = 0x9C; //1001 1100
+		phy->signal = 0x9c;
         }
         else {//11g, 2.4GHZ
-            *pbyPhySgn = 0x8C; //1000 1100
+		phy->signal = 0x8c;
         }
         break;
     }
 
 	if (byPacketType == PK_TYPE_11B) {
-		*pbyPhySrv = 0x00;
+		phy->service = 0x00;
 		if (bExtBit)
-			*pbyPhySrv = *pbyPhySrv | 0x80;
-		*pwPhyLen = cpu_to_le16((u16)cbUsCount);
+			phy->service |= 0x80;
+		phy->len = cpu_to_le16((u16)cbUsCount);
 	} else {
-		*pbyPhySrv = 0x00;
-		*pwPhyLen = cpu_to_le16((u16)cbFrameLength);
+		phy->service = 0x00;
+		phy->len = cpu_to_le16((u16)cbFrameLength);
 	}
 }
 
diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h
index 0a634ad..a8db17d 100644
--- a/drivers/staging/vt6656/baseband.h
+++ b/drivers/staging/vt6656/baseband.h
@@ -81,6 +81,13 @@
 #define TOP_RATE_2M         0x00200000
 #define TOP_RATE_1M         0x00100000
 
+/* Length, Service, and Signal fields of Phy for Tx */
+struct vnt_phy_field {
+	u8 signal;
+	u8 service;
+	u16 len;
+} __packed;
+
 unsigned int
 BBuGetFrameTime(
      u8 byPreambleType,
@@ -90,8 +97,7 @@ BBuGetFrameTime(
     );
 
 void BBvCalculateParameter(struct vnt_private *, u32 cbFrameLength,
-	u16 wRate, u8 byPacketType, u16 *pwPhyLen, u8 *pbyPhySrv,
-	u8 *pbyPhySgn);
+	u16 wRate, u8 byPacketType, struct vnt_phy_field *);
 
 /* timer for antenna diversity */
 
diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c
index c0815d8..dbf11ec 100644
--- a/drivers/staging/vt6656/card.c
+++ b/drivers/staging/vt6656/card.c
@@ -319,53 +319,27 @@ CARDvCalculateOFDMRParameter (
  */
 void CARDvSetRSPINF(struct vnt_private *pDevice, u8 byBBType)
 {
-	u8 abyServ[4] = {0, 0, 0, 0}; /* For CCK */
-	u8 abySignal[4] = {0, 0, 0, 0};
-	u16 awLen[4] = {0, 0, 0, 0};
+	struct vnt_phy_field phy[4];
 	u8 abyTxRate[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; /* For OFDM */
 	u8 abyRsvTime[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
 	u8 abyData[34];
 	int i;
 
     //RSPINF_b_1
-    BBvCalculateParameter(pDevice,
-                         14,
-                         swGetCCKControlRate(pDevice, RATE_1M),
-                         PK_TYPE_11B,
-                         &awLen[0],
-                         &abyServ[0],
-                         &abySignal[0]
-    );
+	BBvCalculateParameter(pDevice, 14,
+		swGetCCKControlRate(pDevice, RATE_1M), PK_TYPE_11B, &phy[0]);
 
     ///RSPINF_b_2
-    BBvCalculateParameter(pDevice,
-                         14,
-                         swGetCCKControlRate(pDevice, RATE_2M),
-                         PK_TYPE_11B,
-                         &awLen[1],
-                         &abyServ[1],
-                         &abySignal[1]
-    );
+	BBvCalculateParameter(pDevice, 14,
+		swGetCCKControlRate(pDevice, RATE_2M), PK_TYPE_11B, &phy[1]);
 
     //RSPINF_b_5
-    BBvCalculateParameter(pDevice,
-                         14,
-                         swGetCCKControlRate(pDevice, RATE_5M),
-                         PK_TYPE_11B,
-                         &awLen[2],
-                         &abyServ[2],
-                         &abySignal[2]
-    );
+	BBvCalculateParameter(pDevice, 14,
+		swGetCCKControlRate(pDevice, RATE_5M), PK_TYPE_11B, &phy[2]);
 
     //RSPINF_b_11
-    BBvCalculateParameter(pDevice,
-                         14,
-                         swGetCCKControlRate(pDevice, RATE_11M),
-                         PK_TYPE_11B,
-                         &awLen[3],
-                         &abyServ[3],
-                         &abySignal[3]
-    );
+	BBvCalculateParameter(pDevice, 14,
+		swGetCCKControlRate(pDevice, RATE_11M), PK_TYPE_11B, &phy[3]);
 
     //RSPINF_a_6
     CARDvCalculateOFDMRParameter (RATE_6M,
@@ -421,21 +395,21 @@ void CARDvSetRSPINF(struct vnt_private *pDevice, u8 byBBType)
                                  &abyTxRate[8],
                                  &abyRsvTime[8]);
 
-	put_unaligned(awLen[0], (u16 *)&abyData[0]);
-    abyData[2] = abySignal[0];
-    abyData[3] = abyServ[0];
+	put_unaligned(phy[0].len, (u16 *)&abyData[0]);
+	abyData[2] = phy[0].signal;
+	abyData[3] = phy[0].service;
 
-	put_unaligned(awLen[1], (u16 *)&abyData[4]);
-    abyData[6] = abySignal[1];
-    abyData[7] = abyServ[1];
+	put_unaligned(phy[1].len, (u16 *)&abyData[4]);
+	abyData[6] = phy[1].signal;
+	abyData[7] = phy[1].service;
 
-	put_unaligned(awLen[2], (u16 *)&abyData[8]);
-    abyData[10] = abySignal[2];
-    abyData[11] = abyServ[2];
+	put_unaligned(phy[2].len, (u16 *)&abyData[8]);
+	abyData[10] = phy[2].signal;
+	abyData[11] = phy[2].service;
 
-	put_unaligned(awLen[3], (u16 *)&abyData[12]);
-    abyData[14] = abySignal[3];
-    abyData[15] = abyServ[3];
+	put_unaligned(phy[3].len, (u16 *)&abyData[12]);
+	abyData[14] = phy[3].signal;
+	abyData[15] = phy[3].service;
 
     for (i = 0; i < 9; i++) {
 	abyData[16+i*2] = abyTxRate[i];
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 8c42781..05e82ec 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -52,7 +52,6 @@
 #include "card.h"
 #include "bssdb.h"
 #include "mac.h"
-#include "baseband.h"
 #include "michael.h"
 #include "tkip.h"
 #include "tcrc.h"
@@ -503,12 +502,10 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
 		struct vnt_tx_datahead_g *pBuf =
 				(struct vnt_tx_datahead_g *)pTxDataHead;
                 //Get SignalField,ServiceField,Length
-                BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                    (u16 *)&(pBuf->wTransmitLength_a), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a)
-                );
-                BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                    (u16 *)&(pBuf->wTransmitLength_b), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
-                );
+		BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
+			byPktType, &pBuf->a);
+		BBvCalculateParameter(pDevice, cbFrameLength,
+			pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
                 //Get Duration and TimeStamp
 		pBuf->wDuration_a = (u16)s_uGetDataDuration(pDevice, DATADUR_A,
 							byPktType, bNeedAck);
@@ -523,12 +520,10 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
 		struct vnt_tx_datahead_g_fb *pBuf =
 			(struct vnt_tx_datahead_g_fb *)pTxDataHead;
                 //Get SignalField,ServiceField,Length
-                BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                    (u16 *)&(pBuf->wTransmitLength_a), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a)
-                );
-                BBvCalculateParameter(pDevice, cbFrameLength, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                    (u16 *)&(pBuf->wTransmitLength_b), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
-                );
+		BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
+			byPktType, &pBuf->a);
+		BBvCalculateParameter(pDevice, cbFrameLength,
+			pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
                 //Get Duration and TimeStamp
 		pBuf->wDuration_a = (u16)s_uGetDataDuration(pDevice, DATADUR_A,
 							byPktType, bNeedAck);
@@ -548,9 +543,8 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
 		struct vnt_tx_datahead_a_fb *pBuf =
 			(struct vnt_tx_datahead_a_fb *)pTxDataHead;
             //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (u16 *)&(pBuf->wTransmitLength), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
-            );
+		BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
+			byPktType, &pBuf->a);
             //Get Duration and TimeStampOff
 		pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_A,
 					byPktType, bNeedAck);
@@ -564,9 +558,8 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
 		struct vnt_tx_datahead_ab *pBuf =
 			(struct vnt_tx_datahead_ab *)pTxDataHead;
             //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (u16 *)&(pBuf->wTransmitLength), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
-            );
+		BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
+			byPktType, &pBuf->ab);
             //Get Duration and TimeStampOff
 		pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_A,
 				byPktType, bNeedAck);
@@ -579,9 +572,8 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
 		struct vnt_tx_datahead_ab *pBuf =
 			(struct vnt_tx_datahead_ab *)pTxDataHead;
             //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (u16 *)&(pBuf->wTransmitLength), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
-            );
+		BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate,
+			byPktType, &pBuf->ab);
             //Get Duration and TimeStampOff
 		pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_B,
 				byPktType, bNeedAck);
@@ -597,7 +589,6 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
 	struct ethhdr *psEthHeader, u16 wCurrentRate, u8 byFBOption)
 {
 	u32 uRTSFrameLen = 20;
-	u16 wLen = 0;
 
     if (pvRTS == NULL)
     	return;
@@ -614,12 +605,10 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
         if (byFBOption == AUTO_FB_NONE) {
 		struct vnt_rts_g *pBuf = (struct vnt_rts_g *)pvRTS;
             //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
-            );
-            BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
-                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a)
-            );
+		BBvCalculateParameter(pDevice, uRTSFrameLen,
+			pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
+		BBvCalculateParameter(pDevice, uRTSFrameLen,
+			pDevice->byTopOFDMBasicRate, byPktType, &pBuf->a);
             //Get Duration
 		pBuf->wDuration_bb = s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
 			cbFrameLength, PK_TYPE_11B,
@@ -648,12 +637,10 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
         else {
 		struct vnt_rts_g_fb *pBuf = (struct vnt_rts_g_fb *)pvRTS;
             //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
-            );
-            BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
-                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a)
-            );
+		BBvCalculateParameter(pDevice, uRTSFrameLen,
+			pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
+		BBvCalculateParameter(pDevice, uRTSFrameLen,
+			pDevice->byTopOFDMBasicRate, byPktType, &pBuf->a);
             //Get Duration
 		pBuf->wDuration_bb = s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
 			cbFrameLength, PK_TYPE_11B,
@@ -696,9 +683,8 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
         if (byFBOption == AUTO_FB_NONE) {
 		struct vnt_rts_ab *pBuf = (struct vnt_rts_ab *)pvRTS;
             //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
-                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
-            );
+		BBvCalculateParameter(pDevice, uRTSFrameLen,
+			pDevice->byTopOFDMBasicRate, byPktType, &pBuf->ab);
             //Get Duration
 		pBuf->wDuration = s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
 			cbFrameLength, byPktType, wCurrentRate,
@@ -721,9 +707,8 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
         else {
 		struct vnt_rts_a_fb *pBuf = (struct vnt_rts_a_fb *)pvRTS;
             //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
-                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
-            );
+		BBvCalculateParameter(pDevice, uRTSFrameLen,
+			pDevice->byTopOFDMBasicRate, byPktType, &pBuf->a);
             //Get Duration
 		pBuf->wDuration = s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
 			cbFrameLength, byPktType, wCurrentRate,
@@ -753,9 +738,8 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
     else if (byPktType == PK_TYPE_11B) {
 	struct vnt_rts_ab *pBuf = (struct vnt_rts_ab *)pvRTS;
         //Get SignalField,ServiceField,Length
-        BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-            (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
-        );
+	BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate,
+		PK_TYPE_11B, &pBuf->ab);
         //Get Duration
 	pBuf->wDuration = s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
 		cbFrameLength, byPktType, wCurrentRate,
@@ -783,7 +767,6 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
 	int bDisCRC, u16 wCurrentRate, u8 byFBOption)
 {
 	u32 uCTSFrameLen = 14;
-	u16 wLen = 0;
 
     if (pvCTS == NULL) {
         return;
@@ -799,10 +782,9 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
 	if (byFBOption != AUTO_FB_NONE) {
 		/* Auto Fall back */
 		struct vnt_cts_fb *pBuf = (struct vnt_cts_fb *)pvCTS;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
-            );
+		/* Get SignalField,ServiceField,Length */
+		BBvCalculateParameter(pDevice, uCTSFrameLen,
+			pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
 		pBuf->wDuration_ba = s_uGetRTSCTSDuration(pDevice, CTSDUR_BA,
 			cbFrameLength, byPktType,
 			wCurrentRate, bNeedAck, byFBOption);
@@ -820,10 +802,9 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
 		memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
 	} else {
 		struct vnt_cts *pBuf = (struct vnt_cts *)pvCTS;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
-                (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
-            );
+		/* Get SignalField,ServiceField,Length */
+		BBvCalculateParameter(pDevice, uCTSFrameLen,
+			pDevice->byTopCCKBasicRate, PK_TYPE_11B, &pBuf->b);
 		/* Get CTSDuration_ba */
 		pBuf->wDuration_ba = s_uGetRTSCTSDuration(pDevice,
 			CTSDUR_BA, cbFrameLength, byPktType,
@@ -1821,9 +1802,8 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice,
 	pTxDataHead = (struct vnt_tx_datahead_ab *)
 			(pbyTxBufferAddr + wTxBufSize);
         //Get SignalField,ServiceField,Length
-        BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11A,
-            (u16 *)&(pTxDataHead->wTransmitLength), (u8 *)&(pTxDataHead->byServiceField), (u8 *)&(pTxDataHead->bySignalField)
-        );
+	BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11A,
+							&pTxDataHead->ab);
         //Get Duration and TimeStampOff
 	pTxDataHead->wDuration = cpu_to_le16((u16)s_uGetDataDuration(pDevice,
 				DATADUR_A, PK_TYPE_11A, false));
@@ -1835,9 +1815,8 @@ CMD_STATUS csBeacon_xmit(struct vnt_private *pDevice,
 	pTxDataHead = (struct vnt_tx_datahead_ab *)
 				(pbyTxBufferAddr + wTxBufSize);
         //Get SignalField,ServiceField,Length
-        BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11B,
-            (u16 *)&(pTxDataHead->wTransmitLength), (u8 *)&(pTxDataHead->byServiceField), (u8 *)&(pTxDataHead->bySignalField)
-        );
+	BBvCalculateParameter(pDevice, cbFrameSize, wCurrentRate, PK_TYPE_11B,
+							&pTxDataHead->ab);
         //Get Duration and TimeStampOff
 	pTxDataHead->wDuration = cpu_to_le16((u16)s_uGetDataDuration(pDevice,
 				DATADUR_B, PK_TYPE_11B, false));
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
index b1ef90e..3484f2b 100644
--- a/drivers/staging/vt6656/rxtx.h
+++ b/drivers/staging/vt6656/rxtx.h
@@ -31,6 +31,7 @@
 
 #include "device.h"
 #include "wcmd.h"
+#include "baseband.h"
 
 /* RsvTime buffer header */
 struct vnt_rrv_time_rts {
@@ -56,12 +57,8 @@ struct vnt_rrv_time_ab {
 
 /* TX data header */
 struct vnt_tx_datahead_g {
-	u8 bySignalField_b;
-	u8 byServiceField_b;
-	u16 wTransmitLength_b;
-	u8 bySignalField_a;
-	u8 byServiceField_a;
-	u16 wTransmitLength_a;
+	struct vnt_phy_field b;
+	struct vnt_phy_field a;
 	u16 wDuration_b;
 	u16 wDuration_a;
 	u16 wTimeStampOff_b;
@@ -69,12 +66,8 @@ struct vnt_tx_datahead_g {
 } __packed;
 
 struct vnt_tx_datahead_g_fb {
-	u8 bySignalField_b;
-	u8 byServiceField_b;
-	u16 wTransmitLength_b;
-	u8 bySignalField_a;
-	u8 byServiceField_a;
-	u16 wTransmitLength_a;
+	struct vnt_phy_field b;
+	struct vnt_phy_field a;
 	u16 wDuration_b;
 	u16 wDuration_a;
 	u16 wDuration_a_f0;
@@ -84,17 +77,13 @@ struct vnt_tx_datahead_g_fb {
 } __packed;
 
 struct vnt_tx_datahead_ab {
-	u8 bySignalField;
-	u8 byServiceField;
-	u16 wTransmitLength;
+	struct vnt_phy_field ab;
 	u16 wDuration;
 	u16 wTimeStampOff;
 } __packed;
 
 struct vnt_tx_datahead_a_fb {
-	u8 bySignalField;
-	u8 byServiceField;
-	u16 wTransmitLength;
+	struct vnt_phy_field a;
 	u16 wDuration;
 	u16 wTimeStampOff;
 	u16 wDuration_f0;
@@ -103,12 +92,8 @@ struct vnt_tx_datahead_a_fb {
 
 /* RTS buffer header */
 struct vnt_rts_g {
-	u8 bySignalField_b;
-	u8 byServiceField_b;
-	u16 wTransmitLength_b;
-	u8 bySignalField_a;
-	u8 byServiceField_a;
-	u16 wTransmitLength_a;
+	struct vnt_phy_field b;
+	struct vnt_phy_field a;
 	u16 wDuration_ba;
 	u16 wDuration_aa;
 	u16 wDuration_bb;
@@ -117,12 +102,8 @@ struct vnt_rts_g {
 } __packed;
 
 struct vnt_rts_g_fb {
-	u8 bySignalField_b;
-	u8 byServiceField_b;
-	u16 wTransmitLength_b;
-	u8 bySignalField_a;
-	u8 byServiceField_a;
-	u16 wTransmitLength_a;
+	struct vnt_phy_field b;
+	struct vnt_phy_field a;
 	u16 wDuration_ba;
 	u16 wDuration_aa;
 	u16 wDuration_bb;
@@ -135,18 +116,14 @@ struct vnt_rts_g_fb {
 } __packed;
 
 struct vnt_rts_ab {
-	u8 bySignalField;
-	u8 byServiceField;
-	u16 wTransmitLength;
+	struct vnt_phy_field ab;
 	u16 wDuration;
 	u16 wReserved;
 	struct ieee80211_rts data;
 } __packed;
 
 struct vnt_rts_a_fb {
-	u8 bySignalField;
-	u8 byServiceField;
-	u16 wTransmitLength;
+	struct vnt_phy_field a;
 	u16 wDuration;
 	u16 wReserved;
 	u16 wRTSDuration_f0;
@@ -156,9 +133,7 @@ struct vnt_rts_a_fb {
 
 /* CTS buffer header */
 struct vnt_cts {
-	u8 bySignalField_b;
-	u8 byServiceField_b;
-	u16 wTransmitLength_b;
+	struct vnt_phy_field b;
 	u16 wDuration_ba;
 	u16 wReserved;
 	struct ieee80211_cts data;
@@ -166,9 +141,7 @@ struct vnt_cts {
 } __packed;
 
 struct vnt_cts_fb {
-	u8 bySignalField_b;
-	u8 byServiceField_b;
-	u16 wTransmitLength_b;
+	struct vnt_phy_field b;
 	u16 wDuration_ba;
 	u16 wReserved;
 	u16 wCTSDuration_ba_f0;
-- 
1.8.1.2




^ permalink raw reply related

* [PATCH 1/2] staging: vt6656: baseband.c  BBvCalculateParameter pwPhyLen return endian corrected.
From: Malcolm Priestley @ 2013-08-20 21:49 UTC (permalink / raw)
  To: gregkh; +Cc: linux-wireless

In rxtx.c many calls to BBvCaculateParameter are not endian
corrected all calls here need to be endian corrected.

Correct the endian in BBvCaculateParameter.

In card.c: CARDvSetRSPINF pwPhyLen points to awLen and is
manually applied to abyData.  Because it is now endian
corrected put_unaligned is needed to correct it.

In rxtx.c remove were endian is corrected.

This allows to merge  BBvCalculateParameter *pwPhyLen,*pbyPhySrv
and *pbyPhySgn to singles structure for tx buffers.

Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
 drivers/staging/vt6656/baseband.c | 19 +++++++++----------
 drivers/staging/vt6656/card.c     | 12 ++++--------
 drivers/staging/vt6656/rxtx.c     |  9 ---------
 3 files changed, 13 insertions(+), 27 deletions(-)

diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c
index a14a6a0..7d34403 100644
--- a/drivers/staging/vt6656/baseband.c
+++ b/drivers/staging/vt6656/baseband.c
@@ -870,16 +870,15 @@ void BBvCalculateParameter(struct vnt_private *pDevice, u32 cbFrameLength,
         break;
     }
 
-    if (byPacketType == PK_TYPE_11B) {
-        *pbyPhySrv = 0x00;
-        if (bExtBit)
-            *pbyPhySrv = *pbyPhySrv | 0x80;
-        *pwPhyLen = (u16) cbUsCount;
-    }
-    else {
-        *pbyPhySrv = 0x00;
-        *pwPhyLen = (u16)cbFrameLength;
-    }
+	if (byPacketType == PK_TYPE_11B) {
+		*pbyPhySrv = 0x00;
+		if (bExtBit)
+			*pbyPhySrv = *pbyPhySrv | 0x80;
+		*pwPhyLen = cpu_to_le16((u16)cbUsCount);
+	} else {
+		*pbyPhySrv = 0x00;
+		*pwPhyLen = cpu_to_le16((u16)cbFrameLength);
+	}
 }
 
 /*
diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c
index 24291ae..c0815d8 100644
--- a/drivers/staging/vt6656/card.c
+++ b/drivers/staging/vt6656/card.c
@@ -421,23 +421,19 @@ void CARDvSetRSPINF(struct vnt_private *pDevice, u8 byBBType)
                                  &abyTxRate[8],
                                  &abyRsvTime[8]);
 
-    abyData[0] = (u8)(awLen[0]&0xFF);
-    abyData[1] = (u8)(awLen[0]>>8);
+	put_unaligned(awLen[0], (u16 *)&abyData[0]);
     abyData[2] = abySignal[0];
     abyData[3] = abyServ[0];
 
-    abyData[4] = (u8)(awLen[1]&0xFF);
-    abyData[5] = (u8)(awLen[1]>>8);
+	put_unaligned(awLen[1], (u16 *)&abyData[4]);
     abyData[6] = abySignal[1];
     abyData[7] = abyServ[1];
 
-    abyData[8] = (u8)(awLen[2]&0xFF);
-    abyData[9] = (u8)(awLen[2]>>8);
+	put_unaligned(awLen[2], (u16 *)&abyData[8]);
     abyData[10] = abySignal[2];
     abyData[11] = abyServ[2];
 
-    abyData[12] = (u8)(awLen[3]&0xFF);
-    abyData[13] = (u8)(awLen[3]>>8);
+	put_unaligned(awLen[3], (u16 *)&abyData[12]);
     abyData[14] = abySignal[3];
     abyData[15] = abyServ[3];
 
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 06950c4..8c42781 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -617,11 +617,9 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
             BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
                 (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
             );
-            pBuf->wTransmitLength_b = cpu_to_le16(wLen);
             BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
                 (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a)
             );
-            pBuf->wTransmitLength_a = cpu_to_le16(wLen);
             //Get Duration
 		pBuf->wDuration_bb = s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
 			cbFrameLength, PK_TYPE_11B,
@@ -653,11 +651,9 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
             BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
                 (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
             );
-            pBuf->wTransmitLength_b = cpu_to_le16(wLen);
             BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
                 (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_a), (u8 *)&(pBuf->bySignalField_a)
             );
-            pBuf->wTransmitLength_a = cpu_to_le16(wLen);
             //Get Duration
 		pBuf->wDuration_bb = s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
 			cbFrameLength, PK_TYPE_11B,
@@ -703,7 +699,6 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
             BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
                 (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
             );
-            pBuf->wTransmitLength = cpu_to_le16(wLen);
             //Get Duration
 		pBuf->wDuration = s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
 			cbFrameLength, byPktType, wCurrentRate,
@@ -729,7 +724,6 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
             BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopOFDMBasicRate, byPktType,
                 (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
             );
-            pBuf->wTransmitLength = cpu_to_le16(wLen);
             //Get Duration
 		pBuf->wDuration = s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
 			cbFrameLength, byPktType, wCurrentRate,
@@ -762,7 +756,6 @@ static void s_vFillRTSHead(struct vnt_private *pDevice, u8 byPktType,
         BBvCalculateParameter(pDevice, uRTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
             (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
         );
-        pBuf->wTransmitLength = cpu_to_le16(wLen);
         //Get Duration
 	pBuf->wDuration = s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
 		cbFrameLength, byPktType, wCurrentRate,
@@ -810,7 +803,6 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
             BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
                 (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
             );
-            pBuf->wTransmitLength_b = cpu_to_le16(wLen);
 		pBuf->wDuration_ba = s_uGetRTSCTSDuration(pDevice, CTSDUR_BA,
 			cbFrameLength, byPktType,
 			wCurrentRate, bNeedAck, byFBOption);
@@ -832,7 +824,6 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
             BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
                 (u16 *)&(wLen), (u8 *)&(pBuf->byServiceField_b), (u8 *)&(pBuf->bySignalField_b)
             );
-            pBuf->wTransmitLength_b = cpu_to_le16(wLen);
 		/* Get CTSDuration_ba */
 		pBuf->wDuration_ba = s_uGetRTSCTSDuration(pDevice,
 			CTSDUR_BA, cbFrameLength, byPktType,
-- 
1.8.1.2





^ permalink raw reply related

* Re: [PATCH 3.10 0/3] Enable 7000 device family on 3.10
From: Greg KH @ 2013-08-20 21:25 UTC (permalink / raw)
  To: Emmanuel Grumbach
  Cc: Johannes Berg, Emmanuel Grumbach, stable@vger.kernel.org,
	linux-wireless
In-Reply-To: <CANUX_P0BxGr9coDjOmHJm+8kVJVsM9XiTDTVsb_kysuRmcmpNw@mail.gmail.com>

On Tue, Aug 20, 2013 at 11:22:21PM +0300, Emmanuel Grumbach wrote:
> On Tue, Aug 6, 2013 at 4:42 PM, Greg KH <greg@kroah.com> wrote:
> > On Tue, Aug 06, 2013 at 02:39:39PM +0200, Johannes Berg wrote:
> >> [Emmanuel is on vacation, I'll cover for him]
> >>
> >> On Fri, 2013-08-02 at 17:02 +0800, Greg KH wrote:
> >> > On Mon, Jul 15, 2013 at 02:44:57PM +0300, Emmanuel Grumbach wrote:
> >> > > This small patch series enables 7260 and 3160 devices on 3.10
> >> > > kernel. Three patches are already in linux.git (3.11-rc1).
> >> > > One patch is 3.10 specific and disables configuration that is not
> >> > > supported in 3.10.
> >> >
> >> > I need the git commit id of these patches in Linus's tree before I can
> >> > apply them.  Please resend them with that information.
> >>
> >> The second and third patch does have it, and the first patch is only
> >> relevant for 3.10 since 3.11 will have more device types enabled, we
> >> just didn't get all the code in. This seems to be described in the
> >> commit log, do you want more details?
> >
> > Yes, please resend them with those details.  For me to take a patch that
> > is not in Linus's tree is a big deal, I need a whole lot of
> > justification for it.
> >
> 
> Just got back. Sorry for the delay.
> I guess I will just drop that patch that is not in Linus's tree.
> This patch disables a feature that is not likely to be used but we
> *know* it is buggy.
> So people who want more than just associating to their router will see
> a bug in 3.10.
> I guess we can leave with that since I was suggesting to disable the
> feature anyway.

Why would this patch not go to Linus's tree?  If it's broken, fix it,
and I can take the backported patch into the 3.10 tree.

> So - do you want to resend, or you can apply the 2 patches I sent as is?

Please resend.

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH 11/16] wcn36xx: Add txrx.c
From: Johannes Berg @ 2013-08-20 21:03 UTC (permalink / raw)
  To: Eugene Krasnikov; +Cc: linux-wireless, wcn36xx
In-Reply-To: <1377020479-16935-12-git-send-email-k.eugene.e@gmail.com>

On Tue, 2013-08-20 at 19:41 +0200, Eugene Krasnikov wrote:

> +int wcn36xx_start_tx(struct wcn36xx *wcn,
> +		     struct wcn36xx_sta *sta_priv,
> +		     struct sk_buff *skb)

err ... this can return errors that you never handle, probably gets you
leaks that way?

johannes


^ permalink raw reply

* Re: [PATCH 11/16] wcn36xx: Add txrx.c
From: Johannes Berg @ 2013-08-20 21:01 UTC (permalink / raw)
  To: Eugene Krasnikov; +Cc: linux-wireless, wcn36xx
In-Reply-To: <1377020479-16935-12-git-send-email-k.eugene.e@gmail.com>

On Tue, 2013-08-20 at 19:41 +0200, Eugene Krasnikov wrote:

> +	/* Data frames served first*/
> +	if (is_low) {
> +		/*
> +		 * Sometimes in AP mode mac80211 is trying to send data
> +		 * frame to nobody. Why?
> +		 */
> +		if (!sta_priv)
> +			wcn36xx_warn("Sending data packet to nobody");

Umm, really? Have you heard of something called multicast? ;-)

johannes


^ permalink raw reply

* Re: [PATCH 01/16] wcn36xx: Add main.c
From: Johannes Berg @ 2013-08-20 20:59 UTC (permalink / raw)
  To: Eugene Krasnikov; +Cc: linux-wireless, wcn36xx
In-Reply-To: <1377020479-16935-2-git-send-email-k.eugene.e@gmail.com>

Just a cursory review ...


> +		.cap = IEEE80211_HT_CAP_GRN_FLD
> +			| IEEE80211_HT_CAP_SGI_20

wouldn't that usually be written as

GRN_FLD |
SGI_20 |
...

(multiple similar places)

> +#ifdef CONFIG_PM
> +
> +static const struct wiphy_wowlan_support wowlan_support = {
> +	.flags = WIPHY_WOWLAN_ANY,
> +	.n_patterns = 0,

that n_patterns is pretty useless.


> +#define WCN36XX_SUPPORTED_FILTERS (0)
> +
> +static void wcn36xx_configure_filter(struct ieee80211_hw *hw,
> +				       unsigned int changed,
> +				       unsigned int *total, u64 multicast)
> +{
> +	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac configure filter");
> +
> +	changed &= WCN36XX_SUPPORTED_FILTERS;

That's pointless

> +		if (IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags) {
> +			sta_priv->is_data_encrypted = true;
> +			/* Reconfigure bss with encrypt_type */
> +			if (NL80211_IFTYPE_STATION == vif->type)
> +				wcn36xx_smd_config_bss(wcn,
> +						       vif,
> +						       sta,
> +						       sta->addr,
> +						       true);

It seems to me this should not be here but you should have mac80211 set
something in e.g. bss_conf that indicates encryption?


> +	/* Not supported so far*/
> +	case IEEE80211_AMPDU_TX_STOP_CONT:
> +		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
> +		break;
> +	case IEEE80211_AMPDU_TX_STOP_FLUSH:
> +	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
> +		break;

You can't just "not support" them - you have to at least stop the
aggregation session, see the commit that introduced this.

> +	static const u32 cipher_suites[] = {
> +		WLAN_CIPHER_SUITE_TKIP,
> +		WLAN_CIPHER_SUITE_CCMP,
> +	};

You actually don't want to support WEP, not even in software? Otherwise
just leave this out and mac80211 will add it.

> +	wcn->hw->wiphy->iface_combinations = &if_comb;
> +	wcn->hw->wiphy->n_iface_combinations = 1;

Your code with "wcn->current_vif = " etc. *really* doesn't look like you
support combinations. Are you positive this is OK?

> +	wcn->hw->wiphy->max_scan_ssids = 1;

Really? You don't even have hardware scan, so why?

johannes


^ permalink raw reply

* Re: Signal loss rtl8723ae wifi driver
From: Phillip Moss @ 2013-08-20 20:50 UTC (permalink / raw)
  To: Larry Finger; +Cc: linux-wireless
In-Reply-To: <520AFD5C.3010905@lwfinger.net>

Hi Larry,
Sorry for taking so long to reply.
I am using Arch Linux  3.10.7-1-ARCH  x86_64 with KDE and Network-Manager.
wlp3s0 is the name of my wireless interface: https://wiki.archlinux.org/index.php/Network_Configuration#Network_Interfaces
I have renamed the interface to the default wlan0 we all know and love with: ln -s /dev/null /etc/udev/rules.d/80-net-name-slot.rules

To measure signal strength I am using "Link Quality", "Signal Level" from iwconfig and signal strength from network manager.

When I am right next to my router I get between: -36  and -42dbm.
Link quality is between 68/70 and 70/70.
Network Manager reports signal at 84%.

When a signal loss period ocurrs Link quality drops to 14/70 (In some cases 12-13) and then quickly jumps back up to 40 then up to 68-70.
While this happens Signal level bounces up to between +2 and +10dbm then backdown to around -90dbm and then stabalizes again at -36 -42.
Network Manager reports signal around 32%

If I step a few meters away signal level is stable around -52 and -64 dbm. Link Quality is around 56/70.
During a Signal loss period Link Quality jumps down to about 12-13/70 and Signal Level to around 14dbm with occasional spikes up to 99.
These spikes only sometimes result in the interface dropping the connection to the AP when at this distance, but never when I am very close to the router.

I am not sure if this is pure paranoia but it seems that the card gets “stuck” and then keeps on receiving/transmitting. To see if this was true I tried airodump and it does seem as if the card stops receiving beacons at irregular intervals.

I have recompiled backports with the proposed patch and I am still experiencing the same problem.
Thank you very much for all your help,
Phillip

--------------------------------------------
El mié, 14/8/13, Larry Finger <Larry.Finger@lwfinger.net> escribió:

 Asunto: Re: Signal loss rtl8723ae wifi driver
 Para: "Phillip Moss" <phillipmoss12@yahoo.es>
 CC: linux-wireless@vger.kernel.org
 Fecha: miércoles, 14 de agosto, 2013 05:45
 
 On 08/13/2013 11:23 AM, Phillip Moss
 wrote:
 > Hi all,
 > I have a rtl8723ae wifi card on my laptop. When
 connecting to any wifi Access Point
 > the wifi signal fluctuates from full strength to very
 low.  In order to connect and
 > stay connected I must be no farther than two meters
 from my router otherwise I get
 > disconnected. I have tried the kernel driver on
 multiple distros as well as the
 > vendor drivers for older kernel versions. All seem to
 have the same problem. The card
 > works ok on Windows 7 with vendor drivers. I have also
 tried compiling
 > backports-3.10-rc1-2 with no luck. During a signal loss
 period I get no logs but if I
 > take the laptop too far from the AP dmesg reports:
 
 Philip,
 
 Could you try the attached patch?
 
 Larry
 
 

^ permalink raw reply

* Re: [PATCH 3.10 0/3] Enable 7000 device family on 3.10
From: Emmanuel Grumbach @ 2013-08-20 20:22 UTC (permalink / raw)
  To: Greg KH
  Cc: Johannes Berg, Emmanuel Grumbach, stable@vger.kernel.org,
	linux-wireless
In-Reply-To: <20130806134218.GB525@kroah.com>

On Tue, Aug 6, 2013 at 4:42 PM, Greg KH <greg@kroah.com> wrote:
> On Tue, Aug 06, 2013 at 02:39:39PM +0200, Johannes Berg wrote:
>> [Emmanuel is on vacation, I'll cover for him]
>>
>> On Fri, 2013-08-02 at 17:02 +0800, Greg KH wrote:
>> > On Mon, Jul 15, 2013 at 02:44:57PM +0300, Emmanuel Grumbach wrote:
>> > > This small patch series enables 7260 and 3160 devices on 3.10
>> > > kernel. Three patches are already in linux.git (3.11-rc1).
>> > > One patch is 3.10 specific and disables configuration that is not
>> > > supported in 3.10.
>> >
>> > I need the git commit id of these patches in Linus's tree before I can
>> > apply them.  Please resend them with that information.
>>
>> The second and third patch does have it, and the first patch is only
>> relevant for 3.10 since 3.11 will have more device types enabled, we
>> just didn't get all the code in. This seems to be described in the
>> commit log, do you want more details?
>
> Yes, please resend them with those details.  For me to take a patch that
> is not in Linus's tree is a big deal, I need a whole lot of
> justification for it.
>

Just got back. Sorry for the delay.
I guess I will just drop that patch that is not in Linus's tree.
This patch disables a feature that is not likely to be used but we
*know* it is buggy.
So people who want more than just associating to their router will see
a bug in 3.10.
I guess we can leave with that since I was suggesting to disable the
feature anyway.

So - do you want to resend, or you can apply the 2 patches I sent as is?

^ permalink raw reply

* Re: [rt2x00-users] [PATCH 2/2] rt2x00: rt2800pci: fix AUX_CTRL register setup for RT3090/3390/3593/5592
From: Stanislaw Gruszka @ 2013-08-20 20:13 UTC (permalink / raw)
  To: Gabor Juhos; +Cc: John W. Linville, linux-wireless, users
In-Reply-To: <1376641410-20798-2-git-send-email-juhosg@openwrt.org>

On Fri, Aug 16, 2013 at 10:23:30AM +0200, Gabor Juhos wrote:
> The 2011_1007_RT5390_RT5392_Linux_STA_V2.5.0.3_DPO
> driver enables PCIe wakeup for these chips as well.
> Do the same in rt2x00.
> 
> References:
>   rt28xx_init in common/rtmp_init_intf.c
>   RTMPInitPCIeLinkCtrlValue in os/linux/rt_rbus_pci_drv.c
> 
> Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>


^ permalink raw reply

* Re: [rt2x00-users] [PATCH 1/2] rt2x00: rt2800lib: introduce rt2800_get_txwi_rxwi_size helper
From: Stanislaw Gruszka @ 2013-08-20 20:13 UTC (permalink / raw)
  To: Gabor Juhos; +Cc: John W. Linville, linux-wireless, users
In-Reply-To: <1376641410-20798-1-git-send-email-juhosg@openwrt.org>

On Fri, Aug 16, 2013 at 10:23:29AM +0200, Gabor Juhos wrote:
> The rt2800pci driver uses the same [RT]XWI size
> for all chipsets, however some chips requires
> different values.
> 
> The size of the [RT]XWI structures is a constant
> value for a given chipset and it does not depend
> on the underlying interface. Add a helper function
> which returns the correct values for the actual
> chipset and use the new helper both in the rt2800usb
> and in the rt2800pci drivers. This ensures that both
> drivers are using the correct values.
> 
> Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>


^ permalink raw reply

* [PATCH ] staging: vt6656: rxtx.c dead code TYPE_ATIMDMA/TYPE_BEACONDMA
From: Malcolm Priestley @ 2013-08-20 19:47 UTC (permalink / raw)
  To: gregkh; +Cc: linux-wireless

Both TYPE_ATIMDMA/TYPE_BEACONDMA are not used in driver for the value of uDMAIdx.

Remove dead code.

Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
---
 drivers/staging/vt6656/rxtx.c | 41 +++++++----------------------------------
 1 file changed, 7 insertions(+), 34 deletions(-)

diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index d7f920d..06950c4 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -499,22 +499,6 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
     }
 
     if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-	if ((uDMAIdx == TYPE_ATIMDMA) || (uDMAIdx == TYPE_BEACONDMA)) {
-		struct vnt_tx_datahead_ab *pBuf =
-			(struct vnt_tx_datahead_ab *)pTxDataHead;
-            //Get SignalField,ServiceField,Length
-            BBvCalculateParameter(pDevice, cbFrameLength, wCurrentRate, byPktType,
-                (u16 *)&(pBuf->wTransmitLength), (u8 *)&(pBuf->byServiceField), (u8 *)&(pBuf->bySignalField)
-            );
-            //Get Duration and TimeStampOff
-		pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_A,
-					byPktType, bNeedAck);
-            if(uDMAIdx!=TYPE_ATIMDMA) {
-                pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE];
-            }
-            return (pBuf->wDuration);
-        }
-        else { // DATA & MANAGE Frame
             if (byFBOption == AUTO_FB_NONE) {
 		struct vnt_tx_datahead_g *pBuf =
 				(struct vnt_tx_datahead_g *)pTxDataHead;
@@ -558,11 +542,9 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
                 pBuf->wTimeStampOff_b = wTimeStampOff[pDevice->byPreambleType%2][pDevice->byTopCCKBasicRate%MAX_RATE];
                 return (pBuf->wDuration_a);
             } //if (byFBOption == AUTO_FB_NONE)
-        }
     }
     else if (byPktType == PK_TYPE_11A) {
-        if ((byFBOption != AUTO_FB_NONE) && (uDMAIdx != TYPE_ATIMDMA) && (uDMAIdx != TYPE_BEACONDMA)) {
-            // Auto Fallback
+	if (byFBOption != AUTO_FB_NONE) {
 		struct vnt_tx_datahead_a_fb *pBuf =
 			(struct vnt_tx_datahead_a_fb *)pTxDataHead;
             //Get SignalField,ServiceField,Length
@@ -576,9 +558,7 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
 				DATADUR_A_F0, byPktType, bNeedAck);
 		pBuf->wDuration_f1 = (u16)s_uGetDataDuration(pDevice,
 				DATADUR_A_F1, byPktType, bNeedAck);
-            if(uDMAIdx!=TYPE_ATIMDMA) {
                 pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE];
-            }
             return (pBuf->wDuration);
         } else {
 		struct vnt_tx_datahead_ab *pBuf =
@@ -590,10 +570,8 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
             //Get Duration and TimeStampOff
 		pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_A,
 				byPktType, bNeedAck);
-
-            if(uDMAIdx!=TYPE_ATIMDMA) {
                 pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE];
-            }
+
             return (pBuf->wDuration);
         }
     }
@@ -607,9 +585,8 @@ static u32 s_uFillDataHead(struct vnt_private *pDevice,
             //Get Duration and TimeStampOff
 		pBuf->wDuration = (u16)s_uGetDataDuration(pDevice, DATADUR_B,
 				byPktType, bNeedAck);
-            if (uDMAIdx != TYPE_ATIMDMA) {
                 pBuf->wTimeStampOff = wTimeStampOff[pDevice->byPreambleType%2][wCurrentRate%MAX_RATE];
-            }
+
             return (pBuf->wDuration);
     }
     return 0;
@@ -826,8 +803,8 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
     }
 
     if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
-        if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) {
-            // Auto Fall back
+	if (byFBOption != AUTO_FB_NONE) {
+		/* Auto Fall back */
 		struct vnt_cts_fb *pBuf = (struct vnt_cts_fb *)pvCTS;
             //Get SignalField,ServiceField,Length
             BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
@@ -849,7 +826,7 @@ static void s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx,
 		pBuf->data.duration = pBuf->wDuration_ba;
 		pBuf->data.frame_control = TYPE_CTL_CTS;
 		memcpy(pBuf->data.ra, pDevice->abyCurrentNetAddr, ETH_ALEN);
-        } else { //if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA)
+	} else {
 		struct vnt_cts *pBuf = (struct vnt_cts *)pvCTS;
             //Get SignalField,ServiceField,Length
             BBvCalculateParameter(pDevice, uCTSFrameLen, pDevice->byTopCCKBasicRate, PK_TYPE_11B,
@@ -1462,11 +1439,7 @@ static void s_vGenerateMACHeader(struct vnt_private *pDevice,
 {
 	struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *)pbyBufferAddr;
 
-    if (uDMAIdx == TYPE_ATIMDMA) {
-    	pMACHeader->frame_control = TYPE_802_11_ATIM;
-    } else {
-        pMACHeader->frame_control = TYPE_802_11_DATA;
-    }
+	pMACHeader->frame_control = TYPE_802_11_DATA;
 
     if (pDevice->eOPMode == OP_MODE_AP) {
 	memcpy(&(pMACHeader->addr1[0]),
-- 
1.8.1.2


^ permalink raw reply related

* Re: [REGRESSION] 3.10.{6,7} crashes on network activity
From: Arend van Spriel @ 2013-08-20 19:04 UTC (permalink / raw)
  To: Felix Fietkau; +Cc: Linux Wireless List
In-Reply-To: <5213A926.8060306@openwrt.org>

On 08/20/2013 07:36 PM, Felix Fietkau wrote:
> On 2013-08-20 10:15 AM, Arend van Spriel wrote:
>> Hi Felix,
>>
>> I have been diving into root causing why brcmsmac can not handle cck
>> fallback rates, because it should. Maybe it is better to flag no cck
>> support and only change brcmsmac.
> I prefer having a flag to enable it over one to disable it, because it
> fits better with the existing flags. Also, future drivers may not always
> be properly prepared to handle CCK in A-MPDU sessions either.

Ok. It just looked a bit strange that a problem in brcmsmac results in 
changing other drivers.

> By the way, I took a short look at brcmsmac and found more issues that
> you should look into if you want to fix this.
>
> First of all, you should probably make sure that the hardware does not
> try to send an A-MPDU using a CCK rate (prepare it as a single frame in
> brcms_c_ampdu_add_frame). It also does not seem to have any checks to
> ensure that rate control probing frames are not aggregated.

Thanks, Felix. I also noticed that our proprietary driver has code in 
place for these scenarios.

Gr. AvS


^ permalink raw reply

* Re: [PATCH 12/12] brcmsmac: add support for BCM4313 iPA variant
From: Joe Perches @ 2013-08-20 18:30 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: John W. Linville, linux-wireless
In-Reply-To: <1377007246-9957-13-git-send-email-arend@broadcom.com>

On Tue, 2013-08-20 at 16:00 +0200, Arend van Spriel wrote:
> This patch completes the changes needed for supporting the
> iPA variant cards of the BCM4313 wireless chipset.
[]
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
[]
> @@ -1826,6 +1826,17 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
>  		write_radio_reg(pi, RADIO_2064_REG038, 3);
>  		write_radio_reg(pi, RADIO_2064_REG091, 7);
>  	}
> +
> +	if (!(pi->sh->boardflags & BFL_FEM)) {
> +		u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc,
> +			0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0};

static const would reduce the object size.

> +		write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
> +		write_radio_reg(pi, RADIO_2064_REG091, 0x3);
> +		write_radio_reg(pi, RADIO_2064_REG038, 0x3);
> +
> +		write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);

Does anything limit channel to < 15?

There seem to be an awful lot of magic numbers
in the patch.



^ permalink raw reply

* Re: [PATCH 09/16] wcn36xx: Add smd.c
From: Joe Perches @ 2013-08-20 18:12 UTC (permalink / raw)
  To: Eugene Krasnikov; +Cc: linux-wireless, wcn36xx
In-Reply-To: <1377020479-16935-10-git-send-email-k.eugene.e@gmail.com>

On Tue, 2013-08-20 at 19:41 +0200, Eugene Krasnikov wrote:

> diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
[]
> +int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
> +{
[]
> +		/* Add NV body itself */
> +		/* Rework me */
> +		memcpy(wcn->smd_buf + sizeof(msg_body),
> +		       (void *)(&nv_d->table) + fm_offset,
> +		       msg_body.nv_img_buffer_size);

Does this really do what you want?

Perhaps it should be:

		memcpy(wcn->smd_buf + sizeof(msg_body),
		       ((void *)&nv_d->table) + fm_offset,
		       msg_body.nv_img_buffer_size);




^ permalink raw reply

* Re: [PATCH 13/16] wcn36xx: Add wcn36xx.h
From: Joe Perches @ 2013-08-20 18:04 UTC (permalink / raw)
  To: Eugene Krasnikov; +Cc: linux-wireless, wcn36xx
In-Reply-To: <1377020479-16935-14-git-send-email-k.eugene.e@gmail.com>

On Tue, 2013-08-20 at 19:41 +0200, Eugene Krasnikov wrote:
> Adding wcn36xx.h
[]
> +#define DRIVER_PREFIX "wcn36xx: "
[]

I think you should use pr_fmt and/or netdev_<level>

> +#define wcn36xx_error(fmt, arg...) do {			\
> +	pr_err(DRIVER_PREFIX "ERROR " fmt "\n", ##arg);	\
> +	__WARN();					\
> +} while (0)

What value is there in this __WARN?

Please use _err rather than _error

> +#define wcn36xx_warn(fmt, arg...)				\
> +	pr_warn(DRIVER_PREFIX "WARNING " fmt "\n", ##arg)
> +
> +#define wcn36xx_info(fmt, arg...)		\
> +	pr_info(DRIVER_PREFIX fmt "\n", ##arg)
> +
> +#define wcn36xx_dbg(mask, fmt, arg...) do {			\
> +	if (debug_mask & mask)					\
> +		pr_debug(DRIVER_PREFIX fmt "\n", ##arg);	\
> +} while (0)
> +
> +#define wcn36xx_dbg_dump(mask, prefix_str, buf, len) do {	\
> +	if (debug_mask & mask)					\
> +		print_hex_dump(KERN_DEBUG, prefix_str,		\
> +			       DUMP_PREFIX_OFFSET, 32, 1,	\
> +			       buf, len, false);		\
> +} while (0)
> +

Please move the "\n" to the uses instead of the macro.
This would be consistent with all the other ath macros.



^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox