All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] wl12xx: move to new firmware (6.1.3.50.49)
@ 2011-01-27 19:54 Eliad Peller
  2011-01-27 19:54 ` [PATCH 1/4] wl12xx: mcp2.5 - add config_ps acx Eliad Peller
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Eliad Peller @ 2011-01-27 19:54 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

Make the wl12xx driver start working with the latest
wl12xx firmware (6.1.3.50.49).

The patchset only migrates exisiting functionality. 
(i.e. it doesn't contain the new firmware features)

Note that this new firmware is not backward compatible with the
current firmware, so a new firmware name is being used.

Eliad Peller (4):
  wl12xx: mcp2.5 - add config_ps acx
  wl12xx: move to new firmware (6.1.3.50.49)
  wl12xx: use the conf struct instead of macros for memory
    configuration
  wl12xx: set supported_rates after association

 drivers/net/wireless/wl12xx/acx.c    |   86 ++++++++++++++++++---
 drivers/net/wireless/wl12xx/acx.h    |   41 ++++++++---
 drivers/net/wireless/wl12xx/cmd.c    |   10 +-
 drivers/net/wireless/wl12xx/cmd.h    |   14 +---
 drivers/net/wireless/wl12xx/conf.h   |   49 ++++++++++++
 drivers/net/wireless/wl12xx/event.c  |   14 ----
 drivers/net/wireless/wl12xx/event.h  |    2 -
 drivers/net/wireless/wl12xx/init.c   |   13 +++
 drivers/net/wireless/wl12xx/main.c   |  139 +++++++++++++++++-----------------
 drivers/net/wireless/wl12xx/ps.c     |    6 +-
 drivers/net/wireless/wl12xx/rx.c     |    6 +-
 drivers/net/wireless/wl12xx/rx.h     |    2 +-
 drivers/net/wireless/wl12xx/tx.c     |   22 ------
 drivers/net/wireless/wl12xx/wl12xx.h |   31 +++++++-
 14 files changed, 279 insertions(+), 156 deletions(-)


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/4] wl12xx: mcp2.5 - add config_ps acx
  2011-01-27 19:54 [PATCH 0/4] wl12xx: move to new firmware (6.1.3.50.49) Eliad Peller
@ 2011-01-27 19:54 ` Eliad Peller
  2011-01-27 19:54 ` [PATCH 2/4] wl12xx: move to new firmware (6.1.3.50.49) Eliad Peller
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Eliad Peller @ 2011-01-27 19:54 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

mcp2.5 uses this acx to configure the fw only once, rather than
passing the params in every enter psm command.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/acx.c  |   30 ++++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/acx.h  |   11 +++++++++++
 drivers/net/wireless/wl12xx/conf.h |    8 ++++++++
 drivers/net/wireless/wl12xx/main.c |    1 +
 4 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index afdc601..84d94b2 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1476,3 +1476,33 @@ out:
 	kfree(acx);
 	return ret;
 }
+
+int wl1271_acx_config_ps(struct wl1271 *wl)
+{
+	struct wl1271_acx_config_ps *config_ps;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx config ps");
+
+	config_ps = kzalloc(sizeof(*config_ps), GFP_KERNEL);
+	if (!config_ps) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	config_ps->exit_retries = wl->conf.conn.psm_exit_retries;
+	config_ps->enter_retries = wl->conf.conn.psm_entry_retries;
+	config_ps->null_data_rate = cpu_to_le32(wl->basic_rate);
+
+	ret = wl1271_cmd_configure(wl, ACX_CONFIG_PS, config_ps,
+				   sizeof(*config_ps));
+
+	if (ret < 0) {
+		wl1271_warning("acx config ps failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(config_ps);
+	return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index c683801..ee67635 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -1136,6 +1136,15 @@ struct wl1271_acx_max_tx_retry {
 	u8 padding_1[2];
 } __packed;
 
+struct wl1271_acx_config_ps {
+	struct acx_header header;
+
+	u8 exit_retries;
+	u8 enter_retries;
+	u8 padding[2];
+	__le32 null_data_rate;
+}__packed;
+
 enum {
 	ACX_WAKE_UP_CONDITIONS      = 0x0002,
 	ACX_MEM_CFG                 = 0x0003,
@@ -1200,6 +1209,7 @@ enum {
 	DOT11_RTS_THRESHOLD         = 0x1013,
 	DOT11_GROUP_ADDRESS_TBL     = 0x1014,
 	ACX_PM_CONFIG               = 0x1016,
+	ACX_CONFIG_PS               = 0x1017,
 
 	MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL,
 
@@ -1269,5 +1279,6 @@ int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
 				       bool enable);
 int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
 int wl1271_acx_max_tx_retry(struct wl1271 *wl);
+int wl1271_acx_config_ps(struct wl1271 *wl);
 
 #endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index fd1dac9..c81aecd 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -960,6 +960,14 @@ struct conf_conn_settings {
 	u8 psm_entry_retries;
 
 	/*
+	 * Specifies the maximum number of times to try PSM exit if it fails
+	 * (if sending the appropriate null-func message fails.)
+	 *
+	 * Range 0 - 255
+	 */
+	u8 psm_exit_retries;
+
+	/*
 	 * Specifies the maximum number of times to try transmit the PSM entry
 	 * null-func frame for each PSM entry attempt
 	 *
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index dfab21e..ec82dd0 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -256,6 +256,7 @@ static struct conf_drv_settings default_conf = {
 		.bet_enable                  = CONF_BET_MODE_ENABLE,
 		.bet_max_consecutive         = 10,
 		.psm_entry_retries           = 5,
+		.psm_exit_retries            = 255,
 		.psm_entry_nullfunc_retries  = 3,
 		.psm_entry_hangover_period   = 1,
 		.keep_alive_interval         = 55000,
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] wl12xx: move to new firmware (6.1.3.50.49)
  2011-01-27 19:54 [PATCH 0/4] wl12xx: move to new firmware (6.1.3.50.49) Eliad Peller
  2011-01-27 19:54 ` [PATCH 1/4] wl12xx: mcp2.5 - add config_ps acx Eliad Peller
