]> git.proxmox.com Git - mirror_qemu.git/blame - hw/scsi/virtio-scsi.c
Merge remote-tracking branch 'remotes/kraxel/tags/audio-20210617-pull-request' into...
[mirror_qemu.git] / hw / scsi / virtio-scsi.c
CommitLineData
973abc7f
SH
1/*
2 * Virtio SCSI HBA
3 *
4 * Copyright IBM, Corp. 2010
5 * Copyright Red Hat, Inc. 2011
6 *
7 * Authors:
8 * Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
9 * Paolo Bonzini <pbonzini@redhat.com>
10 *
11 * This work is licensed under the terms of the GNU GPL, version 2 or later.
12 * See the COPYING file in the top-level directory.
13 *
14 */
15
9b8bfe21 16#include "qemu/osdep.h"
da34e65c 17#include "qapi/error.h"
019adbd3 18#include "standard-headers/linux/virtio_ids.h"
0d09e41a 19#include "hw/virtio/virtio-scsi.h"
ca77ee28 20#include "migration/qemu-file-types.h"
b4a42f81 21#include "qemu/error-report.h"
36b15c79 22#include "qemu/iov.h"
0b8fa32f 23#include "qemu/module.h"
4be74634 24#include "sysemu/block-backend.h"
a27bd6c7 25#include "hw/qdev-properties.h"
a9c94277 26#include "hw/scsi/scsi.h"
08e2c9f1 27#include "scsi/constants.h"
a9c94277 28#include "hw/virtio/virtio-bus.h"
8c085dbe 29#include "hw/virtio/virtio-access.h"
eb8cb3d9 30#include "trace.h"
973abc7f 31
2ccdcd8d
PB
32static inline int virtio_scsi_get_lun(uint8_t *lun)
33{
34 return ((lun[2] << 8) | lun[3]) & 0x3FFF;
35}
36
07a47d4a 37static inline SCSIDevice *virtio_scsi_device_get(VirtIOSCSI *s, uint8_t *lun)
2ccdcd8d
PB
38{
39 if (lun[0] != 1) {
40 return NULL;
41 }
42 if (lun[2] != 0 && !(lun[2] >= 0x40 && lun[2] < 0x80)) {
43 return NULL;
44 }
07a47d4a 45 return scsi_device_get(&s->bus, 0, lun[1], virtio_scsi_get_lun(lun));
2ccdcd8d
PB
46}
47
51b19ebe 48void virtio_scsi_init_req(VirtIOSCSI *s, VirtQueue *vq, VirtIOSCSIReq *req)
36b15c79 49{
025bdeab 50 VirtIODevice *vdev = VIRTIO_DEVICE(s);
e24a47c5
PB
51 const size_t zero_skip =
52 offsetof(VirtIOSCSIReq, resp_iov) + sizeof(req->resp_iov);
36b15c79
PB
53
54 req->vq = vq;
55 req->dev = s;
025bdeab 56 qemu_sglist_init(&req->qsgl, DEVICE(s), 8, vdev->dma_as);
3eff1f46 57 qemu_iovec_init(&req->resp_iov, 1);
faf1e1fb 58 memset((uint8_t *)req + zero_skip, 0, sizeof(*req) - zero_skip);
36b15c79
PB
59}
60
aa8e8f83 61void virtio_scsi_free_req(VirtIOSCSIReq *req)
36b15c79 62{
3eff1f46 63 qemu_iovec_destroy(&req->resp_iov);
36b15c79 64 qemu_sglist_destroy(&req->qsgl);
633dccb4 65 g_free(req);
36b15c79
PB
66}
67
326799c0
SH
68static void virtio_scsi_complete_req(VirtIOSCSIReq *req)
69{
70 VirtIOSCSI *s = req->dev;
71 VirtQueue *vq = req->vq;
0ac8e139 72 VirtIODevice *vdev = VIRTIO_DEVICE(s);
3eff1f46
PB
73
74 qemu_iovec_from_buf(&req->resp_iov, 0, &req->resp, req->resp_size);
e24a47c5 75 virtqueue_push(vq, &req->elem, req->qsgl.size + req->resp_iov.size);
43c696a2 76 if (s->dataplane_started && !s->dataplane_fenced) {
83d768b5 77 virtio_notify_irqfd(vdev, vq);
63c7e542 78 } else {
63c7e542
FZ
79 virtio_notify(vdev, vq);
80 }
81
326799c0
SH
82 if (req->sreq) {
83 req->sreq->hba_private = NULL;
84 scsi_req_unref(req->sreq);
85 }
36b15c79 86 virtio_scsi_free_req(req);
326799c0
SH
87}
88
661e32fb 89static void virtio_scsi_bad_req(VirtIOSCSIReq *req)
326799c0 90{
661e32fb
GK
91 virtio_error(VIRTIO_DEVICE(req->dev), "wrong size for virtio-scsi headers");
92 virtqueue_detach_element(req->vq, &req->elem, 0);
93 virtio_scsi_free_req(req);
326799c0
SH
94}
95
57fbae6e
PB
96static size_t qemu_sgl_concat(VirtIOSCSIReq *req, struct iovec *iov,
97 hwaddr *addr, int num, size_t skip)
326799c0 98{
f487b677 99 QEMUSGList *qsgl = &req->qsgl;
57fbae6e
PB
100 size_t copied = 0;
101
102 while (num) {
103 if (skip >= iov->iov_len) {
104 skip -= iov->iov_len;
105 } else {
106 qemu_sglist_add(qsgl, *addr + skip, iov->iov_len - skip);
107 copied += iov->iov_len - skip;
108 skip = 0;
109 }
110 iov++;
111 addr++;
112 num--;
326799c0 113 }
57fbae6e
PB
114
115 assert(skip == 0);
116 return copied;
326799c0
SH
117}
118
36b15c79
PB
119static int virtio_scsi_parse_req(VirtIOSCSIReq *req,
120 unsigned req_size, unsigned resp_size)
326799c0 121{
55783a55 122 VirtIODevice *vdev = (VirtIODevice *) req->dev;
3eff1f46 123 size_t in_size, out_size;
36b15c79 124
3eff1f46
PB
125 if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
126 &req->req, req_size) < req_size) {
36b15c79
PB
127 return -EINVAL;
128 }
36b15c79 129
3eff1f46
PB
130 if (qemu_iovec_concat_iov(&req->resp_iov,
131 req->elem.in_sg, req->elem.in_num, 0,
132 resp_size) < resp_size) {
36b15c79
PB
133 return -EINVAL;
134 }
55783a55 135
489c7901 136 req->resp_size = resp_size;
326799c0 137
55783a55
PB
138 /* Old BIOSes left some padding by mistake after the req_size/resp_size.
139 * As a workaround, always consider the first buffer as the virtio-scsi
140 * request/response, making the payload start at the second element
141 * of the iovec.
142 *
143 * The actual length of the response header, stored in req->resp_size,
144 * does not change.
145 *
146 * TODO: always disable this workaround for virtio 1.0 devices.
147 */
95129d6f 148 if (!virtio_vdev_has_feature(vdev, VIRTIO_F_ANY_LAYOUT)) {
2034e324
FZ
149 if (req->elem.out_num) {
150 req_size = req->elem.out_sg[0].iov_len;
151 }
152 if (req->elem.in_num) {
153 resp_size = req->elem.in_sg[0].iov_len;
154 }
55783a55
PB
155 }
156
3eff1f46
PB
157 out_size = qemu_sgl_concat(req, req->elem.out_sg,
158 &req->elem.out_addr[0], req->elem.out_num,
159 req_size);
160 in_size = qemu_sgl_concat(req, req->elem.in_sg,
161 &req->elem.in_addr[0], req->elem.in_num,
162 resp_size);
163
164 if (out_size && in_size) {
165 return -ENOTSUP;
166 }
167
168 if (out_size) {
169 req->mode = SCSI_XFER_TO_DEV;
170 } else if (in_size) {
171 req->mode = SCSI_XFER_FROM_DEV;
326799c0 172 }
36b15c79
PB
173
174 return 0;
326799c0
SH
175}
176
177static VirtIOSCSIReq *virtio_scsi_pop_req(VirtIOSCSI *s, VirtQueue *vq)
178{
51b19ebe
PB
179 VirtIOSCSICommon *vs = (VirtIOSCSICommon *)s;
180 VirtIOSCSIReq *req;
181
182 req = virtqueue_pop(vq, sizeof(VirtIOSCSIReq) + vs->cdb_size);
183 if (!req) {
326799c0
SH
184 return NULL;
185 }
51b19ebe 186 virtio_scsi_init_req(s, vq, req);
326799c0
SH
187 return req;
188}
189
5db1764c
PB
190static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
191{
192 VirtIOSCSIReq *req = sreq->hba_private;
292c8e50 193 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(req->dev);
86044b24 194 VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
4e5163bd 195 uint32_t n = virtio_get_queue_index(req->vq) - VIRTIO_SCSI_VQ_NUM_FIXED;
5db1764c 196
292c8e50 197 assert(n < vs->conf.num_queues);
fcf104a7 198 qemu_put_be32s(f, &n);
86044b24 199 qemu_put_virtqueue_element(vdev, f, &req->elem);
5db1764c
PB
200}
201
202static void *virtio_scsi_load_request(QEMUFile *f, SCSIRequest *sreq)
203{
204 SCSIBus *bus = sreq->bus;
205 VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
292c8e50 206 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
8607f5c3 207 VirtIODevice *vdev = VIRTIO_DEVICE(s);
5db1764c 208 VirtIOSCSIReq *req;
fcf104a7 209 uint32_t n;
5db1764c 210
fcf104a7 211 qemu_get_be32s(f, &n);
292c8e50 212 assert(n < vs->conf.num_queues);
8607f5c3
JW
213 req = qemu_get_virtqueue_element(vdev, f,
214 sizeof(VirtIOSCSIReq) + vs->cdb_size);
51b19ebe 215 virtio_scsi_init_req(s, vs->cmd_vqs[n], req);
4ada5331 216
36b15c79
PB
217 if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
218 sizeof(VirtIOSCSICmdResp) + vs->sense_size) < 0) {
219 error_report("invalid SCSI request migration data");
220 exit(1);
221 }
5db1764c
PB
222
223 scsi_req_ref(sreq);
224 req->sreq = sreq;
225 if (req->sreq->cmd.mode != SCSI_XFER_NONE) {
3eff1f46 226 assert(req->sreq->cmd.mode == req->mode);
5db1764c
PB
227 }
228 return req;
229}
230
49e7e31a
FZ
231typedef struct {
232 Notifier notifier;
233 VirtIOSCSIReq *tmf_req;
234} VirtIOSCSICancelNotifier;
235
236static void virtio_scsi_cancel_notify(Notifier *notifier, void *data)
237{
238 VirtIOSCSICancelNotifier *n = container_of(notifier,
239 VirtIOSCSICancelNotifier,
240 notifier);
241
242 if (--n->tmf_req->remaining == 0) {
eb8cb3d9
HR
243 VirtIOSCSIReq *req = n->tmf_req;
244
245 trace_virtio_scsi_tmf_resp(virtio_scsi_get_lun(req->req.tmf.lun),
246 req->req.tmf.tag, req->resp.tmf.response);
247 virtio_scsi_complete_req(req);
49e7e31a 248 }
633dccb4 249 g_free(n);
49e7e31a
FZ
250}
251
2a2d69f4
FZ
252static inline void virtio_scsi_ctx_check(VirtIOSCSI *s, SCSIDevice *d)
253{
254 if (s->dataplane_started && d && blk_is_available(d->conf.blk)) {
255 assert(blk_get_aio_context(d->conf.blk) == s->ctx);
256 }
257}
258
49e7e31a
FZ
259/* Return 0 if the request is ready to be completed and return to guest;
260 * -EINPROGRESS if the request is submitted and will be completed later, in the
261 * case of async cancellation. */
262static int virtio_scsi_do_tmf(VirtIOSCSI *s, VirtIOSCSIReq *req)
326799c0 263{
07a47d4a 264 SCSIDevice *d = virtio_scsi_device_get(s, req->req.tmf.lun);
06114d72 265 SCSIRequest *r, *next;
0866aca1 266 BusChild *kid;
06114d72 267 int target;
49e7e31a 268 int ret = 0;
06114d72 269
2a2d69f4 270 virtio_scsi_ctx_check(s, d);
06114d72 271 /* Here VIRTIO_SCSI_S_OK means "FUNCTION COMPLETE". */
3eff1f46 272 req->resp.tmf.response = VIRTIO_SCSI_S_OK;
06114d72 273
d804232d
GK
274 /*
275 * req->req.tmf has the QEMU_PACKED attribute. Don't use virtio_tswap32s()
276 * to avoid compiler errors.
277 */
278 req->req.tmf.subtype =
279 virtio_tswap32(VIRTIO_DEVICE(s), req->req.tmf.subtype);
280
eb8cb3d9
HR
281 trace_virtio_scsi_tmf_req(virtio_scsi_get_lun(req->req.tmf.lun),
282 req->req.tmf.tag, req->req.tmf.subtype);
283
3eff1f46 284 switch (req->req.tmf.subtype) {
06114d72
PB
285 case VIRTIO_SCSI_T_TMF_ABORT_TASK:
286 case VIRTIO_SCSI_T_TMF_QUERY_TASK:
287 if (!d) {
288 goto fail;
289 }
3eff1f46 290 if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
06114d72
PB
291 goto incorrect_lun;
292 }
293 QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
4dd7c82c 294 VirtIOSCSIReq *cmd_req = r->hba_private;
3eff1f46 295 if (cmd_req && cmd_req->req.cmd.tag == req->req.tmf.tag) {
06114d72
PB
296 break;
297 }
298 }
4dd7c82c
PB
299 if (r) {
300 /*
301 * Assert that the request has not been completed yet, we
302 * check for it in the loop above.
303 */
304 assert(r->hba_private);
3eff1f46 305 if (req->req.tmf.subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK) {
06114d72
PB
306 /* "If the specified command is present in the task set, then
307 * return a service response set to FUNCTION SUCCEEDED".
308 */
3eff1f46 309 req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
06114d72 310 } else {
49e7e31a
FZ
311 VirtIOSCSICancelNotifier *notifier;
312
313 req->remaining = 1;
633dccb4 314 notifier = g_new(VirtIOSCSICancelNotifier, 1);
49e7e31a
FZ
315 notifier->tmf_req = req;
316 notifier->notifier.notify = virtio_scsi_cancel_notify;
317 scsi_req_cancel_async(r, &notifier->notifier);
318 ret = -EINPROGRESS;
06114d72
PB
319 }
320 }
321 break;
322
323 case VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET:
324 if (!d) {
325 goto fail;
326 }
3eff1f46 327 if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
06114d72
PB
328 goto incorrect_lun;
329 }
330 s->resetting++;
331 qdev_reset_all(&d->qdev);
332 s->resetting--;
333 break;
334
335 case VIRTIO_SCSI_T_TMF_ABORT_TASK_SET:
336 case VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET:
337 case VIRTIO_SCSI_T_TMF_QUERY_TASK_SET:
338 if (!d) {
339 goto fail;
340 }
3eff1f46 341 if (d->lun != virtio_scsi_get_lun(req->req.tmf.lun)) {
06114d72
PB
342 goto incorrect_lun;
343 }
49e7e31a
FZ
344
345 /* Add 1 to "remaining" until virtio_scsi_do_tmf returns.
346 * This way, if the bus starts calling back to the notifiers
347 * even before we finish the loop, virtio_scsi_cancel_notify
348 * will not complete the TMF too early.
349 */
350 req->remaining = 1;
06114d72
PB
351 QTAILQ_FOREACH_SAFE(r, &d->requests, next, next) {
352 if (r->hba_private) {
3eff1f46 353 if (req->req.tmf.subtype == VIRTIO_SCSI_T_TMF_QUERY_TASK_SET) {
06114d72
PB
354 /* "If there is any command present in the task set, then
355 * return a service response set to FUNCTION SUCCEEDED".
356 */
3eff1f46 357 req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_SUCCEEDED;
06114d72
PB
358 break;
359 } else {
49e7e31a
FZ
360 VirtIOSCSICancelNotifier *notifier;
361
362 req->remaining++;
633dccb4 363 notifier = g_new(VirtIOSCSICancelNotifier, 1);
49e7e31a
FZ
364 notifier->notifier.notify = virtio_scsi_cancel_notify;
365 notifier->tmf_req = req;
366 scsi_req_cancel_async(r, &notifier->notifier);
06114d72
PB
367 }
368 }
369 }
49e7e31a
FZ
370 if (--req->remaining > 0) {
371 ret = -EINPROGRESS;
372 }
06114d72
PB
373 break;
374
375 case VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET:
3eff1f46 376 target = req->req.tmf.lun[1];
06114d72 377 s->resetting++;
2d24a646
ML
378
379 rcu_read_lock();
380 QTAILQ_FOREACH_RCU(kid, &s->bus.qbus.children, sibling) {
07a47d4a
ML
381 SCSIDevice *d1 = SCSI_DEVICE(kid->child);
382 if (d1->channel == 0 && d1->id == target) {
383 qdev_reset_all(&d1->qdev);
384 }
06114d72 385 }
2d24a646
ML
386 rcu_read_unlock();
387
06114d72
PB
388 s->resetting--;
389 break;
390
391 case VIRTIO_SCSI_T_TMF_CLEAR_ACA:
392 default:
3eff1f46 393 req->resp.tmf.response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
06114d72 394 break;
326799c0
SH
395 }
396
07a47d4a 397 object_unref(OBJECT(d));
49e7e31a 398 return ret;
06114d72
PB
399
400incorrect_lun:
3eff1f46 401 req->resp.tmf.response = VIRTIO_SCSI_S_INCORRECT_LUN;
07a47d4a 402 object_unref(OBJECT(d));
49e7e31a 403 return ret;
06114d72
PB
404
405fail:
3eff1f46 406 req->resp.tmf.response = VIRTIO_SCSI_S_BAD_TARGET;
07a47d4a 407 object_unref(OBJECT(d));
49e7e31a 408 return ret;
326799c0
SH
409}
410
a8f2e5c8 411static void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req)
973abc7f 412{
dc56b7c4 413 VirtIODevice *vdev = (VirtIODevice *)s;
024d9adc 414 uint32_t type;
49e7e31a 415 int r = 0;
326799c0 416
dc56b7c4
FZ
417 if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0,
418 &type, sizeof(type)) < sizeof(type)) {
661e32fb 419 virtio_scsi_bad_req(req);
dc56b7c4
FZ
420 return;
421 }
36b15c79 422
024d9adc
BW
423 virtio_tswap32s(vdev, &type);
424 if (type == VIRTIO_SCSI_T_TMF) {
dc56b7c4
FZ
425 if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlTMFReq),
426 sizeof(VirtIOSCSICtrlTMFResp)) < 0) {
661e32fb
GK
427 virtio_scsi_bad_req(req);
428 return;
dc56b7c4 429 } else {
49e7e31a 430 r = virtio_scsi_do_tmf(s, req);
b0b4ea17 431 }
06114d72 432
024d9adc
BW
433 } else if (type == VIRTIO_SCSI_T_AN_QUERY ||
434 type == VIRTIO_SCSI_T_AN_SUBSCRIBE) {
dc56b7c4
FZ
435 if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlANReq),
436 sizeof(VirtIOSCSICtrlANResp)) < 0) {
661e32fb
GK
437 virtio_scsi_bad_req(req);
438 return;
dc56b7c4 439 } else {
eb8cb3d9
HR
440 req->req.an.event_requested =
441 virtio_tswap32(VIRTIO_DEVICE(s), req->req.an.event_requested);
442 trace_virtio_scsi_an_req(virtio_scsi_get_lun(req->req.an.lun),
443 req->req.an.event_requested);
dc56b7c4
FZ
444 req->resp.an.event_actual = 0;
445 req->resp.an.response = VIRTIO_SCSI_S_OK;
06114d72 446 }
dc56b7c4 447 }
49e7e31a 448 if (r == 0) {
eb8cb3d9
HR
449 if (type == VIRTIO_SCSI_T_TMF)
450 trace_virtio_scsi_tmf_resp(virtio_scsi_get_lun(req->req.tmf.lun),
451 req->req.tmf.tag,
452 req->resp.tmf.response);
453 else if (type == VIRTIO_SCSI_T_AN_QUERY ||
454 type == VIRTIO_SCSI_T_AN_SUBSCRIBE)
455 trace_virtio_scsi_an_resp(virtio_scsi_get_lun(req->req.an.lun),
456 req->resp.an.response);
49e7e31a
FZ
457 virtio_scsi_complete_req(req);
458 } else {
459 assert(r == -EINPROGRESS);
460 }
dc56b7c4
FZ
461}
462
07931698 463bool virtio_scsi_handle_ctrl_vq(VirtIOSCSI *s, VirtQueue *vq)
dc56b7c4 464{
dc56b7c4 465 VirtIOSCSIReq *req;
07931698 466 bool progress = false;
dc56b7c4
FZ
467
468 while ((req = virtio_scsi_pop_req(s, vq))) {
07931698 469 progress = true;
dc56b7c4 470 virtio_scsi_handle_ctrl_req(s, req);
326799c0 471 }
07931698 472 return progress;
326799c0
SH
473}
474
a8f2e5c8
PB
475static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
476{
477 VirtIOSCSI *s = (VirtIOSCSI *)vdev;
478
479 if (s->ctx) {
ad07cd69 480 virtio_device_start_ioeventfd(vdev);
a8f2e5c8
PB
481 if (!s->dataplane_fenced) {
482 return;
483 }
484 }
71407786 485 virtio_scsi_acquire(s);
a8f2e5c8 486 virtio_scsi_handle_ctrl_vq(s, vq);
71407786 487 virtio_scsi_release(s);
a8f2e5c8
PB
488}
489
a3de269c
PB
490static void virtio_scsi_complete_cmd_req(VirtIOSCSIReq *req)
491{
eb8cb3d9
HR
492 trace_virtio_scsi_cmd_resp(virtio_scsi_get_lun(req->req.cmd.lun),
493 req->req.cmd.tag,
494 req->resp.cmd.response,
495 req->resp.cmd.status);
3eff1f46
PB
496 /* Sense data is not in req->resp and is copied separately
497 * in virtio_scsi_command_complete.
498 */
499 req->resp_size = sizeof(VirtIOSCSICmdResp);
a3de269c
PB
500 virtio_scsi_complete_req(req);
501}
502
f3126d65
HR
503static void virtio_scsi_command_failed(SCSIRequest *r)
504{
505 VirtIOSCSIReq *req = r->hba_private;
506
507 if (r->io_canceled) {
508 return;
509 }
510
511 req->resp.cmd.status = GOOD;
512 switch (r->host_status) {
513 case SCSI_HOST_NO_LUN:
514 req->resp.cmd.response = VIRTIO_SCSI_S_INCORRECT_LUN;
515 break;
516 case SCSI_HOST_BUSY:
517 req->resp.cmd.response = VIRTIO_SCSI_S_BUSY;
518 break;
519 case SCSI_HOST_TIME_OUT:
520 case SCSI_HOST_ABORTED:
521 req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED;
522 break;
523 case SCSI_HOST_BAD_RESPONSE:
524 req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
525 break;
526 case SCSI_HOST_RESET:
527 req->resp.cmd.response = VIRTIO_SCSI_S_RESET;
528 break;
529 case SCSI_HOST_TRANSPORT_DISRUPTED:
530 req->resp.cmd.response = VIRTIO_SCSI_S_TRANSPORT_FAILURE;
531 break;
532 case SCSI_HOST_TARGET_FAILURE:
533 req->resp.cmd.response = VIRTIO_SCSI_S_TARGET_FAILURE;
534 break;
535 case SCSI_HOST_RESERVATION_ERROR:
536 req->resp.cmd.response = VIRTIO_SCSI_S_NEXUS_FAILURE;
537 break;
538 case SCSI_HOST_ALLOCATION_FAILURE:
539 case SCSI_HOST_MEDIUM_ERROR:
540 case SCSI_HOST_ERROR:
541 default:
542 req->resp.cmd.response = VIRTIO_SCSI_S_FAILURE;
543 break;
544 }
545 virtio_scsi_complete_cmd_req(req);
546}
547
17ea26c2 548static void virtio_scsi_command_complete(SCSIRequest *r, size_t resid)
2ccdcd8d
PB
549{
550 VirtIOSCSIReq *req = r->hba_private;
489c7901 551 uint8_t sense[SCSI_SENSE_BUF_SIZE];
474ee55a 552 uint32_t sense_len;
8c085dbe 553 VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
2ccdcd8d 554
e9c0f0f5
EF
555 if (r->io_canceled) {
556 return;
557 }
558
3eff1f46 559 req->resp.cmd.response = VIRTIO_SCSI_S_OK;
17ea26c2 560 req->resp.cmd.status = r->status;
3eff1f46 561 if (req->resp.cmd.status == GOOD) {
8c085dbe 562 req->resp.cmd.resid = virtio_tswap32(vdev, resid);
2ccdcd8d 563 } else {
3eff1f46 564 req->resp.cmd.resid = 0;
489c7901 565 sense_len = scsi_req_get_sense(r, sense, sizeof(sense));
3eff1f46
PB
566 sense_len = MIN(sense_len, req->resp_iov.size - sizeof(req->resp.cmd));
567 qemu_iovec_from_buf(&req->resp_iov, sizeof(req->resp.cmd),
b7890c40 568 sense, sense_len);
8c085dbe 569 req->resp.cmd.sense_len = virtio_tswap32(vdev, sense_len);
2ccdcd8d 570 }
a3de269c 571 virtio_scsi_complete_cmd_req(req);
2ccdcd8d
PB
572}
573
33cbb2c5
PB
574static int virtio_scsi_parse_cdb(SCSIDevice *dev, SCSICommand *cmd,
575 uint8_t *buf, void *hba_private)
576{
577 VirtIOSCSIReq *req = hba_private;
578
579 if (cmd->len == 0) {
03325525 580 cmd->len = MIN(VIRTIO_SCSI_CDB_DEFAULT_SIZE, SCSI_CMD_BUF_SIZE);
33cbb2c5
PB
581 memcpy(cmd->buf, buf, cmd->len);
582 }
583
584 /* Extract the direction and mode directly from the request, for
585 * host device passthrough.
586 */
587 cmd->xfer = req->qsgl.size;
9df7bfdd 588 cmd->mode = req->mode;
33cbb2c5
PB
589 return 0;
590}
591
2ccdcd8d
PB
592static QEMUSGList *virtio_scsi_get_sg_list(SCSIRequest *r)
593{
594 VirtIOSCSIReq *req = r->hba_private;
595
596 return &req->qsgl;
597}
598
599static void virtio_scsi_request_cancelled(SCSIRequest *r)
600{
601 VirtIOSCSIReq *req = r->hba_private;
602
603 if (!req) {
604 return;
605 }
06114d72 606 if (req->dev->resetting) {
3eff1f46 607 req->resp.cmd.response = VIRTIO_SCSI_S_RESET;
06114d72 608 } else {
3eff1f46 609 req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED;
06114d72 610 }
a3de269c 611 virtio_scsi_complete_cmd_req(req);
2ccdcd8d
PB
612}
613
614static void virtio_scsi_fail_cmd_req(VirtIOSCSIReq *req)
326799c0 615{
3eff1f46 616 req->resp.cmd.response = VIRTIO_SCSI_S_FAILURE;
a3de269c 617 virtio_scsi_complete_cmd_req(req);
973abc7f
SH
618}
619
661e32fb 620static int virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req)
bf359a44
FZ
621{
622 VirtIOSCSICommon *vs = &s->parent_obj;
bf359a44
FZ
623 SCSIDevice *d;
624 int rc;
625
626 rc = virtio_scsi_parse_req(req, sizeof(VirtIOSCSICmdReq) + vs->cdb_size,
627 sizeof(VirtIOSCSICmdResp) + vs->sense_size);
628 if (rc < 0) {
629 if (rc == -ENOTSUP) {
630 virtio_scsi_fail_cmd_req(req);
661e32fb 631 return -ENOTSUP;
bf359a44 632 } else {
661e32fb
GK
633 virtio_scsi_bad_req(req);
634 return -EINVAL;
bf359a44 635 }
bf359a44 636 }
eb8cb3d9
HR
637 trace_virtio_scsi_cmd_req(virtio_scsi_get_lun(req->req.cmd.lun),
638 req->req.cmd.tag, req->req.cmd.cdb[0]);
bf359a44 639
07a47d4a 640 d = virtio_scsi_device_get(s, req->req.cmd.lun);
bf359a44
FZ
641 if (!d) {
642 req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
643 virtio_scsi_complete_cmd_req(req);
661e32fb 644 return -ENOENT;
bf359a44 645 }
2a2d69f4 646 virtio_scsi_ctx_check(s, d);
bf359a44
FZ
647 req->sreq = scsi_req_new(d, req->req.cmd.tag,
648 virtio_scsi_get_lun(req->req.cmd.lun),
bb72463b 649 req->req.cmd.cdb, req);
bf359a44
FZ
650
651 if (req->sreq->cmd.mode != SCSI_XFER_NONE
652 && (req->sreq->cmd.mode != req->mode ||
653 req->sreq->cmd.xfer > req->qsgl.size)) {
654 req->resp.cmd.response = VIRTIO_SCSI_S_OVERRUN;
655 virtio_scsi_complete_cmd_req(req);
07a47d4a 656 object_unref(OBJECT(d));
661e32fb 657 return -ENOBUFS;
bf359a44 658 }
5170f40b 659 scsi_req_ref(req->sreq);
4be74634 660 blk_io_plug(d->conf.blk);
07a47d4a 661 object_unref(OBJECT(d));
661e32fb 662 return 0;
359eea71 663}
bf359a44 664
a8f2e5c8 665static void virtio_scsi_handle_cmd_req_submit(VirtIOSCSI *s, VirtIOSCSIReq *req)
359eea71 666{
35e4e96c
PB
667 SCSIRequest *sreq = req->sreq;
668 if (scsi_req_enqueue(sreq)) {
669 scsi_req_continue(sreq);
bf359a44 670 }
4be74634 671 blk_io_unplug(sreq->dev->conf.blk);
35e4e96c 672 scsi_req_unref(sreq);
bf359a44
FZ
673}
674
07931698 675bool virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq)
973abc7f 676{
1880ad4f 677 VirtIOSCSIReq *req, *next;
23425cc2 678 int ret = 0;
d0435bc5 679 bool suppress_notifications = virtio_queue_get_notification(vq);
07931698 680 bool progress = false;
661e32fb 681
1880ad4f 682 QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
326799c0 683
23425cc2 684 do {
d0435bc5
SH
685 if (suppress_notifications) {
686 virtio_queue_set_notification(vq, 0);
687 }
23425cc2
SH
688
689 while ((req = virtio_scsi_pop_req(s, vq))) {
07931698 690 progress = true;
23425cc2
SH
691 ret = virtio_scsi_handle_cmd_req_prepare(s, req);
692 if (!ret) {
693 QTAILQ_INSERT_TAIL(&reqs, req, next);
694 } else if (ret == -EINVAL) {
695 /* The device is broken and shouldn't process any request */
696 while (!QTAILQ_EMPTY(&reqs)) {
697 req = QTAILQ_FIRST(&reqs);
698 QTAILQ_REMOVE(&reqs, req, next);
699 blk_io_unplug(req->sreq->dev->conf.blk);
700 scsi_req_unref(req->sreq);
701 virtqueue_detach_element(req->vq, &req->elem, 0);
702 virtio_scsi_free_req(req);
703 }
661e32fb 704 }
359eea71 705 }
23425cc2 706
d0435bc5
SH
707 if (suppress_notifications) {
708 virtio_queue_set_notification(vq, 1);
709 }
23425cc2 710 } while (ret != -EINVAL && !virtio_queue_empty(vq));
1880ad4f
FZ
711
712 QTAILQ_FOREACH_SAFE(req, &reqs, next, next) {
713 virtio_scsi_handle_cmd_req_submit(s, req);
714 }
07931698 715 return progress;
973abc7f
SH
716}
717
a8f2e5c8
PB
718static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
719{
720 /* use non-QOM casts in the data path */
721 VirtIOSCSI *s = (VirtIOSCSI *)vdev;
722
723 if (s->ctx) {
ad07cd69 724 virtio_device_start_ioeventfd(vdev);
a8f2e5c8
PB
725 if (!s->dataplane_fenced) {
726 return;
727 }
728 }
71407786 729 virtio_scsi_acquire(s);
a8f2e5c8 730 virtio_scsi_handle_cmd_vq(s, vq);
71407786 731 virtio_scsi_release(s);
a8f2e5c8
PB
732}
733
973abc7f
SH
734static void virtio_scsi_get_config(VirtIODevice *vdev,
735 uint8_t *config)
736{
737 VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
292c8e50 738 VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(vdev);
973abc7f 739
8c085dbe 740 virtio_stl_p(vdev, &scsiconf->num_queues, s->conf.num_queues);
1bf8a989
DP
741 virtio_stl_p(vdev, &scsiconf->seg_max,
742 s->conf.seg_max_adjust ? s->conf.virtqueue_size - 2 : 128 - 2);
8c085dbe
RR
743 virtio_stl_p(vdev, &scsiconf->max_sectors, s->conf.max_sectors);
744 virtio_stl_p(vdev, &scsiconf->cmd_per_lun, s->conf.cmd_per_lun);
745 virtio_stl_p(vdev, &scsiconf->event_info_size, sizeof(VirtIOSCSIEvent));
746 virtio_stl_p(vdev, &scsiconf->sense_size, s->sense_size);
747 virtio_stl_p(vdev, &scsiconf->cdb_size, s->cdb_size);
748 virtio_stw_p(vdev, &scsiconf->max_channel, VIRTIO_SCSI_MAX_CHANNEL);
749 virtio_stw_p(vdev, &scsiconf->max_target, VIRTIO_SCSI_MAX_TARGET);
750 virtio_stl_p(vdev, &scsiconf->max_lun, VIRTIO_SCSI_MAX_LUN);
973abc7f
SH
751}
752
753static void virtio_scsi_set_config(VirtIODevice *vdev,
754 const uint8_t *config)
755{
756 VirtIOSCSIConfig *scsiconf = (VirtIOSCSIConfig *)config;
292c8e50 757 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
973abc7f 758
8c085dbe
RR
759 if ((uint32_t) virtio_ldl_p(vdev, &scsiconf->sense_size) >= 65536 ||
760 (uint32_t) virtio_ldl_p(vdev, &scsiconf->cdb_size) >= 256) {
ad14a46a
GK
761 virtio_error(vdev,
762 "bad data written to virtio-scsi configuration space");
763 return;
973abc7f
SH
764 }
765
8c085dbe
RR
766 vs->sense_size = virtio_ldl_p(vdev, &scsiconf->sense_size);
767 vs->cdb_size = virtio_ldl_p(vdev, &scsiconf->cdb_size);
973abc7f
SH
768}
769
019a3edb 770static uint64_t virtio_scsi_get_features(VirtIODevice *vdev,
9d5b731d
JW
771 uint64_t requested_features,
772 Error **errp)
973abc7f 773{
da2f84d1
SZ
774 VirtIOSCSI *s = VIRTIO_SCSI(vdev);
775
776 /* Firstly sync all virtio-scsi possible supported features */
777 requested_features |= s->host_features;
973abc7f
SH
778 return requested_features;
779}
780
781static void virtio_scsi_reset(VirtIODevice *vdev)
782{
292c8e50
PB
783 VirtIOSCSI *s = VIRTIO_SCSI(vdev);
784 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
973abc7f 785
ad07cd69 786 assert(!s->dataplane_started);
47a150a4 787 s->resetting++;
824755ba 788 qbus_reset_all(BUS(&s->bus));
47a150a4
PB
789 s->resetting--;
790
03325525
MT
791 vs->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
792 vs->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;
2baa1beb 793 s->events_dropped = false;
973abc7f
SH
794}
795
20e6dca1
FZ
796void virtio_scsi_push_event(VirtIOSCSI *s, SCSIDevice *dev,
797 uint32_t event, uint32_t reason)
b6866fee 798{
292c8e50 799 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s);
91e7fcca 800 VirtIOSCSIReq *req;
b6866fee 801 VirtIOSCSIEvent *evt;
0ac8e139 802 VirtIODevice *vdev = VIRTIO_DEVICE(s);
b6866fee 803
0ac8e139 804 if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
cd41a671
PB
805 return;
806 }
807
e24a47c5 808 req = virtio_scsi_pop_req(s, vs->event_vq);
64f64855
PB
809 if (!req) {
810 s->events_dropped = true;
71407786 811 return;
64f64855 812 }
b6866fee 813
64f64855
PB
814 if (s->events_dropped) {
815 event |= VIRTIO_SCSI_T_EVENTS_MISSED;
816 s->events_dropped = false;
817 }
818
dfecbb95 819 if (virtio_scsi_parse_req(req, 0, sizeof(VirtIOSCSIEvent))) {
661e32fb 820 virtio_scsi_bad_req(req);
71407786 821 return;
64f64855
PB
822 }
823
3eff1f46 824 evt = &req->resp.event;
64f64855 825 memset(evt, 0, sizeof(VirtIOSCSIEvent));
424baff5
CLG
826 evt->event = virtio_tswap32(vdev, event);
827 evt->reason = virtio_tswap32(vdev, reason);
64f64855 828 if (!dev) {
49fb65c7 829 assert(event == VIRTIO_SCSI_T_EVENTS_MISSED);
64f64855 830 } else {
b6866fee
CM
831 evt->lun[0] = 1;
832 evt->lun[1] = dev->id;
833
834 /* Linux wants us to keep the same encoding we use for REPORT LUNS. */
835 if (dev->lun >= 256) {
836 evt->lun[2] = (dev->lun >> 8) | 0x40;
837 }
838 evt->lun[3] = dev->lun & 0xFF;
64f64855 839 }
eb8cb3d9
HR
840 trace_virtio_scsi_event(virtio_scsi_get_lun(evt->lun), event, reason);
841
64f64855
PB
842 virtio_scsi_complete_req(req);
843}
844
07931698 845bool virtio_scsi_handle_event_vq(VirtIOSCSI *s, VirtQueue *vq)
a8f2e5c8
PB
846{
847 if (s->events_dropped) {
848 virtio_scsi_push_event(s, NULL, VIRTIO_SCSI_T_NO_EVENT, 0);
07931698 849 return true;
a8f2e5c8 850 }
07931698 851 return false;
a8f2e5c8
PB
852}
853
64f64855
PB
854static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq)
855{
0ac8e139 856 VirtIOSCSI *s = VIRTIO_SCSI(vdev);
64f64855 857
a8f2e5c8 858 if (s->ctx) {
ad07cd69 859 virtio_device_start_ioeventfd(vdev);
a8f2e5c8
PB
860 if (!s->dataplane_fenced) {
861 return;
862 }
b6866fee 863 }
71407786 864 virtio_scsi_acquire(s);
a8f2e5c8 865 virtio_scsi_handle_event_vq(s, vq);
71407786 866 virtio_scsi_release(s);
b6866fee
CM
867}
868
feda01e4
PB
869static void virtio_scsi_change(SCSIBus *bus, SCSIDevice *dev, SCSISense sense)
870{
871 VirtIOSCSI *s = container_of(bus, VirtIOSCSI, bus);
0ac8e139 872 VirtIODevice *vdev = VIRTIO_DEVICE(s);
feda01e4 873
95129d6f 874 if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_CHANGE) &&
feda01e4 875 dev->type != TYPE_ROM) {
71407786 876 virtio_scsi_acquire(s);
feda01e4
PB
877 virtio_scsi_push_event(s, dev, VIRTIO_SCSI_T_PARAM_CHANGE,
878 sense.asc | (sense.ascq << 8));
71407786 879 virtio_scsi_release(s);
feda01e4
PB
880 }
881}
882
4f71fb43
KW
883static void virtio_scsi_pre_hotplug(HotplugHandler *hotplug_dev,
884 DeviceState *dev, Error **errp)
885{
886 SCSIDevice *sd = SCSI_DEVICE(dev);
887 sd->hba_supports_iothread = true;
888}
889
02206e52
IM
890static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev,
891 Error **errp)
b6866fee 892{
02206e52 893 VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
3e2b2a9c
FZ
894 VirtIOSCSI *s = VIRTIO_SCSI(vdev);
895 SCSIDevice *sd = SCSI_DEVICE(dev);
c7040ff6 896 AioContext *old_context;
97896a48 897 int ret;
3e2b2a9c 898
43c696a2 899 if (s->ctx && !s->dataplane_fenced) {
3e2b2a9c
FZ
900 if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) {
901 return;
eb97813f 902 }
c7040ff6
SL
903 old_context = blk_get_aio_context(sd->conf.blk);
904 aio_context_acquire(old_context);
97896a48 905 ret = blk_set_aio_context(sd->conf.blk, s->ctx, errp);
c7040ff6 906 aio_context_release(old_context);
97896a48
KW
907 if (ret < 0) {
908 return;
909 }
8b5e6caf 910 }
b6866fee 911
95129d6f 912 if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
71407786 913 virtio_scsi_acquire(s);
3e2b2a9c 914 virtio_scsi_push_event(s, sd,
02206e52 915 VIRTIO_SCSI_T_TRANSPORT_RESET,
b6866fee 916 VIRTIO_SCSI_EVT_RESET_RESCAN);
71407786 917 virtio_scsi_release(s);
b6866fee
CM
918 }
919}
920
02206e52
IM
921static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev,
922 Error **errp)
b6866fee 923{
02206e52 924 VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev);
3e2b2a9c
FZ
925 VirtIOSCSI *s = VIRTIO_SCSI(vdev);
926 SCSIDevice *sd = SCSI_DEVICE(dev);
9c5aad84 927 AioContext *ctx = s->ctx ?: qemu_get_aio_context();
b6866fee 928
95129d6f 929 if (virtio_vdev_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) {
71407786 930 virtio_scsi_acquire(s);
3e2b2a9c 931 virtio_scsi_push_event(s, sd,
02206e52 932 VIRTIO_SCSI_T_TRANSPORT_RESET,
b6866fee 933 VIRTIO_SCSI_EVT_RESET_REMOVED);
71407786 934 virtio_scsi_release(s);
b6866fee 935 }
3e2b2a9c 936
9c5aad84
ZL
937 aio_disable_external(ctx);
938 qdev_simple_device_unplug_cb(hotplug_dev, dev, errp);
939 aio_enable_external(ctx);
940
a6f230c8
AG
941 if (s->ctx) {
942 virtio_scsi_acquire(s);
97896a48
KW
943 /* If other users keep the BlockBackend in the iothread, that's ok */
944 blk_set_aio_context(sd->conf.blk, qemu_get_aio_context(), NULL);
a6f230c8
AG
945 virtio_scsi_release(s);
946 }
b6866fee
CM
947}
948
2ccdcd8d
PB
949static struct SCSIBusInfo virtio_scsi_scsi_info = {
950 .tcq = true,
951 .max_channel = VIRTIO_SCSI_MAX_CHANNEL,
952 .max_target = VIRTIO_SCSI_MAX_TARGET,
953 .max_lun = VIRTIO_SCSI_MAX_LUN,
954
955 .complete = virtio_scsi_command_complete,
f3126d65 956 .fail = virtio_scsi_command_failed,
2ccdcd8d 957 .cancel = virtio_scsi_request_cancelled,
feda01e4 958 .change = virtio_scsi_change,
33cbb2c5 959 .parse_cdb = virtio_scsi_parse_cdb,
2ccdcd8d 960 .get_sg_list = virtio_scsi_get_sg_list,
5db1764c
PB
961 .save_request = virtio_scsi_save_request,
962 .load_request = virtio_scsi_load_request,
2ccdcd8d
PB
963};
964
bf46e67d 965void virtio_scsi_common_realize(DeviceState *dev,
209b27bb
FZ
966 VirtIOHandleOutput ctrl,
967 VirtIOHandleOutput evt,
bf46e67d
FZ
968 VirtIOHandleOutput cmd,
969 Error **errp)
973abc7f 970{
71a6520b
AF
971 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
972 VirtIOSCSICommon *s = VIRTIO_SCSI_COMMON(dev);
d2ad7dd4 973 int i;
973abc7f 974
7598f0f3 975 virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI,
763684be 976 sizeof(VirtIOSCSIConfig));
3ab1dfdd 977
6a558822
SH
978 if (s->conf.num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
979 s->conf.num_queues = 1;
980 }
0ba1f531 981 if (s->conf.num_queues == 0 ||
4e5163bd 982 s->conf.num_queues > VIRTIO_QUEUE_MAX - VIRTIO_SCSI_VQ_NUM_FIXED) {
0ba1f531 983 error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
c9f65528 984 "must be a positive integer less than %d.",
4e5163bd
SH
985 s->conf.num_queues,
986 VIRTIO_QUEUE_MAX - VIRTIO_SCSI_VQ_NUM_FIXED);
93bd49af 987 virtio_cleanup(vdev);
c9f65528
FZ
988 return;
989 }
1bf8a989
DP
990 if (s->conf.virtqueue_size <= 2) {
991 error_setg(errp, "invalid virtqueue_size property (= %" PRIu32 "), "
992 "must be > 2", s->conf.virtqueue_size);
993 return;
994 }
3c55fe2a 995 s->cmd_vqs = g_new0(VirtQueue *, s->conf.num_queues);
03325525
MT
996 s->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
997 s->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;
3ab1dfdd 998
5c0919d0
RJ
999 s->ctrl_vq = virtio_add_queue(vdev, s->conf.virtqueue_size, ctrl);
1000 s->event_vq = virtio_add_queue(vdev, s->conf.virtqueue_size, evt);
394e2e4c 1001 for (i = 0; i < s->conf.num_queues; i++) {
5c0919d0 1002 s->cmd_vqs[i] = virtio_add_queue(vdev, s->conf.virtqueue_size, cmd);
9786b592 1003 }
292c8e50
PB
1004}
1005
71a6520b 1006static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
292c8e50 1007{
71a6520b 1008 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
7598f0f3 1009 VirtIOSCSI *s = VIRTIO_SCSI(dev);
caad4eb3 1010 Error *err = NULL;
292c8e50 1011
bf46e67d
FZ
1012 virtio_scsi_common_realize(dev,
1013 virtio_scsi_handle_ctrl,
91d670fb 1014 virtio_scsi_handle_event,
bf46e67d
FZ
1015 virtio_scsi_handle_cmd,
1016 &err);
71a6520b
AF
1017 if (err != NULL) {
1018 error_propagate(errp, err);
1019 return;
292c8e50
PB
1020 }
1021
7598f0f3 1022 scsi_bus_new(&s->bus, sizeof(s->bus), dev,
b1187b51 1023 &virtio_scsi_scsi_info, vdev->bus_name);
02206e52 1024 /* override default SCSI bus hotplug-handler, with virtio-scsi's one */
9bc6bfdf 1025 qbus_set_hotplug_handler(BUS(&s->bus), OBJECT(dev));
6f32a6b4 1026
ad07cd69 1027 virtio_scsi_dataplane_setup(s, errp);
3ab1dfdd
FK
1028}
1029
12e1dc49 1030void virtio_scsi_common_unrealize(DeviceState *dev)
292c8e50 1031{
306ec6c3
AF
1032 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
1033 VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
c9c0ed69 1034 int i;
292c8e50 1035
36fc9bd3
PN
1036 virtio_delete_queue(vs->ctrl_vq);
1037 virtio_delete_queue(vs->event_vq);
c9c0ed69 1038 for (i = 0; i < vs->conf.num_queues; i++) {
36fc9bd3 1039 virtio_delete_queue(vs->cmd_vqs[i]);
c9c0ed69 1040 }
292c8e50 1041 g_free(vs->cmd_vqs);
6a1a8cc7 1042 virtio_cleanup(vdev);
292c8e50
PB
1043}
1044
b69c3c21 1045static void virtio_scsi_device_unrealize(DeviceState *dev)
3ab1dfdd 1046{
2cbe2de5
FZ
1047 VirtIOSCSI *s = VIRTIO_SCSI(dev);
1048
9bc6bfdf 1049 qbus_set_hotplug_handler(BUS(&s->bus), NULL);
12e1dc49 1050 virtio_scsi_common_unrealize(dev);
3ab1dfdd
FK
1051}
1052
1053static Property virtio_scsi_properties[] = {
6a558822
SH
1054 DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues,
1055 VIRTIO_SCSI_AUTO_NUM_QUEUES),
5c0919d0 1056 DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSI,
c9b7d9ec 1057 parent_obj.conf.virtqueue_size, 256),
1bf8a989
DP
1058 DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSI,
1059 parent_obj.conf.seg_max_adjust, true),
0c63237a
SZ
1060 DEFINE_PROP_UINT32("max_sectors", VirtIOSCSI, parent_obj.conf.max_sectors,
1061 0xFFFF),
1062 DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSI, parent_obj.conf.cmd_per_lun,
1063 128),
0c63237a
SZ
1064 DEFINE_PROP_BIT("hotplug", VirtIOSCSI, host_features,
1065 VIRTIO_SCSI_F_HOTPLUG, true),
1066 DEFINE_PROP_BIT("param_change", VirtIOSCSI, host_features,
1067 VIRTIO_SCSI_F_CHANGE, true),
08f1ecd8
FZ
1068 DEFINE_PROP_LINK("iothread", VirtIOSCSI, parent_obj.conf.iothread,
1069 TYPE_IOTHREAD, IOThread *),
3ab1dfdd
FK
1070 DEFINE_PROP_END_OF_LIST(),
1071};
1072
f20476b9
HP
1073static const VMStateDescription vmstate_virtio_scsi = {
1074 .name = "virtio-scsi",
1075 .minimum_version_id = 1,
1076 .version_id = 1,
1077 .fields = (VMStateField[]) {
1078 VMSTATE_VIRTIO_DEVICE,
1079 VMSTATE_END_OF_LIST()
1080 },
1081};
5a289a28 1082
292c8e50
PB
1083static void virtio_scsi_common_class_init(ObjectClass *klass, void *data)
1084{
1085 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
125ee0ed 1086 DeviceClass *dc = DEVICE_CLASS(klass);
292c8e50
PB
1087
1088 vdc->get_config = virtio_scsi_get_config;
125ee0ed 1089 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
292c8e50
PB
1090}
1091
3ab1dfdd
FK
1092static void virtio_scsi_class_init(ObjectClass *klass, void *data)
1093{
1094 DeviceClass *dc = DEVICE_CLASS(klass);
1095 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
02206e52 1096 HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
71a6520b 1097
4f67d30b 1098 device_class_set_props(dc, virtio_scsi_properties);
5a289a28 1099 dc->vmsd = &vmstate_virtio_scsi;
125ee0ed 1100 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
71a6520b 1101 vdc->realize = virtio_scsi_device_realize;
306ec6c3 1102 vdc->unrealize = virtio_scsi_device_unrealize;
3ab1dfdd
FK
1103 vdc->set_config = virtio_scsi_set_config;
1104 vdc->get_features = virtio_scsi_get_features;
1105 vdc->reset = virtio_scsi_reset;
ad07cd69
PB
1106 vdc->start_ioeventfd = virtio_scsi_dataplane_start;
1107 vdc->stop_ioeventfd = virtio_scsi_dataplane_stop;
4f71fb43 1108 hc->pre_plug = virtio_scsi_pre_hotplug;
02206e52
IM
1109 hc->plug = virtio_scsi_hotplug;
1110 hc->unplug = virtio_scsi_hotunplug;
3ab1dfdd
FK
1111}
1112
292c8e50
PB
1113static const TypeInfo virtio_scsi_common_info = {
1114 .name = TYPE_VIRTIO_SCSI_COMMON,
1115 .parent = TYPE_VIRTIO_DEVICE,
1116 .instance_size = sizeof(VirtIOSCSICommon),
a27292b5 1117 .abstract = true,
292c8e50
PB
1118 .class_init = virtio_scsi_common_class_init,
1119};
1120
3ab1dfdd
FK
1121static const TypeInfo virtio_scsi_info = {
1122 .name = TYPE_VIRTIO_SCSI,
292c8e50 1123 .parent = TYPE_VIRTIO_SCSI_COMMON,
3ab1dfdd
FK
1124 .instance_size = sizeof(VirtIOSCSI),
1125 .class_init = virtio_scsi_class_init,
02206e52
IM
1126 .interfaces = (InterfaceInfo[]) {
1127 { TYPE_HOTPLUG_HANDLER },
1128 { }
1129 }
3ab1dfdd
FK
1130};
1131
1132static void virtio_register_types(void)
1133{
292c8e50 1134 type_register_static(&virtio_scsi_common_info);
3ab1dfdd
FK
1135 type_register_static(&virtio_scsi_info);
1136}
1137
1138type_init(virtio_register_types)