drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/broadcom/bnge/bnge_hwrm.c
Extension
.c
Size
14564 bytes
Lines
549
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 (i < BNGE_HWRM_SHORT_TIMEOUT_COUNTER) {
				usleep_range(BNGE_HWRM_SHORT_MIN_TIMEOUT,
					     BNGE_HWRM_SHORT_MAX_TIMEOUT);
			} else {
				usleep_range(BNGE_HWRM_MIN_TIMEOUT,
					     BNGE_HWRM_MAX_TIMEOUT);
			}
		}

		if (READ_ONCE(token->state) != BNGE_HWRM_COMPLETE) {
			bnge_hwrm_err(bd, ctx, "No hwrm cmpl received: 0x%x\n",
				      req_type);
			goto exit;
		}
		len = le16_to_cpu(READ_ONCE(ctx->resp->resp_len));
		valid = ((u8 *)ctx->resp) + len - 1;
	} else {
		__le16 seen_out_of_seq = ctx->req->seq_id; /* will never see */
		int j;

		/* Check if response len is updated */
		for (i = 0; i < tmo_count; i++) {
			if (token &&
			    READ_ONCE(token->state) == BNGE_HWRM_DEFERRED) {
				bnge_hwrm_destroy_token(bd, token);
				token = NULL;
			}

			len = le16_to_cpu(READ_ONCE(ctx->resp->resp_len));
			if (len) {
				__le16 resp_seq = READ_ONCE(ctx->resp->seq_id);

				if (resp_seq == ctx->req->seq_id)
					break;
				if (resp_seq != seen_out_of_seq) {
					dev_warn(bd->dev, "Discarding out of seq response: 0x%x for msg {0x%x 0x%x}\n",
						 le16_to_cpu(resp_seq), req_type, le16_to_cpu(ctx->req->seq_id));
					seen_out_of_seq = resp_seq;
				}
			}

			/* on first few passes, just barely sleep */
			if (i < BNGE_HWRM_SHORT_TIMEOUT_COUNTER) {
				usleep_range(BNGE_HWRM_SHORT_MIN_TIMEOUT,
					     BNGE_HWRM_SHORT_MAX_TIMEOUT);
			} else {
				usleep_range(BNGE_HWRM_MIN_TIMEOUT,
					     BNGE_HWRM_MAX_TIMEOUT);
			}
		}

		if (i >= tmo_count) {
			bnge_hwrm_err(bd, ctx,
				      "Error (timeout: %u) msg {0x%x 0x%x} len:%d\n",
				      bnge_hwrm_timeout(i), req_type,
				      le16_to_cpu(ctx->req->seq_id), len);
			goto exit;
		}

		/* Last byte of resp contains valid bit */
		valid = ((u8 *)ctx->resp) + len - 1;
		for (j = 0; j < BNGE_HWRM_FIN_WAIT_USEC; ) {
			/* make sure we read from updated DMA memory */
			dma_rmb();
			if (*valid)
				break;
			if (j < 10) {
				udelay(1);
				j++;
			} else {
				usleep_range(20, 30);
				j += 20;
			}
		}

		if (j >= BNGE_HWRM_FIN_WAIT_USEC) {
			bnge_hwrm_err(bd, ctx, "Error (timeout: %u) msg {0x%x 0x%x} len:%d v:%d\n",
				      bnge_hwrm_timeout(i) + j, req_type,
				      le16_to_cpu(ctx->req->seq_id), len, *valid);
			goto exit;
		}
	}

	/* Zero valid bit for compatibility.  Valid bit in an older spec
	 * may become a new field in a newer spec.  We must make sure that
	 * a new field not implemented by old spec will read zero.
	 */
	*valid = 0;
	rc = le16_to_cpu(ctx->resp->error_code);
	if (rc == HWRM_ERR_CODE_BUSY && !(ctx->flags & BNGE_HWRM_CTX_SILENT))

Annotation

Implementation Notes