From 65cddbf1353212f8ab00c6084e3063d85c419201 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Tue, 24 Aug 2010 06:28:03 +0300 Subject: wl1271: Reduce rate used for last PSM entry attempt This patch reduces the rate of the null-func used to enter PSM on the last retry as precaution. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/wl1271_event.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_event.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 25ce2cd5e3f..bced8296a25 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -52,7 +52,7 @@ void wl1271_pspoll_work(struct work_struct *work) * delivery failure occurred, and no-one changed state since, so * we should go back to powersave. */ - wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, true); + wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true); out: mutex_unlock(&wl->mutex); @@ -70,7 +70,8 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl) /* force active mode receive data from the AP */ if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { - ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, true); + ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, + wl->basic_rate, true); if (ret < 0) return; set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); @@ -91,6 +92,8 @@ static int wl1271_event_ps_report(struct wl1271 *wl, bool *beacon_loss) { int ret = 0; + u32 total_retries = wl->conf.conn.psm_entry_retries; + u32 rates; wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status); @@ -104,10 +107,14 @@ static int wl1271_event_ps_report(struct wl1271 *wl, break; } - if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) { + if (wl->psm_entry_retry < total_retries) { wl->psm_entry_retry++; + if (wl->psm_entry_retry == total_retries) + rates = wl->basic_rate; + else + rates = wl->basic_rate_set; ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, - true); + rates, true); } else { wl1271_info("No ack to nullfunc from AP."); wl->psm_entry_retry = 0; @@ -143,7 +150,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, /* 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, - false); + wl->basic_rate, false); break; case EVENT_EXIT_POWER_SAVE_SUCCESS: default: -- cgit v1.2.3-70-g09d2 From 8c7f4f3166e16bb350bfc53955ea6cf9bfd34aab Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Tue, 21 Sep 2010 06:23:29 +0200 Subject: wl1271: Fix work cancelling when shutting down the driver The work cancelling has had several hazards, ranging from potentially executing work after the driver is in OFF state, to executing work after the driver and relevant memory structures are already removed. Fix these. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/wl1271_event.c | 3 +++ drivers/net/wireless/wl12xx/wl1271_main.c | 3 +++ drivers/net/wireless/wl12xx/wl1271_ps.c | 3 +++ 3 files changed, 9 insertions(+) (limited to 'drivers/net/wireless/wl12xx/wl1271_event.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index bced8296a25..e6c839af903 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -41,6 +41,9 @@ void wl1271_pspoll_work(struct work_struct *work) mutex_lock(&wl->mutex); + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags)) goto out; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 0026e775bb0..9ab4fc4f7b4 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -792,6 +792,8 @@ int wl1271_plt_stop(struct wl1271 *wl) out: mutex_unlock(&wl->mutex); + cancel_work_sync(&wl->irq_work); + return ret; } @@ -995,6 +997,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, cancel_work_sync(&wl->irq_work); cancel_work_sync(&wl->tx_work); cancel_delayed_work_sync(&wl->pspoll_work); + cancel_delayed_work_sync(&wl->elp_work); mutex_lock(&wl->mutex); diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index f75668e413f..150dc674d8b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c @@ -39,6 +39,9 @@ void wl1271_elp_work(struct work_struct *work) mutex_lock(&wl->mutex); + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || (!test_bit(WL1271_FLAG_PSM, &wl->flags) && !test_bit(WL1271_FLAG_IDLE, &wl->flags))) -- cgit v1.2.3-70-g09d2 From 8eab7b4708b5ef4701ecbe5d659f99743b77b668 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 24 Sep 2010 03:10:11 +0200 Subject: wl1271: Increase connection reliability This patch improves connection reliability by choosing the lowest basic rate for null-func frames (which increases their range, as the firmware does not do rate fall-back for null-func frames.) Also, increase the PSM entry retry-counter. Signed-off-by: Juuso Oikarinen Reviewed-by: Teemu Paasikivi Tested-by: Tuomas Katila Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/wl1271_cmd.c | 10 +++++----- drivers/net/wireless/wl12xx/wl1271_conf.h | 16 ++++++++++++++++ drivers/net/wireless/wl12xx/wl1271_event.c | 7 +------ drivers/net/wireless/wl12xx/wl1271_main.c | 10 ++++++---- 4 files changed, 28 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_event.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 170b5a8bdab..4a56ab05e73 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c @@ -408,8 +408,8 @@ 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 = 5; - ps_params->hang_over_period = 1; + 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, @@ -484,7 +484,7 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl) } ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, - WL1271_RATE_AUTOMATIC); + wl->basic_rate); out: dev_kfree_skb(skb); @@ -507,7 +507,7 @@ int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, skb->data, skb->len, CMD_TEMPL_KLV_IDX_NULL_DATA, - WL1271_RATE_AUTOMATIC); + wl->basic_rate); out: dev_kfree_skb(skb); @@ -584,7 +584,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl) return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, sizeof(template), 0, - WL1271_RATE_AUTOMATIC); + wl->basic_rate); } int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index ab716f51755..60c50d1a983 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h @@ -911,6 +911,22 @@ struct conf_conn_settings { */ u8 psm_entry_retries; + /* + * Specifies the maximum number of times to try transmit the PSM entry + * null-func frame for each PSM entry attempt + * + * Range 0 - 255 + */ + u8 psm_entry_nullfunc_retries; + + /* + * Specifies the time to linger in active mode after successfully + * transmitting the PSM entry null-func frame. + * + * Range 0 - 255 TU's + */ + u8 psm_entry_hangover_period; + /* * * Specifies the interval of the connection keep-alive null-func diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index e6c839af903..7b3f5038296 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c @@ -96,7 +96,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl, { int ret = 0; u32 total_retries = wl->conf.conn.psm_entry_retries; - u32 rates; wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status); @@ -112,12 +111,8 @@ static int wl1271_event_ps_report(struct wl1271 *wl, if (wl->psm_entry_retry < total_retries) { wl->psm_entry_retry++; - if (wl->psm_entry_retry == total_retries) - rates = wl->basic_rate; - else - rates = wl->basic_rate_set; ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, - rates, true); + wl->basic_rate, true); } else { wl1271_info("No ack to nullfunc from AP."); wl->psm_entry_retry = 0; diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b2f2d457f28..b7e9c69f377 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -214,7 +214,9 @@ static struct conf_drv_settings default_conf = { .ps_poll_recovery_period = 700, .bet_enable = CONF_BET_MODE_ENABLE, .bet_max_consecutive = 10, - .psm_entry_retries = 3, + .psm_entry_retries = 5, + .psm_entry_nullfunc_retries = 3, + .psm_entry_hangover_period = 1, .keep_alive_interval = 55000, .max_listen_interval = 20, }, @@ -1360,7 +1362,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { wl1271_debug(DEBUG_PSM, "psm enabled"); ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, - wl->basic_rate_set, true); + wl->basic_rate, true); } } else if (!(conf->flags & IEEE80211_CONF_PS) && test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { @@ -1370,7 +1372,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (test_bit(WL1271_FLAG_PSM, &wl->flags)) ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, - wl->basic_rate_set, true); + wl->basic_rate, true); } if (conf->power_level != wl->power_level) { @@ -1846,7 +1848,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, !test_bit(WL1271_FLAG_PSM, &wl->flags)) { mode = STATION_POWER_SAVE_MODE; ret = wl1271_ps_set_mode(wl, mode, - wl->basic_rate_set, + wl->basic_rate, true); if (ret < 0) goto out_sleep; -- cgit v1.2.3-70-g09d2