diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-lib.c')
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 124 |
1 files changed, 112 insertions, 12 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index e741128842bb..8e79653aed9a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
| @@ -483,8 +483,6 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv) | |||
| 483 | /* init calibration handlers */ | 483 | /* init calibration handlers */ |
| 484 | priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = | 484 | priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = |
| 485 | iwlagn_rx_calib_result; | 485 | iwlagn_rx_calib_result; |
| 486 | priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = | ||
| 487 | iwlagn_rx_calib_complete; | ||
| 488 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; | 486 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; |
| 489 | 487 | ||
| 490 | /* set up notification wait support */ | 488 | /* set up notification wait support */ |
| @@ -667,7 +665,7 @@ int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
| 667 | 665 | ||
| 668 | rb_timeout = RX_RB_TIMEOUT; | 666 | rb_timeout = RX_RB_TIMEOUT; |
| 669 | 667 | ||
| 670 | if (priv->cfg->mod_params->amsdu_size_8K) | 668 | if (iwlagn_mod_params.amsdu_size_8K) |
| 671 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; | 669 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; |
| 672 | else | 670 | else |
| 673 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; | 671 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; |
| @@ -1296,9 +1294,17 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
| 1296 | * mean we never reach it, but at the same time work around | 1294 | * mean we never reach it, but at the same time work around |
| 1297 | * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER | 1295 | * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER |
| 1298 | * here instead of IWL_GOOD_CRC_TH_DISABLED. | 1296 | * here instead of IWL_GOOD_CRC_TH_DISABLED. |
| 1297 | * | ||
| 1298 | * This was fixed in later versions along with some other | ||
| 1299 | * scan changes, and the threshold behaves as a flag in those | ||
| 1300 | * versions. | ||
| 1299 | */ | 1301 | */ |
| 1300 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : | 1302 | if (priv->new_scan_threshold_behaviour) |
| 1301 | IWL_GOOD_CRC_TH_NEVER; | 1303 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : |
| 1304 | IWL_GOOD_CRC_TH_DISABLED; | ||
| 1305 | else | ||
| 1306 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : | ||
| 1307 | IWL_GOOD_CRC_TH_NEVER; | ||
| 1302 | 1308 | ||
| 1303 | band = priv->scan_band; | 1309 | band = priv->scan_band; |
| 1304 | 1310 | ||
| @@ -2256,34 +2262,44 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) | |||
| 2256 | /* notification wait support */ | 2262 | /* notification wait support */ |
| 2257 | void iwlagn_init_notification_wait(struct iwl_priv *priv, | 2263 | void iwlagn_init_notification_wait(struct iwl_priv *priv, |
| 2258 | struct iwl_notification_wait *wait_entry, | 2264 | struct iwl_notification_wait *wait_entry, |
| 2265 | u8 cmd, | ||
| 2259 | void (*fn)(struct iwl_priv *priv, | 2266 | void (*fn)(struct iwl_priv *priv, |
| 2260 | struct iwl_rx_packet *pkt), | 2267 | struct iwl_rx_packet *pkt, |
| 2261 | u8 cmd) | 2268 | void *data), |
| 2269 | void *fn_data) | ||
| 2262 | { | 2270 | { |
| 2263 | wait_entry->fn = fn; | 2271 | wait_entry->fn = fn; |
| 2272 | wait_entry->fn_data = fn_data; | ||
| 2264 | wait_entry->cmd = cmd; | 2273 | wait_entry->cmd = cmd; |
| 2265 | wait_entry->triggered = false; | 2274 | wait_entry->triggered = false; |
| 2275 | wait_entry->aborted = false; | ||
| 2266 | 2276 | ||
| 2267 | spin_lock_bh(&priv->_agn.notif_wait_lock); | 2277 | spin_lock_bh(&priv->_agn.notif_wait_lock); |
| 2268 | list_add(&wait_entry->list, &priv->_agn.notif_waits); | 2278 | list_add(&wait_entry->list, &priv->_agn.notif_waits); |
| 2269 | spin_unlock_bh(&priv->_agn.notif_wait_lock); | 2279 | spin_unlock_bh(&priv->_agn.notif_wait_lock); |
| 2270 | } | 2280 | } |
| 2271 | 2281 | ||
| 2272 | signed long iwlagn_wait_notification(struct iwl_priv *priv, | 2282 | int iwlagn_wait_notification(struct iwl_priv *priv, |
| 2273 | struct iwl_notification_wait *wait_entry, | 2283 | struct iwl_notification_wait *wait_entry, |
| 2274 | unsigned long timeout) | 2284 | unsigned long timeout) |
| 2275 | { | 2285 | { |
| 2276 | int ret; | 2286 | int ret; |
| 2277 | 2287 | ||
| 2278 | ret = wait_event_timeout(priv->_agn.notif_waitq, | 2288 | ret = wait_event_timeout(priv->_agn.notif_waitq, |
| 2279 | wait_entry->triggered, | 2289 | wait_entry->triggered || wait_entry->aborted, |
| 2280 | timeout); | 2290 | timeout); |
| 2281 | 2291 | ||
| 2282 | spin_lock_bh(&priv->_agn.notif_wait_lock); | 2292 | spin_lock_bh(&priv->_agn.notif_wait_lock); |
| 2283 | list_del(&wait_entry->list); | 2293 | list_del(&wait_entry->list); |
| 2284 | spin_unlock_bh(&priv->_agn.notif_wait_lock); | 2294 | spin_unlock_bh(&priv->_agn.notif_wait_lock); |
| 2285 | 2295 | ||
| 2286 | return ret; | 2296 | if (wait_entry->aborted) |
| 2297 | return -EIO; | ||
| 2298 | |||
| 2299 | /* return value is always >= 0 */ | ||
| 2300 | if (ret <= 0) | ||
| 2301 | return -ETIMEDOUT; | ||
| 2302 | return 0; | ||
| 2287 | } | 2303 | } |
| 2288 | 2304 | ||
| 2289 | void iwlagn_remove_notification(struct iwl_priv *priv, | 2305 | void iwlagn_remove_notification(struct iwl_priv *priv, |
| @@ -2293,3 +2309,87 @@ void iwlagn_remove_notification(struct iwl_priv *priv, | |||
| 2293 | list_del(&wait_entry->list); | 2309 | list_del(&wait_entry->list); |
| 2294 | spin_unlock_bh(&priv->_agn.notif_wait_lock); | 2310 | spin_unlock_bh(&priv->_agn.notif_wait_lock); |
| 2295 | } | 2311 | } |
| 2312 | |||
| 2313 | int iwlagn_start_device(struct iwl_priv *priv) | ||
| 2314 | { | ||
| 2315 | int ret; | ||
| 2316 | |||
| 2317 | if (iwl_prepare_card_hw(priv)) { | ||
| 2318 | IWL_WARN(priv, "Exit HW not ready\n"); | ||
| 2319 | return -EIO; | ||
| 2320 | } | ||
| 2321 | |||
| 2322 | /* If platform's RF_KILL switch is NOT set to KILL */ | ||
| 2323 | if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) | ||
| 2324 | clear_bit(STATUS_RF_KILL_HW, &priv->status); | ||
| 2325 | else | ||
| 2326 | set_bit(STATUS_RF_KILL_HW, &priv->status); | ||
| 2327 | |||
| 2328 | if (iwl_is_rfkill(priv)) { | ||
| 2329 | wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); | ||
| 2330 | iwl_enable_interrupts(priv); | ||
| 2331 | return -ERFKILL; | ||
| 2332 | } | ||
| 2333 | |||
| 2334 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | ||
| 2335 | |||
| 2336 | ret = iwlagn_hw_nic_init(priv); | ||
| 2337 | if (ret) { | ||
| 2338 | IWL_ERR(priv, "Unable to init nic\n"); | ||
| 2339 | return ret; | ||
| 2340 | } | ||
| 2341 | |||
| 2342 | /* make sure rfkill handshake bits are cleared */ | ||
| 2343 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
| 2344 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
| 2345 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
| 2346 | |||
| 2347 | /* clear (again), then enable host interrupts */ | ||
| 2348 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | ||
| 2349 | iwl_enable_interrupts(priv); | ||
| 2350 | |||
| 2351 | /* really make sure rfkill handshake bits are cleared */ | ||
| 2352 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
| 2353 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
| 2354 | |||
| 2355 | return 0; | ||
| 2356 | } | ||
| 2357 | |||
| 2358 | void iwlagn_stop_device(struct iwl_priv *priv) | ||
| 2359 | { | ||
| 2360 | unsigned long flags; | ||
| 2361 | |||
| 2362 | /* stop and reset the on-board processor */ | ||
| 2363 | iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); | ||
| 2364 | |||
| 2365 | /* tell the device to stop sending interrupts */ | ||
| 2366 | spin_lock_irqsave(&priv->lock, flags); | ||
| 2367 | iwl_disable_interrupts(priv); | ||
| 2368 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 2369 | iwl_synchronize_irq(priv); | ||
| 2370 | |||
| 2371 | /* device going down, Stop using ICT table */ | ||
| 2372 | iwl_disable_ict(priv); | ||
| 2373 | |||
| 2374 | /* | ||
| 2375 | * If a HW restart happens during firmware loading, | ||
| 2376 | * then the firmware loading might call this function | ||
| 2377 | * and later it might be called again due to the | ||
| 2378 | * restart. So don't process again if the device is | ||
| 2379 | * already dead. | ||
| 2380 | */ | ||
| 2381 | if (test_bit(STATUS_DEVICE_ENABLED, &priv->status)) { | ||
| 2382 | iwlagn_txq_ctx_stop(priv); | ||
| 2383 | iwlagn_rxq_stop(priv); | ||
| 2384 | |||
| 2385 | /* Power-down device's busmaster DMA clocks */ | ||
| 2386 | iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); | ||
| 2387 | udelay(5); | ||
| 2388 | } | ||
| 2389 | |||
| 2390 | /* Make sure (redundant) we've released our request to stay awake */ | ||
| 2391 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); | ||
| 2392 | |||
| 2393 | /* Stop the device, and put it in low power state */ | ||
| 2394 | iwl_apm_stop(priv); | ||
| 2395 | } | ||
