Print this page
LOCAL: mpt_sas: expose drive ID via ioctl


   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.


 352     uint8_t phy);
 353 static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt, int phymask,
 354     uint64_t wwid);
 355 static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt, int phymask,
 356     uint64_t wwid);
 357 
 358 static int mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun,
 359     uchar_t page, unsigned char *buf, int len, int *rlen, uchar_t evpd);
 360 
 361 static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
 362     uint16_t *handle, mptsas_target_t **pptgt);
 363 static void mptsas_update_phymask(mptsas_t *mpt);
 364 static inline void mptsas_remove_cmd0(mptsas_t *mpt, mptsas_cmd_t *cmd);
 365 
 366 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
 367     uint32_t *status, uint8_t cmd);
 368 static dev_info_t *mptsas_get_dip_from_dev(dev_t dev,
 369     mptsas_phymask_t *phymask);
 370 static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr,
 371     mptsas_phymask_t phymask);
 372 static int mptsas_set_led_status(mptsas_t *mpt, mptsas_target_t *ptgt,
 373     uint32_t slotstatus);
 374 
 375 
 376 /*
 377  * Enumeration / DR functions
 378  */
 379 static void mptsas_config_all(dev_info_t *pdip);
 380 static int mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
 381     dev_info_t **lundip);
 382 static int mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
 383     dev_info_t **lundip);
 384 
 385 static int mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt);
 386 static int mptsas_offline_target(dev_info_t *pdip, char *name);
 387 
 388 static int mptsas_config_raid(dev_info_t *pdip, uint16_t target,
 389     dev_info_t **dip);
 390 
 391 static int mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt);
 392 static int mptsas_probe_lun(dev_info_t *pdip, int lun,
 393     dev_info_t **dip, mptsas_target_t *ptgt);


1072 
1073         instance = ddi_get_instance(dip);
1074 
1075         /*
1076          * Allocate softc information.
1077          */
1078         if (ddi_soft_state_zalloc(mptsas_state, instance) != DDI_SUCCESS) {
1079                 mptsas_log(NULL, CE_WARN,
1080                     "mptsas%d: cannot allocate soft state", instance);
1081                 goto fail;
1082         }
1083 
1084         mpt = ddi_get_soft_state(mptsas_state, instance);
1085 
1086         if (mpt == NULL) {
1087                 mptsas_log(NULL, CE_WARN,
1088                     "mptsas%d: cannot get soft state", instance);
1089                 goto fail;
1090         }
1091 




1092         /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
1093         scsi_size_clean(dip);
1094 
1095         mpt->m_dip = dip;
1096         mpt->m_instance = instance;
1097 
1098         /* Make a per-instance copy of the structures */
1099         mpt->m_io_dma_attr = mptsas_dma_attrs64;
1100         mpt->m_msg_dma_attr = mptsas_dma_attrs;
1101         mpt->m_reg_acc_attr = mptsas_dev_attr;
1102         mpt->m_dev_acc_attr = mptsas_dev_attr;
1103 
1104         /*
1105          * Initialize FMA
1106          */
1107         mpt->m_fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, mpt->m_dip,
1108             DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
1109             DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
1110             DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
1111 


6434                             MPTSAS_NUM_PHYS, 0) !=
6435                             DDI_PROP_SUCCESS) {
6436                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6437                                     MPTSAS_NUM_PHYS);
6438                                 mptsas_log(mpt, CE_WARN, "mptsas num phys "
6439                                     "prop update failed");
6440                                 break;
6441                         }
6442                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6443                             MPTSAS_VIRTUAL_PORT, 1) !=
6444                             DDI_PROP_SUCCESS) {
6445                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6446                                     MPTSAS_VIRTUAL_PORT);
6447                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6448                                     "prop update failed");
6449                                 break;
6450                         }
6451                 }
6452 
6453                 mutex_enter(&mpt->m_mutex);
6454                 if (mptsas_set_led_status(mpt, ptgt, 0) != DDI_SUCCESS) {

6455                         NDBG14(("mptsas: clear LED for tgt %x failed",
6456                             ptgt->m_slot_num));
6457                 }
6458                 if (rval == DDI_SUCCESS) {
6459                         mptsas_tgt_free(&mpt->m_active->m_tgttbl,
6460                             ptgt->m_sas_wwn, ptgt->m_phymask);
6461                         ptgt = NULL;
6462                 } else {
6463                         /*
6464                          * clean DR_INTRANSITION flag to allow I/O down to
6465                          * PHCI driver since failover finished.
6466                          * Invalidate the devhdl
6467                          */
6468                         mutex_enter(&ptgt->m_tgt_intr_mutex);
6469                         ptgt->m_devhdl = MPTSAS_INVALID_DEVHDL;
6470                         ptgt->m_tgt_unconfigured = 0;
6471                         ptgt->m_dr_flag = MPTSAS_DR_INACTIVE;
6472                         mutex_exit(&ptgt->m_tgt_intr_mutex);
6473                 }
6474 


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;