@ 2011-01-27 19:54 ` Eliad Peller
  2011-01-27 19:54 ` [PATCH 3/4] wl12xx: use the conf struct instead of macros for memory configuration Eliad Peller
  2011-01-27 19:54 ` [PATCH 4/4] wl12xx: set supported_rates after association Eliad Peller
  3 siblings, 0 replies; 7+ messages in thread
From: Eliad Peller @ 2011-01-27 19:54 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

This patch adds support for the new wl12xx firmware (Rev 6.1.3.50.49)

Since this fw is not backward compatible with previous fw versions,
a new fw (with different name) is being fetched.

(the patch is big because it contains all the required fw api changes.
splitting it into multiple patches will result in corrupted intermediate
commits)

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/acx.c    |   44 +++++++++++++++++++++++++++++----
 drivers/net/wireless/wl12xx/acx.h    |   26 +++++++++++++++----
 drivers/net/wireless/wl12xx/cmd.c    |   13 ++++++----
 drivers/net/wireless/wl12xx/cmd.h    |   14 +++-------
 drivers/net/wireless/wl12xx/conf.h   |   29 ++++++++++++++++++++++
 drivers/net/wireless/wl12xx/event.c  |   14 ----------
 drivers/net/wireless/wl12xx/event.h  |    2 -
 drivers/net/wireless/wl12xx/init.c   |   13 ++++++++++
 drivers/net/wireless/wl12xx/main.c   |   22 +++++++++++++----
 drivers/net/wireless/wl12xx/ps.c     |    6 +---
 drivers/net/wireless/wl12xx/rx.c     |    6 ++--
 drivers/net/wireless/wl12xx/rx.h     |    2 +-
 drivers/net/wireless/wl12xx/wl12xx.h |   31 ++++++++++++++++++++---
 13 files changed, 162 insertions(+), 60 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 84d94b2..f2fbda0 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -947,9 +947,9 @@ out:
 	return ret;
 }
 
-int wl1271_acx_mem_cfg(struct wl1271 *wl)
+int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
 {
-	struct wl1271_acx_config_memory *mem_conf;
+	struct wl1271_acx_ap_config_memory *mem_conf;
 	int ret;
 
 	wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
@@ -979,13 +979,45 @@ out:
 	return ret;
 }
 
-int wl1271_acx_init_mem_config(struct wl1271 *wl)
+int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
 {
+	struct wl1271_acx_sta_config_memory *mem_conf;
 	int ret;
 
-	ret = wl1271_acx_mem_cfg(wl);
-	if (ret < 0)
-		return ret;
+	wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
+
+	mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
+	if (!mem_conf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* memory config */
+	mem_conf->num_stations = DEFAULT_NUM_STATIONS;
+	mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS;
+	mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS;
+	mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES;
+	mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
+	mem_conf->dyn_mem_enable = wl->conf.mem.dynamic_memory;
+	mem_conf->tx_free_req = wl->conf.mem.min_req_tx_blocks;
+	mem_conf->rx_free_req = wl->conf.mem.min_req_rx_blocks;
+	mem_conf->tx_min = wl->conf.mem.tx_min;
+
+	ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
+				   sizeof(*mem_conf));
+	if (ret < 0) {
+		wl1271_warning("wl1271 mem config failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(mem_conf);
+	return ret;
+}
+
+int wl1271_acx_init_mem_config(struct wl1271 *wl)
+{
+	int ret;
 
 	wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map),
 				     GFP_KERNEL);
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index ee67635..c5b1e60 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -802,7 +802,7 @@ struct acx_tx_config_options {
 #define ACX_TX_DESCRIPTORS    32
 #define ACX_NUM_SSID_PROFILES 1
 
-struct wl1271_acx_config_memory {
+struct wl1271_acx_ap_config_memory {
 	struct acx_header header;
 
 	u8 rx_mem_block_num;
@@ -812,6 +812,20 @@ struct wl1271_acx_config_memory {
 	__le32 total_tx_descriptors;
 } __packed;
 
+struct wl1271_acx_sta_config_memory {
+	struct acx_header header;
+
+	u8 rx_mem_block_num;
+	u8 tx_min_mem_block_num;
+	u8 num_stations;
+	u8 num_ssid_profiles;
+	__le32 total_tx_descriptors;
+	u8 dyn_mem_enable;
+	u8 tx_free_req;
+	u8 rx_free_req;
+	u8 tx_min;
+} __packed;
+
 struct wl1271_acx_mem_map {
 	struct acx_header header;
 
@@ -1202,6 +1216,8 @@ enum {
 	ACX_HT_BSS_OPERATION        = 0x0058,
 	ACX_COEX_ACTIVITY           = 0x0059,
 	ACX_SET_DCO_ITRIM_PARAMS    = 0x0061,
+	ACX_GEN_FW_CMD              = 0x0070,
+	ACX_HOST_IF_CFG_BITMAP      = 0x0071,
 	ACX_MAX_TX_FAILURE          = 0x0072,
 	DOT11_RX_MSDU_LIFE_TIME     = 0x1004,
 	DOT11_CUR_TX_PWR            = 0x100D,
@@ -1210,10 +1226,7 @@ enum {
 	DOT11_GROUP_ADDRESS_TBL     = 0x1014,
 	ACX_PM_CONFIG               = 0x1016,
 	ACX_CONFIG_PS               = 0x1017,
-
-	MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL,
-
-	MAX_IE = 0xFFFF
+	ACX_CONFIG_HANGOVER         = 0x1018,
 };
 
 
@@ -1255,7 +1268,8 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
 		       u32 apsd_conf0, u32 apsd_conf1);
 int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold);
 int wl1271_acx_tx_config_options(struct wl1271 *wl);
-int wl1271_acx_mem_cfg(struct wl1271 *wl);
+int wl1271_acx_ap_mem_cfg(struct wl1271 *wl);
+int wl1271_acx_sta_mem_cfg(struct wl1271 *wl);
 int wl1271_acx_init_mem_config(struct wl1271 *wl);
 int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
 int wl1271_acx_smart_reflex(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 1bb8be5..66d15e7 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -286,6 +286,13 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
 	join->rx_filter_options = cpu_to_le32(wl->rx_filter);
 	join->bss_type = bss_type;
 	join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+	/*
+	 * for supported_rate_set, we should use wl->rate_set. however,
+	 * it seems that acx_rate_policies doesn't affect full_rate, and
+	 * since we want to avoid additional join, we'll use a 0xffffffff value,
+	 * and let the fw find the actual supported rates
+	 */
+	join->supported_rate_set = cpu_to_le32(0xffffffff);
 
 	if (wl->band == IEEE80211_BAND_5GHZ)
 		join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
@@ -454,7 +461,7 @@ out:
 	return ret;
 }
 
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
 {
 	struct wl1271_cmd_ps_params *ps_params = NULL;
 	int ret = 0;
@@ -468,10 +475,6 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
 	}
 
 	ps_params->ps_mode = ps_mode;
-	ps_params->send_null_data = send;
-	ps_params->retries = wl->conf.conn.psm_entry_nullfunc_retries;
-	ps_params->hang_over_period = wl->conf.conn.psm_entry_hangover_period;
-	ps_params->null_data_rate = cpu_to_le32(rates);
 
 	ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
 			      sizeof(*ps_params), 0);
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 7512814..54c12e7 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -39,7 +39,7 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
 int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send);
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
 int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
 			   size_t len);
 int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
@@ -140,6 +140,7 @@ enum cmd_templ {
 				  * For CTS-to-self (FastCTS) mechanism
 				  * for BT/WLAN coexistence (SoftGemini). */
 	CMD_TEMPL_ARP_RSP,
+	CMD_TEMPL_LINK_MEASUREMENT_REPORT,
 
 	/* AP-mode specific */
 	CMD_TEMPL_AP_BEACON = 13,
@@ -216,6 +217,7 @@ struct wl1271_cmd_join {
 	 * ACK or CTS frames).
 	 */
 	__le32 basic_rate_set;
+	__le32 supported_rate_set;
 	u8 dtim_interval;
 	/*
 	 * bits 0-2: This bitwise field specifies the type
@@ -278,15 +280,7 @@ struct wl1271_cmd_ps_params {
 	struct wl1271_cmd_header header;
 
 	u8 ps_mode; /* STATION_* */
-	u8 send_null_data; /* Do we have to send NULL data packet ? */
-	u8 retries; /* Number of retires for the initial NULL data packet */
-
-	 /*
-	  * TUs during which the target stays awake after switching
-	  * to power save mode.
-	  */
-	u8 hang_over_period;
-	__le32 null_data_rate;
+	u8 padding[3];
 } __packed;
 
 /* HW encryption keys */
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index c81aecd..d8c1249 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -1151,6 +1151,34 @@ struct conf_ht_setting {
 	u16 inactivity_timeout;
 };
 
+struct conf_memory_settings {
+	/* Disable/Enable dynamic memory */
+	u8 dynamic_memory;
+
+	/*
+	 * Minimum required free tx memory blocks in order to assure optimum
+	 * performence
+	 *
+	 * Range: 0-120
+	 */
+	u8 min_req_tx_blocks;
+
+	/*
+	 * Minimum required free rx memory blocks in order to assure optimum
+	 * performence
+	 *
+	 * Range: 0-120
+	 */
+	u8 min_req_rx_blocks;
+
+	/*
+	 * Minimum number of mem blocks (free+used) guaranteed for TX
+	 *
+	 * Range: 0-120
+	 */
+	u8 tx_min;
+};
+
 struct conf_drv_settings {
 	struct conf_sg_settings sg;
 	struct conf_rx_settings rx;
@@ -1162,6 +1190,7 @@ struct conf_drv_settings {
 	struct conf_scan_settings scan;
 	struct conf_rf_settings rf;
 	struct conf_ht_setting ht;
+	struct conf_memory_settings mem;
 };
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 3376a5d..1b170c5 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -135,20 +135,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
 		/* go to extremely low power mode */
 		wl1271_ps_elp_sleep(wl);
 		break;
-	case EVENT_EXIT_POWER_SAVE_FAIL:
-		wl1271_debug(DEBUG_PSM, "PSM exit failed");
-
-		if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
-			wl->psm_entry_retry = 0;
-			break;
-		}
-
-		/* make sure the firmware goes to active mode - the frame to
-		   be sent next will indicate to the AP, that we are active. */
-		ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
-					 wl->basic_rate, false);
-		break;
-	case EVENT_EXIT_POWER_SAVE_SUCCESS:
 	default:
 		break;
 	}
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index 1d5ef67..0e80886 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -75,8 +75,6 @@ enum {
 enum {
 	EVENT_ENTER_POWER_SAVE_FAIL = 0,
 	EVENT_ENTER_POWER_SAVE_SUCCESS,
-	EVENT_EXIT_POWER_SAVE_FAIL,
-	EVENT_EXIT_POWER_SAVE_SUCCESS,
 };
 
 struct event_debug_report {
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 70b3dc8..62dc983 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -325,6 +325,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
+	/* PS config */
+	ret = wl1271_acx_config_ps(wl);
+	if (ret < 0)
+		return ret;
+
 	ret = wl1271_sta_init_templates_config(wl);
 	if (ret < 0)
 		return ret;
@@ -367,6 +372,10 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
+	ret = wl1271_acx_sta_mem_cfg(wl);
+	if (ret < 0)
+		return ret;
+
 	return 0;
 }
 
@@ -433,6 +442,10 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
+	ret = wl1271_acx_ap_mem_cfg(wl);
+	if (ret < 0)
+		return ret;
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index ec82dd0..c8fe2b0 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -298,6 +298,12 @@ static struct conf_drv_settings default_conf = {
 		.tx_ba_win_size = 64,
 		.inactivity_timeout = 10000,
 	},
+	.mem = {
+		.dynamic_memory               = 0,
+		.min_req_tx_blocks            = 104,
+		.min_req_rx_blocks            = 22,
+		.tx_min                       = 27,
+	}
 };
 
 static void __wl1271_op_remove_interface(struct wl1271 *wl);
@@ -524,13 +530,19 @@ static int wl1271_plt_init(struct wl1271 *wl)
 }
 
 static void wl1271_fw_status(struct wl1271 *wl,
-			     struct wl1271_fw_status *status)
+			     struct wl1271_fw_full_status *full_status)
 {
+	struct wl1271_fw_common_status *status = &full_status->common;
 	struct timespec ts;
 	u32 total = 0;
 	int i;
 
-	wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		wl1271_raw_read(wl, FW_STATUS_ADDR, status,
+				sizeof(struct wl1271_fw_ap_status), false);
+	else
+		wl1271_raw_read(wl, FW_STATUS_ADDR, status,
+				sizeof(struct wl1271_fw_sta_status), false);
 
 	wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
 		     "drv_rx_counter = %d, tx_results_counter = %d)",
@@ -589,7 +601,7 @@ static void wl1271_irq_work(struct work_struct *work)
 		loopcount--;
 
 		wl1271_fw_status(wl, wl->fw_status);
-		intr = le32_to_cpu(wl->fw_status->intr);
+		intr = le32_to_cpu(wl->fw_status->common.intr);
 		if (!intr) {
 			wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
 			spin_lock_irqsave(&wl->wl_lock, flags);
@@ -611,7 +623,7 @@ static void wl1271_irq_work(struct work_struct *work)
 			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
 
 			/* check for tx results */
-			if (wl->fw_status->tx_results_counter !=
+			if (wl->fw_status->common.tx_results_counter !=
 			    (wl->tx_results_count & 0xff))
 				wl1271_tx_complete(wl);
 
@@ -625,7 +637,7 @@ static void wl1271_irq_work(struct work_struct *work)
 				wl1271_tx_work_locked(wl);
 			}
 
-			wl1271_rx(wl, wl->fw_status);
+			wl1271_rx(wl, &wl->fw_status->common);
 		}
 
 		if (intr & WL1271_ACX_INTR_EVENT_A) {
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 60a3738..2d3086a 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -139,8 +139,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
 			return ret;
 		}
 
-		ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE,
-					 rates, send);
+		ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
 		if (ret < 0)
 			return ret;
 
@@ -163,8 +162,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
 		if (ret < 0)
 			return ret;
 
-		ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE,
-					 rates, send);
+		ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index d9f80c4..029597b 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -29,14 +29,14 @@
 #include "rx.h"
 #include "io.h"
 
-static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status,
+static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status,
 				  u32 drv_rx_counter)
 {
 	return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
 		RX_MEM_BLOCK_MASK;
 }
 
-static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status,
+static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status,
 				 u32 drv_rx_counter)
 {
 	return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
@@ -134,7 +134,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
 	return 0;
 }
 
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
+void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
 {
 	struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
 	u32 buf_size;
diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h
index 8d048b3..4cef8fa 100644
--- a/drivers/net/wireless/wl12xx/rx.h
+++ b/drivers/net/wireless/wl12xx/rx.h
@@ -119,7 +119,7 @@ struct wl1271_rx_descriptor {
 	u8  reserved;
 } __packed;
 
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status);
+void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status);
 u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
 void wl1271_set_default_filters(struct wl1271 *wl);
 
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index ed245c2..39adcdf 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -130,7 +130,7 @@ extern u32 wl12xx_debug_level;
 
 
 
-#define WL1271_FW_NAME "wl1271-fw.bin"
+#define WL1271_FW_NAME "wl1271-fw-2.bin"
 #define WL1271_AP_FW_NAME "wl1271-fw-ap.bin"
 
 #define WL1271_NVS_NAME "wl1271-nvs.bin"
@@ -214,8 +214,8 @@ struct wl1271_stats {
 /* Broadcast and Global links + links to stations */
 #define AP_MAX_LINKS               (AP_MAX_STATIONS + 2)
 
-/* FW status registers */
-struct wl1271_fw_status {
+/* FW status registers common for AP/STA */
+struct wl1271_fw_common_status {
 	__le32 intr;
 	u8  fw_rx_counter;
 	u8  drv_rx_counter;
@@ -224,6 +224,11 @@ struct wl1271_fw_status {
 	__le32 rx_pkt_descs[NUM_RX_PKT_DESC];
 	__le32 tx_released_blks[NUM_TX_QUEUES];
 	__le32 fw_localtime;
+} __packed;
+
+/* FW status registers for AP */
+struct wl1271_fw_ap_status {
+	struct wl1271_fw_common_status common;
 
 	/* Next fields valid only in AP FW */
 
@@ -238,6 +243,24 @@ struct wl1271_fw_status {
 	u8 padding_1[1];
 } __packed;
 
+/* FW status registers for STA */
+struct wl1271_fw_sta_status {
+	struct wl1271_fw_common_status common;
+
+	u8  tx_total;
+	u8  reserved1;
+	__le16 reserved2;
+} __packed;
+
+struct wl1271_fw_full_status {
+	union {
+		struct wl1271_fw_common_status common;
+		struct wl1271_fw_sta_status sta;
+		struct wl1271_fw_ap_status ap;
+	};
+} __packed;
+
+
 struct wl1271_rx_mem_pool_addr {
 	u32 addr;
 	u32 addr_extra;
@@ -445,7 +468,7 @@ struct wl1271 {
 	u32 buffer_cmd;
 	u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
 
-	struct wl1271_fw_status *fw_status;
+	struct wl1271_fw_full_status *fw_status;
 	struct wl1271_tx_hw_res_if *tx_res_if;
 
 	struct ieee80211_vif *vif;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] wl12xx: use the conf struct instead of macros for memory configuration
  2011-01-27 19:54 [PATCH 0/4] wl12xx: move to new firmware (6.1.3.50.49) Eliad Peller
  2011-01-27 19:54 ` [PATCH 1/4] wl12xx: mcp2.5 - add config_ps acx Eliad Peller
  2011-01-27 19:54 ` [PATCH 2/4] wl12xx: move to new firmware (6.1.3.50.49) Eliad Peller
@ 2011-01-27 19:54 ` Eliad Peller
  2011-01-27 19:54 ` [PATCH 4/4] wl12xx: set supported_rates after association Eliad Peller
  3 siblings, 0 replies; 7+ messages in thread
From: Eliad Peller @ 2011-01-27 19:54 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

make the configuration management more flexible by using the
conf struct, rather than predefined macros.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/acx.c  |   16 ++++++++--------
 drivers/net/wireless/wl12xx/acx.h  |    4 ----
 drivers/net/wireless/wl12xx/conf.h |   12 ++++++++++++
 drivers/net/wireless/wl12xx/main.c |    4 ++++
 4 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index f2fbda0..6ea19d7 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -961,10 +961,10 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
 	}
 
 	/* memory config */
-	mem_conf->num_stations = DEFAULT_NUM_STATIONS;
-	mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS;
-	mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS;
-	mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES;
+	mem_conf->num_stations = wl->conf.mem.num_stations;
+	mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num;
+	mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num;
+	mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles;
 	mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
 
 	ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
@@ -993,10 +993,10 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
 	}
 
 	/* memory config */
-	mem_conf->num_stations = DEFAULT_NUM_STATIONS;
-	mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS;
-	mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS;
-	mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES;
+	mem_conf->num_stations = wl->conf.mem.num_stations;
+	mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num;
+	mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num;
+	mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles;
 	mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
 	mem_conf->dyn_mem_enable = wl->conf.mem.dynamic_memory;
 	mem_conf->tx_free_req = wl->conf.mem.min_req_tx_blocks;
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index c5b1e60..beb5f30 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -133,7 +133,6 @@ enum {
 
 #define DEFAULT_UCAST_PRIORITY          0
 #define DEFAULT_RX_Q_PRIORITY           0
-#define DEFAULT_NUM_STATIONS            1
 #define DEFAULT_RXQ_PRIORITY            0 /* low 0 .. 15 high  */
 #define DEFAULT_RXQ_TYPE                0x07    /* All frames, Data/Ctrl/Mgmt */
 #define TRACE_BUFFER_MAX_SIZE           256
@@ -797,10 +796,7 @@ struct acx_tx_config_options {
 	__le16 tx_compl_threshold;   /* number of packets */
 } __packed;
 
-#define ACX_RX_MEM_BLOCKS     70
-#define ACX_TX_MIN_MEM_BLOCKS 40
 #define ACX_TX_DESCRIPTORS    32
-#define ACX_NUM_SSID_PROFILES 1
 
 struct wl1271_acx_ap_config_memory {
 	struct acx_header header;
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index d8c1249..856a8a2 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -1152,6 +1152,18 @@ struct conf_ht_setting {
 };
 
 struct conf_memory_settings {
+	/* Number of stations supported in IBSS mode */
+	u8 num_stations;
+
+	/* Number of ssid profiles used in IBSS mode */
+	u8 ssid_profiles;
+
+	/* Number of memory buffers allocated to rx pool */
+	u8 rx_block_num;
+
+	/* Minimum number of blocks allocated to tx pool */
+	u8 tx_min_block_num;
+
 	/* Disable/Enable dynamic memory */
 	u8 dynamic_memory;
 
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index c8fe2b0..0f6786d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -299,6 +299,10 @@ static struct conf_drv_settings default_conf = {
 		.inactivity_timeout = 10000,
 	},
 	.mem = {
+		.num_stations                 = 1,
+		.ssid_profiles                = 1,
+		.rx_block_num                 = 70,
+		.tx_min_block_num             = 40,
 		.dynamic_memory               = 0,
 		.min_req_tx_blocks            = 104,
 		.min_req_rx_blocks            = 22,
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] wl12xx: set supported_rates after association
  2011-01-27 19:54 [PATCH 0/4] wl12xx: move to new firmware (6.1.3.50.49) Eliad Peller
                   ` (2 preceding siblings ...)
  2011-01-27 19:54 ` [PATCH 3/4] wl12xx: use the conf struct instead of macros for memory configuration Eliad Peller
@ 2011-01-27 19:54 ` Eliad Peller
  2011-01-28  6:00   ` Juuso Oikarinen
  2011-01-28  6:51   ` Arik Nemtsov
  3 siblings, 2 replies; 7+ messages in thread
From: Eliad Peller @ 2011-01-27 19:54 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless, Juuso Oikarinen

Instead of looking for supported_rates change on every tx packet,
just extract the supported_rates after association completes (station only).

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/acx.c  |    4 +
 drivers/net/wireless/wl12xx/cmd.c  |   11 +--
 drivers/net/wireless/wl12xx/main.c |  112 +++++++++++++++---------------------
 drivers/net/wireless/wl12xx/tx.c   |   22 -------
 4 files changed, 54 insertions(+), 95 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 6ea19d7..33840d9 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -783,6 +783,10 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
 
 	acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
 
+	wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
+		acx->rate_class[ACX_TX_BASIC_RATE].enabled_rates,
+		acx->rate_class[ACX_TX_AP_FULL_RATE].enabled_rates);
+
 	ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("Setting of rate policies failed: %d", ret);
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 66d15e7..97ffd7a 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -286,13 +286,7 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
 	join->rx_filter_options = cpu_to_le32(wl->rx_filter);
 	join->bss_type = bss_type;
 	join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
-	/*
-	 * for supported_rate_set, we should use wl->rate_set. however,
-	 * it seems that acx_rate_policies doesn't affect full_rate, and
-	 * since we want to avoid additional join, we'll use a 0xffffffff value,
-	 * and let the fw find the actual supported rates
-	 */
-	join->supported_rate_set = cpu_to_le32(0xffffffff);
+	join->supported_rate_set = cpu_to_le32(wl->rate_set);
 
 	if (wl->band == IEEE80211_BAND_5GHZ)
 		join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
