Print this page
OS-1997 mpt_sas: expose LED controls to libtopo
Reviewed by: Keith Wesolowski <keith.wesolowski@joyent.com>


 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_set_led_status(mptsas_t *mpt, mptsas_target_t *ptgt,
 375     uint32_t slotstatus);
 376 
 377 
 378 /*
 379  * Enumeration / DR functions
 380  */
 381 static void mptsas_config_all(dev_info_t *pdip);
 382 static int mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
 383     dev_info_t **lundip);
 384 static int mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
 385     dev_info_t **lundip);
 386 
 387 static int mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt);
 388 static int mptsas_offline_target(dev_info_t *pdip, char *name);
 389 
 390 static int mptsas_config_raid(dev_info_t *pdip, uint16_t target,
 391     dev_info_t **dip);
 392 
 393 static int mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt);
 394 static int mptsas_probe_lun(dev_info_t *pdip, int lun,
 395     dev_info_t **dip, mptsas_target_t *ptgt);


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

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


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);


12112                 if ((cmd == DEVCTL_DEVICE_ONLINE) ||
12113                     (cmd == DEVCTL_DEVICE_OFFLINE)) {
12114                         if (ndi_dc_allochdl((void *)data, &dcp) !=
12115                             NDI_SUCCESS) {
12116                                 goto out;
12117                         }
12118                         addr = ndi_dc_getaddr(dcp);
12119                         ptgt = mptsas_addr_to_ptgt(mpt, addr, phymask);
12120                         if (ptgt == NULL) {
12121                                 NDBG14(("mptsas_ioctl led control: tgt %s not "
12122                                     "found", addr));
12123                                 ndi_dc_freehdl(dcp);
12124                                 goto out;
12125                         }
12126                         mutex_enter(&mpt->m_mutex);
12127                         if (cmd == DEVCTL_DEVICE_ONLINE) {
12128                                 ptgt->m_tgt_unconfigured = 0;
12129                         } else if (cmd == DEVCTL_DEVICE_OFFLINE) {
12130                                 ptgt->m_tgt_unconfigured = 1;
12131                         }
12132                         slotstatus = 0;
12133 #ifdef MPTSAS_GET_LED
12134                         /*
12135                          * The get led status can't get a valid/reasonable
12136                          * state, so ignore the get led status, and write the
12137                          * required value directly
12138                          */
12139                         if (mptsas_get_led_status(mpt, ptgt, &slotstatus) !=
12140                             DDI_SUCCESS) {
12141                                 NDBG14(("mptsas_ioctl: get LED for tgt %s "
12142                                     "failed %x", addr, slotstatus));
12143                                 slotstatus = 0;
12144                         }
12145                         NDBG14(("mptsas_ioctl: LED status %x for %s",
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) {


14609         } else {
14610                 *pip = mptsas_find_path_phy(pdip, phy);
14611         }
14612 
14613         if (*pip != NULL) {
14614                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14615                 ASSERT(*lun_dip != NULL);
14616                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, *lun_dip,
14617                     (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
14618                     MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
14619                         if (strncmp(guid, old_guid, strlen(guid)) == 0) {
14620                                 /*
14621                                  * Same path back online again.
14622                                  */
14623                                 (void) ddi_prop_free(old_guid);
14624                                 if ((!MDI_PI_IS_ONLINE(*pip)) &&
14625                                     (!MDI_PI_IS_STANDBY(*pip)) &&
14626                                     (ptgt->m_tgt_unconfigured == 0)) {
14627                                         rval = mdi_pi_online(*pip, 0);
14628                                         mutex_enter(&mpt->m_mutex);
14629                                         (void) mptsas_set_led_status(mpt, ptgt,
14630                                             0);

14631                                         mutex_exit(&mpt->m_mutex);
14632                                 } else {
14633                                         rval = DDI_SUCCESS;
14634                                 }
14635                                 if (rval != DDI_SUCCESS) {
14636                                         mptsas_log(mpt, CE_WARN, "path:target: "
14637                                             "%x, lun:%x online failed!", target,
14638                                             lun);
14639                                         *pip = NULL;
14640                                         *lun_dip = NULL;
14641                                 }
14642                                 return (rval);
14643                         } else {
14644                                 /*
14645                                  * The GUID of the LUN has changed which maybe
14646                                  * because customer mapped another volume to the
14647                                  * same LUN.
14648                                  */
14649                                 mptsas_log(mpt, CE_WARN, "The GUID of the "
14650                                     "target:%x, lun:%x was changed, maybe "


14867                                     "property, target %d", target);
14868                                 mdi_rtn = MDI_FAILURE;
14869                                 goto virt_create_done;
14870                         }
14871                 }
14872                 /*
14873                  * Create the phy-num property
14874                  */
14875                 if (mdi_prop_update_int(*pip, "phy-num",
14876                     ptgt->m_phynum) != DDI_SUCCESS) {
14877                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14878                             "create phy-num property for target %d lun %d",
14879                             target, lun);
14880                         mdi_rtn = MDI_FAILURE;
14881                         goto virt_create_done;
14882                 }
14883                 NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr));
14884                 mdi_rtn = mdi_pi_online(*pip, 0);
14885                 if (mdi_rtn == MDI_SUCCESS) {
14886                         mutex_enter(&mpt->m_mutex);
14887                         if (mptsas_set_led_status(mpt, ptgt, 0) !=
14888                             DDI_SUCCESS) {
14889                                 NDBG14(("mptsas: clear LED for slot %x "
14890                                     "failed", ptgt->m_slot_num));
14891                         }
14892                         mutex_exit(&mpt->m_mutex);
14893                 }
14894                 if (mdi_rtn == MDI_NOT_SUPPORTED) {
14895                         mdi_rtn = MDI_FAILURE;
14896                 }
14897 virt_create_done:
14898                 if (*pip && mdi_rtn != MDI_SUCCESS) {
14899                         (void) mdi_pi_free(*pip, 0);
14900                         *pip = NULL;
14901                         *lun_dip = NULL;
14902                 }
14903         }
14904 
14905         scsi_hba_nodename_compatible_free(nodename, compatible);
14906         if (lun_addr != NULL) {
14907                 kmem_free(lun_addr, SCSI_MAXNAMELEN);
14908         }