12020                 if ((cmd == DEVCTL_DEVICE_ONLINE) ||
12021                     (cmd == DEVCTL_DEVICE_OFFLINE)) {
12022                         if (ndi_dc_allochdl((void *)data, &dcp) !=
12023                             NDI_SUCCESS) {
12024                                 goto out;
12025                         }
12026                         addr = ndi_dc_getaddr(dcp);
12027                         ptgt = mptsas_addr_to_ptgt(mpt, addr, phymask);
12028                         if (ptgt == NULL) {
12029                                 NDBG14(("mptsas_ioctl led control: tgt %s not "
12030                                     "found", addr));
12031                                 ndi_dc_freehdl(dcp);
12032                                 goto out;
12033                         }
12034                         mutex_enter(&mpt->m_mutex);
12035                         if (cmd == DEVCTL_DEVICE_ONLINE) {
12036                                 ptgt->m_tgt_unconfigured = 0;
12037                         } else if (cmd == DEVCTL_DEVICE_OFFLINE) {
12038                                 ptgt->m_tgt_unconfigured = 1;
12039                         }
12040                         slotstatus = 0;
12041 #ifdef MPTSAS_GET_LED
12042                         /*
12043                          * The get led status can't get a valid/reasonable
12044                          * state, so ignore the get led status, and write the
12045                          * required value directly
12046                          */
12047                         if (mptsas_get_led_status(mpt, ptgt, &slotstatus) !=
12048                             DDI_SUCCESS) {
12049                                 NDBG14(("mptsas_ioctl: get LED for tgt %s "
12050                                     "failed %x", addr, slotstatus));
12051                                 slotstatus = 0;
12052                         }
12053                         NDBG14(("mptsas_ioctl: LED status %x for %s",
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) {


14514         } else {
14515                 *pip = mptsas_find_path_phy(pdip, phy);
14516         }
14517 
14518         if (*pip != NULL) {
14519                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14520                 ASSERT(*lun_dip != NULL);
14521                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, *lun_dip,
14522                     (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
14523                     MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
14524                         if (strncmp(guid, old_guid, strlen(guid)) == 0) {
14525                                 /*
14526                                  * Same path back online again.
14527                                  */
14528                                 (void) ddi_prop_free(old_guid);
14529                                 if ((!MDI_PI_IS_ONLINE(*pip)) &&
14530                                     (!MDI_PI_IS_STANDBY(*pip)) &&
14531                                     (ptgt->m_tgt_unconfigured == 0)) {
14532                                         rval = mdi_pi_online(*pip, 0);
14533                                         mutex_enter(&mpt->m_mutex);
14534                                         (void) mptsas_set_led_status(mpt, ptgt,
14535                                             0);

14536                                         mutex_exit(&mpt->m_mutex);
14537                                 } else {
14538                                         rval = DDI_SUCCESS;
14539                                 }
14540                                 if (rval != DDI_SUCCESS) {
14541                                         mptsas_log(mpt, CE_WARN, "path:target: "
14542                                             "%x, lun:%x online failed!", target,
14543                                             lun);
14544                                         *pip = NULL;
14545                                         *lun_dip = NULL;
14546                                 }
14547                                 return (rval);
14548                         } else {
14549                                 /*
14550                                  * The GUID of the LUN has changed which maybe
14551                                  * because customer mapped another volume to the
14552                                  * same LUN.
14553                                  */
14554                                 mptsas_log(mpt, CE_WARN, "The GUID of the "
14555                                     "target:%x, lun:%x was changed, maybe "


14772                                     "property, target %d", target);
14773                                 mdi_rtn = MDI_FAILURE;
14774                                 goto virt_create_done;
14775                         }
14776                 }
14777                 /*
14778                  * Create the phy-num property
14779                  */
14780                 if (mdi_prop_update_int(*pip, "phy-num",
14781                     ptgt->m_phynum) != DDI_SUCCESS) {
14782                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14783                             "create phy-num property for target %d lun %d",
14784                             target, lun);
14785                         mdi_rtn = MDI_FAILURE;
14786                         goto virt_create_done;
14787                 }
14788                 NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr));
14789                 mdi_rtn = mdi_pi_online(*pip, 0);
14790                 if (mdi_rtn == MDI_SUCCESS) {
14791                         mutex_enter(&mpt->m_mutex);
14792                         if (mptsas_set_led_status(mpt, ptgt, 0) !=
14793                             DDI_SUCCESS) {
14794                                 NDBG14(("mptsas: clear LED for slot %x "
14795                                     "failed", ptgt->m_slot_num));
14796                         }
14797                         mutex_exit(&mpt->m_mutex);
14798                 }
14799                 if (mdi_rtn == MDI_NOT_SUPPORTED) {
14800                         mdi_rtn = MDI_FAILURE;
14801                 }
14802 virt_create_done:
14803                 if (*pip && mdi_rtn != MDI_SUCCESS) {
14804                         (void) mdi_pi_free(*pip, 0);
14805                         *pip = NULL;
14806                         *lun_dip = NULL;
14807                 }
14808         }
14809 
14810         scsi_hba_nodename_compatible_free(nodename, compatible);
14811         if (lun_addr != NULL) {
14812                 kmem_free(lun_addr, SCSI_MAXNAMELEN);
14813         }


