Path: blob/main/sys/contrib/dev/iwlwifi/pcie/gen1_2/trans-gen2.c
48406 views
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause1/*2* Copyright (C) 2017 Intel Deutschland GmbH3* Copyright (C) 2018-2025 Intel Corporation4*/5#if defined(__FreeBSD__)6#include <linux/delay.h>7#endif8#include "iwl-trans.h"9#include "iwl-prph.h"10#include "pcie/iwl-context-info.h"11#include "pcie/iwl-context-info-v2.h"12#include "internal.h"13#include "fw/dbg.h"1415#define FW_RESET_TIMEOUT (HZ / 5)1617/*18* Start up NIC's basic functionality after it has been reset19* (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop())20* NOTE: This does not load uCode nor start the embedded processor21*/22int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)23{24int ret = 0;2526IWL_DEBUG_INFO(trans, "Init card's basic functions\n");2728/*29* Use "set_bit" below rather than "write", to preserve any hardware30* bits already set by default after reset.31*/3233/*34* Disable L0s without affecting L1;35* don't wait for ICH L0s (ICH bug W/A)36*/37iwl_set_bit(trans, CSR_GIO_CHICKEN_BITS,38CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);3940/* Set FH wait threshold to maximum (HW error during stress W/A) */41iwl_set_bit(trans, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL);4243/*44* Enable HAP INTA (interrupt from management bus) to45* wake device's PCI Express link L1a -> L0s46*/47iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,48CSR_HW_IF_CONFIG_REG_HAP_WAKE);4950iwl_pcie_apm_config(trans);5152ret = iwl_finish_nic_init(trans);53if (ret)54return ret;5556set_bit(STATUS_DEVICE_ENABLED, &trans->status);5758return 0;59}6061static void iwl_pcie_gen2_apm_stop(struct iwl_trans *trans, bool op_mode_leave)62{63IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n");6465if (op_mode_leave) {66if (!test_bit(STATUS_DEVICE_ENABLED, &trans->status))67iwl_pcie_gen2_apm_init(trans);6869/* inform ME that we are leaving */70iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,71CSR_RESET_LINK_PWR_MGMT_DISABLED);72iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,73CSR_HW_IF_CONFIG_REG_WAKE_ME |74CSR_HW_IF_CONFIG_REG_WAKE_ME_PCIE_OWNER_EN);75mdelay(1);76iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,77CSR_RESET_LINK_PWR_MGMT_DISABLED);78mdelay(5);79}8081clear_bit(STATUS_DEVICE_ENABLED, &trans->status);8283/* Stop device's DMA activity */84iwl_pcie_apm_stop_master(trans);8586iwl_trans_pcie_sw_reset(trans, false);8788/*89* Clear "initialization complete" bit to move adapter from90* D0A* (powered-up Active) --> D0U* (Uninitialized) state.91*/92if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)93iwl_clear_bit(trans, CSR_GP_CNTRL,94CSR_GP_CNTRL_REG_FLAG_MAC_INIT);95else96iwl_clear_bit(trans, CSR_GP_CNTRL,97CSR_GP_CNTRL_REG_FLAG_INIT_DONE);98}99100void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)101{102struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);103int ret;104105trans_pcie->fw_reset_state = FW_RESET_REQUESTED;106107if (trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210)108iwl_write_umac_prph(trans, UREG_NIC_SET_NMI_DRIVER,109UREG_NIC_SET_NMI_DRIVER_RESET_HANDSHAKE);110else if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210)111iwl_write_umac_prph(trans, UREG_DOORBELL_TO_ISR6,112UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE);113else114iwl_write32(trans, CSR_DOORBELL_VECTOR,115UREG_DOORBELL_TO_ISR6_RESET_HANDSHAKE);116117/* wait 200ms */118ret = wait_event_timeout(trans_pcie->fw_reset_waitq,119trans_pcie->fw_reset_state != FW_RESET_REQUESTED,120FW_RESET_TIMEOUT);121if (!ret || trans_pcie->fw_reset_state == FW_RESET_ERROR) {122bool reset_done;123u32 inta_hw;124125if (trans_pcie->msix_enabled) {126inta_hw = iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD);127reset_done =128inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE;129} else {130inta_hw = iwl_read32(trans, CSR_INT);131reset_done = inta_hw & CSR_INT_BIT_RESET_DONE;132}133134IWL_ERR(trans,135"timeout waiting for FW reset ACK (inta_hw=0x%x, reset_done %d)\n",136inta_hw, reset_done);137138if (!reset_done) {139struct iwl_fw_error_dump_mode mode = {140.type = IWL_ERR_TYPE_RESET_HS_TIMEOUT,141.context = IWL_ERR_CONTEXT_FROM_OPMODE,142};143iwl_op_mode_nic_error(trans->op_mode,144IWL_ERR_TYPE_RESET_HS_TIMEOUT);145iwl_op_mode_dump_error(trans->op_mode, &mode);146}147}148149trans_pcie->fw_reset_state = FW_RESET_IDLE;150}151152static void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)153{154struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);155156lockdep_assert_held(&trans_pcie->mutex);157158if (trans_pcie->is_down)159return;160161if (trans->state >= IWL_TRANS_FW_STARTED &&162trans->conf.fw_reset_handshake) {163/*164* Reset handshake can dump firmware on timeout, but that165* should assume that the firmware is already dead.166*/167trans->state = IWL_TRANS_NO_FW;168iwl_trans_pcie_fw_reset_handshake(trans);169}170171trans_pcie->is_down = true;172173/* tell the device to stop sending interrupts */174iwl_disable_interrupts(trans);175176/* device going down, Stop using ICT table */177iwl_pcie_disable_ict(trans);178179/*180* If a HW restart happens during firmware loading,181* then the firmware loading might call this function182* and later it might be called again due to the183* restart. So don't process again if the device is184* already dead.185*/186if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {187IWL_DEBUG_INFO(trans,188"DEVICE_ENABLED bit was set and is now cleared\n");189iwl_pcie_synchronize_irqs(trans);190iwl_pcie_rx_napi_sync(trans);191iwl_txq_gen2_tx_free(trans);192iwl_pcie_rx_stop(trans);193}194195iwl_pcie_ctxt_info_free_paging(trans);196if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)197iwl_pcie_ctxt_info_v2_free(trans, false);198else199iwl_pcie_ctxt_info_free(trans);200201/* Stop the device, and put it in low power state */202iwl_pcie_gen2_apm_stop(trans, false);203204/* re-take ownership to prevent other users from stealing the device */205iwl_trans_pcie_sw_reset(trans, true);206207/*208* Upon stop, the IVAR table gets erased, so msi-x won't209* work. This causes a bug in RF-KILL flows, since the interrupt210* that enables radio won't fire on the correct irq, and the211* driver won't be able to handle the interrupt.212* Configure the IVAR table again after reset.213*/214iwl_pcie_conf_msix_hw(trans_pcie);215216/*217* Upon stop, the APM issues an interrupt if HW RF kill is set.218* This is a bug in certain verions of the hardware.219* Certain devices also keep sending HW RF kill interrupt all220* the time, unless the interrupt is ACKed even if the interrupt221* should be masked. Re-ACK all the interrupts here.222*/223iwl_disable_interrupts(trans);224225/* clear all status bits */226clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);227clear_bit(STATUS_INT_ENABLED, &trans->status);228clear_bit(STATUS_TPOWER_PMI, &trans->status);229230/*231* Even if we stop the HW, we still want the RF kill232* interrupt233*/234iwl_enable_rfkill_int(trans);235}236237void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)238{239struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);240bool was_in_rfkill;241242iwl_op_mode_time_point(trans->op_mode,243IWL_FW_INI_TIME_POINT_HOST_DEVICE_DISABLE,244NULL);245246mutex_lock(&trans_pcie->mutex);247trans_pcie->opmode_down = true;248was_in_rfkill = test_bit(STATUS_RFKILL_OPMODE, &trans->status);249_iwl_trans_pcie_gen2_stop_device(trans);250iwl_trans_pcie_handle_stop_rfkill(trans, was_in_rfkill);251mutex_unlock(&trans_pcie->mutex);252}253254static int iwl_pcie_gen2_nic_init(struct iwl_trans *trans)255{256struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);257int queue_size = max_t(u32, IWL_CMD_QUEUE_SIZE,258trans->mac_cfg->base->min_txq_size);259int ret;260261/* TODO: most of the logic can be removed in A0 - but not in Z0 */262spin_lock_bh(&trans_pcie->irq_lock);263ret = iwl_pcie_gen2_apm_init(trans);264spin_unlock_bh(&trans_pcie->irq_lock);265if (ret)266return ret;267268iwl_op_mode_nic_config(trans->op_mode);269270/* Allocate the RX queue, or reset if it is already allocated */271if (iwl_pcie_gen2_rx_init(trans))272return -ENOMEM;273274/* Allocate or reset and init all Tx and Command queues */275if (iwl_txq_gen2_init(trans, trans->conf.cmd_queue, queue_size))276return -ENOMEM;277278/* enable shadow regs in HW */279iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL, 0x800FFFFF);280IWL_DEBUG_INFO(trans, "Enabling shadow registers in device\n");281282return 0;283}284285static void iwl_pcie_get_rf_name(struct iwl_trans *trans)286{287struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);288char *buf = trans_pcie->rf_name;289size_t buflen = sizeof(trans_pcie->rf_name);290size_t pos;291u32 version;292293if (buf[0])294return;295296switch (CSR_HW_RFID_TYPE(trans->info.hw_rf_id)) {297case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF):298pos = scnprintf(buf, buflen, "JF");299break;300case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_GF):301pos = scnprintf(buf, buflen, "GF");302break;303case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_GF4):304pos = scnprintf(buf, buflen, "GF4");305break;306case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HR):307pos = scnprintf(buf, buflen, "HR");308break;309case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HR1):310pos = scnprintf(buf, buflen, "HR1");311break;312case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HRCDB):313pos = scnprintf(buf, buflen, "HRCDB");314break;315case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_FM):316pos = scnprintf(buf, buflen, "FM");317break;318case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_WP):319if (SILICON_Z_STEP ==320CSR_HW_RFID_STEP(trans->info.hw_rf_id))321pos = scnprintf(buf, buflen, "WHTC");322else323pos = scnprintf(buf, buflen, "WH");324break;325default:326return;327}328329switch (CSR_HW_RFID_TYPE(trans->info.hw_rf_id)) {330case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HR):331case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HR1):332case CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_HRCDB):333version = iwl_read_prph(trans, CNVI_MBOX_C);334switch (version) {335case 0x20000:336pos += scnprintf(buf + pos, buflen - pos, " B3");337break;338case 0x120000:339pos += scnprintf(buf + pos, buflen - pos, " B5");340break;341default:342pos += scnprintf(buf + pos, buflen - pos,343" (0x%x)", version);344break;345}346break;347default:348break;349}350351pos += scnprintf(buf + pos, buflen - pos, ", rfid=0x%x",352trans->info.hw_rf_id);353354IWL_INFO(trans, "Detected RF %s\n", buf);355356/*357* also add a \n for debugfs - need to do it after printing358* since our IWL_INFO machinery wants to see a static \n at359* the end of the string360*/361pos += scnprintf(buf + pos, buflen - pos, "\n");362}363364void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans)365{366struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);367368iwl_pcie_reset_ict(trans);369370/* make sure all queue are not stopped/used */371memset(trans_pcie->txqs.queue_stopped, 0,372sizeof(trans_pcie->txqs.queue_stopped));373memset(trans_pcie->txqs.queue_used, 0,374sizeof(trans_pcie->txqs.queue_used));375376/* now that we got alive we can free the fw image & the context info.377* paging memory cannot be freed included since FW will still use it378*/379if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)380iwl_pcie_ctxt_info_v2_free(trans, true);381else382iwl_pcie_ctxt_info_free(trans);383384/*385* Re-enable all the interrupts, including the RF-Kill one, now that386* the firmware is alive.387*/388iwl_enable_interrupts(trans);389mutex_lock(&trans_pcie->mutex);390iwl_pcie_check_hw_rf_kill(trans);391392iwl_pcie_get_rf_name(trans);393mutex_unlock(&trans_pcie->mutex);394395if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)396trans->step_urm = !!(iwl_read_umac_prph(trans,397CNVI_PMU_STEP_FLOW) &398CNVI_PMU_STEP_FLOW_FORCE_URM);399}400401static bool iwl_pcie_set_ltr(struct iwl_trans *trans)402{403u32 ltr_val = CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ |404u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC,405CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE) |406u32_encode_bits(250,407CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL) |408CSR_LTR_LONG_VAL_AD_SNOOP_REQ |409u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC,410CSR_LTR_LONG_VAL_AD_SNOOP_SCALE) |411u32_encode_bits(250, CSR_LTR_LONG_VAL_AD_SNOOP_VAL);412413/*414* To workaround hardware latency issues during the boot process,415* initialize the LTR to ~250 usec (see ltr_val above).416* The firmware initializes this again later (to a smaller value).417*/418if ((trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210 ||419trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_22000) &&420!trans->mac_cfg->integrated) {421iwl_write32(trans, CSR_LTR_LONG_VAL_AD, ltr_val);422return true;423}424425if (trans->mac_cfg->integrated &&426trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_22000) {427iwl_write_prph(trans, HPM_MAC_LTR_CSR, HPM_MAC_LRT_ENABLE_ALL);428iwl_write_prph(trans, HPM_UMAC_LTR, ltr_val);429return true;430}431432if (trans->mac_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {433/* First clear the interrupt, just in case */434iwl_write32(trans, CSR_MSIX_HW_INT_CAUSES_AD,435MSIX_HW_INT_CAUSES_REG_IML);436/* In this case, unfortunately the same ROM bug exists in the437* device (not setting LTR correctly), but we don't have control438* over the settings from the host due to some hardware security439* features. The only workaround we've been able to come up with440* so far is to try to keep the CPU and device busy by polling441* it and the IML (image loader) completed interrupt.442*/443return false;444}445446/* nothing needs to be done on other devices */447return true;448}449450static void iwl_pcie_spin_for_iml(struct iwl_trans *trans)451{452/* in practice, this seems to complete in around 20-30ms at most, wait 100 */453#define IML_WAIT_TIMEOUT (HZ / 10)454struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);455unsigned long end_time = jiffies + IML_WAIT_TIMEOUT;456u32 value, loops = 0;457bool irq = false;458459if (WARN_ON(!trans_pcie->iml))460return;461462value = iwl_read32(trans, CSR_LTR_LAST_MSG);463IWL_DEBUG_INFO(trans, "Polling for IML load - CSR_LTR_LAST_MSG=0x%x\n",464value);465466while (time_before(jiffies, end_time)) {467if (iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD) &468MSIX_HW_INT_CAUSES_REG_IML) {469irq = true;470break;471}472/* Keep the CPU and device busy. */473value = iwl_read32(trans, CSR_LTR_LAST_MSG);474loops++;475}476477IWL_DEBUG_INFO(trans,478"Polled for IML load: irq=%d, loops=%d, CSR_LTR_LAST_MSG=0x%x\n",479irq, loops, value);480481/* We don't fail here even if we timed out - maybe we get lucky and the482* interrupt comes in later (and we get alive from firmware) and then483* we're all happy - but if not we'll fail on alive timeout or get some484* other error out.485*/486}487488int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,489const struct iwl_fw *fw,490const struct fw_img *img,491bool run_in_rfkill)492{493struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);494bool hw_rfkill, keep_ram_busy;495bool top_reset_done = false;496int ret;497498mutex_lock(&trans_pcie->mutex);499again:500/* This may fail if AMT took ownership of the device */501if (iwl_pcie_prepare_card_hw(trans)) {502IWL_WARN(trans, "Exit HW not ready\n");503ret = -EIO;504goto out;505}506507iwl_enable_rfkill_int(trans);508509iwl_write32(trans, CSR_INT, 0xFFFFFFFF);510511/*512* We enabled the RF-Kill interrupt and the handler may very513* well be running. Disable the interrupts to make sure no other514* interrupt can be fired.515*/516iwl_disable_interrupts(trans);517518/* Make sure it finished running */519iwl_pcie_synchronize_irqs(trans);520521/* If platform's RF_KILL switch is NOT set to KILL */522hw_rfkill = iwl_pcie_check_hw_rf_kill(trans);523if (hw_rfkill && !run_in_rfkill) {524ret = -ERFKILL;525goto out;526}527528/* Someone called stop_device, don't try to start_fw */529if (trans_pcie->is_down) {530IWL_WARN(trans,531"Can't start_fw since the HW hasn't been started\n");532ret = -EIO;533goto out;534}535536/* make sure rfkill handshake bits are cleared */537iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);538iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,539CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);540541/* clear (again), then enable host interrupts */542iwl_write32(trans, CSR_INT, 0xFFFFFFFF);543544ret = iwl_pcie_gen2_nic_init(trans);545if (ret) {546IWL_ERR(trans, "Unable to init nic\n");547goto out;548}549550if (WARN_ON(trans->do_top_reset &&551trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_SC)) {552ret = -EINVAL;553goto out;554}555556/* we need to wait later - set state */557if (trans->do_top_reset)558trans_pcie->fw_reset_state = FW_RESET_TOP_REQUESTED;559560if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {561if (!top_reset_done) {562ret = iwl_pcie_ctxt_info_v2_alloc(trans, fw, img);563if (ret)564goto out;565}566567iwl_pcie_ctxt_info_v2_kick(trans);568} else {569ret = iwl_pcie_ctxt_info_init(trans, img);570if (ret)571goto out;572}573574keep_ram_busy = !iwl_pcie_set_ltr(trans);575576if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {577IWL_DEBUG_POWER(trans, "function scratch register value is 0x%08x\n",578iwl_read32(trans, CSR_FUNC_SCRATCH));579iwl_write32(trans, CSR_FUNC_SCRATCH, CSR_FUNC_SCRATCH_INIT_VALUE);580iwl_set_bit(trans, CSR_GP_CNTRL,581CSR_GP_CNTRL_REG_FLAG_ROM_START);582} else if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {583iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1);584} else {585iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1);586}587588if (keep_ram_busy)589iwl_pcie_spin_for_iml(trans);590591if (trans->do_top_reset) {592trans->do_top_reset = 0;593594#define FW_TOP_RESET_TIMEOUT (HZ / 4)595ret = wait_event_timeout(trans_pcie->fw_reset_waitq,596trans_pcie->fw_reset_state != FW_RESET_TOP_REQUESTED,597FW_TOP_RESET_TIMEOUT);598599if (trans_pcie->fw_reset_state != FW_RESET_OK) {600if (trans_pcie->fw_reset_state != FW_RESET_TOP_REQUESTED)601IWL_ERR(trans,602"TOP reset interrupted by error (state %d)!\n",603trans_pcie->fw_reset_state);604else605IWL_ERR(trans, "TOP reset timed out!\n");606iwl_op_mode_nic_error(trans->op_mode,607IWL_ERR_TYPE_TOP_RESET_FAILED);608iwl_trans_schedule_reset(trans,609IWL_ERR_TYPE_TOP_RESET_FAILED);610ret = -EIO;611goto out;612}613614msleep(10);615IWL_INFO(trans, "TOP reset successful, reinit now\n");616/* now load the firmware again properly */617ret = _iwl_trans_pcie_start_hw(trans);618if (ret) {619IWL_ERR(trans, "failed to start HW after TOP reset\n");620goto out;621}622trans_pcie->prph_scratch->ctrl_cfg.control.control_flags &=623~cpu_to_le32(IWL_PRPH_SCRATCH_TOP_RESET);624top_reset_done = true;625goto again;626}627628/* re-check RF-Kill state since we may have missed the interrupt */629hw_rfkill = iwl_pcie_check_hw_rf_kill(trans);630if (hw_rfkill && !run_in_rfkill)631ret = -ERFKILL;632633out:634mutex_unlock(&trans_pcie->mutex);635return ret;636}637638void iwl_trans_pcie_gen2_op_mode_leave(struct iwl_trans *trans)639{640struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);641642mutex_lock(&trans_pcie->mutex);643644/* disable interrupts - don't enable HW RF kill interrupt */645iwl_disable_interrupts(trans);646647iwl_pcie_gen2_apm_stop(trans, true);648649iwl_disable_interrupts(trans);650651iwl_pcie_disable_ict(trans);652653mutex_unlock(&trans_pcie->mutex);654655iwl_pcie_synchronize_irqs(trans);656}657658659