diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/main.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 1116 |
1 files changed, 845 insertions, 271 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 062247ef3ad2..254b7daccee1 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -116,11 +116,11 @@ static struct conf_drv_settings default_conf = { | |||
116 | }, | 116 | }, |
117 | .tx = { | 117 | .tx = { |
118 | .tx_energy_detection = 0, | 118 | .tx_energy_detection = 0, |
119 | .rc_conf = { | 119 | .sta_rc_conf = { |
120 | .enabled_rates = 0, | 120 | .enabled_rates = 0, |
121 | .short_retry_limit = 10, | 121 | .short_retry_limit = 10, |
122 | .long_retry_limit = 10, | 122 | .long_retry_limit = 10, |
123 | .aflags = 0 | 123 | .aflags = 0, |
124 | }, | 124 | }, |
125 | .ac_conf_count = 4, | 125 | .ac_conf_count = 4, |
126 | .ac_conf = { | 126 | .ac_conf = { |
@@ -153,6 +153,45 @@ static struct conf_drv_settings default_conf = { | |||
153 | .tx_op_limit = 1504, | 153 | .tx_op_limit = 1504, |
154 | }, | 154 | }, |
155 | }, | 155 | }, |
156 | .ap_rc_conf = { | ||
157 | [0] = { | ||
158 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
159 | .short_retry_limit = 10, | ||
160 | .long_retry_limit = 10, | ||
161 | .aflags = 0, | ||
162 | }, | ||
163 | [1] = { | ||
164 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
165 | .short_retry_limit = 10, | ||
166 | .long_retry_limit = 10, | ||
167 | .aflags = 0, | ||
168 | }, | ||
169 | [2] = { | ||
170 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
171 | .short_retry_limit = 10, | ||
172 | .long_retry_limit = 10, | ||
173 | .aflags = 0, | ||
174 | }, | ||
175 | [3] = { | ||
176 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
177 | .short_retry_limit = 10, | ||
178 | .long_retry_limit = 10, | ||
179 | .aflags = 0, | ||
180 | }, | ||
181 | }, | ||
182 | .ap_mgmt_conf = { | ||
183 | .enabled_rates = CONF_TX_AP_DEFAULT_MGMT_RATES, | ||
184 | .short_retry_limit = 10, | ||
185 | .long_retry_limit = 10, | ||
186 | .aflags = 0, | ||
187 | }, | ||
188 | .ap_bcst_conf = { | ||
189 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS, | ||
190 | .short_retry_limit = 10, | ||
191 | .long_retry_limit = 10, | ||
192 | .aflags = 0, | ||
193 | }, | ||
194 | .ap_max_tx_retries = 100, | ||
156 | .tid_conf_count = 4, | 195 | .tid_conf_count = 4, |
157 | .tid_conf = { | 196 | .tid_conf = { |
158 | [CONF_TX_AC_BE] = { | 197 | [CONF_TX_AC_BE] = { |
@@ -193,6 +232,8 @@ static struct conf_drv_settings default_conf = { | |||
193 | .tx_compl_threshold = 4, | 232 | .tx_compl_threshold = 4, |
194 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, | 233 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, |
195 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, | 234 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, |
235 | .tmpl_short_retry_limit = 10, | ||
236 | .tmpl_long_retry_limit = 10, | ||
196 | }, | 237 | }, |
197 | .conn = { | 238 | .conn = { |
198 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 239 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
@@ -233,13 +274,13 @@ static struct conf_drv_settings default_conf = { | |||
233 | .avg_weight_rssi_beacon = 20, | 274 | .avg_weight_rssi_beacon = 20, |
234 | .avg_weight_rssi_data = 10, | 275 | .avg_weight_rssi_data = 10, |
235 | .avg_weight_snr_beacon = 20, | 276 | .avg_weight_snr_beacon = 20, |
236 | .avg_weight_snr_data = 10 | 277 | .avg_weight_snr_data = 10, |
237 | }, | 278 | }, |
238 | .scan = { | 279 | .scan = { |
239 | .min_dwell_time_active = 7500, | 280 | .min_dwell_time_active = 7500, |
240 | .max_dwell_time_active = 30000, | 281 | .max_dwell_time_active = 30000, |
241 | .min_dwell_time_passive = 30000, | 282 | .min_dwell_time_passive = 100000, |
242 | .max_dwell_time_passive = 60000, | 283 | .max_dwell_time_passive = 100000, |
243 | .num_probe_reqs = 2, | 284 | .num_probe_reqs = 2, |
244 | }, | 285 | }, |
245 | .rf = { | 286 | .rf = { |
@@ -252,9 +293,14 @@ static struct conf_drv_settings default_conf = { | |||
252 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 293 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
253 | }, | 294 | }, |
254 | }, | 295 | }, |
296 | .ht = { | ||
297 | .tx_ba_win_size = 64, | ||
298 | .inactivity_timeout = 10000, | ||
299 | }, | ||
255 | }; | 300 | }; |
256 | 301 | ||
257 | static void __wl1271_op_remove_interface(struct wl1271 *wl); | 302 | static void __wl1271_op_remove_interface(struct wl1271 *wl); |
303 | static void wl1271_free_ap_keys(struct wl1271 *wl); | ||
258 | 304 | ||
259 | 305 | ||
260 | static void wl1271_device_release(struct device *dev) | 306 | static void wl1271_device_release(struct device *dev) |
@@ -393,7 +439,7 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
393 | if (ret < 0) | 439 | if (ret < 0) |
394 | return ret; | 440 | return ret; |
395 | 441 | ||
396 | ret = wl1271_init_templates_config(wl); | 442 | ret = wl1271_sta_init_templates_config(wl); |
397 | if (ret < 0) | 443 | if (ret < 0) |
398 | return ret; | 444 | return ret; |
399 | 445 | ||
@@ -616,9 +662,26 @@ out: | |||
616 | static int wl1271_fetch_firmware(struct wl1271 *wl) | 662 | static int wl1271_fetch_firmware(struct wl1271 *wl) |
617 | { | 663 | { |
618 | const struct firmware *fw; | 664 | const struct firmware *fw; |
665 | const char *fw_name; | ||
619 | int ret; | 666 | int ret; |
620 | 667 | ||
621 | ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl)); | 668 | switch (wl->bss_type) { |
669 | case BSS_TYPE_AP_BSS: | ||
670 | fw_name = WL1271_AP_FW_NAME; | ||
671 | break; | ||
672 | case BSS_TYPE_IBSS: | ||
673 | case BSS_TYPE_STA_BSS: | ||
674 | fw_name = WL1271_FW_NAME; | ||
675 | break; | ||
676 | default: | ||
677 | wl1271_error("no compatible firmware for bss_type %d", | ||
678 | wl->bss_type); | ||
679 | return -EINVAL; | ||
680 | } | ||
681 | |||
682 | wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); | ||
683 | |||
684 | ret = request_firmware(&fw, fw_name, wl1271_wl_to_dev(wl)); | ||
622 | 685 | ||
623 | if (ret < 0) { | 686 | if (ret < 0) { |
624 | wl1271_error("could not get firmware: %d", ret); | 687 | wl1271_error("could not get firmware: %d", ret); |
@@ -632,6 +695,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) | |||
632 | goto out; | 695 | goto out; |
633 | } | 696 | } |
634 | 697 | ||
698 | vfree(wl->fw); | ||
635 | wl->fw_len = fw->size; | 699 | wl->fw_len = fw->size; |
636 | wl->fw = vmalloc(wl->fw_len); | 700 | wl->fw = vmalloc(wl->fw_len); |
637 | 701 | ||
@@ -642,7 +706,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) | |||
642 | } | 706 | } |
643 | 707 | ||
644 | memcpy(wl->fw, fw->data, wl->fw_len); | 708 | memcpy(wl->fw, fw->data, wl->fw_len); |
645 | 709 | wl->fw_bss_type = wl->bss_type; | |
646 | ret = 0; | 710 | ret = 0; |
647 | 711 | ||
648 | out: | 712 | out: |
@@ -778,7 +842,8 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
778 | goto out; | 842 | goto out; |
779 | } | 843 | } |
780 | 844 | ||
781 | if (wl->fw == NULL) { | 845 | /* Make sure the firmware type matches the BSS type */ |
846 | if (wl->fw == NULL || wl->fw_bss_type != wl->bss_type) { | ||
782 | ret = wl1271_fetch_firmware(wl); | 847 | ret = wl1271_fetch_firmware(wl); |
783 | if (ret < 0) | 848 | if (ret < 0) |
784 | goto out; | 849 | goto out; |
@@ -811,6 +876,8 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
811 | goto out; | 876 | goto out; |
812 | } | 877 | } |
813 | 878 | ||
879 | wl->bss_type = BSS_TYPE_STA_BSS; | ||
880 | |||
814 | while (retries) { | 881 | while (retries) { |
815 | retries--; | 882 | retries--; |
816 | ret = wl1271_chip_wakeup(wl); | 883 | ret = wl1271_chip_wakeup(wl); |
@@ -827,7 +894,7 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
827 | 894 | ||
828 | wl->state = WL1271_STATE_PLT; | 895 | wl->state = WL1271_STATE_PLT; |
829 | wl1271_notice("firmware booted in PLT mode (%s)", | 896 | wl1271_notice("firmware booted in PLT mode (%s)", |
830 | wl->chip.fw_ver); | 897 | wl->chip.fw_ver_str); |
831 | goto out; | 898 | goto out; |
832 | 899 | ||
833 | irq_disable: | 900 | irq_disable: |
@@ -854,12 +921,10 @@ out: | |||
854 | return ret; | 921 | return ret; |
855 | } | 922 | } |
856 | 923 | ||
857 | int wl1271_plt_stop(struct wl1271 *wl) | 924 | int __wl1271_plt_stop(struct wl1271 *wl) |
858 | { | 925 | { |
859 | int ret = 0; | 926 | int ret = 0; |
860 | 927 | ||
861 | mutex_lock(&wl->mutex); | ||
862 | |||
863 | wl1271_notice("power down"); | 928 | wl1271_notice("power down"); |
864 | 929 | ||
865 | if (wl->state != WL1271_STATE_PLT) { | 930 | if (wl->state != WL1271_STATE_PLT) { |
@@ -875,12 +940,21 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
875 | wl->state = WL1271_STATE_OFF; | 940 | wl->state = WL1271_STATE_OFF; |
876 | wl->rx_counter = 0; | 941 | wl->rx_counter = 0; |
877 | 942 | ||
878 | out: | ||
879 | mutex_unlock(&wl->mutex); | 943 | mutex_unlock(&wl->mutex); |
880 | |||
881 | cancel_work_sync(&wl->irq_work); | 944 | cancel_work_sync(&wl->irq_work); |
882 | cancel_work_sync(&wl->recovery_work); | 945 | cancel_work_sync(&wl->recovery_work); |
946 | mutex_lock(&wl->mutex); | ||
947 | out: | ||
948 | return ret; | ||
949 | } | ||
950 | |||
951 | int wl1271_plt_stop(struct wl1271 *wl) | ||
952 | { | ||
953 | int ret; | ||
883 | 954 | ||
955 | mutex_lock(&wl->mutex); | ||
956 | ret = __wl1271_plt_stop(wl); | ||
957 | mutex_unlock(&wl->mutex); | ||
884 | return ret; | 958 | return ret; |
885 | } | 959 | } |
886 | 960 | ||
@@ -902,7 +976,8 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
902 | spin_lock_irqsave(&wl->wl_lock, flags); | 976 | spin_lock_irqsave(&wl->wl_lock, flags); |
903 | if (sta && | 977 | if (sta && |
904 | (sta->supp_rates[conf->channel->band] != | 978 | (sta->supp_rates[conf->channel->band] != |
905 | (wl->sta_rate_set & HW_BG_RATES_MASK))) { | 979 | (wl->sta_rate_set & HW_BG_RATES_MASK)) && |
980 | wl->bss_type != BSS_TYPE_AP_BSS) { | ||
906 | wl->sta_rate_set = sta->supp_rates[conf->channel->band]; | 981 | wl->sta_rate_set = sta->supp_rates[conf->channel->band]; |
907 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); | 982 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); |
908 | } | 983 | } |
@@ -967,6 +1042,9 @@ static int wl1271_op_start(struct ieee80211_hw *hw) | |||
967 | * | 1042 | * |
968 | * The MAC address is first known when the corresponding interface | 1043 | * The MAC address is first known when the corresponding interface |
969 | * is added. That is where we will initialize the hardware. | 1044 | * is added. That is where we will initialize the hardware. |
1045 | * | ||
1046 | * In addition, we currently have different firmwares for AP and managed | ||
1047 | * operation. We will know which to boot according to interface type. | ||
970 | */ | 1048 | */ |
971 | 1049 | ||
972 | return 0; | 1050 | return 0; |
@@ -1006,6 +1084,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1006 | wl->bss_type = BSS_TYPE_IBSS; | 1084 | wl->bss_type = BSS_TYPE_IBSS; |
1007 | wl->set_bss_type = BSS_TYPE_STA_BSS; | 1085 | wl->set_bss_type = BSS_TYPE_STA_BSS; |
1008 | break; | 1086 | break; |
1087 | case NL80211_IFTYPE_AP: | ||
1088 | wl->bss_type = BSS_TYPE_AP_BSS; | ||
1089 | break; | ||
1009 | default: | 1090 | default: |
1010 | ret = -EOPNOTSUPP; | 1091 | ret = -EOPNOTSUPP; |
1011 | goto out; | 1092 | goto out; |
@@ -1061,11 +1142,11 @@ power_off: | |||
1061 | 1142 | ||
1062 | wl->vif = vif; | 1143 | wl->vif = vif; |
1063 | wl->state = WL1271_STATE_ON; | 1144 | wl->state = WL1271_STATE_ON; |
1064 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); | 1145 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); |
1065 | 1146 | ||
1066 | /* update hw/fw version info in wiphy struct */ | 1147 | /* update hw/fw version info in wiphy struct */ |
1067 | wiphy->hw_version = wl->chip.id; | 1148 | wiphy->hw_version = wl->chip.id; |
1068 | strncpy(wiphy->fw_version, wl->chip.fw_ver, | 1149 | strncpy(wiphy->fw_version, wl->chip.fw_ver_str, |
1069 | sizeof(wiphy->fw_version)); | 1150 | sizeof(wiphy->fw_version)); |
1070 | 1151 | ||
1071 | /* | 1152 | /* |
@@ -1151,6 +1232,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1151 | wl->flags = 0; | 1232 | wl->flags = 0; |
1152 | wl->vif = NULL; | 1233 | wl->vif = NULL; |
1153 | wl->filters = 0; | 1234 | wl->filters = 0; |
1235 | wl1271_free_ap_keys(wl); | ||
1236 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); | ||
1154 | 1237 | ||
1155 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1238 | for (i = 0; i < NUM_TX_QUEUES; i++) |
1156 | wl->tx_blocks_freed[i] = 0; | 1239 | wl->tx_blocks_freed[i] = 0; |
@@ -1186,8 +1269,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1186 | 1269 | ||
1187 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) | 1270 | static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters) |
1188 | { | 1271 | { |
1189 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 1272 | wl1271_set_default_filters(wl); |
1190 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | ||
1191 | 1273 | ||
1192 | /* combine requested filters with current filter config */ | 1274 | /* combine requested filters with current filter config */ |
1193 | filters = wl->filters | filters; | 1275 | filters = wl->filters | filters; |
@@ -1322,25 +1404,7 @@ static void wl1271_set_band_rate(struct wl1271 *wl) | |||
1322 | wl->basic_rate_set = wl->conf.tx.basic_rate_5; | 1404 | wl->basic_rate_set = wl->conf.tx.basic_rate_5; |
1323 | } | 1405 | } |
1324 | 1406 | ||
1325 | static u32 wl1271_min_rate_get(struct wl1271 *wl) | 1407 | static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) |
1326 | { | ||
1327 | int i; | ||
1328 | u32 rate = 0; | ||
1329 | |||
1330 | if (!wl->basic_rate_set) { | ||
1331 | WARN_ON(1); | ||
1332 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1333 | } | ||
1334 | |||
1335 | for (i = 0; !rate; i++) { | ||
1336 | if ((wl->basic_rate_set >> i) & 0x1) | ||
1337 | rate = 1 << i; | ||
1338 | } | ||
1339 | |||
1340 | return rate; | ||
1341 | } | ||
1342 | |||
1343 | static int wl1271_handle_idle(struct wl1271 *wl, bool idle) | ||
1344 | { | 1408 | { |
1345 | int ret; | 1409 | int ret; |
1346 | 1410 | ||
@@ -1350,9 +1414,9 @@ static int wl1271_handle_idle(struct wl1271 *wl, bool idle) | |||
1350 | if (ret < 0) | 1414 | if (ret < 0) |
1351 | goto out; | 1415 | goto out; |
1352 | } | 1416 | } |
1353 | wl->rate_set = wl1271_min_rate_get(wl); | 1417 | wl->rate_set = wl1271_tx_min_rate_get(wl); |
1354 | wl->sta_rate_set = 0; | 1418 | wl->sta_rate_set = 0; |
1355 | ret = wl1271_acx_rate_policies(wl); | 1419 | ret = wl1271_acx_sta_rate_policies(wl); |
1356 | if (ret < 0) | 1420 | if (ret < 0) |
1357 | goto out; | 1421 | goto out; |
1358 | ret = wl1271_acx_keep_alive_config( | 1422 | ret = wl1271_acx_keep_alive_config( |
@@ -1381,14 +1445,17 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1381 | struct wl1271 *wl = hw->priv; | 1445 | struct wl1271 *wl = hw->priv; |
1382 | struct ieee80211_conf *conf = &hw->conf; | 1446 | struct ieee80211_conf *conf = &hw->conf; |
1383 | int channel, ret = 0; | 1447 | int channel, ret = 0; |
1448 | bool is_ap; | ||
1384 | 1449 | ||
1385 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | 1450 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); |
1386 | 1451 | ||
1387 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s", | 1452 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s" |
1453 | " changed 0x%x", | ||
1388 | channel, | 1454 | channel, |
1389 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | 1455 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", |
1390 | conf->power_level, | 1456 | conf->power_level, |
1391 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); | 1457 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use", |
1458 | changed); | ||
1392 | 1459 | ||
1393 | /* | 1460 | /* |
1394 | * mac80211 will go to idle nearly immediately after transmitting some | 1461 | * mac80211 will go to idle nearly immediately after transmitting some |
@@ -1406,6 +1473,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1406 | goto out; | 1473 | goto out; |
1407 | } | 1474 | } |
1408 | 1475 | ||
1476 | is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | ||
1477 | |||
1409 | ret = wl1271_ps_elp_wakeup(wl, false); | 1478 | ret = wl1271_ps_elp_wakeup(wl, false); |
1410 | if (ret < 0) | 1479 | if (ret < 0) |
1411 | goto out; | 1480 | goto out; |
@@ -1417,31 +1486,34 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1417 | wl->band = conf->channel->band; | 1486 | wl->band = conf->channel->band; |
1418 | wl->channel = channel; | 1487 | wl->channel = channel; |
1419 | 1488 | ||
1420 | /* | 1489 | if (!is_ap) { |
1421 | * FIXME: the mac80211 should really provide a fixed rate | 1490 | /* |
1422 | * to use here. for now, just use the smallest possible rate | 1491 | * FIXME: the mac80211 should really provide a fixed |
1423 | * for the band as a fixed rate for association frames and | 1492 | * rate to use here. for now, just use the smallest |
1424 | * other control messages. | 1493 | * possible rate for the band as a fixed rate for |
1425 | */ | 1494 | * association frames and other control messages. |
1426 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 1495 | */ |
1427 | wl1271_set_band_rate(wl); | 1496 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
1428 | 1497 | wl1271_set_band_rate(wl); | |
1429 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1430 | ret = wl1271_acx_rate_policies(wl); | ||
1431 | if (ret < 0) | ||
1432 | wl1271_warning("rate policy for update channel " | ||
1433 | "failed %d", ret); | ||
1434 | 1498 | ||
1435 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | 1499 | wl->basic_rate = wl1271_tx_min_rate_get(wl); |
1436 | ret = wl1271_join(wl, false); | 1500 | ret = wl1271_acx_sta_rate_policies(wl); |
1437 | if (ret < 0) | 1501 | if (ret < 0) |
1438 | wl1271_warning("cmd join to update channel " | 1502 | wl1271_warning("rate policy for channel " |
1439 | "failed %d", ret); | 1503 | "failed %d", ret); |
1504 | |||
1505 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1506 | ret = wl1271_join(wl, false); | ||
1507 | if (ret < 0) | ||
1508 | wl1271_warning("cmd join on channel " | ||
1509 | "failed %d", ret); | ||
1510 | } | ||
1440 | } | 1511 | } |
1441 | } | 1512 | } |
1442 | 1513 | ||
1443 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1514 | if (changed & IEEE80211_CONF_CHANGE_IDLE && !is_ap) { |
1444 | ret = wl1271_handle_idle(wl, conf->flags & IEEE80211_CONF_IDLE); | 1515 | ret = wl1271_sta_handle_idle(wl, |
1516 | conf->flags & IEEE80211_CONF_IDLE); | ||
1445 | if (ret < 0) | 1517 | if (ret < 0) |
1446 | wl1271_warning("idle mode change failed %d", ret); | 1518 | wl1271_warning("idle mode change failed %d", ret); |
1447 | } | 1519 | } |
@@ -1548,7 +1620,8 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1548 | struct wl1271 *wl = hw->priv; | 1620 | struct wl1271 *wl = hw->priv; |
1549 | int ret; | 1621 | int ret; |
1550 | 1622 | ||
1551 | wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter"); | 1623 | wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter changed %x" |
1624 | " total %x", changed, *total); | ||
1552 | 1625 | ||
1553 | mutex_lock(&wl->mutex); | 1626 | mutex_lock(&wl->mutex); |
1554 | 1627 | ||
@@ -1562,15 +1635,16 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1562 | if (ret < 0) | 1635 | if (ret < 0) |
1563 | goto out; | 1636 | goto out; |
1564 | 1637 | ||
1565 | 1638 | if (wl->bss_type != BSS_TYPE_AP_BSS) { | |
1566 | if (*total & FIF_ALLMULTI) | 1639 | if (*total & FIF_ALLMULTI) |
1567 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); | 1640 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); |
1568 | else if (fp) | 1641 | else if (fp) |
1569 | ret = wl1271_acx_group_address_tbl(wl, fp->enabled, | 1642 | ret = wl1271_acx_group_address_tbl(wl, fp->enabled, |
1570 | fp->mc_list, | 1643 | fp->mc_list, |
1571 | fp->mc_list_length); | 1644 | fp->mc_list_length); |
1572 | if (ret < 0) | 1645 | if (ret < 0) |
1573 | goto out_sleep; | 1646 | goto out_sleep; |
1647 | } | ||
1574 | 1648 | ||
1575 | /* determine, whether supported filter values have changed */ | 1649 | /* determine, whether supported filter values have changed */ |
1576 | if (changed == 0) | 1650 | if (changed == 0) |
@@ -1593,38 +1667,192 @@ out: | |||
1593 | kfree(fp); | 1667 | kfree(fp); |
1594 | } | 1668 | } |
1595 | 1669 | ||
1670 | static int wl1271_record_ap_key(struct wl1271 *wl, u8 id, u8 key_type, | ||
1671 | u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, | ||
1672 | u16 tx_seq_16) | ||
1673 | { | ||
1674 | struct wl1271_ap_key *ap_key; | ||
1675 | int i; | ||
1676 | |||
1677 | wl1271_debug(DEBUG_CRYPT, "record ap key id %d", (int)id); | ||
1678 | |||
1679 | if (key_size > MAX_KEY_SIZE) | ||
1680 | return -EINVAL; | ||
1681 | |||
1682 | /* | ||
1683 | * Find next free entry in ap_keys. Also check we are not replacing | ||
1684 | * an existing key. | ||
1685 | */ | ||
1686 | for (i = 0; i < MAX_NUM_KEYS; i++) { | ||
1687 | if (wl->recorded_ap_keys[i] == NULL) | ||
1688 | break; | ||
1689 | |||
1690 | if (wl->recorded_ap_keys[i]->id == id) { | ||
1691 | wl1271_warning("trying to record key replacement"); | ||
1692 | return -EINVAL; | ||
1693 | } | ||
1694 | } | ||
1695 | |||
1696 | if (i == MAX_NUM_KEYS) | ||
1697 | return -EBUSY; | ||
1698 | |||
1699 | ap_key = kzalloc(sizeof(*ap_key), GFP_KERNEL); | ||
1700 | if (!ap_key) | ||
1701 | return -ENOMEM; | ||
1702 | |||
1703 | ap_key->id = id; | ||
1704 | ap_key->key_type = key_type; | ||
1705 | ap_key->key_size = key_size; | ||
1706 | memcpy(ap_key->key, key, key_size); | ||
1707 | ap_key->hlid = hlid; | ||
1708 | ap_key->tx_seq_32 = tx_seq_32; | ||
1709 | ap_key->tx_seq_16 = tx_seq_16; | ||
1710 | |||
1711 | wl->recorded_ap_keys[i] = ap_key; | ||
1712 | return 0; | ||
1713 | } | ||
1714 | |||
1715 | static void wl1271_free_ap_keys(struct wl1271 *wl) | ||
1716 | { | ||
1717 | int i; | ||
1718 | |||
1719 | for (i = 0; i < MAX_NUM_KEYS; i++) { | ||
1720 | kfree(wl->recorded_ap_keys[i]); | ||
1721 | wl->recorded_ap_keys[i] = NULL; | ||
1722 | } | ||
1723 | } | ||
1724 | |||
1725 | static int wl1271_ap_init_hwenc(struct wl1271 *wl) | ||
1726 | { | ||
1727 | int i, ret = 0; | ||
1728 | struct wl1271_ap_key *key; | ||
1729 | bool wep_key_added = false; | ||
1730 | |||
1731 | for (i = 0; i < MAX_NUM_KEYS; i++) { | ||
1732 | if (wl->recorded_ap_keys[i] == NULL) | ||
1733 | break; | ||
1734 | |||
1735 | key = wl->recorded_ap_keys[i]; | ||
1736 | ret = wl1271_cmd_set_ap_key(wl, KEY_ADD_OR_REPLACE, | ||
1737 | key->id, key->key_type, | ||
1738 | key->key_size, key->key, | ||
1739 | key->hlid, key->tx_seq_32, | ||
1740 | key->tx_seq_16); | ||
1741 | if (ret < 0) | ||
1742 | goto out; | ||
1743 | |||
1744 | if (key->key_type == KEY_WEP) | ||
1745 | wep_key_added = true; | ||
1746 | } | ||
1747 | |||
1748 | if (wep_key_added) { | ||
1749 | ret = wl1271_cmd_set_ap_default_wep_key(wl, wl->default_key); | ||
1750 | if (ret < 0) | ||
1751 | goto out; | ||
1752 | } | ||
1753 | |||
1754 | out: | ||
1755 | wl1271_free_ap_keys(wl); | ||
1756 | return ret; | ||
1757 | } | ||
1758 | |||
1759 | static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | ||
1760 | u8 key_size, const u8 *key, u32 tx_seq_32, | ||
1761 | u16 tx_seq_16, struct ieee80211_sta *sta) | ||
1762 | { | ||
1763 | int ret; | ||
1764 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | ||
1765 | |||
1766 | if (is_ap) { | ||
1767 | struct wl1271_station *wl_sta; | ||
1768 | u8 hlid; | ||
1769 | |||
1770 | if (sta) { | ||
1771 | wl_sta = (struct wl1271_station *)sta->drv_priv; | ||
1772 | hlid = wl_sta->hlid; | ||
1773 | } else { | ||
1774 | hlid = WL1271_AP_BROADCAST_HLID; | ||
1775 | } | ||
1776 | |||
1777 | if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { | ||
1778 | /* | ||
1779 | * We do not support removing keys after AP shutdown. | ||
1780 | * Pretend we do to make mac80211 happy. | ||
1781 | */ | ||
1782 | if (action != KEY_ADD_OR_REPLACE) | ||
1783 | return 0; | ||
1784 | |||
1785 | ret = wl1271_record_ap_key(wl, id, | ||
1786 | key_type, key_size, | ||
1787 | key, hlid, tx_seq_32, | ||
1788 | tx_seq_16); | ||
1789 | } else { | ||
1790 | ret = wl1271_cmd_set_ap_key(wl, action, | ||
1791 | id, key_type, key_size, | ||
1792 | key, hlid, tx_seq_32, | ||
1793 | tx_seq_16); | ||
1794 | } | ||
1795 | |||
1796 | if (ret < 0) | ||
1797 | return ret; | ||
1798 | } else { | ||
1799 | const u8 *addr; | ||
1800 | static const u8 bcast_addr[ETH_ALEN] = { | ||
1801 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
1802 | }; | ||
1803 | |||
1804 | addr = sta ? sta->addr : bcast_addr; | ||
1805 | |||
1806 | if (is_zero_ether_addr(addr)) { | ||
1807 | /* We dont support TX only encryption */ | ||
1808 | return -EOPNOTSUPP; | ||
1809 | } | ||
1810 | |||
1811 | /* The wl1271 does not allow to remove unicast keys - they | ||
1812 | will be cleared automatically on next CMD_JOIN. Ignore the | ||
1813 | request silently, as we dont want the mac80211 to emit | ||
1814 | an error message. */ | ||
1815 | if (action == KEY_REMOVE && !is_broadcast_ether_addr(addr)) | ||
1816 | return 0; | ||
1817 | |||
1818 | ret = wl1271_cmd_set_sta_key(wl, action, | ||
1819 | id, key_type, key_size, | ||
1820 | key, addr, tx_seq_32, | ||
1821 | tx_seq_16); | ||
1822 | if (ret < 0) | ||
1823 | return ret; | ||
1824 | |||
1825 | /* the default WEP key needs to be configured at least once */ | ||
1826 | if (key_type == KEY_WEP) { | ||
1827 | ret = wl1271_cmd_set_sta_default_wep_key(wl, | ||
1828 | wl->default_key); | ||
1829 | if (ret < 0) | ||
1830 | return ret; | ||
1831 | } | ||
1832 | } | ||
1833 | |||
1834 | return 0; | ||
1835 | } | ||
1836 | |||
1596 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 1837 | static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
1597 | struct ieee80211_vif *vif, | 1838 | struct ieee80211_vif *vif, |
1598 | struct ieee80211_sta *sta, | 1839 | struct ieee80211_sta *sta, |
1599 | struct ieee80211_key_conf *key_conf) | 1840 | struct ieee80211_key_conf *key_conf) |
1600 | { | 1841 | { |
1601 | struct wl1271 *wl = hw->priv; | 1842 | struct wl1271 *wl = hw->priv; |
1602 | const u8 *addr; | ||
1603 | int ret; | 1843 | int ret; |
1604 | u32 tx_seq_32 = 0; | 1844 | u32 tx_seq_32 = 0; |
1605 | u16 tx_seq_16 = 0; | 1845 | u16 tx_seq_16 = 0; |
1606 | u8 key_type; | 1846 | u8 key_type; |
1607 | 1847 | ||
1608 | static const u8 bcast_addr[ETH_ALEN] = | ||
1609 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
1610 | |||
1611 | wl1271_debug(DEBUG_MAC80211, "mac80211 set key"); | 1848 | wl1271_debug(DEBUG_MAC80211, "mac80211 set key"); |
1612 | 1849 | ||
1613 | addr = sta ? sta->addr : bcast_addr; | 1850 | wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x sta: %p", cmd, sta); |
1614 | |||
1615 | wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); | ||
1616 | wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); | ||
1617 | wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", | 1851 | wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", |
1618 | key_conf->cipher, key_conf->keyidx, | 1852 | key_conf->cipher, key_conf->keyidx, |
1619 | key_conf->keylen, key_conf->flags); | 1853 | key_conf->keylen, key_conf->flags); |
1620 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); | 1854 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); |
1621 | 1855 | ||
1622 | if (is_zero_ether_addr(addr)) { | ||
1623 | /* We dont support TX only encryption */ | ||
1624 | ret = -EOPNOTSUPP; | ||
1625 | goto out; | ||
1626 | } | ||
1627 | |||
1628 | mutex_lock(&wl->mutex); | 1856 | mutex_lock(&wl->mutex); |
1629 | 1857 | ||
1630 | if (unlikely(wl->state == WL1271_STATE_OFF)) { | 1858 | if (unlikely(wl->state == WL1271_STATE_OFF)) { |
@@ -1671,36 +1899,21 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1671 | 1899 | ||
1672 | switch (cmd) { | 1900 | switch (cmd) { |
1673 | case SET_KEY: | 1901 | case SET_KEY: |
1674 | ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE, | 1902 | ret = wl1271_set_key(wl, KEY_ADD_OR_REPLACE, |
1675 | key_conf->keyidx, key_type, | 1903 | key_conf->keyidx, key_type, |
1676 | key_conf->keylen, key_conf->key, | 1904 | key_conf->keylen, key_conf->key, |
1677 | addr, tx_seq_32, tx_seq_16); | 1905 | tx_seq_32, tx_seq_16, sta); |
1678 | if (ret < 0) { | 1906 | if (ret < 0) { |
1679 | wl1271_error("Could not add or replace key"); | 1907 | wl1271_error("Could not add or replace key"); |
1680 | goto out_sleep; | 1908 | goto out_sleep; |
1681 | } | 1909 | } |
1682 | |||
1683 | /* the default WEP key needs to be configured at least once */ | ||
1684 | if (key_type == KEY_WEP) { | ||
1685 | ret = wl1271_cmd_set_default_wep_key(wl, | ||
1686 | wl->default_key); | ||
1687 | if (ret < 0) | ||
1688 | goto out_sleep; | ||
1689 | } | ||
1690 | break; | 1910 | break; |
1691 | 1911 | ||
1692 | case DISABLE_KEY: | 1912 | case DISABLE_KEY: |
1693 | /* The wl1271 does not allow to remove unicast keys - they | 1913 | ret = wl1271_set_key(wl, KEY_REMOVE, |
1694 | will be cleared automatically on next CMD_JOIN. Ignore the | 1914 | key_conf->keyidx, key_type, |
1695 | request silently, as we dont want the mac80211 to emit | 1915 | key_conf->keylen, key_conf->key, |
1696 | an error message. */ | 1916 | 0, 0, sta); |
1697 | if (!is_broadcast_ether_addr(addr)) | ||
1698 | break; | ||
1699 | |||
1700 | ret = wl1271_cmd_set_key(wl, KEY_REMOVE, | ||
1701 | key_conf->keyidx, key_type, | ||
1702 | key_conf->keylen, key_conf->key, | ||
1703 | addr, 0, 0); | ||
1704 | if (ret < 0) { | 1917 | if (ret < 0) { |
1705 | wl1271_error("Could not remove key"); | 1918 | wl1271_error("Could not remove key"); |
1706 | goto out_sleep; | 1919 | goto out_sleep; |
@@ -1719,7 +1932,6 @@ out_sleep: | |||
1719 | out_unlock: | 1932 | out_unlock: |
1720 | mutex_unlock(&wl->mutex); | 1933 | mutex_unlock(&wl->mutex); |
1721 | 1934 | ||
1722 | out: | ||
1723 | return ret; | 1935 | return ret; |
1724 | } | 1936 | } |
1725 | 1937 | ||
@@ -1821,7 +2033,7 @@ out: | |||
1821 | return ret; | 2033 | return ret; |
1822 | } | 2034 | } |
1823 | 2035 | ||
1824 | static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, | 2036 | static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, |
1825 | int offset) | 2037 | int offset) |
1826 | { | 2038 | { |
1827 | u8 *ptr = skb->data + offset; | 2039 | u8 *ptr = skb->data + offset; |
@@ -1831,89 +2043,210 @@ static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, | |||
1831 | if (ptr[0] == WLAN_EID_SSID) { | 2043 | if (ptr[0] == WLAN_EID_SSID) { |
1832 | wl->ssid_len = ptr[1]; | 2044 | wl->ssid_len = ptr[1]; |
1833 | memcpy(wl->ssid, ptr+2, wl->ssid_len); | 2045 | memcpy(wl->ssid, ptr+2, wl->ssid_len); |
1834 | return; | 2046 | return 0; |
1835 | } | 2047 | } |
1836 | ptr += (ptr[1] + 2); | 2048 | ptr += (ptr[1] + 2); |
1837 | } | 2049 | } |
2050 | |||
1838 | wl1271_error("No SSID in IEs!\n"); | 2051 | wl1271_error("No SSID in IEs!\n"); |
2052 | return -ENOENT; | ||
1839 | } | 2053 | } |
1840 | 2054 | ||
1841 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | 2055 | static int wl1271_bss_erp_info_changed(struct wl1271 *wl, |
1842 | struct ieee80211_vif *vif, | ||
1843 | struct ieee80211_bss_conf *bss_conf, | 2056 | struct ieee80211_bss_conf *bss_conf, |
1844 | u32 changed) | 2057 | u32 changed) |
1845 | { | 2058 | { |
1846 | enum wl1271_cmd_ps_mode mode; | 2059 | int ret = 0; |
1847 | struct wl1271 *wl = hw->priv; | ||
1848 | struct ieee80211_sta *sta = ieee80211_find_sta(vif, bss_conf->bssid); | ||
1849 | bool do_join = false; | ||
1850 | bool set_assoc = false; | ||
1851 | int ret; | ||
1852 | 2060 | ||
1853 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 2061 | if (changed & BSS_CHANGED_ERP_SLOT) { |
2062 | if (bss_conf->use_short_slot) | ||
2063 | ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT); | ||
2064 | else | ||
2065 | ret = wl1271_acx_slot(wl, SLOT_TIME_LONG); | ||
2066 | if (ret < 0) { | ||
2067 | wl1271_warning("Set slot time failed %d", ret); | ||
2068 | goto out; | ||
2069 | } | ||
2070 | } | ||
1854 | 2071 | ||
1855 | mutex_lock(&wl->mutex); | 2072 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
2073 | if (bss_conf->use_short_preamble) | ||
2074 | wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT); | ||
2075 | else | ||
2076 | wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG); | ||
2077 | } | ||
1856 | 2078 | ||
1857 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 2079 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { |
1858 | goto out; | 2080 | if (bss_conf->use_cts_prot) |
2081 | ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE); | ||
2082 | else | ||
2083 | ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE); | ||
2084 | if (ret < 0) { | ||
2085 | wl1271_warning("Set ctsprotect failed %d", ret); | ||
2086 | goto out; | ||
2087 | } | ||
2088 | } | ||
1859 | 2089 | ||
1860 | ret = wl1271_ps_elp_wakeup(wl, false); | 2090 | out: |
1861 | if (ret < 0) | 2091 | return ret; |
1862 | goto out; | 2092 | } |
1863 | 2093 | ||
1864 | if ((changed & BSS_CHANGED_BEACON_INT) && | 2094 | static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, |
1865 | (wl->bss_type == BSS_TYPE_IBSS)) { | 2095 | struct ieee80211_vif *vif, |
1866 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", | 2096 | struct ieee80211_bss_conf *bss_conf, |
2097 | u32 changed) | ||
2098 | { | ||
2099 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | ||
2100 | int ret = 0; | ||
2101 | |||
2102 | if ((changed & BSS_CHANGED_BEACON_INT)) { | ||
2103 | wl1271_debug(DEBUG_MASTER, "beacon interval updated: %d", | ||
1867 | bss_conf->beacon_int); | 2104 | bss_conf->beacon_int); |
1868 | 2105 | ||
1869 | wl->beacon_int = bss_conf->beacon_int; | 2106 | wl->beacon_int = bss_conf->beacon_int; |
1870 | do_join = true; | ||
1871 | } | 2107 | } |
1872 | 2108 | ||
1873 | if ((changed & BSS_CHANGED_BEACON) && | 2109 | if ((changed & BSS_CHANGED_BEACON)) { |
1874 | (wl->bss_type == BSS_TYPE_IBSS)) { | 2110 | struct ieee80211_hdr *hdr; |
1875 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 2111 | int ieoffset = offsetof(struct ieee80211_mgmt, |
2112 | u.beacon.variable); | ||
2113 | struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); | ||
2114 | u16 tmpl_id; | ||
1876 | 2115 | ||
1877 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon updated"); | 2116 | if (!beacon) |
2117 | goto out; | ||
1878 | 2118 | ||
1879 | if (beacon) { | 2119 | wl1271_debug(DEBUG_MASTER, "beacon updated"); |
1880 | struct ieee80211_hdr *hdr; | ||
1881 | int ieoffset = offsetof(struct ieee80211_mgmt, | ||
1882 | u.beacon.variable); | ||
1883 | 2120 | ||
1884 | wl1271_ssid_set(wl, beacon, ieoffset); | 2121 | ret = wl1271_ssid_set(wl, beacon, ieoffset); |
2122 | if (ret < 0) { | ||
2123 | dev_kfree_skb(beacon); | ||
2124 | goto out; | ||
2125 | } | ||
2126 | tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : | ||
2127 | CMD_TEMPL_BEACON; | ||
2128 | ret = wl1271_cmd_template_set(wl, tmpl_id, | ||
2129 | beacon->data, | ||
2130 | beacon->len, 0, | ||
2131 | wl1271_tx_min_rate_get(wl)); | ||
2132 | if (ret < 0) { | ||
2133 | dev_kfree_skb(beacon); | ||
2134 | goto out; | ||
2135 | } | ||
1885 | 2136 | ||
1886 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 2137 | hdr = (struct ieee80211_hdr *) beacon->data; |
1887 | beacon->data, | 2138 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
1888 | beacon->len, 0, | 2139 | IEEE80211_STYPE_PROBE_RESP); |
1889 | wl1271_min_rate_get(wl)); | 2140 | |
2141 | tmpl_id = is_ap ? CMD_TEMPL_AP_PROBE_RESPONSE : | ||
2142 | CMD_TEMPL_PROBE_RESPONSE; | ||
2143 | ret = wl1271_cmd_template_set(wl, | ||
2144 | tmpl_id, | ||
2145 | beacon->data, | ||
2146 | beacon->len, 0, | ||
2147 | wl1271_tx_min_rate_get(wl)); | ||
2148 | dev_kfree_skb(beacon); | ||
2149 | if (ret < 0) | ||
2150 | goto out; | ||
2151 | } | ||
1890 | 2152 | ||
1891 | if (ret < 0) { | 2153 | out: |
1892 | dev_kfree_skb(beacon); | 2154 | return ret; |
1893 | goto out_sleep; | 2155 | } |
1894 | } | ||
1895 | 2156 | ||
1896 | hdr = (struct ieee80211_hdr *) beacon->data; | 2157 | /* AP mode changes */ |
1897 | hdr->frame_control = cpu_to_le16( | 2158 | static void wl1271_bss_info_changed_ap(struct wl1271 *wl, |
1898 | IEEE80211_FTYPE_MGMT | | 2159 | struct ieee80211_vif *vif, |
1899 | IEEE80211_STYPE_PROBE_RESP); | 2160 | struct ieee80211_bss_conf *bss_conf, |
2161 | u32 changed) | ||
2162 | { | ||
2163 | int ret = 0; | ||
1900 | 2164 | ||
1901 | ret = wl1271_cmd_template_set(wl, | 2165 | if ((changed & BSS_CHANGED_BASIC_RATES)) { |
1902 | CMD_TEMPL_PROBE_RESPONSE, | 2166 | u32 rates = bss_conf->basic_rates; |
1903 | beacon->data, | 2167 | struct conf_tx_rate_class mgmt_rc; |
1904 | beacon->len, 0, | 2168 | |
1905 | wl1271_min_rate_get(wl)); | 2169 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); |
1906 | dev_kfree_skb(beacon); | 2170 | wl->basic_rate = wl1271_tx_min_rate_get(wl); |
1907 | if (ret < 0) | 2171 | wl1271_debug(DEBUG_AP, "basic rates: 0x%x", |
1908 | goto out_sleep; | 2172 | wl->basic_rate_set); |
2173 | |||
2174 | /* update the AP management rate policy with the new rates */ | ||
2175 | mgmt_rc.enabled_rates = wl->basic_rate_set; | ||
2176 | mgmt_rc.long_retry_limit = 10; | ||
2177 | mgmt_rc.short_retry_limit = 10; | ||
2178 | mgmt_rc.aflags = 0; | ||
2179 | ret = wl1271_acx_ap_rate_policy(wl, &mgmt_rc, | ||
2180 | ACX_TX_AP_MODE_MGMT_RATE); | ||
2181 | if (ret < 0) { | ||
2182 | wl1271_error("AP mgmt policy change failed %d", ret); | ||
2183 | goto out; | ||
2184 | } | ||
2185 | } | ||
1909 | 2186 | ||
1910 | /* Need to update the SSID (for filtering etc) */ | 2187 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); |
1911 | do_join = true; | 2188 | if (ret < 0) |
2189 | goto out; | ||
2190 | |||
2191 | if ((changed & BSS_CHANGED_BEACON_ENABLED)) { | ||
2192 | if (bss_conf->enable_beacon) { | ||
2193 | if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { | ||
2194 | ret = wl1271_cmd_start_bss(wl); | ||
2195 | if (ret < 0) | ||
2196 | goto out; | ||
2197 | |||
2198 | set_bit(WL1271_FLAG_AP_STARTED, &wl->flags); | ||
2199 | wl1271_debug(DEBUG_AP, "started AP"); | ||
2200 | |||
2201 | ret = wl1271_ap_init_hwenc(wl); | ||
2202 | if (ret < 0) | ||
2203 | goto out; | ||
2204 | } | ||
2205 | } else { | ||
2206 | if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { | ||
2207 | ret = wl1271_cmd_stop_bss(wl); | ||
2208 | if (ret < 0) | ||
2209 | goto out; | ||
2210 | |||
2211 | clear_bit(WL1271_FLAG_AP_STARTED, &wl->flags); | ||
2212 | wl1271_debug(DEBUG_AP, "stopped AP"); | ||
2213 | } | ||
1912 | } | 2214 | } |
1913 | } | 2215 | } |
1914 | 2216 | ||
1915 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && | 2217 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); |
1916 | (wl->bss_type == BSS_TYPE_IBSS)) { | 2218 | if (ret < 0) |
2219 | goto out; | ||
2220 | out: | ||
2221 | return; | ||
2222 | } | ||
2223 | |||
2224 | /* STA/IBSS mode changes */ | ||
2225 | static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | ||
2226 | struct ieee80211_vif *vif, | ||
2227 | struct ieee80211_bss_conf *bss_conf, | ||
2228 | u32 changed) | ||
2229 | { | ||
2230 | bool do_join = false, set_assoc = false; | ||
2231 | bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); | ||
2232 | int ret; | ||
2233 | struct ieee80211_sta *sta; | ||
2234 | |||
2235 | if (is_ibss) { | ||
2236 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, | ||
2237 | changed); | ||
2238 | if (ret < 0) | ||
2239 | goto out; | ||
2240 | } | ||
2241 | |||
2242 | if ((changed & BSS_CHANGED_BEACON_INT) && is_ibss) | ||
2243 | do_join = true; | ||
2244 | |||
2245 | /* Need to update the SSID (for filtering etc) */ | ||
2246 | if ((changed & BSS_CHANGED_BEACON) && is_ibss) | ||
2247 | do_join = true; | ||
2248 | |||
2249 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && is_ibss) { | ||
1917 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", | 2250 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", |
1918 | bss_conf->enable_beacon ? "enabled" : "disabled"); | 2251 | bss_conf->enable_beacon ? "enabled" : "disabled"); |
1919 | 2252 | ||
@@ -1924,7 +2257,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1924 | do_join = true; | 2257 | do_join = true; |
1925 | } | 2258 | } |
1926 | 2259 | ||
1927 | if (changed & BSS_CHANGED_CQM) { | 2260 | if ((changed & BSS_CHANGED_CQM)) { |
1928 | bool enable = false; | 2261 | bool enable = false; |
1929 | if (bss_conf->cqm_rssi_thold) | 2262 | if (bss_conf->cqm_rssi_thold) |
1930 | enable = true; | 2263 | enable = true; |
@@ -1942,24 +2275,26 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1942 | * and enable the BSSID filter | 2275 | * and enable the BSSID filter |
1943 | */ | 2276 | */ |
1944 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | 2277 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { |
1945 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | 2278 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); |
1946 | 2279 | ||
2280 | if (!is_zero_ether_addr(wl->bssid)) { | ||
1947 | ret = wl1271_cmd_build_null_data(wl); | 2281 | ret = wl1271_cmd_build_null_data(wl); |
1948 | if (ret < 0) | 2282 | if (ret < 0) |
1949 | goto out_sleep; | 2283 | goto out; |
1950 | 2284 | ||
1951 | ret = wl1271_build_qos_null_data(wl); | 2285 | ret = wl1271_build_qos_null_data(wl); |
1952 | if (ret < 0) | 2286 | if (ret < 0) |
1953 | goto out_sleep; | 2287 | goto out; |
1954 | 2288 | ||
1955 | /* filter out all packets not from this BSSID */ | 2289 | /* filter out all packets not from this BSSID */ |
1956 | wl1271_configure_filters(wl, 0); | 2290 | wl1271_configure_filters(wl, 0); |
1957 | 2291 | ||
1958 | /* Need to update the BSSID (for filtering etc) */ | 2292 | /* Need to update the BSSID (for filtering etc) */ |
1959 | do_join = true; | 2293 | do_join = true; |
2294 | } | ||
1960 | } | 2295 | } |
1961 | 2296 | ||
1962 | if (changed & BSS_CHANGED_ASSOC) { | 2297 | if ((changed & BSS_CHANGED_ASSOC)) { |
1963 | if (bss_conf->assoc) { | 2298 | if (bss_conf->assoc) { |
1964 | u32 rates; | 2299 | u32 rates; |
1965 | int ieoffset; | 2300 | int ieoffset; |
@@ -1975,10 +2310,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1975 | rates = bss_conf->basic_rates; | 2310 | rates = bss_conf->basic_rates; |
1976 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | 2311 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, |
1977 | rates); | 2312 | rates); |
1978 | wl->basic_rate = wl1271_min_rate_get(wl); | 2313 | wl->basic_rate = wl1271_tx_min_rate_get(wl); |
1979 | ret = wl1271_acx_rate_policies(wl); | 2314 | ret = wl1271_acx_sta_rate_policies(wl); |
1980 | if (ret < 0) | 2315 | if (ret < 0) |
1981 | goto out_sleep; | 2316 | goto out; |
1982 | 2317 | ||
1983 | /* | 2318 | /* |
1984 | * with wl1271, we don't need to update the | 2319 | * with wl1271, we don't need to update the |
@@ -1988,7 +2323,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1988 | */ | 2323 | */ |
1989 | ret = wl1271_cmd_build_ps_poll(wl, wl->aid); | 2324 | ret = wl1271_cmd_build_ps_poll(wl, wl->aid); |
1990 | if (ret < 0) | 2325 | if (ret < 0) |
1991 | goto out_sleep; | 2326 | goto out; |
1992 | 2327 | ||
1993 | /* | 2328 | /* |
1994 | * Get a template for hardware connection maintenance | 2329 | * Get a template for hardware connection maintenance |
@@ -2002,17 +2337,19 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2002 | /* enable the connection monitoring feature */ | 2337 | /* enable the connection monitoring feature */ |
2003 | ret = wl1271_acx_conn_monit_params(wl, true); | 2338 | ret = wl1271_acx_conn_monit_params(wl, true); |
2004 | if (ret < 0) | 2339 | if (ret < 0) |
2005 | goto out_sleep; | 2340 | goto out; |
2006 | 2341 | ||
2007 | /* If we want to go in PSM but we're not there yet */ | 2342 | /* If we want to go in PSM but we're not there yet */ |
2008 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && | 2343 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && |
2009 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 2344 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
2345 | enum wl1271_cmd_ps_mode mode; | ||
2346 | |||
2010 | mode = STATION_POWER_SAVE_MODE; | 2347 | mode = STATION_POWER_SAVE_MODE; |
2011 | ret = wl1271_ps_set_mode(wl, mode, | 2348 | ret = wl1271_ps_set_mode(wl, mode, |
2012 | wl->basic_rate, | 2349 | wl->basic_rate, |
2013 | true); | 2350 | true); |
2014 | if (ret < 0) | 2351 | if (ret < 0) |
2015 | goto out_sleep; | 2352 | goto out; |
2016 | } | 2353 | } |
2017 | } else { | 2354 | } else { |
2018 | /* use defaults when not associated */ | 2355 | /* use defaults when not associated */ |
@@ -2029,10 +2366,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2029 | 2366 | ||
2030 | /* revert back to minimum rates for the current band */ | 2367 | /* revert back to minimum rates for the current band */ |
2031 | wl1271_set_band_rate(wl); | 2368 | wl1271_set_band_rate(wl); |
2032 | wl->basic_rate = wl1271_min_rate_get(wl); | 2369 | wl->basic_rate = wl1271_tx_min_rate_get(wl); |
2033 | ret = wl1271_acx_rate_policies(wl); | 2370 | ret = wl1271_acx_sta_rate_policies(wl); |
2034 | if (ret < 0) | 2371 | if (ret < 0) |
2035 | goto out_sleep; | 2372 | goto out; |
2036 | 2373 | ||
2037 | /* disable connection monitor features */ | 2374 | /* disable connection monitor features */ |
2038 | ret = wl1271_acx_conn_monit_params(wl, false); | 2375 | ret = wl1271_acx_conn_monit_params(wl, false); |
@@ -2040,74 +2377,54 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2040 | /* Disable the keep-alive feature */ | 2377 | /* Disable the keep-alive feature */ |
2041 | ret = wl1271_acx_keep_alive_mode(wl, false); | 2378 | ret = wl1271_acx_keep_alive_mode(wl, false); |
2042 | if (ret < 0) | 2379 | if (ret < 0) |
2043 | goto out_sleep; | 2380 | goto out; |
2044 | 2381 | ||
2045 | /* restore the bssid filter and go to dummy bssid */ | 2382 | /* restore the bssid filter and go to dummy bssid */ |
2046 | wl1271_unjoin(wl); | 2383 | wl1271_unjoin(wl); |
2047 | wl1271_dummy_join(wl); | 2384 | wl1271_dummy_join(wl); |
2048 | } | 2385 | } |
2049 | |||
2050 | } | ||
2051 | |||
2052 | if (changed & BSS_CHANGED_ERP_SLOT) { | ||
2053 | if (bss_conf->use_short_slot) | ||
2054 | ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT); | ||
2055 | else | ||
2056 | ret = wl1271_acx_slot(wl, SLOT_TIME_LONG); | ||
2057 | if (ret < 0) { | ||
2058 | wl1271_warning("Set slot time failed %d", ret); | ||
2059 | goto out_sleep; | ||
2060 | } | ||
2061 | } | ||
2062 | |||
2063 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | ||
2064 | if (bss_conf->use_short_preamble) | ||
2065 | wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT); | ||
2066 | else | ||
2067 | wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG); | ||
2068 | } | 2386 | } |
2069 | 2387 | ||
2070 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | 2388 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); |
2071 | if (bss_conf->use_cts_prot) | 2389 | if (ret < 0) |
2072 | ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE); | 2390 | goto out; |
2073 | else | ||
2074 | ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE); | ||
2075 | if (ret < 0) { | ||
2076 | wl1271_warning("Set ctsprotect failed %d", ret); | ||
2077 | goto out_sleep; | ||
2078 | } | ||
2079 | } | ||
2080 | 2391 | ||
2081 | /* | 2392 | rcu_read_lock(); |
2082 | * Takes care of: New association with HT enable, | 2393 | sta = ieee80211_find_sta(vif, bss_conf->bssid); |
2083 | * HT information change in beacon. | 2394 | if (sta) { |
2084 | */ | 2395 | /* handle new association with HT and HT information change */ |
2085 | if (sta && | 2396 | if ((changed & BSS_CHANGED_HT) && |
2086 | (changed & BSS_CHANGED_HT) && | 2397 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { |
2087 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { | 2398 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, |
2088 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true); | 2399 | true); |
2089 | if (ret < 0) { | 2400 | if (ret < 0) { |
2090 | wl1271_warning("Set ht cap true failed %d", ret); | 2401 | wl1271_warning("Set ht cap true failed %d", |
2091 | goto out_sleep; | 2402 | ret); |
2092 | } | 2403 | rcu_read_unlock(); |
2404 | goto out; | ||
2405 | } | ||
2093 | ret = wl1271_acx_set_ht_information(wl, | 2406 | ret = wl1271_acx_set_ht_information(wl, |
2094 | bss_conf->ht_operation_mode); | 2407 | bss_conf->ht_operation_mode); |
2095 | if (ret < 0) { | 2408 | if (ret < 0) { |
2096 | wl1271_warning("Set ht information failed %d", ret); | 2409 | wl1271_warning("Set ht information failed %d", |
2097 | goto out_sleep; | 2410 | ret); |
2411 | rcu_read_unlock(); | ||
2412 | goto out; | ||
2413 | } | ||
2098 | } | 2414 | } |
2099 | } | 2415 | /* handle new association without HT and disassociation */ |
2100 | /* | 2416 | else if (changed & BSS_CHANGED_ASSOC) { |
2101 | * Takes care of: New association without HT, | 2417 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, |
2102 | * Disassociation. | 2418 | false); |
2103 | */ | 2419 | if (ret < 0) { |
2104 | else if (sta && (changed & BSS_CHANGED_ASSOC)) { | 2420 | wl1271_warning("Set ht cap false failed %d", |
2105 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, false); | 2421 | ret); |
2106 | if (ret < 0) { | 2422 | rcu_read_unlock(); |
2107 | wl1271_warning("Set ht cap false failed %d", ret); | 2423 | goto out; |
2108 | goto out_sleep; | 2424 | } |
2109 | } | 2425 | } |
2110 | } | 2426 | } |
2427 | rcu_read_unlock(); | ||
2111 | 2428 | ||
2112 | if (changed & BSS_CHANGED_ARP_FILTER) { | 2429 | if (changed & BSS_CHANGED_ARP_FILTER) { |
2113 | __be32 addr = bss_conf->arp_addr_list[0]; | 2430 | __be32 addr = bss_conf->arp_addr_list[0]; |
@@ -2124,76 +2441,128 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2124 | ret = wl1271_cmd_build_arp_rsp(wl, addr); | 2441 | ret = wl1271_cmd_build_arp_rsp(wl, addr); |
2125 | if (ret < 0) { | 2442 | if (ret < 0) { |
2126 | wl1271_warning("build arp rsp failed: %d", ret); | 2443 | wl1271_warning("build arp rsp failed: %d", ret); |
2127 | goto out_sleep; | 2444 | goto out; |
2128 | } | 2445 | } |
2129 | 2446 | ||
2130 | ret = wl1271_acx_arp_ip_filter(wl, | 2447 | ret = wl1271_acx_arp_ip_filter(wl, |
2131 | (ACX_ARP_FILTER_ARP_FILTERING | | 2448 | ACX_ARP_FILTER_ARP_FILTERING, |
2132 | ACX_ARP_FILTER_AUTO_ARP), | ||
2133 | addr); | 2449 | addr); |
2134 | } else | 2450 | } else |
2135 | ret = wl1271_acx_arp_ip_filter(wl, 0, addr); | 2451 | ret = wl1271_acx_arp_ip_filter(wl, 0, addr); |
2136 | 2452 | ||
2137 | if (ret < 0) | 2453 | if (ret < 0) |
2138 | goto out_sleep; | 2454 | goto out; |
2139 | } | 2455 | } |
2140 | 2456 | ||
2141 | if (do_join) { | 2457 | if (do_join) { |
2142 | ret = wl1271_join(wl, set_assoc); | 2458 | ret = wl1271_join(wl, set_assoc); |
2143 | if (ret < 0) { | 2459 | if (ret < 0) { |
2144 | wl1271_warning("cmd join failed %d", ret); | 2460 | wl1271_warning("cmd join failed %d", ret); |
2145 | goto out_sleep; | 2461 | goto out; |
2146 | } | 2462 | } |
2147 | } | 2463 | } |
2148 | 2464 | ||
2149 | out_sleep: | ||
2150 | wl1271_ps_elp_sleep(wl); | ||
2151 | |||
2152 | out: | 2465 | out: |
2153 | mutex_unlock(&wl->mutex); | 2466 | return; |
2154 | } | 2467 | } |
2155 | 2468 | ||
2156 | static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | 2469 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, |
2157 | const struct ieee80211_tx_queue_params *params) | 2470 | struct ieee80211_vif *vif, |
2471 | struct ieee80211_bss_conf *bss_conf, | ||
2472 | u32 changed) | ||
2158 | { | 2473 | { |
2159 | struct wl1271 *wl = hw->priv; | 2474 | struct wl1271 *wl = hw->priv; |
2160 | u8 ps_scheme; | 2475 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); |
2161 | int ret; | 2476 | int ret; |
2162 | 2477 | ||
2163 | mutex_lock(&wl->mutex); | 2478 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x", |
2479 | (int)changed); | ||
2164 | 2480 | ||
2165 | wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); | 2481 | mutex_lock(&wl->mutex); |
2166 | 2482 | ||
2167 | if (unlikely(wl->state == WL1271_STATE_OFF)) { | 2483 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
2168 | ret = -EAGAIN; | ||
2169 | goto out; | 2484 | goto out; |
2170 | } | ||
2171 | 2485 | ||
2172 | ret = wl1271_ps_elp_wakeup(wl, false); | 2486 | ret = wl1271_ps_elp_wakeup(wl, false); |
2173 | if (ret < 0) | 2487 | if (ret < 0) |
2174 | goto out; | 2488 | goto out; |
2175 | 2489 | ||
2176 | /* the txop is confed in units of 32us by the mac80211, we need us */ | 2490 | if (is_ap) |
2177 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | 2491 | wl1271_bss_info_changed_ap(wl, vif, bss_conf, changed); |
2178 | params->cw_min, params->cw_max, | 2492 | else |
2179 | params->aifs, params->txop << 5); | 2493 | wl1271_bss_info_changed_sta(wl, vif, bss_conf, changed); |
2180 | if (ret < 0) | 2494 | |
2181 | goto out_sleep; | 2495 | wl1271_ps_elp_sleep(wl); |
2496 | |||
2497 | out: | ||
2498 | mutex_unlock(&wl->mutex); | ||
2499 | } | ||
2500 | |||
2501 | static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
2502 | const struct ieee80211_tx_queue_params *params) | ||
2503 | { | ||
2504 | struct wl1271 *wl = hw->priv; | ||
2505 | u8 ps_scheme; | ||
2506 | int ret = 0; | ||
2507 | |||
2508 | mutex_lock(&wl->mutex); | ||
2509 | |||
2510 | wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue); | ||
2182 | 2511 | ||
2183 | if (params->uapsd) | 2512 | if (params->uapsd) |
2184 | ps_scheme = CONF_PS_SCHEME_UPSD_TRIGGER; | 2513 | ps_scheme = CONF_PS_SCHEME_UPSD_TRIGGER; |
2185 | else | 2514 | else |
2186 | ps_scheme = CONF_PS_SCHEME_LEGACY; | 2515 | ps_scheme = CONF_PS_SCHEME_LEGACY; |
2187 | 2516 | ||
2188 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | 2517 | if (wl->state == WL1271_STATE_OFF) { |
2189 | CONF_CHANNEL_TYPE_EDCF, | 2518 | /* |
2190 | wl1271_tx_get_queue(queue), | 2519 | * If the state is off, the parameters will be recorded and |
2191 | ps_scheme, CONF_ACK_POLICY_LEGACY, 0, 0); | 2520 | * configured on init. This happens in AP-mode. |
2192 | if (ret < 0) | 2521 | */ |
2193 | goto out_sleep; | 2522 | struct conf_tx_ac_category *conf_ac = |
2523 | &wl->conf.tx.ac_conf[wl1271_tx_get_queue(queue)]; | ||
2524 | struct conf_tx_tid *conf_tid = | ||
2525 | &wl->conf.tx.tid_conf[wl1271_tx_get_queue(queue)]; | ||
2526 | |||
2527 | conf_ac->ac = wl1271_tx_get_queue(queue); | ||
2528 | conf_ac->cw_min = (u8)params->cw_min; | ||
2529 | conf_ac->cw_max = params->cw_max; | ||
2530 | conf_ac->aifsn = params->aifs; | ||
2531 | conf_ac->tx_op_limit = params->txop << 5; | ||
2532 | |||
2533 | conf_tid->queue_id = wl1271_tx_get_queue(queue); | ||
2534 | conf_tid->channel_type = CONF_CHANNEL_TYPE_EDCF; | ||
2535 | conf_tid->tsid = wl1271_tx_get_queue(queue); | ||
2536 | conf_tid->ps_scheme = ps_scheme; | ||
2537 | conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY; | ||
2538 | conf_tid->apsd_conf[0] = 0; | ||
2539 | conf_tid->apsd_conf[1] = 0; | ||
2540 | } else { | ||
2541 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
2542 | if (ret < 0) | ||
2543 | goto out; | ||
2544 | |||
2545 | /* | ||
2546 | * the txop is confed in units of 32us by the mac80211, | ||
2547 | * we need us | ||
2548 | */ | ||
2549 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | ||
2550 | params->cw_min, params->cw_max, | ||
2551 | params->aifs, params->txop << 5); | ||
2552 | if (ret < 0) | ||
2553 | goto out_sleep; | ||
2554 | |||
2555 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | ||
2556 | CONF_CHANNEL_TYPE_EDCF, | ||
2557 | wl1271_tx_get_queue(queue), | ||
2558 | ps_scheme, CONF_ACK_POLICY_LEGACY, | ||
2559 | 0, 0); | ||
2560 | if (ret < 0) | ||
2561 | goto out_sleep; | ||
2194 | 2562 | ||
2195 | out_sleep: | 2563 | out_sleep: |
2196 | wl1271_ps_elp_sleep(wl); | 2564 | wl1271_ps_elp_sleep(wl); |
2565 | } | ||
2197 | 2566 | ||
2198 | out: | 2567 | out: |
2199 | mutex_unlock(&wl->mutex); | 2568 | mutex_unlock(&wl->mutex); |
@@ -2247,6 +2616,173 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, | |||
2247 | return 0; | 2616 | return 0; |
2248 | } | 2617 | } |
2249 | 2618 | ||
2619 | static int wl1271_allocate_hlid(struct wl1271 *wl, | ||
2620 | struct ieee80211_sta *sta, | ||
2621 | u8 *hlid) | ||
2622 | { | ||
2623 | struct wl1271_station *wl_sta; | ||
2624 | int id; | ||
2625 | |||
2626 | id = find_first_zero_bit(wl->ap_hlid_map, AP_MAX_STATIONS); | ||
2627 | if (id >= AP_MAX_STATIONS) { | ||
2628 | wl1271_warning("could not allocate HLID - too much stations"); | ||
2629 | return -EBUSY; | ||
2630 | } | ||
2631 | |||
2632 | wl_sta = (struct wl1271_station *)sta->drv_priv; | ||
2633 | |||
2634 | __set_bit(id, wl->ap_hlid_map); | ||
2635 | wl_sta->hlid = WL1271_AP_STA_HLID_START + id; | ||
2636 | *hlid = wl_sta->hlid; | ||
2637 | return 0; | ||
2638 | } | ||
2639 | |||
2640 | static void wl1271_free_hlid(struct wl1271 *wl, u8 hlid) | ||
2641 | { | ||
2642 | int id = hlid - WL1271_AP_STA_HLID_START; | ||
2643 | |||
2644 | __clear_bit(id, wl->ap_hlid_map); | ||
2645 | } | ||
2646 | |||
2647 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, | ||
2648 | struct ieee80211_vif *vif, | ||
2649 | struct ieee80211_sta *sta) | ||
2650 | { | ||
2651 | struct wl1271 *wl = hw->priv; | ||
2652 | int ret = 0; | ||
2653 | u8 hlid; | ||
2654 | |||
2655 | mutex_lock(&wl->mutex); | ||
2656 | |||
2657 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
2658 | goto out; | ||
2659 | |||
2660 | if (wl->bss_type != BSS_TYPE_AP_BSS) | ||
2661 | goto out; | ||
2662 | |||
2663 | wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); | ||
2664 | |||
2665 | ret = wl1271_allocate_hlid(wl, sta, &hlid); | ||
2666 | if (ret < 0) | ||
2667 | goto out; | ||
2668 | |||
2669 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
2670 | if (ret < 0) | ||
2671 | goto out; | ||
2672 | |||
2673 | ret = wl1271_cmd_add_sta(wl, sta, hlid); | ||
2674 | if (ret < 0) | ||
2675 | goto out_sleep; | ||
2676 | |||
2677 | out_sleep: | ||
2678 | wl1271_ps_elp_sleep(wl); | ||
2679 | |||
2680 | out: | ||
2681 | mutex_unlock(&wl->mutex); | ||
2682 | return ret; | ||
2683 | } | ||
2684 | |||
2685 | static int wl1271_op_sta_remove(struct ieee80211_hw *hw, | ||
2686 | struct ieee80211_vif *vif, | ||
2687 | struct ieee80211_sta *sta) | ||
2688 | { | ||
2689 | struct wl1271 *wl = hw->priv; | ||
2690 | struct wl1271_station *wl_sta; | ||
2691 | int ret = 0, id; | ||
2692 | |||
2693 | mutex_lock(&wl->mutex); | ||
2694 | |||
2695 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
2696 | goto out; | ||
2697 | |||
2698 | if (wl->bss_type != BSS_TYPE_AP_BSS) | ||
2699 | goto out; | ||
2700 | |||
2701 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid); | ||
2702 | |||
2703 | wl_sta = (struct wl1271_station *)sta->drv_priv; | ||
2704 | id = wl_sta->hlid - WL1271_AP_STA_HLID_START; | ||
2705 | if (WARN_ON(!test_bit(id, wl->ap_hlid_map))) | ||
2706 | goto out; | ||
2707 | |||
2708 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
2709 | if (ret < 0) | ||
2710 | goto out; | ||
2711 | |||
2712 | ret = wl1271_cmd_remove_sta(wl, wl_sta->hlid); | ||
2713 | if (ret < 0) | ||
2714 | goto out_sleep; | ||
2715 | |||
2716 | wl1271_free_hlid(wl, wl_sta->hlid); | ||
2717 | |||
2718 | out_sleep: | ||
2719 | wl1271_ps_elp_sleep(wl); | ||
2720 | |||
2721 | out: | ||
2722 | mutex_unlock(&wl->mutex); | ||
2723 | return ret; | ||
2724 | } | ||
2725 | |||
2726 | int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
2727 | enum ieee80211_ampdu_mlme_action action, | ||
2728 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, | ||
2729 | u8 buf_size) | ||
2730 | { | ||
2731 | struct wl1271 *wl = hw->priv; | ||
2732 | int ret; | ||
2733 | |||
2734 | mutex_lock(&wl->mutex); | ||
2735 | |||
2736 | if (unlikely(wl->state == WL1271_STATE_OFF)) { | ||
2737 | ret = -EAGAIN; | ||
2738 | goto out; | ||
2739 | } | ||
2740 | |||
2741 | ret = wl1271_ps_elp_wakeup(wl, false); | ||
2742 | if (ret < 0) | ||
2743 | goto out; | ||
2744 | |||
2745 | switch (action) { | ||
2746 | case IEEE80211_AMPDU_RX_START: | ||
2747 | if (wl->ba_support) { | ||
2748 | ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn, | ||
2749 | true); | ||
2750 | if (!ret) | ||
2751 | wl->ba_rx_bitmap |= BIT(tid); | ||
2752 | } else { | ||
2753 | ret = -ENOTSUPP; | ||
2754 | } | ||
2755 | break; | ||
2756 | |||
2757 | case IEEE80211_AMPDU_RX_STOP: | ||
2758 | ret = wl1271_acx_set_ba_receiver_session(wl, tid, 0, false); | ||
2759 | if (!ret) | ||
2760 | wl->ba_rx_bitmap &= ~BIT(tid); | ||
2761 | break; | ||
2762 | |||
2763 | /* | ||
2764 | * The BA initiator session management in FW independently. | ||
2765 | * Falling break here on purpose for all TX APDU commands. | ||
2766 | */ | ||
2767 | case IEEE80211_AMPDU_TX_START: | ||
2768 | case IEEE80211_AMPDU_TX_STOP: | ||
2769 | case IEEE80211_AMPDU_TX_OPERATIONAL: | ||
2770 | ret = -EINVAL; | ||
2771 | break; | ||
2772 | |||
2773 | default: | ||
2774 | wl1271_error("Incorrect ampdu action id=%x\n", action); | ||
2775 | ret = -EINVAL; | ||
2776 | } | ||
2777 | |||
2778 | wl1271_ps_elp_sleep(wl); | ||
2779 | |||
2780 | out: | ||
2781 | mutex_unlock(&wl->mutex); | ||
2782 | |||
2783 | return ret; | ||
2784 | } | ||
2785 | |||
2250 | /* can't be const, mac80211 writes to this */ | 2786 | /* can't be const, mac80211 writes to this */ |
2251 | static struct ieee80211_rate wl1271_rates[] = { | 2787 | static struct ieee80211_rate wl1271_rates[] = { |
2252 | { .bitrate = 10, | 2788 | { .bitrate = 10, |
@@ -2305,6 +2841,7 @@ static struct ieee80211_channel wl1271_channels[] = { | |||
2305 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, | 2841 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, |
2306 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, | 2842 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, |
2307 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, | 2843 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
2844 | { .hw_value = 14, .center_freq = 2484, .max_power = 25 }, | ||
2308 | }; | 2845 | }; |
2309 | 2846 | ||
2310 | /* mapping to indexes for wl1271_rates */ | 2847 | /* mapping to indexes for wl1271_rates */ |
@@ -2493,6 +3030,9 @@ static const struct ieee80211_ops wl1271_ops = { | |||
2493 | .conf_tx = wl1271_op_conf_tx, | 3030 | .conf_tx = wl1271_op_conf_tx, |
2494 | .get_tsf = wl1271_op_get_tsf, | 3031 | .get_tsf = wl1271_op_get_tsf, |
2495 | .get_survey = wl1271_op_get_survey, | 3032 | .get_survey = wl1271_op_get_survey, |
3033 | .sta_add = wl1271_op_sta_add, | ||
3034 | .sta_remove = wl1271_op_sta_remove, | ||
3035 | .ampdu_action = wl1271_op_ampdu_action, | ||
2496 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 3036 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
2497 | }; | 3037 | }; |
2498 | 3038 | ||
@@ -2607,6 +3147,18 @@ int wl1271_register_hw(struct wl1271 *wl) | |||
2607 | if (wl->mac80211_registered) | 3147 | if (wl->mac80211_registered) |
2608 | return 0; | 3148 | return 0; |
2609 | 3149 | ||
3150 | ret = wl1271_fetch_nvs(wl); | ||
3151 | if (ret == 0) { | ||
3152 | u8 *nvs_ptr = (u8 *)wl->nvs->nvs; | ||
3153 | |||
3154 | wl->mac_addr[0] = nvs_ptr[11]; | ||
3155 | wl->mac_addr[1] = nvs_ptr[10]; | ||
3156 | wl->mac_addr[2] = nvs_ptr[6]; | ||
3157 | wl->mac_addr[3] = nvs_ptr[5]; | ||
3158 | wl->mac_addr[4] = nvs_ptr[4]; | ||
3159 | wl->mac_addr[5] = nvs_ptr[3]; | ||
3160 | } | ||
3161 | |||
2610 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | 3162 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); |
2611 | 3163 | ||
2612 | ret = ieee80211_register_hw(wl->hw); | 3164 | ret = ieee80211_register_hw(wl->hw); |
@@ -2629,6 +3181,9 @@ EXPORT_SYMBOL_GPL(wl1271_register_hw); | |||
2629 | 3181 | ||
2630 | void wl1271_unregister_hw(struct wl1271 *wl) | 3182 | void wl1271_unregister_hw(struct wl1271 *wl) |
2631 | { | 3183 | { |
3184 | if (wl->state == WL1271_STATE_PLT) | ||
3185 | __wl1271_plt_stop(wl); | ||
3186 | |||
2632 | unregister_netdevice_notifier(&wl1271_dev_notifier); | 3187 | unregister_netdevice_notifier(&wl1271_dev_notifier); |
2633 | ieee80211_unregister_hw(wl->hw); | 3188 | ieee80211_unregister_hw(wl->hw); |
2634 | wl->mac80211_registered = false; | 3189 | wl->mac80211_registered = false; |
@@ -2667,7 +3222,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2667 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 3222 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
2668 | 3223 | ||
2669 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 3224 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2670 | BIT(NL80211_IFTYPE_ADHOC); | 3225 | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); |
2671 | wl->hw->wiphy->max_scan_ssids = 1; | 3226 | wl->hw->wiphy->max_scan_ssids = 1; |
2672 | /* | 3227 | /* |
2673 | * Maximum length of elements in scanning probe request templates | 3228 | * Maximum length of elements in scanning probe request templates |
@@ -2676,8 +3231,20 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2676 | */ | 3231 | */ |
2677 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - | 3232 | wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - |
2678 | sizeof(struct ieee80211_header); | 3233 | sizeof(struct ieee80211_header); |
2679 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; | 3234 | |
2680 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | 3235 | /* |
3236 | * We keep local copies of the band structs because we need to | ||
3237 | * modify them on a per-device basis. | ||
3238 | */ | ||
3239 | memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz, | ||
3240 | sizeof(wl1271_band_2ghz)); | ||
3241 | memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz, | ||
3242 | sizeof(wl1271_band_5ghz)); | ||
3243 | |||
3244 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | ||
3245 | &wl->bands[IEEE80211_BAND_2GHZ]; | ||
3246 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | ||
3247 | &wl->bands[IEEE80211_BAND_5GHZ]; | ||
2681 | 3248 | ||
2682 | wl->hw->queues = 4; | 3249 | wl->hw->queues = 4; |
2683 | wl->hw->max_rates = 1; | 3250 | wl->hw->max_rates = 1; |
@@ -2686,6 +3253,10 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2686 | 3253 | ||
2687 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); | 3254 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); |
2688 | 3255 | ||
3256 | wl->hw->sta_data_size = sizeof(struct wl1271_station); | ||
3257 | |||
3258 | wl->hw->max_rx_aggregation_subframes = 8; | ||
3259 | |||
2689 | return 0; | 3260 | return 0; |
2690 | } | 3261 | } |
2691 | EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); | 3262 | EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); |
@@ -2735,8 +3306,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2735 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | 3306 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; |
2736 | wl->default_key = 0; | 3307 | wl->default_key = 0; |
2737 | wl->rx_counter = 0; | 3308 | wl->rx_counter = 0; |
2738 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 3309 | wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG; |
2739 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | 3310 | wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER; |
2740 | wl->psm_entry_retry = 0; | 3311 | wl->psm_entry_retry = 0; |
2741 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 3312 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
2742 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; | 3313 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
@@ -2748,6 +3319,9 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2748 | wl->flags = 0; | 3319 | wl->flags = 0; |
2749 | wl->sg_enabled = true; | 3320 | wl->sg_enabled = true; |
2750 | wl->hw_pg_ver = -1; | 3321 | wl->hw_pg_ver = -1; |
3322 | wl->bss_type = MAX_BSS_TYPE; | ||
3323 | wl->set_bss_type = MAX_BSS_TYPE; | ||
3324 | wl->fw_bss_type = MAX_BSS_TYPE; | ||
2751 | 3325 | ||
2752 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); | 3326 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); |
2753 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 3327 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
@@ -2837,9 +3411,9 @@ int wl1271_free_hw(struct wl1271 *wl) | |||
2837 | } | 3411 | } |
2838 | EXPORT_SYMBOL_GPL(wl1271_free_hw); | 3412 | EXPORT_SYMBOL_GPL(wl1271_free_hw); |
2839 | 3413 | ||
2840 | u32 wl12xx_debug_level; | 3414 | u32 wl12xx_debug_level = DEBUG_NONE; |
2841 | EXPORT_SYMBOL_GPL(wl12xx_debug_level); | 3415 | EXPORT_SYMBOL_GPL(wl12xx_debug_level); |
2842 | module_param_named(debug_level, wl12xx_debug_level, uint, DEBUG_NONE); | 3416 | module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR); |
2843 | MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); | 3417 | MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); |
2844 | 3418 | ||
2845 | MODULE_LICENSE("GPL"); | 3419 | MODULE_LICENSE("GPL"); |