15134                             DDI_PROP_SUCCESS) {
15135                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
15136                                     "failed to create phy-num property for "
15137                                     "target %d", target);
15138                                 ndi_rtn = NDI_FAILURE;
15139                                 goto phys_create_done;
15140                         }
15141                 }
15142 phys_create_done:
15143                 /*
15144                  * If props were setup ok, online the lun
15145                  */
15146                 if (ndi_rtn == NDI_SUCCESS) {
15147                         /*
15148                          * Try to online the new node
15149                          */
15150                         ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
15151                 }
15152                 if (ndi_rtn == NDI_SUCCESS) {
15153                         mutex_enter(&mpt->m_mutex);
15154                         if (mptsas_set_led_status(mpt, ptgt, 0) !=
15155                             DDI_SUCCESS) {
15156                                 NDBG14(("mptsas: clear LED for tgt %x "
15157                                     "failed", ptgt->m_slot_num));
15158                         }
15159                         mutex_exit(&mpt->m_mutex);
15160                 }
15161 
15162                 /*
15163                  * If success set rtn flag, else unwire alloc'd lun
15164                  */
15165                 if (ndi_rtn != NDI_SUCCESS) {
15166                         NDBG12(("mptsas driver unable to online "
15167                             "target %d lun %d", target, lun));
15168                         ndi_prop_remove_all(*lun_dip);
15169                         (void) ndi_devi_free(*lun_dip);
15170                         *lun_dip = NULL;
15171                 }
15172         }
15173 
15174         scsi_hba_nodename_compatible_free(nodename, compatible);
15175 


16036 }
16037 static mptsas_target_t *
16038 mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
16039 {
16040         uint8_t                 phynum;
16041         uint64_t                wwn;
16042         int                     lun;
16043         mptsas_target_t         *ptgt = NULL;
16044 
16045         if (mptsas_parse_address(addr, &wwn, &phynum, &lun) != DDI_SUCCESS) {
16046                 return (NULL);
16047         }
16048         if (addr[0] == 'w') {
16049                 ptgt = mptsas_wwid_to_ptgt(mpt, (int)phymask, wwn);
16050         } else {
16051                 ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum);
16052         }
16053         return (ptgt);
16054 }
16055 
16056 #ifdef MPTSAS_GET_LED
16057 static int
16058 mptsas_get_led_status(mptsas_t *mpt, mptsas_target_t *ptgt,
16059     uint32_t *slotstatus)
16060 {
16061         return (mptsas_send_sep(mpt, ptgt, slotstatus,
16062             MPI2_SEP_REQ_ACTION_READ_STATUS));
16063 }
16064 #endif
16065 static int
16066 mptsas_set_led_status(mptsas_t *mpt, mptsas_target_t *ptgt, uint32_t slotstatus)
16067 {




16068         NDBG14(("mptsas_ioctl: set LED status %x for slot %x",
16069             slotstatus, ptgt->m_slot_num));
16070         return (mptsas_send_sep(mpt, ptgt, &slotstatus,
16071             MPI2_SEP_REQ_ACTION_WRITE_STATUS));
16072 }

