diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-lib.c')
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 416 |
1 files changed, 409 insertions, 7 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index c465c8590833..a27347425968 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
| @@ -331,7 +331,7 @@ u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv) | |||
| 331 | } *hdr; | 331 | } *hdr; |
| 332 | 332 | ||
| 333 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | 333 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, |
| 334 | EEPROM_5000_CALIB_ALL); | 334 | EEPROM_CALIB_ALL); |
| 335 | return hdr->version; | 335 | return hdr->version; |
| 336 | 336 | ||
| 337 | } | 337 | } |
| @@ -348,22 +348,22 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) | |||
| 348 | 348 | ||
| 349 | switch (address & INDIRECT_TYPE_MSK) { | 349 | switch (address & INDIRECT_TYPE_MSK) { |
| 350 | case INDIRECT_HOST: | 350 | case INDIRECT_HOST: |
| 351 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST); | 351 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST); |
| 352 | break; | 352 | break; |
| 353 | case INDIRECT_GENERAL: | 353 | case INDIRECT_GENERAL: |
| 354 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL); | 354 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL); |
| 355 | break; | 355 | break; |
| 356 | case INDIRECT_REGULATORY: | 356 | case INDIRECT_REGULATORY: |
| 357 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY); | 357 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY); |
| 358 | break; | 358 | break; |
| 359 | case INDIRECT_CALIBRATION: | 359 | case INDIRECT_CALIBRATION: |
| 360 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION); | 360 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION); |
| 361 | break; | 361 | break; |
| 362 | case INDIRECT_PROCESS_ADJST: | 362 | case INDIRECT_PROCESS_ADJST: |
| 363 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST); | 363 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST); |
| 364 | break; | 364 | break; |
| 365 | case INDIRECT_OTHERS: | 365 | case INDIRECT_OTHERS: |
| 366 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); | 366 | offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS); |
| 367 | break; | 367 | break; |
| 368 | default: | 368 | default: |
| 369 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", | 369 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", |
| @@ -1111,3 +1111,405 @@ void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, | |||
| 1111 | memcpy(&priv->_agn.last_phy_res, pkt->u.raw, | 1111 | memcpy(&priv->_agn.last_phy_res, pkt->u.raw, |
| 1112 | sizeof(struct iwl_rx_phy_res)); | 1112 | sizeof(struct iwl_rx_phy_res)); |
| 1113 | } | 1113 | } |
| 1114 | |||
| 1115 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | ||
| 1116 | enum ieee80211_band band, | ||
| 1117 | struct iwl_scan_channel *scan_ch) | ||
| 1118 | { | ||
| 1119 | const struct ieee80211_supported_band *sband; | ||
| 1120 | const struct iwl_channel_info *ch_info; | ||
| 1121 | u16 passive_dwell = 0; | ||
| 1122 | u16 active_dwell = 0; | ||
| 1123 | int i, added = 0; | ||
| 1124 | u16 channel = 0; | ||
| 1125 | |||
| 1126 | sband = iwl_get_hw_mode(priv, band); | ||
| 1127 | if (!sband) { | ||
| 1128 | IWL_ERR(priv, "invalid band\n"); | ||
| 1129 | return added; | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | active_dwell = iwl_get_active_dwell_time(priv, band, 0); | ||
| 1133 | passive_dwell = iwl_get_passive_dwell_time(priv, band); | ||
| 1134 | |||
| 1135 | if (passive_dwell <= active_dwell) | ||
| 1136 | passive_dwell = active_dwell + 1; | ||
| 1137 | |||
| 1138 | /* only scan single channel, good enough to reset the RF */ | ||
| 1139 | /* pick the first valid not in-use channel */ | ||
| 1140 | if (band == IEEE80211_BAND_5GHZ) { | ||
| 1141 | for (i = 14; i < priv->channel_count; i++) { | ||
| 1142 | if (priv->channel_info[i].channel != | ||
| 1143 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
| 1144 | channel = priv->channel_info[i].channel; | ||
| 1145 | ch_info = iwl_get_channel_info(priv, | ||
| 1146 | band, channel); | ||
| 1147 | if (is_channel_valid(ch_info)) | ||
| 1148 | break; | ||
| 1149 | } | ||
| 1150 | } | ||
| 1151 | } else { | ||
| 1152 | for (i = 0; i < 14; i++) { | ||
| 1153 | if (priv->channel_info[i].channel != | ||
| 1154 | le16_to_cpu(priv->staging_rxon.channel)) { | ||
| 1155 | channel = | ||
| 1156 | priv->channel_info[i].channel; | ||
| 1157 | ch_info = iwl_get_channel_info(priv, | ||
| 1158 | band, channel); | ||
| 1159 | if (is_channel_valid(ch_info)) | ||
| 1160 | break; | ||
| 1161 | } | ||
| 1162 | } | ||
| 1163 | } | ||
| 1164 | if (channel) { | ||
| 1165 | scan_ch->channel = cpu_to_le16(channel); | ||
| 1166 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
| 1167 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
| 1168 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
| 1169 | /* Set txpower levels to defaults */ | ||
| 1170 | scan_ch->dsp_atten = 110; | ||
| 1171 | if (band == IEEE80211_BAND_5GHZ) | ||
| 1172 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
| 1173 | else | ||
| 1174 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
| 1175 | added++; | ||
| 1176 | } else | ||
| 1177 | IWL_ERR(priv, "no valid channel found\n"); | ||
| 1178 | return added; | ||
| 1179 | } | ||
| 1180 | |||
| 1181 | static int iwl_get_channels_for_scan(struct iwl_priv *priv, | ||
| 1182 | enum ieee80211_band band, | ||
| 1183 | u8 is_active, u8 n_probes, | ||
| 1184 | struct iwl_scan_channel *scan_ch) | ||
| 1185 | { | ||
| 1186 | struct ieee80211_channel *chan; | ||
| 1187 | const struct ieee80211_supported_band *sband; | ||
| 1188 | const struct iwl_channel_info *ch_info; | ||
| 1189 | u16 passive_dwell = 0; | ||
| 1190 | u16 active_dwell = 0; | ||
| 1191 | int added, i; | ||
| 1192 | u16 channel; | ||
| 1193 | |||
| 1194 | sband = iwl_get_hw_mode(priv, band); | ||
| 1195 | if (!sband) | ||
| 1196 | return 0; | ||
| 1197 | |||
| 1198 | active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); | ||
| 1199 | passive_dwell = iwl_get_passive_dwell_time(priv, band); | ||
| 1200 | |||
| 1201 | if (passive_dwell <= active_dwell) | ||
| 1202 | passive_dwell = active_dwell + 1; | ||
| 1203 | |||
| 1204 | for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { | ||
| 1205 | chan = priv->scan_request->channels[i]; | ||
| 1206 | |||
| 1207 | if (chan->band != band) | ||
| 1208 | continue; | ||
| 1209 | |||
| 1210 | channel = ieee80211_frequency_to_channel(chan->center_freq); | ||
| 1211 | scan_ch->channel = cpu_to_le16(channel); | ||
| 1212 | |||
| 1213 | ch_info = iwl_get_channel_info(priv, band, channel); | ||
| 1214 | if (!is_channel_valid(ch_info)) { | ||
| 1215 | IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", | ||
| 1216 | channel); | ||
| 1217 | continue; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | if (!is_active || is_channel_passive(ch_info) || | ||
| 1221 | (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) | ||
| 1222 | scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; | ||
| 1223 | else | ||
| 1224 | scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; | ||
| 1225 | |||
| 1226 | if (n_probes) | ||
| 1227 | scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); | ||
| 1228 | |||
| 1229 | scan_ch->active_dwell = cpu_to_le16(active_dwell); | ||
| 1230 | scan_ch->passive_dwell = cpu_to_le16(passive_dwell); | ||
| 1231 | |||
| 1232 | /* Set txpower levels to defaults */ | ||
| 1233 | scan_ch->dsp_atten = 110; | ||
| 1234 | |||
| 1235 | /* NOTE: if we were doing 6Mb OFDM for scans we'd use | ||
| 1236 | * power level: | ||
| 1237 | * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; | ||
| 1238 | */ | ||
| 1239 | if (band == IEEE80211_BAND_5GHZ) | ||
| 1240 | scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; | ||
| 1241 | else | ||
| 1242 | scan_ch->tx_gain = ((1 << 5) | (5 << 3)); | ||
| 1243 | |||
| 1244 | IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", | ||
| 1245 | channel, le32_to_cpu(scan_ch->type), | ||
| 1246 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | ||
| 1247 | "ACTIVE" : "PASSIVE", | ||
| 1248 | (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? | ||
| 1249 | active_dwell : passive_dwell); | ||
| 1250 | |||
| 1251 | scan_ch++; | ||
| 1252 | added++; | ||
| 1253 | } | ||
| 1254 | |||
| 1255 | IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); | ||
| 1256 | return added; | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | void iwlagn_request_scan(struct iwl_priv *priv) | ||
| 1260 | { | ||
| 1261 | struct iwl_host_cmd cmd = { | ||
| 1262 | .id = REPLY_SCAN_CMD, | ||
| 1263 | .len = sizeof(struct iwl_scan_cmd), | ||
| 1264 | .flags = CMD_SIZE_HUGE, | ||
| 1265 | }; | ||
| 1266 | struct iwl_scan_cmd *scan; | ||
| 1267 | struct ieee80211_conf *conf = NULL; | ||
| 1268 | u32 rate_flags = 0; | ||
| 1269 | u16 cmd_len; | ||
| 1270 | u16 rx_chain = 0; | ||
| 1271 | enum ieee80211_band band; | ||
| 1272 | u8 n_probes = 0; | ||
| 1273 | u8 rx_ant = priv->hw_params.valid_rx_ant; | ||
| 1274 | u8 rate; | ||
| 1275 | bool is_active = false; | ||
| 1276 | int chan_mod; | ||
| 1277 | u8 active_chains; | ||
| 1278 | |||
| 1279 | conf = ieee80211_get_hw_conf(priv->hw); | ||
| 1280 | |||
| 1281 | cancel_delayed_work(&priv->scan_check); | ||
| 1282 | |||
| 1283 | if (!iwl_is_ready(priv)) { | ||
| 1284 | IWL_WARN(priv, "request scan called when driver not ready.\n"); | ||
| 1285 | goto done; | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | /* Make sure the scan wasn't canceled before this queued work | ||
| 1289 | * was given the chance to run... */ | ||
| 1290 | if (!test_bit(STATUS_SCANNING, &priv->status)) | ||
| 1291 | goto done; | ||
| 1292 | |||
| 1293 | /* This should never be called or scheduled if there is currently | ||
| 1294 | * a scan active in the hardware. */ | ||
| 1295 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
| 1296 | IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " | ||
| 1297 | "Ignoring second request.\n"); | ||
| 1298 | goto done; | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
| 1302 | IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); | ||
| 1303 | goto done; | ||
| 1304 | } | ||
| 1305 | |||
| 1306 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
| 1307 | IWL_DEBUG_HC(priv, "Scan request while abort pending. Queuing.\n"); | ||
| 1308 | goto done; | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | if (iwl_is_rfkill(priv)) { | ||
| 1312 | IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); | ||
| 1313 | goto done; | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | if (!test_bit(STATUS_READY, &priv->status)) { | ||
| 1317 | IWL_DEBUG_HC(priv, "Scan request while uninitialized. Queuing.\n"); | ||
| 1318 | goto done; | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | if (!priv->scan_cmd) { | ||
| 1322 | priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + | ||
| 1323 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | ||
| 1324 | if (!priv->scan_cmd) { | ||
| 1325 | IWL_DEBUG_SCAN(priv, | ||
| 1326 | "fail to allocate memory for scan\n"); | ||
| 1327 | goto done; | ||
| 1328 | } | ||
| 1329 | } | ||
| 1330 | scan = priv->scan_cmd; | ||
| 1331 | memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); | ||
| 1332 | |||
| 1333 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; | ||
| 1334 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; | ||
| 1335 | |||
| 1336 | if (iwl_is_associated(priv)) { | ||
| 1337 | u16 interval = 0; | ||
| 1338 | u32 extra; | ||
| 1339 | u32 suspend_time = 100; | ||
| 1340 | u32 scan_suspend_time = 100; | ||
| 1341 | unsigned long flags; | ||
| 1342 | |||
| 1343 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | ||
| 1344 | spin_lock_irqsave(&priv->lock, flags); | ||
| 1345 | interval = priv->beacon_int; | ||
| 1346 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 1347 | |||
| 1348 | scan->suspend_time = 0; | ||
| 1349 | scan->max_out_time = cpu_to_le32(200 * 1024); | ||
| 1350 | if (!interval) | ||
| 1351 | interval = suspend_time; | ||
| 1352 | |||
| 1353 | extra = (suspend_time / interval) << 22; | ||
| 1354 | scan_suspend_time = (extra | | ||
| 1355 | ((suspend_time % interval) * 1024)); | ||
| 1356 | scan->suspend_time = cpu_to_le32(scan_suspend_time); | ||
| 1357 | IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", | ||
| 1358 | scan_suspend_time, interval); | ||
| 1359 | } | ||
| 1360 | |||
| 1361 | if (priv->is_internal_short_scan) { | ||
| 1362 | IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); | ||
| 1363 | } else if (priv->scan_request->n_ssids) { | ||
| 1364 | int i, p = 0; | ||
| 1365 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | ||
| 1366 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | ||
| 1367 | /* always does wildcard anyway */ | ||
| 1368 | if (!priv->scan_request->ssids[i].ssid_len) | ||
| 1369 | continue; | ||
| 1370 | scan->direct_scan[p].id = WLAN_EID_SSID; | ||
| 1371 | scan->direct_scan[p].len = | ||
| 1372 | priv->scan_request->ssids[i].ssid_len; | ||
| 1373 | memcpy(scan->direct_scan[p].ssid, | ||
| 1374 | priv->scan_request->ssids[i].ssid, | ||
| 1375 | priv->scan_request->ssids[i].ssid_len); | ||
| 1376 | n_probes++; | ||
| 1377 | p++; | ||
| 1378 | } | ||
| 1379 | is_active = true; | ||
| 1380 | } else | ||
| 1381 | IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); | ||
| 1382 | |||
| 1383 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | ||
| 1384 | scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; | ||
| 1385 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
| 1386 | |||
| 1387 | switch (priv->scan_band) { | ||
| 1388 | case IEEE80211_BAND_2GHZ: | ||
| 1389 | scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; | ||
| 1390 | chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK) | ||
| 1391 | >> RXON_FLG_CHANNEL_MODE_POS; | ||
| 1392 | if (chan_mod == CHANNEL_MODE_PURE_40) { | ||
| 1393 | rate = IWL_RATE_6M_PLCP; | ||
| 1394 | } else { | ||
| 1395 | rate = IWL_RATE_1M_PLCP; | ||
| 1396 | rate_flags = RATE_MCS_CCK_MSK; | ||
| 1397 | } | ||
| 1398 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED; | ||
| 1399 | break; | ||
| 1400 | case IEEE80211_BAND_5GHZ: | ||
| 1401 | rate = IWL_RATE_6M_PLCP; | ||
| 1402 | /* | ||
| 1403 | * If active scanning is requested but a certain channel is | ||
| 1404 | * marked passive, we can do active scanning if we detect | ||
| 1405 | * transmissions. | ||
| 1406 | * | ||
| 1407 | * There is an issue with some firmware versions that triggers | ||
| 1408 | * a sysassert on a "good CRC threshold" of zero (== disabled), | ||
| 1409 | * on a radar channel even though this means that we should NOT | ||
| 1410 | * send probes. | ||
| 1411 | * | ||
| 1412 | * The "good CRC threshold" is the number of frames that we | ||
| 1413 | * need to receive during our dwell time on a channel before | ||
| 1414 | * sending out probes -- setting this to a huge value will | ||
| 1415 | * mean we never reach it, but at the same time work around | ||
| 1416 | * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER | ||
| 1417 | * here instead of IWL_GOOD_CRC_TH_DISABLED. | ||
| 1418 | */ | ||
| 1419 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : | ||
| 1420 | IWL_GOOD_CRC_TH_NEVER; | ||
| 1421 | break; | ||
| 1422 | default: | ||
| 1423 | IWL_WARN(priv, "Invalid scan band count\n"); | ||
| 1424 | goto done; | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | band = priv->scan_band; | ||
| 1428 | |||
| 1429 | if (priv->cfg->scan_antennas[band]) | ||
| 1430 | rx_ant = priv->cfg->scan_antennas[band]; | ||
| 1431 | |||
| 1432 | priv->scan_tx_ant[band] = | ||
| 1433 | iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); | ||
| 1434 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); | ||
| 1435 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); | ||
| 1436 | |||
| 1437 | /* In power save mode use one chain, otherwise use all chains */ | ||
| 1438 | if (test_bit(STATUS_POWER_PMI, &priv->status)) { | ||
| 1439 | /* rx_ant has been set to all valid chains previously */ | ||
| 1440 | active_chains = rx_ant & | ||
| 1441 | ((u8)(priv->chain_noise_data.active_chains)); | ||
| 1442 | if (!active_chains) | ||
| 1443 | active_chains = rx_ant; | ||
| 1444 | |||
| 1445 | IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n", | ||
| 1446 | priv->chain_noise_data.active_chains); | ||
| 1447 | |||
| 1448 | rx_ant = first_antenna(active_chains); | ||
| 1449 | } | ||
| 1450 | /* MIMO is not used here, but value is required */ | ||
| 1451 | rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS; | ||
| 1452 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | ||
| 1453 | rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; | ||
| 1454 | rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; | ||
| 1455 | scan->rx_chain = cpu_to_le16(rx_chain); | ||
| 1456 | if (!priv->is_internal_short_scan) { | ||
| 1457 | cmd_len = iwl_fill_probe_req(priv, | ||
| 1458 | (struct ieee80211_mgmt *)scan->data, | ||
| 1459 | priv->scan_request->ie, | ||
| 1460 | priv->scan_request->ie_len, | ||
| 1461 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
| 1462 | } else { | ||
| 1463 | cmd_len = iwl_fill_probe_req(priv, | ||
| 1464 | (struct ieee80211_mgmt *)scan->data, | ||
| 1465 | NULL, 0, | ||
| 1466 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | ||
| 1467 | |||
| 1468 | } | ||
| 1469 | scan->tx_cmd.len = cpu_to_le16(cmd_len); | ||
| 1470 | |||
| 1471 | scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | | ||
| 1472 | RXON_FILTER_BCON_AWARE_MSK); | ||
| 1473 | |||
| 1474 | if (priv->is_internal_short_scan) { | ||
| 1475 | scan->channel_count = | ||
| 1476 | iwl_get_single_channel_for_scan(priv, band, | ||
| 1477 | (void *)&scan->data[le16_to_cpu( | ||
| 1478 | scan->tx_cmd.len)]); | ||
| 1479 | } else { | ||
| 1480 | scan->channel_count = | ||
| 1481 | iwl_get_channels_for_scan(priv, band, | ||
| 1482 | is_active, n_probes, | ||
| 1483 | (void *)&scan->data[le16_to_cpu( | ||
| 1484 | scan->tx_cmd.len)]); | ||
| 1485 | } | ||
| 1486 | if (scan->channel_count == 0) { | ||
| 1487 | IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); | ||
| 1488 | goto done; | ||
| 1489 | } | ||
| 1490 | |||
| 1491 | cmd.len += le16_to_cpu(scan->tx_cmd.len) + | ||
| 1492 | scan->channel_count * sizeof(struct iwl_scan_channel); | ||
| 1493 | cmd.data = scan; | ||
| 1494 | scan->len = cpu_to_le16(cmd.len); | ||
| 1495 | |||
| 1496 | set_bit(STATUS_SCAN_HW, &priv->status); | ||
| 1497 | if (iwl_send_cmd_sync(priv, &cmd)) | ||
| 1498 | goto done; | ||
| 1499 | |||
| 1500 | queue_delayed_work(priv->workqueue, &priv->scan_check, | ||
| 1501 | IWL_SCAN_CHECK_WATCHDOG); | ||
| 1502 | |||
| 1503 | return; | ||
| 1504 | |||
| 1505 | done: | ||
| 1506 | /* Cannot perform scan. Make sure we clear scanning | ||
| 1507 | * bits from status so next scan request can be performed. | ||
| 1508 | * If we don't clear scanning status bit here all next scan | ||
| 1509 | * will fail | ||
| 1510 | */ | ||
| 1511 | clear_bit(STATUS_SCAN_HW, &priv->status); | ||
| 1512 | clear_bit(STATUS_SCANNING, &priv->status); | ||
| 1513 | /* inform mac80211 scan aborted */ | ||
| 1514 | queue_work(priv->workqueue, &priv->scan_completed); | ||
| 1515 | } | ||
