Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e3f720a authored by Bart Van Assche's avatar Bart Van Assche Committed by Martin K. Petersen
Browse files

scsi: Rework the code for caching Vital Product Data (VPD)



Introduce the scsi_get_vpd_buf() and scsi_update_vpd_page()
functions. The only functional change in this patch is that if updating
page 0x80 fails that it is attempted to update page 0x83.

Signed-off-by: default avatarBart Van Assche <bart.vanassche@wdc.com>
Acked-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarShane Seymour <shane.seymour@hpe.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
Cc: Shane M Seymour <shane.seymour@hpe.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 26e3e3cb
Loading
Loading
Loading
Loading
+66 −78
Original line number Diff line number Diff line
@@ -412,105 +412,93 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
EXPORT_SYMBOL_GPL(scsi_get_vpd_page);

/**
 * scsi_attach_vpd - Attach Vital Product Data to a SCSI device structure
 * scsi_get_vpd_buf - Get Vital Product Data from a SCSI device
 * @sdev: The device to ask
 * @page: Which Vital Product Data to return
 * @len: Upon success, the VPD length will be stored in *@len.
 *
 * Attach the 'Device Identification' VPD page (0x83) and the
 * 'Unit Serial Number' VPD page (0x80) to a SCSI device
 * structure. This information can be used to identify the device
 * uniquely.
 * Returns %NULL upon failure.
 */
void scsi_attach_vpd(struct scsi_device *sdev)
static unsigned char *scsi_get_vpd_buf(struct scsi_device *sdev, u8 page,
				       int *len)
{
	int result, i;
	int vpd_len = SCSI_VPD_PG_LEN;
	int pg80_supported = 0;
	int pg83_supported = 0;
	unsigned char __rcu *vpd_buf, *orig_vpd_buf = NULL;

	if (!scsi_device_supports_vpd(sdev))
		return;
	unsigned char *vpd_buf;
	int vpd_len = SCSI_VPD_PG_LEN, result;

retry_pg0:
retry_pg:
	vpd_buf = kmalloc(vpd_len, GFP_KERNEL);
	if (!vpd_buf)
		return;
		return NULL;

	/* Ask for all the pages supported by this device */
	result = scsi_vpd_inquiry(sdev, vpd_buf, 0, vpd_len);
	result = scsi_vpd_inquiry(sdev, vpd_buf, page, vpd_len);
	if (result < 0) {
		kfree(vpd_buf);
		return;
		return NULL;
	}
	if (result > vpd_len) {
		vpd_len = result;
		kfree(vpd_buf);
		goto retry_pg0;
		goto retry_pg;
	}

	for (i = 4; i < result; i++) {
		if (vpd_buf[i] == 0x80)
			pg80_supported = 1;
		if (vpd_buf[i] == 0x83)
			pg83_supported = 1;
	*len = result;

	return vpd_buf;
}
	kfree(vpd_buf);
	vpd_len = SCSI_VPD_PG_LEN;

	if (pg80_supported) {
retry_pg80:
		vpd_buf = kmalloc(vpd_len, GFP_KERNEL);
static void scsi_update_vpd_page(struct scsi_device *sdev, u8 page,
				 unsigned char __rcu **sdev_vpd_buf,
				 int *sdev_vpd_len)
{
	unsigned char *vpd_buf;
	int len;

	vpd_buf = scsi_get_vpd_buf(sdev, page, &len);
	if (!vpd_buf)
		return;

		result = scsi_vpd_inquiry(sdev, vpd_buf, 0x80, vpd_len);
		if (result < 0) {
			kfree(vpd_buf);
			return;
		}
		if (result > vpd_len) {
			vpd_len = result;
			kfree(vpd_buf);
			goto retry_pg80;
		}
	mutex_lock(&sdev->inquiry_mutex);
		orig_vpd_buf = sdev->vpd_pg80;
		sdev->vpd_pg80_len = result;
		rcu_assign_pointer(sdev->vpd_pg80, vpd_buf);
	rcu_swap_protected(*sdev_vpd_buf, vpd_buf,
			   lockdep_is_held(&sdev->inquiry_mutex));
	*sdev_vpd_len = len;
	mutex_unlock(&sdev->inquiry_mutex);

	synchronize_rcu();
		if (orig_vpd_buf) {
			kfree(orig_vpd_buf);
			orig_vpd_buf = NULL;
		}
		vpd_len = SCSI_VPD_PG_LEN;

	kfree(vpd_buf);
}

	if (pg83_supported) {
retry_pg83:
		vpd_buf = kmalloc(vpd_len, GFP_KERNEL);
		if (!vpd_buf)
/**
 * scsi_attach_vpd - Attach Vital Product Data to a SCSI device structure
 * @sdev: The device to ask
 *
 * Attach the 'Device Identification' VPD page (0x83) and the
 * 'Unit Serial Number' VPD page (0x80) to a SCSI device
 * structure. This information can be used to identify the device
 * uniquely.
 */
void scsi_attach_vpd(struct scsi_device *sdev)
{
	int i, vpd_len;
	unsigned char *vpd_buf;

	if (!scsi_device_supports_vpd(sdev))
		return;

		result = scsi_vpd_inquiry(sdev, vpd_buf, 0x83, vpd_len);
		if (result < 0) {
			kfree(vpd_buf);
	/* Ask for all the pages supported by this device */
	vpd_buf = scsi_get_vpd_buf(sdev, 0, &vpd_len);
	if (!vpd_buf)
		return;

	for (i = 4; i < vpd_len; i++) {
		if (vpd_buf[i] == 0x80)
			scsi_update_vpd_page(sdev, 0x80, &sdev->vpd_pg80,
					     &sdev->vpd_pg80_len);
		if (vpd_buf[i] == 0x83)
			scsi_update_vpd_page(sdev, 0x83, &sdev->vpd_pg83,
					     &sdev->vpd_pg83_len);
	}
		if (result > vpd_len) {
			vpd_len = result;
	kfree(vpd_buf);
			goto retry_pg83;
		}
		mutex_lock(&sdev->inquiry_mutex);
		orig_vpd_buf = sdev->vpd_pg83;
		sdev->vpd_pg83_len = result;
		rcu_assign_pointer(sdev->vpd_pg83, vpd_buf);
		mutex_unlock(&sdev->inquiry_mutex);
		synchronize_rcu();
		if (orig_vpd_buf)
			kfree(orig_vpd_buf);
	}
}

/**