diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_main.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_main.c | 393 |
1 files changed, 316 insertions, 77 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index aa970b759dd5..814f300c3f17 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -117,8 +117,7 @@ static struct conf_drv_settings default_conf = { | |||
117 | .tx = { | 117 | .tx = { |
118 | .tx_energy_detection = 0, | 118 | .tx_energy_detection = 0, |
119 | .rc_conf = { | 119 | .rc_conf = { |
120 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS | | 120 | .enabled_rates = 0, |
121 | CONF_HW_BIT_RATE_2MBPS, | ||
122 | .short_retry_limit = 10, | 121 | .short_retry_limit = 10, |
123 | .long_retry_limit = 10, | 122 | .long_retry_limit = 10, |
124 | .aflags = 0 | 123 | .aflags = 0 |
@@ -215,11 +214,13 @@ static struct conf_drv_settings default_conf = { | |||
215 | }, | 214 | }, |
216 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 215 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
217 | .tx_compl_timeout = 700, | 216 | .tx_compl_timeout = 700, |
218 | .tx_compl_threshold = 4 | 217 | .tx_compl_threshold = 4, |
218 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, | ||
219 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, | ||
219 | }, | 220 | }, |
220 | .conn = { | 221 | .conn = { |
221 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 222 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
222 | .listen_interval = 0, | 223 | .listen_interval = 1, |
223 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | 224 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, |
224 | .bcn_filt_ie_count = 1, | 225 | .bcn_filt_ie_count = 1, |
225 | .bcn_filt_ie = { | 226 | .bcn_filt_ie = { |
@@ -234,38 +235,11 @@ static struct conf_drv_settings default_conf = { | |||
234 | .broadcast_timeout = 20000, | 235 | .broadcast_timeout = 20000, |
235 | .rx_broadcast_in_ps = 1, | 236 | .rx_broadcast_in_ps = 1, |
236 | .ps_poll_threshold = 20, | 237 | .ps_poll_threshold = 20, |
237 | .sig_trigger_count = 2, | ||
238 | .sig_trigger = { | ||
239 | [0] = { | ||
240 | .threshold = -75, | ||
241 | .pacing = 500, | ||
242 | .metric = CONF_TRIG_METRIC_RSSI_BEACON, | ||
243 | .type = CONF_TRIG_EVENT_TYPE_EDGE, | ||
244 | .direction = CONF_TRIG_EVENT_DIR_LOW, | ||
245 | .hysteresis = 2, | ||
246 | .index = 0, | ||
247 | .enable = 1 | ||
248 | }, | ||
249 | [1] = { | ||
250 | .threshold = -75, | ||
251 | .pacing = 500, | ||
252 | .metric = CONF_TRIG_METRIC_RSSI_BEACON, | ||
253 | .type = CONF_TRIG_EVENT_TYPE_EDGE, | ||
254 | .direction = CONF_TRIG_EVENT_DIR_HIGH, | ||
255 | .hysteresis = 2, | ||
256 | .index = 1, | ||
257 | .enable = 1 | ||
258 | } | ||
259 | }, | ||
260 | .sig_weights = { | ||
261 | .rssi_bcn_avg_weight = 10, | ||
262 | .rssi_pkt_avg_weight = 10, | ||
263 | .snr_bcn_avg_weight = 10, | ||
264 | .snr_pkt_avg_weight = 10 | ||
265 | }, | ||
266 | .bet_enable = CONF_BET_MODE_ENABLE, | 238 | .bet_enable = CONF_BET_MODE_ENABLE, |
267 | .bet_max_consecutive = 10, | 239 | .bet_max_consecutive = 10, |
268 | .psm_entry_retries = 3 | 240 | .psm_entry_retries = 3, |
241 | .keep_alive_interval = 55000, | ||
242 | .max_listen_interval = 20, | ||
269 | }, | 243 | }, |
270 | .init = { | 244 | .init = { |
271 | .radioparam = { | 245 | .radioparam = { |
@@ -279,6 +253,14 @@ static struct conf_drv_settings default_conf = { | |||
279 | .pm_config = { | 253 | .pm_config = { |
280 | .host_clk_settling_time = 5000, | 254 | .host_clk_settling_time = 5000, |
281 | .host_fast_wakeup_support = false | 255 | .host_fast_wakeup_support = false |
256 | }, | ||
257 | .roam_trigger = { | ||
258 | /* FIXME: due to firmware bug, must use value 1 for now */ | ||
259 | .trigger_pacing = 1, | ||
260 | .avg_weight_rssi_beacon = 20, | ||
261 | .avg_weight_rssi_data = 10, | ||
262 | .avg_weight_snr_beacon = 20, | ||
263 | .avg_weight_snr_data = 10 | ||
282 | } | 264 | } |
283 | }; | 265 | }; |
284 | 266 | ||
@@ -349,7 +331,7 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
349 | goto out_free_memmap; | 331 | goto out_free_memmap; |
350 | 332 | ||
351 | /* Initialize connection monitoring thresholds */ | 333 | /* Initialize connection monitoring thresholds */ |
352 | ret = wl1271_acx_conn_monit_params(wl); | 334 | ret = wl1271_acx_conn_monit_params(wl, false); |
353 | if (ret < 0) | 335 | if (ret < 0) |
354 | goto out_free_memmap; | 336 | goto out_free_memmap; |
355 | 337 | ||
@@ -959,9 +941,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
959 | switch (vif->type) { | 941 | switch (vif->type) { |
960 | case NL80211_IFTYPE_STATION: | 942 | case NL80211_IFTYPE_STATION: |
961 | wl->bss_type = BSS_TYPE_STA_BSS; | 943 | wl->bss_type = BSS_TYPE_STA_BSS; |
944 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
962 | break; | 945 | break; |
963 | case NL80211_IFTYPE_ADHOC: | 946 | case NL80211_IFTYPE_ADHOC: |
964 | wl->bss_type = BSS_TYPE_IBSS; | 947 | wl->bss_type = BSS_TYPE_IBSS; |
948 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
965 | break; | 949 | break; |
966 | default: | 950 | default: |
967 | ret = -EOPNOTSUPP; | 951 | ret = -EOPNOTSUPP; |
@@ -1066,6 +1050,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1066 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); | 1050 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); |
1067 | wl->ssid_len = 0; | 1051 | wl->ssid_len = 0; |
1068 | wl->bss_type = MAX_BSS_TYPE; | 1052 | wl->bss_type = MAX_BSS_TYPE; |
1053 | wl->set_bss_type = MAX_BSS_TYPE; | ||
1069 | wl->band = IEEE80211_BAND_2GHZ; | 1054 | wl->band = IEEE80211_BAND_2GHZ; |
1070 | 1055 | ||
1071 | wl->rx_counter = 0; | 1056 | wl->rx_counter = 0; |
@@ -1088,6 +1073,14 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1088 | wl->tx_blocks_freed[i] = 0; | 1073 | wl->tx_blocks_freed[i] = 0; |
1089 | 1074 | ||
1090 | wl1271_debugfs_reset(wl); | 1075 | wl1271_debugfs_reset(wl); |
1076 | |||
1077 | kfree(wl->fw_status); | ||
1078 | wl->fw_status = NULL; | ||
1079 | kfree(wl->tx_res_if); | ||
1080 | wl->tx_res_if = NULL; | ||
1081 | kfree(wl->target_mem_map); | ||
1082 | wl->target_mem_map = NULL; | ||
1083 | |||
1091 | mutex_unlock(&wl->mutex); | 1084 | mutex_unlock(&wl->mutex); |
1092 | } | 1085 | } |
1093 | 1086 | ||
@@ -1138,10 +1131,7 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel) | |||
1138 | /* pass through frames from all BSS */ | 1131 | /* pass through frames from all BSS */ |
1139 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | 1132 | wl1271_configure_filters(wl, FIF_OTHER_BSS); |
1140 | 1133 | ||
1141 | /* the dummy join is performed always with STATION BSS type to allow | 1134 | ret = wl1271_cmd_join(wl, wl->set_bss_type); |
1142 | also ad-hoc mode to listen to the surroundings without sending any | ||
1143 | beacons yet. */ | ||
1144 | ret = wl1271_cmd_join(wl, BSS_TYPE_STA_BSS); | ||
1145 | if (ret < 0) | 1135 | if (ret < 0) |
1146 | goto out; | 1136 | goto out; |
1147 | 1137 | ||
@@ -1171,6 +1161,32 @@ out: | |||
1171 | return ret; | 1161 | return ret; |
1172 | } | 1162 | } |
1173 | 1163 | ||
1164 | static void wl1271_set_band_rate(struct wl1271 *wl) | ||
1165 | { | ||
1166 | if (wl->band == IEEE80211_BAND_2GHZ) | ||
1167 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1168 | else | ||
1169 | wl->basic_rate_set = wl->conf.tx.basic_rate_5; | ||
1170 | } | ||
1171 | |||
1172 | static u32 wl1271_min_rate_get(struct wl1271 *wl) | ||
1173 | { | ||
1174 | int i; | ||
1175 | u32 rate = 0; | ||
1176 | |||
1177 | if (!wl->basic_rate_set) { | ||
1178 | WARN_ON(1); | ||
1179 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1180 | } | ||
1181 | |||
1182 | for (i = 0; !rate; i++) { | ||
1183 | if ((wl->basic_rate_set >> i) & 0x1) | ||
1184 | rate = 1 << i; | ||
1185 | } | ||
1186 | |||
1187 | return rate; | ||
1188 | } | ||
1189 | |||
1174 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1190 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1175 | { | 1191 | { |
1176 | struct wl1271 *wl = hw->priv; | 1192 | struct wl1271 *wl = hw->priv; |
@@ -1187,12 +1203,41 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1187 | 1203 | ||
1188 | mutex_lock(&wl->mutex); | 1204 | mutex_lock(&wl->mutex); |
1189 | 1205 | ||
1190 | wl->band = conf->channel->band; | 1206 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
1207 | goto out; | ||
1191 | 1208 | ||
1192 | ret = wl1271_ps_elp_wakeup(wl, false); | 1209 | ret = wl1271_ps_elp_wakeup(wl, false); |
1193 | if (ret < 0) | 1210 | if (ret < 0) |
1194 | goto out; | 1211 | goto out; |
1195 | 1212 | ||
1213 | /* if the channel changes while joined, join again */ | ||
1214 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
1215 | wl->band = conf->channel->band; | ||
1216 | wl->channel = channel; | ||
1217 | |||
1218 | /* | ||
1219 | * FIXME: the mac80211 should really provide a fixed rate | ||
1220 | * to use here. for now, just use the smallest possible rate | ||
1221 | * for the band as a fixed rate for association frames and | ||
1222 | * other control messages. | ||
1223 | */ | ||
1224 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
1225 | wl1271_set_band_rate(wl); | ||
1226 | |||
1227 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1228 | ret = wl1271_acx_rate_policies(wl); | ||
1229 | if (ret < 0) | ||
1230 | wl1271_warning("rate policy for update channel " | ||
1231 | "failed %d", ret); | ||
1232 | |||
1233 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1234 | ret = wl1271_cmd_join(wl, wl->set_bss_type); | ||
1235 | if (ret < 0) | ||
1236 | wl1271_warning("cmd join to update channel " | ||
1237 | "failed %d", ret); | ||
1238 | } | ||
1239 | } | ||
1240 | |||
1196 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1241 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1197 | if (conf->flags & IEEE80211_CONF_IDLE && | 1242 | if (conf->flags & IEEE80211_CONF_IDLE && |
1198 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) | 1243 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
@@ -1201,24 +1246,17 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1201 | wl1271_join_channel(wl, channel); | 1246 | wl1271_join_channel(wl, channel); |
1202 | 1247 | ||
1203 | if (conf->flags & IEEE80211_CONF_IDLE) { | 1248 | if (conf->flags & IEEE80211_CONF_IDLE) { |
1204 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1249 | wl->rate_set = wl1271_min_rate_get(wl); |
1205 | wl->sta_rate_set = 0; | 1250 | wl->sta_rate_set = 0; |
1206 | wl1271_acx_rate_policies(wl); | 1251 | wl1271_acx_rate_policies(wl); |
1207 | } | 1252 | wl1271_acx_keep_alive_config( |
1253 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1254 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
1255 | set_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1256 | } else | ||
1257 | clear_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1208 | } | 1258 | } |
1209 | 1259 | ||
1210 | /* if the channel changes while joined, join again */ | ||
1211 | if (channel != wl->channel && | ||
1212 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1213 | wl->channel = channel; | ||
1214 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ | ||
1215 | ret = wl1271_cmd_join(wl, wl->bss_type); | ||
1216 | if (ret < 0) | ||
1217 | wl1271_warning("cmd join to update channel failed %d", | ||
1218 | ret); | ||
1219 | } else | ||
1220 | wl->channel = channel; | ||
1221 | |||
1222 | if (conf->flags & IEEE80211_CONF_PS && | 1260 | if (conf->flags & IEEE80211_CONF_PS && |
1223 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1261 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1224 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1262 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
@@ -1272,6 +1310,11 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, | |||
1272 | { | 1310 | { |
1273 | struct wl1271_filter_params *fp; | 1311 | struct wl1271_filter_params *fp; |
1274 | struct netdev_hw_addr *ha; | 1312 | struct netdev_hw_addr *ha; |
1313 | struct wl1271 *wl = hw->priv; | ||
1314 | int i; | ||
1315 | |||
1316 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1317 | return 0; | ||
1275 | 1318 | ||
1276 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); | 1319 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); |
1277 | if (!fp) { | 1320 | if (!fp) { |
@@ -1314,15 +1357,16 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1314 | 1357 | ||
1315 | mutex_lock(&wl->mutex); | 1358 | mutex_lock(&wl->mutex); |
1316 | 1359 | ||
1317 | if (wl->state == WL1271_STATE_OFF) | 1360 | *total &= WL1271_SUPPORTED_FILTERS; |
1361 | changed &= WL1271_SUPPORTED_FILTERS; | ||
1362 | |||
1363 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1318 | goto out; | 1364 | goto out; |
1319 | 1365 | ||
1320 | ret = wl1271_ps_elp_wakeup(wl, false); | 1366 | ret = wl1271_ps_elp_wakeup(wl, false); |
1321 | if (ret < 0) | 1367 | if (ret < 0) |
1322 | goto out; | 1368 | goto out; |
1323 | 1369 | ||
1324 | *total &= WL1271_SUPPORTED_FILTERS; | ||
1325 | changed &= WL1271_SUPPORTED_FILTERS; | ||
1326 | 1370 | ||
1327 | if (*total & FIF_ALLMULTI) | 1371 | if (*total & FIF_ALLMULTI) |
1328 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); | 1372 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); |
@@ -1516,10 +1560,13 @@ out: | |||
1516 | static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 1560 | static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
1517 | { | 1561 | { |
1518 | struct wl1271 *wl = hw->priv; | 1562 | struct wl1271 *wl = hw->priv; |
1519 | int ret; | 1563 | int ret = 0; |
1520 | 1564 | ||
1521 | mutex_lock(&wl->mutex); | 1565 | mutex_lock(&wl->mutex); |
1522 | 1566 | ||
1567 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1568 | goto out; | ||
1569 | |||
1523 | ret = wl1271_ps_elp_wakeup(wl, false); | 1570 | ret = wl1271_ps_elp_wakeup(wl, false); |
1524 | if (ret < 0) | 1571 | if (ret < 0) |
1525 | goto out; | 1572 | goto out; |
@@ -1561,6 +1608,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1561 | enum wl1271_cmd_ps_mode mode; | 1608 | enum wl1271_cmd_ps_mode mode; |
1562 | struct wl1271 *wl = hw->priv; | 1609 | struct wl1271 *wl = hw->priv; |
1563 | bool do_join = false; | 1610 | bool do_join = false; |
1611 | bool do_keepalive = false; | ||
1564 | int ret; | 1612 | int ret; |
1565 | 1613 | ||
1566 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 1614 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
@@ -1571,20 +1619,29 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1571 | if (ret < 0) | 1619 | if (ret < 0) |
1572 | goto out; | 1620 | goto out; |
1573 | 1621 | ||
1574 | if (wl->bss_type == BSS_TYPE_IBSS) { | 1622 | if ((changed && BSS_CHANGED_BEACON_INT) && |
1575 | /* FIXME: This implements rudimentary ad-hoc support - | 1623 | (wl->bss_type == BSS_TYPE_IBSS)) { |
1576 | proper templates are on the wish list and notification | 1624 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", |
1577 | on when they change. This patch will update the templates | 1625 | bss_conf->beacon_int); |
1578 | on every call to this function. */ | 1626 | |
1627 | wl->beacon_int = bss_conf->beacon_int; | ||
1628 | do_join = true; | ||
1629 | } | ||
1630 | |||
1631 | if ((changed && BSS_CHANGED_BEACON) && | ||
1632 | (wl->bss_type == BSS_TYPE_IBSS)) { | ||
1579 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 1633 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
1580 | 1634 | ||
1635 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon updated"); | ||
1636 | |||
1581 | if (beacon) { | 1637 | if (beacon) { |
1582 | struct ieee80211_hdr *hdr; | 1638 | struct ieee80211_hdr *hdr; |
1583 | 1639 | ||
1584 | wl1271_ssid_set(wl, beacon); | 1640 | wl1271_ssid_set(wl, beacon); |
1585 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 1641 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, |
1586 | beacon->data, | 1642 | beacon->data, |
1587 | beacon->len); | 1643 | beacon->len, 0, |
1644 | wl1271_min_rate_get(wl)); | ||
1588 | 1645 | ||
1589 | if (ret < 0) { | 1646 | if (ret < 0) { |
1590 | dev_kfree_skb(beacon); | 1647 | dev_kfree_skb(beacon); |
@@ -1599,7 +1656,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1599 | ret = wl1271_cmd_template_set(wl, | 1656 | ret = wl1271_cmd_template_set(wl, |
1600 | CMD_TEMPL_PROBE_RESPONSE, | 1657 | CMD_TEMPL_PROBE_RESPONSE, |
1601 | beacon->data, | 1658 | beacon->data, |
1602 | beacon->len); | 1659 | beacon->len, 0, |
1660 | wl1271_min_rate_get(wl)); | ||
1603 | dev_kfree_skb(beacon); | 1661 | dev_kfree_skb(beacon); |
1604 | if (ret < 0) | 1662 | if (ret < 0) |
1605 | goto out_sleep; | 1663 | goto out_sleep; |
@@ -1609,6 +1667,30 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1609 | } | 1667 | } |
1610 | } | 1668 | } |
1611 | 1669 | ||
1670 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && | ||
1671 | (wl->bss_type == BSS_TYPE_IBSS)) { | ||
1672 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", | ||
1673 | bss_conf->enable_beacon ? "enabled" : "disabled"); | ||
1674 | |||
1675 | if (bss_conf->enable_beacon) | ||
1676 | wl->set_bss_type = BSS_TYPE_IBSS; | ||
1677 | else | ||
1678 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
1679 | do_join = true; | ||
1680 | } | ||
1681 | |||
1682 | if (changed & BSS_CHANGED_CQM) { | ||
1683 | bool enable = false; | ||
1684 | if (bss_conf->cqm_rssi_thold) | ||
1685 | enable = true; | ||
1686 | ret = wl1271_acx_rssi_snr_trigger(wl, enable, | ||
1687 | bss_conf->cqm_rssi_thold, | ||
1688 | bss_conf->cqm_rssi_hyst); | ||
1689 | if (ret < 0) | ||
1690 | goto out; | ||
1691 | wl->rssi_thold = bss_conf->cqm_rssi_thold; | ||
1692 | } | ||
1693 | |||
1612 | if ((changed & BSS_CHANGED_BSSID) && | 1694 | if ((changed & BSS_CHANGED_BSSID) && |
1613 | /* | 1695 | /* |
1614 | * Now we know the correct bssid, so we send a new join command | 1696 | * Now we know the correct bssid, so we send a new join command |
@@ -1630,10 +1712,23 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1630 | 1712 | ||
1631 | if (changed & BSS_CHANGED_ASSOC) { | 1713 | if (changed & BSS_CHANGED_ASSOC) { |
1632 | if (bss_conf->assoc) { | 1714 | if (bss_conf->assoc) { |
1715 | u32 rates; | ||
1633 | wl->aid = bss_conf->aid; | 1716 | wl->aid = bss_conf->aid; |
1634 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1717 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1635 | 1718 | ||
1636 | /* | 1719 | /* |
1720 | * use basic rates from AP, and determine lowest rate | ||
1721 | * to use with control frames. | ||
1722 | */ | ||
1723 | rates = bss_conf->basic_rates; | ||
1724 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | ||
1725 | rates); | ||
1726 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1727 | ret = wl1271_acx_rate_policies(wl); | ||
1728 | if (ret < 0) | ||
1729 | goto out_sleep; | ||
1730 | |||
1731 | /* | ||
1637 | * with wl1271, we don't need to update the | 1732 | * with wl1271, we don't need to update the |
1638 | * beacon_int and dtim_period, because the firmware | 1733 | * beacon_int and dtim_period, because the firmware |
1639 | * updates it by itself when the first beacon is | 1734 | * updates it by itself when the first beacon is |
@@ -1643,7 +1738,30 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1643 | if (ret < 0) | 1738 | if (ret < 0) |
1644 | goto out_sleep; | 1739 | goto out_sleep; |
1645 | 1740 | ||
1646 | ret = wl1271_acx_aid(wl, wl->aid); | 1741 | /* |
1742 | * The SSID is intentionally set to NULL here - the | ||
1743 | * firmware will set the probe request with a | ||
1744 | * broadcast SSID regardless of what we set in the | ||
1745 | * template. | ||
1746 | */ | ||
1747 | ret = wl1271_cmd_build_probe_req(wl, NULL, 0, | ||
1748 | NULL, 0, wl->band); | ||
1749 | |||
1750 | /* Enable the keep-alive feature */ | ||
1751 | ret = wl1271_acx_keep_alive_mode(wl, true); | ||
1752 | if (ret < 0) | ||
1753 | goto out_sleep; | ||
1754 | |||
1755 | /* | ||
1756 | * This is awkward. The keep-alive configs must be done | ||
1757 | * *after* the join command, because otherwise it will | ||
1758 | * not work, but it must only be done *once* because | ||
1759 | * otherwise the firmware will start complaining. | ||
1760 | */ | ||
1761 | do_keepalive = true; | ||
1762 | |||
1763 | /* enable the connection monitoring feature */ | ||
1764 | ret = wl1271_acx_conn_monit_params(wl, true); | ||
1647 | if (ret < 0) | 1765 | if (ret < 0) |
1648 | goto out_sleep; | 1766 | goto out_sleep; |
1649 | 1767 | ||
@@ -1659,6 +1777,22 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1659 | /* use defaults when not associated */ | 1777 | /* use defaults when not associated */ |
1660 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1778 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1661 | wl->aid = 0; | 1779 | wl->aid = 0; |
1780 | |||
1781 | /* revert back to minimum rates for the current band */ | ||
1782 | wl1271_set_band_rate(wl); | ||
1783 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1784 | ret = wl1271_acx_rate_policies(wl); | ||
1785 | if (ret < 0) | ||
1786 | goto out_sleep; | ||
1787 | |||
1788 | /* disable connection monitor features */ | ||
1789 | ret = wl1271_acx_conn_monit_params(wl, false); | ||
1790 | |||
1791 | /* Disable the keep-alive feature */ | ||
1792 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
1793 | |||
1794 | if (ret < 0) | ||
1795 | goto out_sleep; | ||
1662 | } | 1796 | } |
1663 | 1797 | ||
1664 | } | 1798 | } |
@@ -1693,7 +1827,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1693 | } | 1827 | } |
1694 | 1828 | ||
1695 | if (do_join) { | 1829 | if (do_join) { |
1696 | ret = wl1271_cmd_join(wl, wl->bss_type); | 1830 | ret = wl1271_cmd_join(wl, wl->set_bss_type); |
1697 | if (ret < 0) { | 1831 | if (ret < 0) { |
1698 | wl1271_warning("cmd join failed %d", ret); | 1832 | wl1271_warning("cmd join failed %d", ret); |
1699 | goto out_sleep; | 1833 | goto out_sleep; |
@@ -1701,6 +1835,29 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1701 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | 1835 | set_bit(WL1271_FLAG_JOINED, &wl->flags); |
1702 | } | 1836 | } |
1703 | 1837 | ||
1838 | /* | ||
1839 | * The JOIN operation shuts down the firmware keep-alive as a side | ||
1840 | * effect, and the ACX_AID will start the keep-alive as a side effect. | ||
1841 | * Hence, for non-IBSS, the ACX_AID must always happen *after* the | ||
1842 | * JOIN operation, and the template config after the ACX_AID. | ||
1843 | */ | ||
1844 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | ||
1845 | ret = wl1271_acx_aid(wl, wl->aid); | ||
1846 | if (ret < 0) | ||
1847 | goto out_sleep; | ||
1848 | } | ||
1849 | |||
1850 | if (do_keepalive) { | ||
1851 | ret = wl1271_cmd_build_klv_null_data(wl); | ||
1852 | if (ret < 0) | ||
1853 | goto out_sleep; | ||
1854 | ret = wl1271_acx_keep_alive_config( | ||
1855 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1856 | ACX_KEEP_ALIVE_TPL_VALID); | ||
1857 | if (ret < 0) | ||
1858 | goto out_sleep; | ||
1859 | } | ||
1860 | |||
1704 | out_sleep: | 1861 | out_sleep: |
1705 | wl1271_ps_elp_sleep(wl); | 1862 | wl1271_ps_elp_sleep(wl); |
1706 | 1863 | ||
@@ -1812,6 +1969,36 @@ static struct ieee80211_channel wl1271_channels[] = { | |||
1812 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, | 1969 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
1813 | }; | 1970 | }; |
1814 | 1971 | ||
1972 | /* mapping to indexes for wl1271_rates */ | ||
1973 | const static u8 wl1271_rate_to_idx_2ghz[] = { | ||
1974 | /* MCS rates are used only with 11n */ | ||
1975 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
1976 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
1977 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
1978 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
1979 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
1980 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
1981 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
1982 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
1983 | |||
1984 | 11, /* CONF_HW_RXTX_RATE_54 */ | ||
1985 | 10, /* CONF_HW_RXTX_RATE_48 */ | ||
1986 | 9, /* CONF_HW_RXTX_RATE_36 */ | ||
1987 | 8, /* CONF_HW_RXTX_RATE_24 */ | ||
1988 | |||
1989 | /* TI-specific rate */ | ||
1990 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
1991 | |||
1992 | 7, /* CONF_HW_RXTX_RATE_18 */ | ||
1993 | 6, /* CONF_HW_RXTX_RATE_12 */ | ||
1994 | 3, /* CONF_HW_RXTX_RATE_11 */ | ||
1995 | 5, /* CONF_HW_RXTX_RATE_9 */ | ||
1996 | 4, /* CONF_HW_RXTX_RATE_6 */ | ||
1997 | 2, /* CONF_HW_RXTX_RATE_5_5 */ | ||
1998 | 1, /* CONF_HW_RXTX_RATE_2 */ | ||
1999 | 0 /* CONF_HW_RXTX_RATE_1 */ | ||
2000 | }; | ||
2001 | |||
1815 | /* can't be const, mac80211 writes to this */ | 2002 | /* can't be const, mac80211 writes to this */ |
1816 | static struct ieee80211_supported_band wl1271_band_2ghz = { | 2003 | static struct ieee80211_supported_band wl1271_band_2ghz = { |
1817 | .channels = wl1271_channels, | 2004 | .channels = wl1271_channels, |
@@ -1894,6 +2081,35 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { | |||
1894 | { .hw_value = 165, .center_freq = 5825}, | 2081 | { .hw_value = 165, .center_freq = 5825}, |
1895 | }; | 2082 | }; |
1896 | 2083 | ||
2084 | /* mapping to indexes for wl1271_rates_5ghz */ | ||
2085 | const static u8 wl1271_rate_to_idx_5ghz[] = { | ||
2086 | /* MCS rates are used only with 11n */ | ||
2087 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
2088 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
2089 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
2090 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
2091 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
2092 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
2093 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
2094 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
2095 | |||
2096 | 7, /* CONF_HW_RXTX_RATE_54 */ | ||
2097 | 6, /* CONF_HW_RXTX_RATE_48 */ | ||
2098 | 5, /* CONF_HW_RXTX_RATE_36 */ | ||
2099 | 4, /* CONF_HW_RXTX_RATE_24 */ | ||
2100 | |||
2101 | /* TI-specific rate */ | ||
2102 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
2103 | |||
2104 | 3, /* CONF_HW_RXTX_RATE_18 */ | ||
2105 | 2, /* CONF_HW_RXTX_RATE_12 */ | ||
2106 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_11 */ | ||
2107 | 1, /* CONF_HW_RXTX_RATE_9 */ | ||
2108 | 0, /* CONF_HW_RXTX_RATE_6 */ | ||
2109 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_5_5 */ | ||
2110 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_2 */ | ||
2111 | CONF_HW_RXTX_RATE_UNSUPPORTED /* CONF_HW_RXTX_RATE_1 */ | ||
2112 | }; | ||
1897 | 2113 | ||
1898 | static struct ieee80211_supported_band wl1271_band_5ghz = { | 2114 | static struct ieee80211_supported_band wl1271_band_5ghz = { |
1899 | .channels = wl1271_channels_5ghz, | 2115 | .channels = wl1271_channels_5ghz, |
@@ -1902,6 +2118,11 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { | |||
1902 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), | 2118 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), |
1903 | }; | 2119 | }; |
1904 | 2120 | ||
2121 | const static u8 *wl1271_band_rate_to_idx[] = { | ||
2122 | [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz, | ||
2123 | [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz | ||
2124 | }; | ||
2125 | |||
1905 | static const struct ieee80211_ops wl1271_ops = { | 2126 | static const struct ieee80211_ops wl1271_ops = { |
1906 | .start = wl1271_op_start, | 2127 | .start = wl1271_op_start, |
1907 | .stop = wl1271_op_stop, | 2128 | .stop = wl1271_op_stop, |
@@ -1919,6 +2140,27 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1919 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 2140 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
1920 | }; | 2141 | }; |
1921 | 2142 | ||
2143 | |||
2144 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate) | ||
2145 | { | ||
2146 | u8 idx; | ||
2147 | |||
2148 | BUG_ON(wl->band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); | ||
2149 | |||
2150 | if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) { | ||
2151 | wl1271_error("Illegal RX rate from HW: %d", rate); | ||
2152 | return 0; | ||
2153 | } | ||
2154 | |||
2155 | idx = wl1271_band_rate_to_idx[wl->band][rate]; | ||
2156 | if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { | ||
2157 | wl1271_error("Unsupported RX rate from HW: %d", rate); | ||
2158 | return 0; | ||
2159 | } | ||
2160 | |||
2161 | return idx; | ||
2162 | } | ||
2163 | |||
1922 | static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, | 2164 | static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, |
1923 | struct device_attribute *attr, | 2165 | struct device_attribute *attr, |
1924 | char *buf) | 2166 | char *buf) |
@@ -2021,13 +2263,16 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2021 | /* unit us */ | 2263 | /* unit us */ |
2022 | /* FIXME: find a proper value */ | 2264 | /* FIXME: find a proper value */ |
2023 | wl->hw->channel_change_time = 10000; | 2265 | wl->hw->channel_change_time = 10000; |
2266 | wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval; | ||
2024 | 2267 | ||
2025 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 2268 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
2026 | IEEE80211_HW_NOISE_DBM | | 2269 | IEEE80211_HW_NOISE_DBM | |
2027 | IEEE80211_HW_BEACON_FILTER | | 2270 | IEEE80211_HW_BEACON_FILTER | |
2028 | IEEE80211_HW_SUPPORTS_PS | | 2271 | IEEE80211_HW_SUPPORTS_PS | |
2029 | IEEE80211_HW_SUPPORTS_UAPSD | | 2272 | IEEE80211_HW_SUPPORTS_UAPSD | |
2030 | IEEE80211_HW_HAS_RATE_CONTROL; | 2273 | IEEE80211_HW_HAS_RATE_CONTROL | |
2274 | IEEE80211_HW_CONNECTION_MONITOR | | ||
2275 | IEEE80211_HW_SUPPORTS_CQM_RSSI; | ||
2031 | 2276 | ||
2032 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 2277 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2033 | BIT(NL80211_IFTYPE_ADHOC); | 2278 | BIT(NL80211_IFTYPE_ADHOC); |
@@ -2038,6 +2283,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2038 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | 2283 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; |
2039 | 2284 | ||
2040 | wl->hw->queues = 4; | 2285 | wl->hw->queues = 4; |
2286 | wl->hw->max_rates = 1; | ||
2041 | 2287 | ||
2042 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); | 2288 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); |
2043 | 2289 | ||
@@ -2053,7 +2299,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2053 | struct platform_device *plat_dev = NULL; | 2299 | struct platform_device *plat_dev = NULL; |
2054 | struct wl1271 *wl; | 2300 | struct wl1271 *wl; |
2055 | int i, ret; | 2301 | int i, ret; |
2056 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
2057 | 2302 | ||
2058 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 2303 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
2059 | if (!hw) { | 2304 | if (!hw) { |
@@ -2083,6 +2328,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2083 | 2328 | ||
2084 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2329 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
2085 | wl->channel = WL1271_DEFAULT_CHANNEL; | 2330 | wl->channel = WL1271_DEFAULT_CHANNEL; |
2331 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | ||
2086 | wl->default_key = 0; | 2332 | wl->default_key = 0; |
2087 | wl->rx_counter = 0; | 2333 | wl->rx_counter = 0; |
2088 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 2334 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
@@ -2090,6 +2336,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2090 | wl->psm_entry_retry = 0; | 2336 | wl->psm_entry_retry = 0; |
2091 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 2337 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
2092 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; | 2338 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
2339 | wl->basic_rate = CONF_TX_RATE_MASK_BASIC; | ||
2093 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 2340 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
2094 | wl->sta_rate_set = 0; | 2341 | wl->sta_rate_set = 0; |
2095 | wl->band = IEEE80211_BAND_2GHZ; | 2342 | wl->band = IEEE80211_BAND_2GHZ; |
@@ -2105,13 +2352,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2105 | wl->state = WL1271_STATE_OFF; | 2352 | wl->state = WL1271_STATE_OFF; |
2106 | mutex_init(&wl->mutex); | 2353 | mutex_init(&wl->mutex); |
2107 | 2354 | ||
2108 | /* | ||
2109 | * FIXME: we should use a zero MAC address here, but for now we | ||
2110 | * generate a random Nokia address. | ||
2111 | */ | ||
2112 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
2113 | get_random_bytes(wl->mac_addr + 3, 3); | ||
2114 | |||
2115 | /* Apply default driver configuration. */ | 2355 | /* Apply default driver configuration. */ |
2116 | wl1271_conf_init(wl); | 2356 | wl1271_conf_init(wl); |
2117 | 2357 | ||
@@ -2157,7 +2397,6 @@ int wl1271_free_hw(struct wl1271 *wl) | |||
2157 | 2397 | ||
2158 | wl1271_debugfs_exit(wl); | 2398 | wl1271_debugfs_exit(wl); |
2159 | 2399 | ||
2160 | kfree(wl->target_mem_map); | ||
2161 | vfree(wl->fw); | 2400 | vfree(wl->fw); |
2162 | wl->fw = NULL; | 2401 | wl->fw = NULL; |
2163 | kfree(wl->nvs); | 2402 | kfree(wl->nvs); |