summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/iwlwifi/iwl-agn.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c144
1 files changed, 99 insertions, 45 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 8837171ad553..e0fef9f257c2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -50,8 +50,8 @@
#include "iwl-agn-calib.h"
#include "iwl-agn.h"
#include "iwl-shared.h"
-#include "iwl-bus.h"
#include "iwl-trans.h"
+#include "iwl-op-mode.h"
/******************************************************************************
*
@@ -618,7 +618,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
.valid = cpu_to_le32(valid_tx_ant),
};
- if (IWL_UCODE_API(priv->ucode_ver) > 1) {
+ if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) > 1) {
IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
return iwl_trans_send_cmd_pdu(trans(priv),
TX_ANT_CONFIGURATION_CMD,
@@ -738,14 +738,14 @@ int iwl_alive_start(struct iwl_priv *priv)
return iwl_power_update_mode(priv, true);
}
-static void iwl_cancel_deferred_work(struct iwl_priv *priv);
-
-void __iwl_down(struct iwl_priv *priv)
+void iwl_down(struct iwl_priv *priv)
{
int exit_pending;
IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
+ lockdep_assert_held(&priv->shrd->mutex);
+
iwl_scan_cancel_timeout(priv, 200);
/*
@@ -803,15 +803,6 @@ void __iwl_down(struct iwl_priv *priv)
priv->beacon_skb = NULL;
}
-void iwl_down(struct iwl_priv *priv)
-{
- mutex_lock(&priv->shrd->mutex);
- __iwl_down(priv);
- mutex_unlock(&priv->shrd->mutex);
-
- iwl_cancel_deferred_work(priv);
-}
-
/*****************************************************************************
*
* Workqueue callbacks
@@ -869,7 +860,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv)
bt_status = priv->bt_status;
bt_is_sco = priv->bt_is_sco;
- __iwl_down(priv);
+ iwl_down(priv);
priv->bt_full_concurrent = bt_full_concurrent;
priv->bt_ci_compliance = bt_ci_compliance;
@@ -939,7 +930,7 @@ static void iwlagn_disable_roc_work(struct work_struct *work)
static void iwl_setup_deferred_work(struct iwl_priv *priv)
{
- priv->shrd->workqueue = create_singlethread_workqueue(DRV_NAME);
+ priv->workqueue = create_singlethread_workqueue(DRV_NAME);
init_waitqueue_head(&priv->shrd->wait_command_queue);
@@ -970,7 +961,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
priv->watchdog.function = iwl_bg_watchdog;
}
-static void iwl_cancel_deferred_work(struct iwl_priv *priv)
+void iwl_cancel_deferred_work(struct iwl_priv *priv)
{
if (cfg(priv)->lib->cancel_deferred_work)
cfg(priv)->lib->cancel_deferred_work(priv);
@@ -1091,7 +1082,7 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
#define IWL_RX_BUF_SIZE_4K (4 * 1024)
#define IWL_RX_BUF_SIZE_8K (8 * 1024)
-static int iwl_set_hw_params(struct iwl_priv *priv)
+static void iwl_set_hw_params(struct iwl_priv *priv)
{
if (iwlagn_mod_params.amsdu_size_8K)
hw_params(priv).rx_page_order =
@@ -1111,7 +1102,7 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout;
/* Device-specific setup */
- return cfg(priv)->lib->set_hw_params(priv);
+ cfg(priv)->lib->set_hw_params(priv);
}
@@ -1151,37 +1142,43 @@ static void iwl_debug_config(struct iwl_priv *priv)
#endif
}
-int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
- struct iwl_cfg *cfg)
+static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
{
+ struct iwl_fw *fw = &nic(trans)->fw;
int err = 0;
struct iwl_priv *priv;
struct ieee80211_hw *hw;
+ struct iwl_op_mode *op_mode;
u16 num_mac;
+ u32 ucode_flags;
/************************
* 1. Allocating HW data
************************/
hw = iwl_alloc_all();
if (!hw) {
- pr_err("%s: Cannot allocate network device\n", cfg->name);
+ pr_err("%s: Cannot allocate network device\n",
+ cfg(trans)->name);
err = -ENOMEM;
goto out;
}
- priv = hw->priv;
- priv->shrd = bus->shrd;
+ op_mode = hw->priv;
+ op_mode->ops = &iwl_dvm_ops;
+ priv = IWL_OP_MODE_GET_DVM(op_mode);
+ priv->shrd = trans->shrd;
priv->shrd->priv = priv;
+ iwl_trans_configure(trans(priv), op_mode);
+
/* At this point both hw and priv are allocated. */
- SET_IEEE80211_DEV(hw, trans(priv)->dev);
+ SET_IEEE80211_DEV(priv->hw, trans(priv)->dev);
/* show what debugging capabilities we have */
iwl_debug_config(priv);
IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
- cfg(priv) = cfg;
/* is antenna coupling more than 35dB ? */
priv->bt_ant_couple_ok =
@@ -1217,7 +1214,7 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
* 4. Read EEPROM
*****************/
/* Read the EEPROM */
- err = iwl_eeprom_init(priv, trans(priv)->hw_rev);
+ err = iwl_eeprom_init(trans(priv), trans(priv)->hw_rev);
/* Reset chip to save power until we load uCode during "up". */
iwl_trans_stop_hw(trans(priv));
if (err) {
@@ -1248,11 +1245,23 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
/************************
* 5. Setup HW constants
************************/
- if (iwl_set_hw_params(priv)) {
- err = -ENOENT;
- IWL_ERR(priv, "failed to set hw parameters\n");
- goto out_free_eeprom;
- }
+ iwl_set_hw_params(priv);
+
+ ucode_flags = fw->ucode_capa.flags;
+
+#ifndef CONFIG_IWLWIFI_P2P
+ ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
+#endif
+ if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE))
+ ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
+
+ /*
+ * if not PAN, then don't support P2P -- might be a uCode
+ * packaging bug or due to the eeprom check above
+ */
+ if (!(ucode_flags & IWL_UCODE_TLV_FLAGS_PAN))
+ ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
+
/*******************
* 6. Setup priv
@@ -1273,17 +1282,49 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
iwl_power_initialize(priv);
iwl_tt_initialize(priv);
- init_completion(&priv->firmware_loading_complete);
+ snprintf(priv->hw->wiphy->fw_version,
+ sizeof(priv->hw->wiphy->fw_version),
+ "%s", fw->fw_version);
+
+ priv->new_scan_threshold_behaviour =
+ !!(ucode_flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
+
+ if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
+ priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
+ priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
+ } else {
+ priv->sta_key_max_num = STA_KEY_MAX_NUM;
+ priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+ }
+
+ priv->phy_calib_chain_noise_reset_cmd =
+ fw->ucode_capa.standard_phy_calibration_size;
+ priv->phy_calib_chain_noise_gain_cmd =
+ fw->ucode_capa.standard_phy_calibration_size + 1;
- err = iwl_request_firmware(priv, true);
+ /* initialize all valid contexts */
+ iwl_init_context(priv, ucode_flags);
+
+ /**************************************************
+ * This is still part of probe() in a sense...
+ *
+ * 9. Setup and register with mac80211 and debugfs
+ **************************************************/
+ err = iwlagn_mac_setup_register(priv, &fw->ucode_capa);
if (err)
goto out_destroy_workqueue;
- return 0;
+ err = iwl_dbgfs_register(priv, DRV_NAME);
+ if (err)
+ IWL_ERR(priv,
+ "failed to create debugfs files. Ignoring error: %d\n",
+ err);
+
+ return op_mode;
out_destroy_workqueue:
- destroy_workqueue(priv->shrd->workqueue);
- priv->shrd->workqueue = NULL;
+ destroy_workqueue(priv->workqueue);
+ priv->workqueue = NULL;
iwl_uninit_drv(priv);
out_free_eeprom:
iwl_eeprom_free(priv->shrd);
@@ -1291,12 +1332,15 @@ out_free_traffic_mem:
iwl_free_traffic_mem(priv);
ieee80211_free_hw(priv->hw);
out:
- return err;
+ op_mode = NULL;
+ return op_mode;
}
-void __devexit iwl_remove(struct iwl_priv * priv)
+static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
{
- wait_for_completion(&priv->firmware_loading_complete);
+ struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
+
+ wait_for_completion(&nic(priv)->request_firmware_complete);
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
@@ -1316,18 +1360,18 @@ void __devexit iwl_remove(struct iwl_priv * priv)
/*This will stop the queues, move the device to low power state */
iwl_trans_stop_device(trans(priv));
- iwl_dealloc_ucode(trans(priv));
+ iwl_dealloc_ucode(nic(priv));
iwl_eeprom_free(priv->shrd);
/*netif_stop_queue(dev); */
- flush_workqueue(priv->shrd->workqueue);
+ flush_workqueue(priv->workqueue);
/* ieee80211_unregister_hw calls iwlagn_mac_stop, which flushes
- * priv->shrd->workqueue... so we can't take down the workqueue
+ * priv->workqueue... so we can't take down the workqueue
* until now... */
- destroy_workqueue(priv->shrd->workqueue);
- priv->shrd->workqueue = NULL;
+ destroy_workqueue(priv->workqueue);
+ priv->workqueue = NULL;
iwl_free_traffic_mem(priv);
iwl_uninit_drv(priv);
@@ -1337,6 +1381,16 @@ void __devexit iwl_remove(struct iwl_priv * priv)
ieee80211_free_hw(priv->hw);
}
+const struct iwl_op_mode_ops iwl_dvm_ops = {
+ .start = iwl_op_mode_dvm_start,
+ .stop = iwl_op_mode_dvm_stop,
+ .rx = iwl_rx_dispatch,
+ .queue_full = iwl_stop_sw_queue,
+ .queue_not_full = iwl_wake_sw_queue,
+ .hw_rf_kill = iwl_set_hw_rfkill_state,
+ .free_skb = iwl_free_skb,
+ .nic_error = iwl_nic_error,
+};
/*****************************************************************************
*