>From 832fbadba4739821cac427c879fe6481f47a659a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 31 Jul 2012 17:42:11 +0200 Subject: [PATCH] megasas: generate repeatable WWNs Signed-off-by: Paolo Bonzini --- hw/megasas.c | 34 +++++++++++++++++++++++++--------- hw/scsi-bus.c | 10 ++++++++++ hw/scsi-disk.c | 9 +++++++++ hw/scsi.h | 2 ++ 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/hw/megasas.c b/hw/megasas.c index 8a4960f..c07a2bb 100644 --- a/hw/megasas.c +++ b/hw/megasas.c @@ -38,6 +38,9 @@ #define MEGASAS_MAX_SECTORS 0xFFFF /* No real limit */ #define MEGASAS_MAX_ARRAYS 128 +#define MEGASAS_ADDR_BASE 0x5525400123456000ULL +#define MEGASAS_ADDR_STEP 0x1000ULL + #define MEGASAS_FLAG_USE_JBOD 0 #define MEGASAS_MASK_USE_JBOD (1 << MEGASAS_FLAG_USE_JBOD) #define MEGASAS_FLAG_USE_MSIX 1 @@ -49,6 +52,8 @@ static const char *mfi_frame_desc[] = { "MFI init", "LD Read", "LD Write", "LD SCSI", "PD SCSI", "MFI Doorbell", "MFI Abort", "MFI SMP", "MFI Stop"}; +static uint64_t megasas_cur_addr = MEGASAS_ADDR_BASE; + typedef struct MegasasCmd { uint32_t index; uint16_t flags; @@ -89,6 +94,8 @@ typedef struct MegasasState { int shutdown_event; int boot_event; + uint64_t wwn; + uint64_t reply_queue_pa; void *reply_queue; int reply_queue_len; @@ -372,14 +379,17 @@ static uint64_t megasas_fw_time(void) return bcd_time; } -static uint64_t megasas_gen_sas_addr(uint64_t id) +static uint64_t megasas_get_sas_addr(MegasasState *s, uint64_t id) { - uint64_t addr; + return s->wwn + id; +} - addr = 0x5001a4aULL << 36; - addr |= id & 0xfffffffff; +static uint64_t megasas_disk_sas_addr(SCSIDevice *sdev) +{ + MegasasState *s = DO_UPCAST(MegasasState, dev.qdev, + sdev->qdev.parent_bus->parent); - return addr; + return scsi_device_get_wwn(sdev) ?: megasas_get_sas_addr(s, sdev->id + 1); } /* @@ -672,7 +682,7 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) info.host.type = MFI_INFO_HOST_PCIX; info.device.type = MFI_INFO_DEV_SAS3G; info.device.port_count = 2; - info.device.port_addr[0] = cpu_to_le64(megasas_gen_sas_addr((uint64_t)s)); + info.device.port_addr[0] = cpu_to_le64(megasas_get_sas_addr(s, 0)); memcpy(info.product_name, "MegaRAID SAS 8708EM2", 20); snprintf(info.serial_number, 32, "QEMU%08lx", @@ -761,7 +771,7 @@ static int megasas_mfc_get_defaults(MegasasState *s, MegasasCmd *cmd) return MFI_STAT_INVALID_PARAMETER; } - info.sas_addr = cpu_to_le64(megasas_gen_sas_addr((uint64_t)s)); + info.sas_addr = cpu_to_le64(megasas_get_sas_addr(s, 0)); info.stripe_size = 3; info.flush_time = 4; info.background_rate = 30; @@ -891,7 +901,7 @@ static int megasas_dcmd_pd_get_list(MegasasState *s, MegasasCmd *cmd) info.addr[num_pd_disks].scsi_dev_type = sdev->type; info.addr[num_pd_disks].connect_port_bitmap = 0x1; info.addr[num_pd_disks].sas_addr[0] = - cpu_to_le64(megasas_gen_sas_addr((uint64_t)sdev)); + cpu_to_le64(megasas_disk_sas_addr(sdev)); num_pd_disks++; offset += sizeof(struct mfi_pd_address); } @@ -994,7 +1004,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, info->slot_number = (sdev->id & 0xFF); info->path_info.count = 1; info->path_info.sas_addr[0] = - cpu_to_le64(megasas_gen_sas_addr((uint64_t)sdev)); + cpu_to_le64(megasas_disk_sas_addr(sdev)); info->connected_port_bitmap = 0x1; info->device_speed = 1; info->link_speed = 1; @@ -2069,6 +2079,11 @@ static int megasas_scsi_init(PCIDevice *dev) uint8_t *pci_conf; int i, bar_type; + if (!s->wwn) { + s->wwn = megasas_cur_addr; + megasas_cur_addr += MEGASAS_ADDR_STEP; + } + pci_conf = s->dev.config; /* PCI latency timer = 0 */ @@ -2136,6 +2151,7 @@ static Property megasas_properties[] = { MEGASAS_DEFAULT_SGE), DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds, MEGASAS_DEFAULT_FRAMES), + DEFINE_PROP_HEX64("wwn", MegasasState, wwn, 0), #ifdef USE_MSIX DEFINE_PROP_BIT("use_msix", MegasasState, flags, MEGASAS_FLAG_USE_MSIX, false), diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 68049f6..79c732a 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -71,6 +71,16 @@ static void scsi_device_unit_attention_reported(SCSIDevice *s) } } +uint64_t scsi_device_get_wwn(SCSIDevice *s) +{ + SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s); + if (sc->get_wwn) { + return sc->get_wwn(s); + } else { + return 0; + } +} + /* Create a scsi bus, and attach devices to it. */ void scsi_bus_new(SCSIBus *bus, DeviceState *host, const SCSIBusInfo *info) { diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index a9c7279..2cb9d4e 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -2239,6 +2239,12 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag, } #endif +static uint64_t scsi_disk_get_wwn(SCSIDevice *sdev) +{ + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, sdev); + return s->wwn; +} + #define DEFINE_SCSI_DISK_PROPERTIES() \ DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf), \ DEFINE_PROP_STRING("ver", SCSIDiskState, version), \ @@ -2281,6 +2287,7 @@ static void scsi_hd_class_initfn(ObjectClass *klass, void *data) sc->init = scsi_hd_initfn; sc->destroy = scsi_destroy; sc->alloc_req = scsi_new_request; + sc->get_wwn = scsi_disk_get_wwn; sc->unit_attention_reported = scsi_disk_unit_attention_reported; dc->fw_name = "disk"; dc->desc = "virtual SCSI disk"; @@ -2310,6 +2317,7 @@ static void scsi_cd_class_initfn(ObjectClass *klass, void *data) sc->init = scsi_cd_initfn; sc->destroy = scsi_destroy; sc->alloc_req = scsi_new_request; + sc->get_wwn = scsi_disk_get_wwn; sc->unit_attention_reported = scsi_disk_unit_attention_reported; dc->fw_name = "disk"; dc->desc = "virtual SCSI CD-ROM"; @@ -2372,6 +2380,7 @@ static void scsi_disk_class_initfn(ObjectClass *klass, void *data) sc->init = scsi_disk_initfn; sc->destroy = scsi_destroy; sc->alloc_req = scsi_new_request; + sc->get_wwn = scsi_disk_get_wwn; sc->unit_attention_reported = scsi_disk_unit_attention_reported; dc->fw_name = "disk"; dc->desc = "virtual SCSI disk or CD-ROM (legacy)"; diff --git a/hw/scsi.h b/hw/scsi.h index 1aeee46..053a529 100644 --- a/hw/scsi.h +++ b/hw/scsi.h @@ -76,6 +76,7 @@ typedef struct SCSIDeviceClass { SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun, uint8_t *buf, void *hba_private); void (*unit_attention_reported)(SCSIDevice *s); + uint64_t (*get_wwn)(SCSIDevice *s); } SCSIDeviceClass; struct SCSIDevice @@ -242,6 +243,7 @@ void scsi_req_abort(SCSIRequest *req, int status); void scsi_req_cancel(SCSIRequest *req); void scsi_req_retry(SCSIRequest *req); void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense); +uint64_t scsi_device_get_wwn(SCSIDevice *sdev); void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense); void scsi_device_report_change(SCSIDevice *dev, SCSISense sense); int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed); -- 1.7.10.4