16073 /*
16074  *  send sep request, use enclosure/slot addressing
16075  */
16076 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
16077     uint32_t *status, uint8_t act)
16078 {
16079         Mpi2SepRequest_t        req;
16080         Mpi2SepReply_t          rep;
16081         int                     ret;
16082 
16083         ASSERT(mutex_owned(&mpt->m_mutex));
16084 
16085         bzero(&req, sizeof (req));
16086         bzero(&rep, sizeof (rep));
16087 
16088         /* Do nothing for RAID volumes */
16089         if (ptgt->m_phymask == 0) {
16090                 NDBG14(("mptsas_send_sep: Skip RAID volumes"));
16091                 return (DDI_FAILURE);
16092         }




   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) 2012, 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.


 354     uint8_t phy);
 355 static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt, int phymask,
 356     uint64_t wwid);
 357 static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt, int phymask,
 358     uint64_t wwid);
 359 
 360 static int mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun,
 361     uchar_t page, unsigned char *buf, int len, int *rlen, uchar_t evpd);
 362 
 363 static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
 364     uint16_t *handle, mptsas_target_t **pptgt);
 365 static void mptsas_update_phymask(mptsas_t *mpt);
 366 static inline void mptsas_remove_cmd0(mptsas_t *mpt, mptsas_cmd_t *cmd);
 367 
 368 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
 369     uint32_t *status, uint8_t cmd);
 370 static dev_info_t *mptsas_get_dip_from_dev(dev_t dev,
 371     mptsas_phymask_t *phymask);
 372 static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr,
 373     mptsas_phymask_t phymask);
 374 static int mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt);

 375 
 376 
 377 /*
 378  * Enumeration / DR functions
 379  */
 380 static void mptsas_config_all(dev_info_t *pdip);
 381 static int mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
 382     dev_info_t **lundip);
 383 static int mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
 384     dev_info_t **lundip);
 385 
 386 static int mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt);
 387 static int mptsas_offline_target(dev_info_t *pdip, char *name);
 388 
 389 static int mptsas_config_raid(dev_info_t *pdip, uint16_t target,
 390     dev_info_t **dip);
 391 
 392 static int mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt);
 393 static int mptsas_probe_lun(dev_info_t *pdip, int lun,
 394     dev_info_t **dip, mptsas_target_t *ptgt);


1073 
1074         instance = ddi_get_instance(dip);
1075 
1076         /*
1077          * Allocate softc information.
1078          */
1079         if (ddi_soft_state_zalloc(mptsas_state, instance) != DDI_SUCCESS) {
1080                 mptsas_log(NULL, CE_WARN,
1081                     "mptsas%d: cannot allocate soft state", instance);
1082                 goto fail;
1083         }
1084 
1085         mpt = ddi_get_soft_state(mptsas_state, instance);
1086 
1087         if (mpt == NULL) {
1088                 mptsas_log(NULL, CE_WARN,
1089                     "mptsas%d: cannot get soft state", instance);
1090                 goto fail;
1091         }
1092 
1093         /* Mark us as a primary ioctl node for an instance. */
1094         (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, "primary-ioctl-node",
1095             instance);
1096 
1097         /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
1098         scsi_size_clean(dip);
1099 
1100         mpt->m_dip = dip;
1101         mpt->m_instance = instance;
1102 
1103         /* Make a per-instance copy of the structures */
1104         mpt->m_io_dma_attr = mptsas_dma_attrs64;
1105         mpt->m_msg_dma_attr = mptsas_dma_attrs;
1106         mpt->m_reg_acc_attr = mptsas_dev_attr;
1107         mpt->m_dev_acc_attr = mptsas_dev_attr;
1108 
1109         /*
1110          * Initialize FMA
1111          */
1112         mpt->m_fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, mpt->m_dip,
1113             DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
1114             DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
1115             DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
1116 


