[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC PATCH v2 07/13] scsi: add walking of hierarchical LUNs
From: |
Paolo Bonzini |
Subject: |
[Qemu-devel] [RFC PATCH v2 07/13] scsi: add walking of hierarchical LUNs |
Date: |
Mon, 6 Jun 2011 18:04:16 +0200 |
This adds support for parsing a hierarchical LUN and mapping the
result to the qdev hierarchy.
Signed-off-by: Paolo Bonzini <address@hidden>
---
hw/scsi-bus.c | 83 +++++++++++++++++++++++++++++++++++++++++++----------
hw/scsi.h | 9 +++++-
hw/spapr_vscsi.c | 6 ++-
3 files changed, 79 insertions(+), 19 deletions(-)
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index b64ed68..54f308d 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -841,33 +841,84 @@ retry:
abort();
}
-/* Extract bus and target from the given LUN and use it to identify a
- SCSIDevice from a SCSIBus. Right now, only 1 target per bus is
- supported. In the future a SCSIDevice could host its own SCSIBus,
- in an alternation of devices that select a bus (target ports) and
- devices that select a target (initiator ports). */
-SCSIDevice *scsi_decode_lun(SCSIBus *sbus, uint64_t sam_lun, int *lun)
+/* Reusable implementation of the decode_lun entry in SCSIBusOps. */
+SCSIDevice *scsi_decode_bus_from_lun(SCSIBus *sbus, uint64_t sam_lun,
+ uint64_t *next_lun)
{
- int bus, target, decoded_lun;
- uint64_t next_lun;
+ int bus, target;
+ uint64_t my_next_lun;
+ SCSIDevice *sdev;
- if (!scsi_decode_level(sam_lun, &bus, &target, &next_lun)) {
+ if (!scsi_decode_level(sam_lun, &bus, &target, &my_next_lun)) {
/* Unsupported LUN format. */
return NULL;
}
- if (bus >= sbus->ndev || (bus == 0 && target > 0)) {
+ if (bus >= sbus->ndev) {
/* Out of range. */
return NULL;
}
- if (target != 0) {
- /* Only one target for now. */
+
+ sdev = sbus->devs[bus];
+ if (!sdev) {
+ return NULL;
+ } else if (!sdev->children || !sdev->children->ops->decode_lun) {
+ *next_lun = my_next_lun;
+ return target ? NULL : sdev;
+ } else {
+ /* Next we'll find the target, so pass down the same LUN we got. */
+ return sdev->children->ops->decode_lun(sdev->children, sam_lun,
+ next_lun);
+ }
+}
+
+SCSIDevice *scsi_decode_target_from_lun(SCSIBus *sbus, uint64_t sam_lun,
+ uint64_t *next_lun)
+{
+ int bus, target;
+ SCSIDevice *sdev;
+
+ if (!scsi_decode_level(sam_lun, &bus, &target, next_lun)) {
+ /* Unsupported LUN format. */
+ return NULL;
+ }
+ if (target >= sbus->ndev) {
+ /* Out of range. */
return NULL;
}
+ sdev = sbus->devs[target];
+ if (!sdev || !sdev->children || !sdev->children->ops->decode_lun ||
+ (*next_lun >> 56) == ADDR_WELL_KNOWN_LUN) {
+ return sdev;
+ } else {
+ return sdev->children->ops->decode_lun(sdev->children, *next_lun,
+ next_lun);
+ }
+}
+
+/* Extract bus and target from the given LUN and use it to identify a
+ SCSIDevice from a SCSIBus. Right now, only 1 target per bus is
+ supported. In the future a SCSIDevice could host its own SCSIBus,
+ in an alternation of devices that select a bus (target ports) and
+ devices that select a target (initiator ports). */
+SCSIDevice *scsi_decode_lun(SCSIBus *sbus, uint64_t sam_lun,
+ uint8_t *cdb, int *lun)
+{
+ int decoded_lun;
+ uint64_t next_lun;
+ SCSIDevice *sdev;
+
+ sdev = sbus->ops->decode_lun(sbus, sam_lun, &next_lun);
+ if (!sdev) {
+ return NULL;
+ }
decoded_lun = scsi_get_lun(next_lun);
- if (decoded_lun != LUN_INVALID) {
- *lun = decoded_lun;
- return sbus->devs[bus];
+ if (decoded_lun == LUN_INVALID) {
+ return NULL;
+ }
+ if ((decoded_lun & ~LUN_WLUN_MASK) == LUN_WLUN_BASE) {
+ return sdev;
}
- return NULL;
+ *lun = decoded_lun;
+ return scsi_find_lun(sdev, decoded_lun, cdb);
}
diff --git a/hw/scsi.h b/hw/scsi.h
index 67d18cc..9f70771 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -92,6 +92,8 @@ struct SCSIBusOps {
void (*complete)(SCSIRequest *req, uint32_t arg);
void (*cancel)(SCSIRequest *req);
int (*get_child_lun)(SCSIDevice *dev);
+ SCSIDevice *(*decode_lun)(SCSIBus *sbus, uint64_t sam_lun,
+ uint64_t *next_lun);
};
struct SCSIBus {
@@ -156,7 +158,12 @@ extern const struct SCSISense sense_code_LUN_FAILURE;
int scsi_build_sense(SCSISense sense, uint8_t *buf, int len, int fixed);
int scsi_sense_valid(SCSISense sense);
-SCSIDevice *scsi_decode_lun(SCSIBus *sbus, uint64_t sam_lun, int *lun);
+SCSIDevice *scsi_decode_lun(SCSIBus *sbus, uint64_t sam_lun, uint8_t *cdb,
+ int *lun);
+SCSIDevice *scsi_decode_bus_from_lun(SCSIBus *sbus, uint64_t sam_lun,
+ uint64_t *next_lun);
+SCSIDevice *scsi_decode_target_from_lun(SCSIBus *sbus, uint64_t sam_lun,
+ uint64_t *next_lun);
SCSIDevice *scsi_find_lun(SCSIDevice *sdev, int lun, uint8_t *cdb);
SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, DeviceState *initiator,
diff --git a/hw/spapr_vscsi.c b/hw/spapr_vscsi.c
index 5b5fa87..ace9dac 100644
--- a/hw/spapr_vscsi.c
+++ b/hw/spapr_vscsi.c
@@ -637,7 +637,8 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
SCSIDevice *sdev;
int n, lun;
- sdev = scsi_decode_lun(&s->bus, be64_to_cpu(srp->cmd.lun), &lun);
+ sdev = scsi_decode_lun(&s->bus, be64_to_cpu(srp->cmd.lun),
+ srp->cmd.cdb, &lun);
if (!sdev) {
if (srp->cmd.cdb[0] == INQUIRY) {
vscsi_inquiry_no_target(s, req);
@@ -915,7 +916,8 @@ static int vscsi_do_crq(struct VIOsPAPRDevice *dev, uint8_t
*crq_data)
static const struct SCSIBusOps vscsi_scsi_ops = {
.transfer_data = vscsi_transfer_data,
.complete = vscsi_command_complete,
- .cancel = vscsi_request_cancelled
+ .cancel = vscsi_request_cancelled,
+ .decode_lun = scsi_decode_bus_from_lun
};
static int spapr_vscsi_init(VIOsPAPRDevice *dev)
--
1.7.4.4
- [Qemu-devel] [RFC PATCH v2 00/13] support hierarchical LUNs, Paolo Bonzini, 2011/06/06
- [Qemu-devel] [RFC PATCH v2 02/13] scsi: support parsing of SAM logical unit numbers, Paolo Bonzini, 2011/06/06
- [Qemu-devel] [RFC PATCH v2 01/13] scsi: cleanup reset and destroy callbacks, Paolo Bonzini, 2011/06/06
- [Qemu-devel] [RFC PATCH v2 03/13] scsi: add initiator field to SCSIRequest, Paolo Bonzini, 2011/06/06
- [Qemu-devel] [RFC PATCH v2 04/13] scsi: let a SCSIDevice have children devices, Paolo Bonzini, 2011/06/06
- [Qemu-devel] [RFC PATCH v2 05/13] scsi: let the bus pick a LUN for the child device, Paolo Bonzini, 2011/06/06
- [Qemu-devel] [RFC PATCH v2 06/13] scsi-generic: fix passthrough of devices with LUN != 0, Paolo Bonzini, 2011/06/06
- [Qemu-devel] [RFC PATCH v2 07/13] scsi: add walking of hierarchical LUNs,
Paolo Bonzini <=
- [Qemu-devel] [RFC PATCH v2 08/13] scsi: introduce the scsi-path device, Paolo Bonzini, 2011/06/06
- [Qemu-devel] [RFC PATCH v2 09/13] scsi: introduce the scsi-target device, Paolo Bonzini, 2011/06/06
- [Qemu-devel] [RFC PATCH v2 10/13] scsi: include bus and device levels, Paolo Bonzini, 2011/06/06
- [Qemu-devel] [RFC PATCH v2 11/13] qdev: introduce automatic creation of buses, Paolo Bonzini, 2011/06/06
- [Qemu-devel] [RFC PATCH v2 12/13] scsi: create scsi-path and scsi-target devices automatically, Paolo Bonzini, 2011/06/06
- [Qemu-devel] [RFC PATCH v2 13/13] scsi: delete handling of REPORT LUNS and unknown LUNs outside scsi-target, Paolo Bonzini, 2011/06/06