15229                             DDI_PROP_SUCCESS) {
15230                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
15231                                     "failed to create phy-num property for "
15232                                     "target %d", target);
15233                                 ndi_rtn = NDI_FAILURE;
15234                                 goto phys_create_done;
15235                         }
15236                 }
15237 phys_create_done:
15238                 /*
15239                  * If props were setup ok, online the lun
15240                  */
15241                 if (ndi_rtn == NDI_SUCCESS) {
15242                         /*
15243                          * Try to online the new node
15244                          */
15245                         ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
15246                 }
15247                 if (ndi_rtn == NDI_SUCCESS) {
15248                         mutex_enter(&mpt->m_mutex);
15249                         if (mptsas_set_led_status(mpt, ptgt, 0) !=
15250                             DDI_SUCCESS) {
15251                                 NDBG14(("mptsas: clear LED for tgt %x "
15252                                     "failed", ptgt->m_slot_num));
15253                         }
15254                         mutex_exit(&mpt->m_mutex);
15255                 }
15256 
15257                 /*
15258                  * If success set rtn flag, else unwire alloc'd lun
15259                  */
15260                 if (ndi_rtn != NDI_SUCCESS) {
15261                         NDBG12(("mptsas driver unable to online "
15262                             "target %d lun %d", target, lun));
15263                         ndi_prop_remove_all(*lun_dip);
15264                         (void) ndi_devi_free(*lun_dip);
15265                         *lun_dip = NULL;
15266                 }
15267         }
15268 
15269         scsi_hba_nodename_compatible_free(nodename, compatible);
15270 


16131 }
16132 static mptsas_target_t *
16133 mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
16134 {
16135         uint8_t                 phynum;
16136         uint64_t                wwn;
16137         int                     lun;
16138         mptsas_target_t         *ptgt = NULL;
16139 
16140         if (mptsas_parse_address(addr, &wwn, &phynum, &lun) != DDI_SUCCESS) {
16141                 return (NULL);
16142         }
16143         if (addr[0] == 'w') {
16144                 ptgt = mptsas_wwid_to_ptgt(mpt, (int)phymask, wwn);
16145         } else {
16146                 ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum);
16147         }
16148         return (ptgt);
16149 }
16150 
16151 #ifdef MPTSAS_GET_LED
16152 static int
16153 mptsas_get_led_status(mptsas_t *mpt, mptsas_target_t *ptgt,
16154     uint32_t *slotstatus)
16155 {
16156         return (mptsas_send_sep(mpt, ptgt, slotstatus,
16157             MPI2_SEP_REQ_ACTION_READ_STATUS));
16158 }
16159 #endif
16160 static int
16161 mptsas_set_led_status(mptsas_t *mpt, mptsas_target_t *ptgt, uint32_t slotstatus)
16162 {











16163         NDBG14(("mptsas_ioctl: set LED status %x for slot %x",
16164             slotstatus, ptgt->m_slot_num));
16165         return (mptsas_send_sep(mpt, ptgt, &slotstatus,
16166             MPI2_SEP_REQ_ACTION_WRITE_STATUS));
16167 }

