drivers/acpi/nfit/intel.c

Source file repositories/reference/linux-study-clean/drivers/acpi/nfit/intel.c

File Facts

System
Linux kernel
Corpus path
drivers/acpi/nfit/intel.c
Extension
.c
Size
19906 bytes
Lines
735
Domain
Driver Families
Bucket
drivers/acpi
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

else if (info.capability & ND_INTEL_BUS_FWA_CAP_OSQUIESCE) {
			/*
			 * Skip hibernate cycle by default if platform
			 * indicates that it does not need devices to be
			 * quiesced.
			 */
			acpi_desc->fwa_cap = NVDIMM_FWA_CAP_LIVE;
		} else
			acpi_desc->fwa_cap = NVDIMM_FWA_CAP_NONE;
	}

	acpi_desc->fwa_state = state;

	return state;
}

static enum nvdimm_fwa_capability intel_bus_fwa_capability(
		struct nvdimm_bus_descriptor *nd_desc)
{
	struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);

	if (acpi_desc->fwa_cap > NVDIMM_FWA_CAP_INVALID)
		return acpi_desc->fwa_cap;

	if (intel_bus_fwa_state(nd_desc) > NVDIMM_FWA_INVALID)
		return acpi_desc->fwa_cap;

	return NVDIMM_FWA_CAP_INVALID;
}

static int intel_bus_fwa_activate(struct nvdimm_bus_descriptor *nd_desc)
{
	struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
	TRAILING_OVERLAP(struct nd_cmd_pkg, pkg, nd_payload,
		struct nd_intel_bus_fw_activate cmd;
	) nd_cmd;
	int rc;

	nd_cmd.pkg = (struct nd_cmd_pkg) {
		.nd_command = NVDIMM_BUS_INTEL_FW_ACTIVATE,
		.nd_family = NVDIMM_BUS_FAMILY_INTEL,
		.nd_size_in = sizeof(nd_cmd.cmd.iodev_state),
		.nd_size_out =
			sizeof(struct nd_intel_bus_fw_activate),
		.nd_fw_size =
			sizeof(struct nd_intel_bus_fw_activate),
	};
	nd_cmd.cmd = (struct nd_intel_bus_fw_activate) {
		/*
		 * Even though activate is run from a suspended context,
		 * for safety, still ask platform firmware to force
		 * quiesce devices by default. Let a module
		 * parameter override that policy.
		 */
		.iodev_state = acpi_desc->fwa_noidle
			? ND_INTEL_BUS_FWA_IODEV_OS_IDLE
			: ND_INTEL_BUS_FWA_IODEV_FORCE_IDLE,
	};
	switch (intel_bus_fwa_state(nd_desc)) {
	case NVDIMM_FWA_ARMED:
	case NVDIMM_FWA_ARM_OVERFLOW:
		break;
	default:
		return -ENXIO;
	}

	rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd),
			NULL);

	/*
	 * Whether the command succeeded, or failed, the agent checking
	 * for the result needs to query the DIMMs individually.
	 * Increment the activation count to invalidate all the DIMM
	 * states at once (it's otherwise not possible to take
	 * acpi_desc->init_mutex in this context)
	 */
	acpi_desc->fwa_state = NVDIMM_FWA_INVALID;
	acpi_desc->fwa_count++;

	dev_dbg(acpi_desc->dev, "result: %d\n", rc);

	return rc;
}

static const struct nvdimm_bus_fw_ops __intel_bus_fw_ops = {
	.activate_state = intel_bus_fwa_state,
	.capability = intel_bus_fwa_capability,
	.activate = intel_bus_fwa_activate,
};

Annotation

Implementation Notes