diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/dvm/main.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/dvm/main.c | 159 |
1 files changed, 88 insertions, 71 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index 769b75c3fa5b..1d619384c629 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -2,7 +2,7 @@ /****************************************************************************** * * Copyright(c) 2003 - 2014, 2018 - 2022 Intel Corporation. All rights reserved. - * Copyright(c) 2024 Intel Corporation. All rights reserved. + * Copyright(c) 2024-2025 Intel Corporation. All rights reserved. * Copyright(c) 2015 Intel Deutschland GmbH * * Portions of this file are derived from the ipw3945 project, as well @@ -824,11 +824,11 @@ int iwl_alive_start(struct iwl_priv *priv) iwlagn_send_tx_ant_config(priv, priv->nvm_data->valid_tx_ant); if (iwl_is_associated_ctx(ctx) && !priv->wowlan) { - struct iwl_rxon_cmd *active_rxon = - (struct iwl_rxon_cmd *)&ctx->active; + struct iwl_rxon_cmd *active = (void *)(uintptr_t)&ctx->active; + /* apply any changes in staging */ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; + active->filter_flags &= ~RXON_FILTER_ASSOC_MSK; } else { struct iwl_rxon_context *tmp; /* Initialize our rx_config data */ @@ -1082,8 +1082,8 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv) cancel_work_sync(&priv->bt_full_concurrency); cancel_work_sync(&priv->bt_runtime_config); - del_timer_sync(&priv->statistics_periodic); - del_timer_sync(&priv->ucode_trace); + timer_delete_sync(&priv->statistics_periodic); + timer_delete_sync(&priv->ucode_trace); } static int iwl_init_drv(struct iwl_priv *priv) @@ -1137,9 +1137,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv) static void iwl_set_hw_params(struct iwl_priv *priv) { - if (priv->cfg->ht_params) + /* there are no devices with HT but without HT40 on all bands */ + if (priv->cfg->ht_params.ht40_bands) priv->hw_params.use_rts_for_aggregation = - priv->cfg->ht_params->use_rts_for_aggregation; + priv->cfg->ht_params.use_rts_for_aggregation; /* Device-specific setup */ priv->lib->set_hw_params(priv); @@ -1173,8 +1174,9 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) { struct iwl_nvm_data *data = priv->nvm_data; + /* all HT devices also have HT40 on at least one band */ if (data->sku_cap_11n_enable && - !priv->cfg->ht_params) { + !priv->cfg->ht_params.ht40_bands) { IWL_ERR(priv, "Invalid 11n configuration\n"); return -EINVAL; } @@ -1224,7 +1226,7 @@ static int iwl_nvm_check_version(struct iwl_nvm_data *data, } static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, - const struct iwl_cfg *cfg, + const struct iwl_rf_cfg *cfg, const struct iwl_fw *fw, struct dentry *dbgfs_dir) { @@ -1233,7 +1235,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, struct iwl_op_mode *op_mode; u16 num_mac; u32 ucode_flags; - struct iwl_trans_config trans_cfg = {}; static const u8 no_reclaim_cmds[] = { REPLY_RX_PHY_CMD, REPLY_RX_MPDU_CMD, @@ -1241,14 +1242,16 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, STATISTICS_NOTIFICATION, REPLY_TX, }; - int i; + int i, err; /************************ * 1. Allocating HW data ************************/ hw = iwl_alloc_all(); if (!hw) { - pr_err("%s: Cannot allocate network device\n", trans->name); + pr_err("%s: Cannot allocate network device\n", + trans->info.name); + err = -ENOMEM; goto out; } @@ -1260,7 +1263,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, priv->cfg = cfg; priv->fw = fw; - switch (priv->trans->trans_cfg->device_family) { + switch (priv->trans->mac_cfg->device_family) { case IWL_DEVICE_FAMILY_1000: case IWL_DEVICE_FAMILY_100: priv->lib = &iwl_dvm_1000_cfg; @@ -1299,59 +1302,59 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, break; } - if (WARN_ON(!priv->lib)) + if (WARN_ON(!priv->lib)) { + err = -ENODEV; goto out_free_hw; + } /* * Populate the state variables that the transport layer needs * to know about. */ - trans_cfg.op_mode = op_mode; - trans_cfg.no_reclaim_cmds = no_reclaim_cmds; - trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); + BUILD_BUG_ON(sizeof(no_reclaim_cmds) > + sizeof(trans->conf.no_reclaim_cmds)); + memcpy(trans->conf.no_reclaim_cmds, no_reclaim_cmds, + sizeof(no_reclaim_cmds)); switch (iwlwifi_mod_params.amsdu_size) { case IWL_AMSDU_DEF: case IWL_AMSDU_4K: - trans_cfg.rx_buf_size = IWL_AMSDU_4K; + trans->conf.rx_buf_size = IWL_AMSDU_4K; break; case IWL_AMSDU_8K: - trans_cfg.rx_buf_size = IWL_AMSDU_8K; + trans->conf.rx_buf_size = IWL_AMSDU_8K; break; case IWL_AMSDU_12K: default: - trans_cfg.rx_buf_size = IWL_AMSDU_4K; + trans->conf.rx_buf_size = IWL_AMSDU_4K; pr_err("Unsupported amsdu_size: %d\n", iwlwifi_mod_params.amsdu_size); } - trans_cfg.command_groups = iwl_dvm_groups; - trans_cfg.command_groups_size = ARRAY_SIZE(iwl_dvm_groups); + trans->conf.command_groups = iwl_dvm_groups; + trans->conf.command_groups_size = ARRAY_SIZE(iwl_dvm_groups); - trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM; - trans_cfg.cb_data_offs = offsetof(struct ieee80211_tx_info, - driver_data[2]); + trans->conf.cmd_fifo = IWLAGN_CMD_FIFO_NUM; + trans->conf.cb_data_offs = offsetof(struct ieee80211_tx_info, + driver_data[2]); WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE < - priv->trans->trans_cfg->base_params->num_of_queues); + priv->trans->mac_cfg->base->num_of_queues); ucode_flags = fw->ucode_capa.flags; if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; - trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; + trans->conf.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; } else { priv->sta_key_max_num = STA_KEY_MAX_NUM; - trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; + trans->conf.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; } - /* Configure transport layer */ - iwl_trans_configure(priv->trans, &trans_cfg); + trans->conf.rx_mpdu_cmd = REPLY_RX_MPDU_CMD; + trans->conf.rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start); - trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD; - trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start); - trans->command_groups = trans_cfg.command_groups; - trans->command_groups_size = trans_cfg.command_groups_size; + iwl_trans_op_mode_enter(priv->trans, op_mode); /* At this point both hw and priv are allocated. */ @@ -1375,16 +1378,18 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, * 2. Read REV register ***********************/ IWL_INFO(priv, "Detected %s, REV=0x%X\n", - priv->trans->name, priv->trans->hw_rev); + priv->trans->info.name, priv->trans->info.hw_rev); - if (iwl_trans_start_hw(priv->trans)) - goto out_free_hw; + err = iwl_trans_start_hw(priv->trans); + if (err) + goto out_leave_trans; /* Read the EEPROM */ - if (iwl_read_eeprom(priv->trans, &priv->eeprom_blob, - &priv->eeprom_blob_size)) { + err = iwl_read_eeprom(priv->trans, &priv->eeprom_blob, + &priv->eeprom_blob_size); + if (err) { IWL_ERR(priv, "Unable to init EEPROM\n"); - goto out_free_hw; + goto out_leave_trans; } /* Reset chip to save power until we load uCode during "up". */ @@ -1393,13 +1398,17 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, priv->nvm_data = iwl_parse_eeprom_data(priv->trans, priv->cfg, priv->eeprom_blob, priv->eeprom_blob_size); - if (!priv->nvm_data) + if (!priv->nvm_data) { + err = -ENOMEM; goto out_free_eeprom_blob; + } - if (iwl_nvm_check_version(priv->nvm_data, priv->trans)) + err = iwl_nvm_check_version(priv->nvm_data, priv->trans); + if (err) goto out_free_eeprom; - if (iwl_eeprom_init_hw_params(priv)) + err = iwl_eeprom_init_hw_params(priv); + if (err) goto out_free_eeprom; /* extract MAC Address */ @@ -1428,10 +1437,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, * packaging bug or due to the eeprom check above */ priv->sta_key_max_num = STA_KEY_MAX_NUM; - trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; - - /* Configure transport layer again*/ - iwl_trans_configure(priv->trans, &trans_cfg); + trans->conf.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; } /******************* @@ -1446,7 +1452,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, atomic_set(&priv->queue_stop_count[i], 0); } - if (iwl_init_drv(priv)) + err = iwl_init_drv(priv); + if (err) goto out_free_eeprom; /* At this point both hw and priv are initialized. */ @@ -1480,7 +1487,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, * * 7. Setup and register with mac80211 and debugfs **************************************************/ - if (iwlagn_mac_setup_register(priv, &fw->ucode_capa)) + err = iwlagn_mac_setup_register(priv, &fw->ucode_capa); + if (err) goto out_destroy_workqueue; iwl_dbgfs_register(priv, dbgfs_dir); @@ -1497,11 +1505,12 @@ out_free_eeprom_blob: kfree(priv->eeprom_blob); out_free_eeprom: kfree(priv->nvm_data); +out_leave_trans: + iwl_trans_op_mode_leave(priv->trans); out_free_hw: ieee80211_free_hw(priv->hw); out: - op_mode = NULL; - return op_mode; + return ERR_PTR(err); } static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) @@ -1895,17 +1904,9 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) unsigned int reload_msec; unsigned long reload_jiffies; - if (iwl_have_debug_level(IWL_DL_FW)) - iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS); - /* uCode is no longer loaded. */ priv->ucode_loaded = false; - /* Set the FW error flag -- cleared on iwl_down */ - set_bit(STATUS_FW_ERROR, &priv->status); - - iwl_abort_notification_waits(&priv->notif_wait); - /* Keep the restart process from trying to send host * commands by clearing the ready bit */ clear_bit(STATUS_READY, &priv->status); @@ -1942,27 +1943,43 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) } } -static void iwl_nic_error(struct iwl_op_mode *op_mode, bool sync) +static void iwl_nic_error(struct iwl_op_mode *op_mode, + enum iwl_fw_error_type type) { struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); + /* Set the FW error flag -- cleared on iwl_down */ + set_bit(STATUS_FW_ERROR, &priv->status); + + iwl_abort_notification_waits(&priv->notif_wait); + + if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL && iwl_check_for_ct_kill(priv)) + return; + IWL_ERR(priv, "Loaded firmware version: %s\n", priv->fw->fw_version); - iwl_dump_nic_error_log(priv); - iwl_dump_nic_event_log(priv, false, NULL); + if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL) { + IWL_ERR(priv, "Command queue full!\n"); + } else { + iwl_dump_nic_error_log(priv); + iwl_dump_nic_event_log(priv, false, NULL); + } - iwlagn_fw_error(priv, false); + if (iwl_have_debug_level(IWL_DL_FW)) + iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS); } -static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) +static bool iwlagn_sw_reset(struct iwl_op_mode *op_mode, + enum iwl_fw_error_type type) { struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); - if (!iwl_check_for_ct_kill(priv)) { - IWL_ERR(priv, "Restarting adapter queue is full\n"); - iwlagn_fw_error(priv, false); - } + if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL && iwl_check_for_ct_kill(priv)) + return false; + + iwlagn_fw_error(priv, false); + return true; } #define EEPROM_RF_CONFIG_TYPE_MAX 0x3 @@ -1974,7 +1991,7 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode) /* SKU Control */ iwl_trans_set_bits_mask(priv->trans, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP_DASH, - CSR_HW_REV_STEP_DASH(priv->trans->hw_rev)); + CSR_HW_REV_STEP_DASH(priv->trans->info.hw_rev)); /* write radio config values to register */ if (priv->nvm_data->radio_cfg_type <= EEPROM_RF_CONFIG_TYPE_MAX) { @@ -2117,7 +2134,7 @@ static const struct iwl_op_mode_ops iwl_dvm_ops = { .hw_rf_kill = iwl_set_hw_rfkill_state, .free_skb = iwl_free_skb, .nic_error = iwl_nic_error, - .cmd_queue_full = iwl_cmd_queue_full, + .sw_reset = iwlagn_sw_reset, .nic_config = iwl_nic_config, .wimax_active = iwl_wimax_active, }; |