| .. | .. |
|---|
| 6 | 6 | * GPL LICENSE SUMMARY |
|---|
| 7 | 7 | * |
|---|
| 8 | 8 | * Copyright(c) 2017 Intel Deutschland GmbH |
|---|
| 9 | | - * Copyright(c) 2018 Intel Corporation |
|---|
| 9 | + * Copyright(c) 2018 - 2020 Intel Corporation |
|---|
| 10 | 10 | * |
|---|
| 11 | 11 | * This program is free software; you can redistribute it and/or modify |
|---|
| 12 | 12 | * it under the terms of version 2 of the GNU General Public License as |
|---|
| .. | .. |
|---|
| 20 | 20 | * BSD LICENSE |
|---|
| 21 | 21 | * |
|---|
| 22 | 22 | * Copyright(c) 2017 Intel Deutschland GmbH |
|---|
| 23 | | - * Copyright(c) 2018 Intel Corporation |
|---|
| 23 | + * Copyright(c) 2018 - 2020 Intel Corporation |
|---|
| 24 | 24 | * All rights reserved. |
|---|
| 25 | 25 | * |
|---|
| 26 | 26 | * Redistribution and use in source and binary forms, with or without |
|---|
| .. | .. |
|---|
| 55 | 55 | #include "iwl-context-info.h" |
|---|
| 56 | 56 | #include "iwl-context-info-gen3.h" |
|---|
| 57 | 57 | #include "internal.h" |
|---|
| 58 | +#include "fw/dbg.h" |
|---|
| 58 | 59 | |
|---|
| 59 | 60 | /* |
|---|
| 60 | 61 | * Start up NIC's basic functionality after it has been reset |
|---|
| 61 | 62 | * (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop()) |
|---|
| 62 | 63 | * NOTE: This does not load uCode nor start the embedded processor |
|---|
| 63 | 64 | */ |
|---|
| 64 | | -static int iwl_pcie_gen2_apm_init(struct iwl_trans *trans) |
|---|
| 65 | +int iwl_pcie_gen2_apm_init(struct iwl_trans *trans) |
|---|
| 65 | 66 | { |
|---|
| 66 | 67 | int ret = 0; |
|---|
| 67 | 68 | |
|---|
| .. | .. |
|---|
| 91 | 92 | |
|---|
| 92 | 93 | iwl_pcie_apm_config(trans); |
|---|
| 93 | 94 | |
|---|
| 94 | | - /* |
|---|
| 95 | | - * Set "initialization complete" bit to move adapter from |
|---|
| 96 | | - * D0U* --> D0A* (powered-up active) state. |
|---|
| 97 | | - */ |
|---|
| 98 | | - iwl_set_bit(trans, CSR_GP_CNTRL, |
|---|
| 99 | | - BIT(trans->cfg->csr->flag_init_done)); |
|---|
| 100 | | - |
|---|
| 101 | | - /* |
|---|
| 102 | | - * Wait for clock stabilization; once stabilized, access to |
|---|
| 103 | | - * device-internal resources is supported, e.g. iwl_write_prph() |
|---|
| 104 | | - * and accesses to uCode SRAM. |
|---|
| 105 | | - */ |
|---|
| 106 | | - ret = iwl_poll_bit(trans, CSR_GP_CNTRL, |
|---|
| 107 | | - BIT(trans->cfg->csr->flag_mac_clock_ready), |
|---|
| 108 | | - BIT(trans->cfg->csr->flag_mac_clock_ready), |
|---|
| 109 | | - 25000); |
|---|
| 110 | | - if (ret < 0) { |
|---|
| 111 | | - IWL_DEBUG_INFO(trans, "Failed to init the card\n"); |
|---|
| 95 | + ret = iwl_finish_nic_init(trans, trans->trans_cfg); |
|---|
| 96 | + if (ret) |
|---|
| 112 | 97 | return ret; |
|---|
| 113 | | - } |
|---|
| 114 | 98 | |
|---|
| 115 | 99 | set_bit(STATUS_DEVICE_ENABLED, &trans->status); |
|---|
| 116 | 100 | |
|---|
| .. | .. |
|---|
| 148 | 132 | * Clear "initialization complete" bit to move adapter from |
|---|
| 149 | 133 | * D0A* (powered-up Active) --> D0U* (Uninitialized) state. |
|---|
| 150 | 134 | */ |
|---|
| 151 | | - iwl_clear_bit(trans, CSR_GP_CNTRL, |
|---|
| 152 | | - BIT(trans->cfg->csr->flag_init_done)); |
|---|
| 135 | + iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
|---|
| 153 | 136 | } |
|---|
| 154 | 137 | |
|---|
| 155 | | -void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power) |
|---|
| 138 | +void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) |
|---|
| 156 | 139 | { |
|---|
| 157 | 140 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
|---|
| 158 | 141 | |
|---|
| .. | .. |
|---|
| 162 | 145 | return; |
|---|
| 163 | 146 | |
|---|
| 164 | 147 | trans_pcie->is_down = true; |
|---|
| 165 | | - |
|---|
| 166 | | - /* Stop dbgc before stopping device */ |
|---|
| 167 | | - iwl_write_prph(trans, DBGC_IN_SAMPLE, 0); |
|---|
| 168 | | - udelay(100); |
|---|
| 169 | | - iwl_write_prph(trans, DBGC_OUT_CTRL, 0); |
|---|
| 170 | 148 | |
|---|
| 171 | 149 | /* tell the device to stop sending interrupts */ |
|---|
| 172 | 150 | iwl_disable_interrupts(trans); |
|---|
| .. | .. |
|---|
| 184 | 162 | if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) { |
|---|
| 185 | 163 | IWL_DEBUG_INFO(trans, |
|---|
| 186 | 164 | "DEVICE_ENABLED bit was set and is now cleared\n"); |
|---|
| 187 | | - iwl_pcie_gen2_tx_stop(trans); |
|---|
| 165 | + iwl_txq_gen2_tx_stop(trans); |
|---|
| 188 | 166 | iwl_pcie_rx_stop(trans); |
|---|
| 189 | 167 | } |
|---|
| 190 | 168 | |
|---|
| 191 | 169 | iwl_pcie_ctxt_info_free_paging(trans); |
|---|
| 192 | | - if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560) |
|---|
| 170 | + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) |
|---|
| 193 | 171 | iwl_pcie_ctxt_info_gen3_free(trans); |
|---|
| 194 | 172 | else |
|---|
| 195 | 173 | iwl_pcie_ctxt_info_free(trans); |
|---|
| 196 | 174 | |
|---|
| 197 | 175 | /* Make sure (redundant) we've released our request to stay awake */ |
|---|
| 198 | 176 | iwl_clear_bit(trans, CSR_GP_CNTRL, |
|---|
| 199 | | - BIT(trans->cfg->csr->flag_mac_access_req)); |
|---|
| 177 | + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); |
|---|
| 200 | 178 | |
|---|
| 201 | 179 | /* Stop the device, and put it in low power state */ |
|---|
| 202 | 180 | iwl_pcie_gen2_apm_stop(trans, false); |
|---|
| .. | .. |
|---|
| 236 | 214 | iwl_pcie_prepare_card_hw(trans); |
|---|
| 237 | 215 | } |
|---|
| 238 | 216 | |
|---|
| 239 | | -void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans, bool low_power) |
|---|
| 217 | +void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans) |
|---|
| 240 | 218 | { |
|---|
| 241 | 219 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
|---|
| 242 | 220 | bool was_in_rfkill; |
|---|
| .. | .. |
|---|
| 244 | 222 | mutex_lock(&trans_pcie->mutex); |
|---|
| 245 | 223 | trans_pcie->opmode_down = true; |
|---|
| 246 | 224 | was_in_rfkill = test_bit(STATUS_RFKILL_OPMODE, &trans->status); |
|---|
| 247 | | - _iwl_trans_pcie_gen2_stop_device(trans, low_power); |
|---|
| 225 | + _iwl_trans_pcie_gen2_stop_device(trans); |
|---|
| 248 | 226 | iwl_trans_pcie_handle_stop_rfkill(trans, was_in_rfkill); |
|---|
| 249 | 227 | mutex_unlock(&trans_pcie->mutex); |
|---|
| 250 | 228 | } |
|---|
| .. | .. |
|---|
| 252 | 230 | static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans) |
|---|
| 253 | 231 | { |
|---|
| 254 | 232 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
|---|
| 233 | + int queue_size = max_t(u32, IWL_CMD_QUEUE_SIZE, |
|---|
| 234 | + trans->cfg->min_txq_size); |
|---|
| 255 | 235 | |
|---|
| 256 | 236 | /* TODO: most of the logic can be removed in A0 - but not in Z0 */ |
|---|
| 257 | 237 | spin_lock(&trans_pcie->irq_lock); |
|---|
| .. | .. |
|---|
| 265 | 245 | return -ENOMEM; |
|---|
| 266 | 246 | |
|---|
| 267 | 247 | /* Allocate or reset and init all Tx and Command queues */ |
|---|
| 268 | | - if (iwl_pcie_gen2_tx_init(trans)) |
|---|
| 248 | + if (iwl_txq_gen2_init(trans, trans->txqs.cmd.q_id, queue_size)) |
|---|
| 269 | 249 | return -ENOMEM; |
|---|
| 270 | 250 | |
|---|
| 271 | 251 | /* enable shadow regs in HW */ |
|---|
| .. | .. |
|---|
| 282 | 262 | iwl_pcie_reset_ict(trans); |
|---|
| 283 | 263 | |
|---|
| 284 | 264 | /* make sure all queue are not stopped/used */ |
|---|
| 285 | | - memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); |
|---|
| 286 | | - memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used)); |
|---|
| 265 | + memset(trans->txqs.queue_stopped, 0, |
|---|
| 266 | + sizeof(trans->txqs.queue_stopped)); |
|---|
| 267 | + memset(trans->txqs.queue_used, 0, sizeof(trans->txqs.queue_used)); |
|---|
| 287 | 268 | |
|---|
| 288 | 269 | /* now that we got alive we can free the fw image & the context info. |
|---|
| 289 | 270 | * paging memory cannot be freed included since FW will still use it |
|---|
| 290 | 271 | */ |
|---|
| 291 | | - iwl_pcie_ctxt_info_free(trans); |
|---|
| 272 | + if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) |
|---|
| 273 | + iwl_pcie_ctxt_info_free(trans); |
|---|
| 292 | 274 | |
|---|
| 293 | 275 | /* |
|---|
| 294 | 276 | * Re-enable all the interrupts, including the RF-Kill one, now that |
|---|
| .. | .. |
|---|
| 298 | 280 | mutex_lock(&trans_pcie->mutex); |
|---|
| 299 | 281 | iwl_pcie_check_hw_rf_kill(trans); |
|---|
| 300 | 282 | mutex_unlock(&trans_pcie->mutex); |
|---|
| 283 | +} |
|---|
| 284 | + |
|---|
| 285 | +static void iwl_pcie_set_ltr(struct iwl_trans *trans) |
|---|
| 286 | +{ |
|---|
| 287 | + u32 ltr_val = CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ | |
|---|
| 288 | + u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC, |
|---|
| 289 | + CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE) | |
|---|
| 290 | + u32_encode_bits(250, |
|---|
| 291 | + CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL) | |
|---|
| 292 | + CSR_LTR_LONG_VAL_AD_SNOOP_REQ | |
|---|
| 293 | + u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC, |
|---|
| 294 | + CSR_LTR_LONG_VAL_AD_SNOOP_SCALE) | |
|---|
| 295 | + u32_encode_bits(250, CSR_LTR_LONG_VAL_AD_SNOOP_VAL); |
|---|
| 296 | + |
|---|
| 297 | + /* |
|---|
| 298 | + * To workaround hardware latency issues during the boot process, |
|---|
| 299 | + * initialize the LTR to ~250 usec (see ltr_val above). |
|---|
| 300 | + * The firmware initializes this again later (to a smaller value). |
|---|
| 301 | + */ |
|---|
| 302 | + if ((trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210 || |
|---|
| 303 | + trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) && |
|---|
| 304 | + !trans->trans_cfg->integrated) { |
|---|
| 305 | + iwl_write32(trans, CSR_LTR_LONG_VAL_AD, ltr_val); |
|---|
| 306 | + } else if (trans->trans_cfg->integrated && |
|---|
| 307 | + trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) { |
|---|
| 308 | + iwl_write_prph(trans, HPM_MAC_LTR_CSR, HPM_MAC_LRT_ENABLE_ALL); |
|---|
| 309 | + iwl_write_prph(trans, HPM_UMAC_LTR, ltr_val); |
|---|
| 310 | + } |
|---|
| 301 | 311 | } |
|---|
| 302 | 312 | |
|---|
| 303 | 313 | int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, |
|---|
| .. | .. |
|---|
| 358 | 368 | goto out; |
|---|
| 359 | 369 | } |
|---|
| 360 | 370 | |
|---|
| 361 | | - if (trans->cfg->device_family == IWL_DEVICE_FAMILY_22560) |
|---|
| 371 | + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) |
|---|
| 362 | 372 | ret = iwl_pcie_ctxt_info_gen3_init(trans, fw); |
|---|
| 363 | 373 | else |
|---|
| 364 | 374 | ret = iwl_pcie_ctxt_info_init(trans, fw); |
|---|
| 365 | 375 | if (ret) |
|---|
| 366 | 376 | goto out; |
|---|
| 367 | 377 | |
|---|
| 378 | + iwl_pcie_set_ltr(trans); |
|---|
| 379 | + |
|---|
| 380 | + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) |
|---|
| 381 | + iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); |
|---|
| 382 | + else |
|---|
| 383 | + iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1); |
|---|
| 384 | + |
|---|
| 368 | 385 | /* re-check RF-Kill state since we may have missed the interrupt */ |
|---|
| 369 | 386 | hw_rfkill = iwl_pcie_check_hw_rf_kill(trans); |
|---|
| 370 | 387 | if (hw_rfkill && !run_in_rfkill) |
|---|