6439                             MPTSAS_NUM_PHYS, 0) !=
6440                             DDI_PROP_SUCCESS) {
6441                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6442                                     MPTSAS_NUM_PHYS);
6443                                 mptsas_log(mpt, CE_WARN, "mptsas num phys "
6444                                     "prop update failed");
6445                                 break;
6446                         }
6447                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6448                             MPTSAS_VIRTUAL_PORT, 1) !=
6449                             DDI_PROP_SUCCESS) {
6450                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6451                                     MPTSAS_VIRTUAL_PORT);
6452                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6453                                     "prop update failed");
6454                                 break;
6455                         }
6456                 }
6457 
6458                 mutex_enter(&mpt->m_mutex);
6459                 ptgt->m_led_status = 0;
6460                 if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) {
6461                         NDBG14(("mptsas: clear LED for tgt %x failed",
6462                             ptgt->m_slot_num));
6463                 }
6464                 if (rval == DDI_SUCCESS) {
6465                         mptsas_tgt_free(&mpt->m_active->m_tgttbl,
6466                             ptgt->m_sas_wwn, ptgt->m_phymask);
6467                         ptgt = NULL;
6468                 } else {
6469                         /*
6470                          * clean DR_INTRANSITION flag to allow I/O down to
6471                          * PHCI driver since failover finished.
6472                          * Invalidate the devhdl
6473                          */
6474                         mutex_enter(&ptgt->m_tgt_intr_mutex);
6475                         ptgt->m_devhdl = MPTSAS_INVALID_DEVHDL;
6476                         ptgt->m_tgt_unconfigured = 0;
6477                         ptgt->m_dr_flag = MPTSAS_DR_INACTIVE;
6478                         mutex_exit(&ptgt->m_tgt_intr_mutex);
6479                 }
6480 