@@ -310,6 +304,9 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
 	wl->tx_security_last_seq = 0;
 	wl->tx_security_seq = 0;
 
+	wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x",
+		join->basic_rate_set, join->supported_rate_set);
+
 	ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0);
 	if (ret < 0) {
 		wl1271_error("failed to initiate cmd join");
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 0f6786d..57f4553 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -978,39 +978,10 @@ int wl1271_plt_stop(struct wl1271 *wl)
 static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct wl1271 *wl = hw->priv;
-	struct ieee80211_conf *conf = &hw->conf;
-	struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
-	struct ieee80211_sta *sta = txinfo->control.sta;
 	unsigned long flags;
 	int q;
 
-	/*
-	 * peek into the rates configured in the STA entry.
-	 * The rates set after connection stage, The first block only BG sets:
-	 * the compare is for bit 0-16 of sta_rate_set. The second block add
-	 * HT rates in case of HT supported.
-	 */
 	spin_lock_irqsave(&wl->wl_lock, flags);
-	if (sta &&
-	    (sta->supp_rates[conf->channel->band] !=
-	    (wl->sta_rate_set & HW_BG_RATES_MASK)) &&
-		wl->bss_type != BSS_TYPE_AP_BSS) {
-		wl->sta_rate_set = sta->supp_rates[conf->channel->band];
-		set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
-	}
-
-#ifdef CONFIG_WL12XX_HT
-	if (sta &&
-	    sta->ht_cap.ht_supported &&
-	    ((wl->sta_rate_set >> HW_HT_RATES_OFFSET) !=
-	      sta->ht_cap.mcs.rx_mask[0])) {
-		/* Clean MCS bits before setting them */
-		wl->sta_rate_set &= HW_BG_RATES_MASK;
-		wl->sta_rate_set |=
-			(sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
-		set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
-	}
-#endif
 	wl->tx_queue_count++;
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
@@ -2246,6 +2217,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 {
 	bool do_join = false, set_assoc = false;
 	bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
+	u32 sta_rate_set = 0;
 	int ret;
 	struct ieee80211_sta *sta;
 
@@ -2311,6 +2283,46 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 		}
 	}
 
+	rcu_read_lock();
+	sta = ieee80211_find_sta(vif, bss_conf->bssid);
+	if (sta)  {
+		/* save the supp_rates of the ap */
+		sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band];
+
+		/* handle new association with HT and HT information change */
+		if ((changed & BSS_CHANGED_HT) &&
+		    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+			ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap,
+							     true);
+			if (ret < 0) {
+				wl1271_warning("Set ht cap true failed %d",
+					       ret);
+				rcu_read_unlock();
+				goto out;
+			}
+			ret = wl1271_acx_set_ht_information(wl,
+						bss_conf->ht_operation_mode);
+			if (ret < 0) {
+				wl1271_warning("Set ht information failed %d",
+					       ret);
+				rcu_read_unlock();
+				goto out;
+			}
+		}
+		/* handle new association without HT and disassociation */
+		else if (changed & BSS_CHANGED_ASSOC) {
+			ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap,
+							     false);
+			if (ret < 0) {
+				wl1271_warning("Set ht cap false failed %d",
+					       ret);
+				rcu_read_unlock();
+				goto out;
+			}
+		}
+	}
+	rcu_read_unlock();
+
 	if ((changed & BSS_CHANGED_ASSOC)) {
 		if (bss_conf->assoc) {
 			u32 rates;
@@ -2328,6 +2340,11 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 			wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
 									 rates);
 			wl->basic_rate = wl1271_tx_min_rate_get(wl);
+			if (sta_rate_set) {
+				wl->sta_rate_set = sta_rate_set;
+				wl->rate_set = wl1271_tx_enabled_rates_get(wl,
+								sta_rate_set);
+			}
 			ret = wl1271_acx_sta_rate_policies(wl);
 			if (ret < 0)
 				goto out;
@@ -2406,43 +2423,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 	if (ret < 0)
 		goto out;
 
-	rcu_read_lock();
-	sta = ieee80211_find_sta(vif, bss_conf->bssid);
-	if (sta)  {
-		/* handle new association with HT and HT information change */
-		if ((changed & BSS_CHANGED_HT) &&
-		    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
-			ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap,
-							     true);
-			if (ret < 0) {
-				wl1271_warning("Set ht cap true failed %d",
-					       ret);
-				rcu_read_unlock();
-				goto out;
-			}
-			ret = wl1271_acx_set_ht_information(wl,
-						bss_conf->ht_operation_mode);
-			if (ret < 0) {
-				wl1271_warning("Set ht information failed %d",
-					       ret);
-				rcu_read_unlock();
-				goto out;
-			}
-		}
-		/* handle new association without HT and disassociation */
-		else if (changed & BSS_CHANGED_ASSOC) {
-			ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap,
-							     false);
-			if (ret < 0) {
-				wl1271_warning("Set ht cap false failed %d",
-					       ret);
-				rcu_read_unlock();
-				goto out;
-			}
-		}
-	}
-	rcu_read_unlock();
-
 	if (changed & BSS_CHANGED_ARP_FILTER) {
 		__be32 addr = bss_conf->arp_addr_list[0];
 		WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 3507c81..67a0094 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -334,35 +334,13 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
 {
 	struct sk_buff *skb;
 	bool woken_up = false;
-	u32 sta_rates = 0;
 	u32 buf_offset = 0;
 	bool sent_packets = false;
 	int ret;
 
-	/* check if the rates supported by the AP have changed */
-	if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED,
-					&wl->flags))) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&wl->wl_lock, flags);
-		sta_rates = wl->sta_rate_set;
-		spin_unlock_irqrestore(&wl->wl_lock, flags);
-	}
-
 	if (unlikely(wl->state == WL1271_STATE_OFF))
 		goto out;
 
