1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   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 2016 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  26  * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
  27  * Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
  28  */
  29 
  30 /*
  31  * Copyright (c) 2000 to 2010, LSI Corporation.
  32  * All rights reserved.
  33  *
  34  * Redistribution and use in source and binary forms of all code within
  35  * this file that is exclusively owned by LSI, with or without
  36  * modification, is permitted provided that, in addition to the CDDL 1.0
  37  * License requirements, the following conditions are met:
  38  *
  39  *    Neither the name of the author nor the names of its contributors may be
  40  *    used to endorse or promote products derived from this software without
  41  *    specific prior written permission.
  42  *
  43  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  44  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  45  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  46  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  47  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  48  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  49  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  50  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  51  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  52  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  53  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  54  * DAMAGE.
  55  */
  56 
  57 /*
  58  * mptsas - This is a driver based on LSI Logic's MPT2.0/2.5 interface.
  59  *
  60  */
  61 
  62 #if defined(lint) || defined(DEBUG)
  63 #define MPTSAS_DEBUG
  64 #endif
  65 
  66 /*
  67  * standard header files.
  68  */
  69 #include <sys/note.h>
  70 #include <sys/scsi/scsi.h>
  71 #include <sys/pci.h>
  72 #include <sys/file.h>
  73 #include <sys/policy.h>
  74 #include <sys/model.h>
  75 #include <sys/sysevent.h>
  76 #include <sys/sysevent/eventdefs.h>
  77 #include <sys/sysevent/dr.h>
  78 #include <sys/sata/sata_defs.h>
  79 #include <sys/sata/sata_hba.h>
  80 #include <sys/scsi/generic/sas.h>
  81 #include <sys/scsi/impl/scsi_sas.h>
  82 
  83 #pragma pack(1)
  84 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
  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);
 127 #ifdef __sparc
 128 static int mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd);
 129 #else  /* __sparc */
 130 static int mptsas_quiesce(dev_info_t *devi);
 131 #endif  /* __sparc */
 132 
 133 /*
 134  * Resource initilaization for hardware
 135  */
 136 static void mptsas_setup_cmd_reg(mptsas_t *mpt);
 137 static void mptsas_disable_bus_master(mptsas_t *mpt);
 138 static void mptsas_hba_fini(mptsas_t *mpt);
 139 static void mptsas_cfg_fini(mptsas_t *mptsas_blkp);
 140 static int mptsas_hba_setup(mptsas_t *mpt);
 141 static void mptsas_hba_teardown(mptsas_t *mpt);
 142 static int mptsas_config_space_init(mptsas_t *mpt);
 143 static void mptsas_config_space_fini(mptsas_t *mpt);
 144 static void mptsas_iport_register(mptsas_t *mpt);
 145 static int mptsas_smp_setup(mptsas_t *mpt);
 146 static void mptsas_smp_teardown(mptsas_t *mpt);
 147 static int mptsas_cache_create(mptsas_t *mpt);
 148 static void mptsas_cache_destroy(mptsas_t *mpt);
 149 static int mptsas_alloc_request_frames(mptsas_t *mpt);
 150 static int mptsas_alloc_sense_bufs(mptsas_t *mpt);
 151 static int mptsas_alloc_reply_frames(mptsas_t *mpt);
 152 static int mptsas_alloc_free_queue(mptsas_t *mpt);
 153 static int mptsas_alloc_post_queue(mptsas_t *mpt);
 154 static void mptsas_alloc_reply_args(mptsas_t *mpt);
 155 static int mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
 156 static void mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
 157 static int mptsas_init_chip(mptsas_t *mpt, int first_time);
 158 
 159 /*
 160  * SCSA function prototypes
 161  */
 162 static int mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
 163 static int mptsas_scsi_reset(struct scsi_address *ap, int level);
 164 static int mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
 165 static int mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly);
 166 static int mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value,
 167     int tgtonly);
 168 static void mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt);
 169 static struct scsi_pkt *mptsas_scsi_init_pkt(struct scsi_address *ap,
 170     struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen,
 171         int tgtlen, int flags, int (*callback)(), caddr_t arg);
 172 static void mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt);
 173 static void mptsas_scsi_destroy_pkt(struct scsi_address *ap,
 174     struct scsi_pkt *pkt);
 175 static int mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 176     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 177 static void mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 178     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 179 static int mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
 180     void (*callback)(caddr_t), caddr_t arg);
 181 static int mptsas_get_name(struct scsi_device *sd, char *name, int len);
 182 static int mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len);
 183 static int mptsas_scsi_quiesce(dev_info_t *dip);
 184 static int mptsas_scsi_unquiesce(dev_info_t *dip);
 185 static int mptsas_bus_config(dev_info_t *pdip, uint_t flags,
 186     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
 187 
 188 /*
 189  * SMP functions
 190  */
 191 static int mptsas_smp_start(struct smp_pkt *smp_pkt);
 192 
 193 /*
 194  * internal function prototypes.
 195  */
 196 static void mptsas_list_add(mptsas_t *mpt);
 197 static void mptsas_list_del(mptsas_t *mpt);
 198 
 199 static int mptsas_quiesce_bus(mptsas_t *mpt);
 200 static int mptsas_unquiesce_bus(mptsas_t *mpt);
 201 
 202 static int mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size);
 203 static void mptsas_free_handshake_msg(mptsas_t *mpt);
 204 
 205 static void mptsas_ncmds_checkdrain(void *arg);
 206 
 207 static int mptsas_prepare_pkt(mptsas_cmd_t *cmd);
 208 static int mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
 209 static int mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
 210 static void mptsas_accept_tx_waitq(mptsas_t *mpt);
 211 
 212 static int mptsas_do_detach(dev_info_t *dev);
 213 static int mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl);
 214 static int mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun,
 215     struct scsi_pkt *pkt);
 216 static int mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp);
 217 
 218 static void mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd);
 219 static void mptsas_handle_event(void *args);
 220 static int mptsas_handle_event_sync(void *args);
 221 static void mptsas_handle_dr(void *args);
 222 static void mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
 223     dev_info_t *pdip);
 224 
 225 static void mptsas_restart_cmd(void *);
 226 
 227 static void mptsas_flush_hba(mptsas_t *mpt);
 228 static void mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun,
 229         uint8_t tasktype);
 230 static void mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd,
 231     uchar_t reason, uint_t stat);
 232 
 233 static uint_t mptsas_intr(caddr_t arg1, caddr_t arg2);
 234 static void mptsas_process_intr(mptsas_t *mpt,
 235     pMpi2ReplyDescriptorsUnion_t reply_desc_union);
 236 static void mptsas_handle_scsi_io_success(mptsas_t *mpt,
 237     pMpi2ReplyDescriptorsUnion_t reply_desc);
 238 static void mptsas_handle_address_reply(mptsas_t *mpt,
 239     pMpi2ReplyDescriptorsUnion_t reply_desc);
 240 static int mptsas_wait_intr(mptsas_t *mpt, int polltime);
 241 static void mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd,
 242     uint32_t *control, pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl);
 243 
 244 static void mptsas_watch(void *arg);
 245 static void mptsas_watchsubr(mptsas_t *mpt);
 246 static void mptsas_cmd_timeout(mptsas_t *mpt, mptsas_target_t *ptgt);
 247 
 248 static void mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd);
 249 static int mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
 250     uint8_t *data, uint32_t request_size, uint32_t reply_size,
 251     uint32_t data_size, uint32_t direction, uint8_t *dataout,
 252     uint32_t dataout_size, short timeout, int mode);
 253 static int mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl);
 254 
 255 static uint8_t mptsas_get_fw_diag_buffer_number(mptsas_t *mpt,
 256     uint32_t unique_id);
 257 static void mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd);
 258 static int mptsas_post_fw_diag_buffer(mptsas_t *mpt,
 259     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
 260 static int mptsas_release_fw_diag_buffer(mptsas_t *mpt,
 261     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
 262     uint32_t diag_type);
 263 static int mptsas_diag_register(mptsas_t *mpt,
 264     mptsas_fw_diag_register_t *diag_register, uint32_t *return_code);
 265 static int mptsas_diag_unregister(mptsas_t *mpt,
 266     mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code);
 267 static int mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
 268     uint32_t *return_code);
 269 static int mptsas_diag_read_buffer(mptsas_t *mpt,
 270     mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
 271     uint32_t *return_code, int ioctl_mode);
 272 static int mptsas_diag_release(mptsas_t *mpt,
 273     mptsas_fw_diag_release_t *diag_release, uint32_t *return_code);
 274 static int mptsas_do_diag_action(mptsas_t *mpt, uint32_t action,
 275     uint8_t *diag_action, uint32_t length, uint32_t *return_code,
 276     int ioctl_mode);
 277 static int mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *data,
 278     int mode);
 279 
 280 static int mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
 281     int cmdlen, int tgtlen, int statuslen, int kf);
 282 static void mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd);
 283 
 284 static int mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags);
 285 static void mptsas_kmem_cache_destructor(void *buf, void *cdrarg);
 286 
 287 static int mptsas_cache_frames_constructor(void *buf, void *cdrarg,
 288     int kmflags);
 289 static void mptsas_cache_frames_destructor(void *buf, void *cdrarg);
 290 
 291 static void mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
 292     mptsas_cmd_t *cmd);
 293 static void mptsas_check_task_mgt(mptsas_t *mpt,
 294     pMpi2SCSIManagementReply_t reply, mptsas_cmd_t *cmd);
 295 static int mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
 296     mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
 297     int *resid);
 298 
 299 static int mptsas_alloc_active_slots(mptsas_t *mpt, int flag);
 300 static void mptsas_free_active_slots(mptsas_t *mpt);
 301 static int mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 302 
 303 static void mptsas_restart_hba(mptsas_t *mpt);
 304 static void mptsas_restart_waitq(mptsas_t *mpt);
 305 
 306 static void mptsas_deliver_doneq_thread(mptsas_t *mpt);
 307 static void mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd);
 308 static void mptsas_doneq_mv(mptsas_t *mpt, uint64_t t);
 309 
 310 static mptsas_cmd_t *mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t);
 311 static void mptsas_doneq_empty(mptsas_t *mpt);
 312 static void mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg);
 313 
 314 static mptsas_cmd_t *mptsas_waitq_rm(mptsas_t *mpt);
 315 static void mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
 316 static mptsas_cmd_t *mptsas_tx_waitq_rm(mptsas_t *mpt);
 317 static void mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
 318 
 319 
 320 static void mptsas_start_watch_reset_delay();
 321 static void mptsas_setup_bus_reset_delay(mptsas_t *mpt);
 322 static void mptsas_watch_reset_delay(void *arg);
 323 static int mptsas_watch_reset_delay_subr(mptsas_t *mpt);
 324 
 325 /*
 326  * helper functions
 327  */
 328 static void mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 329 
 330 static dev_info_t *mptsas_find_child(dev_info_t *pdip, char *name);
 331 static dev_info_t *mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy);
 332 static dev_info_t *mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr,
 333     int lun);
 334 static mdi_pathinfo_t *mptsas_find_path_addr(dev_info_t *pdip, uint64_t sasaddr,
 335     int lun);
 336 static mdi_pathinfo_t *mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy);
 337 static dev_info_t *mptsas_find_smp_child(dev_info_t *pdip, char *str_wwn);
 338 
 339 static int mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy,
 340     int *lun);
 341 static int mptsas_parse_smp_name(char *name, uint64_t *wwn);
 342 
 343 static mptsas_target_t *mptsas_phy_to_tgt(mptsas_t *mpt,
 344     mptsas_phymask_t phymask, uint8_t phy);
 345 static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt,
 346     mptsas_phymask_t phymask, uint64_t wwid);
 347 static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt,
 348     mptsas_phymask_t phymask, uint64_t wwid);
 349 
 350 static int mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun,
 351     uchar_t page, unsigned char *buf, int len, int *rlen, uchar_t evpd);
 352 
 353 static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
 354     uint16_t *handle, mptsas_target_t **pptgt);
 355 static void mptsas_update_phymask(mptsas_t *mpt);
 356 
 357 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
 358     uint32_t *status, uint8_t cmd);
 359 static dev_info_t *mptsas_get_dip_from_dev(dev_t dev,
 360     mptsas_phymask_t *phymask);
 361 static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr,
 362     mptsas_phymask_t phymask);
 363 static int mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt);
 364 
 365 
 366 /*
 367  * Enumeration / DR functions
 368  */
 369 static void mptsas_config_all(dev_info_t *pdip);
 370 static int mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
 371     dev_info_t **lundip);
 372 static int mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
 373     dev_info_t **lundip);
 374 
 375 static int mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt);
 376 static int mptsas_offline_target(dev_info_t *pdip, char *name);
 377 
 378 static int mptsas_config_raid(dev_info_t *pdip, uint16_t target,
 379     dev_info_t **dip);
 380 
 381 static int mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt);
 382 static int mptsas_probe_lun(dev_info_t *pdip, int lun,
 383     dev_info_t **dip, mptsas_target_t *ptgt);
 384 
 385 static int mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
 386     dev_info_t **dip, mptsas_target_t *ptgt, int lun);
 387 
 388 static int mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
 389     char *guid, dev_info_t **dip, mptsas_target_t *ptgt, int lun);
 390 static int mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
 391     char *guid, dev_info_t **dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt,
 392     int lun);
 393 
 394 static void mptsas_offline_missed_luns(dev_info_t *pdip,
 395     uint16_t *repluns, int lun_cnt, mptsas_target_t *ptgt);
 396 static int mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
 397     mdi_pathinfo_t *rpip, uint_t flags);
 398 
 399 static int mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn,
 400     dev_info_t **smp_dip);
 401 static int mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 402     uint_t flags);
 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  */
 423 static int mptsas_get_pci_cap(mptsas_t *mpt);
 424 static int mptsas_init_pm(mptsas_t *mpt);
 425 
 426 /*
 427  * MPT MSI tunable:
 428  *
 429  * By default MSI is enabled on all supported platforms.
 430  */
 431 boolean_t mptsas_enable_msi = B_TRUE;
 432 boolean_t mptsas_physical_bind_failed_page_83 = B_FALSE;
 433 
 434 /*
 435  * Global switch for use of MPI2.5 FAST PATH.
 436  * We don't really know what FAST PATH actually does, so if it is suspected
 437  * to cause problems it can be turned off by setting this variable to B_FALSE.
 438  */
 439 boolean_t mptsas_use_fastpath = B_TRUE;
 440 
 441 static int mptsas_register_intrs(mptsas_t *);
 442 static void mptsas_unregister_intrs(mptsas_t *);
 443 static int mptsas_add_intrs(mptsas_t *, int);
 444 static void mptsas_rem_intrs(mptsas_t *);
 445 
 446 /*
 447  * FMA Prototypes
 448  */
 449 static void mptsas_fm_init(mptsas_t *mpt);
 450 static void mptsas_fm_fini(mptsas_t *mpt);
 451 static int mptsas_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *);
 452 
 453 extern pri_t minclsyspri, maxclsyspri;
 454 
 455 /*
 456  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).  It is
 457  * under this device that the paths to a physical device are created when
 458  * MPxIO is used.
 459  */
 460 extern dev_info_t       *scsi_vhci_dip;
 461 
 462 /*
 463  * Tunable timeout value for Inquiry VPD page 0x83
 464  * By default the value is 30 seconds.
 465  */
 466 int mptsas_inq83_retry_timeout = 30;
 467 
 468 /*
 469  * This is used to allocate memory for message frame storage, not for
 470  * data I/O DMA. All message frames must be stored in the first 4G of
 471  * physical memory.
 472  */
 473 ddi_dma_attr_t mptsas_dma_attrs = {
 474         DMA_ATTR_V0,    /* attribute layout version             */
 475         0x0ull,         /* address low - should be 0 (longlong) */
 476         0xffffffffull,  /* address high - 32-bit max range      */
 477         0x00ffffffull,  /* count max - max DMA object size      */
 478         4,              /* allocation alignment requirements    */
 479         0x78,           /* burstsizes - binary encoded values   */
 480         1,              /* minxfer - gran. of DMA engine        */
 481         0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 482         0xffffffffull,  /* max segment size (DMA boundary)      */
 483         MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 484         512,            /* granularity - device transfer size   */
 485         0               /* flags, set to 0                      */
 486 };
 487 
 488 /*
 489  * This is used for data I/O DMA memory allocation. (full 64-bit DMA
 490  * physical addresses are supported.)
 491  */
 492 ddi_dma_attr_t mptsas_dma_attrs64 = {
 493         DMA_ATTR_V0,    /* attribute layout version             */
 494         0x0ull,         /* address low - should be 0 (longlong) */
 495         0xffffffffffffffffull,  /* address high - 64-bit max    */
 496         0x00ffffffull,  /* count max - max DMA object size      */
 497         4,              /* allocation alignment requirements    */
 498         0x78,           /* burstsizes - binary encoded values   */
 499         1,              /* minxfer - gran. of DMA engine        */
 500         0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 501         0xffffffffull,  /* max segment size (DMA boundary)      */
 502         MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 503         512,            /* granularity - device transfer size   */
 504         0               /* flags, set to 0 */
 505 };
 506 
 507 ddi_device_acc_attr_t mptsas_dev_attr = {
 508         DDI_DEVICE_ATTR_V1,
 509         DDI_STRUCTURE_LE_ACC,
 510         DDI_STRICTORDER_ACC,
 511         DDI_DEFAULT_ACC
 512 };
 513 
 514 static struct cb_ops mptsas_cb_ops = {
 515         scsi_hba_open,          /* open */
 516         scsi_hba_close,         /* close */
 517         nodev,                  /* strategy */
 518         nodev,                  /* print */
 519         nodev,                  /* dump */
 520         nodev,                  /* read */
 521         nodev,                  /* write */
 522         mptsas_ioctl,           /* ioctl */
 523         nodev,                  /* devmap */
 524         nodev,                  /* mmap */
 525         nodev,                  /* segmap */
 526         nochpoll,               /* chpoll */
 527         ddi_prop_op,            /* cb_prop_op */
 528         NULL,                   /* streamtab */
 529         D_MP,                   /* cb_flag */
 530         CB_REV,                 /* rev */
 531         nodev,                  /* aread */
 532         nodev                   /* awrite */
 533 };
 534 
 535 static struct dev_ops mptsas_ops = {
 536         DEVO_REV,               /* devo_rev, */
 537         0,                      /* refcnt  */
 538         ddi_no_info,            /* info */
 539         nulldev,                /* identify */
 540         nulldev,                /* probe */
 541         mptsas_attach,          /* attach */
 542         mptsas_detach,          /* detach */
 543 #ifdef  __sparc
 544         mptsas_reset,
 545 #else
 546         nodev,                  /* reset */
 547 #endif  /* __sparc */
 548         &mptsas_cb_ops,             /* driver operations */
 549         NULL,                   /* bus operations */
 550         mptsas_power,           /* power management */
 551 #ifdef  __sparc
 552         ddi_quiesce_not_needed
 553 #else
 554         mptsas_quiesce          /* quiesce */
 555 #endif  /* __sparc */
 556 };
 557 
 558 
 559 #define MPTSAS_MOD_STRING "MPTSAS HBA Driver 00.00.00.24"
 560 
 561 static struct modldrv modldrv = {
 562         &mod_driverops,     /* Type of module. This one is a driver */
 563         MPTSAS_MOD_STRING, /* Name of the module. */
 564         &mptsas_ops,        /* driver ops */
 565 };
 566 
 567 static struct modlinkage modlinkage = {
 568         MODREV_1, &modldrv, NULL
 569 };
 570 #define TARGET_PROP     "target"
 571 #define LUN_PROP        "lun"
 572 #define LUN64_PROP      "lun64"
 573 #define SAS_PROP        "sas-mpt"
 574 #define MDI_GUID        "wwn"
 575 #define NDI_GUID        "guid"
 576 #define MPTSAS_DEV_GONE "mptsas_dev_gone"
 577 
 578 /*
 579  * Local static data
 580  */
 581 #if defined(MPTSAS_DEBUG)
 582 /*
 583  * Flags to indicate which debug messages are to be printed and which go to the
 584  * debug log ring buffer. Default is to not print anything, and to log
 585  * everything except the watchsubr() output which normally happens every second.
 586  */
 587 uint32_t mptsas_debugprt_flags = 0x0;
 588 uint32_t mptsas_debuglog_flags = ~(1U << 30);
 589 #endif  /* defined(MPTSAS_DEBUG) */
 590 uint32_t mptsas_debug_resets = 0;
 591 
 592 static kmutex_t         mptsas_global_mutex;
 593 static void             *mptsas_state;          /* soft state ptr */
 594 static krwlock_t        mptsas_global_rwlock;
 595 
 596 static kmutex_t         mptsas_log_mutex;
 597 static char             mptsas_log_buf[256];
 598 _NOTE(MUTEX_PROTECTS_DATA(mptsas_log_mutex, mptsas_log_buf))
 599 
 600 static mptsas_t *mptsas_head, *mptsas_tail;
 601 static clock_t mptsas_scsi_watchdog_tick;
 602 static clock_t mptsas_tick;
 603 static timeout_id_t mptsas_reset_watch;
 604 static timeout_id_t mptsas_timeout_id;
 605 static int mptsas_timeouts_enabled = 0;
 606 
 607 /*
 608  * Default length for extended auto request sense buffers.
 609  * All sense buffers need to be under the same alloc because there
 610  * is only one common top 32bits (of 64bits) address register.
 611  * Most requests only require 32 bytes, but some request >256.
 612  * We use rmalloc()/rmfree() on this additional memory to manage the
 613  * "extended" requests.
 614  */
 615 int mptsas_extreq_sense_bufsize = 256*64;
 616 
 617 /*
 618  * We believe that all software resrictions of having to run with DMA
 619  * attributes to limit allocation to the first 4G are removed.
 620  * However, this flag remains to enable quick switchback should suspicious
 621  * problems emerge.
 622  * Note that scsi_alloc_consistent_buf() does still adhere to allocating
 623  * 32 bit addressable memory, but we can cope if that is changed now.
 624  */
 625 int mptsas_use_64bit_msgaddr = 1;
 626 
 627 /*
 628  * warlock directives
 629  */
 630 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt \
 631         mptsas_cmd NcrTableIndirect buf scsi_cdb scsi_status))
 632 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", smp_pkt))
 633 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
 634 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mptsas_tgt_private))
 635 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_hba_tran::tran_tgt_private))
 636 
 637 /*
 638  * SM - HBA statics
 639  */
 640 char    *mptsas_driver_rev = MPTSAS_MOD_STRING;
 641 
 642 #ifdef MPTSAS_DEBUG
 643 void debug_enter(char *);
 644 #endif
 645 
 646 /*
 647  * Notes:
 648  *      - scsi_hba_init(9F) initializes SCSI HBA modules
 649  *      - must call scsi_hba_fini(9F) if modload() fails
 650  */
 651 int
 652 _init(void)
 653 {
 654         int status;
 655         /* CONSTCOND */
 656         ASSERT(NO_COMPETING_THREADS);
 657 
 658         NDBG0(("_init"));
 659 
 660         status = ddi_soft_state_init(&mptsas_state, MPTSAS_SIZE,
 661             MPTSAS_INITIAL_SOFT_SPACE);
 662         if (status != 0) {
 663                 return (status);
 664         }
 665 
 666         if ((status = scsi_hba_init(&modlinkage)) != 0) {
 667                 ddi_soft_state_fini(&mptsas_state);
 668                 return (status);
 669         }
 670 
 671         mutex_init(&mptsas_global_mutex, NULL, MUTEX_DRIVER, NULL);
 672         rw_init(&mptsas_global_rwlock, NULL, RW_DRIVER, NULL);
 673         mutex_init(&mptsas_log_mutex, NULL, MUTEX_DRIVER, NULL);
 674 
 675         if ((status = mod_install(&modlinkage)) != 0) {
 676                 mutex_destroy(&mptsas_log_mutex);
 677                 rw_destroy(&mptsas_global_rwlock);
 678                 mutex_destroy(&mptsas_global_mutex);
 679                 ddi_soft_state_fini(&mptsas_state);
 680                 scsi_hba_fini(&modlinkage);
 681         }
 682 
 683         return (status);
 684 }
 685 
 686 /*
 687  * Notes:
 688  *      - scsi_hba_fini(9F) uninitializes SCSI HBA modules
 689  */
 690 int
 691 _fini(void)
 692 {
 693         int     status;
 694         /* CONSTCOND */
 695         ASSERT(NO_COMPETING_THREADS);
 696 
 697         NDBG0(("_fini"));
 698 
 699         if ((status = mod_remove(&modlinkage)) == 0) {
 700                 ddi_soft_state_fini(&mptsas_state);
 701                 scsi_hba_fini(&modlinkage);
 702                 mutex_destroy(&mptsas_global_mutex);
 703                 rw_destroy(&mptsas_global_rwlock);
 704                 mutex_destroy(&mptsas_log_mutex);
 705         }
 706         return (status);
 707 }
 708 
 709 /*
 710  * The loadable-module _info(9E) entry point
 711  */
 712 int
 713 _info(struct modinfo *modinfop)
 714 {
 715         /* CONSTCOND */
 716         ASSERT(NO_COMPETING_THREADS);
 717         NDBG0(("mptsas _info"));
 718 
 719         return (mod_info(&modlinkage, modinfop));
 720 }
 721 
 722 static int
 723 mptsas_target_eval_devhdl(const void *op, void *arg)
 724 {
 725         uint16_t dh = *(uint16_t *)arg;
 726         const mptsas_target_t *tp = op;
 727 
 728         return ((int)tp->m_devhdl - (int)dh);
 729 }
 730 
 731 static int
 732 mptsas_target_eval_slot(const void *op, void *arg)
 733 {
 734         mptsas_led_control_t *lcp = arg;
 735         const mptsas_target_t *tp = op;
 736 
 737         if (tp->m_enclosure != lcp->Enclosure)
 738                 return ((int)tp->m_enclosure - (int)lcp->Enclosure);
 739 
 740         return ((int)tp->m_slot_num - (int)lcp->Slot);
 741 }
 742 
 743 static int
 744 mptsas_target_eval_nowwn(const void *op, void *arg)
 745 {
 746         uint8_t phy = *(uint8_t *)arg;
 747         const mptsas_target_t *tp = op;
 748 
 749         if (tp->m_addr.mta_wwn != 0)
 750                 return (-1);
 751 
 752         return ((int)tp->m_phynum - (int)phy);
 753 }
 754 
 755 static int
 756 mptsas_smp_eval_devhdl(const void *op, void *arg)
 757 {
 758         uint16_t dh = *(uint16_t *)arg;
 759         const mptsas_smp_t *sp = op;
 760 
 761         return ((int)sp->m_devhdl - (int)dh);
 762 }
 763 
 764 static uint64_t
 765 mptsas_target_addr_hash(const void *tp)
 766 {
 767         const mptsas_target_addr_t *tap = tp;
 768 
 769         return ((tap->mta_wwn & 0xffffffffffffULL) |
 770             ((uint64_t)tap->mta_phymask << 48));
 771 }
 772 
 773 static int
 774 mptsas_target_addr_cmp(const void *a, const void *b)
 775 {
 776         const mptsas_target_addr_t *aap = a;
 777         const mptsas_target_addr_t *bap = b;
 778 
 779         if (aap->mta_wwn < bap->mta_wwn)
 780                 return (-1);
 781         if (aap->mta_wwn > bap->mta_wwn)
 782                 return (1);
 783         return ((int)bap->mta_phymask - (int)aap->mta_phymask);
 784 }
 785 
 786 static uint64_t
 787 mptsas_tmp_target_hash(const void *tp)
 788 {
 789         return ((uint64_t)(uintptr_t)tp);
 790 }
 791 
 792 static int
 793 mptsas_tmp_target_cmp(const void *a, const void *b)
 794 {
 795         if (a > b)
 796                 return (1);
 797         if (b < a)
 798                 return (-1);
 799 
 800         return (0);
 801 }
 802 
 803 static void
 804 mptsas_target_free(void *op)
 805 {
 806         kmem_free(op, sizeof (mptsas_target_t));
 807 }
 808 
 809 static void
 810 mptsas_smp_free(void *op)
 811 {
 812         kmem_free(op, sizeof (mptsas_smp_t));
 813 }
 814 
 815 static void
 816 mptsas_destroy_hashes(mptsas_t *mpt)
 817 {
 818         mptsas_target_t *tp;
 819         mptsas_smp_t *sp;
 820 
 821         for (tp = refhash_first(mpt->m_targets); tp != NULL;
 822             tp = refhash_next(mpt->m_targets, tp)) {
 823                 refhash_remove(mpt->m_targets, tp);
 824         }
 825         for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
 826             sp = refhash_next(mpt->m_smp_targets, sp)) {
 827                 refhash_remove(mpt->m_smp_targets, sp);
 828         }
 829         refhash_destroy(mpt->m_tmp_targets);
 830         refhash_destroy(mpt->m_targets);
 831         refhash_destroy(mpt->m_smp_targets);
 832         mpt->m_targets = NULL;
 833         mpt->m_smp_targets = NULL;
 834 }
 835 
 836 static int
 837 mptsas_iport_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 838 {
 839         dev_info_t              *pdip;
 840         mptsas_t                *mpt;
 841         scsi_hba_tran_t         *hba_tran;
 842         char                    *iport = NULL;
 843         char                    phymask[MPTSAS_MAX_PHYS];
 844         mptsas_phymask_t        phy_mask = 0;
 845         int                     dynamic_port = 0;
 846         uint32_t                page_address;
 847         char                    initiator_wwnstr[MPTSAS_WWN_STRLEN];
 848         int                     rval = DDI_FAILURE;
 849         int                     i = 0;
 850         uint8_t                 numphys = 0;
 851         uint8_t                 phy_id;
 852         uint8_t                 phy_port = 0;
 853         uint16_t                attached_devhdl = 0;
 854         uint32_t                dev_info;
 855         uint64_t                attached_sas_wwn;
 856         uint16_t                dev_hdl;
 857         uint16_t                pdev_hdl;
 858         uint16_t                bay_num, enclosure, io_flags;
 859         char                    attached_wwnstr[MPTSAS_WWN_STRLEN];
 860 
 861         /* CONSTCOND */
 862         ASSERT(NO_COMPETING_THREADS);
 863 
 864         switch (cmd) {
 865         case DDI_ATTACH:
 866                 break;
 867 
 868         case DDI_RESUME:
 869                 /*
 870                  * If this a scsi-iport node, nothing to do here.
 871                  */
 872                 return (DDI_SUCCESS);
 873 
 874         default:
 875                 return (DDI_FAILURE);
 876         }
 877 
 878         pdip = ddi_get_parent(dip);
 879 
 880         if ((hba_tran = ndi_flavorv_get(pdip, SCSA_FLAVOR_SCSI_DEVICE)) ==
 881             NULL) {
 882                 cmn_err(CE_WARN, "Failed attach iport because fail to "
 883                     "get tran vector for the HBA node");
 884                 return (DDI_FAILURE);
 885         }
 886 
 887         mpt = TRAN2MPT(hba_tran);
 888         ASSERT(mpt != NULL);
 889         if (mpt == NULL)
 890                 return (DDI_FAILURE);
 891 
 892         if ((hba_tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) ==
 893             NULL) {
 894                 mptsas_log(mpt, CE_WARN, "Failed attach iport because fail to "
 895                     "get tran vector for the iport node");
 896                 return (DDI_FAILURE);
 897         }
 898 
 899         /*
 900          * Overwrite parent's tran_hba_private to iport's tran vector
 901          */
 902         hba_tran->tran_hba_private = mpt;
 903 
 904         ddi_report_dev(dip);
 905 
 906         /*
 907          * Get SAS address for initiator port according dev_handle
 908          */
 909         iport = ddi_get_name_addr(dip);
 910         if (iport && strncmp(iport, "v0", 2) == 0) {
 911                 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 912                     MPTSAS_VIRTUAL_PORT, 1) !=
 913                     DDI_PROP_SUCCESS) {
 914                         (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
 915                             MPTSAS_VIRTUAL_PORT);
 916                         mptsas_log(mpt, CE_WARN, "mptsas virtual port "
 917                             "prop update failed");
 918                         return (DDI_FAILURE);
 919                 }
 920                 return (DDI_SUCCESS);
 921         }
 922 
 923         mutex_enter(&mpt->m_mutex);
 924         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 925                 bzero(phymask, sizeof (phymask));
 926                 (void) sprintf(phymask,
 927                     "%x", mpt->m_phy_info[i].phy_mask);
 928                 if (strcmp(phymask, iport) == 0) {
 929                         break;
 930                 }
 931         }
 932 
 933         if (i == MPTSAS_MAX_PHYS) {
 934                 mptsas_log(mpt, CE_WARN, "Failed attach port %s because port"
 935                     "seems not exist", iport);
 936                 mutex_exit(&mpt->m_mutex);
 937                 return (DDI_FAILURE);
 938         }
 939 
 940         phy_mask = mpt->m_phy_info[i].phy_mask;
 941 
 942         if (mpt->m_phy_info[i].port_flags & AUTO_PORT_CONFIGURATION)
 943                 dynamic_port = 1;
 944         else
 945                 dynamic_port = 0;
 946 
 947         /*
 948          * Update PHY info for smhba
 949          */
 950         if (mptsas_smhba_phy_init(mpt)) {
 951                 mutex_exit(&mpt->m_mutex);
 952                 mptsas_log(mpt, CE_WARN, "mptsas phy update "
 953                     "failed");
 954                 return (DDI_FAILURE);
 955         }
 956 
 957         mutex_exit(&mpt->m_mutex);
 958 
 959         numphys = 0;
 960         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 961                 if ((phy_mask >> i) & 0x01) {
 962                         numphys++;
 963                 }
 964         }
 965 
 966         bzero(initiator_wwnstr, sizeof (initiator_wwnstr));
 967         (void) sprintf(initiator_wwnstr, "w%016"PRIx64,
 968             mpt->un.m_base_wwid);
 969 
 970         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
 971             SCSI_ADDR_PROP_INITIATOR_PORT, initiator_wwnstr) !=
 972             DDI_PROP_SUCCESS) {
 973                 (void) ddi_prop_remove(DDI_DEV_T_NONE,
 974                     dip, SCSI_ADDR_PROP_INITIATOR_PORT);
 975                 mptsas_log(mpt, CE_WARN, "mptsas Initiator port "
 976                     "prop update failed");
 977                 return (DDI_FAILURE);
 978         }
 979         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 980             MPTSAS_NUM_PHYS, numphys) !=
 981             DDI_PROP_SUCCESS) {
 982                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, MPTSAS_NUM_PHYS);
 983                 return (DDI_FAILURE);
 984         }
 985 
 986         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 987             "phymask", phy_mask) !=
 988             DDI_PROP_SUCCESS) {
 989                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "phymask");
 990                 mptsas_log(mpt, CE_WARN, "mptsas phy mask "
 991                     "prop update failed");
 992                 return (DDI_FAILURE);
 993         }
 994 
 995         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 996             "dynamic-port", dynamic_port) !=
 997             DDI_PROP_SUCCESS) {
 998                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "dynamic-port");
 999                 mptsas_log(mpt, CE_WARN, "mptsas dynamic port "
1000                     "prop update failed");
1001                 return (DDI_FAILURE);
1002         }
1003         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
1004             MPTSAS_VIRTUAL_PORT, 0) !=
1005             DDI_PROP_SUCCESS) {
1006                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
1007                     MPTSAS_VIRTUAL_PORT);
1008                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
1009                     "prop update failed");
1010                 return (DDI_FAILURE);
1011         }
1012         mptsas_smhba_set_all_phy_props(mpt, dip, numphys, phy_mask,
1013             &attached_devhdl);
1014 
1015         mutex_enter(&mpt->m_mutex);
1016         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
1017             MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)attached_devhdl;
1018         rval = mptsas_get_sas_device_page0(mpt, page_address, &dev_hdl,
1019             &attached_sas_wwn, &dev_info, &phy_port, &phy_id,
1020             &pdev_hdl, &bay_num, &enclosure, &io_flags);
1021         if (rval != DDI_SUCCESS) {
1022                 mptsas_log(mpt, CE_WARN,
1023                     "Failed to get device page0 for handle:%d",
1024                     attached_devhdl);
1025                 mutex_exit(&mpt->m_mutex);
1026                 return (DDI_FAILURE);
1027         }
1028 
1029         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1030                 bzero(phymask, sizeof (phymask));
1031                 (void) sprintf(phymask, "%x", mpt->m_phy_info[i].phy_mask);
1032                 if (strcmp(phymask, iport) == 0) {
1033                         (void) sprintf(&mpt->m_phy_info[i].smhba_info.path[0],
1034                             "%x",
1035                             mpt->m_phy_info[i].phy_mask);
1036                 }
1037         }
1038         mutex_exit(&mpt->m_mutex);
1039 
1040         bzero(attached_wwnstr, sizeof (attached_wwnstr));
1041         (void) sprintf(attached_wwnstr, "w%016"PRIx64,
1042             attached_sas_wwn);
1043         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
1044             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
1045             DDI_PROP_SUCCESS) {
1046                 (void) ddi_prop_remove(DDI_DEV_T_NONE,
1047                     dip, SCSI_ADDR_PROP_ATTACHED_PORT);
1048                 return (DDI_FAILURE);
1049         }
1050 
1051         /* Create kstats for each phy on this iport */
1052 
1053         mptsas_create_phy_stats(mpt, iport, dip);
1054 
1055         /*
1056          * register sas hba iport with mdi (MPxIO/vhci)
1057          */
1058         if (mdi_phci_register(MDI_HCI_CLASS_SCSI,
1059             dip, 0) == MDI_SUCCESS) {
1060                 mpt->m_mpxio_enable = TRUE;
1061         }
1062         return (DDI_SUCCESS);
1063 }
1064 
1065 /*
1066  * Notes:
1067  *      Set up all device state and allocate data structures,
1068  *      mutexes, condition variables, etc. for device operation.
1069  *      Add interrupts needed.
1070  *      Return DDI_SUCCESS if device is ready, else return DDI_FAILURE.
1071  */
1072 static int
1073 mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1074 {
1075         mptsas_t                *mpt = NULL;
1076         int                     instance, i, j;
1077         int                     doneq_thread_num;
1078         char                    intr_added = 0;
1079         char                    map_setup = 0;
1080         char                    config_setup = 0;
1081         char                    hba_attach_setup = 0;
1082         char                    smp_attach_setup = 0;
1083         char                    mutex_init_done = 0;
1084         char                    event_taskq_create = 0;
1085         char                    dr_taskq_create = 0;
1086         char                    doneq_thread_create = 0;
1087         char                    added_watchdog = 0;
1088         scsi_hba_tran_t         *hba_tran;
1089         uint_t                  mem_bar = MEM_SPACE;
1090         int                     rval = DDI_FAILURE;
1091 
1092         /* CONSTCOND */
1093         ASSERT(NO_COMPETING_THREADS);
1094 
1095         if (scsi_hba_iport_unit_address(dip)) {
1096                 return (mptsas_iport_attach(dip, cmd));
1097         }
1098 
1099         switch (cmd) {
1100         case DDI_ATTACH:
1101                 break;
1102 
1103         case DDI_RESUME:
1104                 if ((hba_tran = ddi_get_driver_private(dip)) == NULL)
1105                         return (DDI_FAILURE);
1106 
1107                 mpt = TRAN2MPT(hba_tran);
1108 
1109                 if (!mpt) {
1110                         return (DDI_FAILURE);
1111                 }
1112 
1113                 /*
1114                  * Reset hardware and softc to "no outstanding commands"
1115                  * Note that a check condition can result on first command
1116                  * to a target.
1117                  */
1118                 mutex_enter(&mpt->m_mutex);
1119 
1120                 /*
1121                  * raise power.
1122                  */
1123                 if (mpt->m_options & MPTSAS_OPT_PM) {
1124                         mutex_exit(&mpt->m_mutex);
1125                         (void) pm_busy_component(dip, 0);
1126                         rval = pm_power_has_changed(dip, 0, PM_LEVEL_D0);
1127                         if (rval == DDI_SUCCESS) {
1128                                 mutex_enter(&mpt->m_mutex);
1129                         } else {
1130                                 /*
1131                                  * The pm_raise_power() call above failed,
1132                                  * and that can only occur if we were unable
1133                                  * to reset the hardware.  This is probably
1134                                  * due to unhealty hardware, and because
1135                                  * important filesystems(such as the root
1136                                  * filesystem) could be on the attached disks,
1137                                  * it would not be a good idea to continue,
1138                                  * as we won't be entirely certain we are
1139                                  * writing correct data.  So we panic() here
1140                                  * to not only prevent possible data corruption,
1141                                  * but to give developers or end users a hope
1142                                  * of identifying and correcting any problems.
1143                                  */
1144                                 fm_panic("mptsas could not reset hardware "
1145                                     "during resume");
1146                         }
1147                 }
1148 
1149                 mpt->m_suspended = 0;
1150 
1151                 /*
1152                  * Reinitialize ioc
1153                  */
1154                 mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1155                 if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
1156                         mutex_exit(&mpt->m_mutex);
1157                         if (mpt->m_options & MPTSAS_OPT_PM) {
1158                                 (void) pm_idle_component(dip, 0);
1159                         }
1160                         fm_panic("mptsas init chip fail during resume");
1161                 }
1162                 /*
1163                  * mptsas_update_driver_data needs interrupts so enable them
1164                  * first.
1165                  */
1166                 MPTSAS_ENABLE_INTR(mpt);
1167                 mptsas_update_driver_data(mpt);
1168 
1169                 /* start requests, if possible */
1170                 mptsas_restart_hba(mpt);
1171 
1172                 mutex_exit(&mpt->m_mutex);
1173 
1174                 /*
1175                  * Restart watch thread
1176                  */
1177                 mutex_enter(&mptsas_global_mutex);
1178                 if (mptsas_timeout_id == 0) {
1179                         mptsas_timeout_id = timeout(mptsas_watch, NULL,
1180                             mptsas_tick);
1181                         mptsas_timeouts_enabled = 1;
1182                 }
1183                 mutex_exit(&mptsas_global_mutex);
1184 
1185                 /* report idle status to pm framework */
1186                 if (mpt->m_options & MPTSAS_OPT_PM) {
1187                         (void) pm_idle_component(dip, 0);
1188                 }
1189 
1190                 return (DDI_SUCCESS);
1191 
1192         default:
1193                 return (DDI_FAILURE);
1194 
1195         }
1196 
1197         instance = ddi_get_instance(dip);
1198 
1199         /*
1200          * Allocate softc information.
1201          */
1202         if (ddi_soft_state_zalloc(mptsas_state, instance) != DDI_SUCCESS) {
1203                 mptsas_log(NULL, CE_WARN,
1204                     "mptsas%d: cannot allocate soft state", instance);
1205                 goto fail;
1206         }
1207 
1208         mpt = ddi_get_soft_state(mptsas_state, instance);
1209 
1210         if (mpt == NULL) {
1211                 mptsas_log(NULL, CE_WARN,
1212                     "mptsas%d: cannot get soft state", instance);
1213                 goto fail;
1214         }
1215 
1216         /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
1217         scsi_size_clean(dip);
1218 
1219         mpt->m_dip = dip;
1220         mpt->m_instance = instance;
1221 
1222         /* Make a per-instance copy of the structures */
1223         mpt->m_io_dma_attr = mptsas_dma_attrs64;
1224         if (mptsas_use_64bit_msgaddr) {
1225                 mpt->m_msg_dma_attr = mptsas_dma_attrs64;
1226         } else {
1227                 mpt->m_msg_dma_attr = mptsas_dma_attrs;
1228         }
1229         mpt->m_reg_acc_attr = mptsas_dev_attr;
1230         mpt->m_dev_acc_attr = mptsas_dev_attr;
1231 
1232         /*
1233          * Size of individual request sense buffer
1234          */
1235         mpt->m_req_sense_size = EXTCMDS_STATUS_SIZE;
1236 
1237         /*
1238          * Initialize FMA
1239          */
1240         mpt->m_fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, mpt->m_dip,
1241             DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
1242             DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
1243             DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
1244 
1245         mptsas_fm_init(mpt);
1246 
1247         if (mptsas_alloc_handshake_msg(mpt,
1248             sizeof (Mpi2SCSITaskManagementRequest_t)) == DDI_FAILURE) {
1249                 mptsas_log(mpt, CE_WARN, "cannot initialize handshake msg.");
1250                 goto fail;
1251         }
1252 
1253         /*
1254          * Setup configuration space
1255          */
1256         if (mptsas_config_space_init(mpt) == FALSE) {
1257                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init failed");
1258                 goto fail;
1259         }
1260         config_setup++;
1261 
1262         if (ddi_regs_map_setup(dip, mem_bar, (caddr_t *)&mpt->m_reg,
1263             0, 0, &mpt->m_reg_acc_attr, &mpt->m_datap) != DDI_SUCCESS) {
1264                 mptsas_log(mpt, CE_WARN, "map setup failed");
1265                 goto fail;
1266         }
1267         map_setup++;
1268 
1269         /*
1270          * A taskq is created for dealing with the event handler
1271          */
1272         if ((mpt->m_event_taskq = ddi_taskq_create(dip, "mptsas_event_taskq",
1273             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1274                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create failed");
1275                 goto fail;
1276         }
1277         event_taskq_create++;
1278 
1279         /*
1280          * A taskq is created for dealing with dr events
1281          */
1282         if ((mpt->m_dr_taskq = ddi_taskq_create(dip,
1283             "mptsas_dr_taskq",
1284             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1285                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create for discovery "
1286                     "failed");
1287                 goto fail;
1288         }
1289         dr_taskq_create++;
1290 
1291         mpt->m_doneq_thread_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1292             0, "mptsas_doneq_thread_threshold_prop", 10);
1293         mpt->m_doneq_length_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1294             0, "mptsas_doneq_length_threshold_prop", 8);
1295         mpt->m_doneq_thread_n = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1296             0, "mptsas_doneq_thread_n_prop", 8);
1297 
1298         if (mpt->m_doneq_thread_n) {
1299                 cv_init(&mpt->m_doneq_thread_cv, NULL, CV_DRIVER, NULL);
1300                 mutex_init(&mpt->m_doneq_mutex, NULL, MUTEX_DRIVER, NULL);
1301 
1302                 mutex_enter(&mpt->m_doneq_mutex);
1303                 mpt->m_doneq_thread_id =
1304                     kmem_zalloc(sizeof (mptsas_doneq_thread_list_t)
1305                     * mpt->m_doneq_thread_n, KM_SLEEP);
1306 
1307                 for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1308                         cv_init(&mpt->m_doneq_thread_id[j].cv, NULL,
1309                             CV_DRIVER, NULL);
1310                         mutex_init(&mpt->m_doneq_thread_id[j].mutex, NULL,
1311                             MUTEX_DRIVER, NULL);
1312                         mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1313                         mpt->m_doneq_thread_id[j].flag |=
1314                             MPTSAS_DONEQ_THREAD_ACTIVE;
1315                         mpt->m_doneq_thread_id[j].arg.mpt = mpt;
1316                         mpt->m_doneq_thread_id[j].arg.t = j;
1317                         mpt->m_doneq_thread_id[j].threadp =
1318                             thread_create(NULL, 0, mptsas_doneq_thread,
1319                             &mpt->m_doneq_thread_id[j].arg,
1320                             0, &p0, TS_RUN, minclsyspri);
1321                         mpt->m_doneq_thread_id[j].donetail =
1322                             &mpt->m_doneq_thread_id[j].doneq;
1323                         mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1324                 }
1325                 mutex_exit(&mpt->m_doneq_mutex);
1326                 doneq_thread_create++;
1327         }
1328 
1329         /*
1330          * Disable hardware interrupt since we're not ready to
1331          * handle it yet.
1332          */
1333         MPTSAS_DISABLE_INTR(mpt);
1334         if (mptsas_register_intrs(mpt) == FALSE)
1335                 goto fail;
1336         intr_added++;
1337 
1338         /* Initialize mutex used in interrupt handler */
1339         mutex_init(&mpt->m_mutex, NULL, MUTEX_DRIVER,
1340             DDI_INTR_PRI(mpt->m_intr_pri));
1341         mutex_init(&mpt->m_passthru_mutex, NULL, MUTEX_DRIVER, NULL);
1342         mutex_init(&mpt->m_tx_waitq_mutex, NULL, MUTEX_DRIVER,
1343             DDI_INTR_PRI(mpt->m_intr_pri));
1344         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1345                 mutex_init(&mpt->m_phy_info[i].smhba_info.phy_mutex,
1346                     NULL, MUTEX_DRIVER,
1347                     DDI_INTR_PRI(mpt->m_intr_pri));
1348         }
1349 
1350         cv_init(&mpt->m_cv, NULL, CV_DRIVER, NULL);
1351         cv_init(&mpt->m_passthru_cv, NULL, CV_DRIVER, NULL);
1352         cv_init(&mpt->m_fw_cv, NULL, CV_DRIVER, NULL);
1353         cv_init(&mpt->m_config_cv, NULL, CV_DRIVER, NULL);
1354         cv_init(&mpt->m_fw_diag_cv, NULL, CV_DRIVER, NULL);
1355         mutex_init_done++;
1356 
1357         mutex_enter(&mpt->m_mutex);
1358         /*
1359          * Initialize power management component
1360          */
1361         if (mpt->m_options & MPTSAS_OPT_PM) {
1362                 if (mptsas_init_pm(mpt)) {
1363                         mutex_exit(&mpt->m_mutex);
1364                         mptsas_log(mpt, CE_WARN, "mptsas pm initialization "
1365                             "failed");
1366                         goto fail;
1367                 }
1368         }
1369 
1370         /*
1371          * Initialize chip using Message Unit Reset, if allowed
1372          */
1373         mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1374         if (mptsas_init_chip(mpt, TRUE) == DDI_FAILURE) {
1375                 mutex_exit(&mpt->m_mutex);
1376                 mptsas_log(mpt, CE_WARN, "mptsas chip initialization failed");
1377                 goto fail;
1378         }
1379 
1380         mpt->m_targets = refhash_create(MPTSAS_TARGET_BUCKET_COUNT,
1381             mptsas_target_addr_hash, mptsas_target_addr_cmp,
1382             mptsas_target_free, sizeof (mptsas_target_t),
1383             offsetof(mptsas_target_t, m_link),
1384             offsetof(mptsas_target_t, m_addr), KM_SLEEP);
1385 
1386         /*
1387          * The refhash for temporary targets uses the address of the target
1388          * struct itself as tag, so the tag offset is 0. See the implementation
1389          * of mptsas_tmp_target_hash() and mptsas_tmp_target_cmp().
1390          */
1391         mpt->m_tmp_targets = refhash_create(MPTSAS_TMP_TARGET_BUCKET_COUNT,
1392             mptsas_tmp_target_hash, mptsas_tmp_target_cmp,
1393             mptsas_target_free, sizeof (mptsas_target_t),
1394             offsetof(mptsas_target_t, m_link), 0, KM_SLEEP);
1395 
1396         /*
1397          * Fill in the phy_info structure and get the base WWID
1398          */
1399         if (mptsas_get_manufacture_page5(mpt) == DDI_FAILURE) {
1400                 mptsas_log(mpt, CE_WARN,
1401                     "mptsas_get_manufacture_page5 failed!");
1402                 goto fail;
1403         }
1404 
1405         if (mptsas_get_sas_io_unit_page_hndshk(mpt)) {
1406                 mptsas_log(mpt, CE_WARN,
1407                     "mptsas_get_sas_io_unit_page_hndshk failed!");
1408                 goto fail;
1409         }
1410 
1411         if (mptsas_get_manufacture_page0(mpt) == DDI_FAILURE) {
1412                 mptsas_log(mpt, CE_WARN,
1413                     "mptsas_get_manufacture_page0 failed!");
1414                 goto fail;
1415         }
1416 
1417         mutex_exit(&mpt->m_mutex);
1418 
1419         /*
1420          * Register the iport for multiple port HBA
1421          */
1422         mptsas_iport_register(mpt);
1423 
1424         /*
1425          * initialize SCSI HBA transport structure
1426          */
1427         if (mptsas_hba_setup(mpt) == FALSE)
1428                 goto fail;
1429         hba_attach_setup++;
1430 
1431         if (mptsas_smp_setup(mpt) == FALSE)
1432                 goto fail;
1433         smp_attach_setup++;
1434 
1435         if (mptsas_cache_create(mpt) == FALSE)
1436                 goto fail;
1437 
1438         mpt->m_scsi_reset_delay      = ddi_prop_get_int(DDI_DEV_T_ANY,
1439             dip, 0, "scsi-reset-delay", SCSI_DEFAULT_RESET_DELAY);
1440         if (mpt->m_scsi_reset_delay == 0) {
1441                 mptsas_log(mpt, CE_NOTE,
1442                     "scsi_reset_delay of 0 is not recommended,"
1443                     " resetting to SCSI_DEFAULT_RESET_DELAY\n");
1444                 mpt->m_scsi_reset_delay = SCSI_DEFAULT_RESET_DELAY;
1445         }
1446 
1447         /*
1448          * Initialize the wait and done FIFO queue
1449          */
1450         mpt->m_donetail = &mpt->m_doneq;
1451         mpt->m_waitqtail = &mpt->m_waitq;
1452         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
1453         mpt->m_tx_draining = 0;
1454 
1455         /*
1456          * ioc cmd queue initialize
1457          */
1458         mpt->m_ioc_event_cmdtail = &mpt->m_ioc_event_cmdq;
1459         mpt->m_dev_handle = 0xFFFF;
1460 
1461         MPTSAS_ENABLE_INTR(mpt);
1462 
1463         /*
1464          * enable event notification
1465          */
1466         mutex_enter(&mpt->m_mutex);
1467         if (mptsas_ioc_enable_event_notification(mpt)) {
1468                 mutex_exit(&mpt->m_mutex);
1469                 goto fail;
1470         }
1471         mutex_exit(&mpt->m_mutex);
1472 
1473         /*
1474          * used for mptsas_watch
1475          */
1476         mptsas_list_add(mpt);
1477 
1478         mutex_enter(&mptsas_global_mutex);
1479         if (mptsas_timeouts_enabled == 0) {
1480                 mptsas_scsi_watchdog_tick = ddi_prop_get_int(DDI_DEV_T_ANY,
1481                     dip, 0, "scsi-watchdog-tick", DEFAULT_WD_TICK);
1482 
1483                 mptsas_tick = mptsas_scsi_watchdog_tick *
1484                     drv_usectohz((clock_t)1000000);
1485 
1486                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
1487                 mptsas_timeouts_enabled = 1;
1488         }
1489         mutex_exit(&mptsas_global_mutex);
1490         added_watchdog++;
1491 
1492         /*
1493          * Initialize PHY info for smhba.
1494          * This requires watchdog to be enabled otherwise if interrupts
1495          * don't work the system will hang.
1496          */
1497         if (mptsas_smhba_setup(mpt)) {
1498                 mptsas_log(mpt, CE_WARN, "mptsas phy initialization "
1499                     "failed");
1500                 goto fail;
1501         }
1502 
1503         /* Check all dma handles allocated in attach */
1504         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl)
1505             != DDI_SUCCESS) ||
1506             (mptsas_check_dma_handle(mpt->m_dma_req_sense_hdl)
1507             != DDI_SUCCESS) ||
1508             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl)
1509             != DDI_SUCCESS) ||
1510             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl)
1511             != DDI_SUCCESS) ||
1512             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl)
1513             != DDI_SUCCESS) ||
1514             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl)
1515             != DDI_SUCCESS)) {
1516                 goto fail;
1517         }
1518 
1519         /* Check all acc handles allocated in attach */
1520         if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
1521             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl)
1522             != DDI_SUCCESS) ||
1523             (mptsas_check_acc_handle(mpt->m_acc_req_sense_hdl)
1524             != DDI_SUCCESS) ||
1525             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl)
1526             != DDI_SUCCESS) ||
1527             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl)
1528             != DDI_SUCCESS) ||
1529             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl)
1530             != DDI_SUCCESS) ||
1531             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl)
1532             != DDI_SUCCESS) ||
1533             (mptsas_check_acc_handle(mpt->m_config_handle)
1534             != DDI_SUCCESS)) {
1535                 goto fail;
1536         }
1537 
1538         /*
1539          * After this point, we are not going to fail the attach.
1540          */
1541 
1542         /* Print message of HBA present */
1543         ddi_report_dev(dip);
1544 
1545         /* report idle status to pm framework */
1546         if (mpt->m_options & MPTSAS_OPT_PM) {
1547                 (void) pm_idle_component(dip, 0);
1548         }
1549 
1550         return (DDI_SUCCESS);
1551 
1552 fail:
1553         mptsas_log(mpt, CE_WARN, "attach failed");
1554         mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
1555         ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
1556         if (mpt) {
1557                 /* deallocate in reverse order */
1558                 if (added_watchdog) {
1559                         mptsas_list_del(mpt);
1560                         mutex_enter(&mptsas_global_mutex);
1561 
1562                         if (mptsas_timeout_id && (mptsas_head == NULL)) {
1563                                 timeout_id_t tid = mptsas_timeout_id;
1564                                 mptsas_timeouts_enabled = 0;
1565                                 mptsas_timeout_id = 0;
1566                                 mutex_exit(&mptsas_global_mutex);
1567                                 (void) untimeout(tid);
1568                                 mutex_enter(&mptsas_global_mutex);
1569                         }
1570                         mutex_exit(&mptsas_global_mutex);
1571                 }
1572 
1573                 mptsas_cache_destroy(mpt);
1574 
1575                 if (smp_attach_setup) {
1576                         mptsas_smp_teardown(mpt);
1577                 }
1578                 if (hba_attach_setup) {
1579                         mptsas_hba_teardown(mpt);
1580                 }
1581 
1582                 if (mpt->m_tmp_targets)
1583                         refhash_destroy(mpt->m_tmp_targets);
1584                 if (mpt->m_targets)
1585                         refhash_destroy(mpt->m_targets);
1586                 if (mpt->m_smp_targets)
1587                         refhash_destroy(mpt->m_smp_targets);
1588 
1589                 if (mpt->m_active) {
1590                         mptsas_free_active_slots(mpt);
1591                 }
1592                 if (intr_added) {
1593                         mptsas_unregister_intrs(mpt);
1594                 }
1595 
1596                 if (doneq_thread_create) {
1597                         mutex_enter(&mpt->m_doneq_mutex);
1598                         doneq_thread_num = mpt->m_doneq_thread_n;
1599                         for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1600                                 mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1601                                 mpt->m_doneq_thread_id[j].flag &=
1602                                     (~MPTSAS_DONEQ_THREAD_ACTIVE);
1603                                 cv_signal(&mpt->m_doneq_thread_id[j].cv);
1604                                 mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1605                         }
1606                         while (mpt->m_doneq_thread_n) {
1607                                 cv_wait(&mpt->m_doneq_thread_cv,
1608                                     &mpt->m_doneq_mutex);
1609                         }
1610                         for (j = 0; j < doneq_thread_num; j++) {
1611                                 cv_destroy(&mpt->m_doneq_thread_id[j].cv);
1612                                 mutex_destroy(&mpt->m_doneq_thread_id[j].mutex);
1613                         }
1614                         kmem_free(mpt->m_doneq_thread_id,
1615                             sizeof (mptsas_doneq_thread_list_t)
1616                             * doneq_thread_num);
1617                         mutex_exit(&mpt->m_doneq_mutex);
1618                         cv_destroy(&mpt->m_doneq_thread_cv);
1619                         mutex_destroy(&mpt->m_doneq_mutex);
1620                 }
1621                 if (event_taskq_create) {
1622                         ddi_taskq_destroy(mpt->m_event_taskq);
1623                 }
1624                 if (dr_taskq_create) {
1625                         ddi_taskq_destroy(mpt->m_dr_taskq);
1626                 }
1627                 if (mutex_init_done) {
1628                         mutex_destroy(&mpt->m_tx_waitq_mutex);
1629                         mutex_destroy(&mpt->m_passthru_mutex);
1630                         mutex_destroy(&mpt->m_mutex);
1631                         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1632                                 mutex_destroy(
1633                                     &mpt->m_phy_info[i].smhba_info.phy_mutex);
1634                         }
1635                         cv_destroy(&mpt->m_cv);
1636                         cv_destroy(&mpt->m_passthru_cv);
1637                         cv_destroy(&mpt->m_fw_cv);
1638                         cv_destroy(&mpt->m_config_cv);
1639                         cv_destroy(&mpt->m_fw_diag_cv);
1640                 }
1641 
1642                 if (map_setup) {
1643                         mptsas_cfg_fini(mpt);
1644                 }
1645                 if (config_setup) {
1646                         mptsas_config_space_fini(mpt);
1647                 }
1648                 mptsas_free_handshake_msg(mpt);
1649                 mptsas_hba_fini(mpt);
1650 
1651                 mptsas_fm_fini(mpt);
1652                 ddi_soft_state_free(mptsas_state, instance);
1653                 ddi_prop_remove_all(dip);
1654         }
1655         return (DDI_FAILURE);
1656 }
1657 
1658 static int
1659 mptsas_suspend(dev_info_t *devi)
1660 {
1661         mptsas_t        *mpt, *g;
1662         scsi_hba_tran_t *tran;
1663 
1664         if (scsi_hba_iport_unit_address(devi)) {
1665                 return (DDI_SUCCESS);
1666         }
1667 
1668         if ((tran = ddi_get_driver_private(devi)) == NULL)
1669                 return (DDI_SUCCESS);
1670 
1671         mpt = TRAN2MPT(tran);
1672         if (!mpt) {
1673                 return (DDI_SUCCESS);
1674         }
1675 
1676         mutex_enter(&mpt->m_mutex);
1677 
1678         if (mpt->m_suspended++) {
1679                 mutex_exit(&mpt->m_mutex);
1680                 return (DDI_SUCCESS);
1681         }
1682 
1683         /*
1684          * Cancel timeout threads for this mpt
1685          */
1686         if (mpt->m_quiesce_timeid) {
1687                 timeout_id_t tid = mpt->m_quiesce_timeid;
1688                 mpt->m_quiesce_timeid = 0;
1689                 mutex_exit(&mpt->m_mutex);
1690                 (void) untimeout(tid);
1691                 mutex_enter(&mpt->m_mutex);
1692         }
1693 
1694         if (mpt->m_restart_cmd_timeid) {
1695                 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1696                 mpt->m_restart_cmd_timeid = 0;
1697                 mutex_exit(&mpt->m_mutex);
1698                 (void) untimeout(tid);
1699                 mutex_enter(&mpt->m_mutex);
1700         }
1701 
1702         mutex_exit(&mpt->m_mutex);
1703 
1704         (void) pm_idle_component(mpt->m_dip, 0);
1705 
1706         /*
1707          * Cancel watch threads if all mpts suspended
1708          */
1709         rw_enter(&mptsas_global_rwlock, RW_WRITER);
1710         for (g = mptsas_head; g != NULL; g = g->m_next) {
1711                 if (!g->m_suspended)
1712                         break;
1713         }
1714         rw_exit(&mptsas_global_rwlock);
1715 
1716         mutex_enter(&mptsas_global_mutex);
1717         if (g == NULL) {
1718                 timeout_id_t tid;
1719 
1720                 mptsas_timeouts_enabled = 0;
1721                 if (mptsas_timeout_id) {
1722                         tid = mptsas_timeout_id;
1723                         mptsas_timeout_id = 0;
1724                         mutex_exit(&mptsas_global_mutex);
1725                         (void) untimeout(tid);
1726                         mutex_enter(&mptsas_global_mutex);
1727                 }
1728                 if (mptsas_reset_watch) {
1729                         tid = mptsas_reset_watch;
1730                         mptsas_reset_watch = 0;
1731                         mutex_exit(&mptsas_global_mutex);
1732                         (void) untimeout(tid);
1733                         mutex_enter(&mptsas_global_mutex);
1734                 }
1735         }
1736         mutex_exit(&mptsas_global_mutex);
1737 
1738         mutex_enter(&mpt->m_mutex);
1739 
1740         /*
1741          * If this mpt is not in full power(PM_LEVEL_D0), just return.
1742          */
1743         if ((mpt->m_options & MPTSAS_OPT_PM) &&
1744             (mpt->m_power_level != PM_LEVEL_D0)) {
1745                 mutex_exit(&mpt->m_mutex);
1746                 return (DDI_SUCCESS);
1747         }
1748 
1749         /* Disable HBA interrupts in hardware */
1750         MPTSAS_DISABLE_INTR(mpt);
1751         /*
1752          * Send RAID action system shutdown to sync IR
1753          */
1754         mptsas_raid_action_system_shutdown(mpt);
1755 
1756         mutex_exit(&mpt->m_mutex);
1757 
1758         /* drain the taskq */
1759         ddi_taskq_wait(mpt->m_event_taskq);
1760         ddi_taskq_wait(mpt->m_dr_taskq);
1761 
1762         return (DDI_SUCCESS);
1763 }
1764 
1765 #ifdef  __sparc
1766 /*ARGSUSED*/
1767 static int
1768 mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd)
1769 {
1770         mptsas_t        *mpt;
1771         scsi_hba_tran_t *tran;
1772 
1773         /*
1774          * If this call is for iport, just return.
1775          */
1776         if (scsi_hba_iport_unit_address(devi))
1777                 return (DDI_SUCCESS);
1778 
1779         if ((tran = ddi_get_driver_private(devi)) == NULL)
1780                 return (DDI_SUCCESS);
1781 
1782         if ((mpt = TRAN2MPT(tran)) == NULL)
1783                 return (DDI_SUCCESS);
1784 
1785         /*
1786          * Send RAID action system shutdown to sync IR.  Disable HBA
1787          * interrupts in hardware first.
1788          */
1789         MPTSAS_DISABLE_INTR(mpt);
1790         mptsas_raid_action_system_shutdown(mpt);
1791 
1792         return (DDI_SUCCESS);
1793 }
1794 #else /* __sparc */
1795 /*
1796  * quiesce(9E) entry point.
1797  *
1798  * This function is called when the system is single-threaded at high
1799  * PIL with preemption disabled. Therefore, this function must not be
1800  * blocked.
1801  *
1802  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1803  * DDI_FAILURE indicates an error condition and should almost never happen.
1804  */
1805 static int
1806 mptsas_quiesce(dev_info_t *devi)
1807 {
1808         mptsas_t        *mpt;
1809         scsi_hba_tran_t *tran;
1810 
1811         /*
1812          * If this call is for iport, just return.
1813          */
1814         if (scsi_hba_iport_unit_address(devi))
1815                 return (DDI_SUCCESS);
1816 
1817         if ((tran = ddi_get_driver_private(devi)) == NULL)
1818                 return (DDI_SUCCESS);
1819 
1820         if ((mpt = TRAN2MPT(tran)) == NULL)
1821                 return (DDI_SUCCESS);
1822 
1823         /* Disable HBA interrupts in hardware */
1824         MPTSAS_DISABLE_INTR(mpt);
1825         /* Send RAID action system shutdonw to sync IR */
1826         mptsas_raid_action_system_shutdown(mpt);
1827 
1828         return (DDI_SUCCESS);
1829 }
1830 #endif  /* __sparc */
1831 
1832 /*
1833  * detach(9E).  Remove all device allocations and system resources;
1834  * disable device interrupts.
1835  * Return DDI_SUCCESS if done; DDI_FAILURE if there's a problem.
1836  */
1837 static int
1838 mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1839 {
1840         /* CONSTCOND */
1841         ASSERT(NO_COMPETING_THREADS);
1842         NDBG0(("mptsas_detach: dip=0x%p cmd=0x%p", (void *)devi, (void *)cmd));
1843 
1844         switch (cmd) {
1845         case DDI_DETACH:
1846                 return (mptsas_do_detach(devi));
1847 
1848         case DDI_SUSPEND:
1849                 return (mptsas_suspend(devi));
1850 
1851         default:
1852                 return (DDI_FAILURE);
1853         }
1854         /* NOTREACHED */
1855 }
1856 
1857 static int
1858 mptsas_do_detach(dev_info_t *dip)
1859 {
1860         mptsas_t        *mpt;
1861         scsi_hba_tran_t *tran;
1862         int             circ = 0;
1863         int             circ1 = 0;
1864         mdi_pathinfo_t  *pip = NULL;
1865         int             i;
1866         int             doneq_thread_num = 0;
1867 
1868         NDBG0(("mptsas_do_detach: dip=0x%p", (void *)dip));
1869 
1870         if ((tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) == NULL)
1871                 return (DDI_FAILURE);
1872 
1873         mpt = TRAN2MPT(tran);
1874         if (!mpt) {
1875                 return (DDI_FAILURE);
1876         }
1877         /*
1878          * Still have pathinfo child, should not detach mpt driver
1879          */
1880         if (scsi_hba_iport_unit_address(dip)) {
1881                 if (mpt->m_mpxio_enable) {
1882                         /*
1883                          * MPxIO enabled for the iport
1884                          */
1885                         ndi_devi_enter(scsi_vhci_dip, &circ1);
1886                         ndi_devi_enter(dip, &circ);
1887                         while (pip = mdi_get_next_client_path(dip, NULL)) {
1888                                 if (mdi_pi_free(pip, 0) == MDI_SUCCESS) {
1889                                         continue;
1890                                 }
1891                                 ndi_devi_exit(dip, circ);
1892                                 ndi_devi_exit(scsi_vhci_dip, circ1);
1893                                 NDBG12(("detach failed because of "
1894                                     "outstanding path info"));
1895                                 return (DDI_FAILURE);
1896                         }
1897                         ndi_devi_exit(dip, circ);
1898                         ndi_devi_exit(scsi_vhci_dip, circ1);
1899                         (void) mdi_phci_unregister(dip, 0);
1900                 }
1901 
1902                 ddi_prop_remove_all(dip);
1903 
1904                 return (DDI_SUCCESS);
1905         }
1906 
1907         /* Make sure power level is D0 before accessing registers */
1908         if (mpt->m_options & MPTSAS_OPT_PM) {
1909                 (void) pm_busy_component(dip, 0);
1910                 if (mpt->m_power_level != PM_LEVEL_D0) {
1911                         if (pm_raise_power(dip, 0, PM_LEVEL_D0) !=
1912                             DDI_SUCCESS) {
1913                                 mptsas_log(mpt, CE_WARN,
1914                                     "mptsas%d: Raise power request failed.",
1915                                     mpt->m_instance);
1916                                 (void) pm_idle_component(dip, 0);
1917                                 return (DDI_FAILURE);
1918                         }
1919                 }
1920         }
1921 
1922         /*
1923          * Send RAID action system shutdown to sync IR.  After action, send a
1924          * Message Unit Reset. Since after that DMA resource will be freed,
1925          * set ioc to READY state will avoid HBA initiated DMA operation.
1926          */
1927         mutex_enter(&mpt->m_mutex);
1928         MPTSAS_DISABLE_INTR(mpt);
1929         mptsas_raid_action_system_shutdown(mpt);
1930         mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1931         (void) mptsas_ioc_reset(mpt, FALSE);
1932         mutex_exit(&mpt->m_mutex);
1933         mptsas_rem_intrs(mpt);
1934         ddi_taskq_destroy(mpt->m_event_taskq);
1935         ddi_taskq_destroy(mpt->m_dr_taskq);
1936 
1937         if (mpt->m_doneq_thread_n) {
1938                 mutex_enter(&mpt->m_doneq_mutex);
1939                 doneq_thread_num = mpt->m_doneq_thread_n;
1940                 for (i = 0; i < mpt->m_doneq_thread_n; i++) {
1941                         mutex_enter(&mpt->m_doneq_thread_id[i].mutex);
1942                         mpt->m_doneq_thread_id[i].flag &=
1943                             (~MPTSAS_DONEQ_THREAD_ACTIVE);
1944                         cv_signal(&mpt->m_doneq_thread_id[i].cv);
1945                         mutex_exit(&mpt->m_doneq_thread_id[i].mutex);
1946                 }
1947                 while (mpt->m_doneq_thread_n) {
1948                         cv_wait(&mpt->m_doneq_thread_cv,
1949                             &mpt->m_doneq_mutex);
1950                 }
1951                 for (i = 0;  i < doneq_thread_num; i++) {
1952                         cv_destroy(&mpt->m_doneq_thread_id[i].cv);
1953                         mutex_destroy(&mpt->m_doneq_thread_id[i].mutex);
1954                 }
1955                 kmem_free(mpt->m_doneq_thread_id,
1956                     sizeof (mptsas_doneq_thread_list_t)
1957                     * doneq_thread_num);
1958                 mutex_exit(&mpt->m_doneq_mutex);
1959                 cv_destroy(&mpt->m_doneq_thread_cv);
1960                 mutex_destroy(&mpt->m_doneq_mutex);
1961         }
1962 
1963         scsi_hba_reset_notify_tear_down(mpt->m_reset_notify_listf);
1964 
1965         mptsas_list_del(mpt);
1966 
1967         /*
1968          * Cancel timeout threads for this mpt
1969          */
1970         mutex_enter(&mpt->m_mutex);
1971         if (mpt->m_quiesce_timeid) {
1972                 timeout_id_t tid = mpt->m_quiesce_timeid;
1973                 mpt->m_quiesce_timeid = 0;
1974                 mutex_exit(&mpt->m_mutex);
1975                 (void) untimeout(tid);
1976                 mutex_enter(&mpt->m_mutex);
1977         }
1978 
1979         if (mpt->m_restart_cmd_timeid) {
1980                 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1981                 mpt->m_restart_cmd_timeid = 0;
1982                 mutex_exit(&mpt->m_mutex);
1983                 (void) untimeout(tid);
1984                 mutex_enter(&mpt->m_mutex);
1985         }
1986 
1987         mutex_exit(&mpt->m_mutex);
1988 
1989         /*
1990          * last mpt? ... if active, CANCEL watch threads.
1991          */
1992         mutex_enter(&mptsas_global_mutex);
1993         if (mptsas_head == NULL) {
1994                 timeout_id_t tid;
1995                 /*
1996                  * Clear mptsas_timeouts_enable so that the watch thread
1997                  * gets restarted on DDI_ATTACH
1998                  */
1999                 mptsas_timeouts_enabled = 0;
2000                 if (mptsas_timeout_id) {
2001                         tid = mptsas_timeout_id;
2002                         mptsas_timeout_id = 0;
2003                         mutex_exit(&mptsas_global_mutex);
2004                         (void) untimeout(tid);
2005                         mutex_enter(&mptsas_global_mutex);
2006                 }
2007                 if (mptsas_reset_watch) {
2008                         tid = mptsas_reset_watch;
2009                         mptsas_reset_watch = 0;
2010                         mutex_exit(&mptsas_global_mutex);
2011                         (void) untimeout(tid);
2012                         mutex_enter(&mptsas_global_mutex);
2013                 }
2014         }
2015         mutex_exit(&mptsas_global_mutex);
2016 
2017         /*
2018          * Delete Phy stats
2019          */
2020         mptsas_destroy_phy_stats(mpt);
2021 
2022         mptsas_destroy_hashes(mpt);
2023 
2024         /*
2025          * Delete nt_active.
2026          */
2027         mutex_enter(&mpt->m_mutex);
2028         mptsas_free_active_slots(mpt);
2029         mutex_exit(&mpt->m_mutex);
2030 
2031         /* deallocate everything that was allocated in mptsas_attach */
2032         mptsas_cache_destroy(mpt);
2033 
2034         mptsas_hba_fini(mpt);
2035         mptsas_cfg_fini(mpt);
2036 
2037         /* Lower the power informing PM Framework */
2038         if (mpt->m_options & MPTSAS_OPT_PM) {
2039                 if (pm_lower_power(dip, 0, PM_LEVEL_D3) != DDI_SUCCESS)
2040                         mptsas_log(mpt, CE_WARN,
2041                             "!mptsas%d: Lower power request failed "
2042                             "during detach, ignoring.",
2043                             mpt->m_instance);
2044         }
2045 
2046         mutex_destroy(&mpt->m_tx_waitq_mutex);
2047         mutex_destroy(&mpt->m_passthru_mutex);
2048         mutex_destroy(&mpt->m_mutex);
2049         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
2050                 mutex_destroy(&mpt->m_phy_info[i].smhba_info.phy_mutex);
2051         }
2052         cv_destroy(&mpt->m_cv);
2053         cv_destroy(&mpt->m_passthru_cv);
2054         cv_destroy(&mpt->m_fw_cv);
2055         cv_destroy(&mpt->m_config_cv);
2056         cv_destroy(&mpt->m_fw_diag_cv);
2057 
2058 
2059         mptsas_smp_teardown(mpt);
2060         mptsas_hba_teardown(mpt);
2061 
2062         mptsas_config_space_fini(mpt);
2063 
2064         mptsas_free_handshake_msg(mpt);
2065 
2066         mptsas_fm_fini(mpt);
2067         ddi_soft_state_free(mptsas_state, ddi_get_instance(dip));
2068         ddi_prop_remove_all(dip);
2069 
2070         return (DDI_SUCCESS);
2071 }
2072 
2073 static void
2074 mptsas_list_add(mptsas_t *mpt)
2075 {
2076         rw_enter(&mptsas_global_rwlock, RW_WRITER);
2077 
2078         if (mptsas_head == NULL) {
2079                 mptsas_head = mpt;
2080         } else {
2081                 mptsas_tail->m_next = mpt;
2082         }
2083         mptsas_tail = mpt;
2084         rw_exit(&mptsas_global_rwlock);
2085 }
2086 
2087 static void
2088 mptsas_list_del(mptsas_t *mpt)
2089 {
2090         mptsas_t *m;
2091         /*
2092          * Remove device instance from the global linked list
2093          */
2094         rw_enter(&mptsas_global_rwlock, RW_WRITER);
2095         if (mptsas_head == mpt) {
2096                 m = mptsas_head = mpt->m_next;
2097         } else {
2098                 for (m = mptsas_head; m != NULL; m = m->m_next) {
2099                         if (m->m_next == mpt) {
2100                                 m->m_next = mpt->m_next;
2101                                 break;
2102                         }
2103                 }
2104                 if (m == NULL) {
2105                         mptsas_log(mpt, CE_PANIC, "Not in softc list!");
2106                 }
2107         }
2108 
2109         if (mptsas_tail == mpt) {
2110                 mptsas_tail = m;
2111         }
2112         rw_exit(&mptsas_global_rwlock);
2113 }
2114 
2115 static int
2116 mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size)
2117 {
2118         ddi_dma_attr_t  task_dma_attrs;
2119 
2120         mpt->m_hshk_dma_size = 0;
2121         task_dma_attrs = mpt->m_msg_dma_attr;
2122         task_dma_attrs.dma_attr_sgllen = 1;
2123         task_dma_attrs.dma_attr_granular = (uint32_t)(alloc_size);
2124 
2125         /* allocate Task Management ddi_dma resources */
2126         if (mptsas_dma_addr_create(mpt, task_dma_attrs,
2127             &mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl, &mpt->m_hshk_memp,
2128             alloc_size, NULL) == FALSE) {
2129                 return (DDI_FAILURE);
2130         }
2131         mpt->m_hshk_dma_size = alloc_size;
2132 
2133         return (DDI_SUCCESS);
2134 }
2135 
2136 static void
2137 mptsas_free_handshake_msg(mptsas_t *mpt)
2138 {
2139         if (mpt->m_hshk_dma_size == 0)
2140                 return;
2141         mptsas_dma_addr_destroy(&mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl);
2142         mpt->m_hshk_dma_size = 0;
2143 }
2144 
2145 static int
2146 mptsas_hba_setup(mptsas_t *mpt)
2147 {
2148         scsi_hba_tran_t         *hba_tran;
2149         int                     tran_flags;
2150 
2151         /* Allocate a transport structure */
2152         hba_tran = mpt->m_tran = scsi_hba_tran_alloc(mpt->m_dip,
2153             SCSI_HBA_CANSLEEP);
2154         ASSERT(mpt->m_tran != NULL);
2155 
2156         hba_tran->tran_hba_private   = mpt;
2157         hba_tran->tran_tgt_private   = NULL;
2158 
2159         hba_tran->tran_tgt_init              = mptsas_scsi_tgt_init;
2160         hba_tran->tran_tgt_free              = mptsas_scsi_tgt_free;
2161 
2162         hba_tran->tran_start         = mptsas_scsi_start;
2163         hba_tran->tran_reset         = mptsas_scsi_reset;
2164         hba_tran->tran_abort         = mptsas_scsi_abort;
2165         hba_tran->tran_getcap                = mptsas_scsi_getcap;
2166         hba_tran->tran_setcap                = mptsas_scsi_setcap;
2167         hba_tran->tran_init_pkt              = mptsas_scsi_init_pkt;
2168         hba_tran->tran_destroy_pkt   = mptsas_scsi_destroy_pkt;
2169 
2170         hba_tran->tran_dmafree               = mptsas_scsi_dmafree;
2171         hba_tran->tran_sync_pkt              = mptsas_scsi_sync_pkt;
2172         hba_tran->tran_reset_notify  = mptsas_scsi_reset_notify;
2173 
2174         hba_tran->tran_get_bus_addr  = mptsas_get_bus_addr;
2175         hba_tran->tran_get_name              = mptsas_get_name;
2176 
2177         hba_tran->tran_quiesce               = mptsas_scsi_quiesce;
2178         hba_tran->tran_unquiesce     = mptsas_scsi_unquiesce;
2179         hba_tran->tran_bus_reset     = NULL;
2180 
2181         hba_tran->tran_add_eventcall = NULL;
2182         hba_tran->tran_get_eventcookie       = NULL;
2183         hba_tran->tran_post_event    = NULL;
2184         hba_tran->tran_remove_eventcall      = NULL;
2185 
2186         hba_tran->tran_bus_config    = mptsas_bus_config;
2187 
2188         hba_tran->tran_interconnect_type = INTERCONNECT_SAS;
2189 
2190         /*
2191          * All children of the HBA are iports. We need tran was cloned.
2192          * So we pass the flags to SCSA. SCSI_HBA_TRAN_CLONE will be
2193          * inherited to iport's tran vector.
2194          */
2195         tran_flags = (SCSI_HBA_HBA | SCSI_HBA_TRAN_CLONE);
2196 
2197         if (scsi_hba_attach_setup(mpt->m_dip, &mpt->m_msg_dma_attr,
2198             hba_tran, tran_flags) != DDI_SUCCESS) {
2199                 mptsas_log(mpt, CE_WARN, "hba attach setup failed");
2200                 scsi_hba_tran_free(hba_tran);
2201                 mpt->m_tran = NULL;
2202                 return (FALSE);
2203         }
2204         return (TRUE);
2205 }
2206 
2207 static void
2208 mptsas_hba_teardown(mptsas_t *mpt)
2209 {
2210         (void) scsi_hba_detach(mpt->m_dip);
2211         if (mpt->m_tran != NULL) {
2212                 scsi_hba_tran_free(mpt->m_tran);
2213                 mpt->m_tran = NULL;
2214         }
2215 }
2216 
2217 static void
2218 mptsas_iport_register(mptsas_t *mpt)
2219 {
2220         int i, j;
2221         mptsas_phymask_t        mask = 0x0;
2222         /*
2223          * initial value of mask is 0
2224          */
2225         mutex_enter(&mpt->m_mutex);
2226         for (i = 0; i < mpt->m_num_phys; i++) {
2227                 mptsas_phymask_t phy_mask = 0x0;
2228                 char phy_mask_name[MPTSAS_MAX_PHYS];
2229                 uint8_t current_port;
2230 
2231                 if (mpt->m_phy_info[i].attached_devhdl == 0)
2232                         continue;
2233 
2234                 bzero(phy_mask_name, sizeof (phy_mask_name));
2235 
2236                 current_port = mpt->m_phy_info[i].port_num;
2237 
2238                 if ((mask & (1 << i)) != 0)
2239                         continue;
2240 
2241                 for (j = 0; j < mpt->m_num_phys; j++) {
2242                         if (mpt->m_phy_info[j].attached_devhdl &&
2243                             (mpt->m_phy_info[j].port_num == current_port)) {
2244                                 phy_mask |= (1 << j);
2245                         }
2246                 }
2247                 mask = mask | phy_mask;
2248 
2249                 for (j = 0; j < mpt->m_num_phys; j++) {
2250                         if ((phy_mask >> j) & 0x01) {
2251                                 mpt->m_phy_info[j].phy_mask = phy_mask;
2252                         }
2253                 }
2254 
2255                 (void) sprintf(phy_mask_name, "%x", phy_mask);
2256 
2257                 mutex_exit(&mpt->m_mutex);
2258                 /*
2259                  * register a iport
2260                  */
2261                 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
2262                 mutex_enter(&mpt->m_mutex);
2263         }
2264         mutex_exit(&mpt->m_mutex);
2265         /*
2266          * register a virtual port for RAID volume always
2267          */
2268         (void) scsi_hba_iport_register(mpt->m_dip, "v0");
2269 
2270 }
2271 
2272 static int
2273 mptsas_smp_setup(mptsas_t *mpt)
2274 {
2275         mpt->m_smptran = smp_hba_tran_alloc(mpt->m_dip);
2276         ASSERT(mpt->m_smptran != NULL);
2277         mpt->m_smptran->smp_tran_hba_private = mpt;
2278         mpt->m_smptran->smp_tran_start = mptsas_smp_start;
2279         if (smp_hba_attach_setup(mpt->m_dip, mpt->m_smptran) != DDI_SUCCESS) {
2280                 mptsas_log(mpt, CE_WARN, "smp attach setup failed");
2281                 smp_hba_tran_free(mpt->m_smptran);
2282                 mpt->m_smptran = NULL;
2283                 return (FALSE);
2284         }
2285         /*
2286          * Initialize smp hash table
2287          */
2288         mpt->m_smp_targets = refhash_create(MPTSAS_SMP_BUCKET_COUNT,
2289             mptsas_target_addr_hash, mptsas_target_addr_cmp,
2290             mptsas_smp_free, sizeof (mptsas_smp_t),
2291             offsetof(mptsas_smp_t, m_link), offsetof(mptsas_smp_t, m_addr),
2292             KM_SLEEP);
2293         mpt->m_smp_devhdl = 0xFFFF;
2294 
2295         return (TRUE);
2296 }
2297 
2298 static void
2299 mptsas_smp_teardown(mptsas_t *mpt)
2300 {
2301         (void) smp_hba_detach(mpt->m_dip);
2302         if (mpt->m_smptran != NULL) {
2303                 smp_hba_tran_free(mpt->m_smptran);
2304                 mpt->m_smptran = NULL;
2305         }
2306         mpt->m_smp_devhdl = 0;
2307 }
2308 
2309 static int
2310 mptsas_cache_create(mptsas_t *mpt)
2311 {
2312         int instance = mpt->m_instance;
2313         char buf[64];
2314 
2315         /*
2316          * create kmem cache for packets
2317          */
2318         (void) sprintf(buf, "mptsas%d_cache", instance);
2319         mpt->m_kmem_cache = kmem_cache_create(buf,
2320             sizeof (struct mptsas_cmd) + scsi_pkt_size(), 8,
2321             mptsas_kmem_cache_constructor, mptsas_kmem_cache_destructor,
2322             NULL, (void *)mpt, NULL, 0);
2323 
2324         if (mpt->m_kmem_cache == NULL) {
2325                 mptsas_log(mpt, CE_WARN, "creating kmem cache failed");
2326                 return (FALSE);
2327         }
2328 
2329         /*
2330          * create kmem cache for extra SGL frames if SGL cannot
2331          * be accomodated into main request frame.
2332          */
2333         (void) sprintf(buf, "mptsas%d_cache_frames", instance);
2334         mpt->m_cache_frames = kmem_cache_create(buf,
2335             sizeof (mptsas_cache_frames_t), 8,
2336             mptsas_cache_frames_constructor, mptsas_cache_frames_destructor,
2337             NULL, (void *)mpt, NULL, 0);
2338 
2339         if (mpt->m_cache_frames == NULL) {
2340                 mptsas_log(mpt, CE_WARN, "creating cache for frames failed");
2341                 return (FALSE);
2342         }
2343 
2344         return (TRUE);
2345 }
2346 
2347 static void
2348 mptsas_cache_destroy(mptsas_t *mpt)
2349 {
2350         /* deallocate in reverse order */
2351         if (mpt->m_cache_frames) {
2352                 kmem_cache_destroy(mpt->m_cache_frames);
2353                 mpt->m_cache_frames = NULL;
2354         }
2355         if (mpt->m_kmem_cache) {
2356                 kmem_cache_destroy(mpt->m_kmem_cache);
2357                 mpt->m_kmem_cache = NULL;
2358         }
2359 }
2360 
2361 static int
2362 mptsas_power(dev_info_t *dip, int component, int level)
2363 {
2364 #ifndef __lock_lint
2365         _NOTE(ARGUNUSED(component))
2366 #endif
2367         mptsas_t        *mpt;
2368         int             rval = DDI_SUCCESS;
2369         int             polls = 0;
2370         uint32_t        ioc_status;
2371 
2372         if (scsi_hba_iport_unit_address(dip) != 0)
2373                 return (DDI_SUCCESS);
2374 
2375         mpt = ddi_get_soft_state(mptsas_state, ddi_get_instance(dip));
2376         if (mpt == NULL) {
2377                 return (DDI_FAILURE);
2378         }
2379 
2380         mutex_enter(&mpt->m_mutex);
2381 
2382         /*
2383          * If the device is busy, don't lower its power level
2384          */
2385         if (mpt->m_busy && (mpt->m_power_level > level)) {
2386                 mutex_exit(&mpt->m_mutex);
2387                 return (DDI_FAILURE);
2388         }
2389         switch (level) {
2390         case PM_LEVEL_D0:
2391                 NDBG11(("mptsas%d: turning power ON.", mpt->m_instance));
2392                 MPTSAS_POWER_ON(mpt);
2393                 /*
2394                  * Wait up to 30 seconds for IOC to come out of reset.
2395                  */
2396                 while (((ioc_status = ddi_get32(mpt->m_datap,
2397                     &mpt->m_reg->Doorbell)) &
2398                     MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_RESET) {
2399                         if (polls++ > 3000) {
2400                                 break;
2401                         }
2402                         delay(drv_usectohz(10000));
2403                 }
2404                 /*
2405                  * If IOC is not in operational state, try to hard reset it.
2406                  */
2407                 if ((ioc_status & MPI2_IOC_STATE_MASK) !=
2408                     MPI2_IOC_STATE_OPERATIONAL) {
2409                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
2410                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
2411                                 mptsas_log(mpt, CE_WARN,
2412                                     "mptsas_power: hard reset failed");
2413                                 mutex_exit(&mpt->m_mutex);
2414                                 return (DDI_FAILURE);
2415                         }
2416                 }
2417                 mpt->m_power_level = PM_LEVEL_D0;
2418                 break;
2419         case PM_LEVEL_D3:
2420                 NDBG11(("mptsas%d: turning power OFF.", mpt->m_instance));
2421                 MPTSAS_POWER_OFF(mpt);
2422                 break;
2423         default:
2424                 mptsas_log(mpt, CE_WARN, "mptsas%d: unknown power level <%x>.",
2425                     mpt->m_instance, level);
2426                 rval = DDI_FAILURE;
2427                 break;
2428         }
2429         mutex_exit(&mpt->m_mutex);
2430         return (rval);
2431 }
2432 
2433 /*
2434  * Initialize configuration space and figure out which
2435  * chip and revison of the chip the mpt driver is using.
2436  */
2437 static int
2438 mptsas_config_space_init(mptsas_t *mpt)
2439 {
2440         NDBG0(("mptsas_config_space_init"));
2441 
2442         if (mpt->m_config_handle != NULL)
2443                 return (TRUE);
2444 
2445         if (pci_config_setup(mpt->m_dip,
2446             &mpt->m_config_handle) != DDI_SUCCESS) {
2447                 mptsas_log(mpt, CE_WARN, "cannot map configuration space.");
2448                 return (FALSE);
2449         }
2450 
2451         /*
2452          * This is a workaround for a XMITS ASIC bug which does not
2453          * drive the CBE upper bits.
2454          */
2455         if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT) &
2456             PCI_STAT_PERROR) {
2457                 pci_config_put16(mpt->m_config_handle, PCI_CONF_STAT,
2458                     PCI_STAT_PERROR);
2459         }
2460 
2461         mptsas_setup_cmd_reg(mpt);
2462 
2463         /*
2464          * Get the chip device id:
2465          */
2466         mpt->m_devid = pci_config_get16(mpt->m_config_handle, PCI_CONF_DEVID);
2467 
2468         /*
2469          * Save the revision.
2470          */
2471         mpt->m_revid = pci_config_get8(mpt->m_config_handle, PCI_CONF_REVID);
2472 
2473         /*
2474          * Save the SubSystem Vendor and Device IDs
2475          */
2476         mpt->m_svid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBVENID);
2477         mpt->m_ssid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBSYSID);
2478 
2479         /*
2480          * Set the latency timer to 0x40 as specified by the upa -> pci
2481          * bridge chip design team.  This may be done by the sparc pci
2482          * bus nexus driver, but the driver should make sure the latency
2483          * timer is correct for performance reasons.
2484          */
2485         pci_config_put8(mpt->m_config_handle, PCI_CONF_LATENCY_TIMER,
2486             MPTSAS_LATENCY_TIMER);
2487 
2488         (void) mptsas_get_pci_cap(mpt);
2489         return (TRUE);
2490 }
2491 
2492 static void
2493 mptsas_config_space_fini(mptsas_t *mpt)
2494 {
2495         if (mpt->m_config_handle != NULL) {
2496                 mptsas_disable_bus_master(mpt);
2497                 pci_config_teardown(&mpt->m_config_handle);
2498                 mpt->m_config_handle = NULL;
2499         }
2500 }
2501 
2502 static void
2503 mptsas_setup_cmd_reg(mptsas_t *mpt)
2504 {
2505         ushort_t        cmdreg;
2506 
2507         /*
2508          * Set the command register to the needed values.
2509          */
2510         cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2511         cmdreg |= (PCI_COMM_ME | PCI_COMM_SERR_ENABLE |
2512             PCI_COMM_PARITY_DETECT | PCI_COMM_MAE);
2513         cmdreg &= ~PCI_COMM_IO;
2514         pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2515 }
2516 
2517 static void
2518 mptsas_disable_bus_master(mptsas_t *mpt)
2519 {
2520         ushort_t        cmdreg;
2521 
2522         /*
2523          * Clear the master enable bit in the PCI command register.
2524          * This prevents any bus mastering activity like DMA.
2525          */
2526         cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2527         cmdreg &= ~PCI_COMM_ME;
2528         pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2529 }
2530 
2531 int
2532 mptsas_dma_alloc(mptsas_t *mpt, mptsas_dma_alloc_state_t *dma_statep)
2533 {
2534         ddi_dma_attr_t  attrs;
2535 
2536         attrs = mpt->m_io_dma_attr;
2537         attrs.dma_attr_sgllen = 1;
2538 
2539         ASSERT(dma_statep != NULL);
2540 
2541         if (mptsas_dma_addr_create(mpt, attrs, &dma_statep->handle,
2542             &dma_statep->accessp, &dma_statep->memp, dma_statep->size,
2543             &dma_statep->cookie) == FALSE) {
2544                 return (DDI_FAILURE);
2545         }
2546 
2547         return (DDI_SUCCESS);
2548 }
2549 
2550 void
2551 mptsas_dma_free(mptsas_dma_alloc_state_t *dma_statep)
2552 {
2553         ASSERT(dma_statep != NULL);
2554         mptsas_dma_addr_destroy(&dma_statep->handle, &dma_statep->accessp);
2555         dma_statep->size = 0;
2556 }
2557 
2558 int
2559 mptsas_do_dma(mptsas_t *mpt, uint32_t size, int var, int (*callback)())
2560 {
2561         ddi_dma_attr_t          attrs;
2562         ddi_dma_handle_t        dma_handle;
2563         caddr_t                 memp;
2564         ddi_acc_handle_t        accessp;
2565         int                     rval;
2566 
2567         ASSERT(mutex_owned(&mpt->m_mutex));
2568 
2569         attrs = mpt->m_msg_dma_attr;
2570         attrs.dma_attr_sgllen = 1;
2571         attrs.dma_attr_granular = size;
2572 
2573         if (mptsas_dma_addr_create(mpt, attrs, &dma_handle,
2574             &accessp, &memp, size, NULL) == FALSE) {
2575                 return (DDI_FAILURE);
2576         }
2577 
2578         rval = (*callback) (mpt, memp, var, accessp);
2579 
2580         if ((mptsas_check_dma_handle(dma_handle) != DDI_SUCCESS) ||
2581             (mptsas_check_acc_handle(accessp) != DDI_SUCCESS)) {
2582                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2583                 rval = DDI_FAILURE;
2584         }
2585 
2586         mptsas_dma_addr_destroy(&dma_handle, &accessp);
2587         return (rval);
2588 
2589 }
2590 
2591 static int
2592 mptsas_alloc_request_frames(mptsas_t *mpt)
2593 {
2594         ddi_dma_attr_t          frame_dma_attrs;
2595         caddr_t                 memp;
2596         ddi_dma_cookie_t        cookie;
2597         size_t                  mem_size;
2598 
2599         /*
2600          * re-alloc when it has already alloced
2601          */
2602         if (mpt->m_dma_req_frame_hdl)
2603                 mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2604                     &mpt->m_acc_req_frame_hdl);
2605 
2606         /*
2607          * The size of the request frame pool is:
2608          *   Number of Request Frames * Request Frame Size
2609          */
2610         mem_size = mpt->m_max_requests * mpt->m_req_frame_size;
2611 
2612         /*
2613          * set the DMA attributes.  System Request Message Frames must be
2614          * aligned on a 16-byte boundry.
2615          */
2616         frame_dma_attrs = mpt->m_msg_dma_attr;
2617         frame_dma_attrs.dma_attr_align = 16;
2618         frame_dma_attrs.dma_attr_sgllen = 1;
2619 
2620         /*
2621          * allocate the request frame pool.
2622          */
2623         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2624             &mpt->m_dma_req_frame_hdl, &mpt->m_acc_req_frame_hdl, &memp,
2625             mem_size, &cookie) == FALSE) {
2626                 return (DDI_FAILURE);
2627         }
2628 
2629         /*
2630          * Store the request frame memory address.  This chip uses this
2631          * address to dma to and from the driver's frame.  The second
2632          * address is the address mpt uses to fill in the frame.
2633          */
2634         mpt->m_req_frame_dma_addr = cookie.dmac_laddress;
2635         mpt->m_req_frame = memp;
2636 
2637         /*
2638          * Clear the request frame pool.
2639          */
2640         bzero(mpt->m_req_frame, mem_size);
2641 
2642         return (DDI_SUCCESS);
2643 }
2644 
2645 static int
2646 mptsas_alloc_sense_bufs(mptsas_t *mpt)
2647 {
2648         ddi_dma_attr_t          sense_dma_attrs;
2649         caddr_t                 memp;
2650         ddi_dma_cookie_t        cookie;
2651         size_t                  mem_size;
2652         int                     num_extrqsense_bufs;
2653 
2654         /*
2655          * re-alloc when it has already alloced
2656          */
2657         if (mpt->m_dma_req_sense_hdl) {
2658                 rmfreemap(mpt->m_erqsense_map);
2659                 mptsas_dma_addr_destroy(&mpt->m_dma_req_sense_hdl,
2660                     &mpt->m_acc_req_sense_hdl);
2661         }
2662 
2663         /*
2664          * The size of the request sense pool is:
2665          *   (Number of Request Frames - 2 ) * Request Sense Size +
2666          *   extra memory for extended sense requests.
2667          */
2668         mem_size = ((mpt->m_max_requests - 2) * mpt->m_req_sense_size) +
2669             mptsas_extreq_sense_bufsize;
2670 
2671         /*
2672          * set the DMA attributes.  ARQ buffers
2673          * aligned on a 16-byte boundry.
2674          */
2675         sense_dma_attrs = mpt->m_msg_dma_attr;
2676         sense_dma_attrs.dma_attr_align = 16;
2677         sense_dma_attrs.dma_attr_sgllen = 1;
2678 
2679         /*
2680          * allocate the request sense buffer pool.
2681          */
2682         if (mptsas_dma_addr_create(mpt, sense_dma_attrs,
2683             &mpt->m_dma_req_sense_hdl, &mpt->m_acc_req_sense_hdl, &memp,
2684             mem_size, &cookie) == FALSE) {
2685                 return (DDI_FAILURE);
2686         }
2687 
2688         /*
2689          * Store the request sense base memory address.  This chip uses this
2690          * address to dma the request sense data.  The second
2691          * address is the address mpt uses to access the data.
2692          * The third is the base for the extended rqsense buffers.
2693          */
2694         mpt->m_req_sense_dma_addr = cookie.dmac_laddress;
2695         mpt->m_req_sense = memp;
2696         memp += (mpt->m_max_requests - 2) * mpt->m_req_sense_size;
2697         mpt->m_extreq_sense = memp;
2698 
2699         /*
2700          * The extra memory is divided up into multiples of the base
2701          * buffer size in order to allocate via rmalloc().
2702          * Note that the rmallocmap cannot start at zero!
2703          */
2704         num_extrqsense_bufs = mptsas_extreq_sense_bufsize /
2705             mpt->m_req_sense_size;
2706         mpt->m_erqsense_map = rmallocmap_wait(num_extrqsense_bufs);
2707         rmfree(mpt->m_erqsense_map, num_extrqsense_bufs, 1);
2708 
2709         /*
2710          * Clear the pool.
2711          */
2712         bzero(mpt->m_req_sense, mem_size);
2713 
2714         return (DDI_SUCCESS);
2715 }
2716 
2717 static int
2718 mptsas_alloc_reply_frames(mptsas_t *mpt)
2719 {
2720         ddi_dma_attr_t          frame_dma_attrs;
2721         caddr_t                 memp;
2722         ddi_dma_cookie_t        cookie;
2723         size_t                  mem_size;
2724 
2725         /*
2726          * re-alloc when it has already alloced
2727          */
2728         if (mpt->m_dma_reply_frame_hdl) {
2729                 mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2730                     &mpt->m_acc_reply_frame_hdl);
2731         }
2732 
2733         /*
2734          * The size of the reply frame pool is:
2735          *   Number of Reply Frames * Reply Frame Size
2736          */
2737         mem_size = mpt->m_max_replies * mpt->m_reply_frame_size;
2738 
2739         /*
2740          * set the DMA attributes.   System Reply Message Frames must be
2741          * aligned on a 4-byte boundry.  This is the default.
2742          */
2743         frame_dma_attrs = mpt->m_msg_dma_attr;
2744         frame_dma_attrs.dma_attr_sgllen = 1;
2745 
2746         /*
2747          * allocate the reply frame pool
2748          */
2749         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2750             &mpt->m_dma_reply_frame_hdl, &mpt->m_acc_reply_frame_hdl, &memp,
2751             mem_size, &cookie) == FALSE) {
2752                 return (DDI_FAILURE);
2753         }
2754 
2755         /*
2756          * Store the reply frame memory address.  This chip uses this
2757          * address to dma to and from the driver's frame.  The second
2758          * address is the address mpt uses to process the frame.
2759          */
2760         mpt->m_reply_frame_dma_addr = cookie.dmac_laddress;
2761         mpt->m_reply_frame = memp;
2762 
2763         /*
2764          * Clear the reply frame pool.
2765          */
2766         bzero(mpt->m_reply_frame, mem_size);
2767 
2768         return (DDI_SUCCESS);
2769 }
2770 
2771 static int
2772 mptsas_alloc_free_queue(mptsas_t *mpt)
2773 {
2774         ddi_dma_attr_t          frame_dma_attrs;
2775         caddr_t                 memp;
2776         ddi_dma_cookie_t        cookie;
2777         size_t                  mem_size;
2778 
2779         /*
2780          * re-alloc when it has already alloced
2781          */
2782         if (mpt->m_dma_free_queue_hdl) {
2783                 mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2784                     &mpt->m_acc_free_queue_hdl);
2785         }
2786 
2787         /*
2788          * The reply free queue size is:
2789          *   Reply Free Queue Depth * 4
2790          * The "4" is the size of one 32 bit address (low part of 64-bit
2791          *   address)
2792          */
2793         mem_size = mpt->m_free_queue_depth * 4;
2794 
2795         /*
2796          * set the DMA attributes  The Reply Free Queue must be aligned on a
2797          * 16-byte boundry.
2798          */
2799         frame_dma_attrs = mpt->m_msg_dma_attr;
2800         frame_dma_attrs.dma_attr_align = 16;
2801         frame_dma_attrs.dma_attr_sgllen = 1;
2802 
2803         /*
2804          * allocate the reply free queue
2805          */
2806         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2807             &mpt->m_dma_free_queue_hdl, &mpt->m_acc_free_queue_hdl, &memp,
2808             mem_size, &cookie) == FALSE) {
2809                 return (DDI_FAILURE);
2810         }
2811 
2812         /*
2813          * Store the reply free queue memory address.  This chip uses this
2814          * address to read from the reply free queue.  The second address
2815          * is the address mpt uses to manage the queue.
2816          */
2817         mpt->m_free_queue_dma_addr = cookie.dmac_laddress;
2818         mpt->m_free_queue = memp;
2819 
2820         /*
2821          * Clear the reply free queue memory.
2822          */
2823         bzero(mpt->m_free_queue, mem_size);
2824 
2825         return (DDI_SUCCESS);
2826 }
2827 
2828 static int
2829 mptsas_alloc_post_queue(mptsas_t *mpt)
2830 {
2831         ddi_dma_attr_t          frame_dma_attrs;
2832         caddr_t                 memp;
2833         ddi_dma_cookie_t        cookie;
2834         size_t                  mem_size;
2835 
2836         /*
2837          * re-alloc when it has already alloced
2838          */
2839         if (mpt->m_dma_post_queue_hdl) {
2840                 mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2841                     &mpt->m_acc_post_queue_hdl);
2842         }
2843 
2844         /*
2845          * The reply descriptor post queue size is:
2846          *   Reply Descriptor Post Queue Depth * 8
2847          * The "8" is the size of each descriptor (8 bytes or 64 bits).
2848          */
2849         mem_size = mpt->m_post_queue_depth * 8;
2850 
2851         /*
2852          * set the DMA attributes.  The Reply Descriptor Post Queue must be
2853          * aligned on a 16-byte boundry.
2854          */
2855         frame_dma_attrs = mpt->m_msg_dma_attr;
2856         frame_dma_attrs.dma_attr_align = 16;
2857         frame_dma_attrs.dma_attr_sgllen = 1;
2858 
2859         /*
2860          * allocate the reply post queue
2861          */
2862         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2863             &mpt->m_dma_post_queue_hdl, &mpt->m_acc_post_queue_hdl, &memp,
2864             mem_size, &cookie) == FALSE) {
2865                 return (DDI_FAILURE);
2866         }
2867 
2868         /*
2869          * Store the reply descriptor post queue memory address.  This chip
2870          * uses this address to write to the reply descriptor post queue.  The
2871          * second address is the address mpt uses to manage the queue.
2872          */
2873         mpt->m_post_queue_dma_addr = cookie.dmac_laddress;
2874         mpt->m_post_queue = memp;
2875 
2876         /*
2877          * Clear the reply post queue memory.
2878          */
2879         bzero(mpt->m_post_queue, mem_size);
2880 
2881         return (DDI_SUCCESS);
2882 }
2883 
2884 static void
2885 mptsas_alloc_reply_args(mptsas_t *mpt)
2886 {
2887         if (mpt->m_replyh_args == NULL) {
2888                 mpt->m_replyh_args = kmem_zalloc(sizeof (m_replyh_arg_t) *
2889                     mpt->m_max_replies, KM_SLEEP);
2890         }
2891 }
2892 
2893 static int
2894 mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2895 {
2896         mptsas_cache_frames_t   *frames = NULL;
2897         if (cmd->cmd_extra_frames == NULL) {
2898                 frames = kmem_cache_alloc(mpt->m_cache_frames, KM_NOSLEEP);
2899                 if (frames == NULL) {
2900                         return (DDI_FAILURE);
2901                 }
2902                 cmd->cmd_extra_frames = frames;
2903         }
2904         return (DDI_SUCCESS);
2905 }
2906 
2907 static void
2908 mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2909 {
2910         if (cmd->cmd_extra_frames) {
2911                 kmem_cache_free(mpt->m_cache_frames,
2912                     (void *)cmd->cmd_extra_frames);
2913                 cmd->cmd_extra_frames = NULL;
2914         }
2915 }
2916 
2917 static void
2918 mptsas_cfg_fini(mptsas_t *mpt)
2919 {
2920         NDBG0(("mptsas_cfg_fini"));
2921         ddi_regs_map_free(&mpt->m_datap);
2922 }
2923 
2924 static void
2925 mptsas_hba_fini(mptsas_t *mpt)
2926 {
2927         NDBG0(("mptsas_hba_fini"));
2928 
2929         /*
2930          * Free up any allocated memory
2931          */
2932         if (mpt->m_dma_req_frame_hdl) {
2933                 mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2934                     &mpt->m_acc_req_frame_hdl);
2935         }
2936 
2937         if (mpt->m_dma_req_sense_hdl) {
2938                 rmfreemap(mpt->m_erqsense_map);
2939                 mptsas_dma_addr_destroy(&mpt->m_dma_req_sense_hdl,
2940                     &mpt->m_acc_req_sense_hdl);
2941         }
2942 
2943         if (mpt->m_dma_reply_frame_hdl) {
2944                 mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2945                     &mpt->m_acc_reply_frame_hdl);
2946         }
2947 
2948         if (mpt->m_dma_free_queue_hdl) {
2949                 mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2950                     &mpt->m_acc_free_queue_hdl);
2951         }
2952 
2953         if (mpt->m_dma_post_queue_hdl) {
2954                 mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2955                     &mpt->m_acc_post_queue_hdl);
2956         }
2957 
2958         if (mpt->m_replyh_args != NULL) {
2959                 kmem_free(mpt->m_replyh_args, sizeof (m_replyh_arg_t)
2960                     * mpt->m_max_replies);
2961         }
2962 }
2963 
2964 static int
2965 mptsas_name_child(dev_info_t *lun_dip, char *name, int len)
2966 {
2967         int             lun = 0;
2968         char            *sas_wwn = NULL;
2969         int             phynum = -1;
2970         int             reallen = 0;
2971 
2972         /* Get the target num */
2973         lun = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip, DDI_PROP_DONTPASS,
2974             LUN_PROP, 0);
2975 
2976         if ((phynum = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip,
2977             DDI_PROP_DONTPASS, "sata-phy", -1)) != -1) {
2978                 /*
2979                  * Stick in the address of form "pPHY,LUN"
2980                  */
2981                 reallen = snprintf(name, len, "p%x,%x", phynum, lun);
2982         } else if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lun_dip,
2983             DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &sas_wwn)
2984             == DDI_PROP_SUCCESS) {
2985                 /*
2986                  * Stick in the address of the form "wWWN,LUN"
2987                  */
2988                 reallen = snprintf(name, len, "%s,%x", sas_wwn, lun);
2989                 ddi_prop_free(sas_wwn);
2990         } else {
2991                 return (DDI_FAILURE);
2992         }
2993 
2994         ASSERT(reallen < len);
2995         if (reallen >= len) {
2996                 mptsas_log(0, CE_WARN, "!mptsas_get_name: name parameter "
2997                     "length too small, it needs to be %d bytes", reallen + 1);
2998         }
2999         return (DDI_SUCCESS);
3000 }
3001 
3002 /*
3003  * tran_tgt_init(9E) - target device instance initialization
3004  */
3005 static int
3006 mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
3007     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
3008 {
3009 #ifndef __lock_lint
3010         _NOTE(ARGUNUSED(hba_tran))
3011 #endif
3012 
3013         /*
3014          * At this point, the scsi_device structure already exists
3015          * and has been initialized.
3016          *
3017          * Use this function to allocate target-private data structures,
3018          * if needed by this HBA.  Add revised flow-control and queue
3019          * properties for child here, if desired and if you can tell they
3020          * support tagged queueing by now.
3021          */
3022         mptsas_t                *mpt;
3023         int                     lun = sd->sd_address.a_lun;
3024         mdi_pathinfo_t          *pip = NULL;
3025         mptsas_tgt_private_t    *tgt_private = NULL;
3026         mptsas_target_t         *ptgt = NULL;
3027         char                    *psas_wwn = NULL;
3028         mptsas_phymask_t        phymask = 0;
3029         uint64_t                sas_wwn = 0;
3030         mptsas_target_addr_t    addr;
3031         mpt = SDEV2MPT(sd);
3032 
3033         ASSERT(scsi_hba_iport_unit_address(hba_dip) != 0);
3034 
3035         NDBG0(("mptsas_scsi_tgt_init: hbadip=0x%p tgtdip=0x%p lun=%d",
3036             (void *)hba_dip, (void *)tgt_dip, lun));
3037 
3038         if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
3039                 (void) ndi_merge_node(tgt_dip, mptsas_name_child);
3040                 ddi_set_name_addr(tgt_dip, NULL);
3041                 return (DDI_FAILURE);
3042         }
3043         /*
3044          * phymask is 0 means the virtual port for RAID
3045          */
3046         phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, hba_dip, 0,
3047             "phymask", 0);
3048         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
3049                 if ((pip = (void *)(sd->sd_private)) == NULL) {
3050                         /*
3051                          * Very bad news if this occurs. Somehow scsi_vhci has
3052                          * lost the pathinfo node for this target.
3053                          */
3054                         return (DDI_NOT_WELL_FORMED);
3055                 }
3056 
3057                 if (mdi_prop_lookup_int(pip, LUN_PROP, &lun) !=
3058                     DDI_PROP_SUCCESS) {
3059                         mptsas_log(mpt, CE_WARN, "Get lun property failed\n");
3060                         return (DDI_FAILURE);
3061                 }
3062 
3063                 if (mdi_prop_lookup_string(pip, SCSI_ADDR_PROP_TARGET_PORT,
3064                     &psas_wwn) == MDI_SUCCESS) {
3065                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
3066                                 sas_wwn = 0;
3067                         }
3068                         (void) mdi_prop_free(psas_wwn);
3069                 }
3070         } else {
3071                 lun = ddi_prop_get_int(DDI_DEV_T_ANY, tgt_dip,
3072                     DDI_PROP_DONTPASS, LUN_PROP, 0);
3073                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip,
3074                     DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &psas_wwn) ==
3075                     DDI_PROP_SUCCESS) {
3076                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
3077                                 sas_wwn = 0;
3078                         }
3079                         ddi_prop_free(psas_wwn);
3080                 } else {
3081                         sas_wwn = 0;
3082                 }
3083         }
3084 
3085         ASSERT((sas_wwn != 0) || (phymask != 0));
3086         addr.mta_wwn = sas_wwn;
3087         addr.mta_phymask = phymask;
3088         mutex_enter(&mpt->m_mutex);
3089         ptgt = refhash_lookup(mpt->m_targets, &addr);
3090         mutex_exit(&mpt->m_mutex);
3091         if (ptgt == NULL) {
3092                 mptsas_log(mpt, CE_WARN, "!tgt_init: target doesn't exist or "
3093                     "gone already! phymask:%x, saswwn %"PRIx64, phymask,
3094                     sas_wwn);
3095                 return (DDI_FAILURE);
3096         }
3097         if (hba_tran->tran_tgt_private == NULL) {
3098                 tgt_private = kmem_zalloc(sizeof (mptsas_tgt_private_t),
3099                     KM_SLEEP);
3100                 tgt_private->t_lun = lun;
3101                 tgt_private->t_private = ptgt;
3102                 hba_tran->tran_tgt_private = tgt_private;
3103         }
3104 
3105         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
3106                 return (DDI_SUCCESS);
3107         }
3108         mutex_enter(&mpt->m_mutex);
3109 
3110         if (ptgt->m_deviceinfo &
3111             (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
3112             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
3113                 uchar_t *inq89 = NULL;
3114                 int inq89_len = 0x238;
3115                 int reallen = 0;
3116                 int rval = 0;
3117                 struct sata_id *sid = NULL;
3118                 char model[SATA_ID_MODEL_LEN + 1];
3119                 char fw[SATA_ID_FW_LEN + 1];
3120                 char *vid, *pid;
3121 
3122                 mutex_exit(&mpt->m_mutex);
3123                 /*
3124                  * According SCSI/ATA Translation -2 (SAT-2) revision 01a
3125                  * chapter 12.4.2 VPD page 89h includes 512 bytes ATA IDENTIFY
3126                  * DEVICE data or ATA IDENTIFY PACKET DEVICE data.
3127                  */
3128                 inq89 = kmem_zalloc(inq89_len, KM_SLEEP);
3129                 rval = mptsas_inquiry(mpt, ptgt, 0, 0x89,
3130                     inq89, inq89_len, &reallen, 1);
3131 
3132                 if (rval != 0) {
3133                         if (inq89 != NULL) {
3134                                 kmem_free(inq89, inq89_len);
3135                         }
3136 
3137                         mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
3138                             "0x89 for SATA target:%x failed!", ptgt->m_devhdl);
3139                         return (DDI_SUCCESS);
3140                 }
3141                 sid = (void *)(&inq89[60]);
3142 
3143                 swab(sid->ai_model, model, SATA_ID_MODEL_LEN);
3144                 swab(sid->ai_fw, fw, SATA_ID_FW_LEN);
3145 
3146                 model[SATA_ID_MODEL_LEN] = 0;
3147                 fw[SATA_ID_FW_LEN] = 0;
3148 
3149                 sata_split_model(model, &vid, &pid);
3150 
3151                 /*
3152                  * override SCSA "inquiry-*" properties
3153                  */
3154                 if (vid)
3155                         (void) scsi_device_prop_update_inqstring(sd,
3156                             INQUIRY_VENDOR_ID, vid, strlen(vid));
3157                 if (pid)
3158                         (void) scsi_device_prop_update_inqstring(sd,
3159                             INQUIRY_PRODUCT_ID, pid, strlen(pid));
3160                 (void) scsi_device_prop_update_inqstring(sd,
3161                     INQUIRY_REVISION_ID, fw, strlen(fw));
3162 
3163                 if (inq89 != NULL) {
3164                         kmem_free(inq89, inq89_len);
3165                 }
3166         } else {
3167                 mutex_exit(&mpt->m_mutex);
3168         }
3169 
3170         return (DDI_SUCCESS);
3171 }
3172 /*
3173  * tran_tgt_free(9E) - target device instance deallocation
3174  */
3175 static void
3176 mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
3177     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
3178 {
3179 #ifndef __lock_lint
3180         _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran, sd))
3181 #endif
3182 
3183         mptsas_tgt_private_t    *tgt_private = hba_tran->tran_tgt_private;
3184 
3185         if (tgt_private != NULL) {
3186                 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
3187                 hba_tran->tran_tgt_private = NULL;
3188         }
3189 }
3190 
3191 /*
3192  * scsi_pkt handling
3193  *
3194  * Visible to the external world via the transport structure.
3195  */
3196 
3197 /*
3198  * Notes:
3199  *      - transport the command to the addressed SCSI target/lun device
3200  *      - normal operation is to schedule the command to be transported,
3201  *        and return TRAN_ACCEPT if this is successful.
3202  *      - if NO_INTR, tran_start must poll device for command completion
3203  */
3204 static int
3205 mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
3206 {
3207 #ifndef __lock_lint
3208         _NOTE(ARGUNUSED(ap))
3209 #endif
3210         mptsas_t        *mpt = PKT2MPT(pkt);
3211         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
3212         int             rval;
3213         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3214 
3215         NDBG1(("mptsas_scsi_start: pkt=0x%p", (void *)pkt));
3216         ASSERT(ptgt);
3217         if (ptgt == NULL)
3218                 return (TRAN_FATAL_ERROR);
3219 
3220         /*
3221          * prepare the pkt before taking mutex.
3222          */
3223         rval = mptsas_prepare_pkt(cmd);
3224         if (rval != TRAN_ACCEPT) {
3225                 return (rval);
3226         }
3227 
3228         /*
3229          * Send the command to target/lun, however your HBA requires it.
3230          * If busy, return TRAN_BUSY; if there's some other formatting error
3231          * in the packet, return TRAN_BADPKT; otherwise, fall through to the
3232          * return of TRAN_ACCEPT.
3233          *
3234          * Remember that access to shared resources, including the mptsas_t
3235          * data structure and the HBA hardware registers, must be protected
3236          * with mutexes, here and everywhere.
3237          *
3238          * Also remember that at interrupt time, you'll get an argument
3239          * to the interrupt handler which is a pointer to your mptsas_t
3240          * structure; you'll have to remember which commands are outstanding
3241          * and which scsi_pkt is the currently-running command so the
3242          * interrupt handler can refer to the pkt to set completion
3243          * status, call the target driver back through pkt_comp, etc.
3244          *
3245          * If the instance lock is held by other thread, don't spin to wait
3246          * for it. Instead, queue the cmd and next time when the instance lock
3247          * is not held, accept all the queued cmd. A extra tx_waitq is
3248          * introduced to protect the queue.
3249          *
3250          * The polled cmd will not be queud and accepted as usual.
3251          *
3252          * Under the tx_waitq mutex, record whether a thread is draining
3253          * the tx_waitq.  An IO requesting thread that finds the instance
3254          * mutex contended appends to the tx_waitq and while holding the
3255          * tx_wait mutex, if the draining flag is not set, sets it and then
3256          * proceeds to spin for the instance mutex. This scheme ensures that
3257          * the last cmd in a burst be processed.
3258          *
3259          * we enable this feature only when the helper threads are enabled,
3260          * at which we think the loads are heavy.
3261          *
3262          * per instance mutex m_tx_waitq_mutex is introduced to protect the
3263          * m_tx_waitqtail, m_tx_waitq, m_tx_draining.
3264          */
3265 
3266         if (mpt->m_doneq_thread_n) {
3267                 if (mutex_tryenter(&mpt->m_mutex) != 0) {
3268                         rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3269                         mutex_exit(&mpt->m_mutex);
3270                 } else if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3271                         mutex_enter(&mpt->m_mutex);
3272                         rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3273                         mutex_exit(&mpt->m_mutex);
3274                 } else {
3275                         mutex_enter(&mpt->m_tx_waitq_mutex);
3276                         /*
3277                          * ptgt->m_dr_flag is protected by m_mutex or
3278                          * m_tx_waitq_mutex. In this case, m_tx_waitq_mutex
3279                          * is acquired.
3280                          */
3281                         if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3282                                 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3283                                         /*
3284                                          * The command should be allowed to
3285                                          * retry by returning TRAN_BUSY to
3286                                          * to stall the I/O's which come from
3287                                          * scsi_vhci since the device/path is
3288                                          * in unstable state now.
3289                                          */
3290                                         mutex_exit(&mpt->m_tx_waitq_mutex);
3291                                         return (TRAN_BUSY);
3292                                 } else {
3293                                         /*
3294                                          * The device is offline, just fail the
3295                                          * command by returning
3296                                          * TRAN_FATAL_ERROR.
3297                                          */
3298                                         mutex_exit(&mpt->m_tx_waitq_mutex);
3299                                         return (TRAN_FATAL_ERROR);
3300                                 }
3301                         }
3302                         if (mpt->m_tx_draining) {
3303                                 cmd->cmd_flags |= CFLAG_TXQ;
3304                                 *mpt->m_tx_waitqtail = cmd;
3305                                 mpt->m_tx_waitqtail = &cmd->cmd_linkp;
3306                                 mutex_exit(&mpt->m_tx_waitq_mutex);
3307                         } else { /* drain the queue */
3308                                 mpt->m_tx_draining = 1;
3309                                 mutex_exit(&mpt->m_tx_waitq_mutex);
3310                                 mutex_enter(&mpt->m_mutex);
3311                                 rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3312                                 mutex_exit(&mpt->m_mutex);
3313                         }
3314                 }
3315         } else {
3316                 mutex_enter(&mpt->m_mutex);
3317                 /*
3318                  * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
3319                  * in this case, m_mutex is acquired.
3320                  */
3321                 if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3322                         if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3323                                 /*
3324                                  * commands should be allowed to retry by
3325                                  * returning TRAN_BUSY to stall the I/O's
3326                                  * which come from scsi_vhci since the device/
3327                                  * path is in unstable state now.
3328                                  */
3329                                 mutex_exit(&mpt->m_mutex);
3330                                 return (TRAN_BUSY);
3331                         } else {
3332                                 /*
3333                                  * The device is offline, just fail the
3334                                  * command by returning TRAN_FATAL_ERROR.
3335                                  */
3336                                 mutex_exit(&mpt->m_mutex);
3337                                 return (TRAN_FATAL_ERROR);
3338                         }
3339                 }
3340                 rval = mptsas_accept_pkt(mpt, cmd);
3341                 mutex_exit(&mpt->m_mutex);
3342         }
3343 
3344         return (rval);
3345 }
3346 
3347 /*
3348  * Accept all the queued cmds(if any) before accept the current one.
3349  */
3350 static int
3351 mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3352 {
3353         int rval;
3354         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3355 
3356         ASSERT(mutex_owned(&mpt->m_mutex));
3357         /*
3358          * The call to mptsas_accept_tx_waitq() must always be performed
3359          * because that is where mpt->m_tx_draining is cleared.
3360          */
3361         mutex_enter(&mpt->m_tx_waitq_mutex);
3362         mptsas_accept_tx_waitq(mpt);
3363         mutex_exit(&mpt->m_tx_waitq_mutex);
3364         /*
3365          * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
3366          * in this case, m_mutex is acquired.
3367          */
3368         if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3369                 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3370                         /*
3371                          * The command should be allowed to retry by returning
3372                          * TRAN_BUSY to stall the I/O's which come from
3373                          * scsi_vhci since the device/path is in unstable state
3374                          * now.
3375                          */
3376                         return (TRAN_BUSY);
3377                 } else {
3378                         /*
3379                          * The device is offline, just fail the command by
3380                          * return TRAN_FATAL_ERROR.
3381                          */
3382                         return (TRAN_FATAL_ERROR);
3383                 }
3384         }
3385         rval = mptsas_accept_pkt(mpt, cmd);
3386 
3387         return (rval);
3388 }
3389 
3390 static int
3391 mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3392 {
3393         int             rval = TRAN_ACCEPT;
3394         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3395 
3396         NDBG1(("mptsas_accept_pkt: cmd=0x%p", (void *)cmd));
3397 
3398         ASSERT(mutex_owned(&mpt->m_mutex));
3399 
3400         if ((cmd->cmd_flags & CFLAG_PREPARED) == 0) {
3401                 rval = mptsas_prepare_pkt(cmd);
3402                 if (rval != TRAN_ACCEPT) {
3403                         cmd->cmd_flags &= ~CFLAG_TRANFLAG;
3404                         return (rval);
3405                 }
3406         }
3407 
3408         /*
3409          * reset the throttle if we were draining
3410          */
3411         if ((ptgt->m_t_ncmds == 0) &&
3412             (ptgt->m_t_throttle == DRAIN_THROTTLE)) {
3413                 NDBG23(("reset throttle"));
3414                 ASSERT(ptgt->m_reset_delay == 0);
3415                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
3416         }
3417 
3418         /*
3419          * If HBA is being reset, the DevHandles are being re-initialized,
3420          * which means that they could be invalid even if the target is still
3421          * attached.  Check if being reset and if DevHandle is being
3422          * re-initialized.  If this is the case, return BUSY so the I/O can be
3423          * retried later.
3424          */
3425         if ((ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) && mpt->m_in_reset) {
3426                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
3427                 if (cmd->cmd_flags & CFLAG_TXQ) {
3428                         mptsas_doneq_add(mpt, cmd);
3429                         mptsas_doneq_empty(mpt);
3430                         return (rval);
3431                 } else {
3432                         return (TRAN_BUSY);
3433                 }
3434         }
3435 
3436         /*
3437          * If device handle has already been invalidated, just
3438          * fail the command. In theory, command from scsi_vhci
3439          * client is impossible send down command with invalid
3440          * devhdl since devhdl is set after path offline, target
3441          * driver is not suppose to select a offlined path.
3442          */
3443         if (ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) {
3444                 NDBG3(("rejecting command, it might because invalid devhdl "
3445                     "request."));
3446                 mptsas_set_pkt_reason(mpt, cmd, CMD_DEV_GONE, STAT_TERMINATED);
3447                 if (cmd->cmd_flags & CFLAG_TXQ) {
3448                         mptsas_doneq_add(mpt, cmd);
3449                         mptsas_doneq_empty(mpt);
3450                         return (rval);
3451                 } else {
3452                         return (TRAN_FATAL_ERROR);
3453                 }
3454         }
3455         /*
3456          * The first case is the normal case.  mpt gets a command from the
3457          * target driver and starts it.
3458          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
3459          * commands is m_max_requests - 2.
3460          */
3461         if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
3462             (ptgt->m_t_throttle > HOLD_THROTTLE) &&
3463             (ptgt->m_t_ncmds < ptgt->m_t_throttle) &&
3464             (ptgt->m_reset_delay == 0) &&
3465             (ptgt->m_t_nwait == 0) &&
3466             ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0)) {
3467                 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
3468                         (void) mptsas_start_cmd(mpt, cmd);
3469                 } else {
3470                         mptsas_waitq_add(mpt, cmd);
3471                 }
3472         } else {
3473                 /*
3474                  * Add this pkt to the work queue
3475                  */
3476                 mptsas_waitq_add(mpt, cmd);
3477 
3478                 if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3479                         (void) mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
3480 
3481                         /*
3482                          * Only flush the doneq if this is not a TM
3483                          * cmd.  For TM cmds the flushing of the
3484                          * doneq will be done in those routines.
3485                          */
3486                         if ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
3487                                 mptsas_doneq_empty(mpt);
3488                         }
3489                 }
3490         }
3491         return (rval);
3492 }
3493 
3494 int
3495 mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
3496 {
3497         mptsas_slots_t *slots = mpt->m_active;
3498         uint_t slot, start_rotor;
3499         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3500 
3501         ASSERT(MUTEX_HELD(&mpt->m_mutex));
3502 
3503         /*
3504          * Account for reserved TM request slot and reserved SMID of 0.
3505          */
3506         ASSERT(slots->m_n_normal == (mpt->m_max_requests - 2));
3507 
3508         /*
3509          * Find the next available slot, beginning at m_rotor.  If no slot is
3510          * available, we'll return FALSE to indicate that.  This mechanism
3511          * considers only the normal slots, not the reserved slot 0 nor the
3512          * task management slot m_n_normal + 1.  The rotor is left to point to
3513          * the normal slot after the one we select, unless we select the last
3514          * normal slot in which case it returns to slot 1.
3515          */
3516         start_rotor = slots->m_rotor;
3517         do {
3518                 slot = slots->m_rotor++;
3519                 if (slots->m_rotor > slots->m_n_normal)
3520                         slots->m_rotor = 1;
3521 
3522                 if (slots->m_rotor == start_rotor)
3523                         break;
3524         } while (slots->m_slot[slot] != NULL);
3525 
3526         if (slots->m_slot[slot] != NULL)
3527                 return (FALSE);
3528 
3529         ASSERT(slot != 0 && slot <= slots->m_n_normal);
3530 
3531         cmd->cmd_slot = slot;
3532         slots->m_slot[slot] = cmd;
3533         mpt->m_ncmds++;
3534 
3535         /*
3536          * only increment per target ncmds if this is not a
3537          * command that has no target associated with it (i.e. a
3538          * event acknoledgment)
3539          */
3540         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
3541                 /*
3542                  * Expiration time is set in mptsas_start_cmd
3543                  */
3544                 ptgt->m_t_ncmds++;
3545                 cmd->cmd_active_expiration = 0;
3546         } else {
3547                 /*
3548                  * Initialize expiration time for passthrough commands,
3549                  */
3550                 cmd->cmd_active_expiration = gethrtime() +
3551                     (hrtime_t)cmd->cmd_pkt->pkt_time * NANOSEC;
3552         }
3553         return (TRUE);
3554 }
3555 
3556 /*
3557  * prepare the pkt:
3558  * the pkt may have been resubmitted or just reused so
3559  * initialize some fields and do some checks.
3560  */
3561 static int
3562 mptsas_prepare_pkt(mptsas_cmd_t *cmd)
3563 {
3564         struct scsi_pkt *pkt = CMD2PKT(cmd);
3565 
3566         NDBG1(("mptsas_prepare_pkt: cmd=0x%p", (void *)cmd));
3567 
3568         /*
3569          * Reinitialize some fields that need it; the packet may
3570          * have been resubmitted
3571          */
3572         pkt->pkt_reason = CMD_CMPLT;
3573         pkt->pkt_state = 0;
3574         pkt->pkt_statistics = 0;
3575         pkt->pkt_resid = 0;
3576         cmd->cmd_age = 0;
3577         cmd->cmd_pkt_flags = pkt->pkt_flags;
3578 
3579         /*
3580          * zero status byte.
3581          */
3582         *(pkt->pkt_scbp) = 0;
3583 
3584         if (cmd->cmd_flags & CFLAG_DMAVALID) {
3585                 pkt->pkt_resid = cmd->cmd_dmacount;
3586 
3587                 /*
3588                  * consistent packets need to be sync'ed first
3589                  * (only for data going out)
3590                  */
3591                 if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
3592                     (cmd->cmd_flags & CFLAG_DMASEND)) {
3593                         (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
3594                             DDI_DMA_SYNC_FORDEV);
3595                 }
3596         }
3597 
3598         cmd->cmd_flags =
3599             (cmd->cmd_flags & ~(CFLAG_TRANFLAG)) |
3600             CFLAG_PREPARED | CFLAG_IN_TRANSPORT;
3601 
3602         return (TRAN_ACCEPT);
3603 }
3604 
3605 /*
3606  * tran_init_pkt(9E) - allocate scsi_pkt(9S) for command
3607  *
3608  * One of three possibilities:
3609  *      - allocate scsi_pkt
3610  *      - allocate scsi_pkt and DMA resources
3611  *      - allocate DMA resources to an already-allocated pkt
3612  */
3613 static struct scsi_pkt *
3614 mptsas_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
3615     struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
3616     int (*callback)(), caddr_t arg)
3617 {
3618         mptsas_cmd_t            *cmd, *new_cmd;
3619         mptsas_t                *mpt = ADDR2MPT(ap);
3620         int                     failure = 1;
3621         uint_t                  oldcookiec;
3622         mptsas_target_t         *ptgt = NULL;
3623         int                     rval;
3624         mptsas_tgt_private_t    *tgt_private;
3625         int                     kf;
3626 
3627         kf = (callback == SLEEP_FUNC)? KM_SLEEP: KM_NOSLEEP;
3628 
3629         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
3630             tran_tgt_private;
3631         ASSERT(tgt_private != NULL);
3632         if (tgt_private == NULL) {
3633                 return (NULL);
3634         }
3635         ptgt = tgt_private->t_private;
3636         ASSERT(ptgt != NULL);
3637         if (ptgt == NULL)
3638                 return (NULL);
3639         ap->a_target = ptgt->m_devhdl;
3640         ap->a_lun = tgt_private->t_lun;
3641 
3642         ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC);
3643 #ifdef MPTSAS_TEST_EXTRN_ALLOC
3644         statuslen *= 100; tgtlen *= 4;
3645 #endif
3646         NDBG3(("mptsas_scsi_init_pkt:\n"
3647             "\ttgt=%d in=0x%p bp=0x%p clen=%d slen=%d tlen=%d flags=%x",
3648             ap->a_target, (void *)pkt, (void *)bp,
3649             cmdlen, statuslen, tgtlen, flags));
3650 
3651         /*
3652          * Allocate the new packet.
3653          */
3654         if (pkt == NULL) {
3655                 ddi_dma_handle_t        save_dma_handle;
3656 
3657                 cmd = kmem_cache_alloc(mpt->m_kmem_cache, kf);
3658 
3659                 if (cmd) {
3660                         save_dma_handle = cmd->cmd_dmahandle;
3661                         bzero(cmd, sizeof (*cmd) + scsi_pkt_size());
3662                         cmd->cmd_dmahandle = save_dma_handle;
3663 
3664                         pkt = (void *)((uchar_t *)cmd +
3665                             sizeof (struct mptsas_cmd));
3666                         pkt->pkt_ha_private = (opaque_t)cmd;
3667                         pkt->pkt_address = *ap;
3668                         pkt->pkt_private = (opaque_t)cmd->cmd_pkt_private;
3669                         pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb;
3670                         pkt->pkt_cdbp = (opaque_t)&cmd->cmd_cdb;
3671                         cmd->cmd_pkt = (struct scsi_pkt *)pkt;
3672                         cmd->cmd_cdblen = (uchar_t)cmdlen;
3673                         cmd->cmd_scblen = statuslen;
3674                         cmd->cmd_rqslen = SENSE_LENGTH;
3675                         cmd->cmd_tgt_addr = ptgt;
3676                         failure = 0;
3677                 }
3678 
3679                 if (failure || (cmdlen > sizeof (cmd->cmd_cdb)) ||
3680                     (tgtlen > PKT_PRIV_LEN) ||
3681                     (statuslen > EXTCMDS_STATUS_SIZE)) {
3682                         if (failure == 0) {
3683                                 /*
3684                                  * if extern alloc fails, all will be
3685                                  * deallocated, including cmd
3686                                  */
3687                                 failure = mptsas_pkt_alloc_extern(mpt, cmd,
3688                                     cmdlen, tgtlen, statuslen, kf);
3689                         }
3690                         if (failure) {
3691                                 /*
3692                                  * if extern allocation fails, it will
3693                                  * deallocate the new pkt as well
3694                                  */
3695                                 return (NULL);
3696                         }
3697                 }
3698                 new_cmd = cmd;
3699 
3700         } else {
3701                 cmd = PKT2CMD(pkt);
3702                 new_cmd = NULL;
3703         }
3704 
3705 
3706         /* grab cmd->cmd_cookiec here as oldcookiec */
3707 
3708         oldcookiec = cmd->cmd_cookiec;
3709 
3710         /*
3711          * If the dma was broken up into PARTIAL transfers cmd_nwin will be
3712          * greater than 0 and we'll need to grab the next dma window
3713          */
3714         /*
3715          * SLM-not doing extra command frame right now; may add later
3716          */
3717 
3718         if (cmd->cmd_nwin > 0) {
3719 
3720                 /*
3721                  * Make sure we havn't gone past the the total number
3722                  * of windows
3723                  */
3724                 if (++cmd->cmd_winindex >= cmd->cmd_nwin) {
3725                         return (NULL);
3726                 }
3727                 if (ddi_dma_getwin(cmd->cmd_dmahandle, cmd->cmd_winindex,
3728                     &cmd->cmd_dma_offset, &cmd->cmd_dma_len,
3729                     &cmd->cmd_cookie, &cmd->cmd_cookiec) == DDI_FAILURE) {
3730                         return (NULL);
3731                 }
3732                 goto get_dma_cookies;
3733         }
3734 
3735 
3736         if (flags & PKT_XARQ) {
3737                 cmd->cmd_flags |= CFLAG_XARQ;
3738         }
3739 
3740         /*
3741          * DMA resource allocation.  This version assumes your
3742          * HBA has some sort of bus-mastering or onboard DMA capability, with a
3743          * scatter-gather list of length MPTSAS_MAX_DMA_SEGS, as given in the
3744          * ddi_dma_attr_t structure and passed to scsi_impl_dmaget.
3745          */
3746         if (bp && (bp->b_bcount != 0) &&
3747             (cmd->cmd_flags & CFLAG_DMAVALID) == 0) {
3748 
3749                 int     cnt, dma_flags;
3750                 mptti_t *dmap;          /* ptr to the S/G list */
3751 
3752                 /*
3753                  * Set up DMA memory and position to the next DMA segment.
3754                  */
3755                 ASSERT(cmd->cmd_dmahandle != NULL);
3756 
3757                 if (bp->b_flags & B_READ) {
3758                         dma_flags = DDI_DMA_READ;
3759                         cmd->cmd_flags &= ~CFLAG_DMASEND;
3760                 } else {
3761                         dma_flags = DDI_DMA_WRITE;
3762                         cmd->cmd_flags |= CFLAG_DMASEND;
3763                 }
3764                 if (flags & PKT_CONSISTENT) {
3765                         cmd->cmd_flags |= CFLAG_CMDIOPB;
3766                         dma_flags |= DDI_DMA_CONSISTENT;
3767                 }
3768 
3769                 if (flags & PKT_DMA_PARTIAL) {
3770                         dma_flags |= DDI_DMA_PARTIAL;
3771                 }
3772 
3773                 /*
3774                  * workaround for byte hole issue on psycho and
3775                  * schizo pre 2.1
3776                  */
3777                 if ((bp->b_flags & B_READ) && ((bp->b_flags &
3778                     (B_PAGEIO|B_REMAPPED)) != B_PAGEIO) &&
3779                     ((uintptr_t)bp->b_un.b_addr & 0x7)) {
3780                         dma_flags |= DDI_DMA_CONSISTENT;
3781                 }
3782 
3783                 rval = ddi_dma_buf_bind_handle(cmd->cmd_dmahandle, bp,
3784                     dma_flags, callback, arg,
3785                     &cmd->cmd_cookie, &cmd->cmd_cookiec);
3786                 if (rval == DDI_DMA_PARTIAL_MAP) {
3787                         (void) ddi_dma_numwin(cmd->cmd_dmahandle,
3788                             &cmd->cmd_nwin);
3789                         cmd->cmd_winindex = 0;
3790                         (void) ddi_dma_getwin(cmd->cmd_dmahandle,
3791                             cmd->cmd_winindex, &cmd->cmd_dma_offset,
3792                             &cmd->cmd_dma_len, &cmd->cmd_cookie,
3793                             &cmd->cmd_cookiec);
3794                 } else if (rval && (rval != DDI_DMA_MAPPED)) {
3795                         switch (rval) {
3796                         case DDI_DMA_NORESOURCES:
3797                                 bioerror(bp, 0);
3798                                 break;
3799                         case DDI_DMA_BADATTR:
3800                         case DDI_DMA_NOMAPPING:
3801                                 bioerror(bp, EFAULT);
3802                                 break;
3803                         case DDI_DMA_TOOBIG:
3804                         default:
3805                                 bioerror(bp, EINVAL);
3806                                 break;
3807                         }
3808                         cmd->cmd_flags &= ~CFLAG_DMAVALID;
3809                         if (new_cmd) {
3810                                 mptsas_scsi_destroy_pkt(ap, pkt);
3811                         }
3812                         return ((struct scsi_pkt *)NULL);
3813                 }
3814 
3815 get_dma_cookies:
3816                 cmd->cmd_flags |= CFLAG_DMAVALID;
3817                 ASSERT(cmd->cmd_cookiec > 0);
3818 
3819                 if (cmd->cmd_cookiec > MPTSAS_MAX_CMD_SEGS) {
3820                         mptsas_log(mpt, CE_NOTE, "large cookiec received %d\n",
3821                             cmd->cmd_cookiec);
3822                         bioerror(bp, EINVAL);
3823                         if (new_cmd) {
3824                                 mptsas_scsi_destroy_pkt(ap, pkt);
3825                         }
3826                         return ((struct scsi_pkt *)NULL);
3827                 }
3828 
3829                 /*
3830                  * Allocate extra SGL buffer if needed.
3831                  */
3832                 if ((cmd->cmd_cookiec > MPTSAS_MAX_FRAME_SGES64(mpt)) &&
3833                     (cmd->cmd_extra_frames == NULL)) {
3834                         if (mptsas_alloc_extra_sgl_frame(mpt, cmd) ==
3835                             DDI_FAILURE) {
3836                                 mptsas_log(mpt, CE_WARN, "MPT SGL mem alloc "
3837                                     "failed");
3838                                 bioerror(bp, ENOMEM);
3839                                 if (new_cmd) {
3840                                         mptsas_scsi_destroy_pkt(ap, pkt);
3841                                 }
3842                                 return ((struct scsi_pkt *)NULL);
3843                         }
3844                 }
3845 
3846                 /*
3847                  * Always use scatter-gather transfer
3848                  * Use the loop below to store physical addresses of
3849                  * DMA segments, from the DMA cookies, into your HBA's
3850                  * scatter-gather list.
3851                  * We need to ensure we have enough kmem alloc'd
3852                  * for the sg entries since we are no longer using an
3853                  * array inside mptsas_cmd_t.
3854                  *
3855                  * We check cmd->cmd_cookiec against oldcookiec so
3856                  * the scatter-gather list is correctly allocated
3857                  */
3858 
3859                 if (oldcookiec != cmd->cmd_cookiec) {
3860                         if (cmd->cmd_sg != (mptti_t *)NULL) {
3861                                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) *
3862                                     oldcookiec);
3863                                 cmd->cmd_sg = NULL;
3864                         }
3865                 }
3866 
3867                 if (cmd->cmd_sg == (mptti_t *)NULL) {
3868                         cmd->cmd_sg = kmem_alloc((size_t)(sizeof (mptti_t)*
3869                             cmd->cmd_cookiec), kf);
3870 
3871                         if (cmd->cmd_sg == (mptti_t *)NULL) {
3872                                 mptsas_log(mpt, CE_WARN,
3873                                     "unable to kmem_alloc enough memory "
3874                                     "for scatter/gather list");
3875                 /*
3876                  * if we have an ENOMEM condition we need to behave
3877                  * the same way as the rest of this routine
3878                  */
3879 
3880                                 bioerror(bp, ENOMEM);
3881                                 if (new_cmd) {
3882                                         mptsas_scsi_destroy_pkt(ap, pkt);
3883                                 }
3884                                 return ((struct scsi_pkt *)NULL);
3885                         }
3886                 }
3887 
3888                 dmap = cmd->cmd_sg;
3889 
3890                 ASSERT(cmd->cmd_cookie.dmac_size != 0);
3891 
3892                 /*
3893                  * store the first segment into the S/G list
3894                  */
3895                 dmap->count = cmd->cmd_cookie.dmac_size;
3896                 dmap->addr.address64.Low = (uint32_t)
3897                     (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3898                 dmap->addr.address64.High = (uint32_t)
3899                     (cmd->cmd_cookie.dmac_laddress >> 32);
3900 
3901                 /*
3902                  * dmacount counts the size of the dma for this window
3903                  * (if partial dma is being used).  totaldmacount
3904                  * keeps track of the total amount of dma we have
3905                  * transferred for all the windows (needed to calculate
3906                  * the resid value below).
3907                  */
3908                 cmd->cmd_dmacount = cmd->cmd_cookie.dmac_size;
3909                 cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3910 
3911                 /*
3912                  * We already stored the first DMA scatter gather segment,
3913                  * start at 1 if we need to store more.
3914                  */
3915                 for (cnt = 1; cnt < cmd->cmd_cookiec; cnt++) {
3916                         /*
3917                          * Get next DMA cookie
3918                          */
3919                         ddi_dma_nextcookie(cmd->cmd_dmahandle,
3920                             &cmd->cmd_cookie);
3921                         dmap++;
3922 
3923                         cmd->cmd_dmacount += cmd->cmd_cookie.dmac_size;
3924                         cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3925 
3926                         /*
3927                          * store the segment parms into the S/G list
3928                          */
3929                         dmap->count = cmd->cmd_cookie.dmac_size;
3930                         dmap->addr.address64.Low = (uint32_t)
3931                             (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3932                         dmap->addr.address64.High = (uint32_t)
3933                             (cmd->cmd_cookie.dmac_laddress >> 32);
3934                 }
3935 
3936                 /*
3937                  * If this was partially allocated we set the resid
3938                  * the amount of data NOT transferred in this window
3939                  * If there is only one window, the resid will be 0
3940                  */
3941                 pkt->pkt_resid = (bp->b_bcount - cmd->cmd_totaldmacount);
3942                 NDBG3(("mptsas_scsi_init_pkt: cmd_dmacount=%d.",
3943                     cmd->cmd_dmacount));
3944         }
3945         return (pkt);
3946 }
3947 
3948 /*
3949  * tran_destroy_pkt(9E) - scsi_pkt(9s) deallocation
3950  *
3951  * Notes:
3952  *      - also frees DMA resources if allocated
3953  *      - implicit DMA synchonization
3954  */
3955 static void
3956 mptsas_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
3957 {
3958         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
3959         mptsas_t        *mpt = ADDR2MPT(ap);
3960 
3961         NDBG3(("mptsas_scsi_destroy_pkt: target=%d pkt=0x%p",
3962             ap->a_target, (void *)pkt));
3963 
3964         if (cmd->cmd_flags & CFLAG_DMAVALID) {
3965                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
3966                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
3967         }
3968 
3969         if (cmd->cmd_sg) {
3970                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) * cmd->cmd_cookiec);
3971                 cmd->cmd_sg = NULL;
3972         }
3973 
3974         mptsas_free_extra_sgl_frame(mpt, cmd);
3975 
3976         if ((cmd->cmd_flags &
3977             (CFLAG_FREE | CFLAG_CDBEXTERN | CFLAG_PRIVEXTERN |
3978             CFLAG_SCBEXTERN)) == 0) {
3979                 cmd->cmd_flags = CFLAG_FREE;
3980                 kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
3981         } else {
3982                 mptsas_pkt_destroy_extern(mpt, cmd);
3983         }
3984 }
3985 
3986 /*
3987  * kmem cache constructor and destructor:
3988  * When constructing, we bzero the cmd and allocate the dma handle
3989  * When destructing, just free the dma handle
3990  */
3991 static int
3992 mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags)
3993 {
3994         mptsas_cmd_t            *cmd = buf;
3995         mptsas_t                *mpt  = cdrarg;
3996         int                     (*callback)(caddr_t);
3997 
3998         callback = (kmflags == KM_SLEEP)? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
3999 
4000         NDBG4(("mptsas_kmem_cache_constructor"));
4001 
4002         /*
4003          * allocate a dma handle
4004          */
4005         if ((ddi_dma_alloc_handle(mpt->m_dip, &mpt->m_io_dma_attr, callback,
4006             NULL, &cmd->cmd_dmahandle)) != DDI_SUCCESS) {
4007                 cmd->cmd_dmahandle = NULL;
4008                 return (-1);
4009         }
4010         return (0);
4011 }
4012 
4013 static void
4014 mptsas_kmem_cache_destructor(void *buf, void *cdrarg)
4015 {
4016 #ifndef __lock_lint
4017         _NOTE(ARGUNUSED(cdrarg))
4018 #endif
4019         mptsas_cmd_t    *cmd = buf;
4020 
4021         NDBG4(("mptsas_kmem_cache_destructor"));
4022 
4023         if (cmd->cmd_dmahandle) {
4024                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
4025                 cmd->cmd_dmahandle = NULL;
4026         }
4027 }
4028 
4029 static int
4030 mptsas_cache_frames_constructor(void *buf, void *cdrarg, int kmflags)
4031 {
4032         mptsas_cache_frames_t   *p = buf;
4033         mptsas_t                *mpt = cdrarg;
4034         ddi_dma_attr_t          frame_dma_attr;
4035         size_t                  mem_size, alloc_len;
4036         ddi_dma_cookie_t        cookie;
4037         uint_t                  ncookie;
4038         int (*callback)(caddr_t) = (kmflags == KM_SLEEP)
4039             ? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
4040 
4041         frame_dma_attr = mpt->m_msg_dma_attr;
4042         frame_dma_attr.dma_attr_align = 0x10;
4043         frame_dma_attr.dma_attr_sgllen = 1;
4044 
4045         if (ddi_dma_alloc_handle(mpt->m_dip, &frame_dma_attr, callback, NULL,
4046             &p->m_dma_hdl) != DDI_SUCCESS) {
4047                 mptsas_log(mpt, CE_WARN, "Unable to allocate dma handle for"
4048                     " extra SGL.");
4049                 return (DDI_FAILURE);
4050         }
4051 
4052         mem_size = (mpt->m_max_request_frames - 1) * mpt->m_req_frame_size;
4053 
4054         if (ddi_dma_mem_alloc(p->m_dma_hdl, mem_size, &mpt->m_dev_acc_attr,
4055             DDI_DMA_CONSISTENT, callback, NULL, (caddr_t *)&p->m_frames_addr,
4056             &alloc_len, &p->m_acc_hdl) != DDI_SUCCESS) {
4057                 ddi_dma_free_handle(&p->m_dma_hdl);
4058                 p->m_dma_hdl = NULL;
4059                 mptsas_log(mpt, CE_WARN, "Unable to allocate dma memory for"
4060                     " extra SGL.");
4061                 return (DDI_FAILURE);
4062         }
4063 
4064         if (ddi_dma_addr_bind_handle(p->m_dma_hdl, NULL, p->m_frames_addr,
4065             alloc_len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, callback, NULL,
4066             &cookie, &ncookie) != DDI_DMA_MAPPED) {
4067                 (void) ddi_dma_mem_free(&p->m_acc_hdl);
4068                 ddi_dma_free_handle(&p->m_dma_hdl);
4069                 p->m_dma_hdl = NULL;
4070                 mptsas_log(mpt, CE_WARN, "Unable to bind DMA resources for"
4071                     " extra SGL");
4072                 return (DDI_FAILURE);
4073         }
4074 
4075         /*
4076          * Store the SGL memory address.  This chip uses this
4077          * address to dma to and from the driver.  The second
4078          * address is the address mpt uses to fill in the SGL.
4079          */
4080         p->m_phys_addr = cookie.dmac_laddress;
4081 
4082         return (DDI_SUCCESS);
4083 }
4084 
4085 static void
4086 mptsas_cache_frames_destructor(void *buf, void *cdrarg)
4087 {
4088 #ifndef __lock_lint
4089         _NOTE(ARGUNUSED(cdrarg))
4090 #endif
4091         mptsas_cache_frames_t   *p = buf;
4092         if (p->m_dma_hdl != NULL) {
4093                 (void) ddi_dma_unbind_handle(p->m_dma_hdl);
4094                 (void) ddi_dma_mem_free(&p->m_acc_hdl);
4095                 ddi_dma_free_handle(&p->m_dma_hdl);
4096                 p->m_phys_addr = NULL;
4097                 p->m_frames_addr = NULL;
4098                 p->m_dma_hdl = NULL;
4099                 p->m_acc_hdl = NULL;
4100         }
4101 
4102 }
4103 
4104 /*
4105  * Figure out if we need to use a different method for the request
4106  * sense buffer and allocate from the map if necessary.
4107  */
4108 static boolean_t
4109 mptsas_cmdarqsize(mptsas_t *mpt, mptsas_cmd_t *cmd, size_t senselength, int kf)
4110 {
4111         if (senselength > mpt->m_req_sense_size) {
4112                 unsigned long i;
4113 
4114                 /* Sense length is limited to an 8 bit value in MPI Spec. */
4115                 if (senselength > 255)
4116                         senselength = 255;
4117                 cmd->cmd_extrqschunks = (senselength +
4118                     (mpt->m_req_sense_size - 1))/mpt->m_req_sense_size;
4119                 i = (kf == KM_SLEEP ? rmalloc_wait : rmalloc)
4120                     (mpt->m_erqsense_map, cmd->cmd_extrqschunks);
4121 
4122                 if (i == 0)
4123                         return (B_FALSE);
4124 
4125                 cmd->cmd_extrqslen = (uint16_t)senselength;
4126                 cmd->cmd_extrqsidx = i - 1;
4127                 cmd->cmd_arq_buf = mpt->m_extreq_sense +
4128                     (cmd->cmd_extrqsidx * mpt->m_req_sense_size);
4129         } else {
4130                 cmd->cmd_rqslen = (uchar_t)senselength;
4131         }
4132 
4133         return (B_TRUE);
4134 }
4135 
4136 /*
4137  * allocate and deallocate external pkt space (ie. not part of mptsas_cmd)
4138  * for non-standard length cdb, pkt_private, status areas
4139  * if allocation fails, then deallocate all external space and the pkt
4140  */
4141 /* ARGSUSED */
4142 static int
4143 mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
4144     int cmdlen, int tgtlen, int statuslen, int kf)
4145 {
4146         caddr_t                 cdbp, scbp, tgt;
4147 
4148         NDBG3(("mptsas_pkt_alloc_extern: "
4149             "cmd=0x%p cmdlen=%d tgtlen=%d statuslen=%d kf=%x",
4150             (void *)cmd, cmdlen, tgtlen, statuslen, kf));
4151 
4152         tgt = cdbp = scbp = NULL;
4153         cmd->cmd_scblen              = statuslen;
4154         cmd->cmd_privlen     = (uchar_t)tgtlen;
4155 
4156         if (cmdlen > sizeof (cmd->cmd_cdb)) {
4157                 if ((cdbp = kmem_zalloc((size_t)cmdlen, kf)) == NULL) {
4158                         goto fail;
4159                 }
4160                 cmd->cmd_pkt->pkt_cdbp = (opaque_t)cdbp;
4161                 cmd->cmd_flags |= CFLAG_CDBEXTERN;
4162         }
4163         if (tgtlen > PKT_PRIV_LEN) {
4164                 if ((tgt = kmem_zalloc((size_t)tgtlen, kf)) == NULL) {
4165                         goto fail;
4166                 }
4167                 cmd->cmd_flags |= CFLAG_PRIVEXTERN;
4168                 cmd->cmd_pkt->pkt_private = tgt;
4169         }
4170         if (statuslen > EXTCMDS_STATUS_SIZE) {
4171                 if ((scbp = kmem_zalloc((size_t)statuslen, kf)) == NULL) {
4172                         goto fail;
4173                 }
4174                 cmd->cmd_flags |= CFLAG_SCBEXTERN;
4175                 cmd->cmd_pkt->pkt_scbp = (opaque_t)scbp;
4176 
4177                 /* allocate sense data buf for DMA */
4178                 if (mptsas_cmdarqsize(mpt, cmd, statuslen -
4179                     MPTSAS_GET_ITEM_OFF(struct scsi_arq_status, sts_sensedata),
4180                     kf) == B_FALSE)
4181                         goto fail;
4182         }
4183         return (0);
4184 fail:
4185         mptsas_pkt_destroy_extern(mpt, cmd);
4186         return (1);
4187 }
4188 
4189 /*
4190  * deallocate external pkt space and deallocate the pkt
4191  */
4192 static void
4193 mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd)
4194 {
4195         NDBG3(("mptsas_pkt_destroy_extern: cmd=0x%p", (void *)cmd));
4196 
4197         if (cmd->cmd_flags & CFLAG_FREE) {
4198                 mptsas_log(mpt, CE_PANIC,
4199                     "mptsas_pkt_destroy_extern: freeing free packet");
4200                 _NOTE(NOT_REACHED)
4201                 /* NOTREACHED */
4202         }
4203         if (cmd->cmd_extrqslen != 0) {
4204                 rmfree(mpt->m_erqsense_map, cmd->cmd_extrqschunks,
4205                     cmd->cmd_extrqsidx + 1);
4206         }
4207         if (cmd->cmd_flags & CFLAG_CDBEXTERN) {
4208                 kmem_free(cmd->cmd_pkt->pkt_cdbp, (size_t)cmd->cmd_cdblen);
4209         }
4210         if (cmd->cmd_flags & CFLAG_SCBEXTERN) {
4211                 kmem_free(cmd->cmd_pkt->pkt_scbp, (size_t)cmd->cmd_scblen);
4212         }
4213         if (cmd->cmd_flags & CFLAG_PRIVEXTERN) {
4214                 kmem_free(cmd->cmd_pkt->pkt_private, (size_t)cmd->cmd_privlen);
4215         }
4216         cmd->cmd_flags = CFLAG_FREE;
4217         kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
4218 }
4219 
4220 /*
4221  * tran_sync_pkt(9E) - explicit DMA synchronization
4222  */
4223 /*ARGSUSED*/
4224 static void
4225 mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
4226 {
4227         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
4228 
4229         NDBG3(("mptsas_scsi_sync_pkt: target=%d, pkt=0x%p",
4230             ap->a_target, (void *)pkt));
4231 
4232         if (cmd->cmd_dmahandle) {
4233                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4234                     (cmd->cmd_flags & CFLAG_DMASEND) ?
4235                     DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
4236         }
4237 }
4238 
4239 /*
4240  * tran_dmafree(9E) - deallocate DMA resources allocated for command
4241  */
4242 /*ARGSUSED*/
4243 static void
4244 mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
4245 {
4246         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
4247         mptsas_t        *mpt = ADDR2MPT(ap);
4248 
4249         NDBG3(("mptsas_scsi_dmafree: target=%d pkt=0x%p",
4250             ap->a_target, (void *)pkt));
4251 
4252         if (cmd->cmd_flags & CFLAG_DMAVALID) {
4253                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
4254                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
4255         }
4256 
4257         mptsas_free_extra_sgl_frame(mpt, cmd);
4258 }
4259 
4260 static void
4261 mptsas_pkt_comp(struct scsi_pkt *pkt, mptsas_cmd_t *cmd)
4262 {
4263         if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
4264             (!(cmd->cmd_flags & CFLAG_DMASEND))) {
4265                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4266                     DDI_DMA_SYNC_FORCPU);
4267         }
4268         (*pkt->pkt_comp)(pkt);
4269 }
4270 
4271 static void
4272 mptsas_sge_mainframe(mptsas_cmd_t *cmd, pMpi2SCSIIORequest_t frame,
4273     ddi_acc_handle_t acc_hdl, uint_t cookiec, uint32_t end_flags)
4274 {
4275         pMpi2SGESimple64_t      sge;
4276         mptti_t                 *dmap;
4277         uint32_t                flags;
4278 
4279         dmap = cmd->cmd_sg;
4280 
4281         sge = (pMpi2SGESimple64_t)(&frame->SGL);
4282         while (cookiec--) {
4283                 ddi_put32(acc_hdl,
4284                     &sge->Address.Low, dmap->addr.address64.Low);
4285                 ddi_put32(acc_hdl,
4286                     &sge->Address.High, dmap->addr.address64.High);
4287                 ddi_put32(acc_hdl, &sge->FlagsLength,
4288                     dmap->count);
4289                 flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4290                 flags |= ((uint32_t)
4291                     (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4292                     MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4293                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4294                     MPI2_SGE_FLAGS_SHIFT);
4295 
4296                 /*
4297                  * If this is the last cookie, we set the flags
4298                  * to indicate so
4299                  */
4300                 if (cookiec == 0) {
4301                         flags |= end_flags;
4302                 }
4303                 if (cmd->cmd_flags & CFLAG_DMASEND) {
4304                         flags |= (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4305                             MPI2_SGE_FLAGS_SHIFT);
4306                 } else {
4307                         flags |= (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4308                             MPI2_SGE_FLAGS_SHIFT);
4309                 }
4310                 ddi_put32(acc_hdl, &sge->FlagsLength, flags);
4311                 dmap++;
4312                 sge++;
4313         }
4314 }
4315 
4316 static void
4317 mptsas_sge_chain(mptsas_t *mpt, mptsas_cmd_t *cmd,
4318     pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4319 {
4320         pMpi2SGESimple64_t      sge;
4321         pMpi2SGEChain64_t       sgechain;
4322         uint64_t                nframe_phys_addr;
4323         uint_t                  cookiec;
4324         mptti_t                 *dmap;
4325         uint32_t                flags;
4326 
4327         /*
4328          * Save the number of entries in the DMA
4329          * Scatter/Gather list
4330          */
4331         cookiec = cmd->cmd_cookiec;
4332 
4333         /*
4334          * Hereby we start to deal with multiple frames.
4335          * The process is as follows:
4336          * 1. Determine how many frames are needed for SGL element
4337          *    storage; Note that all frames are stored in contiguous
4338          *    memory space and in 64-bit DMA mode each element is
4339          *    3 double-words (12 bytes) long.
4340          * 2. Fill up the main frame. We need to do this separately
4341          *    since it contains the SCSI IO request header and needs
4342          *    dedicated processing. Note that the last 4 double-words
4343          *    of the SCSI IO header is for SGL element storage
4344          *    (MPI2_SGE_IO_UNION).
4345          * 3. Fill the chain element in the main frame, so the DMA
4346          *    engine can use the following frames.
4347          * 4. Enter a loop to fill the remaining frames. Note that the
4348          *    last frame contains no chain element.  The remaining
4349          *    frames go into the mpt SGL buffer allocated on the fly,
4350          *    not immediately following the main message frame, as in
4351          *    Gen1.
4352          * Some restrictions:
4353          * 1. For 64-bit DMA, the simple element and chain element
4354          *    are both of 3 double-words (12 bytes) in size, even
4355          *    though all frames are stored in the first 4G of mem
4356          *    range and the higher 32-bits of the address are always 0.
4357          * 2. On some controllers (like the 1064/1068), a frame can
4358          *    hold SGL elements with the last 1 or 2 double-words
4359          *    (4 or 8 bytes) un-used. On these controllers, we should
4360          *    recognize that there's not enough room for another SGL
4361          *    element and move the sge pointer to the next frame.
4362          */
4363         int                     i, j, k, l, frames, sgemax;
4364         int                     temp;
4365         uint8_t                 chainflags;
4366         uint16_t                chainlength;
4367         mptsas_cache_frames_t   *p;
4368 
4369         /*
4370          * Sgemax is the number of SGE's that will fit
4371          * each extra frame and frames is total
4372          * number of frames we'll need.  1 sge entry per
4373          * frame is reseverd for the chain element thus the -1 below.
4374          */
4375         sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_SGE_SIMPLE64))
4376             - 1);
4377         temp = (cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) / sgemax;
4378 
4379         /*
4380          * A little check to see if we need to round up the number
4381          * of frames we need
4382          */
4383         if ((cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) - (temp *
4384             sgemax) > 1) {
4385                 frames = (temp + 1);
4386         } else {
4387                 frames = temp;
4388         }
4389         dmap = cmd->cmd_sg;
4390         sge = (pMpi2SGESimple64_t)(&frame->SGL);
4391 
4392         /*
4393          * First fill in the main frame
4394          */
4395         j = MPTSAS_MAX_FRAME_SGES64(mpt) - 1;
4396         mptsas_sge_mainframe(cmd, frame, acc_hdl, j,
4397             ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4398             MPI2_SGE_FLAGS_SHIFT));
4399         dmap += j;
4400         sge += j;
4401         j++;
4402 
4403         /*
4404          * Fill in the chain element in the main frame.
4405          * About calculation on ChainOffset:
4406          * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
4407          *    in the end reserved for SGL element storage
4408          *    (MPI2_SGE_IO_UNION); we should count it in our
4409          *    calculation.  See its definition in the header file.
4410          * 2. Constant j is the counter of the current SGL element
4411          *    that will be processed, and (j - 1) is the number of
4412          *    SGL elements that have been processed (stored in the
4413          *    main frame).
4414          * 3. ChainOffset value should be in units of double-words (4
4415          *    bytes) so the last value should be divided by 4.
4416          */
4417         ddi_put8(acc_hdl, &frame->ChainOffset,
4418             (sizeof (MPI2_SCSI_IO_REQUEST) -
4419             sizeof (MPI2_SGE_IO_UNION) +
4420             (j - 1) * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4421         sgechain = (pMpi2SGEChain64_t)sge;
4422         chainflags = (MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4423             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4424             MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4425         ddi_put8(acc_hdl, &sgechain->Flags, chainflags);
4426 
4427         /*
4428          * The size of the next frame is the accurate size of space
4429          * (in bytes) used to store the SGL elements. j is the counter
4430          * of SGL elements. (j - 1) is the number of SGL elements that
4431          * have been processed (stored in frames).
4432          */
4433         if (frames >= 2) {
4434                 ASSERT(mpt->m_req_frame_size >= sizeof (MPI2_SGE_SIMPLE64));
4435                 chainlength = mpt->m_req_frame_size /
4436                     sizeof (MPI2_SGE_SIMPLE64) *
4437                     sizeof (MPI2_SGE_SIMPLE64);
4438         } else {
4439                 chainlength = ((cookiec - (j - 1)) *
4440                     sizeof (MPI2_SGE_SIMPLE64));
4441         }
4442 
4443         p = cmd->cmd_extra_frames;
4444 
4445         ddi_put16(acc_hdl, &sgechain->Length, chainlength);
4446         ddi_put32(acc_hdl, &sgechain->Address.Low, p->m_phys_addr);
4447         ddi_put32(acc_hdl, &sgechain->Address.High, p->m_phys_addr >> 32);
4448 
4449         /*
4450          * If there are more than 2 frames left we have to
4451          * fill in the next chain offset to the location of
4452          * the chain element in the next frame.
4453          * sgemax is the number of simple elements in an extra
4454          * frame. Note that the value NextChainOffset should be
4455          * in double-words (4 bytes).
4456          */
4457         if (frames >= 2) {
4458                 ddi_put8(acc_hdl, &sgechain->NextChainOffset,
4459                     (sgemax * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4460         } else {
4461                 ddi_put8(acc_hdl, &sgechain->NextChainOffset, 0);
4462         }
4463 
4464         /*
4465          * Jump to next frame;
4466          * Starting here, chain buffers go into the per command SGL.
4467          * This buffer is allocated when chain buffers are needed.
4468          */
4469         sge = (pMpi2SGESimple64_t)p->m_frames_addr;
4470         i = cookiec;
4471 
4472         /*
4473          * Start filling in frames with SGE's.  If we
4474          * reach the end of frame and still have SGE's
4475          * to fill we need to add a chain element and
4476          * use another frame.  j will be our counter
4477          * for what cookie we are at and i will be
4478          * the total cookiec. k is the current frame
4479          */
4480         for (k = 1; k <= frames; k++) {
4481                 for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
4482 
4483                         /*
4484                          * If we have reached the end of frame
4485                          * and we have more SGE's to fill in
4486                          * we have to fill the final entry
4487                          * with a chain element and then
4488                          * continue to the next frame
4489                          */
4490                         if ((l == (sgemax + 1)) && (k != frames)) {
4491                                 sgechain = (pMpi2SGEChain64_t)sge;
4492                                 j--;
4493                                 chainflags = (
4494                                     MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4495                                     MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4496                                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4497                                 ddi_put8(p->m_acc_hdl,
4498                                     &sgechain->Flags, chainflags);
4499                                 /*
4500                                  * k is the frame counter and (k + 1)
4501                                  * is the number of the next frame.
4502                                  * Note that frames are in contiguous
4503                                  * memory space.
4504                                  */
4505                                 nframe_phys_addr = p->m_phys_addr +
4506                                     (mpt->m_req_frame_size * k);
4507                                 ddi_put32(p->m_acc_hdl,
4508                                     &sgechain->Address.Low,
4509                                     nframe_phys_addr);
4510                                 ddi_put32(p->m_acc_hdl,
4511                                     &sgechain->Address.High,
4512                                     nframe_phys_addr >> 32);
4513 
4514                                 /*
4515                                  * If there are more than 2 frames left
4516                                  * we have to next chain offset to
4517                                  * the location of the chain element
4518                                  * in the next frame and fill in the
4519                                  * length of the next chain
4520                                  */
4521                                 if ((frames - k) >= 2) {
4522                                         ddi_put8(p->m_acc_hdl,
4523                                             &sgechain->NextChainOffset,
4524                                             (sgemax *
4525                                             sizeof (MPI2_SGE_SIMPLE64))
4526                                             >> 2);
4527                                         ddi_put16(p->m_acc_hdl,
4528                                             &sgechain->Length,
4529                                             mpt->m_req_frame_size /
4530                                             sizeof (MPI2_SGE_SIMPLE64) *
4531                                             sizeof (MPI2_SGE_SIMPLE64));
4532                                 } else {
4533                                         /*
4534                                          * This is the last frame. Set
4535                                          * the NextChainOffset to 0 and
4536                                          * Length is the total size of
4537                                          * all remaining simple elements
4538                                          */
4539                                         ddi_put8(p->m_acc_hdl,
4540                                             &sgechain->NextChainOffset,
4541                                             0);
4542                                         ddi_put16(p->m_acc_hdl,
4543                                             &sgechain->Length,
4544                                             (cookiec - j) *
4545                                             sizeof (MPI2_SGE_SIMPLE64));
4546                                 }
4547 
4548                                 /* Jump to the next frame */
4549                                 sge = (pMpi2SGESimple64_t)
4550                                     ((char *)p->m_frames_addr +
4551                                     (int)mpt->m_req_frame_size * k);
4552 
4553                                 continue;
4554                         }
4555 
4556                         ddi_put32(p->m_acc_hdl,
4557                             &sge->Address.Low,
4558                             dmap->addr.address64.Low);
4559                         ddi_put32(p->m_acc_hdl,
4560                             &sge->Address.High,
4561                             dmap->addr.address64.High);
4562                         ddi_put32(p->m_acc_hdl,
4563                             &sge->FlagsLength, dmap->count);
4564                         flags = ddi_get32(p->m_acc_hdl,
4565                             &sge->FlagsLength);
4566                         flags |= ((uint32_t)(
4567                             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4568                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4569                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4570                             MPI2_SGE_FLAGS_SHIFT);
4571 
4572                         /*
4573                          * If we are at the end of the frame and
4574                          * there is another frame to fill in
4575                          * we set the last simple element as last
4576                          * element
4577                          */
4578                         if ((l == sgemax) && (k != frames)) {
4579                                 flags |= ((uint32_t)
4580                                     (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4581                                     MPI2_SGE_FLAGS_SHIFT);
4582                         }
4583 
4584                         /*
4585                          * If this is the final cookie we
4586                          * indicate it by setting the flags
4587                          */
4588                         if (j == i) {
4589                                 flags |= ((uint32_t)
4590                                     (MPI2_SGE_FLAGS_LAST_ELEMENT |
4591                                     MPI2_SGE_FLAGS_END_OF_BUFFER |
4592                                     MPI2_SGE_FLAGS_END_OF_LIST) <<
4593                                     MPI2_SGE_FLAGS_SHIFT);
4594                         }
4595                         if (cmd->cmd_flags & CFLAG_DMASEND) {
4596                                 flags |=
4597                                     (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4598                                     MPI2_SGE_FLAGS_SHIFT);
4599                         } else {
4600                                 flags |=
4601                                     (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4602                                     MPI2_SGE_FLAGS_SHIFT);
4603                         }
4604                         ddi_put32(p->m_acc_hdl,
4605                             &sge->FlagsLength, flags);
4606                         dmap++;
4607                         sge++;
4608                 }
4609         }
4610 
4611         /*
4612          * Sync DMA with the chain buffers that were just created
4613          */
4614         (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
4615 }
4616 
4617 static void
4618 mptsas_ieee_sge_mainframe(mptsas_cmd_t *cmd, pMpi2SCSIIORequest_t frame,
4619     ddi_acc_handle_t acc_hdl, uint_t cookiec, uint8_t end_flag)
4620 {
4621         pMpi2IeeeSgeSimple64_t  ieeesge;
4622         mptti_t                 *dmap;
4623         uint8_t                 flags;
4624 
4625         dmap = cmd->cmd_sg;
4626 
4627         NDBG1(("mptsas_ieee_sge_mainframe: cookiec=%d, %s", cookiec,
4628             cmd->cmd_flags & CFLAG_DMASEND?"Out":"In"));
4629 
4630         ieeesge = (pMpi2IeeeSgeSimple64_t)(&frame->SGL);
4631         while (cookiec--) {
4632                 ddi_put32(acc_hdl,
4633                     &ieeesge->Address.Low, dmap->addr.address64.Low);
4634                 ddi_put32(acc_hdl,
4635                     &ieeesge->Address.High, dmap->addr.address64.High);
4636                 ddi_put32(acc_hdl, &ieeesge->Length,
4637                     dmap->count);
4638                 NDBG1(("mptsas_ieee_sge_mainframe: len=%d", dmap->count));
4639                 flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
4640                     MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
4641 
4642                 /*
4643                  * If this is the last cookie, we set the flags
4644                  * to indicate so
4645                  */
4646                 if (cookiec == 0) {
4647                         flags |= end_flag;
4648                 }
4649 
4650                 ddi_put8(acc_hdl, &ieeesge->Flags, flags);
4651                 dmap++;
4652                 ieeesge++;
4653         }
4654 }
4655 
4656 static void
4657 mptsas_ieee_sge_chain(mptsas_t *mpt, mptsas_cmd_t *cmd,
4658     pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4659 {
4660         pMpi2IeeeSgeSimple64_t  ieeesge;
4661         pMpi25IeeeSgeChain64_t  ieeesgechain;
4662         uint64_t                nframe_phys_addr;
4663         uint_t                  cookiec;
4664         mptti_t                 *dmap;
4665         uint8_t                 flags;
4666 
4667         /*
4668          * Save the number of entries in the DMA
4669          * Scatter/Gather list
4670          */
4671         cookiec = cmd->cmd_cookiec;
4672 
4673         NDBG1(("mptsas_ieee_sge_chain: cookiec=%d", cookiec));
4674 
4675         /*
4676          * Hereby we start to deal with multiple frames.
4677          * The process is as follows:
4678          * 1. Determine how many frames are needed for SGL element
4679          *    storage; Note that all frames are stored in contiguous
4680          *    memory space and in 64-bit DMA mode each element is
4681          *    4 double-words (16 bytes) long.
4682          * 2. Fill up the main frame. We need to do this separately
4683          *    since it contains the SCSI IO request header and needs
4684          *    dedicated processing. Note that the last 4 double-words
4685          *    of the SCSI IO header is for SGL element storage
4686          *    (MPI2_SGE_IO_UNION).
4687          * 3. Fill the chain element in the main frame, so the DMA
4688          *    engine can use the following frames.
4689          * 4. Enter a loop to fill the remaining frames. Note that the
4690          *    last frame contains no chain element.  The remaining
4691          *    frames go into the mpt SGL buffer allocated on the fly,
4692          *    not immediately following the main message frame, as in
4693          *    Gen1.
4694          * Restrictions:
4695          *    For 64-bit DMA, the simple element and chain element
4696          *    are both of 4 double-words (16 bytes) in size, even
4697          *    though all frames are stored in the first 4G of mem
4698          *    range and the higher 32-bits of the address are always 0.
4699          */
4700         int                     i, j, k, l, frames, sgemax;
4701         int                     temp;
4702         uint8_t                 chainflags;
4703         uint32_t                chainlength;
4704         mptsas_cache_frames_t   *p;
4705 
4706         /*
4707          * Sgemax is the number of SGE's that will fit
4708          * each extra frame and frames is total
4709          * number of frames we'll need.  1 sge entry per
4710          * frame is reseverd for the chain element thus the -1 below.
4711          */
4712         sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_IEEE_SGE_SIMPLE64))
4713             - 1);
4714         temp = (cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) / sgemax;
4715 
4716         /*
4717          * A little check to see if we need to round up the number
4718          * of frames we need
4719          */
4720         if ((cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) - (temp *
4721             sgemax) > 1) {
4722                 frames = (temp + 1);
4723         } else {
4724                 frames = temp;
4725         }
4726         NDBG1(("mptsas_ieee_sge_chain: temp=%d, frames=%d", temp, frames));
4727         dmap = cmd->cmd_sg;
4728         ieeesge = (pMpi2IeeeSgeSimple64_t)(&frame->SGL);
4729 
4730         /*
4731          * First fill in the main frame
4732          */
4733         j = MPTSAS_MAX_FRAME_SGES64(mpt) - 1;
4734         mptsas_ieee_sge_mainframe(cmd, frame, acc_hdl, j, 0);
4735         dmap += j;
4736         ieeesge += j;
4737         j++;
4738 
4739         /*
4740          * Fill in the chain element in the main frame.
4741          * About calculation on ChainOffset:
4742          * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
4743          *    in the end reserved for SGL element storage
4744          *    (MPI2_SGE_IO_UNION); we should count it in our
4745          *    calculation.  See its definition in the header file.
4746          * 2. Constant j is the counter of the current SGL element
4747          *    that will be processed, and (j - 1) is the number of
4748          *    SGL elements that have been processed (stored in the
4749          *    main frame).
4750          * 3. ChainOffset value should be in units of quad-words (16
4751          *    bytes) so the last value should be divided by 16.
4752          */
4753         ddi_put8(acc_hdl, &frame->ChainOffset,
4754             (sizeof (MPI2_SCSI_IO_REQUEST) -
4755             sizeof (MPI2_SGE_IO_UNION) +
4756             (j - 1) * sizeof (MPI2_IEEE_SGE_SIMPLE64)) >> 4);
4757         ieeesgechain = (pMpi25IeeeSgeChain64_t)ieeesge;
4758         chainflags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
4759             MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
4760         ddi_put8(acc_hdl, &ieeesgechain->Flags, chainflags);
4761 
4762         /*
4763          * The size of the next frame is the accurate size of space
4764          * (in bytes) used to store the SGL elements. j is the counter
4765          * of SGL elements. (j - 1) is the number of SGL elements that
4766          * have been processed (stored in frames).
4767          */
4768         if (frames >= 2) {
4769                 ASSERT(mpt->m_req_frame_size >=
4770                     sizeof (MPI2_IEEE_SGE_SIMPLE64));
4771                 chainlength = mpt->m_req_frame_size /
4772                     sizeof (MPI2_IEEE_SGE_SIMPLE64) *
4773                     sizeof (MPI2_IEEE_SGE_SIMPLE64);
4774         } else {
4775                 chainlength = ((cookiec - (j - 1)) *
4776                     sizeof (MPI2_IEEE_SGE_SIMPLE64));
4777         }
4778 
4779         p = cmd->cmd_extra_frames;
4780 
4781         ddi_put32(acc_hdl, &ieeesgechain->Length, chainlength);
4782         ddi_put32(acc_hdl, &ieeesgechain->Address.Low, p->m_phys_addr);
4783         ddi_put32(acc_hdl, &ieeesgechain->Address.High, p->m_phys_addr >> 32);
4784 
4785         /*
4786          * If there are more than 2 frames left we have to
4787          * fill in the next chain offset to the location of
4788          * the chain element in the next frame.
4789          * sgemax is the number of simple elements in an extra
4790          * frame. Note that the value NextChainOffset should be
4791          * in double-words (4 bytes).
4792          */
4793         if (frames >= 2) {
4794                 ddi_put8(acc_hdl, &ieeesgechain->NextChainOffset,
4795                     (sgemax * sizeof (MPI2_IEEE_SGE_SIMPLE64)) >> 4);
4796         } else {
4797                 ddi_put8(acc_hdl, &ieeesgechain->NextChainOffset, 0);
4798         }
4799 
4800         /*
4801          * Jump to next frame;
4802          * Starting here, chain buffers go into the per command SGL.
4803          * This buffer is allocated when chain buffers are needed.
4804          */
4805         ieeesge = (pMpi2IeeeSgeSimple64_t)p->m_frames_addr;
4806         i = cookiec;
4807 
4808         /*
4809          * Start filling in frames with SGE's.  If we
4810          * reach the end of frame and still have SGE's
4811          * to fill we need to add a chain element and
4812          * use another frame.  j will be our counter
4813          * for what cookie we are at and i will be
4814          * the total cookiec. k is the current frame
4815          */
4816         for (k = 1; k <= frames; k++) {
4817                 for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
4818 
4819                         /*
4820                          * If we have reached the end of frame
4821                          * and we have more SGE's to fill in
4822                          * we have to fill the final entry
4823                          * with a chain element and then
4824                          * continue to the next frame
4825                          */
4826                         if ((l == (sgemax + 1)) && (k != frames)) {
4827                                 ieeesgechain = (pMpi25IeeeSgeChain64_t)ieeesge;
4828                                 j--;
4829                                 chainflags =
4830                                     MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
4831                                     MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
4832                                 ddi_put8(p->m_acc_hdl,
4833                                     &ieeesgechain->Flags, chainflags);
4834                                 /*
4835                                  * k is the frame counter and (k + 1)
4836                                  * is the number of the next frame.
4837                                  * Note that frames are in contiguous
4838                                  * memory space.
4839                                  */
4840                                 nframe_phys_addr = p->m_phys_addr +
4841                                     (mpt->m_req_frame_size * k);
4842                                 ddi_put32(p->m_acc_hdl,
4843                                     &ieeesgechain->Address.Low,
4844                                     nframe_phys_addr);
4845                                 ddi_put32(p->m_acc_hdl,
4846                                     &ieeesgechain->Address.High,
4847                                     nframe_phys_addr >> 32);
4848 
4849                                 /*
4850                                  * If there are more than 2 frames left
4851                                  * we have to next chain offset to
4852                                  * the location of the chain element
4853                                  * in the next frame and fill in the
4854                                  * length of the next chain
4855                                  */
4856                                 if ((frames - k) >= 2) {
4857                                         ddi_put8(p->m_acc_hdl,
4858                                             &ieeesgechain->NextChainOffset,
4859                                             (sgemax *
4860                                             sizeof (MPI2_IEEE_SGE_SIMPLE64))
4861                                             >> 4);
4862                                         ASSERT(mpt->m_req_frame_size >=
4863                                             sizeof (MPI2_IEEE_SGE_SIMPLE64));
4864                                         ddi_put32(p->m_acc_hdl,
4865                                             &ieeesgechain->Length,
4866                                             mpt->m_req_frame_size /
4867                                             sizeof (MPI2_IEEE_SGE_SIMPLE64) *
4868                                             sizeof (MPI2_IEEE_SGE_SIMPLE64));
4869                                 } else {
4870                                         /*
4871                                          * This is the last frame. Set
4872                                          * the NextChainOffset to 0 and
4873                                          * Length is the total size of
4874                                          * all remaining simple elements
4875                                          */
4876                                         ddi_put8(p->m_acc_hdl,
4877                                             &ieeesgechain->NextChainOffset,
4878                                             0);
4879                                         ddi_put32(p->m_acc_hdl,
4880                                             &ieeesgechain->Length,
4881                                             (cookiec - j) *
4882                                             sizeof (MPI2_IEEE_SGE_SIMPLE64));
4883                                 }
4884 
4885                                 /* Jump to the next frame */
4886                                 ieeesge = (pMpi2IeeeSgeSimple64_t)
4887                                     ((char *)p->m_frames_addr +
4888                                     (int)mpt->m_req_frame_size * k);
4889 
4890                                 continue;
4891                         }
4892 
4893                         ddi_put32(p->m_acc_hdl,
4894                             &ieeesge->Address.Low,
4895                             dmap->addr.address64.Low);
4896                         ddi_put32(p->m_acc_hdl,
4897                             &ieeesge->Address.High,
4898                             dmap->addr.address64.High);
4899                         ddi_put32(p->m_acc_hdl,
4900                             &ieeesge->Length, dmap->count);
4901                         flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
4902                             MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
4903 
4904                         /*
4905                          * If we are at the end of the frame and
4906                          * there is another frame to fill in
4907                          * do we need to do anything?
4908                          * if ((l == sgemax) && (k != frames)) {
4909                          * }
4910                          */
4911 
4912                         /*
4913                          * If this is the final cookie set end of list.
4914                          */
4915                         if (j == i) {
4916                                 flags |= MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
4917                         }
4918 
4919                         ddi_put8(p->m_acc_hdl, &ieeesge->Flags, flags);
4920                         dmap++;
4921                         ieeesge++;
4922                 }
4923         }
4924 
4925         /*
4926          * Sync DMA with the chain buffers that were just created
4927          */
4928         (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
4929 }
4930 
4931 static void
4932 mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd, uint32_t *control,
4933     pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4934 {
4935         ASSERT(cmd->cmd_flags & CFLAG_DMAVALID);
4936 
4937         NDBG1(("mptsas_sge_setup: cookiec=%d", cmd->cmd_cookiec));
4938 
4939         /*
4940          * Set read/write bit in control.
4941          */
4942         if (cmd->cmd_flags & CFLAG_DMASEND) {
4943                 *control |= MPI2_SCSIIO_CONTROL_WRITE;
4944         } else {
4945                 *control |= MPI2_SCSIIO_CONTROL_READ;
4946         }
4947 
4948         ddi_put32(acc_hdl, &frame->DataLength, cmd->cmd_dmacount);
4949 
4950         /*
4951          * We have 4 cases here.  First where we can fit all the
4952          * SG elements into the main frame, and the case
4953          * where we can't. The SG element is also different when using
4954          * MPI2.5 interface.
4955          * If we have more cookies than we can attach to a frame
4956          * we will need to use a chain element to point
4957          * a location of memory where the rest of the S/G
4958          * elements reside.
4959          */
4960         if (cmd->cmd_cookiec <= MPTSAS_MAX_FRAME_SGES64(mpt)) {
4961                 if (mpt->m_MPI25) {
4962                         mptsas_ieee_sge_mainframe(cmd, frame, acc_hdl,
4963                             cmd->cmd_cookiec,
4964                             MPI25_IEEE_SGE_FLAGS_END_OF_LIST);
4965                 } else {
4966                         mptsas_sge_mainframe(cmd, frame, acc_hdl,
4967                             cmd->cmd_cookiec,
4968                             ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT
4969                             | MPI2_SGE_FLAGS_END_OF_BUFFER
4970                             | MPI2_SGE_FLAGS_END_OF_LIST) <<
4971                             MPI2_SGE_FLAGS_SHIFT));
4972                 }
4973         } else {
4974                 if (mpt->m_MPI25) {
4975                         mptsas_ieee_sge_chain(mpt, cmd, frame, acc_hdl);
4976                 } else {
4977                         mptsas_sge_chain(mpt, cmd, frame, acc_hdl);
4978                 }
4979         }
4980 }
4981 
4982 /*
4983  * Interrupt handling
4984  * Utility routine.  Poll for status of a command sent to HBA
4985  * without interrupts (a FLAG_NOINTR command).
4986  */
4987 int
4988 mptsas_poll(mptsas_t *mpt, mptsas_cmd_t *poll_cmd, int polltime)
4989 {
4990         int     rval = TRUE;
4991 
4992         NDBG5(("mptsas_poll: cmd=0x%p", (void *)poll_cmd));
4993 
4994         if ((poll_cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
4995                 mptsas_restart_hba(mpt);
4996         }
4997 
4998         /*
4999          * Wait, using drv_usecwait(), long enough for the command to
5000          * reasonably return from the target if the target isn't
5001          * "dead".  A polled command may well be sent from scsi_poll, and
5002          * there are retries built in to scsi_poll if the transport
5003          * accepted the packet (TRAN_ACCEPT).  scsi_poll waits 1 second
5004          * and retries the transport up to scsi_poll_busycnt times
5005          * (currently 60) if
5006          * 1. pkt_reason is CMD_INCOMPLETE and pkt_state is 0, or
5007          * 2. pkt_reason is CMD_CMPLT and *pkt_scbp has STATUS_BUSY
5008          *
5009          * limit the waiting to avoid a hang in the event that the
5010          * cmd never gets started but we are still receiving interrupts
5011          */
5012         while (!(poll_cmd->cmd_flags & CFLAG_FINISHED)) {
5013                 if (mptsas_wait_intr(mpt, polltime) == FALSE) {
5014                         NDBG5(("mptsas_poll: command incomplete"));
5015                         rval = FALSE;
5016                         break;
5017                 }
5018         }
5019 
5020         if (rval == FALSE) {
5021 
5022                 /*
5023                  * this isn't supposed to happen, the hba must be wedged
5024                  * Mark this cmd as a timeout.
5025                  */
5026                 mptsas_set_pkt_reason(mpt, poll_cmd, CMD_TIMEOUT,
5027                     (STAT_TIMEOUT|STAT_ABORTED));
5028 
5029                 if (poll_cmd->cmd_queued == FALSE) {
5030 
5031                         NDBG5(("mptsas_poll: not on waitq"));
5032 
5033                         poll_cmd->cmd_pkt->pkt_state |=
5034                             (STATE_GOT_BUS|STATE_GOT_TARGET|STATE_SENT_CMD);
5035                 } else {
5036 
5037                         /* find and remove it from the waitq */
5038                         NDBG5(("mptsas_poll: delete from waitq"));
5039                         mptsas_waitq_delete(mpt, poll_cmd);
5040                 }
5041 
5042         }
5043         mptsas_fma_check(mpt, poll_cmd);
5044         NDBG5(("mptsas_poll: done"));
5045         return (rval);
5046 }
5047 
5048 /*
5049  * Used for polling cmds and TM function
5050  */
5051 static int
5052 mptsas_wait_intr(mptsas_t *mpt, int polltime)
5053 {
5054         int                             cnt;
5055         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
5056         uint32_t                        int_mask;
5057 
5058         NDBG5(("mptsas_wait_intr"));
5059 
5060         mpt->m_polled_intr = 1;
5061 
5062         /*
5063          * Get the current interrupt mask and disable interrupts.  When
5064          * re-enabling ints, set mask to saved value.
5065          */
5066         int_mask = ddi_get32(mpt->m_datap, &mpt->m_reg->HostInterruptMask);
5067         MPTSAS_DISABLE_INTR(mpt);
5068 
5069         /*
5070          * Keep polling for at least (polltime * 1000) seconds
5071          */
5072         for (cnt = 0; cnt < polltime; cnt++) {
5073                 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5074                     DDI_DMA_SYNC_FORCPU);
5075 
5076                 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
5077                     MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
5078 
5079                 if (ddi_get32(mpt->m_acc_post_queue_hdl,
5080                     &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
5081                     ddi_get32(mpt->m_acc_post_queue_hdl,
5082                     &reply_desc_union->Words.High) == 0xFFFFFFFF) {
5083                         drv_usecwait(1000);
5084                         continue;
5085                 }
5086 
5087                 /*
5088                  * The reply is valid, process it according to its
5089                  * type.
5090                  */
5091                 mptsas_process_intr(mpt, reply_desc_union);
5092 
5093                 if (++mpt->m_post_index == mpt->m_post_queue_depth) {
5094                         mpt->m_post_index = 0;
5095                 }
5096 
5097                 /*
5098                  * Update the global reply index
5099                  */
5100                 ddi_put32(mpt->m_datap,
5101                     &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
5102                 mpt->m_polled_intr = 0;
5103 
5104                 /*
5105                  * Re-enable interrupts and quit.
5106                  */
5107                 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask,
5108                     int_mask);
5109                 return (TRUE);
5110 
5111         }
5112 
5113         /*
5114          * Clear polling flag, re-enable interrupts and quit.
5115          */
5116         mpt->m_polled_intr = 0;
5117         ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask, int_mask);
5118         return (FALSE);
5119 }
5120 
5121 static void
5122 mptsas_handle_scsi_io_success(mptsas_t *mpt,
5123     pMpi2ReplyDescriptorsUnion_t reply_desc)
5124 {
5125         pMpi2SCSIIOSuccessReplyDescriptor_t     scsi_io_success;
5126         uint16_t                                SMID;
5127         mptsas_slots_t                          *slots = mpt->m_active;
5128         mptsas_cmd_t                            *cmd = NULL;
5129         struct scsi_pkt                         *pkt;
5130 
5131         ASSERT(mutex_owned(&mpt->m_mutex));
5132 
5133         scsi_io_success = (pMpi2SCSIIOSuccessReplyDescriptor_t)reply_desc;
5134         SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &scsi_io_success->SMID);
5135 
5136         /*
5137          * This is a success reply so just complete the IO.  First, do a sanity
5138          * check on the SMID.  The final slot is used for TM requests, which
5139          * would not come into this reply handler.
5140          */
5141         if ((SMID == 0) || (SMID > slots->m_n_normal)) {
5142                 mptsas_log(mpt, CE_WARN, "?Received invalid SMID of %d\n",
5143                     SMID);
5144                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5145                 return;
5146         }
5147 
5148         cmd = slots->m_slot[SMID];
5149 
5150         /*
5151          * print warning and return if the slot is empty
5152          */
5153         if (cmd == NULL) {
5154                 mptsas_log(mpt, CE_WARN, "?NULL command for successful SCSI IO "
5155                     "in slot %d", SMID);
5156                 return;
5157         }
5158 
5159         pkt = CMD2PKT(cmd);
5160         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
5161             STATE_GOT_STATUS);
5162         if (cmd->cmd_flags & CFLAG_DMAVALID) {
5163                 pkt->pkt_state |= STATE_XFERRED_DATA;
5164         }
5165         pkt->pkt_resid = 0;
5166 
5167         if (cmd->cmd_flags & CFLAG_PASSTHRU) {
5168                 cmd->cmd_flags |= CFLAG_FINISHED;
5169                 cv_broadcast(&mpt->m_passthru_cv);
5170                 return;
5171         } else {
5172                 mptsas_remove_cmd(mpt, cmd);
5173         }
5174 
5175         if (cmd->cmd_flags & CFLAG_RETRY) {
5176                 /*
5177                  * The target returned QFULL or busy, do not add tihs
5178                  * pkt to the doneq since the hba will retry
5179                  * this cmd.
5180                  *
5181                  * The pkt has already been resubmitted in
5182                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
5183                  * Remove this cmd_flag here.
5184                  */
5185                 cmd->cmd_flags &= ~CFLAG_RETRY;
5186         } else {
5187                 mptsas_doneq_add(mpt, cmd);
5188         }
5189 }
5190 
5191 static void
5192 mptsas_handle_address_reply(mptsas_t *mpt,
5193     pMpi2ReplyDescriptorsUnion_t reply_desc)
5194 {
5195         pMpi2AddressReplyDescriptor_t   address_reply;
5196         pMPI2DefaultReply_t             reply;
5197         mptsas_fw_diagnostic_buffer_t   *pBuffer;
5198         uint32_t                        reply_addr, reply_frame_dma_baseaddr;
5199         uint16_t                        SMID, iocstatus;
5200         mptsas_slots_t                  *slots = mpt->m_active;
5201         mptsas_cmd_t                    *cmd = NULL;
5202         uint8_t                         function, buffer_type;
5203         m_replyh_arg_t                  *args;
5204         int                             reply_frame_no;
5205 
5206         ASSERT(mutex_owned(&mpt->m_mutex));
5207 
5208         address_reply = (pMpi2AddressReplyDescriptor_t)reply_desc;
5209         reply_addr = ddi_get32(mpt->m_acc_post_queue_hdl,
5210             &address_reply->ReplyFrameAddress);
5211         SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &address_reply->SMID);
5212 
5213         /*
5214          * If reply frame is not in the proper range we should ignore this
5215          * message and exit the interrupt handler.
5216          */
5217         reply_frame_dma_baseaddr = mpt->m_reply_frame_dma_addr & 0xffffffffu;
5218         if ((reply_addr < reply_frame_dma_baseaddr) ||
5219             (reply_addr >= (reply_frame_dma_baseaddr +
5220             (mpt->m_reply_frame_size * mpt->m_max_replies))) ||
5221             ((reply_addr - reply_frame_dma_baseaddr) %
5222             mpt->m_reply_frame_size != 0)) {
5223                 mptsas_log(mpt, CE_WARN, "?Received invalid reply frame "
5224                     "address 0x%x\n", reply_addr);
5225                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5226                 return;
5227         }
5228 
5229         (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
5230             DDI_DMA_SYNC_FORCPU);
5231         reply = (pMPI2DefaultReply_t)(mpt->m_reply_frame + (reply_addr -
5232             reply_frame_dma_baseaddr));
5233         function = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->Function);
5234 
5235         NDBG31(("mptsas_handle_address_reply: function 0x%x, reply_addr=0x%x",
5236             function, reply_addr));
5237 
5238         /*
5239          * don't get slot information and command for events since these values
5240          * don't exist
5241          */
5242         if ((function != MPI2_FUNCTION_EVENT_NOTIFICATION) &&
5243             (function != MPI2_FUNCTION_DIAG_BUFFER_POST)) {
5244                 /*
5245                  * This could be a TM reply, which use the last allocated SMID,
5246                  * so allow for that.
5247                  */
5248                 if ((SMID == 0) || (SMID > (slots->m_n_normal + 1))) {
5249                         mptsas_log(mpt, CE_WARN, "?Received invalid SMID of "
5250                             "%d\n", SMID);
5251                         ddi_fm_service_impact(mpt->m_dip,
5252                             DDI_SERVICE_UNAFFECTED);
5253                         return;
5254                 }
5255 
5256                 cmd = slots->m_slot[SMID];
5257 
5258                 /*
5259                  * print warning and return if the slot is empty
5260                  */
5261                 if (cmd == NULL) {
5262                         mptsas_log(mpt, CE_WARN, "?NULL command for address "
5263                             "reply in slot %d", SMID);
5264                         return;
5265                 }
5266                 if ((cmd->cmd_flags &
5267                     (CFLAG_PASSTHRU | CFLAG_CONFIG | CFLAG_FW_DIAG))) {
5268                         cmd->cmd_rfm = reply_addr;
5269                         cmd->cmd_flags |= CFLAG_FINISHED;
5270                         cv_broadcast(&mpt->m_passthru_cv);
5271                         cv_broadcast(&mpt->m_config_cv);
5272                         cv_broadcast(&mpt->m_fw_diag_cv);
5273                         return;
5274                 } else if (!(cmd->cmd_flags & CFLAG_FW_CMD)) {
5275                         mptsas_remove_cmd(mpt, cmd);
5276                 }
5277                 NDBG31(("\t\tmptsas_process_intr: slot=%d", SMID));
5278         }
5279         /*
5280          * Depending on the function, we need to handle
5281          * the reply frame (and cmd) differently.
5282          */
5283         switch (function) {
5284         case MPI2_FUNCTION_SCSI_IO_REQUEST:
5285                 mptsas_check_scsi_io_error(mpt, (pMpi2SCSIIOReply_t)reply, cmd);
5286                 break;
5287         case MPI2_FUNCTION_SCSI_TASK_MGMT:
5288                 cmd->cmd_rfm = reply_addr;
5289                 mptsas_check_task_mgt(mpt, (pMpi2SCSIManagementReply_t)reply,
5290                     cmd);
5291                 break;
5292         case MPI2_FUNCTION_FW_DOWNLOAD:
5293                 cmd->cmd_flags |= CFLAG_FINISHED;
5294                 cv_signal(&mpt->m_fw_cv);
5295                 break;
5296         case MPI2_FUNCTION_EVENT_NOTIFICATION:
5297                 reply_frame_no = (reply_addr - reply_frame_dma_baseaddr) /
5298                     mpt->m_reply_frame_size;
5299                 args = &mpt->m_replyh_args[reply_frame_no];
5300                 args->mpt = (void *)mpt;
5301                 args->rfm = reply_addr;
5302 
5303                 /*
5304                  * Record the event if its type is enabled in
5305                  * this mpt instance by ioctl.
5306                  */
5307                 mptsas_record_event(args);
5308 
5309                 /*
5310                  * Handle time critical events
5311                  * NOT_RESPONDING/ADDED only now
5312                  */
5313                 if (mptsas_handle_event_sync(args) == DDI_SUCCESS) {
5314                         /*
5315                          * Would not return main process,
5316                          * just let taskq resolve ack action
5317                          * and ack would be sent in taskq thread
5318                          */
5319                         NDBG20(("send mptsas_handle_event_sync success"));
5320                 }
5321 
5322                 if (mpt->m_in_reset) {
5323                         NDBG20(("dropping event received during reset"));
5324                         return;
5325                 }
5326 
5327                 if ((ddi_taskq_dispatch(mpt->m_event_taskq, mptsas_handle_event,
5328                     (void *)args, DDI_NOSLEEP)) != DDI_SUCCESS) {
5329                         mptsas_log(mpt, CE_WARN, "No memory available"
5330                         "for dispatch taskq");
5331                         /*
5332                          * Return the reply frame to the free queue.
5333                          */
5334                         ddi_put32(mpt->m_acc_free_queue_hdl,
5335                             &((uint32_t *)(void *)
5336                             mpt->m_free_queue)[mpt->m_free_index], reply_addr);
5337                         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
5338                             DDI_DMA_SYNC_FORDEV);
5339                         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
5340                                 mpt->m_free_index = 0;
5341                         }
5342 
5343                         ddi_put32(mpt->m_datap,
5344                             &mpt->m_reg->ReplyFreeHostIndex, mpt->m_free_index);
5345                 }
5346                 return;
5347         case MPI2_FUNCTION_DIAG_BUFFER_POST:
5348                 /*
5349                  * If SMID is 0, this implies that the reply is due to a
5350                  * release function with a status that the buffer has been
5351                  * released.  Set the buffer flags accordingly.
5352                  */
5353                 if (SMID == 0) {
5354                         iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
5355                             &reply->IOCStatus);
5356                         buffer_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
5357                             &(((pMpi2DiagBufferPostReply_t)reply)->BufferType));
5358                         if (iocstatus == MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED) {
5359                                 pBuffer =
5360                                     &mpt->m_fw_diag_buffer_list[buffer_type];
5361                                 pBuffer->valid_data = TRUE;
5362                                 pBuffer->owned_by_firmware = FALSE;
5363                                 pBuffer->immediate = FALSE;
5364                         }
5365                 } else {
5366                         /*
5367                          * Normal handling of diag post reply with SMID.
5368                          */
5369                         cmd = slots->m_slot[SMID];
5370 
5371                         /*
5372                          * print warning and return if the slot is empty
5373                          */
5374                         if (cmd == NULL) {
5375                                 mptsas_log(mpt, CE_WARN, "?NULL command for "
5376                                     "address reply in slot %d", SMID);
5377                                 return;
5378                         }
5379                         cmd->cmd_rfm = reply_addr;
5380                         cmd->cmd_flags |= CFLAG_FINISHED;
5381                         cv_broadcast(&mpt->m_fw_diag_cv);
5382                 }
5383                 return;
5384         default:
5385                 mptsas_log(mpt, CE_WARN, "Unknown function 0x%x ", function);
5386                 break;
5387         }
5388 
5389         /*
5390          * Return the reply frame to the free queue.
5391          */
5392         ddi_put32(mpt->m_acc_free_queue_hdl,
5393             &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
5394             reply_addr);
5395         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
5396             DDI_DMA_SYNC_FORDEV);
5397         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
5398                 mpt->m_free_index = 0;
5399         }
5400         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
5401             mpt->m_free_index);
5402 
5403         if (cmd->cmd_flags & CFLAG_FW_CMD)
5404                 return;
5405 
5406         if (cmd->cmd_flags & CFLAG_RETRY) {
5407                 /*
5408                  * The target returned QFULL or busy, do not add this
5409                  * pkt to the doneq since the hba will retry
5410                  * this cmd.
5411                  *
5412                  * The pkt has already been resubmitted in
5413                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
5414                  * Remove this cmd_flag here.
5415                  */
5416                 cmd->cmd_flags &= ~CFLAG_RETRY;
5417         } else {
5418                 mptsas_doneq_add(mpt, cmd);
5419         }
5420 }
5421 
5422 #ifdef MPTSAS_DEBUG
5423 static uint8_t mptsas_last_sense[256];
5424 #endif
5425 
5426 static void
5427 mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
5428     mptsas_cmd_t *cmd)
5429 {
5430         uint8_t                 scsi_status, scsi_state;
5431         uint16_t                ioc_status, cmd_rqs_len;
5432         uint32_t                xferred, sensecount, responsedata, loginfo = 0;
5433         struct scsi_pkt         *pkt;
5434         struct scsi_arq_status  *arqstat;
5435         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
5436         uint8_t                 *sensedata = NULL;
5437         uint64_t                sas_wwn;
5438         uint8_t                 phy;
5439         char                    wwn_str[MPTSAS_WWN_STRLEN];
5440 
5441         scsi_status = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIStatus);
5442         ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5443         scsi_state = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIState);
5444         xferred = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->TransferCount);
5445         sensecount = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->SenseCount);
5446         responsedata = ddi_get32(mpt->m_acc_reply_frame_hdl,
5447             &reply->ResponseInfo);
5448 
5449         if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
5450                 sas_wwn = ptgt->m_addr.mta_wwn;
5451                 phy = ptgt->m_phynum;
5452                 if (sas_wwn == 0) {
5453                         (void) sprintf(wwn_str, "p%x", phy);
5454                 } else {
5455                         (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
5456                 }
5457                 loginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
5458                     &reply->IOCLogInfo);
5459                 mptsas_log(mpt, CE_NOTE,
5460                     "?Log info 0x%x received for target %d %s.\n"
5461                     "\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5462                     loginfo, Tgt(cmd), wwn_str, scsi_status, ioc_status,
5463                     scsi_state);
5464         }
5465 
5466         NDBG31(("\t\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5467             scsi_status, ioc_status, scsi_state));
5468 
5469         pkt = CMD2PKT(cmd);
5470         *(pkt->pkt_scbp) = scsi_status;
5471 
5472         if (loginfo == 0x31170000) {
5473                 /*
5474                  * if loginfo PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY
5475                  * 0x31170000 comes, that means the device missing delay
5476                  * is in progressing, the command need retry later.
5477                  */
5478                 *(pkt->pkt_scbp) = STATUS_BUSY;
5479                 return;
5480         }
5481 
5482         if ((scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) &&
5483             ((ioc_status & MPI2_IOCSTATUS_MASK) ==
5484             MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE)) {
5485                 pkt->pkt_reason = CMD_INCOMPLETE;
5486                 pkt->pkt_state |= STATE_GOT_BUS;
5487                 if (ptgt->m_reset_delay == 0) {
5488                         mptsas_set_throttle(mpt, ptgt,
5489                             DRAIN_THROTTLE);
5490                 }
5491                 return;
5492         }
5493 
5494         if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
5495                 responsedata &= 0x000000FF;
5496                 if (responsedata & MPTSAS_SCSI_RESPONSE_CODE_TLR_OFF) {
5497                         mptsas_log(mpt, CE_NOTE, "Do not support the TLR\n");
5498                         pkt->pkt_reason = CMD_TLR_OFF;
5499                         return;
5500                 }
5501         }
5502 
5503 
5504         switch (scsi_status) {
5505         case MPI2_SCSI_STATUS_CHECK_CONDITION:
5506                 pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5507                 arqstat = (void*)(pkt->pkt_scbp);
5508                 arqstat->sts_rqpkt_status = *((struct scsi_status *)
5509                     (pkt->pkt_scbp));
5510                 pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
5511                     STATE_SENT_CMD | STATE_GOT_STATUS | STATE_ARQ_DONE);
5512                 if (cmd->cmd_flags & CFLAG_XARQ) {
5513                         pkt->pkt_state |= STATE_XARQ_DONE;
5514                 }
5515                 if (pkt->pkt_resid != cmd->cmd_dmacount) {
5516                         pkt->pkt_state |= STATE_XFERRED_DATA;
5517                 }
5518                 arqstat->sts_rqpkt_reason = pkt->pkt_reason;
5519                 arqstat->sts_rqpkt_state  = pkt->pkt_state;
5520                 arqstat->sts_rqpkt_state |= STATE_XFERRED_DATA;
5521                 arqstat->sts_rqpkt_statistics = pkt->pkt_statistics;
5522                 sensedata = (uint8_t *)&arqstat->sts_sensedata;
5523                 cmd_rqs_len = cmd->cmd_extrqslen ?
5524                     cmd->cmd_extrqslen : cmd->cmd_rqslen;
5525                 (void) ddi_dma_sync(mpt->m_dma_req_sense_hdl, 0, 0,
5526                     DDI_DMA_SYNC_FORKERNEL);
5527 #ifdef MPTSAS_DEBUG
5528                 bcopy(cmd->cmd_arq_buf, mptsas_last_sense,
5529                     ((cmd_rqs_len >= sizeof (mptsas_last_sense)) ?
5530                     sizeof (mptsas_last_sense):cmd_rqs_len));
5531 #endif
5532                 bcopy((uchar_t *)cmd->cmd_arq_buf, sensedata,
5533                     ((cmd_rqs_len >= sensecount) ? sensecount :
5534                     cmd_rqs_len));
5535                 arqstat->sts_rqpkt_resid = (cmd_rqs_len - sensecount);
5536                 cmd->cmd_flags |= CFLAG_CMDARQ;
5537                 /*
5538                  * Set proper status for pkt if autosense was valid
5539                  */
5540                 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
5541                         struct scsi_status zero_status = { 0 };
5542                         arqstat->sts_rqpkt_status = zero_status;
5543                 }
5544 
5545                 /*
5546                  * ASC=0x47 is parity error
5547                  * ASC=0x48 is initiator detected error received
5548                  */
5549                 if ((scsi_sense_key(sensedata) == KEY_ABORTED_COMMAND) &&
5550                     ((scsi_sense_asc(sensedata) == 0x47) ||
5551                     (scsi_sense_asc(sensedata) == 0x48))) {
5552                         mptsas_log(mpt, CE_NOTE, "Aborted_command!");
5553                 }
5554 
5555                 /*
5556                  * ASC/ASCQ=0x3F/0x0E means report_luns data changed
5557                  * ASC/ASCQ=0x25/0x00 means invalid lun
5558                  */
5559                 if (((scsi_sense_key(sensedata) == KEY_UNIT_ATTENTION) &&
5560                     (scsi_sense_asc(sensedata) == 0x3F) &&
5561                     (scsi_sense_ascq(sensedata) == 0x0E)) ||
5562                     ((scsi_sense_key(sensedata) == KEY_ILLEGAL_REQUEST) &&
5563                     (scsi_sense_asc(sensedata) == 0x25) &&
5564                     (scsi_sense_ascq(sensedata) == 0x00))) {
5565                         mptsas_topo_change_list_t *topo_node = NULL;
5566 
5567                         topo_node = kmem_zalloc(
5568                             sizeof (mptsas_topo_change_list_t),
5569                             KM_NOSLEEP);
5570                         if (topo_node == NULL) {
5571                                 mptsas_log(mpt, CE_NOTE, "No memory"
5572                                     "resource for handle SAS dynamic"
5573                                     "reconfigure.\n");
5574                                 break;
5575                         }
5576                         topo_node->mpt = mpt;
5577                         topo_node->event = MPTSAS_DR_EVENT_RECONFIG_TARGET;
5578                         topo_node->un.phymask = ptgt->m_addr.mta_phymask;
5579                         topo_node->devhdl = ptgt->m_devhdl;
5580                         topo_node->object = (void *)ptgt;
5581                         topo_node->flags = MPTSAS_TOPO_FLAG_LUN_ASSOCIATED;
5582 
5583                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
5584                             mptsas_handle_dr,
5585                             (void *)topo_node,
5586                             DDI_NOSLEEP)) != DDI_SUCCESS) {
5587                                 kmem_free(topo_node,
5588                                     sizeof (mptsas_topo_change_list_t));
5589                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq"
5590                                     "for handle SAS dynamic reconfigure"
5591                                     "failed. \n");
5592                         }
5593                 }
5594                 break;
5595         case MPI2_SCSI_STATUS_GOOD:
5596                 switch (ioc_status & MPI2_IOCSTATUS_MASK) {
5597                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
5598                         pkt->pkt_reason = CMD_DEV_GONE;
5599                         pkt->pkt_state |= STATE_GOT_BUS;
5600                         if (ptgt->m_reset_delay == 0) {
5601                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5602                         }
5603                         NDBG31(("lost disk for target%d, command:%x",
5604                             Tgt(cmd), pkt->pkt_cdbp[0]));
5605                         break;
5606                 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
5607                         NDBG31(("data overrun: xferred=%d", xferred));
5608                         NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5609                         pkt->pkt_reason = CMD_DATA_OVR;
5610                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5611                             | STATE_SENT_CMD | STATE_GOT_STATUS
5612                             | STATE_XFERRED_DATA);
5613                         pkt->pkt_resid = 0;
5614                         break;
5615                 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
5616                 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
5617                         NDBG31(("data underrun: xferred=%d", xferred));
5618                         NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5619                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5620                             | STATE_SENT_CMD | STATE_GOT_STATUS);
5621                         pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5622                         if (pkt->pkt_resid != cmd->cmd_dmacount) {
5623                                 pkt->pkt_state |= STATE_XFERRED_DATA;
5624                         }
5625                         break;
5626                 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
5627                         if (cmd->cmd_active_expiration <= gethrtime()) {
5628                                 /*
5629                                  * When timeout requested, propagate
5630                                  * proper reason and statistics to
5631                                  * target drivers.
5632                                  */
5633                                 mptsas_set_pkt_reason(mpt, cmd, CMD_TIMEOUT,
5634                                     STAT_BUS_RESET | STAT_TIMEOUT);
5635                         } else {
5636                                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
5637                                     STAT_BUS_RESET);
5638                         }
5639                         break;
5640                 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
5641                 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
5642                         mptsas_set_pkt_reason(mpt,
5643                             cmd, CMD_RESET, STAT_DEV_RESET);
5644                         break;
5645                 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
5646                 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
5647                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET);
5648                         mptsas_set_pkt_reason(mpt,
5649                             cmd, CMD_TERMINATED, STAT_TERMINATED);
5650                         break;
5651                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
5652                 case MPI2_IOCSTATUS_BUSY:
5653                         /*
5654                          * set throttles to drain
5655                          */
5656                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
5657                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
5658                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5659                         }
5660 
5661                         /*
5662                          * retry command
5663                          */
5664                         cmd->cmd_flags |= CFLAG_RETRY;
5665                         cmd->cmd_pkt_flags |= FLAG_HEAD;
5666 
5667                         (void) mptsas_accept_pkt(mpt, cmd);
5668                         break;
5669                 default:
5670                         mptsas_log(mpt, CE_WARN,
5671                             "unknown ioc_status = %x\n", ioc_status);
5672                         mptsas_log(mpt, CE_CONT, "scsi_state = %x, transfer "
5673                             "count = %x, scsi_status = %x", scsi_state,
5674                             xferred, scsi_status);
5675                         break;
5676                 }
5677                 break;
5678         case MPI2_SCSI_STATUS_TASK_SET_FULL:
5679                 mptsas_handle_qfull(mpt, cmd);
5680                 break;
5681         case MPI2_SCSI_STATUS_BUSY:
5682                 NDBG31(("scsi_status busy received"));
5683                 break;
5684         case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
5685                 NDBG31(("scsi_status reservation conflict received"));
5686                 break;
5687         default:
5688                 mptsas_log(mpt, CE_WARN, "scsi_status=%x, ioc_status=%x\n",
5689                     scsi_status, ioc_status);
5690                 mptsas_log(mpt, CE_WARN,
5691                     "mptsas_process_intr: invalid scsi status\n");
5692                 break;
5693         }
5694 }
5695 
5696 static void
5697 mptsas_check_task_mgt(mptsas_t *mpt, pMpi2SCSIManagementReply_t reply,
5698         mptsas_cmd_t *cmd)
5699 {
5700         uint8_t         task_type;
5701         uint16_t        ioc_status;
5702         uint32_t        log_info;
5703         uint16_t        dev_handle;
5704         struct scsi_pkt *pkt = CMD2PKT(cmd);
5705 
5706         task_type = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->TaskType);
5707         ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5708         log_info = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->IOCLogInfo);
5709         dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->DevHandle);
5710 
5711         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5712                 mptsas_log(mpt, CE_WARN, "mptsas_check_task_mgt: Task 0x%x "
5713                     "failed. IOCStatus=0x%x IOCLogInfo=0x%x target=%d\n",
5714                     task_type, ioc_status, log_info, dev_handle);
5715                 pkt->pkt_reason = CMD_INCOMPLETE;
5716                 return;
5717         }
5718 
5719         switch (task_type) {
5720         case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
5721         case MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
5722         case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
5723         case MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA:
5724         case MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET:
5725         case MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION:
5726                 break;
5727         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
5728         case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
5729         case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
5730                 /*
5731                  * Check for invalid DevHandle of 0 in case application
5732                  * sends bad command.  DevHandle of 0 could cause problems.
5733                  */
5734                 if (dev_handle == 0) {
5735                         mptsas_log(mpt, CE_WARN, "!Can't flush target with"
5736                             " DevHandle of 0.");
5737                 } else {
5738                         mptsas_flush_target(mpt, dev_handle, Lun(cmd),
5739                             task_type);
5740                 }
5741                 break;
5742         default:
5743                 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
5744                     task_type);
5745                 mptsas_log(mpt, CE_WARN, "ioc status = %x", ioc_status);
5746                 break;
5747         }
5748 }
5749 
5750 static void
5751 mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg)
5752 {
5753         mptsas_t                        *mpt = arg->mpt;
5754         uint64_t                        t = arg->t;
5755         mptsas_cmd_t                    *cmd;
5756         struct scsi_pkt                 *pkt;
5757         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
5758 
5759         mutex_enter(&item->mutex);
5760         while (item->flag & MPTSAS_DONEQ_THREAD_ACTIVE) {
5761                 if (!item->doneq) {
5762                         cv_wait(&item->cv, &item->mutex);
5763                 }
5764                 pkt = NULL;
5765                 if ((cmd = mptsas_doneq_thread_rm(mpt, t)) != NULL) {
5766                         cmd->cmd_flags |= CFLAG_COMPLETED;
5767                         pkt = CMD2PKT(cmd);
5768                 }
5769                 mutex_exit(&item->mutex);
5770                 if (pkt) {
5771                         mptsas_pkt_comp(pkt, cmd);
5772                 }
5773                 mutex_enter(&item->mutex);
5774         }
5775         mutex_exit(&item->mutex);
5776         mutex_enter(&mpt->m_doneq_mutex);
5777         mpt->m_doneq_thread_n--;
5778         cv_broadcast(&mpt->m_doneq_thread_cv);
5779         mutex_exit(&mpt->m_doneq_mutex);
5780 }
5781 
5782 
5783 /*
5784  * mpt interrupt handler.
5785  */
5786 static uint_t
5787 mptsas_intr(caddr_t arg1, caddr_t arg2)
5788 {
5789         mptsas_t                        *mpt = (void *)arg1;
5790         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
5791         uchar_t                         did_reply = FALSE;
5792 
5793         NDBG1(("mptsas_intr: arg1 0x%p arg2 0x%p", (void *)arg1, (void *)arg2));
5794 
5795         mutex_enter(&mpt->m_mutex);
5796 
5797         /*
5798          * If interrupts are shared by two channels then check whether this
5799          * interrupt is genuinely for this channel by making sure first the
5800          * chip is in high power state.
5801          */
5802         if ((mpt->m_options & MPTSAS_OPT_PM) &&
5803             (mpt->m_power_level != PM_LEVEL_D0)) {
5804                 mutex_exit(&mpt->m_mutex);
5805                 return (DDI_INTR_UNCLAIMED);
5806         }
5807 
5808         /*
5809          * If polling, interrupt was triggered by some shared interrupt because
5810          * IOC interrupts are disabled during polling, so polling routine will
5811          * handle any replies.  Considering this, if polling is happening,
5812          * return with interrupt unclaimed.
5813          */
5814         if (mpt->m_polled_intr) {
5815                 mutex_exit(&mpt->m_mutex);
5816                 mptsas_log(mpt, CE_WARN, "mpt_sas: Unclaimed interrupt");
5817                 return (DDI_INTR_UNCLAIMED);
5818         }
5819 
5820         /*
5821          * Read the istat register.
5822          */
5823         if ((INTPENDING(mpt)) != 0) {
5824                 /*
5825                  * read fifo until empty.
5826                  */
5827 #ifndef __lock_lint
5828                 _NOTE(CONSTCOND)
5829 #endif
5830                 while (TRUE) {
5831                         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5832                             DDI_DMA_SYNC_FORCPU);
5833                         reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
5834                             MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
5835 
5836                         if (ddi_get32(mpt->m_acc_post_queue_hdl,
5837                             &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
5838                             ddi_get32(mpt->m_acc_post_queue_hdl,
5839                             &reply_desc_union->Words.High) == 0xFFFFFFFF) {
5840                                 break;
5841                         }
5842 
5843                         /*
5844                          * The reply is valid, process it according to its
5845                          * type.  Also, set a flag for updating the reply index
5846                          * after they've all been processed.
5847                          */
5848                         did_reply = TRUE;
5849 
5850                         mptsas_process_intr(mpt, reply_desc_union);
5851 
5852                         /*
5853                          * Increment post index and roll over if needed.
5854                          */
5855                         if (++mpt->m_post_index == mpt->m_post_queue_depth) {
5856                                 mpt->m_post_index = 0;
5857                         }
5858                 }
5859 
5860                 /*
5861                  * Update the global reply index if at least one reply was
5862                  * processed.
5863                  */
5864                 if (did_reply) {
5865                         ddi_put32(mpt->m_datap,
5866                             &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
5867                 }
5868         } else {
5869                 mutex_exit(&mpt->m_mutex);
5870                 return (DDI_INTR_UNCLAIMED);
5871         }
5872         NDBG1(("mptsas_intr complete"));
5873 
5874         /*
5875          * If no helper threads are created, process the doneq in ISR. If
5876          * helpers are created, use the doneq length as a metric to measure the
5877          * load on the interrupt CPU. If it is long enough, which indicates the
5878          * load is heavy, then we deliver the IO completions to the helpers.
5879          * This measurement has some limitations, although it is simple and
5880          * straightforward and works well for most of the cases at present.
5881          */
5882         if (!mpt->m_doneq_thread_n ||
5883             (mpt->m_doneq_len <= mpt->m_doneq_length_threshold)) {
5884                 mptsas_doneq_empty(mpt);
5885         } else {
5886                 mptsas_deliver_doneq_thread(mpt);
5887         }
5888 
5889         /*
5890          * If there are queued cmd, start them now.
5891          */
5892         if (mpt->m_waitq != NULL) {
5893                 mptsas_restart_waitq(mpt);
5894         }
5895 
5896         mutex_exit(&mpt->m_mutex);
5897         return (DDI_INTR_CLAIMED);
5898 }
5899 
5900 static void
5901 mptsas_process_intr(mptsas_t *mpt,
5902     pMpi2ReplyDescriptorsUnion_t reply_desc_union)
5903 {
5904         uint8_t reply_type;
5905 
5906         ASSERT(mutex_owned(&mpt->m_mutex));
5907 
5908         /*
5909          * The reply is valid, process it according to its
5910          * type.  Also, set a flag for updated the reply index
5911          * after they've all been processed.
5912          */
5913         reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
5914             &reply_desc_union->Default.ReplyFlags);
5915         reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
5916         if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS ||
5917             reply_type == MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS) {
5918                 mptsas_handle_scsi_io_success(mpt, reply_desc_union);
5919         } else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
5920                 mptsas_handle_address_reply(mpt, reply_desc_union);
5921         } else {
5922                 mptsas_log(mpt, CE_WARN, "?Bad reply type %x", reply_type);
5923                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5924         }
5925 
5926         /*
5927          * Clear the reply descriptor for re-use and increment
5928          * index.
5929          */
5930         ddi_put64(mpt->m_acc_post_queue_hdl,
5931             &((uint64_t *)(void *)mpt->m_post_queue)[mpt->m_post_index],
5932             0xFFFFFFFFFFFFFFFF);
5933         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5934             DDI_DMA_SYNC_FORDEV);
5935 }
5936 
5937 /*
5938  * handle qfull condition
5939  */
5940 static void
5941 mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd)
5942 {
5943         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
5944 
5945         if ((++cmd->cmd_qfull_retries > ptgt->m_qfull_retries) ||
5946             (ptgt->m_qfull_retries == 0)) {
5947                 /*
5948                  * We have exhausted the retries on QFULL, or,
5949                  * the target driver has indicated that it
5950                  * wants to handle QFULL itself by setting
5951                  * qfull-retries capability to 0. In either case
5952                  * we want the target driver's QFULL handling
5953                  * to kick in. We do this by having pkt_reason
5954                  * as CMD_CMPLT and pkt_scbp as STATUS_QFULL.
5955                  */
5956                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5957         } else {
5958                 if (ptgt->m_reset_delay == 0) {
5959                         ptgt->m_t_throttle =
5960                             max((ptgt->m_t_ncmds - 2), 0);
5961                 }
5962 
5963                 cmd->cmd_pkt_flags |= FLAG_HEAD;
5964                 cmd->cmd_flags &= ~(CFLAG_TRANFLAG);
5965                 cmd->cmd_flags |= CFLAG_RETRY;
5966 
5967                 (void) mptsas_accept_pkt(mpt, cmd);
5968 
5969                 /*
5970                  * when target gives queue full status with no commands
5971                  * outstanding (m_t_ncmds == 0), throttle is set to 0
5972                  * (HOLD_THROTTLE), and the queue full handling start
5973                  * (see psarc/1994/313); if there are commands outstanding,
5974                  * throttle is set to (m_t_ncmds - 2)
5975                  */
5976                 if (ptgt->m_t_throttle == HOLD_THROTTLE) {
5977                         /*
5978                          * By setting throttle to QFULL_THROTTLE, we
5979                          * avoid submitting new commands and in
5980                          * mptsas_restart_cmd find out slots which need
5981                          * their throttles to be cleared.
5982                          */
5983                         mptsas_set_throttle(mpt, ptgt, QFULL_THROTTLE);
5984                         if (mpt->m_restart_cmd_timeid == 0) {
5985                                 mpt->m_restart_cmd_timeid =
5986                                     timeout(mptsas_restart_cmd, mpt,
5987                                     ptgt->m_qfull_retry_interval);
5988                         }
5989                 }
5990         }
5991 }
5992 
5993 mptsas_phymask_t
5994 mptsas_physport_to_phymask(mptsas_t *mpt, uint8_t physport)
5995 {
5996         mptsas_phymask_t        phy_mask = 0;
5997         uint8_t                 i = 0;
5998 
5999         NDBG20(("mptsas%d physport_to_phymask enter", mpt->m_instance));
6000 
6001         ASSERT(mutex_owned(&mpt->m_mutex));
6002 
6003         /*
6004          * If physport is 0xFF, this is a RAID volume.  Use phymask of 0.
6005          */
6006         if (physport == 0xFF) {
6007                 return (0);
6008         }
6009 
6010         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
6011                 if (mpt->m_phy_info[i].attached_devhdl &&
6012                     (mpt->m_phy_info[i].phy_mask != 0) &&
6013                     (mpt->m_phy_info[i].port_num == physport)) {
6014                         phy_mask = mpt->m_phy_info[i].phy_mask;
6015                         break;
6016                 }
6017         }
6018         NDBG20(("mptsas%d physport_to_phymask:physport :%x phymask :%x, ",
6019             mpt->m_instance, physport, phy_mask));
6020         return (phy_mask);
6021 }
6022 
6023 /*
6024  * mpt free device handle after device gone, by use of passthrough
6025  */
6026 static int
6027 mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl)
6028 {
6029         Mpi2SasIoUnitControlRequest_t   req;
6030         Mpi2SasIoUnitControlReply_t     rep;
6031         int                             ret;
6032 
6033         ASSERT(mutex_owned(&mpt->m_mutex));
6034 
6035         /*
6036          * Need to compose a SAS IO Unit Control request message
6037          * and call mptsas_do_passthru() function
6038          */
6039         bzero(&req, sizeof (req));
6040         bzero(&rep, sizeof (rep));
6041 
6042         req.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
6043         req.Operation = MPI2_SAS_OP_REMOVE_DEVICE;
6044         req.DevHandle = LE_16(devhdl);
6045 
6046         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
6047             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
6048         if (ret != 0) {
6049                 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
6050                     "Control error %d", ret);
6051                 return (DDI_FAILURE);
6052         }
6053 
6054         /* do passthrough success, check the ioc status */
6055         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
6056                 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
6057                     "Control IOCStatus %d", LE_16(rep.IOCStatus));
6058                 return (DDI_FAILURE);
6059         }
6060 
6061         return (DDI_SUCCESS);
6062 }
6063 
6064 static void
6065 mptsas_update_phymask(mptsas_t *mpt)
6066 {
6067         mptsas_phymask_t mask = 0, phy_mask;
6068         char            *phy_mask_name;
6069         uint8_t         current_port;
6070         int             i, j;
6071 
6072         NDBG20(("mptsas%d update phymask ", mpt->m_instance));
6073 
6074         ASSERT(mutex_owned(&mpt->m_mutex));
6075 
6076         (void) mptsas_get_sas_io_unit_page(mpt);
6077 
6078         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
6079 
6080         for (i = 0; i < mpt->m_num_phys; i++) {
6081                 phy_mask = 0x00;
6082 
6083                 if (mpt->m_phy_info[i].attached_devhdl == 0)
6084                         continue;
6085 
6086                 bzero(phy_mask_name, sizeof (phy_mask_name));
6087 
6088                 current_port = mpt->m_phy_info[i].port_num;
6089 
6090                 if ((mask & (1 << i)) != 0)
6091                         continue;
6092 
6093                 for (j = 0; j < mpt->m_num_phys; j++) {
6094                         if (mpt->m_phy_info[j].attached_devhdl &&
6095                             (mpt->m_phy_info[j].port_num == current_port)) {
6096                                 phy_mask |= (1 << j);
6097                         }
6098                 }
6099                 mask = mask | phy_mask;
6100 
6101                 for (j = 0; j < mpt->m_num_phys; j++) {
6102                         if ((phy_mask >> j) & 0x01) {
6103                                 mpt->m_phy_info[j].phy_mask = phy_mask;
6104                         }
6105                 }
6106 
6107                 (void) sprintf(phy_mask_name, "%x", phy_mask);
6108 
6109                 mutex_exit(&mpt->m_mutex);
6110                 /*
6111                  * register a iport, if the port has already been existed
6112                  * SCSA will do nothing and just return.
6113                  */
6114                 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
6115                 mutex_enter(&mpt->m_mutex);
6116         }
6117         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
6118         NDBG20(("mptsas%d update phymask return", mpt->m_instance));
6119 }
6120 
6121 /*
6122  * mptsas_handle_dr is a task handler for DR, the DR action includes:
6123  * 1. Directly attched Device Added/Removed.
6124  * 2. Expander Device Added/Removed.
6125  * 3. Indirectly Attached Device Added/Expander.
6126  * 4. LUNs of a existing device status change.
6127  * 5. RAID volume created/deleted.
6128  * 6. Member of RAID volume is released because of RAID deletion.
6129  * 7. Physical disks are removed because of RAID creation.
6130  */
6131 static void
6132 mptsas_handle_dr(void *args) {
6133         mptsas_topo_change_list_t       *topo_node = NULL;
6134         mptsas_topo_change_list_t       *save_node = NULL;
6135         mptsas_t                        *mpt;
6136         dev_info_t                      *parent = NULL;
6137         mptsas_phymask_t                phymask = 0;
6138         char                            *phy_mask_name;
6139         uint8_t                         flags = 0, physport = 0xff;
6140         uint8_t                         port_update = 0;
6141         uint_t                          event;
6142 
6143         topo_node = (mptsas_topo_change_list_t *)args;
6144 
6145         mpt = topo_node->mpt;
6146         event = topo_node->event;
6147         flags = topo_node->flags;
6148 
6149         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
6150 
6151         NDBG20(("mptsas%d handle_dr enter", mpt->m_instance));
6152 
6153         switch (event) {
6154         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
6155                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6156                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE) ||
6157                     (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6158                         /*
6159                          * Direct attached or expander attached device added
6160                          * into system or a Phys Disk that is being unhidden.
6161                          */
6162                         port_update = 1;
6163                 }
6164                 break;
6165         case MPTSAS_DR_EVENT_RECONFIG_SMP:
6166                 /*
6167                  * New expander added into system, it must be the head
6168                  * of topo_change_list_t
6169                  */
6170                 port_update = 1;
6171                 break;
6172         default:
6173                 port_update = 0;
6174                 break;
6175         }
6176         /*
6177          * All cases port_update == 1 may cause initiator port form change
6178          */
6179         mutex_enter(&mpt->m_mutex);
6180         if (mpt->m_port_chng && port_update) {
6181                 /*
6182                  * mpt->m_port_chng flag indicates some PHYs of initiator
6183                  * port have changed to online. So when expander added or
6184                  * directly attached device online event come, we force to
6185                  * update port information by issueing SAS IO Unit Page and
6186                  * update PHYMASKs.
6187                  */
6188                 (void) mptsas_update_phymask(mpt);
6189                 mpt->m_port_chng = 0;
6190 
6191         }
6192         mutex_exit(&mpt->m_mutex);
6193         while (topo_node) {
6194                 phymask = 0;
6195                 if (parent == NULL) {
6196                         physport = topo_node->un.physport;
6197                         event = topo_node->event;
6198                         flags = topo_node->flags;
6199                         if (event & (MPTSAS_DR_EVENT_OFFLINE_TARGET |
6200                             MPTSAS_DR_EVENT_OFFLINE_SMP)) {
6201                                 /*
6202                                  * For all offline events, phymask is known
6203                                  */
6204                                 phymask = topo_node->un.phymask;
6205                                 goto find_parent;
6206                         }
6207                         if (event & MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
6208                                 goto handle_topo_change;
6209                         }
6210                         if (flags & MPTSAS_TOPO_FLAG_LUN_ASSOCIATED) {
6211                                 phymask = topo_node->un.phymask;
6212                                 goto find_parent;
6213                         }
6214 
6215                         if ((flags ==
6216                             MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) &&
6217                             (event == MPTSAS_DR_EVENT_RECONFIG_TARGET)) {
6218                                 /*
6219                                  * There is no any field in IR_CONFIG_CHANGE
6220                                  * event indicate physport/phynum, let's get
6221                                  * parent after SAS Device Page0 request.
6222                                  */
6223                                 goto handle_topo_change;
6224                         }
6225 
6226                         mutex_enter(&mpt->m_mutex);
6227                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6228                                 /*
6229                                  * If the direct attached device added or a
6230                                  * phys disk is being unhidden, argument
6231                                  * physport actually is PHY#, so we have to get
6232                                  * phymask according PHY#.
6233                                  */
6234                                 physport = mpt->m_phy_info[physport].port_num;
6235                         }
6236 
6237                         /*
6238                          * Translate physport to phymask so that we can search
6239                          * parent dip.
6240                          */
6241                         phymask = mptsas_physport_to_phymask(mpt,
6242                             physport);
6243                         mutex_exit(&mpt->m_mutex);
6244 
6245 find_parent:
6246                         bzero(phy_mask_name, MPTSAS_MAX_PHYS);
6247                         /*
6248                          * For RAID topology change node, write the iport name
6249                          * as v0.
6250                          */
6251                         if (flags & MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
6252                                 (void) sprintf(phy_mask_name, "v0");
6253                         } else {
6254                                 /*
6255                                  * phymask can bo 0 if the drive has been
6256                                  * pulled by the time an add event is
6257                                  * processed.  If phymask is 0, just skip this
6258                                  * event and continue.
6259                                  */
6260                                 if (phymask == 0) {
6261                                         mutex_enter(&mpt->m_mutex);
6262                                         save_node = topo_node;
6263                                         topo_node = topo_node->next;
6264                                         ASSERT(save_node);
6265                                         kmem_free(save_node,
6266                                             sizeof (mptsas_topo_change_list_t));
6267                                         mutex_exit(&mpt->m_mutex);
6268 
6269                                         parent = NULL;
6270                                         continue;
6271                                 }
6272                                 (void) sprintf(phy_mask_name, "%x", phymask);
6273                         }
6274                         parent = scsi_hba_iport_find(mpt->m_dip,
6275                             phy_mask_name);
6276                         if (parent == NULL) {
6277                                 mptsas_log(mpt, CE_WARN, "Failed to find an "
6278                                     "iport, should not happen!");
6279                                 goto out;
6280                         }
6281 
6282                 }
6283                 ASSERT(parent);
6284 handle_topo_change:
6285 
6286                 mutex_enter(&mpt->m_mutex);
6287                 /*
6288                  * If HBA is being reset, don't perform operations depending
6289                  * on the IOC. We must free the topo list, however.
6290                  */
6291                 if (!mpt->m_in_reset)
6292                         mptsas_handle_topo_change(topo_node, parent);
6293                 else
6294                         NDBG20(("skipping topo change received during reset"));
6295                 save_node = topo_node;
6296                 topo_node = topo_node->next;
6297                 ASSERT(save_node);
6298                 kmem_free(save_node, sizeof (mptsas_topo_change_list_t));
6299                 mutex_exit(&mpt->m_mutex);
6300 
6301                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6302                     (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) ||
6303                     (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED)) {
6304                         /*
6305                          * If direct attached device associated, make sure
6306                          * reset the parent before start the next one. But
6307                          * all devices associated with expander shares the
6308                          * parent.  Also, reset parent if this is for RAID.
6309                          */
6310                         parent = NULL;
6311                 }
6312         }
6313 out:
6314         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
6315 }
6316 
6317 static void
6318 mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
6319     dev_info_t *parent)
6320 {
6321         mptsas_target_t *ptgt = NULL;
6322         mptsas_smp_t    *psmp = NULL;
6323         mptsas_t        *mpt = (void *)topo_node->mpt;
6324         uint16_t        devhdl;
6325         uint16_t        attached_devhdl;
6326         uint64_t        sas_wwn = 0;
6327         int             rval = 0;
6328         uint32_t        page_address;
6329         uint8_t         phy, flags;
6330         char            *addr = NULL;
6331         dev_info_t      *lundip;
6332         int             circ = 0, circ1 = 0;
6333         char            attached_wwnstr[MPTSAS_WWN_STRLEN];
6334 
6335         NDBG20(("mptsas%d handle_topo_change enter, devhdl 0x%x,"
6336             "event 0x%x, flags 0x%x", mpt->m_instance, topo_node->devhdl,
6337             topo_node->event, topo_node->flags));
6338 
6339         ASSERT(mutex_owned(&mpt->m_mutex));
6340 
6341         switch (topo_node->event) {
6342         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
6343         {
6344                 char *phy_mask_name;
6345                 mptsas_phymask_t phymask = 0;
6346 
6347                 if (topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
6348                         /*
6349                          * Get latest RAID info.
6350                          */
6351                         (void) mptsas_get_raid_info(mpt);
6352                         ptgt = refhash_linear_search(mpt->m_targets,
6353                             mptsas_target_eval_devhdl, &topo_node->devhdl);
6354                         if (ptgt == NULL)
6355                                 break;
6356                 } else {
6357                         ptgt = (void *)topo_node->object;
6358                 }
6359 
6360                 if (ptgt == NULL) {
6361                         /*
6362                          * If a Phys Disk was deleted, RAID info needs to be
6363                          * updated to reflect the new topology.
6364                          */
6365                         (void) mptsas_get_raid_info(mpt);
6366 
6367                         /*
6368                          * Get sas device page 0 by DevHandle to make sure if
6369                          * SSP/SATA end device exist.
6370                          */
6371                         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
6372                             MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
6373                             topo_node->devhdl;
6374 
6375                         rval = mptsas_get_target_device_info(mpt, page_address,
6376                             &devhdl, &ptgt);
6377                         if (rval == DEV_INFO_WRONG_DEVICE_TYPE) {
6378                                 mptsas_log(mpt, CE_NOTE,
6379                                     "mptsas_handle_topo_change: target %d is "
6380                                     "not a SAS/SATA device. \n",
6381                                     topo_node->devhdl);
6382                         } else if (rval == DEV_INFO_FAIL_ALLOC) {
6383                                 mptsas_log(mpt, CE_NOTE,
6384                                     "mptsas_handle_topo_change: could not "
6385                                     "allocate memory. \n");
6386                         } else if (rval == DEV_INFO_FAIL_GUID) {
6387                                 mptsas_log(mpt, CE_NOTE,
6388                                     "mptsas_handle_topo_change: could not "
6389                                     "get SATA GUID for target %d. \n",
6390                                     topo_node->devhdl);
6391                         }
6392                         /*
6393                          * If rval is DEV_INFO_PHYS_DISK or indicates failure
6394                          * then there is nothing else to do, just leave.
6395                          */
6396                         if (rval != DEV_INFO_SUCCESS) {
6397                                 return;
6398                         }
6399                 }
6400 
6401                 ASSERT(ptgt->m_devhdl == topo_node->devhdl);
6402 
6403                 mutex_exit(&mpt->m_mutex);
6404                 flags = topo_node->flags;
6405 
6406                 if (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) {
6407                         phymask = ptgt->m_addr.mta_phymask;
6408                         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
6409                         (void) sprintf(phy_mask_name, "%x", phymask);
6410                         parent = scsi_hba_iport_find(mpt->m_dip,
6411                             phy_mask_name);
6412                         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
6413                         if (parent == NULL) {
6414                                 mptsas_log(mpt, CE_WARN, "Failed to find a "
6415                                     "iport for PD, should not happen!");
6416                                 mutex_enter(&mpt->m_mutex);
6417                                 break;
6418                         }
6419                 }
6420 
6421                 if (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
6422                         ndi_devi_enter(parent, &circ1);
6423                         (void) mptsas_config_raid(parent, topo_node->devhdl,
6424                             &lundip);
6425                         ndi_devi_exit(parent, circ1);
6426                 } else {
6427                         /*
6428                          * hold nexus for bus configure
6429                          */
6430                         ndi_devi_enter(scsi_vhci_dip, &circ);
6431                         ndi_devi_enter(parent, &circ1);
6432                         rval = mptsas_config_target(parent, ptgt);
6433                         /*
6434                          * release nexus for bus configure
6435                          */
6436                         ndi_devi_exit(parent, circ1);
6437                         ndi_devi_exit(scsi_vhci_dip, circ);
6438 
6439                         /*
6440                          * Add parent's props for SMHBA support
6441                          */
6442                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6443                                 bzero(attached_wwnstr,
6444                                     sizeof (attached_wwnstr));
6445                                 (void) sprintf(attached_wwnstr, "w%016"PRIx64,
6446                                     ptgt->m_addr.mta_wwn);
6447                                 if (ddi_prop_update_string(DDI_DEV_T_NONE,
6448                                     parent,
6449                                     SCSI_ADDR_PROP_ATTACHED_PORT,
6450                                     attached_wwnstr)
6451                                     != DDI_PROP_SUCCESS) {
6452                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6453                                             parent,
6454                                             SCSI_ADDR_PROP_ATTACHED_PORT);
6455                                         mptsas_log(mpt, CE_WARN, "Failed to"
6456                                             "attached-port props");
6457                                         return;
6458                                 }
6459                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6460                                     MPTSAS_NUM_PHYS, 1) !=
6461                                     DDI_PROP_SUCCESS) {
6462                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6463                                             parent, MPTSAS_NUM_PHYS);
6464                                         mptsas_log(mpt, CE_WARN, "Failed to"
6465                                             " create num-phys props");
6466                                         return;
6467                                 }
6468 
6469                                 /*
6470                                  * Update PHY info for smhba
6471                                  */
6472                                 mutex_enter(&mpt->m_mutex);
6473                                 if (mptsas_smhba_phy_init(mpt)) {
6474                                         mutex_exit(&mpt->m_mutex);
6475                                         mptsas_log(mpt, CE_WARN, "mptsas phy"
6476                                             " update failed");
6477                                         return;
6478                                 }
6479                                 mutex_exit(&mpt->m_mutex);
6480 
6481                                 /*
6482                                  * topo_node->un.physport is really the PHY#
6483                                  * for direct attached devices
6484                                  */
6485                                 mptsas_smhba_set_one_phy_props(mpt, parent,
6486                                     topo_node->un.physport, &attached_devhdl);
6487 
6488                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6489                                     MPTSAS_VIRTUAL_PORT, 0) !=
6490                                     DDI_PROP_SUCCESS) {
6491                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6492                                             parent, MPTSAS_VIRTUAL_PORT);
6493                                         mptsas_log(mpt, CE_WARN,
6494                                             "mptsas virtual-port"
6495                                             "port prop update failed");
6496                                         return;
6497                                 }
6498                         }
6499                 }
6500                 mutex_enter(&mpt->m_mutex);
6501 
6502                 NDBG20(("mptsas%d handle_topo_change to online devhdl:%x, "
6503                     "phymask:%x.", mpt->m_instance, ptgt->m_devhdl,
6504                     ptgt->m_addr.mta_phymask));
6505                 break;
6506         }
6507         case MPTSAS_DR_EVENT_OFFLINE_TARGET:
6508         {
6509                 devhdl = topo_node->devhdl;
6510                 ptgt = refhash_linear_search(mpt->m_targets,
6511                     mptsas_target_eval_devhdl, &devhdl);
6512                 if (ptgt == NULL)
6513                         break;
6514 
6515                 sas_wwn = ptgt->m_addr.mta_wwn;
6516                 phy = ptgt->m_phynum;
6517 
6518                 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
6519 
6520                 if (sas_wwn) {
6521                         (void) sprintf(addr, "w%016"PRIx64, sas_wwn);
6522                 } else {
6523                         (void) sprintf(addr, "p%x", phy);
6524                 }
6525                 ASSERT(ptgt->m_devhdl == devhdl);
6526 
6527                 if ((topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) ||
6528                     (topo_node->flags ==
6529                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6530                         /*
6531                          * Get latest RAID info if RAID volume status changes
6532                          * or Phys Disk status changes
6533                          */
6534                         (void) mptsas_get_raid_info(mpt);
6535                 }
6536                 /*
6537                  * Abort all outstanding command on the device
6538                  */
6539                 rval = mptsas_do_scsi_reset(mpt, devhdl);
6540                 if (rval) {
6541                         NDBG20(("mptsas%d handle_topo_change to reset target "
6542                             "before offline devhdl:%x, phymask:%x, rval:%x",
6543                             mpt->m_instance, ptgt->m_devhdl,
6544                             ptgt->m_addr.mta_phymask, rval));
6545                 }
6546 
6547                 mutex_exit(&mpt->m_mutex);
6548 
6549                 ndi_devi_enter(scsi_vhci_dip, &circ);
6550                 ndi_devi_enter(parent, &circ1);
6551                 rval = mptsas_offline_target(parent, addr);
6552                 ndi_devi_exit(parent, circ1);
6553                 ndi_devi_exit(scsi_vhci_dip, circ);
6554                 NDBG20(("mptsas%d handle_topo_change to offline devhdl:%x, "
6555                     "phymask:%x, rval:%x", mpt->m_instance,
6556                     ptgt->m_devhdl, ptgt->m_addr.mta_phymask, rval));
6557 
6558                 kmem_free(addr, SCSI_MAXNAMELEN);
6559 
6560                 /*
6561                  * Clear parent's props for SMHBA support
6562                  */
6563                 flags = topo_node->flags;
6564                 if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6565                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6566                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6567                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6568                             DDI_PROP_SUCCESS) {
6569                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6570                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6571                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6572                                     "prop update failed");
6573                                 break;
6574                         }
6575                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6576                             MPTSAS_NUM_PHYS, 0) !=
6577                             DDI_PROP_SUCCESS) {
6578                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6579                                     MPTSAS_NUM_PHYS);
6580                                 mptsas_log(mpt, CE_WARN, "mptsas num phys "
6581                                     "prop update failed");
6582                                 break;
6583                         }
6584                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6585                             MPTSAS_VIRTUAL_PORT, 1) !=
6586                             DDI_PROP_SUCCESS) {
6587                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6588                                     MPTSAS_VIRTUAL_PORT);
6589                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6590                                     "prop update failed");
6591                                 break;
6592                         }
6593                 }
6594 
6595                 mutex_enter(&mpt->m_mutex);
6596                 ptgt->m_led_status = 0;
6597                 (void) mptsas_flush_led_status(mpt, ptgt);
6598                 if (rval == DDI_SUCCESS) {
6599                         refhash_remove(mpt->m_targets, ptgt);
6600                         ptgt = NULL;
6601                 } else {
6602                         /*
6603                          * clean DR_INTRANSITION flag to allow I/O down to
6604                          * PHCI driver since failover finished.
6605                          * Invalidate the devhdl
6606                          */
6607                         ptgt->m_devhdl = MPTSAS_INVALID_DEVHDL;
6608                         ptgt->m_tgt_unconfigured = 0;
6609                         mutex_enter(&mpt->m_tx_waitq_mutex);
6610                         ptgt->m_dr_flag = MPTSAS_DR_INACTIVE;
6611                         mutex_exit(&mpt->m_tx_waitq_mutex);
6612                 }
6613 
6614                 /*
6615                  * Send SAS IO Unit Control to free the dev handle
6616                  */
6617                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6618                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE)) {
6619                         rval = mptsas_free_devhdl(mpt, devhdl);
6620 
6621                         NDBG20(("mptsas%d handle_topo_change to remove "
6622                             "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6623                             rval));
6624                 }
6625 
6626                 break;
6627         }
6628         case MPTSAS_TOPO_FLAG_REMOVE_HANDLE:
6629         {
6630                 devhdl = topo_node->devhdl;
6631                 /*
6632                  * If this is the remove handle event, do a reset first.
6633                  */
6634                 if (topo_node->event == MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
6635                         rval = mptsas_do_scsi_reset(mpt, devhdl);
6636                         if (rval) {
6637                                 NDBG20(("mpt%d reset target before remove "
6638                                     "devhdl:%x, rval:%x", mpt->m_instance,
6639                                     devhdl, rval));
6640                         }
6641                 }
6642 
6643                 /*
6644                  * Send SAS IO Unit Control to free the dev handle
6645                  */
6646                 rval = mptsas_free_devhdl(mpt, devhdl);
6647                 NDBG20(("mptsas%d handle_topo_change to remove "
6648                     "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6649                     rval));
6650                 break;
6651         }
6652         case MPTSAS_DR_EVENT_RECONFIG_SMP:
6653         {
6654                 mptsas_smp_t smp;
6655                 dev_info_t *smpdip;
6656 
6657                 devhdl = topo_node->devhdl;
6658 
6659                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
6660                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)devhdl;
6661                 rval = mptsas_get_sas_expander_page0(mpt, page_address, &smp);
6662                 if (rval != DDI_SUCCESS) {
6663                         mptsas_log(mpt, CE_WARN, "failed to online smp, "
6664                             "handle %x", devhdl);
6665                         return;
6666                 }
6667 
6668                 psmp = mptsas_smp_alloc(mpt, &smp);
6669                 if (psmp == NULL) {
6670                         return;
6671                 }
6672 
6673                 mutex_exit(&mpt->m_mutex);
6674                 ndi_devi_enter(parent, &circ1);
6675                 (void) mptsas_online_smp(parent, psmp, &smpdip);
6676                 ndi_devi_exit(parent, circ1);
6677 
6678                 mutex_enter(&mpt->m_mutex);
6679                 break;
6680         }
6681         case MPTSAS_DR_EVENT_OFFLINE_SMP:
6682         {
6683                 devhdl = topo_node->devhdl;
6684                 uint32_t dev_info;
6685 
6686                 psmp = refhash_linear_search(mpt->m_smp_targets,
6687                     mptsas_smp_eval_devhdl, &devhdl);
6688                 if (psmp == NULL)
6689                         break;
6690                 /*
6691                  * The mptsas_smp_t data is released only if the dip is offlined
6692                  * successfully.
6693                  */
6694                 mutex_exit(&mpt->m_mutex);
6695 
6696                 ndi_devi_enter(parent, &circ1);
6697                 rval = mptsas_offline_smp(parent, psmp, NDI_DEVI_REMOVE);
6698                 ndi_devi_exit(parent, circ1);
6699 
6700                 dev_info = psmp->m_deviceinfo;
6701                 if ((dev_info & DEVINFO_DIRECT_ATTACHED) ==
6702                     DEVINFO_DIRECT_ATTACHED) {
6703                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6704                             MPTSAS_VIRTUAL_PORT, 1) !=
6705                             DDI_PROP_SUCCESS) {
6706                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6707                                     MPTSAS_VIRTUAL_PORT);
6708                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6709                                     "prop update failed");
6710                                 return;
6711                         }
6712                         /*
6713                          * Check whether the smp connected to the iport,
6714                          */
6715                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6716                             MPTSAS_NUM_PHYS, 0) !=
6717                             DDI_PROP_SUCCESS) {
6718                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6719                                     MPTSAS_NUM_PHYS);
6720                                 mptsas_log(mpt, CE_WARN, "mptsas num phys"
6721                                     "prop update failed");
6722                                 return;
6723                         }
6724                         /*
6725                          * Clear parent's attached-port props
6726                          */
6727                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6728                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6729                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6730                             DDI_PROP_SUCCESS) {
6731                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6732                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6733                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6734                                     "prop update failed");
6735                                 return;
6736                         }
6737                 }
6738 
6739                 mutex_enter(&mpt->m_mutex);
6740                 NDBG20(("mptsas%d handle_topo_change to remove devhdl:%x, "
6741                     "rval:%x", mpt->m_instance, psmp->m_devhdl, rval));
6742                 if (rval == DDI_SUCCESS) {
6743                         refhash_remove(mpt->m_smp_targets, psmp);
6744                 } else {
6745                         psmp->m_devhdl = MPTSAS_INVALID_DEVHDL;
6746                 }
6747 
6748                 bzero(attached_wwnstr, sizeof (attached_wwnstr));
6749 
6750                 break;
6751         }
6752         default:
6753                 return;
6754         }
6755 }
6756 
6757 /*
6758  * Record the event if its type is enabled in mpt instance by ioctl.
6759  */
6760 static void
6761 mptsas_record_event(void *args)
6762 {
6763         m_replyh_arg_t                  *replyh_arg;
6764         pMpi2EventNotificationReply_t   eventreply;
6765         uint32_t                        event, rfm;
6766         mptsas_t                        *mpt;
6767         int                             i, j;
6768         uint16_t                        event_data_len;
6769         boolean_t                       sendAEN = FALSE;
6770 
6771         replyh_arg = (m_replyh_arg_t *)args;
6772         rfm = replyh_arg->rfm;
6773         mpt = replyh_arg->mpt;
6774 
6775         eventreply = (pMpi2EventNotificationReply_t)
6776             (mpt->m_reply_frame + (rfm -
6777             (mpt->m_reply_frame_dma_addr & 0xffffffffu)));
6778         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6779 
6780 
6781         /*
6782          * Generate a system event to let anyone who cares know that a
6783          * LOG_ENTRY_ADDED event has occurred.  This is sent no matter what the
6784          * event mask is set to.
6785          */
6786         if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
6787                 sendAEN = TRUE;
6788         }
6789 
6790         /*
6791          * Record the event only if it is not masked.  Determine which dword
6792          * and bit of event mask to test.
6793          */
6794         i = (uint8_t)(event / 32);
6795         j = (uint8_t)(event % 32);
6796         if ((i < 4) && ((1 << j) & mpt->m_event_mask[i])) {
6797                 i = mpt->m_event_index;
6798                 mpt->m_events[i].Type = event;
6799                 mpt->m_events[i].Number = ++mpt->m_event_number;
6800                 bzero(mpt->m_events[i].Data, MPTSAS_MAX_EVENT_DATA_LENGTH * 4);
6801                 event_data_len = ddi_get16(mpt->m_acc_reply_frame_hdl,
6802                     &eventreply->EventDataLength);
6803 
6804                 if (event_data_len > 0) {
6805                         /*
6806                          * Limit data to size in m_event entry
6807                          */
6808                         if (event_data_len > MPTSAS_MAX_EVENT_DATA_LENGTH) {
6809                                 event_data_len = MPTSAS_MAX_EVENT_DATA_LENGTH;
6810                         }
6811                         for (j = 0; j < event_data_len; j++) {
6812                                 mpt->m_events[i].Data[j] =
6813                                     ddi_get32(mpt->m_acc_reply_frame_hdl,
6814                                     &(eventreply->EventData[j]));
6815                         }
6816 
6817                         /*
6818                          * check for index wrap-around
6819                          */
6820                         if (++i == MPTSAS_EVENT_QUEUE_SIZE) {
6821                                 i = 0;
6822                         }
6823                         mpt->m_event_index = (uint8_t)i;
6824 
6825                         /*
6826                          * Set flag to send the event.
6827                          */
6828                         sendAEN = TRUE;
6829                 }
6830         }
6831 
6832         /*
6833          * Generate a system event if flag is set to let anyone who cares know
6834          * that an event has occurred.
6835          */
6836         if (sendAEN) {
6837                 (void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS",
6838                     "SAS", NULL, NULL, DDI_NOSLEEP);
6839         }
6840 }
6841 
6842 #define SMP_RESET_IN_PROGRESS MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS
6843 /*
6844  * handle sync events from ioc in interrupt
6845  * return value:
6846  * DDI_SUCCESS: The event is handled by this func
6847  * DDI_FAILURE: Event is not handled
6848  */
6849 static int
6850 mptsas_handle_event_sync(void *args)
6851 {
6852         m_replyh_arg_t                  *replyh_arg;
6853         pMpi2EventNotificationReply_t   eventreply;
6854         uint32_t                        event, rfm;
6855         mptsas_t                        *mpt;
6856         uint_t                          iocstatus;
6857 
6858         replyh_arg = (m_replyh_arg_t *)args;
6859         rfm = replyh_arg->rfm;
6860         mpt = replyh_arg->mpt;
6861 
6862         ASSERT(mutex_owned(&mpt->m_mutex));
6863 
6864         eventreply = (pMpi2EventNotificationReply_t)
6865             (mpt->m_reply_frame + (rfm -
6866             (mpt->m_reply_frame_dma_addr & 0xffffffffu)));
6867         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6868 
6869         if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
6870             &eventreply->IOCStatus)) {
6871                 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
6872                         mptsas_log(mpt, CE_WARN,
6873                             "!mptsas_handle_event_sync: event 0x%x, "
6874                             "IOCStatus=0x%x, "
6875                             "IOCLogInfo=0x%x", event, iocstatus,
6876                             ddi_get32(mpt->m_acc_reply_frame_hdl,
6877                             &eventreply->IOCLogInfo));
6878                 } else {
6879                         mptsas_log(mpt, CE_WARN,
6880                             "mptsas_handle_event_sync: event 0x%x, "
6881                             "IOCStatus=0x%x, "
6882                             "(IOCLogInfo=0x%x)", event, iocstatus,
6883                             ddi_get32(mpt->m_acc_reply_frame_hdl,
6884                             &eventreply->IOCLogInfo));
6885                 }
6886         }
6887 
6888         /*
6889          * figure out what kind of event we got and handle accordingly
6890          */
6891         switch (event) {
6892         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
6893         {
6894                 pMpi2EventDataSasTopologyChangeList_t   sas_topo_change_list;
6895                 uint8_t                         num_entries, expstatus, phy;
6896                 uint8_t                         phystatus, physport, state, i;
6897                 uint8_t                         start_phy_num, link_rate;
6898                 uint16_t                        dev_handle, reason_code;
6899                 uint16_t                        enc_handle, expd_handle;
6900                 char                            string[80], curr[80], prev[80];
6901                 mptsas_topo_change_list_t       *topo_head = NULL;
6902                 mptsas_topo_change_list_t       *topo_tail = NULL;
6903                 mptsas_topo_change_list_t       *topo_node = NULL;
6904                 mptsas_target_t                 *ptgt;
6905                 mptsas_smp_t                    *psmp;
6906                 uint8_t                         flags = 0, exp_flag;
6907                 smhba_info_t                    *pSmhba = NULL;
6908 
6909                 NDBG20(("mptsas_handle_event_sync: SAS topology change"));
6910 
6911                 sas_topo_change_list = (pMpi2EventDataSasTopologyChangeList_t)
6912                     eventreply->EventData;
6913 
6914                 enc_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6915                     &sas_topo_change_list->EnclosureHandle);
6916                 expd_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6917                     &sas_topo_change_list->ExpanderDevHandle);
6918                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6919                     &sas_topo_change_list->NumEntries);
6920                 start_phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
6921                     &sas_topo_change_list->StartPhyNum);
6922                 expstatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6923                     &sas_topo_change_list->ExpStatus);
6924                 physport = ddi_get8(mpt->m_acc_reply_frame_hdl,
6925                     &sas_topo_change_list->PhysicalPort);
6926 
6927                 string[0] = 0;
6928                 if (expd_handle) {
6929                         flags = MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED;
6930                         switch (expstatus) {
6931                         case MPI2_EVENT_SAS_TOPO_ES_ADDED:
6932                                 (void) sprintf(string, " added");
6933                                 /*
6934                                  * New expander device added
6935                                  */
6936                                 mpt->m_port_chng = 1;
6937                                 topo_node = kmem_zalloc(
6938                                     sizeof (mptsas_topo_change_list_t),
6939                                     KM_SLEEP);
6940                                 topo_node->mpt = mpt;
6941                                 topo_node->event = MPTSAS_DR_EVENT_RECONFIG_SMP;
6942                                 topo_node->un.physport = physport;
6943                                 topo_node->devhdl = expd_handle;
6944                                 topo_node->flags = flags;
6945                                 topo_node->object = NULL;
6946                                 if (topo_head == NULL) {
6947                                         topo_head = topo_tail = topo_node;
6948                                 } else {
6949                                         topo_tail->next = topo_node;
6950                                         topo_tail = topo_node;
6951                                 }
6952                                 break;
6953                         case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
6954                                 (void) sprintf(string, " not responding, "
6955                                     "removed");
6956                                 psmp = refhash_linear_search(mpt->m_smp_targets,
6957                                     mptsas_smp_eval_devhdl, &expd_handle);
6958                                 if (psmp == NULL)
6959                                         break;
6960 
6961                                 topo_node = kmem_zalloc(
6962                                     sizeof (mptsas_topo_change_list_t),
6963                                     KM_SLEEP);
6964                                 topo_node->mpt = mpt;
6965                                 topo_node->un.phymask =
6966                                     psmp->m_addr.mta_phymask;
6967                                 topo_node->event = MPTSAS_DR_EVENT_OFFLINE_SMP;
6968                                 topo_node->devhdl = expd_handle;
6969                                 topo_node->flags = flags;
6970                                 topo_node->object = NULL;
6971                                 if (topo_head == NULL) {
6972                                         topo_head = topo_tail = topo_node;
6973                                 } else {
6974                                         topo_tail->next = topo_node;
6975                                         topo_tail = topo_node;
6976                                 }
6977                                 break;
6978                         case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
6979                                 break;
6980                         case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
6981                                 (void) sprintf(string, " not responding, "
6982                                     "delaying removal");
6983                                 break;
6984                         default:
6985                                 break;
6986                         }
6987                 } else {
6988                         flags = MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE;
6989                 }
6990 
6991                 NDBG20(("SAS TOPOLOGY CHANGE for enclosure %x expander %x%s\n",
6992                     enc_handle, expd_handle, string));
6993                 for (i = 0; i < num_entries; i++) {
6994                         phy = i + start_phy_num;
6995                         phystatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6996                             &sas_topo_change_list->PHY[i].PhyStatus);
6997                         dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6998                             &sas_topo_change_list->PHY[i].AttachedDevHandle);
6999                         reason_code = phystatus & MPI2_EVENT_SAS_TOPO_RC_MASK;
7000                         /*
7001                          * Filter out processing of Phy Vacant Status unless
7002                          * the reason code is "Not Responding".  Process all
7003                          * other combinations of Phy Status and Reason Codes.
7004                          */
7005                         if ((phystatus &
7006                             MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) &&
7007                             (reason_code !=
7008                             MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) {
7009                                 continue;
7010                         }
7011                         curr[0] = 0;
7012                         prev[0] = 0;
7013                         string[0] = 0;
7014                         switch (reason_code) {
7015                         case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
7016                         {
7017                                 NDBG20(("mptsas%d phy %d physical_port %d "
7018                                     "dev_handle %d added", mpt->m_instance, phy,
7019                                     physport, dev_handle));
7020                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
7021                                     &sas_topo_change_list->PHY[i].LinkRate);
7022                                 state = (link_rate &
7023                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
7024                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
7025                                 switch (state) {
7026                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
7027                                         (void) sprintf(curr, "is disabled");
7028                                         break;
7029                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
7030                                         (void) sprintf(curr, "is offline, "
7031                                             "failed speed negotiation");
7032                                         break;
7033                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
7034                                         (void) sprintf(curr, "SATA OOB "
7035                                             "complete");
7036                                         break;
7037                                 case SMP_RESET_IN_PROGRESS:
7038                                         (void) sprintf(curr, "SMP reset in "
7039                                             "progress");
7040                                         break;
7041                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
7042                                         (void) sprintf(curr, "is online at "
7043                                             "1.5 Gbps");
7044                                         break;
7045                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
7046                                         (void) sprintf(curr, "is online at 3.0 "
7047                                             "Gbps");
7048                                         break;
7049                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
7050                                         (void) sprintf(curr, "is online at 6.0 "
7051                                             "Gbps");
7052                                         break;
7053                                 case MPI25_EVENT_SAS_TOPO_LR_RATE_12_0:
7054                                         (void) sprintf(curr,
7055                                             "is online at 12.0 Gbps");
7056                                         break;
7057                                 default:
7058                                         (void) sprintf(curr, "state is "
7059                                             "unknown");
7060                                         break;
7061                                 }
7062                                 /*
7063                                  * New target device added into the system.
7064                                  * Set association flag according to if an
7065                                  * expander is used or not.
7066                                  */
7067                                 exp_flag =
7068                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
7069                                 if (flags ==
7070                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
7071                                         flags = exp_flag;
7072                                 }
7073                                 topo_node = kmem_zalloc(
7074                                     sizeof (mptsas_topo_change_list_t),
7075                                     KM_SLEEP);
7076                                 topo_node->mpt = mpt;
7077                                 topo_node->event =
7078                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
7079                                 if (expd_handle == 0) {
7080                                         /*
7081                                          * Per MPI 2, if expander dev handle
7082                                          * is 0, it's a directly attached
7083                                          * device. So driver use PHY to decide
7084                                          * which iport is associated
7085                                          */
7086                                         physport = phy;
7087                                         mpt->m_port_chng = 1;
7088                                 }
7089                                 topo_node->un.physport = physport;
7090                                 topo_node->devhdl = dev_handle;
7091                                 topo_node->flags = flags;
7092                                 topo_node->object = NULL;
7093                                 if (topo_head == NULL) {
7094                                         topo_head = topo_tail = topo_node;
7095                                 } else {
7096                                         topo_tail->next = topo_node;
7097                                         topo_tail = topo_node;
7098                                 }
7099                                 break;
7100                         }
7101                         case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
7102                         {
7103                                 NDBG20(("mptsas%d phy %d physical_port %d "
7104                                     "dev_handle %d removed", mpt->m_instance,
7105                                     phy, physport, dev_handle));
7106                                 /*
7107                                  * Set association flag according to if an
7108                                  * expander is used or not.
7109                                  */
7110                                 exp_flag =
7111                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
7112                                 if (flags ==
7113                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
7114                                         flags = exp_flag;
7115                                 }
7116                                 /*
7117                                  * Target device is removed from the system
7118                                  * Before the device is really offline from
7119                                  * from system.
7120                                  */
7121                                 ptgt = refhash_linear_search(mpt->m_targets,
7122                                     mptsas_target_eval_devhdl, &dev_handle);
7123                                 /*
7124                                  * If ptgt is NULL here, it means that the
7125                                  * DevHandle is not in the hash table.  This is
7126                                  * reasonable sometimes.  For example, if a
7127                                  * disk was pulled, then added, then pulled
7128                                  * again, the disk will not have been put into
7129                                  * the hash table because the add event will
7130                                  * have an invalid phymask.  BUT, this does not
7131                                  * mean that the DevHandle is invalid.  The
7132                                  * controller will still have a valid DevHandle
7133                                  * that must be removed.  To do this, use the
7134                                  * MPTSAS_TOPO_FLAG_REMOVE_HANDLE event.
7135                                  */
7136                                 if (ptgt == NULL) {
7137                                         topo_node = kmem_zalloc(
7138                                             sizeof (mptsas_topo_change_list_t),
7139                                             KM_SLEEP);
7140                                         topo_node->mpt = mpt;
7141                                         topo_node->un.phymask = 0;
7142                                         topo_node->event =
7143                                             MPTSAS_TOPO_FLAG_REMOVE_HANDLE;
7144                                         topo_node->devhdl = dev_handle;
7145                                         topo_node->flags = flags;
7146                                         topo_node->object = NULL;
7147                                         if (topo_head == NULL) {
7148                                                 topo_head = topo_tail =
7149                                                     topo_node;
7150                                         } else {
7151                                                 topo_tail->next = topo_node;
7152                                                 topo_tail = topo_node;
7153                                         }
7154                                         break;
7155                                 }
7156 
7157                                 /*
7158                                  * Update DR flag immediately avoid I/O failure
7159                                  * before failover finish. Pay attention to the
7160                                  * mutex protect, we need grab m_tx_waitq_mutex
7161                                  * during set m_dr_flag because we won't add
7162                                  * the following command into waitq, instead,
7163                                  * we need return TRAN_BUSY in the tran_start
7164                                  * context.
7165                                  */
7166                                 mutex_enter(&mpt->m_tx_waitq_mutex);
7167                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
7168                                 mutex_exit(&mpt->m_tx_waitq_mutex);
7169 
7170                                 topo_node = kmem_zalloc(
7171                                     sizeof (mptsas_topo_change_list_t),
7172                                     KM_SLEEP);
7173                                 topo_node->mpt = mpt;
7174                                 topo_node->un.phymask =
7175                                     ptgt->m_addr.mta_phymask;
7176                                 topo_node->event =
7177                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7178                                 topo_node->devhdl = dev_handle;
7179                                 topo_node->flags = flags;
7180                                 topo_node->object = NULL;
7181                                 if (topo_head == NULL) {
7182                                         topo_head = topo_tail = topo_node;
7183                                 } else {
7184                                         topo_tail->next = topo_node;
7185                                         topo_tail = topo_node;
7186                                 }
7187                                 break;
7188                         }
7189                         case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
7190                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
7191                                     &sas_topo_change_list->PHY[i].LinkRate);
7192                                 state = (link_rate &
7193                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
7194                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
7195                                 pSmhba = &mpt->m_phy_info[i].smhba_info;
7196                                 pSmhba->negotiated_link_rate = state;
7197                                 switch (state) {
7198                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
7199                                         (void) sprintf(curr, "is disabled");
7200                                         mptsas_smhba_log_sysevent(mpt,
7201                                             ESC_SAS_PHY_EVENT,
7202                                             SAS_PHY_REMOVE,
7203                                             &mpt->m_phy_info[i].smhba_info);
7204                                         mpt->m_phy_info[i].smhba_info.
7205                                             negotiated_link_rate
7206                                             = 0x1;
7207                                         break;
7208                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
7209                                         (void) sprintf(curr, "is offline, "
7210                                             "failed speed negotiation");
7211                                         mptsas_smhba_log_sysevent(mpt,
7212                                             ESC_SAS_PHY_EVENT,
7213                                             SAS_PHY_OFFLINE,
7214                                             &mpt->m_phy_info[i].smhba_info);
7215                                         break;
7216                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
7217                                         (void) sprintf(curr, "SATA OOB "
7218                                             "complete");
7219                                         break;
7220                                 case SMP_RESET_IN_PROGRESS:
7221                                         (void) sprintf(curr, "SMP reset in "
7222                                             "progress");
7223                                         break;
7224                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
7225                                         (void) sprintf(curr, "is online at "
7226                                             "1.5 Gbps");
7227                                         if ((expd_handle == 0) &&
7228                                             (enc_handle == 1)) {
7229                                                 mpt->m_port_chng = 1;
7230                                         }
7231                                         mptsas_smhba_log_sysevent(mpt,
7232                                             ESC_SAS_PHY_EVENT,
7233                                             SAS_PHY_ONLINE,
7234                                             &mpt->m_phy_info[i].smhba_info);
7235                                         break;
7236                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
7237                                         (void) sprintf(curr, "is online at 3.0 "
7238                                             "Gbps");
7239                                         if ((expd_handle == 0) &&
7240                                             (enc_handle == 1)) {
7241                                                 mpt->m_port_chng = 1;
7242                                         }
7243                                         mptsas_smhba_log_sysevent(mpt,
7244                                             ESC_SAS_PHY_EVENT,
7245                                             SAS_PHY_ONLINE,
7246                                             &mpt->m_phy_info[i].smhba_info);
7247                                         break;
7248                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
7249                                         (void) sprintf(curr, "is online at "
7250                                             "6.0 Gbps");
7251                                         if ((expd_handle == 0) &&
7252                                             (enc_handle == 1)) {
7253                                                 mpt->m_port_chng = 1;
7254                                         }
7255                                         mptsas_smhba_log_sysevent(mpt,
7256                                             ESC_SAS_PHY_EVENT,
7257                                             SAS_PHY_ONLINE,
7258                                             &mpt->m_phy_info[i].smhba_info);
7259                                         break;
7260                                 case MPI25_EVENT_SAS_TOPO_LR_RATE_12_0:
7261                                         (void) sprintf(curr, "is online at "
7262                                             "12.0 Gbps");
7263                                         if ((expd_handle == 0) &&
7264                                             (enc_handle == 1)) {
7265                                                 mpt->m_port_chng = 1;
7266                                         }
7267                                         mptsas_smhba_log_sysevent(mpt,
7268                                             ESC_SAS_PHY_EVENT,
7269                                             SAS_PHY_ONLINE,
7270                                             &mpt->m_phy_info[i].smhba_info);
7271                                         break;
7272                                 default:
7273                                         (void) sprintf(curr, "state is "
7274                                             "unknown");
7275                                         break;
7276                                 }
7277 
7278                                 state = (link_rate &
7279                                     MPI2_EVENT_SAS_TOPO_LR_PREV_MASK) >>
7280                                     MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT;
7281                                 switch (state) {
7282                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
7283                                         (void) sprintf(prev, ", was disabled");
7284                                         break;
7285                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
7286                                         (void) sprintf(prev, ", was offline, "
7287                                             "failed speed negotiation");
7288                                         break;
7289                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
7290                                         (void) sprintf(prev, ", was SATA OOB "
7291                                             "complete");
7292                                         break;
7293                                 case SMP_RESET_IN_PROGRESS:
7294                                         (void) sprintf(prev, ", was SMP reset "
7295                                             "in progress");
7296                                         break;
7297                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
7298                                         (void) sprintf(prev, ", was online at "
7299                                             "1.5 Gbps");
7300                                         break;
7301                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
7302                                         (void) sprintf(prev, ", was online at "
7303                                             "3.0 Gbps");
7304                                         break;
7305                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
7306                                         (void) sprintf(prev, ", was online at "
7307                                             "6.0 Gbps");
7308                                         break;
7309                                 case MPI25_EVENT_SAS_TOPO_LR_RATE_12_0:
7310                                         (void) sprintf(prev, ", was online at "
7311                                             "12.0 Gbps");
7312                                         break;
7313                                 default:
7314                                 break;
7315                                 }
7316                                 (void) sprintf(&string[strlen(string)], "link "
7317                                     "changed, ");
7318                                 break;
7319                         case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
7320                                 continue;
7321                         case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
7322                                 (void) sprintf(&string[strlen(string)],
7323                                     "target not responding, delaying "
7324                                     "removal");
7325                                 break;
7326                         }
7327                         NDBG20(("mptsas%d phy %d DevHandle %x, %s%s%s\n",
7328                             mpt->m_instance, phy, dev_handle, string, curr,
7329                             prev));
7330                 }
7331                 if (topo_head != NULL) {
7332                         /*
7333                          * Launch DR taskq to handle topology change
7334                          */
7335                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
7336                             mptsas_handle_dr, (void *)topo_head,
7337                             DDI_NOSLEEP)) != DDI_SUCCESS) {
7338                                 while (topo_head != NULL) {
7339                                         topo_node = topo_head;
7340                                         topo_head = topo_head->next;
7341                                         kmem_free(topo_node,
7342                                             sizeof (mptsas_topo_change_list_t));
7343                                 }
7344                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
7345                                     "for handle SAS DR event failed. \n");
7346                         }
7347                 }
7348                 break;
7349         }
7350         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7351         {
7352                 Mpi2EventDataIrConfigChangeList_t       *irChangeList;
7353                 mptsas_topo_change_list_t               *topo_head = NULL;
7354                 mptsas_topo_change_list_t               *topo_tail = NULL;
7355                 mptsas_topo_change_list_t               *topo_node = NULL;
7356                 mptsas_target_t                         *ptgt;
7357                 uint8_t                                 num_entries, i, reason;
7358                 uint16_t                                volhandle, diskhandle;
7359 
7360                 irChangeList = (pMpi2EventDataIrConfigChangeList_t)
7361                     eventreply->EventData;
7362                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
7363                     &irChangeList->NumElements);
7364 
7365                 NDBG20(("mptsas%d IR_CONFIGURATION_CHANGE_LIST event received",
7366                     mpt->m_instance));
7367 
7368                 for (i = 0; i < num_entries; i++) {
7369                         reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
7370                             &irChangeList->ConfigElement[i].ReasonCode);
7371                         volhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7372                             &irChangeList->ConfigElement[i].VolDevHandle);
7373                         diskhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7374                             &irChangeList->ConfigElement[i].PhysDiskDevHandle);
7375 
7376                         switch (reason) {
7377                         case MPI2_EVENT_IR_CHANGE_RC_ADDED:
7378                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
7379                         {
7380                                 NDBG20(("mptsas %d volume added\n",
7381                                     mpt->m_instance));
7382 
7383                                 topo_node = kmem_zalloc(
7384                                     sizeof (mptsas_topo_change_list_t),
7385                                     KM_SLEEP);
7386 
7387                                 topo_node->mpt = mpt;
7388                                 topo_node->event =
7389                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
7390                                 topo_node->un.physport = 0xff;
7391                                 topo_node->devhdl = volhandle;
7392                                 topo_node->flags =
7393                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
7394                                 topo_node->object = NULL;
7395                                 if (topo_head == NULL) {
7396                                         topo_head = topo_tail = topo_node;
7397                                 } else {
7398                                         topo_tail->next = topo_node;
7399                                         topo_tail = topo_node;
7400                                 }
7401                                 break;
7402                         }
7403                         case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
7404                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
7405                         {
7406                                 NDBG20(("mptsas %d volume deleted\n",
7407                                     mpt->m_instance));
7408                                 ptgt = refhash_linear_search(mpt->m_targets,
7409                                     mptsas_target_eval_devhdl, &volhandle);
7410                                 if (ptgt == NULL)
7411                                         break;
7412 
7413                                 /*
7414                                  * Clear any flags related to volume
7415                                  */
7416                                 (void) mptsas_delete_volume(mpt, volhandle);
7417 
7418                                 /*
7419                                  * Update DR flag immediately avoid I/O failure
7420                                  */
7421                                 mutex_enter(&mpt->m_tx_waitq_mutex);
7422                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
7423                                 mutex_exit(&mpt->m_tx_waitq_mutex);
7424 
7425                                 topo_node = kmem_zalloc(
7426                                     sizeof (mptsas_topo_change_list_t),
7427                                     KM_SLEEP);
7428                                 topo_node->mpt = mpt;
7429                                 topo_node->un.phymask =
7430                                     ptgt->m_addr.mta_phymask;
7431                                 topo_node->event =
7432                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7433                                 topo_node->devhdl = volhandle;
7434                                 topo_node->flags =
7435                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
7436                                 topo_node->object = (void *)ptgt;
7437                                 if (topo_head == NULL) {
7438                                         topo_head = topo_tail = topo_node;
7439                                 } else {
7440                                         topo_tail->next = topo_node;
7441                                         topo_tail = topo_node;
7442                                 }
7443                                 break;
7444                         }
7445                         case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
7446                         case MPI2_EVENT_IR_CHANGE_RC_HIDE:
7447                         {
7448                                 ptgt = refhash_linear_search(mpt->m_targets,
7449                                     mptsas_target_eval_devhdl, &diskhandle);
7450                                 if (ptgt == NULL)
7451                                         break;
7452 
7453                                 /*
7454                                  * Update DR flag immediately avoid I/O failure
7455                                  */
7456                                 mutex_enter(&mpt->m_tx_waitq_mutex);
7457                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
7458                                 mutex_exit(&mpt->m_tx_waitq_mutex);
7459 
7460                                 topo_node = kmem_zalloc(
7461                                     sizeof (mptsas_topo_change_list_t),
7462                                     KM_SLEEP);
7463                                 topo_node->mpt = mpt;
7464                                 topo_node->un.phymask =
7465                                     ptgt->m_addr.mta_phymask;
7466                                 topo_node->event =
7467                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7468                                 topo_node->devhdl = diskhandle;
7469                                 topo_node->flags =
7470                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
7471                                 topo_node->object = (void *)ptgt;
7472                                 if (topo_head == NULL) {
7473                                         topo_head = topo_tail = topo_node;
7474                                 } else {
7475                                         topo_tail->next = topo_node;
7476                                         topo_tail = topo_node;
7477                                 }
7478                                 break;
7479                         }
7480                         case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
7481                         case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
7482                         {
7483                                 /*
7484                                  * The physical drive is released by a IR
7485                                  * volume. But we cannot get the the physport
7486                                  * or phynum from the event data, so we only
7487                                  * can get the physport/phynum after SAS
7488                                  * Device Page0 request for the devhdl.
7489                                  */
7490                                 topo_node = kmem_zalloc(
7491                                     sizeof (mptsas_topo_change_list_t),
7492                                     KM_SLEEP);
7493                                 topo_node->mpt = mpt;
7494                                 topo_node->un.phymask = 0;
7495                                 topo_node->event =
7496                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
7497                                 topo_node->devhdl = diskhandle;
7498                                 topo_node->flags =
7499                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
7500                                 topo_node->object = NULL;
7501                                 mpt->m_port_chng = 1;
7502                                 if (topo_head == NULL) {
7503                                         topo_head = topo_tail = topo_node;
7504                                 } else {
7505                                         topo_tail->next = topo_node;
7506                                         topo_tail = topo_node;
7507                                 }
7508                                 break;
7509                         }
7510                         default:
7511                                 break;
7512                         }
7513                 }
7514 
7515                 if (topo_head != NULL) {
7516                         /*
7517                          * Launch DR taskq to handle topology change
7518                          */
7519                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
7520                             mptsas_handle_dr, (void *)topo_head,
7521                             DDI_NOSLEEP)) != DDI_SUCCESS) {
7522                                 while (topo_head != NULL) {
7523                                         topo_node = topo_head;
7524                                         topo_head = topo_head->next;
7525                                         kmem_free(topo_node,
7526                                             sizeof (mptsas_topo_change_list_t));
7527                                 }
7528                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
7529                                     "for handle SAS DR event failed. \n");
7530                         }
7531                 }
7532                 break;
7533         }
7534         default:
7535                 return (DDI_FAILURE);
7536         }
7537 
7538         return (DDI_SUCCESS);
7539 }
7540 
7541 /*
7542  * handle events from ioc
7543  */
7544 static void
7545 mptsas_handle_event(void *args)
7546 {
7547         m_replyh_arg_t                  *replyh_arg;
7548         pMpi2EventNotificationReply_t   eventreply;
7549         uint32_t                        event, iocloginfo, rfm;
7550         uint32_t                        status;
7551         uint8_t                         port;
7552         mptsas_t                        *mpt;
7553         uint_t                          iocstatus;
7554 
7555         replyh_arg = (m_replyh_arg_t *)args;
7556         rfm = replyh_arg->rfm;
7557         mpt = replyh_arg->mpt;
7558 
7559         mutex_enter(&mpt->m_mutex);
7560         /*
7561          * If HBA is being reset, drop incoming event.
7562          */
7563         if (mpt->m_in_reset) {
7564                 NDBG20(("dropping event received prior to reset"));
7565                 mutex_exit(&mpt->m_mutex);
7566                 return;
7567         }
7568 
7569         eventreply = (pMpi2EventNotificationReply_t)
7570             (mpt->m_reply_frame + (rfm -
7571             (mpt->m_reply_frame_dma_addr & 0xffffffffu)));
7572         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
7573 
7574         if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
7575             &eventreply->IOCStatus)) {
7576                 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
7577                         mptsas_log(mpt, CE_WARN,
7578                             "!mptsas_handle_event: IOCStatus=0x%x, "
7579                             "IOCLogInfo=0x%x", iocstatus,
7580                             ddi_get32(mpt->m_acc_reply_frame_hdl,
7581                             &eventreply->IOCLogInfo));
7582                 } else {
7583                         mptsas_log(mpt, CE_WARN,
7584                             "mptsas_handle_event: IOCStatus=0x%x, "
7585                             "IOCLogInfo=0x%x", iocstatus,
7586                             ddi_get32(mpt->m_acc_reply_frame_hdl,
7587                             &eventreply->IOCLogInfo));
7588                 }
7589         }
7590 
7591         /*
7592          * figure out what kind of event we got and handle accordingly
7593          */
7594         switch (event) {
7595         case MPI2_EVENT_LOG_ENTRY_ADDED:
7596                 break;
7597         case MPI2_EVENT_LOG_DATA:
7598                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7599                     &eventreply->IOCLogInfo);
7600                 NDBG20(("mptsas %d log info %x received.\n", mpt->m_instance,
7601                     iocloginfo));
7602                 break;
7603         case MPI2_EVENT_STATE_CHANGE:
7604                 NDBG20(("mptsas%d state change.", mpt->m_instance));
7605                 break;
7606         case MPI2_EVENT_HARD_RESET_RECEIVED:
7607                 NDBG20(("mptsas%d event change.", mpt->m_instance));
7608                 break;
7609         case MPI2_EVENT_SAS_DISCOVERY:
7610         {
7611                 MPI2_EVENT_DATA_SAS_DISCOVERY   *sasdiscovery;
7612                 char                            string[80];
7613                 uint8_t                         rc;
7614 
7615                 sasdiscovery =
7616                     (pMpi2EventDataSasDiscovery_t)eventreply->EventData;
7617 
7618                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7619                     &sasdiscovery->ReasonCode);
7620                 port = ddi_get8(mpt->m_acc_reply_frame_hdl,
7621                     &sasdiscovery->PhysicalPort);
7622                 status = ddi_get32(mpt->m_acc_reply_frame_hdl,
7623                     &sasdiscovery->DiscoveryStatus);
7624 
7625                 string[0] = 0;
7626                 switch (rc) {
7627                 case MPI2_EVENT_SAS_DISC_RC_STARTED:
7628                         (void) sprintf(string, "STARTING");
7629                         break;
7630                 case MPI2_EVENT_SAS_DISC_RC_COMPLETED:
7631                         (void) sprintf(string, "COMPLETED");
7632                         break;
7633                 default:
7634                         (void) sprintf(string, "UNKNOWN");
7635                         break;
7636                 }
7637 
7638                 NDBG20(("SAS DISCOVERY is %s for port %d, status %x", string,
7639                     port, status));
7640 
7641                 break;
7642         }
7643         case MPI2_EVENT_EVENT_CHANGE:
7644                 NDBG20(("mptsas%d event change.", mpt->m_instance));
7645                 break;
7646         case MPI2_EVENT_TASK_SET_FULL:
7647         {
7648                 pMpi2EventDataTaskSetFull_t     taskfull;
7649 
7650                 taskfull = (pMpi2EventDataTaskSetFull_t)eventreply->EventData;
7651 
7652                 NDBG20(("TASK_SET_FULL received for mptsas%d, depth %d\n",
7653                     mpt->m_instance,  ddi_get16(mpt->m_acc_reply_frame_hdl,
7654                     &taskfull->CurrentDepth)));
7655                 break;
7656         }
7657         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7658         {
7659                 /*
7660                  * SAS TOPOLOGY CHANGE LIST Event has already been handled
7661                  * in mptsas_handle_event_sync() of interrupt context
7662                  */
7663                 break;
7664         }
7665         case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7666         {
7667                 pMpi2EventDataSasEnclDevStatusChange_t  encstatus;
7668                 uint8_t                                 rc;
7669                 char                                    string[80];
7670 
7671                 encstatus = (pMpi2EventDataSasEnclDevStatusChange_t)
7672                     eventreply->EventData;
7673 
7674                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7675                     &encstatus->ReasonCode);
7676                 switch (rc) {
7677                 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
7678                         (void) sprintf(string, "added");
7679                         break;
7680                 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
7681                         (void) sprintf(string, ", not responding");
7682                         break;
7683                 default:
7684                 break;
7685                 }
7686                 NDBG20(("mptsas%d ENCLOSURE STATUS CHANGE for enclosure "
7687                     "%x%s\n", mpt->m_instance,
7688                     ddi_get16(mpt->m_acc_reply_frame_hdl,
7689                     &encstatus->EnclosureHandle), string));
7690                 break;
7691         }
7692 
7693         /*
7694          * MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE is handled by
7695          * mptsas_handle_event_sync,in here just send ack message.
7696          */
7697         case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7698         {
7699                 pMpi2EventDataSasDeviceStatusChange_t   statuschange;
7700                 uint8_t                                 rc;
7701                 uint16_t                                devhdl;
7702                 uint64_t                                wwn = 0;
7703                 uint32_t                                wwn_lo, wwn_hi;
7704 
7705                 statuschange = (pMpi2EventDataSasDeviceStatusChange_t)
7706                     eventreply->EventData;
7707                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7708                     &statuschange->ReasonCode);
7709                 wwn_lo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7710                     (uint32_t *)(void *)&statuschange->SASAddress);
7711                 wwn_hi = ddi_get32(mpt->m_acc_reply_frame_hdl,
7712                     (uint32_t *)(void *)&statuschange->SASAddress + 1);
7713                 wwn = ((uint64_t)wwn_hi << 32) | wwn_lo;
7714                 devhdl =  ddi_get16(mpt->m_acc_reply_frame_hdl,
7715                     &statuschange->DevHandle);
7716 
7717                 NDBG13(("MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE wwn is %"PRIx64,
7718                     wwn));
7719 
7720                 switch (rc) {
7721                 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
7722                         NDBG20(("SMART data received, ASC/ASCQ = %02x/%02x",
7723                             ddi_get8(mpt->m_acc_reply_frame_hdl,
7724                             &statuschange->ASC),
7725                             ddi_get8(mpt->m_acc_reply_frame_hdl,
7726                             &statuschange->ASCQ)));
7727                         break;
7728 
7729                 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
7730                         NDBG20(("Device not supported"));
7731                         break;
7732 
7733                 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
7734                         NDBG20(("IOC internally generated the Target Reset "
7735                             "for devhdl:%x", devhdl));
7736                         break;
7737 
7738                 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
7739                         NDBG20(("IOC's internally generated Target Reset "
7740                             "completed for devhdl:%x", devhdl));
7741                         break;
7742 
7743                 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
7744                         NDBG20(("IOC internally generated Abort Task"));
7745                         break;
7746 
7747                 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
7748                         NDBG20(("IOC's internally generated Abort Task "
7749                             "completed"));
7750                         break;
7751 
7752                 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
7753                         NDBG20(("IOC internally generated Abort Task Set"));
7754                         break;
7755 
7756                 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
7757                         NDBG20(("IOC internally generated Clear Task Set"));
7758                         break;
7759 
7760                 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
7761                         NDBG20(("IOC internally generated Query Task"));
7762                         break;
7763 
7764                 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
7765                         NDBG20(("Device sent an Asynchronous Notification"));
7766                         break;
7767 
7768                 default:
7769                         break;
7770                 }
7771                 break;
7772         }
7773         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7774         {
7775                 /*
7776                  * IR TOPOLOGY CHANGE LIST Event has already been handled
7777                  * in mpt_handle_event_sync() of interrupt context
7778                  */
7779                 break;
7780         }
7781         case MPI2_EVENT_IR_OPERATION_STATUS:
7782         {
7783                 Mpi2EventDataIrOperationStatus_t        *irOpStatus;
7784                 char                                    reason_str[80];
7785                 uint8_t                                 rc, percent;
7786                 uint16_t                                handle;
7787 
7788                 irOpStatus = (pMpi2EventDataIrOperationStatus_t)
7789                     eventreply->EventData;
7790                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7791                     &irOpStatus->RAIDOperation);
7792                 percent = ddi_get8(mpt->m_acc_reply_frame_hdl,
7793                     &irOpStatus->PercentComplete);
7794                 handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7795                     &irOpStatus->VolDevHandle);
7796 
7797                 switch (rc) {
7798                         case MPI2_EVENT_IR_RAIDOP_RESYNC:
7799                                 (void) sprintf(reason_str, "resync");
7800                                 break;
7801                         case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
7802                                 (void) sprintf(reason_str, "online capacity "
7803                                     "expansion");
7804                                 break;
7805                         case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
7806                                 (void) sprintf(reason_str, "consistency check");
7807                                 break;
7808                         default:
7809                                 (void) sprintf(reason_str, "unknown reason %x",
7810                                     rc);
7811                 }
7812 
7813                 NDBG20(("mptsas%d raid operational status: (%s)"
7814                     "\thandle(0x%04x), percent complete(%d)\n",
7815                     mpt->m_instance, reason_str, handle, percent));
7816                 break;
7817         }
7818         case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7819         {
7820                 pMpi2EventDataSasBroadcastPrimitive_t   sas_broadcast;
7821                 uint8_t                                 phy_num;
7822                 uint8_t                                 primitive;
7823 
7824                 sas_broadcast = (pMpi2EventDataSasBroadcastPrimitive_t)
7825                     eventreply->EventData;
7826 
7827                 phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
7828                     &sas_broadcast->PhyNum);
7829                 primitive = ddi_get8(mpt->m_acc_reply_frame_hdl,
7830                     &sas_broadcast->Primitive);
7831 
7832                 switch (primitive) {
7833                 case MPI2_EVENT_PRIMITIVE_CHANGE:
7834                         mptsas_smhba_log_sysevent(mpt,
7835                             ESC_SAS_HBA_PORT_BROADCAST,
7836                             SAS_PORT_BROADCAST_CHANGE,
7837                             &mpt->m_phy_info[phy_num].smhba_info);
7838                         break;
7839                 case MPI2_EVENT_PRIMITIVE_SES:
7840                         mptsas_smhba_log_sysevent(mpt,
7841                             ESC_SAS_HBA_PORT_BROADCAST,
7842                             SAS_PORT_BROADCAST_SES,
7843                             &mpt->m_phy_info[phy_num].smhba_info);
7844                         break;
7845                 case MPI2_EVENT_PRIMITIVE_EXPANDER:
7846                         mptsas_smhba_log_sysevent(mpt,
7847                             ESC_SAS_HBA_PORT_BROADCAST,
7848                             SAS_PORT_BROADCAST_D01_4,
7849                             &mpt->m_phy_info[phy_num].smhba_info);
7850                         break;
7851                 case MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT:
7852                         mptsas_smhba_log_sysevent(mpt,
7853                             ESC_SAS_HBA_PORT_BROADCAST,
7854                             SAS_PORT_BROADCAST_D04_7,
7855                             &mpt->m_phy_info[phy_num].smhba_info);
7856                         break;
7857                 case MPI2_EVENT_PRIMITIVE_RESERVED3:
7858                         mptsas_smhba_log_sysevent(mpt,
7859                             ESC_SAS_HBA_PORT_BROADCAST,
7860                             SAS_PORT_BROADCAST_D16_7,
7861                             &mpt->m_phy_info[phy_num].smhba_info);
7862                         break;
7863                 case MPI2_EVENT_PRIMITIVE_RESERVED4:
7864                         mptsas_smhba_log_sysevent(mpt,
7865                             ESC_SAS_HBA_PORT_BROADCAST,
7866                             SAS_PORT_BROADCAST_D29_7,
7867                             &mpt->m_phy_info[phy_num].smhba_info);
7868                         break;
7869                 case MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED:
7870                         mptsas_smhba_log_sysevent(mpt,
7871                             ESC_SAS_HBA_PORT_BROADCAST,
7872                             SAS_PORT_BROADCAST_D24_0,
7873                             &mpt->m_phy_info[phy_num].smhba_info);
7874                         break;
7875                 case MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED:
7876                         mptsas_smhba_log_sysevent(mpt,
7877                             ESC_SAS_HBA_PORT_BROADCAST,
7878                             SAS_PORT_BROADCAST_D27_4,
7879                             &mpt->m_phy_info[phy_num].smhba_info);
7880                         break;
7881                 default:
7882                         NDBG16(("mptsas%d: unknown BROADCAST PRIMITIVE"
7883                             " %x received",
7884                             mpt->m_instance, primitive));
7885                         break;
7886                 }
7887                 NDBG16(("mptsas%d sas broadcast primitive: "
7888                     "\tprimitive(0x%04x), phy(%d) complete\n",
7889                     mpt->m_instance, primitive, phy_num));
7890                 break;
7891         }
7892         case MPI2_EVENT_IR_VOLUME:
7893         {
7894                 Mpi2EventDataIrVolume_t         *irVolume;
7895                 uint16_t                        devhandle;
7896                 uint32_t                        state;
7897                 int                             config, vol;
7898                 uint8_t                         found = FALSE;
7899 
7900                 irVolume = (pMpi2EventDataIrVolume_t)eventreply->EventData;
7901                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7902                     &irVolume->NewValue);
7903                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7904                     &irVolume->VolDevHandle);
7905 
7906                 NDBG20(("EVENT_IR_VOLUME event is received"));
7907 
7908                 /*
7909                  * Get latest RAID info and then find the DevHandle for this
7910                  * event in the configuration.  If the DevHandle is not found
7911                  * just exit the event.
7912                  */
7913                 (void) mptsas_get_raid_info(mpt);
7914                 for (config = 0; (config < mpt->m_num_raid_configs) &&
7915                     (!found); config++) {
7916                         for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
7917                                 if (mpt->m_raidconfig[config].m_raidvol[vol].
7918                                     m_raidhandle == devhandle) {
7919                                         found = TRUE;
7920                                         break;
7921                                 }
7922                         }
7923                 }
7924                 if (!found) {
7925                         break;
7926                 }
7927 
7928                 switch (irVolume->ReasonCode) {
7929                 case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
7930                 {
7931                         uint32_t i;
7932                         mpt->m_raidconfig[config].m_raidvol[vol].m_settings =
7933                             state;
7934 
7935                         i = state & MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING;
7936                         mptsas_log(mpt, CE_NOTE, " Volume %d settings changed"
7937                             ", auto-config of hot-swap drives is %s"
7938                             ", write caching is %s"
7939                             ", hot-spare pool mask is %02x\n",
7940                             vol, state &
7941                             MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE
7942                             ? "disabled" : "enabled",
7943                             i == MPI2_RAIDVOL0_SETTING_UNCHANGED
7944                             ? "controlled by member disks" :
7945                             i == MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING
7946                             ? "disabled" :
7947                             i == MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING
7948                             ? "enabled" :
7949                             "incorrectly set",
7950                             (state >> 16) & 0xff);
7951                                 break;
7952                 }
7953                 case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
7954                 {
7955                         mpt->m_raidconfig[config].m_raidvol[vol].m_state =
7956                             (uint8_t)state;
7957 
7958                         mptsas_log(mpt, CE_NOTE,
7959                             "Volume %d is now %s\n", vol,
7960                             state == MPI2_RAID_VOL_STATE_OPTIMAL
7961                             ? "optimal" :
7962                             state == MPI2_RAID_VOL_STATE_DEGRADED
7963                             ? "degraded" :
7964                             state == MPI2_RAID_VOL_STATE_ONLINE
7965                             ? "online" :
7966                             state == MPI2_RAID_VOL_STATE_INITIALIZING
7967                             ? "initializing" :
7968                             state == MPI2_RAID_VOL_STATE_FAILED
7969                             ? "failed" :
7970                             state == MPI2_RAID_VOL_STATE_MISSING
7971                             ? "missing" :
7972                             "state unknown");
7973                         break;
7974                 }
7975                 case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
7976                 {
7977                         mpt->m_raidconfig[config].m_raidvol[vol].
7978                             m_statusflags = state;
7979 
7980                         mptsas_log(mpt, CE_NOTE,
7981                             " Volume %d is now %s%s%s%s%s%s%s%s%s\n",
7982                             vol,
7983                             state & MPI2_RAIDVOL0_STATUS_FLAG_ENABLED
7984                             ? ", enabled" : ", disabled",
7985                             state & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED
7986                             ? ", quiesced" : "",
7987                             state & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE
7988                             ? ", inactive" : ", active",
7989                             state &
7990                             MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL
7991                             ? ", bad block table is full" : "",
7992                             state &
7993                             MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
7994                             ? ", resync in progress" : "",
7995                             state & MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT
7996                             ? ", background initialization in progress" : "",
7997                             state &
7998                             MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION
7999                             ? ", capacity expansion in progress" : "",
8000                             state &
8001                             MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK
8002                             ? ", consistency check in progress" : "",
8003                             state & MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB
8004                             ? ", data scrub in progress" : "");
8005                         break;
8006                 }
8007                 default:
8008                         break;
8009                 }
8010                 break;
8011         }
8012         case MPI2_EVENT_IR_PHYSICAL_DISK:
8013         {
8014                 Mpi2EventDataIrPhysicalDisk_t   *irPhysDisk;
8015                 uint16_t                        devhandle, enchandle, slot;
8016                 uint32_t                        status, state;
8017                 uint8_t                         physdisknum, reason;
8018 
8019                 irPhysDisk = (Mpi2EventDataIrPhysicalDisk_t *)
8020                     eventreply->EventData;
8021                 physdisknum = ddi_get8(mpt->m_acc_reply_frame_hdl,
8022                     &irPhysDisk->PhysDiskNum);
8023                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
8024                     &irPhysDisk->PhysDiskDevHandle);
8025                 enchandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
8026                     &irPhysDisk->EnclosureHandle);
8027                 slot = ddi_get16(mpt->m_acc_reply_frame_hdl,
8028                     &irPhysDisk->Slot);
8029                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
8030                     &irPhysDisk->NewValue);
8031                 reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
8032                     &irPhysDisk->ReasonCode);
8033 
8034                 NDBG20(("EVENT_IR_PHYSICAL_DISK event is received"));
8035 
8036                 switch (reason) {
8037                 case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
8038                         mptsas_log(mpt, CE_NOTE,
8039                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
8040                             "for enclosure with handle 0x%x is now in hot "
8041                             "spare pool %d",
8042                             physdisknum, devhandle, slot, enchandle,
8043                             (state >> 16) & 0xff);
8044                         break;
8045 
8046                 case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
8047                         status = state;
8048                         mptsas_log(mpt, CE_NOTE,
8049                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
8050                             "for enclosure with handle 0x%x is now "
8051                             "%s%s%s%s%s\n", physdisknum, devhandle, slot,
8052                             enchandle,
8053                             status & MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME
8054                             ? ", inactive" : ", active",
8055                             status & MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
8056                             ? ", out of sync" : "",
8057                             status & MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED
8058                             ? ", quiesced" : "",
8059                             status &
8060                             MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED
8061                             ? ", write cache enabled" : "",
8062                             status & MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET
8063                             ? ", capacity expansion target" : "");
8064                         break;
8065 
8066                 case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
8067                         mptsas_log(mpt, CE_NOTE,
8068                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
8069                             "for enclosure with handle 0x%x is now %s\n",
8070                             physdisknum, devhandle, slot, enchandle,
8071                             state == MPI2_RAID_PD_STATE_OPTIMAL
8072                             ? "optimal" :
8073                             state == MPI2_RAID_PD_STATE_REBUILDING
8074                             ? "rebuilding" :
8075                             state == MPI2_RAID_PD_STATE_DEGRADED
8076                             ? "degraded" :
8077                             state == MPI2_RAID_PD_STATE_HOT_SPARE
8078                             ? "a hot spare" :
8079                             state == MPI2_RAID_PD_STATE_ONLINE
8080                             ? "online" :
8081                             state == MPI2_RAID_PD_STATE_OFFLINE
8082                             ? "offline" :
8083                             state == MPI2_RAID_PD_STATE_NOT_COMPATIBLE
8084                             ? "not compatible" :
8085                             state == MPI2_RAID_PD_STATE_NOT_CONFIGURED
8086                             ? "not configured" :
8087                             "state unknown");
8088                         break;
8089                 }
8090                 break;
8091         }
8092         default:
8093                 NDBG20(("mptsas%d: unknown event %x received",
8094                     mpt->m_instance, event));
8095                 break;
8096         }
8097 
8098         /*
8099          * Return the reply frame to the free queue.
8100          */
8101         ddi_put32(mpt->m_acc_free_queue_hdl,
8102             &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index], rfm);
8103         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
8104             DDI_DMA_SYNC_FORDEV);
8105         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
8106                 mpt->m_free_index = 0;
8107         }
8108         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
8109             mpt->m_free_index);
8110         mutex_exit(&mpt->m_mutex);
8111 }
8112 
8113 /*
8114  * invoked from timeout() to restart qfull cmds with throttle == 0
8115  */
8116 static void
8117 mptsas_restart_cmd(void *arg)
8118 {
8119         mptsas_t        *mpt = arg;
8120         mptsas_target_t *ptgt = NULL;
8121 
8122         mutex_enter(&mpt->m_mutex);
8123 
8124         mpt->m_restart_cmd_timeid = 0;
8125 
8126         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
8127             ptgt = refhash_next(mpt->m_targets, ptgt)) {
8128                 if (ptgt->m_reset_delay == 0) {
8129                         if (ptgt->m_t_throttle == QFULL_THROTTLE) {
8130                                 mptsas_set_throttle(mpt, ptgt,
8131                                     MAX_THROTTLE);
8132                         }
8133                 }
8134         }
8135         mptsas_restart_hba(mpt);
8136         mutex_exit(&mpt->m_mutex);
8137 }
8138 
8139 void
8140 mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
8141 {
8142         int             slot;
8143         mptsas_slots_t  *slots = mpt->m_active;
8144         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8145 
8146         ASSERT(cmd != NULL);
8147         ASSERT(cmd->cmd_queued == FALSE);
8148 
8149         /*
8150          * Task Management cmds are removed in their own routines.  Also,
8151          * we don't want to modify timeout based on TM cmds.
8152          */
8153         if (cmd->cmd_flags & CFLAG_TM_CMD) {
8154                 return;
8155         }
8156 
8157         slot = cmd->cmd_slot;
8158 
8159         /*
8160          * remove the cmd.
8161          */
8162         if (cmd == slots->m_slot[slot]) {
8163                 NDBG31(("mptsas_remove_cmd: removing cmd=0x%p, flags "
8164                     "0x%x", (void *)cmd, cmd->cmd_flags));
8165                 slots->m_slot[slot] = NULL;
8166                 mpt->m_ncmds--;
8167 
8168                 /*
8169                  * only decrement per target ncmds if command
8170                  * has a target associated with it.
8171                  */
8172                 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
8173                         ptgt->m_t_ncmds--;
8174                         /*
8175                          * reset throttle if we just ran an untagged command
8176                          * to a tagged target
8177                          */
8178                         if ((ptgt->m_t_ncmds == 0) &&
8179                             ((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0)) {
8180                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
8181                         }
8182 
8183                         /*
8184                          * Remove this command from the active queue.
8185                          */
8186                         if (cmd->cmd_active_expiration != 0) {
8187                                 TAILQ_REMOVE(&ptgt->m_active_cmdq, cmd,
8188                                     cmd_active_link);
8189                                 cmd->cmd_active_expiration = 0;
8190                         }
8191                 }
8192         }
8193 
8194         /*
8195          * This is all we need to do for ioc commands.
8196          */
8197         if (cmd->cmd_flags & CFLAG_CMDIOC) {
8198                 mptsas_return_to_pool(mpt, cmd);
8199                 return;
8200         }
8201 
8202         ASSERT(cmd != slots->m_slot[cmd->cmd_slot]);
8203 }
8204 
8205 /*
8206  * accept all cmds on the tx_waitq if any and then
8207  * start a fresh request from the top of the device queue.
8208  *
8209  * since there are always cmds queued on the tx_waitq, and rare cmds on
8210  * the instance waitq, so this function should not be invoked in the ISR,
8211  * the mptsas_restart_waitq() is invoked in the ISR instead. otherwise, the
8212  * burden belongs to the IO dispatch CPUs is moved the interrupt CPU.
8213  */
8214 static void
8215 mptsas_restart_hba(mptsas_t *mpt)
8216 {
8217         ASSERT(mutex_owned(&mpt->m_mutex));
8218 
8219         mutex_enter(&mpt->m_tx_waitq_mutex);
8220         if (mpt->m_tx_waitq) {
8221                 mptsas_accept_tx_waitq(mpt);
8222         }
8223         mutex_exit(&mpt->m_tx_waitq_mutex);
8224         mptsas_restart_waitq(mpt);
8225 }
8226 
8227 /*
8228  * start a fresh request from the top of the device queue
8229  */
8230 static void
8231 mptsas_restart_waitq(mptsas_t *mpt)
8232 {
8233         mptsas_cmd_t    *cmd, *next_cmd;
8234         mptsas_target_t *ptgt = NULL;
8235 
8236         NDBG1(("mptsas_restart_waitq: mpt=0x%p", (void *)mpt));
8237 
8238         ASSERT(mutex_owned(&mpt->m_mutex));
8239 
8240         /*
8241          * If there is a reset delay, don't start any cmds.  Otherwise, start
8242          * as many cmds as possible.
8243          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
8244          * commands is m_max_requests - 2.
8245          */
8246         cmd = mpt->m_waitq;
8247 
8248         while (cmd != NULL) {
8249                 next_cmd = cmd->cmd_linkp;
8250                 if (cmd->cmd_flags & CFLAG_PASSTHRU) {
8251                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8252                                 /*
8253                                  * passthru command get slot need
8254                                  * set CFLAG_PREPARED.
8255                                  */
8256                                 cmd->cmd_flags |= CFLAG_PREPARED;
8257                                 mptsas_waitq_delete(mpt, cmd);
8258                                 mptsas_start_passthru(mpt, cmd);
8259                         }
8260                         cmd = next_cmd;
8261                         continue;
8262                 }
8263                 if (cmd->cmd_flags & CFLAG_CONFIG) {
8264                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8265                                 /*
8266                                  * Send the config page request and delete it
8267                                  * from the waitq.
8268                                  */
8269                                 cmd->cmd_flags |= CFLAG_PREPARED;
8270                                 mptsas_waitq_delete(mpt, cmd);
8271                                 mptsas_start_config_page_access(mpt, cmd);
8272                         }
8273                         cmd = next_cmd;
8274                         continue;
8275                 }
8276                 if (cmd->cmd_flags & CFLAG_FW_DIAG) {
8277                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8278                                 /*
8279                                  * Send the FW Diag request and delete if from
8280                                  * the waitq.
8281                                  */
8282                                 cmd->cmd_flags |= CFLAG_PREPARED;
8283                                 mptsas_waitq_delete(mpt, cmd);
8284                                 mptsas_start_diag(mpt, cmd);
8285                         }
8286                         cmd = next_cmd;
8287                         continue;
8288                 }
8289 
8290                 ptgt = cmd->cmd_tgt_addr;
8291                 if (ptgt && (ptgt->m_t_throttle == DRAIN_THROTTLE) &&
8292                     (ptgt->m_t_ncmds == 0)) {
8293                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
8294                 }
8295                 if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
8296                     (ptgt && (ptgt->m_reset_delay == 0)) &&
8297                     (ptgt && (ptgt->m_t_ncmds <
8298                     ptgt->m_t_throttle))) {
8299                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8300                                 mptsas_waitq_delete(mpt, cmd);
8301                                 (void) mptsas_start_cmd(mpt, cmd);
8302                         }
8303                 }
8304                 cmd = next_cmd;
8305         }
8306 }
8307 /*
8308  * Cmds are queued if tran_start() doesn't get the m_mutexlock(no wait).
8309  * Accept all those queued cmds before new cmd is accept so that the
8310  * cmds are sent in order.
8311  */
8312 static void
8313 mptsas_accept_tx_waitq(mptsas_t *mpt)
8314 {
8315         mptsas_cmd_t *cmd;
8316 
8317         ASSERT(mutex_owned(&mpt->m_mutex));
8318         ASSERT(mutex_owned(&mpt->m_tx_waitq_mutex));
8319 
8320         /*
8321          * A Bus Reset could occur at any time and flush the tx_waitq,
8322          * so we cannot count on the tx_waitq to contain even one cmd.
8323          * And when the m_tx_waitq_mutex is released and run
8324          * mptsas_accept_pkt(), the tx_waitq may be flushed.
8325          */
8326         cmd = mpt->m_tx_waitq;
8327         for (;;) {
8328                 if ((cmd = mpt->m_tx_waitq) == NULL) {
8329                         mpt->m_tx_draining = 0;
8330                         break;
8331                 }
8332                 if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL) {
8333                         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
8334                 }
8335                 cmd->cmd_linkp = NULL;
8336                 mutex_exit(&mpt->m_tx_waitq_mutex);
8337                 if (mptsas_accept_pkt(mpt, cmd) != TRAN_ACCEPT)
8338                         cmn_err(CE_WARN, "mpt: mptsas_accept_tx_waitq: failed "
8339                             "to accept cmd on queue\n");
8340                 mutex_enter(&mpt->m_tx_waitq_mutex);
8341         }
8342 }
8343 
8344 
8345 /*
8346  * mpt tag type lookup
8347  */
8348 static char mptsas_tag_lookup[] =
8349         {0, MSG_HEAD_QTAG, MSG_ORDERED_QTAG, 0, MSG_SIMPLE_QTAG};
8350 
8351 static int
8352 mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
8353 {
8354         struct scsi_pkt         *pkt = CMD2PKT(cmd);
8355         uint32_t                control = 0;
8356         caddr_t                 mem, arsbuf;
8357         pMpi2SCSIIORequest_t    io_request;
8358         ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
8359         ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
8360         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
8361         uint16_t                SMID, io_flags = 0;
8362         uint8_t                 ars_size;
8363         uint64_t                request_desc;
8364         uint32_t                ars_dmaaddrlow;
8365         mptsas_cmd_t            *c;
8366 
8367         NDBG1(("mptsas_start_cmd: cmd=0x%p, flags 0x%x", (void *)cmd,
8368             cmd->cmd_flags));
8369 
8370         /*
8371          * Set SMID and increment index.  Rollover to 1 instead of 0 if index
8372          * is at the max.  0 is an invalid SMID, so we call the first index 1.
8373          */
8374         SMID = cmd->cmd_slot;
8375 
8376         /*
8377          * It is possible for back to back device reset to
8378          * happen before the reset delay has expired.  That's
8379          * ok, just let the device reset go out on the bus.
8380          */
8381         if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
8382                 ASSERT(ptgt->m_reset_delay == 0);
8383         }
8384 
8385         /*
8386          * if a non-tagged cmd is submitted to an active tagged target
8387          * then drain before submitting this cmd; SCSI-2 allows RQSENSE
8388          * to be untagged
8389          */
8390         if (((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0) &&
8391             (ptgt->m_t_ncmds > 1) &&
8392             ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) &&
8393             (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE)) {
8394                 if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
8395                         NDBG23(("target=%d, untagged cmd, start draining\n",
8396                             ptgt->m_devhdl));
8397 
8398                         if (ptgt->m_reset_delay == 0) {
8399                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
8400                         }
8401 
8402                         mptsas_remove_cmd(mpt, cmd);
8403                         cmd->cmd_pkt_flags |= FLAG_HEAD;
8404                         mptsas_waitq_add(mpt, cmd);
8405                 }
8406                 return (DDI_FAILURE);
8407         }
8408 
8409         /*
8410          * Set correct tag bits.
8411          */
8412         if (cmd->cmd_pkt_flags & FLAG_TAGMASK) {
8413                 switch (mptsas_tag_lookup[((cmd->cmd_pkt_flags &
8414                     FLAG_TAGMASK) >> 12)]) {
8415                 case MSG_SIMPLE_QTAG:
8416                         control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
8417                         break;
8418                 case MSG_HEAD_QTAG:
8419                         control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
8420                         break;
8421                 case MSG_ORDERED_QTAG:
8422                         control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
8423                         break;
8424                 default:
8425                         mptsas_log(mpt, CE_WARN, "mpt: Invalid tag type\n");
8426                         break;
8427                 }
8428         } else {
8429                 if (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE) {
8430                                 ptgt->m_t_throttle = 1;
8431                 }
8432                 control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
8433         }
8434 
8435         if (cmd->cmd_pkt_flags & FLAG_TLR) {
8436                 control |= MPI2_SCSIIO_CONTROL_TLR_ON;
8437         }
8438 
8439         mem = mpt->m_req_frame + (mpt->m_req_frame_size * SMID);
8440         io_request = (pMpi2SCSIIORequest_t)mem;
8441         if (cmd->cmd_extrqslen != 0) {
8442                 /*
8443                  * Mapping of the buffer was done in mptsas_pkt_alloc_extern().
8444                  * Calculate the DMA address with the same offset.
8445                  */
8446                 arsbuf = cmd->cmd_arq_buf;
8447                 ars_size = cmd->cmd_extrqslen;
8448                 ars_dmaaddrlow = (mpt->m_req_sense_dma_addr +
8449                     ((uintptr_t)arsbuf - (uintptr_t)mpt->m_req_sense)) &
8450                     0xffffffffu;
8451         } else {
8452                 arsbuf = mpt->m_req_sense + (mpt->m_req_sense_size * (SMID-1));
8453                 cmd->cmd_arq_buf = arsbuf;
8454                 ars_size = mpt->m_req_sense_size;
8455                 ars_dmaaddrlow = (mpt->m_req_sense_dma_addr +
8456                     (mpt->m_req_sense_size * (SMID-1))) &
8457                     0xffffffffu;
8458         }
8459         bzero(io_request, sizeof (Mpi2SCSIIORequest_t));
8460         bzero(arsbuf, ars_size);
8461 
8462         ddi_put8(acc_hdl, &io_request->SGLOffset0, offsetof
8463             (MPI2_SCSI_IO_REQUEST, SGL) / 4);
8464         mptsas_init_std_hdr(acc_hdl, io_request, ptgt->m_devhdl, Lun(cmd), 0,
8465             MPI2_FUNCTION_SCSI_IO_REQUEST);
8466 
8467         (void) ddi_rep_put8(acc_hdl, (uint8_t *)pkt->pkt_cdbp,
8468             io_request->CDB.CDB32, cmd->cmd_cdblen, DDI_DEV_AUTOINCR);
8469 
8470         io_flags = cmd->cmd_cdblen;
8471         if (mptsas_use_fastpath &&
8472             ptgt->m_io_flags & MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) {
8473                 io_flags |= MPI25_SCSIIO_IOFLAGS_FAST_PATH;
8474                 request_desc = MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
8475         } else {
8476                 request_desc = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
8477         }
8478         ddi_put16(acc_hdl, &io_request->IoFlags, io_flags);
8479         /*
8480          * setup the Scatter/Gather DMA list for this request
8481          */
8482         if (cmd->cmd_cookiec > 0) {
8483                 mptsas_sge_setup(mpt, cmd, &control, io_request, acc_hdl);
8484         } else {
8485                 ddi_put32(acc_hdl, &io_request->SGL.MpiSimple.FlagsLength,
8486                     ((uint32_t)MPI2_SGE_FLAGS_LAST_ELEMENT |
8487                     MPI2_SGE_FLAGS_END_OF_BUFFER |
8488                     MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
8489                     MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
8490         }
8491 
8492         /*
8493          * save ARQ information
8494          */
8495         ddi_put8(acc_hdl, &io_request->SenseBufferLength, ars_size);
8496         ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress, ars_dmaaddrlow);
8497 
8498         ddi_put32(acc_hdl, &io_request->Control, control);
8499 
8500         NDBG31(("starting message=%d(0x%p), with cmd=0x%p",
8501             SMID, (void *)io_request, (void *)cmd));
8502 
8503         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
8504         (void) ddi_dma_sync(mpt->m_dma_req_sense_hdl, 0, 0,
8505             DDI_DMA_SYNC_FORDEV);
8506 
8507         /*
8508          * Build request descriptor and write it to the request desc post reg.
8509          */
8510         request_desc |= (SMID << 16);
8511         request_desc |= (uint64_t)ptgt->m_devhdl << 48;
8512         MPTSAS_START_CMD(mpt, request_desc);
8513 
8514         /*
8515          * Start timeout.
8516          */
8517         cmd->cmd_active_expiration =
8518             gethrtime() + (hrtime_t)pkt->pkt_time * NANOSEC;
8519 #ifdef MPTSAS_TEST
8520         /*
8521          * Force timeouts to happen immediately.
8522          */
8523         if (mptsas_test_timeouts)
8524                 cmd->cmd_active_expiration = gethrtime();
8525 #endif
8526         c = TAILQ_FIRST(&ptgt->m_active_cmdq);
8527         if (c == NULL ||
8528             c->cmd_active_expiration < cmd->cmd_active_expiration) {
8529                 /*
8530                  * Common case is that this is the last pending expiration
8531                  * (or queue is empty). Insert at head of the queue.
8532                  */
8533                 TAILQ_INSERT_HEAD(&ptgt->m_active_cmdq, cmd, cmd_active_link);
8534         } else {
8535                 /*
8536                  * Queue is not empty and first element expires later than
8537                  * this command. Search for element expiring sooner.
8538                  */
8539                 while ((c = TAILQ_NEXT(c, cmd_active_link)) != NULL) {
8540                         if (c->cmd_active_expiration <
8541                             cmd->cmd_active_expiration) {
8542                                 TAILQ_INSERT_BEFORE(c, cmd, cmd_active_link);
8543                                 break;
8544                         }
8545                 }
8546                 if (c == NULL) {
8547                         /*
8548                          * No element found expiring sooner, append to
8549                          * non-empty queue.
8550                          */
8551                         TAILQ_INSERT_TAIL(&ptgt->m_active_cmdq, cmd,
8552                             cmd_active_link);
8553                 }
8554         }
8555 
8556         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
8557             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
8558                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8559                 return (DDI_FAILURE);
8560         }
8561         return (DDI_SUCCESS);
8562 }
8563 
8564 /*
8565  * Select a helper thread to handle current doneq
8566  */
8567 static void
8568 mptsas_deliver_doneq_thread(mptsas_t *mpt)
8569 {
8570         uint64_t                        t, i;
8571         uint32_t                        min = 0xffffffff;
8572         mptsas_doneq_thread_list_t      *item;
8573 
8574         for (i = 0; i < mpt->m_doneq_thread_n; i++) {
8575                 item = &mpt->m_doneq_thread_id[i];
8576                 /*
8577                  * If the completed command on help thread[i] less than
8578                  * doneq_thread_threshold, then pick the thread[i]. Otherwise
8579                  * pick a thread which has least completed command.
8580                  */
8581 
8582                 mutex_enter(&item->mutex);
8583                 if (item->len < mpt->m_doneq_thread_threshold) {
8584                         t = i;
8585                         mutex_exit(&item->mutex);
8586                         break;
8587                 }
8588                 if (item->len < min) {
8589                         min = item->len;
8590                         t = i;
8591                 }
8592                 mutex_exit(&item->mutex);
8593         }
8594         mutex_enter(&mpt->m_doneq_thread_id[t].mutex);
8595         mptsas_doneq_mv(mpt, t);
8596         cv_signal(&mpt->m_doneq_thread_id[t].cv);
8597         mutex_exit(&mpt->m_doneq_thread_id[t].mutex);
8598 }
8599 
8600 /*
8601  * move the current global doneq to the doneq of thead[t]
8602  */
8603 static void
8604 mptsas_doneq_mv(mptsas_t *mpt, uint64_t t)
8605 {
8606         mptsas_cmd_t                    *cmd;
8607         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
8608 
8609         ASSERT(mutex_owned(&item->mutex));
8610         while ((cmd = mpt->m_doneq) != NULL) {
8611                 if ((mpt->m_doneq = cmd->cmd_linkp) == NULL) {
8612                         mpt->m_donetail = &mpt->m_doneq;
8613                 }
8614                 cmd->cmd_linkp = NULL;
8615                 *item->donetail = cmd;
8616                 item->donetail = &cmd->cmd_linkp;
8617                 mpt->m_doneq_len--;
8618                 item->len++;
8619         }
8620 }
8621 
8622 void
8623 mptsas_fma_check(mptsas_t *mpt, mptsas_cmd_t *cmd)
8624 {
8625         struct scsi_pkt *pkt = CMD2PKT(cmd);
8626 
8627         /* Check all acc and dma handles */
8628         if ((mptsas_check_acc_handle(mpt->m_datap) !=
8629             DDI_SUCCESS) ||
8630             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
8631             DDI_SUCCESS) ||
8632             (mptsas_check_acc_handle(mpt->m_acc_req_sense_hdl) !=
8633             DDI_SUCCESS) ||
8634             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
8635             DDI_SUCCESS) ||
8636             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
8637             DDI_SUCCESS) ||
8638             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
8639             DDI_SUCCESS) ||
8640             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
8641             DDI_SUCCESS) ||
8642             (mptsas_check_acc_handle(mpt->m_config_handle) !=
8643             DDI_SUCCESS)) {
8644                 ddi_fm_service_impact(mpt->m_dip,
8645                     DDI_SERVICE_UNAFFECTED);
8646                 ddi_fm_acc_err_clear(mpt->m_config_handle,
8647                     DDI_FME_VER0);
8648                 pkt->pkt_reason = CMD_TRAN_ERR;
8649                 pkt->pkt_statistics = 0;
8650         }
8651         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
8652             DDI_SUCCESS) ||
8653             (mptsas_check_dma_handle(mpt->m_dma_req_sense_hdl) !=
8654             DDI_SUCCESS) ||
8655             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
8656             DDI_SUCCESS) ||
8657             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
8658             DDI_SUCCESS) ||
8659             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
8660             DDI_SUCCESS) ||
8661             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
8662             DDI_SUCCESS)) {
8663                 ddi_fm_service_impact(mpt->m_dip,
8664                     DDI_SERVICE_UNAFFECTED);
8665                 pkt->pkt_reason = CMD_TRAN_ERR;
8666                 pkt->pkt_statistics = 0;
8667         }
8668         if (cmd->cmd_dmahandle &&
8669             (mptsas_check_dma_handle(cmd->cmd_dmahandle) != DDI_SUCCESS)) {
8670                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8671                 pkt->pkt_reason = CMD_TRAN_ERR;
8672                 pkt->pkt_statistics = 0;
8673         }
8674         if ((cmd->cmd_extra_frames &&
8675             ((mptsas_check_dma_handle(cmd->cmd_extra_frames->m_dma_hdl) !=
8676             DDI_SUCCESS) ||
8677             (mptsas_check_acc_handle(cmd->cmd_extra_frames->m_acc_hdl) !=
8678             DDI_SUCCESS)))) {
8679                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8680                 pkt->pkt_reason = CMD_TRAN_ERR;
8681                 pkt->pkt_statistics = 0;
8682         }
8683 }
8684 
8685 /*
8686  * These routines manipulate the queue of commands that
8687  * are waiting for their completion routines to be called.
8688  * The queue is usually in FIFO order but on an MP system
8689  * it's possible for the completion routines to get out
8690  * of order. If that's a problem you need to add a global
8691  * mutex around the code that calls the completion routine
8692  * in the interrupt handler.
8693  */
8694 static void
8695 mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8696 {
8697         struct scsi_pkt *pkt = CMD2PKT(cmd);
8698 
8699         NDBG31(("mptsas_doneq_add: cmd=0x%p", (void *)cmd));
8700 
8701         ASSERT((cmd->cmd_flags & CFLAG_COMPLETED) == 0);
8702         cmd->cmd_linkp = NULL;
8703         cmd->cmd_flags |= CFLAG_FINISHED;
8704         cmd->cmd_flags &= ~CFLAG_IN_TRANSPORT;
8705 
8706         mptsas_fma_check(mpt, cmd);
8707 
8708         /*
8709          * only add scsi pkts that have completion routines to
8710          * the doneq.  no intr cmds do not have callbacks.
8711          */
8712         if (pkt && (pkt->pkt_comp)) {
8713                 *mpt->m_donetail = cmd;
8714                 mpt->m_donetail = &cmd->cmd_linkp;
8715                 mpt->m_doneq_len++;
8716         }
8717 }
8718 
8719 static mptsas_cmd_t *
8720 mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t)
8721 {
8722         mptsas_cmd_t                    *cmd;
8723         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
8724 
8725         /* pop one off the done queue */
8726         if ((cmd = item->doneq) != NULL) {
8727                 /* if the queue is now empty fix the tail pointer */
8728                 NDBG31(("mptsas_doneq_thread_rm: cmd=0x%p", (void *)cmd));
8729                 if ((item->doneq = cmd->cmd_linkp) == NULL) {
8730                         item->donetail = &item->doneq;
8731                 }
8732                 cmd->cmd_linkp = NULL;
8733                 item->len--;
8734         }
8735         return (cmd);
8736 }
8737 
8738 static void
8739 mptsas_doneq_empty(mptsas_t *mpt)
8740 {
8741         if (mpt->m_doneq && !mpt->m_in_callback) {
8742                 mptsas_cmd_t    *cmd, *next;
8743                 struct scsi_pkt *pkt;
8744 
8745                 mpt->m_in_callback = 1;
8746                 cmd = mpt->m_doneq;
8747                 mpt->m_doneq = NULL;
8748                 mpt->m_donetail = &mpt->m_doneq;
8749                 mpt->m_doneq_len = 0;
8750 
8751                 mutex_exit(&mpt->m_mutex);
8752                 /*
8753                  * run the completion routines of all the
8754                  * completed commands
8755                  */
8756                 while (cmd != NULL) {
8757                         next = cmd->cmd_linkp;
8758                         cmd->cmd_linkp = NULL;
8759                         /* run this command's completion routine */
8760                         cmd->cmd_flags |= CFLAG_COMPLETED;
8761                         pkt = CMD2PKT(cmd);
8762                         mptsas_pkt_comp(pkt, cmd);
8763                         cmd = next;
8764                 }
8765                 mutex_enter(&mpt->m_mutex);
8766                 mpt->m_in_callback = 0;
8767         }
8768 }
8769 
8770 /*
8771  * These routines manipulate the target's queue of pending requests
8772  */
8773 void
8774 mptsas_waitq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8775 {
8776         NDBG7(("mptsas_waitq_add: cmd=0x%p", (void *)cmd));
8777         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8778         cmd->cmd_queued = TRUE;
8779         if (ptgt)
8780                 ptgt->m_t_nwait++;
8781         if (cmd->cmd_pkt_flags & FLAG_HEAD) {
8782                 if ((cmd->cmd_linkp = mpt->m_waitq) == NULL) {
8783                         mpt->m_waitqtail = &cmd->cmd_linkp;
8784                 }
8785                 mpt->m_waitq = cmd;
8786         } else {
8787                 cmd->cmd_linkp = NULL;
8788                 *(mpt->m_waitqtail) = cmd;
8789                 mpt->m_waitqtail = &cmd->cmd_linkp;
8790         }
8791 }
8792 
8793 static mptsas_cmd_t *
8794 mptsas_waitq_rm(mptsas_t *mpt)
8795 {
8796         mptsas_cmd_t    *cmd;
8797         mptsas_target_t *ptgt;
8798         NDBG7(("mptsas_waitq_rm"));
8799 
8800         MPTSAS_WAITQ_RM(mpt, cmd);
8801 
8802         NDBG7(("mptsas_waitq_rm: cmd=0x%p", (void *)cmd));
8803         if (cmd) {
8804                 ptgt = cmd->cmd_tgt_addr;
8805                 if (ptgt) {
8806                         ptgt->m_t_nwait--;
8807                         ASSERT(ptgt->m_t_nwait >= 0);
8808                 }
8809         }
8810         return (cmd);
8811 }
8812 
8813 /*
8814  * remove specified cmd from the middle of the wait queue.
8815  */
8816 static void
8817 mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8818 {
8819         mptsas_cmd_t    *prevp = mpt->m_waitq;
8820         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8821 
8822         NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8823             (void *)mpt, (void *)cmd));
8824         if (ptgt) {
8825                 ptgt->m_t_nwait--;
8826                 ASSERT(ptgt->m_t_nwait >= 0);
8827         }
8828 
8829         if (prevp == cmd) {
8830                 if ((mpt->m_waitq = cmd->cmd_linkp) == NULL)
8831                         mpt->m_waitqtail = &mpt->m_waitq;
8832 
8833                 cmd->cmd_linkp = NULL;
8834                 cmd->cmd_queued = FALSE;
8835                 NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8836                     (void *)mpt, (void *)cmd));
8837                 return;
8838         }
8839 
8840         while (prevp != NULL) {
8841                 if (prevp->cmd_linkp == cmd) {
8842                         if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8843                                 mpt->m_waitqtail = &prevp->cmd_linkp;
8844 
8845                         cmd->cmd_linkp = NULL;
8846                         cmd->cmd_queued = FALSE;
8847                         NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8848                             (void *)mpt, (void *)cmd));
8849                         return;
8850                 }
8851                 prevp = prevp->cmd_linkp;
8852         }
8853         cmn_err(CE_PANIC, "mpt: mptsas_waitq_delete: queue botch");
8854 }
8855 
8856 static mptsas_cmd_t *
8857 mptsas_tx_waitq_rm(mptsas_t *mpt)
8858 {
8859         mptsas_cmd_t *cmd;
8860         NDBG7(("mptsas_tx_waitq_rm"));
8861 
8862         MPTSAS_TX_WAITQ_RM(mpt, cmd);
8863 
8864         NDBG7(("mptsas_tx_waitq_rm: cmd=0x%p", (void *)cmd));
8865 
8866         return (cmd);
8867 }
8868 
8869 /*
8870  * remove specified cmd from the middle of the tx_waitq.
8871  */
8872 static void
8873 mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8874 {
8875         mptsas_cmd_t *prevp = mpt->m_tx_waitq;
8876 
8877         NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8878             (void *)mpt, (void *)cmd));
8879 
8880         if (prevp == cmd) {
8881                 if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL)
8882                         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
8883 
8884                 cmd->cmd_linkp = NULL;
8885                 cmd->cmd_queued = FALSE;
8886                 NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8887                     (void *)mpt, (void *)cmd));
8888                 return;
8889         }
8890 
8891         while (prevp != NULL) {
8892                 if (prevp->cmd_linkp == cmd) {
8893                         if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8894                                 mpt->m_tx_waitqtail = &prevp->cmd_linkp;
8895 
8896                         cmd->cmd_linkp = NULL;
8897                         cmd->cmd_queued = FALSE;
8898                         NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8899                             (void *)mpt, (void *)cmd));
8900                         return;
8901                 }
8902                 prevp = prevp->cmd_linkp;
8903         }
8904         cmn_err(CE_PANIC, "mpt: mptsas_tx_waitq_delete: queue botch");
8905 }
8906 
8907 /*
8908  * device and bus reset handling
8909  *
8910  * Notes:
8911  *      - RESET_ALL:    reset the controller
8912  *      - RESET_TARGET: reset the target specified in scsi_address
8913  */
8914 static int
8915 mptsas_scsi_reset(struct scsi_address *ap, int level)
8916 {
8917         mptsas_t                *mpt = ADDR2MPT(ap);
8918         int                     rval;
8919         mptsas_tgt_private_t    *tgt_private;
8920         mptsas_target_t         *ptgt = NULL;
8921 
8922         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->tran_tgt_private;
8923         ptgt = tgt_private->t_private;
8924         if (ptgt == NULL) {
8925                 return (FALSE);
8926         }
8927         NDBG22(("mptsas_scsi_reset: target=%d level=%d", ptgt->m_devhdl,
8928             level));
8929 
8930         mutex_enter(&mpt->m_mutex);
8931         /*
8932          * if we are not in panic set up a reset delay for this target
8933          */
8934         if (!ddi_in_panic()) {
8935                 mptsas_setup_bus_reset_delay(mpt);
8936         } else {
8937                 drv_usecwait(mpt->m_scsi_reset_delay * 1000);
8938         }
8939         rval = mptsas_do_scsi_reset(mpt, ptgt->m_devhdl);
8940         mutex_exit(&mpt->m_mutex);
8941 
8942         /*
8943          * The transport layer expect to only see TRUE and
8944          * FALSE. Therefore, we will adjust the return value
8945          * if mptsas_do_scsi_reset returns FAILED.
8946          */
8947         if (rval == FAILED)
8948                 rval = FALSE;
8949         return (rval);
8950 }
8951 
8952 static int
8953 mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl)
8954 {
8955         int             rval = FALSE;
8956         uint8_t         config, disk;
8957 
8958         ASSERT(mutex_owned(&mpt->m_mutex));
8959 
8960         if (mptsas_debug_resets) {
8961                 mptsas_log(mpt, CE_WARN, "mptsas_do_scsi_reset: target=%d",
8962                     devhdl);
8963         }
8964 
8965         /*
8966          * Issue a Target Reset message to the target specified but not to a
8967          * disk making up a raid volume.  Just look through the RAID config
8968          * Phys Disk list of DevHandles.  If the target's DevHandle is in this
8969          * list, then don't reset this target.
8970          */
8971         for (config = 0; config < mpt->m_num_raid_configs; config++) {
8972                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
8973                         if (devhdl == mpt->m_raidconfig[config].
8974                             m_physdisk_devhdl[disk]) {
8975                                 return (TRUE);
8976                         }
8977                 }
8978         }
8979 
8980         rval = mptsas_ioc_task_management(mpt,
8981             MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, devhdl, 0, NULL, 0, 0);
8982 
8983         mptsas_doneq_empty(mpt);
8984         return (rval);
8985 }
8986 
8987 static int
8988 mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
8989         void (*callback)(caddr_t), caddr_t arg)
8990 {
8991         mptsas_t        *mpt = ADDR2MPT(ap);
8992 
8993         NDBG22(("mptsas_scsi_reset_notify: tgt=%d", ap->a_target));
8994 
8995         return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
8996             &mpt->m_mutex, &mpt->m_reset_notify_listf));
8997 }
8998 
8999 static int
9000 mptsas_get_name(struct scsi_device *sd, char *name, int len)
9001 {
9002         dev_info_t      *lun_dip = NULL;
9003 
9004         ASSERT(sd != NULL);
9005         ASSERT(name != NULL);
9006         lun_dip = sd->sd_dev;
9007         ASSERT(lun_dip != NULL);
9008 
9009         if (mptsas_name_child(lun_dip, name, len) == DDI_SUCCESS) {
9010                 return (1);
9011         } else {
9012                 return (0);
9013         }
9014 }
9015 
9016 static int
9017 mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len)
9018 {
9019         return (mptsas_get_name(sd, name, len));
9020 }
9021 
9022 void
9023 mptsas_set_throttle(mptsas_t *mpt, mptsas_target_t *ptgt, int what)
9024 {
9025 
9026         NDBG25(("mptsas_set_throttle: throttle=%x", what));
9027 
9028         /*
9029          * if the bus is draining/quiesced, no changes to the throttles
9030          * are allowed. Not allowing change of throttles during draining
9031          * limits error recovery but will reduce draining time
9032          *
9033          * all throttles should have been set to HOLD_THROTTLE
9034          */
9035         if (mpt->m_softstate & (MPTSAS_SS_QUIESCED | MPTSAS_SS_DRAINING)) {
9036                 return;
9037         }
9038 
9039         if (what == HOLD_THROTTLE) {
9040                 ptgt->m_t_throttle = HOLD_THROTTLE;
9041         } else if (ptgt->m_reset_delay == 0) {
9042                 ptgt->m_t_throttle = what;
9043         }
9044 }
9045 
9046 /*
9047  * Clean up from a device reset.
9048  * For the case of target reset, this function clears the waitq of all
9049  * commands for a particular target.   For the case of abort task set, this
9050  * function clears the waitq of all commonds for a particular target/lun.
9051  */
9052 static void
9053 mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun, uint8_t tasktype)
9054 {
9055         mptsas_slots_t  *slots = mpt->m_active;
9056         mptsas_cmd_t    *cmd, *next_cmd;
9057         int             slot;
9058         uchar_t         reason;
9059         uint_t          stat;
9060         hrtime_t        timestamp;
9061 
9062         NDBG25(("mptsas_flush_target: target=%d lun=%d", target, lun));
9063 
9064         timestamp = gethrtime();
9065 
9066         /*
9067          * Make sure the I/O Controller has flushed all cmds
9068          * that are associated with this target for a target reset
9069          * and target/lun for abort task set.
9070          * Account for TM requests, which use the last SMID.
9071          */
9072         for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
9073                 if ((cmd = slots->m_slot[slot]) == NULL)
9074                         continue;
9075                 reason = CMD_RESET;
9076                 stat = STAT_DEV_RESET;
9077                 switch (tasktype) {
9078                 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
9079                         if (Tgt(cmd) == target) {
9080                                 if (cmd->cmd_active_expiration <= timestamp) {
9081                                         /*
9082                                          * When timeout requested, propagate
9083                                          * proper reason and statistics to
9084                                          * target drivers.
9085                                          */
9086                                         reason = CMD_TIMEOUT;
9087                                         stat |= STAT_TIMEOUT;
9088                                 }
9089                                 NDBG25(("mptsas_flush_target discovered non-"
9090                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
9091                                     tasktype));
9092                                 mptsas_dump_cmd(mpt, cmd);
9093                                 mptsas_remove_cmd(mpt, cmd);
9094                                 mptsas_set_pkt_reason(mpt, cmd, reason, stat);
9095                                 mptsas_doneq_add(mpt, cmd);
9096                         }
9097                         break;
9098                 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
9099                         reason = CMD_ABORTED;
9100                         stat = STAT_ABORTED;
9101                         /*FALLTHROUGH*/
9102                 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
9103                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
9104 
9105                                 NDBG25(("mptsas_flush_target discovered non-"
9106                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
9107                                     tasktype));
9108                                 mptsas_dump_cmd(mpt, cmd);
9109                                 mptsas_remove_cmd(mpt, cmd);
9110                                 mptsas_set_pkt_reason(mpt, cmd, reason,
9111                                     stat);
9112                                 mptsas_doneq_add(mpt, cmd);
9113                         }
9114                         break;
9115                 default:
9116                         break;
9117                 }
9118         }
9119 
9120         /*
9121          * Flush the waitq and tx_waitq of this target's cmds
9122          */
9123         cmd = mpt->m_waitq;
9124 
9125         reason = CMD_RESET;
9126         stat = STAT_DEV_RESET;
9127 
9128         switch (tasktype) {
9129         case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
9130                 while (cmd != NULL) {
9131                         next_cmd = cmd->cmd_linkp;
9132                         if (Tgt(cmd) == target) {
9133                                 mptsas_waitq_delete(mpt, cmd);
9134                                 mptsas_set_pkt_reason(mpt, cmd,
9135                                     reason, stat);
9136                                 mptsas_doneq_add(mpt, cmd);
9137                         }
9138                         cmd = next_cmd;
9139                 }
9140                 mutex_enter(&mpt->m_tx_waitq_mutex);
9141                 cmd = mpt->m_tx_waitq;
9142                 while (cmd != NULL) {
9143                         next_cmd = cmd->cmd_linkp;
9144                         if (Tgt(cmd) == target) {
9145                                 mptsas_tx_waitq_delete(mpt, cmd);
9146                                 mutex_exit(&mpt->m_tx_waitq_mutex);
9147                                 mptsas_set_pkt_reason(mpt, cmd,
9148                                     reason, stat);
9149                                 mptsas_doneq_add(mpt, cmd);
9150                                 mutex_enter(&mpt->m_tx_waitq_mutex);
9151                         }
9152                         cmd = next_cmd;
9153                 }
9154                 mutex_exit(&mpt->m_tx_waitq_mutex);
9155                 break;
9156         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
9157                 reason = CMD_ABORTED;
9158                 stat =  STAT_ABORTED;
9159                 /*FALLTHROUGH*/
9160         case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
9161                 while (cmd != NULL) {
9162                         next_cmd = cmd->cmd_linkp;
9163                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
9164                                 mptsas_waitq_delete(mpt, cmd);
9165                                 mptsas_set_pkt_reason(mpt, cmd,
9166                                     reason, stat);
9167                                 mptsas_doneq_add(mpt, cmd);
9168                         }
9169                         cmd = next_cmd;
9170                 }
9171                 mutex_enter(&mpt->m_tx_waitq_mutex);
9172                 cmd = mpt->m_tx_waitq;
9173                 while (cmd != NULL) {
9174                         next_cmd = cmd->cmd_linkp;
9175                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
9176                                 mptsas_tx_waitq_delete(mpt, cmd);
9177                                 mutex_exit(&mpt->m_tx_waitq_mutex);
9178                                 mptsas_set_pkt_reason(mpt, cmd,
9179                                     reason, stat);
9180                                 mptsas_doneq_add(mpt, cmd);
9181                                 mutex_enter(&mpt->m_tx_waitq_mutex);
9182                         }
9183                         cmd = next_cmd;
9184                 }
9185                 mutex_exit(&mpt->m_tx_waitq_mutex);
9186                 break;
9187         default:
9188                 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
9189                     tasktype);
9190                 break;
9191         }
9192 }
9193 
9194 /*
9195  * Clean up hba state, abort all outstanding command and commands in waitq
9196  * reset timeout of all targets.
9197  */
9198 static void
9199 mptsas_flush_hba(mptsas_t *mpt)
9200 {
9201         mptsas_slots_t  *slots = mpt->m_active;
9202         mptsas_cmd_t    *cmd;
9203         int             slot;
9204 
9205         NDBG25(("mptsas_flush_hba"));
9206 
9207         /*
9208          * The I/O Controller should have already sent back
9209          * all commands via the scsi I/O reply frame.  Make
9210          * sure all commands have been flushed.
9211          * Account for TM request, which use the last SMID.
9212          */
9213         for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
9214                 if ((cmd = slots->m_slot[slot]) == NULL)
9215                         continue;
9216 
9217                 if (cmd->cmd_flags & CFLAG_CMDIOC) {
9218                         /*
9219                          * Need to make sure to tell everyone that might be
9220                          * waiting on this command that it's going to fail.  If
9221                          * we get here, this command will never timeout because
9222                          * the active command table is going to be re-allocated,
9223                          * so there will be nothing to check against a time out.
9224                          * Instead, mark the command as failed due to reset.
9225                          */
9226                         mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
9227                             STAT_BUS_RESET);
9228                         if ((cmd->cmd_flags &
9229                             (CFLAG_PASSTHRU | CFLAG_CONFIG | CFLAG_FW_DIAG))) {
9230                                 cmd->cmd_flags |= CFLAG_FINISHED;
9231                                 cv_broadcast(&mpt->m_passthru_cv);
9232                                 cv_broadcast(&mpt->m_config_cv);
9233                                 cv_broadcast(&mpt->m_fw_diag_cv);
9234                         }
9235                         continue;
9236                 }
9237 
9238                 NDBG25(("mptsas_flush_hba discovered non-NULL cmd in slot %d",
9239                     slot));
9240                 mptsas_dump_cmd(mpt, cmd);
9241 
9242                 mptsas_remove_cmd(mpt, cmd);
9243                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
9244                 mptsas_doneq_add(mpt, cmd);
9245         }
9246 
9247         /*
9248          * Flush the waitq.
9249          */
9250         while ((cmd = mptsas_waitq_rm(mpt)) != NULL) {
9251                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
9252                 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
9253                     (cmd->cmd_flags & CFLAG_CONFIG) ||
9254                     (cmd->cmd_flags & CFLAG_FW_DIAG)) {
9255                         cmd->cmd_flags |= CFLAG_FINISHED;
9256                         cv_broadcast(&mpt->m_passthru_cv);
9257                         cv_broadcast(&mpt->m_config_cv);
9258                         cv_broadcast(&mpt->m_fw_diag_cv);
9259                 } else {
9260                         mptsas_doneq_add(mpt, cmd);
9261                 }
9262         }
9263 
9264         /*
9265          * Flush the tx_waitq
9266          */
9267         mutex_enter(&mpt->m_tx_waitq_mutex);
9268         while ((cmd = mptsas_tx_waitq_rm(mpt)) != NULL) {
9269                 mutex_exit(&mpt->m_tx_waitq_mutex);
9270                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
9271                 mptsas_doneq_add(mpt, cmd);
9272                 mutex_enter(&mpt->m_tx_waitq_mutex);
9273         }
9274         mutex_exit(&mpt->m_tx_waitq_mutex);
9275 
9276         /*
9277          * Drain the taskqs prior to reallocating resources. The thread
9278          * passing through here could be launched from either (dr)
9279          * or (event) taskqs so only wait on the 'other' queue since
9280          * waiting on 'this' queue is a deadlock condition.
9281          */
9282         mutex_exit(&mpt->m_mutex);
9283         if (!taskq_member((taskq_t *)mpt->m_event_taskq, curthread))
9284                 ddi_taskq_wait(mpt->m_event_taskq);
9285         if (!taskq_member((taskq_t *)mpt->m_dr_taskq, curthread))
9286                 ddi_taskq_wait(mpt->m_dr_taskq);
9287 
9288         mutex_enter(&mpt->m_mutex);
9289 }
9290 
9291 /*
9292  * set pkt_reason and OR in pkt_statistics flag
9293  */
9294 static void
9295 mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd, uchar_t reason,
9296     uint_t stat)
9297 {
9298 #ifndef __lock_lint
9299         _NOTE(ARGUNUSED(mpt))
9300 #endif
9301 
9302         NDBG25(("mptsas_set_pkt_reason: cmd=0x%p reason=%x stat=%x",
9303             (void *)cmd, reason, stat));
9304 
9305         if (cmd) {
9306                 if (cmd->cmd_pkt->pkt_reason == CMD_CMPLT) {
9307                         cmd->cmd_pkt->pkt_reason = reason;
9308                 }
9309                 cmd->cmd_pkt->pkt_statistics |= stat;
9310         }
9311 }
9312 
9313 static void
9314 mptsas_start_watch_reset_delay()
9315 {
9316         NDBG22(("mptsas_start_watch_reset_delay"));
9317 
9318         mutex_enter(&mptsas_global_mutex);
9319         if (mptsas_reset_watch == NULL && mptsas_timeouts_enabled) {
9320                 mptsas_reset_watch = timeout(mptsas_watch_reset_delay, NULL,
9321                     drv_usectohz((clock_t)
9322                     MPTSAS_WATCH_RESET_DELAY_TICK * 1000));
9323                 ASSERT(mptsas_reset_watch != NULL);
9324         }
9325         mutex_exit(&mptsas_global_mutex);
9326 }
9327 
9328 static void
9329 mptsas_setup_bus_reset_delay(mptsas_t *mpt)
9330 {
9331         mptsas_target_t *ptgt = NULL;
9332 
9333         ASSERT(MUTEX_HELD(&mpt->m_mutex));
9334 
9335         NDBG22(("mptsas_setup_bus_reset_delay"));
9336         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9337             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9338                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9339                 ptgt->m_reset_delay = mpt->m_scsi_reset_delay;
9340         }
9341 
9342         mptsas_start_watch_reset_delay();
9343 }
9344 
9345 /*
9346  * mptsas_watch_reset_delay(_subr) is invoked by timeout() and checks every
9347  * mpt instance for active reset delays
9348  */
9349 static void
9350 mptsas_watch_reset_delay(void *arg)
9351 {
9352 #ifndef __lock_lint
9353         _NOTE(ARGUNUSED(arg))
9354 #endif
9355 
9356         mptsas_t        *mpt;
9357         int             not_done = 0;
9358 
9359         NDBG22(("mptsas_watch_reset_delay"));
9360 
9361         mutex_enter(&mptsas_global_mutex);
9362         mptsas_reset_watch = 0;
9363         mutex_exit(&mptsas_global_mutex);
9364         rw_enter(&mptsas_global_rwlock, RW_READER);
9365         for (mpt = mptsas_head; mpt != NULL; mpt = mpt->m_next) {
9366                 if (mpt->m_tran == 0) {
9367                         continue;
9368                 }
9369                 mutex_enter(&mpt->m_mutex);
9370                 not_done += mptsas_watch_reset_delay_subr(mpt);
9371                 mutex_exit(&mpt->m_mutex);
9372         }
9373         rw_exit(&mptsas_global_rwlock);
9374 
9375         if (not_done) {
9376                 mptsas_start_watch_reset_delay();
9377         }
9378 }
9379 
9380 static int
9381 mptsas_watch_reset_delay_subr(mptsas_t *mpt)
9382 {
9383         int             done = 0;
9384         int             restart = 0;
9385         mptsas_target_t *ptgt = NULL;
9386 
9387         NDBG22(("mptsas_watch_reset_delay_subr: mpt=0x%p", (void *)mpt));
9388 
9389         ASSERT(mutex_owned(&mpt->m_mutex));
9390 
9391         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9392             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9393                 if (ptgt->m_reset_delay != 0) {
9394                         ptgt->m_reset_delay -=
9395                             MPTSAS_WATCH_RESET_DELAY_TICK;
9396                         if (ptgt->m_reset_delay <= 0) {
9397                                 ptgt->m_reset_delay = 0;
9398                                 mptsas_set_throttle(mpt, ptgt,
9399                                     MAX_THROTTLE);
9400                                 restart++;
9401                         } else {
9402                                 done = -1;
9403                         }
9404                 }
9405         }
9406 
9407         if (restart > 0) {
9408                 mptsas_restart_hba(mpt);
9409         }
9410         return (done);
9411 }
9412 
9413 #ifdef MPTSAS_TEST
9414 static void
9415 mptsas_test_reset(mptsas_t *mpt, int target)
9416 {
9417         mptsas_target_t    *ptgt = NULL;
9418 
9419         if (mptsas_rtest == target) {
9420                 if (mptsas_do_scsi_reset(mpt, target) == TRUE) {
9421                         mptsas_rtest = -1;
9422                 }
9423                 if (mptsas_rtest == -1) {
9424                         NDBG22(("mptsas_test_reset success"));
9425                 }
9426         }
9427 }
9428 #endif
9429 
9430 /*
9431  * abort handling:
9432  *
9433  * Notes:
9434  *      - if pkt is not NULL, abort just that command
9435  *      - if pkt is NULL, abort all outstanding commands for target
9436  */
9437 static int
9438 mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
9439 {
9440         mptsas_t                *mpt = ADDR2MPT(ap);
9441         int                     rval;
9442         mptsas_tgt_private_t    *tgt_private;
9443         int                     target, lun;
9444 
9445         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
9446             tran_tgt_private;
9447         ASSERT(tgt_private != NULL);
9448         target = tgt_private->t_private->m_devhdl;
9449         lun = tgt_private->t_lun;
9450 
9451         NDBG23(("mptsas_scsi_abort: target=%d.%d", target, lun));
9452 
9453         mutex_enter(&mpt->m_mutex);
9454         rval = mptsas_do_scsi_abort(mpt, target, lun, pkt);
9455         mutex_exit(&mpt->m_mutex);
9456         return (rval);
9457 }
9458 
9459 static int
9460 mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun, struct scsi_pkt *pkt)
9461 {
9462         mptsas_cmd_t    *sp = NULL;
9463         mptsas_slots_t  *slots = mpt->m_active;
9464         int             rval = FALSE;
9465 
9466         ASSERT(mutex_owned(&mpt->m_mutex));
9467 
9468         /*
9469          * Abort the command pkt on the target/lun in ap.  If pkt is
9470          * NULL, abort all outstanding commands on that target/lun.
9471          * If you can abort them, return 1, else return 0.
9472          * Each packet that's aborted should be sent back to the target
9473          * driver through the callback routine, with pkt_reason set to
9474          * CMD_ABORTED.
9475          *
9476          * abort cmd pkt on HBA hardware; clean out of outstanding
9477          * command lists, etc.
9478          */
9479         if (pkt != NULL) {
9480                 /* abort the specified packet */
9481                 sp = PKT2CMD(pkt);
9482 
9483                 if (sp->cmd_queued) {
9484                         NDBG23(("mptsas_do_scsi_abort: queued sp=0x%p aborted",
9485                             (void *)sp));
9486                         mptsas_waitq_delete(mpt, sp);
9487                         mptsas_set_pkt_reason(mpt, sp, CMD_ABORTED,
9488                             STAT_ABORTED);
9489                         mptsas_doneq_add(mpt, sp);
9490                         rval = TRUE;
9491                         goto done;
9492                 }
9493 
9494                 /*
9495                  * Have mpt firmware abort this command
9496                  */
9497 
9498                 if (slots->m_slot[sp->cmd_slot] != NULL) {
9499                         rval = mptsas_ioc_task_management(mpt,
9500                             MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, target,
9501                             lun, NULL, 0, 0);
9502 
9503                         /*
9504                          * The transport layer expects only TRUE and FALSE.
9505                          * Therefore, if mptsas_ioc_task_management returns
9506                          * FAILED we will return FALSE.
9507                          */
9508                         if (rval == FAILED)
9509                                 rval = FALSE;
9510                         goto done;
9511                 }
9512         }
9513 
9514         /*
9515          * If pkt is NULL then abort task set
9516          */
9517         rval = mptsas_ioc_task_management(mpt,
9518             MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, target, lun, NULL, 0, 0);
9519 
9520         /*
9521          * The transport layer expects only TRUE and FALSE.
9522          * Therefore, if mptsas_ioc_task_management returns
9523          * FAILED we will return FALSE.
9524          */
9525         if (rval == FAILED)
9526                 rval = FALSE;
9527 
9528 #ifdef MPTSAS_TEST
9529         if (rval && mptsas_test_stop) {
9530                 debug_enter("mptsas_do_scsi_abort");
9531         }
9532 #endif
9533 
9534 done:
9535         mptsas_doneq_empty(mpt);
9536         return (rval);
9537 }
9538 
9539 /*
9540  * capability handling:
9541  * (*tran_getcap).  Get the capability named, and return its value.
9542  */
9543 static int
9544 mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly)
9545 {
9546         mptsas_t        *mpt = ADDR2MPT(ap);
9547         int             ckey;
9548         int             rval = FALSE;
9549 
9550         NDBG24(("mptsas_scsi_getcap: target=%d, cap=%s tgtonly=%x",
9551             ap->a_target, cap, tgtonly));
9552 
9553         mutex_enter(&mpt->m_mutex);
9554 
9555         if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9556                 mutex_exit(&mpt->m_mutex);
9557                 return (UNDEFINED);
9558         }
9559 
9560         switch (ckey) {
9561         case SCSI_CAP_DMA_MAX:
9562                 rval = (int)mpt->m_msg_dma_attr.dma_attr_maxxfer;
9563                 break;
9564         case SCSI_CAP_ARQ:
9565                 rval = TRUE;
9566                 break;
9567         case SCSI_CAP_MSG_OUT:
9568         case SCSI_CAP_PARITY:
9569         case SCSI_CAP_UNTAGGED_QING:
9570                 rval = TRUE;
9571                 break;
9572         case SCSI_CAP_TAGGED_QING:
9573                 rval = TRUE;
9574                 break;
9575         case SCSI_CAP_RESET_NOTIFICATION:
9576                 rval = TRUE;
9577                 break;
9578         case SCSI_CAP_LINKED_CMDS:
9579                 rval = FALSE;
9580                 break;
9581         case SCSI_CAP_QFULL_RETRIES:
9582                 rval = ((mptsas_tgt_private_t *)(ap->a_hba_tran->
9583                     tran_tgt_private))->t_private->m_qfull_retries;
9584                 break;
9585         case SCSI_CAP_QFULL_RETRY_INTERVAL:
9586                 rval = drv_hztousec(((mptsas_tgt_private_t *)
9587                     (ap->a_hba_tran->tran_tgt_private))->
9588                     t_private->m_qfull_retry_interval) / 1000;
9589                 break;
9590         case SCSI_CAP_CDB_LEN:
9591                 rval = CDB_GROUP4;
9592                 break;
9593         case SCSI_CAP_INTERCONNECT_TYPE:
9594                 rval = INTERCONNECT_SAS;
9595                 break;
9596         case SCSI_CAP_TRAN_LAYER_RETRIES:
9597                 if (mpt->m_ioc_capabilities &
9598                     MPI2_IOCFACTS_CAPABILITY_TLR)
9599                         rval = TRUE;
9600                 else
9601                         rval = FALSE;
9602                 break;
9603         default:
9604                 rval = UNDEFINED;
9605                 break;
9606         }
9607 
9608         NDBG24(("mptsas_scsi_getcap: %s, rval=%x", cap, rval));
9609 
9610         mutex_exit(&mpt->m_mutex);
9611         return (rval);
9612 }
9613 
9614 /*
9615  * (*tran_setcap).  Set the capability named to the value given.
9616  */
9617 static int
9618 mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value, int tgtonly)
9619 {
9620         mptsas_t        *mpt = ADDR2MPT(ap);
9621         int             ckey;
9622         int             rval = FALSE;
9623 
9624         NDBG24(("mptsas_scsi_setcap: target=%d, cap=%s value=%x tgtonly=%x",
9625             ap->a_target, cap, value, tgtonly));
9626 
9627         if (!tgtonly) {
9628                 return (rval);
9629         }
9630 
9631         mutex_enter(&mpt->m_mutex);
9632 
9633         if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9634                 mutex_exit(&mpt->m_mutex);
9635                 return (UNDEFINED);
9636         }
9637 
9638         switch (ckey) {
9639         case SCSI_CAP_DMA_MAX:
9640         case SCSI_CAP_MSG_OUT:
9641         case SCSI_CAP_PARITY:
9642         case SCSI_CAP_INITIATOR_ID:
9643         case SCSI_CAP_LINKED_CMDS:
9644         case SCSI_CAP_UNTAGGED_QING:
9645         case SCSI_CAP_RESET_NOTIFICATION:
9646                 /*
9647                  * None of these are settable via
9648                  * the capability interface.
9649                  */
9650                 break;
9651         case SCSI_CAP_ARQ:
9652                 /*
9653                  * We cannot turn off arq so return false if asked to
9654                  */
9655                 if (value) {
9656                         rval = TRUE;
9657                 } else {
9658                         rval = FALSE;
9659                 }
9660                 break;
9661         case SCSI_CAP_TAGGED_QING:
9662                 mptsas_set_throttle(mpt, ((mptsas_tgt_private_t *)
9663                     (ap->a_hba_tran->tran_tgt_private))->t_private,
9664                     MAX_THROTTLE);
9665                 rval = TRUE;
9666                 break;
9667         case SCSI_CAP_QFULL_RETRIES:
9668                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9669                     t_private->m_qfull_retries = (uchar_t)value;
9670                 rval = TRUE;
9671                 break;
9672         case SCSI_CAP_QFULL_RETRY_INTERVAL:
9673                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9674                     t_private->m_qfull_retry_interval =
9675                     drv_usectohz(value * 1000);
9676                 rval = TRUE;
9677                 break;
9678         default:
9679                 rval = UNDEFINED;
9680                 break;
9681         }
9682         mutex_exit(&mpt->m_mutex);
9683         return (rval);
9684 }
9685 
9686 /*
9687  * Utility routine for mptsas_ifsetcap/ifgetcap
9688  */
9689 /*ARGSUSED*/
9690 static int
9691 mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp)
9692 {
9693         NDBG24(("mptsas_scsi_capchk: cap=%s", cap));
9694 
9695         if (!cap)
9696                 return (FALSE);
9697 
9698         *cidxp = scsi_hba_lookup_capstr(cap);
9699         return (TRUE);
9700 }
9701 
9702 static int
9703 mptsas_alloc_active_slots(mptsas_t *mpt, int flag)
9704 {
9705         mptsas_slots_t  *old_active = mpt->m_active;
9706         mptsas_slots_t  *new_active;
9707         size_t          size;
9708 
9709         /*
9710          * if there are active commands, then we cannot
9711          * change size of active slots array.
9712          */
9713         ASSERT(mpt->m_ncmds == 0);
9714 
9715         size = MPTSAS_SLOTS_SIZE(mpt);
9716         new_active = kmem_zalloc(size, flag);
9717         if (new_active == NULL) {
9718                 NDBG1(("new active alloc failed"));
9719                 return (-1);
9720         }
9721         /*
9722          * Since SMID 0 is reserved and the TM slot is reserved, the
9723          * number of slots that can be used at any one time is
9724          * m_max_requests - 2.
9725          */
9726         new_active->m_n_normal = (mpt->m_max_requests - 2);
9727         new_active->m_size = size;
9728         new_active->m_rotor = 1;
9729         if (old_active)
9730                 mptsas_free_active_slots(mpt);
9731         mpt->m_active = new_active;
9732 
9733         return (0);
9734 }
9735 
9736 static void
9737 mptsas_free_active_slots(mptsas_t *mpt)
9738 {
9739         mptsas_slots_t  *active = mpt->m_active;
9740         size_t          size;
9741 
9742         if (active == NULL)
9743                 return;
9744         size = active->m_size;
9745         kmem_free(active, size);
9746         mpt->m_active = NULL;
9747 }
9748 
9749 /*
9750  * Error logging, printing, and debug print routines.
9751  */
9752 static char *mptsas_label = "mpt_sas";
9753 
9754 /*PRINTFLIKE3*/
9755 void
9756 mptsas_log(mptsas_t *mpt, int level, char *fmt, ...)
9757 {
9758         dev_info_t      *dev;
9759         va_list         ap;
9760 
9761         if (mpt) {
9762                 dev = mpt->m_dip;
9763         } else {
9764                 dev = 0;
9765         }
9766 
9767         mutex_enter(&mptsas_log_mutex);
9768 
9769         va_start(ap, fmt);
9770         (void) vsprintf(mptsas_log_buf, fmt, ap);
9771         va_end(ap);
9772 
9773         if (level == CE_CONT) {
9774                 scsi_log(dev, mptsas_label, level, "%s\n", mptsas_log_buf);
9775         } else {
9776                 scsi_log(dev, mptsas_label, level, "%s", mptsas_log_buf);
9777         }
9778 
9779         mutex_exit(&mptsas_log_mutex);
9780 }
9781 
9782 #ifdef MPTSAS_DEBUG
9783 /*
9784  * Use a circular buffer to log messages to private memory.
9785  * Increment idx atomically to minimize risk to miss lines.
9786  * It's fast and does not hold up the proceedings too much.
9787  */
9788 static const size_t mptsas_dbglog_linecnt = MPTSAS_DBGLOG_LINECNT;
9789 static const size_t mptsas_dbglog_linelen = MPTSAS_DBGLOG_LINELEN;
9790 static char mptsas_dbglog_bufs[MPTSAS_DBGLOG_LINECNT][MPTSAS_DBGLOG_LINELEN];
9791 static uint32_t mptsas_dbglog_idx = 0;
9792 
9793 /*PRINTFLIKE1*/
9794 void
9795 mptsas_debug_log(char *fmt, ...)
9796 {
9797         va_list         ap;
9798         uint32_t        idx;
9799 
9800         idx = atomic_inc_32_nv(&mptsas_dbglog_idx) &
9801             (mptsas_dbglog_linecnt - 1);
9802 
9803         va_start(ap, fmt);
9804         (void) vsnprintf(mptsas_dbglog_bufs[idx],
9805             mptsas_dbglog_linelen, fmt, ap);
9806         va_end(ap);
9807 }
9808 
9809 /*PRINTFLIKE1*/
9810 void
9811 mptsas_printf(char *fmt, ...)
9812 {
9813         dev_info_t      *dev = 0;
9814         va_list         ap;
9815 
9816         mutex_enter(&mptsas_log_mutex);
9817 
9818         va_start(ap, fmt);
9819         (void) vsprintf(mptsas_log_buf, fmt, ap);
9820         va_end(ap);
9821 
9822 #ifdef PROM_PRINTF
9823         prom_printf("%s:\t%s\n", mptsas_label, mptsas_log_buf);
9824 #else
9825         scsi_log(dev, mptsas_label, CE_CONT, "!%s\n", mptsas_log_buf);
9826 #endif
9827         mutex_exit(&mptsas_log_mutex);
9828 }
9829 #endif
9830 
9831 /*
9832  * timeout handling
9833  */
9834 static void
9835 mptsas_watch(void *arg)
9836 {
9837 #ifndef __lock_lint
9838         _NOTE(ARGUNUSED(arg))
9839 #endif
9840 
9841         mptsas_t        *mpt;
9842         uint32_t        doorbell;
9843 
9844         NDBG30(("mptsas_watch"));
9845 
9846         rw_enter(&mptsas_global_rwlock, RW_READER);
9847         for (mpt = mptsas_head; mpt != (mptsas_t *)NULL; mpt = mpt->m_next) {
9848 
9849                 mutex_enter(&mpt->m_mutex);
9850 
9851                 /* Skip device if not powered on */
9852                 if (mpt->m_options & MPTSAS_OPT_PM) {
9853                         if (mpt->m_power_level == PM_LEVEL_D0) {
9854                                 (void) pm_busy_component(mpt->m_dip, 0);
9855                                 mpt->m_busy = 1;
9856                         } else {
9857                                 mutex_exit(&mpt->m_mutex);
9858                                 continue;
9859                         }
9860                 }
9861 
9862                 /*
9863                  * Check if controller is in a FAULT state. If so, reset it.
9864                  */
9865                 doorbell = ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell);
9866                 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
9867                         doorbell &= MPI2_DOORBELL_DATA_MASK;
9868                         mptsas_log(mpt, CE_WARN, "MPT Firmware Fault, "
9869                             "code: %04x", doorbell);
9870                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
9871                         if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
9872                                 mptsas_log(mpt, CE_WARN, "Reset failed"
9873                                     "after fault was detected");
9874                         }
9875                 }
9876 
9877                 /*
9878                  * For now, always call mptsas_watchsubr.
9879                  */
9880                 mptsas_watchsubr(mpt);
9881 
9882                 if (mpt->m_options & MPTSAS_OPT_PM) {
9883                         mpt->m_busy = 0;
9884                         (void) pm_idle_component(mpt->m_dip, 0);
9885                 }
9886 
9887                 mutex_exit(&mpt->m_mutex);
9888         }
9889         rw_exit(&mptsas_global_rwlock);
9890 
9891         mutex_enter(&mptsas_global_mutex);
9892         if (mptsas_timeouts_enabled)
9893                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
9894         mutex_exit(&mptsas_global_mutex);
9895 }
9896 
9897 static void
9898 mptsas_watchsubr_tgt(mptsas_t *mpt, mptsas_target_t *ptgt, hrtime_t timestamp)
9899 {
9900         mptsas_cmd_t    *cmd;
9901 
9902         /*
9903          * If we were draining due to a qfull condition,
9904          * go back to full throttle.
9905          */
9906         if ((ptgt->m_t_throttle < MAX_THROTTLE) &&
9907             (ptgt->m_t_throttle > HOLD_THROTTLE) &&
9908             (ptgt->m_t_ncmds < ptgt->m_t_throttle)) {
9909                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9910                 mptsas_restart_hba(mpt);
9911         }
9912 
9913         cmd = TAILQ_LAST(&ptgt->m_active_cmdq, mptsas_active_cmdq);
9914         if (cmd == NULL)
9915                 return;
9916 
9917         if (cmd->cmd_active_expiration <= timestamp) {
9918                 /*
9919                  * Earliest command timeout expired. Drain throttle.
9920                  */
9921                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
9922 
9923                 /*
9924                  * Check for remaining commands.
9925                  */
9926                 cmd = TAILQ_FIRST(&ptgt->m_active_cmdq);
9927                 if (cmd->cmd_active_expiration > timestamp) {
9928                         /*
9929                          * Wait for remaining commands to complete or
9930                          * time out.
9931                          */
9932                         NDBG23(("command timed out, pending drain"));
9933                         return;
9934                 }
9935 
9936                 /*
9937                  * All command timeouts expired.
9938                  */
9939                 mptsas_log(mpt, CE_NOTE, "Timeout of %d seconds "
9940                     "expired with %d commands on target %d lun %d.",
9941                     cmd->cmd_pkt->pkt_time, ptgt->m_t_ncmds,
9942                     ptgt->m_devhdl, Lun(cmd));
9943 
9944                 mptsas_cmd_timeout(mpt, ptgt);
9945         } else if (cmd->cmd_active_expiration <=
9946             timestamp + (hrtime_t)mptsas_scsi_watchdog_tick * NANOSEC) {
9947                 NDBG23(("pending timeout"));
9948                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
9949         }
9950 }
9951 
9952 static void
9953 mptsas_watchsubr(mptsas_t *mpt)
9954 {
9955         int             i;
9956         mptsas_cmd_t    *cmd;
9957         mptsas_target_t *ptgt = NULL;
9958         hrtime_t        timestamp = gethrtime();
9959 
9960         ASSERT(MUTEX_HELD(&mpt->m_mutex));
9961 
9962         NDBG30(("mptsas_watchsubr: mpt=0x%p", (void *)mpt));
9963 
9964 #ifdef MPTSAS_TEST
9965         if (mptsas_enable_untagged) {
9966                 mptsas_test_untagged++;
9967         }
9968 #endif
9969 
9970         /*
9971          * Check for commands stuck in active slot
9972          * Account for TM requests, which use the last SMID.
9973          */
9974         for (i = 0; i <= mpt->m_active->m_n_normal; i++) {
9975                 if ((cmd = mpt->m_active->m_slot[i]) != NULL) {
9976                         if (cmd->cmd_active_expiration <= timestamp) {
9977                                 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
9978                                         /*
9979                                          * There seems to be a command stuck
9980                                          * in the active slot.  Drain throttle.
9981                                          */
9982                                         mptsas_set_throttle(mpt,
9983                                             cmd->cmd_tgt_addr,
9984                                             DRAIN_THROTTLE);
9985                                 } else if (cmd->cmd_flags &
9986                                     (CFLAG_PASSTHRU | CFLAG_CONFIG |
9987                                     CFLAG_FW_DIAG)) {
9988                                         /*
9989                                          * passthrough command timeout
9990                                          */
9991                                         cmd->cmd_flags |= (CFLAG_FINISHED |
9992                                             CFLAG_TIMEOUT);
9993                                         cv_broadcast(&mpt->m_passthru_cv);
9994                                         cv_broadcast(&mpt->m_config_cv);
9995                                         cv_broadcast(&mpt->m_fw_diag_cv);
9996                                 }
9997                         }
9998                 }
9999         }
10000 
10001         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
10002             ptgt = refhash_next(mpt->m_targets, ptgt)) {
10003                 mptsas_watchsubr_tgt(mpt, ptgt, timestamp);
10004         }
10005 
10006         for (ptgt = refhash_first(mpt->m_tmp_targets); ptgt != NULL;
10007             ptgt = refhash_next(mpt->m_tmp_targets, ptgt)) {
10008                 mptsas_watchsubr_tgt(mpt, ptgt, timestamp);
10009         }
10010 }
10011 
10012 /*
10013  * timeout recovery
10014  */
10015 static void
10016 mptsas_cmd_timeout(mptsas_t *mpt, mptsas_target_t *ptgt)
10017 {
10018         uint16_t        devhdl;
10019         uint64_t        sas_wwn;
10020         uint8_t         phy;
10021         char            wwn_str[MPTSAS_WWN_STRLEN];
10022 
10023         devhdl = ptgt->m_devhdl;
10024         sas_wwn = ptgt->m_addr.mta_wwn;
10025         phy = ptgt->m_phynum;
10026         if (sas_wwn == 0) {
10027                 (void) sprintf(wwn_str, "p%x", phy);
10028         } else {
10029                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
10030         }
10031 
10032         NDBG29(("mptsas_cmd_timeout: target=%d", devhdl));
10033         mptsas_log(mpt, CE_WARN, "Disconnected command timeout for "
10034             "target %d %s, enclosure %u", devhdl, wwn_str,
10035             ptgt->m_enclosure);
10036 
10037         /*
10038          * Abort all outstanding commands on the device.
10039          */
10040         NDBG29(("mptsas_cmd_timeout: device reset"));
10041         if (mptsas_do_scsi_reset(mpt, devhdl) != TRUE) {
10042                 mptsas_log(mpt, CE_WARN, "Target %d reset for command timeout "
10043                     "recovery failed!", devhdl);
10044         }
10045 }
10046 
10047 /*
10048  * Device / Hotplug control
10049  */
10050 static int
10051 mptsas_scsi_quiesce(dev_info_t *dip)
10052 {
10053         mptsas_t        *mpt;
10054         scsi_hba_tran_t *tran;
10055 
10056         tran = ddi_get_driver_private(dip);
10057         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
10058                 return (-1);
10059 
10060         return (mptsas_quiesce_bus(mpt));
10061 }
10062 
10063 static int
10064 mptsas_scsi_unquiesce(dev_info_t *dip)
10065 {
10066         mptsas_t                *mpt;
10067         scsi_hba_tran_t *tran;
10068 
10069         tran = ddi_get_driver_private(dip);
10070         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
10071                 return (-1);
10072 
10073         return (mptsas_unquiesce_bus(mpt));
10074 }
10075 
10076 static int
10077 mptsas_quiesce_bus(mptsas_t *mpt)
10078 {
10079         mptsas_target_t *ptgt = NULL;
10080 
10081         NDBG28(("mptsas_quiesce_bus"));
10082         mutex_enter(&mpt->m_mutex);
10083 
10084         /* Set all the throttles to zero */
10085         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
10086             ptgt = refhash_next(mpt->m_targets, ptgt)) {
10087                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
10088         }
10089 
10090         /* If there are any outstanding commands in the queue */
10091         if (mpt->m_ncmds) {
10092                 mpt->m_softstate |= MPTSAS_SS_DRAINING;
10093                 mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
10094                     mpt, (MPTSAS_QUIESCE_TIMEOUT * drv_usectohz(1000000)));
10095                 if (cv_wait_sig(&mpt->m_cv, &mpt->m_mutex) == 0) {
10096                         /*
10097                          * Quiesce has been interrupted
10098                          */
10099                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
10100                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
10101                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
10102                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
10103                         }
10104                         mptsas_restart_hba(mpt);
10105                         if (mpt->m_quiesce_timeid != 0) {
10106                                 timeout_id_t tid = mpt->m_quiesce_timeid;
10107                                 mpt->m_quiesce_timeid = 0;
10108                                 mutex_exit(&mpt->m_mutex);
10109                                 (void) untimeout(tid);
10110                                 return (-1);
10111                         }
10112                         mutex_exit(&mpt->m_mutex);
10113                         return (-1);
10114                 } else {
10115                         /* Bus has been quiesced */
10116                         ASSERT(mpt->m_quiesce_timeid == 0);
10117                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
10118                         mpt->m_softstate |= MPTSAS_SS_QUIESCED;
10119                         mutex_exit(&mpt->m_mutex);
10120                         return (0);
10121                 }
10122         }
10123         /* Bus was not busy - QUIESCED */
10124         mutex_exit(&mpt->m_mutex);
10125 
10126         return (0);
10127 }
10128 
10129 static int
10130 mptsas_unquiesce_bus(mptsas_t *mpt)
10131 {
10132         mptsas_target_t *ptgt = NULL;
10133 
10134         NDBG28(("mptsas_unquiesce_bus"));
10135         mutex_enter(&mpt->m_mutex);
10136         mpt->m_softstate &= ~MPTSAS_SS_QUIESCED;
10137         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
10138             ptgt = refhash_next(mpt->m_targets, ptgt)) {
10139                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
10140         }
10141         mptsas_restart_hba(mpt);
10142         mutex_exit(&mpt->m_mutex);
10143         return (0);
10144 }
10145 
10146 static void
10147 mptsas_ncmds_checkdrain(void *arg)
10148 {
10149         mptsas_t        *mpt = arg;
10150         mptsas_target_t *ptgt = NULL;
10151 
10152         mutex_enter(&mpt->m_mutex);
10153         if (mpt->m_softstate & MPTSAS_SS_DRAINING) {
10154                 mpt->m_quiesce_timeid = 0;
10155                 if (mpt->m_ncmds == 0) {
10156                         /* Command queue has been drained */
10157                         cv_signal(&mpt->m_cv);
10158                 } else {
10159                         /*
10160                          * The throttle may have been reset because
10161                          * of a SCSI bus reset
10162                          */
10163                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
10164                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
10165                                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
10166                         }
10167 
10168                         mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
10169                             mpt, (MPTSAS_QUIESCE_TIMEOUT *
10170                             drv_usectohz(1000000)));
10171                 }
10172         }
10173         mutex_exit(&mpt->m_mutex);
10174 }
10175 
10176 /*ARGSUSED*/
10177 static void
10178 mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
10179 {
10180         int     i;
10181         uint8_t *cp = (uchar_t *)cmd->cmd_pkt->pkt_cdbp;
10182         char    buf[128];
10183 
10184         buf[0] = '\0';
10185         NDBG25(("?Cmd (0x%p) dump for Target %d Lun %d:\n", (void *)cmd,
10186             Tgt(cmd), Lun(cmd)));
10187         (void) sprintf(&buf[0], "\tcdb=[");
10188         for (i = 0; i < (int)cmd->cmd_cdblen; i++) {
10189                 (void) sprintf(&buf[strlen(buf)], " 0x%x", *cp++);
10190         }
10191         (void) sprintf(&buf[strlen(buf)], " ]");
10192         NDBG25(("?%s\n", buf));
10193         NDBG25(("?pkt_flags=0x%x pkt_statistics=0x%x pkt_state=0x%x\n",
10194             cmd->cmd_pkt->pkt_flags, cmd->cmd_pkt->pkt_statistics,
10195             cmd->cmd_pkt->pkt_state));
10196         NDBG25(("?pkt_scbp=0x%x cmd_flags=0x%x\n", cmd->cmd_pkt->pkt_scbp ?
10197             *(cmd->cmd_pkt->pkt_scbp) : 0, cmd->cmd_flags));
10198 }
10199 
10200 static void
10201 mptsas_passthru_sge(ddi_acc_handle_t acc_hdl, mptsas_pt_request_t *pt,
10202     pMpi2SGESimple64_t sgep)
10203 {
10204         uint32_t                sge_flags;
10205         uint32_t                data_size, dataout_size;
10206         ddi_dma_cookie_t        data_cookie;
10207         ddi_dma_cookie_t        dataout_cookie;
10208 
10209         data_size = pt->data_size;
10210         dataout_size = pt->dataout_size;
10211         data_cookie = pt->data_cookie;
10212         dataout_cookie = pt->dataout_cookie;
10213 
10214         if (dataout_size) {
10215                 sge_flags = dataout_size |
10216                     ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
10217                     MPI2_SGE_FLAGS_END_OF_BUFFER |
10218                     MPI2_SGE_FLAGS_HOST_TO_IOC |
10219                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
10220                     MPI2_SGE_FLAGS_SHIFT);
10221                 ddi_put32(acc_hdl, &sgep->FlagsLength, sge_flags);
10222                 ddi_put32(acc_hdl, &sgep->Address.Low,
10223                     (uint32_t)(dataout_cookie.dmac_laddress &
10224                     0xffffffffull));
10225                 ddi_put32(acc_hdl, &sgep->Address.High,
10226                     (uint32_t)(dataout_cookie.dmac_laddress
10227                     >> 32));
10228                 sgep++;
10229         }
10230         sge_flags = data_size;
10231         sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
10232             MPI2_SGE_FLAGS_LAST_ELEMENT |
10233             MPI2_SGE_FLAGS_END_OF_BUFFER |
10234             MPI2_SGE_FLAGS_END_OF_LIST |
10235             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
10236             MPI2_SGE_FLAGS_SHIFT);
10237         if (pt->direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10238                 sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_HOST_TO_IOC) <<
10239                     MPI2_SGE_FLAGS_SHIFT);
10240         } else {
10241                 sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_IOC_TO_HOST) <<
10242                     MPI2_SGE_FLAGS_SHIFT);
10243         }
10244         ddi_put32(acc_hdl, &sgep->FlagsLength,
10245             sge_flags);
10246         ddi_put32(acc_hdl, &sgep->Address.Low,
10247             (uint32_t)(data_cookie.dmac_laddress &
10248             0xffffffffull));
10249         ddi_put32(acc_hdl, &sgep->Address.High,
10250             (uint32_t)(data_cookie.dmac_laddress >> 32));
10251 }
10252 
10253 static void
10254 mptsas_passthru_ieee_sge(ddi_acc_handle_t acc_hdl, mptsas_pt_request_t *pt,
10255     pMpi2IeeeSgeSimple64_t ieeesgep)
10256 {
10257         uint8_t                 sge_flags;
10258         uint32_t                data_size, dataout_size;
10259         ddi_dma_cookie_t        data_cookie;
10260         ddi_dma_cookie_t        dataout_cookie;
10261 
10262         data_size = pt->data_size;
10263         dataout_size = pt->dataout_size;
10264         data_cookie = pt->data_cookie;
10265         dataout_cookie = pt->dataout_cookie;
10266 
10267         sge_flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
10268             MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
10269         if (dataout_size) {
10270                 ddi_put32(acc_hdl, &ieeesgep->Length, dataout_size);
10271                 ddi_put32(acc_hdl, &ieeesgep->Address.Low,
10272                     (uint32_t)(dataout_cookie.dmac_laddress &
10273                     0xffffffffull));
10274                 ddi_put32(acc_hdl, &ieeesgep->Address.High,
10275                     (uint32_t)(dataout_cookie.dmac_laddress >> 32));
10276                 ddi_put8(acc_hdl, &ieeesgep->Flags, sge_flags);
10277                 ieeesgep++;
10278         }
10279         sge_flags |= MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
10280         ddi_put32(acc_hdl, &ieeesgep->Length, data_size);
10281         ddi_put32(acc_hdl, &ieeesgep->Address.Low,
10282             (uint32_t)(data_cookie.dmac_laddress & 0xffffffffull));
10283         ddi_put32(acc_hdl, &ieeesgep->Address.High,
10284             (uint32_t)(data_cookie.dmac_laddress >> 32));
10285         ddi_put8(acc_hdl, &ieeesgep->Flags, sge_flags);
10286 }
10287 
10288 static void
10289 mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd)
10290 {
10291         caddr_t                 memp;
10292         pMPI2RequestHeader_t    request_hdrp;
10293         struct scsi_pkt         *pkt = cmd->cmd_pkt;
10294         mptsas_pt_request_t     *pt = pkt->pkt_ha_private;
10295         uint32_t                request_size;
10296         uint32_t                i;
10297         uint64_t                request_desc = 0;
10298         uint8_t                 desc_type;
10299         uint16_t                SMID;
10300         uint8_t                 *request, function;
10301         ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
10302         ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
10303 
10304         desc_type = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
10305 
10306         request = pt->request;
10307         request_size = pt->request_size;
10308 
10309         SMID = cmd->cmd_slot;
10310 
10311         /*
10312          * Store the passthrough message in memory location
10313          * corresponding to our slot number
10314          */
10315         memp = mpt->m_req_frame + (mpt->m_req_frame_size * SMID);
10316         request_hdrp = (pMPI2RequestHeader_t)memp;
10317         bzero(memp, mpt->m_req_frame_size);
10318 
10319         for (i = 0; i < request_size; i++) {
10320                 bcopy(request + i, memp + i, 1);
10321         }
10322 
10323         NDBG15(("mptsas_start_passthru: Func 0x%x, MsgFlags 0x%x, "
10324             "size=%d, in %d, out %d, SMID %d", request_hdrp->Function,
10325             request_hdrp->MsgFlags, request_size,
10326             pt->data_size, pt->dataout_size, SMID));
10327 
10328         /*
10329          * Add an SGE, even if the length is zero.
10330          */
10331         if (mpt->m_MPI25 && pt->simple == 0) {
10332                 mptsas_passthru_ieee_sge(acc_hdl, pt,
10333                     (pMpi2IeeeSgeSimple64_t)
10334                     ((uint8_t *)request_hdrp + pt->sgl_offset));
10335         } else {
10336                 mptsas_passthru_sge(acc_hdl, pt,
10337                     (pMpi2SGESimple64_t)
10338                     ((uint8_t *)request_hdrp + pt->sgl_offset));
10339         }
10340 
10341         function = request_hdrp->Function;
10342         if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
10343             (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
10344                 pMpi2SCSIIORequest_t    scsi_io_req;
10345                 caddr_t                 arsbuf;
10346                 uint8_t                 ars_size;
10347                 uint32_t                ars_dmaaddrlow;
10348 
10349                 NDBG15(("mptsas_start_passthru: Is SCSI IO Req"));
10350                 scsi_io_req = (pMpi2SCSIIORequest_t)request_hdrp;
10351 
10352                 if (cmd->cmd_extrqslen != 0) {
10353                         /*
10354                          * Mapping of the buffer was done in
10355                          * mptsas_do_passthru().
10356                          * Calculate the DMA address with the same offset.
10357                          */
10358                         arsbuf = cmd->cmd_arq_buf;
10359                         ars_size = cmd->cmd_extrqslen;
10360                         ars_dmaaddrlow = (mpt->m_req_sense_dma_addr +
10361                             ((uintptr_t)arsbuf - (uintptr_t)mpt->m_req_sense)) &
10362                             0xffffffffu;
10363                 } else {
10364                         arsbuf = mpt->m_req_sense +
10365                             (mpt->m_req_sense_size * (SMID-1));
10366                         cmd->cmd_arq_buf = arsbuf;
10367                         ars_size = mpt->m_req_sense_size;
10368                         ars_dmaaddrlow = (mpt->m_req_sense_dma_addr +
10369                             (mpt->m_req_sense_size * (SMID-1))) &
10370                             0xffffffffu;
10371                 }
10372                 bzero(arsbuf, ars_size);
10373 
10374                 ddi_put8(acc_hdl, &scsi_io_req->SenseBufferLength, ars_size);
10375                 ddi_put32(acc_hdl, &scsi_io_req->SenseBufferLowAddress,
10376                     ars_dmaaddrlow);
10377 
10378                 /*
10379                  * Put SGE for data and data_out buffer at the end of
10380                  * scsi_io_request message header.(64 bytes in total)
10381                  * Set SGLOffset0 value
10382                  */
10383                 ddi_put8(acc_hdl, &scsi_io_req->SGLOffset0,
10384                     offsetof(MPI2_SCSI_IO_REQUEST, SGL) / 4);
10385 
10386                 /*
10387                  * Setup descriptor info.  RAID passthrough must use the
10388                  * default request descriptor which is already set, so if this
10389                  * is a SCSI IO request, change the descriptor to SCSI IO.
10390                  */
10391                 if (function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
10392                         desc_type = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
10393                         request_desc = ((uint64_t)ddi_get16(acc_hdl,
10394                             &scsi_io_req->DevHandle) << 48);
10395                 }
10396                 (void) ddi_dma_sync(mpt->m_dma_req_sense_hdl, 0, 0,
10397                     DDI_DMA_SYNC_FORDEV);
10398         }
10399 
10400         /*
10401          * We must wait till the message has been completed before
10402          * beginning the next message so we wait for this one to
10403          * finish.
10404          */
10405         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
10406         request_desc |= (SMID << 16) + desc_type;
10407         cmd->cmd_rfm = NULL;
10408         MPTSAS_START_CMD(mpt, request_desc);
10409         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
10410             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
10411                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
10412         }
10413 }
10414 
10415 typedef void (mptsas_pre_f)(mptsas_t *, mptsas_pt_request_t *);
10416 static mptsas_pre_f     mpi_pre_ioc_facts;
10417 static mptsas_pre_f     mpi_pre_port_facts;
10418 static mptsas_pre_f     mpi_pre_fw_download;
10419 static mptsas_pre_f     mpi_pre_fw_25_download;
10420 static mptsas_pre_f     mpi_pre_fw_upload;
10421 static mptsas_pre_f     mpi_pre_fw_25_upload;
10422 static mptsas_pre_f     mpi_pre_sata_passthrough;
10423 static mptsas_pre_f     mpi_pre_smp_passthrough;
10424 static mptsas_pre_f     mpi_pre_config;
10425 static mptsas_pre_f     mpi_pre_sas_io_unit_control;
10426 static mptsas_pre_f     mpi_pre_scsi_io_req;
10427 
10428 /*
10429  * Prepare the pt for a SAS2 FW_DOWNLOAD request.
10430  */
10431 static void
10432 mpi_pre_fw_download(mptsas_t *mpt, mptsas_pt_request_t *pt)
10433 {
10434         pMpi2FWDownloadTCSGE_t tcsge;
10435         pMpi2FWDownloadRequest req;
10436 
10437         /*
10438          * If SAS3, call separate function.
10439          */
10440         if (mpt->m_MPI25) {
10441                 mpi_pre_fw_25_download(mpt, pt);
10442                 return;
10443         }
10444 
10445         /*
10446          * User requests should come in with the Transaction
10447          * context element where the SGL will go. Putting the
10448          * SGL after that seems to work, but don't really know
10449          * why. Other drivers tend to create an extra SGL and
10450          * refer to the TCE through that.
10451          */
10452         req = (pMpi2FWDownloadRequest)pt->request;
10453         tcsge = (pMpi2FWDownloadTCSGE_t)&req->SGL;
10454         if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
10455             tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
10456                 mptsas_log(mpt, CE_WARN, "FW Download tce invalid!");
10457         }
10458 
10459         pt->sgl_offset = offsetof(MPI2_FW_DOWNLOAD_REQUEST, SGL) +
10460             sizeof (*tcsge);
10461         if (pt->request_size != pt->sgl_offset)
10462                 NDBG15(("mpi_pre_fw_download(): Incorrect req size, "
10463                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10464                     (int)pt->request_size, (int)pt->sgl_offset,
10465                     (int)pt->dataout_size));
10466         if (pt->data_size < sizeof (MPI2_FW_DOWNLOAD_REPLY))
10467                 NDBG15(("mpi_pre_fw_download(): Incorrect rep size, "
10468                     "0x%x, should be 0x%x", pt->data_size,
10469                     (int)sizeof (MPI2_FW_DOWNLOAD_REPLY)));
10470 }
10471 
10472 /*
10473  * Prepare the pt for a SAS3 FW_DOWNLOAD request.
10474  */
10475 static void
10476 mpi_pre_fw_25_download(mptsas_t *mpt, mptsas_pt_request_t *pt)
10477 {
10478         pMpi2FWDownloadTCSGE_t tcsge;
10479         pMpi2FWDownloadRequest req2;
10480         pMpi25FWDownloadRequest req25;
10481 
10482         /*
10483          * User requests should come in with the Transaction
10484          * context element where the SGL will go. The new firmware
10485          * Doesn't use TCE and has space in the main request for
10486          * this information. So move to the right place.
10487          */
10488         req2 = (pMpi2FWDownloadRequest)pt->request;
10489         req25 = (pMpi25FWDownloadRequest)pt->request;
10490         tcsge = (pMpi2FWDownloadTCSGE_t)&req2->SGL;
10491         if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
10492             tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
10493                 mptsas_log(mpt, CE_WARN, "FW Download tce invalid!");
10494         }
10495         req25->ImageOffset = tcsge->ImageOffset;
10496         req25->ImageSize = tcsge->ImageSize;
10497 
10498         pt->sgl_offset = offsetof(MPI25_FW_DOWNLOAD_REQUEST, SGL);
10499         if (pt->request_size != pt->sgl_offset)
10500                 NDBG15(("mpi_pre_fw_25_download(): Incorrect req size, "
10501                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10502                     pt->request_size, pt->sgl_offset,
10503                     pt->dataout_size));
10504         if (pt->data_size < sizeof (MPI2_FW_DOWNLOAD_REPLY))
10505                 NDBG15(("mpi_pre_fw_25_download(): Incorrect rep size, "
10506                     "0x%x, should be 0x%x", pt->data_size,
10507                     (int)sizeof (MPI2_FW_UPLOAD_REPLY)));
10508 }
10509 
10510 /*
10511  * Prepare the pt for a SAS2 FW_UPLOAD request.
10512  */
10513 static void
10514 mpi_pre_fw_upload(mptsas_t *mpt, mptsas_pt_request_t *pt)
10515 {
10516         pMpi2FWUploadTCSGE_t tcsge;
10517         pMpi2FWUploadRequest_t req;
10518 
10519         /*
10520          * If SAS3, call separate function.
10521          */
10522         if (mpt->m_MPI25) {
10523                 mpi_pre_fw_25_upload(mpt, pt);
10524                 return;
10525         }
10526 
10527         /*
10528          * User requests should come in with the Transaction
10529          * context element where the SGL will go. Putting the
10530          * SGL after that seems to work, but don't really know
10531          * why. Other drivers tend to create an extra SGL and
10532          * refer to the TCE through that.
10533          */
10534         req = (pMpi2FWUploadRequest_t)pt->request;
10535         tcsge = (pMpi2FWUploadTCSGE_t)&req->SGL;
10536         if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
10537             tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
10538                 mptsas_log(mpt, CE_WARN, "FW Upload tce invalid!");
10539         }
10540 
10541         pt->sgl_offset = offsetof(MPI2_FW_UPLOAD_REQUEST, SGL) +
10542             sizeof (*tcsge);
10543         if (pt->request_size != pt->sgl_offset)
10544                 NDBG15(("mpi_pre_fw_upload(): Incorrect req size, "
10545                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10546                     pt->request_size, pt->sgl_offset,
10547                     pt->dataout_size));
10548         if (pt->data_size < sizeof (MPI2_FW_UPLOAD_REPLY))
10549                 NDBG15(("mpi_pre_fw_upload(): Incorrect rep size, "
10550                     "0x%x, should be 0x%x", pt->data_size,
10551                     (int)sizeof (MPI2_FW_UPLOAD_REPLY)));
10552 }
10553 
10554 /*
10555  * Prepare the pt a SAS3 FW_UPLOAD request.
10556  */
10557 static void
10558 mpi_pre_fw_25_upload(mptsas_t *mpt, mptsas_pt_request_t *pt)
10559 {
10560         pMpi2FWUploadTCSGE_t tcsge;
10561         pMpi2FWUploadRequest_t req2;
10562         pMpi25FWUploadRequest_t req25;
10563 
10564         /*
10565          * User requests should come in with the Transaction
10566          * context element where the SGL will go. The new firmware
10567          * Doesn't use TCE and has space in the main request for
10568          * this information. So move to the right place.
10569          */
10570         req2 = (pMpi2FWUploadRequest_t)pt->request;
10571         req25 = (pMpi25FWUploadRequest_t)pt->request;
10572         tcsge = (pMpi2FWUploadTCSGE_t)&req2->SGL;
10573         if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
10574             tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
10575                 mptsas_log(mpt, CE_WARN, "FW Upload tce invalid!");
10576         }
10577         req25->ImageOffset = tcsge->ImageOffset;
10578         req25->ImageSize = tcsge->ImageSize;
10579 
10580         pt->sgl_offset = offsetof(MPI25_FW_UPLOAD_REQUEST, SGL);
10581         if (pt->request_size != pt->sgl_offset)
10582                 NDBG15(("mpi_pre_fw_25_upload(): Incorrect req size, "
10583                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10584                     pt->request_size, pt->sgl_offset,
10585                     pt->dataout_size));
10586         if (pt->data_size < sizeof (MPI2_FW_UPLOAD_REPLY))
10587                 NDBG15(("mpi_pre_fw_25_upload(): Incorrect rep size, "
10588                     "0x%x, should be 0x%x", pt->data_size,
10589                     (int)sizeof (MPI2_FW_UPLOAD_REPLY)));
10590 }
10591 
10592 /*
10593  * Prepare the pt for an IOC_FACTS request.
10594  */
10595 static void
10596 mpi_pre_ioc_facts(mptsas_t *mpt, mptsas_pt_request_t *pt)
10597 {
10598 #ifndef __lock_lint
10599         _NOTE(ARGUNUSED(mpt))
10600 #endif
10601         if (pt->request_size != sizeof (MPI2_IOC_FACTS_REQUEST))
10602                 NDBG15(("mpi_pre_ioc_facts(): Incorrect req size, "
10603                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10604                     pt->request_size,
10605                     (int)sizeof (MPI2_IOC_FACTS_REQUEST),
10606                     pt->dataout_size));
10607         if (pt->data_size != sizeof (MPI2_IOC_FACTS_REPLY))
10608                 NDBG15(("mpi_pre_ioc_facts(): Incorrect rep size, "
10609                     "0x%x, should be 0x%x", pt->data_size,
10610                     (int)sizeof (MPI2_IOC_FACTS_REPLY)));
10611         pt->sgl_offset = (uint16_t)pt->request_size;
10612 }
10613 
10614 /*
10615  * Prepare the pt for a PORT_FACTS request.
10616  */
10617 static void
10618 mpi_pre_port_facts(mptsas_t *mpt, mptsas_pt_request_t *pt)
10619 {
10620 #ifndef __lock_lint
10621         _NOTE(ARGUNUSED(mpt))
10622 #endif
10623         if (pt->request_size != sizeof (MPI2_PORT_FACTS_REQUEST))
10624                 NDBG15(("mpi_pre_port_facts(): Incorrect req size, "
10625                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10626                     pt->request_size,
10627                     (int)sizeof (MPI2_PORT_FACTS_REQUEST),
10628                     pt->dataout_size));
10629         if (pt->data_size != sizeof (MPI2_PORT_FACTS_REPLY))
10630                 NDBG15(("mpi_pre_port_facts(): Incorrect rep size, "
10631                     "0x%x, should be 0x%x", pt->data_size,
10632                     (int)sizeof (MPI2_PORT_FACTS_REPLY)));
10633         pt->sgl_offset = (uint16_t)pt->request_size;
10634 }
10635 
10636 /*
10637  * Prepare pt for a SATA_PASSTHROUGH request.
10638  */
10639 static void
10640 mpi_pre_sata_passthrough(mptsas_t *mpt, mptsas_pt_request_t *pt)
10641 {
10642 #ifndef __lock_lint
10643         _NOTE(ARGUNUSED(mpt))
10644 #endif
10645         pt->sgl_offset = offsetof(MPI2_SATA_PASSTHROUGH_REQUEST, SGL);
10646         if (pt->request_size != pt->sgl_offset)
10647                 NDBG15(("mpi_pre_sata_passthrough(): Incorrect req size, "
10648                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10649                     pt->request_size, pt->sgl_offset,
10650                     pt->dataout_size));
10651         if (pt->data_size != sizeof (MPI2_SATA_PASSTHROUGH_REPLY))
10652                 NDBG15(("mpi_pre_sata_passthrough(): Incorrect rep size, "
10653                     "0x%x, should be 0x%x", pt->data_size,
10654                     (int)sizeof (MPI2_SATA_PASSTHROUGH_REPLY)));
10655 }
10656 
10657 static void
10658 mpi_pre_smp_passthrough(mptsas_t *mpt, mptsas_pt_request_t *pt)
10659 {
10660 #ifndef __lock_lint
10661         _NOTE(ARGUNUSED(mpt))
10662 #endif
10663         pt->sgl_offset = offsetof(MPI2_SMP_PASSTHROUGH_REQUEST, SGL);
10664         if (pt->request_size != pt->sgl_offset)
10665                 NDBG15(("mpi_pre_smp_passthrough(): Incorrect req size, "
10666                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10667                     pt->request_size, pt->sgl_offset,
10668                     pt->dataout_size));
10669         if (pt->data_size != sizeof (MPI2_SMP_PASSTHROUGH_REPLY))
10670                 NDBG15(("mpi_pre_smp_passthrough(): Incorrect rep size, "
10671                     "0x%x, should be 0x%x", pt->data_size,
10672                     (int)sizeof (MPI2_SMP_PASSTHROUGH_REPLY)));
10673 }
10674 
10675 /*
10676  * Prepare pt for a CONFIG request.
10677  */
10678 static void
10679 mpi_pre_config(mptsas_t *mpt, mptsas_pt_request_t *pt)
10680 {
10681 #ifndef __lock_lint
10682         _NOTE(ARGUNUSED(mpt))
10683 #endif
10684         pt->sgl_offset = offsetof(MPI2_CONFIG_REQUEST, PageBufferSGE);
10685         if (pt->request_size != pt->sgl_offset)
10686                 NDBG15(("mpi_pre_config(): Incorrect req size, 0x%x, "
10687                     "should be 0x%x, dataoutsz 0x%x", pt->request_size,
10688                     pt->sgl_offset, pt->dataout_size));
10689         if (pt->data_size != sizeof (MPI2_CONFIG_REPLY))
10690                 NDBG15(("mpi_pre_config(): Incorrect rep size, 0x%x, "
10691                     "should be 0x%x", pt->data_size,
10692                     (int)sizeof (MPI2_CONFIG_REPLY)));
10693         pt->simple = 1;
10694 }
10695 
10696 /*
10697  * Prepare pt for a SCSI_IO_REQ request.
10698  */
10699 static void
10700 mpi_pre_scsi_io_req(mptsas_t *mpt, mptsas_pt_request_t *pt)
10701 {
10702 #ifndef __lock_lint
10703         _NOTE(ARGUNUSED(mpt))
10704 #endif
10705         pt->sgl_offset = offsetof(MPI2_SCSI_IO_REQUEST, SGL);
10706         if (pt->request_size != pt->sgl_offset)
10707                 NDBG15(("mpi_pre_config(): Incorrect req size, 0x%x, "
10708                     "should be 0x%x, dataoutsz 0x%x", pt->request_size,
10709                     pt->sgl_offset,
10710                     pt->dataout_size));
10711         if (pt->data_size != sizeof (MPI2_SCSI_IO_REPLY))
10712                 NDBG15(("mpi_pre_config(): Incorrect rep size, 0x%x, "
10713                     "should be 0x%x", pt->data_size,
10714                     (int)sizeof (MPI2_SCSI_IO_REPLY)));
10715 }
10716 
10717 /*
10718  * Prepare the mptsas_cmd for a SAS_IO_UNIT_CONTROL request.
10719  */
10720 static void
10721 mpi_pre_sas_io_unit_control(mptsas_t *mpt, mptsas_pt_request_t *pt)
10722 {
10723 #ifndef __lock_lint
10724         _NOTE(ARGUNUSED(mpt))
10725 #endif
10726         pt->sgl_offset = (uint16_t)pt->request_size;
10727 }
10728 
10729 /*
10730  * A set of functions to prepare an mptsas_cmd for the various
10731  * supported requests.
10732  */
10733 static struct mptsas_func {
10734         U8              Function;
10735         char            *Name;
10736         mptsas_pre_f    *f_pre;
10737 } mptsas_func_list[] = {
10738         { MPI2_FUNCTION_IOC_FACTS, "IOC_FACTS",         mpi_pre_ioc_facts },
10739         { MPI2_FUNCTION_PORT_FACTS, "PORT_FACTS",       mpi_pre_port_facts },
10740         { MPI2_FUNCTION_FW_DOWNLOAD, "FW_DOWNLOAD",     mpi_pre_fw_download },
10741         { MPI2_FUNCTION_FW_UPLOAD, "FW_UPLOAD",         mpi_pre_fw_upload },
10742         { MPI2_FUNCTION_SATA_PASSTHROUGH, "SATA_PASSTHROUGH",
10743             mpi_pre_sata_passthrough },
10744         { MPI2_FUNCTION_SMP_PASSTHROUGH, "SMP_PASSTHROUGH",
10745             mpi_pre_smp_passthrough},
10746         { MPI2_FUNCTION_SCSI_IO_REQUEST, "SCSI_IO_REQUEST",
10747             mpi_pre_scsi_io_req},
10748         { MPI2_FUNCTION_CONFIG, "CONFIG",               mpi_pre_config},
10749         { MPI2_FUNCTION_SAS_IO_UNIT_CONTROL, "SAS_IO_UNIT_CONTROL",
10750             mpi_pre_sas_io_unit_control },
10751         { 0xFF, NULL,                           NULL } /* list end */
10752 };
10753 
10754 static void
10755 mptsas_prep_sgl_offset(mptsas_t *mpt, mptsas_pt_request_t *pt)
10756 {
10757         pMPI2RequestHeader_t    hdr;
10758         struct mptsas_func      *f;
10759 
10760         hdr = (pMPI2RequestHeader_t)pt->request;
10761 
10762         for (f = mptsas_func_list; f->f_pre != NULL; f++) {
10763                 if (hdr->Function == f->Function) {
10764                         f->f_pre(mpt, pt);
10765                         NDBG15(("mptsas_prep_sgl_offset: Function %s,"
10766                             " sgl_offset 0x%x", f->Name,
10767                             pt->sgl_offset));
10768                         return;
10769                 }
10770         }
10771         NDBG15(("mptsas_prep_sgl_offset: Unknown Function 0x%02x,"
10772             " returning req_size 0x%x for sgl_offset",
10773             hdr->Function, pt->request_size));
10774         pt->sgl_offset = (uint16_t)pt->request_size;
10775 }
10776 
10777 
10778 static int
10779 mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
10780     uint8_t *data, uint32_t request_size, uint32_t reply_size,
10781     uint32_t data_size, uint32_t direction, uint8_t *dataout,
10782     uint32_t dataout_size, short timeout, int mode)
10783 {
10784         mptsas_pt_request_t             pt;
10785         mptsas_dma_alloc_state_t        data_dma_state;
10786         mptsas_dma_alloc_state_t        dataout_dma_state;
10787         caddr_t                         memp;
10788         mptsas_cmd_t                    *cmd = NULL;
10789         struct scsi_pkt                 *pkt;
10790         uint32_t                        reply_len = 0, sense_len = 0;
10791         pMPI2RequestHeader_t            request_hdrp;
10792         pMPI2RequestHeader_t            request_msg;
10793         pMPI2DefaultReply_t             reply_msg;
10794         Mpi2SCSIIOReply_t               rep_msg;
10795         int                             rvalue;
10796         int                             i, status = 0, pt_flags = 0, rv = 0;
10797         uint8_t                         function;
10798 
10799         ASSERT(mutex_owned(&mpt->m_mutex));
10800 
10801         reply_msg = (pMPI2DefaultReply_t)(&rep_msg);
10802         bzero(reply_msg, sizeof (MPI2_DEFAULT_REPLY));
10803         request_msg = kmem_zalloc(request_size, KM_SLEEP);
10804 
10805         mutex_exit(&mpt->m_mutex);
10806         /*
10807          * copy in the request buffer since it could be used by
10808          * another thread when the pt request into waitq
10809          */
10810         if (ddi_copyin(request, request_msg, request_size, mode)) {
10811                 mutex_enter(&mpt->m_mutex);
10812                 status = EFAULT;
10813                 mptsas_log(mpt, CE_WARN, "failed to copy request data");
10814                 goto out;
10815         }
10816         NDBG27(("mptsas_do_passthru: mode 0x%x, size 0x%x, Func 0x%x",
10817             mode, request_size, request_msg->Function));
10818         mutex_enter(&mpt->m_mutex);
10819 
10820         function = request_msg->Function;
10821         if (function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
10822                 pMpi2SCSITaskManagementRequest_t        task;
10823                 task = (pMpi2SCSITaskManagementRequest_t)request_msg;
10824                 mptsas_setup_bus_reset_delay(mpt);
10825                 rv = mptsas_ioc_task_management(mpt, task->TaskType,
10826                     task->DevHandle, (int)task->LUN[1], reply, reply_size,
10827                     mode);
10828 
10829                 if (rv != TRUE) {
10830                         status = EIO;
10831                         mptsas_log(mpt, CE_WARN, "task management failed");
10832                 }
10833                 goto out;
10834         }
10835 
10836         if (data_size != 0) {
10837                 data_dma_state.size = data_size;
10838                 if (mptsas_dma_alloc(mpt, &data_dma_state) != DDI_SUCCESS) {
10839                         status = ENOMEM;
10840                         mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
10841                             "resource");
10842                         goto out;
10843                 }
10844                 pt_flags |= MPTSAS_DATA_ALLOCATED;
10845                 if (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10846                         mutex_exit(&mpt->m_mutex);
10847                         for (i = 0; i < data_size; i++) {
10848                                 if (ddi_copyin(data + i, (uint8_t *)
10849                                     data_dma_state.memp + i, 1, mode)) {
10850                                         mutex_enter(&mpt->m_mutex);
10851                                         status = EFAULT;
10852                                         mptsas_log(mpt, CE_WARN, "failed to "
10853                                             "copy read data");
10854                                         goto out;
10855                                 }
10856                         }
10857                         mutex_enter(&mpt->m_mutex);
10858                 }
10859         } else {
10860                 bzero(&data_dma_state, sizeof (data_dma_state));
10861         }
10862 
10863         if (dataout_size != 0) {
10864                 dataout_dma_state.size = dataout_size;
10865                 if (mptsas_dma_alloc(mpt, &dataout_dma_state) != DDI_SUCCESS) {
10866                         status = ENOMEM;
10867                         mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
10868                             "resource");
10869                         goto out;
10870                 }
10871                 pt_flags |= MPTSAS_DATAOUT_ALLOCATED;
10872                 mutex_exit(&mpt->m_mutex);
10873                 for (i = 0; i < dataout_size; i++) {
10874                         if (ddi_copyin(dataout + i, (uint8_t *)
10875                             dataout_dma_state.memp + i, 1, mode)) {
10876                                 mutex_enter(&mpt->m_mutex);
10877                                 mptsas_log(mpt, CE_WARN, "failed to copy out"
10878                                     " data");
10879                                 status = EFAULT;
10880                                 goto out;
10881                         }
10882                 }
10883                 mutex_enter(&mpt->m_mutex);
10884         } else {
10885                 bzero(&dataout_dma_state, sizeof (dataout_dma_state));
10886         }
10887 
10888         if ((rvalue = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
10889                 status = EAGAIN;
10890                 mptsas_log(mpt, CE_NOTE, "event ack command pool is full");
10891                 goto out;
10892         }
10893         pt_flags |= MPTSAS_REQUEST_POOL_CMD;
10894 
10895         bzero((caddr_t)cmd, sizeof (*cmd));
10896         bzero((caddr_t)pkt, scsi_pkt_size());
10897         bzero((caddr_t)&pt, sizeof (pt));
10898 
10899         cmd->ioc_cmd_slot = (uint32_t)(rvalue);
10900 
10901         pt.request = (uint8_t *)request_msg;
10902         pt.direction = direction;
10903         pt.simple = 0;
10904         pt.request_size = request_size;
10905         pt.data_size = data_size;
10906         pt.dataout_size = dataout_size;
10907         pt.data_cookie = data_dma_state.cookie;
10908         pt.dataout_cookie = dataout_dma_state.cookie;
10909         mptsas_prep_sgl_offset(mpt, &pt);
10910 
10911         /*
10912          * Form a blank cmd/pkt to store the acknowledgement message
10913          */
10914         pkt->pkt_cdbp                = (opaque_t)&cmd->cmd_cdb[0];
10915         pkt->pkt_scbp                = (opaque_t)&cmd->cmd_scb;
10916         pkt->pkt_ha_private  = (opaque_t)&pt;
10917         pkt->pkt_flags               = FLAG_HEAD;
10918         pkt->pkt_time                = timeout;
10919         cmd->cmd_pkt         = pkt;
10920         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_PASSTHRU;
10921 
10922         if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
10923             (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
10924                 uint8_t                 com, cdb_group_id;
10925                 boolean_t               ret;
10926 
10927                 pkt->pkt_cdbp = ((pMpi2SCSIIORequest_t)request_msg)->CDB.CDB32;
10928                 com = pkt->pkt_cdbp[0];
10929                 cdb_group_id = CDB_GROUPID(com);
10930                 switch (cdb_group_id) {
10931                 case CDB_GROUPID_0: cmd->cmd_cdblen = CDB_GROUP0; break;
10932                 case CDB_GROUPID_1: cmd->cmd_cdblen = CDB_GROUP1; break;
10933                 case CDB_GROUPID_2: cmd->cmd_cdblen = CDB_GROUP2; break;
10934                 case CDB_GROUPID_4: cmd->cmd_cdblen = CDB_GROUP4; break;
10935                 case CDB_GROUPID_5: cmd->cmd_cdblen = CDB_GROUP5; break;
10936                 default:
10937                         NDBG27(("mptsas_do_passthru: SCSI_IO, reserved "
10938                             "CDBGROUP 0x%x requested!", cdb_group_id));
10939                         break;
10940                 }
10941 
10942                 reply_len = sizeof (MPI2_SCSI_IO_REPLY);
10943                 sense_len = reply_size - reply_len;
10944                 ret = mptsas_cmdarqsize(mpt, cmd, sense_len, KM_SLEEP);
10945                 VERIFY(ret == B_TRUE);
10946         } else {
10947                 reply_len = reply_size;
10948                 sense_len = 0;
10949         }
10950 
10951         NDBG27(("mptsas_do_passthru: %s, dsz 0x%x, dosz 0x%x, replen 0x%x, "
10952             "snslen 0x%x",
10953             (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE)?"Write":"Read",
10954             data_size, dataout_size, reply_len, sense_len));
10955 
10956         /*
10957          * Save the command in a slot
10958          */
10959         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
10960                 /*
10961                  * Once passthru command get slot, set cmd_flags
10962                  * CFLAG_PREPARED.
10963                  */
10964                 cmd->cmd_flags |= CFLAG_PREPARED;
10965                 mptsas_start_passthru(mpt, cmd);
10966         } else {
10967                 mptsas_waitq_add(mpt, cmd);
10968         }
10969 
10970         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
10971                 cv_wait(&mpt->m_passthru_cv, &mpt->m_mutex);
10972         }
10973 
10974         NDBG27(("mptsas_do_passthru: Cmd complete, flags 0x%x, rfm 0x%x "
10975             "pktreason 0x%x", cmd->cmd_flags, cmd->cmd_rfm,
10976             pkt->pkt_reason));
10977 
10978         if (cmd->cmd_flags & CFLAG_PREPARED) {
10979                 memp = mpt->m_req_frame + (mpt->m_req_frame_size *
10980                     cmd->cmd_slot);
10981                 request_hdrp = (pMPI2RequestHeader_t)memp;
10982         }
10983 
10984         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
10985                 status = ETIMEDOUT;
10986                 mptsas_log(mpt, CE_WARN, "passthrough command timeout");
10987                 pt_flags |= MPTSAS_CMD_TIMEOUT;
10988                 goto out;
10989         }
10990 
10991         if (cmd->cmd_rfm) {
10992                 /*
10993                  * cmd_rfm is zero means the command reply is a CONTEXT
10994                  * reply and no PCI Write to post the free reply SMFA
10995                  * because no reply message frame is used.
10996                  * cmd_rfm is non-zero means the reply is a ADDRESS
10997                  * reply and reply message frame is used.
10998                  */
10999                 pt_flags |= MPTSAS_ADDRESS_REPLY;
11000                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
11001                     DDI_DMA_SYNC_FORCPU);
11002                 reply_msg = (pMPI2DefaultReply_t)
11003                     (mpt->m_reply_frame + (cmd->cmd_rfm -
11004                     (mpt->m_reply_frame_dma_addr & 0xffffffffu)));
11005         }
11006 
11007         mptsas_fma_check(mpt, cmd);
11008         if (pkt->pkt_reason == CMD_TRAN_ERR) {
11009                 status = EAGAIN;
11010                 mptsas_log(mpt, CE_WARN, "passthru fma error");
11011                 goto out;
11012         }
11013         if (pkt->pkt_reason == CMD_RESET) {
11014                 status = EAGAIN;
11015                 mptsas_log(mpt, CE_WARN, "ioc reset abort passthru");
11016                 goto out;
11017         }
11018 
11019         if (pkt->pkt_reason == CMD_INCOMPLETE) {
11020                 status = EIO;
11021                 mptsas_log(mpt, CE_WARN, "passthrough command incomplete");
11022                 goto out;
11023         }
11024 
11025         mutex_exit(&mpt->m_mutex);
11026         if (cmd->cmd_flags & CFLAG_PREPARED) {
11027                 function = request_hdrp->Function;
11028                 if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
11029                     (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
11030                         reply_len = sizeof (MPI2_SCSI_IO_REPLY);
11031                         sense_len = cmd->cmd_extrqslen ?
11032                             min(sense_len, cmd->cmd_extrqslen) :
11033                             min(sense_len, cmd->cmd_rqslen);
11034                 } else {
11035                         reply_len = reply_size;
11036                         sense_len = 0;
11037                 }
11038 
11039                 for (i = 0; i < reply_len; i++) {
11040                         if (ddi_copyout((uint8_t *)reply_msg + i, reply + i, 1,
11041                             mode)) {
11042                                 mutex_enter(&mpt->m_mutex);
11043                                 status = EFAULT;
11044                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
11045                                     "reply data");
11046                                 goto out;
11047                         }
11048                 }
11049                 for (i = 0; i < sense_len; i++) {
11050                         if (ddi_copyout((uint8_t *)request_hdrp + 64 + i,
11051                             reply + reply_len + i, 1, mode)) {
11052                                 mutex_enter(&mpt->m_mutex);
11053                                 status = EFAULT;
11054                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
11055                                     "sense data");
11056                                 goto out;
11057                         }
11058                 }
11059         }
11060 
11061         if (data_size) {
11062                 if (direction != MPTSAS_PASS_THRU_DIRECTION_WRITE) {
11063                         (void) ddi_dma_sync(data_dma_state.handle, 0, 0,
11064                             DDI_DMA_SYNC_FORCPU);
11065                         for (i = 0; i < data_size; i++) {
11066                                 if (ddi_copyout((uint8_t *)(
11067                                     data_dma_state.memp + i), data + i,  1,
11068                                     mode)) {
11069                                         mutex_enter(&mpt->m_mutex);
11070                                         status = EFAULT;
11071                                         mptsas_log(mpt, CE_WARN, "failed to "
11072                                             "copy out the reply data");
11073                                         goto out;
11074                                 }
11075                         }
11076                 }
11077         }
11078         mutex_enter(&mpt->m_mutex);
11079 out:
11080         /*
11081          * Put the reply frame back on the free queue, increment the free
11082          * index, and write the new index to the free index register.  But only
11083          * if this reply is an ADDRESS reply.
11084          */
11085         if (pt_flags & MPTSAS_ADDRESS_REPLY) {
11086                 ddi_put32(mpt->m_acc_free_queue_hdl,
11087                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
11088                     cmd->cmd_rfm);
11089                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
11090                     DDI_DMA_SYNC_FORDEV);
11091                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
11092                         mpt->m_free_index = 0;
11093                 }
11094                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
11095                     mpt->m_free_index);
11096         }
11097         if (cmd) {
11098                 if (cmd->cmd_extrqslen != 0) {
11099                         rmfree(mpt->m_erqsense_map, cmd->cmd_extrqschunks,
11100                             cmd->cmd_extrqsidx + 1);
11101                 }
11102                 if (cmd->cmd_flags & CFLAG_PREPARED) {
11103                         mptsas_remove_cmd(mpt, cmd);
11104                         pt_flags &= (~MPTSAS_REQUEST_POOL_CMD);
11105                 }
11106         }
11107         if (pt_flags & MPTSAS_REQUEST_POOL_CMD)
11108                 mptsas_return_to_pool(mpt, cmd);
11109         if (pt_flags & MPTSAS_DATA_ALLOCATED) {
11110                 if (mptsas_check_dma_handle(data_dma_state.handle) !=
11111                     DDI_SUCCESS) {
11112                         ddi_fm_service_impact(mpt->m_dip,
11113                             DDI_SERVICE_UNAFFECTED);
11114                         status = EFAULT;
11115                 }
11116                 mptsas_dma_free(&data_dma_state);
11117         }
11118         if (pt_flags & MPTSAS_DATAOUT_ALLOCATED) {
11119                 if (mptsas_check_dma_handle(dataout_dma_state.handle) !=
11120                     DDI_SUCCESS) {
11121                         ddi_fm_service_impact(mpt->m_dip,
11122                             DDI_SERVICE_UNAFFECTED);
11123                         status = EFAULT;
11124                 }
11125                 mptsas_dma_free(&dataout_dma_state);
11126         }
11127         if (pt_flags & MPTSAS_CMD_TIMEOUT) {
11128                 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
11129                         mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
11130                 }
11131         }
11132         if (request_msg)
11133                 kmem_free(request_msg, request_size);
11134         NDBG27(("mptsas_do_passthru: Done status 0x%x", status));
11135 
11136         return (status);
11137 }
11138 
11139 static int
11140 mptsas_pass_thru(mptsas_t *mpt, mptsas_pass_thru_t *data, int mode)
11141 {
11142         /*
11143          * If timeout is 0, set timeout to default of 60 seconds.
11144          */
11145         if (data->Timeout == 0) {
11146                 data->Timeout = MPTSAS_PASS_THRU_TIME_DEFAULT;
11147         }
11148 
11149         if (((data->DataSize == 0) &&
11150             (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_NONE)) ||
11151             ((data->DataSize != 0) &&
11152             ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_READ) ||
11153             (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_WRITE) ||
11154             ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) &&
11155             (data->DataOutSize != 0))))) {
11156                 if (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) {
11157                         data->DataDirection = MPTSAS_PASS_THRU_DIRECTION_READ;
11158                 } else {
11159                         data->DataOutSize = 0;
11160                 }
11161                 /*
11162                  * Send passthru request messages
11163                  */
11164                 return (mptsas_do_passthru(mpt,
11165                     (uint8_t *)((uintptr_t)data->PtrRequest),
11166                     (uint8_t *)((uintptr_t)data->PtrReply),
11167                     (uint8_t *)((uintptr_t)data->PtrData),
11168                     data->RequestSize, data->ReplySize,
11169                     data->DataSize, data->DataDirection,
11170                     (uint8_t *)((uintptr_t)data->PtrDataOut),
11171                     data->DataOutSize, data->Timeout, mode));
11172         } else {
11173                 return (EINVAL);
11174         }
11175 }
11176 
11177 static uint8_t
11178 mptsas_get_fw_diag_buffer_number(mptsas_t *mpt, uint32_t unique_id)
11179 {
11180         uint8_t index;
11181 
11182         for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
11183                 if (mpt->m_fw_diag_buffer_list[index].unique_id == unique_id) {
11184                         return (index);
11185                 }
11186         }
11187 
11188         return (MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND);
11189 }
11190 
11191 static void
11192 mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd)
11193 {
11194         pMpi2DiagBufferPostRequest_t    pDiag_post_msg;
11195         pMpi2DiagReleaseRequest_t       pDiag_release_msg;
11196         struct scsi_pkt                 *pkt = cmd->cmd_pkt;
11197         mptsas_diag_request_t           *diag = pkt->pkt_ha_private;
11198         uint32_t                        i;
11199         uint64_t                        request_desc;
11200 
11201         ASSERT(mutex_owned(&mpt->m_mutex));
11202 
11203         /*
11204          * Form the diag message depending on the post or release function.
11205          */
11206         if (diag->function == MPI2_FUNCTION_DIAG_BUFFER_POST) {
11207                 pDiag_post_msg = (pMpi2DiagBufferPostRequest_t)
11208                     (mpt->m_req_frame + (mpt->m_req_frame_size *
11209                     cmd->cmd_slot));
11210                 bzero(pDiag_post_msg, mpt->m_req_frame_size);
11211                 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->Function,
11212                     diag->function);
11213                 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->BufferType,
11214                     diag->pBuffer->buffer_type);
11215                 ddi_put8(mpt->m_acc_req_frame_hdl,
11216                     &pDiag_post_msg->ExtendedType,
11217                     diag->pBuffer->extended_type);
11218                 ddi_put32(mpt->m_acc_req_frame_hdl,
11219                     &pDiag_post_msg->BufferLength,
11220                     diag->pBuffer->buffer_data.size);
11221                 for (i = 0; i < (sizeof (pDiag_post_msg->ProductSpecific) / 4);
11222                     i++) {
11223                         ddi_put32(mpt->m_acc_req_frame_hdl,
11224                             &pDiag_post_msg->ProductSpecific[i],
11225                             diag->pBuffer->product_specific[i]);
11226                 }
11227                 ddi_put32(mpt->m_acc_req_frame_hdl,
11228                     &pDiag_post_msg->BufferAddress.Low,
11229                     (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
11230                     & 0xffffffffull));
11231                 ddi_put32(mpt->m_acc_req_frame_hdl,
11232                     &pDiag_post_msg->BufferAddress.High,
11233                     (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
11234                     >> 32));
11235         } else {
11236                 pDiag_release_msg = (pMpi2DiagReleaseRequest_t)
11237                     (mpt->m_req_frame + (mpt->m_req_frame_size *
11238                     cmd->cmd_slot));
11239                 bzero(pDiag_release_msg, mpt->m_req_frame_size);
11240                 ddi_put8(mpt->m_acc_req_frame_hdl,
11241                     &pDiag_release_msg->Function, diag->function);
11242                 ddi_put8(mpt->m_acc_req_frame_hdl,
11243                     &pDiag_release_msg->BufferType,
11244                     diag->pBuffer->buffer_type);
11245         }
11246 
11247         /*
11248          * Send the message
11249          */
11250         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
11251             DDI_DMA_SYNC_FORDEV);
11252         request_desc = (cmd->cmd_slot << 16) +
11253             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
11254         cmd->cmd_rfm = NULL;
11255         MPTSAS_START_CMD(mpt, request_desc);
11256         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
11257             DDI_SUCCESS) ||
11258             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
11259             DDI_SUCCESS)) {
11260                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
11261         }
11262 }
11263 
11264 static int
11265 mptsas_post_fw_diag_buffer(mptsas_t *mpt,
11266     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
11267 {
11268         mptsas_diag_request_t           diag;
11269         int                             status, slot_num, post_flags = 0;
11270         mptsas_cmd_t                    *cmd = NULL;
11271         struct scsi_pkt                 *pkt;
11272         pMpi2DiagBufferPostReply_t      reply;
11273         uint16_t                        iocstatus;
11274         uint32_t                        iocloginfo, transfer_length;
11275 
11276         /*
11277          * If buffer is not enabled, just leave.
11278          */
11279         *return_code = MPTSAS_FW_DIAG_ERROR_POST_FAILED;
11280         if (!pBuffer->enabled) {
11281                 status = DDI_FAILURE;
11282                 goto out;
11283         }
11284 
11285         /*
11286          * Clear some flags initially.
11287          */
11288         pBuffer->force_release = FALSE;
11289         pBuffer->valid_data = FALSE;
11290         pBuffer->owned_by_firmware = FALSE;
11291 
11292         /*
11293          * Get a cmd buffer from the cmd buffer pool
11294          */
11295         if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
11296                 status = DDI_FAILURE;
11297                 mptsas_log(mpt, CE_NOTE, "command pool is full: Post FW Diag");
11298                 goto out;
11299         }
11300         post_flags |= MPTSAS_REQUEST_POOL_CMD;
11301 
11302         bzero((caddr_t)cmd, sizeof (*cmd));
11303         bzero((caddr_t)pkt, scsi_pkt_size());
11304 
11305         cmd->ioc_cmd_slot = (uint32_t)(slot_num);
11306 
11307         diag.pBuffer = pBuffer;
11308         diag.function = MPI2_FUNCTION_DIAG_BUFFER_POST;
11309 
11310         /*
11311          * Form a blank cmd/pkt to store the acknowledgement message
11312          */
11313         pkt->pkt_ha_private  = (opaque_t)&diag;
11314         pkt->pkt_flags               = FLAG_HEAD;
11315         pkt->pkt_time                = 60;
11316         cmd->cmd_pkt         = pkt;
11317         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_DIAG;
11318 
11319         /*
11320          * Save the command in a slot
11321          */
11322         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
11323                 /*
11324                  * Once passthru command get slot, set cmd_flags
11325                  * CFLAG_PREPARED.
11326                  */
11327                 cmd->cmd_flags |= CFLAG_PREPARED;
11328                 mptsas_start_diag(mpt, cmd);
11329         } else {
11330                 mptsas_waitq_add(mpt, cmd);
11331         }
11332 
11333         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
11334                 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
11335         }
11336 
11337         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
11338                 status = DDI_FAILURE;
11339                 mptsas_log(mpt, CE_WARN, "Post FW Diag command timeout");
11340                 goto out;
11341         }
11342 
11343         /*
11344          * cmd_rfm points to the reply message if a reply was given.  Check the
11345          * IOCStatus to make sure everything went OK with the FW diag request
11346          * and set buffer flags.
11347          */
11348         if (cmd->cmd_rfm) {
11349                 post_flags |= MPTSAS_ADDRESS_REPLY;
11350                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
11351                     DDI_DMA_SYNC_FORCPU);
11352                 reply = (pMpi2DiagBufferPostReply_t)(mpt->m_reply_frame +
11353                     (cmd->cmd_rfm -
11354                     (mpt->m_reply_frame_dma_addr & 0xffffffffu)));
11355 
11356                 /*
11357                  * Get the reply message data
11358                  */
11359                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
11360                     &reply->IOCStatus);
11361                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
11362                     &reply->IOCLogInfo);
11363                 transfer_length = ddi_get32(mpt->m_acc_reply_frame_hdl,
11364                     &reply->TransferLength);
11365 
11366                 /*
11367                  * If post failed quit.
11368                  */
11369                 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
11370                         status = DDI_FAILURE;
11371                         NDBG13(("post FW Diag Buffer failed: IOCStatus=0x%x, "
11372                             "IOCLogInfo=0x%x, TransferLength=0x%x", iocstatus,
11373                             iocloginfo, transfer_length));
11374                         goto out;
11375                 }
11376 
11377                 /*
11378                  * Post was successful.
11379                  */
11380                 pBuffer->valid_data = TRUE;
11381                 pBuffer->owned_by_firmware = TRUE;
11382                 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
11383                 status = DDI_SUCCESS;
11384         }
11385 
11386 out:
11387         /*
11388          * Put the reply frame back on the free queue, increment the free
11389          * index, and write the new index to the free index register.  But only
11390          * if this reply is an ADDRESS reply.
11391          */
11392         if (post_flags & MPTSAS_ADDRESS_REPLY) {
11393                 ddi_put32(mpt->m_acc_free_queue_hdl,
11394                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
11395                     cmd->cmd_rfm);
11396                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
11397                     DDI_DMA_SYNC_FORDEV);
11398                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
11399                         mpt->m_free_index = 0;
11400                 }
11401                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
11402                     mpt->m_free_index);
11403         }
11404         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
11405                 mptsas_remove_cmd(mpt, cmd);
11406                 post_flags &= (~MPTSAS_REQUEST_POOL_CMD);
11407         }
11408         if (post_flags & MPTSAS_REQUEST_POOL_CMD) {
11409                 mptsas_return_to_pool(mpt, cmd);
11410         }
11411 
11412         return (status);
11413 }
11414 
11415 static int
11416 mptsas_release_fw_diag_buffer(mptsas_t *mpt,
11417     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
11418     uint32_t diag_type)
11419 {
11420         mptsas_diag_request_t   diag;
11421         int                     status, slot_num, rel_flags = 0;
11422         mptsas_cmd_t            *cmd = NULL;
11423         struct scsi_pkt         *pkt;
11424         pMpi2DiagReleaseReply_t reply;
11425         uint16_t                iocstatus;
11426         uint32_t                iocloginfo;
11427 
11428         /*
11429          * If buffer is not enabled, just leave.
11430          */
11431         *return_code = MPTSAS_FW_DIAG_ERROR_RELEASE_FAILED;
11432         if (!pBuffer->enabled) {
11433                 mptsas_log(mpt, CE_NOTE, "This buffer type is not supported "
11434                     "by the IOC");
11435                 status = DDI_FAILURE;
11436                 goto out;
11437         }
11438 
11439         /*
11440          * Clear some flags initially.
11441          */
11442         pBuffer->force_release = FALSE;
11443         pBuffer->valid_data = FALSE;
11444         pBuffer->owned_by_firmware = FALSE;
11445 
11446         /*
11447          * Get a cmd buffer from the cmd buffer pool
11448          */
11449         if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
11450                 status = DDI_FAILURE;
11451                 mptsas_log(mpt, CE_NOTE, "command pool is full: Release FW "
11452                     "Diag");
11453                 goto out;
11454         }
11455         rel_flags |= MPTSAS_REQUEST_POOL_CMD;
11456 
11457         bzero((caddr_t)cmd, sizeof (*cmd));
11458         bzero((caddr_t)pkt, scsi_pkt_size());
11459 
11460         cmd->ioc_cmd_slot = (uint32_t)(slot_num);
11461 
11462         diag.pBuffer = pBuffer;
11463         diag.function = MPI2_FUNCTION_DIAG_RELEASE;
11464 
11465         /*
11466          * Form a blank cmd/pkt to store the acknowledgement message
11467          */
11468         pkt->pkt_ha_private  = (opaque_t)&diag;
11469         pkt->pkt_flags               = FLAG_HEAD;
11470         pkt->pkt_time                = 60;
11471         cmd->cmd_pkt         = pkt;
11472         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_DIAG;
11473 
11474         /*
11475          * Save the command in a slot
11476          */
11477         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
11478                 /*
11479                  * Once passthru command get slot, set cmd_flags
11480                  * CFLAG_PREPARED.
11481                  */
11482                 cmd->cmd_flags |= CFLAG_PREPARED;
11483                 mptsas_start_diag(mpt, cmd);
11484         } else {
11485                 mptsas_waitq_add(mpt, cmd);
11486         }
11487 
11488         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
11489                 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
11490         }
11491 
11492         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
11493                 status = DDI_FAILURE;
11494                 mptsas_log(mpt, CE_WARN, "Release FW Diag command timeout");
11495                 goto out;
11496         }
11497 
11498         /*
11499          * cmd_rfm points to the reply message if a reply was given.  Check the
11500          * IOCStatus to make sure everything went OK with the FW diag request
11501          * and set buffer flags.
11502          */
11503         if (cmd->cmd_rfm) {
11504                 rel_flags |= MPTSAS_ADDRESS_REPLY;
11505                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
11506                     DDI_DMA_SYNC_FORCPU);
11507                 reply = (pMpi2DiagReleaseReply_t)(mpt->m_reply_frame +
11508                     (cmd->cmd_rfm -
11509                     (mpt->m_reply_frame_dma_addr & 0xffffffffu)));
11510 
11511                 /*
11512                  * Get the reply message data
11513                  */
11514                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
11515                     &reply->IOCStatus);
11516                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
11517                     &reply->IOCLogInfo);
11518 
11519                 /*
11520                  * If release failed quit.
11521                  */
11522                 if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) ||
11523                     pBuffer->owned_by_firmware) {
11524                         status = DDI_FAILURE;
11525                         NDBG13(("release FW Diag Buffer failed: "
11526                             "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
11527                             iocloginfo));
11528                         goto out;
11529                 }
11530 
11531                 /*
11532                  * Release was successful.
11533                  */
11534                 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
11535                 status = DDI_SUCCESS;
11536 
11537                 /*
11538                  * If this was for an UNREGISTER diag type command, clear the
11539                  * unique ID.
11540                  */
11541                 if (diag_type == MPTSAS_FW_DIAG_TYPE_UNREGISTER) {
11542                         pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
11543                 }
11544         }
11545 
11546 out:
11547         /*
11548          * Put the reply frame back on the free queue, increment the free
11549          * index, and write the new index to the free index register.  But only
11550          * if this reply is an ADDRESS reply.
11551          */
11552         if (rel_flags & MPTSAS_ADDRESS_REPLY) {
11553                 ddi_put32(mpt->m_acc_free_queue_hdl,
11554                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
11555                     cmd->cmd_rfm);
11556                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
11557                     DDI_DMA_SYNC_FORDEV);
11558                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
11559                         mpt->m_free_index = 0;
11560                 }
11561                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
11562                     mpt->m_free_index);
11563         }
11564         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
11565                 mptsas_remove_cmd(mpt, cmd);
11566                 rel_flags &= (~MPTSAS_REQUEST_POOL_CMD);
11567         }
11568         if (rel_flags & MPTSAS_REQUEST_POOL_CMD) {
11569                 mptsas_return_to_pool(mpt, cmd);
11570         }
11571 
11572         return (status);
11573 }
11574 
11575 static int
11576 mptsas_diag_register(mptsas_t *mpt, mptsas_fw_diag_register_t *diag_register,
11577     uint32_t *return_code)
11578 {
11579         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11580         uint8_t                         extended_type, buffer_type, i;
11581         uint32_t                        buffer_size;
11582         uint32_t                        unique_id;
11583         int                             status;
11584 
11585         ASSERT(mutex_owned(&mpt->m_mutex));
11586 
11587         extended_type = diag_register->ExtendedType;
11588         buffer_type = diag_register->BufferType;
11589         buffer_size = diag_register->RequestedBufferSize;
11590         unique_id = diag_register->UniqueId;
11591 
11592         /*
11593          * Check for valid buffer type
11594          */
11595         if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) {
11596                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11597                 return (DDI_FAILURE);
11598         }
11599 
11600         /*
11601          * Get the current buffer and look up the unique ID.  The unique ID
11602          * should not be found.  If it is, the ID is already in use.
11603          */
11604         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11605         pBuffer = &mpt->m_fw_diag_buffer_list[buffer_type];
11606         if (i != MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11607                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11608                 return (DDI_FAILURE);
11609         }
11610 
11611         /*
11612          * The buffer's unique ID should not be registered yet, and the given
11613          * unique ID cannot be 0.
11614          */
11615         if ((pBuffer->unique_id != MPTSAS_FW_DIAG_INVALID_UID) ||
11616             (unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
11617                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11618                 return (DDI_FAILURE);
11619         }
11620 
11621         /*
11622          * If this buffer is already posted as immediate, just change owner.
11623          */
11624         if (pBuffer->immediate && pBuffer->owned_by_firmware &&
11625             (pBuffer->unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
11626                 pBuffer->immediate = FALSE;
11627                 pBuffer->unique_id = unique_id;
11628                 return (DDI_SUCCESS);
11629         }
11630 
11631         /*
11632          * Post a new buffer after checking if it's enabled.  The DMA buffer
11633          * that is allocated will be contiguous (sgl_len = 1).
11634          */
11635         if (!pBuffer->enabled) {
11636                 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
11637                 return (DDI_FAILURE);
11638         }
11639         bzero(&pBuffer->buffer_data, sizeof (mptsas_dma_alloc_state_t));
11640         pBuffer->buffer_data.size = buffer_size;
11641         if (mptsas_dma_alloc(mpt, &pBuffer->buffer_data) != DDI_SUCCESS) {
11642                 mptsas_log(mpt, CE_WARN, "failed to alloc DMA resource for "
11643                     "diag buffer: size = %d bytes", buffer_size);
11644                 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
11645                 return (DDI_FAILURE);
11646         }
11647 
11648         /*
11649          * Copy the given info to the diag buffer and post the buffer.
11650          */
11651         pBuffer->buffer_type = buffer_type;
11652         pBuffer->immediate = FALSE;
11653         if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) {
11654                 for (i = 0; i < (sizeof (pBuffer->product_specific) / 4);
11655                     i++) {
11656                         pBuffer->product_specific[i] =
11657                             diag_register->ProductSpecific[i];
11658                 }
11659         }
11660         pBuffer->extended_type = extended_type;
11661         pBuffer->unique_id = unique_id;
11662         status = mptsas_post_fw_diag_buffer(mpt, pBuffer, return_code);
11663 
11664         if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
11665             DDI_SUCCESS) {
11666                 mptsas_log(mpt, CE_WARN, "Check of DMA handle failed in "
11667                     "mptsas_diag_register.");
11668                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
11669                         status = DDI_FAILURE;
11670         }
11671 
11672         /*
11673          * In case there was a failure, free the DMA buffer.
11674          */
11675         if (status == DDI_FAILURE) {
11676                 mptsas_dma_free(&pBuffer->buffer_data);
11677         }
11678 
11679         return (status);
11680 }
11681 
11682 static int
11683 mptsas_diag_unregister(mptsas_t *mpt,
11684     mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
11685 {
11686         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11687         uint8_t                         i;
11688         uint32_t                        unique_id;
11689         int                             status;
11690 
11691         ASSERT(mutex_owned(&mpt->m_mutex));
11692 
11693         unique_id = diag_unregister->UniqueId;
11694 
11695         /*
11696          * Get the current buffer and look up the unique ID.  The unique ID
11697          * should be there.
11698          */
11699         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11700         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11701                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11702                 return (DDI_FAILURE);
11703         }
11704 
11705         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11706 
11707         /*
11708          * Try to release the buffer from FW before freeing it.  If release
11709          * fails, don't free the DMA buffer in case FW tries to access it
11710          * later.  If buffer is not owned by firmware, can't release it.
11711          */
11712         if (!pBuffer->owned_by_firmware) {
11713                 status = DDI_SUCCESS;
11714         } else {
11715                 status = mptsas_release_fw_diag_buffer(mpt, pBuffer,
11716                     return_code, MPTSAS_FW_DIAG_TYPE_UNREGISTER);
11717         }
11718 
11719         /*
11720          * At this point, return the current status no matter what happens with
11721          * the DMA buffer.
11722          */
11723         pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
11724         if (status == DDI_SUCCESS) {
11725                 if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
11726                     DDI_SUCCESS) {
11727                         mptsas_log(mpt, CE_WARN, "Check of DMA handle failed "
11728                             "in mptsas_diag_unregister.");
11729                         ddi_fm_service_impact(mpt->m_dip,
11730                             DDI_SERVICE_UNAFFECTED);
11731                 }
11732                 mptsas_dma_free(&pBuffer->buffer_data);
11733         }
11734 
11735         return (status);
11736 }
11737 
11738 static int
11739 mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
11740     uint32_t *return_code)
11741 {
11742         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11743         uint8_t                         i;
11744         uint32_t                        unique_id;
11745 
11746         ASSERT(mutex_owned(&mpt->m_mutex));
11747 
11748         unique_id = diag_query->UniqueId;
11749 
11750         /*
11751          * If ID is valid, query on ID.
11752          * If ID is invalid, query on buffer type.
11753          */
11754         if (unique_id == MPTSAS_FW_DIAG_INVALID_UID) {
11755                 i = diag_query->BufferType;
11756                 if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
11757                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11758                         return (DDI_FAILURE);
11759                 }
11760         } else {
11761                 i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11762                 if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11763                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11764                         return (DDI_FAILURE);
11765                 }
11766         }
11767 
11768         /*
11769          * Fill query structure with the diag buffer info.
11770          */
11771         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11772         diag_query->BufferType = pBuffer->buffer_type;
11773         diag_query->ExtendedType = pBuffer->extended_type;
11774         if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) {
11775                 for (i = 0; i < (sizeof (diag_query->ProductSpecific) / 4);
11776                     i++) {
11777                         diag_query->ProductSpecific[i] =
11778                             pBuffer->product_specific[i];
11779                 }
11780         }
11781         diag_query->TotalBufferSize = pBuffer->buffer_data.size;
11782         diag_query->DriverAddedBufferSize = 0;
11783         diag_query->UniqueId = pBuffer->unique_id;
11784         diag_query->ApplicationFlags = 0;
11785         diag_query->DiagnosticFlags = 0;
11786 
11787         /*
11788          * Set/Clear application flags
11789          */
11790         if (pBuffer->immediate) {
11791                 diag_query->ApplicationFlags &= ~MPTSAS_FW_DIAG_FLAG_APP_OWNED;
11792         } else {
11793                 diag_query->ApplicationFlags |= MPTSAS_FW_DIAG_FLAG_APP_OWNED;
11794         }
11795         if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
11796                 diag_query->ApplicationFlags |=
11797                     MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
11798         } else {
11799                 diag_query->ApplicationFlags &=
11800                     ~MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
11801         }
11802         if (pBuffer->owned_by_firmware) {
11803                 diag_query->ApplicationFlags |=
11804                     MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
11805         } else {
11806                 diag_query->ApplicationFlags &=
11807                     ~MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
11808         }
11809 
11810         return (DDI_SUCCESS);
11811 }
11812 
11813 static int
11814 mptsas_diag_read_buffer(mptsas_t *mpt,
11815     mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
11816     uint32_t *return_code, int ioctl_mode)
11817 {
11818         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11819         uint8_t                         i, *pData;
11820         uint32_t                        unique_id, byte;
11821         int                             status;
11822 
11823         ASSERT(mutex_owned(&mpt->m_mutex));
11824 
11825         unique_id = diag_read_buffer->UniqueId;
11826 
11827         /*
11828          * Get the current buffer and look up the unique ID.  The unique ID
11829          * should be there.
11830          */
11831         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11832         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11833                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11834                 return (DDI_FAILURE);
11835         }
11836 
11837         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11838 
11839         /*
11840          * Make sure requested read is within limits
11841          */
11842         if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
11843             pBuffer->buffer_data.size) {
11844                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11845                 return (DDI_FAILURE);
11846         }
11847 
11848         /*
11849          * Copy the requested data from DMA to the diag_read_buffer.  The DMA
11850          * buffer that was allocated is one contiguous buffer.
11851          */
11852         pData = (uint8_t *)(pBuffer->buffer_data.memp +
11853             diag_read_buffer->StartingOffset);
11854         (void) ddi_dma_sync(pBuffer->buffer_data.handle, 0, 0,
11855             DDI_DMA_SYNC_FORCPU);
11856         for (byte = 0; byte < diag_read_buffer->BytesToRead; byte++) {
11857                 if (ddi_copyout(pData + byte, ioctl_buf + byte, 1, ioctl_mode)
11858                     != 0) {
11859                         return (DDI_FAILURE);
11860                 }
11861         }
11862         diag_read_buffer->Status = 0;
11863 
11864         /*
11865          * Set or clear the Force Release flag.
11866          */
11867         if (pBuffer->force_release) {
11868                 diag_read_buffer->Flags |= MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
11869         } else {
11870                 diag_read_buffer->Flags &= ~MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
11871         }
11872 
11873         /*
11874          * If buffer is to be reregistered, make sure it's not already owned by
11875          * firmware first.
11876          */
11877         status = DDI_SUCCESS;
11878         if (!pBuffer->owned_by_firmware) {
11879                 if (diag_read_buffer->Flags & MPTSAS_FW_DIAG_FLAG_REREGISTER) {
11880                         status = mptsas_post_fw_diag_buffer(mpt, pBuffer,
11881                             return_code);
11882                 }
11883         }
11884 
11885         return (status);
11886 }
11887 
11888 static int
11889 mptsas_diag_release(mptsas_t *mpt, mptsas_fw_diag_release_t *diag_release,
11890     uint32_t *return_code)
11891 {
11892         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11893         uint8_t                         i;
11894         uint32_t                        unique_id;
11895         int                             status;
11896 
11897         ASSERT(mutex_owned(&mpt->m_mutex));
11898 
11899         unique_id = diag_release->UniqueId;
11900 
11901         /*
11902          * Get the current buffer and look up the unique ID.  The unique ID
11903          * should be there.
11904          */
11905         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11906         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11907                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11908                 return (DDI_FAILURE);
11909         }
11910 
11911         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11912 
11913         /*
11914          * If buffer is not owned by firmware, it's already been released.
11915          */
11916         if (!pBuffer->owned_by_firmware) {
11917                 *return_code = MPTSAS_FW_DIAG_ERROR_ALREADY_RELEASED;
11918                 return (DDI_FAILURE);
11919         }
11920 
11921         /*
11922          * Release the buffer.
11923          */
11924         status = mptsas_release_fw_diag_buffer(mpt, pBuffer, return_code,
11925             MPTSAS_FW_DIAG_TYPE_RELEASE);
11926         return (status);
11927 }
11928 
11929 static int
11930 mptsas_do_diag_action(mptsas_t *mpt, uint32_t action, uint8_t *diag_action,
11931     uint32_t length, uint32_t *return_code, int ioctl_mode)
11932 {
11933         mptsas_fw_diag_register_t       diag_register;
11934         mptsas_fw_diag_unregister_t     diag_unregister;
11935         mptsas_fw_diag_query_t          diag_query;
11936         mptsas_diag_read_buffer_t       diag_read_buffer;
11937         mptsas_fw_diag_release_t        diag_release;
11938         int                             status = DDI_SUCCESS;
11939         uint32_t                        original_return_code, read_buf_len;
11940 
11941         ASSERT(mutex_owned(&mpt->m_mutex));
11942 
11943         original_return_code = *return_code;
11944         *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
11945 
11946         switch (action) {
11947                 case MPTSAS_FW_DIAG_TYPE_REGISTER:
11948                         if (!length) {
11949                                 *return_code =
11950                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11951                                 status = DDI_FAILURE;
11952                                 break;
11953                         }
11954                         if (ddi_copyin(diag_action, &diag_register,
11955                             sizeof (diag_register), ioctl_mode) != 0) {
11956                                 return (DDI_FAILURE);
11957                         }
11958                         status = mptsas_diag_register(mpt, &diag_register,
11959                             return_code);
11960                         break;
11961 
11962                 case MPTSAS_FW_DIAG_TYPE_UNREGISTER:
11963                         if (length < sizeof (diag_unregister)) {
11964                                 *return_code =
11965                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11966                                 status = DDI_FAILURE;
11967                                 break;
11968                         }
11969                         if (ddi_copyin(diag_action, &diag_unregister,
11970                             sizeof (diag_unregister), ioctl_mode) != 0) {
11971                                 return (DDI_FAILURE);
11972                         }
11973                         status = mptsas_diag_unregister(mpt, &diag_unregister,
11974                             return_code);
11975                         break;
11976 
11977                 case MPTSAS_FW_DIAG_TYPE_QUERY:
11978                         if (length < sizeof (diag_query)) {
11979                                 *return_code =
11980                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11981                                 status = DDI_FAILURE;
11982                                 break;
11983                         }
11984                         if (ddi_copyin(diag_action, &diag_query,
11985                             sizeof (diag_query), ioctl_mode) != 0) {
11986                                 return (DDI_FAILURE);
11987                         }
11988                         status = mptsas_diag_query(mpt, &diag_query,
11989                             return_code);
11990                         if (status == DDI_SUCCESS) {
11991                                 if (ddi_copyout(&diag_query, diag_action,
11992                                     sizeof (diag_query), ioctl_mode) != 0) {
11993                                         return (DDI_FAILURE);
11994                                 }
11995                         }
11996                         break;
11997 
11998                 case MPTSAS_FW_DIAG_TYPE_READ_BUFFER:
11999                         if (ddi_copyin(diag_action, &diag_read_buffer,
12000                             sizeof (diag_read_buffer) - 4, ioctl_mode) != 0) {
12001                                 return (DDI_FAILURE);
12002                         }
12003                         read_buf_len = sizeof (diag_read_buffer) -
12004                             sizeof (diag_read_buffer.DataBuffer) +
12005                             diag_read_buffer.BytesToRead;
12006                         if (length < read_buf_len) {
12007                                 *return_code =
12008                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
12009                                 status = DDI_FAILURE;
12010                                 break;
12011                         }
12012                         status = mptsas_diag_read_buffer(mpt,
12013                             &diag_read_buffer, diag_action +
12014                             sizeof (diag_read_buffer) - 4, return_code,
12015                             ioctl_mode);
12016                         if (status == DDI_SUCCESS) {
12017                                 if (ddi_copyout(&diag_read_buffer, diag_action,
12018                                     sizeof (diag_read_buffer) - 4, ioctl_mode)
12019                                     != 0) {
12020                                         return (DDI_FAILURE);
12021                                 }
12022                         }
12023                         break;
12024 
12025                 case MPTSAS_FW_DIAG_TYPE_RELEASE:
12026                         if (length < sizeof (diag_release)) {
12027                                 *return_code =
12028                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
12029                                 status = DDI_FAILURE;
12030                                 break;
12031                         }
12032                         if (ddi_copyin(diag_action, &diag_release,
12033                             sizeof (diag_release), ioctl_mode) != 0) {
12034                                 return (DDI_FAILURE);
12035                         }
12036                         status = mptsas_diag_release(mpt, &diag_release,
12037                             return_code);
12038                         break;
12039 
12040                 default:
12041                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
12042                         status = DDI_FAILURE;
12043                         break;
12044         }
12045 
12046         if ((status == DDI_FAILURE) &&
12047             (original_return_code == MPTSAS_FW_DIAG_NEW) &&
12048             (*return_code != MPTSAS_FW_DIAG_ERROR_SUCCESS)) {
12049                 status = DDI_SUCCESS;
12050         }
12051 
12052         return (status);
12053 }
12054 
12055 static int
12056 mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *user_data, int mode)
12057 {
12058         int                     status;
12059         mptsas_diag_action_t    driver_data;
12060 
12061         ASSERT(mutex_owned(&mpt->m_mutex));
12062 
12063         /*
12064          * Copy the user data to a driver data buffer.
12065          */
12066         if (ddi_copyin(user_data, &driver_data, sizeof (mptsas_diag_action_t),
12067             mode) == 0) {
12068                 /*
12069                  * Send diag action request if Action is valid
12070                  */
12071                 if (driver_data.Action == MPTSAS_FW_DIAG_TYPE_REGISTER ||
12072                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_UNREGISTER ||
12073                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_QUERY ||
12074                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_READ_BUFFER ||
12075                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_RELEASE) {
12076                         status = mptsas_do_diag_action(mpt, driver_data.Action,
12077                             (void *)(uintptr_t)driver_data.PtrDiagAction,
12078                             driver_data.Length, &driver_data.ReturnCode,
12079                             mode);
12080                         if (status == DDI_SUCCESS) {
12081                                 if (ddi_copyout(&driver_data.ReturnCode,
12082                                     &user_data->ReturnCode,
12083                                     sizeof (user_data->ReturnCode), mode)
12084                                     != 0) {
12085                                         status = EFAULT;
12086                                 } else {
12087                                         status = 0;
12088                                 }
12089                         } else {
12090                                 status = EIO;
12091                         }
12092                 } else {
12093                         status = EINVAL;
12094                 }
12095         } else {
12096                 status = EFAULT;
12097         }
12098 
12099         return (status);
12100 }
12101 
12102 /*
12103  * This routine handles the "event query" ioctl.
12104  */
12105 static int
12106 mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data, int mode,
12107     int *rval)
12108 {
12109         int                     status;
12110         mptsas_event_query_t    driverdata;
12111         uint8_t                 i;
12112 
12113         driverdata.Entries = MPTSAS_EVENT_QUEUE_SIZE;
12114 
12115         mutex_enter(&mpt->m_mutex);
12116         for (i = 0; i < 4; i++) {
12117                 driverdata.Types[i] = mpt->m_event_mask[i];
12118         }
12119         mutex_exit(&mpt->m_mutex);
12120 
12121         if (ddi_copyout(&driverdata, data, sizeof (driverdata), mode) != 0) {
12122                 status = EFAULT;
12123         } else {
12124                 *rval = MPTIOCTL_STATUS_GOOD;
12125                 status = 0;
12126         }
12127 
12128         return (status);
12129 }
12130 
12131 /*
12132  * This routine handles the "event enable" ioctl.
12133  */
12134 static int
12135 mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data, int mode,
12136     int *rval)
12137 {
12138         int                     status;
12139         mptsas_event_enable_t   driverdata;
12140         uint8_t                 i;
12141 
12142         if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
12143                 mutex_enter(&mpt->m_mutex);
12144                 for (i = 0; i < 4; i++) {
12145                         mpt->m_event_mask[i] = driverdata.Types[i];
12146                 }
12147                 mutex_exit(&mpt->m_mutex);
12148 
12149                 *rval = MPTIOCTL_STATUS_GOOD;
12150                 status = 0;
12151         } else {
12152                 status = EFAULT;
12153         }
12154         return (status);
12155 }
12156 
12157 /*
12158  * This routine handles the "event report" ioctl.
12159  */
12160 static int
12161 mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data, int mode,
12162     int *rval)
12163 {
12164         int                     status;
12165         mptsas_event_report_t   driverdata;
12166 
12167         mutex_enter(&mpt->m_mutex);
12168 
12169         if (ddi_copyin(&data->Size, &driverdata.Size, sizeof (driverdata.Size),
12170             mode) == 0) {
12171                 if (driverdata.Size >= sizeof (mpt->m_events)) {
12172                         if (ddi_copyout(mpt->m_events, data->Events,
12173                             sizeof (mpt->m_events), mode) != 0) {
12174                                 status = EFAULT;
12175                         } else {
12176                                 if (driverdata.Size > sizeof (mpt->m_events)) {
12177                                         driverdata.Size =
12178                                             sizeof (mpt->m_events);
12179                                         if (ddi_copyout(&driverdata.Size,
12180                                             &data->Size,
12181                                             sizeof (driverdata.Size),
12182                                             mode) != 0) {
12183                                                 status = EFAULT;
12184                                         } else {
12185                                                 *rval = MPTIOCTL_STATUS_GOOD;
12186                                                 status = 0;
12187                                         }
12188                                 } else {
12189                                         *rval = MPTIOCTL_STATUS_GOOD;
12190                                         status = 0;
12191                                 }
12192                         }
12193                 } else {
12194                         *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
12195                         status = 0;
12196                 }
12197         } else {
12198                 status = EFAULT;
12199         }
12200 
12201         mutex_exit(&mpt->m_mutex);
12202         return (status);
12203 }
12204 
12205 static void
12206 mptsas_lookup_pci_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
12207 {
12208         int     *reg_data;
12209         uint_t  reglen;
12210 
12211         /*
12212          * Lookup the 'reg' property and extract the other data
12213          */
12214         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
12215             DDI_PROP_DONTPASS, "reg", &reg_data, &reglen) ==
12216             DDI_PROP_SUCCESS) {
12217                 /*
12218                  * Extract the PCI data from the 'reg' property first DWORD.
12219                  * The entry looks like the following:
12220                  * First DWORD:
12221                  * Bits 0 - 7 8-bit Register number
12222                  * Bits 8 - 10 3-bit Function number
12223                  * Bits 11 - 15 5-bit Device number
12224                  * Bits 16 - 23 8-bit Bus number
12225                  * Bits 24 - 25 2-bit Address Space type identifier
12226                  *
12227                  */
12228                 adapter_data->PciInformation.u.bits.BusNumber =
12229                     (reg_data[0] & 0x00FF0000) >> 16;
12230                 adapter_data->PciInformation.u.bits.DeviceNumber =
12231                     (reg_data[0] & 0x0000F800) >> 11;
12232                 adapter_data->PciInformation.u.bits.FunctionNumber =
12233                     (reg_data[0] & 0x00000700) >> 8;
12234                 ddi_prop_free((void *)reg_data);
12235         } else {
12236                 /*
12237                  * If we can't determine the PCI data then we fill in FF's for
12238                  * the data to indicate this.
12239                  */
12240                 adapter_data->PCIDeviceHwId = 0xFFFFFFFF;
12241                 adapter_data->MpiPortNumber = 0xFFFFFFFF;
12242                 adapter_data->PciInformation.u.AsDWORD = 0xFFFFFFFF;
12243         }
12244 
12245         /*
12246          * Saved in the mpt->m_fwversion
12247          */
12248         adapter_data->MpiFirmwareVersion = mpt->m_fwversion;
12249 }
12250 
12251 static void
12252 mptsas_read_adapter_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
12253 {
12254         char    *driver_verstr = MPTSAS_MOD_STRING;
12255 
12256         mptsas_lookup_pci_data(mpt, adapter_data);
12257         adapter_data->AdapterType = mpt->m_MPI25 ?
12258             MPTIOCTL_ADAPTER_TYPE_SAS3 :
12259             MPTIOCTL_ADAPTER_TYPE_SAS2;
12260         adapter_data->PCIDeviceHwId = (uint32_t)mpt->m_devid;
12261         adapter_data->PCIDeviceHwRev = (uint32_t)mpt->m_revid;
12262         adapter_data->SubSystemId = (uint32_t)mpt->m_ssid;
12263         adapter_data->SubsystemVendorId = (uint32_t)mpt->m_svid;
12264         (void) strcpy((char *)&adapter_data->DriverVersion[0], driver_verstr);
12265         adapter_data->BiosVersion = 0;
12266         (void) mptsas_get_bios_page3(mpt, &adapter_data->BiosVersion);
12267 }
12268 
12269 static void
12270 mptsas_read_pci_info(mptsas_t *mpt, mptsas_pci_info_t *pci_info)
12271 {
12272         int     *reg_data, i;
12273         uint_t  reglen;
12274 
12275         /*
12276          * Lookup the 'reg' property and extract the other data
12277          */
12278         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
12279             DDI_PROP_DONTPASS, "reg", &reg_data, &reglen) ==
12280             DDI_PROP_SUCCESS) {
12281                 /*
12282                  * Extract the PCI data from the 'reg' property first DWORD.
12283                  * The entry looks like the following:
12284                  * First DWORD:
12285                  * Bits 8 - 10 3-bit Function number
12286                  * Bits 11 - 15 5-bit Device number
12287                  * Bits 16 - 23 8-bit Bus number
12288                  */
12289                 pci_info->BusNumber = (reg_data[0] & 0x00FF0000) >> 16;
12290                 pci_info->DeviceNumber = (reg_data[0] & 0x0000F800) >> 11;
12291                 pci_info->FunctionNumber = (reg_data[0] & 0x00000700) >> 8;
12292                 ddi_prop_free((void *)reg_data);
12293         } else {
12294                 /*
12295                  * If we can't determine the PCI info then we fill in FF's for
12296                  * the data to indicate this.
12297                  */
12298                 pci_info->BusNumber = 0xFFFFFFFF;
12299                 pci_info->DeviceNumber = 0xFF;
12300                 pci_info->FunctionNumber = 0xFF;
12301         }
12302 
12303         /*
12304          * Now get the interrupt vector and the pci header.  The vector can
12305          * only be 0 right now.  The header is the first 256 bytes of config
12306          * space.
12307          */
12308         pci_info->InterruptVector = 0;
12309         for (i = 0; i < sizeof (pci_info->PciHeader); i++) {
12310                 pci_info->PciHeader[i] = pci_config_get8(mpt->m_config_handle,
12311                     i);
12312         }
12313 }
12314 
12315 static int
12316 mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data, int mode)
12317 {
12318         int                     status = 0;
12319         mptsas_reg_access_t     driverdata;
12320 
12321         mutex_enter(&mpt->m_mutex);
12322         if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
12323                 switch (driverdata.Command) {
12324                         /*
12325                          * IO access is not supported.
12326                          */
12327                         case REG_IO_READ:
12328                         case REG_IO_WRITE:
12329                                 mptsas_log(mpt, CE_WARN, "IO access is not "
12330                                     "supported.  Use memory access.");
12331                                 status = EINVAL;
12332                                 break;
12333 
12334                         case REG_MEM_READ:
12335                                 driverdata.RegData = ddi_get32(mpt->m_datap,
12336                                     (uint32_t *)(void *)mpt->m_reg +
12337                                     driverdata.RegOffset);
12338                                 if (ddi_copyout(&driverdata.RegData,
12339                                     &data->RegData,
12340                                     sizeof (driverdata.RegData), mode) != 0) {
12341                                         mptsas_log(mpt, CE_WARN, "Register "
12342                                             "Read Failed");
12343                                         status = EFAULT;
12344                                 }
12345                                 break;
12346 
12347                         case REG_MEM_WRITE:
12348                                 ddi_put32(mpt->m_datap,
12349                                     (uint32_t *)(void *)mpt->m_reg +
12350                                     driverdata.RegOffset,
12351                                     driverdata.RegData);
12352                                 break;
12353 
12354                         default:
12355                                 status = EINVAL;
12356                                 break;
12357                 }
12358         } else {
12359                 status = EFAULT;
12360         }
12361 
12362         mutex_exit(&mpt->m_mutex);
12363         return (status);
12364 }
12365 
12366 static int
12367 led_control(mptsas_t *mpt, intptr_t data, int mode)
12368 {
12369         int ret = 0;
12370         mptsas_led_control_t lc;
12371         mptsas_target_t *ptgt;
12372 
12373         if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) {
12374                 return (EFAULT);
12375         }
12376 
12377         if ((lc.Command != MPTSAS_LEDCTL_FLAG_SET &&
12378             lc.Command != MPTSAS_LEDCTL_FLAG_GET) ||
12379             lc.Led < MPTSAS_LEDCTL_LED_MIN ||
12380             lc.Led > MPTSAS_LEDCTL_LED_MAX ||
12381             (lc.Command == MPTSAS_LEDCTL_FLAG_SET && lc.LedStatus != 0 &&
12382             lc.LedStatus != 1)) {
12383                 return (EINVAL);
12384         }
12385 
12386         if ((lc.Command == MPTSAS_LEDCTL_FLAG_SET && (mode & FWRITE) == 0) ||
12387             (lc.Command == MPTSAS_LEDCTL_FLAG_GET && (mode & FREAD) == 0))
12388                 return (EACCES);
12389 
12390         /* Locate the target we're interrogating... */
12391         mutex_enter(&mpt->m_mutex);
12392         ptgt = refhash_linear_search(mpt->m_targets,
12393             mptsas_target_eval_slot, &lc);
12394         if (ptgt == NULL) {
12395                 /* We could not find a target for that enclosure/slot. */
12396                 mutex_exit(&mpt->m_mutex);
12397                 return (ENOENT);
12398         }
12399 
12400         if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) {
12401                 /* Update our internal LED state. */
12402                 ptgt->m_led_status &= ~(1 << (lc.Led - 1));
12403                 ptgt->m_led_status |= lc.LedStatus << (lc.Led - 1);
12404 
12405                 /* Flush it to the controller. */
12406                 ret = mptsas_flush_led_status(mpt, ptgt);
12407                 mutex_exit(&mpt->m_mutex);
12408                 return (ret);
12409         }
12410 
12411         /* Return our internal LED state. */
12412         lc.LedStatus = (ptgt->m_led_status >> (lc.Led - 1)) & 1;
12413         mutex_exit(&mpt->m_mutex);
12414 
12415         if (ddi_copyout(&lc, (void *)data, sizeof (lc), mode) != 0) {
12416                 return (EFAULT);
12417         }
12418 
12419         return (0);
12420 }
12421 
12422 static int
12423 get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
12424 {
12425         uint16_t i = 0;
12426         uint16_t count = 0;
12427         int ret = 0;
12428         mptsas_target_t *ptgt;
12429         mptsas_disk_info_t *di;
12430         STRUCT_DECL(mptsas_get_disk_info, gdi);
12431 
12432         if ((mode & FREAD) == 0)
12433                 return (EACCES);
12434 
12435         STRUCT_INIT(gdi, get_udatamodel());
12436 
12437         if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi),
12438             mode) != 0) {
12439                 return (EFAULT);
12440         }
12441 
12442         /* Find out how many targets there are. */
12443         mutex_enter(&mpt->m_mutex);
12444         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
12445             ptgt = refhash_next(mpt->m_targets, ptgt)) {
12446                 count++;
12447         }
12448         mutex_exit(&mpt->m_mutex);
12449 
12450         /*
12451          * If we haven't been asked to copy out information on each target,
12452          * then just return the count.
12453          */
12454         STRUCT_FSET(gdi, DiskCount, count);
12455         if (STRUCT_FGETP(gdi, PtrDiskInfoArray) == NULL)
12456                 goto copy_out;
12457 
12458         /*
12459          * If we haven't been given a large enough buffer to copy out into,
12460          * let the caller know.
12461          */
12462         if (STRUCT_FGET(gdi, DiskInfoArraySize) <
12463             count * sizeof (mptsas_disk_info_t)) {
12464                 ret = ENOSPC;
12465                 goto copy_out;
12466         }
12467 
12468         di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP);
12469 
12470         mutex_enter(&mpt->m_mutex);
12471         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
12472             ptgt = refhash_next(mpt->m_targets, ptgt)) {
12473                 if (i >= count) {
12474                         /*
12475                          * The number of targets changed while we weren't
12476                          * looking, so give up.
12477                          */
12478                         refhash_rele(mpt->m_targets, ptgt);
12479                         mutex_exit(&mpt->m_mutex);
12480                         kmem_free(di, count * sizeof (mptsas_disk_info_t));
12481                         return (EAGAIN);
12482                 }
12483                 di[i].Instance = mpt->m_instance;
12484                 di[i].Enclosure = ptgt->m_enclosure;
12485                 di[i].Slot = ptgt->m_slot_num;
12486                 di[i].SasAddress = ptgt->m_addr.mta_wwn;
12487                 i++;
12488         }
12489         mutex_exit(&mpt->m_mutex);
12490         STRUCT_FSET(gdi, DiskCount, i);
12491 
12492         /* Copy out the disk information to the caller. */
12493         if (ddi_copyout((void *)di, STRUCT_FGETP(gdi, PtrDiskInfoArray),
12494             i * sizeof (mptsas_disk_info_t), mode) != 0) {
12495                 ret = EFAULT;
12496         }
12497 
12498         kmem_free(di, count * sizeof (mptsas_disk_info_t));
12499 
12500 copy_out:
12501         if (ddi_copyout(STRUCT_BUF(gdi), (void *)data, STRUCT_SIZE(gdi),
12502             mode) != 0) {
12503                 ret = EFAULT;
12504         }
12505 
12506         return (ret);
12507 }
12508 
12509 static int
12510 mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
12511     int *rval)
12512 {
12513         int                     status = 0;
12514         mptsas_t                *mpt;
12515         mptsas_update_flash_t   flashdata;
12516         mptsas_pass_thru_t      passthru_data;
12517         mptsas_adapter_data_t   adapter_data;
12518         mptsas_pci_info_t       pci_info;
12519         int                     copylen;
12520 
12521         int                     iport_flag = 0;
12522         dev_info_t              *dip = NULL;
12523         mptsas_phymask_t        phymask = 0;
12524         struct devctl_iocdata   *dcp = NULL;
12525         char                    *addr = NULL;
12526         mptsas_target_t         *ptgt = NULL;
12527 
12528         *rval = MPTIOCTL_STATUS_GOOD;
12529         if (secpolicy_sys_config(credp, B_FALSE) != 0) {
12530                 return (EPERM);
12531         }
12532 
12533         mpt = ddi_get_soft_state(mptsas_state, MINOR2INST(getminor(dev)));
12534         if (mpt == NULL) {
12535                 /*
12536                  * Called from iport node, get the states
12537                  */
12538                 iport_flag = 1;
12539                 dip = mptsas_get_dip_from_dev(dev, &phymask);
12540                 if (dip == NULL) {
12541                         return (ENXIO);
12542                 }
12543                 mpt = DIP2MPT(dip);
12544         }
12545         /* Make sure power level is D0 before accessing registers */
12546         mutex_enter(&mpt->m_mutex);
12547         if (mpt->m_options & MPTSAS_OPT_PM) {
12548                 (void) pm_busy_component(mpt->m_dip, 0);
12549                 if (mpt->m_power_level != PM_LEVEL_D0) {
12550                         mutex_exit(&mpt->m_mutex);
12551                         if (pm_raise_power(mpt->m_dip, 0, PM_LEVEL_D0) !=
12552                             DDI_SUCCESS) {
12553                                 mptsas_log(mpt, CE_WARN,
12554                                     "mptsas%d: mptsas_ioctl: Raise power "
12555                                     "request failed.", mpt->m_instance);
12556                                 (void) pm_idle_component(mpt->m_dip, 0);
12557                                 return (ENXIO);
12558                         }
12559                 } else {
12560                         mutex_exit(&mpt->m_mutex);
12561                 }
12562         } else {
12563                 mutex_exit(&mpt->m_mutex);
12564         }
12565 
12566         if (iport_flag) {
12567                 status = scsi_hba_ioctl(dev, cmd, data, mode, credp, rval);
12568                 if (status != 0) {
12569                         goto out;
12570                 }
12571                 /*
12572                  * The following code control the OK2RM LED, it doesn't affect
12573                  * the ioctl return status.
12574                  */
12575                 if ((cmd == DEVCTL_DEVICE_ONLINE) ||
12576                     (cmd == DEVCTL_DEVICE_OFFLINE)) {
12577                         if (ndi_dc_allochdl((void *)data, &dcp) !=
12578                             NDI_SUCCESS) {
12579                                 goto out;
12580                         }
12581                         addr = ndi_dc_getaddr(dcp);
12582                         ptgt = mptsas_addr_to_ptgt(mpt, addr, phymask);
12583                         if (ptgt == NULL) {
12584                                 NDBG14(("mptsas_ioctl led control: tgt %s not "
12585                                     "found", addr));
12586                                 ndi_dc_freehdl(dcp);
12587                                 goto out;
12588                         }
12589                         mutex_enter(&mpt->m_mutex);
12590                         if (cmd == DEVCTL_DEVICE_ONLINE) {
12591                                 ptgt->m_tgt_unconfigured = 0;
12592                         } else if (cmd == DEVCTL_DEVICE_OFFLINE) {
12593                                 ptgt->m_tgt_unconfigured = 1;
12594                         }
12595                         if (cmd == DEVCTL_DEVICE_OFFLINE) {
12596                                 ptgt->m_led_status |=
12597                                     (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
12598                         } else {
12599                                 ptgt->m_led_status &=
12600                                     ~(1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
12601                         }
12602                         (void) mptsas_flush_led_status(mpt, ptgt);
12603                         mutex_exit(&mpt->m_mutex);
12604                         ndi_dc_freehdl(dcp);
12605                 }
12606                 goto out;
12607         }
12608         switch (cmd) {
12609                 case MPTIOCTL_GET_DISK_INFO:
12610                         status = get_disk_info(mpt, data, mode);
12611                         break;
12612                 case MPTIOCTL_LED_CONTROL:
12613                         status = led_control(mpt, data, mode);
12614                         break;
12615                 case MPTIOCTL_UPDATE_FLASH:
12616                         if (ddi_copyin((void *)data, &flashdata,
12617                                 sizeof (struct mptsas_update_flash), mode)) {
12618                                 status = EFAULT;
12619                                 break;
12620                         }
12621 
12622                         mutex_enter(&mpt->m_mutex);
12623                         if (mptsas_update_flash(mpt,
12624                             (caddr_t)(long)flashdata.PtrBuffer,
12625                             flashdata.ImageSize, flashdata.ImageType, mode)) {
12626                                 status = EFAULT;
12627                         }
12628 
12629                         /*
12630                          * Reset the chip to start using the new
12631                          * firmware.  Reset if failed also.
12632                          */
12633                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
12634                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
12635                                 status = EFAULT;
12636                         }
12637                         mutex_exit(&mpt->m_mutex);
12638                         break;
12639                 case MPTIOCTL_PASS_THRU:
12640                         /*
12641                          * The user has requested to pass through a command to
12642                          * be executed by the MPT firmware.  Call our routine
12643                          * which does this.  Only allow one passthru IOCTL at
12644                          * one time. Other threads will block on
12645                          * m_passthru_mutex, which is of adaptive variant.
12646                          */
12647                         if (ddi_copyin((void *)data, &passthru_data,
12648                             sizeof (mptsas_pass_thru_t), mode)) {
12649                                 status = EFAULT;
12650                                 break;
12651                         }
12652                         mutex_enter(&mpt->m_passthru_mutex);
12653                         mutex_enter(&mpt->m_mutex);
12654                         status = mptsas_pass_thru(mpt, &passthru_data, mode);
12655                         mutex_exit(&mpt->m_mutex);
12656                         mutex_exit(&mpt->m_passthru_mutex);
12657 
12658                         break;
12659                 case MPTIOCTL_GET_ADAPTER_DATA:
12660                         /*
12661                          * The user has requested to read adapter data.  Call
12662                          * our routine which does this.
12663                          */
12664                         bzero(&adapter_data, sizeof (mptsas_adapter_data_t));
12665                         if (ddi_copyin((void *)data, (void *)&adapter_data,
12666                             sizeof (mptsas_adapter_data_t), mode)) {
12667                                 status = EFAULT;
12668                                 break;
12669                         }
12670                         if (adapter_data.StructureLength >=
12671                             sizeof (mptsas_adapter_data_t)) {
12672                                 adapter_data.StructureLength = (uint32_t)
12673                                     sizeof (mptsas_adapter_data_t);
12674                                 copylen = sizeof (mptsas_adapter_data_t);
12675                                 mutex_enter(&mpt->m_mutex);
12676                                 mptsas_read_adapter_data(mpt, &adapter_data);
12677                                 mutex_exit(&mpt->m_mutex);
12678                         } else {
12679                                 adapter_data.StructureLength = (uint32_t)
12680                                     sizeof (mptsas_adapter_data_t);
12681                                 copylen = sizeof (adapter_data.StructureLength);
12682                                 *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
12683                         }
12684                         if (ddi_copyout((void *)(&adapter_data), (void *)data,
12685                             copylen, mode) != 0) {
12686                                 status = EFAULT;
12687                         }
12688                         break;
12689                 case MPTIOCTL_GET_PCI_INFO:
12690                         /*
12691                          * The user has requested to read pci info.  Call
12692                          * our routine which does this.
12693                          */
12694                         bzero(&pci_info, sizeof (mptsas_pci_info_t));
12695                         mutex_enter(&mpt->m_mutex);
12696                         mptsas_read_pci_info(mpt, &pci_info);
12697                         mutex_exit(&mpt->m_mutex);
12698                         if (ddi_copyout((void *)(&pci_info), (void *)data,
12699                             sizeof (mptsas_pci_info_t), mode) != 0) {
12700                                 status = EFAULT;
12701                         }
12702                         break;
12703                 case MPTIOCTL_RESET_ADAPTER:
12704                         mutex_enter(&mpt->m_mutex);
12705                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
12706                         if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
12707                                 mptsas_log(mpt, CE_WARN, "reset adapter IOCTL "
12708                                     "failed");
12709                                 status = EFAULT;
12710                         }
12711                         mutex_exit(&mpt->m_mutex);
12712                         break;
12713                 case MPTIOCTL_DIAG_ACTION:
12714                         /*
12715                          * The user has done a diag buffer action.  Call our
12716                          * routine which does this.  Only allow one diag action
12717                          * at one time.
12718                          */
12719                         mutex_enter(&mpt->m_mutex);
12720                         if (mpt->m_diag_action_in_progress) {
12721                                 mutex_exit(&mpt->m_mutex);
12722                                 return (EBUSY);
12723                         }
12724                         mpt->m_diag_action_in_progress = 1;
12725                         status = mptsas_diag_action(mpt,
12726                             (mptsas_diag_action_t *)data, mode);
12727                         mpt->m_diag_action_in_progress = 0;
12728                         mutex_exit(&mpt->m_mutex);
12729                         break;
12730                 case MPTIOCTL_EVENT_QUERY:
12731                         /*
12732                          * The user has done an event query. Call our routine
12733                          * which does this.
12734                          */
12735                         status = mptsas_event_query(mpt,
12736                             (mptsas_event_query_t *)data, mode, rval);
12737                         break;
12738                 case MPTIOCTL_EVENT_ENABLE:
12739                         /*
12740                          * The user has done an event enable. Call our routine
12741                          * which does this.
12742                          */
12743                         status = mptsas_event_enable(mpt,
12744                             (mptsas_event_enable_t *)data, mode, rval);
12745                         break;
12746                 case MPTIOCTL_EVENT_REPORT:
12747                         /*
12748                          * The user has done an event report. Call our routine
12749                          * which does this.
12750                          */
12751                         status = mptsas_event_report(mpt,
12752                             (mptsas_event_report_t *)data, mode, rval);
12753                         break;
12754                 case MPTIOCTL_REG_ACCESS:
12755                         /*
12756                          * The user has requested register access.  Call our
12757                          * routine which does this.
12758                          */
12759                         status = mptsas_reg_access(mpt,
12760                             (mptsas_reg_access_t *)data, mode);
12761                         break;
12762                 default:
12763                         status = scsi_hba_ioctl(dev, cmd, data, mode, credp,
12764                             rval);
12765                         break;
12766         }
12767 
12768 out:
12769         return (status);
12770 }
12771 
12772 int
12773 mptsas_restart_ioc(mptsas_t *mpt)
12774 {
12775         int             rval = DDI_SUCCESS;
12776         mptsas_target_t *ptgt = NULL;
12777 
12778         ASSERT(mutex_owned(&mpt->m_mutex));
12779 
12780         /*
12781          * Set a flag telling I/O path that we're processing a reset.  This is
12782          * needed because after the reset is complete, the hash table still
12783          * needs to be rebuilt.  If I/Os are started before the hash table is
12784          * rebuilt, I/O errors will occur.  This flag allows I/Os to be marked
12785          * so that they can be retried.
12786          */
12787         mpt->m_in_reset = TRUE;
12788 
12789         /*
12790          * Set all throttles to HOLD
12791          */
12792         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
12793             ptgt = refhash_next(mpt->m_targets, ptgt)) {
12794                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
12795         }
12796 
12797         /*
12798          * Disable interrupts
12799          */
12800         MPTSAS_DISABLE_INTR(mpt);
12801 
12802         /*
12803          * Abort all commands: outstanding commands, commands in waitq and
12804          * tx_waitq.
12805          */
12806         mptsas_flush_hba(mpt);
12807 
12808         /*
12809          * Reinitialize the chip.
12810          */
12811         if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
12812                 rval = DDI_FAILURE;
12813         }
12814 
12815         /*
12816          * Enable interrupts again
12817          */
12818         MPTSAS_ENABLE_INTR(mpt);
12819 
12820         /*
12821          * If mptsas_init_chip was successful, update the driver data.
12822          */
12823         if (rval == DDI_SUCCESS) {
12824                 mptsas_update_driver_data(mpt);
12825         }
12826 
12827         /*
12828          * Reset the throttles
12829          */
12830         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
12831             ptgt = refhash_next(mpt->m_targets, ptgt)) {
12832                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
12833         }
12834 
12835         mptsas_doneq_empty(mpt);
12836         mptsas_restart_hba(mpt);
12837 
12838         if (rval != DDI_SUCCESS) {
12839                 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
12840                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
12841         }
12842 
12843         /*
12844          * Clear the reset flag so that I/Os can continue.
12845          */
12846         mpt->m_in_reset = FALSE;
12847 
12848         return (rval);
12849 }
12850 
12851 static int
12852 mptsas_init_chip(mptsas_t *mpt, int first_time)
12853 {
12854         ddi_dma_cookie_t        cookie;
12855         uint32_t                i;
12856         int                     rval;
12857 
12858         /*
12859          * Check to see if the firmware image is valid
12860          */
12861         if (ddi_get32(mpt->m_datap, &mpt->m_reg->HostDiagnostic) &
12862             MPI2_DIAG_FLASH_BAD_SIG) {
12863                 mptsas_log(mpt, CE_WARN, "mptsas bad flash signature!");
12864                 goto fail;
12865         }
12866 
12867         /*
12868          * Reset the chip
12869          */
12870         rval = mptsas_ioc_reset(mpt, first_time);
12871         if (rval == MPTSAS_RESET_FAIL) {
12872                 mptsas_log(mpt, CE_WARN, "hard reset failed!");
12873                 goto fail;
12874         }
12875 
12876         if ((rval == MPTSAS_SUCCESS_MUR) && (!first_time)) {
12877                 goto mur;
12878         }
12879         /*
12880          * Setup configuration space
12881          */
12882         if (mptsas_config_space_init(mpt) == FALSE) {
12883                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init "
12884                     "failed!");
12885                 goto fail;
12886         }
12887 
12888         /*
12889          * IOC facts can change after a diag reset so all buffers that are
12890          * based on these numbers must be de-allocated and re-allocated.  Get
12891          * new IOC facts each time chip is initialized.
12892          */
12893         if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
12894                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed");
12895                 goto fail;
12896         }
12897 
12898         if (mptsas_alloc_active_slots(mpt, KM_SLEEP)) {
12899                 goto fail;
12900         }
12901         /*
12902          * Allocate request message frames, reply free queue, reply descriptor
12903          * post queue, and reply message frames using latest IOC facts.
12904          */
12905         if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) {
12906                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames failed");
12907                 goto fail;
12908         }
12909         if (mptsas_alloc_sense_bufs(mpt) == DDI_FAILURE) {
12910                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_sense_bufs failed");
12911                 goto fail;
12912         }
12913         if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) {
12914                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue failed!");
12915                 goto fail;
12916         }
12917         if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) {
12918                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue failed!");
12919                 goto fail;
12920         }
12921         if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) {
12922                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_reply_frames failed!");
12923                 goto fail;
12924         }
12925 
12926 mur:
12927         /*
12928          * Re-Initialize ioc to operational state
12929          */
12930         if (mptsas_ioc_init(mpt) == DDI_FAILURE) {
12931                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_init failed");
12932                 goto fail;
12933         }
12934 
12935         mptsas_alloc_reply_args(mpt);
12936 
12937         /*
12938          * Initialize reply post index.  Reply free index is initialized after
12939          * the next loop.
12940          */
12941         mpt->m_post_index = 0;
12942 
12943         /*
12944          * Initialize the Reply Free Queue with the physical addresses of our
12945          * reply frames.
12946          */
12947         cookie.dmac_address = mpt->m_reply_frame_dma_addr & 0xffffffffu;
12948         for (i = 0; i < mpt->m_max_replies; i++) {
12949                 ddi_put32(mpt->m_acc_free_queue_hdl,
12950                     &((uint32_t *)(void *)mpt->m_free_queue)[i],
12951                     cookie.dmac_address);
12952                 cookie.dmac_address += mpt->m_reply_frame_size;
12953         }
12954         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
12955             DDI_DMA_SYNC_FORDEV);
12956 
12957         /*
12958          * Initialize the reply free index to one past the last frame on the
12959          * queue.  This will signify that the queue is empty to start with.
12960          */
12961         mpt->m_free_index = i;
12962         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex, i);
12963 
12964         /*
12965          * Initialize the reply post queue to 0xFFFFFFFF,0xFFFFFFFF's.
12966          */
12967         for (i = 0; i < mpt->m_post_queue_depth; i++) {
12968                 ddi_put64(mpt->m_acc_post_queue_hdl,
12969                     &((uint64_t *)(void *)mpt->m_post_queue)[i],
12970                     0xFFFFFFFFFFFFFFFF);
12971         }
12972         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
12973             DDI_DMA_SYNC_FORDEV);
12974 
12975         /*
12976          * Enable ports
12977          */
12978         if (mptsas_ioc_enable_port(mpt) == DDI_FAILURE) {
12979                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_enable_port failed");
12980                 goto fail;
12981         }
12982 
12983         /*
12984          * enable events
12985          */
12986         if (mptsas_ioc_enable_event_notification(mpt)) {
12987                 mptsas_log(mpt, CE_WARN,
12988                     "mptsas_ioc_enable_event_notification failed");
12989                 goto fail;
12990         }
12991 
12992         /*
12993          * We need checks in attach and these.
12994          * chip_init is called in mult. places
12995          */
12996 
12997         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
12998             DDI_SUCCESS) ||
12999             (mptsas_check_dma_handle(mpt->m_dma_req_sense_hdl) !=
13000             DDI_SUCCESS) ||
13001             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
13002             DDI_SUCCESS) ||
13003             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
13004             DDI_SUCCESS) ||
13005             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
13006             DDI_SUCCESS) ||
13007             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
13008             DDI_SUCCESS)) {
13009                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
13010                 goto fail;
13011         }
13012 
13013         /* Check all acc handles */
13014         if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
13015             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
13016             DDI_SUCCESS) ||
13017             (mptsas_check_acc_handle(mpt->m_acc_req_sense_hdl) !=
13018             DDI_SUCCESS) ||
13019             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
13020             DDI_SUCCESS) ||
13021             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
13022             DDI_SUCCESS) ||
13023             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
13024             DDI_SUCCESS) ||
13025             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
13026             DDI_SUCCESS) ||
13027             (mptsas_check_acc_handle(mpt->m_config_handle) !=
13028             DDI_SUCCESS)) {
13029                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
13030                 goto fail;
13031         }
13032 
13033         return (DDI_SUCCESS);
13034 
13035 fail:
13036         return (DDI_FAILURE);
13037 }
13038 
13039 static int
13040 mptsas_get_pci_cap(mptsas_t *mpt)
13041 {
13042         ushort_t caps_ptr, cap, cap_count;
13043 
13044         if (mpt->m_config_handle == NULL)
13045                 return (FALSE);
13046         /*
13047          * Check if capabilities list is supported and if so,
13048          * get initial capabilities pointer and clear bits 0,1.
13049          */
13050         if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT)
13051             & PCI_STAT_CAP) {
13052                 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
13053                     PCI_CONF_CAP_PTR), 4);
13054         } else {
13055                 caps_ptr = PCI_CAP_NEXT_PTR_NULL;
13056         }
13057 
13058         /*
13059          * Walk capabilities if supported.
13060          */
13061         for (cap_count = 0; caps_ptr != PCI_CAP_NEXT_PTR_NULL; ) {
13062 
13063                 /*
13064                  * Check that we haven't exceeded the maximum number of
13065                  * capabilities and that the pointer is in a valid range.
13066                  */
13067                 if (++cap_count > 48) {
13068                         mptsas_log(mpt, CE_WARN,
13069                             "too many device capabilities.\n");
13070                         break;
13071                 }
13072                 if (caps_ptr < 64) {
13073                         mptsas_log(mpt, CE_WARN,
13074                             "capabilities pointer 0x%x out of range.\n",
13075                             caps_ptr);
13076                         break;
13077                 }
13078 
13079                 /*
13080                  * Get next capability and check that it is valid.
13081                  * For now, we only support power management.
13082                  */
13083                 cap = pci_config_get8(mpt->m_config_handle, caps_ptr);
13084                 switch (cap) {
13085                         case PCI_CAP_ID_PM:
13086                                 mptsas_log(mpt, CE_NOTE,
13087                                     "?mptsas%d supports power management.\n",
13088                                     mpt->m_instance);
13089                                 mpt->m_options |= MPTSAS_OPT_PM;
13090 
13091                                 /* Save PMCSR offset */
13092                                 mpt->m_pmcsr_offset = caps_ptr + PCI_PMCSR;
13093                                 break;
13094                         /*
13095                          * The following capabilities are valid.  Any others
13096                          * will cause a message to be logged.
13097                          */
13098                         case PCI_CAP_ID_VPD:
13099                         case PCI_CAP_ID_MSI:
13100                         case PCI_CAP_ID_PCIX:
13101                         case PCI_CAP_ID_PCI_E:
13102                         case PCI_CAP_ID_MSI_X:
13103                                 break;
13104                         default:
13105                                 mptsas_log(mpt, CE_NOTE,
13106                                     "?mptsas%d unrecognized capability "
13107                                     "0x%x.\n", mpt->m_instance, cap);
13108                                 break;
13109                 }
13110 
13111                 /*
13112                  * Get next capabilities pointer and clear bits 0,1.
13113                  */
13114                 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
13115                     (caps_ptr + PCI_CAP_NEXT_PTR)), 4);
13116         }
13117         return (TRUE);
13118 }
13119 
13120 static int
13121 mptsas_init_pm(mptsas_t *mpt)
13122 {
13123         char            pmc_name[16];
13124         char            *pmc[] = {
13125                                 NULL,
13126                                 "0=Off (PCI D3 State)",
13127                                 "3=On (PCI D0 State)",
13128                                 NULL
13129                         };
13130         uint16_t        pmcsr_stat;
13131 
13132         if (mptsas_get_pci_cap(mpt) == FALSE) {
13133                 return (DDI_FAILURE);
13134         }
13135         /*
13136          * If PCI's capability does not support PM, then don't need
13137          * to registe the pm-components
13138          */
13139         if (!(mpt->m_options & MPTSAS_OPT_PM))
13140                 return (DDI_SUCCESS);
13141         /*
13142          * If power management is supported by this chip, create
13143          * pm-components property for the power management framework
13144          */
13145         (void) sprintf(pmc_name, "NAME=mptsas%d", mpt->m_instance);
13146         pmc[0] = pmc_name;
13147         if (ddi_prop_update_string_array(DDI_DEV_T_NONE, mpt->m_dip,
13148             "pm-components", pmc, 3) != DDI_PROP_SUCCESS) {
13149                 mpt->m_options &= ~MPTSAS_OPT_PM;
13150                 mptsas_log(mpt, CE_WARN,
13151                     "mptsas%d: pm-component property creation failed.",
13152                     mpt->m_instance);
13153                 return (DDI_FAILURE);
13154         }
13155 
13156         /*
13157          * Power on device.
13158          */
13159         (void) pm_busy_component(mpt->m_dip, 0);
13160         pmcsr_stat = pci_config_get16(mpt->m_config_handle,
13161             mpt->m_pmcsr_offset);
13162         if ((pmcsr_stat & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_D0) {
13163                 mptsas_log(mpt, CE_WARN, "mptsas%d: Power up the device",
13164                     mpt->m_instance);
13165                 pci_config_put16(mpt->m_config_handle, mpt->m_pmcsr_offset,
13166                     PCI_PMCSR_D0);
13167         }
13168         if (pm_power_has_changed(mpt->m_dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) {
13169                 mptsas_log(mpt, CE_WARN, "pm_power_has_changed failed");
13170                 return (DDI_FAILURE);
13171         }
13172         mpt->m_power_level = PM_LEVEL_D0;
13173         /*
13174          * Set pm idle delay.
13175          */
13176         mpt->m_pm_idle_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
13177             mpt->m_dip, 0, "mptsas-pm-idle-delay", MPTSAS_PM_IDLE_TIMEOUT);
13178 
13179         return (DDI_SUCCESS);
13180 }
13181 
13182 static int
13183 mptsas_register_intrs(mptsas_t *mpt)
13184 {
13185         dev_info_t *dip;
13186         int intr_types;
13187 
13188         dip = mpt->m_dip;
13189 
13190         /* Get supported interrupt types */
13191         if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) {
13192                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_supported_types "
13193                     "failed\n");
13194                 return (FALSE);
13195         }
13196 
13197         NDBG6(("ddi_intr_get_supported_types() returned: 0x%x", intr_types));
13198 
13199         /*
13200          * Try MSI, but fall back to FIXED
13201          */
13202         if (mptsas_enable_msi && (intr_types & DDI_INTR_TYPE_MSI)) {
13203                 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_MSI) == DDI_SUCCESS) {
13204                         NDBG0(("Using MSI interrupt type"));
13205                         mpt->m_intr_type = DDI_INTR_TYPE_MSI;
13206                         return (TRUE);
13207                 }
13208         }
13209         if (intr_types & DDI_INTR_TYPE_FIXED) {
13210                 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_FIXED) == DDI_SUCCESS) {
13211                         NDBG0(("Using FIXED interrupt type"));
13212                         mpt->m_intr_type = DDI_INTR_TYPE_FIXED;
13213                         return (TRUE);
13214                 } else {
13215                         NDBG0(("FIXED interrupt registration failed"));
13216                         return (FALSE);
13217                 }
13218         }
13219 
13220         return (FALSE);
13221 }
13222 
13223 static void
13224 mptsas_unregister_intrs(mptsas_t *mpt)
13225 {
13226         mptsas_rem_intrs(mpt);
13227 }
13228 
13229 /*
13230  * mptsas_add_intrs:
13231  *
13232  * Register FIXED or MSI interrupts.
13233  */
13234 static int
13235 mptsas_add_intrs(mptsas_t *mpt, int intr_type)
13236 {
13237         dev_info_t      *dip = mpt->m_dip;
13238         int             avail, actual, count = 0;
13239         int             i, flag, ret;
13240 
13241         NDBG6(("mptsas_add_intrs:interrupt type 0x%x", intr_type));
13242 
13243         /* Get number of interrupts */
13244         ret = ddi_intr_get_nintrs(dip, intr_type, &count);
13245         if ((ret != DDI_SUCCESS) || (count <= 0)) {
13246                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_nintrs() failed, "
13247                     "ret %d count %d\n", ret, count);
13248 
13249                 return (DDI_FAILURE);
13250         }
13251 
13252         /* Get number of available interrupts */
13253         ret = ddi_intr_get_navail(dip, intr_type, &avail);
13254         if ((ret != DDI_SUCCESS) || (avail == 0)) {
13255                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_navail() failed, "
13256                     "ret %d avail %d\n", ret, avail);
13257 
13258                 return (DDI_FAILURE);
13259         }
13260 
13261         if (avail < count) {
13262                 mptsas_log(mpt, CE_NOTE, "ddi_intr_get_nvail returned %d, "
13263                     "navail() returned %d", count, avail);
13264         }
13265 
13266         /* Mpt only have one interrupt routine */
13267         if ((intr_type == DDI_INTR_TYPE_MSI) && (count > 1)) {
13268                 count = 1;
13269         }
13270 
13271         /* Allocate an array of interrupt handles */
13272         mpt->m_intr_size = count * sizeof (ddi_intr_handle_t);
13273         mpt->m_htable = kmem_alloc(mpt->m_intr_size, KM_SLEEP);
13274 
13275         flag = DDI_INTR_ALLOC_NORMAL;
13276 
13277         /* call ddi_intr_alloc() */
13278         ret = ddi_intr_alloc(dip, mpt->m_htable, intr_type, 0,
13279             count, &actual, flag);
13280 
13281         if ((ret != DDI_SUCCESS) || (actual == 0)) {
13282                 mptsas_log(mpt, CE_WARN, "ddi_intr_alloc() failed, ret %d\n",
13283                     ret);
13284                 kmem_free(mpt->m_htable, mpt->m_intr_size);
13285                 return (DDI_FAILURE);
13286         }
13287 
13288         /* use interrupt count returned or abort? */
13289         if (actual < count) {
13290                 mptsas_log(mpt, CE_NOTE, "Requested: %d, Received: %d\n",
13291                     count, actual);
13292         }
13293 
13294         mpt->m_intr_cnt = actual;
13295 
13296         /*
13297          * Get priority for first msi, assume remaining are all the same
13298          */
13299         if ((ret = ddi_intr_get_pri(mpt->m_htable[0],
13300             &mpt->m_intr_pri)) != DDI_SUCCESS) {
13301                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_pri() failed %d\n", ret);
13302 
13303                 /* Free already allocated intr */
13304                 for (i = 0; i < actual; i++) {
13305                         (void) ddi_intr_free(mpt->m_htable[i]);
13306                 }
13307 
13308                 kmem_free(mpt->m_htable, mpt->m_intr_size);
13309                 return (DDI_FAILURE);
13310         }
13311 
13312         /* Test for high level mutex */
13313         if (mpt->m_intr_pri >= ddi_intr_get_hilevel_pri()) {
13314                 mptsas_log(mpt, CE_WARN, "mptsas_add_intrs: "
13315                     "Hi level interrupt not supported\n");
13316 
13317                 /* Free already allocated intr */
13318                 for (i = 0; i < actual; i++) {
13319                         (void) ddi_intr_free(mpt->m_htable[i]);
13320                 }
13321 
13322                 kmem_free(mpt->m_htable, mpt->m_intr_size);
13323                 return (DDI_FAILURE);
13324         }
13325 
13326         /* Call ddi_intr_add_handler() */
13327         for (i = 0; i < actual; i++) {
13328                 if ((ret = ddi_intr_add_handler(mpt->m_htable[i], mptsas_intr,
13329                     (caddr_t)mpt, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
13330                         mptsas_log(mpt, CE_WARN, "ddi_intr_add_handler() "
13331                             "failed %d\n", ret);
13332 
13333                         /* Free already allocated intr */
13334                         for (i = 0; i < actual; i++) {
13335                                 (void) ddi_intr_free(mpt->m_htable[i]);
13336                         }
13337 
13338                         kmem_free(mpt->m_htable, mpt->m_intr_size);
13339                         return (DDI_FAILURE);
13340                 }
13341         }
13342 
13343         if ((ret = ddi_intr_get_cap(mpt->m_htable[0], &mpt->m_intr_cap))
13344             != DDI_SUCCESS) {
13345                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_cap() failed %d\n", ret);
13346 
13347                 /* Free already allocated intr */
13348                 for (i = 0; i < actual; i++) {
13349                         (void) ddi_intr_free(mpt->m_htable[i]);
13350                 }
13351 
13352                 kmem_free(mpt->m_htable, mpt->m_intr_size);
13353                 return (DDI_FAILURE);
13354         }
13355 
13356         /*
13357          * Enable interrupts
13358          */
13359         if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
13360                 /* Call ddi_intr_block_enable() for MSI interrupts */
13361                 (void) ddi_intr_block_enable(mpt->m_htable, mpt->m_intr_cnt);
13362         } else {
13363                 /* Call ddi_intr_enable for MSI or FIXED interrupts */
13364                 for (i = 0; i < mpt->m_intr_cnt; i++) {
13365                         (void) ddi_intr_enable(mpt->m_htable[i]);
13366                 }
13367         }
13368         return (DDI_SUCCESS);
13369 }
13370 
13371 /*
13372  * mptsas_rem_intrs:
13373  *
13374  * Unregister FIXED or MSI interrupts
13375  */
13376 static void
13377 mptsas_rem_intrs(mptsas_t *mpt)
13378 {
13379         int     i;
13380 
13381         NDBG6(("mptsas_rem_intrs"));
13382 
13383         /* Disable all interrupts */
13384         if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
13385                 /* Call ddi_intr_block_disable() */
13386                 (void) ddi_intr_block_disable(mpt->m_htable, mpt->m_intr_cnt);
13387         } else {
13388                 for (i = 0; i < mpt->m_intr_cnt; i++) {
13389                         (void) ddi_intr_disable(mpt->m_htable[i]);
13390                 }
13391         }
13392 
13393         /* Call ddi_intr_remove_handler() */
13394         for (i = 0; i < mpt->m_intr_cnt; i++) {
13395                 (void) ddi_intr_remove_handler(mpt->m_htable[i]);
13396                 (void) ddi_intr_free(mpt->m_htable[i]);
13397         }
13398 
13399         kmem_free(mpt->m_htable, mpt->m_intr_size);
13400 }
13401 
13402 /*
13403  * The IO fault service error handling callback function
13404  */
13405 /*ARGSUSED*/
13406 static int
13407 mptsas_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
13408 {
13409         /*
13410          * as the driver can always deal with an error in any dma or
13411          * access handle, we can just return the fme_status value.
13412          */
13413         pci_ereport_post(dip, err, NULL);
13414         return (err->fme_status);
13415 }
13416 
13417 /*
13418  * mptsas_fm_init - initialize fma capabilities and register with IO
13419  *               fault services.
13420  */
13421 static void
13422 mptsas_fm_init(mptsas_t *mpt)
13423 {
13424         /*
13425          * Need to change iblock to priority for new MSI intr
13426          */
13427         ddi_iblock_cookie_t     fm_ibc;
13428 
13429         /* Only register with IO Fault Services if we have some capability */
13430         if (mpt->m_fm_capabilities) {
13431                 /* Adjust access and dma attributes for FMA */
13432                 mpt->m_reg_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
13433                 mpt->m_msg_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
13434                 mpt->m_io_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
13435 
13436                 /*
13437                  * Register capabilities with IO Fault Services.
13438                  * mpt->m_fm_capabilities will be updated to indicate
13439                  * capabilities actually supported (not requested.)
13440                  */
13441                 ddi_fm_init(mpt->m_dip, &mpt->m_fm_capabilities, &fm_ibc);
13442 
13443                 /*
13444                  * Initialize pci ereport capabilities if ereport
13445                  * capable (should always be.)
13446                  */
13447                 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
13448                     DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13449                         pci_ereport_setup(mpt->m_dip);
13450                 }
13451 
13452                 /*
13453                  * Register error callback if error callback capable.
13454                  */
13455                 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13456                         ddi_fm_handler_register(mpt->m_dip,
13457                             mptsas_fm_error_cb, (void *) mpt);
13458                 }
13459         }
13460 }
13461 
13462 /*
13463  * mptsas_fm_fini - Releases fma capabilities and un-registers with IO
13464  *               fault services.
13465  *
13466  */
13467 static void
13468 mptsas_fm_fini(mptsas_t *mpt)
13469 {
13470         /* Only unregister FMA capabilities if registered */
13471         if (mpt->m_fm_capabilities) {
13472 
13473                 /*
13474                  * Un-register error callback if error callback capable.
13475                  */
13476 
13477                 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13478                         ddi_fm_handler_unregister(mpt->m_dip);
13479                 }
13480 
13481                 /*
13482                  * Release any resources allocated by pci_ereport_setup()
13483                  */
13484 
13485                 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
13486                     DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13487                         pci_ereport_teardown(mpt->m_dip);
13488                 }
13489 
13490                 /* Unregister from IO Fault Services */
13491                 ddi_fm_fini(mpt->m_dip);
13492 
13493                 /* Adjust access and dma attributes for FMA */
13494                 mpt->m_reg_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
13495                 mpt->m_msg_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
13496                 mpt->m_io_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
13497 
13498         }
13499 }
13500 
13501 int
13502 mptsas_check_acc_handle(ddi_acc_handle_t handle)
13503 {
13504         ddi_fm_error_t  de;
13505 
13506         if (handle == NULL)
13507                 return (DDI_FAILURE);
13508         ddi_fm_acc_err_get(handle, &de, DDI_FME_VER0);
13509         return (de.fme_status);
13510 }
13511 
13512 int
13513 mptsas_check_dma_handle(ddi_dma_handle_t handle)
13514 {
13515         ddi_fm_error_t  de;
13516 
13517         if (handle == NULL)
13518                 return (DDI_FAILURE);
13519         ddi_fm_dma_err_get(handle, &de, DDI_FME_VER0);
13520         return (de.fme_status);
13521 }
13522 
13523 void
13524 mptsas_fm_ereport(mptsas_t *mpt, char *detail)
13525 {
13526         uint64_t        ena;
13527         char            buf[FM_MAX_CLASS];
13528 
13529         (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
13530         ena = fm_ena_generate(0, FM_ENA_FMT1);
13531         if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities)) {
13532                 ddi_fm_ereport_post(mpt->m_dip, buf, ena, DDI_NOSLEEP,
13533                     FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
13534         }
13535 }
13536 
13537 static int
13538 mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
13539     uint16_t *dev_handle, mptsas_target_t **pptgt)
13540 {
13541         int             rval;
13542         uint32_t        dev_info;
13543         uint64_t        sas_wwn;
13544         mptsas_phymask_t phymask;
13545         uint8_t         physport, phynum, config, disk;
13546         uint64_t        devicename;
13547         uint16_t        pdev_hdl;
13548         mptsas_target_t *tmp_tgt = NULL;
13549         uint16_t        bay_num, enclosure, io_flags;
13550 
13551         ASSERT(*pptgt == NULL);
13552 
13553         rval = mptsas_get_sas_device_page0(mpt, page_address, dev_handle,
13554             &sas_wwn, &dev_info, &physport, &phynum, &pdev_hdl,
13555             &bay_num, &enclosure, &io_flags);
13556         if (rval != DDI_SUCCESS) {
13557                 rval = DEV_INFO_FAIL_PAGE0;
13558                 return (rval);
13559         }
13560 
13561         if ((dev_info & (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
13562             MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
13563             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) == NULL) {
13564                 rval = DEV_INFO_WRONG_DEVICE_TYPE;
13565                 return (rval);
13566         }
13567 
13568         /*
13569          * Check if the dev handle is for a Phys Disk. If so, set return value
13570          * and exit.  Don't add Phys Disks to hash.
13571          */
13572         for (config = 0; config < mpt->m_num_raid_configs; config++) {
13573                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
13574                         if (*dev_handle == mpt->m_raidconfig[config].
13575                             m_physdisk_devhdl[disk]) {
13576                                 rval = DEV_INFO_PHYS_DISK;
13577                                 return (rval);
13578                         }
13579                 }
13580         }
13581 
13582         /*
13583          * Get SATA Device Name from SAS device page0 for
13584          * sata device, if device name doesn't exist, set mta_wwn to
13585          * 0 for direct attached SATA. For the device behind the expander
13586          * we still can use STP address assigned by expander.
13587          */
13588         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
13589             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
13590                 /* alloc a temporary target to send the cmd to */
13591                 tmp_tgt = mptsas_tgt_alloc(mpt->m_tmp_targets, *dev_handle,
13592                     0, dev_info, 0, 0);
13593                 mutex_exit(&mpt->m_mutex);
13594 
13595                 devicename = mptsas_get_sata_guid(mpt, tmp_tgt, 0);
13596 
13597                 if (devicename == -1) {
13598                         mutex_enter(&mpt->m_mutex);
13599                         refhash_remove(mpt->m_tmp_targets, tmp_tgt);
13600                         rval = DEV_INFO_FAIL_GUID;
13601                         return (rval);
13602                 }
13603 
13604                 if (devicename != 0 && (((devicename >> 56) & 0xf0) == 0x50)) {
13605                         sas_wwn = devicename;
13606                 } else if (dev_info & MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH) {
13607                         sas_wwn = 0;
13608                 }
13609 
13610                 mutex_enter(&mpt->m_mutex);
13611                 refhash_remove(mpt->m_tmp_targets, tmp_tgt);
13612         }
13613 
13614         phymask = mptsas_physport_to_phymask(mpt, physport);
13615         *pptgt = mptsas_tgt_alloc(mpt->m_targets, *dev_handle, sas_wwn,
13616             dev_info, phymask, phynum);
13617         if (*pptgt == NULL) {
13618                 mptsas_log(mpt, CE_WARN, "Failed to allocated target"
13619                     "structure!");
13620                 rval = DEV_INFO_FAIL_ALLOC;
13621                 return (rval);
13622         }
13623         (*pptgt)->m_io_flags = io_flags;
13624         (*pptgt)->m_enclosure = enclosure;
13625         (*pptgt)->m_slot_num = bay_num;
13626         return (DEV_INFO_SUCCESS);
13627 }
13628 
13629 uint64_t
13630 mptsas_get_sata_guid(mptsas_t *mpt, mptsas_target_t *ptgt, int lun)
13631 {
13632         uint64_t        sata_guid = 0, *pwwn = NULL;
13633         int             target = ptgt->m_devhdl;
13634         uchar_t         *inq83 = NULL;
13635         int             inq83_len = 0xFF;
13636         uchar_t         *dblk = NULL;
13637         int             inq83_retry = 3;
13638         int             rval = DDI_FAILURE;
13639 
13640         inq83   = kmem_zalloc(inq83_len, KM_SLEEP);
13641 
13642 inq83_retry:
13643         rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
13644             inq83_len, NULL, 1);
13645         if (rval != DDI_SUCCESS) {
13646                 mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
13647                     "0x83 for target:%x, lun:%x failed!", target, lun);
13648                 sata_guid = -1;
13649                 goto out;
13650         }
13651         /* According to SAT2, the first descriptor is logic unit name */
13652         dblk = &inq83[4];
13653         if ((dblk[1] & 0x30) != 0) {
13654                 mptsas_log(mpt, CE_WARN, "!Descriptor is not lun associated.");
13655                 goto out;
13656         }
13657         pwwn = (uint64_t *)(void *)(&dblk[4]);
13658         if ((dblk[4] & 0xf0) == 0x50) {
13659                 sata_guid = BE_64(*pwwn);
13660                 goto out;
13661         } else if (dblk[4] == 'A') {
13662                 NDBG20(("SATA drive has no NAA format GUID."));
13663                 goto out;
13664         } else {
13665                 /* The data is not ready, wait and retry */
13666                 inq83_retry--;
13667                 if (inq83_retry <= 0) {
13668                         goto out;
13669                 }
13670                 NDBG20(("The GUID is not ready, retry..."));
13671                 delay(1 * drv_usectohz(1000000));
13672                 goto inq83_retry;
13673         }
13674 out:
13675         kmem_free(inq83, inq83_len);
13676         return (sata_guid);
13677 }
13678 
13679 static int
13680 mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun, uchar_t page,
13681     unsigned char *buf, int len, int *reallen, uchar_t evpd)
13682 {
13683         uchar_t                 cdb[CDB_GROUP0];
13684         struct scsi_address     ap;
13685         struct buf              *data_bp = NULL;
13686         int                     resid = 0;
13687         int                     ret = DDI_FAILURE;
13688 
13689         ASSERT(len <= 0xffff);
13690 
13691         ap.a_target = MPTSAS_INVALID_DEVHDL;
13692         ap.a_lun = (uchar_t)(lun);
13693         ap.a_hba_tran = mpt->m_tran;
13694 
13695         data_bp = scsi_alloc_consistent_buf(&ap,
13696             (struct buf *)NULL, len, B_READ, NULL_FUNC, NULL);
13697         if (data_bp == NULL) {
13698                 return (ret);
13699         }
13700         bzero(cdb, CDB_GROUP0);
13701         cdb[0] = SCMD_INQUIRY;
13702         cdb[1] = evpd;
13703         cdb[2] = page;
13704         cdb[3] = (len & 0xff00) >> 8;
13705         cdb[4] = (len & 0x00ff);
13706         cdb[5] = 0;
13707 
13708         ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP0, data_bp,
13709             &resid);
13710         if (ret == DDI_SUCCESS) {
13711                 if (reallen) {
13712                         *reallen = len - resid;
13713                 }
13714                 bcopy((caddr_t)data_bp->b_un.b_addr, buf, len);
13715         }
13716         if (data_bp) {
13717                 scsi_free_consistent_buf(data_bp);
13718         }
13719         return (ret);
13720 }
13721 
13722 static int
13723 mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
13724     mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
13725     int *resid)
13726 {
13727         struct scsi_pkt         *pktp = NULL;
13728         scsi_hba_tran_t         *tran_clone = NULL;
13729         mptsas_tgt_private_t    *tgt_private = NULL;
13730         int                     ret = DDI_FAILURE;
13731 
13732         /*
13733          * scsi_hba_tran_t->tran_tgt_private is used to pass the address
13734          * information to scsi_init_pkt, allocate a scsi_hba_tran structure
13735          * to simulate the cmds from sd
13736          */
13737         tran_clone = kmem_alloc(
13738             sizeof (scsi_hba_tran_t), KM_SLEEP);
13739         if (tran_clone == NULL) {
13740                 goto out;
13741         }
13742         bcopy((caddr_t)mpt->m_tran,
13743             (caddr_t)tran_clone, sizeof (scsi_hba_tran_t));
13744         tgt_private = kmem_alloc(
13745             sizeof (mptsas_tgt_private_t), KM_SLEEP);
13746         if (tgt_private == NULL) {
13747                 goto out;
13748         }
13749         tgt_private->t_lun = ap->a_lun;
13750         tgt_private->t_private = ptgt;
13751         tran_clone->tran_tgt_private = tgt_private;
13752         ap->a_hba_tran = tran_clone;
13753 
13754         pktp = scsi_init_pkt(ap, (struct scsi_pkt *)NULL,
13755             data_bp, cdblen, sizeof (struct scsi_arq_status),
13756             0, PKT_CONSISTENT, NULL, NULL);
13757         if (pktp == NULL) {
13758                 goto out;
13759         }
13760         bcopy(cdb, pktp->pkt_cdbp, cdblen);
13761         pktp->pkt_flags = FLAG_NOPARITY;
13762         if (scsi_poll(pktp) < 0) {
13763                 goto out;
13764         }
13765         if (((struct scsi_status *)pktp->pkt_scbp)->sts_chk) {
13766                 goto out;
13767         }
13768         if (resid != NULL) {
13769                 *resid = pktp->pkt_resid;
13770         }
13771 
13772         ret = DDI_SUCCESS;
13773 out:
13774         if (pktp) {
13775                 scsi_destroy_pkt(pktp);
13776         }
13777         if (tran_clone) {
13778                 kmem_free(tran_clone, sizeof (scsi_hba_tran_t));
13779         }
13780         if (tgt_private) {
13781                 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
13782         }
13783         return (ret);
13784 }
13785 static int
13786 mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy, int *lun)
13787 {
13788         char    *cp = NULL;
13789         char    *ptr = NULL;
13790         size_t  s = 0;
13791         char    *wwid_str = NULL;
13792         char    *lun_str = NULL;
13793         long    lunnum;
13794         long    phyid = -1;
13795         int     rc = DDI_FAILURE;
13796 
13797         ptr = name;
13798         ASSERT(ptr[0] == 'w' || ptr[0] == 'p');
13799         ptr++;
13800         if ((cp = strchr(ptr, ',')) == NULL) {
13801                 return (DDI_FAILURE);
13802         }
13803 
13804         wwid_str = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13805         s = (uintptr_t)cp - (uintptr_t)ptr;
13806 
13807         bcopy(ptr, wwid_str, s);
13808         wwid_str[s] = '\0';
13809 
13810         ptr = ++cp;
13811 
13812         if ((cp = strchr(ptr, '\0')) == NULL) {
13813                 goto out;
13814         }
13815         lun_str =  kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13816         s = (uintptr_t)cp - (uintptr_t)ptr;
13817 
13818         bcopy(ptr, lun_str, s);
13819         lun_str[s] = '\0';
13820 
13821         if (name[0] == 'p') {
13822                 rc = ddi_strtol(wwid_str, NULL, 0x10, &phyid);
13823         } else {
13824                 rc = scsi_wwnstr_to_wwn(wwid_str, wwid);
13825         }
13826         if (rc != DDI_SUCCESS)
13827                 goto out;
13828 
13829         if (phyid != -1) {
13830                 ASSERT(phyid < MPTSAS_MAX_PHYS);
13831                 *phy = (uint8_t)phyid;
13832         }
13833         rc = ddi_strtol(lun_str, NULL, 0x10, &lunnum);
13834         if (rc != 0)
13835                 goto out;
13836 
13837         *lun = (int)lunnum;
13838         rc = DDI_SUCCESS;
13839 out:
13840         if (wwid_str)
13841                 kmem_free(wwid_str, SCSI_MAXNAMELEN);
13842         if (lun_str)
13843                 kmem_free(lun_str, SCSI_MAXNAMELEN);
13844 
13845         return (rc);
13846 }
13847 
13848 /*
13849  * mptsas_parse_smp_name() is to parse sas wwn string
13850  * which format is "wWWN"
13851  */
13852 static int
13853 mptsas_parse_smp_name(char *name, uint64_t *wwn)
13854 {
13855         char    *ptr = name;
13856 
13857         if (*ptr != 'w') {
13858                 return (DDI_FAILURE);
13859         }
13860 
13861         ptr++;
13862         if (scsi_wwnstr_to_wwn(ptr, wwn)) {
13863                 return (DDI_FAILURE);
13864         }
13865         return (DDI_SUCCESS);
13866 }
13867 
13868 static int
13869 mptsas_bus_config(dev_info_t *pdip, uint_t flag,
13870     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
13871 {
13872         int             ret = NDI_FAILURE;
13873         int             circ = 0;
13874         int             circ1 = 0;
13875         mptsas_t        *mpt;
13876         char            *ptr = NULL;
13877         char            *devnm = NULL;
13878         uint64_t        wwid = 0;
13879         uint8_t         phy = 0xFF;
13880         int             lun = 0;
13881         uint_t          mflags = flag;
13882         int             bconfig = TRUE;
13883 
13884         if (scsi_hba_iport_unit_address(pdip) == 0) {
13885                 return (DDI_FAILURE);
13886         }
13887 
13888         mpt = DIP2MPT(pdip);
13889         if (!mpt) {
13890                 return (DDI_FAILURE);
13891         }
13892         /*
13893          * Hold the nexus across the bus_config
13894          */
13895         ndi_devi_enter(scsi_vhci_dip, &circ);
13896         ndi_devi_enter(pdip, &circ1);
13897         switch (op) {
13898         case BUS_CONFIG_ONE:
13899                 /* parse wwid/target name out of name given */
13900                 if ((ptr = strchr((char *)arg, '@')) == NULL) {
13901                         ret = NDI_FAILURE;
13902                         break;
13903                 }
13904                 ptr++;
13905                 if (strncmp((char *)arg, "smp", 3) == 0) {
13906                         /*
13907                          * This is a SMP target device
13908                          */
13909                         ret = mptsas_parse_smp_name(ptr, &wwid);
13910                         if (ret != DDI_SUCCESS) {
13911                                 ret = NDI_FAILURE;
13912                                 break;
13913                         }
13914                         ret = mptsas_config_smp(pdip, wwid, childp);
13915                 } else if ((ptr[0] == 'w') || (ptr[0] == 'p')) {
13916                         /*
13917                          * OBP could pass down a non-canonical form
13918                          * bootpath without LUN part when LUN is 0.
13919                          * So driver need adjust the string.
13920                          */
13921                         if (strchr(ptr, ',') == NULL) {
13922                                 devnm = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13923                                 (void) sprintf(devnm, "%s,0", (char *)arg);
13924                                 ptr = strchr(devnm, '@');
13925                                 ptr++;
13926                         }
13927 
13928                         /*
13929                          * The device path is wWWID format and the device
13930                          * is not SMP target device.
13931                          */
13932                         ret = mptsas_parse_address(ptr, &wwid, &phy, &lun);
13933                         if (ret != DDI_SUCCESS) {
13934                                 ret = NDI_FAILURE;
13935                                 break;
13936                         }
13937                         *childp = NULL;
13938                         if (ptr[0] == 'w') {
13939                                 ret = mptsas_config_one_addr(pdip, wwid,
13940                                     lun, childp);
13941                         } else if (ptr[0] == 'p') {
13942                                 ret = mptsas_config_one_phy(pdip, phy, lun,
13943                                     childp);
13944                         }
13945 
13946                         /*
13947                          * If this is CD/DVD device in OBP path, the
13948                          * ndi_busop_bus_config can be skipped as config one
13949                          * operation is done above.
13950                          */
13951                         if ((ret == NDI_SUCCESS) && (*childp != NULL) &&
13952                             (strcmp(ddi_node_name(*childp), "cdrom") == 0) &&
13953                             (strncmp((char *)arg, "disk", 4) == 0)) {
13954                                 bconfig = FALSE;
13955                                 ndi_hold_devi(*childp);
13956                         }
13957                 } else {
13958                         ret = NDI_FAILURE;
13959                         break;
13960                 }
13961 
13962                 /*
13963                  * DDI group instructed us to use this flag.
13964                  */
13965                 mflags |= NDI_MDI_FALLBACK;
13966                 break;
13967         case BUS_CONFIG_DRIVER:
13968         case BUS_CONFIG_ALL:
13969                 mptsas_config_all(pdip);
13970                 ret = NDI_SUCCESS;
13971                 break;
13972         }
13973 
13974         if ((ret == NDI_SUCCESS) && bconfig) {
13975                 ret = ndi_busop_bus_config(pdip, mflags, op,
13976                     (devnm == NULL) ? arg : devnm, childp, 0);
13977         }
13978 
13979         ndi_devi_exit(pdip, circ1);
13980         ndi_devi_exit(scsi_vhci_dip, circ);
13981         if (devnm != NULL)
13982                 kmem_free(devnm, SCSI_MAXNAMELEN);
13983         return (ret);
13984 }
13985 
13986 static int
13987 mptsas_probe_lun(dev_info_t *pdip, int lun, dev_info_t **dip,
13988     mptsas_target_t *ptgt)
13989 {
13990         int                     rval = DDI_FAILURE;
13991         struct scsi_inquiry     *sd_inq = NULL;
13992         mptsas_t                *mpt = DIP2MPT(pdip);
13993 
13994         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
13995 
13996         rval = mptsas_inquiry(mpt, ptgt, lun, 0, (uchar_t *)sd_inq,
13997             SUN_INQSIZE, 0, (uchar_t)0);
13998 
13999         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
14000                 rval = mptsas_create_lun(pdip, sd_inq, dip, ptgt, lun);
14001         } else {
14002                 rval = DDI_FAILURE;
14003         }
14004 
14005         kmem_free(sd_inq, SUN_INQSIZE);
14006         return (rval);
14007 }
14008 
14009 static int
14010 mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
14011     dev_info_t **lundip)
14012 {
14013         int             rval;
14014         mptsas_t                *mpt = DIP2MPT(pdip);
14015         int             phymask;
14016         mptsas_target_t *ptgt = NULL;
14017 
14018         /*
14019          * Get the physical port associated to the iport
14020          */
14021         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
14022             "phymask", 0);
14023 
14024         ptgt = mptsas_wwid_to_ptgt(mpt, phymask, sasaddr);
14025         if (ptgt == NULL) {
14026                 /*
14027                  * didn't match any device by searching
14028                  */
14029                 return (DDI_FAILURE);
14030         }
14031         /*
14032          * If the LUN already exists and the status is online,
14033          * we just return the pointer to dev_info_t directly.
14034          * For the mdi_pathinfo node, we'll handle it in
14035          * mptsas_create_virt_lun()
14036          * TODO should be also in mptsas_handle_dr
14037          */
14038 
14039         *lundip = mptsas_find_child_addr(pdip, sasaddr, lun);
14040         if (*lundip != NULL) {
14041                 /*
14042                  * TODO Another senario is, we hotplug the same disk
14043                  * on the same slot, the devhdl changed, is this
14044                  * possible?
14045                  * tgt_private->t_private != ptgt
14046                  */
14047                 if (sasaddr != ptgt->m_addr.mta_wwn) {
14048                         /*
14049                          * The device has changed although the devhdl is the
14050                          * same (Enclosure mapping mode, change drive on the
14051                          * same slot)
14052                          */
14053                         return (DDI_FAILURE);
14054                 }
14055                 return (DDI_SUCCESS);
14056         }
14057 
14058         if (phymask == 0) {
14059                 /*
14060                  * Configure IR volume
14061                  */
14062                 rval =  mptsas_config_raid(pdip, ptgt->m_devhdl, lundip);
14063                 return (rval);
14064         }
14065         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
14066 
14067         return (rval);
14068 }
14069 
14070 static int
14071 mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
14072     dev_info_t **lundip)
14073 {
14074         int             rval;
14075         mptsas_t        *mpt = DIP2MPT(pdip);
14076         mptsas_phymask_t phymask;
14077         mptsas_target_t *ptgt = NULL;
14078 
14079         /*
14080          * Get the physical port associated to the iport
14081          */
14082         phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
14083             "phymask", 0);
14084 
14085         ptgt = mptsas_phy_to_tgt(mpt, phymask, phy);
14086         if (ptgt == NULL) {
14087                 /*
14088                  * didn't match any device by searching
14089                  */
14090                 return (DDI_FAILURE);
14091         }
14092 
14093         /*
14094          * If the LUN already exists and the status is online,
14095          * we just return the pointer to dev_info_t directly.
14096          * For the mdi_pathinfo node, we'll handle it in
14097          * mptsas_create_virt_lun().
14098          */
14099 
14100         *lundip = mptsas_find_child_phy(pdip, phy);
14101         if (*lundip != NULL) {
14102                 return (DDI_SUCCESS);
14103         }
14104 
14105         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
14106 
14107         return (rval);
14108 }
14109 
14110 static int
14111 mptsas_retrieve_lundata(int lun_cnt, uint8_t *buf, uint16_t *lun_num,
14112     uint8_t *lun_addr_type)
14113 {
14114         uint32_t        lun_idx = 0;
14115 
14116         ASSERT(lun_num != NULL);
14117         ASSERT(lun_addr_type != NULL);
14118 
14119         lun_idx = (lun_cnt + 1) * MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
14120         /* determine report luns addressing type */
14121         switch (buf[lun_idx] & MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) {
14122                 /*
14123                  * Vendors in the field have been found to be concatenating
14124                  * bus/target/lun to equal the complete lun value instead
14125                  * of switching to flat space addressing
14126                  */
14127                 /* 00b - peripheral device addressing method */
14128         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_PERIPHERAL:
14129                 /* FALLTHRU */
14130                 /* 10b - logical unit addressing method */
14131         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT:
14132                 /* FALLTHRU */
14133                 /* 01b - flat space addressing method */
14134         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE:
14135                 /* byte0 bit0-5=msb lun byte1 bit0-7=lsb lun */
14136                 *lun_addr_type = (buf[lun_idx] &
14137                     MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) >> 6;
14138                 *lun_num = (buf[lun_idx] & 0x3F) << 8;
14139                 *lun_num |= buf[lun_idx + 1];
14140                 return (DDI_SUCCESS);
14141         default:
14142                 return (DDI_FAILURE);
14143         }
14144 }
14145 
14146 static int
14147 mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt)
14148 {
14149         struct buf              *repluns_bp = NULL;
14150         struct scsi_address     ap;
14151         uchar_t                 cdb[CDB_GROUP5];
14152         int                     ret = DDI_FAILURE;
14153         int                     retry = 0;
14154         int                     lun_list_len = 0;
14155         uint16_t                lun_num = 0;
14156         uint8_t                 lun_addr_type = 0;
14157         uint32_t                lun_cnt = 0;
14158         uint32_t                lun_total = 0;
14159         dev_info_t              *cdip = NULL;
14160         uint16_t                *saved_repluns = NULL;
14161         char                    *buffer = NULL;
14162         int                     buf_len = 128;
14163         mptsas_t                *mpt = DIP2MPT(pdip);
14164         uint64_t                sas_wwn = 0;
14165         uint8_t                 phy = 0xFF;
14166         uint32_t                dev_info = 0;
14167 
14168         mutex_enter(&mpt->m_mutex);
14169         sas_wwn = ptgt->m_addr.mta_wwn;
14170         phy = ptgt->m_phynum;
14171         dev_info = ptgt->m_deviceinfo;
14172         mutex_exit(&mpt->m_mutex);
14173 
14174         if (sas_wwn == 0) {
14175                 /*
14176                  * It's a SATA without Device Name
14177                  * So don't try multi-LUNs
14178                  */
14179                 if (mptsas_find_child_phy(pdip, phy)) {
14180                         return (DDI_SUCCESS);
14181                 } else {
14182                         /*
14183                          * need configure and create node
14184                          */
14185                         return (DDI_FAILURE);
14186                 }
14187         }
14188 
14189         /*
14190          * WWN (SAS address or Device Name exist)
14191          */
14192         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
14193             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
14194                 /*
14195                  * SATA device with Device Name
14196                  * So don't try multi-LUNs
14197                  */
14198                 if (mptsas_find_child_addr(pdip, sas_wwn, 0)) {
14199                         return (DDI_SUCCESS);
14200                 } else {
14201                         return (DDI_FAILURE);
14202                 }
14203         }
14204 
14205         do {
14206                 ap.a_target = MPTSAS_INVALID_DEVHDL;
14207                 ap.a_lun = 0;
14208                 ap.a_hba_tran = mpt->m_tran;
14209                 repluns_bp = scsi_alloc_consistent_buf(&ap,
14210                     (struct buf *)NULL, buf_len, B_READ, NULL_FUNC, NULL);
14211                 if (repluns_bp == NULL) {
14212                         retry++;
14213                         continue;
14214                 }
14215                 bzero(cdb, CDB_GROUP5);
14216                 cdb[0] = SCMD_REPORT_LUNS;
14217                 cdb[6] = (buf_len & 0xff000000) >> 24;
14218                 cdb[7] = (buf_len & 0x00ff0000) >> 16;
14219                 cdb[8] = (buf_len & 0x0000ff00) >> 8;
14220                 cdb[9] = (buf_len & 0x000000ff);
14221 
14222                 ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP5,
14223                     repluns_bp, NULL);
14224                 if (ret != DDI_SUCCESS) {
14225                         scsi_free_consistent_buf(repluns_bp);
14226                         retry++;
14227                         continue;
14228                 }
14229                 lun_list_len = BE_32(*(int *)((void *)(
14230                     repluns_bp->b_un.b_addr)));
14231                 if (buf_len >= lun_list_len + 8) {
14232                         ret = DDI_SUCCESS;
14233                         break;
14234                 }
14235                 scsi_free_consistent_buf(repluns_bp);
14236                 buf_len = lun_list_len + 8;
14237 
14238         } while (retry < 3);
14239 
14240         if (ret != DDI_SUCCESS)
14241                 return (ret);
14242         buffer = (char *)repluns_bp->b_un.b_addr;
14243         /*
14244          * find out the number of luns returned by the SCSI ReportLun call
14245          * and allocate buffer space
14246          */
14247         lun_total = lun_list_len / MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
14248         saved_repluns = kmem_zalloc(sizeof (uint16_t) * lun_total, KM_SLEEP);
14249         if (saved_repluns == NULL) {
14250                 scsi_free_consistent_buf(repluns_bp);
14251                 return (DDI_FAILURE);
14252         }
14253         for (lun_cnt = 0; lun_cnt < lun_total; lun_cnt++) {
14254                 if (mptsas_retrieve_lundata(lun_cnt, (uint8_t *)(buffer),
14255                     &lun_num, &lun_addr_type) != DDI_SUCCESS) {
14256                         continue;
14257                 }
14258                 saved_repluns[lun_cnt] = lun_num;
14259                 if (cdip = mptsas_find_child_addr(pdip, sas_wwn, lun_num))
14260                         ret = DDI_SUCCESS;
14261                 else
14262                         ret = mptsas_probe_lun(pdip, lun_num, &cdip,
14263                             ptgt);
14264                 if ((ret == DDI_SUCCESS) && (cdip != NULL)) {
14265                         (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip,
14266                             MPTSAS_DEV_GONE);
14267                 }
14268         }
14269         mptsas_offline_missed_luns(pdip, saved_repluns, lun_total, ptgt);
14270         kmem_free(saved_repluns, sizeof (uint16_t) * lun_total);
14271         scsi_free_consistent_buf(repluns_bp);
14272         return (DDI_SUCCESS);
14273 }
14274 
14275 static int
14276 mptsas_config_raid(dev_info_t *pdip, uint16_t target, dev_info_t **dip)
14277 {
14278         int                     rval = DDI_FAILURE;
14279         struct scsi_inquiry     *sd_inq = NULL;
14280         mptsas_t                *mpt = DIP2MPT(pdip);
14281         mptsas_target_t         *ptgt = NULL;
14282 
14283         mutex_enter(&mpt->m_mutex);
14284         ptgt = refhash_linear_search(mpt->m_targets,
14285             mptsas_target_eval_devhdl, &target);
14286         mutex_exit(&mpt->m_mutex);
14287         if (ptgt == NULL) {
14288                 mptsas_log(mpt, CE_WARN, "Volume with VolDevHandle of 0x%x "
14289                     "not found.", target);
14290                 return (rval);
14291         }
14292 
14293         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
14294         rval = mptsas_inquiry(mpt, ptgt, 0, 0, (uchar_t *)sd_inq,
14295             SUN_INQSIZE, 0, (uchar_t)0);
14296 
14297         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
14298                 rval = mptsas_create_phys_lun(pdip, sd_inq, NULL, dip, ptgt,
14299                     0);
14300         } else {
14301                 rval = DDI_FAILURE;
14302         }
14303 
14304         kmem_free(sd_inq, SUN_INQSIZE);
14305         return (rval);
14306 }
14307 
14308 /*
14309  * configure all RAID volumes for virtual iport
14310  */
14311 static void
14312 mptsas_config_all_viport(dev_info_t *pdip)
14313 {
14314         mptsas_t        *mpt = DIP2MPT(pdip);
14315         int             config, vol;
14316         int             target;
14317         dev_info_t      *lundip = NULL;
14318 
14319         /*
14320          * Get latest RAID info and search for any Volume DevHandles.  If any
14321          * are found, configure the volume.
14322          */
14323         mutex_enter(&mpt->m_mutex);
14324         for (config = 0; config < mpt->m_num_raid_configs; config++) {
14325                 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
14326                         if (mpt->m_raidconfig[config].m_raidvol[vol].m_israid
14327                             == 1) {
14328                                 target = mpt->m_raidconfig[config].
14329                                     m_raidvol[vol].m_raidhandle;
14330                                 mutex_exit(&mpt->m_mutex);
14331                                 (void) mptsas_config_raid(pdip, target,
14332                                     &lundip);
14333                                 mutex_enter(&mpt->m_mutex);
14334                         }
14335                 }
14336         }
14337         mutex_exit(&mpt->m_mutex);
14338 }
14339 
14340 static void
14341 mptsas_offline_missed_luns(dev_info_t *pdip, uint16_t *repluns,
14342     int lun_cnt, mptsas_target_t *ptgt)
14343 {
14344         dev_info_t      *child = NULL, *savechild = NULL;
14345         mdi_pathinfo_t  *pip = NULL, *savepip = NULL;
14346         uint64_t        sas_wwn, wwid;
14347         uint8_t         phy;
14348         int             lun;
14349         int             i;
14350         int             find;
14351         char            *addr;
14352         char            *nodename;
14353         mptsas_t        *mpt = DIP2MPT(pdip);
14354 
14355         mutex_enter(&mpt->m_mutex);
14356         wwid = ptgt->m_addr.mta_wwn;
14357         mutex_exit(&mpt->m_mutex);
14358 
14359         child = ddi_get_child(pdip);
14360         while (child) {
14361                 find = 0;
14362                 savechild = child;
14363                 child = ddi_get_next_sibling(child);
14364 
14365                 nodename = ddi_node_name(savechild);
14366                 if (strcmp(nodename, "smp") == 0) {
14367                         continue;
14368                 }
14369 
14370                 addr = ddi_get_name_addr(savechild);
14371                 if (addr == NULL) {
14372                         continue;
14373                 }
14374 
14375                 if (mptsas_parse_address(addr, &sas_wwn, &phy, &lun) !=
14376                     DDI_SUCCESS) {
14377                         continue;
14378                 }
14379 
14380                 if (wwid == sas_wwn) {
14381                         for (i = 0; i < lun_cnt; i++) {
14382                                 if (repluns[i] == lun) {
14383                                         find = 1;
14384                                         break;
14385                                 }
14386                         }
14387                 } else {
14388                         continue;
14389                 }
14390                 if (find == 0) {
14391                         /*
14392                          * The lun has not been there already
14393                          */
14394                         (void) mptsas_offline_lun(pdip, savechild, NULL,
14395                             NDI_DEVI_REMOVE);
14396                 }
14397         }
14398 
14399         pip = mdi_get_next_client_path(pdip, NULL);
14400         while (pip) {
14401                 find = 0;
14402                 savepip = pip;
14403                 addr = MDI_PI(pip)->pi_addr;
14404 
14405                 pip = mdi_get_next_client_path(pdip, pip);
14406 
14407                 if (addr == NULL) {
14408                         continue;
14409                 }
14410 
14411                 if (mptsas_parse_address(addr, &sas_wwn, &phy,
14412                     &lun) != DDI_SUCCESS) {
14413                         continue;
14414                 }
14415 
14416                 if (sas_wwn == wwid) {
14417                         for (i = 0; i < lun_cnt; i++) {
14418                                 if (repluns[i] == lun) {
14419                                         find = 1;
14420                                         break;
14421                                 }
14422                         }
14423                 } else {
14424                         continue;
14425                 }
14426 
14427                 if (find == 0) {
14428                         /*
14429                          * The lun has not been there already
14430                          */
14431                         (void) mptsas_offline_lun(pdip, NULL, savepip,
14432                             NDI_DEVI_REMOVE);
14433                 }
14434         }
14435 }
14436 
14437 void
14438 mptsas_update_hashtab(struct mptsas *mpt)
14439 {
14440         uint32_t        page_address;
14441         int             rval = 0;
14442         uint16_t        dev_handle;
14443         mptsas_target_t *ptgt = NULL;
14444         mptsas_smp_t    smp_node;
14445 
14446         /*
14447          * Get latest RAID info.
14448          */
14449         (void) mptsas_get_raid_info(mpt);
14450 
14451         dev_handle = mpt->m_smp_devhdl;
14452         for (; mpt->m_done_traverse_smp == 0; ) {
14453                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
14454                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)dev_handle;
14455                 if (mptsas_get_sas_expander_page0(mpt, page_address, &smp_node)
14456                     != DDI_SUCCESS) {
14457                         break;
14458                 }
14459                 mpt->m_smp_devhdl = dev_handle = smp_node.m_devhdl;
14460                 (void) mptsas_smp_alloc(mpt, &smp_node);
14461         }
14462 
14463         /*
14464          * Config target devices
14465          */
14466         dev_handle = mpt->m_dev_handle;
14467 
14468         /*
14469          * Do loop to get sas device page 0 by GetNextHandle till the
14470          * the last handle. If the sas device is a SATA/SSP target,
14471          * we try to config it.
14472          */
14473         for (; mpt->m_done_traverse_dev == 0; ) {
14474                 ptgt = NULL;
14475                 page_address =
14476                     (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
14477                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14478                     (uint32_t)dev_handle;
14479                 rval = mptsas_get_target_device_info(mpt, page_address,
14480                     &dev_handle, &ptgt);
14481                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
14482                     (rval == DEV_INFO_FAIL_ALLOC) ||
14483                     (rval == DEV_INFO_FAIL_GUID)) {
14484                         break;
14485                 }
14486 
14487                 mpt->m_dev_handle = dev_handle;
14488         }
14489 
14490 }
14491 
14492 void
14493 mptsas_update_driver_data(struct mptsas *mpt)
14494 {
14495         mptsas_target_t *tp;
14496         mptsas_smp_t *sp;
14497 
14498         ASSERT(MUTEX_HELD(&mpt->m_mutex));
14499 
14500         /*
14501          * TODO after hard reset, update the driver data structures
14502          * 1. update port/phymask mapping table mpt->m_phy_info
14503          * 2. invalid all the entries in hash table
14504          *    m_devhdl = 0xffff and m_deviceinfo = 0
14505          * 3. call sas_device_page/expander_page to update hash table
14506          */
14507         mptsas_update_phymask(mpt);
14508 
14509         /*
14510          * Remove all the devhdls for existing entries but leave their
14511          * addresses alone.  In update_hashtab() below, we'll find all
14512          * targets that are still present and reassociate them with
14513          * their potentially new devhdls.  Leaving the targets around in
14514          * this fashion allows them to be used on the tx waitq even
14515          * while IOC reset is occurring.
14516          */
14517         for (tp = refhash_first(mpt->m_targets); tp != NULL;
14518             tp = refhash_next(mpt->m_targets, tp)) {
14519                 tp->m_devhdl = MPTSAS_INVALID_DEVHDL;
14520                 tp->m_deviceinfo = 0;
14521                 tp->m_dr_flag = MPTSAS_DR_INACTIVE;
14522         }
14523         for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
14524             sp = refhash_next(mpt->m_smp_targets, sp)) {
14525                 sp->m_devhdl = MPTSAS_INVALID_DEVHDL;
14526                 sp->m_deviceinfo = 0;
14527         }
14528         mpt->m_done_traverse_dev = 0;
14529         mpt->m_done_traverse_smp = 0;
14530         mpt->m_dev_handle = mpt->m_smp_devhdl = MPTSAS_INVALID_DEVHDL;
14531         mptsas_update_hashtab(mpt);
14532 }
14533 
14534 static void
14535 mptsas_config_all(dev_info_t *pdip)
14536 {
14537         dev_info_t      *smpdip = NULL;
14538         mptsas_t        *mpt = DIP2MPT(pdip);
14539         int             phymask = 0;
14540         mptsas_phymask_t phy_mask;
14541         mptsas_target_t *ptgt = NULL;
14542         mptsas_smp_t    *psmp;
14543 
14544         /*
14545          * Get the phymask associated to the iport
14546          */
14547         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
14548             "phymask", 0);
14549 
14550         /*
14551          * Enumerate RAID volumes here (phymask == 0).
14552          */
14553         if (phymask == 0) {
14554                 mptsas_config_all_viport(pdip);
14555                 return;
14556         }
14557 
14558         mutex_enter(&mpt->m_mutex);
14559 
14560         if (!mpt->m_done_traverse_dev || !mpt->m_done_traverse_smp) {
14561                 mptsas_update_hashtab(mpt);
14562         }
14563 
14564         for (psmp = refhash_first(mpt->m_smp_targets); psmp != NULL;
14565             psmp = refhash_next(mpt->m_smp_targets, psmp)) {
14566                 phy_mask = psmp->m_addr.mta_phymask;
14567                 if (phy_mask == phymask) {
14568                         smpdip = NULL;
14569                         mutex_exit(&mpt->m_mutex);
14570                         (void) mptsas_online_smp(pdip, psmp, &smpdip);
14571                         mutex_enter(&mpt->m_mutex);
14572                 }
14573         }
14574 
14575         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
14576             ptgt = refhash_next(mpt->m_targets, ptgt)) {
14577                 phy_mask = ptgt->m_addr.mta_phymask;
14578                 if (phy_mask == phymask) {
14579                         mutex_exit(&mpt->m_mutex);
14580                         (void) mptsas_config_target(pdip, ptgt);
14581                         mutex_enter(&mpt->m_mutex);
14582                 }
14583         }
14584         mutex_exit(&mpt->m_mutex);
14585 }
14586 
14587 static int
14588 mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt)
14589 {
14590         int             rval = DDI_FAILURE;
14591         dev_info_t      *tdip;
14592 
14593         rval = mptsas_config_luns(pdip, ptgt);
14594         if (rval != DDI_SUCCESS) {
14595                 /*
14596                  * The return value means the SCMD_REPORT_LUNS
14597                  * did not execute successfully. The target maybe
14598                  * doesn't support such command.
14599                  */
14600                 rval = mptsas_probe_lun(pdip, 0, &tdip, ptgt);
14601         }
14602         return (rval);
14603 }
14604 
14605 /*
14606  * Return fail if not all the childs/paths are freed.
14607  * if there is any path under the HBA, the return value will be always fail
14608  * because we didn't call mdi_pi_free for path
14609  */
14610 static int
14611 mptsas_offline_target(dev_info_t *pdip, char *name)
14612 {
14613         dev_info_t              *child = NULL, *prechild = NULL;
14614         mdi_pathinfo_t          *pip = NULL, *savepip = NULL;
14615         int                     tmp_rval, rval = DDI_SUCCESS;
14616         char                    *addr, *cp;
14617         size_t                  s;
14618         mptsas_t                *mpt = DIP2MPT(pdip);
14619 
14620         child = ddi_get_child(pdip);
14621         while (child) {
14622                 addr = ddi_get_name_addr(child);
14623                 prechild = child;
14624                 child = ddi_get_next_sibling(child);
14625 
14626                 if (addr == NULL) {
14627                         continue;
14628                 }
14629                 if ((cp = strchr(addr, ',')) == NULL) {
14630                         continue;
14631                 }
14632 
14633                 s = (uintptr_t)cp - (uintptr_t)addr;
14634 
14635                 if (strncmp(addr, name, s) != 0) {
14636                         continue;
14637                 }
14638 
14639                 tmp_rval = mptsas_offline_lun(pdip, prechild, NULL,
14640                     NDI_DEVI_REMOVE);
14641                 if (tmp_rval != DDI_SUCCESS) {
14642                         rval = DDI_FAILURE;
14643                         if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
14644                             prechild, MPTSAS_DEV_GONE) !=
14645                             DDI_PROP_SUCCESS) {
14646                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
14647                                     "unable to create property for "
14648                                     "SAS %s (MPTSAS_DEV_GONE)", addr);
14649                         }
14650                 }
14651         }
14652 
14653         pip = mdi_get_next_client_path(pdip, NULL);
14654         while (pip) {
14655                 addr = MDI_PI(pip)->pi_addr;
14656                 savepip = pip;
14657                 pip = mdi_get_next_client_path(pdip, pip);
14658                 if (addr == NULL) {
14659                         continue;
14660                 }
14661 
14662                 if ((cp = strchr(addr, ',')) == NULL) {
14663                         continue;
14664                 }
14665 
14666                 s = (uintptr_t)cp - (uintptr_t)addr;
14667 
14668                 if (strncmp(addr, name, s) != 0) {
14669                         continue;
14670                 }
14671 
14672                 (void) mptsas_offline_lun(pdip, NULL, savepip,
14673                     NDI_DEVI_REMOVE);
14674                 /*
14675                  * driver will not invoke mdi_pi_free, so path will not
14676                  * be freed forever, return DDI_FAILURE.
14677                  */
14678                 rval = DDI_FAILURE;
14679         }
14680         return (rval);
14681 }
14682 
14683 static int
14684 mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
14685     mdi_pathinfo_t *rpip, uint_t flags)
14686 {
14687         int             rval = DDI_FAILURE;
14688         char            *devname;
14689         dev_info_t      *cdip, *parent;
14690 
14691         if (rpip != NULL) {
14692                 parent = scsi_vhci_dip;
14693                 cdip = mdi_pi_get_client(rpip);
14694         } else if (rdip != NULL) {
14695                 parent = pdip;
14696                 cdip = rdip;
14697         } else {
14698                 return (DDI_FAILURE);
14699         }
14700 
14701         /*
14702          * Make sure node is attached otherwise
14703          * it won't have related cache nodes to
14704          * clean up.  i_ddi_devi_attached is
14705          * similiar to i_ddi_node_state(cdip) >=
14706          * DS_ATTACHED.
14707          */
14708         if (i_ddi_devi_attached(cdip)) {
14709 
14710                 /* Get full devname */
14711                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
14712                 (void) ddi_deviname(cdip, devname);
14713                 /* Clean cache */
14714                 (void) devfs_clean(parent, devname + 1,
14715                     DV_CLEAN_FORCE);
14716                 kmem_free(devname, MAXNAMELEN + 1);
14717         }
14718         if (rpip != NULL) {
14719                 if (MDI_PI_IS_OFFLINE(rpip)) {
14720                         rval = DDI_SUCCESS;
14721                 } else {
14722                         rval = mdi_pi_offline(rpip, 0);
14723                 }
14724         } else {
14725                 rval = ndi_devi_offline(cdip, flags);
14726         }
14727 
14728         return (rval);
14729 }
14730 
14731 static dev_info_t *
14732 mptsas_find_smp_child(dev_info_t *parent, char *str_wwn)
14733 {
14734         dev_info_t      *child = NULL;
14735         char            *smp_wwn = NULL;
14736 
14737         child = ddi_get_child(parent);
14738         while (child) {
14739                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
14740                     DDI_PROP_DONTPASS, SMP_WWN, &smp_wwn)
14741                     != DDI_SUCCESS) {
14742                         child = ddi_get_next_sibling(child);
14743                         continue;
14744                 }
14745 
14746                 if (strcmp(smp_wwn, str_wwn) == 0) {
14747                         ddi_prop_free(smp_wwn);
14748                         break;
14749                 }
14750                 child = ddi_get_next_sibling(child);
14751                 ddi_prop_free(smp_wwn);
14752         }
14753         return (child);
14754 }
14755 
14756 static int
14757 mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, uint_t flags)
14758 {
14759         int             rval = DDI_FAILURE;
14760         char            *devname;
14761         char            wwn_str[MPTSAS_WWN_STRLEN];
14762         dev_info_t      *cdip;
14763 
14764         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
14765 
14766         cdip = mptsas_find_smp_child(pdip, wwn_str);
14767 
14768         if (cdip == NULL)
14769                 return (DDI_SUCCESS);
14770 
14771         /*
14772          * Make sure node is attached otherwise
14773          * it won't have related cache nodes to
14774          * clean up.  i_ddi_devi_attached is
14775          * similiar to i_ddi_node_state(cdip) >=
14776          * DS_ATTACHED.
14777          */
14778         if (i_ddi_devi_attached(cdip)) {
14779 
14780                 /* Get full devname */
14781                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
14782                 (void) ddi_deviname(cdip, devname);
14783                 /* Clean cache */
14784                 (void) devfs_clean(pdip, devname + 1,
14785                     DV_CLEAN_FORCE);
14786                 kmem_free(devname, MAXNAMELEN + 1);
14787         }
14788 
14789         rval = ndi_devi_offline(cdip, flags);
14790 
14791         return (rval);
14792 }
14793 
14794 static dev_info_t *
14795 mptsas_find_child(dev_info_t *pdip, char *name)
14796 {
14797         dev_info_t      *child = NULL;
14798         char            *rname = NULL;
14799         int             rval = DDI_FAILURE;
14800 
14801         rname = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14802 
14803         child = ddi_get_child(pdip);
14804         while (child) {
14805                 rval = mptsas_name_child(child, rname, SCSI_MAXNAMELEN);
14806                 if (rval != DDI_SUCCESS) {
14807                         child = ddi_get_next_sibling(child);
14808                         bzero(rname, SCSI_MAXNAMELEN);
14809                         continue;
14810                 }
14811 
14812                 if (strcmp(rname, name) == 0) {
14813                         break;
14814                 }
14815                 child = ddi_get_next_sibling(child);
14816                 bzero(rname, SCSI_MAXNAMELEN);
14817         }
14818 
14819         kmem_free(rname, SCSI_MAXNAMELEN);
14820 
14821         return (child);
14822 }
14823 
14824 
14825 static dev_info_t *
14826 mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr, int lun)
14827 {
14828         dev_info_t      *child = NULL;
14829         char            *name = NULL;
14830         char            *addr = NULL;
14831 
14832         name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14833         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14834         (void) sprintf(name, "%016"PRIx64, sasaddr);
14835         (void) sprintf(addr, "w%s,%x", name, lun);
14836         child = mptsas_find_child(pdip, addr);
14837         kmem_free(name, SCSI_MAXNAMELEN);
14838         kmem_free(addr, SCSI_MAXNAMELEN);
14839         return (child);
14840 }
14841 
14842 static dev_info_t *
14843 mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy)
14844 {
14845         dev_info_t      *child;
14846         char            *addr;
14847 
14848         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14849         (void) sprintf(addr, "p%x,0", phy);
14850         child = mptsas_find_child(pdip, addr);
14851         kmem_free(addr, SCSI_MAXNAMELEN);
14852         return (child);
14853 }
14854 
14855 static mdi_pathinfo_t *
14856 mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy)
14857 {
14858         mdi_pathinfo_t  *path;
14859         char            *addr = NULL;
14860 
14861         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14862         (void) sprintf(addr, "p%x,0", phy);
14863         path = mdi_pi_find(pdip, NULL, addr);
14864         kmem_free(addr, SCSI_MAXNAMELEN);
14865         return (path);
14866 }
14867 
14868 static mdi_pathinfo_t *
14869 mptsas_find_path_addr(dev_info_t *parent, uint64_t sasaddr, int lun)
14870 {
14871         mdi_pathinfo_t  *path;
14872         char            *name = NULL;
14873         char            *addr = NULL;
14874 
14875         name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14876         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14877         (void) sprintf(name, "%016"PRIx64, sasaddr);
14878         (void) sprintf(addr, "w%s,%x", name, lun);
14879         path = mdi_pi_find(parent, NULL, addr);
14880         kmem_free(name, SCSI_MAXNAMELEN);
14881         kmem_free(addr, SCSI_MAXNAMELEN);
14882 
14883         return (path);
14884 }
14885 
14886 static int
14887 mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
14888     dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
14889 {
14890         int                     i = 0;
14891         uchar_t                 *inq83 = NULL;
14892         int                     inq83_len1 = 0xFF;
14893         int                     inq83_len = 0;
14894         int                     rval = DDI_FAILURE;
14895         ddi_devid_t             devid;
14896         char                    *guid = NULL;
14897         int                     target = ptgt->m_devhdl;
14898         mdi_pathinfo_t          *pip = NULL;
14899         mptsas_t                *mpt = DIP2MPT(pdip);
14900 
14901         /*
14902          * For DVD/CD ROM and tape devices and optical
14903          * devices, we won't try to enumerate them under
14904          * scsi_vhci, so no need to try page83
14905          */
14906         if (sd_inq && (sd_inq->inq_dtype == DTYPE_RODIRECT ||
14907             sd_inq->inq_dtype == DTYPE_OPTICAL ||
14908             sd_inq->inq_dtype == DTYPE_ESI))
14909                 goto create_lun;
14910 
14911         /*
14912          * The LCA returns good SCSI status, but corrupt page 83 data the first
14913          * time it is queried. The solution is to keep trying to request page83
14914          * and verify the GUID is not (DDI_NOT_WELL_FORMED) in
14915          * mptsas_inq83_retry_timeout seconds. If the timeout expires, driver
14916          * give up to get VPD page at this stage and fail the enumeration.
14917          */
14918 
14919         inq83   = kmem_zalloc(inq83_len1, KM_SLEEP);
14920 
14921         for (i = 0; i < mptsas_inq83_retry_timeout; i++) {
14922                 rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
14923                     inq83_len1, &inq83_len, 1);
14924                 if (rval != 0) {
14925                         mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
14926                             "0x83 for target:%x, lun:%x failed!", target, lun);
14927                         if (mptsas_physical_bind_failed_page_83 != B_FALSE)
14928                                 goto create_lun;
14929                         goto out;
14930                 }
14931                 /*
14932                  * create DEVID from inquiry data
14933                  */
14934                 if ((rval = ddi_devid_scsi_encode(
14935                     DEVID_SCSI_ENCODE_VERSION_LATEST, NULL, (uchar_t *)sd_inq,
14936                     sizeof (struct scsi_inquiry), NULL, 0, inq83,
14937                     (size_t)inq83_len, &devid)) == DDI_SUCCESS) {
14938                         /*
14939                          * extract GUID from DEVID
14940                          */
14941                         guid = ddi_devid_to_guid(devid);
14942 
14943                         /*
14944                          * Do not enable MPXIO if the strlen(guid) is greater
14945                          * than MPTSAS_MAX_GUID_LEN, this constrain would be
14946                          * handled by framework later.
14947                          */
14948                         if (guid && (strlen(guid) > MPTSAS_MAX_GUID_LEN)) {
14949                                 ddi_devid_free_guid(guid);
14950                                 guid = NULL;
14951                                 if (mpt->m_mpxio_enable == TRUE) {
14952                                         mptsas_log(mpt, CE_NOTE, "!Target:%x, "
14953                                             "lun:%x doesn't have a valid GUID, "
14954                                             "multipathing for this drive is "
14955                                             "not enabled", target, lun);
14956                                 }
14957                         }
14958 
14959                         /*
14960                          * devid no longer needed
14961                          */
14962                         ddi_devid_free(devid);
14963                         break;
14964                 } else if (rval == DDI_NOT_WELL_FORMED) {
14965                         /*
14966                          * return value of ddi_devid_scsi_encode equal to
14967                          * DDI_NOT_WELL_FORMED means DEVID_RETRY, it worth
14968                          * to retry inquiry page 0x83 and get GUID.
14969                          */
14970                         NDBG20(("Not well formed devid, retry..."));
14971                         delay(1 * drv_usectohz(1000000));
14972                         continue;
14973                 } else {
14974                         mptsas_log(mpt, CE_WARN, "!Encode devid failed for "
14975                             "path target:%x, lun:%x", target, lun);
14976                         rval = DDI_FAILURE;
14977                         goto create_lun;
14978                 }
14979         }
14980 
14981         if (i == mptsas_inq83_retry_timeout) {
14982                 mptsas_log(mpt, CE_WARN, "!Repeated page83 requests timeout "
14983                     "for path target:%x, lun:%x", target, lun);
14984         }
14985 
14986         rval = DDI_FAILURE;
14987 
14988 create_lun:
14989         if ((guid != NULL) && (mpt->m_mpxio_enable == TRUE)) {
14990                 rval = mptsas_create_virt_lun(pdip, sd_inq, guid, lun_dip, &pip,
14991                     ptgt, lun);
14992         }
14993         if (rval != DDI_SUCCESS) {
14994                 rval = mptsas_create_phys_lun(pdip, sd_inq, guid, lun_dip,
14995                     ptgt, lun);
14996 
14997         }
14998 out:
14999         if (guid != NULL) {
15000                 /*
15001                  * guid no longer needed
15002                  */
15003                 ddi_devid_free_guid(guid);
15004         }
15005         if (inq83 != NULL)
15006                 kmem_free(inq83, inq83_len1);
15007         return (rval);
15008 }
15009 
15010 static int
15011 mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *inq, char *guid,
15012     dev_info_t **lun_dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt, int lun)
15013 {
15014         int                     target;
15015         char                    *nodename = NULL;
15016         char                    **compatible = NULL;
15017         int                     ncompatible     = 0;
15018         int                     mdi_rtn = MDI_FAILURE;
15019         int                     rval = DDI_FAILURE;
15020         char                    *old_guid = NULL;
15021         mptsas_t                *mpt = DIP2MPT(pdip);
15022         char                    *lun_addr = NULL;
15023         char                    *wwn_str = NULL;
15024         char                    *attached_wwn_str = NULL;
15025         char                    *component = NULL;
15026         uint8_t                 phy = 0xFF;
15027         uint64_t                sas_wwn;
15028         int64_t                 lun64 = 0;
15029         uint32_t                devinfo;
15030         uint16_t                dev_hdl;
15031         uint16_t                pdev_hdl;
15032         uint64_t                dev_sas_wwn;
15033         uint64_t                pdev_sas_wwn;
15034         uint32_t                pdev_info;
15035         uint8_t                 physport;
15036         uint8_t                 phy_id;
15037         uint32_t                page_address;
15038         uint16_t                bay_num, enclosure, io_flags;
15039         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
15040         uint32_t                dev_info;
15041 
15042         mutex_enter(&mpt->m_mutex);
15043         target = ptgt->m_devhdl;
15044         sas_wwn = ptgt->m_addr.mta_wwn;
15045         devinfo = ptgt->m_deviceinfo;
15046         phy = ptgt->m_phynum;
15047         mutex_exit(&mpt->m_mutex);
15048 
15049         if (sas_wwn) {
15050                 *pip = mptsas_find_path_addr(pdip, sas_wwn, lun);
15051         } else {
15052                 *pip = mptsas_find_path_phy(pdip, phy);
15053         }
15054 
15055         if (*pip != NULL) {
15056                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
15057                 ASSERT(*lun_dip != NULL);
15058                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, *lun_dip,
15059                     (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
15060                     MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
15061                         if (strncmp(guid, old_guid, strlen(guid)) == 0) {
15062                                 /*
15063                                  * Same path back online again.
15064                                  */
15065                                 (void) ddi_prop_free(old_guid);
15066                                 if ((!MDI_PI_IS_ONLINE(*pip)) &&
15067                                     (!MDI_PI_IS_STANDBY(*pip)) &&
15068                                     (ptgt->m_tgt_unconfigured == 0)) {
15069                                         rval = mdi_pi_online(*pip, 0);
15070                                         mutex_enter(&mpt->m_mutex);
15071                                         ptgt->m_led_status = 0;
15072                                         (void) mptsas_flush_led_status(mpt,
15073                                             ptgt);
15074                                         mutex_exit(&mpt->m_mutex);
15075                                 } else {
15076                                         rval = DDI_SUCCESS;
15077                                 }
15078                                 if (rval != DDI_SUCCESS) {
15079                                         mptsas_log(mpt, CE_WARN, "path:target: "
15080                                             "%x, lun:%x online failed!", target,
15081                                             lun);
15082                                         *pip = NULL;
15083                                         *lun_dip = NULL;
15084                                 }
15085                                 return (rval);
15086                         } else {
15087                                 /*
15088                                  * The GUID of the LUN has changed which maybe
15089                                  * because customer mapped another volume to the
15090                                  * same LUN.
15091                                  */
15092                                 mptsas_log(mpt, CE_WARN, "The GUID of the "
15093                                     "target:%x, lun:%x was changed, maybe "
15094                                     "because someone mapped another volume "
15095                                     "to the same LUN", target, lun);
15096                                 (void) ddi_prop_free(old_guid);
15097                                 if (!MDI_PI_IS_OFFLINE(*pip)) {
15098                                         rval = mdi_pi_offline(*pip, 0);
15099                                         if (rval != MDI_SUCCESS) {
15100                                                 mptsas_log(mpt, CE_WARN, "path:"
15101                                                     "target:%x, lun:%x offline "
15102                                                     "failed!", target, lun);
15103                                                 *pip = NULL;
15104                                                 *lun_dip = NULL;
15105                                                 return (DDI_FAILURE);
15106                                         }
15107                                 }
15108                                 if (mdi_pi_free(*pip, 0) != MDI_SUCCESS) {
15109                                         mptsas_log(mpt, CE_WARN, "path:target:"
15110                                             "%x, lun:%x free failed!", target,
15111                                             lun);
15112                                         *pip = NULL;
15113                                         *lun_dip = NULL;
15114                                         return (DDI_FAILURE);
15115                                 }
15116                         }
15117                 } else {
15118                         mptsas_log(mpt, CE_WARN, "Can't get client-guid "
15119                             "property for path:target:%x, lun:%x", target, lun);
15120                         *pip = NULL;
15121                         *lun_dip = NULL;
15122                         return (DDI_FAILURE);
15123                 }
15124         }
15125         scsi_hba_nodename_compatible_get(inq, NULL,
15126             inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
15127 
15128         /*
15129          * if nodename can't be determined then print a message and skip it
15130          */
15131         if (nodename == NULL) {
15132                 mptsas_log(mpt, CE_WARN, "mptsas driver found no compatible "
15133                     "driver for target%d lun %d dtype:0x%02x", target, lun,
15134                     inq->inq_dtype);
15135                 return (DDI_FAILURE);
15136         }
15137 
15138         wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
15139         /* The property is needed by MPAPI */
15140         (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
15141 
15142         lun_addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
15143         if (guid) {
15144                 (void) sprintf(lun_addr, "w%s,%x", wwn_str, lun);
15145                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15146         } else {
15147                 (void) sprintf(lun_addr, "p%x,%x", phy, lun);
15148                 (void) sprintf(wwn_str, "p%x", phy);
15149         }
15150 
15151         mdi_rtn = mdi_pi_alloc_compatible(pdip, nodename,
15152             guid, lun_addr, compatible, ncompatible,
15153             0, pip);
15154         if (mdi_rtn == MDI_SUCCESS) {
15155 
15156                 if (mdi_prop_update_string(*pip, MDI_GUID,
15157                     guid) != DDI_SUCCESS) {
15158                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15159                             "create prop for target %d lun %d (MDI_GUID)",
15160                             target, lun);
15161                         mdi_rtn = MDI_FAILURE;
15162                         goto virt_create_done;
15163                 }
15164 
15165                 if (mdi_prop_update_int(*pip, LUN_PROP,
15166                     lun) != DDI_SUCCESS) {
15167                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15168                             "create prop for target %d lun %d (LUN_PROP)",
15169                             target, lun);
15170                         mdi_rtn = MDI_FAILURE;
15171                         goto virt_create_done;
15172                 }
15173                 lun64 = (int64_t)lun;
15174                 if (mdi_prop_update_int64(*pip, LUN64_PROP,
15175                     lun64) != DDI_SUCCESS) {
15176                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15177                             "create prop for target %d (LUN64_PROP)",
15178                             target);
15179                         mdi_rtn = MDI_FAILURE;
15180                         goto virt_create_done;
15181                 }
15182                 if (mdi_prop_update_string_array(*pip, "compatible",
15183                     compatible, ncompatible) !=
15184                     DDI_PROP_SUCCESS) {
15185                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15186                             "create prop for target %d lun %d (COMPATIBLE)",
15187                             target, lun);
15188                         mdi_rtn = MDI_FAILURE;
15189                         goto virt_create_done;
15190                 }
15191                 if (sas_wwn && (mdi_prop_update_string(*pip,
15192                     SCSI_ADDR_PROP_TARGET_PORT, wwn_str) != DDI_PROP_SUCCESS)) {
15193                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15194                             "create prop for target %d lun %d "
15195                             "(target-port)", target, lun);
15196                         mdi_rtn = MDI_FAILURE;
15197                         goto virt_create_done;
15198                 } else if ((sas_wwn == 0) && (mdi_prop_update_int(*pip,
15199                     "sata-phy", phy) != DDI_PROP_SUCCESS)) {
15200                         /*
15201                          * Direct attached SATA device without DeviceName
15202                          */
15203                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15204                             "create prop for SAS target %d lun %d "
15205                             "(sata-phy)", target, lun);
15206                         mdi_rtn = MDI_FAILURE;
15207                         goto virt_create_done;
15208                 }
15209                 mutex_enter(&mpt->m_mutex);
15210 
15211                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15212                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15213                     (uint32_t)ptgt->m_devhdl;
15214                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15215                     &dev_hdl, &dev_sas_wwn, &dev_info, &physport,
15216                     &phy_id, &pdev_hdl, &bay_num, &enclosure, &io_flags);
15217                 if (rval != DDI_SUCCESS) {
15218                         mutex_exit(&mpt->m_mutex);
15219                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
15220                             "parent device for handle %d", page_address);
15221                         mdi_rtn = MDI_FAILURE;
15222                         goto virt_create_done;
15223                 }
15224 
15225                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15226                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
15227                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15228                     &dev_hdl, &pdev_sas_wwn, &pdev_info, &physport,
15229                     &phy_id, &pdev_hdl, &bay_num, &enclosure, &io_flags);
15230                 if (rval != DDI_SUCCESS) {
15231                         mutex_exit(&mpt->m_mutex);
15232                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
15233                             "device info for handle %d", page_address);
15234                         mdi_rtn = MDI_FAILURE;
15235                         goto virt_create_done;
15236                 }
15237 
15238                 mutex_exit(&mpt->m_mutex);
15239 
15240                 /*
15241                  * If this device direct attached to the controller
15242                  * set the attached-port to the base wwid
15243                  */
15244                 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15245                     != DEVINFO_DIRECT_ATTACHED) {
15246                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15247                             pdev_sas_wwn);
15248                 } else {
15249                         /*
15250                          * Update the iport's attached-port to guid
15251                          */
15252                         if (sas_wwn == 0) {
15253                                 (void) sprintf(wwn_str, "p%x", phy);
15254                         } else {
15255                                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15256                         }
15257                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
15258                             pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
15259                             DDI_PROP_SUCCESS) {
15260                                 mptsas_log(mpt, CE_WARN,
15261                                     "mptsas unable to create "
15262                                     "property for iport target-port"
15263                                     " %s (sas_wwn)",
15264                                     wwn_str);
15265                                 mdi_rtn = MDI_FAILURE;
15266                                 goto virt_create_done;
15267                         }
15268 
15269                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15270                             mpt->un.m_base_wwid);
15271                 }
15272 
15273                 if (mdi_prop_update_string(*pip,
15274                     SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
15275                     DDI_PROP_SUCCESS) {
15276                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15277                             "property for iport attached-port %s (sas_wwn)",
15278                             attached_wwn_str);
15279                         mdi_rtn = MDI_FAILURE;
15280                         goto virt_create_done;
15281                 }
15282 
15283 
15284                 if (inq->inq_dtype == 0) {
15285                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
15286                         /*
15287                          * set obp path for pathinfo
15288                          */
15289                         (void) snprintf(component, MAXPATHLEN,
15290                             "disk@%s", lun_addr);
15291 
15292                         if (mdi_pi_pathname_obp_set(*pip, component) !=
15293                             DDI_SUCCESS) {
15294                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
15295                                     "unable to set obp-path for object %s",
15296                                     component);
15297                                 mdi_rtn = MDI_FAILURE;
15298                                 goto virt_create_done;
15299                         }
15300                 }
15301 
15302                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
15303                 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
15304                     MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
15305                         if ((ndi_prop_update_int(DDI_DEV_T_NONE, *lun_dip,
15306                             "pm-capable", 1)) !=
15307                             DDI_PROP_SUCCESS) {
15308                                 mptsas_log(mpt, CE_WARN, "mptsas driver"
15309                                     "failed to create pm-capable "
15310                                     "property, target %d", target);
15311                                 mdi_rtn = MDI_FAILURE;
15312                                 goto virt_create_done;
15313                         }
15314                 }
15315                 /*
15316                  * Create the phy-num property
15317                  */
15318                 if (mdi_prop_update_int(*pip, "phy-num",
15319                     ptgt->m_phynum) != DDI_SUCCESS) {
15320                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15321                             "create phy-num property for target %d lun %d",
15322                             target, lun);
15323                         mdi_rtn = MDI_FAILURE;
15324                         goto virt_create_done;
15325                 }
15326                 NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr));
15327                 mdi_rtn = mdi_pi_online(*pip, 0);
15328                 if (mdi_rtn == MDI_SUCCESS) {
15329                         mutex_enter(&mpt->m_mutex);
15330                         ptgt->m_led_status = 0;
15331                         (void) mptsas_flush_led_status(mpt, ptgt);
15332                         mutex_exit(&mpt->m_mutex);
15333                 }
15334                 if (mdi_rtn == MDI_NOT_SUPPORTED) {
15335                         mdi_rtn = MDI_FAILURE;
15336                 }
15337 virt_create_done:
15338                 if (*pip && mdi_rtn != MDI_SUCCESS) {
15339                         (void) mdi_pi_free(*pip, 0);
15340                         *pip = NULL;
15341                         *lun_dip = NULL;
15342                 }
15343         }
15344 
15345         scsi_hba_nodename_compatible_free(nodename, compatible);
15346         if (lun_addr != NULL) {
15347                 kmem_free(lun_addr, SCSI_MAXNAMELEN);
15348         }
15349         if (wwn_str != NULL) {
15350                 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
15351         }
15352         if (component != NULL) {
15353                 kmem_free(component, MAXPATHLEN);
15354         }
15355 
15356         return ((mdi_rtn == MDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
15357 }
15358 
15359 static int
15360 mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *inq,
15361     char *guid, dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
15362 {
15363         int                     target;
15364         int                     rval;
15365         int                     ndi_rtn = NDI_FAILURE;
15366         uint64_t                be_sas_wwn;
15367         char                    *nodename = NULL;
15368         char                    **compatible = NULL;
15369         int                     ncompatible = 0;
15370         int                     instance = 0;
15371         mptsas_t                *mpt = DIP2MPT(pdip);
15372         char                    *wwn_str = NULL;
15373         char                    *component = NULL;
15374         char                    *attached_wwn_str = NULL;
15375         uint8_t                 phy = 0xFF;
15376         uint64_t                sas_wwn;
15377         uint32_t                devinfo;
15378         uint16_t                dev_hdl;
15379         uint16_t                pdev_hdl;
15380         uint64_t                pdev_sas_wwn;
15381         uint64_t                dev_sas_wwn;
15382         uint32_t                pdev_info;
15383         uint8_t                 physport;
15384         uint8_t                 phy_id;
15385         uint32_t                page_address;
15386         uint16_t                bay_num, enclosure, io_flags;
15387         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
15388         uint32_t                dev_info;
15389         int64_t                 lun64 = 0;
15390 
15391         mutex_enter(&mpt->m_mutex);
15392         target = ptgt->m_devhdl;
15393         sas_wwn = ptgt->m_addr.mta_wwn;
15394         devinfo = ptgt->m_deviceinfo;
15395         phy = ptgt->m_phynum;
15396         mutex_exit(&mpt->m_mutex);
15397 
15398         /*
15399          * generate compatible property with binding-set "mpt"
15400          */
15401         scsi_hba_nodename_compatible_get(inq, NULL, inq->inq_dtype, NULL,
15402             &nodename, &compatible, &ncompatible);
15403 
15404         /*
15405          * if nodename can't be determined then print a message and skip it
15406          */
15407         if (nodename == NULL) {
15408                 mptsas_log(mpt, CE_WARN, "mptsas found no compatible driver "
15409                     "for target %d lun %d", target, lun);
15410                 return (DDI_FAILURE);
15411         }
15412 
15413         ndi_rtn = ndi_devi_alloc(pdip, nodename,
15414             DEVI_SID_NODEID, lun_dip);
15415 
15416         /*
15417          * if lun alloc success, set props
15418          */
15419         if (ndi_rtn == NDI_SUCCESS) {
15420 
15421                 if (ndi_prop_update_int(DDI_DEV_T_NONE,
15422                     *lun_dip, LUN_PROP, lun) !=
15423                     DDI_PROP_SUCCESS) {
15424                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15425                             "property for target %d lun %d (LUN_PROP)",
15426                             target, lun);
15427                         ndi_rtn = NDI_FAILURE;
15428                         goto phys_create_done;
15429                 }
15430 
15431                 lun64 = (int64_t)lun;
15432                 if (ndi_prop_update_int64(DDI_DEV_T_NONE,
15433                     *lun_dip, LUN64_PROP, lun64) !=
15434                     DDI_PROP_SUCCESS) {
15435                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15436                             "property for target %d lun64 %d (LUN64_PROP)",
15437                             target, lun);
15438                         ndi_rtn = NDI_FAILURE;
15439                         goto phys_create_done;
15440                 }
15441                 if (ndi_prop_update_string_array(DDI_DEV_T_NONE,
15442                     *lun_dip, "compatible", compatible, ncompatible)
15443                     != DDI_PROP_SUCCESS) {
15444                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15445                             "property for target %d lun %d (COMPATIBLE)",
15446                             target, lun);
15447                         ndi_rtn = NDI_FAILURE;
15448                         goto phys_create_done;
15449                 }
15450 
15451                 /*
15452                  * We need the SAS WWN for non-multipath devices, so
15453                  * we'll use the same property as that multipathing
15454                  * devices need to present for MPAPI. If we don't have
15455                  * a WWN (e.g. parallel SCSI), don't create the prop.
15456                  */
15457                 wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
15458                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15459                 if (sas_wwn && ndi_prop_update_string(DDI_DEV_T_NONE,
15460                     *lun_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str)
15461                     != DDI_PROP_SUCCESS) {
15462                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15463                             "create property for SAS target %d lun %d "
15464                             "(target-port)", target, lun);
15465                         ndi_rtn = NDI_FAILURE;
15466                         goto phys_create_done;
15467                 }
15468 
15469                 be_sas_wwn = BE_64(sas_wwn);
15470                 if (sas_wwn && ndi_prop_update_byte_array(
15471                     DDI_DEV_T_NONE, *lun_dip, "port-wwn",
15472                     (uchar_t *)&be_sas_wwn, 8) != DDI_PROP_SUCCESS) {
15473                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15474                             "create property for SAS target %d lun %d "
15475                             "(port-wwn)", target, lun);
15476                         ndi_rtn = NDI_FAILURE;
15477                         goto phys_create_done;
15478                 } else if ((sas_wwn == 0) && (ndi_prop_update_int(
15479                     DDI_DEV_T_NONE, *lun_dip, "sata-phy", phy) !=
15480                     DDI_PROP_SUCCESS)) {
15481                         /*
15482                          * Direct attached SATA device without DeviceName
15483                          */
15484                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15485                             "create property for SAS target %d lun %d "
15486                             "(sata-phy)", target, lun);
15487                         ndi_rtn = NDI_FAILURE;
15488                         goto phys_create_done;
15489                 }
15490 
15491                 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
15492                     *lun_dip, SAS_PROP) != DDI_PROP_SUCCESS) {
15493                         mptsas_log(mpt, CE_WARN, "mptsas unable to"
15494                             "create property for SAS target %d lun %d"
15495                             " (SAS_PROP)", target, lun);
15496                         ndi_rtn = NDI_FAILURE;
15497                         goto phys_create_done;
15498                 }
15499                 if (guid && (ndi_prop_update_string(DDI_DEV_T_NONE,
15500                     *lun_dip, NDI_GUID, guid) != DDI_SUCCESS)) {
15501                         mptsas_log(mpt, CE_WARN, "mptsas unable "
15502                             "to create guid property for target %d "
15503                             "lun %d", target, lun);
15504                         ndi_rtn = NDI_FAILURE;
15505                         goto phys_create_done;
15506                 }
15507 
15508                 /*
15509                  * The following code is to set properties for SM-HBA support,
15510                  * it doesn't apply to RAID volumes
15511                  */
15512                 if (ptgt->m_addr.mta_phymask == 0)
15513                         goto phys_raid_lun;
15514 
15515                 mutex_enter(&mpt->m_mutex);
15516 
15517                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15518                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15519                     (uint32_t)ptgt->m_devhdl;
15520                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15521                     &dev_hdl, &dev_sas_wwn, &dev_info,
15522                     &physport, &phy_id, &pdev_hdl,
15523                     &bay_num, &enclosure, &io_flags);
15524                 if (rval != DDI_SUCCESS) {
15525                         mutex_exit(&mpt->m_mutex);
15526                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
15527                             "parent device for handle %d.", page_address);
15528                         ndi_rtn = NDI_FAILURE;
15529                         goto phys_create_done;
15530                 }
15531 
15532                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15533                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
15534                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15535                     &dev_hdl, &pdev_sas_wwn, &pdev_info, &physport,
15536                     &phy_id, &pdev_hdl, &bay_num, &enclosure, &io_flags);
15537                 if (rval != DDI_SUCCESS) {
15538                         mutex_exit(&mpt->m_mutex);
15539                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15540                             "device for handle %d.", page_address);
15541                         ndi_rtn = NDI_FAILURE;
15542                         goto phys_create_done;
15543                 }
15544 
15545                 mutex_exit(&mpt->m_mutex);
15546 
15547                 /*
15548                  * If this device direct attached to the controller
15549                  * set the attached-port to the base wwid
15550                  */
15551                 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15552                     != DEVINFO_DIRECT_ATTACHED) {
15553                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15554                             pdev_sas_wwn);
15555                 } else {
15556                         /*
15557                          * Update the iport's attached-port to guid
15558                          */
15559                         if (sas_wwn == 0) {
15560                                 (void) sprintf(wwn_str, "p%x", phy);
15561                         } else {
15562                                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15563                         }
15564                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
15565                             pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
15566                             DDI_PROP_SUCCESS) {
15567                                 mptsas_log(mpt, CE_WARN,
15568                                     "mptsas unable to create "
15569                                     "property for iport target-port"
15570                                     " %s (sas_wwn)",
15571                                     wwn_str);
15572                                 ndi_rtn = NDI_FAILURE;
15573                                 goto phys_create_done;
15574                         }
15575 
15576                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15577                             mpt->un.m_base_wwid);
15578                 }
15579 
15580                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15581                     *lun_dip, SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
15582                     DDI_PROP_SUCCESS) {
15583                         mptsas_log(mpt, CE_WARN,
15584                             "mptsas unable to create "
15585                             "property for iport attached-port %s (sas_wwn)",
15586                             attached_wwn_str);
15587                         ndi_rtn = NDI_FAILURE;
15588                         goto phys_create_done;
15589                 }
15590 
15591                 if (IS_SATA_DEVICE(dev_info)) {
15592                         if (ndi_prop_update_string(DDI_DEV_T_NONE,
15593                             *lun_dip, MPTSAS_VARIANT, "sata") !=
15594                             DDI_PROP_SUCCESS) {
15595                                 mptsas_log(mpt, CE_WARN,
15596                                     "mptsas unable to create "
15597                                     "property for device variant ");
15598                                 ndi_rtn = NDI_FAILURE;
15599                                 goto phys_create_done;
15600                         }
15601                 }
15602 
15603                 if (IS_ATAPI_DEVICE(dev_info)) {
15604                         if (ndi_prop_update_string(DDI_DEV_T_NONE,
15605                             *lun_dip, MPTSAS_VARIANT, "atapi") !=
15606                             DDI_PROP_SUCCESS) {
15607                                 mptsas_log(mpt, CE_WARN,
15608                                     "mptsas unable to create "
15609                                     "property for device variant ");
15610                                 ndi_rtn = NDI_FAILURE;
15611                                 goto phys_create_done;
15612                         }
15613                 }
15614 
15615 phys_raid_lun:
15616                 /*
15617                  * if this is a SAS controller, and the target is a SATA
15618                  * drive, set the 'pm-capable' property for sd and if on
15619                  * an OPL platform, also check if this is an ATAPI
15620                  * device.
15621                  */
15622                 instance = ddi_get_instance(mpt->m_dip);
15623                 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
15624                     MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
15625                         NDBG2(("mptsas%d: creating pm-capable property, "
15626                             "target %d", instance, target));
15627 
15628                         if ((ndi_prop_update_int(DDI_DEV_T_NONE,
15629                             *lun_dip, "pm-capable", 1)) !=
15630                             DDI_PROP_SUCCESS) {
15631                                 mptsas_log(mpt, CE_WARN, "mptsas "
15632                                     "failed to create pm-capable "
15633                                     "property, target %d", target);
15634                                 ndi_rtn = NDI_FAILURE;
15635                                 goto phys_create_done;
15636                         }
15637 
15638                 }
15639 
15640                 if ((inq->inq_dtype == 0) || (inq->inq_dtype == 5)) {
15641                         /*
15642                          * add 'obp-path' properties for devinfo
15643                          */
15644                         bzero(wwn_str, sizeof (wwn_str));
15645                         (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
15646                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
15647                         if (guid) {
15648                                 (void) snprintf(component, MAXPATHLEN,
15649                                     "disk@w%s,%x", wwn_str, lun);
15650                         } else {
15651                                 (void) snprintf(component, MAXPATHLEN,
15652                                     "disk@p%x,%x", phy, lun);
15653                         }
15654                         if (ddi_pathname_obp_set(*lun_dip, component)
15655                             != DDI_SUCCESS) {
15656                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
15657                                     "unable to set obp-path for SAS "
15658                                     "object %s", component);
15659                                 ndi_rtn = NDI_FAILURE;
15660                                 goto phys_create_done;
15661                         }
15662                 }
15663                 /*
15664                  * Create the phy-num property for non-raid disk
15665                  */
15666                 if (ptgt->m_addr.mta_phymask != 0) {
15667                         if (ndi_prop_update_int(DDI_DEV_T_NONE,
15668                             *lun_dip, "phy-num", ptgt->m_phynum) !=
15669                             DDI_PROP_SUCCESS) {
15670                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
15671                                     "failed to create phy-num property for "
15672                                     "target %d", target);
15673                                 ndi_rtn = NDI_FAILURE;
15674                                 goto phys_create_done;
15675                         }
15676                 }
15677 phys_create_done:
15678                 /*
15679                  * If props were setup ok, online the lun
15680                  */
15681                 if (ndi_rtn == NDI_SUCCESS) {
15682                         /*
15683                          * Try to online the new node
15684                          */
15685                         ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
15686                 }
15687                 if (ndi_rtn == NDI_SUCCESS) {
15688                         mutex_enter(&mpt->m_mutex);
15689                         ptgt->m_led_status = 0;
15690                         (void) mptsas_flush_led_status(mpt, ptgt);
15691                         mutex_exit(&mpt->m_mutex);
15692                 }
15693 
15694                 /*
15695                  * If success set rtn flag, else unwire alloc'd lun
15696                  */
15697                 if (ndi_rtn != NDI_SUCCESS) {
15698                         NDBG12(("mptsas driver unable to online "
15699                             "target %d lun %d", target, lun));
15700                         ndi_prop_remove_all(*lun_dip);
15701                         (void) ndi_devi_free(*lun_dip);
15702                         *lun_dip = NULL;
15703                 }
15704         }
15705 
15706         scsi_hba_nodename_compatible_free(nodename, compatible);
15707 
15708         if (wwn_str != NULL) {
15709                 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
15710         }
15711         if (component != NULL) {
15712                 kmem_free(component, MAXPATHLEN);
15713         }
15714 
15715 
15716         return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
15717 }
15718 
15719 static int
15720 mptsas_probe_smp(dev_info_t *pdip, uint64_t wwn)
15721 {
15722         mptsas_t        *mpt = DIP2MPT(pdip);
15723         struct smp_device smp_sd;
15724 
15725         /* XXX An HBA driver should not be allocating an smp_device. */
15726         bzero(&smp_sd, sizeof (struct smp_device));
15727         smp_sd.smp_sd_address.smp_a_hba_tran = mpt->m_smptran;
15728         bcopy(&wwn, smp_sd.smp_sd_address.smp_a_wwn, SAS_WWN_BYTE_SIZE);
15729 
15730         if (smp_probe(&smp_sd) != DDI_PROBE_SUCCESS)
15731                 return (NDI_FAILURE);
15732         return (NDI_SUCCESS);
15733 }
15734 
15735 static int
15736 mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn, dev_info_t **smp_dip)
15737 {
15738         mptsas_t        *mpt = DIP2MPT(pdip);
15739         mptsas_smp_t    *psmp = NULL;
15740         int             rval;
15741         int             phymask;
15742 
15743         /*
15744          * Get the physical port associated to the iport
15745          * PHYMASK TODO
15746          */
15747         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
15748             "phymask", 0);
15749         /*
15750          * Find the smp node in hash table with specified sas address and
15751          * physical port
15752          */
15753         psmp = mptsas_wwid_to_psmp(mpt, phymask, sas_wwn);
15754         if (psmp == NULL) {
15755                 return (DDI_FAILURE);
15756         }
15757 
15758         rval = mptsas_online_smp(pdip, psmp, smp_dip);
15759 
15760         return (rval);
15761 }
15762 
15763 static int
15764 mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
15765     dev_info_t **smp_dip)
15766 {
15767         char            wwn_str[MPTSAS_WWN_STRLEN];
15768         char            attached_wwn_str[MPTSAS_WWN_STRLEN];
15769         int             ndi_rtn = NDI_FAILURE;
15770         int             rval = 0;
15771         mptsas_smp_t    dev_info;
15772         uint32_t        page_address;
15773         mptsas_t        *mpt = DIP2MPT(pdip);
15774         uint16_t        dev_hdl;
15775         uint64_t        sas_wwn;
15776         uint64_t        smp_sas_wwn;
15777         uint8_t         physport;
15778         uint8_t         phy_id;
15779         uint16_t        pdev_hdl;
15780         uint8_t         numphys = 0;
15781         uint16_t        i = 0;
15782         char            phymask[MPTSAS_MAX_PHYS];
15783         char            *iport = NULL;
15784         mptsas_phymask_t        phy_mask = 0;
15785         uint16_t        attached_devhdl;
15786         uint16_t        bay_num, enclosure, io_flags;
15787 
15788         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
15789 
15790         /*
15791          * Probe smp device, prevent the node of removed device from being
15792          * configured succesfully
15793          */
15794         if (mptsas_probe_smp(pdip, smp_node->m_addr.mta_wwn) != NDI_SUCCESS) {
15795                 return (DDI_FAILURE);
15796         }
15797 
15798         if ((*smp_dip = mptsas_find_smp_child(pdip, wwn_str)) != NULL) {
15799                 return (DDI_SUCCESS);
15800         }
15801 
15802         ndi_rtn = ndi_devi_alloc(pdip, "smp", DEVI_SID_NODEID, smp_dip);
15803 
15804         /*
15805          * if lun alloc success, set props
15806          */
15807         if (ndi_rtn == NDI_SUCCESS) {
15808                 /*
15809                  * Set the flavor of the child to be SMP flavored
15810                  */
15811                 ndi_flavor_set(*smp_dip, SCSA_FLAVOR_SMP);
15812 
15813                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15814                     *smp_dip, SMP_WWN, wwn_str) !=
15815                     DDI_PROP_SUCCESS) {
15816                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15817                             "property for smp device %s (sas_wwn)",
15818                             wwn_str);
15819                         ndi_rtn = NDI_FAILURE;
15820                         goto smp_create_done;
15821                 }
15822                 (void) sprintf(wwn_str, "w%"PRIx64, smp_node->m_addr.mta_wwn);
15823                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15824                     *smp_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str) !=
15825                     DDI_PROP_SUCCESS) {
15826                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15827                             "property for iport target-port %s (sas_wwn)",
15828                             wwn_str);
15829                         ndi_rtn = NDI_FAILURE;
15830                         goto smp_create_done;
15831                 }
15832 
15833                 mutex_enter(&mpt->m_mutex);
15834 
15835                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
15836                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | smp_node->m_devhdl;
15837                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
15838                     &dev_info);
15839                 if (rval != DDI_SUCCESS) {
15840                         mutex_exit(&mpt->m_mutex);
15841                         mptsas_log(mpt, CE_WARN,
15842                             "mptsas unable to get expander "
15843                             "parent device info for %x", page_address);
15844                         ndi_rtn = NDI_FAILURE;
15845                         goto smp_create_done;
15846                 }
15847 
15848                 smp_node->m_pdevhdl = dev_info.m_pdevhdl;
15849                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15850                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15851                     (uint32_t)dev_info.m_pdevhdl;
15852                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15853                     &dev_hdl, &sas_wwn, &smp_node->m_pdevinfo, &physport,
15854                     &phy_id, &pdev_hdl, &bay_num, &enclosure, &io_flags);
15855                 if (rval != DDI_SUCCESS) {
15856                         mutex_exit(&mpt->m_mutex);
15857                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
15858                             "device info for %x", page_address);
15859                         ndi_rtn = NDI_FAILURE;
15860                         goto smp_create_done;
15861                 }
15862 
15863                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15864                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15865                     (uint32_t)dev_info.m_devhdl;
15866                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15867                     &dev_hdl, &smp_sas_wwn, &smp_node->m_deviceinfo,
15868                     &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure,
15869                     &io_flags);
15870                 if (rval != DDI_SUCCESS) {
15871                         mutex_exit(&mpt->m_mutex);
15872                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
15873                             "device info for %x", page_address);
15874                         ndi_rtn = NDI_FAILURE;
15875                         goto smp_create_done;
15876                 }
15877                 mutex_exit(&mpt->m_mutex);
15878 
15879                 /*
15880                  * If this smp direct attached to the controller
15881                  * set the attached-port to the base wwid
15882                  */
15883                 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15884                     != DEVINFO_DIRECT_ATTACHED) {
15885                         (void) sprintf(attached_wwn_str, "w%016"PRIx64,
15886                             sas_wwn);
15887                 } else {
15888                         (void) sprintf(attached_wwn_str, "w%016"PRIx64,
15889                             mpt->un.m_base_wwid);
15890                 }
15891 
15892                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15893                     *smp_dip, SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwn_str) !=
15894                     DDI_PROP_SUCCESS) {
15895                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15896                             "property for smp attached-port %s (sas_wwn)",
15897                             attached_wwn_str);
15898                         ndi_rtn = NDI_FAILURE;
15899                         goto smp_create_done;
15900                 }
15901 
15902                 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
15903                     *smp_dip, SMP_PROP) != DDI_PROP_SUCCESS) {
15904                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15905                             "create property for SMP %s (SMP_PROP) ",
15906                             wwn_str);
15907                         ndi_rtn = NDI_FAILURE;
15908                         goto smp_create_done;
15909                 }
15910 
15911                 /*
15912                  * check the smp to see whether it direct
15913                  * attached to the controller
15914                  */
15915                 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15916                     != DEVINFO_DIRECT_ATTACHED) {
15917                         goto smp_create_done;
15918                 }
15919                 numphys = ddi_prop_get_int(DDI_DEV_T_ANY, pdip,
15920                     DDI_PROP_DONTPASS, MPTSAS_NUM_PHYS, -1);
15921                 if (numphys > 0) {
15922                         goto smp_create_done;
15923                 }
15924                 /*
15925                  * this iport is an old iport, we need to
15926                  * reconfig the props for it.
15927                  */
15928                 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
15929                     MPTSAS_VIRTUAL_PORT, 0) !=
15930                     DDI_PROP_SUCCESS) {
15931                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
15932                             MPTSAS_VIRTUAL_PORT);
15933                         mptsas_log(mpt, CE_WARN, "mptsas virtual port "
15934                             "prop update failed");
15935                         goto smp_create_done;
15936                 }
15937 
15938                 mutex_enter(&mpt->m_mutex);
15939                 numphys = 0;
15940                 iport = ddi_get_name_addr(pdip);
15941                 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15942                         bzero(phymask, sizeof (phymask));
15943                         (void) sprintf(phymask,
15944                             "%x", mpt->m_phy_info[i].phy_mask);
15945                         if (strcmp(phymask, iport) == 0) {
15946                                 phy_mask = mpt->m_phy_info[i].phy_mask;
15947                                 break;
15948                         }
15949                 }
15950 
15951                 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15952                         if ((phy_mask >> i) & 0x01) {
15953                                 numphys++;
15954                         }
15955                 }
15956                 /*
15957                  * Update PHY info for smhba
15958                  */
15959                 if (mptsas_smhba_phy_init(mpt)) {
15960                         mutex_exit(&mpt->m_mutex);
15961                         mptsas_log(mpt, CE_WARN, "mptsas phy update "
15962                             "failed");
15963                         goto smp_create_done;
15964                 }
15965                 mutex_exit(&mpt->m_mutex);
15966 
15967                 mptsas_smhba_set_all_phy_props(mpt, pdip, numphys, phy_mask,
15968                     &attached_devhdl);
15969 
15970                 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
15971                     MPTSAS_NUM_PHYS, numphys) !=
15972                     DDI_PROP_SUCCESS) {
15973                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
15974                             MPTSAS_NUM_PHYS);
15975                         mptsas_log(mpt, CE_WARN, "mptsas update "
15976                             "num phys props failed");
15977                         goto smp_create_done;
15978                 }
15979                 /*
15980                  * Add parent's props for SMHBA support
15981                  */
15982                 if (ddi_prop_update_string(DDI_DEV_T_NONE, pdip,
15983                     SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
15984                     DDI_PROP_SUCCESS) {
15985                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
15986                             SCSI_ADDR_PROP_ATTACHED_PORT);
15987                         mptsas_log(mpt, CE_WARN, "mptsas update iport"
15988                             "attached-port failed");
15989                         goto smp_create_done;
15990                 }
15991 
15992 smp_create_done:
15993                 /*
15994                  * If props were setup ok, online the lun
15995                  */
15996                 if (ndi_rtn == NDI_SUCCESS) {
15997                         /*
15998                          * Try to online the new node
15999                          */
16000                         ndi_rtn = ndi_devi_online(*smp_dip, NDI_ONLINE_ATTACH);
16001                 }
16002 
16003                 /*
16004                  * If success set rtn flag, else unwire alloc'd lun
16005                  */
16006                 if (ndi_rtn != NDI_SUCCESS) {
16007                         NDBG12(("mptsas unable to online "
16008                             "SMP target %s", wwn_str));
16009                         ndi_prop_remove_all(*smp_dip);
16010                         (void) ndi_devi_free(*smp_dip);
16011                 }
16012         }
16013 
16014         return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
16015 }
16016 
16017 /* smp transport routine */
16018 static int mptsas_smp_start(struct smp_pkt *smp_pkt)
16019 {
16020         uint64_t                        wwn;
16021         Mpi2SmpPassthroughRequest_t     req;
16022         Mpi2SmpPassthroughReply_t       rep;
16023         uint32_t                        direction = 0;
16024         mptsas_t                        *mpt;
16025         int                             ret;
16026         uint64_t                        tmp64;
16027 
16028         mpt = (mptsas_t *)smp_pkt->smp_pkt_address->
16029             smp_a_hba_tran->smp_tran_hba_private;
16030 
16031         bcopy(smp_pkt->smp_pkt_address->smp_a_wwn, &wwn, SAS_WWN_BYTE_SIZE);
16032         /*
16033          * Need to compose a SMP request message
16034          * and call mptsas_do_passthru() function
16035          */
16036         bzero(&req, sizeof (req));
16037         bzero(&rep, sizeof (rep));
16038         req.PassthroughFlags = 0;
16039         req.PhysicalPort = 0xff;
16040         req.ChainOffset = 0;
16041         req.Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
16042 
16043         if ((smp_pkt->smp_pkt_reqsize & 0xffff0000ul) != 0) {
16044                 smp_pkt->smp_pkt_reason = ERANGE;
16045                 return (DDI_FAILURE);
16046         }
16047         req.RequestDataLength = LE_16((uint16_t)(smp_pkt->smp_pkt_reqsize - 4));
16048 
16049         req.MsgFlags = 0;
16050         tmp64 = LE_64(wwn);
16051         bcopy(&tmp64, &req.SASAddress, SAS_WWN_BYTE_SIZE);
16052         if (smp_pkt->smp_pkt_rspsize > 0) {
16053                 direction |= MPTSAS_PASS_THRU_DIRECTION_READ;
16054         }
16055         if (smp_pkt->smp_pkt_reqsize > 0) {
16056                 direction |= MPTSAS_PASS_THRU_DIRECTION_WRITE;
16057         }
16058 
16059         mutex_enter(&mpt->m_mutex);
16060         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep,
16061             (uint8_t *)smp_pkt->smp_pkt_rsp,
16062             offsetof(Mpi2SmpPassthroughRequest_t, SGL), sizeof (rep),
16063             smp_pkt->smp_pkt_rspsize - 4, direction,
16064             (uint8_t *)smp_pkt->smp_pkt_req, smp_pkt->smp_pkt_reqsize - 4,
16065             smp_pkt->smp_pkt_timeout, FKIOCTL);
16066         mutex_exit(&mpt->m_mutex);
16067         if (ret != 0) {
16068                 cmn_err(CE_WARN, "smp_start do passthru error %d", ret);
16069                 smp_pkt->smp_pkt_reason = (uchar_t)(ret);
16070                 return (DDI_FAILURE);
16071         }
16072         /* do passthrough success, check the smp status */
16073         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
16074                 switch (LE_16(rep.IOCStatus)) {
16075                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
16076                         smp_pkt->smp_pkt_reason = ENODEV;
16077                         break;
16078                 case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
16079                         smp_pkt->smp_pkt_reason = EOVERFLOW;
16080                         break;
16081                 case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
16082                         smp_pkt->smp_pkt_reason = EIO;
16083                         break;
16084                 default:
16085                         mptsas_log(mpt, CE_NOTE, "smp_start: get unknown ioc"
16086                             "status:%x", LE_16(rep.IOCStatus));
16087                         smp_pkt->smp_pkt_reason = EIO;
16088                         break;
16089                 }
16090                 return (DDI_FAILURE);
16091         }
16092         if (rep.SASStatus != MPI2_SASSTATUS_SUCCESS) {
16093                 mptsas_log(mpt, CE_NOTE, "smp_start: get error SAS status:%x",
16094                     rep.SASStatus);
16095                 smp_pkt->smp_pkt_reason = EIO;
16096                 return (DDI_FAILURE);
16097         }
16098 
16099         return (DDI_SUCCESS);
16100 }
16101 
16102 /*
16103  * If we didn't get a match, we need to get sas page0 for each device, and
16104  * untill we get a match. If failed, return NULL
16105  */
16106 static mptsas_target_t *
16107 mptsas_phy_to_tgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint8_t phy)
16108 {
16109         int             i, j = 0;
16110         int             rval = 0;
16111         uint16_t        cur_handle;
16112         uint32_t        page_address;
16113         mptsas_target_t *ptgt = NULL;
16114 
16115         /*
16116          * PHY named device must be direct attached and attaches to
16117          * narrow port, if the iport is not parent of the device which
16118          * we are looking for.
16119          */
16120         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
16121                 if ((1 << i) & phymask)
16122                         j++;
16123         }
16124 
16125         if (j > 1)
16126                 return (NULL);
16127 
16128         /*
16129          * Must be a narrow port and single device attached to the narrow port
16130          * So the physical port num of device  which is equal to the iport's
16131          * port num is the device what we are looking for.
16132          */
16133 
16134         if (mpt->m_phy_info[phy].phy_mask != phymask)
16135                 return (NULL);
16136 
16137         mutex_enter(&mpt->m_mutex);
16138 
16139         ptgt = refhash_linear_search(mpt->m_targets, mptsas_target_eval_nowwn,
16140             &phy);
16141         if (ptgt != NULL) {
16142                 mutex_exit(&mpt->m_mutex);
16143                 return (ptgt);
16144         }
16145 
16146         if (mpt->m_done_traverse_dev) {
16147                 mutex_exit(&mpt->m_mutex);
16148                 return (NULL);
16149         }
16150 
16151         /* If didn't get a match, come here */
16152         cur_handle = mpt->m_dev_handle;
16153         for (; ; ) {
16154                 ptgt = NULL;
16155                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
16156                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)cur_handle;
16157                 rval = mptsas_get_target_device_info(mpt, page_address,
16158                     &cur_handle, &ptgt);
16159                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
16160                     (rval == DEV_INFO_FAIL_ALLOC) ||
16161                     (rval == DEV_INFO_FAIL_GUID)) {
16162                         break;
16163                 }
16164                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
16165                     (rval == DEV_INFO_PHYS_DISK)) {
16166                         continue;
16167                 }
16168                 mpt->m_dev_handle = cur_handle;
16169 
16170                 if ((ptgt->m_addr.mta_wwn == 0) && (ptgt->m_phynum == phy)) {
16171                         break;
16172                 }
16173         }
16174 
16175         mutex_exit(&mpt->m_mutex);
16176         return (ptgt);
16177 }
16178 
16179 /*
16180  * The ptgt->m_addr.mta_wwn contains the wwid for each disk.
16181  * For Raid volumes, we need to check m_raidvol[x].m_raidwwid
16182  * If we didn't get a match, we need to get sas page0 for each device, and
16183  * untill we get a match
16184  * If failed, return NULL
16185  */
16186 static mptsas_target_t *
16187 mptsas_wwid_to_ptgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
16188 {
16189         int             rval = 0;
16190         uint16_t        cur_handle;
16191         uint32_t        page_address;
16192         mptsas_target_t *tmp_tgt = NULL;
16193         mptsas_target_addr_t addr;
16194 
16195         addr.mta_wwn = wwid;
16196         addr.mta_phymask = phymask;
16197         mutex_enter(&mpt->m_mutex);
16198         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
16199         if (tmp_tgt != NULL) {
16200                 mutex_exit(&mpt->m_mutex);
16201                 return (tmp_tgt);
16202         }
16203 
16204         if (phymask == 0) {
16205                 /*
16206                  * It's IR volume
16207                  */
16208                 rval = mptsas_get_raid_info(mpt);
16209                 if (rval) {
16210                         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
16211                 }
16212                 mutex_exit(&mpt->m_mutex);
16213                 return (tmp_tgt);
16214         }
16215 
16216         if (mpt->m_done_traverse_dev) {
16217                 mutex_exit(&mpt->m_mutex);
16218                 return (NULL);
16219         }
16220 
16221         /* If didn't get a match, come here */
16222         cur_handle = mpt->m_dev_handle;
16223         for (;;) {
16224                 tmp_tgt = NULL;
16225                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
16226                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | cur_handle;
16227                 rval = mptsas_get_target_device_info(mpt, page_address,
16228                     &cur_handle, &tmp_tgt);
16229                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
16230                     (rval == DEV_INFO_FAIL_ALLOC) ||
16231                     (rval == DEV_INFO_FAIL_GUID)) {
16232                         tmp_tgt = NULL;
16233                         break;
16234                 }
16235                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
16236                     (rval == DEV_INFO_PHYS_DISK)) {
16237                         continue;
16238                 }
16239                 mpt->m_dev_handle = cur_handle;
16240                 if ((tmp_tgt->m_addr.mta_wwn) &&
16241                     (tmp_tgt->m_addr.mta_wwn == wwid) &&
16242                     (tmp_tgt->m_addr.mta_phymask == phymask)) {
16243                         break;
16244                 }
16245         }
16246 
16247         mutex_exit(&mpt->m_mutex);
16248         return (tmp_tgt);
16249 }
16250 
16251 static mptsas_smp_t *
16252 mptsas_wwid_to_psmp(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
16253 {
16254         int             rval = 0;
16255         uint16_t        cur_handle;
16256         uint32_t        page_address;
16257         mptsas_smp_t    smp_node, *psmp = NULL;
16258         mptsas_target_addr_t addr;
16259 
16260         addr.mta_wwn = wwid;
16261         addr.mta_phymask = phymask;
16262         mutex_enter(&mpt->m_mutex);
16263         psmp = refhash_lookup(mpt->m_smp_targets, &addr);
16264         if (psmp != NULL) {
16265                 mutex_exit(&mpt->m_mutex);
16266                 return (psmp);
16267         }
16268 
16269         if (mpt->m_done_traverse_smp) {
16270                 mutex_exit(&mpt->m_mutex);
16271                 return (NULL);
16272         }
16273 
16274         /* If didn't get a match, come here */
16275         cur_handle = mpt->m_smp_devhdl;
16276         for (;;) {
16277                 psmp = NULL;
16278                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
16279                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)cur_handle;
16280                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
16281                     &smp_node);
16282                 if (rval != DDI_SUCCESS) {
16283                         break;
16284                 }
16285                 mpt->m_smp_devhdl = cur_handle = smp_node.m_devhdl;
16286                 psmp = mptsas_smp_alloc(mpt, &smp_node);
16287                 ASSERT(psmp);
16288                 if ((psmp->m_addr.mta_wwn) && (psmp->m_addr.mta_wwn == wwid) &&
16289                     (psmp->m_addr.mta_phymask == phymask)) {
16290                         break;
16291                 }
16292         }
16293 
16294         mutex_exit(&mpt->m_mutex);
16295         return (psmp);
16296 }
16297 
16298 mptsas_target_t *
16299 mptsas_tgt_alloc(refhash_t *refhash, uint16_t devhdl, uint64_t wwid,
16300     uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum)
16301 {
16302         mptsas_target_t *tmp_tgt = NULL;
16303         mptsas_target_addr_t addr;
16304 
16305         addr.mta_wwn = wwid;
16306         addr.mta_phymask = phymask;
16307         tmp_tgt = refhash_lookup(refhash, &addr);
16308         if (tmp_tgt != NULL) {
16309                 NDBG20(("Hash item already exist"));
16310                 tmp_tgt->m_deviceinfo = devinfo;
16311                 tmp_tgt->m_devhdl = devhdl;  /* XXX - duplicate? */
16312                 return (tmp_tgt);
16313         }
16314         tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target), KM_SLEEP);
16315         if (tmp_tgt == NULL) {
16316                 cmn_err(CE_WARN, "Fatal, allocated tgt failed");
16317                 return (NULL);
16318         }
16319         tmp_tgt->m_devhdl = devhdl;
16320         tmp_tgt->m_addr.mta_wwn = wwid;
16321         tmp_tgt->m_deviceinfo = devinfo;
16322         tmp_tgt->m_addr.mta_phymask = phymask;
16323         tmp_tgt->m_phynum = phynum;
16324         /* Initialized the tgt structure */
16325         tmp_tgt->m_qfull_retries = QFULL_RETRIES;
16326         tmp_tgt->m_qfull_retry_interval =
16327             drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
16328         tmp_tgt->m_t_throttle = MAX_THROTTLE;
16329         TAILQ_INIT(&tmp_tgt->m_active_cmdq);
16330 
16331         refhash_insert(refhash, tmp_tgt);
16332 
16333         return (tmp_tgt);
16334 }
16335 
16336 static void
16337 mptsas_smp_target_copy(mptsas_smp_t *src, mptsas_smp_t *dst)
16338 {
16339         dst->m_devhdl = src->m_devhdl;
16340         dst->m_deviceinfo = src->m_deviceinfo;
16341         dst->m_pdevhdl = src->m_pdevhdl;
16342         dst->m_pdevinfo = src->m_pdevinfo;
16343 }
16344 
16345 static mptsas_smp_t *
16346 mptsas_smp_alloc(mptsas_t *mpt, mptsas_smp_t *data)
16347 {
16348         mptsas_target_addr_t addr;
16349         mptsas_smp_t *ret_data;
16350 
16351         addr.mta_wwn = data->m_addr.mta_wwn;
16352         addr.mta_phymask = data->m_addr.mta_phymask;
16353         ret_data = refhash_lookup(mpt->m_smp_targets, &addr);
16354         /*
16355          * If there's already a matching SMP target, update its fields
16356          * in place.  Since the address is not changing, it's safe to do
16357          * this.  We cannot just bcopy() here because the structure we've
16358          * been given has invalid hash links.
16359          */
16360         if (ret_data != NULL) {
16361                 mptsas_smp_target_copy(data, ret_data);
16362                 return (ret_data);
16363         }
16364 
16365         ret_data = kmem_alloc(sizeof (mptsas_smp_t), KM_SLEEP);
16366         bcopy(data, ret_data, sizeof (mptsas_smp_t));
16367         refhash_insert(mpt->m_smp_targets, ret_data);
16368         return (ret_data);
16369 }
16370 
16371 /*
16372  * Functions for SGPIO LED support
16373  */
16374 static dev_info_t *
16375 mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask)
16376 {
16377         dev_info_t      *dip;
16378         int             prop;
16379         dip = e_ddi_hold_devi_by_dev(dev, 0);
16380         if (dip == NULL)
16381                 return (dip);
16382         prop = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
16383             "phymask", 0);
16384         *phymask = (mptsas_phymask_t)prop;
16385         ddi_release_devi(dip);
16386         return (dip);
16387 }
16388 static mptsas_target_t *
16389 mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
16390 {
16391         uint8_t                 phynum;
16392         uint64_t                wwn;
16393         int                     lun;
16394         mptsas_target_t         *ptgt = NULL;
16395 
16396         if (mptsas_parse_address(addr, &wwn, &phynum, &lun) != DDI_SUCCESS) {
16397                 return (NULL);
16398         }
16399         if (addr[0] == 'w') {
16400                 ptgt = mptsas_wwid_to_ptgt(mpt, (int)phymask, wwn);
16401         } else {
16402                 ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum);
16403         }
16404         return (ptgt);
16405 }
16406 
16407 static int
16408 mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt)
16409 {
16410         uint32_t slotstatus = 0;
16411 
16412         /* Build an MPI2 Slot Status based on our view of the world */
16413         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_IDENT - 1)))
16414                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST;
16415         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_FAIL - 1)))
16416                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT;
16417         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1)))
16418                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
16419 
16420         /* Write it to the controller */
16421         NDBG14(("mptsas_ioctl: set LED status %x for slot %x",
16422             slotstatus, ptgt->m_slot_num));
16423         return (mptsas_send_sep(mpt, ptgt, &slotstatus,
16424             MPI2_SEP_REQ_ACTION_WRITE_STATUS));
16425 }
16426 
16427 /*
16428  *  send sep request, use enclosure/slot addressing
16429  */
16430 static int
16431 mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
16432     uint32_t *status, uint8_t act)
16433 {
16434         Mpi2SepRequest_t        req;
16435         Mpi2SepReply_t          rep;
16436         int                     ret;
16437 
16438         ASSERT(mutex_owned(&mpt->m_mutex));
16439 
16440         /*
16441          * We only support SEP control of directly-attached targets, in which
16442          * case the "SEP" we're talking to is a virtual one contained within
16443          * the HBA itself.  This is necessary because DA targets typically have
16444          * no other mechanism for LED control.  Targets for which a separate
16445          * enclosure service processor exists should be controlled via ses(7d)
16446          * or sgen(7d).  Furthermore, since such requests can time out, they
16447          * should be made in user context rather than in response to
16448          * asynchronous fabric changes.
16449          *
16450          * In addition, we do not support this operation for RAID volumes,
16451          * since there is no slot associated with them.
16452          */
16453         if (!(ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED) ||
16454             ptgt->m_addr.mta_phymask == 0) {
16455                 return (ENOTTY);
16456         }
16457 
16458         bzero(&req, sizeof (req));
16459         bzero(&rep, sizeof (rep));
16460 
16461         req.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
16462         req.Action = act;
16463         req.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
16464         req.EnclosureHandle = LE_16(ptgt->m_enclosure);
16465         req.Slot = LE_16(ptgt->m_slot_num);
16466         if (act == MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
16467                 req.SlotStatus = LE_32(*status);
16468         }
16469         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
16470             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
16471         if (ret != 0) {
16472                 mptsas_log(mpt, CE_NOTE, "mptsas_send_sep: passthru SEP "
16473                     "Processor Request message error %d", ret);
16474                 return (ret);
16475         }
16476         /* do passthrough success, check the ioc status */
16477         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
16478                 mptsas_log(mpt, CE_NOTE, "send_sep act %x: ioc "
16479                     "status:%x loginfo %x", act, LE_16(rep.IOCStatus),
16480                     LE_32(rep.IOCLogInfo));
16481                 switch (LE_16(rep.IOCStatus) & MPI2_IOCSTATUS_MASK) {
16482                 case MPI2_IOCSTATUS_INVALID_FUNCTION:
16483                 case MPI2_IOCSTATUS_INVALID_VPID:
16484                 case MPI2_IOCSTATUS_INVALID_FIELD:
16485                 case MPI2_IOCSTATUS_INVALID_STATE:
16486                 case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
16487                 case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
16488                 case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
16489                 case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
16490                 case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
16491                 case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
16492                         return (EINVAL);
16493                 case MPI2_IOCSTATUS_BUSY:
16494                         return (EBUSY);
16495                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
16496                         return (EAGAIN);
16497                 case MPI2_IOCSTATUS_INVALID_SGL:
16498                 case MPI2_IOCSTATUS_INTERNAL_ERROR:
16499                 case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
16500                 default:
16501                         return (EIO);
16502                 }
16503         }
16504         if (act != MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
16505                 *status = LE_32(rep.SlotStatus);
16506         }
16507 
16508         return (0);
16509 }
16510 
16511 int
16512 mptsas_dma_addr_create(mptsas_t *mpt, ddi_dma_attr_t dma_attr,
16513     ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp, caddr_t *dma_memp,
16514     uint32_t alloc_size, ddi_dma_cookie_t *cookiep)
16515 {
16516         ddi_dma_cookie_t        new_cookie;
16517         size_t                  alloc_len;
16518         uint_t                  ncookie;
16519 
16520         if (cookiep == NULL)
16521                 cookiep = &new_cookie;
16522 
16523         if (ddi_dma_alloc_handle(mpt->m_dip, &dma_attr, DDI_DMA_SLEEP,
16524             NULL, dma_hdp) != DDI_SUCCESS) {
16525                 return (FALSE);
16526         }
16527 
16528         if (ddi_dma_mem_alloc(*dma_hdp, alloc_size, &mpt->m_dev_acc_attr,
16529             DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, dma_memp, &alloc_len,
16530             acc_hdp) != DDI_SUCCESS) {
16531                 ddi_dma_free_handle(dma_hdp);
16532                 *dma_hdp = NULL;
16533                 return (FALSE);
16534         }
16535 
16536         if (ddi_dma_addr_bind_handle(*dma_hdp, NULL, *dma_memp, alloc_len,
16537             (DDI_DMA_RDWR | DDI_DMA_CONSISTENT), DDI_DMA_SLEEP, NULL,
16538             cookiep, &ncookie) != DDI_DMA_MAPPED) {
16539                 (void) ddi_dma_mem_free(acc_hdp);
16540                 ddi_dma_free_handle(dma_hdp);
16541                 *dma_hdp = NULL;
16542                 return (FALSE);
16543         }
16544 
16545         return (TRUE);
16546 }
16547 
16548 void
16549 mptsas_dma_addr_destroy(ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp)
16550 {
16551         if (*dma_hdp == NULL)
16552                 return;
16553 
16554         (void) ddi_dma_unbind_handle(*dma_hdp);
16555         (void) ddi_dma_mem_free(acc_hdp);
16556         ddi_dma_free_handle(dma_hdp);
16557         *dma_hdp = NULL;
16558 }