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: Paul Luse <paul.e.luse@intel.com>
Reviewed-on: https://review.gerrithub.io/387183
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Paul Luse 2017-11-14 07:33:08 -07:00 committed by Jim Harris
parent e0ba4da0b1
commit 04f528938d
2 changed files with 89 additions and 3 deletions

View File

@ -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,

View File

@ -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;