Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-core.c
index 8096463..e3427c2 100644 (file)
@@ -273,22 +273,27 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
 EXPORT_SYMBOL(iwl_hw_nic_init);
 
 /**
- * iwlcore_clear_stations_table - Clear the driver's station table
+ * iwl_clear_stations_table - Clear the driver's station table
  *
  * NOTE:  This does not clear or otherwise alter the device's station table.
  */
-void iwlcore_clear_stations_table(struct iwl_priv *priv)
+void iwl_clear_stations_table(struct iwl_priv *priv)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&priv->sta_lock, flags);
 
+       if (iwl_is_alive(priv) &&
+          !test_bit(STATUS_EXIT_PENDING, &priv->status) &&
+          iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL))
+               IWL_ERROR("Couldn't clear the station table\n");
+
        priv->num_stations = 0;
        memset(priv->stations, 0, sizeof(priv->stations));
 
        spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
-EXPORT_SYMBOL(iwlcore_clear_stations_table);
+EXPORT_SYMBOL(iwl_clear_stations_table);
 
 void iwl_reset_qos(struct iwl_priv *priv)
 {
@@ -490,7 +495,9 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
        sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
        sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
 
-       iwlcore_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_5GHZ);
+       if (priv->cfg->sku & IWL_SKU_N)
+               iwlcore_init_ht_hw_capab(priv, &sband->ht_info,
+                                        IEEE80211_BAND_5GHZ);
 
        sband = &priv->bands[IEEE80211_BAND_2GHZ];
        sband->channels = channels;
@@ -498,7 +505,9 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
        sband->bitrates = rates;
        sband->n_bitrates = IWL_RATE_COUNT;
 
-       iwlcore_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_2GHZ);
+       if (priv->cfg->sku & IWL_SKU_N)
+               iwlcore_init_ht_hw_capab(priv, &sband->ht_info,
+                                        IEEE80211_BAND_2GHZ);
 
        priv->ieee_channels = channels;
        priv->ieee_rates = rates;
@@ -809,13 +818,13 @@ int iwl_setup_mac(struct iwl_priv *priv)
        hw->rate_control_algorithm = "iwl-4965-rs";
 
        /* Tell mac80211 our characteristics */
-       hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
-                   IEEE80211_HW_SIGNAL_DBM |
+       hw->flags = IEEE80211_HW_SIGNAL_DBM |
                    IEEE80211_HW_NOISE_DBM;
        /* Default value; 4 EDCA QOS priorities */
        hw->queues = 4;
-       /* Enhanced value; more queues, to support 11n aggregation */
-       hw->ampdu_queues = 12;
+       /* queues to support 11n aggregation */
+       if (priv->cfg->sku & IWL_SKU_N)
+               hw->ampdu_queues = priv->cfg->mod_params->num_of_ampdu_queues;
 
        hw->conf.beacon_int = 100;
 
@@ -837,11 +846,28 @@ int iwl_setup_mac(struct iwl_priv *priv)
 }
 EXPORT_SYMBOL(iwl_setup_mac);
 
+int iwl_set_hw_params(struct iwl_priv *priv)
+{
+       priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto;
+       priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
+       priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
+       if (priv->cfg->mod_params->amsdu_size_8K)
+               priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K;
+       else
+               priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;
+       priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;
+
+       if (priv->cfg->mod_params->disable_11n)
+               priv->cfg->sku &= ~IWL_SKU_N;
+
+       /* Device-specific setup */
+       return priv->cfg->ops->lib->set_hw_params(priv);
+}
+EXPORT_SYMBOL(iwl_set_hw_params);
 
 int iwl_init_drv(struct iwl_priv *priv)
 {
        int ret;
-       int i;
 
        priv->retry_rate = 1;
        priv->ibss_beacon = NULL;
@@ -852,15 +878,12 @@ int iwl_init_drv(struct iwl_priv *priv)
        spin_lock_init(&priv->hcmd_lock);
        spin_lock_init(&priv->lq_mngr.lock);
 
-       for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
-               INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
-
        INIT_LIST_HEAD(&priv->free_frames);
 
        mutex_init(&priv->mutex);
 
        /* Clear the driver's (not device's) station table */
-       iwlcore_clear_stations_table(priv);
+       iwl_clear_stations_table(priv);
 
        priv->data_retry_limit = -1;
        priv->ieee_channels = NULL;
@@ -965,37 +988,6 @@ void iwl_uninit_drv(struct iwl_priv *priv)
 }
 EXPORT_SYMBOL(iwl_uninit_drv);
 
