drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans-gen2.c
Extension
.c
Size
19549 bytes
Lines
673
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (trans_pcie->msix_enabled) {
			inta_hw = iwl_read32(trans, CSR_MSIX_HW_INT_CAUSES_AD);
			reset_done =
				inta_hw & MSIX_HW_INT_CAUSES_REG_RESET_DONE;
		} else {
			inta_hw = iwl_read32(trans, CSR_INT);
			reset_done = inta_hw & CSR_INT_BIT_RESET_DONE;
		}

		IWL_ERR(trans,
			"timeout waiting for FW reset ACK (inta_hw=0x%x, reset_done %d)\n",
			inta_hw, reset_done);

		if (!reset_done && dump_on_timeout) {
			struct iwl_fw_error_dump_mode mode = {
				.type = IWL_ERR_TYPE_RESET_HS_TIMEOUT,
				.context = IWL_ERR_CONTEXT_FROM_OPMODE,
			};
			iwl_op_mode_nic_error(trans->op_mode,
					      IWL_ERR_TYPE_RESET_HS_TIMEOUT);
			iwl_op_mode_dump_error(trans->op_mode, &mode);
		}
	}

	trans_pcie->fw_reset_state = FW_RESET_IDLE;
}

void iwl_trans_pcie_fw_reset_handshake(struct iwl_trans *trans)
{
	_iwl_trans_pcie_fw_reset_handshake(trans, false);
}

static void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
{
	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);

	lockdep_assert_held(&trans_pcie->mutex);

	if (trans_pcie->is_down)
		return;

	if (trans->state >= IWL_TRANS_FW_STARTED &&
	    trans->conf.fw_reset_handshake) {
		/*
		 * Reset handshake can dump firmware on timeout, but that
		 * should assume that the firmware is already dead.
		 */
		trans->state = IWL_TRANS_NO_FW;
		_iwl_trans_pcie_fw_reset_handshake(trans, true);
	}

	trans_pcie->is_down = true;

	/* tell the device to stop sending interrupts */
	iwl_disable_interrupts(trans);

	/* device going down, Stop using ICT table */
	iwl_pcie_disable_ict(trans);

	/*
	 * If a HW restart happens during firmware loading,
	 * then the firmware loading might call this function
	 * and later it might be called again due to the
	 * restart. So don't process again if the device is
	 * already dead.
	 */
	if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
		IWL_DEBUG_INFO(trans,
			       "DEVICE_ENABLED bit was set and is now cleared\n");
		iwl_pcie_synchronize_irqs(trans);
		iwl_pcie_rx_napi_sync(trans);
		iwl_txq_gen2_tx_free(trans);
		iwl_pcie_rx_stop(trans);
	}

	iwl_pcie_ctxt_info_free_paging(trans);
	if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
		iwl_pcie_ctxt_info_v2_free(trans, false);
	else
		iwl_pcie_ctxt_info_free(trans);

	/* Stop the device, and put it in low power state */
	iwl_pcie_gen2_apm_stop(trans, false);

	/* re-take ownership to prevent other users from stealing the device */
	iwl_trans_pcie_sw_reset(trans, true);

	/*
	 * Upon stop, the IVAR table gets erased, so msi-x won't
	 * work. This causes a bug in RF-KILL flows, since the interrupt

Annotation

Implementation Notes