drivers/nvme/host/apple.c

Source file repositories/reference/linux-study-clean/drivers/nvme/host/apple.c

File Facts

System
Linux kernel
Corpus path
drivers/nvme/host/apple.c
Extension
.c
Size
46090 bytes
Lines
1725
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct blk_mq_ops apple_nvme_mq_admin_ops = {
	.queue_rq = apple_nvme_queue_rq,
	.complete = apple_nvme_complete_rq,
	.init_hctx = apple_nvme_init_hctx,
	.init_request = apple_nvme_init_request,
	.timeout = apple_nvme_timeout,
};

static const struct blk_mq_ops apple_nvme_mq_ops = {
	.queue_rq = apple_nvme_queue_rq,
	.complete = apple_nvme_complete_rq,
	.init_hctx = apple_nvme_init_hctx,
	.init_request = apple_nvme_init_request,
	.timeout = apple_nvme_timeout,
	.poll = apple_nvme_poll,
};

static void apple_nvme_init_queue(struct apple_nvme_queue *q)
{
	unsigned int depth = apple_nvme_queue_depth(q);
	struct apple_nvme *anv = queue_to_apple_nvme(q);

	q->sq_tail = 0;
	q->cq_head = 0;
	q->cq_phase = 1;
	if (anv->hw->has_lsq_nvmmu)
		memset(q->tcbs, 0, anv->hw->max_queue_depth
			* sizeof(struct apple_nvmmu_tcb));
	memset(q->cqes, 0, depth * sizeof(struct nvme_completion));
	WRITE_ONCE(q->enabled, true);
	wmb(); /* ensure the first interrupt sees the initialization */
}

static void apple_nvme_reset_work(struct work_struct *work)
{
	unsigned int nr_io_queues = 1;
	int ret;
	u32 boot_status, aqa;
	struct apple_nvme *anv =
		container_of(work, struct apple_nvme, ctrl.reset_work);
	enum nvme_ctrl_state state = nvme_ctrl_state(&anv->ctrl);

	if (state != NVME_CTRL_RESETTING) {
		dev_warn(anv->dev, "ctrl state %d is not RESETTING\n", state);
		ret = -ENODEV;
		goto out;
	}

	/* there's unfortunately no known way to recover if RTKit crashed :( */
	if (apple_rtkit_is_crashed(anv->rtk)) {
		dev_err(anv->dev,
			"RTKit has crashed without any way to recover.");
		ret = -EIO;
		goto out;
	}

	/* RTKit must be shut down cleanly for the (soft)-reset to work */
	if (apple_rtkit_is_running(anv->rtk)) {
		/* reset the controller if it is enabled */
		if (anv->ctrl.ctrl_config & NVME_CC_ENABLE)
			apple_nvme_disable(anv, false);
		dev_dbg(anv->dev, "Trying to shut down RTKit before reset.");
		ret = apple_rtkit_shutdown(anv->rtk);
		if (ret)
			goto out;

		writel(0, anv->mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL);
	}

	/*
	 * Only do the soft-reset if the CPU is not running, which means either we
	 * or the previous stage shut it down cleanly.
	 */
	if (!(readl(anv->mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL) &
		APPLE_ANS_COPROC_CPU_CONTROL_RUN)) {

		ret = reset_control_assert(anv->reset);
		if (ret)
			goto out;

		ret = apple_rtkit_reinit(anv->rtk);
		if (ret)
			goto out;

		ret = reset_control_deassert(anv->reset);
		if (ret)
			goto out;

		writel(APPLE_ANS_COPROC_CPU_CONTROL_RUN,
		       anv->mmio_coproc + APPLE_ANS_COPROC_CPU_CONTROL);

Annotation

Implementation Notes