11940                         case REG_MEM_WRITE:
11941                                 ddi_put32(mpt->m_datap,
11942                                     (uint32_t *)(void *)mpt->m_reg +
11943                                     driverdata.RegOffset,
11944                                     driverdata.RegData);
11945                                 break;
11946 
11947                         default:
11948                                 status = EINVAL;
11949                                 break;
11950                 }
11951         } else {
11952                 status = EFAULT;
11953         }
11954 
11955         mutex_exit(&mpt->m_mutex);
11956         return (status);
11957 }
11958 
11959 static int
11960 led_control(mptsas_t *mpt, intptr_t data, int mode)
11961 {
11962         int ret = 0;
11963         mptsas_led_control_t lc;
11964         mptsas_target_t *ptgt;
11965 
11966         if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) {
11967                 return (EFAULT);
11968         }
11969 
11970         if ((lc.Command != MPTSAS_LEDCTL_FLAG_SET &&
11971             lc.Command != MPTSAS_LEDCTL_FLAG_GET) ||
11972             lc.Led < MPTSAS_LEDCTL_LED_IDENT ||
11973             lc.Led > MPTSAS_LEDCTL_LED_OK2RM) {
11974                 return (EINVAL);
11975         }
11976 
11977         /* Locate the target we're interrogating... */
11978         mutex_enter(&mpt->m_mutex);
11979         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
11980             MPTSAS_HASH_FIRST);
11981         while (ptgt != NULL) {
11982                 if (ptgt->m_enclosure == lc.Enclosure &&
11983                     ptgt->m_slot_num == lc.Slot) {
11984                         break;
11985                 }
11986                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
11987                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
11988         }
11989         if (ptgt == NULL) {
11990                 /* We could not find a target for that enclosure/slot. */
11991                 mutex_exit(&mpt->m_mutex);
11992                 return (ENOENT);
11993         }
11994 
11995         if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) {
11996                 /* Update our internal LED state. */
11997                 ptgt->m_led_status &= ~(1 << (lc.Led - 1));
11998                 ptgt->m_led_status |= (!!lc.LedStatus) << (lc.Led - 1);
11999 
12000                 /* Flush it to the controller. */
12001                 ret = mptsas_flush_led_status(mpt, ptgt);
12002                 mutex_exit(&mpt->m_mutex);
12003                 return (ret);
12004         }
12005 
12006         /* Return our internal LED state. */
12007         lc.LedStatus = !!(ptgt->m_led_status & (1 << (lc.Led - 1)));
12008         mutex_exit(&mpt->m_mutex);
12009 
12010         if (ddi_copyout(&lc, (void *)data, sizeof (lc), mode) != 0) {
12011                 return (EFAULT);
12012         }
12013 
12014         return (0);
12015 }
12016 
12017 static int
12018 get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
12019 {
12020         int i;
12021         int count = 0;
12022         int ret = 0;
12023         mptsas_target_t *ptgt;
12024         mptsas_disk_info_t *di;
12025         STRUCT_DECL(mptsas_get_disk_info, gdi);
12026 
12027         STRUCT_INIT(gdi, get_udatamodel());
12028 
12029         if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi),
12030             mode) != 0) {
12031                 return (EFAULT);
12032         }
12033 
12034 restart:
12035         /* Find out how many targets there are. */
12036         mutex_enter(&mpt->m_mutex);
12037         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
12038             MPTSAS_HASH_FIRST);
12039         while (ptgt != NULL) {
12040                 count++;
12041                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
12042                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
12043         }
12044         mutex_exit(&mpt->m_mutex);
12045 
12046         /*
12047          * If we haven't been asked to copy out information on each target,
12048          * then just return the count.
12049          */
12050         STRUCT_FSET(gdi, DiskCount, count);
12051         if (STRUCT_FGETP(gdi, PtrDiskInfoArray) == NULL)
12052                 goto copy_out;
12053 
12054         /*
12055          * If we haven't been given a large enough buffer to copy out into,
12056          * let the caller know.
12057          */
12058         if (STRUCT_FGET(gdi, DiskInfoArraySize) <
12059             count * sizeof (mptsas_disk_info_t)) {
12060                 ret = ENOSPC;
12061                 goto copy_out;
12062         }
12063 
12064         di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP);
12065 
12066         mutex_enter(&mpt->m_mutex);
12067         i = 0;
12068         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
12069             MPTSAS_HASH_FIRST);
12070         while (ptgt != NULL) {
12071                 if (i >= count) {
12072                         /*
12073                          * The number of targets changed while we weren't
12074                          * looking.  Go again.
12075                          */
12076                         mutex_exit(&mpt->m_mutex);
12077                         kmem_free(di, count * sizeof (mptsas_disk_info_t));
12078                         goto restart;
12079                 }
12080                 di[i].Instance = mpt->m_instance;
12081                 di[i].Enclosure = ptgt->m_enclosure;
12082                 di[i].Slot = ptgt->m_slot_num;
12083                 di[i].SasAddress = ptgt->m_sas_wwn;
12084 
12085                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
12086                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
12087                 i++;
12088         }
12089         mutex_exit(&mpt->m_mutex);
12090         STRUCT_FSET(gdi, DiskCount, i);
12091 
12092         /* Copy out the disk information to the caller. */
12093         if (ddi_copyout((void *)di, STRUCT_FGETP(gdi, PtrDiskInfoArray),
12094             i * sizeof (mptsas_disk_info_t), mode) != 0) {
12095                 ret = EFAULT;
12096         }
12097 
12098         kmem_free(di, count * sizeof (mptsas_disk_info_t));
12099 
12100 copy_out:
12101         if (ddi_copyout(STRUCT_BUF(gdi), (void *)data, STRUCT_SIZE(gdi),
12102             mode) != 0) {
12103                 ret = EFAULT;
12104         }
12105 
12106         return (ret);
12107 }
12108 
12109 static int
12110 mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
12111     int *rval)
12112 {
12113         int                     status = 0;
12114         mptsas_t                *mpt;
12115         mptsas_update_flash_t   flashdata;
12116         mptsas_pass_thru_t      passthru_data;
12117         mptsas_adapter_data_t   adapter_data;
12118         mptsas_pci_info_t       pci_info;
12119         int                     copylen;
12120 
12121         int                     iport_flag = 0;
12122         dev_info_t              *dip = NULL;
12123         mptsas_phymask_t        phymask = 0;
12124         struct devctl_iocdata   *dcp = NULL;
12125         uint32_t                slotstatus = 0;
12126         char                    *addr = NULL;
12127         mptsas_target_t         *ptgt = NULL;
12128 
12129         *rval = MPTIOCTL_STATUS_GOOD;


12176                 if ((cmd == DEVCTL_DEVICE_ONLINE) ||
12177                     (cmd == DEVCTL_DEVICE_OFFLINE)) {
12178                         if (ndi_dc_allochdl((void *)data, &dcp) !=
12179                             NDI_SUCCESS) {
12180                                 goto out;
12181                         }
12182                         addr = ndi_dc_getaddr(dcp);
12183                         ptgt = mptsas_addr_to_ptgt(mpt, addr, phymask);
12184                         if (ptgt == NULL) {
12185                                 NDBG14(("mptsas_ioctl led control: tgt %s not "
12186                                     "found", addr));
12187                                 ndi_dc_freehdl(dcp);
12188                                 goto out;
12189                         }
12190                         mutex_enter(&mpt->m_mutex);
12191                         if (cmd == DEVCTL_DEVICE_ONLINE) {
12192                                 ptgt->m_tgt_unconfigured = 0;
12193                         } else if (cmd == DEVCTL_DEVICE_OFFLINE) {
12194                                 ptgt->m_tgt_unconfigured = 1;
12195                         }
















12196                         if (cmd == DEVCTL_DEVICE_OFFLINE) {
12197                                 ptgt->m_led_status |=
12198                                     (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
12199                         } else {
12200                                 ptgt->m_led_status &=
12201                                     ~(1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
12202                         }
12203                         if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) {

12204                                 NDBG14(("mptsas_ioctl: set LED for tgt %s "
12205                                     "failed %x", addr, slotstatus));
12206                         }
12207                         mutex_exit(&mpt->m_mutex);
12208                         ndi_dc_freehdl(dcp);
12209                 }
12210                 goto out;
12211         }
12212         switch (cmd) {
12213                 case MPTIOCTL_GET_DISK_INFO:
12214                         status = get_disk_info(mpt, data, mode);
12215                         break;
12216                 case MPTIOCTL_LED_CONTROL:
12217                         status = led_control(mpt, data, mode);
12218                         break;
12219                 case MPTIOCTL_UPDATE_FLASH:
12220                         if (ddi_copyin((void *)data, &flashdata,
12221                                 sizeof (struct mptsas_update_flash), mode)) {
12222                                 status = EFAULT;
12223                                 break;
12224                         }
12225 
12226                         mutex_enter(&mpt->m_mutex);
12227                         if (mptsas_update_flash(mpt,
12228                             (caddr_t)(long)flashdata.PtrBuffer,
12229                             flashdata.ImageSize, flashdata.ImageType, mode)) {
12230                                 status = EFAULT;
12231                         }
12232 
12233                         /*
12234                          * Reset the chip to start using the new
12235                          * firmware.  Reset if failed also.
12236                          */
12237                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
12238                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {


14659         } else {
14660                 *pip = mptsas_find_path_phy(pdip, phy);
14661         }
14662 
14663         if (*pip != NULL) {
14664                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14665                 ASSERT(*lun_dip != NULL);
14666                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, *lun_dip,
14667                     (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
14668                     MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
14669                         if (strncmp(guid, old_guid, strlen(guid)) == 0) {
14670                                 /*
14671                                  * Same path back online again.
14672                                  */
14673                                 (void) ddi_prop_free(old_guid);
14674                                 if ((!MDI_PI_IS_ONLINE(*pip)) &&
14675                                     (!MDI_PI_IS_STANDBY(*pip)) &&
14676                                     (ptgt->m_tgt_unconfigured == 0)) {
14677                                         rval = mdi_pi_online(*pip, 0);
14678                                         mutex_enter(&mpt->m_mutex);
14679                                         ptgt->m_led_status = 0;
14680                                         (void) mptsas_flush_led_status(mpt,
14681                                             ptgt);
14682                                         mutex_exit(&mpt->m_mutex);
14683                                 } else {
14684                                         rval = DDI_SUCCESS;
14685                                 }
14686                                 if (rval != DDI_SUCCESS) {
14687                                         mptsas_log(mpt, CE_WARN, "path:target: "
14688                                             "%x, lun:%x online failed!", target,
14689                                             lun);
14690                                         *pip = NULL;
14691                                         *lun_dip = NULL;
14692                                 }
14693                                 return (rval);
14694                         } else {
14695                                 /*
14696                                  * The GUID of the LUN has changed which maybe
14697                                  * because customer mapped another volume to the
14698                                  * same LUN.
14699                                  */
14700                                 mptsas_log(mpt, CE_WARN, "The GUID of the "
14701                                     "target:%x, lun:%x was changed, maybe "


14918                                     "property, target %d", target);
14919                                 mdi_rtn = MDI_FAILURE;
14920                                 goto virt_create_done;
14921                         }
14922                 }
14923                 /*
14924                  * Create the phy-num property
14925                  */
14926                 if (mdi_prop_update_int(*pip, "phy-num",
14927                     ptgt->m_phynum) != DDI_SUCCESS) {
14928                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14929                             "create phy-num property for target %d lun %d",
14930                             target, lun);
14931                         mdi_rtn = MDI_FAILURE;
14932                         goto virt_create_done;
14933                 }
14934                 NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr));
14935                 mdi_rtn = mdi_pi_online(*pip, 0);
14936                 if (mdi_rtn == MDI_SUCCESS) {
14937                         mutex_enter(&mpt->m_mutex);
14938                         ptgt->m_led_status = 0;
14939                         if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) {
14940                                 NDBG14(("mptsas: clear LED for slot %x "
14941                                     "failed", ptgt->m_slot_num));
14942                         }
14943                         mutex_exit(&mpt->m_mutex);
14944                 }
14945                 if (mdi_rtn == MDI_NOT_SUPPORTED) {
14946                         mdi_rtn = MDI_FAILURE;
14947                 }
14948 virt_create_done:
14949                 if (*pip && mdi_rtn != MDI_SUCCESS) {
14950                         (void) mdi_pi_free(*pip, 0);
14951                         *pip = NULL;
14952                         *lun_dip = NULL;
14953                 }
14954         }
14955 
14956         scsi_hba_nodename_compatible_free(nodename, compatible);
14957         if (lun_addr != NULL) {
14958                 kmem_free(lun_addr, SCSI_MAXNAMELEN);
14959         }


