Print this page
OS-1996 mpt_sas: allow physical topology enumeration in libtopo
Reviewed by: Keith Wesolowski <keith.wesolowski@joyent.com>

*** 20,29 **** --- 20,30 ---- */ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* * Copyright (c) 2000 to 2010, LSI Corporation. * All rights reserved.
*** 67,76 **** --- 68,78 ---- #include <sys/scsi/scsi.h> #include <sys/pci.h> #include <sys/file.h> #include <sys/cpuvar.h> #include <sys/policy.h> + #include <sys/model.h> #include <sys/sysevent.h> #include <sys/sysevent/eventdefs.h> #include <sys/sysevent/dr.h> #include <sys/sata/sata_defs.h> #include <sys/scsi/generic/sas.h>
*** 11949,11958 **** --- 11951,12050 ---- mutex_exit(&mpt->m_mutex); return (status); } static int + get_disk_info(mptsas_t *mpt, intptr_t data, int mode) + { + int i = 0; + int count = 0; + int ret = 0; + mptsas_target_t *ptgt; + mptsas_disk_info_t *di; + STRUCT_DECL(mptsas_get_disk_info, gdi); + + STRUCT_INIT(gdi, get_udatamodel()); + + if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi), + mode) != 0) { + return (EFAULT); + } + + /* Find out how many targets there are. */ + mutex_enter(&mpt->m_mutex); + ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl, + MPTSAS_HASH_FIRST); + while (ptgt != NULL) { + count++; + ptgt = (mptsas_target_t *)mptsas_hash_traverse( + &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT); + } + mutex_exit(&mpt->m_mutex); + + /* + * If we haven't been asked to copy out information on each target, + * then just return the count. + */ + STRUCT_FSET(gdi, DiskCount, count); + if (STRUCT_FGETP(gdi, PtrDiskInfoArray) == NULL) + goto copy_out; + + /* + * If we haven't been given a large enough buffer to copy out into, + * let the caller know. + */ + if (STRUCT_FGET(gdi, DiskInfoArraySize) < + count * sizeof (mptsas_disk_info_t)) { + ret = ENOSPC; + goto copy_out; + } + + di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP); + + mutex_enter(&mpt->m_mutex); + ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl, + MPTSAS_HASH_FIRST); + while (ptgt != NULL) { + if (i >= count) { + /* + * The number of targets changed while we weren't + * looking, so give up. + */ + mutex_exit(&mpt->m_mutex); + kmem_free(di, count * sizeof (mptsas_disk_info_t)); + return (EAGAIN); + } + di[i].Instance = mpt->m_instance; + di[i].Enclosure = ptgt->m_enclosure; + di[i].Slot = ptgt->m_slot_num; + di[i].SasAddress = ptgt->m_sas_wwn; + + ptgt = (mptsas_target_t *)mptsas_hash_traverse( + &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT); + i++; + } + mutex_exit(&mpt->m_mutex); + STRUCT_FSET(gdi, DiskCount, i); + + /* Copy out the disk information to the caller. */ + if (ddi_copyout((void *)di, STRUCT_FGETP(gdi, PtrDiskInfoArray), + i * sizeof (mptsas_disk_info_t), mode) != 0) { + ret = EFAULT; + } + + kmem_free(di, count * sizeof (mptsas_disk_info_t)); + + copy_out: + if (ddi_copyout(STRUCT_BUF(gdi), (void *)data, STRUCT_SIZE(gdi), + mode) != 0) { + ret = EFAULT; + } + + return (ret); + } + + static int mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, int *rval) { int status = 0; mptsas_t *mpt;
*** 12069,12078 **** --- 12161,12173 ---- ndi_dc_freehdl(dcp); } goto out; } switch (cmd) { + case MPTIOCTL_GET_DISK_INFO: + status = get_disk_info(mpt, data, mode); + break; case MPTIOCTL_UPDATE_FLASH: if (ddi_copyin((void *)data, &flashdata, sizeof (struct mptsas_update_flash), mode)) { status = EFAULT; break;