Revision ad2d30f7
b/hw/scsi-bus.c | ||
---|---|---|
136 | 136 |
SCSIRequest *req; |
137 | 137 |
|
138 | 138 |
req = qemu_mallocz(size); |
139 |
/* Two references: one is passed back to the HBA, one is in d->requests. */ |
|
140 |
req->refcount = 2; |
|
139 | 141 |
req->bus = scsi_bus_from_device(d); |
140 | 142 |
req->dev = d; |
141 | 143 |
req->tag = tag; |
... | ... | |
159 | 161 |
return NULL; |
160 | 162 |
} |
161 | 163 |
|
162 |
static void scsi_req_dequeue(SCSIRequest *req)
|
|
164 |
void scsi_req_dequeue(SCSIRequest *req) |
|
163 | 165 |
{ |
164 | 166 |
trace_scsi_req_dequeue(req->dev->id, req->lun, req->tag); |
165 | 167 |
if (req->enqueued) { |
166 | 168 |
QTAILQ_REMOVE(&req->dev->requests, req, next); |
167 | 169 |
req->enqueued = false; |
170 |
scsi_req_unref(req); |
|
168 | 171 |
} |
169 | 172 |
} |
170 | 173 |
|
171 |
void scsi_req_free(SCSIRequest *req) |
|
172 |
{ |
|
173 |
scsi_req_dequeue(req); |
|
174 |
qemu_free(req); |
|
175 |
} |
|
176 |
|
|
177 | 174 |
static int scsi_req_length(SCSIRequest *req, uint8_t *cmd) |
178 | 175 |
{ |
179 | 176 |
switch (cmd[0] >> 5) { |
... | ... | |
495 | 492 |
return names[cmd]; |
496 | 493 |
} |
497 | 494 |
|
495 |
SCSIRequest *scsi_req_ref(SCSIRequest *req) |
|
496 |
{ |
|
497 |
req->refcount++; |
|
498 |
return req; |
|
499 |
} |
|
500 |
|
|
501 |
void scsi_req_unref(SCSIRequest *req) |
|
502 |
{ |
|
503 |
if (--req->refcount == 0) { |
|
504 |
if (req->dev->info->free_req) { |
|
505 |
req->dev->info->free_req(req); |
|
506 |
} |
|
507 |
qemu_free(req); |
|
508 |
} |
|
509 |
} |
|
510 |
|
|
498 | 511 |
/* Called by the devices when data is ready for the HBA. The HBA should |
499 | 512 |
start a DMA operation to read or fill the device's data buffer. |
500 | 513 |
Once it completes, calling one of req->dev->info->read_data or |
... | ... | |
537 | 550 |
void scsi_req_complete(SCSIRequest *req) |
538 | 551 |
{ |
539 | 552 |
assert(req->status != -1); |
553 |
scsi_req_ref(req); |
|
540 | 554 |
scsi_req_dequeue(req); |
541 | 555 |
req->bus->ops->complete(req->bus, SCSI_REASON_DONE, |
542 | 556 |
req->tag, |
543 | 557 |
req->status); |
558 |
scsi_req_unref(req); |
|
544 | 559 |
} |
545 | 560 |
|
546 | 561 |
static char *scsibus_get_fw_dev_path(DeviceState *dev) |
b/hw/scsi-disk.c | ||
---|---|---|
98 | 98 |
return r; |
99 | 99 |
} |
100 | 100 |
|
101 |
static void scsi_remove_request(SCSIDiskReq *r)
|
|
101 |
static void scsi_free_request(SCSIRequest *req)
|
|
102 | 102 |
{ |
103 |
SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); |
|
104 |
|
|
103 | 105 |
qemu_vfree(r->iov.iov_base); |
104 |
scsi_req_free(&r->req); |
|
105 | 106 |
} |
106 | 107 |
|
107 | 108 |
static SCSIDiskReq *scsi_find_request(SCSIDiskState *s, uint32_t tag) |
... | ... | |
134 | 135 |
r->req.tag, status, sense); |
135 | 136 |
scsi_req_set_status(r, status, sense); |
136 | 137 |
scsi_req_complete(&r->req); |
137 |
scsi_remove_request(r); |
|
138 | 138 |
} |
139 | 139 |
|
140 | 140 |
/* Cancel a pending data transfer. */ |
... | ... | |
148 | 148 |
if (r->req.aiocb) |
149 | 149 |
bdrv_aio_cancel(r->req.aiocb); |
150 | 150 |
r->req.aiocb = NULL; |
151 |
scsi_remove_request(r);
|
|
151 |
scsi_req_dequeue(&r->req);
|
|
152 | 152 |
} |
153 | 153 |
} |
154 | 154 |
|
... | ... | |
1033 | 1033 |
uint8_t *buf, int lun) |
1034 | 1034 |
{ |
1035 | 1035 |
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d); |
1036 |
uint32_t len;
|
|
1036 |
int32_t len; |
|
1037 | 1037 |
int is_write; |
1038 | 1038 |
uint8_t command; |
1039 | 1039 |
uint8_t *outbuf; |
... | ... | |
1095 | 1095 |
case REZERO_UNIT: |
1096 | 1096 |
rc = scsi_disk_emulate_command(r, outbuf); |
1097 | 1097 |
if (rc < 0) { |
1098 |
scsi_req_unref(&r->req); |
|
1098 | 1099 |
return 0; |
1099 | 1100 |
} |
1100 | 1101 |
|
... | ... | |
1181 | 1182 |
DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]); |
1182 | 1183 |
fail: |
1183 | 1184 |
scsi_command_complete(r, CHECK_CONDITION, ILLEGAL_REQUEST); |
1185 |
scsi_req_unref(&r->req); |
|
1184 | 1186 |
return 0; |
1185 | 1187 |
illegal_lba: |
1186 | 1188 |
scsi_command_complete(r, CHECK_CONDITION, HARDWARE_ERROR); |
1189 |
scsi_req_unref(&r->req); |
|
1187 | 1190 |
return 0; |
1188 | 1191 |
} |
1189 | 1192 |
if (r->sector_count == 0 && r->iov.iov_len == 0) { |
... | ... | |
1191 | 1194 |
} |
1192 | 1195 |
len = r->sector_count * 512 + r->iov.iov_len; |
1193 | 1196 |
if (is_write) { |
1194 |
return -len;
|
|
1197 |
len = -len;
|
|
1195 | 1198 |
} else { |
1196 | 1199 |
if (!r->sector_count) |
1197 | 1200 |
r->sector_count = -1; |
1198 |
return len; |
|
1199 | 1201 |
} |
1202 |
scsi_req_unref(&r->req); |
|
1203 |
return len; |
|
1200 | 1204 |
} |
1201 | 1205 |
|
1202 | 1206 |
static void scsi_disk_purge_requests(SCSIDiskState *s) |
... | ... | |
1208 | 1212 |
if (r->req.aiocb) { |
1209 | 1213 |
bdrv_aio_cancel(r->req.aiocb); |
1210 | 1214 |
} |
1211 |
scsi_remove_request(r);
|
|
1215 |
scsi_req_dequeue(&r->req);
|
|
1212 | 1216 |
} |
1213 | 1217 |
} |
1214 | 1218 |
|
... | ... | |
1321 | 1325 |
.qdev.reset = scsi_disk_reset, |
1322 | 1326 |
.init = scsi_hd_initfn, |
1323 | 1327 |
.destroy = scsi_destroy, |
1328 |
.free_req = scsi_free_request, |
|
1324 | 1329 |
.send_command = scsi_send_command, |
1325 | 1330 |
.read_data = scsi_read_data, |
1326 | 1331 |
.write_data = scsi_write_data, |
... | ... | |
1339 | 1344 |
.qdev.reset = scsi_disk_reset, |
1340 | 1345 |
.init = scsi_cd_initfn, |
1341 | 1346 |
.destroy = scsi_destroy, |
1347 |
.free_req = scsi_free_request, |
|
1342 | 1348 |
.send_command = scsi_send_command, |
1343 | 1349 |
.read_data = scsi_read_data, |
1344 | 1350 |
.write_data = scsi_write_data, |
... | ... | |
1356 | 1362 |
.qdev.reset = scsi_disk_reset, |
1357 | 1363 |
.init = scsi_disk_initfn, |
1358 | 1364 |
.destroy = scsi_destroy, |
1365 |
.free_req = scsi_free_request, |
|
1359 | 1366 |
.send_command = scsi_send_command, |
1360 | 1367 |
.read_data = scsi_read_data, |
1361 | 1368 |
.write_data = scsi_write_data, |
b/hw/scsi-generic.c | ||
---|---|---|
74 | 74 |
return DO_UPCAST(SCSIGenericReq, req, req); |
75 | 75 |
} |
76 | 76 |
|
77 |
static void scsi_remove_request(SCSIGenericReq *r)
|
|
77 |
static void scsi_free_request(SCSIRequest *req)
|
|
78 | 78 |
{ |
79 |
SCSIGenericReq *r = DO_UPCAST(SCSIGenericReq, req, req); |
|
80 |
|
|
79 | 81 |
qemu_free(r->buf); |
80 |
scsi_req_free(&r->req); |
|
81 | 82 |
} |
82 | 83 |
|
83 | 84 |
static SCSIGenericReq *scsi_find_request(SCSIGenericState *s, uint32_t tag) |
... | ... | |
113 | 114 |
r, r->req.tag, r->req.status); |
114 | 115 |
|
115 | 116 |
scsi_req_complete(&r->req); |
116 |
scsi_remove_request(r); |
|
117 | 117 |
} |
118 | 118 |
|
119 | 119 |
/* Cancel a pending data transfer. */ |
... | ... | |
128 | 128 |
if (r->req.aiocb) |
129 | 129 |
bdrv_aio_cancel(r->req.aiocb); |
130 | 130 |
r->req.aiocb = NULL; |
131 |
scsi_remove_request(r);
|
|
131 |
scsi_req_dequeue(&r->req);
|
|
132 | 132 |
} |
133 | 133 |
} |
134 | 134 |
|
... | ... | |
323 | 323 |
SCSIGenericReq *r; |
324 | 324 |
SCSIBus *bus; |
325 | 325 |
int ret; |
326 |
int32_t len; |
|
326 | 327 |
|
327 | 328 |
if (cmd[0] != REQUEST_SENSE && |
328 | 329 |
(lun != s->lun || (cmd[1] >> 5) != s->lun)) { |
... | ... | |
351 | 352 |
|
352 | 353 |
if (-1 == scsi_req_parse(&r->req, cmd)) { |
353 | 354 |
BADF("Unsupported command length, command %x\n", cmd[0]); |
354 |
scsi_remove_request(r); |
|
355 |
scsi_req_dequeue(&r->req); |
|
356 |
scsi_req_unref(&r->req); |
|
355 | 357 |
return 0; |
356 | 358 |
} |
357 | 359 |
scsi_req_fixup(&r->req); |
... | ... | |
377 | 379 |
ret = execute_command(s->bs, r, SG_DXFER_NONE, scsi_command_complete); |
378 | 380 |
if (ret == -1) { |
379 | 381 |
scsi_command_complete(r, -EINVAL); |
382 |
scsi_req_unref(&r->req); |
|
380 | 383 |
return 0; |
381 | 384 |
} |
385 |
scsi_req_unref(&r->req); |
|
382 | 386 |
return 0; |
383 | 387 |
} |
384 | 388 |
|
... | ... | |
393 | 397 |
r->len = r->req.cmd.xfer; |
394 | 398 |
if (r->req.cmd.mode == SCSI_XFER_TO_DEV) { |
395 | 399 |
r->len = 0; |
396 |
return -r->req.cmd.xfer; |
|
400 |
len = -r->req.cmd.xfer; |
|
401 |
} else { |
|
402 |
len = r->req.cmd.xfer; |
|
397 | 403 |
} |
398 | 404 |
|
399 |
return r->req.cmd.xfer; |
|
405 |
scsi_req_unref(&r->req); |
|
406 |
return len; |
|
400 | 407 |
} |
401 | 408 |
|
402 | 409 |
static int get_blocksize(BlockDriverState *bdrv) |
... | ... | |
469 | 476 |
if (r->req.aiocb) { |
470 | 477 |
bdrv_aio_cancel(r->req.aiocb); |
471 | 478 |
} |
472 |
scsi_remove_request(r);
|
|
479 |
scsi_req_dequeue(&r->req);
|
|
473 | 480 |
} |
474 | 481 |
} |
475 | 482 |
|
... | ... | |
561 | 568 |
.qdev.reset = scsi_generic_reset, |
562 | 569 |
.init = scsi_generic_initfn, |
563 | 570 |
.destroy = scsi_destroy, |
571 |
.free_req = scsi_free_request, |
|
564 | 572 |
.send_command = scsi_send_command, |
565 | 573 |
.read_data = scsi_read_data, |
566 | 574 |
.write_data = scsi_write_data, |
b/hw/scsi.h | ||
---|---|---|
29 | 29 |
typedef struct SCSIRequest { |
30 | 30 |
SCSIBus *bus; |
31 | 31 |
SCSIDevice *dev; |
32 |
uint32_t refcount; |
|
32 | 33 |
uint32_t tag; |
33 | 34 |
uint32_t lun; |
34 | 35 |
uint32_t status; |
... | ... | |
65 | 66 |
DeviceInfo qdev; |
66 | 67 |
scsi_qdev_initfn init; |
67 | 68 |
void (*destroy)(SCSIDevice *s); |
69 |
void (*free_req)(SCSIRequest *req); |
|
68 | 70 |
int32_t (*send_command)(SCSIDevice *s, uint32_t tag, uint8_t *buf, |
69 | 71 |
int lun); |
70 | 72 |
void (*read_data)(SCSIDevice *s, uint32_t tag); |
... | ... | |
103 | 105 |
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t lun); |
104 | 106 |
SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag); |
105 | 107 |
void scsi_req_free(SCSIRequest *req); |
108 |
void scsi_req_dequeue(SCSIRequest *req); |
|
109 |
SCSIRequest *scsi_req_ref(SCSIRequest *req); |
|
110 |
void scsi_req_unref(SCSIRequest *req); |
|
106 | 111 |
|
107 | 112 |
int scsi_req_parse(SCSIRequest *req, uint8_t *buf); |
108 | 113 |
void scsi_req_print(SCSIRequest *req); |
Also available in: Unified diff