aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-sta.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-sta.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c108
1 files changed, 85 insertions, 23 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index b1aad306efa9..312099099ed3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -34,9 +34,6 @@
34#include "iwl-core.h" 34#include "iwl-core.h"
35#include "iwl-sta.h" 35#include "iwl-sta.h"
36 36
37#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
38#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */
39
40u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) 37u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
41{ 38{
42 int i; 39 int i;
@@ -495,37 +492,102 @@ out:
495} 492}
496 493
497/** 494/**
498 * iwl_clear_stations_table - Clear the driver's station table 495 * iwl_clear_ucode_stations() - clear entire station table driver and/or ucode
499 * 496 * @priv:
500 * NOTE: This does not clear or otherwise alter the device's station table. 497 * @force: If set then the uCode station table needs to be cleared here. If
498 * not set then the uCode station table has already been cleared,
499 * for example after sending it a RXON command without ASSOC bit
500 * set, and we just need to change driver state here.
501 */ 501 */
502void iwl_clear_stations_table(struct iwl_priv *priv) 502void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force)
503{ 503{
504 unsigned long flags;
505 int i; 504 int i;
505 unsigned long flags_spin;
506 bool cleared = false;
507
508 IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver%s\n",
509 force ? " and ucode" : "");
510
511 if (force) {
512 if (!iwl_is_ready(priv)) {
513 /*
514 * If device is not ready at this point the station
515 * table is likely already empty (uCode not ready
516 * to receive station requests) or will soon be
517 * due to interface going down.
518 */
519 IWL_DEBUG_INFO(priv, "Unable to remove stations from device - device not ready\n");
520 } else {
521 iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL);
522 }
523 }
506 524
507 spin_lock_irqsave(&priv->sta_lock, flags); 525 spin_lock_irqsave(&priv->sta_lock, flags_spin);
526 if (force) {
527 IWL_DEBUG_INFO(priv, "Clearing all station information in driver\n");
528 priv->num_stations = 0;
529 memset(priv->stations, 0, sizeof(priv->stations));
530 } else {
531 for (i = 0; i < priv->hw_params.max_stations; i++) {
532 if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) {
533 IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d \n", i);
534 priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
535 cleared = true;
536 }
537 }
538 }
539 spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
540
541 if (!cleared)
542 IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n");
543}
544EXPORT_SYMBOL(iwl_clear_ucode_stations);
508 545
509 if (iwl_is_alive(priv) && 546/**
510 !test_bit(STATUS_EXIT_PENDING, &priv->status) && 547 * iwl_restore_stations() - Restore driver known stations to device
511 iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL)) 548 *
512 IWL_ERR(priv, "Couldn't clear the station table\n"); 549 * All stations considered active by driver, but not present in ucode, is
550 * restored.
551 */
552void iwl_restore_stations(struct iwl_priv *priv)
553{
554 unsigned long flags_spin;
555 int i;
556 bool found = false;
513 557
514 priv->num_stations = 0; 558 if (!iwl_is_ready(priv)) {
515 memset(priv->stations, 0, sizeof(priv->stations)); 559 IWL_DEBUG_INFO(priv, "Not ready yet, not restoring any stations.\n");
560 return;
561 }
516 562
517 /* clean ucode key table bit map */ 563 IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
518 priv->ucode_key_table = 0; 564 spin_lock_irqsave(&priv->sta_lock, flags_spin);
565 for (i = 0; i < priv->hw_params.max_stations; i++) {
566 if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) &&
567 !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) {
568 IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n",
569 priv->stations[i].sta.sta.addr);
570 priv->stations[i].sta.mode = 0;
571 priv->stations[i].used |= IWL_STA_UCODE_INPROGRESS;
572 found = true;
573 }
574 }
519 575
520 /* keep track of static keys */ 576 for (i = 0; i < priv->hw_params.max_stations; i++) {
521 for (i = 0; i < WEP_KEYS_MAX ; i++) { 577 if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) {
522 if (priv->wep_keys[i].key_size) 578 iwl_send_add_sta(priv, &priv->stations[i].sta,
523 set_bit(i, &priv->ucode_key_table); 579 CMD_ASYNC);
580 priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
581 }
524 } 582 }
525 583
526 spin_unlock_irqrestore(&priv->sta_lock, flags); 584 spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
585 if (!found)
586 IWL_DEBUG_INFO(priv, "Restoring all known stations .... no stations to be restored.\n");
587 else
588 IWL_DEBUG_INFO(priv, "Restoring all known stations .... in progress.\n");
527} 589}
528EXPORT_SYMBOL(iwl_clear_stations_table); 590EXPORT_SYMBOL(iwl_restore_stations);
529 591
530int iwl_get_free_ucode_key_index(struct iwl_priv *priv) 592int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
531{ 593{