15280                             DDI_PROP_SUCCESS) {
15281                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
15282                                     "failed to create phy-num property for "
15283                                     "target %d", target);
15284                                 ndi_rtn = NDI_FAILURE;
15285                                 goto phys_create_done;
15286                         }
15287                 }
15288 phys_create_done:
15289                 /*
15290                  * If props were setup ok, online the lun
15291                  */
15292                 if (ndi_rtn == NDI_SUCCESS) {
15293                         /*
15294                          * Try to online the new node
15295                          */
15296                         ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
15297                 }
15298                 if (ndi_rtn == NDI_SUCCESS) {
15299                         mutex_enter(&mpt->m_mutex);
15300                         ptgt->m_led_status = 0;
15301                         if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) {
15302                                 NDBG14(("mptsas: clear LED for tgt %x "
15303                                     "failed", ptgt->m_slot_num));
15304                         }
15305                         mutex_exit(&mpt->m_mutex);
15306                 }
15307 
15308                 /*
15309                  * If success set rtn flag, else unwire alloc'd lun
15310                  */
15311                 if (ndi_rtn != NDI_SUCCESS) {
15312                         NDBG12(("mptsas driver unable to online "
15313                             "target %d lun %d", target, lun));
15314                         ndi_prop_remove_all(*lun_dip);
15315                         (void) ndi_devi_free(*lun_dip);
15316                         *lun_dip = NULL;
15317                 }
15318         }
15319 
15320         scsi_hba_nodename_compatible_free(nodename, compatible);
15321 


