drivers/net/ethernet/fungible/funcore/fun_dev.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/fungible/funcore/fun_dev.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/fungible/funcore/fun_dev.c
Extension
.c
Size
21052 bytes
Lines
834
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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 fun_cmd_ctx {
	fun_admin_callback_t cb;  /* callback to invoke on completion */
	void *cb_data;            /* user data provided to callback */
	int cpu;                  /* CPU where the cmd's tag was allocated */
};

/* Context for synchronous admin commands. */
struct fun_sync_cmd_ctx {
	struct completion compl;
	u8 *rsp_buf;              /* caller provided response buffer */
	unsigned int rsp_len;     /* response buffer size */
	u8 rsp_status;            /* command response status */
};

/* Wait for the CSTS.RDY bit to match @enabled. */
static int fun_wait_ready(struct fun_dev *fdev, bool enabled)
{
	unsigned int cap_to = NVME_CAP_TIMEOUT(fdev->cap_reg);
	u32 bit = enabled ? NVME_CSTS_RDY : 0;
	unsigned long deadline;

	deadline = ((cap_to + 1) * HZ / 2) + jiffies; /* CAP.TO is in 500ms */

	for (;;) {
		u32 csts = readl(fdev->bar + NVME_REG_CSTS);

		if (csts == ~0) {
			dev_err(fdev->dev, "CSTS register read %#x\n", csts);
			return -EIO;
		}

		if ((csts & NVME_CSTS_RDY) == bit)
			return 0;

		if (time_is_before_jiffies(deadline))
			break;

		msleep(100);
	}

	dev_err(fdev->dev,
		"Timed out waiting for device to indicate RDY %u; aborting %s\n",
		enabled, enabled ? "initialization" : "reset");
	return -ETIMEDOUT;
}

/* Check CSTS and return an error if it is unreadable or has unexpected
 * RDY value.
 */
static int fun_check_csts_rdy(struct fun_dev *fdev, unsigned int expected_rdy)
{
	u32 csts = readl(fdev->bar + NVME_REG_CSTS);
	u32 actual_rdy = csts & NVME_CSTS_RDY;

	if (csts == ~0) {
		dev_err(fdev->dev, "CSTS register read %#x\n", csts);
		return -EIO;
	}
	if (actual_rdy != expected_rdy) {
		dev_err(fdev->dev, "Unexpected CSTS RDY %u\n", actual_rdy);
		return -EINVAL;
	}
	return 0;
}

/* Check that CSTS RDY has the expected value. Then write a new value to the CC
 * register and wait for CSTS RDY to match the new CC ENABLE state.
 */
static int fun_update_cc_enable(struct fun_dev *fdev, unsigned int initial_rdy)
{
	int rc = fun_check_csts_rdy(fdev, initial_rdy);

	if (rc)
		return rc;
	writel(fdev->cc_reg, fdev->bar + NVME_REG_CC);
	return fun_wait_ready(fdev, !!(fdev->cc_reg & NVME_CC_ENABLE));
}

static int fun_disable_ctrl(struct fun_dev *fdev)
{
	fdev->cc_reg &= ~(NVME_CC_SHN_MASK | NVME_CC_ENABLE);
	return fun_update_cc_enable(fdev, 1);
}

static int fun_enable_ctrl(struct fun_dev *fdev, u32 admin_cqesz_log2,
			   u32 admin_sqesz_log2)
{
	fdev->cc_reg = (admin_cqesz_log2 << NVME_CC_IOCQES_SHIFT) |
		       (admin_sqesz_log2 << NVME_CC_IOSQES_SHIFT) |
		       ((PAGE_SHIFT - 12) << NVME_CC_MPS_SHIFT) |

Annotation

Implementation Notes