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;