85 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
86 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
87 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
88 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
89 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
90 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
91 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
92 #pragma pack()
93
94 /*
95 * private header files.
96 *
97 */
98 #include <sys/scsi/impl/scsi_reset_notify.h>
99 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
100 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
101 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
102 #include <sys/scsi/adapters/mpt_sas/mptsas_hash.h>
103 #include <sys/raidioctl.h>
104
105 #include <sys/fs/dv_node.h> /* devfs_clean */
106
107 /*
108 * FMA header files
109 */
110 #include <sys/ddifm.h>
111 #include <sys/fm/protocol.h>
112 #include <sys/fm/util.h>
113 #include <sys/fm/io/ddi.h>
114
115 /*
116 * autoconfiguration data and routines.
117 */
118 static int mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
119 static int mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
120 static int mptsas_power(dev_info_t *dip, int component, int level);
121
122 /*
123 * cb_ops function
124 */
125 static int mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
126 cred_t *credp, int *rval);
380 static int mptsas_offline_target(dev_info_t *pdip, char *name);
381
382 static int mptsas_config_raid(dev_info_t *pdip, uint16_t target,
383 dev_info_t **dip);
384
385 static int mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt);
386 static int mptsas_probe_lun(dev_info_t *pdip, int lun,
387 dev_info_t **dip, mptsas_target_t *ptgt);
388
389 static int mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
390 dev_info_t **dip, mptsas_target_t *ptgt, int lun);
391
392 static int mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
393 char *guid, dev_info_t **dip, mptsas_target_t *ptgt, int lun);
394 static int mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
395 char *guid, dev_info_t **dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt,
396 int lun);
397
398 static void mptsas_offline_missed_luns(dev_info_t *pdip,
399 uint16_t *repluns, int lun_cnt, mptsas_target_t *ptgt);
400 static int mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
401 mdi_pathinfo_t *rpip, uint_t flags);
402
403 static int mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn,
404 dev_info_t **smp_dip);
405 static int mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
406 uint_t flags);
407
408 static int mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data,
409 int mode, int *rval);
410 static int mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data,
411 int mode, int *rval);
412 static int mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data,
413 int mode, int *rval);
414 static void mptsas_record_event(void *args);
415 static int mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data,
416 int mode);
417
418 mptsas_target_t *mptsas_tgt_alloc(refhash_t *, uint16_t, uint64_t,
419 uint32_t, mptsas_phymask_t, uint8_t);
420 static mptsas_smp_t *mptsas_smp_alloc(mptsas_t *, mptsas_smp_t *);
421 static int mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
422 dev_info_t **smp_dip);
423
424 /*
425 * Power management functions
426 */
6874
6875 mutex_enter(&mpt->m_mutex);
6876 break;
6877 }
6878 case MPTSAS_DR_EVENT_OFFLINE_SMP:
6879 {
6880 devhdl = topo_node->devhdl;
6881 uint32_t dev_info;
6882
6883 psmp = refhash_linear_search(mpt->m_smp_targets,
6884 mptsas_smp_eval_devhdl, &devhdl);
6885 if (psmp == NULL)
6886 break;
6887 /*
6888 * The mptsas_smp_t data is released only if the dip is offlined
6889 * successfully.
6890 */
6891 mutex_exit(&mpt->m_mutex);
6892
6893 ndi_devi_enter(parent, &circ1);
6894 rval = mptsas_offline_smp(parent, psmp, NDI_DEVI_REMOVE);
6895 ndi_devi_exit(parent, circ1);
6896
6897 dev_info = psmp->m_deviceinfo;
6898 if ((dev_info & DEVINFO_DIRECT_ATTACHED) ==
6899 DEVINFO_DIRECT_ATTACHED) {
6900 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6901 MPTSAS_VIRTUAL_PORT, 1) !=
6902 DDI_PROP_SUCCESS) {
6903 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6904 MPTSAS_VIRTUAL_PORT);
6905 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6906 "prop update failed");
6907 mutex_enter(&mpt->m_mutex);
6908 return;
6909 }
6910 /*
6911 * Check whether the smp connected to the iport,
6912 */
6913 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6914 MPTSAS_NUM_PHYS, 0) !=
14676
14677 if (mptsas_parse_address(addr, &sas_wwn, &phy, &lun) !=
14678 DDI_SUCCESS) {
14679 continue;
14680 }
14681
14682 if (wwid == sas_wwn) {
14683 for (i = 0; i < lun_cnt; i++) {
14684 if (repluns[i] == lun) {
14685 find = 1;
14686 break;
14687 }
14688 }
14689 } else {
14690 continue;
14691 }
14692 if (find == 0) {
14693 /*
14694 * The lun has not been there already
14695 */
14696 (void) mptsas_offline_lun(pdip, savechild, NULL,
14697 NDI_DEVI_REMOVE);
14698 }
14699 }
14700
14701 pip = mdi_get_next_client_path(pdip, NULL);
14702 while (pip) {
14703 find = 0;
14704 savepip = pip;
14705 addr = MDI_PI(pip)->pi_addr;
14706
14707 pip = mdi_get_next_client_path(pdip, pip);
14708
14709 if (addr == NULL) {
14710 continue;
14711 }
14712
14713 if (mptsas_parse_address(addr, &sas_wwn, &phy,
14714 &lun) != DDI_SUCCESS) {
14715 continue;
14716 }
14717
14718 if (sas_wwn == wwid) {
14719 for (i = 0; i < lun_cnt; i++) {
14720 if (repluns[i] == lun) {
14721 find = 1;
14722 break;
14723 }
14724 }
14725 } else {
14726 continue;
14727 }
14728
14729 if (find == 0) {
14730 /*
14731 * The lun has not been there already
14732 */
14733 (void) mptsas_offline_lun(pdip, NULL, savepip,
14734 NDI_DEVI_REMOVE);
14735 }
14736 }
14737 }
14738
14739 /*
14740 * If this enclosure doesn't exist in the enclosure list, add it. If it does,
14741 * update it.
14742 */
14743 static void
14744 mptsas_enclosure_update(mptsas_t *mpt, mptsas_enclosure_t *mep)
14745 {
14746 mptsas_enclosure_t *m;
14747
14748 ASSERT(MUTEX_HELD(&mpt->m_mutex));
14749 m = mptsas_enc_lookup(mpt, mep->me_enchdl);
14750 if (m != NULL) {
14751 uint8_t *ledp;
14752 m->me_flags = mep->me_flags;
14753
14754
15008
15009 child = ddi_get_child(pdip);
15010 while (child) {
15011 addr = ddi_get_name_addr(child);
15012 prechild = child;
15013 child = ddi_get_next_sibling(child);
15014
15015 if (addr == NULL) {
15016 continue;
15017 }
15018 if ((cp = strchr(addr, ',')) == NULL) {
15019 continue;
15020 }
15021
15022 s = (uintptr_t)cp - (uintptr_t)addr;
15023
15024 if (strncmp(addr, name, s) != 0) {
15025 continue;
15026 }
15027
15028 tmp_rval = mptsas_offline_lun(pdip, prechild, NULL,
15029 NDI_DEVI_REMOVE);
15030 if (tmp_rval != DDI_SUCCESS) {
15031 rval = DDI_FAILURE;
15032 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
15033 prechild, MPTSAS_DEV_GONE) !=
15034 DDI_PROP_SUCCESS) {
15035 mptsas_log(mpt, CE_WARN, "mptsas driver "
15036 "unable to create property for "
15037 "SAS %s (MPTSAS_DEV_GONE)", addr);
15038 }
15039 }
15040 }
15041
15042 pip = mdi_get_next_client_path(pdip, NULL);
15043 while (pip) {
15044 addr = MDI_PI(pip)->pi_addr;
15045 savepip = pip;
15046 pip = mdi_get_next_client_path(pdip, pip);
15047 if (addr == NULL) {
15048 continue;
15049 }
15050
15051 if ((cp = strchr(addr, ',')) == NULL) {
15052 continue;
15053 }
15054
15055 s = (uintptr_t)cp - (uintptr_t)addr;
15056
15057 if (strncmp(addr, name, s) != 0) {
15058 continue;
15059 }
15060
15061 (void) mptsas_offline_lun(pdip, NULL, savepip,
15062 NDI_DEVI_REMOVE);
15063 /*
15064 * driver will not invoke mdi_pi_free, so path will not
15065 * be freed forever, return DDI_FAILURE.
15066 */
15067 rval = DDI_FAILURE;
15068 }
15069 return (rval);
15070 }
15071
15072 static int
15073 mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
15074 mdi_pathinfo_t *rpip, uint_t flags)
15075 {
15076 int rval = DDI_FAILURE;
15077 char *devname;
15078 dev_info_t *cdip, *parent;
15079
15080 if (rpip != NULL) {
15081 parent = scsi_vhci_dip;
15082 cdip = mdi_pi_get_client(rpip);
15083 } else if (rdip != NULL) {
15084 parent = pdip;
15085 cdip = rdip;
15086 } else {
15087 return (DDI_FAILURE);
15088 }
15089
15090 /*
15091 * Make sure node is attached otherwise
15092 * it won't have related cache nodes to
15093 * clean up. i_ddi_devi_attached is
15094 * similiar to i_ddi_node_state(cdip) >=
15095 * DS_ATTACHED.
15096 */
15097 if (i_ddi_devi_attached(cdip)) {
15098
15099 /* Get full devname */
15100 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
15101 (void) ddi_deviname(cdip, devname);
15102 /* Clean cache */
15103 (void) devfs_clean(parent, devname + 1,
15104 DV_CLEAN_FORCE);
15105 kmem_free(devname, MAXNAMELEN + 1);
15106 }
15107 if (rpip != NULL) {
15108 if (MDI_PI_IS_OFFLINE(rpip)) {
15109 rval = DDI_SUCCESS;
15110 } else {
15111 rval = mdi_pi_offline(rpip, 0);
15112 }
15113 } else {
15114 rval = ndi_devi_offline(cdip, flags);
15115 }
15116
15117 return (rval);
15118 }
15119
15120 static dev_info_t *
15121 mptsas_find_smp_child(dev_info_t *parent, char *str_wwn)
15122 {
15123 dev_info_t *child = NULL;
15124 char *smp_wwn = NULL;
15125
15126 child = ddi_get_child(parent);
15127 while (child) {
15128 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
15129 DDI_PROP_DONTPASS, SMP_WWN, &smp_wwn)
15130 != DDI_SUCCESS) {
15131 child = ddi_get_next_sibling(child);
15132 continue;
15133 }
15134
15135 if (strcmp(smp_wwn, str_wwn) == 0) {
15136 ddi_prop_free(smp_wwn);
15137 break;
15138 }
15139 child = ddi_get_next_sibling(child);
15140 ddi_prop_free(smp_wwn);
15141 }
15142 return (child);
15143 }
15144
15145 static int
15146 mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, uint_t flags)
15147 {
15148 int rval = DDI_FAILURE;
15149 char *devname;
15150 char wwn_str[MPTSAS_WWN_STRLEN];
15151 dev_info_t *cdip;
15152
15153 (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
15154
15155 cdip = mptsas_find_smp_child(pdip, wwn_str);
15156
15157 if (cdip == NULL)
15158 return (DDI_SUCCESS);
15159
15160 /*
15161 * Make sure node is attached otherwise
15162 * it won't have related cache nodes to
15163 * clean up. i_ddi_devi_attached is
15164 * similiar to i_ddi_node_state(cdip) >=
15165 * DS_ATTACHED.
15166 */
15167 if (i_ddi_devi_attached(cdip)) {
15168
15169 /* Get full devname */
15170 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
15171 (void) ddi_deviname(cdip, devname);
15172 /* Clean cache */
15173 (void) devfs_clean(pdip, devname + 1,
15174 DV_CLEAN_FORCE);
15175 kmem_free(devname, MAXNAMELEN + 1);
15176 }
15177
15178 rval = ndi_devi_offline(cdip, flags);
15179
15180 return (rval);
15181 }
15182
15183 static dev_info_t *
15184 mptsas_find_child(dev_info_t *pdip, char *name)
15185 {
15186 dev_info_t *child = NULL;
15187 char *rname = NULL;
15188 int rval = DDI_FAILURE;
15189
15190 rname = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
15191
15192 child = ddi_get_child(pdip);
15193 while (child) {
15194 rval = mptsas_name_child(child, rname, SCSI_MAXNAMELEN);
15195 if (rval != DDI_SUCCESS) {
15196 child = ddi_get_next_sibling(child);
15197 bzero(rname, SCSI_MAXNAMELEN);
15198 continue;
15199 }
|
85 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
86 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
87 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
88 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
89 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
90 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
91 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
92 #pragma pack()
93
94 /*
95 * private header files.
96 *
97 */
98 #include <sys/scsi/impl/scsi_reset_notify.h>
99 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
100 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
101 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
102 #include <sys/scsi/adapters/mpt_sas/mptsas_hash.h>
103 #include <sys/raidioctl.h>
104
105 /*
106 * FMA header files
107 */
108 #include <sys/ddifm.h>
109 #include <sys/fm/protocol.h>
110 #include <sys/fm/util.h>
111 #include <sys/fm/io/ddi.h>
112
113 /*
114 * autoconfiguration data and routines.
115 */
116 static int mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
117 static int mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
118 static int mptsas_power(dev_info_t *dip, int component, int level);
119
120 /*
121 * cb_ops function
122 */
123 static int mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
124 cred_t *credp, int *rval);
378 static int mptsas_offline_target(dev_info_t *pdip, char *name);
379
380 static int mptsas_config_raid(dev_info_t *pdip, uint16_t target,
381 dev_info_t **dip);
382
383 static int mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt);
384 static int mptsas_probe_lun(dev_info_t *pdip, int lun,
385 dev_info_t **dip, mptsas_target_t *ptgt);
386
387 static int mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
388 dev_info_t **dip, mptsas_target_t *ptgt, int lun);
389
390 static int mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
391 char *guid, dev_info_t **dip, mptsas_target_t *ptgt, int lun);
392 static int mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
393 char *guid, dev_info_t **dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt,
394 int lun);
395
396 static void mptsas_offline_missed_luns(dev_info_t *pdip,
397 uint16_t *repluns, int lun_cnt, mptsas_target_t *ptgt);
398 static int mptsas_offline_lun(dev_info_t *rdip, mdi_pathinfo_t *rpip);
399
400 static int mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn,
401 dev_info_t **smp_dip);
402 static int mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node);
403
404 static int mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data,
405 int mode, int *rval);
406 static int mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data,
407 int mode, int *rval);
408 static int mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data,
409 int mode, int *rval);
410 static void mptsas_record_event(void *args);
411 static int mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data,
412 int mode);
413
414 mptsas_target_t *mptsas_tgt_alloc(refhash_t *, uint16_t, uint64_t,
415 uint32_t, mptsas_phymask_t, uint8_t);
416 static mptsas_smp_t *mptsas_smp_alloc(mptsas_t *, mptsas_smp_t *);
417 static int mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
418 dev_info_t **smp_dip);
419
420 /*
421 * Power management functions
422 */
6870
6871 mutex_enter(&mpt->m_mutex);
6872 break;
6873 }
6874 case MPTSAS_DR_EVENT_OFFLINE_SMP:
6875 {
6876 devhdl = topo_node->devhdl;
6877 uint32_t dev_info;
6878
6879 psmp = refhash_linear_search(mpt->m_smp_targets,
6880 mptsas_smp_eval_devhdl, &devhdl);
6881 if (psmp == NULL)
6882 break;
6883 /*
6884 * The mptsas_smp_t data is released only if the dip is offlined
6885 * successfully.
6886 */
6887 mutex_exit(&mpt->m_mutex);
6888
6889 ndi_devi_enter(parent, &circ1);
6890 rval = mptsas_offline_smp(parent, psmp);
6891 ndi_devi_exit(parent, circ1);
6892
6893 dev_info = psmp->m_deviceinfo;
6894 if ((dev_info & DEVINFO_DIRECT_ATTACHED) ==
6895 DEVINFO_DIRECT_ATTACHED) {
6896 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6897 MPTSAS_VIRTUAL_PORT, 1) !=
6898 DDI_PROP_SUCCESS) {
6899 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6900 MPTSAS_VIRTUAL_PORT);
6901 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6902 "prop update failed");
6903 mutex_enter(&mpt->m_mutex);
6904 return;
6905 }
6906 /*
6907 * Check whether the smp connected to the iport,
6908 */
6909 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6910 MPTSAS_NUM_PHYS, 0) !=
14672
14673 if (mptsas_parse_address(addr, &sas_wwn, &phy, &lun) !=
14674 DDI_SUCCESS) {
14675 continue;
14676 }
14677
14678 if (wwid == sas_wwn) {
14679 for (i = 0; i < lun_cnt; i++) {
14680 if (repluns[i] == lun) {
14681 find = 1;
14682 break;
14683 }
14684 }
14685 } else {
14686 continue;
14687 }
14688 if (find == 0) {
14689 /*
14690 * The lun has not been there already
14691 */
14692 (void) mptsas_offline_lun(savechild, NULL);
14693 }
14694 }
14695
14696 pip = mdi_get_next_client_path(pdip, NULL);
14697 while (pip) {
14698 find = 0;
14699 savepip = pip;
14700 addr = MDI_PI(pip)->pi_addr;
14701
14702 pip = mdi_get_next_client_path(pdip, pip);
14703
14704 if (addr == NULL) {
14705 continue;
14706 }
14707
14708 if (mptsas_parse_address(addr, &sas_wwn, &phy,
14709 &lun) != DDI_SUCCESS) {
14710 continue;
14711 }
14712
14713 if (sas_wwn == wwid) {
14714 for (i = 0; i < lun_cnt; i++) {
14715 if (repluns[i] == lun) {
14716 find = 1;
14717 break;
14718 }
14719 }
14720 } else {
14721 continue;
14722 }
14723
14724 if (find == 0) {
14725 /*
14726 * The lun has not been there already
14727 */
14728 (void) mptsas_offline_lun(NULL, savepip);
14729 }
14730 }
14731 }
14732
14733 /*
14734 * If this enclosure doesn't exist in the enclosure list, add it. If it does,
14735 * update it.
14736 */
14737 static void
14738 mptsas_enclosure_update(mptsas_t *mpt, mptsas_enclosure_t *mep)
14739 {
14740 mptsas_enclosure_t *m;
14741
14742 ASSERT(MUTEX_HELD(&mpt->m_mutex));
14743 m = mptsas_enc_lookup(mpt, mep->me_enchdl);
14744 if (m != NULL) {
14745 uint8_t *ledp;
14746 m->me_flags = mep->me_flags;
14747
14748
15002
15003 child = ddi_get_child(pdip);
15004 while (child) {
15005 addr = ddi_get_name_addr(child);
15006 prechild = child;
15007 child = ddi_get_next_sibling(child);
15008
15009 if (addr == NULL) {
15010 continue;
15011 }
15012 if ((cp = strchr(addr, ',')) == NULL) {
15013 continue;
15014 }
15015
15016 s = (uintptr_t)cp - (uintptr_t)addr;
15017
15018 if (strncmp(addr, name, s) != 0) {
15019 continue;
15020 }
15021
15022 tmp_rval = mptsas_offline_lun(prechild, NULL);
15023 if (tmp_rval != DDI_SUCCESS) {
15024 rval = DDI_FAILURE;
15025 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
15026 prechild, MPTSAS_DEV_GONE) !=
15027 DDI_PROP_SUCCESS) {
15028 mptsas_log(mpt, CE_WARN, "mptsas driver "
15029 "unable to create property for "
15030 "SAS %s (MPTSAS_DEV_GONE)", addr);
15031 }
15032 }
15033 }
15034
15035 pip = mdi_get_next_client_path(pdip, NULL);
15036 while (pip) {
15037 addr = MDI_PI(pip)->pi_addr;
15038 savepip = pip;
15039 pip = mdi_get_next_client_path(pdip, pip);
15040 if (addr == NULL) {
15041 continue;
15042 }
15043
15044 if ((cp = strchr(addr, ',')) == NULL) {
15045 continue;
15046 }
15047
15048 s = (uintptr_t)cp - (uintptr_t)addr;
15049
15050 if (strncmp(addr, name, s) != 0) {
15051 continue;
15052 }
15053
15054 (void) mptsas_offline_lun(NULL, savepip);
15055 /*
15056 * driver will not invoke mdi_pi_free, so path will not
15057 * be freed forever, return DDI_FAILURE.
15058 */
15059 rval = DDI_FAILURE;
15060 }
15061 return (rval);
15062 }
15063
15064 static int
15065 mptsas_offline_lun(dev_info_t *rdip, mdi_pathinfo_t *rpip)
15066 {
15067 int rval = DDI_FAILURE;
15068
15069 if (rpip != NULL) {
15070 if (MDI_PI_IS_OFFLINE(rpip)) {
15071 rval = DDI_SUCCESS;
15072 } else {
15073 rval = mdi_pi_offline(rpip, 0);
15074 }
15075 } else if (rdip != NULL) {
15076 rval = ndi_devi_offline(rdip,
15077 NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE);
15078 }
15079
15080 return (rval);
15081 }
15082
15083 static dev_info_t *
15084 mptsas_find_smp_child(dev_info_t *parent, char *str_wwn)
15085 {
15086 dev_info_t *child = NULL;
15087 char *smp_wwn = NULL;
15088
15089 child = ddi_get_child(parent);
15090 while (child) {
15091 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
15092 DDI_PROP_DONTPASS, SMP_WWN, &smp_wwn)
15093 != DDI_SUCCESS) {
15094 child = ddi_get_next_sibling(child);
15095 continue;
15096 }
15097
15098 if (strcmp(smp_wwn, str_wwn) == 0) {
15099 ddi_prop_free(smp_wwn);
15100 break;
15101 }
15102 child = ddi_get_next_sibling(child);
15103 ddi_prop_free(smp_wwn);
15104 }
15105 return (child);
15106 }
15107
15108 static int
15109 mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node)
15110 {
15111 int rval = DDI_FAILURE;
15112 char wwn_str[MPTSAS_WWN_STRLEN];
15113 dev_info_t *cdip;
15114
15115 (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
15116
15117 cdip = mptsas_find_smp_child(pdip, wwn_str);
15118 if (cdip == NULL)
15119 return (DDI_SUCCESS);
15120
15121 rval = ndi_devi_offline(cdip, NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE);
15122
15123 return (rval);
15124 }
15125
15126 static dev_info_t *
15127 mptsas_find_child(dev_info_t *pdip, char *name)
15128 {
15129 dev_info_t *child = NULL;
15130 char *rname = NULL;
15131 int rval = DDI_FAILURE;
15132
15133 rname = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
15134
15135 child = ddi_get_child(pdip);
15136 while (child) {
15137 rval = mptsas_name_child(child, rname, SCSI_MAXNAMELEN);
15138 if (rval != DDI_SUCCESS) {
15139 child = ddi_get_next_sibling(child);
15140 bzero(rname, SCSI_MAXNAMELEN);
15141 continue;
15142 }
|