drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c
Extension
.c
Size
26659 bytes
Lines
820
Domain
Driver Families
Bucket
drivers/net
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

if (token->seq_id == seq_id) {
			WRITE_ONCE(token->state, state);
			rcu_read_unlock();
			return;
		}
	}
	rcu_read_unlock();
	netdev_err(bp->dev, "Invalid hwrm seq id %d\n", seq_id);
}

static void hwrm_req_dbg(struct bnxt *bp, struct input *req)
{
	u32 ring = le16_to_cpu(req->cmpl_ring);
	u32 type = le16_to_cpu(req->req_type);
	u32 tgt = le16_to_cpu(req->target_id);
	u32 seq = le16_to_cpu(req->seq_id);
	char opt[32] = "\n";

	if (unlikely(ring != (u16)BNXT_HWRM_NO_CMPL_RING))
		snprintf(opt, 16, " ring %d\n", ring);

	if (unlikely(tgt != BNXT_HWRM_TARGET))
		snprintf(opt + strlen(opt) - 1, 16, " tgt 0x%x\n", tgt);

	netdev_dbg(bp->dev, "sent hwrm req_type 0x%x seq id 0x%x%s",
		   type, seq, opt);
}

#define hwrm_err(bp, ctx, fmt, ...)				       \
	do {							       \
		if ((ctx)->flags & BNXT_HWRM_CTX_SILENT)	       \
			netdev_dbg((bp)->dev, fmt, __VA_ARGS__);       \
		else						       \
			netdev_err((bp)->dev, fmt, __VA_ARGS__);       \
	} while (0)

static bool hwrm_wait_must_abort(struct bnxt *bp, u32 req_type, u32 *fw_status)
{
	if (req_type == HWRM_VER_GET)
		return false;

	if (!bp->fw_health || !bp->fw_health->status_reliable)
		return false;

	*fw_status = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
	return *fw_status && !BNXT_FW_IS_HEALTHY(*fw_status);
}

static int __hwrm_send(struct bnxt *bp, struct bnxt_hwrm_ctx *ctx)
{
	u32 doorbell_offset = BNXT_GRCPF_REG_CHIMP_COMM_TRIGGER;
	enum bnxt_hwrm_chnl dst = BNXT_HWRM_CHNL_CHIMP;
	u32 bar_offset = BNXT_GRCPF_REG_CHIMP_COMM;
	struct bnxt_hwrm_wait_token *token = NULL;
	struct hwrm_short_input short_input = {0};
	u16 max_req_len = BNXT_HWRM_MAX_REQ_LEN;
	unsigned int i, timeout, tmo_count;
	u32 *data = (u32 *)ctx->req;
	u32 msg_len = ctx->req_len;
	u32 req_type, sts;
	int rc = -EBUSY;
	u16 len = 0;
	u8 *valid;

	if (ctx->flags & BNXT_HWRM_INTERNAL_RESP_DIRTY)
		memset(ctx->resp, 0, PAGE_SIZE);

	req_type = le16_to_cpu(ctx->req->req_type);
	if (BNXT_NO_FW_ACCESS(bp) &&
	    (req_type != HWRM_FUNC_RESET && req_type != HWRM_VER_GET)) {
		netdev_dbg(bp->dev, "hwrm req_type 0x%x skipped, FW channel down\n",
			   req_type);
		goto exit;
	}

	if (msg_len > BNXT_HWRM_MAX_REQ_LEN &&
	    msg_len > bp->hwrm_max_ext_req_len) {
		netdev_warn(bp->dev, "oversized hwrm request, req_type 0x%x",
			    req_type);
		rc = -E2BIG;
		goto exit;
	}

	if (bnxt_kong_hwrm_message(bp, ctx->req)) {
		dst = BNXT_HWRM_CHNL_KONG;
		bar_offset = BNXT_GRCPF_REG_KONG_COMM;
		doorbell_offset = BNXT_GRCPF_REG_KONG_COMM_TRIGGER;
		if (le16_to_cpu(ctx->req->cmpl_ring) != INVALID_HW_RING_ID) {
			netdev_err(bp->dev, "Ring completions not supported for KONG commands, req_type = %d\n",
				   req_type);

Annotation

Implementation Notes