drivers/scsi/pm8001/pm8001_ctl.c

Source file repositories/reference/linux-study-clean/drivers/scsi/pm8001/pm8001_ctl.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/pm8001/pm8001_ctl.c
Extension
.c
Size
32582 bytes
Lines
1054
Domain
Driver Families
Bucket
drivers/scsi
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 flash_command {
     u8      command[8] __nonstring;
     int     code;
};

static const struct flash_command flash_command_table[] = {
     {"set_nvmd",    FLASH_CMD_SET_NVMD},
     {"update",      FLASH_CMD_UPDATE},
     {"",            FLASH_CMD_NONE} /* Last entry should be NULL. */
};

struct error_fw {
     char    *reason;
     int     err_code;
};

static const struct error_fw flash_error_table[] = {
     {"Failed to open fw image file",	FAIL_OPEN_BIOS_FILE},
     {"image header mismatch",		FLASH_UPDATE_HDR_ERR},
     {"image offset mismatch",		FLASH_UPDATE_OFFSET_ERR},
     {"image CRC Error",		FLASH_UPDATE_CRC_ERR},
     {"image length Error.",		FLASH_UPDATE_LENGTH_ERR},
     {"Failed to program flash chip",	FLASH_UPDATE_HW_ERR},
     {"Flash chip not supported.",	FLASH_UPDATE_DNLD_NOT_SUPPORTED},
     {"Flash update disabled.",		FLASH_UPDATE_DISABLED},
     {"Flash in progress",		FLASH_IN_PROGRESS},
     {"Image file size Error",		FAIL_FILE_SIZE},
     {"Input parameter error",		FAIL_PARAMETERS},
     {"Out of memory",			FAIL_OUT_MEMORY},
     {"OK", 0}	/* Last entry err_code = 0. */
};

static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha)
{
	struct pm8001_ioctl_payload	*payload;
	DECLARE_COMPLETION_ONSTACK(completion);
	u8		*ioctlbuffer;
	int		ret;
	u32		length = 1024 * 5 + sizeof(*payload) - 1;

	if (pm8001_ha->fw_image->size > 4096) {
		pm8001_ha->fw_status = FAIL_FILE_SIZE;
		return -EFAULT;
	}

	ioctlbuffer = kzalloc(length, GFP_KERNEL);
	if (!ioctlbuffer) {
		pm8001_ha->fw_status = FAIL_OUT_MEMORY;
		return -ENOMEM;
	}
	payload = (struct pm8001_ioctl_payload *)ioctlbuffer;
	memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data,
				pm8001_ha->fw_image->size);
	payload->wr_length = pm8001_ha->fw_image->size;
	payload->id = 0;
	payload->minor_function = 0x1;
	pm8001_ha->nvmd_completion = &completion;
	ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload);
	if (ret) {
		pm8001_ha->fw_status = FAIL_OUT_MEMORY;
		goto out;
	}
	wait_for_completion(&completion);
out:
	kfree(ioctlbuffer);
	return ret;
}

static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha)
{
	struct pm8001_ioctl_payload	*payload;
	DECLARE_COMPLETION_ONSTACK(completion);
	u8		*ioctlbuffer;
	struct fw_control_info	*fwControl;
	__be32		partitionSizeTmp;
	u32		partitionSize;
	u32		loopNumber, loopcount;
	struct pm8001_fw_image_header *image_hdr;
	u32		sizeRead = 0;
	u32		ret = 0;
	u32		length = 1024 * 16 + sizeof(*payload) - 1;
	u32		fc_len;
	u8		*read_buf;

	if (pm8001_ha->fw_image->size < 28) {
		pm8001_ha->fw_status = FAIL_FILE_SIZE;
		return -EFAULT;
	}
	ioctlbuffer = kzalloc(length, GFP_KERNEL);
	if (!ioctlbuffer) {

Annotation

Implementation Notes