drivers/net/ethernet/sfc/ef100_nic.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/sfc/ef100_nic.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sfc/ef100_nic.c
Extension
.c
Size
41428 bytes
Lines
1387
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

struct ef100_tlv_state {
	enum ef100_tlv_state_machine state;
	u64 value;
	u32 value_offset;
	u16 type;
	u8 len;
};

static int ef100_tlv_feed(struct ef100_tlv_state *state, u8 byte)
{
	switch (state->state) {
	case EF100_TLV_TYPE:
		state->type = byte & 0x7f;
		state->state = (byte & 0x80) ? EF100_TLV_TYPE_CONT
					     : EF100_TLV_LENGTH;
		/* Clear ready to read in a new entry */
		state->value = 0;
		state->value_offset = 0;
		return 0;
	case EF100_TLV_TYPE_CONT:
		state->type |= byte << 7;
		state->state = EF100_TLV_LENGTH;
		return 0;
	case EF100_TLV_LENGTH:
		state->len = byte;
		/* We only handle TLVs that fit in a u64 */
		if (state->len > sizeof(state->value))
			return -EOPNOTSUPP;
		/* len may be zero, implying a value of zero */
		state->state = state->len ? EF100_TLV_VALUE : EF100_TLV_TYPE;
		return 0;
	case EF100_TLV_VALUE:
		state->value |= ((u64)byte) << (state->value_offset * 8);
		state->value_offset++;
		if (state->value_offset >= state->len)
			state->state = EF100_TLV_TYPE;
		return 0;
	default: /* state machine error, can't happen */
		WARN_ON_ONCE(1);
		return -EIO;
	}
}

static int ef100_process_design_param(struct efx_nic *efx,
				      const struct ef100_tlv_state *reader)
{
	struct ef100_nic_data *nic_data = efx->nic_data;

	switch (reader->type) {
	case ESE_EF100_DP_GZ_PAD: /* padding, skip it */
		return 0;
	case ESE_EF100_DP_GZ_PARTIAL_TSTAMP_SUB_NANO_BITS:
		/* Driver doesn't support timestamping yet, so we don't care */
		return 0;
	case ESE_EF100_DP_GZ_EVQ_UNSOL_CREDIT_SEQ_BITS:
		/* Driver doesn't support unsolicited-event credits yet, so
		 * we don't care
		 */
		return 0;
	case ESE_EF100_DP_GZ_NMMU_GROUP_SIZE:
		/* Driver doesn't manage the NMMU (so we don't care) */
		return 0;
	case ESE_EF100_DP_GZ_RX_L4_CSUM_PROTOCOLS:
		/* Driver uses CHECKSUM_COMPLETE, so we don't care about
		 * protocol checksum validation
		 */
		return 0;
	case ESE_EF100_DP_GZ_TSO_MAX_HDR_LEN:
		nic_data->tso_max_hdr_len = min_t(u64, reader->value, 0xffff);
		return 0;
	case ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS:
		/* We always put HDR_NUM_SEGS=1 in our TSO descriptors */
		if (!reader->value) {
			pci_err(efx->pci_dev, "TSO_MAX_HDR_NUM_SEGS < 1\n");
			return -EOPNOTSUPP;
		}
		return 0;
	case ESE_EF100_DP_GZ_RXQ_SIZE_GRANULARITY:
	case ESE_EF100_DP_GZ_TXQ_SIZE_GRANULARITY:
		/* Our TXQ and RXQ sizes are always power-of-two and thus divisible by
		 * EFX_MIN_DMAQ_SIZE, so we just need to check that
		 * EFX_MIN_DMAQ_SIZE is divisible by GRANULARITY.
		 * This is very unlikely to fail.
		 */
		if (!reader->value || reader->value > EFX_MIN_DMAQ_SIZE ||
		    EFX_MIN_DMAQ_SIZE % (u32)reader->value) {
			pci_err(efx->pci_dev,
				"%s size granularity is %llu, can't guarantee safety\n",
				reader->type == ESE_EF100_DP_GZ_RXQ_SIZE_GRANULARITY ? "RXQ" : "TXQ",
				reader->value);

Annotation

Implementation Notes