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 }
|