virtio_scsi: v1.0 support

Note: for consistency, and to avoid sparse errors,
  convert all fields, even those no longer in use
  for virtio v1.0.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Michael S. Tsirkin 2014-11-23 17:28:57 +02:00
parent 6ae7feb316
commit d75dff39df
2 changed files with 49 additions and 34 deletions

View File

@ -158,7 +158,7 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf)
sc, resp->response, resp->status, resp->sense_len); sc, resp->response, resp->status, resp->sense_len);
sc->result = resp->status; sc->result = resp->status;
virtscsi_compute_resid(sc, resp->resid); virtscsi_compute_resid(sc, virtio32_to_cpu(vscsi->vdev, resp->resid));
switch (resp->response) { switch (resp->response) {
case VIRTIO_SCSI_S_OK: case VIRTIO_SCSI_S_OK:
set_host_byte(sc, DID_OK); set_host_byte(sc, DID_OK);
@ -196,10 +196,13 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf)
break; break;
} }
WARN_ON(resp->sense_len > VIRTIO_SCSI_SENSE_SIZE); WARN_ON(virtio32_to_cpu(vscsi->vdev, resp->sense_len) >
VIRTIO_SCSI_SENSE_SIZE);
if (sc->sense_buffer) { if (sc->sense_buffer) {
memcpy(sc->sense_buffer, resp->sense, memcpy(sc->sense_buffer, resp->sense,
min_t(u32, resp->sense_len, VIRTIO_SCSI_SENSE_SIZE)); min_t(u32,
virtio32_to_cpu(vscsi->vdev, resp->sense_len),
VIRTIO_SCSI_SENSE_SIZE));
if (resp->sense_len) if (resp->sense_len)
set_driver_byte(sc, DRIVER_SENSE); set_driver_byte(sc, DRIVER_SENSE);
} }
@ -323,7 +326,7 @@ static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi,
unsigned int target = event->lun[1]; unsigned int target = event->lun[1];
unsigned int lun = (event->lun[2] << 8) | event->lun[3]; unsigned int lun = (event->lun[2] << 8) | event->lun[3];
switch (event->reason) { switch (virtio32_to_cpu(vscsi->vdev, event->reason)) {
case VIRTIO_SCSI_EVT_RESET_RESCAN: case VIRTIO_SCSI_EVT_RESET_RESCAN:
scsi_add_device(shost, 0, target, lun); scsi_add_device(shost, 0, target, lun);
break; break;
@ -349,8 +352,8 @@ static void virtscsi_handle_param_change(struct virtio_scsi *vscsi,
struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
unsigned int target = event->lun[1]; unsigned int target = event->lun[1];
unsigned int lun = (event->lun[2] << 8) | event->lun[3]; unsigned int lun = (event->lun[2] << 8) | event->lun[3];
u8 asc = event->reason & 255; u8 asc = virtio32_to_cpu(vscsi->vdev, event->reason) & 255;
u8 ascq = event->reason >> 8; u8 ascq = virtio32_to_cpu(vscsi->vdev, event->reason) >> 8;
sdev = scsi_device_lookup(shost, 0, target, lun); sdev = scsi_device_lookup(shost, 0, target, lun);
if (!sdev) { if (!sdev) {
@ -374,12 +377,14 @@ static void virtscsi_handle_event(struct work_struct *work)
struct virtio_scsi *vscsi = event_node->vscsi; struct virtio_scsi *vscsi = event_node->vscsi;
struct virtio_scsi_event *event = &event_node->event; struct virtio_scsi_event *event = &event_node->event;
if (event->event & VIRTIO_SCSI_T_EVENTS_MISSED) { if (event->event &
event->event &= ~VIRTIO_SCSI_T_EVENTS_MISSED; cpu_to_virtio32(vscsi->vdev, VIRTIO_SCSI_T_EVENTS_MISSED)) {
event->event &= ~cpu_to_virtio32(vscsi->vdev,
VIRTIO_SCSI_T_EVENTS_MISSED);
scsi_scan_host(virtio_scsi_host(vscsi->vdev)); scsi_scan_host(virtio_scsi_host(vscsi->vdev));
} }
switch (event->event) { switch (virtio32_to_cpu(vscsi->vdev, event->event)) {
case VIRTIO_SCSI_T_NO_EVENT: case VIRTIO_SCSI_T_NO_EVENT:
break; break;
case VIRTIO_SCSI_T_TRANSPORT_RESET: case VIRTIO_SCSI_T_TRANSPORT_RESET:
@ -482,26 +487,28 @@ static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq,
return err; return err;
} }
static void virtio_scsi_init_hdr(struct virtio_scsi_cmd_req *cmd, static void virtio_scsi_init_hdr(struct virtio_device *vdev,
struct virtio_scsi_cmd_req *cmd,
struct scsi_cmnd *sc) struct scsi_cmnd *sc)
{ {
cmd->lun[0] = 1; cmd->lun[0] = 1;
cmd->lun[1] = sc->device->id; cmd->lun[1] = sc->device->id;
cmd->lun[2] = (sc->device->lun >> 8) | 0x40; cmd->lun[2] = (sc->device->lun >> 8) | 0x40;
cmd->lun[3] = sc->device->lun & 0xff; cmd->lun[3] = sc->device->lun & 0xff;
cmd->tag = (unsigned long)sc; cmd->tag = cpu_to_virtio64(vdev, (unsigned long)sc);
cmd->task_attr = VIRTIO_SCSI_S_SIMPLE; cmd->task_attr = VIRTIO_SCSI_S_SIMPLE;
cmd->prio = 0; cmd->prio = 0;
cmd->crn = 0; cmd->crn = 0;
} }
static void virtio_scsi_init_hdr_pi(struct virtio_scsi_cmd_req_pi *cmd_pi, static void virtio_scsi_init_hdr_pi(struct virtio_device *vdev,
struct virtio_scsi_cmd_req_pi *cmd_pi,
struct scsi_cmnd *sc) struct scsi_cmnd *sc)
{ {
struct request *rq = sc->request; struct request *rq = sc->request;
struct blk_integrity *bi; struct blk_integrity *bi;
virtio_scsi_init_hdr((struct virtio_scsi_cmd_req *)cmd_pi, sc); virtio_scsi_init_hdr(vdev, (struct virtio_scsi_cmd_req *)cmd_pi, sc);
if (!rq || !scsi_prot_sg_count(sc)) if (!rq || !scsi_prot_sg_count(sc))
return; return;
@ -509,9 +516,13 @@ static void virtio_scsi_init_hdr_pi(struct virtio_scsi_cmd_req_pi *cmd_pi,
bi = blk_get_integrity(rq->rq_disk); bi = blk_get_integrity(rq->rq_disk);
if (sc->sc_data_direction == DMA_TO_DEVICE) if (sc->sc_data_direction == DMA_TO_DEVICE)
cmd_pi->pi_bytesout = blk_rq_sectors(rq) * bi->tuple_size; cmd_pi->pi_bytesout = cpu_to_virtio32(vdev,
blk_rq_sectors(rq) *
bi->tuple_size);
else if (sc->sc_data_direction == DMA_FROM_DEVICE) else if (sc->sc_data_direction == DMA_FROM_DEVICE)
cmd_pi->pi_bytesin = blk_rq_sectors(rq) * bi->tuple_size; cmd_pi->pi_bytesin = cpu_to_virtio32(vdev,
blk_rq_sectors(rq) *
bi->tuple_size);
} }
static int virtscsi_queuecommand(struct virtio_scsi *vscsi, static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
@ -536,11 +547,11 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE); BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE);
if (virtio_has_feature(vscsi->vdev, VIRTIO_SCSI_F_T10_PI)) { if (virtio_has_feature(vscsi->vdev, VIRTIO_SCSI_F_T10_PI)) {
virtio_scsi_init_hdr_pi(&cmd->req.cmd_pi, sc); virtio_scsi_init_hdr_pi(vscsi->vdev, &cmd->req.cmd_pi, sc);
memcpy(cmd->req.cmd_pi.cdb, sc->cmnd, sc->cmd_len); memcpy(cmd->req.cmd_pi.cdb, sc->cmnd, sc->cmd_len);
req_size = sizeof(cmd->req.cmd_pi); req_size = sizeof(cmd->req.cmd_pi);
} else { } else {
virtio_scsi_init_hdr(&cmd->req.cmd, sc); virtio_scsi_init_hdr(vscsi->vdev, &cmd->req.cmd, sc);
memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len);
req_size = sizeof(cmd->req.cmd); req_size = sizeof(cmd->req.cmd);
} }
@ -655,7 +666,8 @@ static int virtscsi_device_reset(struct scsi_cmnd *sc)
cmd->sc = sc; cmd->sc = sc;
cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){ cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){
.type = VIRTIO_SCSI_T_TMF, .type = VIRTIO_SCSI_T_TMF,
.subtype = VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET, .subtype = cpu_to_virtio32(vscsi->vdev,
VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET),
.lun[0] = 1, .lun[0] = 1,
.lun[1] = sc->device->id, .lun[1] = sc->device->id,
.lun[2] = (sc->device->lun >> 8) | 0x40, .lun[2] = (sc->device->lun >> 8) | 0x40,
@ -713,7 +725,7 @@ static int virtscsi_abort(struct scsi_cmnd *sc)
.lun[1] = sc->device->id, .lun[1] = sc->device->id,
.lun[2] = (sc->device->lun >> 8) | 0x40, .lun[2] = (sc->device->lun >> 8) | 0x40,
.lun[3] = sc->device->lun & 0xff, .lun[3] = sc->device->lun & 0xff,
.tag = (unsigned long)sc, .tag = cpu_to_virtio64(vscsi->vdev, (unsigned long)sc),
}; };
return virtscsi_tmf(vscsi, cmd); return virtscsi_tmf(vscsi, cmd);
} }
@ -1073,6 +1085,7 @@ static unsigned int features[] = {
VIRTIO_SCSI_F_HOTPLUG, VIRTIO_SCSI_F_HOTPLUG,
VIRTIO_SCSI_F_CHANGE, VIRTIO_SCSI_F_CHANGE,
VIRTIO_SCSI_F_T10_PI, VIRTIO_SCSI_F_T10_PI,
VIRTIO_F_VERSION_1,
}; };
static struct virtio_driver virtio_scsi_driver = { static struct virtio_driver virtio_scsi_driver = {

View File

@ -27,13 +27,15 @@
#ifndef _LINUX_VIRTIO_SCSI_H #ifndef _LINUX_VIRTIO_SCSI_H
#define _LINUX_VIRTIO_SCSI_H #define _LINUX_VIRTIO_SCSI_H
#include <linux/virtio_types.h>
#define VIRTIO_SCSI_CDB_SIZE 32 #define VIRTIO_SCSI_CDB_SIZE 32
#define VIRTIO_SCSI_SENSE_SIZE 96 #define VIRTIO_SCSI_SENSE_SIZE 96
/* SCSI command request, followed by data-out */ /* SCSI command request, followed by data-out */
struct virtio_scsi_cmd_req { struct virtio_scsi_cmd_req {
u8 lun[8]; /* Logical Unit Number */ u8 lun[8]; /* Logical Unit Number */
u64 tag; /* Command identifier */ __virtio64 tag; /* Command identifier */
u8 task_attr; /* Task attribute */ u8 task_attr; /* Task attribute */
u8 prio; /* SAM command priority field */ u8 prio; /* SAM command priority field */
u8 crn; u8 crn;
@ -43,20 +45,20 @@ struct virtio_scsi_cmd_req {
/* SCSI command request, followed by protection information */ /* SCSI command request, followed by protection information */
struct virtio_scsi_cmd_req_pi { struct virtio_scsi_cmd_req_pi {
u8 lun[8]; /* Logical Unit Number */ u8 lun[8]; /* Logical Unit Number */
u64 tag; /* Command identifier */ __virtio64 tag; /* Command identifier */
u8 task_attr; /* Task attribute */ u8 task_attr; /* Task attribute */
u8 prio; /* SAM command priority field */ u8 prio; /* SAM command priority field */
u8 crn; u8 crn;
u32 pi_bytesout; /* DataOUT PI Number of bytes */ __virtio32 pi_bytesout; /* DataOUT PI Number of bytes */
u32 pi_bytesin; /* DataIN PI Number of bytes */ __virtio32 pi_bytesin; /* DataIN PI Number of bytes */
u8 cdb[VIRTIO_SCSI_CDB_SIZE]; u8 cdb[VIRTIO_SCSI_CDB_SIZE];
} __packed; } __packed;
/* Response, followed by sense data and data-in */ /* Response, followed by sense data and data-in */
struct virtio_scsi_cmd_resp { struct virtio_scsi_cmd_resp {
u32 sense_len; /* Sense data length */ __virtio32 sense_len; /* Sense data length */
u32 resid; /* Residual bytes in data buffer */ __virtio32 resid; /* Residual bytes in data buffer */
u16 status_qualifier; /* Status qualifier */ __virtio16 status_qualifier; /* Status qualifier */
u8 status; /* Command completion status */ u8 status; /* Command completion status */
u8 response; /* Response values */ u8 response; /* Response values */
u8 sense[VIRTIO_SCSI_SENSE_SIZE]; u8 sense[VIRTIO_SCSI_SENSE_SIZE];
@ -64,10 +66,10 @@ struct virtio_scsi_cmd_resp {
/* Task Management Request */ /* Task Management Request */
struct virtio_scsi_ctrl_tmf_req { struct virtio_scsi_ctrl_tmf_req {
u32 type; __virtio32 type;
u32 subtype; __virtio32 subtype;
u8 lun[8]; u8 lun[8];
u64 tag; __virtio64 tag;
} __packed; } __packed;
struct virtio_scsi_ctrl_tmf_resp { struct virtio_scsi_ctrl_tmf_resp {
@ -76,20 +78,20 @@ struct virtio_scsi_ctrl_tmf_resp {
/* Asynchronous notification query/subscription */ /* Asynchronous notification query/subscription */
struct virtio_scsi_ctrl_an_req { struct virtio_scsi_ctrl_an_req {
u32 type; __virtio32 type;
u8 lun[8]; u8 lun[8];
u32 event_requested; __virtio32 event_requested;
} __packed; } __packed;
struct virtio_scsi_ctrl_an_resp { struct virtio_scsi_ctrl_an_resp {
u32 event_actual; __virtio32 event_actual;
u8 response; u8 response;
} __packed; } __packed;
struct virtio_scsi_event { struct virtio_scsi_event {
u32 event; __virtio32 event;
u8 lun[8]; u8 lun[8];
u32 reason; __virtio32 reason;
} __packed; } __packed;
struct virtio_scsi_config { struct virtio_scsi_config {