diff options
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.c | 51 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/acx.h | 41 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/boot.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/conf.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/init.c | 42 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/wl12xx/wl12xx.h | 17 |
7 files changed, 183 insertions, 10 deletions
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index 679bb37f0ca4..0b9cacc74903 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c | |||
@@ -1342,6 +1342,57 @@ out: | |||
1342 | return ret; | 1342 | return ret; |
1343 | } | 1343 | } |
1344 | 1344 | ||
1345 | /* Configure BA session initiator/receiver parameters setting in the FW. */ | ||
1346 | int wl1271_acx_set_ba_session(struct wl1271 *wl, | ||
1347 | enum ieee80211_back_parties direction, | ||
1348 | u8 tid_index, u8 policy) | ||
1349 | { | ||
1350 | struct wl1271_acx_ba_session_policy *acx; | ||
1351 | int ret; | ||
1352 | |||
1353 | wl1271_debug(DEBUG_ACX, "acx ba session setting"); | ||
1354 | |||
1355 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1356 | if (!acx) { | ||
1357 | ret = -ENOMEM; | ||
1358 | goto out; | ||
1359 | } | ||
1360 | |||
1361 | /* ANY role */ | ||
1362 | acx->role_id = 0xff; | ||
1363 | acx->tid = tid_index; | ||
1364 | acx->enable = policy; | ||
1365 | acx->ba_direction = direction; | ||
1366 | |||
1367 | switch (direction) { | ||
1368 | case WLAN_BACK_INITIATOR: | ||
1369 | acx->win_size = wl->conf.ht.tx_ba_win_size; | ||
1370 | acx->inactivity_timeout = wl->conf.ht.inactivity_timeout; | ||
1371 | break; | ||
1372 | case WLAN_BACK_RECIPIENT: | ||
1373 | acx->win_size = RX_BA_WIN_SIZE; | ||
1374 | acx->inactivity_timeout = 0; | ||
1375 | break; | ||
1376 | default: | ||
1377 | wl1271_error("Incorrect acx command id=%x\n", direction); | ||
1378 | ret = -EINVAL; | ||
1379 | goto out; | ||
1380 | } | ||
1381 | |||
1382 | ret = wl1271_cmd_configure(wl, | ||
1383 | ACX_BA_SESSION_POLICY_CFG, | ||
1384 | acx, | ||
1385 | sizeof(*acx)); | ||
1386 | if (ret < 0) { | ||
1387 | wl1271_warning("acx ba session setting failed: %d", ret); | ||
1388 | goto out; | ||
1389 | } | ||
1390 | |||
1391 | out: | ||
1392 | kfree(acx); | ||
1393 | return ret; | ||
1394 | } | ||
1395 | |||
1345 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) | 1396 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) |
1346 | { | 1397 | { |
1347 | struct wl1271_acx_fw_tsf_information *tsf_info; | 1398 | struct wl1271_acx_fw_tsf_information *tsf_info; |
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 62a269d84ebe..f643e60a566b 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h | |||
@@ -1061,6 +1061,40 @@ struct wl1271_acx_ht_information { | |||
1061 | u8 padding[3]; | 1061 | u8 padding[3]; |
1062 | } __packed; | 1062 | } __packed; |
1063 | 1063 | ||
1064 | #define RX_BA_WIN_SIZE 8 | ||
1065 | |||
1066 | struct wl1271_acx_ba_session_policy { | ||
1067 | struct acx_header header; | ||
1068 | /* | ||
1069 | * Specifies role Id, Range 0-7, 0xFF means ANY role. | ||
1070 | * Future use. For now this field is irrelevant | ||
1071 | */ | ||
1072 | u8 role_id; | ||
1073 | /* | ||
1074 | * Specifies Link Id, Range 0-31, 0xFF means ANY Link Id. | ||
1075 | * Not applicable if Role Id is set to ANY. | ||
1076 | */ | ||
1077 | u8 link_id; | ||
1078 | |||
1079 | u8 tid; | ||
1080 | |||
1081 | u8 enable; | ||
1082 | |||
1083 | /* Windows size in number of packets */ | ||
1084 | u16 win_size; | ||
1085 | |||
1086 | /* | ||
1087 | * As initiator inactivity timeout in time units(TU) of 1024us. | ||
1088 | * As receiver reserved | ||
1089 | */ | ||
1090 | u16 inactivity_timeout; | ||
1091 | |||
1092 | /* Initiator = 1/Receiver = 0 */ | ||
1093 | u8 ba_direction; | ||
1094 | |||
1095 | u8 padding[3]; | ||
1096 | } __packed; | ||
1097 | |||
1064 | struct wl1271_acx_fw_tsf_information { | 1098 | struct wl1271_acx_fw_tsf_information { |
1065 | struct acx_header header; | 1099 | struct acx_header header; |
1066 | 1100 | ||
@@ -1134,8 +1168,8 @@ enum { | |||
1134 | ACX_RSSI_SNR_WEIGHTS = 0x0052, | 1168 | ACX_RSSI_SNR_WEIGHTS = 0x0052, |
1135 | ACX_KEEP_ALIVE_MODE = 0x0053, | 1169 | ACX_KEEP_ALIVE_MODE = 0x0053, |
1136 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, | 1170 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, |
1137 | ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, | 1171 | ACX_BA_SESSION_POLICY_CFG = 0x0055, |
1138 | ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, | 1172 | ACX_BA_SESSION_RX_SETUP = 0x0056, |
1139 | ACX_PEER_HT_CAP = 0x0057, | 1173 | ACX_PEER_HT_CAP = 0x0057, |
1140 | ACX_HT_BSS_OPERATION = 0x0058, | 1174 | ACX_HT_BSS_OPERATION = 0x0058, |
1141 | ACX_COEX_ACTIVITY = 0x0059, | 1175 | ACX_COEX_ACTIVITY = 0x0059, |
@@ -1209,6 +1243,9 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl, | |||
1209 | bool allow_ht_operation); | 1243 | bool allow_ht_operation); |
1210 | int wl1271_acx_set_ht_information(struct wl1271 *wl, | 1244 | int wl1271_acx_set_ht_information(struct wl1271 *wl, |
1211 | u16 ht_operation_mode); | 1245 | u16 ht_operation_mode); |
1246 | int wl1271_acx_set_ba_session(struct wl1271 *wl, | ||
1247 | enum ieee80211_back_parties direction, | ||
1248 | u8 tid_index, u8 policy); | ||
1212 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); | 1249 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); |
1213 | int wl1271_acx_max_tx_retry(struct wl1271 *wl); | 1250 | int wl1271_acx_max_tx_retry(struct wl1271 *wl); |
1214 | 1251 | ||
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index d7e036f42958..1ffbad67d2d8 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c | |||
@@ -101,6 +101,22 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | |||
101 | wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); | 101 | wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); |
102 | } | 102 | } |
103 | 103 | ||
104 | static void wl1271_parse_fw_ver(struct wl1271 *wl) | ||
105 | { | ||
106 | int ret; | ||
107 | |||
108 | ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u", | ||
109 | &wl->chip.fw_ver[0], &wl->chip.fw_ver[1], | ||
110 | &wl->chip.fw_ver[2], &wl->chip.fw_ver[3], | ||
111 | &wl->chip.fw_ver[4]); | ||
112 | |||
113 | if (ret != 5) { | ||
114 | wl1271_warning("fw version incorrect value"); | ||
115 | memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver)); | ||
116 | return; | ||
117 | } | ||
118 | } | ||
119 | |||
104 | static void wl1271_boot_fw_version(struct wl1271 *wl) | 120 | static void wl1271_boot_fw_version(struct wl1271 *wl) |
105 | { | 121 | { |
106 | struct wl1271_static_data static_data; | 122 | struct wl1271_static_data static_data; |
@@ -108,11 +124,13 @@ static void wl1271_boot_fw_version(struct wl1271 *wl) | |||
108 | wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data), | 124 | wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data), |
109 | false); | 125 | false); |
110 | 126 | ||
111 | strncpy(wl->chip.fw_ver, static_data.fw_version, | 127 | strncpy(wl->chip.fw_ver_str, static_data.fw_version, |
112 | sizeof(wl->chip.fw_ver)); | 128 | sizeof(wl->chip.fw_ver_str)); |
113 | 129 | ||
114 | /* make sure the string is NULL-terminated */ | 130 | /* make sure the string is NULL-terminated */ |
115 | wl->chip.fw_ver[sizeof(wl->chip.fw_ver) - 1] = '\0'; | 131 | wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0'; |
132 | |||
133 | wl1271_parse_fw_ver(wl); | ||
116 | } | 134 | } |
117 | 135 | ||
118 | static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | 136 | static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, |
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index f5c048c9bea4..135d837cefb1 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h | |||
@@ -1138,6 +1138,11 @@ struct conf_rf_settings { | |||
1138 | u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; | 1138 | u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5]; |
1139 | }; | 1139 | }; |
1140 | 1140 | ||
1141 | struct conf_ht_setting { | ||
1142 | u16 tx_ba_win_size; | ||
1143 | u16 inactivity_timeout; | ||
1144 | }; | ||
1145 | |||
1141 | struct conf_drv_settings { | 1146 | struct conf_drv_settings { |
1142 | struct conf_sg_settings sg; | 1147 | struct conf_sg_settings sg; |
1143 | struct conf_rx_settings rx; | 1148 | struct conf_rx_settings rx; |
@@ -1148,6 +1153,7 @@ struct conf_drv_settings { | |||
1148 | struct conf_roam_trigger_settings roam_trigger; | 1153 | struct conf_roam_trigger_settings roam_trigger; |
1149 | struct conf_scan_settings scan; | 1154 | struct conf_scan_settings scan; |
1150 | struct conf_rf_settings rf; | 1155 | struct conf_rf_settings rf; |
1156 | struct conf_ht_setting ht; | ||
1151 | }; | 1157 | }; |
1152 | 1158 | ||
1153 | #endif | 1159 | #endif |
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index bdb61232f80c..2348eadc0de1 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c | |||
@@ -455,6 +455,43 @@ static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) | |||
455 | return 0; | 455 | return 0; |
456 | } | 456 | } |
457 | 457 | ||
458 | static void wl1271_check_ba_support(struct wl1271 *wl) | ||
459 | { | ||
460 | /* validate FW cose ver x.x.x.50-60.x */ | ||
461 | if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) && | ||
462 | (wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) { | ||
463 | wl->ba_support = true; | ||
464 | return; | ||
465 | } | ||
466 | |||
467 | wl->ba_support = false; | ||
468 | } | ||
469 | |||
470 | static int wl1271_set_ba_policies(struct wl1271 *wl) | ||
471 | { | ||
472 | u8 tid_index; | ||
473 | u8 ret = 0; | ||
474 | |||
475 | /* Reset the BA RX indicators */ | ||
476 | wl->ba_allowed = true; | ||
477 | wl->ba_rx_bitmap = 0; | ||
478 | |||
479 | /* validate that FW support BA */ | ||
480 | wl1271_check_ba_support(wl); | ||
481 | |||
482 | if (wl->ba_support) | ||
483 | /* 802.11n initiator BA session setting */ | ||
484 | for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT; | ||
485 | ++tid_index) { | ||
486 | ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR, | ||
487 | tid_index, true); | ||
488 | if (ret < 0) | ||
489 | break; | ||
490 | } | ||
491 | |||
492 | return ret; | ||
493 | } | ||
494 | |||
458 | int wl1271_hw_init(struct wl1271 *wl) | 495 | int wl1271_hw_init(struct wl1271 *wl) |
459 | { | 496 | { |
460 | struct conf_tx_ac_category *conf_ac; | 497 | struct conf_tx_ac_category *conf_ac; |
@@ -568,6 +605,11 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
568 | if (ret < 0) | 605 | if (ret < 0) |
569 | goto out_free_memmap; | 606 | goto out_free_memmap; |
570 | 607 | ||
608 | /* Configure initiator BA sessions policies */ | ||
609 | ret = wl1271_set_ba_policies(wl); | ||
610 | if (ret < 0) | ||
611 | goto out_free_memmap; | ||
612 | |||
571 | return 0; | 613 | return 0; |
572 | 614 | ||
573 | out_free_memmap: | 615 | out_free_memmap: |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 48194629c00b..01ca666b6c2d 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -274,7 +274,7 @@ static struct conf_drv_settings default_conf = { | |||
274 | .avg_weight_rssi_beacon = 20, | 274 | .avg_weight_rssi_beacon = 20, |
275 | .avg_weight_rssi_data = 10, | 275 | .avg_weight_rssi_data = 10, |
276 | .avg_weight_snr_beacon = 20, | 276 | .avg_weight_snr_beacon = 20, |
277 | .avg_weight_snr_data = 10 | 277 | .avg_weight_snr_data = 10, |
278 | }, | 278 | }, |
279 | .scan = { | 279 | .scan = { |
280 | .min_dwell_time_active = 7500, | 280 | .min_dwell_time_active = 7500, |
@@ -293,6 +293,10 @@ static struct conf_drv_settings default_conf = { | |||
293 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 293 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
294 | }, | 294 | }, |
295 | }, | 295 | }, |
296 | .ht = { | ||
297 | .tx_ba_win_size = 64, | ||
298 | .inactivity_timeout = 10000, | ||
299 | }, | ||
296 | }; | 300 | }; |
297 | 301 | ||
298 | static void __wl1271_op_remove_interface(struct wl1271 *wl); | 302 | static void __wl1271_op_remove_interface(struct wl1271 *wl); |
@@ -890,7 +894,7 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
890 | 894 | ||
891 | wl->state = WL1271_STATE_PLT; | 895 | wl->state = WL1271_STATE_PLT; |
892 | wl1271_notice("firmware booted in PLT mode (%s)", | 896 | wl1271_notice("firmware booted in PLT mode (%s)", |
893 | wl->chip.fw_ver); | 897 | wl->chip.fw_ver_str); |
894 | goto out; | 898 | goto out; |
895 | 899 | ||
896 | irq_disable: | 900 | irq_disable: |
@@ -1138,11 +1142,11 @@ power_off: | |||
1138 | 1142 | ||
1139 | wl->vif = vif; | 1143 | wl->vif = vif; |
1140 | wl->state = WL1271_STATE_ON; | 1144 | wl->state = WL1271_STATE_ON; |
1141 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); | 1145 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); |
1142 | 1146 | ||
1143 | /* update hw/fw version info in wiphy struct */ | 1147 | /* update hw/fw version info in wiphy struct */ |
1144 | wiphy->hw_version = wl->chip.id; | 1148 | wiphy->hw_version = wl->chip.id; |
1145 | strncpy(wiphy->fw_version, wl->chip.fw_ver, | 1149 | strncpy(wiphy->fw_version, wl->chip.fw_ver_str, |
1146 | sizeof(wiphy->fw_version)); | 1150 | sizeof(wiphy->fw_version)); |
1147 | 1151 | ||
1148 | /* | 1152 | /* |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index ca727e0c4ce9..e0bac79cd516 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -38,6 +38,13 @@ | |||
38 | #define DRIVER_NAME "wl1271" | 38 | #define DRIVER_NAME "wl1271" |
39 | #define DRIVER_PREFIX DRIVER_NAME ": " | 39 | #define DRIVER_PREFIX DRIVER_NAME ": " |
40 | 40 | ||
41 | /* | ||
42 | * FW versions support BA 11n | ||
43 | * versions marks x.x.x.50-60.x | ||
44 | */ | ||
45 | #define WL12XX_BA_SUPPORT_FW_COST_VER2_START 50 | ||
46 | #define WL12XX_BA_SUPPORT_FW_COST_VER2_END 60 | ||
47 | |||
41 | enum { | 48 | enum { |
42 | DEBUG_NONE = 0, | 49 | DEBUG_NONE = 0, |
43 | DEBUG_IRQ = BIT(0), | 50 | DEBUG_IRQ = BIT(0), |
@@ -182,10 +189,13 @@ struct wl1271_partition_set { | |||
182 | 189 | ||
183 | struct wl1271; | 190 | struct wl1271; |
184 | 191 | ||
192 | #define WL12XX_NUM_FW_VER 5 | ||
193 | |||
185 | /* FIXME: I'm not sure about this structure name */ | 194 | /* FIXME: I'm not sure about this structure name */ |
186 | struct wl1271_chip { | 195 | struct wl1271_chip { |
187 | u32 id; | 196 | u32 id; |
188 | char fw_ver[21]; | 197 | char fw_ver_str[ETHTOOL_BUSINFO_LEN]; |
198 | unsigned int fw_ver[WL12XX_NUM_FW_VER]; | ||
189 | }; | 199 | }; |
190 | 200 | ||
191 | struct wl1271_stats { | 201 | struct wl1271_stats { |
@@ -460,6 +470,11 @@ struct wl1271 { | |||
460 | 470 | ||
461 | /* bands supported by this instance of wl12xx */ | 471 | /* bands supported by this instance of wl12xx */ |
462 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | 472 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; |
473 | |||
474 | /* RX BA constraint value */ | ||
475 | bool ba_support; | ||
476 | u8 ba_allowed; | ||
477 | u8 ba_rx_bitmap; | ||
463 | }; | 478 | }; |
464 | 479 | ||
465 | struct wl1271_station { | 480 | struct wl1271_station { |