drivers/infiniband/hw/efa/efa_com.c

Source file repositories/reference/linux-study-clean/drivers/infiniband/hw/efa/efa_com.c

File Facts

System
Linux kernel
Corpus path
drivers/infiniband/hw/efa/efa_com.c
Extension
.c
Size
34962 bytes
Lines
1295
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

struct efa_comp_ctx {
	struct completion wait_event;
	struct efa_admin_acq_entry *user_cqe;
	u32 comp_size;
	enum efa_cmd_status status;
	u16 cmd_id;
	u8 cmd_opcode;
};

static const char *efa_com_cmd_str(u8 cmd)
{
#define EFA_CMD_STR_CASE(_cmd) case EFA_ADMIN_##_cmd: return #_cmd

	switch (cmd) {
	EFA_CMD_STR_CASE(CREATE_QP);
	EFA_CMD_STR_CASE(MODIFY_QP);
	EFA_CMD_STR_CASE(QUERY_QP);
	EFA_CMD_STR_CASE(DESTROY_QP);
	EFA_CMD_STR_CASE(CREATE_AH);
	EFA_CMD_STR_CASE(DESTROY_AH);
	EFA_CMD_STR_CASE(REG_MR);
	EFA_CMD_STR_CASE(DEREG_MR);
	EFA_CMD_STR_CASE(CREATE_CQ);
	EFA_CMD_STR_CASE(DESTROY_CQ);
	EFA_CMD_STR_CASE(GET_FEATURE);
	EFA_CMD_STR_CASE(SET_FEATURE);
	EFA_CMD_STR_CASE(GET_STATS);
	EFA_CMD_STR_CASE(ALLOC_PD);
	EFA_CMD_STR_CASE(DEALLOC_PD);
	EFA_CMD_STR_CASE(ALLOC_UAR);
	EFA_CMD_STR_CASE(DEALLOC_UAR);
	EFA_CMD_STR_CASE(CREATE_EQ);
	EFA_CMD_STR_CASE(DESTROY_EQ);
	default: return "unknown command opcode";
	}
#undef EFA_CMD_STR_CASE
}

void efa_com_set_dma_addr(dma_addr_t addr, u32 *addr_high, u32 *addr_low)
{
	*addr_low = lower_32_bits(addr);
	*addr_high = upper_32_bits(addr);
}

static u32 efa_com_reg_read32(struct efa_com_dev *edev, u16 offset)
{
	struct efa_com_mmio_read *mmio_read = &edev->mmio_read;
	struct efa_admin_mmio_req_read_less_resp *read_resp;
	unsigned long exp_time;
	u32 mmio_read_reg = 0;
	u32 err;

	read_resp = mmio_read->read_resp;

	spin_lock(&mmio_read->lock);
	mmio_read->seq_num++;

	/* trash DMA req_id to identify when hardware is done */
	read_resp->req_id = mmio_read->seq_num + 0x9aL;
	EFA_SET(&mmio_read_reg, EFA_REGS_MMIO_REG_READ_REG_OFF, offset);
	EFA_SET(&mmio_read_reg, EFA_REGS_MMIO_REG_READ_REQ_ID,
		mmio_read->seq_num);

	writel(mmio_read_reg, edev->reg_bar + EFA_REGS_MMIO_REG_READ_OFF);

	exp_time = jiffies + usecs_to_jiffies(mmio_read->mmio_read_timeout);
	do {
		if (READ_ONCE(read_resp->req_id) == mmio_read->seq_num)
			break;
		udelay(1);
	} while (time_is_after_jiffies(exp_time));

	if (read_resp->req_id != mmio_read->seq_num) {
		ibdev_err_ratelimited(
			edev->efa_dev,
			"Reading register timed out. expected: req id[%u] offset[%#x] actual: req id[%u] offset[%#x]\n",
			mmio_read->seq_num, offset, read_resp->req_id,
			read_resp->reg_off);
		err = EFA_MMIO_READ_INVALID;
		goto out;
	}

	if (read_resp->reg_off != offset) {
		ibdev_err_ratelimited(
			edev->efa_dev,
			"Reading register failed: wrong offset provided\n");
		err = EFA_MMIO_READ_INVALID;
		goto out;
	}

Annotation

Implementation Notes