16182 }
16183 static mptsas_target_t *
16184 mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
16185 {
16186         uint8_t                 phynum;
16187         uint64_t                wwn;
16188         int                     lun;
16189         mptsas_target_t         *ptgt = NULL;
16190 
16191         if (mptsas_parse_address(addr, &wwn, &phynum, &lun) != DDI_SUCCESS) {
16192                 return (NULL);
16193         }
16194         if (addr[0] == 'w') {
16195                 ptgt = mptsas_wwid_to_ptgt(mpt, (int)phymask, wwn);
16196         } else {
16197                 ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum);
16198         }
16199         return (ptgt);
16200 }
16201 

16202 static int
16203 mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt)

16204 {
16205         uint32_t slotstatus = 0;
16206 
16207         /* Build an MPI2 Slot Status based on our view of the world */
16208         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_IDENT - 1)))
16209                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST;
16210         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_FAIL - 1)))
16211                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT;
16212         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1)))
16213                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
16214 
16215         /* Write it to the controller */
16216         NDBG14(("mptsas_ioctl: set LED status %x for slot %x",
16217             slotstatus, ptgt->m_slot_num));
16218         return (mptsas_send_sep(mpt, ptgt, &slotstatus,
16219             MPI2_SEP_REQ_ACTION_WRITE_STATUS));
16220 }
16221 
16222 /*
16223  *  send sep request, use enclosure/slot addressing
16224  */
16225 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
16226     uint32_t *status, uint8_t act)
16227 {
16228         Mpi2SepRequest_t        req;
16229         Mpi2SepReply_t          rep;
16230         int                     ret;
16231 
16232         ASSERT(mutex_owned(&mpt->m_mutex));
16233 
16234         bzero(&req, sizeof (req));
16235         bzero(&rep, sizeof (rep));
16236 
16237         /* Do nothing for RAID volumes */
16238         if (ptgt->m_phymask == 0) {
16239                 NDBG14(("mptsas_send_sep: Skip RAID volumes"));
16240                 return (DDI_FAILURE);
16241         }