-	/* if rates have changed, re-configure the rate policy */
-	if (unlikely(sta_rates)) {
-		ret = wl1271_ps_elp_wakeup(wl, false);
-		if (ret < 0)
-			goto out;
-		woken_up = true;
-
-		wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
-		wl1271_acx_sta_rate_policies(wl);
-	}
-
 	while ((skb = wl1271_skb_dequeue(wl))) {
 		if (!woken_up) {
 			ret = wl1271_ps_elp_wakeup(wl, false);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 4/4] wl12xx: set supported_rates after association
  2011-01-27 19:54 ` [PATCH 4/4] wl12xx: set supported_rates after association Eliad Peller
@ 2011-01-28  6:00   ` Juuso Oikarinen
  2011-01-28  6:51   ` Arik Nemtsov
  1 sibling, 0 replies; 7+ messages in thread
From: Juuso Oikarinen @ 2011-01-28  6:00 UTC (permalink / raw)
  To: ext Eliad Peller; +Cc: Luciano Coelho, linux-wireless

On Thu, 2011-01-27 at 21:54 +0200, ext Eliad Peller wrote:
> Instead of looking for supported_rates change on every tx packet,
> just extract the supported_rates after association completes (station only).
> 
> Signed-off-by: Eliad Peller <eliad@wizery.com>
> ---
>  

A very good change (and optimization.) This is how it should have been
from the beginning (but there was something with the old mac80211 stack
we used at the time of implementing this that created some issue.)

However, looks good to me:

Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>

-Juuso


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 4/4] wl12xx: set supported_rates after association
  2011-01-27 19:54 ` [PATCH 4/4] wl12xx: set supported_rates after association Eliad Peller
  2011-01-28  6:00   ` Juuso Oikarinen
@ 2011-01-28  6:51   ` Arik Nemtsov
  1 sibling, 0 replies; 7+ messages in thread
From: Arik Nemtsov @ 2011-01-28  6:51 UTC (permalink / raw)
  To: Eliad Peller; +Cc: Luciano Coelho, linux-wireless, Juuso Oikarinen

On Thu, Jan 27, 2011 at 21:54, Eliad Peller <eliad@wizery.com> wrote:
> Instead of looking for supported_rates change on every tx packet,
> just extract the supported_rates after association completes (station only).
>
> Signed-off-by: Eliad Peller <eliad@wizery.com>
> ---
>  drivers/net/wireless/wl12xx/acx.c  |    4 +
>  drivers/net/wireless/wl12xx/cmd.c  |   11 +--
>  drivers/net/wireless/wl12xx/main.c |  112 +++++++++++++++---------------------
>  drivers/net/wireless/wl12xx/tx.c   |   22 -------
>  4 files changed, 54 insertions(+), 95 deletions(-)
>
> diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
> index 6ea19d7..33840d9 100644
> --- a/drivers/net/wireless/wl12xx/acx.c
> +++ b/drivers/net/wireless/wl12xx/acx.c
> @@ -783,6 +783,10 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
>
>        acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
>
> +       wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
> +               acx->rate_class[ACX_TX_BASIC_RATE].enabled_rates,
> +               acx->rate_class[ACX_TX_AP_FULL_RATE].enabled_rates);
> +
>        ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
>        if (ret < 0) {
>                wl1271_warning("Setting of rate policies failed: %d", ret);
> diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
> index 66d15e7..97ffd7a 100644
> --- a/drivers/net/wireless/wl12xx/cmd.c
> +++ b/drivers/net/wireless/wl12xx/cmd.c
> @@ -286,13 +286,7 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
>        join->rx_filter_options = cpu_to_le32(wl->rx_filter);
>        join->bss_type = bss_type;
>        join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
> -       /*
> -        * for supported_rate_set, we should use wl->rate_set. however,
> -        * it seems that acx_rate_policies doesn't affect full_rate, and
> -        * since we want to avoid additional join, we'll use a 0xffffffff value,
> -        * and let the fw find the actual supported rates
> -        */
> -       join->supported_rate_set = cpu_to_le32(0xffffffff);
> +       join->supported_rate_set = cpu_to_le32(wl->rate_set);
>
>        if (wl->band == IEEE80211_BAND_5GHZ)
>                join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
> @@ -310,6 +304,9 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
>        wl->tx_security_last_seq = 0;
>        wl->tx_security_seq = 0;
>
> +       wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x",
> +               join->basic_rate_set, join->supported_rate_set);
> +
>        ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0);
>        if (ret < 0) {
>                wl1271_error("failed to initiate cmd join");
> diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
> index 0f6786d..57f4553 100644
> --- a/drivers/net/wireless/wl12xx/main.c
> +++ b/drivers/net/wireless/wl12xx/main.c
> @@ -978,39 +978,10 @@ int wl1271_plt_stop(struct wl1271 *wl)
>  static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
>  {
>        struct wl1271 *wl = hw->priv;
> -       struct ieee80211_conf *conf = &hw->conf;
> -       struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
> -       struct ieee80211_sta *sta = txinfo->control.sta;
>        unsigned long flags;
>        int q;
>
> -       /*
> -        * peek into the rates configured in the STA entry.
> -        * The rates set after connection stage, The first block only BG sets:
> -        * the compare is for bit 0-16 of sta_rate_set. The second block add
> -        * HT rates in case of HT supported.
> -        */
>        spin_lock_irqsave(&wl->wl_lock, flags);
> -       if (sta &&
> -           (sta->supp_rates[conf->channel->band] !=
> -           (wl->sta_rate_set & HW_BG_RATES_MASK)) &&
> -               wl->bss_type != BSS_TYPE_AP_BSS) {
> -               wl->sta_rate_set = sta->supp_rates[conf->channel->band];
> -               set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
> -       }
> -
> -#ifdef CONFIG_WL12XX_HT
> -       if (sta &&
> -           sta->ht_cap.ht_supported &&
> -           ((wl->sta_rate_set >> HW_HT_RATES_OFFSET) !=
> -             sta->ht_cap.mcs.rx_mask[0])) {
> -               /* Clean MCS bits before setting them */
> -               wl->sta_rate_set &= HW_BG_RATES_MASK;
> -               wl->sta_rate_set |=
> -                       (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
> -               set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
> -       }
> -#endif
>        wl->tx_queue_count++;
>        spin_unlock_irqrestore(&wl->wl_lock, flags);
>
> @@ -2246,6 +2217,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
>  {
>        bool do_join = false, set_assoc = false;
>        bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
> +       u32 sta_rate_set = 0;
>        int ret;
>        struct ieee80211_sta *sta;
>
> @@ -2311,6 +2283,46 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
>                }
>        }
>
> +       rcu_read_lock();
> +       sta = ieee80211_find_sta(vif, bss_conf->bssid);
> +       if (sta)  {
> +               /* save the supp_rates of the ap */
> +               sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band];
> +
> +               /* handle new association with HT and HT information change */
> +               if ((changed & BSS_CHANGED_HT) &&
> +                   (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
> +                       ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap,
> +                                                            true);
> +                       if (ret < 0) {
> +                               wl1271_warning("Set ht cap true failed %d",
> +                                              ret);
> +                               rcu_read_unlock();
> +                               goto out;
> +                       }
> +                       ret = wl1271_acx_set_ht_information(wl,
> +                                               bss_conf->ht_operation_mode);
> +                       if (ret < 0) {
> +                               wl1271_warning("Set ht information failed %d",
> +                                              ret);
> +                               rcu_read_unlock();
> +                               goto out;

Perhaps its better to also save sta->ht_cap locally and
rcu_read_unlock() immediately? Seems to me wl1271_acx_set_ht_*()
functions might block.

Arik

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-01-28  6:51 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-27 19:54 [PATCH 0/4] wl12xx: move to new firmware (6.1.3.50.49) Eliad Peller
2011-01-27 19:54 ` [PATCH 1/4] wl12xx: mcp2.5 - add config_ps acx Eliad Peller
2011-01-27 19:54 ` [PATCH 2/4] wl12xx: move to new firmware (6.1.3.50.49) Eliad Peller
2011-01-27 19:54 ` [PATCH 3/4] wl12xx: use the conf struct instead of macros for memory configuration Eliad Peller
2011-01-27 19:54 ` [PATCH 4/4] wl12xx: set supported_rates after association Eliad Peller
2011-01-28  6:00   ` Juuso Oikarinen
2011-01-28  6:51   ` Arik Nemtsov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.