From 76c0f8d396bd306111d349cfe770e1c4fcf70248 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:41 +0200 Subject: wl1271: updated general parameters structure for newer firmwares In revision 6.1.0.0.288 the general parameters structure has changed. This patch updates the driver code accordingly. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b62c00ff42fe..7ab45c446ab8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -259,6 +259,19 @@ static struct conf_drv_settings default_conf = { .tx_bip_fem_autodetect = 0, .tx_bip_fem_manufacturer = 1, .settings = 1, + .sr_state = 1, + .srf1 = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + .srf2 = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + .srf3 = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + .sr_debug_table = { 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }, + .sr_sen_n_p = 0, + .sr_sen_n_p_gain = 0, + .sr_sen_nrn = 0, + .sr_sen_prn = 0, }, .radioparam = { .rx_trace_loss = 10, -- cgit v1.2.3 From a3e84847b042f10262f8ef66db66a0e527a00cff Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:42 +0200 Subject: wl1271: update radio and general parameters values There were some changes in the values we have to use for these settings. This patches updates them. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 7ab45c446ab8..1d5b73ca23b7 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -256,7 +256,7 @@ static struct conf_drv_settings default_conf = { .clk_valid_on_wakeup = 0, .dc2dcmode = 0, .single_dual_band = CONF_SINGLE_BAND, - .tx_bip_fem_autodetect = 0, + .tx_bip_fem_autodetect = 1, .tx_bip_fem_manufacturer = 1, .settings = 1, .sr_state = 1, @@ -274,8 +274,8 @@ static struct conf_drv_settings default_conf = { .sr_sen_prn = 0, }, .radioparam = { - .rx_trace_loss = 10, - .tx_trace_loss = 10, + .rx_trace_loss = 0x24, + .tx_trace_loss = 0x0, .rx_rssi_and_proc_compens = { 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8, @@ -286,13 +286,13 @@ static struct conf_drv_settings default_conf = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - .tx_ref_pd_voltage = 0x24e, - .tx_ref_power = 0x78, + .tx_ref_pd_voltage = 0x1a9, + .tx_ref_power = 0x80, .tx_offset_db = 0x0, .tx_rate_limits_normal = { - 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 }, + 0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 }, .tx_rate_limits_degraded = { - 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, + 0x19, 0x1f, 0x22, 0x23, 0x27, 0x28 }, .tx_channel_limits_11b = { 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, @@ -302,10 +302,10 @@ static struct conf_drv_settings default_conf = { 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, 0x20, 0x50 }, .tx_pdv_rate_offsets = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 0x07, 0x08, 0x04, 0x02, 0x02, 0x00 }, .tx_ibias = { - 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 }, - .rx_fem_insertion_loss = 0x14, + 0x11, 0x11, 0x15, 0x11, 0x15, 0x0f }, + .rx_fem_insertion_loss = 0x0e, .tx_ref_pd_voltage_5 = { 0x0190, 0x01a4, 0x01c3, 0x01d8, 0x020a, 0x021c }, -- cgit v1.2.3 From cf18be4467b5aca1ccf3b5a72b67fc33a0b30c59 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:43 +0200 Subject: wl1271: added radio parameters configuration values newer firmwares Add new radio parameters for new structures based on firmware revision 6.1.0.0.288. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 1d5b73ca23b7..f1cb7cbd7c1c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -293,6 +293,8 @@ static struct conf_drv_settings default_conf = { 0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 }, .tx_rate_limits_degraded = { 0x19, 0x1f, 0x22, 0x23, 0x27, 0x28 }, + .tx_rate_limits_extreme = { + 0x19, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, .tx_channel_limits_11b = { 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, @@ -306,6 +308,8 @@ static struct conf_drv_settings default_conf = { .tx_ibias = { 0x11, 0x11, 0x15, 0x11, 0x15, 0x0f }, .rx_fem_insertion_loss = 0x0e, + .degraded_low_to_normal_threshold = 0x1e, + .degraded_normal_to_high_threshold = 0x2d, .tx_ref_pd_voltage_5 = { 0x0190, 0x01a4, 0x01c3, 0x01d8, 0x020a, 0x021c }, @@ -317,6 +321,8 @@ static struct conf_drv_settings default_conf = { 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, .tx_rate_limits_degraded_5 = { 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, + .tx_rate_limits_extreme_5 = { + 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, .tx_channel_limits_ofdm_5 = { 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, @@ -328,7 +334,9 @@ static struct conf_drv_settings default_conf = { .tx_ibias_5 = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, .rx_fem_insertion_loss_5 = { - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 } + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, + .degraded_low_to_normal_threshold_5 = 0x00, + .degraded_normal_to_high_threshold_5 = 0x00 } } }; -- cgit v1.2.3 From c7f43e451ba40e66a89d51e63bc21a57824592f2 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:44 +0200 Subject: wl1271: use join command with dummy BSSID When we need to change the channel before association, we have to send a join command with a valid BSSID. With this patch we use 0baddeadbeef as the BSSID. There are ongoing discussions with TI to get this done in a cleaner way. When we go back to idle, we issue a CMD_DISCONNECT to make sure the firmware stops listening to the channel and cleans things up internally. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 75 ++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index f1cb7cbd7c1c..f6d42e613a56 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1130,6 +1130,47 @@ out: } #endif +static int wl1271_join_channel(struct wl1271 *wl, int channel) +{ + int ret; + /* we need to use a dummy BSSID for now */ + static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, + 0xad, 0xbe, 0xef }; + + /* disable mac filter, so we hear everything */ + wl->rx_config &= ~CFG_BSSID_FILTER_EN; + + wl->channel = channel; + memcpy(wl->bssid, dummy_bssid, ETH_ALEN); + + ret = wl1271_cmd_join(wl); + if (ret < 0) + goto out; + + wl->joined = true; + +out: + return ret; +} + +static int wl1271_unjoin_channel(struct wl1271 *wl) +{ + int ret; + + /* to stop listening to a channel, we disconnect */ + ret = wl1271_cmd_disconnect(wl); + if (ret < 0) + goto out; + + wl->joined = false; + wl->channel = 0; + memset(wl->bssid, 0, ETH_ALEN); + wl->rx_config = WL1271_DEFAULT_RX_CONFIG; + +out: + return ret; +} + static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) { struct wl1271 *wl = hw->priv; @@ -1138,10 +1179,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", + wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s", channel, conf->flags & IEEE80211_CONF_PS ? "on" : "off", - conf->power_level); + conf->power_level, + conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); mutex_lock(&wl->mutex); @@ -1151,16 +1193,17 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (ret < 0) goto out; - if (channel != wl->channel) { - /* - * We assume that the stack will configure the right channel - * before associating, so we don't need to send a join - * command here. We will join the right channel when the - * BSSID changes - */ - wl->channel = channel; + if (changed & IEEE80211_CONF_CHANGE_IDLE) { + if (conf->flags & IEEE80211_CONF_IDLE && wl->joined) + wl1271_unjoin_channel(wl); + else + wl1271_join_channel(wl, channel); } + /* if the channel changes while joined, join again */ + if (channel != wl->channel && wl->joined) + wl1271_join_channel(wl, channel); + if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { wl1271_info("psm enabled"); @@ -1494,6 +1537,18 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (ret < 0) goto out; + if ((changed & BSS_CHANGED_BSSID) && + /* + * Now we know the correct bssid, so we send a new join command + * and enable the BSSID filter + */ + memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { + wl->rx_config |= CFG_BSSID_FILTER_EN; + memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); + wl1271_cmd_join(wl); + wl->joined = true; + } + if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { wl->aid = bss_conf->aid; -- cgit v1.2.3 From a2d0e3f13037fa7dc4094c47e0378800a064ee26 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:46 +0200 Subject: wl1271: limit TX power to 25dBm for every channel The wl1271 firmware supports maximun 25.5dBm, so the driver was returning -EINVALID to anything above that. This patch uses the channel max_power option to limit the TX power to 25dBm. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index f6d42e613a56..7f164e532211 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1675,19 +1675,19 @@ static struct ieee80211_rate wl1271_rates[] = { /* can't be const, mac80211 writes to this */ static struct ieee80211_channel wl1271_channels[] = { - { .hw_value = 1, .center_freq = 2412}, - { .hw_value = 2, .center_freq = 2417}, - { .hw_value = 3, .center_freq = 2422}, - { .hw_value = 4, .center_freq = 2427}, - { .hw_value = 5, .center_freq = 2432}, - { .hw_value = 6, .center_freq = 2437}, - { .hw_value = 7, .center_freq = 2442}, - { .hw_value = 8, .center_freq = 2447}, - { .hw_value = 9, .center_freq = 2452}, - { .hw_value = 10, .center_freq = 2457}, - { .hw_value = 11, .center_freq = 2462}, - { .hw_value = 12, .center_freq = 2467}, - { .hw_value = 13, .center_freq = 2472}, + { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, + { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, + { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, + { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, + { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, + { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, + { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, + { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, + { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, + { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, + { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, + { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, + { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, }; /* can't be const, mac80211 writes to this */ -- cgit v1.2.3 From cd264769f7a571fc2a61765757ed85c56f02e9d3 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:47 +0200 Subject: wl1271: check result code from the join command We were not checking the return value from the call to wl1271_cmd_join(). Added a check to make things more reliable. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 7f164e532211..bf1d0fd93bcc 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1545,7 +1545,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { wl->rx_config |= CFG_BSSID_FILTER_EN; memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); - wl1271_cmd_join(wl); + ret = wl1271_cmd_join(wl); + if (ret < 0) { + wl1271_warning("cmd join failed %d", ret); + goto out_sleep; + } wl->joined = true; } -- cgit v1.2.3 From bdcbbb947be9778f740797a2bfc69c44a0d54776 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:48 +0200 Subject: wl1271: set null data template when BSSID is known The call to wl1271_cmd_build_null_data() was missing when we got associated, this was causing PS to fail. This patch adds the call and now PS seems to work. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index bf1d0fd93bcc..64f8623e0325 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1545,6 +1545,12 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { wl->rx_config |= CFG_BSSID_FILTER_EN; memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); + ret = wl1271_cmd_build_null_data(wl); + if (ret < 0) { + wl1271_warning("cmd buld null data failed %d", + ret); + goto out_sleep; + } ret = wl1271_cmd_join(wl); if (ret < 0) { wl1271_warning("cmd join failed %d", ret); -- cgit v1.2.3 From 6e92b416b0aa6a59629cc32ee2b27129d73b98b8 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:50 +0200 Subject: wl1271: implement dco itrim parameters setting Newer firmwares require the dco itrim parameters to be set during initialization. This patch implements the new ACX function and calls it. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 64f8623e0325..8c44f4cd688d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -338,6 +338,10 @@ static struct conf_drv_settings default_conf = { .degraded_low_to_normal_threshold_5 = 0x00, .degraded_normal_to_high_threshold_5 = 0x00 } + }, + .itrim = { + .enable = false, + .timeout = 50000, } }; -- cgit v1.2.3 From 1b38ea8858fd169064683e27add43511308e521a Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:51 +0200 Subject: wl1271: fix one typo in the rx_rssi_and_proc_compens values There was a typo in one of the values in the rx_rssi_and_proc_compens elemt of the Radio Parameters struct. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 8c44f4cd688d..147aab222354 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -278,7 +278,7 @@ static struct conf_drv_settings default_conf = { .tx_trace_loss = 0x0, .rx_rssi_and_proc_compens = { 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, - 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8, + 0xfc, 0x00, 0x80, 0x10, 0xf0, 0xf8, 0x00, 0x0a, 0x14 }, .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, -- cgit v1.2.3 From 98b2a68473ae975bc4abdeb66cd719ccfdad9d4a Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:52 +0200 Subject: wl1271: add gpio_power file in debugfs to power the chip on and off Some debugging tools require the chip to be powered on before they can work. With these tools, we shouldn't upload the firmware nor boot the firmware ourselves, so this debufs file is provided. It always contains the gpio power setting (0 = off, 1 = on). To change the power setting, just write 0 or 1 to the file. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Reviewed-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 147aab222354..b33bdcc1eb4e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -399,11 +399,13 @@ static void wl1271_disable_interrupts(struct wl1271 *wl) static void wl1271_power_off(struct wl1271 *wl) { wl->set_power(false); + wl->gpio_power = false; } static void wl1271_power_on(struct wl1271 *wl) { wl->set_power(true); + wl->gpio_power = true; } static void wl1271_fw_status(struct wl1271 *wl, @@ -1923,6 +1925,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; wl->joined = false; + wl->gpio_power = false; for (i = 0; i < ACX_TX_DESCRIPTORS; i++) wl->tx_frames[i] = NULL; -- cgit v1.2.3 From 3ed8f2c61466f10d99585365fd2aaafaf2d4c949 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:54 +0200 Subject: wl1271: some new configuration values according to new reference In the new reference driver, some of the firmware configuration values have been changed. This patch changes them in the wl1271 driver accordingly. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b33bdcc1eb4e..fb2221749f7b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -67,10 +67,10 @@ static struct conf_drv_settings default_conf = { .ps_poll_timeout = 15, .upsd_timeout = 15, .rts_threshold = 2347, - .rx_cca_threshold = 0xFFEF, - .irq_blk_threshold = 0, - .irq_pkt_threshold = USHORT_MAX, - .irq_timeout = 5, + .rx_cca_threshold = 0, + .irq_blk_threshold = 0xFFFF, + .irq_pkt_threshold = 0, + .irq_timeout = 600, .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, }, .tx = { @@ -172,8 +172,8 @@ static struct conf_drv_settings default_conf = { } }, .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, - .tx_compl_timeout = 5, - .tx_compl_threshold = 5 + .tx_compl_timeout = 700, + .tx_compl_threshold = 4 }, .conn = { .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, @@ -186,12 +186,12 @@ static struct conf_drv_settings default_conf = { .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, } }, - .synch_fail_thold = 5, + .synch_fail_thold = 10, .bss_lose_timeout = 100, .beacon_rx_timeout = 10000, .broadcast_timeout = 20000, .rx_broadcast_in_ps = 1, - .ps_poll_threshold = 4, + .ps_poll_threshold = 20, .sig_trigger_count = 2, .sig_trigger = { [0] = { -- cgit v1.2.3 From 94210897e2b7df8446fdecd360342149e5b4a400 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Fri, 11 Dec 2009 15:40:55 +0200 Subject: wl1271: use channel 1 when configuring the data path In the data path configuration, one of the parameters is the channel. We have been setting it to wl->channel, which is not correct in this case. This channel has nothing to do with the channel we're currently tuned to, since it is only used for calibration during this phase. Hardcoded the channel to 1, according to the reference driver. Signed-off-by: Luciano Coelho Reviewed-by: Juuso Oikarinen Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index fb2221749f7b..55a45d339184 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -384,7 +384,7 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) return ret; - ret = wl1271_cmd_data_path(wl, wl->channel, 1); + ret = wl1271_cmd_data_path(wl, 1); if (ret < 0) return ret; -- cgit v1.2.3 From 149e38789f3fea74b581f8ebb7eb947d3c6d8a4e Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:40:56 +0200 Subject: wl1271: Configure smart-reflex paramter values. Configure correct values to be used with the smart-reflex configuration of the firmware. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 55a45d339184..b0f4c6efa415 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -260,12 +260,12 @@ static struct conf_drv_settings default_conf = { .tx_bip_fem_manufacturer = 1, .settings = 1, .sr_state = 1, - .srf1 = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }, - .srf2 = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }, - .srf3 = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 }, + .srf1 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, + 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, + .srf2 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, + 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, + .srf3 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, + 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, .sr_debug_table = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, .sr_sen_n_p = 0, -- cgit v1.2.3 From 018b171c40b613da867e054f9b6b258ae9298133 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:40:57 +0200 Subject: wl1271: Remove smart reflex ACX Remove the smart-reflex ACX - the associated parameters are now configured in the radio parameters config. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b0f4c6efa415..5a6e4d446962 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -226,30 +226,6 @@ static struct conf_drv_settings default_conf = { .psm_entry_retries = 3 }, .init = { - .sr_err_tbl = { - [0] = { - .len = 7, - .upper_limit = 0x03, - .values = { - 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, - 0x00 } - }, - [1] = { - .len = 7, - .upper_limit = 0x03, - .values = { - 0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8, - 0x00 } - }, - [2] = { - .len = 7, - .upper_limit = 0x03, - .values = { - 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, - 0x00 } - } - }, - .sr_enable = 1, .genparam = { .ref_clk = CONF_REF_CLK_38_4_E, .settling_time = 5, -- cgit v1.2.3 From a6fe231361e35e3d068a63bbfd2318fa4e961ec5 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:40:58 +0200 Subject: wl1271: Use slow rates for association messages While not associated, default the data rates to 1 and 2mbps, so that only those rates will be used for association related message transfer. Once associated, configure the full rate-set supported by the AP. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 5a6e4d446962..272a8fa677ef 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1180,6 +1180,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl1271_unjoin_channel(wl); else wl1271_join_channel(wl, channel); + + if (conf->flags & IEEE80211_CONF_IDLE) { + wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; + wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_BASIC); + } } /* if the channel changes while joined, join again */ @@ -1568,7 +1573,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } else { /* use defaults when not associated */ - wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; wl->aid = 0; } @@ -1897,7 +1901,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl->psm_entry_retry = 0; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; - wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; + wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; wl->joined = false; -- cgit v1.2.3 From 13f2dc52c69bcca074cd12d4806953b2af45c386 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:40:59 +0200 Subject: wl1271: Fix event acknowledging functionality In reference source, events are acknowledged separately - fix the driver to do the same. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 272a8fa677ef..d507dae19e17 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -450,14 +450,13 @@ static void wl1271_irq_work(struct work_struct *work) intr &= WL1271_INTR_MASK; if (intr & WL1271_ACX_INTR_EVENT_A) { - bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true; wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); - wl1271_event_handle(wl, 0, do_ack); + wl1271_event_handle(wl, 0); } if (intr & WL1271_ACX_INTR_EVENT_B) { wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); - wl1271_event_handle(wl, 1, true); + wl1271_event_handle(wl, 1); } if (intr & WL1271_ACX_INTR_INIT_COMPLETE) -- cgit v1.2.3 From af5e084b3200ab6e3033068a34fe16fd139be17b Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:00 +0200 Subject: wl1271: prevent power save entry while not associated The mac80211 sometimes requests power save entry while not associated - this will cause problems, so prevent it if not associated. Go to powersave once association is complete. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index d507dae19e17..d07f03565196 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -978,6 +978,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->elp = false; wl->psm = 0; wl->psm_entry_retry = 0; + wl->associated = false; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->tx_blocks_available = 0; @@ -1191,8 +1192,6 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl1271_join_channel(wl, channel); if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { - wl1271_info("psm enabled"); - wl->psm_requested = true; /* @@ -1200,7 +1199,10 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) * If we're not, we'll enter it when joining an SSID, * through the bss_info_changed() hook. */ - ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); + if (wl->associated) { + wl1271_info("psm enabled"); + ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); + } } else if (!(conf->flags & IEEE80211_CONF_PS) && wl->psm_requested) { wl1271_info("psm disabled"); @@ -1548,6 +1550,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { wl->aid = bss_conf->aid; + wl->associated = true; /* * with wl1271, we don't need to update the @@ -1572,6 +1575,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } else { /* use defaults when not associated */ + wl->associated = false; wl->aid = 0; } @@ -1898,6 +1902,7 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl->psm = 0; wl->psm_requested = false; wl->psm_entry_retry = 0; + wl->associated = false; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; -- cgit v1.2.3 From 9ccd921792e5b6719ff9e561438e095cba757727 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:01 +0200 Subject: wl1271: Implement chipset boot retry The wl1271 has a hardware bug which causes it to randomly (very infrequently) to fail powering up properly. This patch implements retry for the chipset boot sequence, to work around the hardware problem. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 130 ++++++++++++++++++------------ 1 file changed, 77 insertions(+), 53 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index d07f03565196..0795bf3c60da 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -47,6 +47,8 @@ #include "wl1271_cmd.h" #include "wl1271_boot.h" +#define WL1271_BOOT_RETRIES 3 + static struct conf_drv_settings default_conf = { .sg = { .per_threshold = 7500, @@ -645,7 +647,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) ret = wl1271_setup(wl); if (ret < 0) - goto out_power_off; + goto out; break; case CHIP_ID_1271_PG20: wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", @@ -653,38 +655,34 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) ret = wl1271_setup(wl); if (ret < 0) - goto out_power_off; + goto out; break; default: - wl1271_error("unsupported chip id: 0x%x", wl->chip.id); + wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); ret = -ENODEV; - goto out_power_off; + goto out; } if (wl->fw == NULL) { ret = wl1271_fetch_firmware(wl); if (ret < 0) - goto out_power_off; + goto out; } /* No NVS from netlink, try to get it from the filesystem */ if (wl->nvs == NULL) { ret = wl1271_fetch_nvs(wl); if (ret < 0) - goto out_power_off; + goto out; } - goto out; - -out_power_off: - wl1271_power_off(wl); - out: return ret; } int wl1271_plt_start(struct wl1271 *wl) { + int retries = WL1271_BOOT_RETRIES; int ret; mutex_lock(&wl->mutex); @@ -698,35 +696,48 @@ int wl1271_plt_start(struct wl1271 *wl) goto out; } - wl->state = WL1271_STATE_PLT; - - ret = wl1271_chip_wakeup(wl); - if (ret < 0) - goto out; - - ret = wl1271_boot(wl); - if (ret < 0) - goto out_power_off; - - wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); + while (retries) { + retries--; + ret = wl1271_chip_wakeup(wl); + if (ret < 0) + goto power_off; - ret = wl1271_plt_init(wl); - if (ret < 0) - goto out_irq_disable; + ret = wl1271_boot(wl); + if (ret < 0) + goto power_off; - /* Make sure power saving is disabled */ - ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); - if (ret < 0) - goto out_irq_disable; + ret = wl1271_plt_init(wl); + if (ret < 0) + goto irq_disable; - goto out; + /* Make sure power saving is disabled */ + ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); + if (ret < 0) + goto irq_disable; -out_irq_disable: - wl1271_disable_interrupts(wl); + wl->state = WL1271_STATE_PLT; + wl1271_notice("firmware booted in PLT mode (%s)", + wl->chip.fw_ver); + goto out; -out_power_off: - wl1271_power_off(wl); +irq_disable: + wl1271_disable_interrupts(wl); + mutex_unlock(&wl->mutex); + /* Unlocking the mutex in the middle of handling is + inherently unsafe. In this case we deem it safe to do, + because we need to let any possibly pending IRQ out of + the system (and while we are WL1271_STATE_OFF the IRQ + work function will not do anything.) Also, any other + possible concurrent operations will fail due to the + current state, hence the wl1271 struct should be safe. */ + cancel_work_sync(&wl->irq_work); + mutex_lock(&wl->mutex); +power_off: + wl1271_power_off(wl); + } + wl1271_error("firmware boot in PLT mode failed despite %d retries", + WL1271_BOOT_RETRIES); out: mutex_unlock(&wl->mutex); @@ -882,6 +893,7 @@ static struct notifier_block wl1271_dev_notifier = { static int wl1271_op_start(struct ieee80211_hw *hw) { struct wl1271 *wl = hw->priv; + int retries = WL1271_BOOT_RETRIES; int ret = 0; wl1271_debug(DEBUG_MAC80211, "mac80211 start"); @@ -895,30 +907,42 @@ static int wl1271_op_start(struct ieee80211_hw *hw) goto out; } - ret = wl1271_chip_wakeup(wl); - if (ret < 0) - goto out; - - ret = wl1271_boot(wl); - if (ret < 0) - goto out_power_off; - - ret = wl1271_hw_init(wl); - if (ret < 0) - goto out_irq_disable; - - wl->state = WL1271_STATE_ON; + while (retries) { + retries--; + ret = wl1271_chip_wakeup(wl); + if (ret < 0) + goto power_off; - wl1271_info("firmware booted (%s)", wl->chip.fw_ver); + ret = wl1271_boot(wl); + if (ret < 0) + goto power_off; - goto out; + ret = wl1271_hw_init(wl); + if (ret < 0) + goto irq_disable; -out_irq_disable: - wl1271_disable_interrupts(wl); + wl->state = WL1271_STATE_ON; + wl1271_info("firmware booted (%s)", wl->chip.fw_ver); + goto out; -out_power_off: - wl1271_power_off(wl); +irq_disable: + wl1271_disable_interrupts(wl); + mutex_unlock(&wl->mutex); + /* Unlocking the mutex in the middle of handling is + inherently unsafe. In this case we deem it safe to do, + because we need to let any possibly pending IRQ out of + the system (and while we are WL1271_STATE_OFF the IRQ + work function will not do anything.) Also, any other + possible concurrent operations will fail due to the + current state, hence the wl1271 struct should be safe. */ + cancel_work_sync(&wl->irq_work); + mutex_lock(&wl->mutex); +power_off: + wl1271_power_off(wl); + } + wl1271_error("firmware boot failed despite %d retries", + WL1271_BOOT_RETRIES); out: mutex_unlock(&wl->mutex); -- cgit v1.2.3 From 01ac17ecb6292ceab9bfc498145491b78552b239 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:02 +0200 Subject: wl1271: Add pre-power-on sleep This patch adds a short delay before powering on the wl1271. Normally, it is not needed, but if the wl1271 has been powered off shortly before, for reliable firmware-booting this small stabilization delay is required. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 0795bf3c60da..0520b38e8e72 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -618,6 +618,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) struct wl1271_partition_set partition; int ret = 0; + msleep(WL1271_PRE_POWER_ON_SLEEP); wl1271_power_on(wl); msleep(WL1271_POWER_ON_SLEEP); wl1271_spi_reset(wl); -- cgit v1.2.3 From e0d8bbf0d23e6b82f13b29f39593d5d13d923b2b Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:04 +0200 Subject: wl1271: Add rudimentary ad-hoc support This patch adds rudimentary a-hoc support for the driver. It will allow setting up ad-hoc, and for other devices to scan and join. The beacon and probe response template setting is slightly dirty, and need to be properly implemented with support from mac80211. Also, the SSID is not configured to the firmware - the FW will not be able to respond to probe requests autonomously. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 45 +++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 0520b38e8e72..d7b1bb3e08a8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1139,11 +1139,15 @@ out: static int wl1271_join_channel(struct wl1271 *wl, int channel) { - int ret; + int ret = 0; /* we need to use a dummy BSSID for now */ static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, 0xad, 0xbe, 0xef }; + /* the dummy join is not required for ad-hoc */ + if (wl->bss_type == BSS_TYPE_IBSS) + goto out; + /* disable mac filter, so we hear everything */ wl->rx_config &= ~CFG_BSSID_FILTER_EN; @@ -1572,6 +1576,42 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, wl->joined = true; } + if (wl->bss_type == BSS_TYPE_IBSS) { + /* FIXME: This implements rudimentary ad-hoc support - + proper templates are on the wish list and notification + on when they change. This patch will update the templates + on every call to this function. Also, the firmware will not + answer to probe-requests as it does not have the proper + SSID set in the JOIN command. The probe-response template + is set nevertheless, as the FW will ASSERT without it */ + struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); + + if (beacon) { + struct ieee80211_hdr *hdr; + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, + beacon->data, + beacon->len); + + if (ret < 0) { + dev_kfree_skb(beacon); + goto out_sleep; + } + + hdr = (struct ieee80211_hdr *) beacon->data; + hdr->frame_control = cpu_to_le16( + IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_PROBE_RESP); + + ret = wl1271_cmd_template_set(wl, + CMD_TEMPL_PROBE_RESPONSE, + beacon->data, + beacon->len); + dev_kfree_skb(beacon); + if (ret < 0) + goto out_sleep; + } + } + if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { wl->aid = bss_conf->aid; @@ -1857,7 +1897,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_SUPPORTS_PS; - wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC); wl->hw->wiphy->max_scan_ssids = 1; wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; -- cgit v1.2.3 From ec078d943b89c03e55ac9c8b28f39256d4d4045e Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:05 +0200 Subject: wl1271: Change rates configured for templates Previously a "firmware chooses" value was used for the rates of all control message templates set to the firmware. This resulted in a too high rate to be chosen to transmit those messages. Change this by configuring a fixed low rate for the templates. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index d7b1bb3e08a8..7a73aaadd04c 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -78,7 +78,8 @@ static struct conf_drv_settings default_conf = { .tx = { .tx_energy_detection = 0, .rc_conf = { - .enabled_rates = CONF_TX_RATE_MASK_UNSPECIFIED, + .enabled_rates = CONF_HW_BIT_RATE_1MBPS | + CONF_HW_BIT_RATE_2MBPS, .short_retry_limit = 10, .long_retry_limit = 10, .aflags = 0 -- cgit v1.2.3 From 830fb67b8e37fb03cf703b4e1217fe30ce32d579 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:06 +0200 Subject: wl1271: Fix supported rate management Previously, only basic rates were used for data transmission - resulting in reduced transfer rates. This patch takes enables the firmware to take advantage of the full set of data rates supported by the AP. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 59 +++++++++++++------------------ 1 file changed, 25 insertions(+), 34 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 7a73aaadd04c..775b1e82ca81 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -777,7 +777,20 @@ out: 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; + /* peek into the rates configured in the STA entry */ + spin_lock_irqsave(&wl->wl_lock, flags); + if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) { + wl->sta_rate_set = sta->supp_rates[conf->channel->band]; + set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); + } + spin_unlock_irqrestore(&wl->wl_lock, flags); + + /* queue the packet */ skb_queue_tail(&wl->tx_queue, skb); /* @@ -1004,7 +1017,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->elp = false; wl->psm = 0; wl->psm_entry_retry = 0; - wl->associated = false; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->tx_blocks_available = 0; @@ -1016,6 +1028,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->time_offset = 0; wl->session_counter = 0; wl->joined = false; + wl->rate_set = CONF_TX_RATE_MASK_BASIC; + wl->sta_rate_set = 0; + wl->flags = 0; for (i = 0; i < NUM_TX_QUEUES; i++) wl->tx_blocks_freed[i] = 0; @@ -1212,8 +1227,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) wl1271_join_channel(wl, channel); if (conf->flags & IEEE80211_CONF_IDLE) { - wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; - wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_BASIC); + wl->rate_set = CONF_TX_RATE_MASK_BASIC; + wl->sta_rate_set = 0; + wl1271_acx_rate_policies(wl); } } @@ -1229,7 +1245,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) * If we're not, we'll enter it when joining an SSID, * through the bss_info_changed() hook. */ - if (wl->associated) { + if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { wl1271_info("psm enabled"); ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); } @@ -1522,22 +1538,6 @@ out: return ret; } -static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set) -{ - struct ieee80211_supported_band *band; - u32 enabled_rates = 0; - int bit; - - band = wl->hw->wiphy->bands[wl->band]; - for (bit = 0; bit < band->n_bitrates; bit++) { - if (basic_rate_set & 0x1) - enabled_rates |= band->bitrates[bit].hw_value; - basic_rate_set >>= 1; - } - - return enabled_rates; -} - static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -1616,7 +1616,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) { if (bss_conf->assoc) { wl->aid = bss_conf->aid; - wl->associated = true; + set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); /* * with wl1271, we don't need to update the @@ -1641,7 +1641,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } else { /* use defaults when not associated */ - wl->associated = false; + clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); wl->aid = 0; } @@ -1676,17 +1676,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, } } - if (changed & BSS_CHANGED_BASIC_RATES) { - wl->basic_rate_set = wl1271_enabled_rates_get( - wl, bss_conf->basic_rates); - - ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set); - if (ret < 0) { - wl1271_warning("Set rate policies failed %d", ret); - goto out_sleep; - } - } - out_sleep: wl1271_ps_elp_sleep(wl); @@ -1969,14 +1958,16 @@ static int __devinit wl1271_probe(struct spi_device *spi) wl->psm = 0; wl->psm_requested = false; wl->psm_entry_retry = 0; - wl->associated = false; wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; + wl->rate_set = CONF_TX_RATE_MASK_BASIC; + wl->sta_rate_set = 0; wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; wl->joined = false; wl->gpio_power = false; + wl->flags = 0; for (i = 0; i < ACX_TX_DESCRIPTORS; i++) wl->tx_frames[i] = NULL; -- cgit v1.2.3 From 71449f8d7059b69e6e45063997d225d8202221a2 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:07 +0200 Subject: wl1271: Change booleans in struct wl1271 into a flags bitmask For cleaner implementation, change the bunch of booleans in the struct wl1271 structure into a flags bitmask. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 45 +++++++++++++------------------ 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 775b1e82ca81..90a60c1147a8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -378,13 +378,13 @@ static void wl1271_disable_interrupts(struct wl1271 *wl) static void wl1271_power_off(struct wl1271 *wl) { wl->set_power(false); - wl->gpio_power = false; + clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); } static void wl1271_power_on(struct wl1271 *wl) { wl->set_power(true); - wl->gpio_power = true; + set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); } static void wl1271_fw_status(struct wl1271 *wl, @@ -812,7 +812,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * protected. Maybe fix this by removing the stupid * variable altogether and checking the real queue state? */ - wl->tx_queue_stopped = true; + set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); } return NETDEV_TX_OK; @@ -985,11 +985,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) WARN_ON(wl->state != WL1271_STATE_ON); - if (wl->scanning) { + if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) { mutex_unlock(&wl->mutex); ieee80211_scan_completed(wl->hw, true); mutex_lock(&wl->mutex); - wl->scanning = false; } wl->state = WL1271_STATE_OFF; @@ -1014,10 +1013,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->band = IEEE80211_BAND_2GHZ; wl->rx_counter = 0; - wl->elp = false; - wl->psm = 0; wl->psm_entry_retry = 0; - wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->tx_blocks_available = 0; wl->tx_results_count = 0; @@ -1027,7 +1023,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl->tx_security_seq_32 = 0; wl->time_offset = 0; wl->session_counter = 0; - wl->joined = false; wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->sta_rate_set = 0; wl->flags = 0; @@ -1174,7 +1169,7 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel) if (ret < 0) goto out; - wl->joined = true; + set_bit(WL1271_FLAG_JOINED, &wl->flags); out: return ret; @@ -1189,7 +1184,7 @@ static int wl1271_unjoin_channel(struct wl1271 *wl) if (ret < 0) goto out; - wl->joined = false; + clear_bit(WL1271_FLAG_JOINED, &wl->flags); wl->channel = 0; memset(wl->bssid, 0, ETH_ALEN); wl->rx_config = WL1271_DEFAULT_RX_CONFIG; @@ -1221,7 +1216,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) goto out; if (changed & IEEE80211_CONF_CHANGE_IDLE) { - if (conf->flags & IEEE80211_CONF_IDLE && wl->joined) + if (conf->flags & IEEE80211_CONF_IDLE && + test_bit(WL1271_FLAG_JOINED, &wl->flags)) wl1271_unjoin_channel(wl); else wl1271_join_channel(wl, channel); @@ -1234,11 +1230,12 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) } /* if the channel changes while joined, join again */ - if (channel != wl->channel && wl->joined) + if (channel != wl->channel && test_bit(WL1271_FLAG_JOINED, &wl->flags)) wl1271_join_channel(wl, channel); - if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { - wl->psm_requested = true; + if (conf->flags & IEEE80211_CONF_PS && + !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { + set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); /* * We enter PSM only if we're already associated. @@ -1250,12 +1247,12 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); } } else if (!(conf->flags & IEEE80211_CONF_PS) && - wl->psm_requested) { + test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { wl1271_info("psm disabled"); - wl->psm_requested = false; + clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); - if (wl->psm) + if (test_bit(WL1271_FLAG_PSM, &wl->flags)) ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); } @@ -1574,7 +1571,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, wl1271_warning("cmd join failed %d", ret); goto out_sleep; } - wl->joined = true; + set_bit(WL1271_FLAG_JOINED, &wl->flags); } if (wl->bss_type == BSS_TYPE_IBSS) { @@ -1633,7 +1630,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, goto out_sleep; /* If we want to go in PSM but we're not there yet */ - if (wl->psm_requested && !wl->psm) { + if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && + !test_bit(WL1271_FLAG_PSM, &wl->flags)) { mode = STATION_POWER_SAVE_MODE; ret = wl1271_ps_set_mode(wl, mode); if (ret < 0) @@ -1949,24 +1947,17 @@ static int __devinit wl1271_probe(struct spi_device *spi) INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); wl->channel = WL1271_DEFAULT_CHANNEL; - wl->scanning = false; wl->default_key = 0; wl->rx_counter = 0; wl->rx_config = WL1271_DEFAULT_RX_CONFIG; wl->rx_filter = WL1271_DEFAULT_RX_FILTER; - wl->elp = false; - wl->psm = 0; - wl->psm_requested = false; wl->psm_entry_retry = 0; - wl->tx_queue_stopped = false; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->sta_rate_set = 0; wl->band = IEEE80211_BAND_2GHZ; wl->vif = NULL; - wl->joined = false; - wl->gpio_power = false; wl->flags = 0; for (i = 0; i < ACX_TX_DESCRIPTORS; i++) -- cgit v1.2.3 From 38ad2d87d42ba847c100ef132e8e363513982c8b Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:08 +0200 Subject: wl1271: Add support for acx_pm_config This acx configures host clock parameters in correspondence with the clock request line - the settling time of the clock, and whether fast wake-up is supported. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 90a60c1147a8..7e6b500dfb6f 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -321,6 +321,10 @@ static struct conf_drv_settings default_conf = { .itrim = { .enable = false, .timeout = 50000, + }, + .pm_config = { + .host_clk_settling_time = 5000, + .host_fast_wakeup_support = false } }; -- cgit v1.2.3 From 8f648c00039a42e67a9dff034c77d41502dab1f3 Mon Sep 17 00:00:00 2001 From: Juuso Oikarinen Date: Fri, 11 Dec 2009 15:41:10 +0200 Subject: wl1271: Prevent performing "join" before association There is a minor bug in the code causing a "join" to be performed before there is an intention to associate. Fix this. Signed-off-by: Juuso Oikarinen Reviewed-by: Luciano Coelho Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 7e6b500dfb6f..4a997381a8d0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1223,7 +1223,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (conf->flags & IEEE80211_CONF_IDLE && test_bit(WL1271_FLAG_JOINED, &wl->flags)) wl1271_unjoin_channel(wl); - else + else if (!(conf->flags & IEEE80211_CONF_IDLE)) wl1271_join_channel(wl, channel); if (conf->flags & IEEE80211_CONF_IDLE) { -- cgit v1.2.3 From 1ed32e4fc8cfc9656cc1101e7f9617d485fcbe7b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 23 Dec 2009 13:15:45 +0100 Subject: mac80211: remove struct ieee80211_if_init_conf All its members (vif, mac_addr, type) are now available in the vif struct directly, so we can pass that instead of the conf struct. I generated this patch (except the mac80211 and header file changes) with this semantic patch: @@ identifier conf, fn, hw; type tp; @@ tp fn(struct ieee80211_hw *hw, -struct ieee80211_if_init_conf *conf) +struct ieee80211_vif *vif) { <... ( -conf->type +vif->type | -conf->mac_addr +vif->addr | -conf->vif +vif ) ...> } Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/wl12xx/wl1271_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c') diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4a997381a8d0..e4867b895c43 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c @@ -1039,13 +1039,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) } static int wl1271_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; int ret = 0; wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", - conf->type, conf->mac_addr); + vif->type, vif->addr); mutex_lock(&wl->mutex); if (wl->vif) { @@ -1053,9 +1053,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; } - wl->vif = conf->vif; + wl->vif = vif; - switch (conf->type) { + switch (vif->type) { case NL80211_IFTYPE_STATION: wl->bss_type = BSS_TYPE_STA_BSS; break; @@ -1075,7 +1075,7 @@ out: } static void wl1271_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) + struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; -- cgit v1.2.3