-
-
-/* Low level driver call this function to update iwlcore with
- * driver status.
- */
-int iwlcore_low_level_notify(struct iwl_priv *priv,
-                             enum iwlcore_card_notify notify)
-{
-       int ret;
-       switch (notify) {
-       case IWLCORE_INIT_EVT:
-               ret = iwl_rfkill_init(priv);
-               if (ret)
-                       IWL_ERROR("Unable to initialize RFKILL system. "
-                                 "Ignoring error: %d\n", ret);
-               iwl_power_initialize(priv);
-               break;
-       case IWLCORE_START_EVT:
-               iwl_power_update_mode(priv, 1);
-               break;
-       case IWLCORE_STOP_EVT:
-               break;
-       case IWLCORE_REMOVE_EVT:
-               iwl_rfkill_unregister(priv);
-               break;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(iwlcore_low_level_notify);
-
 int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags)
 {
        u32 stat_flags = 0;
@@ -1350,3 +1342,99 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
                        cmd.critical_temperature_R);
 }
 EXPORT_SYMBOL(iwl_rf_kill_ct_config);
+
+/*
+ * CARD_STATE_CMD
+ *
+ * Use: Sets the device's internal card state to enable, disable, or halt
+ *
+ * When in the 'enable' state the card operates as normal.
+ * When in the 'disable' state, the card enters into a low power mode.
+ * When in the 'halt' state, the card is shut down and must be fully
+ * restarted to come back on.
+ */
+static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
+{
+       struct iwl_host_cmd cmd = {
+               .id = REPLY_CARD_STATE_CMD,
+               .len = sizeof(u32),
+               .data = &flags,
+               .meta.flags = meta_flag,
+       };
+
+       return iwl_send_cmd(priv, &cmd);
+}
+
+void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv)
+{
+       unsigned long flags;
+
+       if (test_bit(STATUS_RF_KILL_SW, &priv->status))
+               return;
+
+       IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO OFF\n");
+
+       iwl_scan_cancel(priv);
+       /* FIXME: This is a workaround for AP */
+       if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+               spin_lock_irqsave(&priv->lock, flags);
+               iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+                           CSR_UCODE_SW_BIT_RFKILL);
+               spin_unlock_irqrestore(&priv->lock, flags);
+               /* call the host command only if no hw rf-kill set */
+               if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
+                   iwl_is_ready(priv))
+                       iwl_send_card_state(priv,
+                               CARD_STATE_CMD_DISABLE, 0);
+               set_bit(STATUS_RF_KILL_SW, &priv->status);
+                       /* make sure mac80211 stop sending Tx frame */
+               if (priv->mac80211_registered)
+                       ieee80211_stop_queues(priv->hw);
+       }
+}
+EXPORT_SYMBOL(iwl_radio_kill_sw_disable_radio);
+
+int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
+{
+       unsigned long flags;
+
+       if (!test_bit(STATUS_RF_KILL_SW, &priv->status))
+               return 0;
+
+       IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO ON\n");
+
+       spin_lock_irqsave(&priv->lock, flags);
+       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+
+       /* If the driver is up it will receive CARD_STATE_NOTIFICATION
+        * notification where it will clear SW rfkill status.
+        * Setting it here would break the handler. Only if the
+        * interface is down we can set here since we don't
+        * receive any further notification.
+        */
+       if (!priv->is_open)
+               clear_bit(STATUS_RF_KILL_SW, &priv->status);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       /* wake up ucode */
+       msleep(10);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       iwl_read32(priv, CSR_UCODE_DRV_GP1);
+       if (!iwl_grab_nic_access(priv))
+               iwl_release_nic_access(priv);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
+               IWL_DEBUG_RF_KILL("Can not turn radio back on - "
+                                 "disabled by HW switch\n");
+               return 0;
+       }
+
+       /* If the driver is already loaded, it will receive
+        * CARD_STATE_NOTIFICATION notifications and the handler will
+        * call restart to reload the driver.
+        */
+       return 1;
+}
+EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio);