drivers/net/ethernet/sfc/efx_reflash.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sfc/efx_reflash.c
Extension
.c
Size
16072 bytes
Lines
523
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 (offset >= next_update) {
			devlink_flash_update_status_notify(devlink, "Erasing",
							   NULL, offset,
							   partition_size);
			next_update += partition_size / EFX_DEVLINK_STATUS_UPDATE_COUNT;
		}

		chunk = min_t(size_t, partition_size - offset, chunk);
		rc = efx_mcdi_nvram_erase(efx, type, offset, chunk);
		if (rc) {
			NL_SET_ERR_MSG_FMT_MOD(extack,
					       "Erase failed for NVRAM partition %#x at %#zx-%#zx",
					       type, offset, offset + chunk - 1);
			return rc;
		}
	}

	devlink_flash_update_status_notify(devlink, "Erasing", NULL,
					   partition_size, partition_size);

	return 0;
}

static int efx_reflash_write_partition(struct efx_nic *efx,
				       struct netlink_ext_ack *extack,
				       struct devlink *devlink, u32 type,
				       const u8 *data, size_t data_size,
				       size_t align)
{
	size_t write_max, chunk, offset, next_update;
	int rc;

	if (align == 0)
		return -EINVAL;

	/* Write the NVRAM partition in chunks that are the largest multiple
	 * of the partition's required write alignment that will fit into the
	 * MCDI NVRAM_WRITE RPC payload.
	 */
	if (efx->type->mcdi_max_ver < 2)
		write_max = MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_LEN *
			    MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MAXNUM;
	else
		write_max = MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_LEN *
			    MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MAXNUM_MCDI2;
	chunk = rounddown(write_max, align);

	for (offset = 0, next_update = 0; offset + chunk <= data_size; offset += chunk) {
		if (offset >= next_update) {
			devlink_flash_update_status_notify(devlink, "Writing",
							   NULL, offset,
							   data_size);
			next_update += data_size / EFX_DEVLINK_STATUS_UPDATE_COUNT;
		}

		rc = efx_mcdi_nvram_write(efx, type, offset, data + offset, chunk);
		if (rc) {
			NL_SET_ERR_MSG_FMT_MOD(extack,
					       "Write failed for NVRAM partition %#x at %#zx-%#zx",
					       type, offset, offset + chunk - 1);
			return rc;
		}
	}

	/* Round up left over data to satisfy write alignment */
	if (offset < data_size) {
		size_t remaining = data_size - offset;
		u8 *buf;

		if (offset >= next_update)
			devlink_flash_update_status_notify(devlink, "Writing",
							   NULL, offset,
							   data_size);

		chunk = roundup(remaining, align);
		buf = kmalloc(chunk, GFP_KERNEL);
		if (!buf)
			return -ENOMEM;

		memcpy(buf, data + offset, remaining);
		memset(buf + remaining, 0xFF, chunk - remaining);
		rc = efx_mcdi_nvram_write(efx, type, offset, buf, chunk);
		kfree(buf);
		if (rc) {
			NL_SET_ERR_MSG_FMT_MOD(extack,
					       "Write failed for NVRAM partition %#x at %#zx-%#zx",
					       type, offset, offset + chunk - 1);
			return rc;
		}
	}

Annotation

Implementation Notes