Commit 04f52893 authored by Paul Luse's avatar Paul Luse Committed by Jim Harris
Browse files

bdev-virtio: add test unit ready and start/stop to scan sequence



Tested with bdevio, hardcoded TUR response to test the start/stop
unit code

Change-Id: I5038e6bcce9fcd423f1b93c8bb8b466ee3817654
Signed-off-by: default avatarPaul Luse <paul.e.luse@intel.com>
Reviewed-on: https://review.gerrithub.io/387183


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarDariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent e0ba4da0
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -232,6 +232,8 @@ enum spdk_sbc_opcode {
	SPDK_SBC_VL_XPWRITE_32 = 0x0006,
};

#define SPDK_SBC_START_STOP_UNIT_START_BIT (1 << 0)

enum spdk_mmc_opcode {
	/* MMC6 */
	SPDK_MMC_READ_DISC_STRUCTURE = 0xad,
+87 −3
Original line number Diff line number Diff line
@@ -723,18 +723,97 @@ send_read_cap_16(struct virtio_scsi_scan_base *base, uint8_t target_id, struct v
	}
}

static void
send_test_unit_ready(struct virtio_scsi_scan_base *base, uint8_t target_id, struct virtio_req *vreq)
{
	struct virtio_scsi_cmd_req *req = vreq->iov_req.iov_base;
	int rc;

	memset(req, 0, sizeof(*req));
	req->lun[0] = 1;
	req->lun[1] = target_id;
	req->cdb[0] = SPDK_SPC_TEST_UNIT_READY;

	rc = virtio_xmit_pkt(base->vq, vreq);
	if (rc != 0) {
		assert(false);
	}
}

static void
send_start_stop_unit(struct virtio_scsi_scan_base *base, uint8_t target_id, struct virtio_req *vreq)
{
	struct virtio_scsi_cmd_req *req = vreq->iov_req.iov_base;
	int rc;

	memset(req, 0, sizeof(*req));
	req->lun[0] = 1;
	req->lun[1] = target_id;
	req->cdb[0] = SPDK_SBC_START_STOP_UNIT;
	req->cdb[4] = SPDK_SBC_START_STOP_UNIT_START_BIT;

	rc = virtio_xmit_pkt(base->vq, vreq);
	if (rc != 0) {
		assert(false);
	}
}

static int
process_scan_start_stop_unit(struct virtio_scsi_scan_base *base, struct virtio_req *vreq)
{
	struct virtio_scsi_cmd_req *req = vreq->iov_req.iov_base;
	struct virtio_scsi_cmd_resp *resp = vreq->iov_resp.iov_base;
	uint8_t target_id = req->lun[1];
	int rc = 0;

	if (resp->response == VIRTIO_SCSI_S_OK && resp->status == SPDK_SCSI_STATUS_GOOD) {
		send_inquiry_vpd(base, target_id, vreq, SPDK_SPC_VPD_SUPPORTED_VPD_PAGES);
	} else {
		rc = -1;
	}

	return rc;
}

static int
process_scan_test_unit_ready(struct virtio_scsi_scan_base *base, struct virtio_req *vreq)
{
	struct virtio_scsi_cmd_req *req = vreq->iov_req.iov_base;
	struct virtio_scsi_cmd_resp *resp = vreq->iov_resp.iov_base;
	uint8_t target_id = req->lun[1];
	int sk, asc, ascq;
	int rc = 0;

	get_scsi_status(resp, &sk, &asc, &ascq);

	/* check response, get VPD if spun up otherwise send SSU */
	if (resp->response == VIRTIO_SCSI_S_OK && resp->status == SPDK_SCSI_STATUS_GOOD) {
		send_inquiry_vpd(base, target_id, vreq, SPDK_SPC_VPD_SUPPORTED_VPD_PAGES);
	} else if (resp->response == VIRTIO_SCSI_S_OK &&
		   resp->status == SPDK_SCSI_STATUS_CHECK_CONDITION &&
		   sk == SPDK_SCSI_SENSE_UNIT_ATTENTION &&
		   asc == SPDK_SCSI_ASC_LOGICAL_UNIT_NOT_READY) {
		send_start_stop_unit(base, target_id, vreq);
	} else {
		rc = -1;
	}

	return rc;
}

static int
process_scan_inquiry_standard(struct virtio_scsi_scan_base *base, struct virtio_req *vreq)
{
	struct virtio_scsi_cmd_req *req = vreq->iov_req.iov_base;
	struct virtio_scsi_cmd_resp *resp = vreq->iov_resp.iov_base;
	struct spdk_scsi_cdb_inquiry_data *inquiry_data = vreq->iov[0].iov_base;
	uint8_t target_id;
	uint8_t target_id = req->lun[1];

	if (resp->response != VIRTIO_SCSI_S_OK || resp->status != SPDK_SCSI_STATUS_GOOD) {
		return -1;
	}

	/* check to make sure its a supported device */
	if (inquiry_data->peripheral_device_type != SPDK_SPC_PERIPHERAL_DEVICE_TYPE_DISK ||
	    inquiry_data->peripheral_qualifier != SPDK_SPC_PERIPHERAL_QUALIFIER_CONNECTED) {
		SPDK_WARNLOG("Unsupported peripheral device type 0x%02x (qualifier 0x%02x)\n",
@@ -743,8 +822,7 @@ process_scan_inquiry_standard(struct virtio_scsi_scan_base *base, struct virtio_
		return -1;
	}

	target_id = req->lun[1];
	send_inquiry_vpd(base, target_id, vreq, SPDK_SPC_VPD_SUPPORTED_VPD_PAGES);
	send_test_unit_ready(base, target_id, vreq);
	return 0;
}

@@ -956,6 +1034,12 @@ process_scan_resp(struct virtio_scsi_scan_base *base, struct virtio_req *vreq)
	case SPDK_SPC_INQUIRY:
		rc = process_scan_inquiry(base, vreq);
		break;
	case SPDK_SPC_TEST_UNIT_READY:
		rc = process_scan_test_unit_ready(base, vreq);
		break;
	case SPDK_SBC_START_STOP_UNIT:
		rc = process_scan_start_stop_unit(base, vreq);
		break;
	case SPDK_SBC_READ_CAPACITY_10:
		rc = process_read_cap_10(base, vreq);
		break;