16168 /*
16169  *  send sep request, use enclosure/slot addressing
16170  */
16171 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
16172     uint32_t *status, uint8_t act)
16173 {
16174         Mpi2SepRequest_t        req;
16175         Mpi2SepReply_t          rep;
16176         int                     ret;
16177 
16178         ASSERT(mutex_owned(&mpt->m_mutex));
16179 
16180         bzero(&req, sizeof (req));
16181         bzero(&rep, sizeof (rep));
16182 
16183         /* Do nothing for RAID volumes */
16184         if (ptgt->m_phymask == 0) {
16185                 NDBG14(("mptsas_send_sep: Skip RAID volumes"));
16186                 return (DDI_FAILURE);
16187         }




 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);


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


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 led_control(mptsas_t *mpt, intptr_t data, int mode)
11957 {
11958         int ret = 0;
11959         mptsas_led_control_t lc;
11960         mptsas_target_t *ptgt;
11961 
11962         if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) {
11963                 return (EFAULT);
11964         }
11965 
11966         if ((lc.Command != MPTSAS_LEDCTL_FLAG_SET &&
11967              lc.Command != MPTSAS_LEDCTL_FLAG_GET) ||
11968              lc.Led < MPTSAS_LEDCTL_LED_IDENT ||
11969              lc.Led > MPTSAS_LEDCTL_LED_OK2RM ||
11970              (lc.Command == MPTSAS_LEDCTL_FLAG_SET && lc.LedStatus != 0 &&
11971              lc.LedStatus != 1)) {
11972                 return (EINVAL);
11973         }
11974 
11975         /* Locate the target we're interrogating... */
11976         mutex_enter(&mpt->m_mutex);
11977         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
11978             MPTSAS_HASH_FIRST);
11979         while (ptgt != NULL) {
11980                 if (ptgt->m_enclosure == lc.Enclosure &&
11981                     ptgt->m_slot_num == lc.Slot) {
11982                         break;
11983                 }
11984                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
11985                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
11986         }
11987         if (ptgt == NULL) {
11988                 /* We could not find a target for that enclosure/slot. */
11989                 mutex_exit(&mpt->m_mutex);
11990                 return (ENOENT);
11991         }
11992 
11993         if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) {
11994                 /* Update our internal LED state. */
11995                 ptgt->m_led_status &= ~(1 << (lc.Led - 1));
11996                 ptgt->m_led_status |= lc.LedStatus << (lc.Led - 1);
11997 
11998                 /* Flush it to the controller. */
11999                 ret = mptsas_flush_led_status(mpt, ptgt);
12000                 mutex_exit(&mpt->m_mutex);
12001                 return (ret);
12002         }
12003 
12004         /* Return our internal LED state. */
12005         lc.LedStatus = (ptgt->m_led_status >> (lc.Led - 1)) & 1;
12006         mutex_exit(&mpt->m_mutex);
12007 
12008         if (ddi_copyout(&lc, (void *)data, sizeof (lc), mode) != 0) {
12009                 return (EFAULT);
12010         }
12011 
12012         return (0);
12013 }
12014 
12015 static int
12016 get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
12017 {
12018         int i = 0;
12019         int count = 0;
12020         int ret = 0;
12021         mptsas_target_t *ptgt;
12022         mptsas_disk_info_t *di;
12023         STRUCT_DECL(mptsas_get_disk_info, gdi);
12024 
12025         STRUCT_INIT(gdi, get_udatamodel());
12026 
12027         if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi),
12028             mode) != 0) {
12029                 return (EFAULT);
12030         }
12031 
12032         /* Find out how many targets there are. */
12033         mutex_enter(&mpt->m_mutex);
12034         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
12035             MPTSAS_HASH_FIRST);


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
















12192                         if (cmd == DEVCTL_DEVICE_OFFLINE) {
12193                                 ptgt->m_led_status |=
12194                                     (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
12195                         } else {
12196                                 ptgt->m_led_status &=
12197                                     ~(1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
12198                         }
12199                         if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) {

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


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


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


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


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









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