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


   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.

  25  */
  26 
  27 /*
  28  * Copyright (c) 2000 to 2010, LSI Corporation.
  29  * All rights reserved.
  30  *
  31  * Redistribution and use in source and binary forms of all code within
  32  * this file that is exclusively owned by LSI, with or without
  33  * modification, is permitted provided that, in addition to the CDDL 1.0
  34  * License requirements, the following conditions are met:
  35  *
  36  *    Neither the name of the author nor the names of its contributors may be
  37  *    used to endorse or promote products derived from this software without
  38  *    specific prior written permission.
  39  *
  40  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  41  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  42  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  43  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  44  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,


  52  */
  53 
  54 /*
  55  * mptsas - This is a driver based on LSI Logic's MPT2.0 interface.
  56  *
  57  */
  58 
  59 #if defined(lint) || defined(DEBUG)
  60 #define MPTSAS_DEBUG
  61 #endif
  62 
  63 /*
  64  * standard header files.
  65  */
  66 #include <sys/note.h>
  67 #include <sys/scsi/scsi.h>
  68 #include <sys/pci.h>
  69 #include <sys/file.h>
  70 #include <sys/cpuvar.h>
  71 #include <sys/policy.h>

  72 #include <sys/sysevent.h>
  73 #include <sys/sysevent/eventdefs.h>
  74 #include <sys/sysevent/dr.h>
  75 #include <sys/sata/sata_defs.h>
  76 #include <sys/scsi/generic/sas.h>
  77 #include <sys/scsi/impl/scsi_sas.h>
  78 
  79 #pragma pack(1)
  80 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
  81 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
  82 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
  83 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
  84 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
  85 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
  86 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
  87 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
  88 #pragma pack()
  89 
  90 /*
  91  * private header files.


11934                         case REG_MEM_WRITE:
11935                                 ddi_put32(mpt->m_datap,
11936                                     (uint32_t *)(void *)mpt->m_reg +
11937                                     driverdata.RegOffset,
11938                                     driverdata.RegData);
11939                                 break;
11940 
11941                         default:
11942                                 status = EINVAL;
11943                                 break;
11944                 }
11945         } else {
11946                 status = EFAULT;
11947         }
11948 
11949         mutex_exit(&mpt->m_mutex);
11950         return (status);
11951 }
11952 
11953 static int


























































































11954 mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
11955     int *rval)
11956 {
11957         int                     status = 0;
11958         mptsas_t                *mpt;
11959         mptsas_update_flash_t   flashdata;
11960         mptsas_pass_thru_t      passthru_data;
11961         mptsas_adapter_data_t   adapter_data;
11962         mptsas_pci_info_t       pci_info;
11963         int                     copylen;
11964 
11965         int                     iport_flag = 0;
11966         dev_info_t              *dip = NULL;
11967         mptsas_phymask_t        phymask = 0;
11968         struct devctl_iocdata   *dcp = NULL;
11969         uint32_t                slotstatus = 0;
11970         char                    *addr = NULL;
11971         mptsas_target_t         *ptgt = NULL;
11972 
11973         *rval = MPTIOCTL_STATUS_GOOD;


12054                             slotstatus, addr));
12055 #endif
12056                         if (cmd == DEVCTL_DEVICE_OFFLINE) {
12057                                 slotstatus |=
12058                                     MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
12059                         } else {
12060                                 slotstatus &=
12061                                     ~MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
12062                         }
12063                         if (mptsas_set_led_status(mpt, ptgt, slotstatus) !=
12064                             DDI_SUCCESS) {
12065                                 NDBG14(("mptsas_ioctl: set LED for tgt %s "
12066                                     "failed %x", addr, slotstatus));
12067                         }
12068                         mutex_exit(&mpt->m_mutex);
12069                         ndi_dc_freehdl(dcp);
12070                 }
12071                 goto out;
12072         }
12073         switch (cmd) {



12074                 case MPTIOCTL_UPDATE_FLASH:
12075                         if (ddi_copyin((void *)data, &flashdata,
12076                                 sizeof (struct mptsas_update_flash), mode)) {
12077                                 status = EFAULT;
12078                                 break;
12079                         }
12080 
12081                         mutex_enter(&mpt->m_mutex);
12082                         if (mptsas_update_flash(mpt,
12083                             (caddr_t)(long)flashdata.PtrBuffer,
12084                             flashdata.ImageSize, flashdata.ImageType, mode)) {
12085                                 status = EFAULT;
12086                         }
12087 
12088                         /*
12089                          * Reset the chip to start using the new
12090                          * firmware.  Reset if failed also.
12091                          */
12092                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
12093                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {




   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  26  */
  27 
  28 /*
  29  * Copyright (c) 2000 to 2010, LSI Corporation.
  30  * All rights reserved.
  31  *
  32  * Redistribution and use in source and binary forms of all code within
  33  * this file that is exclusively owned by LSI, with or without
  34  * modification, is permitted provided that, in addition to the CDDL 1.0
  35  * License requirements, the following conditions are met:
  36  *
  37  *    Neither the name of the author nor the names of its contributors may be
  38  *    used to endorse or promote products derived from this software without
  39  *    specific prior written permission.
  40  *
  41  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  42  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  43  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  44  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  45  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,


  53  */
  54 
  55 /*
  56  * mptsas - This is a driver based on LSI Logic's MPT2.0 interface.
  57  *
  58  */
  59 
  60 #if defined(lint) || defined(DEBUG)
  61 #define MPTSAS_DEBUG
  62 #endif
  63 
  64 /*
  65  * standard header files.
  66  */
  67 #include <sys/note.h>
  68 #include <sys/scsi/scsi.h>
  69 #include <sys/pci.h>
  70 #include <sys/file.h>
  71 #include <sys/cpuvar.h>
  72 #include <sys/policy.h>
  73 #include <sys/model.h>
  74 #include <sys/sysevent.h>
  75 #include <sys/sysevent/eventdefs.h>
  76 #include <sys/sysevent/dr.h>
  77 #include <sys/sata/sata_defs.h>
  78 #include <sys/scsi/generic/sas.h>
  79 #include <sys/scsi/impl/scsi_sas.h>
  80 
  81 #pragma pack(1)
  82 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
  83 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
  84 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
  85 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
  86 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
  87 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
  88 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
  89 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
  90 #pragma pack()
  91 
  92 /*
  93  * private header files.


11936                         case REG_MEM_WRITE:
11937                                 ddi_put32(mpt->m_datap,
11938                                     (uint32_t *)(void *)mpt->m_reg +
11939                                     driverdata.RegOffset,
11940                                     driverdata.RegData);
11941                                 break;
11942 
11943                         default:
11944                                 status = EINVAL;
11945                                 break;
11946                 }
11947         } else {
11948                 status = EFAULT;
11949         }
11950 
11951         mutex_exit(&mpt->m_mutex);
11952         return (status);
11953 }
11954 
11955 static int
11956 get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
11957 {
11958         int i = 0;
11959         int count = 0;
11960         int ret = 0;
11961         mptsas_target_t *ptgt;
11962         mptsas_disk_info_t *di;
11963         STRUCT_DECL(mptsas_get_disk_info, gdi);
11964 
11965         STRUCT_INIT(gdi, get_udatamodel());
11966 
11967         if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi),
11968             mode) != 0) {
11969                 return (EFAULT);
11970         }
11971 
11972         /* Find out how many targets there are. */
11973         mutex_enter(&mpt->m_mutex);
11974         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
11975             MPTSAS_HASH_FIRST);
11976         while (ptgt != NULL) {
11977                 count++;
11978                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
11979                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
11980         }
11981         mutex_exit(&mpt->m_mutex);
11982 
11983         /*
11984          * If we haven't been asked to copy out information on each target,
11985          * then just return the count.
11986          */
11987         STRUCT_FSET(gdi, DiskCount, count);
11988         if (STRUCT_FGETP(gdi, PtrDiskInfoArray) == NULL)
11989                 goto copy_out;
11990 
11991         /*
11992          * If we haven't been given a large enough buffer to copy out into,
11993          * let the caller know.
11994          */
11995         if (STRUCT_FGET(gdi, DiskInfoArraySize) <
11996             count * sizeof (mptsas_disk_info_t)) {
11997                 ret = ENOSPC;
11998                 goto copy_out;
11999         }
12000 
12001         di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP);
12002 
12003         mutex_enter(&mpt->m_mutex);
12004         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
12005             MPTSAS_HASH_FIRST);
12006         while (ptgt != NULL) {
12007                 if (i >= count) {
12008                         /*
12009                          * The number of targets changed while we weren't
12010                          * looking, so give up.
12011                          */
12012                         mutex_exit(&mpt->m_mutex);
12013                         kmem_free(di, count * sizeof (mptsas_disk_info_t));
12014                         return (EAGAIN);
12015                 }
12016                 di[i].Instance = mpt->m_instance;
12017                 di[i].Enclosure = ptgt->m_enclosure;
12018                 di[i].Slot = ptgt->m_slot_num;
12019                 di[i].SasAddress = ptgt->m_sas_wwn;
12020 
12021                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
12022                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
12023                 i++;
12024         }
12025         mutex_exit(&mpt->m_mutex);
12026         STRUCT_FSET(gdi, DiskCount, i);
12027 
12028         /* Copy out the disk information to the caller. */
12029         if (ddi_copyout((void *)di, STRUCT_FGETP(gdi, PtrDiskInfoArray),
12030             i * sizeof (mptsas_disk_info_t), mode) != 0) {
12031                 ret = EFAULT;
12032         }
12033 
12034         kmem_free(di, count * sizeof (mptsas_disk_info_t));
12035 
12036 copy_out:
12037         if (ddi_copyout(STRUCT_BUF(gdi), (void *)data, STRUCT_SIZE(gdi),
12038             mode) != 0) {
12039                 ret = EFAULT;
12040         }
12041 
12042         return (ret);
12043 }
12044 
12045 static int
12046 mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
12047     int *rval)
12048 {
12049         int                     status = 0;
12050         mptsas_t                *mpt;
12051         mptsas_update_flash_t   flashdata;
12052         mptsas_pass_thru_t      passthru_data;
12053         mptsas_adapter_data_t   adapter_data;
12054         mptsas_pci_info_t       pci_info;
12055         int                     copylen;
12056 
12057         int                     iport_flag = 0;
12058         dev_info_t              *dip = NULL;
12059         mptsas_phymask_t        phymask = 0;
12060         struct devctl_iocdata   *dcp = NULL;
12061         uint32_t                slotstatus = 0;
12062         char                    *addr = NULL;
12063         mptsas_target_t         *ptgt = NULL;
12064 
12065         *rval = MPTIOCTL_STATUS_GOOD;


12146                             slotstatus, addr));
12147 #endif
12148                         if (cmd == DEVCTL_DEVICE_OFFLINE) {
12149                                 slotstatus |=
12150                                     MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
12151                         } else {
12152                                 slotstatus &=
12153                                     ~MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
12154                         }
12155                         if (mptsas_set_led_status(mpt, ptgt, slotstatus) !=
12156                             DDI_SUCCESS) {
12157                                 NDBG14(("mptsas_ioctl: set LED for tgt %s "
12158                                     "failed %x", addr, slotstatus));
12159                         }
12160                         mutex_exit(&mpt->m_mutex);
12161                         ndi_dc_freehdl(dcp);
12162                 }
12163                 goto out;
12164         }
12165         switch (cmd) {
12166                 case MPTIOCTL_GET_DISK_INFO:
12167                         status = get_disk_info(mpt, data, mode);
12168                         break;
12169                 case MPTIOCTL_UPDATE_FLASH:
12170                         if (ddi_copyin((void *)data, &flashdata,
12171                                 sizeof (struct mptsas_update_flash), mode)) {
12172                                 status = EFAULT;
12173                                 break;
12174                         }
12175 
12176                         mutex_enter(&mpt->m_mutex);
12177                         if (mptsas_update_flash(mpt,
12178                             (caddr_t)(long)flashdata.PtrBuffer,
12179                             flashdata.ImageSize, flashdata.ImageType, mode)) {
12180                                 status = EFAULT;
12181                         }
12182 
12183                         /*
12184                          * Reset the chip to start using the new
12185                          * firmware.  Reset if failed also.
12186                          */
12187                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
12188                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {