drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
Extension
.c
Size
12263 bytes
Lines
441
Domain
Driver Families
Bucket
drivers/gpu
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

switch (adev->asic_type) {
		case CHIP_VEGA20:
			/* D161 and D163 are the VG20 server SKUs */
			if (atom_ctx && (strnstr(atom_ctx->vbios_pn, "D161",
						 sizeof(atom_ctx->vbios_pn)) ||
					 strnstr(atom_ctx->vbios_pn, "D163",
						 sizeof(atom_ctx->vbios_pn)))) {
				if (fru_addr)
					*fru_addr = FRU_EEPROM_MADDR_6;
				return true;
			} else {
				return false;
			}
		case CHIP_ARCTURUS:
		default:
			return false;
		}
	case IP_VERSION(11, 0, 7):
		if (atom_ctx && strnstr(atom_ctx->vbios_pn, "D603",
					sizeof(atom_ctx->vbios_pn))) {
			if (strnstr(atom_ctx->vbios_pn, "D603GLXE",
				    sizeof(atom_ctx->vbios_pn))) {
				return false;
			}

			if (fru_addr)
				*fru_addr = FRU_EEPROM_MADDR_6;
			return true;

		} else {
			return false;
		}
	case IP_VERSION(13, 0, 2):
		/* All Aldebaran SKUs have an FRU */
		if (atom_ctx && !strnstr(atom_ctx->vbios_pn, "D673",
					 sizeof(atom_ctx->vbios_pn)))
			if (fru_addr)
				*fru_addr = FRU_EEPROM_MADDR_6;
		return true;
	case IP_VERSION(13, 0, 6):
	case IP_VERSION(13, 0, 14):
			if (fru_addr)
				*fru_addr = FRU_EEPROM_MADDR_8;
			return true;
	case IP_VERSION(13, 0, 12):
	case IP_VERSION(15, 0, 8):
			if (fru_addr)
				*fru_addr = FRU_EEPROM_MADDR_INV;
			return true;
	default:
		return false;
	}
}

/*
 * IPMI FRU Product Info Area fields are TLV: one type/length byte
 * (low 6 bits = data length) followed by that many data bytes. These
 * helpers walk the cursor and copy a single field while bounding all
 * accesses to the actual buffer length read from the EEPROM.
 */
#define FRU_FIELD_LEN(p, a)	((p)[a] & 0x3F)

/* Advance cursor past the current TLV. Returns false if no more data. */
static bool fru_pia_advance(u32 *addr, const unsigned char *pia, int len)
{
	if (*addr >= (u32)len)
		return false;
	*addr += 1 + FRU_FIELD_LEN(pia, *addr);
	return true;
}

/*
 * Copy the current TLV's data into dst (NUL-terminated). Returns false if
 * the TLV header or data would read past the end of pia.
 */
static bool fru_pia_copy_field(char *dst, size_t dst_size,
			       const unsigned char *pia, u32 addr, int len)
{
	size_t fl;

	if (addr + 1 >= (u32)len)
		return false;

	fl = min3((size_t)FRU_FIELD_LEN(pia, addr),
			  dst_size - 1,
			  (size_t)(len - addr - 1));
	memcpy(dst, pia + addr + 1, fl);
	dst[fl] = '\0';
	return true;
}

Annotation

Implementation Notes