drivers/infiniband/hw/erdma/erdma_cmdq.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/hw/erdma/erdma_cmdq.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/erdma/erdma_cmdq.c
Extension
.c
Size
11329 bytes
Lines
453
Domain
Driver Families
Bucket
drivers/infiniband
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

// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause

/* Authors: Cheng Xu <chengyou@linux.alibaba.com> */
/*          Kai Shen <kaishen@linux.alibaba.com> */
/* Copyright (c) 2020-2022, Alibaba Group. */

#include "erdma.h"

static void arm_cmdq_cq(struct erdma_cmdq *cmdq)
{
	struct erdma_dev *dev = container_of(cmdq, struct erdma_dev, cmdq);
	u64 db_data = FIELD_PREP(ERDMA_CQDB_CI_MASK, cmdq->cq.ci) |
		      FIELD_PREP(ERDMA_CQDB_ARM_MASK, 1) |
		      FIELD_PREP(ERDMA_CQDB_CMDSN_MASK, cmdq->cq.cmdsn) |
		      FIELD_PREP(ERDMA_CQDB_IDX_MASK, cmdq->cq.cmdsn);

	*cmdq->cq.dbrec = db_data;
	writeq(db_data, dev->func_bar + ERDMA_CMDQ_CQDB_REG);

	atomic64_inc(&cmdq->cq.armed_num);
}

static void kick_cmdq_db(struct erdma_cmdq *cmdq)
{
	struct erdma_dev *dev = container_of(cmdq, struct erdma_dev, cmdq);
	u64 db_data = FIELD_PREP(ERDMA_CMD_HDR_WQEBB_INDEX_MASK, cmdq->sq.pi);

	*cmdq->sq.dbrec = db_data;
	writeq(db_data, dev->func_bar + ERDMA_CMDQ_SQDB_REG);
}

static struct erdma_comp_wait *get_comp_wait(struct erdma_cmdq *cmdq)
{
	int comp_idx;

	spin_lock(&cmdq->lock);
	comp_idx = find_first_zero_bit(cmdq->comp_wait_bitmap,
				       cmdq->max_outstandings);
	if (comp_idx == cmdq->max_outstandings) {
		spin_unlock(&cmdq->lock);
		return ERR_PTR(-ENOMEM);
	}

	__set_bit(comp_idx, cmdq->comp_wait_bitmap);
	spin_unlock(&cmdq->lock);

	return &cmdq->wait_pool[comp_idx];
}

static void put_comp_wait(struct erdma_cmdq *cmdq,
			  struct erdma_comp_wait *comp_wait)
{
	int used;

	cmdq->wait_pool[comp_wait->ctx_id].cmd_status = ERDMA_CMD_STATUS_INIT;
	spin_lock(&cmdq->lock);
	used = __test_and_clear_bit(comp_wait->ctx_id, cmdq->comp_wait_bitmap);
	spin_unlock(&cmdq->lock);

	WARN_ON(!used);
}

static int erdma_cmdq_wait_res_init(struct erdma_dev *dev,
				    struct erdma_cmdq *cmdq)
{
	int i;

	cmdq->wait_pool =
		devm_kcalloc(&dev->pdev->dev, cmdq->max_outstandings,
			     sizeof(struct erdma_comp_wait), GFP_KERNEL);
	if (!cmdq->wait_pool)
		return -ENOMEM;

	spin_lock_init(&cmdq->lock);
	cmdq->comp_wait_bitmap = devm_bitmap_zalloc(
		&dev->pdev->dev, cmdq->max_outstandings, GFP_KERNEL);
	if (!cmdq->comp_wait_bitmap)
		return -ENOMEM;

	for (i = 0; i < cmdq->max_outstandings; i++) {
		init_completion(&cmdq->wait_pool[i].wait_event);
		cmdq->wait_pool[i].ctx_id = i;
	}

	return 0;
}

static int erdma_cmdq_sq_init(struct erdma_dev *dev)
{
	struct erdma_cmdq *cmdq = &dev->cmdq;

Annotation

Implementation Notes