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 2012 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  26  */
  27 
  28 /*
  29  * Copyright (c) 2000 to 2010, LSI Corporation.
  30  * All rights reserved.
  31  *
  32  * Redistribution and use in source and binary forms of all code within
  33  * this file that is exclusively owned by LSI, with or without
  34  * modification, is permitted provided that, in addition to the CDDL 1.0
  35  * License requirements, the following conditions are met:
  36  *
  37  *    Neither the name of the author nor the names of its contributors may be
  38  *    used to endorse or promote products derived from this software without
  39  *    specific prior written permission.
  40  *
  41  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  42  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  43  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  44  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  45  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  46  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  47  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  48  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  49  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  50  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  51  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  52  * DAMAGE.
  53  */
  54 
  55 /*
  56  * mptsas - This is a driver based on LSI Logic's MPT2.0 interface.
  57  *
  58  */
  59 
  60 #if defined(lint) || defined(DEBUG)
  61 #define MPTSAS_DEBUG
  62 #endif
  63 
  64 /*
  65  * standard header files.
  66  */
  67 #include <sys/note.h>
  68 #include <sys/scsi/scsi.h>
  69 #include <sys/pci.h>
  70 #include <sys/file.h>
  71 #include <sys/cpuvar.h>
  72 #include <sys/policy.h>
  73 #include <sys/model.h>
  74 #include <sys/sysevent.h>
  75 #include <sys/sysevent/eventdefs.h>
  76 #include <sys/sysevent/dr.h>
  77 #include <sys/sata/sata_defs.h>
  78 #include <sys/scsi/generic/sas.h>
  79 #include <sys/scsi/impl/scsi_sas.h>
  80 
  81 #pragma pack(1)
  82 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
  83 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
  84 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
  85 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
  86 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
  87 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
  88 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
  89 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
  90 #pragma pack()
  91 
  92 /*
  93  * private header files.
  94  *
  95  */
  96 #include <sys/scsi/impl/scsi_reset_notify.h>
  97 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
  98 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
  99 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
 100 
 101 #include <sys/raidioctl.h>
 102 
 103 #include <sys/fs/dv_node.h>       /* devfs_clean */
 104 
 105 /*
 106  * FMA header files
 107  */
 108 #include <sys/ddifm.h>
 109 #include <sys/fm/protocol.h>
 110 #include <sys/fm/util.h>
 111 #include <sys/fm/io/ddi.h>
 112 
 113 /*
 114  * For anyone who would modify the code in mptsas_driver, it must be awared
 115  * that from snv_145 where CR6910752(mpt_sas driver performance can be
 116  * improved) is integrated, the per_instance mutex m_mutex is not hold
 117  * in the key IO code path, including mptsas_scsi_start(), mptsas_intr()
 118  * and all of the recursive functions called in them, so don't
 119  * make it for granted that all operations are sync/exclude correctly. Before
 120  * doing any modification in key code path, and even other code path such as
 121  * DR, watchsubr, ioctl, passthrough etc, make sure the elements modified have
 122  * no releationship to elements shown in the fastpath
 123  * (function mptsas_handle_io_fastpath()) in ISR and its recursive functions.
 124  * otherwise, you have to use the new introduced mutex to protect them.
 125  * As to how to do correctly, refer to the comments in mptsas_intr().
 126  */
 127 
 128 /*
 129  * autoconfiguration data and routines.
 130  */
 131 static int mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
 132 static int mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
 133 static int mptsas_power(dev_info_t *dip, int component, int level);
 134 
 135 /*
 136  * cb_ops function
 137  */
 138 static int mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
 139         cred_t *credp, int *rval);
 140 #ifdef __sparc
 141 static int mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd);
 142 #else  /* __sparc */
 143 static int mptsas_quiesce(dev_info_t *devi);
 144 #endif  /* __sparc */
 145 
 146 /*
 147  * Resource initilaization for hardware
 148  */
 149 static void mptsas_setup_cmd_reg(mptsas_t *mpt);
 150 static void mptsas_disable_bus_master(mptsas_t *mpt);
 151 static void mptsas_hba_fini(mptsas_t *mpt);
 152 static void mptsas_cfg_fini(mptsas_t *mptsas_blkp);
 153 static int mptsas_hba_setup(mptsas_t *mpt);
 154 static void mptsas_hba_teardown(mptsas_t *mpt);
 155 static int mptsas_config_space_init(mptsas_t *mpt);
 156 static void mptsas_config_space_fini(mptsas_t *mpt);
 157 static void mptsas_iport_register(mptsas_t *mpt);
 158 static int mptsas_smp_setup(mptsas_t *mpt);
 159 static void mptsas_smp_teardown(mptsas_t *mpt);
 160 static int mptsas_cache_create(mptsas_t *mpt);
 161 static void mptsas_cache_destroy(mptsas_t *mpt);
 162 static int mptsas_alloc_request_frames(mptsas_t *mpt);
 163 static int mptsas_alloc_reply_frames(mptsas_t *mpt);
 164 static int mptsas_alloc_free_queue(mptsas_t *mpt);
 165 static int mptsas_alloc_post_queue(mptsas_t *mpt);
 166 static void mptsas_alloc_reply_args(mptsas_t *mpt);
 167 static int mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
 168 static void mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
 169 static int mptsas_init_chip(mptsas_t *mpt, int first_time);
 170 
 171 /*
 172  * SCSA function prototypes
 173  */
 174 static int mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
 175 static int mptsas_scsi_reset(struct scsi_address *ap, int level);
 176 static int mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
 177 static int mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly);
 178 static int mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value,
 179     int tgtonly);
 180 static void mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt);
 181 static struct scsi_pkt *mptsas_scsi_init_pkt(struct scsi_address *ap,
 182     struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen,
 183         int tgtlen, int flags, int (*callback)(), caddr_t arg);
 184 static void mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt);
 185 static void mptsas_scsi_destroy_pkt(struct scsi_address *ap,
 186     struct scsi_pkt *pkt);
 187 static int mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 188     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 189 static void mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 190     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 191 static int mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
 192     void (*callback)(caddr_t), caddr_t arg);
 193 static int mptsas_get_name(struct scsi_device *sd, char *name, int len);
 194 static int mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len);
 195 static int mptsas_scsi_quiesce(dev_info_t *dip);
 196 static int mptsas_scsi_unquiesce(dev_info_t *dip);
 197 static int mptsas_bus_config(dev_info_t *pdip, uint_t flags,
 198     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
 199 
 200 /*
 201  * SMP functions
 202  */
 203 static int mptsas_smp_start(struct smp_pkt *smp_pkt);
 204 
 205 /*
 206  * internal function prototypes.
 207  */
 208 static void mptsas_list_add(mptsas_t *mpt);
 209 static void mptsas_list_del(mptsas_t *mpt);
 210 
 211 static int mptsas_quiesce_bus(mptsas_t *mpt);
 212 static int mptsas_unquiesce_bus(mptsas_t *mpt);
 213 
 214 static int mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size);
 215 static void mptsas_free_handshake_msg(mptsas_t *mpt);
 216 
 217 static void mptsas_ncmds_checkdrain(void *arg);
 218 
 219 static int mptsas_prepare_pkt(mptsas_cmd_t *cmd);
 220 static int mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
 221 
 222 static int mptsas_do_detach(dev_info_t *dev);
 223 static int mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl);
 224 static int mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun,
 225     struct scsi_pkt *pkt);
 226 static int mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp);
 227 
 228 static void mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd);
 229 static void mptsas_handle_event(void *args);
 230 static int mptsas_handle_event_sync(void *args);
 231 static void mptsas_handle_dr(void *args);
 232 static void mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
 233     dev_info_t *pdip);
 234 
 235 static void mptsas_restart_cmd(void *);
 236 
 237 static void mptsas_flush_hba(mptsas_t *mpt);
 238 static void mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun,
 239         uint8_t tasktype);
 240 static void mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd,
 241     uchar_t reason, uint_t stat);
 242 
 243 static uint_t mptsas_intr(caddr_t arg1, caddr_t arg2);
 244 static void mptsas_process_intr(mptsas_t *mpt,
 245     pMpi2ReplyDescriptorsUnion_t reply_desc_union);
 246 static int mptsas_handle_io_fastpath(mptsas_t *mpt, uint16_t SMID);
 247 static void mptsas_handle_scsi_io_success(mptsas_t *mpt,
 248     pMpi2ReplyDescriptorsUnion_t reply_desc);
 249 static void mptsas_handle_address_reply(mptsas_t *mpt,
 250     pMpi2ReplyDescriptorsUnion_t reply_desc);
 251 static int mptsas_wait_intr(mptsas_t *mpt, int polltime);
 252 static void mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd,
 253     uint32_t *control, pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl);
 254 
 255 static void mptsas_watch(void *arg);
 256 static void mptsas_watchsubr(mptsas_t *mpt);
 257 static void mptsas_cmd_timeout(mptsas_t *mpt, uint16_t devhdl);
 258 
 259 static void mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd);
 260 static int mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
 261     uint8_t *data, uint32_t request_size, uint32_t reply_size,
 262     uint32_t data_size, uint32_t direction, uint8_t *dataout,
 263     uint32_t dataout_size, short timeout, int mode);
 264 static int mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl);
 265 
 266 static uint8_t mptsas_get_fw_diag_buffer_number(mptsas_t *mpt,
 267     uint32_t unique_id);
 268 static void mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd);
 269 static int mptsas_post_fw_diag_buffer(mptsas_t *mpt,
 270     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
 271 static int mptsas_release_fw_diag_buffer(mptsas_t *mpt,
 272     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
 273     uint32_t diag_type);
 274 static int mptsas_diag_register(mptsas_t *mpt,
 275     mptsas_fw_diag_register_t *diag_register, uint32_t *return_code);
 276 static int mptsas_diag_unregister(mptsas_t *mpt,
 277     mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code);
 278 static int mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
 279     uint32_t *return_code);
 280 static int mptsas_diag_read_buffer(mptsas_t *mpt,
 281     mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
 282     uint32_t *return_code, int ioctl_mode);
 283 static int mptsas_diag_release(mptsas_t *mpt,
 284     mptsas_fw_diag_release_t *diag_release, uint32_t *return_code);
 285 static int mptsas_do_diag_action(mptsas_t *mpt, uint32_t action,
 286     uint8_t *diag_action, uint32_t length, uint32_t *return_code,
 287     int ioctl_mode);
 288 static int mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *data,
 289     int mode);
 290 
 291 static int mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
 292     int cmdlen, int tgtlen, int statuslen, int kf);
 293 static void mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd);
 294 
 295 static int mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags);
 296 static void mptsas_kmem_cache_destructor(void *buf, void *cdrarg);
 297 
 298 static int mptsas_cache_frames_constructor(void *buf, void *cdrarg,
 299     int kmflags);
 300 static void mptsas_cache_frames_destructor(void *buf, void *cdrarg);
 301 
 302 static void mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
 303     mptsas_cmd_t *cmd);
 304 static void mptsas_check_task_mgt(mptsas_t *mpt,
 305     pMpi2SCSIManagementReply_t reply, mptsas_cmd_t *cmd);
 306 static int mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
 307     mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
 308     int *resid);
 309 
 310 static int mptsas_alloc_active_slots(mptsas_t *mpt, int flag);
 311 static void mptsas_free_active_slots(mptsas_t *mpt);
 312 static int mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 313 static int mptsas_start_cmd0(mptsas_t *mpt, mptsas_cmd_t *cmd);
 314 
 315 static void mptsas_restart_hba(mptsas_t *mpt);
 316 
 317 static void mptsas_deliver_doneq_thread(mptsas_t *mpt);
 318 static void mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd);
 319 static inline void mptsas_doneq_add0(mptsas_t *mpt, mptsas_cmd_t *cmd);
 320 static void mptsas_doneq_mv(mptsas_t *mpt, uint64_t t);
 321 
 322 static mptsas_cmd_t *mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t);
 323 static void mptsas_doneq_empty(mptsas_t *mpt);
 324 static void mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg);
 325 
 326 static mptsas_cmd_t *mptsas_waitq_rm(mptsas_t *mpt);
 327 static void mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
 328 
 329 static void mptsas_start_watch_reset_delay();
 330 static void mptsas_setup_bus_reset_delay(mptsas_t *mpt);
 331 static void mptsas_watch_reset_delay(void *arg);
 332 static int mptsas_watch_reset_delay_subr(mptsas_t *mpt);
 333 
 334 static int mptsas_outstanding_cmds_n(mptsas_t *mpt);
 335 /*
 336  * helper functions
 337  */
 338 static void mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 339 
 340 static dev_info_t *mptsas_find_child(dev_info_t *pdip, char *name);
 341 static dev_info_t *mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy);
 342 static dev_info_t *mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr,
 343     int lun);
 344 static mdi_pathinfo_t *mptsas_find_path_addr(dev_info_t *pdip, uint64_t sasaddr,
 345     int lun);
 346 static mdi_pathinfo_t *mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy);
 347 static dev_info_t *mptsas_find_smp_child(dev_info_t *pdip, char *str_wwn);
 348 
 349 static int mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy,
 350     int *lun);
 351 static int mptsas_parse_smp_name(char *name, uint64_t *wwn);
 352 
 353 static mptsas_target_t *mptsas_phy_to_tgt(mptsas_t *mpt, int phymask,
 354     uint8_t phy);
 355 static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt, int phymask,
 356     uint64_t wwid);
 357 static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt, int phymask,
 358     uint64_t wwid);
 359 
 360 static int mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun,
 361     uchar_t page, unsigned char *buf, int len, int *rlen, uchar_t evpd);
 362 
 363 static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
 364     uint16_t *handle, mptsas_target_t **pptgt);
 365 static void mptsas_update_phymask(mptsas_t *mpt);
 366 static inline void mptsas_remove_cmd0(mptsas_t *mpt, mptsas_cmd_t *cmd);
 367 
 368 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
 369     uint32_t *status, uint8_t cmd);
 370 static dev_info_t *mptsas_get_dip_from_dev(dev_t dev,
 371     mptsas_phymask_t *phymask);
 372 static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr,
 373     mptsas_phymask_t phymask);
 374 static int mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt);
 375 
 376 
 377 /*
 378  * Enumeration / DR functions
 379  */
 380 static void mptsas_config_all(dev_info_t *pdip);
 381 static int mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
 382     dev_info_t **lundip);
 383 static int mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
 384     dev_info_t **lundip);
 385 
 386 static int mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt);
 387 static int mptsas_offline_target(dev_info_t *pdip, char *name);
 388 
 389 static int mptsas_config_raid(dev_info_t *pdip, uint16_t target,
 390     dev_info_t **dip);
 391 
 392 static int mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt);
 393 static int mptsas_probe_lun(dev_info_t *pdip, int lun,
 394     dev_info_t **dip, mptsas_target_t *ptgt);
 395 
 396 static int mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
 397     dev_info_t **dip, mptsas_target_t *ptgt, int lun);
 398 
 399 static int mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
 400     char *guid, dev_info_t **dip, mptsas_target_t *ptgt, int lun);
 401 static int mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
 402     char *guid, dev_info_t **dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt,
 403     int lun);
 404 
 405 static void mptsas_offline_missed_luns(dev_info_t *pdip,
 406     uint16_t *repluns, int lun_cnt, mptsas_target_t *ptgt);
 407 static int mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
 408     mdi_pathinfo_t *rpip, uint_t flags);
 409 
 410 static int mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn,
 411     dev_info_t **smp_dip);
 412 static int mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 413     uint_t flags);
 414 
 415 static int mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data,
 416     int mode, int *rval);
 417 static int mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data,
 418     int mode, int *rval);
 419 static int mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data,
 420     int mode, int *rval);
 421 static void mptsas_record_event(void *args);
 422 static int mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data,
 423     int mode);
 424 
 425 static void mptsas_hash_init(mptsas_hash_table_t *hashtab);
 426 static void mptsas_hash_uninit(mptsas_hash_table_t *hashtab, size_t datalen);
 427 static void mptsas_hash_add(mptsas_hash_table_t *hashtab, void *data);
 428 static void * mptsas_hash_rem(mptsas_hash_table_t *hashtab, uint64_t key1,
 429     mptsas_phymask_t key2);
 430 static void * mptsas_hash_search(mptsas_hash_table_t *hashtab, uint64_t key1,
 431     mptsas_phymask_t key2);
 432 static void * mptsas_hash_traverse(mptsas_hash_table_t *hashtab, int pos);
 433 
 434 mptsas_target_t *mptsas_tgt_alloc(mptsas_hash_table_t *, uint16_t, uint64_t,
 435     uint32_t, mptsas_phymask_t, uint8_t, mptsas_t *);
 436 static mptsas_smp_t *mptsas_smp_alloc(mptsas_hash_table_t *hashtab,
 437     mptsas_smp_t *data);
 438 static void mptsas_smp_free(mptsas_hash_table_t *hashtab, uint64_t wwid,
 439     mptsas_phymask_t phymask);
 440 static void mptsas_tgt_free(mptsas_hash_table_t *, uint64_t, mptsas_phymask_t);
 441 static void * mptsas_search_by_devhdl(mptsas_hash_table_t *, uint16_t);
 442 static int mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 443     dev_info_t **smp_dip);
 444 
 445 /*
 446  * Power management functions
 447  */
 448 static int mptsas_get_pci_cap(mptsas_t *mpt);
 449 static int mptsas_init_pm(mptsas_t *mpt);
 450 
 451 /*
 452  * MPT MSI tunable:
 453  *
 454  * By default MSI is enabled on all supported platforms.
 455  */
 456 boolean_t mptsas_enable_msi = B_TRUE;
 457 boolean_t mptsas_physical_bind_failed_page_83 = B_FALSE;
 458 
 459 static int mptsas_register_intrs(mptsas_t *);
 460 static void mptsas_unregister_intrs(mptsas_t *);
 461 static int mptsas_add_intrs(mptsas_t *, int);
 462 static void mptsas_rem_intrs(mptsas_t *);
 463 
 464 /*
 465  * FMA Prototypes
 466  */
 467 static void mptsas_fm_init(mptsas_t *mpt);
 468 static void mptsas_fm_fini(mptsas_t *mpt);
 469 static int mptsas_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *);
 470 
 471 extern pri_t minclsyspri, maxclsyspri;
 472 
 473 /*
 474  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).  It is
 475  * under this device that the paths to a physical device are created when
 476  * MPxIO is used.
 477  */
 478 extern dev_info_t       *scsi_vhci_dip;
 479 
 480 /*
 481  * Tunable timeout value for Inquiry VPD page 0x83
 482  * By default the value is 30 seconds.
 483  */
 484 int mptsas_inq83_retry_timeout = 30;
 485 
 486 /*
 487  * This is used to allocate memory for message frame storage, not for
 488  * data I/O DMA. All message frames must be stored in the first 4G of
 489  * physical memory.
 490  */
 491 ddi_dma_attr_t mptsas_dma_attrs = {
 492         DMA_ATTR_V0,    /* attribute layout version             */
 493         0x0ull,         /* address low - should be 0 (longlong) */
 494         0xffffffffull,  /* address high - 32-bit max range      */
 495         0x00ffffffull,  /* count max - max DMA object size      */
 496         4,              /* allocation alignment requirements    */
 497         0x78,           /* burstsizes - binary encoded values   */
 498         1,              /* minxfer - gran. of DMA engine        */
 499         0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 500         0xffffffffull,  /* max segment size (DMA boundary)      */
 501         MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 502         512,            /* granularity - device transfer size   */
 503         0               /* flags, set to 0                      */
 504 };
 505 
 506 /*
 507  * This is used for data I/O DMA memory allocation. (full 64-bit DMA
 508  * physical addresses are supported.)
 509  */
 510 ddi_dma_attr_t mptsas_dma_attrs64 = {
 511         DMA_ATTR_V0,    /* attribute layout version             */
 512         0x0ull,         /* address low - should be 0 (longlong) */
 513         0xffffffffffffffffull,  /* address high - 64-bit max    */
 514         0x00ffffffull,  /* count max - max DMA object size      */
 515         4,              /* allocation alignment requirements    */
 516         0x78,           /* burstsizes - binary encoded values   */
 517         1,              /* minxfer - gran. of DMA engine        */
 518         0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 519         0xffffffffull,  /* max segment size (DMA boundary)      */
 520         MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 521         512,            /* granularity - device transfer size   */
 522         DDI_DMA_RELAXED_ORDERING        /* flags, enable relaxed ordering */
 523 };
 524 
 525 ddi_device_acc_attr_t mptsas_dev_attr = {
 526         DDI_DEVICE_ATTR_V1,
 527         DDI_STRUCTURE_LE_ACC,
 528         DDI_STRICTORDER_ACC,
 529         DDI_DEFAULT_ACC
 530 };
 531 
 532 static struct cb_ops mptsas_cb_ops = {
 533         scsi_hba_open,          /* open */
 534         scsi_hba_close,         /* close */
 535         nodev,                  /* strategy */
 536         nodev,                  /* print */
 537         nodev,                  /* dump */
 538         nodev,                  /* read */
 539         nodev,                  /* write */
 540         mptsas_ioctl,           /* ioctl */
 541         nodev,                  /* devmap */
 542         nodev,                  /* mmap */
 543         nodev,                  /* segmap */
 544         nochpoll,               /* chpoll */
 545         ddi_prop_op,            /* cb_prop_op */
 546         NULL,                   /* streamtab */
 547         D_MP,                   /* cb_flag */
 548         CB_REV,                 /* rev */
 549         nodev,                  /* aread */
 550         nodev                   /* awrite */
 551 };
 552 
 553 static struct dev_ops mptsas_ops = {
 554         DEVO_REV,               /* devo_rev, */
 555         0,                      /* refcnt  */
 556         ddi_no_info,            /* info */
 557         nulldev,                /* identify */
 558         nulldev,                /* probe */
 559         mptsas_attach,          /* attach */
 560         mptsas_detach,          /* detach */
 561 #ifdef  __sparc
 562         mptsas_reset,
 563 #else
 564         nodev,                  /* reset */
 565 #endif  /* __sparc */
 566         &mptsas_cb_ops,             /* driver operations */
 567         NULL,                   /* bus operations */
 568         mptsas_power,           /* power management */
 569 #ifdef  __sparc
 570         ddi_quiesce_not_needed
 571 #else
 572         mptsas_quiesce          /* quiesce */
 573 #endif  /* __sparc */
 574 };
 575 
 576 
 577 #define MPTSAS_MOD_STRING "MPTSAS HBA Driver 00.00.00.24"
 578 
 579 static struct modldrv modldrv = {
 580         &mod_driverops,     /* Type of module. This one is a driver */
 581         MPTSAS_MOD_STRING, /* Name of the module. */
 582         &mptsas_ops,        /* driver ops */
 583 };
 584 
 585 static struct modlinkage modlinkage = {
 586         MODREV_1, &modldrv, NULL
 587 };
 588 #define TARGET_PROP     "target"
 589 #define LUN_PROP        "lun"
 590 #define LUN64_PROP      "lun64"
 591 #define SAS_PROP        "sas-mpt"
 592 #define MDI_GUID        "wwn"
 593 #define NDI_GUID        "guid"
 594 #define MPTSAS_DEV_GONE "mptsas_dev_gone"
 595 
 596 /*
 597  * Local static data
 598  */
 599 #if defined(MPTSAS_DEBUG)
 600 uint32_t mptsas_debug_flags = 0;
 601 #endif  /* defined(MPTSAS_DEBUG) */
 602 uint32_t mptsas_debug_resets = 0;
 603 
 604 static kmutex_t         mptsas_global_mutex;
 605 static void             *mptsas_state;          /* soft state ptr */
 606 static krwlock_t        mptsas_global_rwlock;
 607 
 608 static kmutex_t         mptsas_log_mutex;
 609 static char             mptsas_log_buf[256];
 610 _NOTE(MUTEX_PROTECTS_DATA(mptsas_log_mutex, mptsas_log_buf))
 611 
 612 static mptsas_t *mptsas_head, *mptsas_tail;
 613 static clock_t mptsas_scsi_watchdog_tick;
 614 static clock_t mptsas_tick;
 615 static timeout_id_t mptsas_reset_watch;
 616 static timeout_id_t mptsas_timeout_id;
 617 static int mptsas_timeouts_enabled = 0;
 618 /*
 619  * warlock directives
 620  */
 621 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt \
 622         mptsas_cmd NcrTableIndirect buf scsi_cdb scsi_status))
 623 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", smp_pkt))
 624 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
 625 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mptsas_tgt_private))
 626 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_hba_tran::tran_tgt_private))
 627 
 628 /*
 629  * SM - HBA statics
 630  */
 631 char    *mptsas_driver_rev = MPTSAS_MOD_STRING;
 632 
 633 #ifdef MPTSAS_DEBUG
 634 void debug_enter(char *);
 635 #endif
 636 
 637 /*
 638  * Notes:
 639  *      - scsi_hba_init(9F) initializes SCSI HBA modules
 640  *      - must call scsi_hba_fini(9F) if modload() fails
 641  */
 642 int
 643 _init(void)
 644 {
 645         int status;
 646         /* CONSTCOND */
 647         ASSERT(NO_COMPETING_THREADS);
 648 
 649         NDBG0(("_init"));
 650 
 651         status = ddi_soft_state_init(&mptsas_state, MPTSAS_SIZE,
 652             MPTSAS_INITIAL_SOFT_SPACE);
 653         if (status != 0) {
 654                 return (status);
 655         }
 656 
 657         if ((status = scsi_hba_init(&modlinkage)) != 0) {
 658                 ddi_soft_state_fini(&mptsas_state);
 659                 return (status);
 660         }
 661 
 662         mutex_init(&mptsas_global_mutex, NULL, MUTEX_DRIVER, NULL);
 663         rw_init(&mptsas_global_rwlock, NULL, RW_DRIVER, NULL);
 664         mutex_init(&mptsas_log_mutex, NULL, MUTEX_DRIVER, NULL);
 665 
 666         if ((status = mod_install(&modlinkage)) != 0) {
 667                 mutex_destroy(&mptsas_log_mutex);
 668                 rw_destroy(&mptsas_global_rwlock);
 669                 mutex_destroy(&mptsas_global_mutex);
 670                 ddi_soft_state_fini(&mptsas_state);
 671                 scsi_hba_fini(&modlinkage);
 672         }
 673 
 674         return (status);
 675 }
 676 
 677 /*
 678  * Notes:
 679  *      - scsi_hba_fini(9F) uninitializes SCSI HBA modules
 680  */
 681 int
 682 _fini(void)
 683 {
 684         int     status;
 685         /* CONSTCOND */
 686         ASSERT(NO_COMPETING_THREADS);
 687 
 688         NDBG0(("_fini"));
 689 
 690         if ((status = mod_remove(&modlinkage)) == 0) {
 691                 ddi_soft_state_fini(&mptsas_state);
 692                 scsi_hba_fini(&modlinkage);
 693                 mutex_destroy(&mptsas_global_mutex);
 694                 rw_destroy(&mptsas_global_rwlock);
 695                 mutex_destroy(&mptsas_log_mutex);
 696         }
 697         return (status);
 698 }
 699 
 700 /*
 701  * The loadable-module _info(9E) entry point
 702  */
 703 int
 704 _info(struct modinfo *modinfop)
 705 {
 706         /* CONSTCOND */
 707         ASSERT(NO_COMPETING_THREADS);
 708         NDBG0(("mptsas _info"));
 709 
 710         return (mod_info(&modlinkage, modinfop));
 711 }
 712 
 713 
 714 static int
 715 mptsas_iport_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 716 {
 717         dev_info_t              *pdip;
 718         mptsas_t                *mpt;
 719         scsi_hba_tran_t         *hba_tran;
 720         char                    *iport = NULL;
 721         char                    phymask[MPTSAS_MAX_PHYS];
 722         mptsas_phymask_t        phy_mask = 0;
 723         int                     dynamic_port = 0;
 724         uint32_t                page_address;
 725         char                    initiator_wwnstr[MPTSAS_WWN_STRLEN];
 726         int                     rval = DDI_FAILURE;
 727         int                     i = 0;
 728         uint8_t                 numphys = 0;
 729         uint8_t                 phy_id;
 730         uint8_t                 phy_port = 0;
 731         uint16_t                attached_devhdl = 0;
 732         uint32_t                dev_info;
 733         uint64_t                attached_sas_wwn;
 734         uint16_t                dev_hdl;
 735         uint16_t                pdev_hdl;
 736         uint16_t                bay_num, enclosure;
 737         char                    attached_wwnstr[MPTSAS_WWN_STRLEN];
 738 
 739         /* CONSTCOND */
 740         ASSERT(NO_COMPETING_THREADS);
 741 
 742         switch (cmd) {
 743         case DDI_ATTACH:
 744                 break;
 745 
 746         case DDI_RESUME:
 747                 /*
 748                  * If this a scsi-iport node, nothing to do here.
 749                  */
 750                 return (DDI_SUCCESS);
 751 
 752         default:
 753                 return (DDI_FAILURE);
 754         }
 755 
 756         pdip = ddi_get_parent(dip);
 757 
 758         if ((hba_tran = ndi_flavorv_get(pdip, SCSA_FLAVOR_SCSI_DEVICE)) ==
 759             NULL) {
 760                 cmn_err(CE_WARN, "Failed attach iport because fail to "
 761                     "get tran vector for the HBA node");
 762                 return (DDI_FAILURE);
 763         }
 764 
 765         mpt = TRAN2MPT(hba_tran);
 766         ASSERT(mpt != NULL);
 767         if (mpt == NULL)
 768                 return (DDI_FAILURE);
 769 
 770         if ((hba_tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) ==
 771             NULL) {
 772                 mptsas_log(mpt, CE_WARN, "Failed attach iport because fail to "
 773                     "get tran vector for the iport node");
 774                 return (DDI_FAILURE);
 775         }
 776 
 777         /*
 778          * Overwrite parent's tran_hba_private to iport's tran vector
 779          */
 780         hba_tran->tran_hba_private = mpt;
 781 
 782         ddi_report_dev(dip);
 783 
 784         /*
 785          * Get SAS address for initiator port according dev_handle
 786          */
 787         iport = ddi_get_name_addr(dip);
 788         if (iport && strncmp(iport, "v0", 2) == 0) {
 789                 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 790                     MPTSAS_VIRTUAL_PORT, 1) !=
 791                     DDI_PROP_SUCCESS) {
 792                         (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
 793                             MPTSAS_VIRTUAL_PORT);
 794                         mptsas_log(mpt, CE_WARN, "mptsas virtual port "
 795                             "prop update failed");
 796                         return (DDI_FAILURE);
 797                 }
 798                 return (DDI_SUCCESS);
 799         }
 800 
 801         mutex_enter(&mpt->m_mutex);
 802         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 803                 bzero(phymask, sizeof (phymask));
 804                 (void) sprintf(phymask,
 805                     "%x", mpt->m_phy_info[i].phy_mask);
 806                 if (strcmp(phymask, iport) == 0) {
 807                         break;
 808                 }
 809         }
 810 
 811         if (i == MPTSAS_MAX_PHYS) {
 812                 mptsas_log(mpt, CE_WARN, "Failed attach port %s because port"
 813                     "seems not exist", iport);
 814                 mutex_exit(&mpt->m_mutex);
 815                 return (DDI_FAILURE);
 816         }
 817 
 818         phy_mask = mpt->m_phy_info[i].phy_mask;
 819 
 820         if (mpt->m_phy_info[i].port_flags & AUTO_PORT_CONFIGURATION)
 821                 dynamic_port = 1;
 822         else
 823                 dynamic_port = 0;
 824 
 825         /*
 826          * Update PHY info for smhba
 827          */
 828         if (mptsas_smhba_phy_init(mpt)) {
 829                 mutex_exit(&mpt->m_mutex);
 830                 mptsas_log(mpt, CE_WARN, "mptsas phy update "
 831                     "failed");
 832                 return (DDI_FAILURE);
 833         }
 834 
 835         mutex_exit(&mpt->m_mutex);
 836 
 837         numphys = 0;
 838         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 839                 if ((phy_mask >> i) & 0x01) {
 840                         numphys++;
 841                 }
 842         }
 843 
 844         bzero(initiator_wwnstr, sizeof (initiator_wwnstr));
 845         (void) sprintf(initiator_wwnstr, "w%016"PRIx64,
 846             mpt->un.m_base_wwid);
 847 
 848         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
 849             SCSI_ADDR_PROP_INITIATOR_PORT, initiator_wwnstr) !=
 850             DDI_PROP_SUCCESS) {
 851                 (void) ddi_prop_remove(DDI_DEV_T_NONE,
 852                     dip, SCSI_ADDR_PROP_INITIATOR_PORT);
 853                 mptsas_log(mpt, CE_WARN, "mptsas Initiator port "
 854                     "prop update failed");
 855                 return (DDI_FAILURE);
 856         }
 857         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 858             MPTSAS_NUM_PHYS, numphys) !=
 859             DDI_PROP_SUCCESS) {
 860                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, MPTSAS_NUM_PHYS);
 861                 return (DDI_FAILURE);
 862         }
 863 
 864         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 865             "phymask", phy_mask) !=
 866             DDI_PROP_SUCCESS) {
 867                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "phymask");
 868                 mptsas_log(mpt, CE_WARN, "mptsas phy mask "
 869                     "prop update failed");
 870                 return (DDI_FAILURE);
 871         }
 872 
 873         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 874             "dynamic-port", dynamic_port) !=
 875             DDI_PROP_SUCCESS) {
 876                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "dynamic-port");
 877                 mptsas_log(mpt, CE_WARN, "mptsas dynamic port "
 878                     "prop update failed");
 879                 return (DDI_FAILURE);
 880         }
 881         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 882             MPTSAS_VIRTUAL_PORT, 0) !=
 883             DDI_PROP_SUCCESS) {
 884                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
 885                     MPTSAS_VIRTUAL_PORT);
 886                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
 887                     "prop update failed");
 888                 return (DDI_FAILURE);
 889         }
 890         mptsas_smhba_set_phy_props(mpt,
 891             iport, dip, numphys, &attached_devhdl);
 892 
 893         mutex_enter(&mpt->m_mutex);
 894         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
 895             MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)attached_devhdl;
 896         rval = mptsas_get_sas_device_page0(mpt, page_address, &dev_hdl,
 897             &attached_sas_wwn, &dev_info, &phy_port, &phy_id,
 898             &pdev_hdl, &bay_num, &enclosure);
 899         if (rval != DDI_SUCCESS) {
 900                 mptsas_log(mpt, CE_WARN,
 901                     "Failed to get device page0 for handle:%d",
 902                     attached_devhdl);
 903                 mutex_exit(&mpt->m_mutex);
 904                 return (DDI_FAILURE);
 905         }
 906 
 907         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 908                 bzero(phymask, sizeof (phymask));
 909                 (void) sprintf(phymask, "%x", mpt->m_phy_info[i].phy_mask);
 910                 if (strcmp(phymask, iport) == 0) {
 911                         (void) sprintf(&mpt->m_phy_info[i].smhba_info.path[0],
 912                             "%x",
 913                             mpt->m_phy_info[i].phy_mask);
 914                 }
 915         }
 916         mutex_exit(&mpt->m_mutex);
 917 
 918         bzero(attached_wwnstr, sizeof (attached_wwnstr));
 919         (void) sprintf(attached_wwnstr, "w%016"PRIx64,
 920             attached_sas_wwn);
 921         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
 922             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
 923             DDI_PROP_SUCCESS) {
 924                 (void) ddi_prop_remove(DDI_DEV_T_NONE,
 925                     dip, SCSI_ADDR_PROP_ATTACHED_PORT);
 926                 return (DDI_FAILURE);
 927         }
 928 
 929         /* Create kstats for each phy on this iport */
 930 
 931         mptsas_create_phy_stats(mpt, iport, dip);
 932 
 933         /*
 934          * register sas hba iport with mdi (MPxIO/vhci)
 935          */
 936         if (mdi_phci_register(MDI_HCI_CLASS_SCSI,
 937             dip, 0) == MDI_SUCCESS) {
 938                 mpt->m_mpxio_enable = TRUE;
 939         }
 940         return (DDI_SUCCESS);
 941 }
 942 
 943 /*
 944  * Notes:
 945  *      Set up all device state and allocate data structures,
 946  *      mutexes, condition variables, etc. for device operation.
 947  *      Add interrupts needed.
 948  *      Return DDI_SUCCESS if device is ready, else return DDI_FAILURE.
 949  */
 950 static int
 951 mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 952 {
 953         mptsas_t                *mpt = NULL;
 954         int                     instance, i, j;
 955         int                     doneq_thread_num;
 956         char                    intr_added = 0;
 957         char                    map_setup = 0;
 958         char                    config_setup = 0;
 959         char                    hba_attach_setup = 0;
 960         char                    smp_attach_setup = 0;
 961         char                    mutex_init_done = 0;
 962         char                    event_taskq_create = 0;
 963         char                    dr_taskq_create = 0;
 964         char                    doneq_thread_create = 0;
 965         scsi_hba_tran_t         *hba_tran;
 966         uint_t                  mem_bar = MEM_SPACE;
 967         int                     rval = DDI_FAILURE;
 968 
 969         /* CONSTCOND */
 970         ASSERT(NO_COMPETING_THREADS);
 971 
 972         if (scsi_hba_iport_unit_address(dip)) {
 973                 return (mptsas_iport_attach(dip, cmd));
 974         }
 975 
 976         switch (cmd) {
 977         case DDI_ATTACH:
 978                 break;
 979 
 980         case DDI_RESUME:
 981                 if ((hba_tran = ddi_get_driver_private(dip)) == NULL)
 982                         return (DDI_FAILURE);
 983 
 984                 mpt = TRAN2MPT(hba_tran);
 985 
 986                 if (!mpt) {
 987                         return (DDI_FAILURE);
 988                 }
 989 
 990                 /*
 991                  * Reset hardware and softc to "no outstanding commands"
 992                  * Note that a check condition can result on first command
 993                  * to a target.
 994                  */
 995                 mutex_enter(&mpt->m_mutex);
 996 
 997                 /*
 998                  * raise power.
 999                  */
1000                 if (mpt->m_options & MPTSAS_OPT_PM) {
1001                         mutex_exit(&mpt->m_mutex);
1002                         (void) pm_busy_component(dip, 0);
1003                         rval = pm_power_has_changed(dip, 0, PM_LEVEL_D0);
1004                         if (rval == DDI_SUCCESS) {
1005                                 mutex_enter(&mpt->m_mutex);
1006                         } else {
1007                                 /*
1008                                  * The pm_raise_power() call above failed,
1009                                  * and that can only occur if we were unable
1010                                  * to reset the hardware.  This is probably
1011                                  * due to unhealty hardware, and because
1012                                  * important filesystems(such as the root
1013                                  * filesystem) could be on the attached disks,
1014                                  * it would not be a good idea to continue,
1015                                  * as we won't be entirely certain we are
1016                                  * writing correct data.  So we panic() here
1017                                  * to not only prevent possible data corruption,
1018                                  * but to give developers or end users a hope
1019                                  * of identifying and correcting any problems.
1020                                  */
1021                                 fm_panic("mptsas could not reset hardware "
1022                                     "during resume");
1023                         }
1024                 }
1025 
1026                 mpt->m_suspended = 0;
1027 
1028                 /*
1029                  * Reinitialize ioc
1030                  */
1031                 mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1032                 if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
1033                         mutex_exit(&mpt->m_mutex);
1034                         if (mpt->m_options & MPTSAS_OPT_PM) {
1035                                 (void) pm_idle_component(dip, 0);
1036                         }
1037                         fm_panic("mptsas init chip fail during resume");
1038                 }
1039                 /*
1040                  * mptsas_update_driver_data needs interrupts so enable them
1041                  * first.
1042                  */
1043                 MPTSAS_ENABLE_INTR(mpt);
1044                 mptsas_update_driver_data(mpt);
1045 
1046                 /* start requests, if possible */
1047                 mptsas_restart_hba(mpt);
1048 
1049                 mutex_exit(&mpt->m_mutex);
1050 
1051                 /*
1052                  * Restart watch thread
1053                  */
1054                 mutex_enter(&mptsas_global_mutex);
1055                 if (mptsas_timeout_id == 0) {
1056                         mptsas_timeout_id = timeout(mptsas_watch, NULL,
1057                             mptsas_tick);
1058                         mptsas_timeouts_enabled = 1;
1059                 }
1060                 mutex_exit(&mptsas_global_mutex);
1061 
1062                 /* report idle status to pm framework */
1063                 if (mpt->m_options & MPTSAS_OPT_PM) {
1064                         (void) pm_idle_component(dip, 0);
1065                 }
1066 
1067                 return (DDI_SUCCESS);
1068 
1069         default:
1070                 return (DDI_FAILURE);
1071 
1072         }
1073 
1074         instance = ddi_get_instance(dip);
1075 
1076         /*
1077          * Allocate softc information.
1078          */
1079         if (ddi_soft_state_zalloc(mptsas_state, instance) != DDI_SUCCESS) {
1080                 mptsas_log(NULL, CE_WARN,
1081                     "mptsas%d: cannot allocate soft state", instance);
1082                 goto fail;
1083         }
1084 
1085         mpt = ddi_get_soft_state(mptsas_state, instance);
1086 
1087         if (mpt == NULL) {
1088                 mptsas_log(NULL, CE_WARN,
1089                     "mptsas%d: cannot get soft state", instance);
1090                 goto fail;
1091         }
1092 
1093         /* Mark us as a primary ioctl node for an instance. */
1094         (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, "primary-ioctl-node",
1095             instance);
1096 
1097         /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
1098         scsi_size_clean(dip);
1099 
1100         mpt->m_dip = dip;
1101         mpt->m_instance = instance;
1102 
1103         /* Make a per-instance copy of the structures */
1104         mpt->m_io_dma_attr = mptsas_dma_attrs64;
1105         mpt->m_msg_dma_attr = mptsas_dma_attrs;
1106         mpt->m_reg_acc_attr = mptsas_dev_attr;
1107         mpt->m_dev_acc_attr = mptsas_dev_attr;
1108 
1109         /*
1110          * Initialize FMA
1111          */
1112         mpt->m_fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, mpt->m_dip,
1113             DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
1114             DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
1115             DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
1116 
1117         mptsas_fm_init(mpt);
1118 
1119         if (mptsas_alloc_handshake_msg(mpt,
1120             sizeof (Mpi2SCSITaskManagementRequest_t)) == DDI_FAILURE) {
1121                 mptsas_log(mpt, CE_WARN, "cannot initialize handshake msg.");
1122                 goto fail;
1123         }
1124 
1125         /*
1126          * Setup configuration space
1127          */
1128         if (mptsas_config_space_init(mpt) == FALSE) {
1129                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init failed");
1130                 goto fail;
1131         }
1132         config_setup++;
1133 
1134         if (ddi_regs_map_setup(dip, mem_bar, (caddr_t *)&mpt->m_reg,
1135             0, 0, &mpt->m_reg_acc_attr, &mpt->m_datap) != DDI_SUCCESS) {
1136                 mptsas_log(mpt, CE_WARN, "map setup failed");
1137                 goto fail;
1138         }
1139         map_setup++;
1140 
1141         /*
1142          * A taskq is created for dealing with the event handler
1143          */
1144         if ((mpt->m_event_taskq = ddi_taskq_create(dip, "mptsas_event_taskq",
1145             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1146                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create failed");
1147                 goto fail;
1148         }
1149         event_taskq_create++;
1150 
1151         /*
1152          * A taskq is created for dealing with dr events
1153          */
1154         if ((mpt->m_dr_taskq = ddi_taskq_create(dip,
1155             "mptsas_dr_taskq",
1156             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1157                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create for discovery "
1158                     "failed");
1159                 goto fail;
1160         }
1161         dr_taskq_create++;
1162 
1163         mpt->m_doneq_thread_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1164             0, "mptsas_doneq_thread_threshold_prop", 10);
1165         mpt->m_doneq_length_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1166             0, "mptsas_doneq_length_threshold_prop", 8);
1167         mpt->m_doneq_thread_n = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1168             0, "mptsas_doneq_thread_n_prop", 8);
1169 
1170         if (mpt->m_doneq_thread_n) {
1171                 cv_init(&mpt->m_doneq_thread_cv, NULL, CV_DRIVER, NULL);
1172                 mutex_init(&mpt->m_doneq_mutex, NULL, MUTEX_DRIVER, NULL);
1173 
1174                 mutex_enter(&mpt->m_doneq_mutex);
1175                 mpt->m_doneq_thread_id =
1176                     kmem_zalloc(sizeof (mptsas_doneq_thread_list_t)
1177                     * mpt->m_doneq_thread_n, KM_SLEEP);
1178 
1179                 for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1180                         cv_init(&mpt->m_doneq_thread_id[j].cv, NULL,
1181                             CV_DRIVER, NULL);
1182                         mutex_init(&mpt->m_doneq_thread_id[j].mutex, NULL,
1183                             MUTEX_DRIVER, NULL);
1184                         mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1185                         mpt->m_doneq_thread_id[j].flag |=
1186                             MPTSAS_DONEQ_THREAD_ACTIVE;
1187                         mpt->m_doneq_thread_id[j].arg.mpt = mpt;
1188                         mpt->m_doneq_thread_id[j].arg.t = j;
1189                         mpt->m_doneq_thread_id[j].threadp =
1190                             thread_create(NULL, 0, mptsas_doneq_thread,
1191                             &mpt->m_doneq_thread_id[j].arg,
1192                             0, &p0, TS_RUN, minclsyspri);
1193                         mpt->m_doneq_thread_id[j].donetail =
1194                             &mpt->m_doneq_thread_id[j].doneq;
1195                         mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1196                 }
1197                 mutex_exit(&mpt->m_doneq_mutex);
1198                 doneq_thread_create++;
1199         }
1200 
1201         /* Initialize mutex used in interrupt handler */
1202         mutex_init(&mpt->m_mutex, NULL, MUTEX_DRIVER,
1203             DDI_INTR_PRI(mpt->m_intr_pri));
1204         mutex_init(&mpt->m_passthru_mutex, NULL, MUTEX_DRIVER, NULL);
1205         mutex_init(&mpt->m_intr_mutex, NULL, MUTEX_DRIVER,
1206             DDI_INTR_PRI(mpt->m_intr_pri));
1207         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1208                 mutex_init(&mpt->m_phy_info[i].smhba_info.phy_mutex,
1209                     NULL, MUTEX_DRIVER,
1210                     DDI_INTR_PRI(mpt->m_intr_pri));
1211         }
1212 
1213         cv_init(&mpt->m_cv, NULL, CV_DRIVER, NULL);
1214         cv_init(&mpt->m_passthru_cv, NULL, CV_DRIVER, NULL);
1215         cv_init(&mpt->m_fw_cv, NULL, CV_DRIVER, NULL);
1216         cv_init(&mpt->m_config_cv, NULL, CV_DRIVER, NULL);
1217         cv_init(&mpt->m_fw_diag_cv, NULL, CV_DRIVER, NULL);
1218         mutex_init_done++;
1219 
1220         /*
1221          * Disable hardware interrupt since we're not ready to
1222          * handle it yet.
1223          */
1224         MPTSAS_DISABLE_INTR(mpt);
1225         if (mptsas_register_intrs(mpt) == FALSE)
1226                 goto fail;
1227         intr_added++;
1228 
1229         mutex_enter(&mpt->m_mutex);
1230         /*
1231          * Initialize power management component
1232          */
1233         if (mpt->m_options & MPTSAS_OPT_PM) {
1234                 if (mptsas_init_pm(mpt)) {
1235                         mutex_exit(&mpt->m_mutex);
1236                         mptsas_log(mpt, CE_WARN, "mptsas pm initialization "
1237                             "failed");
1238                         goto fail;
1239                 }
1240         }
1241 
1242         /*
1243          * Initialize chip using Message Unit Reset, if allowed
1244          */
1245         mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1246         if (mptsas_init_chip(mpt, TRUE) == DDI_FAILURE) {
1247                 mutex_exit(&mpt->m_mutex);
1248                 mptsas_log(mpt, CE_WARN, "mptsas chip initialization failed");
1249                 goto fail;
1250         }
1251 
1252         /*
1253          * Fill in the phy_info structure and get the base WWID
1254          */
1255         if (mptsas_get_manufacture_page5(mpt) == DDI_FAILURE) {
1256                 mptsas_log(mpt, CE_WARN,
1257                     "mptsas_get_manufacture_page5 failed!");
1258                 goto fail;
1259         }
1260 
1261         if (mptsas_get_sas_io_unit_page_hndshk(mpt)) {
1262                 mptsas_log(mpt, CE_WARN,
1263                     "mptsas_get_sas_io_unit_page_hndshk failed!");
1264                 goto fail;
1265         }
1266 
1267         if (mptsas_get_manufacture_page0(mpt) == DDI_FAILURE) {
1268                 mptsas_log(mpt, CE_WARN,
1269                     "mptsas_get_manufacture_page0 failed!");
1270                 goto fail;
1271         }
1272 
1273         mutex_exit(&mpt->m_mutex);
1274 
1275         /*
1276          * Register the iport for multiple port HBA
1277          */
1278         mptsas_iport_register(mpt);
1279 
1280         /*
1281          * initialize SCSI HBA transport structure
1282          */
1283         if (mptsas_hba_setup(mpt) == FALSE)
1284                 goto fail;
1285         hba_attach_setup++;
1286 
1287         if (mptsas_smp_setup(mpt) == FALSE)
1288                 goto fail;
1289         smp_attach_setup++;
1290 
1291         if (mptsas_cache_create(mpt) == FALSE)
1292                 goto fail;
1293 
1294         mpt->m_scsi_reset_delay      = ddi_prop_get_int(DDI_DEV_T_ANY,
1295             dip, 0, "scsi-reset-delay", SCSI_DEFAULT_RESET_DELAY);
1296         if (mpt->m_scsi_reset_delay == 0) {
1297                 mptsas_log(mpt, CE_NOTE,
1298                     "scsi_reset_delay of 0 is not recommended,"
1299                     " resetting to SCSI_DEFAULT_RESET_DELAY\n");
1300                 mpt->m_scsi_reset_delay = SCSI_DEFAULT_RESET_DELAY;
1301         }
1302 
1303         /*
1304          * Initialize the wait and done FIFO queue
1305          */
1306         mpt->m_donetail = &mpt->m_doneq;
1307         mpt->m_waitqtail = &mpt->m_waitq;
1308 
1309         /*
1310          * ioc cmd queue initialize
1311          */
1312         mpt->m_ioc_event_cmdtail = &mpt->m_ioc_event_cmdq;
1313         mpt->m_dev_handle = 0xFFFF;
1314 
1315         MPTSAS_ENABLE_INTR(mpt);
1316 
1317         /*
1318          * enable event notification
1319          */
1320         mutex_enter(&mpt->m_mutex);
1321         if (mptsas_ioc_enable_event_notification(mpt)) {
1322                 mutex_exit(&mpt->m_mutex);
1323                 goto fail;
1324         }
1325         mutex_exit(&mpt->m_mutex);
1326 
1327         /*
1328          * Initialize PHY info for smhba
1329          */
1330         if (mptsas_smhba_setup(mpt)) {
1331                 mptsas_log(mpt, CE_WARN, "mptsas phy initialization "
1332                     "failed");
1333                 goto fail;
1334         }
1335 
1336         /* Check all dma handles allocated in attach */
1337         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl)
1338             != DDI_SUCCESS) ||
1339             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl)
1340             != DDI_SUCCESS) ||
1341             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl)
1342             != DDI_SUCCESS) ||
1343             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl)
1344             != DDI_SUCCESS) ||
1345             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl)
1346             != DDI_SUCCESS)) {
1347                 goto fail;
1348         }
1349 
1350         /* Check all acc handles allocated in attach */
1351         if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
1352             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl)
1353             != DDI_SUCCESS) ||
1354             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl)
1355             != DDI_SUCCESS) ||
1356             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl)
1357             != DDI_SUCCESS) ||
1358             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl)
1359             != DDI_SUCCESS) ||
1360             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl)
1361             != DDI_SUCCESS) ||
1362             (mptsas_check_acc_handle(mpt->m_config_handle)
1363             != DDI_SUCCESS)) {
1364                 goto fail;
1365         }
1366 
1367         /*
1368          * After this point, we are not going to fail the attach.
1369          */
1370         /*
1371          * used for mptsas_watch
1372          */
1373         mptsas_list_add(mpt);
1374 
1375         mutex_enter(&mptsas_global_mutex);
1376         if (mptsas_timeouts_enabled == 0) {
1377                 mptsas_scsi_watchdog_tick = ddi_prop_get_int(DDI_DEV_T_ANY,
1378                     dip, 0, "scsi-watchdog-tick", DEFAULT_WD_TICK);
1379 
1380                 mptsas_tick = mptsas_scsi_watchdog_tick *
1381                     drv_usectohz((clock_t)1000000);
1382 
1383                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
1384                 mptsas_timeouts_enabled = 1;
1385         }
1386         mutex_exit(&mptsas_global_mutex);
1387 
1388         /* Print message of HBA present */
1389         ddi_report_dev(dip);
1390 
1391         /* report idle status to pm framework */
1392         if (mpt->m_options & MPTSAS_OPT_PM) {
1393                 (void) pm_idle_component(dip, 0);
1394         }
1395 
1396         return (DDI_SUCCESS);
1397 
1398 fail:
1399         mptsas_log(mpt, CE_WARN, "attach failed");
1400         mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
1401         ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
1402         if (mpt) {
1403                 mutex_enter(&mptsas_global_mutex);
1404 
1405                 if (mptsas_timeout_id && (mptsas_head == NULL)) {
1406                         timeout_id_t tid = mptsas_timeout_id;
1407                         mptsas_timeouts_enabled = 0;
1408                         mptsas_timeout_id = 0;
1409                         mutex_exit(&mptsas_global_mutex);
1410                         (void) untimeout(tid);
1411                         mutex_enter(&mptsas_global_mutex);
1412                 }
1413                 mutex_exit(&mptsas_global_mutex);
1414                 /* deallocate in reverse order */
1415                 mptsas_cache_destroy(mpt);
1416 
1417                 if (smp_attach_setup) {
1418                         mptsas_smp_teardown(mpt);
1419                 }
1420                 if (hba_attach_setup) {
1421                         mptsas_hba_teardown(mpt);
1422                 }
1423 
1424                 if (mpt->m_active) {
1425                         mptsas_hash_uninit(&mpt->m_active->m_smptbl,
1426                             sizeof (mptsas_smp_t));
1427                         mptsas_hash_uninit(&mpt->m_active->m_tgttbl,
1428                             sizeof (mptsas_target_t));
1429                         mptsas_free_active_slots(mpt);
1430                 }
1431                 if (intr_added) {
1432                         mptsas_unregister_intrs(mpt);
1433                 }
1434 
1435                 if (doneq_thread_create) {
1436                         mutex_enter(&mpt->m_doneq_mutex);
1437                         doneq_thread_num = mpt->m_doneq_thread_n;
1438                         for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1439                                 mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1440                                 mpt->m_doneq_thread_id[j].flag &=
1441                                     (~MPTSAS_DONEQ_THREAD_ACTIVE);
1442                                 cv_signal(&mpt->m_doneq_thread_id[j].cv);
1443                                 mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1444                         }
1445                         while (mpt->m_doneq_thread_n) {
1446                                 cv_wait(&mpt->m_doneq_thread_cv,
1447                                     &mpt->m_doneq_mutex);
1448                         }
1449                         for (j = 0; j < doneq_thread_num; j++) {
1450                                 cv_destroy(&mpt->m_doneq_thread_id[j].cv);
1451                                 mutex_destroy(&mpt->m_doneq_thread_id[j].mutex);
1452                         }
1453                         kmem_free(mpt->m_doneq_thread_id,
1454                             sizeof (mptsas_doneq_thread_list_t)
1455                             * doneq_thread_num);
1456                         mutex_exit(&mpt->m_doneq_mutex);
1457                         cv_destroy(&mpt->m_doneq_thread_cv);
1458                         mutex_destroy(&mpt->m_doneq_mutex);
1459                 }
1460                 if (event_taskq_create) {
1461                         ddi_taskq_destroy(mpt->m_event_taskq);
1462                 }
1463                 if (dr_taskq_create) {
1464                         ddi_taskq_destroy(mpt->m_dr_taskq);
1465                 }
1466                 if (mutex_init_done) {
1467                         mutex_destroy(&mpt->m_intr_mutex);
1468                         mutex_destroy(&mpt->m_passthru_mutex);
1469                         mutex_destroy(&mpt->m_mutex);
1470                         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1471                                 mutex_destroy(
1472                                     &mpt->m_phy_info[i].smhba_info.phy_mutex);
1473                         }
1474                         cv_destroy(&mpt->m_cv);
1475                         cv_destroy(&mpt->m_passthru_cv);
1476                         cv_destroy(&mpt->m_fw_cv);
1477                         cv_destroy(&mpt->m_config_cv);
1478                         cv_destroy(&mpt->m_fw_diag_cv);
1479                 }
1480 
1481                 if (map_setup) {
1482                         mptsas_cfg_fini(mpt);
1483                 }
1484                 if (config_setup) {
1485                         mptsas_config_space_fini(mpt);
1486                 }
1487                 mptsas_free_handshake_msg(mpt);
1488                 mptsas_hba_fini(mpt);
1489 
1490                 mptsas_fm_fini(mpt);
1491                 ddi_soft_state_free(mptsas_state, instance);
1492                 ddi_prop_remove_all(dip);
1493         }
1494         return (DDI_FAILURE);
1495 }
1496 
1497 static int
1498 mptsas_suspend(dev_info_t *devi)
1499 {
1500         mptsas_t        *mpt, *g;
1501         scsi_hba_tran_t *tran;
1502 
1503         if (scsi_hba_iport_unit_address(devi)) {
1504                 return (DDI_SUCCESS);
1505         }
1506 
1507         if ((tran = ddi_get_driver_private(devi)) == NULL)
1508                 return (DDI_SUCCESS);
1509 
1510         mpt = TRAN2MPT(tran);
1511         if (!mpt) {
1512                 return (DDI_SUCCESS);
1513         }
1514 
1515         mutex_enter(&mpt->m_mutex);
1516 
1517         if (mpt->m_suspended++) {
1518                 mutex_exit(&mpt->m_mutex);
1519                 return (DDI_SUCCESS);
1520         }
1521 
1522         /*
1523          * Cancel timeout threads for this mpt
1524          */
1525         if (mpt->m_quiesce_timeid) {
1526                 timeout_id_t tid = mpt->m_quiesce_timeid;
1527                 mpt->m_quiesce_timeid = 0;
1528                 mutex_exit(&mpt->m_mutex);
1529                 (void) untimeout(tid);
1530                 mutex_enter(&mpt->m_mutex);
1531         }
1532 
1533         if (mpt->m_restart_cmd_timeid) {
1534                 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1535                 mpt->m_restart_cmd_timeid = 0;
1536                 mutex_exit(&mpt->m_mutex);
1537                 (void) untimeout(tid);
1538                 mutex_enter(&mpt->m_mutex);
1539         }
1540 
1541         mutex_exit(&mpt->m_mutex);
1542 
1543         (void) pm_idle_component(mpt->m_dip, 0);
1544 
1545         /*
1546          * Cancel watch threads if all mpts suspended
1547          */
1548         rw_enter(&mptsas_global_rwlock, RW_WRITER);
1549         for (g = mptsas_head; g != NULL; g = g->m_next) {
1550                 if (!g->m_suspended)
1551                         break;
1552         }
1553         rw_exit(&mptsas_global_rwlock);
1554 
1555         mutex_enter(&mptsas_global_mutex);
1556         if (g == NULL) {
1557                 timeout_id_t tid;
1558 
1559                 mptsas_timeouts_enabled = 0;
1560                 if (mptsas_timeout_id) {
1561                         tid = mptsas_timeout_id;
1562                         mptsas_timeout_id = 0;
1563                         mutex_exit(&mptsas_global_mutex);
1564                         (void) untimeout(tid);
1565                         mutex_enter(&mptsas_global_mutex);
1566                 }
1567                 if (mptsas_reset_watch) {
1568                         tid = mptsas_reset_watch;
1569                         mptsas_reset_watch = 0;
1570                         mutex_exit(&mptsas_global_mutex);
1571                         (void) untimeout(tid);
1572                         mutex_enter(&mptsas_global_mutex);
1573                 }
1574         }
1575         mutex_exit(&mptsas_global_mutex);
1576 
1577         mutex_enter(&mpt->m_mutex);
1578 
1579         /*
1580          * If this mpt is not in full power(PM_LEVEL_D0), just return.
1581          */
1582         if ((mpt->m_options & MPTSAS_OPT_PM) &&
1583             (mpt->m_power_level != PM_LEVEL_D0)) {
1584                 mutex_exit(&mpt->m_mutex);
1585                 return (DDI_SUCCESS);
1586         }
1587 
1588         /* Disable HBA interrupts in hardware */
1589         MPTSAS_DISABLE_INTR(mpt);
1590         /*
1591          * Send RAID action system shutdown to sync IR
1592          */
1593         mptsas_raid_action_system_shutdown(mpt);
1594 
1595         mutex_exit(&mpt->m_mutex);
1596 
1597         /* drain the taskq */
1598         ddi_taskq_wait(mpt->m_event_taskq);
1599         ddi_taskq_wait(mpt->m_dr_taskq);
1600 
1601         return (DDI_SUCCESS);
1602 }
1603 
1604 #ifdef  __sparc
1605 /*ARGSUSED*/
1606 static int
1607 mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd)
1608 {
1609         mptsas_t        *mpt;
1610         scsi_hba_tran_t *tran;
1611 
1612         /*
1613          * If this call is for iport, just return.
1614          */
1615         if (scsi_hba_iport_unit_address(devi))
1616                 return (DDI_SUCCESS);
1617 
1618         if ((tran = ddi_get_driver_private(devi)) == NULL)
1619                 return (DDI_SUCCESS);
1620 
1621         if ((mpt = TRAN2MPT(tran)) == NULL)
1622                 return (DDI_SUCCESS);
1623 
1624         /*
1625          * Send RAID action system shutdown to sync IR.  Disable HBA
1626          * interrupts in hardware first.
1627          */
1628         MPTSAS_DISABLE_INTR(mpt);
1629         mptsas_raid_action_system_shutdown(mpt);
1630 
1631         return (DDI_SUCCESS);
1632 }
1633 #else /* __sparc */
1634 /*
1635  * quiesce(9E) entry point.
1636  *
1637  * This function is called when the system is single-threaded at high
1638  * PIL with preemption disabled. Therefore, this function must not be
1639  * blocked.
1640  *
1641  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1642  * DDI_FAILURE indicates an error condition and should almost never happen.
1643  */
1644 static int
1645 mptsas_quiesce(dev_info_t *devi)
1646 {
1647         mptsas_t        *mpt;
1648         scsi_hba_tran_t *tran;
1649 
1650         /*
1651          * If this call is for iport, just return.
1652          */
1653         if (scsi_hba_iport_unit_address(devi))
1654                 return (DDI_SUCCESS);
1655 
1656         if ((tran = ddi_get_driver_private(devi)) == NULL)
1657                 return (DDI_SUCCESS);
1658 
1659         if ((mpt = TRAN2MPT(tran)) == NULL)
1660                 return (DDI_SUCCESS);
1661 
1662         /* Disable HBA interrupts in hardware */
1663         MPTSAS_DISABLE_INTR(mpt);
1664         /* Send RAID action system shutdonw to sync IR */
1665         mptsas_raid_action_system_shutdown(mpt);
1666 
1667         return (DDI_SUCCESS);
1668 }
1669 #endif  /* __sparc */
1670 
1671 /*
1672  * detach(9E).  Remove all device allocations and system resources;
1673  * disable device interrupts.
1674  * Return DDI_SUCCESS if done; DDI_FAILURE if there's a problem.
1675  */
1676 static int
1677 mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1678 {
1679         /* CONSTCOND */
1680         ASSERT(NO_COMPETING_THREADS);
1681         NDBG0(("mptsas_detach: dip=0x%p cmd=0x%p", (void *)devi, (void *)cmd));
1682 
1683         switch (cmd) {
1684         case DDI_DETACH:
1685                 return (mptsas_do_detach(devi));
1686 
1687         case DDI_SUSPEND:
1688                 return (mptsas_suspend(devi));
1689 
1690         default:
1691                 return (DDI_FAILURE);
1692         }
1693         /* NOTREACHED */
1694 }
1695 
1696 static int
1697 mptsas_do_detach(dev_info_t *dip)
1698 {
1699         mptsas_t        *mpt;
1700         scsi_hba_tran_t *tran;
1701         int             circ = 0;
1702         int             circ1 = 0;
1703         mdi_pathinfo_t  *pip = NULL;
1704         int             i;
1705         int             doneq_thread_num = 0;
1706 
1707         NDBG0(("mptsas_do_detach: dip=0x%p", (void *)dip));
1708 
1709         if ((tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) == NULL)
1710                 return (DDI_FAILURE);
1711 
1712         mpt = TRAN2MPT(tran);
1713         if (!mpt) {
1714                 return (DDI_FAILURE);
1715         }
1716         /*
1717          * Still have pathinfo child, should not detach mpt driver
1718          */
1719         if (scsi_hba_iport_unit_address(dip)) {
1720                 if (mpt->m_mpxio_enable) {
1721                         /*
1722                          * MPxIO enabled for the iport
1723                          */
1724                         ndi_devi_enter(scsi_vhci_dip, &circ1);
1725                         ndi_devi_enter(dip, &circ);
1726                         while (pip = mdi_get_next_client_path(dip, NULL)) {
1727                                 if (mdi_pi_free(pip, 0) == MDI_SUCCESS) {
1728                                         continue;
1729                                 }
1730                                 ndi_devi_exit(dip, circ);
1731                                 ndi_devi_exit(scsi_vhci_dip, circ1);
1732                                 NDBG12(("detach failed because of "
1733                                     "outstanding path info"));
1734                                 return (DDI_FAILURE);
1735                         }
1736                         ndi_devi_exit(dip, circ);
1737                         ndi_devi_exit(scsi_vhci_dip, circ1);
1738                         (void) mdi_phci_unregister(dip, 0);
1739                 }
1740 
1741                 ddi_prop_remove_all(dip);
1742 
1743                 return (DDI_SUCCESS);
1744         }
1745 
1746         /* Make sure power level is D0 before accessing registers */
1747         if (mpt->m_options & MPTSAS_OPT_PM) {
1748                 (void) pm_busy_component(dip, 0);
1749                 if (mpt->m_power_level != PM_LEVEL_D0) {
1750                         if (pm_raise_power(dip, 0, PM_LEVEL_D0) !=
1751                             DDI_SUCCESS) {
1752                                 mptsas_log(mpt, CE_WARN,
1753                                     "mptsas%d: Raise power request failed.",
1754                                     mpt->m_instance);
1755                                 (void) pm_idle_component(dip, 0);
1756                                 return (DDI_FAILURE);
1757                         }
1758                 }
1759         }
1760 
1761         /*
1762          * Send RAID action system shutdown to sync IR.  After action, send a
1763          * Message Unit Reset. Since after that DMA resource will be freed,
1764          * set ioc to READY state will avoid HBA initiated DMA operation.
1765          */
1766         mutex_enter(&mpt->m_mutex);
1767         MPTSAS_DISABLE_INTR(mpt);
1768         mptsas_raid_action_system_shutdown(mpt);
1769         mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1770         (void) mptsas_ioc_reset(mpt, FALSE);
1771         mutex_exit(&mpt->m_mutex);
1772         mptsas_rem_intrs(mpt);
1773         ddi_taskq_destroy(mpt->m_event_taskq);
1774         ddi_taskq_destroy(mpt->m_dr_taskq);
1775 
1776         if (mpt->m_doneq_thread_n) {
1777                 mutex_enter(&mpt->m_doneq_mutex);
1778                 doneq_thread_num = mpt->m_doneq_thread_n;
1779                 for (i = 0; i < mpt->m_doneq_thread_n; i++) {
1780                         mutex_enter(&mpt->m_doneq_thread_id[i].mutex);
1781                         mpt->m_doneq_thread_id[i].flag &=
1782                             (~MPTSAS_DONEQ_THREAD_ACTIVE);
1783                         cv_signal(&mpt->m_doneq_thread_id[i].cv);
1784                         mutex_exit(&mpt->m_doneq_thread_id[i].mutex);
1785                 }
1786                 while (mpt->m_doneq_thread_n) {
1787                         cv_wait(&mpt->m_doneq_thread_cv,
1788                             &mpt->m_doneq_mutex);
1789                 }
1790                 for (i = 0;  i < doneq_thread_num; i++) {
1791                         cv_destroy(&mpt->m_doneq_thread_id[i].cv);
1792                         mutex_destroy(&mpt->m_doneq_thread_id[i].mutex);
1793                 }
1794                 kmem_free(mpt->m_doneq_thread_id,
1795                     sizeof (mptsas_doneq_thread_list_t)
1796                     * doneq_thread_num);
1797                 mutex_exit(&mpt->m_doneq_mutex);
1798                 cv_destroy(&mpt->m_doneq_thread_cv);
1799                 mutex_destroy(&mpt->m_doneq_mutex);
1800         }
1801 
1802         scsi_hba_reset_notify_tear_down(mpt->m_reset_notify_listf);
1803 
1804         mptsas_list_del(mpt);
1805 
1806         /*
1807          * Cancel timeout threads for this mpt
1808          */
1809         mutex_enter(&mpt->m_mutex);
1810         if (mpt->m_quiesce_timeid) {
1811                 timeout_id_t tid = mpt->m_quiesce_timeid;
1812                 mpt->m_quiesce_timeid = 0;
1813                 mutex_exit(&mpt->m_mutex);
1814                 (void) untimeout(tid);
1815                 mutex_enter(&mpt->m_mutex);
1816         }
1817 
1818         if (mpt->m_restart_cmd_timeid) {
1819                 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1820                 mpt->m_restart_cmd_timeid = 0;
1821                 mutex_exit(&mpt->m_mutex);
1822                 (void) untimeout(tid);
1823                 mutex_enter(&mpt->m_mutex);
1824         }
1825 
1826         mutex_exit(&mpt->m_mutex);
1827 
1828         /*
1829          * last mpt? ... if active, CANCEL watch threads.
1830          */
1831         mutex_enter(&mptsas_global_mutex);
1832         if (mptsas_head == NULL) {
1833                 timeout_id_t tid;
1834                 /*
1835                  * Clear mptsas_timeouts_enable so that the watch thread
1836                  * gets restarted on DDI_ATTACH
1837                  */
1838                 mptsas_timeouts_enabled = 0;
1839                 if (mptsas_timeout_id) {
1840                         tid = mptsas_timeout_id;
1841                         mptsas_timeout_id = 0;
1842                         mutex_exit(&mptsas_global_mutex);
1843                         (void) untimeout(tid);
1844                         mutex_enter(&mptsas_global_mutex);
1845                 }
1846                 if (mptsas_reset_watch) {
1847                         tid = mptsas_reset_watch;
1848                         mptsas_reset_watch = 0;
1849                         mutex_exit(&mptsas_global_mutex);
1850                         (void) untimeout(tid);
1851                         mutex_enter(&mptsas_global_mutex);
1852                 }
1853         }
1854         mutex_exit(&mptsas_global_mutex);
1855 
1856         /*
1857          * Delete Phy stats
1858          */
1859         mptsas_destroy_phy_stats(mpt);
1860 
1861         /*
1862          * Delete nt_active.
1863          */
1864         mutex_enter(&mpt->m_mutex);
1865         mptsas_hash_uninit(&mpt->m_active->m_tgttbl, sizeof (mptsas_target_t));
1866         mptsas_hash_uninit(&mpt->m_active->m_smptbl, sizeof (mptsas_smp_t));
1867         mptsas_free_active_slots(mpt);
1868         mutex_exit(&mpt->m_mutex);
1869 
1870         /* deallocate everything that was allocated in mptsas_attach */
1871         mptsas_cache_destroy(mpt);
1872 
1873         mptsas_hba_fini(mpt);
1874         mptsas_cfg_fini(mpt);
1875 
1876         /* Lower the power informing PM Framework */
1877         if (mpt->m_options & MPTSAS_OPT_PM) {
1878                 if (pm_lower_power(dip, 0, PM_LEVEL_D3) != DDI_SUCCESS)
1879                         mptsas_log(mpt, CE_WARN,
1880                             "!mptsas%d: Lower power request failed "
1881                             "during detach, ignoring.",
1882                             mpt->m_instance);
1883         }
1884 
1885         mutex_destroy(&mpt->m_intr_mutex);
1886         mutex_destroy(&mpt->m_passthru_mutex);
1887         mutex_destroy(&mpt->m_mutex);
1888         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1889                 mutex_destroy(&mpt->m_phy_info[i].smhba_info.phy_mutex);
1890         }
1891         cv_destroy(&mpt->m_cv);
1892         cv_destroy(&mpt->m_passthru_cv);
1893         cv_destroy(&mpt->m_fw_cv);
1894         cv_destroy(&mpt->m_config_cv);
1895         cv_destroy(&mpt->m_fw_diag_cv);
1896 
1897 
1898         mptsas_smp_teardown(mpt);
1899         mptsas_hba_teardown(mpt);
1900 
1901         mptsas_config_space_fini(mpt);
1902 
1903         mptsas_free_handshake_msg(mpt);
1904 
1905         mptsas_fm_fini(mpt);
1906         ddi_soft_state_free(mptsas_state, ddi_get_instance(dip));
1907         ddi_prop_remove_all(dip);
1908 
1909         return (DDI_SUCCESS);
1910 }
1911 
1912 static void
1913 mptsas_list_add(mptsas_t *mpt)
1914 {
1915         rw_enter(&mptsas_global_rwlock, RW_WRITER);
1916 
1917         if (mptsas_head == NULL) {
1918                 mptsas_head = mpt;
1919         } else {
1920                 mptsas_tail->m_next = mpt;
1921         }
1922         mptsas_tail = mpt;
1923         rw_exit(&mptsas_global_rwlock);
1924 }
1925 
1926 static void
1927 mptsas_list_del(mptsas_t *mpt)
1928 {
1929         mptsas_t *m;
1930         /*
1931          * Remove device instance from the global linked list
1932          */
1933         rw_enter(&mptsas_global_rwlock, RW_WRITER);
1934         if (mptsas_head == mpt) {
1935                 m = mptsas_head = mpt->m_next;
1936         } else {
1937                 for (m = mptsas_head; m != NULL; m = m->m_next) {
1938                         if (m->m_next == mpt) {
1939                                 m->m_next = mpt->m_next;
1940                                 break;
1941                         }
1942                 }
1943                 if (m == NULL) {
1944                         mptsas_log(mpt, CE_PANIC, "Not in softc list!");
1945                 }
1946         }
1947 
1948         if (mptsas_tail == mpt) {
1949                 mptsas_tail = m;
1950         }
1951         rw_exit(&mptsas_global_rwlock);
1952 }
1953 
1954 static int
1955 mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size)
1956 {
1957         ddi_dma_attr_t  task_dma_attrs;
1958 
1959         task_dma_attrs = mpt->m_msg_dma_attr;
1960         task_dma_attrs.dma_attr_sgllen = 1;
1961         task_dma_attrs.dma_attr_granular = (uint32_t)(alloc_size);
1962 
1963         /* allocate Task Management ddi_dma resources */
1964         if (mptsas_dma_addr_create(mpt, task_dma_attrs,
1965             &mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl, &mpt->m_hshk_memp,
1966             alloc_size, NULL) == FALSE) {
1967                 return (DDI_FAILURE);
1968         }
1969         mpt->m_hshk_dma_size = alloc_size;
1970 
1971         return (DDI_SUCCESS);
1972 }
1973 
1974 static void
1975 mptsas_free_handshake_msg(mptsas_t *mpt)
1976 {
1977         mptsas_dma_addr_destroy(&mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl);
1978         mpt->m_hshk_dma_size = 0;
1979 }
1980 
1981 static int
1982 mptsas_hba_setup(mptsas_t *mpt)
1983 {
1984         scsi_hba_tran_t         *hba_tran;
1985         int                     tran_flags;
1986 
1987         /* Allocate a transport structure */
1988         hba_tran = mpt->m_tran = scsi_hba_tran_alloc(mpt->m_dip,
1989             SCSI_HBA_CANSLEEP);
1990         ASSERT(mpt->m_tran != NULL);
1991 
1992         hba_tran->tran_hba_private   = mpt;
1993         hba_tran->tran_tgt_private   = NULL;
1994 
1995         hba_tran->tran_tgt_init              = mptsas_scsi_tgt_init;
1996         hba_tran->tran_tgt_free              = mptsas_scsi_tgt_free;
1997 
1998         hba_tran->tran_start         = mptsas_scsi_start;
1999         hba_tran->tran_reset         = mptsas_scsi_reset;
2000         hba_tran->tran_abort         = mptsas_scsi_abort;
2001         hba_tran->tran_getcap                = mptsas_scsi_getcap;
2002         hba_tran->tran_setcap                = mptsas_scsi_setcap;
2003         hba_tran->tran_init_pkt              = mptsas_scsi_init_pkt;
2004         hba_tran->tran_destroy_pkt   = mptsas_scsi_destroy_pkt;
2005 
2006         hba_tran->tran_dmafree               = mptsas_scsi_dmafree;
2007         hba_tran->tran_sync_pkt              = mptsas_scsi_sync_pkt;
2008         hba_tran->tran_reset_notify  = mptsas_scsi_reset_notify;
2009 
2010         hba_tran->tran_get_bus_addr  = mptsas_get_bus_addr;
2011         hba_tran->tran_get_name              = mptsas_get_name;
2012 
2013         hba_tran->tran_quiesce               = mptsas_scsi_quiesce;
2014         hba_tran->tran_unquiesce     = mptsas_scsi_unquiesce;
2015         hba_tran->tran_bus_reset     = NULL;
2016 
2017         hba_tran->tran_add_eventcall = NULL;
2018         hba_tran->tran_get_eventcookie       = NULL;
2019         hba_tran->tran_post_event    = NULL;
2020         hba_tran->tran_remove_eventcall      = NULL;
2021 
2022         hba_tran->tran_bus_config    = mptsas_bus_config;
2023 
2024         hba_tran->tran_interconnect_type = INTERCONNECT_SAS;
2025 
2026         /*
2027          * All children of the HBA are iports. We need tran was cloned.
2028          * So we pass the flags to SCSA. SCSI_HBA_TRAN_CLONE will be
2029          * inherited to iport's tran vector.
2030          */
2031         tran_flags = (SCSI_HBA_HBA | SCSI_HBA_TRAN_CLONE);
2032 
2033         if (scsi_hba_attach_setup(mpt->m_dip, &mpt->m_msg_dma_attr,
2034             hba_tran, tran_flags) != DDI_SUCCESS) {
2035                 mptsas_log(mpt, CE_WARN, "hba attach setup failed");
2036                 scsi_hba_tran_free(hba_tran);
2037                 mpt->m_tran = NULL;
2038                 return (FALSE);
2039         }
2040         return (TRUE);
2041 }
2042 
2043 static void
2044 mptsas_hba_teardown(mptsas_t *mpt)
2045 {
2046         (void) scsi_hba_detach(mpt->m_dip);
2047         if (mpt->m_tran != NULL) {
2048                 scsi_hba_tran_free(mpt->m_tran);
2049                 mpt->m_tran = NULL;
2050         }
2051 }
2052 
2053 static void
2054 mptsas_iport_register(mptsas_t *mpt)
2055 {
2056         int i, j;
2057         mptsas_phymask_t        mask = 0x0;
2058         /*
2059          * initial value of mask is 0
2060          */
2061         mutex_enter(&mpt->m_mutex);
2062         for (i = 0; i < mpt->m_num_phys; i++) {
2063                 mptsas_phymask_t phy_mask = 0x0;
2064                 char phy_mask_name[MPTSAS_MAX_PHYS];
2065                 uint8_t current_port;
2066 
2067                 if (mpt->m_phy_info[i].attached_devhdl == 0)
2068                         continue;
2069 
2070                 bzero(phy_mask_name, sizeof (phy_mask_name));
2071 
2072                 current_port = mpt->m_phy_info[i].port_num;
2073 
2074                 if ((mask & (1 << i)) != 0)
2075                         continue;
2076 
2077                 for (j = 0; j < mpt->m_num_phys; j++) {
2078                         if (mpt->m_phy_info[j].attached_devhdl &&
2079                             (mpt->m_phy_info[j].port_num == current_port)) {
2080                                 phy_mask |= (1 << j);
2081                         }
2082                 }
2083                 mask = mask | phy_mask;
2084 
2085                 for (j = 0; j < mpt->m_num_phys; j++) {
2086                         if ((phy_mask >> j) & 0x01) {
2087                                 mpt->m_phy_info[j].phy_mask = phy_mask;
2088                         }
2089                 }
2090 
2091                 (void) sprintf(phy_mask_name, "%x", phy_mask);
2092 
2093                 mutex_exit(&mpt->m_mutex);
2094                 /*
2095                  * register a iport
2096                  */
2097                 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
2098                 mutex_enter(&mpt->m_mutex);
2099         }
2100         mutex_exit(&mpt->m_mutex);
2101         /*
2102          * register a virtual port for RAID volume always
2103          */
2104         (void) scsi_hba_iport_register(mpt->m_dip, "v0");
2105 
2106 }
2107 
2108 static int
2109 mptsas_smp_setup(mptsas_t *mpt)
2110 {
2111         mpt->m_smptran = smp_hba_tran_alloc(mpt->m_dip);
2112         ASSERT(mpt->m_smptran != NULL);
2113         mpt->m_smptran->smp_tran_hba_private = mpt;
2114         mpt->m_smptran->smp_tran_start = mptsas_smp_start;
2115         if (smp_hba_attach_setup(mpt->m_dip, mpt->m_smptran) != DDI_SUCCESS) {
2116                 mptsas_log(mpt, CE_WARN, "smp attach setup failed");
2117                 smp_hba_tran_free(mpt->m_smptran);
2118                 mpt->m_smptran = NULL;
2119                 return (FALSE);
2120         }
2121         /*
2122          * Initialize smp hash table
2123          */
2124         mptsas_hash_init(&mpt->m_active->m_smptbl);
2125         mpt->m_smp_devhdl = 0xFFFF;
2126 
2127         return (TRUE);
2128 }
2129 
2130 static void
2131 mptsas_smp_teardown(mptsas_t *mpt)
2132 {
2133         (void) smp_hba_detach(mpt->m_dip);
2134         if (mpt->m_smptran != NULL) {
2135                 smp_hba_tran_free(mpt->m_smptran);
2136                 mpt->m_smptran = NULL;
2137         }
2138         mpt->m_smp_devhdl = 0;
2139 }
2140 
2141 static int
2142 mptsas_cache_create(mptsas_t *mpt)
2143 {
2144         int instance = mpt->m_instance;
2145         char buf[64];
2146 
2147         /*
2148          * create kmem cache for packets
2149          */
2150         (void) sprintf(buf, "mptsas%d_cache", instance);
2151         mpt->m_kmem_cache = kmem_cache_create(buf,
2152             sizeof (struct mptsas_cmd) + scsi_pkt_size(), 8,
2153             mptsas_kmem_cache_constructor, mptsas_kmem_cache_destructor,
2154             NULL, (void *)mpt, NULL, 0);
2155 
2156         if (mpt->m_kmem_cache == NULL) {
2157                 mptsas_log(mpt, CE_WARN, "creating kmem cache failed");
2158                 return (FALSE);
2159         }
2160 
2161         /*
2162          * create kmem cache for extra SGL frames if SGL cannot
2163          * be accomodated into main request frame.
2164          */
2165         (void) sprintf(buf, "mptsas%d_cache_frames", instance);
2166         mpt->m_cache_frames = kmem_cache_create(buf,
2167             sizeof (mptsas_cache_frames_t), 8,
2168             mptsas_cache_frames_constructor, mptsas_cache_frames_destructor,
2169             NULL, (void *)mpt, NULL, 0);
2170 
2171         if (mpt->m_cache_frames == NULL) {
2172                 mptsas_log(mpt, CE_WARN, "creating cache for frames failed");
2173                 return (FALSE);
2174         }
2175 
2176         return (TRUE);
2177 }
2178 
2179 static void
2180 mptsas_cache_destroy(mptsas_t *mpt)
2181 {
2182         /* deallocate in reverse order */
2183         if (mpt->m_cache_frames) {
2184                 kmem_cache_destroy(mpt->m_cache_frames);
2185                 mpt->m_cache_frames = NULL;
2186         }
2187         if (mpt->m_kmem_cache) {
2188                 kmem_cache_destroy(mpt->m_kmem_cache);
2189                 mpt->m_kmem_cache = NULL;
2190         }
2191 }
2192 
2193 static int
2194 mptsas_power(dev_info_t *dip, int component, int level)
2195 {
2196 #ifndef __lock_lint
2197         _NOTE(ARGUNUSED(component))
2198 #endif
2199         mptsas_t        *mpt;
2200         int             rval = DDI_SUCCESS;
2201         int             polls = 0;
2202         uint32_t        ioc_status;
2203 
2204         if (scsi_hba_iport_unit_address(dip) != 0)
2205                 return (DDI_SUCCESS);
2206 
2207         mpt = ddi_get_soft_state(mptsas_state, ddi_get_instance(dip));
2208         if (mpt == NULL) {
2209                 return (DDI_FAILURE);
2210         }
2211 
2212         mutex_enter(&mpt->m_mutex);
2213 
2214         /*
2215          * If the device is busy, don't lower its power level
2216          */
2217         if (mpt->m_busy && (mpt->m_power_level > level)) {
2218                 mutex_exit(&mpt->m_mutex);
2219                 return (DDI_FAILURE);
2220         }
2221         switch (level) {
2222         case PM_LEVEL_D0:
2223                 NDBG11(("mptsas%d: turning power ON.", mpt->m_instance));
2224                 MPTSAS_POWER_ON(mpt);
2225                 /*
2226                  * Wait up to 30 seconds for IOC to come out of reset.
2227                  */
2228                 while (((ioc_status = ddi_get32(mpt->m_datap,
2229                     &mpt->m_reg->Doorbell)) &
2230                     MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_RESET) {
2231                         if (polls++ > 3000) {
2232                                 break;
2233                         }
2234                         delay(drv_usectohz(10000));
2235                 }
2236                 /*
2237                  * If IOC is not in operational state, try to hard reset it.
2238                  */
2239                 if ((ioc_status & MPI2_IOC_STATE_MASK) !=
2240                     MPI2_IOC_STATE_OPERATIONAL) {
2241                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
2242                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
2243                                 mptsas_log(mpt, CE_WARN,
2244                                     "mptsas_power: hard reset failed");
2245                                 mutex_exit(&mpt->m_mutex);
2246                                 return (DDI_FAILURE);
2247                         }
2248                 }
2249                 mutex_enter(&mpt->m_intr_mutex);
2250                 mpt->m_power_level = PM_LEVEL_D0;
2251                 mutex_exit(&mpt->m_intr_mutex);
2252                 break;
2253         case PM_LEVEL_D3:
2254                 NDBG11(("mptsas%d: turning power OFF.", mpt->m_instance));
2255                 MPTSAS_POWER_OFF(mpt);
2256                 break;
2257         default:
2258                 mptsas_log(mpt, CE_WARN, "mptsas%d: unknown power level <%x>.",
2259                     mpt->m_instance, level);
2260                 rval = DDI_FAILURE;
2261                 break;
2262         }
2263         mutex_exit(&mpt->m_mutex);
2264         return (rval);
2265 }
2266 
2267 /*
2268  * Initialize configuration space and figure out which
2269  * chip and revison of the chip the mpt driver is using.
2270  */
2271 static int
2272 mptsas_config_space_init(mptsas_t *mpt)
2273 {
2274         NDBG0(("mptsas_config_space_init"));
2275 
2276         if (mpt->m_config_handle != NULL)
2277                 return (TRUE);
2278 
2279         if (pci_config_setup(mpt->m_dip,
2280             &mpt->m_config_handle) != DDI_SUCCESS) {
2281                 mptsas_log(mpt, CE_WARN, "cannot map configuration space.");
2282                 return (FALSE);
2283         }
2284 
2285         /*
2286          * This is a workaround for a XMITS ASIC bug which does not
2287          * drive the CBE upper bits.
2288          */
2289         if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT) &
2290             PCI_STAT_PERROR) {
2291                 pci_config_put16(mpt->m_config_handle, PCI_CONF_STAT,
2292                     PCI_STAT_PERROR);
2293         }
2294 
2295         mptsas_setup_cmd_reg(mpt);
2296 
2297         /*
2298          * Get the chip device id:
2299          */
2300         mpt->m_devid = pci_config_get16(mpt->m_config_handle, PCI_CONF_DEVID);
2301 
2302         /*
2303          * Save the revision.
2304          */
2305         mpt->m_revid = pci_config_get8(mpt->m_config_handle, PCI_CONF_REVID);
2306 
2307         /*
2308          * Save the SubSystem Vendor and Device IDs
2309          */
2310         mpt->m_svid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBVENID);
2311         mpt->m_ssid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBSYSID);
2312 
2313         /*
2314          * Set the latency timer to 0x40 as specified by the upa -> pci
2315          * bridge chip design team.  This may be done by the sparc pci
2316          * bus nexus driver, but the driver should make sure the latency
2317          * timer is correct for performance reasons.
2318          */
2319         pci_config_put8(mpt->m_config_handle, PCI_CONF_LATENCY_TIMER,
2320             MPTSAS_LATENCY_TIMER);
2321 
2322         (void) mptsas_get_pci_cap(mpt);
2323         return (TRUE);
2324 }
2325 
2326 static void
2327 mptsas_config_space_fini(mptsas_t *mpt)
2328 {
2329         if (mpt->m_config_handle != NULL) {
2330                 mptsas_disable_bus_master(mpt);
2331                 pci_config_teardown(&mpt->m_config_handle);
2332                 mpt->m_config_handle = NULL;
2333         }
2334 }
2335 
2336 static void
2337 mptsas_setup_cmd_reg(mptsas_t *mpt)
2338 {
2339         ushort_t        cmdreg;
2340 
2341         /*
2342          * Set the command register to the needed values.
2343          */
2344         cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2345         cmdreg |= (PCI_COMM_ME | PCI_COMM_SERR_ENABLE |
2346             PCI_COMM_PARITY_DETECT | PCI_COMM_MAE);
2347         cmdreg &= ~PCI_COMM_IO;
2348         pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2349 }
2350 
2351 static void
2352 mptsas_disable_bus_master(mptsas_t *mpt)
2353 {
2354         ushort_t        cmdreg;
2355 
2356         /*
2357          * Clear the master enable bit in the PCI command register.
2358          * This prevents any bus mastering activity like DMA.
2359          */
2360         cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2361         cmdreg &= ~PCI_COMM_ME;
2362         pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2363 }
2364 
2365 int
2366 mptsas_dma_alloc(mptsas_t *mpt, mptsas_dma_alloc_state_t *dma_statep)
2367 {
2368         ddi_dma_attr_t  attrs;
2369 
2370         attrs = mpt->m_io_dma_attr;
2371         attrs.dma_attr_sgllen = 1;
2372 
2373         ASSERT(dma_statep != NULL);
2374 
2375         if (mptsas_dma_addr_create(mpt, attrs, &dma_statep->handle,
2376             &dma_statep->accessp, &dma_statep->memp, dma_statep->size,
2377             &dma_statep->cookie) == FALSE) {
2378                 return (DDI_FAILURE);
2379         }
2380 
2381         return (DDI_SUCCESS);
2382 }
2383 
2384 void
2385 mptsas_dma_free(mptsas_dma_alloc_state_t *dma_statep)
2386 {
2387         ASSERT(dma_statep != NULL);
2388         mptsas_dma_addr_destroy(&dma_statep->handle, &dma_statep->accessp);
2389         dma_statep->size = 0;
2390 }
2391 
2392 int
2393 mptsas_do_dma(mptsas_t *mpt, uint32_t size, int var, int (*callback)())
2394 {
2395         ddi_dma_attr_t          attrs;
2396         ddi_dma_handle_t        dma_handle;
2397         caddr_t                 memp;
2398         ddi_acc_handle_t        accessp;
2399         int                     rval;
2400 
2401         ASSERT(mutex_owned(&mpt->m_mutex));
2402 
2403         attrs = mpt->m_msg_dma_attr;
2404         attrs.dma_attr_sgllen = 1;
2405         attrs.dma_attr_granular = size;
2406 
2407         if (mptsas_dma_addr_create(mpt, attrs, &dma_handle,
2408             &accessp, &memp, size, NULL) == FALSE) {
2409                 return (DDI_FAILURE);
2410         }
2411 
2412         rval = (*callback) (mpt, memp, var, accessp);
2413 
2414         if ((mptsas_check_dma_handle(dma_handle) != DDI_SUCCESS) ||
2415             (mptsas_check_acc_handle(accessp) != DDI_SUCCESS)) {
2416                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2417                 rval = DDI_FAILURE;
2418         }
2419 
2420         mptsas_dma_addr_destroy(&dma_handle, &accessp);
2421         return (rval);
2422 
2423 }
2424 
2425 static int
2426 mptsas_alloc_request_frames(mptsas_t *mpt)
2427 {
2428         ddi_dma_attr_t          frame_dma_attrs;
2429         caddr_t                 memp;
2430         ddi_dma_cookie_t        cookie;
2431         size_t                  mem_size;
2432 
2433         /*
2434          * re-alloc when it has already alloced
2435          */
2436         mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2437             &mpt->m_acc_req_frame_hdl);
2438 
2439         /*
2440          * The size of the request frame pool is:
2441          *   Number of Request Frames * Request Frame Size
2442          */
2443         mem_size = mpt->m_max_requests * mpt->m_req_frame_size;
2444 
2445         /*
2446          * set the DMA attributes.  System Request Message Frames must be
2447          * aligned on a 16-byte boundry.
2448          */
2449         frame_dma_attrs = mpt->m_msg_dma_attr;
2450         frame_dma_attrs.dma_attr_align = 16;
2451         frame_dma_attrs.dma_attr_sgllen = 1;
2452 
2453         /*
2454          * allocate the request frame pool.
2455          */
2456         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2457             &mpt->m_dma_req_frame_hdl, &mpt->m_acc_req_frame_hdl, &memp,
2458             mem_size, &cookie) == FALSE) {
2459                 return (DDI_FAILURE);
2460         }
2461 
2462         /*
2463          * Store the request frame memory address.  This chip uses this
2464          * address to dma to and from the driver's frame.  The second
2465          * address is the address mpt uses to fill in the frame.
2466          */
2467         mpt->m_req_frame_dma_addr = cookie.dmac_laddress;
2468         mpt->m_req_frame = memp;
2469 
2470         /*
2471          * Clear the request frame pool.
2472          */
2473         bzero(mpt->m_req_frame, mem_size);
2474 
2475         return (DDI_SUCCESS);
2476 }
2477 
2478 static int
2479 mptsas_alloc_reply_frames(mptsas_t *mpt)
2480 {
2481         ddi_dma_attr_t          frame_dma_attrs;
2482         caddr_t                 memp;
2483         ddi_dma_cookie_t        cookie;
2484         size_t                  mem_size;
2485 
2486         /*
2487          * re-alloc when it has already alloced
2488          */
2489         mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2490             &mpt->m_acc_reply_frame_hdl);
2491 
2492         /*
2493          * The size of the reply frame pool is:
2494          *   Number of Reply Frames * Reply Frame Size
2495          */
2496         mem_size = mpt->m_max_replies * mpt->m_reply_frame_size;
2497 
2498         /*
2499          * set the DMA attributes.   System Reply Message Frames must be
2500          * aligned on a 4-byte boundry.  This is the default.
2501          */
2502         frame_dma_attrs = mpt->m_msg_dma_attr;
2503         frame_dma_attrs.dma_attr_sgllen = 1;
2504 
2505         /*
2506          * allocate the reply frame pool
2507          */
2508         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2509             &mpt->m_dma_reply_frame_hdl, &mpt->m_acc_reply_frame_hdl, &memp,
2510             mem_size, &cookie) == FALSE) {
2511                 return (DDI_FAILURE);
2512         }
2513 
2514         /*
2515          * Store the reply frame memory address.  This chip uses this
2516          * address to dma to and from the driver's frame.  The second
2517          * address is the address mpt uses to process the frame.
2518          */
2519         mpt->m_reply_frame_dma_addr = cookie.dmac_laddress;
2520         mpt->m_reply_frame = memp;
2521 
2522         /*
2523          * Clear the reply frame pool.
2524          */
2525         bzero(mpt->m_reply_frame, mem_size);
2526 
2527         return (DDI_SUCCESS);
2528 }
2529 
2530 static int
2531 mptsas_alloc_free_queue(mptsas_t *mpt)
2532 {
2533         ddi_dma_attr_t          frame_dma_attrs;
2534         caddr_t                 memp;
2535         ddi_dma_cookie_t        cookie;
2536         size_t                  mem_size;
2537 
2538         /*
2539          * re-alloc when it has already alloced
2540          */
2541         mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2542             &mpt->m_acc_free_queue_hdl);
2543 
2544         /*
2545          * The reply free queue size is:
2546          *   Reply Free Queue Depth * 4
2547          * The "4" is the size of one 32 bit address (low part of 64-bit
2548          *   address)
2549          */
2550         mem_size = mpt->m_free_queue_depth * 4;
2551 
2552         /*
2553          * set the DMA attributes  The Reply Free Queue must be aligned on a
2554          * 16-byte boundry.
2555          */
2556         frame_dma_attrs = mpt->m_msg_dma_attr;
2557         frame_dma_attrs.dma_attr_align = 16;
2558         frame_dma_attrs.dma_attr_sgllen = 1;
2559 
2560         /*
2561          * allocate the reply free queue
2562          */
2563         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2564             &mpt->m_dma_free_queue_hdl, &mpt->m_acc_free_queue_hdl, &memp,
2565             mem_size, &cookie) == FALSE) {
2566                 return (DDI_FAILURE);
2567         }
2568 
2569         /*
2570          * Store the reply free queue memory address.  This chip uses this
2571          * address to read from the reply free queue.  The second address
2572          * is the address mpt uses to manage the queue.
2573          */
2574         mpt->m_free_queue_dma_addr = cookie.dmac_laddress;
2575         mpt->m_free_queue = memp;
2576 
2577         /*
2578          * Clear the reply free queue memory.
2579          */
2580         bzero(mpt->m_free_queue, mem_size);
2581 
2582         return (DDI_SUCCESS);
2583 }
2584 
2585 static int
2586 mptsas_alloc_post_queue(mptsas_t *mpt)
2587 {
2588         ddi_dma_attr_t          frame_dma_attrs;
2589         caddr_t                 memp;
2590         ddi_dma_cookie_t        cookie;
2591         size_t                  mem_size;
2592 
2593         /*
2594          * re-alloc when it has already alloced
2595          */
2596         mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2597             &mpt->m_acc_post_queue_hdl);
2598 
2599         /*
2600          * The reply descriptor post queue size is:
2601          *   Reply Descriptor Post Queue Depth * 8
2602          * The "8" is the size of each descriptor (8 bytes or 64 bits).
2603          */
2604         mem_size = mpt->m_post_queue_depth * 8;
2605 
2606         /*
2607          * set the DMA attributes.  The Reply Descriptor Post Queue must be
2608          * aligned on a 16-byte boundry.
2609          */
2610         frame_dma_attrs = mpt->m_msg_dma_attr;
2611         frame_dma_attrs.dma_attr_align = 16;
2612         frame_dma_attrs.dma_attr_sgllen = 1;
2613 
2614         /*
2615          * allocate the reply post queue
2616          */
2617         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2618             &mpt->m_dma_post_queue_hdl, &mpt->m_acc_post_queue_hdl, &memp,
2619             mem_size, &cookie) == FALSE) {
2620                 return (DDI_FAILURE);
2621         }
2622 
2623         /*
2624          * Store the reply descriptor post queue memory address.  This chip
2625          * uses this address to write to the reply descriptor post queue.  The
2626          * second address is the address mpt uses to manage the queue.
2627          */
2628         mpt->m_post_queue_dma_addr = cookie.dmac_laddress;
2629         mpt->m_post_queue = memp;
2630 
2631         /*
2632          * Clear the reply post queue memory.
2633          */
2634         bzero(mpt->m_post_queue, mem_size);
2635 
2636         return (DDI_SUCCESS);
2637 }
2638 
2639 static void
2640 mptsas_alloc_reply_args(mptsas_t *mpt)
2641 {
2642         if (mpt->m_replyh_args != NULL) {
2643                 kmem_free(mpt->m_replyh_args, sizeof (m_replyh_arg_t)
2644                     * mpt->m_max_replies);
2645                 mpt->m_replyh_args = NULL;
2646         }
2647         mpt->m_replyh_args = kmem_zalloc(sizeof (m_replyh_arg_t) *
2648             mpt->m_max_replies, KM_SLEEP);
2649 }
2650 
2651 static int
2652 mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2653 {
2654         mptsas_cache_frames_t   *frames = NULL;
2655         if (cmd->cmd_extra_frames == NULL) {
2656                 frames = kmem_cache_alloc(mpt->m_cache_frames, KM_NOSLEEP);
2657                 if (frames == NULL) {
2658                         return (DDI_FAILURE);
2659                 }
2660                 cmd->cmd_extra_frames = frames;
2661         }
2662         return (DDI_SUCCESS);
2663 }
2664 
2665 static void
2666 mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2667 {
2668         if (cmd->cmd_extra_frames) {
2669                 kmem_cache_free(mpt->m_cache_frames,
2670                     (void *)cmd->cmd_extra_frames);
2671                 cmd->cmd_extra_frames = NULL;
2672         }
2673 }
2674 
2675 static void
2676 mptsas_cfg_fini(mptsas_t *mpt)
2677 {
2678         NDBG0(("mptsas_cfg_fini"));
2679         ddi_regs_map_free(&mpt->m_datap);
2680 }
2681 
2682 static void
2683 mptsas_hba_fini(mptsas_t *mpt)
2684 {
2685         NDBG0(("mptsas_hba_fini"));
2686 
2687         /*
2688          * Free up any allocated memory
2689          */
2690         mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2691             &mpt->m_acc_req_frame_hdl);
2692 
2693         mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2694             &mpt->m_acc_reply_frame_hdl);
2695 
2696         mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2697             &mpt->m_acc_free_queue_hdl);
2698 
2699         mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2700             &mpt->m_acc_post_queue_hdl);
2701 
2702         if (mpt->m_replyh_args != NULL) {
2703                 kmem_free(mpt->m_replyh_args, sizeof (m_replyh_arg_t)
2704                     * mpt->m_max_replies);
2705         }
2706 }
2707 
2708 static int
2709 mptsas_name_child(dev_info_t *lun_dip, char *name, int len)
2710 {
2711         int             lun = 0;
2712         char            *sas_wwn = NULL;
2713         int             phynum = -1;
2714         int             reallen = 0;
2715 
2716         /* Get the target num */
2717         lun = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip, DDI_PROP_DONTPASS,
2718             LUN_PROP, 0);
2719 
2720         if ((phynum = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip,
2721             DDI_PROP_DONTPASS, "sata-phy", -1)) != -1) {
2722                 /*
2723                  * Stick in the address of form "pPHY,LUN"
2724                  */
2725                 reallen = snprintf(name, len, "p%x,%x", phynum, lun);
2726         } else if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lun_dip,
2727             DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &sas_wwn)
2728             == DDI_PROP_SUCCESS) {
2729                 /*
2730                  * Stick in the address of the form "wWWN,LUN"
2731                  */
2732                 reallen = snprintf(name, len, "%s,%x", sas_wwn, lun);
2733                 ddi_prop_free(sas_wwn);
2734         } else {
2735                 return (DDI_FAILURE);
2736         }
2737 
2738         ASSERT(reallen < len);
2739         if (reallen >= len) {
2740                 mptsas_log(0, CE_WARN, "!mptsas_get_name: name parameter "
2741                     "length too small, it needs to be %d bytes", reallen + 1);
2742         }
2743         return (DDI_SUCCESS);
2744 }
2745 
2746 /*
2747  * tran_tgt_init(9E) - target device instance initialization
2748  */
2749 static int
2750 mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
2751     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
2752 {
2753 #ifndef __lock_lint
2754         _NOTE(ARGUNUSED(hba_tran))
2755 #endif
2756 
2757         /*
2758          * At this point, the scsi_device structure already exists
2759          * and has been initialized.
2760          *
2761          * Use this function to allocate target-private data structures,
2762          * if needed by this HBA.  Add revised flow-control and queue
2763          * properties for child here, if desired and if you can tell they
2764          * support tagged queueing by now.
2765          */
2766         mptsas_t                *mpt;
2767         int                     lun = sd->sd_address.a_lun;
2768         mdi_pathinfo_t          *pip = NULL;
2769         mptsas_tgt_private_t    *tgt_private = NULL;
2770         mptsas_target_t         *ptgt = NULL;
2771         char                    *psas_wwn = NULL;
2772         int                     phymask = 0;
2773         uint64_t                sas_wwn = 0;
2774         mpt = SDEV2MPT(sd);
2775 
2776         ASSERT(scsi_hba_iport_unit_address(hba_dip) != 0);
2777 
2778         NDBG0(("mptsas_scsi_tgt_init: hbadip=0x%p tgtdip=0x%p lun=%d",
2779             (void *)hba_dip, (void *)tgt_dip, lun));
2780 
2781         if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
2782                 (void) ndi_merge_node(tgt_dip, mptsas_name_child);
2783                 ddi_set_name_addr(tgt_dip, NULL);
2784                 return (DDI_FAILURE);
2785         }
2786         /*
2787          * phymask is 0 means the virtual port for RAID
2788          */
2789         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, hba_dip, 0,
2790             "phymask", 0);
2791         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2792                 if ((pip = (void *)(sd->sd_private)) == NULL) {
2793                         /*
2794                          * Very bad news if this occurs. Somehow scsi_vhci has
2795                          * lost the pathinfo node for this target.
2796                          */
2797                         return (DDI_NOT_WELL_FORMED);
2798                 }
2799 
2800                 if (mdi_prop_lookup_int(pip, LUN_PROP, &lun) !=
2801                     DDI_PROP_SUCCESS) {
2802                         mptsas_log(mpt, CE_WARN, "Get lun property failed\n");
2803                         return (DDI_FAILURE);
2804                 }
2805 
2806                 if (mdi_prop_lookup_string(pip, SCSI_ADDR_PROP_TARGET_PORT,
2807                     &psas_wwn) == MDI_SUCCESS) {
2808                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2809                                 sas_wwn = 0;
2810                         }
2811                         (void) mdi_prop_free(psas_wwn);
2812                 }
2813         } else {
2814                 lun = ddi_prop_get_int(DDI_DEV_T_ANY, tgt_dip,
2815                     DDI_PROP_DONTPASS, LUN_PROP, 0);
2816                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip,
2817                     DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &psas_wwn) ==
2818                     DDI_PROP_SUCCESS) {
2819                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2820                                 sas_wwn = 0;
2821                         }
2822                         ddi_prop_free(psas_wwn);
2823                 } else {
2824                         sas_wwn = 0;
2825                 }
2826         }
2827         ASSERT((sas_wwn != 0) || (phymask != 0));
2828         mutex_enter(&mpt->m_mutex);
2829         ptgt = mptsas_hash_search(&mpt->m_active->m_tgttbl, sas_wwn, phymask);
2830         mutex_exit(&mpt->m_mutex);
2831         if (ptgt == NULL) {
2832                 mptsas_log(mpt, CE_WARN, "!tgt_init: target doesn't exist or "
2833                     "gone already! phymask:%x, saswwn %"PRIx64, phymask,
2834                     sas_wwn);
2835                 return (DDI_FAILURE);
2836         }
2837         if (hba_tran->tran_tgt_private == NULL) {
2838                 tgt_private = kmem_zalloc(sizeof (mptsas_tgt_private_t),
2839                     KM_SLEEP);
2840                 tgt_private->t_lun = lun;
2841                 tgt_private->t_private = ptgt;
2842                 hba_tran->tran_tgt_private = tgt_private;
2843         }
2844 
2845         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2846                 return (DDI_SUCCESS);
2847         }
2848         mutex_enter(&mpt->m_mutex);
2849 
2850         if (ptgt->m_deviceinfo &
2851             (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
2852             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
2853                 uchar_t *inq89 = NULL;
2854                 int inq89_len = 0x238;
2855                 int reallen = 0;
2856                 int rval = 0;
2857                 struct sata_id *sid = NULL;
2858                 char model[SATA_ID_MODEL_LEN + 1];
2859                 char fw[SATA_ID_FW_LEN + 1];
2860                 char *vid, *pid;
2861                 int i;
2862 
2863                 mutex_exit(&mpt->m_mutex);
2864                 /*
2865                  * According SCSI/ATA Translation -2 (SAT-2) revision 01a
2866                  * chapter 12.4.2 VPD page 89h includes 512 bytes ATA IDENTIFY
2867                  * DEVICE data or ATA IDENTIFY PACKET DEVICE data.
2868                  */
2869                 inq89 = kmem_zalloc(inq89_len, KM_SLEEP);
2870                 rval = mptsas_inquiry(mpt, ptgt, 0, 0x89,
2871                     inq89, inq89_len, &reallen, 1);
2872 
2873                 if (rval != 0) {
2874                         if (inq89 != NULL) {
2875                                 kmem_free(inq89, inq89_len);
2876                         }
2877 
2878                         mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
2879                             "0x89 for SATA target:%x failed!", ptgt->m_devhdl);
2880                         return (DDI_SUCCESS);
2881                 }
2882                 sid = (void *)(&inq89[60]);
2883 
2884                 swab(sid->ai_model, model, SATA_ID_MODEL_LEN);
2885                 swab(sid->ai_fw, fw, SATA_ID_FW_LEN);
2886 
2887                 model[SATA_ID_MODEL_LEN] = 0;
2888                 fw[SATA_ID_FW_LEN] = 0;
2889 
2890                 /*
2891                  * split model into into vid/pid
2892                  */
2893                 for (i = 0, pid = model; i < SATA_ID_MODEL_LEN; i++, pid++)
2894                         if ((*pid == ' ') || (*pid == '\t'))
2895                                 break;
2896                 if (i < SATA_ID_MODEL_LEN) {
2897                         vid = model;
2898                         /*
2899                          * terminate vid, establish pid
2900                          */
2901                         *pid++ = 0;
2902                 } else {
2903                         /*
2904                          * vid will stay "ATA     ", the rule is same
2905                          * as sata framework implementation.
2906                          */
2907                         vid = NULL;
2908                         /*
2909                          * model is all pid
2910                          */
2911                         pid = model;
2912                 }
2913 
2914                 /*
2915                  * override SCSA "inquiry-*" properties
2916                  */
2917                 if (vid)
2918                         (void) scsi_device_prop_update_inqstring(sd,
2919                             INQUIRY_VENDOR_ID, vid, strlen(vid));
2920                 if (pid)
2921                         (void) scsi_device_prop_update_inqstring(sd,
2922                             INQUIRY_PRODUCT_ID, pid, strlen(pid));
2923                 (void) scsi_device_prop_update_inqstring(sd,
2924                     INQUIRY_REVISION_ID, fw, strlen(fw));
2925 
2926                 if (inq89 != NULL) {
2927                         kmem_free(inq89, inq89_len);
2928                 }
2929         } else {
2930                 mutex_exit(&mpt->m_mutex);
2931         }
2932 
2933         return (DDI_SUCCESS);
2934 }
2935 /*
2936  * tran_tgt_free(9E) - target device instance deallocation
2937  */
2938 static void
2939 mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
2940     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
2941 {
2942 #ifndef __lock_lint
2943         _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran, sd))
2944 #endif
2945 
2946         mptsas_tgt_private_t    *tgt_private = hba_tran->tran_tgt_private;
2947 
2948         if (tgt_private != NULL) {
2949                 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
2950                 hba_tran->tran_tgt_private = NULL;
2951         }
2952 }
2953 
2954 /*
2955  * scsi_pkt handling
2956  *
2957  * Visible to the external world via the transport structure.
2958  */
2959 
2960 /*
2961  * Notes:
2962  *      - transport the command to the addressed SCSI target/lun device
2963  *      - normal operation is to schedule the command to be transported,
2964  *        and return TRAN_ACCEPT if this is successful.
2965  *      - if NO_INTR, tran_start must poll device for command completion
2966  */
2967 static int
2968 mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
2969 {
2970 #ifndef __lock_lint
2971         _NOTE(ARGUNUSED(ap))
2972 #endif
2973         mptsas_t        *mpt = PKT2MPT(pkt);
2974         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
2975         int             rval;
2976         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
2977 
2978         NDBG1(("mptsas_scsi_start: pkt=0x%p", (void *)pkt));
2979         ASSERT(ptgt);
2980         if (ptgt == NULL)
2981                 return (TRAN_FATAL_ERROR);
2982 
2983         /*
2984          * prepare the pkt before taking mutex.
2985          */
2986         rval = mptsas_prepare_pkt(cmd);
2987         if (rval != TRAN_ACCEPT) {
2988                 return (rval);
2989         }
2990 
2991         /*
2992          * Send the command to target/lun, however your HBA requires it.
2993          * If busy, return TRAN_BUSY; if there's some other formatting error
2994          * in the packet, return TRAN_BADPKT; otherwise, fall through to the
2995          * return of TRAN_ACCEPT.
2996          *
2997          * Remember that access to shared resources, including the mptsas_t
2998          * data structure and the HBA hardware registers, must be protected
2999          * with mutexes, here and everywhere.
3000          *
3001          * Also remember that at interrupt time, you'll get an argument
3002          * to the interrupt handler which is a pointer to your mptsas_t
3003          * structure; you'll have to remember which commands are outstanding
3004          * and which scsi_pkt is the currently-running command so the
3005          * interrupt handler can refer to the pkt to set completion
3006          * status, call the target driver back through pkt_comp, etc.
3007          */
3008 
3009         mutex_enter(&ptgt->m_tgt_intr_mutex);
3010         if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3011                 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3012                         /*
3013                          * commands should be allowed to retry by
3014                          * returning TRAN_BUSY to stall the I/O's
3015                          * which come from scsi_vhci since the device/
3016                          * path is in unstable state now.
3017                          */
3018                         mutex_exit(&ptgt->m_tgt_intr_mutex);
3019                         return (TRAN_BUSY);
3020                 } else {
3021                         /*
3022                          * The device is offline, just fail the
3023                          * command by returning TRAN_FATAL_ERROR.
3024                          */
3025                         mutex_exit(&ptgt->m_tgt_intr_mutex);
3026                         return (TRAN_FATAL_ERROR);
3027                 }
3028         }
3029         mutex_exit(&ptgt->m_tgt_intr_mutex);
3030         rval = mptsas_accept_pkt(mpt, cmd);
3031 
3032         return (rval);
3033 }
3034 
3035 static int
3036 mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3037 {
3038         int             rval = TRAN_ACCEPT;
3039         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3040 
3041         NDBG1(("mptsas_accept_pkt: cmd=0x%p", (void *)cmd));
3042 
3043         if ((cmd->cmd_flags & CFLAG_PREPARED) == 0) {
3044                 rval = mptsas_prepare_pkt(cmd);
3045                 if (rval != TRAN_ACCEPT) {
3046                         cmd->cmd_flags &= ~CFLAG_TRANFLAG;
3047                         return (rval);
3048                 }
3049         }
3050 
3051         /*
3052          * reset the throttle if we were draining
3053          */
3054         mutex_enter(&ptgt->m_tgt_intr_mutex);
3055         if ((ptgt->m_t_ncmds == 0) &&
3056             (ptgt->m_t_throttle == DRAIN_THROTTLE)) {
3057                 NDBG23(("reset throttle"));
3058                 ASSERT(ptgt->m_reset_delay == 0);
3059                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
3060         }
3061 
3062         /*
3063          * If device handle has already been invalidated, just
3064          * fail the command. In theory, command from scsi_vhci
3065          * client is impossible send down command with invalid
3066          * devhdl since devhdl is set after path offline, target
3067          * driver is not suppose to select a offlined path.
3068          */
3069         if (ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) {
3070                 NDBG20(("rejecting command, it might because invalid devhdl "
3071                     "request."));
3072                 mutex_exit(&ptgt->m_tgt_intr_mutex);
3073                 mutex_enter(&mpt->m_mutex);
3074                 /*
3075                  * If HBA is being reset, the DevHandles are being
3076                  * re-initialized, which means that they could be invalid
3077                  * even if the target is still attached. Check if being reset
3078                  * and if DevHandle is being re-initialized. If this is the
3079                  * case, return BUSY so the I/O can be retried later.
3080                  */
3081                 if (mpt->m_in_reset) {
3082                         mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
3083                             STAT_BUS_RESET);
3084                         if (cmd->cmd_flags & CFLAG_TXQ) {
3085                                 mptsas_doneq_add(mpt, cmd);
3086                                 mptsas_doneq_empty(mpt);
3087                                 mutex_exit(&mpt->m_mutex);
3088                                 return (rval);
3089                         } else {
3090                                 mutex_exit(&mpt->m_mutex);
3091                                 return (TRAN_BUSY);
3092                         }
3093                 }
3094                 mptsas_set_pkt_reason(mpt, cmd, CMD_DEV_GONE, STAT_TERMINATED);
3095                 if (cmd->cmd_flags & CFLAG_TXQ) {
3096                         mptsas_doneq_add(mpt, cmd);
3097                         mptsas_doneq_empty(mpt);
3098                         mutex_exit(&mpt->m_mutex);
3099                         return (rval);
3100                 } else {
3101                         mutex_exit(&mpt->m_mutex);
3102                         return (TRAN_FATAL_ERROR);
3103                 }
3104         }
3105         mutex_exit(&ptgt->m_tgt_intr_mutex);
3106         /*
3107          * The first case is the normal case.  mpt gets a command from the
3108          * target driver and starts it.
3109          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
3110          * commands is m_max_requests - 2.
3111          */
3112         mutex_enter(&ptgt->m_tgt_intr_mutex);
3113         if ((ptgt->m_t_throttle > HOLD_THROTTLE) &&
3114             (ptgt->m_t_ncmds < ptgt->m_t_throttle) &&
3115             (ptgt->m_reset_delay == 0) &&
3116             (ptgt->m_t_nwait == 0) &&
3117             ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0)) {
3118                 mutex_exit(&ptgt->m_tgt_intr_mutex);
3119                 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
3120                         (void) mptsas_start_cmd0(mpt, cmd);
3121                 } else {
3122                         mutex_enter(&mpt->m_mutex);
3123                         mptsas_waitq_add(mpt, cmd);
3124                         mutex_exit(&mpt->m_mutex);
3125                 }
3126         } else {
3127                 /*
3128                  * Add this pkt to the work queue
3129                  */
3130                 mutex_exit(&ptgt->m_tgt_intr_mutex);
3131                 mutex_enter(&mpt->m_mutex);
3132                 mptsas_waitq_add(mpt, cmd);
3133 
3134                 if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3135                         (void) mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
3136 
3137                         /*
3138                          * Only flush the doneq if this is not a TM
3139                          * cmd.  For TM cmds the flushing of the
3140                          * doneq will be done in those routines.
3141                          */
3142                         if ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
3143                                 mptsas_doneq_empty(mpt);
3144                         }
3145                 }
3146                 mutex_exit(&mpt->m_mutex);
3147         }
3148         return (rval);
3149 }
3150 
3151 int
3152 mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
3153 {
3154         mptsas_slots_t  *slots;
3155         int             slot;
3156         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3157         mptsas_slot_free_e_t    *pe;
3158         int             qn, qn_first;
3159 
3160         slots = mpt->m_active;
3161 
3162         /*
3163          * Account for reserved TM request slot and reserved SMID of 0.
3164          */
3165         ASSERT(slots->m_n_slots == (mpt->m_max_requests - 2));
3166 
3167         qn = qn_first = CPU->cpu_seqid & (mpt->m_slot_freeq_pair_n - 1);
3168 
3169 qpair_retry:
3170         ASSERT(qn < mpt->m_slot_freeq_pair_n);
3171         mutex_enter(&mpt->m_slot_freeq_pairp[qn].m_slot_allocq.s.m_fq_mutex);
3172         pe = list_head(&mpt->m_slot_freeq_pairp[qn].m_slot_allocq.
3173             s.m_fq_list);
3174         if (!pe) { /* switch the allocq and releq */
3175                 mutex_enter(&mpt->m_slot_freeq_pairp[qn].m_slot_releq.
3176                     s.m_fq_mutex);
3177                 if (mpt->m_slot_freeq_pairp[qn].m_slot_releq.s.m_fq_n) {
3178                         mpt->m_slot_freeq_pairp[qn].
3179                             m_slot_allocq.s.m_fq_n =
3180                             mpt->m_slot_freeq_pairp[qn].
3181                             m_slot_releq.s.m_fq_n;
3182                         mpt->m_slot_freeq_pairp[qn].
3183                             m_slot_allocq.s.m_fq_list.list_head.list_next =
3184                             mpt->m_slot_freeq_pairp[qn].
3185                             m_slot_releq.s.m_fq_list.list_head.list_next;
3186                         mpt->m_slot_freeq_pairp[qn].
3187                             m_slot_allocq.s.m_fq_list.list_head.list_prev =
3188                             mpt->m_slot_freeq_pairp[qn].
3189                             m_slot_releq.s.m_fq_list.list_head.list_prev;
3190                         mpt->m_slot_freeq_pairp[qn].
3191                             m_slot_releq.s.m_fq_list.list_head.list_prev->
3192                             list_next =
3193                             &mpt->m_slot_freeq_pairp[qn].
3194                             m_slot_allocq.s.m_fq_list.list_head;
3195                         mpt->m_slot_freeq_pairp[qn].
3196                             m_slot_releq.s.m_fq_list.list_head.list_next->
3197                             list_prev =
3198                             &mpt->m_slot_freeq_pairp[qn].
3199                             m_slot_allocq.s.m_fq_list.list_head;
3200 
3201                         mpt->m_slot_freeq_pairp[qn].
3202                             m_slot_releq.s.m_fq_list.list_head.list_next =
3203                             mpt->m_slot_freeq_pairp[qn].
3204                             m_slot_releq.s.m_fq_list.list_head.list_prev =
3205                             &mpt->m_slot_freeq_pairp[qn].
3206                             m_slot_releq.s.m_fq_list.list_head;
3207                         mpt->m_slot_freeq_pairp[qn].
3208                             m_slot_releq.s.m_fq_n = 0;
3209                 } else {
3210                         mutex_exit(&mpt->m_slot_freeq_pairp[qn].
3211                             m_slot_releq.s.m_fq_mutex);
3212                         mutex_exit(&mpt->m_slot_freeq_pairp[qn].
3213                             m_slot_allocq.s.m_fq_mutex);
3214                         qn = (qn + 1) & (mpt->m_slot_freeq_pair_n - 1);
3215                         if (qn == qn_first)
3216                                 return (FALSE);
3217                         else
3218                                 goto qpair_retry;
3219                 }
3220                 mutex_exit(&mpt->m_slot_freeq_pairp[qn].
3221                     m_slot_releq.s.m_fq_mutex);
3222                 pe = list_head(&mpt->m_slot_freeq_pairp[qn].
3223                     m_slot_allocq.s.m_fq_list);
3224                 ASSERT(pe);
3225         }
3226         list_remove(&mpt->m_slot_freeq_pairp[qn].
3227             m_slot_allocq.s.m_fq_list, pe);
3228         slot = pe->slot;
3229         /*
3230          * Make sure SMID is not using reserved value of 0
3231          * and the TM request slot.
3232          */
3233         ASSERT((slot > 0) && (slot <= slots->m_n_slots) &&
3234             mpt->m_slot_freeq_pairp[qn].m_slot_allocq.s.m_fq_n > 0);
3235         cmd->cmd_slot = slot;
3236         mpt->m_slot_freeq_pairp[qn].m_slot_allocq.s.m_fq_n--;
3237         ASSERT(mpt->m_slot_freeq_pairp[qn].m_slot_allocq.s.m_fq_n >= 0);
3238 
3239         mutex_exit(&mpt->m_slot_freeq_pairp[qn].m_slot_allocq.s.m_fq_mutex);
3240         /*
3241          * only increment per target ncmds if this is not a
3242          * command that has no target associated with it (i.e. a
3243          * event acknoledgment)
3244          */
3245         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
3246                 mutex_enter(&ptgt->m_tgt_intr_mutex);
3247                 ptgt->m_t_ncmds++;
3248                 mutex_exit(&ptgt->m_tgt_intr_mutex);
3249         }
3250         cmd->cmd_active_timeout = cmd->cmd_pkt->pkt_time;
3251 
3252         /*
3253          * If initial timout is less than or equal to one tick, bump
3254          * the timeout by a tick so that command doesn't timeout before
3255          * its allotted time.
3256          */
3257         if (cmd->cmd_active_timeout <= mptsas_scsi_watchdog_tick) {
3258                 cmd->cmd_active_timeout += mptsas_scsi_watchdog_tick;
3259         }
3260         return (TRUE);
3261 }
3262 
3263 /*
3264  * prepare the pkt:
3265  * the pkt may have been resubmitted or just reused so
3266  * initialize some fields and do some checks.
3267  */
3268 static int
3269 mptsas_prepare_pkt(mptsas_cmd_t *cmd)
3270 {
3271         struct scsi_pkt *pkt = CMD2PKT(cmd);
3272 
3273         NDBG1(("mptsas_prepare_pkt: cmd=0x%p", (void *)cmd));
3274 
3275         /*
3276          * Reinitialize some fields that need it; the packet may
3277          * have been resubmitted
3278          */
3279         pkt->pkt_reason = CMD_CMPLT;
3280         pkt->pkt_state = 0;
3281         pkt->pkt_statistics = 0;
3282         pkt->pkt_resid = 0;
3283         cmd->cmd_age = 0;
3284         cmd->cmd_pkt_flags = pkt->pkt_flags;
3285 
3286         /*
3287          * zero status byte.
3288          */
3289         *(pkt->pkt_scbp) = 0;
3290 
3291         if (cmd->cmd_flags & CFLAG_DMAVALID) {
3292                 pkt->pkt_resid = cmd->cmd_dmacount;
3293 
3294                 /*
3295                  * consistent packets need to be sync'ed first
3296                  * (only for data going out)
3297                  */
3298                 if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
3299                     (cmd->cmd_flags & CFLAG_DMASEND)) {
3300                         (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
3301                             DDI_DMA_SYNC_FORDEV);
3302                 }
3303         }
3304 
3305         cmd->cmd_flags =
3306             (cmd->cmd_flags & ~(CFLAG_TRANFLAG)) |
3307             CFLAG_PREPARED | CFLAG_IN_TRANSPORT;
3308 
3309         return (TRAN_ACCEPT);
3310 }
3311 
3312 /*
3313  * tran_init_pkt(9E) - allocate scsi_pkt(9S) for command
3314  *
3315  * One of three possibilities:
3316  *      - allocate scsi_pkt
3317  *      - allocate scsi_pkt and DMA resources
3318  *      - allocate DMA resources to an already-allocated pkt
3319  */
3320 static struct scsi_pkt *
3321 mptsas_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
3322     struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
3323     int (*callback)(), caddr_t arg)
3324 {
3325         mptsas_cmd_t            *cmd, *new_cmd;
3326         mptsas_t                *mpt = ADDR2MPT(ap);
3327         int                     failure = 1;
3328 #ifndef __sparc
3329         uint_t                  oldcookiec;
3330 #endif  /* __sparc */
3331         mptsas_target_t         *ptgt = NULL;
3332         int                     rval;
3333         mptsas_tgt_private_t    *tgt_private;
3334         int                     kf;
3335 
3336         kf = (callback == SLEEP_FUNC)? KM_SLEEP: KM_NOSLEEP;
3337 
3338         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
3339             tran_tgt_private;
3340         ASSERT(tgt_private != NULL);
3341         if (tgt_private == NULL) {
3342                 return (NULL);
3343         }
3344         ptgt = tgt_private->t_private;
3345         ASSERT(ptgt != NULL);
3346         if (ptgt == NULL)
3347                 return (NULL);
3348         ap->a_target = ptgt->m_devhdl;
3349         ap->a_lun = tgt_private->t_lun;
3350 
3351         ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC);
3352 #ifdef MPTSAS_TEST_EXTRN_ALLOC
3353         statuslen *= 100; tgtlen *= 4;
3354 #endif
3355         NDBG3(("mptsas_scsi_init_pkt:\n"
3356             "\ttgt=%d in=0x%p bp=0x%p clen=%d slen=%d tlen=%d flags=%x",
3357             ap->a_target, (void *)pkt, (void *)bp,
3358             cmdlen, statuslen, tgtlen, flags));
3359 
3360         /*
3361          * Allocate the new packet.
3362          */
3363         if (pkt == NULL) {
3364                 ddi_dma_handle_t        save_dma_handle;
3365                 ddi_dma_handle_t        save_arq_dma_handle;
3366                 struct buf              *save_arq_bp;
3367                 ddi_dma_cookie_t        save_arqcookie;
3368 #ifdef  __sparc
3369                 mptti_t                 *save_sg;
3370 #endif  /* __sparc */
3371 
3372                 cmd = kmem_cache_alloc(mpt->m_kmem_cache, kf);
3373 
3374                 if (cmd) {
3375                         save_dma_handle = cmd->cmd_dmahandle;
3376                         save_arq_dma_handle = cmd->cmd_arqhandle;
3377                         save_arq_bp = cmd->cmd_arq_buf;
3378                         save_arqcookie = cmd->cmd_arqcookie;
3379 #ifdef  __sparc
3380                         save_sg = cmd->cmd_sg;
3381 #endif  /* __sparc */
3382                         bzero(cmd, sizeof (*cmd) + scsi_pkt_size());
3383                         cmd->cmd_dmahandle = save_dma_handle;
3384                         cmd->cmd_arqhandle = save_arq_dma_handle;
3385                         cmd->cmd_arq_buf = save_arq_bp;
3386                         cmd->cmd_arqcookie = save_arqcookie;
3387 #ifdef  __sparc
3388                         cmd->cmd_sg = save_sg;
3389 #endif  /* __sparc */
3390                         pkt = (void *)((uchar_t *)cmd +
3391                             sizeof (struct mptsas_cmd));
3392                         pkt->pkt_ha_private = (opaque_t)cmd;
3393                         pkt->pkt_address = *ap;
3394                         pkt->pkt_private = (opaque_t)cmd->cmd_pkt_private;
3395                         pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb;
3396                         pkt->pkt_cdbp = (opaque_t)&cmd->cmd_cdb;
3397                         cmd->cmd_pkt = (struct scsi_pkt *)pkt;
3398                         cmd->cmd_cdblen = (uchar_t)cmdlen;
3399                         cmd->cmd_scblen = statuslen;
3400                         cmd->cmd_rqslen = SENSE_LENGTH;
3401                         cmd->cmd_tgt_addr = ptgt;
3402                         failure = 0;
3403                 }
3404 
3405                 if (failure || (cmdlen > sizeof (cmd->cmd_cdb)) ||
3406                     (tgtlen > PKT_PRIV_LEN) ||
3407                     (statuslen > EXTCMDS_STATUS_SIZE)) {
3408                         if (failure == 0) {
3409                                 /*
3410                                  * if extern alloc fails, all will be
3411                                  * deallocated, including cmd
3412                                  */
3413                                 failure = mptsas_pkt_alloc_extern(mpt, cmd,
3414                                     cmdlen, tgtlen, statuslen, kf);
3415                         }
3416                         if (failure) {
3417                                 /*
3418                                  * if extern allocation fails, it will
3419                                  * deallocate the new pkt as well
3420                                  */
3421                                 return (NULL);
3422                         }
3423                 }
3424                 new_cmd = cmd;
3425 
3426         } else {
3427                 cmd = PKT2CMD(pkt);
3428                 new_cmd = NULL;
3429         }
3430 
3431 
3432 #ifndef __sparc
3433         /* grab cmd->cmd_cookiec here as oldcookiec */
3434 
3435         oldcookiec = cmd->cmd_cookiec;
3436 #endif  /* __sparc */
3437 
3438         /*
3439          * If the dma was broken up into PARTIAL transfers cmd_nwin will be
3440          * greater than 0 and we'll need to grab the next dma window
3441          */
3442         /*
3443          * SLM-not doing extra command frame right now; may add later
3444          */
3445 
3446         if (cmd->cmd_nwin > 0) {
3447 
3448                 /*
3449                  * Make sure we havn't gone past the the total number
3450                  * of windows
3451                  */
3452                 if (++cmd->cmd_winindex >= cmd->cmd_nwin) {
3453                         return (NULL);
3454                 }
3455                 if (ddi_dma_getwin(cmd->cmd_dmahandle, cmd->cmd_winindex,
3456                     &cmd->cmd_dma_offset, &cmd->cmd_dma_len,
3457                     &cmd->cmd_cookie, &cmd->cmd_cookiec) == DDI_FAILURE) {
3458                         return (NULL);
3459                 }
3460                 goto get_dma_cookies;
3461         }
3462 
3463 
3464         if (flags & PKT_XARQ) {
3465                 cmd->cmd_flags |= CFLAG_XARQ;
3466         }
3467 
3468         /*
3469          * DMA resource allocation.  This version assumes your
3470          * HBA has some sort of bus-mastering or onboard DMA capability, with a
3471          * scatter-gather list of length MPTSAS_MAX_DMA_SEGS, as given in the
3472          * ddi_dma_attr_t structure and passed to scsi_impl_dmaget.
3473          */
3474         if (bp && (bp->b_bcount != 0) &&
3475             (cmd->cmd_flags & CFLAG_DMAVALID) == 0) {
3476 
3477                 int     cnt, dma_flags;
3478                 mptti_t *dmap;          /* ptr to the S/G list */
3479 
3480                 /*
3481                  * Set up DMA memory and position to the next DMA segment.
3482                  */
3483                 ASSERT(cmd->cmd_dmahandle != NULL);
3484 
3485                 if (bp->b_flags & B_READ) {
3486                         dma_flags = DDI_DMA_READ;
3487                         cmd->cmd_flags &= ~CFLAG_DMASEND;
3488                 } else {
3489                         dma_flags = DDI_DMA_WRITE;
3490                         cmd->cmd_flags |= CFLAG_DMASEND;
3491                 }
3492                 if (flags & PKT_CONSISTENT) {
3493                         cmd->cmd_flags |= CFLAG_CMDIOPB;
3494                         dma_flags |= DDI_DMA_CONSISTENT;
3495                 }
3496 
3497                 if (flags & PKT_DMA_PARTIAL) {
3498                         dma_flags |= DDI_DMA_PARTIAL;
3499                 }
3500 
3501                 /*
3502                  * workaround for byte hole issue on psycho and
3503                  * schizo pre 2.1
3504                  */
3505                 if ((bp->b_flags & B_READ) && ((bp->b_flags &
3506                     (B_PAGEIO|B_REMAPPED)) != B_PAGEIO) &&
3507                     ((uintptr_t)bp->b_un.b_addr & 0x7)) {
3508                         dma_flags |= DDI_DMA_CONSISTENT;
3509                 }
3510 
3511                 rval = ddi_dma_buf_bind_handle(cmd->cmd_dmahandle, bp,
3512                     dma_flags, callback, arg,
3513                     &cmd->cmd_cookie, &cmd->cmd_cookiec);
3514                 if (rval == DDI_DMA_PARTIAL_MAP) {
3515                         (void) ddi_dma_numwin(cmd->cmd_dmahandle,
3516                             &cmd->cmd_nwin);
3517                         cmd->cmd_winindex = 0;
3518                         (void) ddi_dma_getwin(cmd->cmd_dmahandle,
3519                             cmd->cmd_winindex, &cmd->cmd_dma_offset,
3520                             &cmd->cmd_dma_len, &cmd->cmd_cookie,
3521                             &cmd->cmd_cookiec);
3522                 } else if (rval && (rval != DDI_DMA_MAPPED)) {
3523                         switch (rval) {
3524                         case DDI_DMA_NORESOURCES:
3525                                 bioerror(bp, 0);
3526                                 break;
3527                         case DDI_DMA_BADATTR:
3528                         case DDI_DMA_NOMAPPING:
3529                                 bioerror(bp, EFAULT);
3530                                 break;
3531                         case DDI_DMA_TOOBIG:
3532                         default:
3533                                 bioerror(bp, EINVAL);
3534                                 break;
3535                         }
3536                         cmd->cmd_flags &= ~CFLAG_DMAVALID;
3537                         if (new_cmd) {
3538                                 mptsas_scsi_destroy_pkt(ap, pkt);
3539                         }
3540                         return ((struct scsi_pkt *)NULL);
3541                 }
3542 
3543 get_dma_cookies:
3544                 cmd->cmd_flags |= CFLAG_DMAVALID;
3545                 ASSERT(cmd->cmd_cookiec > 0);
3546 
3547                 if (cmd->cmd_cookiec > MPTSAS_MAX_CMD_SEGS) {
3548                         mptsas_log(mpt, CE_NOTE, "large cookiec received %d\n",
3549                             cmd->cmd_cookiec);
3550                         bioerror(bp, EINVAL);
3551                         if (new_cmd) {
3552                                 mptsas_scsi_destroy_pkt(ap, pkt);
3553                         }
3554                         return ((struct scsi_pkt *)NULL);
3555                 }
3556 
3557                 /*
3558                  * Allocate extra SGL buffer if needed.
3559                  */
3560                 if ((cmd->cmd_cookiec > MPTSAS_MAX_FRAME_SGES64(mpt)) &&
3561                     (cmd->cmd_extra_frames == NULL)) {
3562                         if (mptsas_alloc_extra_sgl_frame(mpt, cmd) ==
3563                             DDI_FAILURE) {
3564                                 mptsas_log(mpt, CE_WARN, "MPT SGL mem alloc "
3565                                     "failed");
3566                                 bioerror(bp, ENOMEM);
3567                                 if (new_cmd) {
3568                                         mptsas_scsi_destroy_pkt(ap, pkt);
3569                                 }
3570                                 return ((struct scsi_pkt *)NULL);
3571                         }
3572                 }
3573 
3574                 /*
3575                  * Always use scatter-gather transfer
3576                  * Use the loop below to store physical addresses of
3577                  * DMA segments, from the DMA cookies, into your HBA's
3578                  * scatter-gather list.
3579                  * We need to ensure we have enough kmem alloc'd
3580                  * for the sg entries since we are no longer using an
3581                  * array inside mptsas_cmd_t.
3582                  *
3583                  * We check cmd->cmd_cookiec against oldcookiec so
3584                  * the scatter-gather list is correctly allocated
3585                  */
3586 #ifndef __sparc
3587                 if (oldcookiec != cmd->cmd_cookiec) {
3588                         if (cmd->cmd_sg != (mptti_t *)NULL) {
3589                                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) *
3590                                     oldcookiec);
3591                                 cmd->cmd_sg = NULL;
3592                         }
3593                 }
3594 
3595                 if (cmd->cmd_sg == (mptti_t *)NULL) {
3596                         cmd->cmd_sg = kmem_alloc((size_t)(sizeof (mptti_t)*
3597                             cmd->cmd_cookiec), kf);
3598 
3599                         if (cmd->cmd_sg == (mptti_t *)NULL) {
3600                                 mptsas_log(mpt, CE_WARN,
3601                                     "unable to kmem_alloc enough memory "
3602                                     "for scatter/gather list");
3603                 /*
3604                  * if we have an ENOMEM condition we need to behave
3605                  * the same way as the rest of this routine
3606                  */
3607 
3608                                 bioerror(bp, ENOMEM);
3609                                 if (new_cmd) {
3610                                         mptsas_scsi_destroy_pkt(ap, pkt);
3611                                 }
3612                                 return ((struct scsi_pkt *)NULL);
3613                         }
3614                 }
3615 #endif  /* __sparc */
3616                 dmap = cmd->cmd_sg;
3617 
3618                 ASSERT(cmd->cmd_cookie.dmac_size != 0);
3619 
3620                 /*
3621                  * store the first segment into the S/G list
3622                  */
3623                 dmap->count = cmd->cmd_cookie.dmac_size;
3624                 dmap->addr.address64.Low = (uint32_t)
3625                     (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3626                 dmap->addr.address64.High = (uint32_t)
3627                     (cmd->cmd_cookie.dmac_laddress >> 32);
3628 
3629                 /*
3630                  * dmacount counts the size of the dma for this window
3631                  * (if partial dma is being used).  totaldmacount
3632                  * keeps track of the total amount of dma we have
3633                  * transferred for all the windows (needed to calculate
3634                  * the resid value below).
3635                  */
3636                 cmd->cmd_dmacount = cmd->cmd_cookie.dmac_size;
3637                 cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3638 
3639                 /*
3640                  * We already stored the first DMA scatter gather segment,
3641                  * start at 1 if we need to store more.
3642                  */
3643                 for (cnt = 1; cnt < cmd->cmd_cookiec; cnt++) {
3644                         /*
3645                          * Get next DMA cookie
3646                          */
3647                         ddi_dma_nextcookie(cmd->cmd_dmahandle,
3648                             &cmd->cmd_cookie);
3649                         dmap++;
3650 
3651                         cmd->cmd_dmacount += cmd->cmd_cookie.dmac_size;
3652                         cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3653 
3654                         /*
3655                          * store the segment parms into the S/G list
3656                          */
3657                         dmap->count = cmd->cmd_cookie.dmac_size;
3658                         dmap->addr.address64.Low = (uint32_t)
3659                             (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3660                         dmap->addr.address64.High = (uint32_t)
3661                             (cmd->cmd_cookie.dmac_laddress >> 32);
3662                 }
3663 
3664                 /*
3665                  * If this was partially allocated we set the resid
3666                  * the amount of data NOT transferred in this window
3667                  * If there is only one window, the resid will be 0
3668                  */
3669                 pkt->pkt_resid = (bp->b_bcount - cmd->cmd_totaldmacount);
3670                 NDBG16(("mptsas_dmaget: cmd_dmacount=%d.", cmd->cmd_dmacount));
3671         }
3672         return (pkt);
3673 }
3674 
3675 /*
3676  * tran_destroy_pkt(9E) - scsi_pkt(9s) deallocation
3677  *
3678  * Notes:
3679  *      - also frees DMA resources if allocated
3680  *      - implicit DMA synchonization
3681  */
3682 static void
3683 mptsas_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
3684 {
3685         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
3686         mptsas_t        *mpt = ADDR2MPT(ap);
3687 
3688         NDBG3(("mptsas_scsi_destroy_pkt: target=%d pkt=0x%p",
3689             ap->a_target, (void *)pkt));
3690 
3691         if (cmd->cmd_flags & CFLAG_DMAVALID) {
3692                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
3693                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
3694         }
3695 #ifndef __sparc
3696         if (cmd->cmd_sg) {
3697                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) * cmd->cmd_cookiec);
3698                 cmd->cmd_sg = NULL;
3699         }
3700 #endif  /* __sparc */
3701         mptsas_free_extra_sgl_frame(mpt, cmd);
3702 
3703         if ((cmd->cmd_flags &
3704             (CFLAG_FREE | CFLAG_CDBEXTERN | CFLAG_PRIVEXTERN |
3705             CFLAG_SCBEXTERN)) == 0) {
3706                 cmd->cmd_flags = CFLAG_FREE;
3707                 kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
3708         } else {
3709                 mptsas_pkt_destroy_extern(mpt, cmd);
3710         }
3711 }
3712 
3713 /*
3714  * kmem cache constructor and destructor:
3715  * When constructing, we bzero the cmd and allocate the dma handle
3716  * When destructing, just free the dma handle
3717  */
3718 static int
3719 mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags)
3720 {
3721         mptsas_cmd_t            *cmd = buf;
3722         mptsas_t                *mpt  = cdrarg;
3723         struct scsi_address     ap;
3724         uint_t                  cookiec;
3725         ddi_dma_attr_t          arq_dma_attr;
3726         int                     (*callback)(caddr_t);
3727 
3728         callback = (kmflags == KM_SLEEP)? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
3729 
3730         NDBG4(("mptsas_kmem_cache_constructor"));
3731 
3732         ap.a_hba_tran = mpt->m_tran;
3733         ap.a_target = 0;
3734         ap.a_lun = 0;
3735 
3736         /*
3737          * allocate a dma handle
3738          */
3739         if ((ddi_dma_alloc_handle(mpt->m_dip, &mpt->m_io_dma_attr, callback,
3740             NULL, &cmd->cmd_dmahandle)) != DDI_SUCCESS) {
3741                 cmd->cmd_dmahandle = NULL;
3742                 return (-1);
3743         }
3744 
3745         cmd->cmd_arq_buf = scsi_alloc_consistent_buf(&ap, (struct buf *)NULL,
3746             SENSE_LENGTH, B_READ, callback, NULL);
3747         if (cmd->cmd_arq_buf == NULL) {
3748                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3749                 cmd->cmd_dmahandle = NULL;
3750                 return (-1);
3751         }
3752 
3753         /*
3754          * allocate a arq handle
3755          */
3756         arq_dma_attr = mpt->m_msg_dma_attr;
3757         arq_dma_attr.dma_attr_sgllen = 1;
3758         if ((ddi_dma_alloc_handle(mpt->m_dip, &arq_dma_attr, callback,
3759             NULL, &cmd->cmd_arqhandle)) != DDI_SUCCESS) {
3760                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3761                 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3762                 cmd->cmd_dmahandle = NULL;
3763                 cmd->cmd_arqhandle = NULL;
3764                 return (-1);
3765         }
3766 
3767         if (ddi_dma_buf_bind_handle(cmd->cmd_arqhandle,
3768             cmd->cmd_arq_buf, (DDI_DMA_READ | DDI_DMA_CONSISTENT),
3769             callback, NULL, &cmd->cmd_arqcookie, &cookiec) != DDI_SUCCESS) {
3770                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3771                 ddi_dma_free_handle(&cmd->cmd_arqhandle);
3772                 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3773                 cmd->cmd_dmahandle = NULL;
3774                 cmd->cmd_arqhandle = NULL;
3775                 cmd->cmd_arq_buf = NULL;
3776                 return (-1);
3777         }
3778         /*
3779          * In sparc, the sgl length in most of the cases would be 1, so we
3780          * pre-allocate it in cache. On x86, the max number would be 256,
3781          * pre-allocate a maximum would waste a lot of memory especially
3782          * when many cmds are put onto waitq.
3783          */
3784 #ifdef  __sparc
3785         cmd->cmd_sg = kmem_alloc((size_t)(sizeof (mptti_t)*
3786             MPTSAS_MAX_CMD_SEGS), KM_SLEEP);
3787 #endif  /* __sparc */
3788 
3789         return (0);
3790 }
3791 
3792 static void
3793 mptsas_kmem_cache_destructor(void *buf, void *cdrarg)
3794 {
3795 #ifndef __lock_lint
3796         _NOTE(ARGUNUSED(cdrarg))
3797 #endif
3798         mptsas_cmd_t    *cmd = buf;
3799 
3800         NDBG4(("mptsas_kmem_cache_destructor"));
3801 
3802         if (cmd->cmd_arqhandle) {
3803                 (void) ddi_dma_unbind_handle(cmd->cmd_arqhandle);
3804                 ddi_dma_free_handle(&cmd->cmd_arqhandle);
3805                 cmd->cmd_arqhandle = NULL;
3806         }
3807         if (cmd->cmd_arq_buf) {
3808                 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3809                 cmd->cmd_arq_buf = NULL;
3810         }
3811         if (cmd->cmd_dmahandle) {
3812                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3813                 cmd->cmd_dmahandle = NULL;
3814         }
3815 #ifdef  __sparc
3816         if (cmd->cmd_sg) {
3817                 kmem_free(cmd->cmd_sg, sizeof (mptti_t)* MPTSAS_MAX_CMD_SEGS);
3818                 cmd->cmd_sg = NULL;
3819         }
3820 #endif  /* __sparc */
3821 }
3822 
3823 static int
3824 mptsas_cache_frames_constructor(void *buf, void *cdrarg, int kmflags)
3825 {
3826         mptsas_cache_frames_t   *p = buf;
3827         mptsas_t                *mpt = cdrarg;
3828         ddi_dma_attr_t          frame_dma_attr;
3829         size_t                  mem_size, alloc_len;
3830         ddi_dma_cookie_t        cookie;
3831         uint_t                  ncookie;
3832         int (*callback)(caddr_t) = (kmflags == KM_SLEEP)
3833             ? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
3834 
3835         frame_dma_attr = mpt->m_msg_dma_attr;
3836         frame_dma_attr.dma_attr_align = 0x10;
3837         frame_dma_attr.dma_attr_sgllen = 1;
3838 
3839         if (ddi_dma_alloc_handle(mpt->m_dip, &frame_dma_attr, callback, NULL,
3840             &p->m_dma_hdl) != DDI_SUCCESS) {
3841                 mptsas_log(mpt, CE_WARN, "Unable to allocate dma handle for"
3842                     " extra SGL.");
3843                 return (DDI_FAILURE);
3844         }
3845 
3846         mem_size = (mpt->m_max_request_frames - 1) * mpt->m_req_frame_size;
3847 
3848         if (ddi_dma_mem_alloc(p->m_dma_hdl, mem_size, &mpt->m_dev_acc_attr,
3849             DDI_DMA_CONSISTENT, callback, NULL, (caddr_t *)&p->m_frames_addr,
3850             &alloc_len, &p->m_acc_hdl) != DDI_SUCCESS) {
3851                 ddi_dma_free_handle(&p->m_dma_hdl);
3852                 p->m_dma_hdl = NULL;
3853                 mptsas_log(mpt, CE_WARN, "Unable to allocate dma memory for"
3854                     " extra SGL.");
3855                 return (DDI_FAILURE);
3856         }
3857 
3858         if (ddi_dma_addr_bind_handle(p->m_dma_hdl, NULL, p->m_frames_addr,
3859             alloc_len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, callback, NULL,
3860             &cookie, &ncookie) != DDI_DMA_MAPPED) {
3861                 (void) ddi_dma_mem_free(&p->m_acc_hdl);
3862                 ddi_dma_free_handle(&p->m_dma_hdl);
3863                 p->m_dma_hdl = NULL;
3864                 mptsas_log(mpt, CE_WARN, "Unable to bind DMA resources for"
3865                     " extra SGL");
3866                 return (DDI_FAILURE);
3867         }
3868 
3869         /*
3870          * Store the SGL memory address.  This chip uses this
3871          * address to dma to and from the driver.  The second
3872          * address is the address mpt uses to fill in the SGL.
3873          */
3874         p->m_phys_addr = cookie.dmac_address;
3875 
3876         return (DDI_SUCCESS);
3877 }
3878 
3879 static void
3880 mptsas_cache_frames_destructor(void *buf, void *cdrarg)
3881 {
3882 #ifndef __lock_lint
3883         _NOTE(ARGUNUSED(cdrarg))
3884 #endif
3885         mptsas_cache_frames_t   *p = buf;
3886         if (p->m_dma_hdl != NULL) {
3887                 (void) ddi_dma_unbind_handle(p->m_dma_hdl);
3888                 (void) ddi_dma_mem_free(&p->m_acc_hdl);
3889                 ddi_dma_free_handle(&p->m_dma_hdl);
3890                 p->m_phys_addr = NULL;
3891                 p->m_frames_addr = NULL;
3892                 p->m_dma_hdl = NULL;
3893                 p->m_acc_hdl = NULL;
3894         }
3895 
3896 }
3897 
3898 /*
3899  * allocate and deallocate external pkt space (ie. not part of mptsas_cmd)
3900  * for non-standard length cdb, pkt_private, status areas
3901  * if allocation fails, then deallocate all external space and the pkt
3902  */
3903 /* ARGSUSED */
3904 static int
3905 mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
3906     int cmdlen, int tgtlen, int statuslen, int kf)
3907 {
3908         caddr_t                 cdbp, scbp, tgt;
3909         int                     (*callback)(caddr_t) = (kf == KM_SLEEP) ?
3910             DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
3911         struct scsi_address     ap;
3912         size_t                  senselength;
3913         ddi_dma_attr_t          ext_arq_dma_attr;
3914         uint_t                  cookiec;
3915 
3916         NDBG3(("mptsas_pkt_alloc_extern: "
3917             "cmd=0x%p cmdlen=%d tgtlen=%d statuslen=%d kf=%x",
3918             (void *)cmd, cmdlen, tgtlen, statuslen, kf));
3919 
3920         tgt = cdbp = scbp = NULL;
3921         cmd->cmd_scblen              = statuslen;
3922         cmd->cmd_privlen     = (uchar_t)tgtlen;
3923 
3924         if (cmdlen > sizeof (cmd->cmd_cdb)) {
3925                 if ((cdbp = kmem_zalloc((size_t)cmdlen, kf)) == NULL) {
3926                         goto fail;
3927                 }
3928                 cmd->cmd_pkt->pkt_cdbp = (opaque_t)cdbp;
3929                 cmd->cmd_flags |= CFLAG_CDBEXTERN;
3930         }
3931         if (tgtlen > PKT_PRIV_LEN) {
3932                 if ((tgt = kmem_zalloc((size_t)tgtlen, kf)) == NULL) {
3933                         goto fail;
3934                 }
3935                 cmd->cmd_flags |= CFLAG_PRIVEXTERN;
3936                 cmd->cmd_pkt->pkt_private = tgt;
3937         }
3938         if (statuslen > EXTCMDS_STATUS_SIZE) {
3939                 if ((scbp = kmem_zalloc((size_t)statuslen, kf)) == NULL) {
3940                         goto fail;
3941                 }
3942                 cmd->cmd_flags |= CFLAG_SCBEXTERN;
3943                 cmd->cmd_pkt->pkt_scbp = (opaque_t)scbp;
3944 
3945                 /* allocate sense data buf for DMA */
3946 
3947                 senselength = statuslen - MPTSAS_GET_ITEM_OFF(
3948                     struct scsi_arq_status, sts_sensedata);
3949                 cmd->cmd_rqslen = (uchar_t)senselength;
3950 
3951                 ap.a_hba_tran = mpt->m_tran;
3952                 ap.a_target = 0;
3953                 ap.a_lun = 0;
3954 
3955                 cmd->cmd_ext_arq_buf = scsi_alloc_consistent_buf(&ap,
3956                     (struct buf *)NULL, senselength, B_READ,
3957                     callback, NULL);
3958 
3959                 if (cmd->cmd_ext_arq_buf == NULL) {
3960                         goto fail;
3961                 }
3962                 /*
3963                  * allocate a extern arq handle and bind the buf
3964                  */
3965                 ext_arq_dma_attr = mpt->m_msg_dma_attr;
3966                 ext_arq_dma_attr.dma_attr_sgllen = 1;
3967                 if ((ddi_dma_alloc_handle(mpt->m_dip,
3968                     &ext_arq_dma_attr, callback,
3969                     NULL, &cmd->cmd_ext_arqhandle)) != DDI_SUCCESS) {
3970                         goto fail;
3971                 }
3972 
3973                 if (ddi_dma_buf_bind_handle(cmd->cmd_ext_arqhandle,
3974                     cmd->cmd_ext_arq_buf, (DDI_DMA_READ | DDI_DMA_CONSISTENT),
3975                     callback, NULL, &cmd->cmd_ext_arqcookie,
3976                     &cookiec)
3977                     != DDI_SUCCESS) {
3978                         goto fail;
3979                 }
3980                 cmd->cmd_flags |= CFLAG_EXTARQBUFVALID;
3981         }
3982         return (0);
3983 fail:
3984         mptsas_pkt_destroy_extern(mpt, cmd);
3985         return (1);
3986 }
3987 
3988 /*
3989  * deallocate external pkt space and deallocate the pkt
3990  */
3991 static void
3992 mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd)
3993 {
3994         NDBG3(("mptsas_pkt_destroy_extern: cmd=0x%p", (void *)cmd));
3995 
3996         if (cmd->cmd_flags & CFLAG_FREE) {
3997                 mptsas_log(mpt, CE_PANIC,
3998                     "mptsas_pkt_destroy_extern: freeing free packet");
3999                 _NOTE(NOT_REACHED)
4000                 /* NOTREACHED */
4001         }
4002         if (cmd->cmd_flags & CFLAG_CDBEXTERN) {
4003                 kmem_free(cmd->cmd_pkt->pkt_cdbp, (size_t)cmd->cmd_cdblen);
4004         }
4005         if (cmd->cmd_flags & CFLAG_SCBEXTERN) {
4006                 kmem_free(cmd->cmd_pkt->pkt_scbp, (size_t)cmd->cmd_scblen);
4007                 if (cmd->cmd_flags & CFLAG_EXTARQBUFVALID) {
4008                         (void) ddi_dma_unbind_handle(cmd->cmd_ext_arqhandle);
4009                 }
4010                 if (cmd->cmd_ext_arqhandle) {
4011                         ddi_dma_free_handle(&cmd->cmd_ext_arqhandle);
4012                         cmd->cmd_ext_arqhandle = NULL;
4013                 }
4014                 if (cmd->cmd_ext_arq_buf)
4015                         scsi_free_consistent_buf(cmd->cmd_ext_arq_buf);
4016         }
4017         if (cmd->cmd_flags & CFLAG_PRIVEXTERN) {
4018                 kmem_free(cmd->cmd_pkt->pkt_private, (size_t)cmd->cmd_privlen);
4019         }
4020         cmd->cmd_flags = CFLAG_FREE;
4021         kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
4022 }
4023 
4024 /*
4025  * tran_sync_pkt(9E) - explicit DMA synchronization
4026  */
4027 /*ARGSUSED*/
4028 static void
4029 mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
4030 {
4031         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
4032 
4033         NDBG3(("mptsas_scsi_sync_pkt: target=%d, pkt=0x%p",
4034             ap->a_target, (void *)pkt));
4035 
4036         if (cmd->cmd_dmahandle) {
4037                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4038                     (cmd->cmd_flags & CFLAG_DMASEND) ?
4039                     DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
4040         }
4041 }
4042 
4043 /*
4044  * tran_dmafree(9E) - deallocate DMA resources allocated for command
4045  */
4046 /*ARGSUSED*/
4047 static void
4048 mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
4049 {
4050         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
4051         mptsas_t        *mpt = ADDR2MPT(ap);
4052 
4053         NDBG3(("mptsas_scsi_dmafree: target=%d pkt=0x%p",
4054             ap->a_target, (void *)pkt));
4055 
4056         if (cmd->cmd_flags & CFLAG_DMAVALID) {
4057                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
4058                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
4059         }
4060 
4061         if (cmd->cmd_flags & CFLAG_EXTARQBUFVALID) {
4062                 (void) ddi_dma_unbind_handle(cmd->cmd_ext_arqhandle);
4063                 cmd->cmd_flags &= ~CFLAG_EXTARQBUFVALID;
4064         }
4065 
4066         mptsas_free_extra_sgl_frame(mpt, cmd);
4067 }
4068 
4069 static void
4070 mptsas_pkt_comp(struct scsi_pkt *pkt, mptsas_cmd_t *cmd)
4071 {
4072         if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
4073             (!(cmd->cmd_flags & CFLAG_DMASEND))) {
4074                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4075                     DDI_DMA_SYNC_FORCPU);
4076         }
4077         (*pkt->pkt_comp)(pkt);
4078 }
4079 
4080 static void
4081 mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd, uint32_t *control,
4082         pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4083 {
4084         uint_t                  cookiec;
4085         mptti_t                 *dmap;
4086         uint32_t                flags;
4087         pMpi2SGESimple64_t      sge;
4088         pMpi2SGEChain64_t       sgechain;
4089         ASSERT(cmd->cmd_flags & CFLAG_DMAVALID);
4090 
4091         /*
4092          * Save the number of entries in the DMA
4093          * Scatter/Gather list
4094          */
4095         cookiec = cmd->cmd_cookiec;
4096 
4097         NDBG1(("mptsas_sge_setup: cookiec=%d", cookiec));
4098 
4099         /*
4100          * Set read/write bit in control.
4101          */
4102         if (cmd->cmd_flags & CFLAG_DMASEND) {
4103                 *control |= MPI2_SCSIIO_CONTROL_WRITE;
4104         } else {
4105                 *control |= MPI2_SCSIIO_CONTROL_READ;
4106         }
4107 
4108         ddi_put32(acc_hdl, &frame->DataLength, cmd->cmd_dmacount);
4109 
4110         /*
4111          * We have 2 cases here.  First where we can fit all the
4112          * SG elements into the main frame, and the case
4113          * where we can't.
4114          * If we have more cookies than we can attach to a frame
4115          * we will need to use a chain element to point
4116          * a location of memory where the rest of the S/G
4117          * elements reside.
4118          */
4119         if (cookiec <= MPTSAS_MAX_FRAME_SGES64(mpt)) {
4120                 dmap = cmd->cmd_sg;
4121                 sge = (pMpi2SGESimple64_t)(&frame->SGL);
4122                 while (cookiec--) {
4123                         ddi_put32(acc_hdl,
4124                             &sge->Address.Low, dmap->addr.address64.Low);
4125                         ddi_put32(acc_hdl,
4126                             &sge->Address.High, dmap->addr.address64.High);
4127                         ddi_put32(acc_hdl, &sge->FlagsLength,
4128                             dmap->count);
4129                         flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4130                         flags |= ((uint32_t)
4131                             (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4132                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4133                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4134                             MPI2_SGE_FLAGS_SHIFT);
4135 
4136                         /*
4137                          * If this is the last cookie, we set the flags
4138                          * to indicate so
4139                          */
4140                         if (cookiec == 0) {
4141                                 flags |=
4142                                     ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT
4143                                     | MPI2_SGE_FLAGS_END_OF_BUFFER
4144                                     | MPI2_SGE_FLAGS_END_OF_LIST) <<
4145                                     MPI2_SGE_FLAGS_SHIFT);
4146                         }
4147                         if (cmd->cmd_flags & CFLAG_DMASEND) {
4148                                 flags |= (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4149                                     MPI2_SGE_FLAGS_SHIFT);
4150                         } else {
4151                                 flags |= (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4152                                     MPI2_SGE_FLAGS_SHIFT);
4153                         }
4154                         ddi_put32(acc_hdl, &sge->FlagsLength, flags);
4155                         dmap++;
4156                         sge++;
4157                 }
4158         } else {
4159                 /*
4160                  * Hereby we start to deal with multiple frames.
4161                  * The process is as follows:
4162                  * 1. Determine how many frames are needed for SGL element
4163                  *    storage; Note that all frames are stored in contiguous
4164                  *    memory space and in 64-bit DMA mode each element is
4165                  *    3 double-words (12 bytes) long.
4166                  * 2. Fill up the main frame. We need to do this separately
4167                  *    since it contains the SCSI IO request header and needs
4168                  *    dedicated processing. Note that the last 4 double-words
4169                  *    of the SCSI IO header is for SGL element storage
4170                  *    (MPI2_SGE_IO_UNION).
4171                  * 3. Fill the chain element in the main frame, so the DMA
4172                  *    engine can use the following frames.
4173                  * 4. Enter a loop to fill the remaining frames. Note that the
4174                  *    last frame contains no chain element.  The remaining
4175                  *    frames go into the mpt SGL buffer allocated on the fly,
4176                  *    not immediately following the main message frame, as in
4177                  *    Gen1.
4178                  * Some restrictions:
4179                  * 1. For 64-bit DMA, the simple element and chain element
4180                  *    are both of 3 double-words (12 bytes) in size, even
4181                  *    though all frames are stored in the first 4G of mem
4182                  *    range and the higher 32-bits of the address are always 0.
4183                  * 2. On some controllers (like the 1064/1068), a frame can
4184                  *    hold SGL elements with the last 1 or 2 double-words
4185                  *    (4 or 8 bytes) un-used. On these controllers, we should
4186                  *    recognize that there's not enough room for another SGL
4187                  *    element and move the sge pointer to the next frame.
4188                  */
4189                 int             i, j, k, l, frames, sgemax;
4190                 int             temp;
4191                 uint8_t         chainflags;
4192                 uint16_t        chainlength;
4193                 mptsas_cache_frames_t *p;
4194 
4195                 /*
4196                  * Sgemax is the number of SGE's that will fit
4197                  * each extra frame and frames is total
4198                  * number of frames we'll need.  1 sge entry per
4199                  * frame is reseverd for the chain element thus the -1 below.
4200                  */
4201                 sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_SGE_SIMPLE64))
4202                     - 1);
4203                 temp = (cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) / sgemax;
4204 
4205                 /*
4206                  * A little check to see if we need to round up the number
4207                  * of frames we need
4208                  */
4209                 if ((cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) - (temp *
4210                     sgemax) > 1) {
4211                         frames = (temp + 1);
4212                 } else {
4213                         frames = temp;
4214                 }
4215                 dmap = cmd->cmd_sg;
4216                 sge = (pMpi2SGESimple64_t)(&frame->SGL);
4217 
4218                 /*
4219                  * First fill in the main frame
4220                  */
4221                 for (j = 1; j < MPTSAS_MAX_FRAME_SGES64(mpt); j++) {
4222                         ddi_put32(acc_hdl, &sge->Address.Low,
4223                             dmap->addr.address64.Low);
4224                         ddi_put32(acc_hdl, &sge->Address.High,
4225                             dmap->addr.address64.High);
4226                         ddi_put32(acc_hdl, &sge->FlagsLength, dmap->count);
4227                         flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4228                         flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4229                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4230                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4231                             MPI2_SGE_FLAGS_SHIFT);
4232 
4233                         /*
4234                          * If this is the last SGE of this frame
4235                          * we set the end of list flag
4236                          */
4237                         if (j == (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) {
4238                                 flags |= ((uint32_t)
4239                                     (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4240                                     MPI2_SGE_FLAGS_SHIFT);
4241                         }
4242                         if (cmd->cmd_flags & CFLAG_DMASEND) {
4243                                 flags |=
4244                                     (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4245                                     MPI2_SGE_FLAGS_SHIFT);
4246                         } else {
4247                                 flags |=
4248                                     (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4249                                     MPI2_SGE_FLAGS_SHIFT);
4250                         }
4251                         ddi_put32(acc_hdl, &sge->FlagsLength, flags);
4252                         dmap++;
4253                         sge++;
4254                 }
4255 
4256                 /*
4257                  * Fill in the chain element in the main frame.
4258                  * About calculation on ChainOffset:
4259                  * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
4260                  *    in the end reserved for SGL element storage
4261                  *    (MPI2_SGE_IO_UNION); we should count it in our
4262                  *    calculation.  See its definition in the header file.
4263                  * 2. Constant j is the counter of the current SGL element
4264                  *    that will be processed, and (j - 1) is the number of
4265                  *    SGL elements that have been processed (stored in the
4266                  *    main frame).
4267                  * 3. ChainOffset value should be in units of double-words (4
4268                  *    bytes) so the last value should be divided by 4.
4269                  */
4270                 ddi_put8(acc_hdl, &frame->ChainOffset,
4271                     (sizeof (MPI2_SCSI_IO_REQUEST) -
4272                     sizeof (MPI2_SGE_IO_UNION) +
4273                     (j - 1) * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4274                 sgechain = (pMpi2SGEChain64_t)sge;
4275                 chainflags = (MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4276                     MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4277                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4278                 ddi_put8(acc_hdl, &sgechain->Flags, chainflags);
4279 
4280                 /*
4281                  * The size of the next frame is the accurate size of space
4282                  * (in bytes) used to store the SGL elements. j is the counter
4283                  * of SGL elements. (j - 1) is the number of SGL elements that
4284                  * have been processed (stored in frames).
4285                  */
4286                 if (frames >= 2) {
4287                         chainlength = mpt->m_req_frame_size /
4288                             sizeof (MPI2_SGE_SIMPLE64) *
4289                             sizeof (MPI2_SGE_SIMPLE64);
4290                 } else {
4291                         chainlength = ((cookiec - (j - 1)) *
4292                             sizeof (MPI2_SGE_SIMPLE64));
4293                 }
4294 
4295                 p = cmd->cmd_extra_frames;
4296 
4297                 ddi_put16(acc_hdl, &sgechain->Length, chainlength);
4298                 ddi_put32(acc_hdl, &sgechain->Address.Low,
4299                     p->m_phys_addr);
4300                 /* SGL is allocated in the first 4G mem range */
4301                 ddi_put32(acc_hdl, &sgechain->Address.High, 0);
4302 
4303                 /*
4304                  * If there are more than 2 frames left we have to
4305                  * fill in the next chain offset to the location of
4306                  * the chain element in the next frame.
4307                  * sgemax is the number of simple elements in an extra
4308                  * frame. Note that the value NextChainOffset should be
4309                  * in double-words (4 bytes).
4310                  */
4311                 if (frames >= 2) {
4312                         ddi_put8(acc_hdl, &sgechain->NextChainOffset,
4313                             (sgemax * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4314                 } else {
4315                         ddi_put8(acc_hdl, &sgechain->NextChainOffset, 0);
4316                 }
4317 
4318                 /*
4319                  * Jump to next frame;
4320                  * Starting here, chain buffers go into the per command SGL.
4321                  * This buffer is allocated when chain buffers are needed.
4322                  */
4323                 sge = (pMpi2SGESimple64_t)p->m_frames_addr;
4324                 i = cookiec;
4325 
4326                 /*
4327                  * Start filling in frames with SGE's.  If we
4328                  * reach the end of frame and still have SGE's
4329                  * to fill we need to add a chain element and
4330                  * use another frame.  j will be our counter
4331                  * for what cookie we are at and i will be
4332                  * the total cookiec. k is the current frame
4333                  */
4334                 for (k = 1; k <= frames; k++) {
4335                         for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
4336 
4337                                 /*
4338                                  * If we have reached the end of frame
4339                                  * and we have more SGE's to fill in
4340                                  * we have to fill the final entry
4341                                  * with a chain element and then
4342                                  * continue to the next frame
4343                                  */
4344                                 if ((l == (sgemax + 1)) && (k != frames)) {
4345                                         sgechain = (pMpi2SGEChain64_t)sge;
4346                                         j--;
4347                                         chainflags = (
4348                                             MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4349                                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4350                                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4351                                         ddi_put8(p->m_acc_hdl,
4352                                             &sgechain->Flags, chainflags);
4353                                         /*
4354                                          * k is the frame counter and (k + 1)
4355                                          * is the number of the next frame.
4356                                          * Note that frames are in contiguous
4357                                          * memory space.
4358                                          */
4359                                         ddi_put32(p->m_acc_hdl,
4360                                             &sgechain->Address.Low,
4361                                             (p->m_phys_addr +
4362                                             (mpt->m_req_frame_size * k)));
4363                                         ddi_put32(p->m_acc_hdl,
4364                                             &sgechain->Address.High, 0);
4365 
4366                                         /*
4367                                          * If there are more than 2 frames left
4368                                          * we have to next chain offset to
4369                                          * the location of the chain element
4370                                          * in the next frame and fill in the
4371                                          * length of the next chain
4372                                          */
4373                                         if ((frames - k) >= 2) {
4374                                                 ddi_put8(p->m_acc_hdl,
4375                                                     &sgechain->NextChainOffset,
4376                                                     (sgemax *
4377                                                     sizeof (MPI2_SGE_SIMPLE64))
4378                                                     >> 2);
4379                                                 ddi_put16(p->m_acc_hdl,
4380                                                     &sgechain->Length,
4381                                                     mpt->m_req_frame_size /
4382                                                     sizeof (MPI2_SGE_SIMPLE64) *
4383                                                     sizeof (MPI2_SGE_SIMPLE64));
4384                                         } else {
4385                                                 /*
4386                                                  * This is the last frame. Set
4387                                                  * the NextChainOffset to 0 and
4388                                                  * Length is the total size of
4389                                                  * all remaining simple elements
4390                                                  */
4391                                                 ddi_put8(p->m_acc_hdl,
4392                                                     &sgechain->NextChainOffset,
4393                                                     0);
4394                                                 ddi_put16(p->m_acc_hdl,
4395                                                     &sgechain->Length,
4396                                                     (cookiec - j) *
4397                                                     sizeof (MPI2_SGE_SIMPLE64));
4398                                         }
4399 
4400                                         /* Jump to the next frame */
4401                                         sge = (pMpi2SGESimple64_t)
4402                                             ((char *)p->m_frames_addr +
4403                                             (int)mpt->m_req_frame_size * k);
4404 
4405                                         continue;
4406                                 }
4407 
4408                                 ddi_put32(p->m_acc_hdl,
4409                                     &sge->Address.Low,
4410                                     dmap->addr.address64.Low);
4411                                 ddi_put32(p->m_acc_hdl,
4412                                     &sge->Address.High,
4413                                     dmap->addr.address64.High);
4414                                 ddi_put32(p->m_acc_hdl,
4415                                     &sge->FlagsLength, dmap->count);
4416                                 flags = ddi_get32(p->m_acc_hdl,
4417                                     &sge->FlagsLength);
4418                                 flags |= ((uint32_t)(
4419                                     MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4420                                     MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4421                                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4422                                     MPI2_SGE_FLAGS_SHIFT);
4423 
4424                                 /*
4425                                  * If we are at the end of the frame and
4426                                  * there is another frame to fill in
4427                                  * we set the last simple element as last
4428                                  * element
4429                                  */
4430                                 if ((l == sgemax) && (k != frames)) {
4431                                         flags |= ((uint32_t)
4432                                             (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4433                                             MPI2_SGE_FLAGS_SHIFT);
4434                                 }
4435 
4436                                 /*
4437                                  * If this is the final cookie we
4438                                  * indicate it by setting the flags
4439                                  */
4440                                 if (j == i) {
4441                                         flags |= ((uint32_t)
4442                                             (MPI2_SGE_FLAGS_LAST_ELEMENT |
4443                                             MPI2_SGE_FLAGS_END_OF_BUFFER |
4444                                             MPI2_SGE_FLAGS_END_OF_LIST) <<
4445                                             MPI2_SGE_FLAGS_SHIFT);
4446                                 }
4447                                 if (cmd->cmd_flags & CFLAG_DMASEND) {
4448                                         flags |=
4449                                             (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4450                                             MPI2_SGE_FLAGS_SHIFT);
4451                                 } else {
4452                                         flags |=
4453                                             (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4454                                             MPI2_SGE_FLAGS_SHIFT);
4455                                 }
4456                                 ddi_put32(p->m_acc_hdl,
4457                                     &sge->FlagsLength, flags);
4458                                 dmap++;
4459                                 sge++;
4460                         }
4461                 }
4462 
4463                 /*
4464                  * Sync DMA with the chain buffers that were just created
4465                  */
4466                 (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
4467         }
4468 }
4469 
4470 /*
4471  * Interrupt handling
4472  * Utility routine.  Poll for status of a command sent to HBA
4473  * without interrupts (a FLAG_NOINTR command).
4474  */
4475 int
4476 mptsas_poll(mptsas_t *mpt, mptsas_cmd_t *poll_cmd, int polltime)
4477 {
4478         int     rval = TRUE;
4479 
4480         NDBG5(("mptsas_poll: cmd=0x%p", (void *)poll_cmd));
4481 
4482         /*
4483          * In order to avoid using m_mutex in ISR(a new separate mutex
4484          * m_intr_mutex is introduced) and keep the same lock logic,
4485          * the m_intr_mutex should be used to protect the getting and
4486          * setting of the ReplyDescriptorIndex.
4487          *
4488          * Since the m_intr_mutex would be released during processing the poll
4489          * cmd, so we should set the poll flag earlier here to make sure the
4490          * polled cmd be handled in this thread/context. A side effect is other
4491          * cmds during the period between the flag set and reset are also
4492          * handled in this thread and not the ISR. Since the poll cmd is not
4493          * so common, so the performance degradation in this case is not a big
4494          * issue.
4495          */
4496         mutex_enter(&mpt->m_intr_mutex);
4497         mpt->m_polled_intr = 1;
4498         mutex_exit(&mpt->m_intr_mutex);
4499 
4500         if ((poll_cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
4501                 mptsas_restart_hba(mpt);
4502         }
4503 
4504         /*
4505          * Wait, using drv_usecwait(), long enough for the command to
4506          * reasonably return from the target if the target isn't
4507          * "dead".  A polled command may well be sent from scsi_poll, and
4508          * there are retries built in to scsi_poll if the transport
4509          * accepted the packet (TRAN_ACCEPT).  scsi_poll waits 1 second
4510          * and retries the transport up to scsi_poll_busycnt times
4511          * (currently 60) if
4512          * 1. pkt_reason is CMD_INCOMPLETE and pkt_state is 0, or
4513          * 2. pkt_reason is CMD_CMPLT and *pkt_scbp has STATUS_BUSY
4514          *
4515          * limit the waiting to avoid a hang in the event that the
4516          * cmd never gets started but we are still receiving interrupts
4517          */
4518         while (!(poll_cmd->cmd_flags & CFLAG_FINISHED)) {
4519                 if (mptsas_wait_intr(mpt, polltime) == FALSE) {
4520                         NDBG5(("mptsas_poll: command incomplete"));
4521                         rval = FALSE;
4522                         break;
4523                 }
4524         }
4525 
4526         mutex_enter(&mpt->m_intr_mutex);
4527         mpt->m_polled_intr = 0;
4528         mutex_exit(&mpt->m_intr_mutex);
4529 
4530         if (rval == FALSE) {
4531 
4532                 /*
4533                  * this isn't supposed to happen, the hba must be wedged
4534                  * Mark this cmd as a timeout.
4535                  */
4536                 mptsas_set_pkt_reason(mpt, poll_cmd, CMD_TIMEOUT,
4537                     (STAT_TIMEOUT|STAT_ABORTED));
4538 
4539                 if (poll_cmd->cmd_queued == FALSE) {
4540 
4541                         NDBG5(("mptsas_poll: not on waitq"));
4542 
4543                         poll_cmd->cmd_pkt->pkt_state |=
4544                             (STATE_GOT_BUS|STATE_GOT_TARGET|STATE_SENT_CMD);
4545                 } else {
4546 
4547                         /* find and remove it from the waitq */
4548                         NDBG5(("mptsas_poll: delete from waitq"));
4549                         mptsas_waitq_delete(mpt, poll_cmd);
4550                 }
4551 
4552         }
4553         mptsas_fma_check(mpt, poll_cmd);
4554         NDBG5(("mptsas_poll: done"));
4555         return (rval);
4556 }
4557 
4558 /*
4559  * Used for polling cmds and TM function
4560  */
4561 static int
4562 mptsas_wait_intr(mptsas_t *mpt, int polltime)
4563 {
4564         int                             cnt;
4565         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
4566         Mpi2ReplyDescriptorsUnion_t     reply_desc_union_v;
4567         uint32_t                        int_mask;
4568         uint8_t reply_type;
4569 
4570         NDBG5(("mptsas_wait_intr"));
4571 
4572 
4573         /*
4574          * Get the current interrupt mask and disable interrupts.  When
4575          * re-enabling ints, set mask to saved value.
4576          */
4577         int_mask = ddi_get32(mpt->m_datap, &mpt->m_reg->HostInterruptMask);
4578         MPTSAS_DISABLE_INTR(mpt);
4579 
4580         /*
4581          * Keep polling for at least (polltime * 1000) seconds
4582          */
4583         for (cnt = 0; cnt < polltime; cnt++) {
4584                 mutex_enter(&mpt->m_intr_mutex);
4585                 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
4586                     DDI_DMA_SYNC_FORCPU);
4587 
4588                 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
4589                     MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
4590 
4591                 if (ddi_get32(mpt->m_acc_post_queue_hdl,
4592                     &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
4593                     ddi_get32(mpt->m_acc_post_queue_hdl,
4594                     &reply_desc_union->Words.High) == 0xFFFFFFFF) {
4595                         mutex_exit(&mpt->m_intr_mutex);
4596                         drv_usecwait(1000);
4597                         continue;
4598                 }
4599 
4600                 reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
4601                     &reply_desc_union->Default.ReplyFlags);
4602                 reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
4603                 reply_desc_union_v.Default.ReplyFlags = reply_type;
4604                 if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
4605                         reply_desc_union_v.SCSIIOSuccess.SMID =
4606                             ddi_get16(mpt->m_acc_post_queue_hdl,
4607                             &reply_desc_union->SCSIIOSuccess.SMID);
4608                 } else if (reply_type ==
4609                     MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
4610                         reply_desc_union_v.AddressReply.ReplyFrameAddress =
4611                             ddi_get32(mpt->m_acc_post_queue_hdl,
4612                             &reply_desc_union->AddressReply.ReplyFrameAddress);
4613                         reply_desc_union_v.AddressReply.SMID =
4614                             ddi_get16(mpt->m_acc_post_queue_hdl,
4615                             &reply_desc_union->AddressReply.SMID);
4616                 }
4617                 /*
4618                  * Clear the reply descriptor for re-use and increment
4619                  * index.
4620                  */
4621                 ddi_put64(mpt->m_acc_post_queue_hdl,
4622                     &((uint64_t *)(void *)mpt->m_post_queue)[mpt->m_post_index],
4623                     0xFFFFFFFFFFFFFFFF);
4624                 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
4625                     DDI_DMA_SYNC_FORDEV);
4626 
4627                 if (++mpt->m_post_index == mpt->m_post_queue_depth) {
4628                         mpt->m_post_index = 0;
4629                 }
4630 
4631                 /*
4632                  * Update the global reply index
4633                  */
4634                 ddi_put32(mpt->m_datap,
4635                     &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
4636                 mutex_exit(&mpt->m_intr_mutex);
4637 
4638                 /*
4639                  * The reply is valid, process it according to its
4640                  * type.
4641                  */
4642                 mptsas_process_intr(mpt, &reply_desc_union_v);
4643 
4644 
4645                 /*
4646                  * Re-enable interrupts and quit.
4647                  */
4648                 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask,
4649                     int_mask);
4650                 return (TRUE);
4651 
4652         }
4653 
4654         /*
4655          * Clear polling flag, re-enable interrupts and quit.
4656          */
4657         ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask, int_mask);
4658         return (FALSE);
4659 }
4660 
4661 /*
4662  * For fastpath, the m_intr_mutex should be held from the begining to the end,
4663  * so we only treat those cmds that need not release m_intr_mutex(even just for
4664  * a moment) as candidate for fast processing. otherwise, we don't handle them
4665  * and just return, then in ISR, those cmds would be handled later with m_mutex
4666  * held and m_intr_mutex not held.
4667  */
4668 static int
4669 mptsas_handle_io_fastpath(mptsas_t *mpt,
4670     uint16_t SMID)
4671 {
4672         mptsas_slots_t                          *slots = mpt->m_active;
4673         mptsas_cmd_t                            *cmd = NULL;
4674         struct scsi_pkt                         *pkt;
4675 
4676         /*
4677          * This is a success reply so just complete the IO.  First, do a sanity
4678          * check on the SMID.  The final slot is used for TM requests, which
4679          * would not come into this reply handler.
4680          */
4681         if ((SMID == 0) || (SMID > slots->m_n_slots)) {
4682                 mptsas_log(mpt, CE_WARN, "?Received invalid SMID of %d\n",
4683                     SMID);
4684                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4685                 return (TRUE);
4686         }
4687 
4688         cmd = slots->m_slot[SMID];
4689 
4690         /*
4691          * print warning and return if the slot is empty
4692          */
4693         if (cmd == NULL) {
4694                 mptsas_log(mpt, CE_WARN, "?NULL command for successful SCSI IO "
4695                     "in slot %d", SMID);
4696                 return (TRUE);
4697         }
4698 
4699         pkt = CMD2PKT(cmd);
4700         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
4701             STATE_GOT_STATUS);
4702         if (cmd->cmd_flags & CFLAG_DMAVALID) {
4703                 pkt->pkt_state |= STATE_XFERRED_DATA;
4704         }
4705         pkt->pkt_resid = 0;
4706 
4707         /*
4708          * If the cmd is a IOC, or a passthrough, then we don't process it in
4709          * fastpath, and later it would be handled by mptsas_process_intr()
4710          * with m_mutex protected.
4711          */
4712         if (cmd->cmd_flags & (CFLAG_PASSTHRU | CFLAG_CMDIOC)) {
4713                 return (FALSE);
4714         } else {
4715                 mptsas_remove_cmd0(mpt, cmd);
4716         }
4717 
4718         if (cmd->cmd_flags & CFLAG_RETRY) {
4719                 /*
4720                  * The target returned QFULL or busy, do not add tihs
4721                  * pkt to the doneq since the hba will retry
4722                  * this cmd.
4723                  *
4724                  * The pkt has already been resubmitted in
4725                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
4726                  * Remove this cmd_flag here.
4727                  */
4728                 cmd->cmd_flags &= ~CFLAG_RETRY;
4729         } else {
4730                 mptsas_doneq_add0(mpt, cmd);
4731         }
4732 
4733         /*
4734          * In fastpath, the cmd should only be a context reply, so just check
4735          * the post queue of the reply descriptor and the dmahandle of the cmd
4736          * is enough. No sense data in this case and no need to check the dma
4737          * handle where sense data dma info is saved, the dma handle of the
4738          * reply frame, and the dma handle of the reply free queue.
4739          * For the dma handle of the request queue. Check fma here since we
4740          * are sure the request must have already been sent/DMAed correctly.
4741          * otherwise checking in mptsas_scsi_start() is not correct since
4742          * at that time the dma may not start.
4743          */
4744         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
4745             DDI_SUCCESS) ||
4746             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
4747             DDI_SUCCESS)) {
4748                 ddi_fm_service_impact(mpt->m_dip,
4749                     DDI_SERVICE_UNAFFECTED);
4750                 pkt->pkt_reason = CMD_TRAN_ERR;
4751                 pkt->pkt_statistics = 0;
4752         }
4753         if (cmd->cmd_dmahandle &&
4754             (mptsas_check_dma_handle(cmd->cmd_dmahandle) != DDI_SUCCESS)) {
4755                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4756                 pkt->pkt_reason = CMD_TRAN_ERR;
4757                 pkt->pkt_statistics = 0;
4758         }
4759         if ((cmd->cmd_extra_frames &&
4760             ((mptsas_check_dma_handle(cmd->cmd_extra_frames->m_dma_hdl) !=
4761             DDI_SUCCESS) ||
4762             (mptsas_check_acc_handle(cmd->cmd_extra_frames->m_acc_hdl) !=
4763             DDI_SUCCESS)))) {
4764                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4765                 pkt->pkt_reason = CMD_TRAN_ERR;
4766                 pkt->pkt_statistics = 0;
4767         }
4768 
4769         return (TRUE);
4770 }
4771 
4772 static void
4773 mptsas_handle_scsi_io_success(mptsas_t *mpt,
4774     pMpi2ReplyDescriptorsUnion_t reply_desc)
4775 {
4776         pMpi2SCSIIOSuccessReplyDescriptor_t     scsi_io_success;
4777         uint16_t                                SMID;
4778         mptsas_slots_t                          *slots = mpt->m_active;
4779         mptsas_cmd_t                            *cmd = NULL;
4780         struct scsi_pkt                         *pkt;
4781 
4782         scsi_io_success = (pMpi2SCSIIOSuccessReplyDescriptor_t)reply_desc;
4783         SMID = scsi_io_success->SMID;
4784 
4785         /*
4786          * This is a success reply so just complete the IO.  First, do a sanity
4787          * check on the SMID.  The final slot is used for TM requests, which
4788          * would not come into this reply handler.
4789          */
4790         if ((SMID == 0) || (SMID > slots->m_n_slots)) {
4791                 mptsas_log(mpt, CE_WARN, "?Received invalid SMID of %d\n",
4792                     SMID);
4793                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4794                 return;
4795         }
4796 
4797         cmd = slots->m_slot[SMID];
4798 
4799         /*
4800          * print warning and return if the slot is empty
4801          */
4802         if (cmd == NULL) {
4803                 mptsas_log(mpt, CE_WARN, "?NULL command for successful SCSI IO "
4804                     "in slot %d", SMID);
4805                 return;
4806         }
4807 
4808         pkt = CMD2PKT(cmd);
4809         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
4810             STATE_GOT_STATUS);
4811         if (cmd->cmd_flags & CFLAG_DMAVALID) {
4812                 pkt->pkt_state |= STATE_XFERRED_DATA;
4813         }
4814         pkt->pkt_resid = 0;
4815 
4816         if (cmd->cmd_flags & CFLAG_PASSTHRU) {
4817                 cmd->cmd_flags |= CFLAG_FINISHED;
4818                 cv_broadcast(&mpt->m_passthru_cv);
4819                 return;
4820         } else {
4821                 mptsas_remove_cmd(mpt, cmd);
4822         }
4823 
4824         if (cmd->cmd_flags & CFLAG_RETRY) {
4825                 /*
4826                  * The target returned QFULL or busy, do not add tihs
4827                  * pkt to the doneq since the hba will retry
4828                  * this cmd.
4829                  *
4830                  * The pkt has already been resubmitted in
4831                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
4832                  * Remove this cmd_flag here.
4833                  */
4834                 cmd->cmd_flags &= ~CFLAG_RETRY;
4835         } else {
4836                 mptsas_doneq_add(mpt, cmd);
4837         }
4838 }
4839 
4840 static void
4841 mptsas_handle_address_reply(mptsas_t *mpt,
4842     pMpi2ReplyDescriptorsUnion_t reply_desc)
4843 {
4844         pMpi2AddressReplyDescriptor_t   address_reply;
4845         pMPI2DefaultReply_t             reply;
4846         mptsas_fw_diagnostic_buffer_t   *pBuffer;
4847         uint32_t                        reply_addr;
4848         uint16_t                        SMID, iocstatus;
4849         mptsas_slots_t                  *slots = mpt->m_active;
4850         mptsas_cmd_t                    *cmd = NULL;
4851         uint8_t                         function, buffer_type;
4852         m_replyh_arg_t                  *args;
4853         int                             reply_frame_no;
4854 
4855         ASSERT(mutex_owned(&mpt->m_mutex));
4856 
4857         address_reply = (pMpi2AddressReplyDescriptor_t)reply_desc;
4858 
4859         reply_addr = address_reply->ReplyFrameAddress;
4860         SMID = address_reply->SMID;
4861         /*
4862          * If reply frame is not in the proper range we should ignore this
4863          * message and exit the interrupt handler.
4864          */
4865         if ((reply_addr < mpt->m_reply_frame_dma_addr) ||
4866             (reply_addr >= (mpt->m_reply_frame_dma_addr +
4867             (mpt->m_reply_frame_size * mpt->m_max_replies))) ||
4868             ((reply_addr - mpt->m_reply_frame_dma_addr) %
4869             mpt->m_reply_frame_size != 0)) {
4870                 mptsas_log(mpt, CE_WARN, "?Received invalid reply frame "
4871                     "address 0x%x\n", reply_addr);
4872                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4873                 return;
4874         }
4875 
4876         (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
4877             DDI_DMA_SYNC_FORCPU);
4878         reply = (pMPI2DefaultReply_t)(mpt->m_reply_frame + (reply_addr -
4879             mpt->m_reply_frame_dma_addr));
4880         function = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->Function);
4881 
4882         /*
4883          * don't get slot information and command for events since these values
4884          * don't exist
4885          */
4886         if ((function != MPI2_FUNCTION_EVENT_NOTIFICATION) &&
4887             (function != MPI2_FUNCTION_DIAG_BUFFER_POST)) {
4888                 /*
4889                  * This could be a TM reply, which use the last allocated SMID,
4890                  * so allow for that.
4891                  */
4892                 if ((SMID == 0) || (SMID > (slots->m_n_slots + 1))) {
4893                         mptsas_log(mpt, CE_WARN, "?Received invalid SMID of "
4894                             "%d\n", SMID);
4895                         ddi_fm_service_impact(mpt->m_dip,
4896                             DDI_SERVICE_UNAFFECTED);
4897                         return;
4898                 }
4899 
4900                 cmd = slots->m_slot[SMID];
4901 
4902                 /*
4903                  * print warning and return if the slot is empty
4904                  */
4905                 if (cmd == NULL) {
4906                         mptsas_log(mpt, CE_WARN, "?NULL command for address "
4907                             "reply in slot %d", SMID);
4908                         return;
4909                 }
4910                 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
4911                     (cmd->cmd_flags & CFLAG_CONFIG) ||
4912                     (cmd->cmd_flags & CFLAG_FW_DIAG)) {
4913                         cmd->cmd_rfm = reply_addr;
4914                         cmd->cmd_flags |= CFLAG_FINISHED;
4915                         cv_broadcast(&mpt->m_passthru_cv);
4916                         cv_broadcast(&mpt->m_config_cv);
4917                         cv_broadcast(&mpt->m_fw_diag_cv);
4918                         return;
4919                 } else if (!(cmd->cmd_flags & CFLAG_FW_CMD)) {
4920                         mptsas_remove_cmd(mpt, cmd);
4921                 }
4922                 NDBG31(("\t\tmptsas_process_intr: slot=%d", SMID));
4923         }
4924         /*
4925          * Depending on the function, we need to handle
4926          * the reply frame (and cmd) differently.
4927          */
4928         switch (function) {
4929         case MPI2_FUNCTION_SCSI_IO_REQUEST:
4930                 mptsas_check_scsi_io_error(mpt, (pMpi2SCSIIOReply_t)reply, cmd);
4931                 break;
4932         case MPI2_FUNCTION_SCSI_TASK_MGMT:
4933                 cmd->cmd_rfm = reply_addr;
4934                 mptsas_check_task_mgt(mpt, (pMpi2SCSIManagementReply_t)reply,
4935                     cmd);
4936                 break;
4937         case MPI2_FUNCTION_FW_DOWNLOAD:
4938                 cmd->cmd_flags |= CFLAG_FINISHED;
4939                 cv_signal(&mpt->m_fw_cv);
4940                 break;
4941         case MPI2_FUNCTION_EVENT_NOTIFICATION:
4942                 reply_frame_no = (reply_addr - mpt->m_reply_frame_dma_addr) /
4943                     mpt->m_reply_frame_size;
4944                 args = &mpt->m_replyh_args[reply_frame_no];
4945                 args->mpt = (void *)mpt;
4946                 args->rfm = reply_addr;
4947 
4948                 /*
4949                  * Record the event if its type is enabled in
4950                  * this mpt instance by ioctl.
4951                  */
4952                 mptsas_record_event(args);
4953 
4954                 /*
4955                  * Handle time critical events
4956                  * NOT_RESPONDING/ADDED only now
4957                  */
4958                 if (mptsas_handle_event_sync(args) == DDI_SUCCESS) {
4959                         /*
4960                          * Would not return main process,
4961                          * just let taskq resolve ack action
4962                          * and ack would be sent in taskq thread
4963                          */
4964                         NDBG20(("send mptsas_handle_event_sync success"));
4965                 }
4966                 if ((ddi_taskq_dispatch(mpt->m_event_taskq, mptsas_handle_event,
4967                     (void *)args, DDI_NOSLEEP)) != DDI_SUCCESS) {
4968                         mptsas_log(mpt, CE_WARN, "No memory available"
4969                         "for dispatch taskq");
4970                         /*
4971                          * Return the reply frame to the free queue.
4972                          */
4973                         ddi_put32(mpt->m_acc_free_queue_hdl,
4974                             &((uint32_t *)(void *)
4975                             mpt->m_free_queue)[mpt->m_free_index], reply_addr);
4976                         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
4977                             DDI_DMA_SYNC_FORDEV);
4978                         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
4979                                 mpt->m_free_index = 0;
4980                         }
4981 
4982                         ddi_put32(mpt->m_datap,
4983                             &mpt->m_reg->ReplyFreeHostIndex, mpt->m_free_index);
4984                 }
4985                 return;
4986         case MPI2_FUNCTION_DIAG_BUFFER_POST:
4987                 /*
4988                  * If SMID is 0, this implies that the reply is due to a
4989                  * release function with a status that the buffer has been
4990                  * released.  Set the buffer flags accordingly.
4991                  */
4992                 if (SMID == 0) {
4993                         iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
4994                             &reply->IOCStatus);
4995                         buffer_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
4996                             &(((pMpi2DiagBufferPostReply_t)reply)->BufferType));
4997                         if (iocstatus == MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED) {
4998                                 pBuffer =
4999                                     &mpt->m_fw_diag_buffer_list[buffer_type];
5000                                 pBuffer->valid_data = TRUE;
5001                                 pBuffer->owned_by_firmware = FALSE;
5002                                 pBuffer->immediate = FALSE;
5003                         }
5004                 } else {
5005                         /*
5006                          * Normal handling of diag post reply with SMID.
5007                          */
5008                         cmd = slots->m_slot[SMID];
5009 
5010                         /*
5011                          * print warning and return if the slot is empty
5012                          */
5013                         if (cmd == NULL) {
5014                                 mptsas_log(mpt, CE_WARN, "?NULL command for "
5015                                     "address reply in slot %d", SMID);
5016                                 return;
5017                         }
5018                         cmd->cmd_rfm = reply_addr;
5019                         cmd->cmd_flags |= CFLAG_FINISHED;
5020                         cv_broadcast(&mpt->m_fw_diag_cv);
5021                 }
5022                 return;
5023         default:
5024                 mptsas_log(mpt, CE_WARN, "Unknown function 0x%x ", function);
5025                 break;
5026         }
5027 
5028         /*
5029          * Return the reply frame to the free queue.
5030          */
5031         ddi_put32(mpt->m_acc_free_queue_hdl,
5032             &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
5033             reply_addr);
5034         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
5035             DDI_DMA_SYNC_FORDEV);
5036         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
5037                 mpt->m_free_index = 0;
5038         }
5039         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
5040             mpt->m_free_index);
5041 
5042         if (cmd->cmd_flags & CFLAG_FW_CMD)
5043                 return;
5044 
5045         if (cmd->cmd_flags & CFLAG_RETRY) {
5046                 /*
5047                  * The target returned QFULL or busy, do not add tihs
5048                  * pkt to the doneq since the hba will retry
5049                  * this cmd.
5050                  *
5051                  * The pkt has already been resubmitted in
5052                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
5053                  * Remove this cmd_flag here.
5054                  */
5055                 cmd->cmd_flags &= ~CFLAG_RETRY;
5056         } else {
5057                 mptsas_doneq_add(mpt, cmd);
5058         }
5059 }
5060 
5061 static void
5062 mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
5063     mptsas_cmd_t *cmd)
5064 {
5065         uint8_t                 scsi_status, scsi_state;
5066         uint16_t                ioc_status;
5067         uint32_t                xferred, sensecount, responsedata, loginfo = 0;
5068         struct scsi_pkt         *pkt;
5069         struct scsi_arq_status  *arqstat;
5070         struct buf              *bp;
5071         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
5072         uint8_t                 *sensedata = NULL;
5073 
5074         if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
5075             (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
5076                 bp = cmd->cmd_ext_arq_buf;
5077         } else {
5078                 bp = cmd->cmd_arq_buf;
5079         }
5080 
5081         scsi_status = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIStatus);
5082         ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5083         scsi_state = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIState);
5084         xferred = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->TransferCount);
5085         sensecount = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->SenseCount);
5086         responsedata = ddi_get32(mpt->m_acc_reply_frame_hdl,
5087             &reply->ResponseInfo);
5088 
5089         if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
5090                 loginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
5091                     &reply->IOCLogInfo);
5092                 mptsas_log(mpt, CE_NOTE,
5093                     "?Log info 0x%x received for target %d.\n"
5094                     "\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5095                     loginfo, Tgt(cmd), scsi_status, ioc_status,
5096                     scsi_state);
5097         }
5098 
5099         NDBG31(("\t\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5100             scsi_status, ioc_status, scsi_state));
5101 
5102         pkt = CMD2PKT(cmd);
5103         *(pkt->pkt_scbp) = scsi_status;
5104 
5105         if (loginfo == 0x31170000) {
5106                 /*
5107                  * if loginfo PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY
5108                  * 0x31170000 comes, that means the device missing delay
5109                  * is in progressing, the command need retry later.
5110                  */
5111                 *(pkt->pkt_scbp) = STATUS_BUSY;
5112                 return;
5113         }
5114 
5115         if ((scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) &&
5116             ((ioc_status & MPI2_IOCSTATUS_MASK) ==
5117             MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE)) {
5118                 pkt->pkt_reason = CMD_INCOMPLETE;
5119                 pkt->pkt_state |= STATE_GOT_BUS;
5120                 mutex_enter(&ptgt->m_tgt_intr_mutex);
5121                 if (ptgt->m_reset_delay == 0) {
5122                         mptsas_set_throttle(mpt, ptgt,
5123                             DRAIN_THROTTLE);
5124                 }
5125                 mutex_exit(&ptgt->m_tgt_intr_mutex);
5126                 return;
5127         }
5128 
5129         if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
5130                 responsedata &= 0x000000FF;
5131                 if (responsedata & MPTSAS_SCSI_RESPONSE_CODE_TLR_OFF) {
5132                         mptsas_log(mpt, CE_NOTE, "Do not support the TLR\n");
5133                         pkt->pkt_reason = CMD_TLR_OFF;
5134                         return;
5135                 }
5136         }
5137 
5138 
5139         switch (scsi_status) {
5140         case MPI2_SCSI_STATUS_CHECK_CONDITION:
5141                 pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5142                 arqstat = (void*)(pkt->pkt_scbp);
5143                 arqstat->sts_rqpkt_status = *((struct scsi_status *)
5144                     (pkt->pkt_scbp));
5145                 pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
5146                     STATE_SENT_CMD | STATE_GOT_STATUS | STATE_ARQ_DONE);
5147                 if (cmd->cmd_flags & CFLAG_XARQ) {
5148                         pkt->pkt_state |= STATE_XARQ_DONE;
5149                 }
5150                 if (pkt->pkt_resid != cmd->cmd_dmacount) {
5151                         pkt->pkt_state |= STATE_XFERRED_DATA;
5152                 }
5153                 arqstat->sts_rqpkt_reason = pkt->pkt_reason;
5154                 arqstat->sts_rqpkt_state  = pkt->pkt_state;
5155                 arqstat->sts_rqpkt_state |= STATE_XFERRED_DATA;
5156                 arqstat->sts_rqpkt_statistics = pkt->pkt_statistics;
5157                 sensedata = (uint8_t *)&arqstat->sts_sensedata;
5158 
5159                 bcopy((uchar_t *)bp->b_un.b_addr, sensedata,
5160                     ((cmd->cmd_rqslen >= sensecount) ? sensecount :
5161                     cmd->cmd_rqslen));
5162                 arqstat->sts_rqpkt_resid = (cmd->cmd_rqslen - sensecount);
5163                 cmd->cmd_flags |= CFLAG_CMDARQ;
5164                 /*
5165                  * Set proper status for pkt if autosense was valid
5166                  */
5167                 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
5168                         struct scsi_status zero_status = { 0 };
5169                         arqstat->sts_rqpkt_status = zero_status;
5170                 }
5171 
5172                 /*
5173                  * ASC=0x47 is parity error
5174                  * ASC=0x48 is initiator detected error received
5175                  */
5176                 if ((scsi_sense_key(sensedata) == KEY_ABORTED_COMMAND) &&
5177                     ((scsi_sense_asc(sensedata) == 0x47) ||
5178                     (scsi_sense_asc(sensedata) == 0x48))) {
5179                         mptsas_log(mpt, CE_NOTE, "Aborted_command!");
5180                 }
5181 
5182                 /*
5183                  * ASC/ASCQ=0x3F/0x0E means report_luns data changed
5184                  * ASC/ASCQ=0x25/0x00 means invalid lun
5185                  */
5186                 if (((scsi_sense_key(sensedata) == KEY_UNIT_ATTENTION) &&
5187                     (scsi_sense_asc(sensedata) == 0x3F) &&
5188                     (scsi_sense_ascq(sensedata) == 0x0E)) ||
5189                     ((scsi_sense_key(sensedata) == KEY_ILLEGAL_REQUEST) &&
5190                     (scsi_sense_asc(sensedata) == 0x25) &&
5191                     (scsi_sense_ascq(sensedata) == 0x00))) {
5192                         mptsas_topo_change_list_t *topo_node = NULL;
5193 
5194                         topo_node = kmem_zalloc(
5195                             sizeof (mptsas_topo_change_list_t),
5196                             KM_NOSLEEP);
5197                         if (topo_node == NULL) {
5198                                 mptsas_log(mpt, CE_NOTE, "No memory"
5199                                     "resource for handle SAS dynamic"
5200                                     "reconfigure.\n");
5201                                 break;
5202                         }
5203                         topo_node->mpt = mpt;
5204                         topo_node->event = MPTSAS_DR_EVENT_RECONFIG_TARGET;
5205                         topo_node->un.phymask = ptgt->m_phymask;
5206                         topo_node->devhdl = ptgt->m_devhdl;
5207                         topo_node->object = (void *)ptgt;
5208                         topo_node->flags = MPTSAS_TOPO_FLAG_LUN_ASSOCIATED;
5209 
5210                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
5211                             mptsas_handle_dr,
5212                             (void *)topo_node,
5213                             DDI_NOSLEEP)) != DDI_SUCCESS) {
5214                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq"
5215                                     "for handle SAS dynamic reconfigure"
5216                                     "failed. \n");
5217                         }
5218                 }
5219                 break;
5220         case MPI2_SCSI_STATUS_GOOD:
5221                 switch (ioc_status & MPI2_IOCSTATUS_MASK) {
5222                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
5223                         pkt->pkt_reason = CMD_DEV_GONE;
5224                         pkt->pkt_state |= STATE_GOT_BUS;
5225                         mutex_enter(&ptgt->m_tgt_intr_mutex);
5226                         if (ptgt->m_reset_delay == 0) {
5227                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5228                         }
5229                         mutex_exit(&ptgt->m_tgt_intr_mutex);
5230                         NDBG31(("lost disk for target%d, command:%x",
5231                             Tgt(cmd), pkt->pkt_cdbp[0]));
5232                         break;
5233                 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
5234                         NDBG31(("data overrun: xferred=%d", xferred));
5235                         NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5236                         pkt->pkt_reason = CMD_DATA_OVR;
5237                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5238                             | STATE_SENT_CMD | STATE_GOT_STATUS
5239                             | STATE_XFERRED_DATA);
5240                         pkt->pkt_resid = 0;
5241                         break;
5242                 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
5243                 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
5244                         NDBG31(("data underrun: xferred=%d", xferred));
5245                         NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5246                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5247                             | STATE_SENT_CMD | STATE_GOT_STATUS);
5248                         pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5249                         if (pkt->pkt_resid != cmd->cmd_dmacount) {
5250                                 pkt->pkt_state |= STATE_XFERRED_DATA;
5251                         }
5252                         break;
5253                 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
5254                         mptsas_set_pkt_reason(mpt,
5255                             cmd, CMD_RESET, STAT_BUS_RESET);
5256                         break;
5257                 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
5258                 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
5259                         mptsas_set_pkt_reason(mpt,
5260                             cmd, CMD_RESET, STAT_DEV_RESET);
5261                         break;
5262                 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
5263                 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
5264                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET);
5265                         mptsas_set_pkt_reason(mpt,
5266                             cmd, CMD_TERMINATED, STAT_TERMINATED);
5267                         break;
5268                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
5269                 case MPI2_IOCSTATUS_BUSY:
5270                         /*
5271                          * set throttles to drain
5272                          */
5273                         ptgt = (mptsas_target_t *)mptsas_hash_traverse(
5274                             &mpt->m_active->m_tgttbl, MPTSAS_HASH_FIRST);
5275                         while (ptgt != NULL) {
5276                                 mutex_enter(&ptgt->m_tgt_intr_mutex);
5277                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5278                                 mutex_exit(&ptgt->m_tgt_intr_mutex);
5279 
5280                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
5281                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
5282                         }
5283 
5284                         /*
5285                          * retry command
5286                          */
5287                         cmd->cmd_flags |= CFLAG_RETRY;
5288                         cmd->cmd_pkt_flags |= FLAG_HEAD;
5289 
5290                         mutex_exit(&mpt->m_mutex);
5291                         (void) mptsas_accept_pkt(mpt, cmd);
5292                         mutex_enter(&mpt->m_mutex);
5293                         break;
5294                 default:
5295                         mptsas_log(mpt, CE_WARN,
5296                             "unknown ioc_status = %x\n", ioc_status);
5297                         mptsas_log(mpt, CE_CONT, "scsi_state = %x, transfer "
5298                             "count = %x, scsi_status = %x", scsi_state,
5299                             xferred, scsi_status);
5300                         break;
5301                 }
5302                 break;
5303         case MPI2_SCSI_STATUS_TASK_SET_FULL:
5304                 mptsas_handle_qfull(mpt, cmd);
5305                 break;
5306         case MPI2_SCSI_STATUS_BUSY:
5307                 NDBG31(("scsi_status busy received"));
5308                 break;
5309         case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
5310                 NDBG31(("scsi_status reservation conflict received"));
5311                 break;
5312         default:
5313                 mptsas_log(mpt, CE_WARN, "scsi_status=%x, ioc_status=%x\n",
5314                     scsi_status, ioc_status);
5315                 mptsas_log(mpt, CE_WARN,
5316                     "mptsas_process_intr: invalid scsi status\n");
5317                 break;
5318         }
5319 }
5320 
5321 static void
5322 mptsas_check_task_mgt(mptsas_t *mpt, pMpi2SCSIManagementReply_t reply,
5323         mptsas_cmd_t *cmd)
5324 {
5325         uint8_t         task_type;
5326         uint16_t        ioc_status;
5327         uint32_t        log_info;
5328         uint16_t        dev_handle;
5329         struct scsi_pkt *pkt = CMD2PKT(cmd);
5330 
5331         task_type = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->TaskType);
5332         ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5333         log_info = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->IOCLogInfo);
5334         dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->DevHandle);
5335 
5336         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5337                 mptsas_log(mpt, CE_WARN, "mptsas_check_task_mgt: Task 0x%x "
5338                     "failed. IOCStatus=0x%x IOCLogInfo=0x%x target=%d\n",
5339                     task_type, ioc_status, log_info, dev_handle);
5340                 pkt->pkt_reason = CMD_INCOMPLETE;
5341                 return;
5342         }
5343 
5344         switch (task_type) {
5345         case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
5346         case MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
5347         case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
5348         case MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA:
5349         case MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET:
5350         case MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION:
5351                 break;
5352         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
5353         case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
5354         case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
5355                 /*
5356                  * Check for invalid DevHandle of 0 in case application
5357                  * sends bad command.  DevHandle of 0 could cause problems.
5358                  */
5359                 if (dev_handle == 0) {
5360                         mptsas_log(mpt, CE_WARN, "!Can't flush target with"
5361                             " DevHandle of 0.");
5362                 } else {
5363                         mptsas_flush_target(mpt, dev_handle, Lun(cmd),
5364                             task_type);
5365                 }
5366                 break;
5367         default:
5368                 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
5369                     task_type);
5370                 mptsas_log(mpt, CE_WARN, "ioc status = %x", ioc_status);
5371                 break;
5372         }
5373 }
5374 
5375 static void
5376 mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg)
5377 {
5378         mptsas_t                        *mpt = arg->mpt;
5379         uint64_t                        t = arg->t;
5380         mptsas_cmd_t                    *cmd;
5381         struct scsi_pkt                 *pkt;
5382         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
5383 
5384         mutex_enter(&item->mutex);
5385         while (item->flag & MPTSAS_DONEQ_THREAD_ACTIVE) {
5386                 if (!item->doneq) {
5387                         cv_wait(&item->cv, &item->mutex);
5388                 }
5389                 pkt = NULL;
5390                 if ((cmd = mptsas_doneq_thread_rm(mpt, t)) != NULL) {
5391                         cmd->cmd_flags |= CFLAG_COMPLETED;
5392                         pkt = CMD2PKT(cmd);
5393                 }
5394                 mutex_exit(&item->mutex);
5395                 if (pkt) {
5396                         mptsas_pkt_comp(pkt, cmd);
5397                 }
5398                 mutex_enter(&item->mutex);
5399         }
5400         mutex_exit(&item->mutex);
5401         mutex_enter(&mpt->m_doneq_mutex);
5402         mpt->m_doneq_thread_n--;
5403         cv_broadcast(&mpt->m_doneq_thread_cv);
5404         mutex_exit(&mpt->m_doneq_mutex);
5405 }
5406 
5407 /*
5408  * mpt interrupt handler.
5409  */
5410 static uint_t
5411 mptsas_intr(caddr_t arg1, caddr_t arg2)
5412 {
5413         mptsas_t                        *mpt = (void *)arg1;
5414         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
5415         uchar_t                         did_reply = FALSE;
5416         int                             i = 0, j;
5417         uint8_t                         reply_type;
5418         uint16_t                        SMID;
5419 
5420         NDBG1(("mptsas_intr: arg1 0x%p arg2 0x%p", (void *)arg1, (void *)arg2));
5421 
5422         /*
5423          * 1.
5424          * To avoid using m_mutex in the ISR(ISR referes not only mptsas_intr,
5425          * but all of the recursive called functions in it. the same below),
5426          * separate mutexs are introduced to protect the elements shown in ISR.
5427          * 3 type of mutex are involved here:
5428          *      a)per instance mutex m_intr_mutex.
5429          *      b)per target mutex m_tgt_intr_mutex.
5430          *      c)mutex that protect the free slot.
5431          *
5432          * a)per instance mutex m_intr_mutex:
5433          * used to protect m_options, m_power, m_waitq, etc that would be
5434          * checked/modified in ISR; protect the getting and setting the reply
5435          * descriptor index; protect the m_slots[];
5436          *
5437          * b)per target mutex m_tgt_intr_mutex:
5438          * used to protect per target element which has relationship to ISR.
5439          * contention for the new per target mutex is just as high as it in
5440          * sd(7d) driver.
5441          *
5442          * c)mutexs that protect the free slots:
5443          * those mutexs are introduced to minimize the mutex contentions
5444          * between the IO request threads where free slots are allocated
5445          * for sending cmds and ISR where slots holding outstanding cmds
5446          * are returned to the free pool.
5447          * the idea is like this:
5448          * 1) Partition all of the free slot into NCPU groups. For example,
5449          * In system where we have 15 slots, and 4 CPU, then slot s1,s5,s9,s13
5450          * are marked belonging to CPU1, s2,s6,s10,s14 to CPU2, s3,s7,s11,s15
5451          * to CPU3, and s4,s8,s12 to CPU4.
5452          * 2) In each of the group, an alloc/release queue pair is created,
5453          * and both the allocq and the releaseq have a dedicated mutex.
5454          * 3) When init, all of the slots in a CPU group are inserted into the
5455          * allocq of its CPU's pair.
5456          * 4) When doing IO,
5457          * mptsas_scsi_start()
5458          * {
5459          *      cpuid = the cpu NO of the cpu where this thread is running on
5460          * retry:
5461          *      mutex_enter(&allocq[cpuid]);
5462          *      if (get free slot = success) {
5463          *              remove the slot from the allocq
5464          *              mutex_exit(&allocq[cpuid]);
5465          *              return(success);
5466          *      } else { // exchange allocq and releaseq and try again
5467          *              mutex_enter(&releq[cpuid]);
5468          *              exchange the allocq and releaseq of this pair;
5469          *              mutex_exit(&releq[cpuid]);
5470          *              if (try to get free slot again = success) {
5471          *                      remove the slot from the allocq
5472          *                      mutex_exit(&allocq[cpuid]);
5473          *                      return(success);
5474          *              } else {
5475          *                      MOD(cpuid)++;
5476          *                      goto retry;
5477          *                      if (all CPU groups tried)
5478          *                              mutex_exit(&allocq[cpuid]);
5479          *                              return(failure);
5480          *              }
5481          *      }
5482          * }
5483          * ISR()
5484          * {
5485          *              cpuid = the CPU group id where the slot sending the
5486          *              cmd belongs;
5487          *              mutex_enter(&releq[cpuid]);
5488          *              remove the slot from the releaseq
5489          *              mutex_exit(&releq[cpuid]);
5490          * }
5491          * This way, only when the queue pair doing exchange have mutex
5492          * contentions.
5493          *
5494          * For mutex m_intr_mutex and m_tgt_intr_mutex, there are 2 scenarios:
5495          *
5496          * a)If the elements are only checked but not modified in the ISR, then
5497          * only the places where those elements are modifed(outside of ISR)
5498          * need to be protected by the new introduced mutex.
5499          * For example, data A is only read/checked in ISR, then we need do
5500          * like this:
5501          * In ISR:
5502          * {
5503          *      mutex_enter(&new_mutex);
5504          *      read(A);
5505          *      mutex_exit(&new_mutex);
5506          *      //the new_mutex here is either the m_tgt_intr_mutex or
5507          *      //the m_intr_mutex.
5508          * }
5509          * In non-ISR
5510          * {
5511          *      mutex_enter(&m_mutex); //the stock driver already did this
5512          *      mutex_enter(&new_mutex);
5513          *      write(A);
5514          *      mutex_exit(&new_mutex);
5515          *      mutex_exit(&m_mutex); //the stock driver already did this
5516          *
5517          *      read(A);
5518          *      // read(A) in non-ISR is not required to be protected by new
5519          *      // mutex since 'A' has already been protected by m_mutex
5520          *      // outside of the ISR
5521          * }
5522          *
5523          * Those fields in mptsas_target_t/ptgt which are only read in ISR
5524          * fall into this catergory. So they, together with the fields which
5525          * are never read in ISR, are not necessary to be protected by
5526          * m_tgt_intr_mutex, don't bother.
5527          * checking of m_waitq also falls into this catergory. so all of the
5528          * place outside of ISR where the m_waitq is modified, such as in
5529          * mptsas_waitq_add(), mptsas_waitq_delete(), mptsas_waitq_rm(),
5530          * m_intr_mutex should be used.
5531          *
5532          * b)If the elements are modified in the ISR, then each place where
5533          * those elements are referred(outside of ISR) need to be protected
5534          * by the new introduced mutex. Of course, if those elements only
5535          * appear in the non-key code path, that is, they don't affect
5536          * performance, then the m_mutex can still be used as before.
5537          * For example, data B is modified in key code path in ISR, and data C
5538          * is modified in non-key code path in ISR, then we can do like this:
5539          * In ISR:
5540          * {
5541          *      mutex_enter(&new_mutex);
5542          *      wirte(B);
5543          *      mutex_exit(&new_mutex);
5544          *      if (seldom happen) {
5545          *              mutex_enter(&m_mutex);
5546          *              write(C);
5547          *              mutex_exit(&m_mutex);
5548          *      }
5549          *      //the new_mutex here is either the m_tgt_intr_mutex or
5550          *      //the m_intr_mutex.
5551          * }
5552          * In non-ISR
5553          * {
5554          *      mutex_enter(&new_mutex);
5555          *      write(B);
5556          *      mutex_exit(&new_mutex);
5557          *
5558          *      mutex_enter(&new_mutex);
5559          *      read(B);
5560          *      mutex_exit(&new_mutex);
5561          *      // both write(B) and read(B) in non-ISR is required to be
5562          *      // protected by new mutex outside of the ISR
5563          *
5564          *      mutex_enter(&m_mutex); //the stock driver already did this
5565          *      read(C);
5566          *      write(C);
5567          *      mutex_exit(&m_mutex); //the stock driver already did this
5568          *      // both write(C) and read(C) in non-ISR have been already
5569          *      // been protected by m_mutex outside of the ISR
5570          * }
5571          *
5572          * For example, ptgt->m_t_ncmds fall into 'B' of this catergory, and
5573          * elements shown in address reply, restart_hba, passthrough, IOC
5574          * fall into 'C' of  this catergory.
5575          *
5576          * In any case where mutexs are nested, make sure in the following
5577          * order:
5578          *      m_mutex -> m_intr_mutex -> m_tgt_intr_mutex
5579          *      m_intr_mutex -> m_tgt_intr_mutex
5580          *      m_mutex -> m_intr_mutex
5581          *      m_mutex -> m_tgt_intr_mutex
5582          *
5583          * 2.
5584          * Make sure at any time, getting the ReplyDescriptor by m_post_index
5585          * and setting m_post_index to the ReplyDescriptorIndex register are
5586          * atomic. Since m_mutex is not used for this purpose in ISR, the new
5587          * mutex m_intr_mutex must play this role. So mptsas_poll(), where this
5588          * kind of getting/setting is also performed, must use m_intr_mutex.
5589          * Note, since context reply in ISR/process_intr is the only code path
5590          * which affect performance, a fast path is introduced to only handle
5591          * the read/write IO having context reply. For other IOs such as
5592          * passthrough and IOC with context reply and all address reply, we
5593          * use the as-is process_intr() to handle them. In order to keep the
5594          * same semantics in process_intr(), make sure any new mutex is not held
5595          * before enterring it.
5596          */
5597 
5598         mutex_enter(&mpt->m_intr_mutex);
5599 
5600         /*
5601          * If interrupts are shared by two channels then check whether this
5602          * interrupt is genuinely for this channel by making sure first the
5603          * chip is in high power state.
5604          */
5605         if ((mpt->m_options & MPTSAS_OPT_PM) &&
5606             (mpt->m_power_level != PM_LEVEL_D0)) {
5607                 mutex_exit(&mpt->m_intr_mutex);
5608                 return (DDI_INTR_UNCLAIMED);
5609         }
5610 
5611         /*
5612          * If polling, interrupt was triggered by some shared interrupt because
5613          * IOC interrupts are disabled during polling, so polling routine will
5614          * handle any replies.  Considering this, if polling is happening,
5615          * return with interrupt unclaimed.
5616          */
5617         if (mpt->m_polled_intr) {
5618                 mutex_exit(&mpt->m_intr_mutex);
5619                 mptsas_log(mpt, CE_WARN, "mpt_sas: Unclaimed interrupt");
5620                 return (DDI_INTR_UNCLAIMED);
5621         }
5622 
5623         /*
5624          * Read the istat register.
5625          */
5626         if ((INTPENDING(mpt)) != 0) {
5627                 /*
5628                  * read fifo until empty.
5629                  */
5630 #ifndef __lock_lint
5631                 _NOTE(CONSTCOND)
5632 #endif
5633                 while (TRUE) {
5634                         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5635                             DDI_DMA_SYNC_FORCPU);
5636                         reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
5637                             MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
5638 
5639                         if (ddi_get32(mpt->m_acc_post_queue_hdl,
5640                             &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
5641                             ddi_get32(mpt->m_acc_post_queue_hdl,
5642                             &reply_desc_union->Words.High) == 0xFFFFFFFF) {
5643                                 break;
5644                         }
5645 
5646                         /*
5647                          * The reply is valid, process it according to its
5648                          * type.  Also, set a flag for updating the reply index
5649                          * after they've all been processed.
5650                          */
5651                         did_reply = TRUE;
5652 
5653                         reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
5654                             &reply_desc_union->Default.ReplyFlags);
5655                         reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
5656                         mpt->m_reply[i].Default.ReplyFlags = reply_type;
5657                         if (reply_type ==
5658                             MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
5659                                 SMID = ddi_get16(mpt->m_acc_post_queue_hdl,
5660                                     &reply_desc_union->SCSIIOSuccess.SMID);
5661                                 if (mptsas_handle_io_fastpath(mpt, SMID) !=
5662                                     TRUE) {
5663                                         mpt->m_reply[i].SCSIIOSuccess.SMID =
5664                                             SMID;
5665                                         i++;
5666                                 }
5667                         } else if (reply_type ==
5668                             MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
5669                                 mpt->m_reply[i].AddressReply.ReplyFrameAddress =
5670                                     ddi_get32(mpt->m_acc_post_queue_hdl,
5671                                     &reply_desc_union->AddressReply.
5672                                     ReplyFrameAddress);
5673                                 mpt->m_reply[i].AddressReply.SMID =
5674                                     ddi_get16(mpt->m_acc_post_queue_hdl,
5675                                     &reply_desc_union->AddressReply.SMID);
5676                                 i++;
5677                         }
5678                         /*
5679                          * Clear the reply descriptor for re-use and increment
5680                          * index.
5681                          */
5682                         ddi_put64(mpt->m_acc_post_queue_hdl,
5683                             &((uint64_t *)(void *)mpt->m_post_queue)
5684                             [mpt->m_post_index], 0xFFFFFFFFFFFFFFFF);
5685                         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5686                             DDI_DMA_SYNC_FORDEV);
5687 
5688                         /*
5689                          * Increment post index and roll over if needed.
5690                          */
5691                         if (++mpt->m_post_index == mpt->m_post_queue_depth) {
5692                                 mpt->m_post_index = 0;
5693                         }
5694                         if (i >= MPI_ADDRESS_COALSCE_MAX)
5695                                 break;
5696                 }
5697 
5698                 /*
5699                  * Update the global reply index if at least one reply was
5700                  * processed.
5701                  */
5702                 if (did_reply) {
5703                         ddi_put32(mpt->m_datap,
5704                             &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
5705 
5706                         /*
5707                          * For fma, only check the PIO is required and enough
5708                          * here. Those cases where fastpath is not hit, the
5709                          * mptsas_fma_check() check all of the types of
5710                          * fma. That is not necessary and sometimes not
5711                          * correct. fma check should only be done after
5712                          * the PIO and/or dma is performed.
5713                          */
5714                         if ((mptsas_check_acc_handle(mpt->m_datap) !=
5715                             DDI_SUCCESS)) {
5716                                 ddi_fm_service_impact(mpt->m_dip,
5717                                     DDI_SERVICE_UNAFFECTED);
5718                         }
5719 
5720                 }
5721         } else {
5722                 mutex_exit(&mpt->m_intr_mutex);
5723                 return (DDI_INTR_UNCLAIMED);
5724         }
5725         NDBG1(("mptsas_intr complete"));
5726         mutex_exit(&mpt->m_intr_mutex);
5727 
5728         /*
5729          * Since most of the cmds(read and write IO with success return.)
5730          * have already been processed in fast path in which the m_mutex
5731          * is not held, handling here the address reply and other context reply
5732          * such as passthrough and IOC cmd with m_mutex held should be a big
5733          * issue for performance.
5734          * If holding m_mutex to process these cmds was still an obvious issue,
5735          * we can process them in a taskq.
5736          */
5737         for (j = 0; j < i; j++) {
5738                 mutex_enter(&mpt->m_mutex);
5739                 mptsas_process_intr(mpt, &mpt->m_reply[j]);
5740                 mutex_exit(&mpt->m_mutex);
5741         }
5742 
5743         /*
5744          * If no helper threads are created, process the doneq in ISR. If
5745          * helpers are created, use the doneq length as a metric to measure the
5746          * load on the interrupt CPU. If it is long enough, which indicates the
5747          * load is heavy, then we deliver the IO completions to the helpers.
5748          * This measurement has some limitations, although it is simple and
5749          * straightforward and works well for most of the cases at present.
5750          */
5751         if (!mpt->m_doneq_thread_n) {
5752                 mptsas_doneq_empty(mpt);
5753         } else {
5754                 int helper = 1;
5755                 mutex_enter(&mpt->m_intr_mutex);
5756                 if (mpt->m_doneq_len <= mpt->m_doneq_length_threshold)
5757                         helper = 0;
5758                 mutex_exit(&mpt->m_intr_mutex);
5759                 if (helper) {
5760                         mptsas_deliver_doneq_thread(mpt);
5761                 } else {
5762                         mptsas_doneq_empty(mpt);
5763                 }
5764         }
5765 
5766         /*
5767          * If there are queued cmd, start them now.
5768          */
5769         mutex_enter(&mpt->m_intr_mutex);
5770         if (mpt->m_waitq != NULL) {
5771                 mutex_exit(&mpt->m_intr_mutex);
5772                 mutex_enter(&mpt->m_mutex);
5773                 mptsas_restart_hba(mpt);
5774                 mutex_exit(&mpt->m_mutex);
5775                 return (DDI_INTR_CLAIMED);
5776         }
5777         mutex_exit(&mpt->m_intr_mutex);
5778         return (DDI_INTR_CLAIMED);
5779 }
5780 
5781 /*
5782  * In ISR, the successfully completed read and write IO are processed in a
5783  * fast path. This function is only used to handle non-fastpath IO, including
5784  * all of the address reply, and the context reply for IOC cmd, passthrough,
5785  * etc.
5786  * This function is also used to process polled cmd.
5787  */
5788 static void
5789 mptsas_process_intr(mptsas_t *mpt,
5790     pMpi2ReplyDescriptorsUnion_t reply_desc_union)
5791 {
5792         uint8_t reply_type;
5793 
5794         /*
5795          * The reply is valid, process it according to its
5796          * type.  Also, set a flag for updated the reply index
5797          * after they've all been processed.
5798          */
5799         reply_type = reply_desc_union->Default.ReplyFlags;
5800         if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
5801                 mptsas_handle_scsi_io_success(mpt, reply_desc_union);
5802         } else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
5803                 mptsas_handle_address_reply(mpt, reply_desc_union);
5804         } else {
5805                 mptsas_log(mpt, CE_WARN, "?Bad reply type %x", reply_type);
5806                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5807         }
5808 }
5809 
5810 /*
5811  * handle qfull condition
5812  */
5813 static void
5814 mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd)
5815 {
5816         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
5817 
5818         if ((++cmd->cmd_qfull_retries > ptgt->m_qfull_retries) ||
5819             (ptgt->m_qfull_retries == 0)) {
5820                 /*
5821                  * We have exhausted the retries on QFULL, or,
5822                  * the target driver has indicated that it
5823                  * wants to handle QFULL itself by setting
5824                  * qfull-retries capability to 0. In either case
5825                  * we want the target driver's QFULL handling
5826                  * to kick in. We do this by having pkt_reason
5827                  * as CMD_CMPLT and pkt_scbp as STATUS_QFULL.
5828                  */
5829                 mutex_enter(&ptgt->m_tgt_intr_mutex);
5830                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5831                 mutex_exit(&ptgt->m_tgt_intr_mutex);
5832         } else {
5833                 mutex_enter(&ptgt->m_tgt_intr_mutex);
5834                 if (ptgt->m_reset_delay == 0) {
5835                         ptgt->m_t_throttle =
5836                             max((ptgt->m_t_ncmds - 2), 0);
5837                 }
5838                 mutex_exit(&ptgt->m_tgt_intr_mutex);
5839 
5840                 cmd->cmd_pkt_flags |= FLAG_HEAD;
5841                 cmd->cmd_flags &= ~(CFLAG_TRANFLAG);
5842                 cmd->cmd_flags |= CFLAG_RETRY;
5843 
5844                 mutex_exit(&mpt->m_mutex);
5845                 (void) mptsas_accept_pkt(mpt, cmd);
5846                 mutex_enter(&mpt->m_mutex);
5847 
5848                 /*
5849                  * when target gives queue full status with no commands
5850                  * outstanding (m_t_ncmds == 0), throttle is set to 0
5851                  * (HOLD_THROTTLE), and the queue full handling start
5852                  * (see psarc/1994/313); if there are commands outstanding,
5853                  * throttle is set to (m_t_ncmds - 2)
5854                  */
5855                 mutex_enter(&ptgt->m_tgt_intr_mutex);
5856                 if (ptgt->m_t_throttle == HOLD_THROTTLE) {
5857                         /*
5858                          * By setting throttle to QFULL_THROTTLE, we
5859                          * avoid submitting new commands and in
5860                          * mptsas_restart_cmd find out slots which need
5861                          * their throttles to be cleared.
5862                          */
5863                         mptsas_set_throttle(mpt, ptgt, QFULL_THROTTLE);
5864                         if (mpt->m_restart_cmd_timeid == 0) {
5865                                 mpt->m_restart_cmd_timeid =
5866                                     timeout(mptsas_restart_cmd, mpt,
5867                                     ptgt->m_qfull_retry_interval);
5868                         }
5869                 }
5870                 mutex_exit(&ptgt->m_tgt_intr_mutex);
5871         }
5872 }
5873 
5874 mptsas_phymask_t
5875 mptsas_physport_to_phymask(mptsas_t *mpt, uint8_t physport)
5876 {
5877         mptsas_phymask_t        phy_mask = 0;
5878         uint8_t                 i = 0;
5879 
5880         NDBG20(("mptsas%d physport_to_phymask enter", mpt->m_instance));
5881 
5882         ASSERT(mutex_owned(&mpt->m_mutex));
5883 
5884         /*
5885          * If physport is 0xFF, this is a RAID volume.  Use phymask of 0.
5886          */
5887         if (physport == 0xFF) {
5888                 return (0);
5889         }
5890 
5891         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
5892                 if (mpt->m_phy_info[i].attached_devhdl &&
5893                     (mpt->m_phy_info[i].phy_mask != 0) &&
5894                     (mpt->m_phy_info[i].port_num == physport)) {
5895                         phy_mask = mpt->m_phy_info[i].phy_mask;
5896                         break;
5897                 }
5898         }
5899         NDBG20(("mptsas%d physport_to_phymask:physport :%x phymask :%x, ",
5900             mpt->m_instance, physport, phy_mask));
5901         return (phy_mask);
5902 }
5903 
5904 /*
5905  * mpt free device handle after device gone, by use of passthrough
5906  */
5907 static int
5908 mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl)
5909 {
5910         Mpi2SasIoUnitControlRequest_t   req;
5911         Mpi2SasIoUnitControlReply_t     rep;
5912         int                             ret;
5913 
5914         ASSERT(mutex_owned(&mpt->m_mutex));
5915 
5916         /*
5917          * Need to compose a SAS IO Unit Control request message
5918          * and call mptsas_do_passthru() function
5919          */
5920         bzero(&req, sizeof (req));
5921         bzero(&rep, sizeof (rep));
5922 
5923         req.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
5924         req.Operation = MPI2_SAS_OP_REMOVE_DEVICE;
5925         req.DevHandle = LE_16(devhdl);
5926 
5927         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
5928             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
5929         if (ret != 0) {
5930                 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
5931                     "Control error %d", ret);
5932                 return (DDI_FAILURE);
5933         }
5934 
5935         /* do passthrough success, check the ioc status */
5936         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
5937                 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
5938                     "Control IOCStatus %d", LE_16(rep.IOCStatus));
5939                 return (DDI_FAILURE);
5940         }
5941 
5942         return (DDI_SUCCESS);
5943 }
5944 
5945 static void
5946 mptsas_update_phymask(mptsas_t *mpt)
5947 {
5948         mptsas_phymask_t mask = 0, phy_mask;
5949         char            *phy_mask_name;
5950         uint8_t         current_port;
5951         int             i, j;
5952 
5953         NDBG20(("mptsas%d update phymask ", mpt->m_instance));
5954 
5955         ASSERT(mutex_owned(&mpt->m_mutex));
5956 
5957         (void) mptsas_get_sas_io_unit_page(mpt);
5958 
5959         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
5960 
5961         for (i = 0; i < mpt->m_num_phys; i++) {
5962                 phy_mask = 0x00;
5963 
5964                 if (mpt->m_phy_info[i].attached_devhdl == 0)
5965                         continue;
5966 
5967                 bzero(phy_mask_name, sizeof (phy_mask_name));
5968 
5969                 current_port = mpt->m_phy_info[i].port_num;
5970 
5971                 if ((mask & (1 << i)) != 0)
5972                         continue;
5973 
5974                 for (j = 0; j < mpt->m_num_phys; j++) {
5975                         if (mpt->m_phy_info[j].attached_devhdl &&
5976                             (mpt->m_phy_info[j].port_num == current_port)) {
5977                                 phy_mask |= (1 << j);
5978                         }
5979                 }
5980                 mask = mask | phy_mask;
5981 
5982                 for (j = 0; j < mpt->m_num_phys; j++) {
5983                         if ((phy_mask >> j) & 0x01) {
5984                                 mpt->m_phy_info[j].phy_mask = phy_mask;
5985                         }
5986                 }
5987 
5988                 (void) sprintf(phy_mask_name, "%x", phy_mask);
5989 
5990                 mutex_exit(&mpt->m_mutex);
5991                 /*
5992                  * register a iport, if the port has already been existed
5993                  * SCSA will do nothing and just return.
5994                  */
5995                 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
5996                 mutex_enter(&mpt->m_mutex);
5997         }
5998         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
5999         NDBG20(("mptsas%d update phymask return", mpt->m_instance));
6000 }
6001 
6002 /*
6003  * mptsas_handle_dr is a task handler for DR, the DR action includes:
6004  * 1. Directly attched Device Added/Removed.
6005  * 2. Expander Device Added/Removed.
6006  * 3. Indirectly Attached Device Added/Expander.
6007  * 4. LUNs of a existing device status change.
6008  * 5. RAID volume created/deleted.
6009  * 6. Member of RAID volume is released because of RAID deletion.
6010  * 7. Physical disks are removed because of RAID creation.
6011  */
6012 static void
6013 mptsas_handle_dr(void *args) {
6014         mptsas_topo_change_list_t       *topo_node = NULL;
6015         mptsas_topo_change_list_t       *save_node = NULL;
6016         mptsas_t                        *mpt;
6017         dev_info_t                      *parent = NULL;
6018         mptsas_phymask_t                phymask = 0;
6019         char                            *phy_mask_name;
6020         uint8_t                         flags = 0, physport = 0xff;
6021         uint8_t                         port_update = 0;
6022         uint_t                          event;
6023 
6024         topo_node = (mptsas_topo_change_list_t *)args;
6025 
6026         mpt = topo_node->mpt;
6027         event = topo_node->event;
6028         flags = topo_node->flags;
6029 
6030         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
6031 
6032         NDBG20(("mptsas%d handle_dr enter", mpt->m_instance));
6033 
6034         switch (event) {
6035         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
6036                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6037                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE) ||
6038                     (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6039                         /*
6040                          * Direct attached or expander attached device added
6041                          * into system or a Phys Disk that is being unhidden.
6042                          */
6043                         port_update = 1;
6044                 }
6045                 break;
6046         case MPTSAS_DR_EVENT_RECONFIG_SMP:
6047                 /*
6048                  * New expander added into system, it must be the head
6049                  * of topo_change_list_t
6050                  */
6051                 port_update = 1;
6052                 break;
6053         default:
6054                 port_update = 0;
6055                 break;
6056         }
6057         /*
6058          * All cases port_update == 1 may cause initiator port form change
6059          */
6060         mutex_enter(&mpt->m_mutex);
6061         if (mpt->m_port_chng && port_update) {
6062                 /*
6063                  * mpt->m_port_chng flag indicates some PHYs of initiator
6064                  * port have changed to online. So when expander added or
6065                  * directly attached device online event come, we force to
6066                  * update port information by issueing SAS IO Unit Page and
6067                  * update PHYMASKs.
6068                  */
6069                 (void) mptsas_update_phymask(mpt);
6070                 mpt->m_port_chng = 0;
6071 
6072         }
6073         mutex_exit(&mpt->m_mutex);
6074         while (topo_node) {
6075                 phymask = 0;
6076                 if (parent == NULL) {
6077                         physport = topo_node->un.physport;
6078                         event = topo_node->event;
6079                         flags = topo_node->flags;
6080                         if (event & (MPTSAS_DR_EVENT_OFFLINE_TARGET |
6081                             MPTSAS_DR_EVENT_OFFLINE_SMP)) {
6082                                 /*
6083                                  * For all offline events, phymask is known
6084                                  */
6085                                 phymask = topo_node->un.phymask;
6086                                 goto find_parent;
6087                         }
6088                         if (event & MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
6089                                 goto handle_topo_change;
6090                         }
6091                         if (flags & MPTSAS_TOPO_FLAG_LUN_ASSOCIATED) {
6092                                 phymask = topo_node->un.phymask;
6093                                 goto find_parent;
6094                         }
6095 
6096                         if ((flags ==
6097                             MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) &&
6098                             (event == MPTSAS_DR_EVENT_RECONFIG_TARGET)) {
6099                                 /*
6100                                  * There is no any field in IR_CONFIG_CHANGE
6101                                  * event indicate physport/phynum, let's get
6102                                  * parent after SAS Device Page0 request.
6103                                  */
6104                                 goto handle_topo_change;
6105                         }
6106 
6107                         mutex_enter(&mpt->m_mutex);
6108                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6109                                 /*
6110                                  * If the direct attached device added or a
6111                                  * phys disk is being unhidden, argument
6112                                  * physport actually is PHY#, so we have to get
6113                                  * phymask according PHY#.
6114                                  */
6115                                 physport = mpt->m_phy_info[physport].port_num;
6116                         }
6117 
6118                         /*
6119                          * Translate physport to phymask so that we can search
6120                          * parent dip.
6121                          */
6122                         phymask = mptsas_physport_to_phymask(mpt,
6123                             physport);
6124                         mutex_exit(&mpt->m_mutex);
6125 
6126 find_parent:
6127                         bzero(phy_mask_name, MPTSAS_MAX_PHYS);
6128                         /*
6129                          * For RAID topology change node, write the iport name
6130                          * as v0.
6131                          */
6132                         if (flags & MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
6133                                 (void) sprintf(phy_mask_name, "v0");
6134                         } else {
6135                                 /*
6136                                  * phymask can bo 0 if the drive has been
6137                                  * pulled by the time an add event is
6138                                  * processed.  If phymask is 0, just skip this
6139                                  * event and continue.
6140                                  */
6141                                 if (phymask == 0) {
6142                                         mutex_enter(&mpt->m_mutex);
6143                                         save_node = topo_node;
6144                                         topo_node = topo_node->next;
6145                                         ASSERT(save_node);
6146                                         kmem_free(save_node,
6147                                             sizeof (mptsas_topo_change_list_t));
6148                                         mutex_exit(&mpt->m_mutex);
6149 
6150                                         parent = NULL;
6151                                         continue;
6152                                 }
6153                                 (void) sprintf(phy_mask_name, "%x", phymask);
6154                         }
6155                         parent = scsi_hba_iport_find(mpt->m_dip,
6156                             phy_mask_name);
6157                         if (parent == NULL) {
6158                                 mptsas_log(mpt, CE_WARN, "Failed to find an "
6159                                     "iport, should not happen!");
6160                                 goto out;
6161                         }
6162 
6163                 }
6164                 ASSERT(parent);
6165 handle_topo_change:
6166 
6167                 mutex_enter(&mpt->m_mutex);
6168 
6169                 mptsas_handle_topo_change(topo_node, parent);
6170                 save_node = topo_node;
6171                 topo_node = topo_node->next;
6172                 ASSERT(save_node);
6173                 kmem_free(save_node, sizeof (mptsas_topo_change_list_t));
6174                 mutex_exit(&mpt->m_mutex);
6175 
6176                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6177                     (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) ||
6178                     (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED)) {
6179                         /*
6180                          * If direct attached device associated, make sure
6181                          * reset the parent before start the next one. But
6182                          * all devices associated with expander shares the
6183                          * parent.  Also, reset parent if this is for RAID.
6184                          */
6185                         parent = NULL;
6186                 }
6187         }
6188 out:
6189         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
6190 }
6191 
6192 static void
6193 mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
6194     dev_info_t *parent)
6195 {
6196         mptsas_target_t *ptgt = NULL;
6197         mptsas_smp_t    *psmp = NULL;
6198         mptsas_t        *mpt = (void *)topo_node->mpt;
6199         uint16_t        devhdl;
6200         uint16_t        attached_devhdl;
6201         uint64_t        sas_wwn = 0;
6202         int             rval = 0;
6203         uint32_t        page_address;
6204         uint8_t         phy, flags;
6205         char            *addr = NULL;
6206         dev_info_t      *lundip;
6207         int             circ = 0, circ1 = 0;
6208         char            attached_wwnstr[MPTSAS_WWN_STRLEN];
6209 
6210         NDBG20(("mptsas%d handle_topo_change enter", mpt->m_instance));
6211 
6212         ASSERT(mutex_owned(&mpt->m_mutex));
6213 
6214         switch (topo_node->event) {
6215         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
6216         {
6217                 char *phy_mask_name;
6218                 mptsas_phymask_t phymask = 0;
6219 
6220                 if (topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
6221                         /*
6222                          * Get latest RAID info.
6223                          */
6224                         (void) mptsas_get_raid_info(mpt);
6225                         ptgt = mptsas_search_by_devhdl(
6226                             &mpt->m_active->m_tgttbl, topo_node->devhdl);
6227                         if (ptgt == NULL)
6228                                 break;
6229                 } else {
6230                         ptgt = (void *)topo_node->object;
6231                 }
6232 
6233                 if (ptgt == NULL) {
6234                         /*
6235                          * If a Phys Disk was deleted, RAID info needs to be
6236                          * updated to reflect the new topology.
6237                          */
6238                         (void) mptsas_get_raid_info(mpt);
6239 
6240                         /*
6241                          * Get sas device page 0 by DevHandle to make sure if
6242                          * SSP/SATA end device exist.
6243                          */
6244                         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
6245                             MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
6246                             topo_node->devhdl;
6247 
6248                         rval = mptsas_get_target_device_info(mpt, page_address,
6249                             &devhdl, &ptgt);
6250                         if (rval == DEV_INFO_WRONG_DEVICE_TYPE) {
6251                                 mptsas_log(mpt, CE_NOTE,
6252                                     "mptsas_handle_topo_change: target %d is "
6253                                     "not a SAS/SATA device. \n",
6254                                     topo_node->devhdl);
6255                         } else if (rval == DEV_INFO_FAIL_ALLOC) {
6256                                 mptsas_log(mpt, CE_NOTE,
6257                                     "mptsas_handle_topo_change: could not "
6258                                     "allocate memory. \n");
6259                         }
6260                         /*
6261                          * If rval is DEV_INFO_PHYS_DISK than there is nothing
6262                          * else to do, just leave.
6263                          */
6264                         if (rval != DEV_INFO_SUCCESS) {
6265                                 return;
6266                         }
6267                 }
6268 
6269                 ASSERT(ptgt->m_devhdl == topo_node->devhdl);
6270 
6271                 mutex_exit(&mpt->m_mutex);
6272                 flags = topo_node->flags;
6273 
6274                 if (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) {
6275                         phymask = ptgt->m_phymask;
6276                         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
6277                         (void) sprintf(phy_mask_name, "%x", phymask);
6278                         parent = scsi_hba_iport_find(mpt->m_dip,
6279                             phy_mask_name);
6280                         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
6281                         if (parent == NULL) {
6282                                 mptsas_log(mpt, CE_WARN, "Failed to find a "
6283                                     "iport for PD, should not happen!");
6284                                 mutex_enter(&mpt->m_mutex);
6285                                 break;
6286                         }
6287                 }
6288 
6289                 if (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
6290                         ndi_devi_enter(parent, &circ1);
6291                         (void) mptsas_config_raid(parent, topo_node->devhdl,
6292                             &lundip);
6293                         ndi_devi_exit(parent, circ1);
6294                 } else {
6295                         /*
6296                          * hold nexus for bus configure
6297                          */
6298                         ndi_devi_enter(scsi_vhci_dip, &circ);
6299                         ndi_devi_enter(parent, &circ1);
6300                         rval = mptsas_config_target(parent, ptgt);
6301                         /*
6302                          * release nexus for bus configure
6303                          */
6304                         ndi_devi_exit(parent, circ1);
6305                         ndi_devi_exit(scsi_vhci_dip, circ);
6306 
6307                         /*
6308                          * Add parent's props for SMHBA support
6309                          */
6310                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6311                                 bzero(attached_wwnstr,
6312                                     sizeof (attached_wwnstr));
6313                                 (void) sprintf(attached_wwnstr, "w%016"PRIx64,
6314                                     ptgt->m_sas_wwn);
6315                                 if (ddi_prop_update_string(DDI_DEV_T_NONE,
6316                                     parent,
6317                                     SCSI_ADDR_PROP_ATTACHED_PORT,
6318                                     attached_wwnstr)
6319                                     != DDI_PROP_SUCCESS) {
6320                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6321                                             parent,
6322                                             SCSI_ADDR_PROP_ATTACHED_PORT);
6323                                         mptsas_log(mpt, CE_WARN, "Failed to"
6324                                             "attached-port props");
6325                                         return;
6326                                 }
6327                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6328                                     MPTSAS_NUM_PHYS, 1) !=
6329                                     DDI_PROP_SUCCESS) {
6330                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6331                                             parent, MPTSAS_NUM_PHYS);
6332                                         mptsas_log(mpt, CE_WARN, "Failed to"
6333                                             " create num-phys props");
6334                                         return;
6335                                 }
6336 
6337                                 /*
6338                                  * Update PHY info for smhba
6339                                  */
6340                                 mutex_enter(&mpt->m_mutex);
6341                                 if (mptsas_smhba_phy_init(mpt)) {
6342                                         mutex_exit(&mpt->m_mutex);
6343                                         mptsas_log(mpt, CE_WARN, "mptsas phy"
6344                                             " update failed");
6345                                         return;
6346                                 }
6347                                 mutex_exit(&mpt->m_mutex);
6348                                 mptsas_smhba_set_phy_props(mpt,
6349                                     ddi_get_name_addr(parent), parent,
6350                                     1, &attached_devhdl);
6351                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6352                                     MPTSAS_VIRTUAL_PORT, 0) !=
6353                                     DDI_PROP_SUCCESS) {
6354                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6355                                             parent, MPTSAS_VIRTUAL_PORT);
6356                                         mptsas_log(mpt, CE_WARN,
6357                                             "mptsas virtual-port"
6358                                             "port prop update failed");
6359                                         return;
6360                                 }
6361                         }
6362                 }
6363                 mutex_enter(&mpt->m_mutex);
6364 
6365                 NDBG20(("mptsas%d handle_topo_change to online devhdl:%x, "
6366                     "phymask:%x.", mpt->m_instance, ptgt->m_devhdl,
6367                     ptgt->m_phymask));
6368                 break;
6369         }
6370         case MPTSAS_DR_EVENT_OFFLINE_TARGET:
6371         {
6372                 mptsas_hash_table_t *tgttbl = &mpt->m_active->m_tgttbl;
6373                 devhdl = topo_node->devhdl;
6374                 ptgt = mptsas_search_by_devhdl(tgttbl, devhdl);
6375                 if (ptgt == NULL)
6376                         break;
6377 
6378                 sas_wwn = ptgt->m_sas_wwn;
6379                 phy = ptgt->m_phynum;
6380 
6381                 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
6382 
6383                 if (sas_wwn) {
6384                         (void) sprintf(addr, "w%016"PRIx64, sas_wwn);
6385                 } else {
6386                         (void) sprintf(addr, "p%x", phy);
6387                 }
6388                 ASSERT(ptgt->m_devhdl == devhdl);
6389 
6390                 if ((topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) ||
6391                     (topo_node->flags ==
6392                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6393                         /*
6394                          * Get latest RAID info if RAID volume status changes
6395                          * or Phys Disk status changes
6396                          */
6397                         (void) mptsas_get_raid_info(mpt);
6398                 }
6399                 /*
6400                  * Abort all outstanding command on the device
6401                  */
6402                 rval = mptsas_do_scsi_reset(mpt, devhdl);
6403                 if (rval) {
6404                         NDBG20(("mptsas%d handle_topo_change to reset target "
6405                             "before offline devhdl:%x, phymask:%x, rval:%x",
6406                             mpt->m_instance, ptgt->m_devhdl, ptgt->m_phymask,
6407                             rval));
6408                 }
6409 
6410                 mutex_exit(&mpt->m_mutex);
6411 
6412                 ndi_devi_enter(scsi_vhci_dip, &circ);
6413                 ndi_devi_enter(parent, &circ1);
6414                 rval = mptsas_offline_target(parent, addr);
6415                 ndi_devi_exit(parent, circ1);
6416                 ndi_devi_exit(scsi_vhci_dip, circ);
6417                 NDBG20(("mptsas%d handle_topo_change to offline devhdl:%x, "
6418                     "phymask:%x, rval:%x", mpt->m_instance,
6419                     ptgt->m_devhdl, ptgt->m_phymask, rval));
6420 
6421                 kmem_free(addr, SCSI_MAXNAMELEN);
6422 
6423                 /*
6424                  * Clear parent's props for SMHBA support
6425                  */
6426                 flags = topo_node->flags;
6427                 if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6428                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6429                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6430                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6431                             DDI_PROP_SUCCESS) {
6432                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6433                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6434                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6435                                     "prop update failed");
6436                                 break;
6437                         }
6438                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6439                             MPTSAS_NUM_PHYS, 0) !=
6440                             DDI_PROP_SUCCESS) {
6441                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6442                                     MPTSAS_NUM_PHYS);
6443                                 mptsas_log(mpt, CE_WARN, "mptsas num phys "
6444                                     "prop update failed");
6445                                 break;
6446                         }
6447                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6448                             MPTSAS_VIRTUAL_PORT, 1) !=
6449                             DDI_PROP_SUCCESS) {
6450                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6451                                     MPTSAS_VIRTUAL_PORT);
6452                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6453                                     "prop update failed");
6454                                 break;
6455                         }
6456                 }
6457 
6458                 mutex_enter(&mpt->m_mutex);
6459                 ptgt->m_led_status = 0;
6460                 if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) {
6461                         NDBG14(("mptsas: clear LED for tgt %x failed",
6462                             ptgt->m_slot_num));
6463                 }
6464                 if (rval == DDI_SUCCESS) {
6465                         mptsas_tgt_free(&mpt->m_active->m_tgttbl,
6466                             ptgt->m_sas_wwn, ptgt->m_phymask);
6467                         ptgt = NULL;
6468                 } else {
6469                         /*
6470                          * clean DR_INTRANSITION flag to allow I/O down to
6471                          * PHCI driver since failover finished.
6472                          * Invalidate the devhdl
6473                          */
6474                         mutex_enter(&ptgt->m_tgt_intr_mutex);
6475                         ptgt->m_devhdl = MPTSAS_INVALID_DEVHDL;
6476                         ptgt->m_tgt_unconfigured = 0;
6477                         ptgt->m_dr_flag = MPTSAS_DR_INACTIVE;
6478                         mutex_exit(&ptgt->m_tgt_intr_mutex);
6479                 }
6480 
6481                 /*
6482                  * Send SAS IO Unit Control to free the dev handle
6483                  */
6484                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6485                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE)) {
6486                         rval = mptsas_free_devhdl(mpt, devhdl);
6487 
6488                         NDBG20(("mptsas%d handle_topo_change to remove "
6489                             "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6490                             rval));
6491                 }
6492 
6493                 break;
6494         }
6495         case MPTSAS_TOPO_FLAG_REMOVE_HANDLE:
6496         {
6497                 devhdl = topo_node->devhdl;
6498                 /*
6499                  * If this is the remove handle event, do a reset first.
6500                  */
6501                 if (topo_node->event == MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
6502                         rval = mptsas_do_scsi_reset(mpt, devhdl);
6503                         if (rval) {
6504                                 NDBG20(("mpt%d reset target before remove "
6505                                     "devhdl:%x, rval:%x", mpt->m_instance,
6506                                     devhdl, rval));
6507                         }
6508                 }
6509 
6510                 /*
6511                  * Send SAS IO Unit Control to free the dev handle
6512                  */
6513                 rval = mptsas_free_devhdl(mpt, devhdl);
6514                 NDBG20(("mptsas%d handle_topo_change to remove "
6515                     "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6516                     rval));
6517                 break;
6518         }
6519         case MPTSAS_DR_EVENT_RECONFIG_SMP:
6520         {
6521                 mptsas_smp_t smp;
6522                 dev_info_t *smpdip;
6523                 mptsas_hash_table_t *smptbl = &mpt->m_active->m_smptbl;
6524 
6525                 devhdl = topo_node->devhdl;
6526 
6527                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
6528                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)devhdl;
6529                 rval = mptsas_get_sas_expander_page0(mpt, page_address, &smp);
6530                 if (rval != DDI_SUCCESS) {
6531                         mptsas_log(mpt, CE_WARN, "failed to online smp, "
6532                             "handle %x", devhdl);
6533                         return;
6534                 }
6535 
6536                 psmp = mptsas_smp_alloc(smptbl, &smp);
6537                 if (psmp == NULL) {
6538                         return;
6539                 }
6540 
6541                 mutex_exit(&mpt->m_mutex);
6542                 ndi_devi_enter(parent, &circ1);
6543                 (void) mptsas_online_smp(parent, psmp, &smpdip);
6544                 ndi_devi_exit(parent, circ1);
6545 
6546                 mutex_enter(&mpt->m_mutex);
6547                 break;
6548         }
6549         case MPTSAS_DR_EVENT_OFFLINE_SMP:
6550         {
6551                 mptsas_hash_table_t *smptbl = &mpt->m_active->m_smptbl;
6552                 devhdl = topo_node->devhdl;
6553                 uint32_t dev_info;
6554 
6555                 psmp = mptsas_search_by_devhdl(smptbl, devhdl);
6556                 if (psmp == NULL)
6557                         break;
6558                 /*
6559                  * The mptsas_smp_t data is released only if the dip is offlined
6560                  * successfully.
6561                  */
6562                 mutex_exit(&mpt->m_mutex);
6563 
6564                 ndi_devi_enter(parent, &circ1);
6565                 rval = mptsas_offline_smp(parent, psmp, NDI_DEVI_REMOVE);
6566                 ndi_devi_exit(parent, circ1);
6567 
6568                 dev_info = psmp->m_deviceinfo;
6569                 if ((dev_info & DEVINFO_DIRECT_ATTACHED) ==
6570                     DEVINFO_DIRECT_ATTACHED) {
6571                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6572                             MPTSAS_VIRTUAL_PORT, 1) !=
6573                             DDI_PROP_SUCCESS) {
6574                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6575                                     MPTSAS_VIRTUAL_PORT);
6576                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6577                                     "prop update failed");
6578                                 return;
6579                         }
6580                         /*
6581                          * Check whether the smp connected to the iport,
6582                          */
6583                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6584                             MPTSAS_NUM_PHYS, 0) !=
6585                             DDI_PROP_SUCCESS) {
6586                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6587                                     MPTSAS_NUM_PHYS);
6588                                 mptsas_log(mpt, CE_WARN, "mptsas num phys"
6589                                     "prop update failed");
6590                                 return;
6591                         }
6592                         /*
6593                          * Clear parent's attached-port props
6594                          */
6595                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6596                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6597                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6598                             DDI_PROP_SUCCESS) {
6599                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6600                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6601                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6602                                     "prop update failed");
6603                                 return;
6604                         }
6605                 }
6606 
6607                 mutex_enter(&mpt->m_mutex);
6608                 NDBG20(("mptsas%d handle_topo_change to remove devhdl:%x, "
6609                     "rval:%x", mpt->m_instance, psmp->m_devhdl, rval));
6610                 if (rval == DDI_SUCCESS) {
6611                         mptsas_smp_free(smptbl, psmp->m_sasaddr,
6612                             psmp->m_phymask);
6613                 } else {
6614                         psmp->m_devhdl = MPTSAS_INVALID_DEVHDL;
6615                 }
6616 
6617                 bzero(attached_wwnstr, sizeof (attached_wwnstr));
6618 
6619                 break;
6620         }
6621         default:
6622                 return;
6623         }
6624 }
6625 
6626 /*
6627  * Record the event if its type is enabled in mpt instance by ioctl.
6628  */
6629 static void
6630 mptsas_record_event(void *args)
6631 {
6632         m_replyh_arg_t                  *replyh_arg;
6633         pMpi2EventNotificationReply_t   eventreply;
6634         uint32_t                        event, rfm;
6635         mptsas_t                        *mpt;
6636         int                             i, j;
6637         uint16_t                        event_data_len;
6638         boolean_t                       sendAEN = FALSE;
6639 
6640         replyh_arg = (m_replyh_arg_t *)args;
6641         rfm = replyh_arg->rfm;
6642         mpt = replyh_arg->mpt;
6643 
6644         eventreply = (pMpi2EventNotificationReply_t)
6645             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
6646         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6647 
6648 
6649         /*
6650          * Generate a system event to let anyone who cares know that a
6651          * LOG_ENTRY_ADDED event has occurred.  This is sent no matter what the
6652          * event mask is set to.
6653          */
6654         if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
6655                 sendAEN = TRUE;
6656         }
6657 
6658         /*
6659          * Record the event only if it is not masked.  Determine which dword
6660          * and bit of event mask to test.
6661          */
6662         i = (uint8_t)(event / 32);
6663         j = (uint8_t)(event % 32);
6664         if ((i < 4) && ((1 << j) & mpt->m_event_mask[i])) {
6665                 i = mpt->m_event_index;
6666                 mpt->m_events[i].Type = event;
6667                 mpt->m_events[i].Number = ++mpt->m_event_number;
6668                 bzero(mpt->m_events[i].Data, MPTSAS_MAX_EVENT_DATA_LENGTH * 4);
6669                 event_data_len = ddi_get16(mpt->m_acc_reply_frame_hdl,
6670                     &eventreply->EventDataLength);
6671 
6672                 if (event_data_len > 0) {
6673                         /*
6674                          * Limit data to size in m_event entry
6675                          */
6676                         if (event_data_len > MPTSAS_MAX_EVENT_DATA_LENGTH) {
6677                                 event_data_len = MPTSAS_MAX_EVENT_DATA_LENGTH;
6678                         }
6679                         for (j = 0; j < event_data_len; j++) {
6680                                 mpt->m_events[i].Data[j] =
6681                                     ddi_get32(mpt->m_acc_reply_frame_hdl,
6682                                     &(eventreply->EventData[j]));
6683                         }
6684 
6685                         /*
6686                          * check for index wrap-around
6687                          */
6688                         if (++i == MPTSAS_EVENT_QUEUE_SIZE) {
6689                                 i = 0;
6690                         }
6691                         mpt->m_event_index = (uint8_t)i;
6692 
6693                         /*
6694                          * Set flag to send the event.
6695                          */
6696                         sendAEN = TRUE;
6697                 }
6698         }
6699 
6700         /*
6701          * Generate a system event if flag is set to let anyone who cares know
6702          * that an event has occurred.
6703          */
6704         if (sendAEN) {
6705                 (void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS",
6706                     "SAS", NULL, NULL, DDI_NOSLEEP);
6707         }
6708 }
6709 
6710 #define SMP_RESET_IN_PROGRESS MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS
6711 /*
6712  * handle sync events from ioc in interrupt
6713  * return value:
6714  * DDI_SUCCESS: The event is handled by this func
6715  * DDI_FAILURE: Event is not handled
6716  */
6717 static int
6718 mptsas_handle_event_sync(void *args)
6719 {
6720         m_replyh_arg_t                  *replyh_arg;
6721         pMpi2EventNotificationReply_t   eventreply;
6722         uint32_t                        event, rfm;
6723         mptsas_t                        *mpt;
6724         uint_t                          iocstatus;
6725 
6726         replyh_arg = (m_replyh_arg_t *)args;
6727         rfm = replyh_arg->rfm;
6728         mpt = replyh_arg->mpt;
6729 
6730         ASSERT(mutex_owned(&mpt->m_mutex));
6731 
6732         eventreply = (pMpi2EventNotificationReply_t)
6733             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
6734         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6735 
6736         if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
6737             &eventreply->IOCStatus)) {
6738                 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
6739                         mptsas_log(mpt, CE_WARN,
6740                             "!mptsas_handle_event_sync: IOCStatus=0x%x, "
6741                             "IOCLogInfo=0x%x", iocstatus,
6742                             ddi_get32(mpt->m_acc_reply_frame_hdl,
6743                             &eventreply->IOCLogInfo));
6744                 } else {
6745                         mptsas_log(mpt, CE_WARN,
6746                             "mptsas_handle_event_sync: IOCStatus=0x%x, "
6747                             "IOCLogInfo=0x%x", iocstatus,
6748                             ddi_get32(mpt->m_acc_reply_frame_hdl,
6749                             &eventreply->IOCLogInfo));
6750                 }
6751         }
6752 
6753         /*
6754          * figure out what kind of event we got and handle accordingly
6755          */
6756         switch (event) {
6757         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
6758         {
6759                 pMpi2EventDataSasTopologyChangeList_t   sas_topo_change_list;
6760                 uint8_t                         num_entries, expstatus, phy;
6761                 uint8_t                         phystatus, physport, state, i;
6762                 uint8_t                         start_phy_num, link_rate;
6763                 uint16_t                        dev_handle, reason_code;
6764                 uint16_t                        enc_handle, expd_handle;
6765                 char                            string[80], curr[80], prev[80];
6766                 mptsas_topo_change_list_t       *topo_head = NULL;
6767                 mptsas_topo_change_list_t       *topo_tail = NULL;
6768                 mptsas_topo_change_list_t       *topo_node = NULL;
6769                 mptsas_target_t                 *ptgt;
6770                 mptsas_smp_t                    *psmp;
6771                 mptsas_hash_table_t             *tgttbl, *smptbl;
6772                 uint8_t                         flags = 0, exp_flag;
6773                 smhba_info_t                    *pSmhba = NULL;
6774 
6775                 NDBG20(("mptsas_handle_event_sync: SAS topology change"));
6776 
6777                 tgttbl = &mpt->m_active->m_tgttbl;
6778                 smptbl = &mpt->m_active->m_smptbl;
6779 
6780                 sas_topo_change_list = (pMpi2EventDataSasTopologyChangeList_t)
6781                     eventreply->EventData;
6782 
6783                 enc_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6784                     &sas_topo_change_list->EnclosureHandle);
6785                 expd_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6786                     &sas_topo_change_list->ExpanderDevHandle);
6787                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6788                     &sas_topo_change_list->NumEntries);
6789                 start_phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
6790                     &sas_topo_change_list->StartPhyNum);
6791                 expstatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6792                     &sas_topo_change_list->ExpStatus);
6793                 physport = ddi_get8(mpt->m_acc_reply_frame_hdl,
6794                     &sas_topo_change_list->PhysicalPort);
6795 
6796                 string[0] = 0;
6797                 if (expd_handle) {
6798                         flags = MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED;
6799                         switch (expstatus) {
6800                         case MPI2_EVENT_SAS_TOPO_ES_ADDED:
6801                                 (void) sprintf(string, " added");
6802                                 /*
6803                                  * New expander device added
6804                                  */
6805                                 mpt->m_port_chng = 1;
6806                                 topo_node = kmem_zalloc(
6807                                     sizeof (mptsas_topo_change_list_t),
6808                                     KM_SLEEP);
6809                                 topo_node->mpt = mpt;
6810                                 topo_node->event = MPTSAS_DR_EVENT_RECONFIG_SMP;
6811                                 topo_node->un.physport = physport;
6812                                 topo_node->devhdl = expd_handle;
6813                                 topo_node->flags = flags;
6814                                 topo_node->object = NULL;
6815                                 if (topo_head == NULL) {
6816                                         topo_head = topo_tail = topo_node;
6817                                 } else {
6818                                         topo_tail->next = topo_node;
6819                                         topo_tail = topo_node;
6820                                 }
6821                                 break;
6822                         case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
6823                                 (void) sprintf(string, " not responding, "
6824                                     "removed");
6825                                 psmp = mptsas_search_by_devhdl(smptbl,
6826                                     expd_handle);
6827                                 if (psmp == NULL)
6828                                         break;
6829 
6830                                 topo_node = kmem_zalloc(
6831                                     sizeof (mptsas_topo_change_list_t),
6832                                     KM_SLEEP);
6833                                 topo_node->mpt = mpt;
6834                                 topo_node->un.phymask = psmp->m_phymask;
6835                                 topo_node->event = MPTSAS_DR_EVENT_OFFLINE_SMP;
6836                                 topo_node->devhdl = expd_handle;
6837                                 topo_node->flags = flags;
6838                                 topo_node->object = NULL;
6839                                 if (topo_head == NULL) {
6840                                         topo_head = topo_tail = topo_node;
6841                                 } else {
6842                                         topo_tail->next = topo_node;
6843                                         topo_tail = topo_node;
6844                                 }
6845                                 break;
6846                         case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
6847                                 break;
6848                         case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
6849                                 (void) sprintf(string, " not responding, "
6850                                     "delaying removal");
6851                                 break;
6852                         default:
6853                                 break;
6854                         }
6855                 } else {
6856                         flags = MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE;
6857                 }
6858 
6859                 NDBG20(("SAS TOPOLOGY CHANGE for enclosure %x expander %x%s\n",
6860                     enc_handle, expd_handle, string));
6861                 for (i = 0; i < num_entries; i++) {
6862                         phy = i + start_phy_num;
6863                         phystatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6864                             &sas_topo_change_list->PHY[i].PhyStatus);
6865                         dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6866                             &sas_topo_change_list->PHY[i].AttachedDevHandle);
6867                         reason_code = phystatus & MPI2_EVENT_SAS_TOPO_RC_MASK;
6868                         /*
6869                          * Filter out processing of Phy Vacant Status unless
6870                          * the reason code is "Not Responding".  Process all
6871                          * other combinations of Phy Status and Reason Codes.
6872                          */
6873                         if ((phystatus &
6874                             MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) &&
6875                             (reason_code !=
6876                             MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) {
6877                                 continue;
6878                         }
6879                         curr[0] = 0;
6880                         prev[0] = 0;
6881                         string[0] = 0;
6882                         switch (reason_code) {
6883                         case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
6884                         {
6885                                 NDBG20(("mptsas%d phy %d physical_port %d "
6886                                     "dev_handle %d added", mpt->m_instance, phy,
6887                                     physport, dev_handle));
6888                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
6889                                     &sas_topo_change_list->PHY[i].LinkRate);
6890                                 state = (link_rate &
6891                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
6892                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
6893                                 switch (state) {
6894                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
6895                                         (void) sprintf(curr, "is disabled");
6896                                         break;
6897                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
6898                                         (void) sprintf(curr, "is offline, "
6899                                             "failed speed negotiation");
6900                                         break;
6901                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
6902                                         (void) sprintf(curr, "SATA OOB "
6903                                             "complete");
6904                                         break;
6905                                 case SMP_RESET_IN_PROGRESS:
6906                                         (void) sprintf(curr, "SMP reset in "
6907                                             "progress");
6908                                         break;
6909                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
6910                                         (void) sprintf(curr, "is online at "
6911                                             "1.5 Gbps");
6912                                         break;
6913                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
6914                                         (void) sprintf(curr, "is online at 3.0 "
6915                                             "Gbps");
6916                                         break;
6917                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
6918                                         (void) sprintf(curr, "is online at 6.0 "
6919                                             "Gbps");
6920                                         break;
6921                                 default:
6922                                         (void) sprintf(curr, "state is "
6923                                             "unknown");
6924                                         break;
6925                                 }
6926                                 /*
6927                                  * New target device added into the system.
6928                                  * Set association flag according to if an
6929                                  * expander is used or not.
6930                                  */
6931                                 exp_flag =
6932                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
6933                                 if (flags ==
6934                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
6935                                         flags = exp_flag;
6936                                 }
6937                                 topo_node = kmem_zalloc(
6938                                     sizeof (mptsas_topo_change_list_t),
6939                                     KM_SLEEP);
6940                                 topo_node->mpt = mpt;
6941                                 topo_node->event =
6942                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
6943                                 if (expd_handle == 0) {
6944                                         /*
6945                                          * Per MPI 2, if expander dev handle
6946                                          * is 0, it's a directly attached
6947                                          * device. So driver use PHY to decide
6948                                          * which iport is associated
6949                                          */
6950                                         physport = phy;
6951                                         mpt->m_port_chng = 1;
6952                                 }
6953                                 topo_node->un.physport = physport;
6954                                 topo_node->devhdl = dev_handle;
6955                                 topo_node->flags = flags;
6956                                 topo_node->object = NULL;
6957                                 if (topo_head == NULL) {
6958                                         topo_head = topo_tail = topo_node;
6959                                 } else {
6960                                         topo_tail->next = topo_node;
6961                                         topo_tail = topo_node;
6962                                 }
6963                                 break;
6964                         }
6965                         case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
6966                         {
6967                                 NDBG20(("mptsas%d phy %d physical_port %d "
6968                                     "dev_handle %d removed", mpt->m_instance,
6969                                     phy, physport, dev_handle));
6970                                 /*
6971                                  * Set association flag according to if an
6972                                  * expander is used or not.
6973                                  */
6974                                 exp_flag =
6975                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
6976                                 if (flags ==
6977                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
6978                                         flags = exp_flag;
6979                                 }
6980                                 /*
6981                                  * Target device is removed from the system
6982                                  * Before the device is really offline from
6983                                  * from system.
6984                                  */
6985                                 ptgt = mptsas_search_by_devhdl(tgttbl,
6986                                     dev_handle);
6987                                 /*
6988                                  * If ptgt is NULL here, it means that the
6989                                  * DevHandle is not in the hash table.  This is
6990                                  * reasonable sometimes.  For example, if a
6991                                  * disk was pulled, then added, then pulled
6992                                  * again, the disk will not have been put into
6993                                  * the hash table because the add event will
6994                                  * have an invalid phymask.  BUT, this does not
6995                                  * mean that the DevHandle is invalid.  The
6996                                  * controller will still have a valid DevHandle
6997                                  * that must be removed.  To do this, use the
6998                                  * MPTSAS_TOPO_FLAG_REMOVE_HANDLE event.
6999                                  */
7000                                 if (ptgt == NULL) {
7001                                         topo_node = kmem_zalloc(
7002                                             sizeof (mptsas_topo_change_list_t),
7003                                             KM_SLEEP);
7004                                         topo_node->mpt = mpt;
7005                                         topo_node->un.phymask = 0;
7006                                         topo_node->event =
7007                                             MPTSAS_TOPO_FLAG_REMOVE_HANDLE;
7008                                         topo_node->devhdl = dev_handle;
7009                                         topo_node->flags = flags;
7010                                         topo_node->object = NULL;
7011                                         if (topo_head == NULL) {
7012                                                 topo_head = topo_tail =
7013                                                     topo_node;
7014                                         } else {
7015                                                 topo_tail->next = topo_node;
7016                                                 topo_tail = topo_node;
7017                                         }
7018                                         break;
7019                                 }
7020 
7021                                 /*
7022                                  * Update DR flag immediately avoid I/O failure
7023                                  * before failover finish. Pay attention to the
7024                                  * mutex protect, we need grab the per target
7025                                  * mutex during set m_dr_flag because the
7026                                  * m_mutex would not be held all the time in
7027                                  * mptsas_scsi_start().
7028                                  */
7029                                 mutex_enter(&ptgt->m_tgt_intr_mutex);
7030                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
7031                                 mutex_exit(&ptgt->m_tgt_intr_mutex);
7032 
7033                                 topo_node = kmem_zalloc(
7034                                     sizeof (mptsas_topo_change_list_t),
7035                                     KM_SLEEP);
7036                                 topo_node->mpt = mpt;
7037                                 topo_node->un.phymask = ptgt->m_phymask;
7038                                 topo_node->event =
7039                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7040                                 topo_node->devhdl = dev_handle;
7041                                 topo_node->flags = flags;
7042                                 topo_node->object = NULL;
7043                                 if (topo_head == NULL) {
7044                                         topo_head = topo_tail = topo_node;
7045                                 } else {
7046                                         topo_tail->next = topo_node;
7047                                         topo_tail = topo_node;
7048                                 }
7049                                 break;
7050                         }
7051                         case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
7052                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
7053                                     &sas_topo_change_list->PHY[i].LinkRate);
7054                                 state = (link_rate &
7055                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
7056                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
7057                                 pSmhba = &mpt->m_phy_info[i].smhba_info;
7058                                 pSmhba->negotiated_link_rate = state;
7059                                 switch (state) {
7060                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
7061                                         (void) sprintf(curr, "is disabled");
7062                                         mptsas_smhba_log_sysevent(mpt,
7063                                             ESC_SAS_PHY_EVENT,
7064                                             SAS_PHY_REMOVE,
7065                                             &mpt->m_phy_info[i].smhba_info);
7066                                         mpt->m_phy_info[i].smhba_info.
7067                                             negotiated_link_rate
7068                                             = 0x1;
7069                                         break;
7070                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
7071                                         (void) sprintf(curr, "is offline, "
7072                                             "failed speed negotiation");
7073                                         mptsas_smhba_log_sysevent(mpt,
7074                                             ESC_SAS_PHY_EVENT,
7075                                             SAS_PHY_OFFLINE,
7076                                             &mpt->m_phy_info[i].smhba_info);
7077                                         break;
7078                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
7079                                         (void) sprintf(curr, "SATA OOB "
7080                                             "complete");
7081                                         break;
7082                                 case SMP_RESET_IN_PROGRESS:
7083                                         (void) sprintf(curr, "SMP reset in "
7084                                             "progress");
7085                                         break;
7086                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
7087                                         (void) sprintf(curr, "is online at "
7088                                             "1.5 Gbps");
7089                                         if ((expd_handle == 0) &&
7090                                             (enc_handle == 1)) {
7091                                                 mpt->m_port_chng = 1;
7092                                         }
7093                                         mptsas_smhba_log_sysevent(mpt,
7094                                             ESC_SAS_PHY_EVENT,
7095                                             SAS_PHY_ONLINE,
7096                                             &mpt->m_phy_info[i].smhba_info);
7097                                         break;
7098                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
7099                                         (void) sprintf(curr, "is online at 3.0 "
7100                                             "Gbps");
7101                                         if ((expd_handle == 0) &&
7102                                             (enc_handle == 1)) {
7103                                                 mpt->m_port_chng = 1;
7104                                         }
7105                                         mptsas_smhba_log_sysevent(mpt,
7106                                             ESC_SAS_PHY_EVENT,
7107                                             SAS_PHY_ONLINE,
7108                                             &mpt->m_phy_info[i].smhba_info);
7109                                         break;
7110                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
7111                                         (void) sprintf(curr, "is online at "
7112                                             "6.0 Gbps");
7113                                         if ((expd_handle == 0) &&
7114                                             (enc_handle == 1)) {
7115                                                 mpt->m_port_chng = 1;
7116                                         }
7117                                         mptsas_smhba_log_sysevent(mpt,
7118                                             ESC_SAS_PHY_EVENT,
7119                                             SAS_PHY_ONLINE,
7120                                             &mpt->m_phy_info[i].smhba_info);
7121                                         break;
7122                                 default:
7123                                         (void) sprintf(curr, "state is "
7124                                             "unknown");
7125                                         break;
7126                                 }
7127 
7128                                 state = (link_rate &
7129                                     MPI2_EVENT_SAS_TOPO_LR_PREV_MASK) >>
7130                                     MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT;
7131                                 switch (state) {
7132                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
7133                                         (void) sprintf(prev, ", was disabled");
7134                                         break;
7135                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
7136                                         (void) sprintf(prev, ", was offline, "
7137                                             "failed speed negotiation");
7138                                         break;
7139                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
7140                                         (void) sprintf(prev, ", was SATA OOB "
7141                                             "complete");
7142                                         break;
7143                                 case SMP_RESET_IN_PROGRESS:
7144                                         (void) sprintf(prev, ", was SMP reset "
7145                                             "in progress");
7146                                         break;
7147                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
7148                                         (void) sprintf(prev, ", was online at "
7149                                             "1.5 Gbps");
7150                                         break;
7151                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
7152                                         (void) sprintf(prev, ", was online at "
7153                                             "3.0 Gbps");
7154                                         break;
7155                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
7156                                         (void) sprintf(prev, ", was online at "
7157                                             "6.0 Gbps");
7158                                         break;
7159                                 default:
7160                                 break;
7161                                 }
7162                                 (void) sprintf(&string[strlen(string)], "link "
7163                                     "changed, ");
7164                                 break;
7165                         case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
7166                                 continue;
7167                         case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
7168                                 (void) sprintf(&string[strlen(string)],
7169                                     "target not responding, delaying "
7170                                     "removal");
7171                                 break;
7172                         }
7173                         NDBG20(("mptsas%d phy %d DevHandle %x, %s%s%s\n",
7174                             mpt->m_instance, phy, dev_handle, string, curr,
7175                             prev));
7176                 }
7177                 if (topo_head != NULL) {
7178                         /*
7179                          * Launch DR taskq to handle topology change
7180                          */
7181                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
7182                             mptsas_handle_dr, (void *)topo_head,
7183                             DDI_NOSLEEP)) != DDI_SUCCESS) {
7184                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
7185                                     "for handle SAS DR event failed. \n");
7186                         }
7187                 }
7188                 break;
7189         }
7190         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7191         {
7192                 Mpi2EventDataIrConfigChangeList_t       *irChangeList;
7193                 mptsas_topo_change_list_t               *topo_head = NULL;
7194                 mptsas_topo_change_list_t               *topo_tail = NULL;
7195                 mptsas_topo_change_list_t               *topo_node = NULL;
7196                 mptsas_target_t                         *ptgt;
7197                 mptsas_hash_table_t                     *tgttbl;
7198                 uint8_t                                 num_entries, i, reason;
7199                 uint16_t                                volhandle, diskhandle;
7200 
7201                 irChangeList = (pMpi2EventDataIrConfigChangeList_t)
7202                     eventreply->EventData;
7203                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
7204                     &irChangeList->NumElements);
7205 
7206                 tgttbl = &mpt->m_active->m_tgttbl;
7207 
7208                 NDBG20(("mptsas%d IR_CONFIGURATION_CHANGE_LIST event received",
7209                     mpt->m_instance));
7210 
7211                 for (i = 0; i < num_entries; i++) {
7212                         reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
7213                             &irChangeList->ConfigElement[i].ReasonCode);
7214                         volhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7215                             &irChangeList->ConfigElement[i].VolDevHandle);
7216                         diskhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7217                             &irChangeList->ConfigElement[i].PhysDiskDevHandle);
7218 
7219                         switch (reason) {
7220                         case MPI2_EVENT_IR_CHANGE_RC_ADDED:
7221                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
7222                         {
7223                                 NDBG20(("mptsas %d volume added\n",
7224                                     mpt->m_instance));
7225 
7226                                 topo_node = kmem_zalloc(
7227                                     sizeof (mptsas_topo_change_list_t),
7228                                     KM_SLEEP);
7229 
7230                                 topo_node->mpt = mpt;
7231                                 topo_node->event =
7232                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
7233                                 topo_node->un.physport = 0xff;
7234                                 topo_node->devhdl = volhandle;
7235                                 topo_node->flags =
7236                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
7237                                 topo_node->object = NULL;
7238                                 if (topo_head == NULL) {
7239                                         topo_head = topo_tail = topo_node;
7240                                 } else {
7241                                         topo_tail->next = topo_node;
7242                                         topo_tail = topo_node;
7243                                 }
7244                                 break;
7245                         }
7246                         case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
7247                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
7248                         {
7249                                 NDBG20(("mptsas %d volume deleted\n",
7250                                     mpt->m_instance));
7251                                 ptgt = mptsas_search_by_devhdl(tgttbl,
7252                                     volhandle);
7253                                 if (ptgt == NULL)
7254                                         break;
7255 
7256                                 /*
7257                                  * Clear any flags related to volume
7258                                  */
7259                                 (void) mptsas_delete_volume(mpt, volhandle);
7260 
7261                                 /*
7262                                  * Update DR flag immediately avoid I/O failure
7263                                  */
7264                                 mutex_enter(&ptgt->m_tgt_intr_mutex);
7265                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
7266                                 mutex_exit(&ptgt->m_tgt_intr_mutex);
7267 
7268                                 topo_node = kmem_zalloc(
7269                                     sizeof (mptsas_topo_change_list_t),
7270                                     KM_SLEEP);
7271                                 topo_node->mpt = mpt;
7272                                 topo_node->un.phymask = ptgt->m_phymask;
7273                                 topo_node->event =
7274                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7275                                 topo_node->devhdl = volhandle;
7276                                 topo_node->flags =
7277                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
7278                                 topo_node->object = (void *)ptgt;
7279                                 if (topo_head == NULL) {
7280                                         topo_head = topo_tail = topo_node;
7281                                 } else {
7282                                         topo_tail->next = topo_node;
7283                                         topo_tail = topo_node;
7284                                 }
7285                                 break;
7286                         }
7287                         case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
7288                         case MPI2_EVENT_IR_CHANGE_RC_HIDE:
7289                         {
7290                                 ptgt = mptsas_search_by_devhdl(tgttbl,
7291                                     diskhandle);
7292                                 if (ptgt == NULL)
7293                                         break;
7294 
7295                                 /*
7296                                  * Update DR flag immediately avoid I/O failure
7297                                  */
7298                                 mutex_enter(&ptgt->m_tgt_intr_mutex);
7299                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
7300                                 mutex_exit(&ptgt->m_tgt_intr_mutex);
7301 
7302                                 topo_node = kmem_zalloc(
7303                                     sizeof (mptsas_topo_change_list_t),
7304                                     KM_SLEEP);
7305                                 topo_node->mpt = mpt;
7306                                 topo_node->un.phymask = ptgt->m_phymask;
7307                                 topo_node->event =
7308                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7309                                 topo_node->devhdl = diskhandle;
7310                                 topo_node->flags =
7311                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
7312                                 topo_node->object = (void *)ptgt;
7313                                 if (topo_head == NULL) {
7314                                         topo_head = topo_tail = topo_node;
7315                                 } else {
7316                                         topo_tail->next = topo_node;
7317                                         topo_tail = topo_node;
7318                                 }
7319                                 break;
7320                         }
7321                         case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
7322                         case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
7323                         {
7324                                 /*
7325                                  * The physical drive is released by a IR
7326                                  * volume. But we cannot get the the physport
7327                                  * or phynum from the event data, so we only
7328                                  * can get the physport/phynum after SAS
7329                                  * Device Page0 request for the devhdl.
7330                                  */
7331                                 topo_node = kmem_zalloc(
7332                                     sizeof (mptsas_topo_change_list_t),
7333                                     KM_SLEEP);
7334                                 topo_node->mpt = mpt;
7335                                 topo_node->un.phymask = 0;
7336                                 topo_node->event =
7337                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
7338                                 topo_node->devhdl = diskhandle;
7339                                 topo_node->flags =
7340                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
7341                                 topo_node->object = NULL;
7342                                 mpt->m_port_chng = 1;
7343                                 if (topo_head == NULL) {
7344                                         topo_head = topo_tail = topo_node;
7345                                 } else {
7346                                         topo_tail->next = topo_node;
7347                                         topo_tail = topo_node;
7348                                 }
7349                                 break;
7350                         }
7351                         default:
7352                                 break;
7353                         }
7354                 }
7355 
7356                 if (topo_head != NULL) {
7357                         /*
7358                          * Launch DR taskq to handle topology change
7359                          */
7360                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
7361                             mptsas_handle_dr, (void *)topo_head,
7362                             DDI_NOSLEEP)) != DDI_SUCCESS) {
7363                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
7364                                     "for handle SAS DR event failed. \n");
7365                         }
7366                 }
7367                 break;
7368         }
7369         default:
7370                 return (DDI_FAILURE);
7371         }
7372 
7373         return (DDI_SUCCESS);
7374 }
7375 
7376 /*
7377  * handle events from ioc
7378  */
7379 static void
7380 mptsas_handle_event(void *args)
7381 {
7382         m_replyh_arg_t                  *replyh_arg;
7383         pMpi2EventNotificationReply_t   eventreply;
7384         uint32_t                        event, iocloginfo, rfm;
7385         uint32_t                        status;
7386         uint8_t                         port;
7387         mptsas_t                        *mpt;
7388         uint_t                          iocstatus;
7389 
7390         replyh_arg = (m_replyh_arg_t *)args;
7391         rfm = replyh_arg->rfm;
7392         mpt = replyh_arg->mpt;
7393 
7394         mutex_enter(&mpt->m_mutex);
7395 
7396         eventreply = (pMpi2EventNotificationReply_t)
7397             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
7398         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
7399 
7400         if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
7401             &eventreply->IOCStatus)) {
7402                 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
7403                         mptsas_log(mpt, CE_WARN,
7404                             "!mptsas_handle_event: IOCStatus=0x%x, "
7405                             "IOCLogInfo=0x%x", iocstatus,
7406                             ddi_get32(mpt->m_acc_reply_frame_hdl,
7407                             &eventreply->IOCLogInfo));
7408                 } else {
7409                         mptsas_log(mpt, CE_WARN,
7410                             "mptsas_handle_event: IOCStatus=0x%x, "
7411                             "IOCLogInfo=0x%x", iocstatus,
7412                             ddi_get32(mpt->m_acc_reply_frame_hdl,
7413                             &eventreply->IOCLogInfo));
7414                 }
7415         }
7416 
7417         /*
7418          * figure out what kind of event we got and handle accordingly
7419          */
7420         switch (event) {
7421         case MPI2_EVENT_LOG_ENTRY_ADDED:
7422                 break;
7423         case MPI2_EVENT_LOG_DATA:
7424                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7425                     &eventreply->IOCLogInfo);
7426                 NDBG20(("mptsas %d log info %x received.\n", mpt->m_instance,
7427                     iocloginfo));
7428                 break;
7429         case MPI2_EVENT_STATE_CHANGE:
7430                 NDBG20(("mptsas%d state change.", mpt->m_instance));
7431                 break;
7432         case MPI2_EVENT_HARD_RESET_RECEIVED:
7433                 NDBG20(("mptsas%d event change.", mpt->m_instance));
7434                 break;
7435         case MPI2_EVENT_SAS_DISCOVERY:
7436         {
7437                 MPI2_EVENT_DATA_SAS_DISCOVERY   *sasdiscovery;
7438                 char                            string[80];
7439                 uint8_t                         rc;
7440 
7441                 sasdiscovery =
7442                     (pMpi2EventDataSasDiscovery_t)eventreply->EventData;
7443 
7444                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7445                     &sasdiscovery->ReasonCode);
7446                 port = ddi_get8(mpt->m_acc_reply_frame_hdl,
7447                     &sasdiscovery->PhysicalPort);
7448                 status = ddi_get32(mpt->m_acc_reply_frame_hdl,
7449                     &sasdiscovery->DiscoveryStatus);
7450 
7451                 string[0] = 0;
7452                 switch (rc) {
7453                 case MPI2_EVENT_SAS_DISC_RC_STARTED:
7454                         (void) sprintf(string, "STARTING");
7455                         break;
7456                 case MPI2_EVENT_SAS_DISC_RC_COMPLETED:
7457                         (void) sprintf(string, "COMPLETED");
7458                         break;
7459                 default:
7460                         (void) sprintf(string, "UNKNOWN");
7461                         break;
7462                 }
7463 
7464                 NDBG20(("SAS DISCOVERY is %s for port %d, status %x", string,
7465                     port, status));
7466 
7467                 break;
7468         }
7469         case MPI2_EVENT_EVENT_CHANGE:
7470                 NDBG20(("mptsas%d event change.", mpt->m_instance));
7471                 break;
7472         case MPI2_EVENT_TASK_SET_FULL:
7473         {
7474                 pMpi2EventDataTaskSetFull_t     taskfull;
7475 
7476                 taskfull = (pMpi2EventDataTaskSetFull_t)eventreply->EventData;
7477 
7478                 NDBG20(("TASK_SET_FULL received for mptsas%d, depth %d\n",
7479                     mpt->m_instance,  ddi_get16(mpt->m_acc_reply_frame_hdl,
7480                     &taskfull->CurrentDepth)));
7481                 break;
7482         }
7483         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7484         {
7485                 /*
7486                  * SAS TOPOLOGY CHANGE LIST Event has already been handled
7487                  * in mptsas_handle_event_sync() of interrupt context
7488                  */
7489                 break;
7490         }
7491         case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7492         {
7493                 pMpi2EventDataSasEnclDevStatusChange_t  encstatus;
7494                 uint8_t                                 rc;
7495                 char                                    string[80];
7496 
7497                 encstatus = (pMpi2EventDataSasEnclDevStatusChange_t)
7498                     eventreply->EventData;
7499 
7500                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7501                     &encstatus->ReasonCode);
7502                 switch (rc) {
7503                 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
7504                         (void) sprintf(string, "added");
7505                         break;
7506                 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
7507                         (void) sprintf(string, ", not responding");
7508                         break;
7509                 default:
7510                 break;
7511                 }
7512                 NDBG20(("mptsas%d ENCLOSURE STATUS CHANGE for enclosure %x%s\n",
7513                     mpt->m_instance, ddi_get16(mpt->m_acc_reply_frame_hdl,
7514                     &encstatus->EnclosureHandle), string));
7515                 break;
7516         }
7517 
7518         /*
7519          * MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE is handled by
7520          * mptsas_handle_event_sync,in here just send ack message.
7521          */
7522         case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7523         {
7524                 pMpi2EventDataSasDeviceStatusChange_t   statuschange;
7525                 uint8_t                                 rc;
7526                 uint16_t                                devhdl;
7527                 uint64_t                                wwn = 0;
7528                 uint32_t                                wwn_lo, wwn_hi;
7529 
7530                 statuschange = (pMpi2EventDataSasDeviceStatusChange_t)
7531                     eventreply->EventData;
7532                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7533                     &statuschange->ReasonCode);
7534                 wwn_lo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7535                     (uint32_t *)(void *)&statuschange->SASAddress);
7536                 wwn_hi = ddi_get32(mpt->m_acc_reply_frame_hdl,
7537                     (uint32_t *)(void *)&statuschange->SASAddress + 1);
7538                 wwn = ((uint64_t)wwn_hi << 32) | wwn_lo;
7539                 devhdl =  ddi_get16(mpt->m_acc_reply_frame_hdl,
7540                     &statuschange->DevHandle);
7541 
7542                 NDBG13(("MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE wwn is %"PRIx64,
7543                     wwn));
7544 
7545                 switch (rc) {
7546                 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
7547                         NDBG20(("SMART data received, ASC/ASCQ = %02x/%02x",
7548                             ddi_get8(mpt->m_acc_reply_frame_hdl,
7549                             &statuschange->ASC),
7550                             ddi_get8(mpt->m_acc_reply_frame_hdl,
7551                             &statuschange->ASCQ)));
7552                         break;
7553 
7554                 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
7555                         NDBG20(("Device not supported"));
7556                         break;
7557 
7558                 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
7559                         NDBG20(("IOC internally generated the Target Reset "
7560                             "for devhdl:%x", devhdl));
7561                         break;
7562 
7563                 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
7564                         NDBG20(("IOC's internally generated Target Reset "
7565                             "completed for devhdl:%x", devhdl));
7566                         break;
7567 
7568                 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
7569                         NDBG20(("IOC internally generated Abort Task"));
7570                         break;
7571 
7572                 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
7573                         NDBG20(("IOC's internally generated Abort Task "
7574                             "completed"));
7575                         break;
7576 
7577                 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
7578                         NDBG20(("IOC internally generated Abort Task Set"));
7579                         break;
7580 
7581                 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
7582                         NDBG20(("IOC internally generated Clear Task Set"));
7583                         break;
7584 
7585                 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
7586                         NDBG20(("IOC internally generated Query Task"));
7587                         break;
7588 
7589                 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
7590                         NDBG20(("Device sent an Asynchronous Notification"));
7591                         break;
7592 
7593                 default:
7594                         break;
7595                 }
7596                 break;
7597         }
7598         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7599         {
7600                 /*
7601                  * IR TOPOLOGY CHANGE LIST Event has already been handled
7602                  * in mpt_handle_event_sync() of interrupt context
7603                  */
7604                 break;
7605         }
7606         case MPI2_EVENT_IR_OPERATION_STATUS:
7607         {
7608                 Mpi2EventDataIrOperationStatus_t        *irOpStatus;
7609                 char                                    reason_str[80];
7610                 uint8_t                                 rc, percent;
7611                 uint16_t                                handle;
7612 
7613                 irOpStatus = (pMpi2EventDataIrOperationStatus_t)
7614                     eventreply->EventData;
7615                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7616                     &irOpStatus->RAIDOperation);
7617                 percent = ddi_get8(mpt->m_acc_reply_frame_hdl,
7618                     &irOpStatus->PercentComplete);
7619                 handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7620                     &irOpStatus->VolDevHandle);
7621 
7622                 switch (rc) {
7623                         case MPI2_EVENT_IR_RAIDOP_RESYNC:
7624                                 (void) sprintf(reason_str, "resync");
7625                                 break;
7626                         case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
7627                                 (void) sprintf(reason_str, "online capacity "
7628                                     "expansion");
7629                                 break;
7630                         case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
7631                                 (void) sprintf(reason_str, "consistency check");
7632                                 break;
7633                         default:
7634                                 (void) sprintf(reason_str, "unknown reason %x",
7635                                     rc);
7636                 }
7637 
7638                 NDBG20(("mptsas%d raid operational status: (%s)"
7639                     "\thandle(0x%04x), percent complete(%d)\n",
7640                     mpt->m_instance, reason_str, handle, percent));
7641                 break;
7642         }
7643         case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7644         {
7645                 pMpi2EventDataSasBroadcastPrimitive_t   sas_broadcast;
7646                 uint8_t                                 phy_num;
7647                 uint8_t                                 primitive;
7648 
7649                 sas_broadcast = (pMpi2EventDataSasBroadcastPrimitive_t)
7650                     eventreply->EventData;
7651 
7652                 phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
7653                     &sas_broadcast->PhyNum);
7654                 primitive = ddi_get8(mpt->m_acc_reply_frame_hdl,
7655                     &sas_broadcast->Primitive);
7656 
7657                 switch (primitive) {
7658                 case MPI2_EVENT_PRIMITIVE_CHANGE:
7659                         mptsas_smhba_log_sysevent(mpt,
7660                             ESC_SAS_HBA_PORT_BROADCAST,
7661                             SAS_PORT_BROADCAST_CHANGE,
7662                             &mpt->m_phy_info[phy_num].smhba_info);
7663                         break;
7664                 case MPI2_EVENT_PRIMITIVE_SES:
7665                         mptsas_smhba_log_sysevent(mpt,
7666                             ESC_SAS_HBA_PORT_BROADCAST,
7667                             SAS_PORT_BROADCAST_SES,
7668                             &mpt->m_phy_info[phy_num].smhba_info);
7669                         break;
7670                 case MPI2_EVENT_PRIMITIVE_EXPANDER:
7671                         mptsas_smhba_log_sysevent(mpt,
7672                             ESC_SAS_HBA_PORT_BROADCAST,
7673                             SAS_PORT_BROADCAST_D01_4,
7674                             &mpt->m_phy_info[phy_num].smhba_info);
7675                         break;
7676                 case MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT:
7677                         mptsas_smhba_log_sysevent(mpt,
7678                             ESC_SAS_HBA_PORT_BROADCAST,
7679                             SAS_PORT_BROADCAST_D04_7,
7680                             &mpt->m_phy_info[phy_num].smhba_info);
7681                         break;
7682                 case MPI2_EVENT_PRIMITIVE_RESERVED3:
7683                         mptsas_smhba_log_sysevent(mpt,
7684                             ESC_SAS_HBA_PORT_BROADCAST,
7685                             SAS_PORT_BROADCAST_D16_7,
7686                             &mpt->m_phy_info[phy_num].smhba_info);
7687                         break;
7688                 case MPI2_EVENT_PRIMITIVE_RESERVED4:
7689                         mptsas_smhba_log_sysevent(mpt,
7690                             ESC_SAS_HBA_PORT_BROADCAST,
7691                             SAS_PORT_BROADCAST_D29_7,
7692                             &mpt->m_phy_info[phy_num].smhba_info);
7693                         break;
7694                 case MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED:
7695                         mptsas_smhba_log_sysevent(mpt,
7696                             ESC_SAS_HBA_PORT_BROADCAST,
7697                             SAS_PORT_BROADCAST_D24_0,
7698                             &mpt->m_phy_info[phy_num].smhba_info);
7699                         break;
7700                 case MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED:
7701                         mptsas_smhba_log_sysevent(mpt,
7702                             ESC_SAS_HBA_PORT_BROADCAST,
7703                             SAS_PORT_BROADCAST_D27_4,
7704                             &mpt->m_phy_info[phy_num].smhba_info);
7705                         break;
7706                 default:
7707                         NDBG20(("mptsas%d: unknown BROADCAST PRIMITIVE"
7708                             " %x received",
7709                             mpt->m_instance, primitive));
7710                         break;
7711                 }
7712                 NDBG20(("mptsas%d sas broadcast primitive: "
7713                     "\tprimitive(0x%04x), phy(%d) complete\n",
7714                     mpt->m_instance, primitive, phy_num));
7715                 break;
7716         }
7717         case MPI2_EVENT_IR_VOLUME:
7718         {
7719                 Mpi2EventDataIrVolume_t         *irVolume;
7720                 uint16_t                        devhandle;
7721                 uint32_t                        state;
7722                 int                             config, vol;
7723                 mptsas_slots_t                  *slots = mpt->m_active;
7724                 uint8_t                         found = FALSE;
7725 
7726                 irVolume = (pMpi2EventDataIrVolume_t)eventreply->EventData;
7727                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7728                     &irVolume->NewValue);
7729                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7730                     &irVolume->VolDevHandle);
7731 
7732                 NDBG20(("EVENT_IR_VOLUME event is received"));
7733 
7734                 /*
7735                  * Get latest RAID info and then find the DevHandle for this
7736                  * event in the configuration.  If the DevHandle is not found
7737                  * just exit the event.
7738                  */
7739                 (void) mptsas_get_raid_info(mpt);
7740                 for (config = 0; (config < slots->m_num_raid_configs) &&
7741                     (!found); config++) {
7742                         for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
7743                                 if (slots->m_raidconfig[config].m_raidvol[vol].
7744                                     m_raidhandle == devhandle) {
7745                                         found = TRUE;
7746                                         break;
7747                                 }
7748                         }
7749                 }
7750                 if (!found) {
7751                         break;
7752                 }
7753 
7754                 switch (irVolume->ReasonCode) {
7755                 case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
7756                 {
7757                         uint32_t i;
7758                         slots->m_raidconfig[config].m_raidvol[vol].m_settings =
7759                             state;
7760 
7761                         i = state & MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING;
7762                         mptsas_log(mpt, CE_NOTE, " Volume %d settings changed"
7763                             ", auto-config of hot-swap drives is %s"
7764                             ", write caching is %s"
7765                             ", hot-spare pool mask is %02x\n",
7766                             vol, state &
7767                             MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE
7768                             ? "disabled" : "enabled",
7769                             i == MPI2_RAIDVOL0_SETTING_UNCHANGED
7770                             ? "controlled by member disks" :
7771                             i == MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING
7772                             ? "disabled" :
7773                             i == MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING
7774                             ? "enabled" :
7775                             "incorrectly set",
7776                             (state >> 16) & 0xff);
7777                                 break;
7778                 }
7779                 case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
7780                 {
7781                         slots->m_raidconfig[config].m_raidvol[vol].m_state =
7782                             (uint8_t)state;
7783 
7784                         mptsas_log(mpt, CE_NOTE,
7785                             "Volume %d is now %s\n", vol,
7786                             state == MPI2_RAID_VOL_STATE_OPTIMAL
7787                             ? "optimal" :
7788                             state == MPI2_RAID_VOL_STATE_DEGRADED
7789                             ? "degraded" :
7790                             state == MPI2_RAID_VOL_STATE_ONLINE
7791                             ? "online" :
7792                             state == MPI2_RAID_VOL_STATE_INITIALIZING
7793                             ? "initializing" :
7794                             state == MPI2_RAID_VOL_STATE_FAILED
7795                             ? "failed" :
7796                             state == MPI2_RAID_VOL_STATE_MISSING
7797                             ? "missing" :
7798                             "state unknown");
7799                         break;
7800                 }
7801                 case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
7802                 {
7803                         slots->m_raidconfig[config].m_raidvol[vol].
7804                             m_statusflags = state;
7805 
7806                         mptsas_log(mpt, CE_NOTE,
7807                             " Volume %d is now %s%s%s%s%s%s%s%s%s\n",
7808                             vol,
7809                             state & MPI2_RAIDVOL0_STATUS_FLAG_ENABLED
7810                             ? ", enabled" : ", disabled",
7811                             state & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED
7812                             ? ", quiesced" : "",
7813                             state & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE
7814                             ? ", inactive" : ", active",
7815                             state &
7816                             MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL
7817                             ? ", bad block table is full" : "",
7818                             state &
7819                             MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
7820                             ? ", resync in progress" : "",
7821                             state & MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT
7822                             ? ", background initialization in progress" : "",
7823                             state &
7824                             MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION
7825                             ? ", capacity expansion in progress" : "",
7826                             state &
7827                             MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK
7828                             ? ", consistency check in progress" : "",
7829                             state & MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB
7830                             ? ", data scrub in progress" : "");
7831                         break;
7832                 }
7833                 default:
7834                         break;
7835                 }
7836                 break;
7837         }
7838         case MPI2_EVENT_IR_PHYSICAL_DISK:
7839         {
7840                 Mpi2EventDataIrPhysicalDisk_t   *irPhysDisk;
7841                 uint16_t                        devhandle, enchandle, slot;
7842                 uint32_t                        status, state;
7843                 uint8_t                         physdisknum, reason;
7844 
7845                 irPhysDisk = (Mpi2EventDataIrPhysicalDisk_t *)
7846                     eventreply->EventData;
7847                 physdisknum = ddi_get8(mpt->m_acc_reply_frame_hdl,
7848                     &irPhysDisk->PhysDiskNum);
7849                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7850                     &irPhysDisk->PhysDiskDevHandle);
7851                 enchandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7852                     &irPhysDisk->EnclosureHandle);
7853                 slot = ddi_get16(mpt->m_acc_reply_frame_hdl,
7854                     &irPhysDisk->Slot);
7855                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7856                     &irPhysDisk->NewValue);
7857                 reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
7858                     &irPhysDisk->ReasonCode);
7859 
7860                 NDBG20(("EVENT_IR_PHYSICAL_DISK event is received"));
7861 
7862                 switch (reason) {
7863                 case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
7864                         mptsas_log(mpt, CE_NOTE,
7865                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7866                             "for enclosure with handle 0x%x is now in hot "
7867                             "spare pool %d",
7868                             physdisknum, devhandle, slot, enchandle,
7869                             (state >> 16) & 0xff);
7870                         break;
7871 
7872                 case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
7873                         status = state;
7874                         mptsas_log(mpt, CE_NOTE,
7875                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7876                             "for enclosure with handle 0x%x is now "
7877                             "%s%s%s%s%s\n", physdisknum, devhandle, slot,
7878                             enchandle,
7879                             status & MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME
7880                             ? ", inactive" : ", active",
7881                             status & MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
7882                             ? ", out of sync" : "",
7883                             status & MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED
7884                             ? ", quiesced" : "",
7885                             status &
7886                             MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED
7887                             ? ", write cache enabled" : "",
7888                             status & MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET
7889                             ? ", capacity expansion target" : "");
7890                         break;
7891 
7892                 case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
7893                         mptsas_log(mpt, CE_NOTE,
7894                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7895                             "for enclosure with handle 0x%x is now %s\n",
7896                             physdisknum, devhandle, slot, enchandle,
7897                             state == MPI2_RAID_PD_STATE_OPTIMAL
7898                             ? "optimal" :
7899                             state == MPI2_RAID_PD_STATE_REBUILDING
7900                             ? "rebuilding" :
7901                             state == MPI2_RAID_PD_STATE_DEGRADED
7902                             ? "degraded" :
7903                             state == MPI2_RAID_PD_STATE_HOT_SPARE
7904                             ? "a hot spare" :
7905                             state == MPI2_RAID_PD_STATE_ONLINE
7906                             ? "online" :
7907                             state == MPI2_RAID_PD_STATE_OFFLINE
7908                             ? "offline" :
7909                             state == MPI2_RAID_PD_STATE_NOT_COMPATIBLE
7910                             ? "not compatible" :
7911                             state == MPI2_RAID_PD_STATE_NOT_CONFIGURED
7912                             ? "not configured" :
7913                             "state unknown");
7914                         break;
7915                 }
7916                 break;
7917         }
7918         default:
7919                 NDBG20(("mptsas%d: unknown event %x received",
7920                     mpt->m_instance, event));
7921                 break;
7922         }
7923 
7924         /*
7925          * Return the reply frame to the free queue.
7926          */
7927         ddi_put32(mpt->m_acc_free_queue_hdl,
7928             &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index], rfm);
7929         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
7930             DDI_DMA_SYNC_FORDEV);
7931         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
7932                 mpt->m_free_index = 0;
7933         }
7934         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
7935             mpt->m_free_index);
7936         mutex_exit(&mpt->m_mutex);
7937 }
7938 
7939 /*
7940  * invoked from timeout() to restart qfull cmds with throttle == 0
7941  */
7942 static void
7943 mptsas_restart_cmd(void *arg)
7944 {
7945         mptsas_t        *mpt = arg;
7946         mptsas_target_t *ptgt = NULL;
7947 
7948         mutex_enter(&mpt->m_mutex);
7949 
7950         mpt->m_restart_cmd_timeid = 0;
7951 
7952         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
7953             MPTSAS_HASH_FIRST);
7954         while (ptgt != NULL) {
7955                 mutex_enter(&ptgt->m_tgt_intr_mutex);
7956                 if (ptgt->m_reset_delay == 0) {
7957                         if (ptgt->m_t_throttle == QFULL_THROTTLE) {
7958                                 mptsas_set_throttle(mpt, ptgt,
7959                                     MAX_THROTTLE);
7960                         }
7961                 }
7962                 mutex_exit(&ptgt->m_tgt_intr_mutex);
7963 
7964                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
7965                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
7966         }
7967         mptsas_restart_hba(mpt);
7968         mutex_exit(&mpt->m_mutex);
7969 }
7970 
7971 /*
7972  * mptsas_remove_cmd0 is similar to mptsas_remove_cmd except that it is called
7973  * where m_intr_mutex has already been held.
7974  */
7975 void
7976 mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
7977 {
7978         ASSERT(mutex_owned(&mpt->m_mutex));
7979 
7980         /*
7981          * With new fine-grained lock mechanism, the outstanding cmd is only
7982          * linked to m_active before the dma is triggerred(MPTSAS_START_CMD)
7983          * to send it. that is, mptsas_save_cmd() doesn't link the outstanding
7984          * cmd now. So when mptsas_remove_cmd is called, a mptsas_save_cmd must
7985          * have been called, but the cmd may have not been linked.
7986          * For mptsas_remove_cmd0, the cmd must have been linked.
7987          * In order to keep the same semantic, we link the cmd to the
7988          * outstanding cmd list.
7989          */
7990         mpt->m_active->m_slot[cmd->cmd_slot] = cmd;
7991 
7992         mutex_enter(&mpt->m_intr_mutex);
7993         mptsas_remove_cmd0(mpt, cmd);
7994         mutex_exit(&mpt->m_intr_mutex);
7995 }
7996 
7997 static inline void
7998 mptsas_remove_cmd0(mptsas_t *mpt, mptsas_cmd_t *cmd)
7999 {
8000         int             slot;
8001         mptsas_slots_t  *slots = mpt->m_active;
8002         int             t;
8003         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8004         mptsas_slot_free_e_t    *pe;
8005 
8006         ASSERT(cmd != NULL);
8007         ASSERT(cmd->cmd_queued == FALSE);
8008 
8009         /*
8010          * Task Management cmds are removed in their own routines.  Also,
8011          * we don't want to modify timeout based on TM cmds.
8012          */
8013         if (cmd->cmd_flags & CFLAG_TM_CMD) {
8014                 return;
8015         }
8016 
8017         t = Tgt(cmd);
8018         slot = cmd->cmd_slot;
8019         pe = mpt->m_slot_free_ae + slot - 1;
8020         ASSERT(cmd == slots->m_slot[slot]);
8021         ASSERT((slot > 0) && slot < (mpt->m_max_requests - 1));
8022 
8023         /*
8024          * remove the cmd.
8025          */
8026         mutex_enter(&mpt->m_slot_freeq_pairp[pe->cpuid].
8027             m_slot_releq.s.m_fq_mutex);
8028         NDBG31(("mptsas_remove_cmd0: removing cmd=0x%p", (void *)cmd));
8029         slots->m_slot[slot] = NULL;
8030         ASSERT(pe->slot == slot);
8031         list_insert_tail(&mpt->m_slot_freeq_pairp[pe->cpuid].
8032             m_slot_releq.s.m_fq_list, pe);
8033         mpt->m_slot_freeq_pairp[pe->cpuid].m_slot_releq.s.m_fq_n++;
8034         ASSERT(mpt->m_slot_freeq_pairp[pe->cpuid].
8035             m_slot_releq.s.m_fq_n <= mpt->m_max_requests - 2);
8036         mutex_exit(&mpt->m_slot_freeq_pairp[pe->cpuid].
8037             m_slot_releq.s.m_fq_mutex);
8038 
8039         /*
8040          * only decrement per target ncmds if command
8041          * has a target associated with it.
8042          */
8043         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
8044                 mutex_enter(&ptgt->m_tgt_intr_mutex);
8045                 ptgt->m_t_ncmds--;
8046                 /*
8047                  * reset throttle if we just ran an untagged command
8048                  * to a tagged target
8049                  */
8050                 if ((ptgt->m_t_ncmds == 0) &&
8051                     ((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0)) {
8052                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
8053                 }
8054                 mutex_exit(&ptgt->m_tgt_intr_mutex);
8055         }
8056 
8057         /*
8058          * This is all we need to do for ioc commands.
8059          * The ioc cmds would never be handled in fastpath in ISR, so we make
8060          * sure the mptsas_return_to_pool() would always be called with
8061          * m_mutex protected.
8062          */
8063         if (cmd->cmd_flags & CFLAG_CMDIOC) {
8064                 ASSERT(mutex_owned(&mpt->m_mutex));
8065                 mptsas_return_to_pool(mpt, cmd);
8066                 return;
8067         }
8068 
8069         /*
8070          * Figure out what to set tag Q timeout for...
8071          *
8072          * Optimize: If we have duplicate's of same timeout
8073          * we're using, then we'll use it again until we run
8074          * out of duplicates.  This should be the normal case
8075          * for block and raw I/O.
8076          * If no duplicates, we have to scan through tag que and
8077          * find the longest timeout value and use it.  This is
8078          * going to take a while...
8079          * Add 1 to m_n_slots to account for TM request.
8080          */
8081         mutex_enter(&ptgt->m_tgt_intr_mutex);
8082         if (cmd->cmd_pkt->pkt_time == ptgt->m_timebase) {
8083                 if (--(ptgt->m_dups) == 0) {
8084                         if (ptgt->m_t_ncmds) {
8085                                 mptsas_cmd_t *ssp;
8086                                 uint_t n = 0;
8087                                 ushort_t nslots = (slots->m_n_slots + 1);
8088                                 ushort_t i;
8089                                 /*
8090                                  * This crude check assumes we don't do
8091                                  * this too often which seems reasonable
8092                                  * for block and raw I/O.
8093                                  */
8094                                 for (i = 0; i < nslots; i++) {
8095                                         ssp = slots->m_slot[i];
8096                                         if (ssp && (Tgt(ssp) == t) &&
8097                                             (ssp->cmd_pkt->pkt_time > n)) {
8098                                                 n = ssp->cmd_pkt->pkt_time;
8099                                                 ptgt->m_dups = 1;
8100                                         } else if (ssp && (Tgt(ssp) == t) &&
8101                                             (ssp->cmd_pkt->pkt_time == n)) {
8102                                                 ptgt->m_dups++;
8103                                         }
8104                                 }
8105                                 ptgt->m_timebase = n;
8106                         } else {
8107                                 ptgt->m_dups = 0;
8108                                 ptgt->m_timebase = 0;
8109                         }
8110                 }
8111         }
8112         ptgt->m_timeout = ptgt->m_timebase;
8113 
8114         ASSERT(cmd != slots->m_slot[cmd->cmd_slot]);
8115         mutex_exit(&ptgt->m_tgt_intr_mutex);
8116 }
8117 
8118 /*
8119  * start a fresh request from the top of the device queue.
8120  */
8121 static void
8122 mptsas_restart_hba(mptsas_t *mpt)
8123 {
8124         mptsas_cmd_t    *cmd, *next_cmd;
8125         mptsas_target_t *ptgt = NULL;
8126 
8127         NDBG1(("mptsas_restart_hba: mpt=0x%p", (void *)mpt));
8128 
8129         ASSERT(mutex_owned(&mpt->m_mutex));
8130 
8131         /*
8132          * If there is a reset delay, don't start any cmds.  Otherwise, start
8133          * as many cmds as possible.
8134          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
8135          * commands is m_max_requests - 2.
8136          */
8137         cmd = mpt->m_waitq;
8138 
8139         while (cmd != NULL) {
8140                 next_cmd = cmd->cmd_linkp;
8141                 if (cmd->cmd_flags & CFLAG_PASSTHRU) {
8142                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8143                                 /*
8144                                  * passthru command get slot need
8145                                  * set CFLAG_PREPARED.
8146                                  */
8147                                 cmd->cmd_flags |= CFLAG_PREPARED;
8148                                 mptsas_waitq_delete(mpt, cmd);
8149                                 mptsas_start_passthru(mpt, cmd);
8150                         }
8151                         cmd = next_cmd;
8152                         continue;
8153                 }
8154                 if (cmd->cmd_flags & CFLAG_CONFIG) {
8155                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8156                                 /*
8157                                  * Send the config page request and delete it
8158                                  * from the waitq.
8159                                  */
8160                                 cmd->cmd_flags |= CFLAG_PREPARED;
8161                                 mptsas_waitq_delete(mpt, cmd);
8162                                 mptsas_start_config_page_access(mpt, cmd);
8163                         }
8164                         cmd = next_cmd;
8165                         continue;
8166                 }
8167                 if (cmd->cmd_flags & CFLAG_FW_DIAG) {
8168                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8169                                 /*
8170                                  * Send the FW Diag request and delete if from
8171                                  * the waitq.
8172                                  */
8173                                 cmd->cmd_flags |= CFLAG_PREPARED;
8174                                 mptsas_waitq_delete(mpt, cmd);
8175                                 mptsas_start_diag(mpt, cmd);
8176                         }
8177                         cmd = next_cmd;
8178                         continue;
8179                 }
8180 
8181                 ptgt = cmd->cmd_tgt_addr;
8182                 if (ptgt) {
8183                         mutex_enter(&mpt->m_intr_mutex);
8184                         mutex_enter(&ptgt->m_tgt_intr_mutex);
8185                         if ((ptgt->m_t_throttle == DRAIN_THROTTLE) &&
8186                             (ptgt->m_t_ncmds == 0)) {
8187                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
8188                         }
8189                         if ((ptgt->m_reset_delay == 0) &&
8190                             (ptgt->m_t_ncmds < ptgt->m_t_throttle)) {
8191                                 mutex_exit(&ptgt->m_tgt_intr_mutex);
8192                                 mutex_exit(&mpt->m_intr_mutex);
8193                                 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8194                                         mptsas_waitq_delete(mpt, cmd);
8195                                         (void) mptsas_start_cmd(mpt, cmd);
8196                                 }
8197                                 goto out;
8198                         }
8199                         mutex_exit(&ptgt->m_tgt_intr_mutex);
8200                         mutex_exit(&mpt->m_intr_mutex);
8201                 }
8202 out:
8203                 cmd = next_cmd;
8204         }
8205 }
8206 
8207 /*
8208  * mpt tag type lookup
8209  */
8210 static char mptsas_tag_lookup[] =
8211         {0, MSG_HEAD_QTAG, MSG_ORDERED_QTAG, 0, MSG_SIMPLE_QTAG};
8212 
8213 /*
8214  * mptsas_start_cmd0 is similar to mptsas_start_cmd, except that, it is called
8215  * without ANY mutex protected, while, mptsas_start_cmd is called with m_mutex
8216  * protected.
8217  *
8218  * the relevant field in ptgt should be protected by m_tgt_intr_mutex in both
8219  * functions.
8220  *
8221  * before the cmds are linked on the slot for monitor as outstanding cmds, they
8222  * are accessed as slab objects, so slab framework ensures the exclusive access,
8223  * and no other mutex is requireed. Linking for monitor and the trigger of dma
8224  * must be done exclusively.
8225  */
8226 static int
8227 mptsas_start_cmd0(mptsas_t *mpt, mptsas_cmd_t *cmd)
8228 {
8229         struct scsi_pkt         *pkt = CMD2PKT(cmd);
8230         uint32_t                control = 0;
8231         int                     n;
8232         caddr_t                 mem;
8233         pMpi2SCSIIORequest_t    io_request;
8234         ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
8235         ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
8236         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
8237         uint16_t                SMID, io_flags = 0;
8238         uint32_t                request_desc_low, request_desc_high;
8239 
8240         NDBG1(("mptsas_start_cmd0: cmd=0x%p", (void *)cmd));
8241 
8242         /*
8243          * Set SMID and increment index.  Rollover to 1 instead of 0 if index
8244          * is at the max.  0 is an invalid SMID, so we call the first index 1.
8245          */
8246         SMID = cmd->cmd_slot;
8247 
8248         /*
8249          * It is possible for back to back device reset to
8250          * happen before the reset delay has expired.  That's
8251          * ok, just let the device reset go out on the bus.
8252          */
8253         if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
8254                 ASSERT(ptgt->m_reset_delay == 0);
8255         }
8256 
8257         /*
8258          * if a non-tagged cmd is submitted to an active tagged target
8259          * then drain before submitting this cmd; SCSI-2 allows RQSENSE
8260          * to be untagged
8261          */
8262         mutex_enter(&ptgt->m_tgt_intr_mutex);
8263         if (((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0) &&
8264             (ptgt->m_t_ncmds > 1) &&
8265             ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) &&
8266             (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE)) {
8267                 if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
8268                         NDBG23(("target=%d, untagged cmd, start draining\n",
8269                             ptgt->m_devhdl));
8270 
8271                         if (ptgt->m_reset_delay == 0) {
8272                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
8273                         }
8274                         mutex_exit(&ptgt->m_tgt_intr_mutex);
8275 
8276                         mutex_enter(&mpt->m_mutex);
8277                         mptsas_remove_cmd(mpt, cmd);
8278                         cmd->cmd_pkt_flags |= FLAG_HEAD;
8279                         mptsas_waitq_add(mpt, cmd);
8280                         mutex_exit(&mpt->m_mutex);
8281                         return (DDI_FAILURE);
8282                 }
8283                 mutex_exit(&ptgt->m_tgt_intr_mutex);
8284                 return (DDI_FAILURE);
8285         }
8286         mutex_exit(&ptgt->m_tgt_intr_mutex);
8287 
8288         /*
8289          * Set correct tag bits.
8290          */
8291         if (cmd->cmd_pkt_flags & FLAG_TAGMASK) {
8292                 switch (mptsas_tag_lookup[((cmd->cmd_pkt_flags &
8293                     FLAG_TAGMASK) >> 12)]) {
8294                 case MSG_SIMPLE_QTAG:
8295                         control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
8296                         break;
8297                 case MSG_HEAD_QTAG:
8298                         control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
8299                         break;
8300                 case MSG_ORDERED_QTAG:
8301                         control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
8302                         break;
8303                 default:
8304                         mptsas_log(mpt, CE_WARN, "mpt: Invalid tag type\n");
8305                         break;
8306                 }
8307         } else {
8308                 if (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE) {
8309                                 ptgt->m_t_throttle = 1;
8310                 }
8311                 control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
8312         }
8313 
8314         if (cmd->cmd_pkt_flags & FLAG_TLR) {
8315                 control |= MPI2_SCSIIO_CONTROL_TLR_ON;
8316         }
8317 
8318         mem = mpt->m_req_frame + (mpt->m_req_frame_size * SMID);
8319         io_request = (pMpi2SCSIIORequest_t)mem;
8320 
8321         bzero(io_request, sizeof (Mpi2SCSIIORequest_t));
8322         ddi_put8(acc_hdl, &io_request->SGLOffset0, offsetof
8323             (MPI2_SCSI_IO_REQUEST, SGL) / 4);
8324         mptsas_init_std_hdr(acc_hdl, io_request, ptgt->m_devhdl, Lun(cmd), 0,
8325             MPI2_FUNCTION_SCSI_IO_REQUEST);
8326 
8327         (void) ddi_rep_put8(acc_hdl, (uint8_t *)pkt->pkt_cdbp,
8328             io_request->CDB.CDB32, cmd->cmd_cdblen, DDI_DEV_AUTOINCR);
8329 
8330         io_flags = cmd->cmd_cdblen;
8331         ddi_put16(acc_hdl, &io_request->IoFlags, io_flags);
8332         /*
8333          * setup the Scatter/Gather DMA list for this request
8334          */
8335         if (cmd->cmd_cookiec > 0) {
8336                 mptsas_sge_setup(mpt, cmd, &control, io_request, acc_hdl);
8337         } else {
8338                 ddi_put32(acc_hdl, &io_request->SGL.MpiSimple.FlagsLength,
8339                     ((uint32_t)MPI2_SGE_FLAGS_LAST_ELEMENT |
8340                     MPI2_SGE_FLAGS_END_OF_BUFFER |
8341                     MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
8342                     MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
8343         }
8344 
8345         /*
8346          * save ARQ information
8347          */
8348         ddi_put8(acc_hdl, &io_request->SenseBufferLength, cmd->cmd_rqslen);
8349         if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
8350             (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
8351                 ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
8352                     cmd->cmd_ext_arqcookie.dmac_address);
8353         } else {
8354                 ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
8355                     cmd->cmd_arqcookie.dmac_address);
8356         }
8357 
8358         ddi_put32(acc_hdl, &io_request->Control, control);
8359 
8360         NDBG31(("starting message=0x%p, with cmd=0x%p",
8361             (void *)(uintptr_t)mpt->m_req_frame_dma_addr, (void *)cmd));
8362 
8363         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
8364 
8365         /*
8366          * Build request descriptor and write it to the request desc post reg.
8367          */
8368         request_desc_low = (SMID << 16) + MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
8369         request_desc_high = ptgt->m_devhdl << 16;
8370 
8371         mutex_enter(&mpt->m_mutex);
8372         mpt->m_active->m_slot[cmd->cmd_slot] = cmd;
8373         MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
8374         mutex_exit(&mpt->m_mutex);
8375 
8376         /*
8377          * Start timeout.
8378          */
8379         mutex_enter(&ptgt->m_tgt_intr_mutex);
8380 #ifdef MPTSAS_TEST
8381         /*
8382          * Temporarily set timebase = 0;  needed for
8383          * timeout torture test.
8384          */
8385         if (mptsas_test_timeouts) {
8386                 ptgt->m_timebase = 0;
8387         }
8388 #endif
8389         n = pkt->pkt_time - ptgt->m_timebase;
8390 
8391         if (n == 0) {
8392                 (ptgt->m_dups)++;
8393                 ptgt->m_timeout = ptgt->m_timebase;
8394         } else if (n > 0) {
8395                 ptgt->m_timeout =
8396                     ptgt->m_timebase = pkt->pkt_time;
8397                 ptgt->m_dups = 1;
8398         } else if (n < 0) {
8399                 ptgt->m_timeout = ptgt->m_timebase;
8400         }
8401 #ifdef MPTSAS_TEST
8402         /*
8403          * Set back to a number higher than
8404          * mptsas_scsi_watchdog_tick
8405          * so timeouts will happen in mptsas_watchsubr
8406          */
8407         if (mptsas_test_timeouts) {
8408                 ptgt->m_timebase = 60;
8409         }
8410 #endif
8411         mutex_exit(&ptgt->m_tgt_intr_mutex);
8412 
8413         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
8414             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
8415                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8416                 return (DDI_FAILURE);
8417         }
8418         return (DDI_SUCCESS);
8419 }
8420 
8421 static int
8422 mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
8423 {
8424         struct scsi_pkt         *pkt = CMD2PKT(cmd);
8425         uint32_t                control = 0;
8426         int                     n;
8427         caddr_t                 mem;
8428         pMpi2SCSIIORequest_t    io_request;
8429         ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
8430         ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
8431         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
8432         uint16_t                SMID, io_flags = 0;
8433         uint32_t                request_desc_low, request_desc_high;
8434 
8435         NDBG1(("mptsas_start_cmd: cmd=0x%p", (void *)cmd));
8436 
8437         /*
8438          * Set SMID and increment index.  Rollover to 1 instead of 0 if index
8439          * is at the max.  0 is an invalid SMID, so we call the first index 1.
8440          */
8441         SMID = cmd->cmd_slot;
8442 
8443         /*
8444          * It is possible for back to back device reset to
8445          * happen before the reset delay has expired.  That's
8446          * ok, just let the device reset go out on the bus.
8447          */
8448         if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
8449                 ASSERT(ptgt->m_reset_delay == 0);
8450         }
8451 
8452         /*
8453          * if a non-tagged cmd is submitted to an active tagged target
8454          * then drain before submitting this cmd; SCSI-2 allows RQSENSE
8455          * to be untagged
8456          */
8457         mutex_enter(&ptgt->m_tgt_intr_mutex);
8458         if (((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0) &&
8459             (ptgt->m_t_ncmds > 1) &&
8460             ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) &&
8461             (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE)) {
8462                 if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
8463                         NDBG23(("target=%d, untagged cmd, start draining\n",
8464                             ptgt->m_devhdl));
8465 
8466                         if (ptgt->m_reset_delay == 0) {
8467                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
8468                         }
8469                         mutex_exit(&ptgt->m_tgt_intr_mutex);
8470 
8471                         mptsas_remove_cmd(mpt, cmd);
8472                         cmd->cmd_pkt_flags |= FLAG_HEAD;
8473                         mptsas_waitq_add(mpt, cmd);
8474                         return (DDI_FAILURE);
8475                 }
8476                 mutex_exit(&ptgt->m_tgt_intr_mutex);
8477                 return (DDI_FAILURE);
8478         }
8479         mutex_exit(&ptgt->m_tgt_intr_mutex);
8480 
8481         /*
8482          * Set correct tag bits.
8483          */
8484         if (cmd->cmd_pkt_flags & FLAG_TAGMASK) {
8485                 switch (mptsas_tag_lookup[((cmd->cmd_pkt_flags &
8486                     FLAG_TAGMASK) >> 12)]) {
8487                 case MSG_SIMPLE_QTAG:
8488                         control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
8489                         break;
8490                 case MSG_HEAD_QTAG:
8491                         control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
8492                         break;
8493                 case MSG_ORDERED_QTAG:
8494                         control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
8495                         break;
8496                 default:
8497                         mptsas_log(mpt, CE_WARN, "mpt: Invalid tag type\n");
8498                         break;
8499                 }
8500         } else {
8501                 if (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE) {
8502                                 ptgt->m_t_throttle = 1;
8503                 }
8504                 control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
8505         }
8506 
8507         if (cmd->cmd_pkt_flags & FLAG_TLR) {
8508                 control |= MPI2_SCSIIO_CONTROL_TLR_ON;
8509         }
8510 
8511         mem = mpt->m_req_frame + (mpt->m_req_frame_size * SMID);
8512         io_request = (pMpi2SCSIIORequest_t)mem;
8513 
8514         bzero(io_request, sizeof (Mpi2SCSIIORequest_t));
8515         ddi_put8(acc_hdl, &io_request->SGLOffset0, offsetof
8516             (MPI2_SCSI_IO_REQUEST, SGL) / 4);
8517         mptsas_init_std_hdr(acc_hdl, io_request, ptgt->m_devhdl, Lun(cmd), 0,
8518             MPI2_FUNCTION_SCSI_IO_REQUEST);
8519 
8520         (void) ddi_rep_put8(acc_hdl, (uint8_t *)pkt->pkt_cdbp,
8521             io_request->CDB.CDB32, cmd->cmd_cdblen, DDI_DEV_AUTOINCR);
8522 
8523         io_flags = cmd->cmd_cdblen;
8524         ddi_put16(acc_hdl, &io_request->IoFlags, io_flags);
8525         /*
8526          * setup the Scatter/Gather DMA list for this request
8527          */
8528         if (cmd->cmd_cookiec > 0) {
8529                 mptsas_sge_setup(mpt, cmd, &control, io_request, acc_hdl);
8530         } else {
8531                 ddi_put32(acc_hdl, &io_request->SGL.MpiSimple.FlagsLength,
8532                     ((uint32_t)MPI2_SGE_FLAGS_LAST_ELEMENT |
8533                     MPI2_SGE_FLAGS_END_OF_BUFFER |
8534                     MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
8535                     MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
8536         }
8537 
8538         /*
8539          * save ARQ information
8540          */
8541         ddi_put8(acc_hdl, &io_request->SenseBufferLength, cmd->cmd_rqslen);
8542         if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
8543             (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
8544                 ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
8545                     cmd->cmd_ext_arqcookie.dmac_address);
8546         } else {
8547                 ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
8548                     cmd->cmd_arqcookie.dmac_address);
8549         }
8550 
8551         ddi_put32(acc_hdl, &io_request->Control, control);
8552 
8553         NDBG31(("starting message=0x%p, with cmd=0x%p",
8554             (void *)(uintptr_t)mpt->m_req_frame_dma_addr, (void *)cmd));
8555 
8556         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
8557 
8558         /*
8559          * Build request descriptor and write it to the request desc post reg.
8560          */
8561         request_desc_low = (SMID << 16) + MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
8562         request_desc_high = ptgt->m_devhdl << 16;
8563 
8564         mpt->m_active->m_slot[cmd->cmd_slot] = cmd;
8565         MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
8566 
8567         /*
8568          * Start timeout.
8569          */
8570         mutex_enter(&ptgt->m_tgt_intr_mutex);
8571 #ifdef MPTSAS_TEST
8572         /*
8573          * Temporarily set timebase = 0;  needed for
8574          * timeout torture test.
8575          */
8576         if (mptsas_test_timeouts) {
8577                 ptgt->m_timebase = 0;
8578         }
8579 #endif
8580         n = pkt->pkt_time - ptgt->m_timebase;
8581 
8582         if (n == 0) {
8583                 (ptgt->m_dups)++;
8584                 ptgt->m_timeout = ptgt->m_timebase;
8585         } else if (n > 0) {
8586                 ptgt->m_timeout =
8587                     ptgt->m_timebase = pkt->pkt_time;
8588                 ptgt->m_dups = 1;
8589         } else if (n < 0) {
8590                 ptgt->m_timeout = ptgt->m_timebase;
8591         }
8592 #ifdef MPTSAS_TEST
8593         /*
8594          * Set back to a number higher than
8595          * mptsas_scsi_watchdog_tick
8596          * so timeouts will happen in mptsas_watchsubr
8597          */
8598         if (mptsas_test_timeouts) {
8599                 ptgt->m_timebase = 60;
8600         }
8601 #endif
8602         mutex_exit(&ptgt->m_tgt_intr_mutex);
8603 
8604         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
8605             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
8606                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8607                 return (DDI_FAILURE);
8608         }
8609         return (DDI_SUCCESS);
8610 }
8611 
8612 /*
8613  * Select a helper thread to handle current doneq
8614  */
8615 static void
8616 mptsas_deliver_doneq_thread(mptsas_t *mpt)
8617 {
8618         uint64_t                        t, i;
8619         uint32_t                        min = 0xffffffff;
8620         mptsas_doneq_thread_list_t      *item;
8621 
8622         for (i = 0; i < mpt->m_doneq_thread_n; i++) {
8623                 item = &mpt->m_doneq_thread_id[i];
8624                 /*
8625                  * If the completed command on help thread[i] less than
8626                  * doneq_thread_threshold, then pick the thread[i]. Otherwise
8627                  * pick a thread which has least completed command.
8628                  */
8629 
8630                 mutex_enter(&item->mutex);
8631                 if (item->len < mpt->m_doneq_thread_threshold) {
8632                         t = i;
8633                         mutex_exit(&item->mutex);
8634                         break;
8635                 }
8636                 if (item->len < min) {
8637                         min = item->len;
8638                         t = i;
8639                 }
8640                 mutex_exit(&item->mutex);
8641         }
8642         mutex_enter(&mpt->m_doneq_thread_id[t].mutex);
8643         mptsas_doneq_mv(mpt, t);
8644         cv_signal(&mpt->m_doneq_thread_id[t].cv);
8645         mutex_exit(&mpt->m_doneq_thread_id[t].mutex);
8646 }
8647 
8648 /*
8649  * move the current global doneq to the doneq of thread[t]
8650  */
8651 static void
8652 mptsas_doneq_mv(mptsas_t *mpt, uint64_t t)
8653 {
8654         mptsas_cmd_t                    *cmd;
8655         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
8656 
8657         ASSERT(mutex_owned(&item->mutex));
8658         mutex_enter(&mpt->m_intr_mutex);
8659         while ((cmd = mpt->m_doneq) != NULL) {
8660                 if ((mpt->m_doneq = cmd->cmd_linkp) == NULL) {
8661                         mpt->m_donetail = &mpt->m_doneq;
8662                 }
8663                 cmd->cmd_linkp = NULL;
8664                 *item->donetail = cmd;
8665                 item->donetail = &cmd->cmd_linkp;
8666                 mpt->m_doneq_len--;
8667                 item->len++;
8668         }
8669         mutex_exit(&mpt->m_intr_mutex);
8670 }
8671 
8672 void
8673 mptsas_fma_check(mptsas_t *mpt, mptsas_cmd_t *cmd)
8674 {
8675         struct scsi_pkt *pkt = CMD2PKT(cmd);
8676 
8677         /* Check all acc and dma handles */
8678         if ((mptsas_check_acc_handle(mpt->m_datap) !=
8679             DDI_SUCCESS) ||
8680             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
8681             DDI_SUCCESS) ||
8682             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
8683             DDI_SUCCESS) ||
8684             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
8685             DDI_SUCCESS) ||
8686             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
8687             DDI_SUCCESS) ||
8688             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
8689             DDI_SUCCESS) ||
8690             (mptsas_check_acc_handle(mpt->m_config_handle) !=
8691             DDI_SUCCESS)) {
8692                 ddi_fm_service_impact(mpt->m_dip,
8693                     DDI_SERVICE_UNAFFECTED);
8694                 ddi_fm_acc_err_clear(mpt->m_config_handle,
8695                     DDI_FME_VER0);
8696                 pkt->pkt_reason = CMD_TRAN_ERR;
8697                 pkt->pkt_statistics = 0;
8698         }
8699         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
8700             DDI_SUCCESS) ||
8701             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
8702             DDI_SUCCESS) ||
8703             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
8704             DDI_SUCCESS) ||
8705             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
8706             DDI_SUCCESS) ||
8707             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
8708             DDI_SUCCESS)) {
8709                 ddi_fm_service_impact(mpt->m_dip,
8710                     DDI_SERVICE_UNAFFECTED);
8711                 pkt->pkt_reason = CMD_TRAN_ERR;
8712                 pkt->pkt_statistics = 0;
8713         }
8714         if (cmd->cmd_dmahandle &&
8715             (mptsas_check_dma_handle(cmd->cmd_dmahandle) != DDI_SUCCESS)) {
8716                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8717                 pkt->pkt_reason = CMD_TRAN_ERR;
8718                 pkt->pkt_statistics = 0;
8719         }
8720         if ((cmd->cmd_extra_frames &&
8721             ((mptsas_check_dma_handle(cmd->cmd_extra_frames->m_dma_hdl) !=
8722             DDI_SUCCESS) ||
8723             (mptsas_check_acc_handle(cmd->cmd_extra_frames->m_acc_hdl) !=
8724             DDI_SUCCESS)))) {
8725                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8726                 pkt->pkt_reason = CMD_TRAN_ERR;
8727                 pkt->pkt_statistics = 0;
8728         }
8729         if (cmd->cmd_arqhandle &&
8730             (mptsas_check_dma_handle(cmd->cmd_arqhandle) != DDI_SUCCESS)) {
8731                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8732                 pkt->pkt_reason = CMD_TRAN_ERR;
8733                 pkt->pkt_statistics = 0;
8734         }
8735         if (cmd->cmd_ext_arqhandle &&
8736             (mptsas_check_dma_handle(cmd->cmd_ext_arqhandle) != DDI_SUCCESS)) {
8737                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8738                 pkt->pkt_reason = CMD_TRAN_ERR;
8739                 pkt->pkt_statistics = 0;
8740         }
8741 }
8742 
8743 /*
8744  * mptsas_doneq_add0 is similar to mptsas_doneq_add except that it is called
8745  * where m_intr_mutex has already been held.
8746  */
8747 static inline void
8748 mptsas_doneq_add0(mptsas_t *mpt, mptsas_cmd_t *cmd)
8749 {
8750         struct scsi_pkt *pkt = CMD2PKT(cmd);
8751 
8752         NDBG31(("mptsas_doneq_add0: cmd=0x%p", (void *)cmd));
8753 
8754         ASSERT((cmd->cmd_flags & CFLAG_COMPLETED) == 0);
8755         cmd->cmd_linkp = NULL;
8756         cmd->cmd_flags |= CFLAG_FINISHED;
8757         cmd->cmd_flags &= ~CFLAG_IN_TRANSPORT;
8758 
8759         /*
8760          * only add scsi pkts that have completion routines to
8761          * the doneq.  no intr cmds do not have callbacks.
8762          */
8763         if (pkt && (pkt->pkt_comp)) {
8764                 *mpt->m_donetail = cmd;
8765                 mpt->m_donetail = &cmd->cmd_linkp;
8766                 mpt->m_doneq_len++;
8767         }
8768 }
8769 
8770 /*
8771  * These routines manipulate the queue of commands that
8772  * are waiting for their completion routines to be called.
8773  * The queue is usually in FIFO order but on an MP system
8774  * it's possible for the completion routines to get out
8775  * of order. If that's a problem you need to add a global
8776  * mutex around the code that calls the completion routine
8777  * in the interrupt handler.
8778  */
8779 static void
8780 mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8781 {
8782         ASSERT(mutex_owned(&mpt->m_mutex));
8783 
8784         mptsas_fma_check(mpt, cmd);
8785 
8786         mutex_enter(&mpt->m_intr_mutex);
8787         mptsas_doneq_add0(mpt, cmd);
8788         mutex_exit(&mpt->m_intr_mutex);
8789 }
8790 
8791 static mptsas_cmd_t *
8792 mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t)
8793 {
8794         mptsas_cmd_t                    *cmd;
8795         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
8796 
8797         /* pop one off the done queue */
8798         if ((cmd = item->doneq) != NULL) {
8799                 /* if the queue is now empty fix the tail pointer */
8800                 NDBG31(("mptsas_doneq_thread_rm: cmd=0x%p", (void *)cmd));
8801                 if ((item->doneq = cmd->cmd_linkp) == NULL) {
8802                         item->donetail = &item->doneq;
8803                 }
8804                 cmd->cmd_linkp = NULL;
8805                 item->len--;
8806         }
8807         return (cmd);
8808 }
8809 
8810 static void
8811 mptsas_doneq_empty(mptsas_t *mpt)
8812 {
8813         mutex_enter(&mpt->m_intr_mutex);
8814         if (mpt->m_doneq && !mpt->m_in_callback) {
8815                 mptsas_cmd_t    *cmd, *next;
8816                 struct scsi_pkt *pkt;
8817 
8818                 mpt->m_in_callback = 1;
8819                 cmd = mpt->m_doneq;
8820                 mpt->m_doneq = NULL;
8821                 mpt->m_donetail = &mpt->m_doneq;
8822                 mpt->m_doneq_len = 0;
8823 
8824                 mutex_exit(&mpt->m_intr_mutex);
8825 
8826                 /*
8827                  * ONLY in ISR, is it called without m_mutex held, otherwise,
8828                  * it is always called with m_mutex held.
8829                  */
8830                 if ((curthread->t_flag & T_INTR_THREAD) == 0)
8831                         mutex_exit(&mpt->m_mutex);
8832                 /*
8833                  * run the completion routines of all the
8834                  * completed commands
8835                  */
8836                 while (cmd != NULL) {
8837                         next = cmd->cmd_linkp;
8838                         cmd->cmd_linkp = NULL;
8839                         /* run this command's completion routine */
8840                         cmd->cmd_flags |= CFLAG_COMPLETED;
8841                         pkt = CMD2PKT(cmd);
8842                         mptsas_pkt_comp(pkt, cmd);
8843                         cmd = next;
8844                 }
8845                 if ((curthread->t_flag & T_INTR_THREAD) == 0)
8846                         mutex_enter(&mpt->m_mutex);
8847                 mpt->m_in_callback = 0;
8848                 return;
8849         }
8850         mutex_exit(&mpt->m_intr_mutex);
8851 }
8852 
8853 /*
8854  * These routines manipulate the target's queue of pending requests
8855  */
8856 void
8857 mptsas_waitq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8858 {
8859         NDBG7(("mptsas_waitq_add: cmd=0x%p", (void *)cmd));
8860         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8861         cmd->cmd_queued = TRUE;
8862         if (ptgt)
8863                 ptgt->m_t_nwait++;
8864         if (cmd->cmd_pkt_flags & FLAG_HEAD) {
8865                 mutex_enter(&mpt->m_intr_mutex);
8866                 if ((cmd->cmd_linkp = mpt->m_waitq) == NULL) {
8867                         mpt->m_waitqtail = &cmd->cmd_linkp;
8868                 }
8869                 mpt->m_waitq = cmd;
8870                 mutex_exit(&mpt->m_intr_mutex);
8871         } else {
8872                 cmd->cmd_linkp = NULL;
8873                 *(mpt->m_waitqtail) = cmd;
8874                 mpt->m_waitqtail = &cmd->cmd_linkp;
8875         }
8876 }
8877 
8878 static mptsas_cmd_t *
8879 mptsas_waitq_rm(mptsas_t *mpt)
8880 {
8881         mptsas_cmd_t    *cmd;
8882         mptsas_target_t *ptgt;
8883         NDBG7(("mptsas_waitq_rm"));
8884 
8885         mutex_enter(&mpt->m_intr_mutex);
8886         MPTSAS_WAITQ_RM(mpt, cmd);
8887         mutex_exit(&mpt->m_intr_mutex);
8888 
8889         NDBG7(("mptsas_waitq_rm: cmd=0x%p", (void *)cmd));
8890         if (cmd) {
8891                 ptgt = cmd->cmd_tgt_addr;
8892                 if (ptgt) {
8893                         ptgt->m_t_nwait--;
8894                         ASSERT(ptgt->m_t_nwait >= 0);
8895                 }
8896         }
8897         return (cmd);
8898 }
8899 
8900 /*
8901  * remove specified cmd from the middle of the wait queue.
8902  */
8903 static void
8904 mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8905 {
8906         mptsas_cmd_t    *prevp = mpt->m_waitq;
8907         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8908 
8909         NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8910             (void *)mpt, (void *)cmd));
8911         if (ptgt) {
8912                 ptgt->m_t_nwait--;
8913                 ASSERT(ptgt->m_t_nwait >= 0);
8914         }
8915 
8916         if (prevp == cmd) {
8917                 mutex_enter(&mpt->m_intr_mutex);
8918                 if ((mpt->m_waitq = cmd->cmd_linkp) == NULL)
8919                         mpt->m_waitqtail = &mpt->m_waitq;
8920                 mutex_exit(&mpt->m_intr_mutex);
8921 
8922                 cmd->cmd_linkp = NULL;
8923                 cmd->cmd_queued = FALSE;
8924                 NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8925                     (void *)mpt, (void *)cmd));
8926                 return;
8927         }
8928 
8929         while (prevp != NULL) {
8930                 if (prevp->cmd_linkp == cmd) {
8931                         if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8932                                 mpt->m_waitqtail = &prevp->cmd_linkp;
8933 
8934                         cmd->cmd_linkp = NULL;
8935                         cmd->cmd_queued = FALSE;
8936                         NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8937                             (void *)mpt, (void *)cmd));
8938                         return;
8939                 }
8940                 prevp = prevp->cmd_linkp;
8941         }
8942         cmn_err(CE_PANIC, "mpt: mptsas_waitq_delete: queue botch");
8943 }
8944 
8945 /*
8946  * device and bus reset handling
8947  *
8948  * Notes:
8949  *      - RESET_ALL:    reset the controller
8950  *      - RESET_TARGET: reset the target specified in scsi_address
8951  */
8952 static int
8953 mptsas_scsi_reset(struct scsi_address *ap, int level)
8954 {
8955         mptsas_t                *mpt = ADDR2MPT(ap);
8956         int                     rval;
8957         mptsas_tgt_private_t    *tgt_private;
8958         mptsas_target_t         *ptgt = NULL;
8959 
8960         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->tran_tgt_private;
8961         ptgt = tgt_private->t_private;
8962         if (ptgt == NULL) {
8963                 return (FALSE);
8964         }
8965         NDBG22(("mptsas_scsi_reset: target=%d level=%d", ptgt->m_devhdl,
8966             level));
8967 
8968         mutex_enter(&mpt->m_mutex);
8969         /*
8970          * if we are not in panic set up a reset delay for this target
8971          */
8972         if (!ddi_in_panic()) {
8973                 mptsas_setup_bus_reset_delay(mpt);
8974         } else {
8975                 drv_usecwait(mpt->m_scsi_reset_delay * 1000);
8976         }
8977         rval = mptsas_do_scsi_reset(mpt, ptgt->m_devhdl);
8978         mutex_exit(&mpt->m_mutex);
8979 
8980         /*
8981          * The transport layer expect to only see TRUE and
8982          * FALSE. Therefore, we will adjust the return value
8983          * if mptsas_do_scsi_reset returns FAILED.
8984          */
8985         if (rval == FAILED)
8986                 rval = FALSE;
8987         return (rval);
8988 }
8989 
8990 static int
8991 mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl)
8992 {
8993         int             rval = FALSE;
8994         uint8_t         config, disk;
8995         mptsas_slots_t  *slots = mpt->m_active;
8996 
8997         ASSERT(mutex_owned(&mpt->m_mutex));
8998 
8999         if (mptsas_debug_resets) {
9000                 mptsas_log(mpt, CE_WARN, "mptsas_do_scsi_reset: target=%d",
9001                     devhdl);
9002         }
9003 
9004         /*
9005          * Issue a Target Reset message to the target specified but not to a
9006          * disk making up a raid volume.  Just look through the RAID config
9007          * Phys Disk list of DevHandles.  If the target's DevHandle is in this
9008          * list, then don't reset this target.
9009          */
9010         for (config = 0; config < slots->m_num_raid_configs; config++) {
9011                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
9012                         if (devhdl == slots->m_raidconfig[config].
9013                             m_physdisk_devhdl[disk]) {
9014                                 return (TRUE);
9015                         }
9016                 }
9017         }
9018 
9019         rval = mptsas_ioc_task_management(mpt,
9020             MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, devhdl, 0, NULL, 0, 0);
9021 
9022         mptsas_doneq_empty(mpt);
9023         return (rval);
9024 }
9025 
9026 static int
9027 mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
9028         void (*callback)(caddr_t), caddr_t arg)
9029 {
9030         mptsas_t        *mpt = ADDR2MPT(ap);
9031 
9032         NDBG22(("mptsas_scsi_reset_notify: tgt=%d", ap->a_target));
9033 
9034         return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
9035             &mpt->m_mutex, &mpt->m_reset_notify_listf));
9036 }
9037 
9038 static int
9039 mptsas_get_name(struct scsi_device *sd, char *name, int len)
9040 {
9041         dev_info_t      *lun_dip = NULL;
9042 
9043         ASSERT(sd != NULL);
9044         ASSERT(name != NULL);
9045         lun_dip = sd->sd_dev;
9046         ASSERT(lun_dip != NULL);
9047 
9048         if (mptsas_name_child(lun_dip, name, len) == DDI_SUCCESS) {
9049                 return (1);
9050         } else {
9051                 return (0);
9052         }
9053 }
9054 
9055 static int
9056 mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len)
9057 {
9058         return (mptsas_get_name(sd, name, len));
9059 }
9060 
9061 void
9062 mptsas_set_throttle(mptsas_t *mpt, mptsas_target_t *ptgt, int what)
9063 {
9064 
9065         NDBG25(("mptsas_set_throttle: throttle=%x", what));
9066 
9067         /*
9068          * if the bus is draining/quiesced, no changes to the throttles
9069          * are allowed. Not allowing change of throttles during draining
9070          * limits error recovery but will reduce draining time
9071          *
9072          * all throttles should have been set to HOLD_THROTTLE
9073          */
9074         if (mpt->m_softstate & (MPTSAS_SS_QUIESCED | MPTSAS_SS_DRAINING)) {
9075                 return;
9076         }
9077 
9078         if (what == HOLD_THROTTLE) {
9079                 ptgt->m_t_throttle = HOLD_THROTTLE;
9080         } else if (ptgt->m_reset_delay == 0) {
9081                 ptgt->m_t_throttle = what;
9082         }
9083 }
9084 
9085 /*
9086  * Clean up from a device reset.
9087  * For the case of target reset, this function clears the waitq of all
9088  * commands for a particular target.   For the case of abort task set, this
9089  * function clears the waitq of all commonds for a particular target/lun.
9090  */
9091 static void
9092 mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun, uint8_t tasktype)
9093 {
9094         mptsas_slots_t  *slots = mpt->m_active;
9095         mptsas_cmd_t    *cmd, *next_cmd;
9096         int             slot;
9097         uchar_t         reason;
9098         uint_t          stat;
9099 
9100         NDBG25(("mptsas_flush_target: target=%d lun=%d", target, lun));
9101 
9102         /*
9103          * Make sure the I/O Controller has flushed all cmds
9104          * that are associated with this target for a target reset
9105          * and target/lun for abort task set.
9106          * Account for TM requests, which use the last SMID.
9107          */
9108         mutex_enter(&mpt->m_intr_mutex);
9109         for (slot = 0; slot <= mpt->m_active->m_n_slots; slot++) {
9110                 if ((cmd = slots->m_slot[slot]) == NULL) {
9111                         continue;
9112                 }
9113                 reason = CMD_RESET;
9114                 stat = STAT_DEV_RESET;
9115                 switch (tasktype) {
9116                 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
9117                         if (Tgt(cmd) == target) {
9118                                 NDBG25(("mptsas_flush_target discovered non-"
9119                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
9120                                     tasktype));
9121                                 mptsas_dump_cmd(mpt, cmd);
9122                                 mptsas_remove_cmd0(mpt, cmd);
9123                                 mptsas_set_pkt_reason(mpt, cmd, reason, stat);
9124                                 mptsas_doneq_add0(mpt, cmd);
9125                         }
9126                         break;
9127                 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
9128                         reason = CMD_ABORTED;
9129                         stat = STAT_ABORTED;
9130                         /*FALLTHROUGH*/
9131                 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
9132                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
9133 
9134                                 NDBG25(("mptsas_flush_target discovered non-"
9135                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
9136                                     tasktype));
9137                                 mptsas_dump_cmd(mpt, cmd);
9138                                 mptsas_remove_cmd0(mpt, cmd);
9139                                 mptsas_set_pkt_reason(mpt, cmd, reason,
9140                                     stat);
9141                                 mptsas_doneq_add0(mpt, cmd);
9142                         }
9143                         break;
9144                 default:
9145                         break;
9146                 }
9147         }
9148         mutex_exit(&mpt->m_intr_mutex);
9149 
9150         /*
9151          * Flush the waitq of this target's cmds
9152          */
9153         cmd = mpt->m_waitq;
9154 
9155         reason = CMD_RESET;
9156         stat = STAT_DEV_RESET;
9157 
9158         switch (tasktype) {
9159         case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
9160                 while (cmd != NULL) {
9161                         next_cmd = cmd->cmd_linkp;
9162                         if (Tgt(cmd) == target) {
9163                                 mptsas_waitq_delete(mpt, cmd);
9164                                 mptsas_set_pkt_reason(mpt, cmd,
9165                                     reason, stat);
9166                                 mptsas_doneq_add(mpt, cmd);
9167                         }
9168                         cmd = next_cmd;
9169                 }
9170                 break;
9171         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
9172                 reason = CMD_ABORTED;
9173                 stat =  STAT_ABORTED;
9174                 /*FALLTHROUGH*/
9175         case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
9176                 while (cmd != NULL) {
9177                         next_cmd = cmd->cmd_linkp;
9178                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
9179                                 mptsas_waitq_delete(mpt, cmd);
9180                                 mptsas_set_pkt_reason(mpt, cmd,
9181                                     reason, stat);
9182                                 mptsas_doneq_add(mpt, cmd);
9183                         }
9184                         cmd = next_cmd;
9185                 }
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         mutex_enter(&mpt->m_intr_mutex);
9214         for (slot = 0; slot <= mpt->m_active->m_n_slots; slot++) {
9215                 if ((cmd = slots->m_slot[slot]) == NULL) {
9216                         continue;
9217                 }
9218 
9219                 if (cmd->cmd_flags & CFLAG_CMDIOC) {
9220                         /*
9221                          * Need to make sure to tell everyone that might be
9222                          * waiting on this command that it's going to fail.  If
9223                          * we get here, this command will never timeout because
9224                          * the active command table is going to be re-allocated,
9225                          * so there will be nothing to check against a time out.
9226                          * Instead, mark the command as failed due to reset.
9227                          */
9228                         mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
9229                             STAT_BUS_RESET);
9230                         if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
9231                             (cmd->cmd_flags & CFLAG_CONFIG) ||
9232                             (cmd->cmd_flags & CFLAG_FW_DIAG)) {
9233                                 cmd->cmd_flags |= CFLAG_FINISHED;
9234                                 cv_broadcast(&mpt->m_passthru_cv);
9235                                 cv_broadcast(&mpt->m_config_cv);
9236                                 cv_broadcast(&mpt->m_fw_diag_cv);
9237                         }
9238                         continue;
9239                 }
9240 
9241                 NDBG25(("mptsas_flush_hba discovered non-NULL cmd in slot %d",
9242                     slot));
9243                 mptsas_dump_cmd(mpt, cmd);
9244 
9245                 mptsas_remove_cmd0(mpt, cmd);
9246                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
9247                 mptsas_doneq_add0(mpt, cmd);
9248         }
9249         mutex_exit(&mpt->m_intr_mutex);
9250 
9251         /*
9252          * Flush the waitq.
9253          */
9254         while ((cmd = mptsas_waitq_rm(mpt)) != NULL) {
9255                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
9256                 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
9257                     (cmd->cmd_flags & CFLAG_CONFIG) ||
9258                     (cmd->cmd_flags & CFLAG_FW_DIAG)) {
9259                         cmd->cmd_flags |= CFLAG_FINISHED;
9260                         cv_broadcast(&mpt->m_passthru_cv);
9261                         cv_broadcast(&mpt->m_config_cv);
9262                         cv_broadcast(&mpt->m_fw_diag_cv);
9263                 } else {
9264                         mptsas_doneq_add(mpt, cmd);
9265                 }
9266         }
9267 }
9268 
9269 /*
9270  * set pkt_reason and OR in pkt_statistics flag
9271  */
9272 static void
9273 mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd, uchar_t reason,
9274     uint_t stat)
9275 {
9276 #ifndef __lock_lint
9277         _NOTE(ARGUNUSED(mpt))
9278 #endif
9279 
9280         NDBG25(("mptsas_set_pkt_reason: cmd=0x%p reason=%x stat=%x",
9281             (void *)cmd, reason, stat));
9282 
9283         if (cmd) {
9284                 if (cmd->cmd_pkt->pkt_reason == CMD_CMPLT) {
9285                         cmd->cmd_pkt->pkt_reason = reason;
9286                 }
9287                 cmd->cmd_pkt->pkt_statistics |= stat;
9288         }
9289 }
9290 
9291 static void
9292 mptsas_start_watch_reset_delay()
9293 {
9294         NDBG22(("mptsas_start_watch_reset_delay"));
9295 
9296         mutex_enter(&mptsas_global_mutex);
9297         if (mptsas_reset_watch == NULL && mptsas_timeouts_enabled) {
9298                 mptsas_reset_watch = timeout(mptsas_watch_reset_delay, NULL,
9299                     drv_usectohz((clock_t)
9300                     MPTSAS_WATCH_RESET_DELAY_TICK * 1000));
9301                 ASSERT(mptsas_reset_watch != NULL);
9302         }
9303         mutex_exit(&mptsas_global_mutex);
9304 }
9305 
9306 static void
9307 mptsas_setup_bus_reset_delay(mptsas_t *mpt)
9308 {
9309         mptsas_target_t *ptgt = NULL;
9310 
9311         NDBG22(("mptsas_setup_bus_reset_delay"));
9312         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
9313             MPTSAS_HASH_FIRST);
9314         while (ptgt != NULL) {
9315                 mutex_enter(&ptgt->m_tgt_intr_mutex);
9316                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9317                 ptgt->m_reset_delay = mpt->m_scsi_reset_delay;
9318                 mutex_exit(&ptgt->m_tgt_intr_mutex);
9319 
9320                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
9321                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
9322         }
9323 
9324         mptsas_start_watch_reset_delay();
9325 }
9326 
9327 /*
9328  * mptsas_watch_reset_delay(_subr) is invoked by timeout() and checks every
9329  * mpt instance for active reset delays
9330  */
9331 static void
9332 mptsas_watch_reset_delay(void *arg)
9333 {
9334 #ifndef __lock_lint
9335         _NOTE(ARGUNUSED(arg))
9336 #endif
9337 
9338         mptsas_t        *mpt;
9339         int             not_done = 0;
9340 
9341         NDBG22(("mptsas_watch_reset_delay"));
9342 
9343         mutex_enter(&mptsas_global_mutex);
9344         mptsas_reset_watch = 0;
9345         mutex_exit(&mptsas_global_mutex);
9346         rw_enter(&mptsas_global_rwlock, RW_READER);
9347         for (mpt = mptsas_head; mpt != NULL; mpt = mpt->m_next) {
9348                 if (mpt->m_tran == 0) {
9349                         continue;
9350                 }
9351                 mutex_enter(&mpt->m_mutex);
9352                 not_done += mptsas_watch_reset_delay_subr(mpt);
9353                 mutex_exit(&mpt->m_mutex);
9354         }
9355         rw_exit(&mptsas_global_rwlock);
9356 
9357         if (not_done) {
9358                 mptsas_start_watch_reset_delay();
9359         }
9360 }
9361 
9362 static int
9363 mptsas_watch_reset_delay_subr(mptsas_t *mpt)
9364 {
9365         int             done = 0;
9366         int             restart = 0;
9367         mptsas_target_t *ptgt = NULL;
9368 
9369         NDBG22(("mptsas_watch_reset_delay_subr: mpt=0x%p", (void *)mpt));
9370 
9371         ASSERT(mutex_owned(&mpt->m_mutex));
9372 
9373         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
9374             MPTSAS_HASH_FIRST);
9375         while (ptgt != NULL) {
9376                 mutex_enter(&ptgt->m_tgt_intr_mutex);
9377                 if (ptgt->m_reset_delay != 0) {
9378                         ptgt->m_reset_delay -=
9379                             MPTSAS_WATCH_RESET_DELAY_TICK;
9380                         if (ptgt->m_reset_delay <= 0) {
9381                                 ptgt->m_reset_delay = 0;
9382                                 mptsas_set_throttle(mpt, ptgt,
9383                                     MAX_THROTTLE);
9384                                 restart++;
9385                         } else {
9386                                 done = -1;
9387                         }
9388                 }
9389                 mutex_exit(&ptgt->m_tgt_intr_mutex);
9390 
9391                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
9392                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
9393         }
9394 
9395         if (restart > 0) {
9396                 mptsas_restart_hba(mpt);
9397         }
9398         return (done);
9399 }
9400 
9401 #ifdef MPTSAS_TEST
9402 static void
9403 mptsas_test_reset(mptsas_t *mpt, int target)
9404 {
9405         mptsas_target_t    *ptgt = NULL;
9406 
9407         if (mptsas_rtest == target) {
9408                 if (mptsas_do_scsi_reset(mpt, target) == TRUE) {
9409                         mptsas_rtest = -1;
9410                 }
9411                 if (mptsas_rtest == -1) {
9412                         NDBG22(("mptsas_test_reset success"));
9413                 }
9414         }
9415 }
9416 #endif
9417 
9418 /*
9419  * abort handling:
9420  *
9421  * Notes:
9422  *      - if pkt is not NULL, abort just that command
9423  *      - if pkt is NULL, abort all outstanding commands for target
9424  */
9425 static int
9426 mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
9427 {
9428         mptsas_t                *mpt = ADDR2MPT(ap);
9429         int                     rval;
9430         mptsas_tgt_private_t    *tgt_private;
9431         int                     target, lun;
9432 
9433         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
9434             tran_tgt_private;
9435         ASSERT(tgt_private != NULL);
9436         target = tgt_private->t_private->m_devhdl;
9437         lun = tgt_private->t_lun;
9438 
9439         NDBG23(("mptsas_scsi_abort: target=%d.%d", target, lun));
9440 
9441         mutex_enter(&mpt->m_mutex);
9442         rval = mptsas_do_scsi_abort(mpt, target, lun, pkt);
9443         mutex_exit(&mpt->m_mutex);
9444         return (rval);
9445 }
9446 
9447 static int
9448 mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun, struct scsi_pkt *pkt)
9449 {
9450         mptsas_cmd_t    *sp = NULL;
9451         mptsas_slots_t  *slots = mpt->m_active;
9452         int             rval = FALSE;
9453 
9454         ASSERT(mutex_owned(&mpt->m_mutex));
9455 
9456         /*
9457          * Abort the command pkt on the target/lun in ap.  If pkt is
9458          * NULL, abort all outstanding commands on that target/lun.
9459          * If you can abort them, return 1, else return 0.
9460          * Each packet that's aborted should be sent back to the target
9461          * driver through the callback routine, with pkt_reason set to
9462          * CMD_ABORTED.
9463          *
9464          * abort cmd pkt on HBA hardware; clean out of outstanding
9465          * command lists, etc.
9466          */
9467         if (pkt != NULL) {
9468                 /* abort the specified packet */
9469                 sp = PKT2CMD(pkt);
9470 
9471                 if (sp->cmd_queued) {
9472                         NDBG23(("mptsas_do_scsi_abort: queued sp=0x%p aborted",
9473                             (void *)sp));
9474                         mptsas_waitq_delete(mpt, sp);
9475                         mptsas_set_pkt_reason(mpt, sp, CMD_ABORTED,
9476                             STAT_ABORTED);
9477                         mptsas_doneq_add(mpt, sp);
9478                         rval = TRUE;
9479                         goto done;
9480                 }
9481 
9482                 /*
9483                  * Have mpt firmware abort this command
9484                  */
9485                 mutex_enter(&mpt->m_intr_mutex);
9486                 if (slots->m_slot[sp->cmd_slot] != NULL) {
9487                         mutex_exit(&mpt->m_intr_mutex);
9488                         rval = mptsas_ioc_task_management(mpt,
9489                             MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, target,
9490                             lun, NULL, 0, 0);
9491 
9492                         /*
9493                          * The transport layer expects only TRUE and FALSE.
9494                          * Therefore, if mptsas_ioc_task_management returns
9495                          * FAILED we will return FALSE.
9496                          */
9497                         if (rval == FAILED)
9498                                 rval = FALSE;
9499                         goto done;
9500                 }
9501                 mutex_exit(&mpt->m_intr_mutex);
9502         }
9503 
9504         /*
9505          * If pkt is NULL then abort task set
9506          */
9507         rval = mptsas_ioc_task_management(mpt,
9508             MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, target, lun, NULL, 0, 0);
9509 
9510         /*
9511          * The transport layer expects only TRUE and FALSE.
9512          * Therefore, if mptsas_ioc_task_management returns
9513          * FAILED we will return FALSE.
9514          */
9515         if (rval == FAILED)
9516                 rval = FALSE;
9517 
9518 #ifdef MPTSAS_TEST
9519         if (rval && mptsas_test_stop) {
9520                 debug_enter("mptsas_do_scsi_abort");
9521         }
9522 #endif
9523 
9524 done:
9525         mptsas_doneq_empty(mpt);
9526         return (rval);
9527 }
9528 
9529 /*
9530  * capability handling:
9531  * (*tran_getcap).  Get the capability named, and return its value.
9532  */
9533 static int
9534 mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly)
9535 {
9536         mptsas_t        *mpt = ADDR2MPT(ap);
9537         int             ckey;
9538         int             rval = FALSE;
9539 
9540         NDBG24(("mptsas_scsi_getcap: target=%d, cap=%s tgtonly=%x",
9541             ap->a_target, cap, tgtonly));
9542 
9543         mutex_enter(&mpt->m_mutex);
9544 
9545         if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9546                 mutex_exit(&mpt->m_mutex);
9547                 return (UNDEFINED);
9548         }
9549 
9550         switch (ckey) {
9551         case SCSI_CAP_DMA_MAX:
9552                 rval = (int)mpt->m_msg_dma_attr.dma_attr_maxxfer;
9553                 break;
9554         case SCSI_CAP_ARQ:
9555                 rval = TRUE;
9556                 break;
9557         case SCSI_CAP_MSG_OUT:
9558         case SCSI_CAP_PARITY:
9559         case SCSI_CAP_UNTAGGED_QING:
9560                 rval = TRUE;
9561                 break;
9562         case SCSI_CAP_TAGGED_QING:
9563                 rval = TRUE;
9564                 break;
9565         case SCSI_CAP_RESET_NOTIFICATION:
9566                 rval = TRUE;
9567                 break;
9568         case SCSI_CAP_LINKED_CMDS:
9569                 rval = FALSE;
9570                 break;
9571         case SCSI_CAP_QFULL_RETRIES:
9572                 rval = ((mptsas_tgt_private_t *)(ap->a_hba_tran->
9573                     tran_tgt_private))->t_private->m_qfull_retries;
9574                 break;
9575         case SCSI_CAP_QFULL_RETRY_INTERVAL:
9576                 rval = drv_hztousec(((mptsas_tgt_private_t *)
9577                     (ap->a_hba_tran->tran_tgt_private))->
9578                     t_private->m_qfull_retry_interval) / 1000;
9579                 break;
9580         case SCSI_CAP_CDB_LEN:
9581                 rval = CDB_GROUP4;
9582                 break;
9583         case SCSI_CAP_INTERCONNECT_TYPE:
9584                 rval = INTERCONNECT_SAS;
9585                 break;
9586         case SCSI_CAP_TRAN_LAYER_RETRIES:
9587                 if (mpt->m_ioc_capabilities &
9588                     MPI2_IOCFACTS_CAPABILITY_TLR)
9589                         rval = TRUE;
9590                 else
9591                         rval = FALSE;
9592                 break;
9593         default:
9594                 rval = UNDEFINED;
9595                 break;
9596         }
9597 
9598         NDBG24(("mptsas_scsi_getcap: %s, rval=%x", cap, rval));
9599 
9600         mutex_exit(&mpt->m_mutex);
9601         return (rval);
9602 }
9603 
9604 /*
9605  * (*tran_setcap).  Set the capability named to the value given.
9606  */
9607 static int
9608 mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value, int tgtonly)
9609 {
9610         mptsas_t        *mpt = ADDR2MPT(ap);
9611         int             ckey;
9612         int             rval = FALSE;
9613         mptsas_target_t *ptgt;
9614 
9615         NDBG24(("mptsas_scsi_setcap: target=%d, cap=%s value=%x tgtonly=%x",
9616             ap->a_target, cap, value, tgtonly));
9617 
9618         if (!tgtonly) {
9619                 return (rval);
9620         }
9621 
9622         mutex_enter(&mpt->m_mutex);
9623 
9624         if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9625                 mutex_exit(&mpt->m_mutex);
9626                 return (UNDEFINED);
9627         }
9628 
9629         switch (ckey) {
9630         case SCSI_CAP_DMA_MAX:
9631         case SCSI_CAP_MSG_OUT:
9632         case SCSI_CAP_PARITY:
9633         case SCSI_CAP_INITIATOR_ID:
9634         case SCSI_CAP_LINKED_CMDS:
9635         case SCSI_CAP_UNTAGGED_QING:
9636         case SCSI_CAP_RESET_NOTIFICATION:
9637                 /*
9638                  * None of these are settable via
9639                  * the capability interface.
9640                  */
9641                 break;
9642         case SCSI_CAP_ARQ:
9643                 /*
9644                  * We cannot turn off arq so return false if asked to
9645                  */
9646                 if (value) {
9647                         rval = TRUE;
9648                 } else {
9649                         rval = FALSE;
9650                 }
9651                 break;
9652         case SCSI_CAP_TAGGED_QING:
9653                 ptgt = ((mptsas_tgt_private_t *)
9654                     (ap->a_hba_tran->tran_tgt_private))->t_private;
9655                 mutex_enter(&ptgt->m_tgt_intr_mutex);
9656                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9657                 mutex_exit(&ptgt->m_tgt_intr_mutex);
9658                 rval = TRUE;
9659                 break;
9660         case SCSI_CAP_QFULL_RETRIES:
9661                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9662                     t_private->m_qfull_retries = (uchar_t)value;
9663                 rval = TRUE;
9664                 break;
9665         case SCSI_CAP_QFULL_RETRY_INTERVAL:
9666                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9667                     t_private->m_qfull_retry_interval =
9668                     drv_usectohz(value * 1000);
9669                 rval = TRUE;
9670                 break;
9671         default:
9672                 rval = UNDEFINED;
9673                 break;
9674         }
9675         mutex_exit(&mpt->m_mutex);
9676         return (rval);
9677 }
9678 
9679 /*
9680  * Utility routine for mptsas_ifsetcap/ifgetcap
9681  */
9682 /*ARGSUSED*/
9683 static int
9684 mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp)
9685 {
9686         NDBG24(("mptsas_scsi_capchk: cap=%s", cap));
9687 
9688         if (!cap)
9689                 return (FALSE);
9690 
9691         *cidxp = scsi_hba_lookup_capstr(cap);
9692         return (TRUE);
9693 }
9694 
9695 static int
9696 mptsas_alloc_active_slots(mptsas_t *mpt, int flag)
9697 {
9698         mptsas_slots_t  *old_active = mpt->m_active;
9699         mptsas_slots_t  *new_active;
9700         size_t          size;
9701         int             rval = -1, nslot, i;
9702         mptsas_slot_free_e_t    *pe;
9703 
9704         if (mptsas_outstanding_cmds_n(mpt)) {
9705                 NDBG9(("cannot change size of active slots array"));
9706                 return (rval);
9707         }
9708 
9709         size = MPTSAS_SLOTS_SIZE(mpt);
9710         new_active = kmem_zalloc(size, flag);
9711         if (new_active == NULL) {
9712                 NDBG1(("new active alloc failed"));
9713                 return (rval);
9714         }
9715         /*
9716          * Since SMID 0 is reserved and the TM slot is reserved, the
9717          * number of slots that can be used at any one time is
9718          * m_max_requests - 2.
9719          */
9720         new_active->m_n_slots = nslot = (mpt->m_max_requests - 2);
9721         new_active->m_size = size;
9722         new_active->m_tags = 1;
9723 
9724         if (old_active) {
9725                 new_active->m_tgttbl = old_active->m_tgttbl;
9726                 new_active->m_smptbl = old_active->m_smptbl;
9727                 new_active->m_num_raid_configs =
9728                     old_active->m_num_raid_configs;
9729                 for (i = 0; i < new_active->m_num_raid_configs; i++) {
9730                         new_active->m_raidconfig[i] =
9731                             old_active->m_raidconfig[i];
9732                 }
9733                 mptsas_free_active_slots(mpt);
9734         }
9735 
9736         if (max_ncpus & (max_ncpus - 1)) {
9737                 mpt->m_slot_freeq_pair_n = (1 << highbit(max_ncpus));
9738         } else {
9739                 mpt->m_slot_freeq_pair_n = max_ncpus;
9740         }
9741         mpt->m_slot_freeq_pairp = kmem_zalloc(
9742             mpt->m_slot_freeq_pair_n *
9743             sizeof (mptsas_slot_freeq_pair_t), KM_SLEEP);
9744         for (i = 0; i < mpt->m_slot_freeq_pair_n; i++) {
9745                 list_create(&mpt->m_slot_freeq_pairp[i].
9746                     m_slot_allocq.s.m_fq_list,
9747                     sizeof (mptsas_slot_free_e_t),
9748                     offsetof(mptsas_slot_free_e_t, node));
9749                 list_create(&mpt->m_slot_freeq_pairp[i].
9750                     m_slot_releq.s.m_fq_list,
9751                     sizeof (mptsas_slot_free_e_t),
9752                     offsetof(mptsas_slot_free_e_t, node));
9753                 mpt->m_slot_freeq_pairp[i].m_slot_allocq.s.m_fq_n = 0;
9754                 mpt->m_slot_freeq_pairp[i].m_slot_releq.s.m_fq_n = 0;
9755                 mutex_init(&mpt->m_slot_freeq_pairp[i].
9756                     m_slot_allocq.s.m_fq_mutex, NULL, MUTEX_DRIVER,
9757                     DDI_INTR_PRI(mpt->m_intr_pri));
9758                 mutex_init(&mpt->m_slot_freeq_pairp[i].
9759                     m_slot_releq.s.m_fq_mutex, NULL, MUTEX_DRIVER,
9760                     DDI_INTR_PRI(mpt->m_intr_pri));
9761         }
9762         pe = mpt->m_slot_free_ae = kmem_zalloc(nslot *
9763             sizeof (mptsas_slot_free_e_t), KM_SLEEP);
9764         /*
9765          * An array of Mpi2ReplyDescriptorsUnion_t is defined here.
9766          * We are trying to eliminate the m_mutex in the context
9767          * reply code path in the ISR. Since the read of the
9768          * ReplyDescriptor and update/write of the ReplyIndex must
9769          * be atomic (since the poll thread may also update them at
9770          * the same time) so we first read out of the ReplyDescriptor
9771          * into this array and update the ReplyIndex register with a
9772          * separate mutex m_intr_mutex protected, and then release the
9773          * mutex and process all of them. the length of the array is
9774          * defined as max as 128(128*64=8k), which is
9775          * assumed as the maxmium depth of the interrupt coalese.
9776          */
9777         mpt->m_reply = kmem_zalloc(MPI_ADDRESS_COALSCE_MAX *
9778             sizeof (Mpi2ReplyDescriptorsUnion_t), KM_SLEEP);
9779         for (i = 0; i < nslot; i++, pe++) {
9780                 pe->slot = i + 1; /* SMID 0 is reserved */
9781                 pe->cpuid = i % mpt->m_slot_freeq_pair_n;
9782                 list_insert_tail(&mpt->m_slot_freeq_pairp
9783                     [i % mpt->m_slot_freeq_pair_n]
9784                     .m_slot_allocq.s.m_fq_list, pe);
9785                 mpt->m_slot_freeq_pairp[i % mpt->m_slot_freeq_pair_n]
9786                     .m_slot_allocq.s.m_fq_n++;
9787                 mpt->m_slot_freeq_pairp[i % mpt->m_slot_freeq_pair_n]
9788                     .m_slot_allocq.s.m_fq_n_init++;
9789         }
9790 
9791         mpt->m_active = new_active;
9792         rval = 0;
9793 
9794         return (rval);
9795 }
9796 
9797 static void
9798 mptsas_free_active_slots(mptsas_t *mpt)
9799 {
9800         mptsas_slots_t  *active = mpt->m_active;
9801         size_t          size;
9802         mptsas_slot_free_e_t    *pe;
9803         int     i;
9804 
9805         if (active == NULL)
9806                 return;
9807 
9808         if (mpt->m_slot_freeq_pairp) {
9809                 for (i = 0; i < mpt->m_slot_freeq_pair_n; i++) {
9810                         while ((pe = list_head(&mpt->m_slot_freeq_pairp
9811                             [i].m_slot_allocq.s.m_fq_list)) != NULL) {
9812                                 list_remove(&mpt->m_slot_freeq_pairp[i]
9813                                     .m_slot_allocq.s.m_fq_list, pe);
9814                         }
9815                         list_destroy(&mpt->m_slot_freeq_pairp
9816                             [i].m_slot_allocq.s.m_fq_list);
9817                         while ((pe = list_head(&mpt->m_slot_freeq_pairp
9818                             [i].m_slot_releq.s.m_fq_list)) != NULL) {
9819                                 list_remove(&mpt->m_slot_freeq_pairp[i]
9820                                     .m_slot_releq.s.m_fq_list, pe);
9821                         }
9822                         list_destroy(&mpt->m_slot_freeq_pairp
9823                             [i].m_slot_releq.s.m_fq_list);
9824                         mutex_destroy(&mpt->m_slot_freeq_pairp
9825                             [i].m_slot_allocq.s.m_fq_mutex);
9826                         mutex_destroy(&mpt->m_slot_freeq_pairp
9827                             [i].m_slot_releq.s.m_fq_mutex);
9828                 }
9829                 kmem_free(mpt->m_slot_freeq_pairp, mpt->m_slot_freeq_pair_n *
9830                     sizeof (mptsas_slot_freeq_pair_t));
9831         }
9832         if (mpt->m_slot_free_ae)
9833                 kmem_free(mpt->m_slot_free_ae, mpt->m_active->m_n_slots *
9834                     sizeof (mptsas_slot_free_e_t));
9835 
9836         if (mpt->m_reply)
9837                 kmem_free(mpt->m_reply, MPI_ADDRESS_COALSCE_MAX *
9838                     sizeof (Mpi2ReplyDescriptorsUnion_t));
9839 
9840         size = active->m_size;
9841         kmem_free(active, size);
9842         mpt->m_active = NULL;
9843 }
9844 
9845 /*
9846  * Error logging, printing, and debug print routines.
9847  */
9848 static char *mptsas_label = "mpt_sas";
9849 
9850 /*PRINTFLIKE3*/
9851 void
9852 mptsas_log(mptsas_t *mpt, int level, char *fmt, ...)
9853 {
9854         dev_info_t      *dev;
9855         va_list         ap;
9856 
9857         if (mpt) {
9858                 dev = mpt->m_dip;
9859         } else {
9860                 dev = 0;
9861         }
9862 
9863         mutex_enter(&mptsas_log_mutex);
9864 
9865         va_start(ap, fmt);
9866         (void) vsprintf(mptsas_log_buf, fmt, ap);
9867         va_end(ap);
9868 
9869         if (level == CE_CONT) {
9870                 scsi_log(dev, mptsas_label, level, "%s\n", mptsas_log_buf);
9871         } else {
9872                 scsi_log(dev, mptsas_label, level, "%s", mptsas_log_buf);
9873         }
9874 
9875         mutex_exit(&mptsas_log_mutex);
9876 }
9877 
9878 #ifdef MPTSAS_DEBUG
9879 /*PRINTFLIKE1*/
9880 void
9881 mptsas_printf(char *fmt, ...)
9882 {
9883         dev_info_t      *dev = 0;
9884         va_list         ap;
9885 
9886         mutex_enter(&mptsas_log_mutex);
9887 
9888         va_start(ap, fmt);
9889         (void) vsprintf(mptsas_log_buf, fmt, ap);
9890         va_end(ap);
9891 
9892 #ifdef PROM_PRINTF
9893         prom_printf("%s:\t%s\n", mptsas_label, mptsas_log_buf);
9894 #else
9895         scsi_log(dev, mptsas_label, SCSI_DEBUG, "%s\n", mptsas_log_buf);
9896 #endif
9897         mutex_exit(&mptsas_log_mutex);
9898 }
9899 #endif
9900 
9901 /*
9902  * timeout handling
9903  */
9904 static void
9905 mptsas_watch(void *arg)
9906 {
9907 #ifndef __lock_lint
9908         _NOTE(ARGUNUSED(arg))
9909 #endif
9910 
9911         mptsas_t        *mpt;
9912         uint32_t        doorbell;
9913 
9914         NDBG30(("mptsas_watch"));
9915 
9916         rw_enter(&mptsas_global_rwlock, RW_READER);
9917         for (mpt = mptsas_head; mpt != (mptsas_t *)NULL; mpt = mpt->m_next) {
9918 
9919                 mutex_enter(&mpt->m_mutex);
9920 
9921                 /* Skip device if not powered on */
9922                 if (mpt->m_options & MPTSAS_OPT_PM) {
9923                         if (mpt->m_power_level == PM_LEVEL_D0) {
9924                                 (void) pm_busy_component(mpt->m_dip, 0);
9925                                 mpt->m_busy = 1;
9926                         } else {
9927                                 mutex_exit(&mpt->m_mutex);
9928                                 continue;
9929                         }
9930                 }
9931 
9932                 /*
9933                  * Check if controller is in a FAULT state. If so, reset it.
9934                  */
9935                 doorbell = ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell);
9936                 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
9937                         doorbell &= MPI2_DOORBELL_DATA_MASK;
9938                         mptsas_log(mpt, CE_WARN, "MPT Firmware Fault, "
9939                             "code: %04x", doorbell);
9940                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
9941                         if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
9942                                 mptsas_log(mpt, CE_WARN, "Reset failed"
9943                                     "after fault was detected");
9944                         }
9945                 }
9946 
9947                 /*
9948                  * For now, always call mptsas_watchsubr.
9949                  */
9950                 mptsas_watchsubr(mpt);
9951 
9952                 if (mpt->m_options & MPTSAS_OPT_PM) {
9953                         mpt->m_busy = 0;
9954                         (void) pm_idle_component(mpt->m_dip, 0);
9955                 }
9956 
9957                 mutex_exit(&mpt->m_mutex);
9958         }
9959         rw_exit(&mptsas_global_rwlock);
9960 
9961         mutex_enter(&mptsas_global_mutex);
9962         if (mptsas_timeouts_enabled)
9963                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
9964         mutex_exit(&mptsas_global_mutex);
9965 }
9966 
9967 static void
9968 mptsas_watchsubr(mptsas_t *mpt)
9969 {
9970         int             i;
9971         mptsas_cmd_t    *cmd;
9972         mptsas_target_t *ptgt = NULL;
9973 
9974         NDBG30(("mptsas_watchsubr: mpt=0x%p", (void *)mpt));
9975 
9976 #ifdef MPTSAS_TEST
9977         if (mptsas_enable_untagged) {
9978                 mptsas_test_untagged++;
9979         }
9980 #endif
9981 
9982         /*
9983          * Check for commands stuck in active slot
9984          * Account for TM requests, which use the last SMID.
9985          */
9986         mutex_enter(&mpt->m_intr_mutex);
9987         for (i = 0; i <= mpt->m_active->m_n_slots; i++) {
9988                 if ((cmd = mpt->m_active->m_slot[i]) != NULL) {
9989                         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
9990                                 cmd->cmd_active_timeout -=
9991                                     mptsas_scsi_watchdog_tick;
9992                                 if (cmd->cmd_active_timeout <= 0) {
9993                                         /*
9994                                          * There seems to be a command stuck
9995                                          * in the active slot.  Drain throttle.
9996                                          */
9997                                         ptgt = cmd->cmd_tgt_addr;
9998                                         mutex_enter(&ptgt->m_tgt_intr_mutex);
9999                                         mptsas_set_throttle(mpt, ptgt,
10000                                             DRAIN_THROTTLE);
10001                                         mutex_exit(&ptgt->m_tgt_intr_mutex);
10002                                 }
10003                         }
10004                         if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
10005                             (cmd->cmd_flags & CFLAG_CONFIG) ||
10006                             (cmd->cmd_flags & CFLAG_FW_DIAG)) {
10007                                 cmd->cmd_active_timeout -=
10008                                     mptsas_scsi_watchdog_tick;
10009                                 if (cmd->cmd_active_timeout <= 0) {
10010                                         /*
10011                                          * passthrough command timeout
10012                                          */
10013                                         cmd->cmd_flags |= (CFLAG_FINISHED |
10014                                             CFLAG_TIMEOUT);
10015                                         cv_broadcast(&mpt->m_passthru_cv);
10016                                         cv_broadcast(&mpt->m_config_cv);
10017                                         cv_broadcast(&mpt->m_fw_diag_cv);
10018                                 }
10019                         }
10020                 }
10021         }
10022         mutex_exit(&mpt->m_intr_mutex);
10023 
10024         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
10025             MPTSAS_HASH_FIRST);
10026         while (ptgt != NULL) {
10027                 /*
10028                  * In order to avoid using m_mutex in the key code path in ISR,
10029                  * separate mutexs are introduced to protect those elements
10030                  * shown in ISR.
10031                  */
10032                 mutex_enter(&ptgt->m_tgt_intr_mutex);
10033 
10034                 /*
10035                  * If we were draining due to a qfull condition,
10036                  * go back to full throttle.
10037                  */
10038                 if ((ptgt->m_t_throttle < MAX_THROTTLE) &&
10039                     (ptgt->m_t_throttle > HOLD_THROTTLE) &&
10040                     (ptgt->m_t_ncmds < ptgt->m_t_throttle)) {
10041                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
10042                         mptsas_restart_hba(mpt);
10043                 }
10044 
10045                 if ((ptgt->m_t_ncmds > 0) &&
10046                     (ptgt->m_timebase)) {
10047 
10048                         if (ptgt->m_timebase <=
10049                             mptsas_scsi_watchdog_tick) {
10050                                 ptgt->m_timebase +=
10051                                     mptsas_scsi_watchdog_tick;
10052                                 mutex_exit(&ptgt->m_tgt_intr_mutex);
10053                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
10054                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
10055                                 continue;
10056                         }
10057 
10058                         ptgt->m_timeout -= mptsas_scsi_watchdog_tick;
10059 
10060                         if (ptgt->m_timeout < 0) {
10061                                 mutex_exit(&ptgt->m_tgt_intr_mutex);
10062                                 mptsas_cmd_timeout(mpt, ptgt->m_devhdl);
10063                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
10064                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
10065                                 continue;
10066                         }
10067 
10068                         if ((ptgt->m_timeout) <=
10069                             mptsas_scsi_watchdog_tick) {
10070                                 NDBG23(("pending timeout"));
10071                                 mptsas_set_throttle(mpt, ptgt,
10072                                     DRAIN_THROTTLE);
10073                         }
10074                 }
10075                 mutex_exit(&ptgt->m_tgt_intr_mutex);
10076                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
10077                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
10078         }
10079 }
10080 
10081 /*
10082  * timeout recovery
10083  */
10084 static void
10085 mptsas_cmd_timeout(mptsas_t *mpt, uint16_t devhdl)
10086 {
10087 
10088         NDBG29(("mptsas_cmd_timeout: target=%d", devhdl));
10089         mptsas_log(mpt, CE_WARN, "Disconnected command timeout for "
10090             "Target %d", devhdl);
10091 
10092         /*
10093          * If the current target is not the target passed in,
10094          * try to reset that target.
10095          */
10096         NDBG29(("mptsas_cmd_timeout: device reset"));
10097         if (mptsas_do_scsi_reset(mpt, devhdl) != TRUE) {
10098                 mptsas_log(mpt, CE_WARN, "Target %d reset for command timeout "
10099                     "recovery failed!", devhdl);
10100         }
10101 }
10102 
10103 /*
10104  * Device / Hotplug control
10105  */
10106 static int
10107 mptsas_scsi_quiesce(dev_info_t *dip)
10108 {
10109         mptsas_t        *mpt;
10110         scsi_hba_tran_t *tran;
10111 
10112         tran = ddi_get_driver_private(dip);
10113         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
10114                 return (-1);
10115 
10116         return (mptsas_quiesce_bus(mpt));
10117 }
10118 
10119 static int
10120 mptsas_scsi_unquiesce(dev_info_t *dip)
10121 {
10122         mptsas_t                *mpt;
10123         scsi_hba_tran_t *tran;
10124 
10125         tran = ddi_get_driver_private(dip);
10126         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
10127                 return (-1);
10128 
10129         return (mptsas_unquiesce_bus(mpt));
10130 }
10131 
10132 static int
10133 mptsas_quiesce_bus(mptsas_t *mpt)
10134 {
10135         mptsas_target_t *ptgt = NULL;
10136 
10137         NDBG28(("mptsas_quiesce_bus"));
10138         mutex_enter(&mpt->m_mutex);
10139 
10140         /* Set all the throttles to zero */
10141         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
10142             MPTSAS_HASH_FIRST);
10143         while (ptgt != NULL) {
10144                 mutex_enter(&ptgt->m_tgt_intr_mutex);
10145                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
10146                 mutex_exit(&ptgt->m_tgt_intr_mutex);
10147 
10148                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
10149                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
10150         }
10151 
10152         /* If there are any outstanding commands in the queue */
10153         mutex_enter(&mpt->m_intr_mutex);
10154         if (mptsas_outstanding_cmds_n(mpt)) {
10155                 mutex_exit(&mpt->m_intr_mutex);
10156                 mpt->m_softstate |= MPTSAS_SS_DRAINING;
10157                 mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
10158                     mpt, (MPTSAS_QUIESCE_TIMEOUT * drv_usectohz(1000000)));
10159                 if (cv_wait_sig(&mpt->m_cv, &mpt->m_mutex) == 0) {
10160                         /*
10161                          * Quiesce has been interrupted
10162                          */
10163                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
10164                         ptgt = (mptsas_target_t *)mptsas_hash_traverse(
10165                             &mpt->m_active->m_tgttbl, MPTSAS_HASH_FIRST);
10166                         while (ptgt != NULL) {
10167                                 mutex_enter(&ptgt->m_tgt_intr_mutex);
10168                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
10169                                 mutex_exit(&ptgt->m_tgt_intr_mutex);
10170 
10171                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
10172                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
10173                         }
10174                         mptsas_restart_hba(mpt);
10175                         if (mpt->m_quiesce_timeid != 0) {
10176                                 timeout_id_t tid = mpt->m_quiesce_timeid;
10177                                 mpt->m_quiesce_timeid = 0;
10178                                 mutex_exit(&mpt->m_mutex);
10179                                 (void) untimeout(tid);
10180                                 return (-1);
10181                         }
10182                         mutex_exit(&mpt->m_mutex);
10183                         return (-1);
10184                 } else {
10185                         /* Bus has been quiesced */
10186                         ASSERT(mpt->m_quiesce_timeid == 0);
10187                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
10188                         mpt->m_softstate |= MPTSAS_SS_QUIESCED;
10189                         mutex_exit(&mpt->m_mutex);
10190                         return (0);
10191                 }
10192         }
10193         mutex_exit(&mpt->m_intr_mutex);
10194         /* Bus was not busy - QUIESCED */
10195         mutex_exit(&mpt->m_mutex);
10196 
10197         return (0);
10198 }
10199 
10200 static int
10201 mptsas_unquiesce_bus(mptsas_t *mpt)
10202 {
10203         mptsas_target_t *ptgt = NULL;
10204 
10205         NDBG28(("mptsas_unquiesce_bus"));
10206         mutex_enter(&mpt->m_mutex);
10207         mpt->m_softstate &= ~MPTSAS_SS_QUIESCED;
10208         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
10209             MPTSAS_HASH_FIRST);
10210         while (ptgt != NULL) {
10211                 mutex_enter(&ptgt->m_tgt_intr_mutex);
10212                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
10213                 mutex_exit(&ptgt->m_tgt_intr_mutex);
10214 
10215                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
10216                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
10217         }
10218         mptsas_restart_hba(mpt);
10219         mutex_exit(&mpt->m_mutex);
10220         return (0);
10221 }
10222 
10223 static void
10224 mptsas_ncmds_checkdrain(void *arg)
10225 {
10226         mptsas_t        *mpt = arg;
10227         mptsas_target_t *ptgt = NULL;
10228 
10229         mutex_enter(&mpt->m_mutex);
10230         if (mpt->m_softstate & MPTSAS_SS_DRAINING) {
10231                 mpt->m_quiesce_timeid = 0;
10232                 mutex_enter(&mpt->m_intr_mutex);
10233                 if (mptsas_outstanding_cmds_n(mpt)) {
10234                         mutex_exit(&mpt->m_intr_mutex);
10235                         /*
10236                          * The throttle may have been reset because
10237                          * of a SCSI bus reset
10238                          */
10239                         ptgt = (mptsas_target_t *)mptsas_hash_traverse(
10240                             &mpt->m_active->m_tgttbl, MPTSAS_HASH_FIRST);
10241                         while (ptgt != NULL) {
10242                                 mutex_enter(&ptgt->m_tgt_intr_mutex);
10243                                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
10244                                 mutex_exit(&ptgt->m_tgt_intr_mutex);
10245 
10246                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
10247                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
10248                         }
10249 
10250                         mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
10251                             mpt, (MPTSAS_QUIESCE_TIMEOUT *
10252                             drv_usectohz(1000000)));
10253                 } else {
10254                         mutex_exit(&mpt->m_intr_mutex);
10255                         /* Command queue has been drained */
10256                         cv_signal(&mpt->m_cv);
10257                 }
10258         }
10259         mutex_exit(&mpt->m_mutex);
10260 }
10261 
10262 /*ARGSUSED*/
10263 static void
10264 mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
10265 {
10266         int     i;
10267         uint8_t *cp = (uchar_t *)cmd->cmd_pkt->pkt_cdbp;
10268         char    buf[128];
10269 
10270         buf[0] = '\0';
10271         NDBG25(("?Cmd (0x%p) dump for Target %d Lun %d:\n", (void *)cmd,
10272             Tgt(cmd), Lun(cmd)));
10273         (void) sprintf(&buf[0], "\tcdb=[");
10274         for (i = 0; i < (int)cmd->cmd_cdblen; i++) {
10275                 (void) sprintf(&buf[strlen(buf)], " 0x%x", *cp++);
10276         }
10277         (void) sprintf(&buf[strlen(buf)], " ]");
10278         NDBG25(("?%s\n", buf));
10279         NDBG25(("?pkt_flags=0x%x pkt_statistics=0x%x pkt_state=0x%x\n",
10280             cmd->cmd_pkt->pkt_flags, cmd->cmd_pkt->pkt_statistics,
10281             cmd->cmd_pkt->pkt_state));
10282         NDBG25(("?pkt_scbp=0x%x cmd_flags=0x%x\n", cmd->cmd_pkt->pkt_scbp ?
10283             *(cmd->cmd_pkt->pkt_scbp) : 0, cmd->cmd_flags));
10284 }
10285 
10286 static void
10287 mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd)
10288 {
10289         caddr_t                 memp;
10290         pMPI2RequestHeader_t    request_hdrp;
10291         struct scsi_pkt         *pkt = cmd->cmd_pkt;
10292         mptsas_pt_request_t     *pt = pkt->pkt_ha_private;
10293         uint32_t                request_size, data_size, dataout_size;
10294         uint32_t                direction;
10295         ddi_dma_cookie_t        data_cookie;
10296         ddi_dma_cookie_t        dataout_cookie;
10297         uint32_t                request_desc_low, request_desc_high = 0;
10298         uint32_t                i, sense_bufp;
10299         uint8_t                 desc_type;
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         direction = pt->direction;
10308         request_size = pt->request_size;
10309         data_size = pt->data_size;
10310         dataout_size = pt->dataout_size;
10311         data_cookie = pt->data_cookie;
10312         dataout_cookie = pt->dataout_cookie;
10313 
10314         /*
10315          * Store the passthrough message in memory location
10316          * corresponding to our slot number
10317          */
10318         memp = mpt->m_req_frame + (mpt->m_req_frame_size * cmd->cmd_slot);
10319         request_hdrp = (pMPI2RequestHeader_t)memp;
10320         bzero(memp, mpt->m_req_frame_size);
10321 
10322         for (i = 0; i < request_size; i++) {
10323                 bcopy(request + i, memp + i, 1);
10324         }
10325 
10326         if (data_size || dataout_size) {
10327                 pMpi2SGESimple64_t      sgep;
10328                 uint32_t                sge_flags;
10329 
10330                 sgep = (pMpi2SGESimple64_t)((uint8_t *)request_hdrp +
10331                     request_size);
10332                 if (dataout_size) {
10333 
10334                         sge_flags = dataout_size |
10335                             ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
10336                             MPI2_SGE_FLAGS_END_OF_BUFFER |
10337                             MPI2_SGE_FLAGS_HOST_TO_IOC |
10338                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
10339                             MPI2_SGE_FLAGS_SHIFT);
10340                         ddi_put32(acc_hdl, &sgep->FlagsLength, sge_flags);
10341                         ddi_put32(acc_hdl, &sgep->Address.Low,
10342                             (uint32_t)(dataout_cookie.dmac_laddress &
10343                             0xffffffffull));
10344                         ddi_put32(acc_hdl, &sgep->Address.High,
10345                             (uint32_t)(dataout_cookie.dmac_laddress
10346                             >> 32));
10347                         sgep++;
10348                 }
10349                 sge_flags = data_size;
10350                 sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
10351                     MPI2_SGE_FLAGS_LAST_ELEMENT |
10352                     MPI2_SGE_FLAGS_END_OF_BUFFER |
10353                     MPI2_SGE_FLAGS_END_OF_LIST |
10354                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
10355                     MPI2_SGE_FLAGS_SHIFT);
10356                 if (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10357                         sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_HOST_TO_IOC) <<
10358                             MPI2_SGE_FLAGS_SHIFT);
10359                 } else {
10360                         sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_IOC_TO_HOST) <<
10361                             MPI2_SGE_FLAGS_SHIFT);
10362                 }
10363                 ddi_put32(acc_hdl, &sgep->FlagsLength,
10364                     sge_flags);
10365                 ddi_put32(acc_hdl, &sgep->Address.Low,
10366                     (uint32_t)(data_cookie.dmac_laddress &
10367                     0xffffffffull));
10368                 ddi_put32(acc_hdl, &sgep->Address.High,
10369                     (uint32_t)(data_cookie.dmac_laddress >> 32));
10370         }
10371 
10372         function = request_hdrp->Function;
10373         if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
10374             (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
10375                 pMpi2SCSIIORequest_t    scsi_io_req;
10376 
10377                 scsi_io_req = (pMpi2SCSIIORequest_t)request_hdrp;
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                  * Following above SGEs, the residual space will be
10382                  * used by sense data.
10383                  */
10384                 ddi_put8(acc_hdl,
10385                     &scsi_io_req->SenseBufferLength,
10386                     (uint8_t)(request_size - 64));
10387 
10388                 sense_bufp = mpt->m_req_frame_dma_addr +
10389                     (mpt->m_req_frame_size * cmd->cmd_slot);
10390                 sense_bufp += 64;
10391                 ddi_put32(acc_hdl,
10392                     &scsi_io_req->SenseBufferLowAddress, sense_bufp);
10393 
10394                 /*
10395                  * Set SGLOffset0 value
10396                  */
10397                 ddi_put8(acc_hdl, &scsi_io_req->SGLOffset0,
10398                     offsetof(MPI2_SCSI_IO_REQUEST, SGL) / 4);
10399 
10400                 /*
10401                  * Setup descriptor info.  RAID passthrough must use the
10402                  * default request descriptor which is already set, so if this
10403                  * is a SCSI IO request, change the descriptor to SCSI IO.
10404                  */
10405                 if (function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
10406                         desc_type = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
10407                         request_desc_high = (ddi_get16(acc_hdl,
10408                             &scsi_io_req->DevHandle) << 16);
10409                 }
10410         }
10411 
10412         /*
10413          * We must wait till the message has been completed before
10414          * beginning the next message so we wait for this one to
10415          * finish.
10416          */
10417         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
10418         request_desc_low = (cmd->cmd_slot << 16) + desc_type;
10419         cmd->cmd_rfm = NULL;
10420         mpt->m_active->m_slot[cmd->cmd_slot] = cmd;
10421         MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
10422         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
10423             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
10424                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
10425         }
10426 }
10427 
10428 
10429 
10430 static int
10431 mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
10432     uint8_t *data, uint32_t request_size, uint32_t reply_size,
10433     uint32_t data_size, uint32_t direction, uint8_t *dataout,
10434     uint32_t dataout_size, short timeout, int mode)
10435 {
10436         mptsas_pt_request_t             pt;
10437         mptsas_dma_alloc_state_t        data_dma_state;
10438         mptsas_dma_alloc_state_t        dataout_dma_state;
10439         caddr_t                         memp;
10440         mptsas_cmd_t                    *cmd = NULL;
10441         struct scsi_pkt                 *pkt;
10442         uint32_t                        reply_len = 0, sense_len = 0;
10443         pMPI2RequestHeader_t            request_hdrp;
10444         pMPI2RequestHeader_t            request_msg;
10445         pMPI2DefaultReply_t             reply_msg;
10446         Mpi2SCSIIOReply_t               rep_msg;
10447         int                             i, status = 0, pt_flags = 0, rv = 0;
10448         int                             rvalue;
10449         uint8_t                         function;
10450 
10451         ASSERT(mutex_owned(&mpt->m_mutex));
10452 
10453         reply_msg = (pMPI2DefaultReply_t)(&rep_msg);
10454         bzero(reply_msg, sizeof (MPI2_DEFAULT_REPLY));
10455         request_msg = kmem_zalloc(request_size, KM_SLEEP);
10456 
10457         mutex_exit(&mpt->m_mutex);
10458         /*
10459          * copy in the request buffer since it could be used by
10460          * another thread when the pt request into waitq
10461          */
10462         if (ddi_copyin(request, request_msg, request_size, mode)) {
10463                 mutex_enter(&mpt->m_mutex);
10464                 status = EFAULT;
10465                 mptsas_log(mpt, CE_WARN, "failed to copy request data");
10466                 goto out;
10467         }
10468         mutex_enter(&mpt->m_mutex);
10469 
10470         function = request_msg->Function;
10471         if (function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
10472                 pMpi2SCSITaskManagementRequest_t        task;
10473                 task = (pMpi2SCSITaskManagementRequest_t)request_msg;
10474                 mptsas_setup_bus_reset_delay(mpt);
10475                 rv = mptsas_ioc_task_management(mpt, task->TaskType,
10476                     task->DevHandle, (int)task->LUN[1], reply, reply_size,
10477                     mode);
10478 
10479                 if (rv != TRUE) {
10480                         status = EIO;
10481                         mptsas_log(mpt, CE_WARN, "task management failed");
10482                 }
10483                 goto out;
10484         }
10485 
10486         if (data_size != 0) {
10487                 data_dma_state.size = data_size;
10488                 if (mptsas_dma_alloc(mpt, &data_dma_state) != DDI_SUCCESS) {
10489                         status = ENOMEM;
10490                         mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
10491                             "resource");
10492                         goto out;
10493                 }
10494                 pt_flags |= MPTSAS_DATA_ALLOCATED;
10495                 if (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10496                         mutex_exit(&mpt->m_mutex);
10497                         for (i = 0; i < data_size; i++) {
10498                                 if (ddi_copyin(data + i, (uint8_t *)
10499                                     data_dma_state.memp + i, 1, mode)) {
10500                                         mutex_enter(&mpt->m_mutex);
10501                                         status = EFAULT;
10502                                         mptsas_log(mpt, CE_WARN, "failed to "
10503                                             "copy read data");
10504                                         goto out;
10505                                 }
10506                         }
10507                         mutex_enter(&mpt->m_mutex);
10508                 }
10509         }
10510 
10511         if (dataout_size != 0) {
10512                 dataout_dma_state.size = dataout_size;
10513                 if (mptsas_dma_alloc(mpt, &dataout_dma_state) != DDI_SUCCESS) {
10514                         status = ENOMEM;
10515                         mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
10516                             "resource");
10517                         goto out;
10518                 }
10519                 pt_flags |= MPTSAS_DATAOUT_ALLOCATED;
10520                 mutex_exit(&mpt->m_mutex);
10521                 for (i = 0; i < dataout_size; i++) {
10522                         if (ddi_copyin(dataout + i, (uint8_t *)
10523                             dataout_dma_state.memp + i, 1, mode)) {
10524                                 mutex_enter(&mpt->m_mutex);
10525                                 mptsas_log(mpt, CE_WARN, "failed to copy out"
10526                                     " data");
10527                                 status = EFAULT;
10528                                 goto out;
10529                         }
10530                 }
10531                 mutex_enter(&mpt->m_mutex);
10532         }
10533 
10534         if ((rvalue = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
10535                 status = EAGAIN;
10536                 mptsas_log(mpt, CE_NOTE, "event ack command pool is full");
10537                 goto out;
10538         }
10539         pt_flags |= MPTSAS_REQUEST_POOL_CMD;
10540 
10541         bzero((caddr_t)cmd, sizeof (*cmd));
10542         bzero((caddr_t)pkt, scsi_pkt_size());
10543         bzero((caddr_t)&pt, sizeof (pt));
10544 
10545         cmd->ioc_cmd_slot = (uint32_t)(rvalue);
10546 
10547         pt.request = (uint8_t *)request_msg;
10548         pt.direction = direction;
10549         pt.request_size = request_size;
10550         pt.data_size = data_size;
10551         pt.dataout_size = dataout_size;
10552         pt.data_cookie = data_dma_state.cookie;
10553         pt.dataout_cookie = dataout_dma_state.cookie;
10554 
10555         /*
10556          * Form a blank cmd/pkt to store the acknowledgement message
10557          */
10558         pkt->pkt_cdbp                = (opaque_t)&cmd->cmd_cdb[0];
10559         pkt->pkt_scbp                = (opaque_t)&cmd->cmd_scb;
10560         pkt->pkt_ha_private  = (opaque_t)&pt;
10561         pkt->pkt_flags               = FLAG_HEAD;
10562         pkt->pkt_time                = timeout;
10563         cmd->cmd_pkt         = pkt;
10564         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_PASSTHRU;
10565 
10566         /*
10567          * Save the command in a slot
10568          */
10569         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
10570                 /*
10571                  * Once passthru command get slot, set cmd_flags
10572                  * CFLAG_PREPARED.
10573                  */
10574                 cmd->cmd_flags |= CFLAG_PREPARED;
10575                 mptsas_start_passthru(mpt, cmd);
10576         } else {
10577                 mptsas_waitq_add(mpt, cmd);
10578         }
10579 
10580         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
10581                 cv_wait(&mpt->m_passthru_cv, &mpt->m_mutex);
10582         }
10583 
10584         if (cmd->cmd_flags & CFLAG_PREPARED) {
10585                 memp = mpt->m_req_frame + (mpt->m_req_frame_size *
10586                     cmd->cmd_slot);
10587                 request_hdrp = (pMPI2RequestHeader_t)memp;
10588         }
10589 
10590         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
10591                 status = ETIMEDOUT;
10592                 mptsas_log(mpt, CE_WARN, "passthrough command timeout");
10593                 pt_flags |= MPTSAS_CMD_TIMEOUT;
10594                 goto out;
10595         }
10596 
10597         if (cmd->cmd_rfm) {
10598                 /*
10599                  * cmd_rfm is zero means the command reply is a CONTEXT
10600                  * reply and no PCI Write to post the free reply SMFA
10601                  * because no reply message frame is used.
10602                  * cmd_rfm is non-zero means the reply is a ADDRESS
10603                  * reply and reply message frame is used.
10604                  */
10605                 pt_flags |= MPTSAS_ADDRESS_REPLY;
10606                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
10607                     DDI_DMA_SYNC_FORCPU);
10608                 reply_msg = (pMPI2DefaultReply_t)
10609                     (mpt->m_reply_frame + (cmd->cmd_rfm -
10610                     mpt->m_reply_frame_dma_addr));
10611         }
10612 
10613         mptsas_fma_check(mpt, cmd);
10614         if (pkt->pkt_reason == CMD_TRAN_ERR) {
10615                 status = EAGAIN;
10616                 mptsas_log(mpt, CE_WARN, "passthru fma error");
10617                 goto out;
10618         }
10619         if (pkt->pkt_reason == CMD_RESET) {
10620                 status = EAGAIN;
10621                 mptsas_log(mpt, CE_WARN, "ioc reset abort passthru");
10622                 goto out;
10623         }
10624 
10625         if (pkt->pkt_reason == CMD_INCOMPLETE) {
10626                 status = EIO;
10627                 mptsas_log(mpt, CE_WARN, "passthrough command incomplete");
10628                 goto out;
10629         }
10630 
10631         mutex_exit(&mpt->m_mutex);
10632         if (cmd->cmd_flags & CFLAG_PREPARED) {
10633                 function = request_hdrp->Function;
10634                 if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
10635                     (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
10636                         reply_len = sizeof (MPI2_SCSI_IO_REPLY);
10637                         sense_len = reply_size - reply_len;
10638                 } else {
10639                         reply_len = reply_size;
10640                         sense_len = 0;
10641                 }
10642 
10643                 for (i = 0; i < reply_len; i++) {
10644                         if (ddi_copyout((uint8_t *)reply_msg + i, reply + i, 1,
10645                             mode)) {
10646                                 mutex_enter(&mpt->m_mutex);
10647                                 status = EFAULT;
10648                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
10649                                     "reply data");
10650                                 goto out;
10651                         }
10652                 }
10653                 for (i = 0; i < sense_len; i++) {
10654                         if (ddi_copyout((uint8_t *)request_hdrp + 64 + i,
10655                             reply + reply_len + i, 1, mode)) {
10656                                 mutex_enter(&mpt->m_mutex);
10657                                 status = EFAULT;
10658                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
10659                                     "sense data");
10660                                 goto out;
10661                         }
10662                 }
10663         }
10664 
10665         if (data_size) {
10666                 if (direction != MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10667                         (void) ddi_dma_sync(data_dma_state.handle, 0, 0,
10668                             DDI_DMA_SYNC_FORCPU);
10669                         for (i = 0; i < data_size; i++) {
10670                                 if (ddi_copyout((uint8_t *)(
10671                                     data_dma_state.memp + i), data + i,  1,
10672                                     mode)) {
10673                                         mutex_enter(&mpt->m_mutex);
10674                                         status = EFAULT;
10675                                         mptsas_log(mpt, CE_WARN, "failed to "
10676                                             "copy out the reply data");
10677                                         goto out;
10678                                 }
10679                         }
10680                 }
10681         }
10682         mutex_enter(&mpt->m_mutex);
10683 out:
10684         /*
10685          * Put the reply frame back on the free queue, increment the free
10686          * index, and write the new index to the free index register.  But only
10687          * if this reply is an ADDRESS reply.
10688          */
10689         if (pt_flags & MPTSAS_ADDRESS_REPLY) {
10690                 ddi_put32(mpt->m_acc_free_queue_hdl,
10691                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
10692                     cmd->cmd_rfm);
10693                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
10694                     DDI_DMA_SYNC_FORDEV);
10695                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
10696                         mpt->m_free_index = 0;
10697                 }
10698                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
10699                     mpt->m_free_index);
10700         }
10701         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
10702                 mptsas_remove_cmd(mpt, cmd);
10703                 pt_flags &= (~MPTSAS_REQUEST_POOL_CMD);
10704         }
10705         if (pt_flags & MPTSAS_REQUEST_POOL_CMD)
10706                 mptsas_return_to_pool(mpt, cmd);
10707         if (pt_flags & MPTSAS_DATA_ALLOCATED) {
10708                 if (mptsas_check_dma_handle(data_dma_state.handle) !=
10709                     DDI_SUCCESS) {
10710                         ddi_fm_service_impact(mpt->m_dip,
10711                             DDI_SERVICE_UNAFFECTED);
10712                         status = EFAULT;
10713                 }
10714                 mptsas_dma_free(&data_dma_state);
10715         }
10716         if (pt_flags & MPTSAS_DATAOUT_ALLOCATED) {
10717                 if (mptsas_check_dma_handle(dataout_dma_state.handle) !=
10718                     DDI_SUCCESS) {
10719                         ddi_fm_service_impact(mpt->m_dip,
10720                             DDI_SERVICE_UNAFFECTED);
10721                         status = EFAULT;
10722                 }
10723                 mptsas_dma_free(&dataout_dma_state);
10724         }
10725         if (pt_flags & MPTSAS_CMD_TIMEOUT) {
10726                 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
10727                         mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
10728                 }
10729         }
10730         if (request_msg)
10731                 kmem_free(request_msg, request_size);
10732 
10733         return (status);
10734 }
10735 
10736 static int
10737 mptsas_pass_thru(mptsas_t *mpt, mptsas_pass_thru_t *data, int mode)
10738 {
10739         /*
10740          * If timeout is 0, set timeout to default of 60 seconds.
10741          */
10742         if (data->Timeout == 0) {
10743                 data->Timeout = MPTSAS_PASS_THRU_TIME_DEFAULT;
10744         }
10745 
10746         if (((data->DataSize == 0) &&
10747             (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_NONE)) ||
10748             ((data->DataSize != 0) &&
10749             ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_READ) ||
10750             (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_WRITE) ||
10751             ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) &&
10752             (data->DataOutSize != 0))))) {
10753                 if (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) {
10754                         data->DataDirection = MPTSAS_PASS_THRU_DIRECTION_READ;
10755                 } else {
10756                         data->DataOutSize = 0;
10757                 }
10758                 /*
10759                  * Send passthru request messages
10760                  */
10761                 return (mptsas_do_passthru(mpt,
10762                     (uint8_t *)((uintptr_t)data->PtrRequest),
10763                     (uint8_t *)((uintptr_t)data->PtrReply),
10764                     (uint8_t *)((uintptr_t)data->PtrData),
10765                     data->RequestSize, data->ReplySize,
10766                     data->DataSize, data->DataDirection,
10767                     (uint8_t *)((uintptr_t)data->PtrDataOut),
10768                     data->DataOutSize, data->Timeout, mode));
10769         } else {
10770                 return (EINVAL);
10771         }
10772 }
10773 
10774 static uint8_t
10775 mptsas_get_fw_diag_buffer_number(mptsas_t *mpt, uint32_t unique_id)
10776 {
10777         uint8_t index;
10778 
10779         for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
10780                 if (mpt->m_fw_diag_buffer_list[index].unique_id == unique_id) {
10781                         return (index);
10782                 }
10783         }
10784 
10785         return (MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND);
10786 }
10787 
10788 static void
10789 mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd)
10790 {
10791         pMpi2DiagBufferPostRequest_t    pDiag_post_msg;
10792         pMpi2DiagReleaseRequest_t       pDiag_release_msg;
10793         struct scsi_pkt                 *pkt = cmd->cmd_pkt;
10794         mptsas_diag_request_t           *diag = pkt->pkt_ha_private;
10795         uint32_t                        request_desc_low, i;
10796 
10797         ASSERT(mutex_owned(&mpt->m_mutex));
10798 
10799         /*
10800          * Form the diag message depending on the post or release function.
10801          */
10802         if (diag->function == MPI2_FUNCTION_DIAG_BUFFER_POST) {
10803                 pDiag_post_msg = (pMpi2DiagBufferPostRequest_t)
10804                     (mpt->m_req_frame + (mpt->m_req_frame_size *
10805                     cmd->cmd_slot));
10806                 bzero(pDiag_post_msg, mpt->m_req_frame_size);
10807                 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->Function,
10808                     diag->function);
10809                 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->BufferType,
10810                     diag->pBuffer->buffer_type);
10811                 ddi_put8(mpt->m_acc_req_frame_hdl,
10812                     &pDiag_post_msg->ExtendedType,
10813                     diag->pBuffer->extended_type);
10814                 ddi_put32(mpt->m_acc_req_frame_hdl,
10815                     &pDiag_post_msg->BufferLength,
10816                     diag->pBuffer->buffer_data.size);
10817                 for (i = 0; i < (sizeof (pDiag_post_msg->ProductSpecific) / 4);
10818                     i++) {
10819                         ddi_put32(mpt->m_acc_req_frame_hdl,
10820                             &pDiag_post_msg->ProductSpecific[i],
10821                             diag->pBuffer->product_specific[i]);
10822                 }
10823                 ddi_put32(mpt->m_acc_req_frame_hdl,
10824                     &pDiag_post_msg->BufferAddress.Low,
10825                     (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
10826                     & 0xffffffffull));
10827                 ddi_put32(mpt->m_acc_req_frame_hdl,
10828                     &pDiag_post_msg->BufferAddress.High,
10829                     (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
10830                     >> 32));
10831         } else {
10832                 pDiag_release_msg = (pMpi2DiagReleaseRequest_t)
10833                     (mpt->m_req_frame + (mpt->m_req_frame_size *
10834                     cmd->cmd_slot));
10835                 bzero(pDiag_release_msg, mpt->m_req_frame_size);
10836                 ddi_put8(mpt->m_acc_req_frame_hdl,
10837                     &pDiag_release_msg->Function, diag->function);
10838                 ddi_put8(mpt->m_acc_req_frame_hdl,
10839                     &pDiag_release_msg->BufferType,
10840                     diag->pBuffer->buffer_type);
10841         }
10842 
10843         /*
10844          * Send the message
10845          */
10846         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
10847             DDI_DMA_SYNC_FORDEV);
10848         request_desc_low = (cmd->cmd_slot << 16) +
10849             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
10850         cmd->cmd_rfm = NULL;
10851         mpt->m_active->m_slot[cmd->cmd_slot] = cmd;
10852         MPTSAS_START_CMD(mpt, request_desc_low, 0);
10853         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
10854             DDI_SUCCESS) ||
10855             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
10856             DDI_SUCCESS)) {
10857                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
10858         }
10859 }
10860 
10861 static int
10862 mptsas_post_fw_diag_buffer(mptsas_t *mpt,
10863     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
10864 {
10865         mptsas_diag_request_t           diag;
10866         int                             status, slot_num, post_flags = 0;
10867         mptsas_cmd_t                    *cmd = NULL;
10868         struct scsi_pkt                 *pkt;
10869         pMpi2DiagBufferPostReply_t      reply;
10870         uint16_t                        iocstatus;
10871         uint32_t                        iocloginfo, transfer_length;
10872 
10873         /*
10874          * If buffer is not enabled, just leave.
10875          */
10876         *return_code = MPTSAS_FW_DIAG_ERROR_POST_FAILED;
10877         if (!pBuffer->enabled) {
10878                 status = DDI_FAILURE;
10879                 goto out;
10880         }
10881 
10882         /*
10883          * Clear some flags initially.
10884          */
10885         pBuffer->force_release = FALSE;
10886         pBuffer->valid_data = FALSE;
10887         pBuffer->owned_by_firmware = FALSE;
10888 
10889         /*
10890          * Get a cmd buffer from the cmd buffer pool
10891          */
10892         if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
10893                 status = DDI_FAILURE;
10894                 mptsas_log(mpt, CE_NOTE, "command pool is full: Post FW Diag");
10895                 goto out;
10896         }
10897         post_flags |= MPTSAS_REQUEST_POOL_CMD;
10898 
10899         bzero((caddr_t)cmd, sizeof (*cmd));
10900         bzero((caddr_t)pkt, scsi_pkt_size());
10901 
10902         cmd->ioc_cmd_slot = (uint32_t)(slot_num);
10903 
10904         diag.pBuffer = pBuffer;
10905         diag.function = MPI2_FUNCTION_DIAG_BUFFER_POST;
10906 
10907         /*
10908          * Form a blank cmd/pkt to store the acknowledgement message
10909          */
10910         pkt->pkt_ha_private  = (opaque_t)&diag;
10911         pkt->pkt_flags               = FLAG_HEAD;
10912         pkt->pkt_time                = 60;
10913         cmd->cmd_pkt         = pkt;
10914         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_DIAG;
10915 
10916         /*
10917          * Save the command in a slot
10918          */
10919         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
10920                 /*
10921                  * Once passthru command get slot, set cmd_flags
10922                  * CFLAG_PREPARED.
10923                  */
10924                 cmd->cmd_flags |= CFLAG_PREPARED;
10925                 mptsas_start_diag(mpt, cmd);
10926         } else {
10927                 mptsas_waitq_add(mpt, cmd);
10928         }
10929 
10930         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
10931                 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
10932         }
10933 
10934         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
10935                 status = DDI_FAILURE;
10936                 mptsas_log(mpt, CE_WARN, "Post FW Diag command timeout");
10937                 goto out;
10938         }
10939 
10940         /*
10941          * cmd_rfm points to the reply message if a reply was given.  Check the
10942          * IOCStatus to make sure everything went OK with the FW diag request
10943          * and set buffer flags.
10944          */
10945         if (cmd->cmd_rfm) {
10946                 post_flags |= MPTSAS_ADDRESS_REPLY;
10947                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
10948                     DDI_DMA_SYNC_FORCPU);
10949                 reply = (pMpi2DiagBufferPostReply_t)(mpt->m_reply_frame +
10950                     (cmd->cmd_rfm - mpt->m_reply_frame_dma_addr));
10951 
10952                 /*
10953                  * Get the reply message data
10954                  */
10955                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
10956                     &reply->IOCStatus);
10957                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
10958                     &reply->IOCLogInfo);
10959                 transfer_length = ddi_get32(mpt->m_acc_reply_frame_hdl,
10960                     &reply->TransferLength);
10961 
10962                 /*
10963                  * If post failed quit.
10964                  */
10965                 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
10966                         status = DDI_FAILURE;
10967                         NDBG13(("post FW Diag Buffer failed: IOCStatus=0x%x, "
10968                             "IOCLogInfo=0x%x, TransferLength=0x%x", iocstatus,
10969                             iocloginfo, transfer_length));
10970                         goto out;
10971                 }
10972 
10973                 /*
10974                  * Post was successful.
10975                  */
10976                 pBuffer->valid_data = TRUE;
10977                 pBuffer->owned_by_firmware = TRUE;
10978                 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
10979                 status = DDI_SUCCESS;
10980         }
10981 
10982 out:
10983         /*
10984          * Put the reply frame back on the free queue, increment the free
10985          * index, and write the new index to the free index register.  But only
10986          * if this reply is an ADDRESS reply.
10987          */
10988         if (post_flags & MPTSAS_ADDRESS_REPLY) {
10989                 ddi_put32(mpt->m_acc_free_queue_hdl,
10990                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
10991                     cmd->cmd_rfm);
10992                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
10993                     DDI_DMA_SYNC_FORDEV);
10994                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
10995                         mpt->m_free_index = 0;
10996                 }
10997                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
10998                     mpt->m_free_index);
10999         }
11000         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
11001                 mptsas_remove_cmd(mpt, cmd);
11002                 post_flags &= (~MPTSAS_REQUEST_POOL_CMD);
11003         }
11004         if (post_flags & MPTSAS_REQUEST_POOL_CMD) {
11005                 mptsas_return_to_pool(mpt, cmd);
11006         }
11007 
11008         return (status);
11009 }
11010 
11011 static int
11012 mptsas_release_fw_diag_buffer(mptsas_t *mpt,
11013     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
11014     uint32_t diag_type)
11015 {
11016         mptsas_diag_request_t   diag;
11017         int                     status, slot_num, rel_flags = 0;
11018         mptsas_cmd_t            *cmd = NULL;
11019         struct scsi_pkt         *pkt;
11020         pMpi2DiagReleaseReply_t reply;
11021         uint16_t                iocstatus;
11022         uint32_t                iocloginfo;
11023 
11024         /*
11025          * If buffer is not enabled, just leave.
11026          */
11027         *return_code = MPTSAS_FW_DIAG_ERROR_RELEASE_FAILED;
11028         if (!pBuffer->enabled) {
11029                 mptsas_log(mpt, CE_NOTE, "This buffer type is not supported "
11030                     "by the IOC");
11031                 status = DDI_FAILURE;
11032                 goto out;
11033         }
11034 
11035         /*
11036          * Clear some flags initially.
11037          */
11038         pBuffer->force_release = FALSE;
11039         pBuffer->valid_data = FALSE;
11040         pBuffer->owned_by_firmware = FALSE;
11041 
11042         /*
11043          * Get a cmd buffer from the cmd buffer pool
11044          */
11045         if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
11046                 status = DDI_FAILURE;
11047                 mptsas_log(mpt, CE_NOTE, "command pool is full: Release FW "
11048                     "Diag");
11049                 goto out;
11050         }
11051         rel_flags |= MPTSAS_REQUEST_POOL_CMD;
11052 
11053         bzero((caddr_t)cmd, sizeof (*cmd));
11054         bzero((caddr_t)pkt, scsi_pkt_size());
11055 
11056         cmd->ioc_cmd_slot = (uint32_t)(slot_num);
11057 
11058         diag.pBuffer = pBuffer;
11059         diag.function = MPI2_FUNCTION_DIAG_RELEASE;
11060 
11061         /*
11062          * Form a blank cmd/pkt to store the acknowledgement message
11063          */
11064         pkt->pkt_ha_private  = (opaque_t)&diag;
11065         pkt->pkt_flags               = FLAG_HEAD;
11066         pkt->pkt_time                = 60;
11067         cmd->cmd_pkt         = pkt;
11068         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_DIAG;
11069 
11070         /*
11071          * Save the command in a slot
11072          */
11073         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
11074                 /*
11075                  * Once passthru command get slot, set cmd_flags
11076                  * CFLAG_PREPARED.
11077                  */
11078                 cmd->cmd_flags |= CFLAG_PREPARED;
11079                 mptsas_start_diag(mpt, cmd);
11080         } else {
11081                 mptsas_waitq_add(mpt, cmd);
11082         }
11083 
11084         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
11085                 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
11086         }
11087 
11088         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
11089                 status = DDI_FAILURE;
11090                 mptsas_log(mpt, CE_WARN, "Release FW Diag command timeout");
11091                 goto out;
11092         }
11093 
11094         /*
11095          * cmd_rfm points to the reply message if a reply was given.  Check the
11096          * IOCStatus to make sure everything went OK with the FW diag request
11097          * and set buffer flags.
11098          */
11099         if (cmd->cmd_rfm) {
11100                 rel_flags |= MPTSAS_ADDRESS_REPLY;
11101                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
11102                     DDI_DMA_SYNC_FORCPU);
11103                 reply = (pMpi2DiagReleaseReply_t)(mpt->m_reply_frame +
11104                     (cmd->cmd_rfm - mpt->m_reply_frame_dma_addr));
11105 
11106                 /*
11107                  * Get the reply message data
11108                  */
11109                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
11110                     &reply->IOCStatus);
11111                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
11112                     &reply->IOCLogInfo);
11113 
11114                 /*
11115                  * If release failed quit.
11116                  */
11117                 if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) ||
11118                     pBuffer->owned_by_firmware) {
11119                         status = DDI_FAILURE;
11120                         NDBG13(("release FW Diag Buffer failed: "
11121                             "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
11122                             iocloginfo));
11123                         goto out;
11124                 }
11125 
11126                 /*
11127                  * Release was successful.
11128                  */
11129                 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
11130                 status = DDI_SUCCESS;
11131 
11132                 /*
11133                  * If this was for an UNREGISTER diag type command, clear the
11134                  * unique ID.
11135                  */
11136                 if (diag_type == MPTSAS_FW_DIAG_TYPE_UNREGISTER) {
11137                         pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
11138                 }
11139         }
11140 
11141 out:
11142         /*
11143          * Put the reply frame back on the free queue, increment the free
11144          * index, and write the new index to the free index register.  But only
11145          * if this reply is an ADDRESS reply.
11146          */
11147         if (rel_flags & MPTSAS_ADDRESS_REPLY) {
11148                 ddi_put32(mpt->m_acc_free_queue_hdl,
11149                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
11150                     cmd->cmd_rfm);
11151                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
11152                     DDI_DMA_SYNC_FORDEV);
11153                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
11154                         mpt->m_free_index = 0;
11155                 }
11156                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
11157                     mpt->m_free_index);
11158         }
11159         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
11160                 mptsas_remove_cmd(mpt, cmd);
11161                 rel_flags &= (~MPTSAS_REQUEST_POOL_CMD);
11162         }
11163         if (rel_flags & MPTSAS_REQUEST_POOL_CMD) {
11164                 mptsas_return_to_pool(mpt, cmd);
11165         }
11166 
11167         return (status);
11168 }
11169 
11170 static int
11171 mptsas_diag_register(mptsas_t *mpt, mptsas_fw_diag_register_t *diag_register,
11172     uint32_t *return_code)
11173 {
11174         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11175         uint8_t                         extended_type, buffer_type, i;
11176         uint32_t                        buffer_size;
11177         uint32_t                        unique_id;
11178         int                             status;
11179 
11180         ASSERT(mutex_owned(&mpt->m_mutex));
11181 
11182         extended_type = diag_register->ExtendedType;
11183         buffer_type = diag_register->BufferType;
11184         buffer_size = diag_register->RequestedBufferSize;
11185         unique_id = diag_register->UniqueId;
11186 
11187         /*
11188          * Check for valid buffer type
11189          */
11190         if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) {
11191                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11192                 return (DDI_FAILURE);
11193         }
11194 
11195         /*
11196          * Get the current buffer and look up the unique ID.  The unique ID
11197          * should not be found.  If it is, the ID is already in use.
11198          */
11199         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11200         pBuffer = &mpt->m_fw_diag_buffer_list[buffer_type];
11201         if (i != MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11202                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11203                 return (DDI_FAILURE);
11204         }
11205 
11206         /*
11207          * The buffer's unique ID should not be registered yet, and the given
11208          * unique ID cannot be 0.
11209          */
11210         if ((pBuffer->unique_id != MPTSAS_FW_DIAG_INVALID_UID) ||
11211             (unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
11212                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11213                 return (DDI_FAILURE);
11214         }
11215 
11216         /*
11217          * If this buffer is already posted as immediate, just change owner.
11218          */
11219         if (pBuffer->immediate && pBuffer->owned_by_firmware &&
11220             (pBuffer->unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
11221                 pBuffer->immediate = FALSE;
11222                 pBuffer->unique_id = unique_id;
11223                 return (DDI_SUCCESS);
11224         }
11225 
11226         /*
11227          * Post a new buffer after checking if it's enabled.  The DMA buffer
11228          * that is allocated will be contiguous (sgl_len = 1).
11229          */
11230         if (!pBuffer->enabled) {
11231                 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
11232                 return (DDI_FAILURE);
11233         }
11234         bzero(&pBuffer->buffer_data, sizeof (mptsas_dma_alloc_state_t));
11235         pBuffer->buffer_data.size = buffer_size;
11236         if (mptsas_dma_alloc(mpt, &pBuffer->buffer_data) != DDI_SUCCESS) {
11237                 mptsas_log(mpt, CE_WARN, "failed to alloc DMA resource for "
11238                     "diag buffer: size = %d bytes", buffer_size);
11239                 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
11240                 return (DDI_FAILURE);
11241         }
11242 
11243         /*
11244          * Copy the given info to the diag buffer and post the buffer.
11245          */
11246         pBuffer->buffer_type = buffer_type;
11247         pBuffer->immediate = FALSE;
11248         if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) {
11249                 for (i = 0; i < (sizeof (pBuffer->product_specific) / 4);
11250                     i++) {
11251                         pBuffer->product_specific[i] =
11252                             diag_register->ProductSpecific[i];
11253                 }
11254         }
11255         pBuffer->extended_type = extended_type;
11256         pBuffer->unique_id = unique_id;
11257         status = mptsas_post_fw_diag_buffer(mpt, pBuffer, return_code);
11258 
11259         if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
11260             DDI_SUCCESS) {
11261                 mptsas_log(mpt, CE_WARN, "Check of DMA handle failed in "
11262                     "mptsas_diag_register.");
11263                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
11264                         status = DDI_FAILURE;
11265         }
11266 
11267         /*
11268          * In case there was a failure, free the DMA buffer.
11269          */
11270         if (status == DDI_FAILURE) {
11271                 mptsas_dma_free(&pBuffer->buffer_data);
11272         }
11273 
11274         return (status);
11275 }
11276 
11277 static int
11278 mptsas_diag_unregister(mptsas_t *mpt,
11279     mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
11280 {
11281         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11282         uint8_t                         i;
11283         uint32_t                        unique_id;
11284         int                             status;
11285 
11286         ASSERT(mutex_owned(&mpt->m_mutex));
11287 
11288         unique_id = diag_unregister->UniqueId;
11289 
11290         /*
11291          * Get the current buffer and look up the unique ID.  The unique ID
11292          * should be there.
11293          */
11294         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11295         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11296                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11297                 return (DDI_FAILURE);
11298         }
11299 
11300         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11301 
11302         /*
11303          * Try to release the buffer from FW before freeing it.  If release
11304          * fails, don't free the DMA buffer in case FW tries to access it
11305          * later.  If buffer is not owned by firmware, can't release it.
11306          */
11307         if (!pBuffer->owned_by_firmware) {
11308                 status = DDI_SUCCESS;
11309         } else {
11310                 status = mptsas_release_fw_diag_buffer(mpt, pBuffer,
11311                     return_code, MPTSAS_FW_DIAG_TYPE_UNREGISTER);
11312         }
11313 
11314         /*
11315          * At this point, return the current status no matter what happens with
11316          * the DMA buffer.
11317          */
11318         pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
11319         if (status == DDI_SUCCESS) {
11320                 if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
11321                     DDI_SUCCESS) {
11322                         mptsas_log(mpt, CE_WARN, "Check of DMA handle failed "
11323                             "in mptsas_diag_unregister.");
11324                         ddi_fm_service_impact(mpt->m_dip,
11325                             DDI_SERVICE_UNAFFECTED);
11326                 }
11327                 mptsas_dma_free(&pBuffer->buffer_data);
11328         }
11329 
11330         return (status);
11331 }
11332 
11333 static int
11334 mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
11335     uint32_t *return_code)
11336 {
11337         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11338         uint8_t                         i;
11339         uint32_t                        unique_id;
11340 
11341         ASSERT(mutex_owned(&mpt->m_mutex));
11342 
11343         unique_id = diag_query->UniqueId;
11344 
11345         /*
11346          * If ID is valid, query on ID.
11347          * If ID is invalid, query on buffer type.
11348          */
11349         if (unique_id == MPTSAS_FW_DIAG_INVALID_UID) {
11350                 i = diag_query->BufferType;
11351                 if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
11352                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11353                         return (DDI_FAILURE);
11354                 }
11355         } else {
11356                 i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11357                 if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11358                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11359                         return (DDI_FAILURE);
11360                 }
11361         }
11362 
11363         /*
11364          * Fill query structure with the diag buffer info.
11365          */
11366         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11367         diag_query->BufferType = pBuffer->buffer_type;
11368         diag_query->ExtendedType = pBuffer->extended_type;
11369         if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) {
11370                 for (i = 0; i < (sizeof (diag_query->ProductSpecific) / 4);
11371                     i++) {
11372                         diag_query->ProductSpecific[i] =
11373                             pBuffer->product_specific[i];
11374                 }
11375         }
11376         diag_query->TotalBufferSize = pBuffer->buffer_data.size;
11377         diag_query->DriverAddedBufferSize = 0;
11378         diag_query->UniqueId = pBuffer->unique_id;
11379         diag_query->ApplicationFlags = 0;
11380         diag_query->DiagnosticFlags = 0;
11381 
11382         /*
11383          * Set/Clear application flags
11384          */
11385         if (pBuffer->immediate) {
11386                 diag_query->ApplicationFlags &= ~MPTSAS_FW_DIAG_FLAG_APP_OWNED;
11387         } else {
11388                 diag_query->ApplicationFlags |= MPTSAS_FW_DIAG_FLAG_APP_OWNED;
11389         }
11390         if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
11391                 diag_query->ApplicationFlags |=
11392                     MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
11393         } else {
11394                 diag_query->ApplicationFlags &=
11395                     ~MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
11396         }
11397         if (pBuffer->owned_by_firmware) {
11398                 diag_query->ApplicationFlags |=
11399                     MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
11400         } else {
11401                 diag_query->ApplicationFlags &=
11402                     ~MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
11403         }
11404 
11405         return (DDI_SUCCESS);
11406 }
11407 
11408 static int
11409 mptsas_diag_read_buffer(mptsas_t *mpt,
11410     mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
11411     uint32_t *return_code, int ioctl_mode)
11412 {
11413         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11414         uint8_t                         i, *pData;
11415         uint32_t                        unique_id, byte;
11416         int                             status;
11417 
11418         ASSERT(mutex_owned(&mpt->m_mutex));
11419 
11420         unique_id = diag_read_buffer->UniqueId;
11421 
11422         /*
11423          * Get the current buffer and look up the unique ID.  The unique ID
11424          * should be there.
11425          */
11426         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11427         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11428                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11429                 return (DDI_FAILURE);
11430         }
11431 
11432         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11433 
11434         /*
11435          * Make sure requested read is within limits
11436          */
11437         if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
11438             pBuffer->buffer_data.size) {
11439                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11440                 return (DDI_FAILURE);
11441         }
11442 
11443         /*
11444          * Copy the requested data from DMA to the diag_read_buffer.  The DMA
11445          * buffer that was allocated is one contiguous buffer.
11446          */
11447         pData = (uint8_t *)(pBuffer->buffer_data.memp +
11448             diag_read_buffer->StartingOffset);
11449         (void) ddi_dma_sync(pBuffer->buffer_data.handle, 0, 0,
11450             DDI_DMA_SYNC_FORCPU);
11451         for (byte = 0; byte < diag_read_buffer->BytesToRead; byte++) {
11452                 if (ddi_copyout(pData + byte, ioctl_buf + byte, 1, ioctl_mode)
11453                     != 0) {
11454                         return (DDI_FAILURE);
11455                 }
11456         }
11457         diag_read_buffer->Status = 0;
11458 
11459         /*
11460          * Set or clear the Force Release flag.
11461          */
11462         if (pBuffer->force_release) {
11463                 diag_read_buffer->Flags |= MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
11464         } else {
11465                 diag_read_buffer->Flags &= ~MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
11466         }
11467 
11468         /*
11469          * If buffer is to be reregistered, make sure it's not already owned by
11470          * firmware first.
11471          */
11472         status = DDI_SUCCESS;
11473         if (!pBuffer->owned_by_firmware) {
11474                 if (diag_read_buffer->Flags & MPTSAS_FW_DIAG_FLAG_REREGISTER) {
11475                         status = mptsas_post_fw_diag_buffer(mpt, pBuffer,
11476                             return_code);
11477                 }
11478         }
11479 
11480         return (status);
11481 }
11482 
11483 static int
11484 mptsas_diag_release(mptsas_t *mpt, mptsas_fw_diag_release_t *diag_release,
11485     uint32_t *return_code)
11486 {
11487         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11488         uint8_t                         i;
11489         uint32_t                        unique_id;
11490         int                             status;
11491 
11492         ASSERT(mutex_owned(&mpt->m_mutex));
11493 
11494         unique_id = diag_release->UniqueId;
11495 
11496         /*
11497          * Get the current buffer and look up the unique ID.  The unique ID
11498          * should be there.
11499          */
11500         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11501         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11502                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11503                 return (DDI_FAILURE);
11504         }
11505 
11506         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11507 
11508         /*
11509          * If buffer is not owned by firmware, it's already been released.
11510          */
11511         if (!pBuffer->owned_by_firmware) {
11512                 *return_code = MPTSAS_FW_DIAG_ERROR_ALREADY_RELEASED;
11513                 return (DDI_FAILURE);
11514         }
11515 
11516         /*
11517          * Release the buffer.
11518          */
11519         status = mptsas_release_fw_diag_buffer(mpt, pBuffer, return_code,
11520             MPTSAS_FW_DIAG_TYPE_RELEASE);
11521         return (status);
11522 }
11523 
11524 static int
11525 mptsas_do_diag_action(mptsas_t *mpt, uint32_t action, uint8_t *diag_action,
11526     uint32_t length, uint32_t *return_code, int ioctl_mode)
11527 {
11528         mptsas_fw_diag_register_t       diag_register;
11529         mptsas_fw_diag_unregister_t     diag_unregister;
11530         mptsas_fw_diag_query_t          diag_query;
11531         mptsas_diag_read_buffer_t       diag_read_buffer;
11532         mptsas_fw_diag_release_t        diag_release;
11533         int                             status = DDI_SUCCESS;
11534         uint32_t                        original_return_code, read_buf_len;
11535 
11536         ASSERT(mutex_owned(&mpt->m_mutex));
11537 
11538         original_return_code = *return_code;
11539         *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
11540 
11541         switch (action) {
11542                 case MPTSAS_FW_DIAG_TYPE_REGISTER:
11543                         if (!length) {
11544                                 *return_code =
11545                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11546                                 status = DDI_FAILURE;
11547                                 break;
11548                         }
11549                         if (ddi_copyin(diag_action, &diag_register,
11550                             sizeof (diag_register), ioctl_mode) != 0) {
11551                                 return (DDI_FAILURE);
11552                         }
11553                         status = mptsas_diag_register(mpt, &diag_register,
11554                             return_code);
11555                         break;
11556 
11557                 case MPTSAS_FW_DIAG_TYPE_UNREGISTER:
11558                         if (length < sizeof (diag_unregister)) {
11559                                 *return_code =
11560                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11561                                 status = DDI_FAILURE;
11562                                 break;
11563                         }
11564                         if (ddi_copyin(diag_action, &diag_unregister,
11565                             sizeof (diag_unregister), ioctl_mode) != 0) {
11566                                 return (DDI_FAILURE);
11567                         }
11568                         status = mptsas_diag_unregister(mpt, &diag_unregister,
11569                             return_code);
11570                         break;
11571 
11572                 case MPTSAS_FW_DIAG_TYPE_QUERY:
11573                         if (length < sizeof (diag_query)) {
11574                                 *return_code =
11575                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11576                                 status = DDI_FAILURE;
11577                                 break;
11578                         }
11579                         if (ddi_copyin(diag_action, &diag_query,
11580                             sizeof (diag_query), ioctl_mode) != 0) {
11581                                 return (DDI_FAILURE);
11582                         }
11583                         status = mptsas_diag_query(mpt, &diag_query,
11584                             return_code);
11585                         if (status == DDI_SUCCESS) {
11586                                 if (ddi_copyout(&diag_query, diag_action,
11587                                     sizeof (diag_query), ioctl_mode) != 0) {
11588                                         return (DDI_FAILURE);
11589                                 }
11590                         }
11591                         break;
11592 
11593                 case MPTSAS_FW_DIAG_TYPE_READ_BUFFER:
11594                         if (ddi_copyin(diag_action, &diag_read_buffer,
11595                             sizeof (diag_read_buffer) - 4, ioctl_mode) != 0) {
11596                                 return (DDI_FAILURE);
11597                         }
11598                         read_buf_len = sizeof (diag_read_buffer) -
11599                             sizeof (diag_read_buffer.DataBuffer) +
11600                             diag_read_buffer.BytesToRead;
11601                         if (length < read_buf_len) {
11602                                 *return_code =
11603                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11604                                 status = DDI_FAILURE;
11605                                 break;
11606                         }
11607                         status = mptsas_diag_read_buffer(mpt,
11608                             &diag_read_buffer, diag_action +
11609                             sizeof (diag_read_buffer) - 4, return_code,
11610                             ioctl_mode);
11611                         if (status == DDI_SUCCESS) {
11612                                 if (ddi_copyout(&diag_read_buffer, diag_action,
11613                                     sizeof (diag_read_buffer) - 4, ioctl_mode)
11614                                     != 0) {
11615                                         return (DDI_FAILURE);
11616                                 }
11617                         }
11618                         break;
11619 
11620                 case MPTSAS_FW_DIAG_TYPE_RELEASE:
11621                         if (length < sizeof (diag_release)) {
11622                                 *return_code =
11623                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11624                                 status = DDI_FAILURE;
11625                                 break;
11626                         }
11627                         if (ddi_copyin(diag_action, &diag_release,
11628                             sizeof (diag_release), ioctl_mode) != 0) {
11629                                 return (DDI_FAILURE);
11630                         }
11631                         status = mptsas_diag_release(mpt, &diag_release,
11632                             return_code);
11633                         break;
11634 
11635                 default:
11636                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11637                         status = DDI_FAILURE;
11638                         break;
11639         }
11640 
11641         if ((status == DDI_FAILURE) &&
11642             (original_return_code == MPTSAS_FW_DIAG_NEW) &&
11643             (*return_code != MPTSAS_FW_DIAG_ERROR_SUCCESS)) {
11644                 status = DDI_SUCCESS;
11645         }
11646 
11647         return (status);
11648 }
11649 
11650 static int
11651 mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *user_data, int mode)
11652 {
11653         int                     status;
11654         mptsas_diag_action_t    driver_data;
11655 
11656         ASSERT(mutex_owned(&mpt->m_mutex));
11657 
11658         /*
11659          * Copy the user data to a driver data buffer.
11660          */
11661         if (ddi_copyin(user_data, &driver_data, sizeof (mptsas_diag_action_t),
11662             mode) == 0) {
11663                 /*
11664                  * Send diag action request if Action is valid
11665                  */
11666                 if (driver_data.Action == MPTSAS_FW_DIAG_TYPE_REGISTER ||
11667                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_UNREGISTER ||
11668                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_QUERY ||
11669                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_READ_BUFFER ||
11670                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_RELEASE) {
11671                         status = mptsas_do_diag_action(mpt, driver_data.Action,
11672                             (void *)(uintptr_t)driver_data.PtrDiagAction,
11673                             driver_data.Length, &driver_data.ReturnCode,
11674                             mode);
11675                         if (status == DDI_SUCCESS) {
11676                                 if (ddi_copyout(&driver_data.ReturnCode,
11677                                     &user_data->ReturnCode,
11678                                     sizeof (user_data->ReturnCode), mode)
11679                                     != 0) {
11680                                         status = EFAULT;
11681                                 } else {
11682                                         status = 0;
11683                                 }
11684                         } else {
11685                                 status = EIO;
11686                         }
11687                 } else {
11688                         status = EINVAL;
11689                 }
11690         } else {
11691                 status = EFAULT;
11692         }
11693 
11694         return (status);
11695 }
11696 
11697 /*
11698  * This routine handles the "event query" ioctl.
11699  */
11700 static int
11701 mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data, int mode,
11702     int *rval)
11703 {
11704         int                     status;
11705         mptsas_event_query_t    driverdata;
11706         uint8_t                 i;
11707 
11708         driverdata.Entries = MPTSAS_EVENT_QUEUE_SIZE;
11709 
11710         mutex_enter(&mpt->m_mutex);
11711         for (i = 0; i < 4; i++) {
11712                 driverdata.Types[i] = mpt->m_event_mask[i];
11713         }
11714         mutex_exit(&mpt->m_mutex);
11715 
11716         if (ddi_copyout(&driverdata, data, sizeof (driverdata), mode) != 0) {
11717                 status = EFAULT;
11718         } else {
11719                 *rval = MPTIOCTL_STATUS_GOOD;
11720                 status = 0;
11721         }
11722 
11723         return (status);
11724 }
11725 
11726 /*
11727  * This routine handles the "event enable" ioctl.
11728  */
11729 static int
11730 mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data, int mode,
11731     int *rval)
11732 {
11733         int                     status;
11734         mptsas_event_enable_t   driverdata;
11735         uint8_t                 i;
11736 
11737         if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
11738                 mutex_enter(&mpt->m_mutex);
11739                 for (i = 0; i < 4; i++) {
11740                         mpt->m_event_mask[i] = driverdata.Types[i];
11741                 }
11742                 mutex_exit(&mpt->m_mutex);
11743 
11744                 *rval = MPTIOCTL_STATUS_GOOD;
11745                 status = 0;
11746         } else {
11747                 status = EFAULT;
11748         }
11749         return (status);
11750 }
11751 
11752 /*
11753  * This routine handles the "event report" ioctl.
11754  */
11755 static int
11756 mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data, int mode,
11757     int *rval)
11758 {
11759         int                     status;
11760         mptsas_event_report_t   driverdata;
11761 
11762         mutex_enter(&mpt->m_mutex);
11763 
11764         if (ddi_copyin(&data->Size, &driverdata.Size, sizeof (driverdata.Size),
11765             mode) == 0) {
11766                 if (driverdata.Size >= sizeof (mpt->m_events)) {
11767                         if (ddi_copyout(mpt->m_events, data->Events,
11768                             sizeof (mpt->m_events), mode) != 0) {
11769                                 status = EFAULT;
11770                         } else {
11771                                 if (driverdata.Size > sizeof (mpt->m_events)) {
11772                                         driverdata.Size =
11773                                             sizeof (mpt->m_events);
11774                                         if (ddi_copyout(&driverdata.Size,
11775                                             &data->Size,
11776                                             sizeof (driverdata.Size),
11777                                             mode) != 0) {
11778                                                 status = EFAULT;
11779                                         } else {
11780                                                 *rval = MPTIOCTL_STATUS_GOOD;
11781                                                 status = 0;
11782                                         }
11783                                 } else {
11784                                         *rval = MPTIOCTL_STATUS_GOOD;
11785                                         status = 0;
11786                                 }
11787                         }
11788                 } else {
11789                         *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
11790                         status = 0;
11791                 }
11792         } else {
11793                 status = EFAULT;
11794         }
11795 
11796         mutex_exit(&mpt->m_mutex);
11797         return (status);
11798 }
11799 
11800 static void
11801 mptsas_lookup_pci_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
11802 {
11803         int     *reg_data;
11804         uint_t  reglen;
11805 
11806         /*
11807          * Lookup the 'reg' property and extract the other data
11808          */
11809         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
11810             DDI_PROP_DONTPASS, "reg", &reg_data, &reglen) ==
11811             DDI_PROP_SUCCESS) {
11812                 /*
11813                  * Extract the PCI data from the 'reg' property first DWORD.
11814                  * The entry looks like the following:
11815                  * First DWORD:
11816                  * Bits 0 - 7 8-bit Register number
11817                  * Bits 8 - 10 3-bit Function number
11818                  * Bits 11 - 15 5-bit Device number
11819                  * Bits 16 - 23 8-bit Bus number
11820                  * Bits 24 - 25 2-bit Address Space type identifier
11821                  *
11822                  */
11823                 adapter_data->PciInformation.u.bits.BusNumber =
11824                     (reg_data[0] & 0x00FF0000) >> 16;
11825                 adapter_data->PciInformation.u.bits.DeviceNumber =
11826                     (reg_data[0] & 0x0000F800) >> 11;
11827                 adapter_data->PciInformation.u.bits.FunctionNumber =
11828                     (reg_data[0] & 0x00000700) >> 8;
11829                 ddi_prop_free((void *)reg_data);
11830         } else {
11831                 /*
11832                  * If we can't determine the PCI data then we fill in FF's for
11833                  * the data to indicate this.
11834                  */
11835                 adapter_data->PCIDeviceHwId = 0xFFFFFFFF;
11836                 adapter_data->MpiPortNumber = 0xFFFFFFFF;
11837                 adapter_data->PciInformation.u.AsDWORD = 0xFFFFFFFF;
11838         }
11839 
11840         /*
11841          * Saved in the mpt->m_fwversion
11842          */
11843         adapter_data->MpiFirmwareVersion = mpt->m_fwversion;
11844 }
11845 
11846 static void
11847 mptsas_read_adapter_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
11848 {
11849         char    *driver_verstr = MPTSAS_MOD_STRING;
11850 
11851         mptsas_lookup_pci_data(mpt, adapter_data);
11852         adapter_data->AdapterType = MPTIOCTL_ADAPTER_TYPE_SAS2;
11853         adapter_data->PCIDeviceHwId = (uint32_t)mpt->m_devid;
11854         adapter_data->PCIDeviceHwRev = (uint32_t)mpt->m_revid;
11855         adapter_data->SubSystemId = (uint32_t)mpt->m_ssid;
11856         adapter_data->SubsystemVendorId = (uint32_t)mpt->m_svid;
11857         (void) strcpy((char *)&adapter_data->DriverVersion[0], driver_verstr);
11858         adapter_data->BiosVersion = 0;
11859         (void) mptsas_get_bios_page3(mpt, &adapter_data->BiosVersion);
11860 }
11861 
11862 static void
11863 mptsas_read_pci_info(mptsas_t *mpt, mptsas_pci_info_t *pci_info)
11864 {
11865         int     *reg_data, i;
11866         uint_t  reglen;
11867 
11868         /*
11869          * Lookup the 'reg' property and extract the other data
11870          */
11871         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
11872             DDI_PROP_DONTPASS, "reg", &reg_data, &reglen) ==
11873             DDI_PROP_SUCCESS) {
11874                 /*
11875                  * Extract the PCI data from the 'reg' property first DWORD.
11876                  * The entry looks like the following:
11877                  * First DWORD:
11878                  * Bits 8 - 10 3-bit Function number
11879                  * Bits 11 - 15 5-bit Device number
11880                  * Bits 16 - 23 8-bit Bus number
11881                  */
11882                 pci_info->BusNumber = (reg_data[0] & 0x00FF0000) >> 16;
11883                 pci_info->DeviceNumber = (reg_data[0] & 0x0000F800) >> 11;
11884                 pci_info->FunctionNumber = (reg_data[0] & 0x00000700) >> 8;
11885                 ddi_prop_free((void *)reg_data);
11886         } else {
11887                 /*
11888                  * If we can't determine the PCI info then we fill in FF's for
11889                  * the data to indicate this.
11890                  */
11891                 pci_info->BusNumber = 0xFFFFFFFF;
11892                 pci_info->DeviceNumber = 0xFF;
11893                 pci_info->FunctionNumber = 0xFF;
11894         }
11895 
11896         /*
11897          * Now get the interrupt vector and the pci header.  The vector can
11898          * only be 0 right now.  The header is the first 256 bytes of config
11899          * space.
11900          */
11901         pci_info->InterruptVector = 0;
11902         for (i = 0; i < sizeof (pci_info->PciHeader); i++) {
11903                 pci_info->PciHeader[i] = pci_config_get8(mpt->m_config_handle,
11904                     i);
11905         }
11906 }
11907 
11908 static int
11909 mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data, int mode)
11910 {
11911         int                     status = 0;
11912         mptsas_reg_access_t     driverdata;
11913 
11914         mutex_enter(&mpt->m_mutex);
11915         if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
11916                 switch (driverdata.Command) {
11917                         /*
11918                          * IO access is not supported.
11919                          */
11920                         case REG_IO_READ:
11921                         case REG_IO_WRITE:
11922                                 mptsas_log(mpt, CE_WARN, "IO access is not "
11923                                     "supported.  Use memory access.");
11924                                 status = EINVAL;
11925                                 break;
11926 
11927                         case REG_MEM_READ:
11928                                 driverdata.RegData = ddi_get32(mpt->m_datap,
11929                                     (uint32_t *)(void *)mpt->m_reg +
11930                                     driverdata.RegOffset);
11931                                 if (ddi_copyout(&driverdata.RegData,
11932                                     &data->RegData,
11933                                     sizeof (driverdata.RegData), mode) != 0) {
11934                                         mptsas_log(mpt, CE_WARN, "Register "
11935                                             "Read Failed");
11936                                         status = EFAULT;
11937                                 }
11938                                 break;
11939 
11940                         case REG_MEM_WRITE:
11941                                 ddi_put32(mpt->m_datap,
11942                                     (uint32_t *)(void *)mpt->m_reg +
11943                                     driverdata.RegOffset,
11944                                     driverdata.RegData);
11945                                 break;
11946 
11947                         default:
11948                                 status = EINVAL;
11949                                 break;
11950                 }
11951         } else {
11952                 status = EFAULT;
11953         }
11954 
11955         mutex_exit(&mpt->m_mutex);
11956         return (status);
11957 }
11958 
11959 static int
11960 led_control(mptsas_t *mpt, intptr_t data, int mode)
11961 {
11962         int ret = 0;
11963         mptsas_led_control_t lc;
11964         mptsas_target_t *ptgt;
11965 
11966         if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) {
11967                 return (EFAULT);
11968         }
11969 
11970         if ((lc.Command != MPTSAS_LEDCTL_FLAG_SET &&
11971             lc.Command != MPTSAS_LEDCTL_FLAG_GET) ||
11972             lc.Led < MPTSAS_LEDCTL_LED_IDENT ||
11973             lc.Led > MPTSAS_LEDCTL_LED_OK2RM) {
11974                 return (EINVAL);
11975         }
11976 
11977         /* Locate the target we're interrogating... */
11978         mutex_enter(&mpt->m_mutex);
11979         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
11980             MPTSAS_HASH_FIRST);
11981         while (ptgt != NULL) {
11982                 if (ptgt->m_enclosure == lc.Enclosure &&
11983                     ptgt->m_slot_num == lc.Slot) {
11984                         break;
11985                 }
11986                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
11987                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
11988         }
11989         if (ptgt == NULL) {
11990                 /* We could not find a target for that enclosure/slot. */
11991                 mutex_exit(&mpt->m_mutex);
11992                 return (ENOENT);
11993         }
11994 
11995         if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) {
11996                 /* Update our internal LED state. */
11997                 ptgt->m_led_status &= ~(1 << (lc.Led - 1));
11998                 ptgt->m_led_status |= (!!lc.LedStatus) << (lc.Led - 1);
11999 
12000                 /* Flush it to the controller. */
12001                 ret = mptsas_flush_led_status(mpt, ptgt);
12002                 mutex_exit(&mpt->m_mutex);
12003                 return (ret);
12004         }
12005 
12006         /* Return our internal LED state. */
12007         lc.LedStatus = !!(ptgt->m_led_status & (1 << (lc.Led - 1)));
12008         mutex_exit(&mpt->m_mutex);
12009 
12010         if (ddi_copyout(&lc, (void *)data, sizeof (lc), mode) != 0) {
12011                 return (EFAULT);
12012         }
12013 
12014         return (0);
12015 }
12016 
12017 static int
12018 get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
12019 {
12020         int i;
12021         int count = 0;
12022         int ret = 0;
12023         mptsas_target_t *ptgt;
12024         mptsas_disk_info_t *di;
12025         STRUCT_DECL(mptsas_get_disk_info, gdi);
12026 
12027         STRUCT_INIT(gdi, get_udatamodel());
12028 
12029         if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi),
12030             mode) != 0) {
12031                 return (EFAULT);
12032         }
12033 
12034 restart:
12035         /* Find out how many targets there are. */
12036         mutex_enter(&mpt->m_mutex);
12037         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
12038             MPTSAS_HASH_FIRST);
12039         while (ptgt != NULL) {
12040                 count++;
12041                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
12042                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
12043         }
12044         mutex_exit(&mpt->m_mutex);
12045 
12046         /*
12047          * If we haven't been asked to copy out information on each target,
12048          * then just return the count.
12049          */
12050         STRUCT_FSET(gdi, DiskCount, count);
12051         if (STRUCT_FGETP(gdi, PtrDiskInfoArray) == NULL)
12052                 goto copy_out;
12053 
12054         /*
12055          * If we haven't been given a large enough buffer to copy out into,
12056          * let the caller know.
12057          */
12058         if (STRUCT_FGET(gdi, DiskInfoArraySize) <
12059             count * sizeof (mptsas_disk_info_t)) {
12060                 ret = ENOSPC;
12061                 goto copy_out;
12062         }
12063 
12064         di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP);
12065 
12066         mutex_enter(&mpt->m_mutex);
12067         i = 0;
12068         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
12069             MPTSAS_HASH_FIRST);
12070         while (ptgt != NULL) {
12071                 if (i >= count) {
12072                         /*
12073                          * The number of targets changed while we weren't
12074                          * looking.  Go again.
12075                          */
12076                         mutex_exit(&mpt->m_mutex);
12077                         kmem_free(di, count * sizeof (mptsas_disk_info_t));
12078                         goto restart;
12079                 }
12080                 di[i].Instance = mpt->m_instance;
12081                 di[i].Enclosure = ptgt->m_enclosure;
12082                 di[i].Slot = ptgt->m_slot_num;
12083                 di[i].SasAddress = ptgt->m_sas_wwn;
12084 
12085                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
12086                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
12087                 i++;
12088         }
12089         mutex_exit(&mpt->m_mutex);
12090         STRUCT_FSET(gdi, DiskCount, i);
12091 
12092         /* Copy out the disk information to the caller. */
12093         if (ddi_copyout((void *)di, STRUCT_FGETP(gdi, PtrDiskInfoArray),
12094             i * sizeof (mptsas_disk_info_t), mode) != 0) {
12095                 ret = EFAULT;
12096         }
12097 
12098         kmem_free(di, count * sizeof (mptsas_disk_info_t));
12099 
12100 copy_out:
12101         if (ddi_copyout(STRUCT_BUF(gdi), (void *)data, STRUCT_SIZE(gdi),
12102             mode) != 0) {
12103                 ret = EFAULT;
12104         }
12105 
12106         return (ret);
12107 }
12108 
12109 static int
12110 mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
12111     int *rval)
12112 {
12113         int                     status = 0;
12114         mptsas_t                *mpt;
12115         mptsas_update_flash_t   flashdata;
12116         mptsas_pass_thru_t      passthru_data;
12117         mptsas_adapter_data_t   adapter_data;
12118         mptsas_pci_info_t       pci_info;
12119         int                     copylen;
12120 
12121         int                     iport_flag = 0;
12122         dev_info_t              *dip = NULL;
12123         mptsas_phymask_t        phymask = 0;
12124         struct devctl_iocdata   *dcp = NULL;
12125         uint32_t                slotstatus = 0;
12126         char                    *addr = NULL;
12127         mptsas_target_t         *ptgt = NULL;
12128 
12129         *rval = MPTIOCTL_STATUS_GOOD;
12130         if (secpolicy_sys_config(credp, B_FALSE) != 0) {
12131                 return (EPERM);
12132         }
12133 
12134         mpt = ddi_get_soft_state(mptsas_state, MINOR2INST(getminor(dev)));
12135         if (mpt == NULL) {
12136                 /*
12137                  * Called from iport node, get the states
12138                  */
12139                 iport_flag = 1;
12140                 dip = mptsas_get_dip_from_dev(dev, &phymask);
12141                 if (dip == NULL) {
12142                         return (ENXIO);
12143                 }
12144                 mpt = DIP2MPT(dip);
12145         }
12146         /* Make sure power level is D0 before accessing registers */
12147         mutex_enter(&mpt->m_mutex);
12148         if (mpt->m_options & MPTSAS_OPT_PM) {
12149                 (void) pm_busy_component(mpt->m_dip, 0);
12150                 if (mpt->m_power_level != PM_LEVEL_D0) {
12151                         mutex_exit(&mpt->m_mutex);
12152                         if (pm_raise_power(mpt->m_dip, 0, PM_LEVEL_D0) !=
12153                             DDI_SUCCESS) {
12154                                 mptsas_log(mpt, CE_WARN,
12155                                     "mptsas%d: mptsas_ioctl: Raise power "
12156                                     "request failed.", mpt->m_instance);
12157                                 (void) pm_idle_component(mpt->m_dip, 0);
12158                                 return (ENXIO);
12159                         }
12160                 } else {
12161                         mutex_exit(&mpt->m_mutex);
12162                 }
12163         } else {
12164                 mutex_exit(&mpt->m_mutex);
12165         }
12166 
12167         if (iport_flag) {
12168                 status = scsi_hba_ioctl(dev, cmd, data, mode, credp, rval);
12169                 if (status != 0) {
12170                         goto out;
12171                 }
12172                 /*
12173                  * The following code control the OK2RM LED, it doesn't affect
12174                  * the ioctl return status.
12175                  */
12176                 if ((cmd == DEVCTL_DEVICE_ONLINE) ||
12177                     (cmd == DEVCTL_DEVICE_OFFLINE)) {
12178                         if (ndi_dc_allochdl((void *)data, &dcp) !=
12179                             NDI_SUCCESS) {
12180                                 goto out;
12181                         }
12182                         addr = ndi_dc_getaddr(dcp);
12183                         ptgt = mptsas_addr_to_ptgt(mpt, addr, phymask);
12184                         if (ptgt == NULL) {
12185                                 NDBG14(("mptsas_ioctl led control: tgt %s not "
12186                                     "found", addr));
12187                                 ndi_dc_freehdl(dcp);
12188                                 goto out;
12189                         }
12190                         mutex_enter(&mpt->m_mutex);
12191                         if (cmd == DEVCTL_DEVICE_ONLINE) {
12192                                 ptgt->m_tgt_unconfigured = 0;
12193                         } else if (cmd == DEVCTL_DEVICE_OFFLINE) {
12194                                 ptgt->m_tgt_unconfigured = 1;
12195                         }
12196                         if (cmd == DEVCTL_DEVICE_OFFLINE) {
12197                                 ptgt->m_led_status |=
12198                                     (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
12199                         } else {
12200                                 ptgt->m_led_status &=
12201                                     ~(1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
12202                         }
12203                         if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) {
12204                                 NDBG14(("mptsas_ioctl: set LED for tgt %s "
12205                                     "failed %x", addr, slotstatus));
12206                         }
12207                         mutex_exit(&mpt->m_mutex);
12208                         ndi_dc_freehdl(dcp);
12209                 }
12210                 goto out;
12211         }
12212         switch (cmd) {
12213                 case MPTIOCTL_GET_DISK_INFO:
12214                         status = get_disk_info(mpt, data, mode);
12215                         break;
12216                 case MPTIOCTL_LED_CONTROL:
12217                         status = led_control(mpt, data, mode);
12218                         break;
12219                 case MPTIOCTL_UPDATE_FLASH:
12220                         if (ddi_copyin((void *)data, &flashdata,
12221                                 sizeof (struct mptsas_update_flash), mode)) {
12222                                 status = EFAULT;
12223                                 break;
12224                         }
12225 
12226                         mutex_enter(&mpt->m_mutex);
12227                         if (mptsas_update_flash(mpt,
12228                             (caddr_t)(long)flashdata.PtrBuffer,
12229                             flashdata.ImageSize, flashdata.ImageType, mode)) {
12230                                 status = EFAULT;
12231                         }
12232 
12233                         /*
12234                          * Reset the chip to start using the new
12235                          * firmware.  Reset if failed also.
12236                          */
12237                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
12238                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
12239                                 status = EFAULT;
12240                         }
12241                         mutex_exit(&mpt->m_mutex);
12242                         break;
12243                 case MPTIOCTL_PASS_THRU:
12244                         /*
12245                          * The user has requested to pass through a command to
12246                          * be executed by the MPT firmware.  Call our routine
12247                          * which does this.  Only allow one passthru IOCTL at
12248                          * one time. Other threads will block on
12249                          * m_passthru_mutex, which is of adaptive variant.
12250                          */
12251                         if (ddi_copyin((void *)data, &passthru_data,
12252                             sizeof (mptsas_pass_thru_t), mode)) {
12253                                 status = EFAULT;
12254                                 break;
12255                         }
12256                         mutex_enter(&mpt->m_passthru_mutex);
12257                         mutex_enter(&mpt->m_mutex);
12258                         status = mptsas_pass_thru(mpt, &passthru_data, mode);
12259                         mutex_exit(&mpt->m_mutex);
12260                         mutex_exit(&mpt->m_passthru_mutex);
12261 
12262                         break;
12263                 case MPTIOCTL_GET_ADAPTER_DATA:
12264                         /*
12265                          * The user has requested to read adapter data.  Call
12266                          * our routine which does this.
12267                          */
12268                         bzero(&adapter_data, sizeof (mptsas_adapter_data_t));
12269                         if (ddi_copyin((void *)data, (void *)&adapter_data,
12270                             sizeof (mptsas_adapter_data_t), mode)) {
12271                                 status = EFAULT;
12272                                 break;
12273                         }
12274                         if (adapter_data.StructureLength >=
12275                             sizeof (mptsas_adapter_data_t)) {
12276                                 adapter_data.StructureLength = (uint32_t)
12277                                     sizeof (mptsas_adapter_data_t);
12278                                 copylen = sizeof (mptsas_adapter_data_t);
12279                                 mutex_enter(&mpt->m_mutex);
12280                                 mptsas_read_adapter_data(mpt, &adapter_data);
12281                                 mutex_exit(&mpt->m_mutex);
12282                         } else {
12283                                 adapter_data.StructureLength = (uint32_t)
12284                                     sizeof (mptsas_adapter_data_t);
12285                                 copylen = sizeof (adapter_data.StructureLength);
12286                                 *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
12287                         }
12288                         if (ddi_copyout((void *)(&adapter_data), (void *)data,
12289                             copylen, mode) != 0) {
12290                                 status = EFAULT;
12291                         }
12292                         break;
12293                 case MPTIOCTL_GET_PCI_INFO:
12294                         /*
12295                          * The user has requested to read pci info.  Call
12296                          * our routine which does this.
12297                          */
12298                         bzero(&pci_info, sizeof (mptsas_pci_info_t));
12299                         mutex_enter(&mpt->m_mutex);
12300                         mptsas_read_pci_info(mpt, &pci_info);
12301                         mutex_exit(&mpt->m_mutex);
12302                         if (ddi_copyout((void *)(&pci_info), (void *)data,
12303                             sizeof (mptsas_pci_info_t), mode) != 0) {
12304                                 status = EFAULT;
12305                         }
12306                         break;
12307                 case MPTIOCTL_RESET_ADAPTER:
12308                         mutex_enter(&mpt->m_mutex);
12309                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
12310                         if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
12311                                 mptsas_log(mpt, CE_WARN, "reset adapter IOCTL "
12312                                     "failed");
12313                                 status = EFAULT;
12314                         }
12315                         mutex_exit(&mpt->m_mutex);
12316                         break;
12317                 case MPTIOCTL_DIAG_ACTION:
12318                         /*
12319                          * The user has done a diag buffer action.  Call our
12320                          * routine which does this.  Only allow one diag action
12321                          * at one time.
12322                          */
12323                         mutex_enter(&mpt->m_mutex);
12324                         if (mpt->m_diag_action_in_progress) {
12325                                 mutex_exit(&mpt->m_mutex);
12326                                 return (EBUSY);
12327                         }
12328                         mpt->m_diag_action_in_progress = 1;
12329                         status = mptsas_diag_action(mpt,
12330                             (mptsas_diag_action_t *)data, mode);
12331                         mpt->m_diag_action_in_progress = 0;
12332                         mutex_exit(&mpt->m_mutex);
12333                         break;
12334                 case MPTIOCTL_EVENT_QUERY:
12335                         /*
12336                          * The user has done an event query. Call our routine
12337                          * which does this.
12338                          */
12339                         status = mptsas_event_query(mpt,
12340                             (mptsas_event_query_t *)data, mode, rval);
12341                         break;
12342                 case MPTIOCTL_EVENT_ENABLE:
12343                         /*
12344                          * The user has done an event enable. Call our routine
12345                          * which does this.
12346                          */
12347                         status = mptsas_event_enable(mpt,
12348                             (mptsas_event_enable_t *)data, mode, rval);
12349                         break;
12350                 case MPTIOCTL_EVENT_REPORT:
12351                         /*
12352                          * The user has done an event report. Call our routine
12353                          * which does this.
12354                          */
12355                         status = mptsas_event_report(mpt,
12356                             (mptsas_event_report_t *)data, mode, rval);
12357                         break;
12358                 case MPTIOCTL_REG_ACCESS:
12359                         /*
12360                          * The user has requested register access.  Call our
12361                          * routine which does this.
12362                          */
12363                         status = mptsas_reg_access(mpt,
12364                             (mptsas_reg_access_t *)data, mode);
12365                         break;
12366                 default:
12367                         status = scsi_hba_ioctl(dev, cmd, data, mode, credp,
12368                             rval);
12369                         break;
12370         }
12371 
12372 out:
12373         if (mpt->m_options & MPTSAS_OPT_PM)
12374                 (void) pm_idle_component(mpt->m_dip, 0);
12375         return (status);
12376 }
12377 
12378 int
12379 mptsas_restart_ioc(mptsas_t *mpt)
12380 {
12381         int             rval = DDI_SUCCESS;
12382         mptsas_target_t *ptgt = NULL;
12383 
12384         ASSERT(mutex_owned(&mpt->m_mutex));
12385 
12386         /*
12387          * Set a flag telling I/O path that we're processing a reset.  This is
12388          * needed because after the reset is complete, the hash table still
12389          * needs to be rebuilt.  If I/Os are started before the hash table is
12390          * rebuilt, I/O errors will occur.  This flag allows I/Os to be marked
12391          * so that they can be retried.
12392          */
12393         mpt->m_in_reset = TRUE;
12394 
12395         /*
12396          * Set all throttles to HOLD
12397          */
12398         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
12399             MPTSAS_HASH_FIRST);
12400         while (ptgt != NULL) {
12401                 mutex_enter(&ptgt->m_tgt_intr_mutex);
12402                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
12403                 mutex_exit(&ptgt->m_tgt_intr_mutex);
12404 
12405                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
12406                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
12407         }
12408 
12409         /*
12410          * Disable interrupts
12411          */
12412         MPTSAS_DISABLE_INTR(mpt);
12413 
12414         /*
12415          * Abort all commands: outstanding commands, commands in waitq
12416          */
12417         mptsas_flush_hba(mpt);
12418 
12419         /*
12420          * Reinitialize the chip.
12421          */
12422         if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
12423                 rval = DDI_FAILURE;
12424         }
12425 
12426         /*
12427          * Enable interrupts again
12428          */
12429         MPTSAS_ENABLE_INTR(mpt);
12430 
12431         /*
12432          * If mptsas_init_chip was successful, update the driver data.
12433          */
12434         if (rval == DDI_SUCCESS) {
12435                 mptsas_update_driver_data(mpt);
12436         }
12437 
12438         /*
12439          * Reset the throttles
12440          */
12441         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
12442             MPTSAS_HASH_FIRST);
12443         while (ptgt != NULL) {
12444                 mutex_enter(&ptgt->m_tgt_intr_mutex);
12445                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
12446                 mutex_exit(&ptgt->m_tgt_intr_mutex);
12447 
12448                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
12449                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
12450         }
12451 
12452         mptsas_doneq_empty(mpt);
12453         mptsas_restart_hba(mpt);
12454 
12455         if (rval != DDI_SUCCESS) {
12456                 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
12457                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
12458         }
12459 
12460         /*
12461          * Clear the reset flag so that I/Os can continue.
12462          */
12463         mpt->m_in_reset = FALSE;
12464 
12465         return (rval);
12466 }
12467 
12468 static int
12469 mptsas_init_chip(mptsas_t *mpt, int first_time)
12470 {
12471         ddi_dma_cookie_t        cookie;
12472         uint32_t                i;
12473         int                     rval;
12474 
12475         /*
12476          * Check to see if the firmware image is valid
12477          */
12478         if (ddi_get32(mpt->m_datap, &mpt->m_reg->HostDiagnostic) &
12479             MPI2_DIAG_FLASH_BAD_SIG) {
12480                 mptsas_log(mpt, CE_WARN, "mptsas bad flash signature!");
12481                 goto fail;
12482         }
12483 
12484         /*
12485          * Reset the chip
12486          */
12487         rval = mptsas_ioc_reset(mpt, first_time);
12488         if (rval == MPTSAS_RESET_FAIL) {
12489                 mptsas_log(mpt, CE_WARN, "hard reset failed!");
12490                 goto fail;
12491         }
12492 
12493         if ((rval == MPTSAS_SUCCESS_MUR) && (!first_time)) {
12494                 goto mur;
12495         }
12496         /*
12497          * Setup configuration space
12498          */
12499         if (mptsas_config_space_init(mpt) == FALSE) {
12500                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init "
12501                     "failed!");
12502                 goto fail;
12503         }
12504 
12505         /*
12506          * IOC facts can change after a diag reset so all buffers that are
12507          * based on these numbers must be de-allocated and re-allocated.  Get
12508          * new IOC facts each time chip is initialized.
12509          */
12510         if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
12511                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed");
12512                 goto fail;
12513         }
12514 
12515         if (mptsas_alloc_active_slots(mpt, KM_SLEEP)) {
12516                 goto fail;
12517         }
12518         /*
12519          * Allocate request message frames, reply free queue, reply descriptor
12520          * post queue, and reply message frames using latest IOC facts.
12521          */
12522         if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) {
12523                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames failed");
12524                 goto fail;
12525         }
12526         if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) {
12527                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue failed!");
12528                 goto fail;
12529         }
12530         if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) {
12531                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue failed!");
12532                 goto fail;
12533         }
12534         if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) {
12535                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_reply_frames failed!");
12536                 goto fail;
12537         }
12538 
12539 mur:
12540         /*
12541          * Re-Initialize ioc to operational state
12542          */
12543         if (mptsas_ioc_init(mpt) == DDI_FAILURE) {
12544                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_init failed");
12545                 goto fail;
12546         }
12547 
12548         mptsas_alloc_reply_args(mpt);
12549 
12550         /*
12551          * Initialize reply post index.  Reply free index is initialized after
12552          * the next loop.
12553          */
12554         mpt->m_post_index = 0;
12555 
12556         /*
12557          * Initialize the Reply Free Queue with the physical addresses of our
12558          * reply frames.
12559          */
12560         cookie.dmac_address = mpt->m_reply_frame_dma_addr;
12561         for (i = 0; i < mpt->m_max_replies; i++) {
12562                 ddi_put32(mpt->m_acc_free_queue_hdl,
12563                     &((uint32_t *)(void *)mpt->m_free_queue)[i],
12564                     cookie.dmac_address);
12565                 cookie.dmac_address += mpt->m_reply_frame_size;
12566         }
12567         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
12568             DDI_DMA_SYNC_FORDEV);
12569 
12570         /*
12571          * Initialize the reply free index to one past the last frame on the
12572          * queue.  This will signify that the queue is empty to start with.
12573          */
12574         mpt->m_free_index = i;
12575         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex, i);
12576 
12577         /*
12578          * Initialize the reply post queue to 0xFFFFFFFF,0xFFFFFFFF's.
12579          */
12580         for (i = 0; i < mpt->m_post_queue_depth; i++) {
12581                 ddi_put64(mpt->m_acc_post_queue_hdl,
12582                     &((uint64_t *)(void *)mpt->m_post_queue)[i],
12583                     0xFFFFFFFFFFFFFFFF);
12584         }
12585         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
12586             DDI_DMA_SYNC_FORDEV);
12587 
12588         /*
12589          * Enable ports
12590          */
12591         if (mptsas_ioc_enable_port(mpt) == DDI_FAILURE) {
12592                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_enable_port failed");
12593                 goto fail;
12594         }
12595 
12596         /*
12597          * enable events
12598          */
12599         if (mptsas_ioc_enable_event_notification(mpt)) {
12600                 goto fail;
12601         }
12602 
12603         /*
12604          * We need checks in attach and these.
12605          * chip_init is called in mult. places
12606          */
12607 
12608         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
12609             DDI_SUCCESS) ||
12610             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
12611             DDI_SUCCESS) ||
12612             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
12613             DDI_SUCCESS) ||
12614             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
12615             DDI_SUCCESS) ||
12616             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
12617             DDI_SUCCESS)) {
12618                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
12619                 goto fail;
12620         }
12621 
12622         /* Check all acc handles */
12623         if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
12624             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
12625             DDI_SUCCESS) ||
12626             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
12627             DDI_SUCCESS) ||
12628             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
12629             DDI_SUCCESS) ||
12630             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
12631             DDI_SUCCESS) ||
12632             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
12633             DDI_SUCCESS) ||
12634             (mptsas_check_acc_handle(mpt->m_config_handle) !=
12635             DDI_SUCCESS)) {
12636                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
12637                 goto fail;
12638         }
12639 
12640         return (DDI_SUCCESS);
12641 
12642 fail:
12643         return (DDI_FAILURE);
12644 }
12645 
12646 static int
12647 mptsas_get_pci_cap(mptsas_t *mpt)
12648 {
12649         ushort_t caps_ptr, cap, cap_count;
12650 
12651         if (mpt->m_config_handle == NULL)
12652                 return (FALSE);
12653         /*
12654          * Check if capabilities list is supported and if so,
12655          * get initial capabilities pointer and clear bits 0,1.
12656          */
12657         if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT)
12658             & PCI_STAT_CAP) {
12659                 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
12660                     PCI_CONF_CAP_PTR), 4);
12661         } else {
12662                 caps_ptr = PCI_CAP_NEXT_PTR_NULL;
12663         }
12664 
12665         /*
12666          * Walk capabilities if supported.
12667          */
12668         for (cap_count = 0; caps_ptr != PCI_CAP_NEXT_PTR_NULL; ) {
12669 
12670                 /*
12671                  * Check that we haven't exceeded the maximum number of
12672                  * capabilities and that the pointer is in a valid range.
12673                  */
12674                 if (++cap_count > 48) {
12675                         mptsas_log(mpt, CE_WARN,
12676                             "too many device capabilities.\n");
12677                         break;
12678                 }
12679                 if (caps_ptr < 64) {
12680                         mptsas_log(mpt, CE_WARN,
12681                             "capabilities pointer 0x%x out of range.\n",
12682                             caps_ptr);
12683                         break;
12684                 }
12685 
12686                 /*
12687                  * Get next capability and check that it is valid.
12688                  * For now, we only support power management.
12689                  */
12690                 cap = pci_config_get8(mpt->m_config_handle, caps_ptr);
12691                 switch (cap) {
12692                         case PCI_CAP_ID_PM:
12693                                 mptsas_log(mpt, CE_NOTE,
12694                                     "?mptsas%d supports power management.\n",
12695                                     mpt->m_instance);
12696                                 mpt->m_options |= MPTSAS_OPT_PM;
12697 
12698                                 /* Save PMCSR offset */
12699                                 mpt->m_pmcsr_offset = caps_ptr + PCI_PMCSR;
12700                                 break;
12701                         /*
12702                          * The following capabilities are valid.  Any others
12703                          * will cause a message to be logged.
12704                          */
12705                         case PCI_CAP_ID_VPD:
12706                         case PCI_CAP_ID_MSI:
12707                         case PCI_CAP_ID_PCIX:
12708                         case PCI_CAP_ID_PCI_E:
12709                         case PCI_CAP_ID_MSI_X:
12710                                 break;
12711                         default:
12712                                 mptsas_log(mpt, CE_NOTE,
12713                                     "?mptsas%d unrecognized capability "
12714                                     "0x%x.\n", mpt->m_instance, cap);
12715                                 break;
12716                 }
12717 
12718                 /*
12719                  * Get next capabilities pointer and clear bits 0,1.
12720                  */
12721                 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
12722                     (caps_ptr + PCI_CAP_NEXT_PTR)), 4);
12723         }
12724         return (TRUE);
12725 }
12726 
12727 static int
12728 mptsas_init_pm(mptsas_t *mpt)
12729 {
12730         char            pmc_name[16];
12731         char            *pmc[] = {
12732                                 NULL,
12733                                 "0=Off (PCI D3 State)",
12734                                 "3=On (PCI D0 State)",
12735                                 NULL
12736                         };
12737         uint16_t        pmcsr_stat;
12738 
12739         if (mptsas_get_pci_cap(mpt) == FALSE) {
12740                 return (DDI_FAILURE);
12741         }
12742         /*
12743          * If PCI's capability does not support PM, then don't need
12744          * to registe the pm-components
12745          */
12746         if (!(mpt->m_options & MPTSAS_OPT_PM))
12747                 return (DDI_SUCCESS);
12748         /*
12749          * If power management is supported by this chip, create
12750          * pm-components property for the power management framework
12751          */
12752         (void) sprintf(pmc_name, "NAME=mptsas%d", mpt->m_instance);
12753         pmc[0] = pmc_name;
12754         if (ddi_prop_update_string_array(DDI_DEV_T_NONE, mpt->m_dip,
12755             "pm-components", pmc, 3) != DDI_PROP_SUCCESS) {
12756                 mutex_enter(&mpt->m_intr_mutex);
12757                 mpt->m_options &= ~MPTSAS_OPT_PM;
12758                 mutex_exit(&mpt->m_intr_mutex);
12759                 mptsas_log(mpt, CE_WARN,
12760                     "mptsas%d: pm-component property creation failed.",
12761                     mpt->m_instance);
12762                 return (DDI_FAILURE);
12763         }
12764 
12765         /*
12766          * Power on device.
12767          */
12768         (void) pm_busy_component(mpt->m_dip, 0);
12769         pmcsr_stat = pci_config_get16(mpt->m_config_handle,
12770             mpt->m_pmcsr_offset);
12771         if ((pmcsr_stat & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_D0) {
12772                 mptsas_log(mpt, CE_WARN, "mptsas%d: Power up the device",
12773                     mpt->m_instance);
12774                 pci_config_put16(mpt->m_config_handle, mpt->m_pmcsr_offset,
12775                     PCI_PMCSR_D0);
12776         }
12777         if (pm_power_has_changed(mpt->m_dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) {
12778                 mptsas_log(mpt, CE_WARN, "pm_power_has_changed failed");
12779                 return (DDI_FAILURE);
12780         }
12781         mutex_enter(&mpt->m_intr_mutex);
12782         mpt->m_power_level = PM_LEVEL_D0;
12783         mutex_exit(&mpt->m_intr_mutex);
12784         /*
12785          * Set pm idle delay.
12786          */
12787         mpt->m_pm_idle_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
12788             mpt->m_dip, 0, "mptsas-pm-idle-delay", MPTSAS_PM_IDLE_TIMEOUT);
12789 
12790         return (DDI_SUCCESS);
12791 }
12792 
12793 static int
12794 mptsas_register_intrs(mptsas_t *mpt)
12795 {
12796         dev_info_t *dip;
12797         int intr_types;
12798 
12799         dip = mpt->m_dip;
12800 
12801         /* Get supported interrupt types */
12802         if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) {
12803                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_supported_types "
12804                     "failed\n");
12805                 return (FALSE);
12806         }
12807 
12808         NDBG6(("ddi_intr_get_supported_types() returned: 0x%x", intr_types));
12809 
12810         /*
12811          * Try MSI, but fall back to FIXED
12812          */
12813         if (mptsas_enable_msi && (intr_types & DDI_INTR_TYPE_MSI)) {
12814                 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_MSI) == DDI_SUCCESS) {
12815                         NDBG0(("Using MSI interrupt type"));
12816                         mpt->m_intr_type = DDI_INTR_TYPE_MSI;
12817                         return (TRUE);
12818                 }
12819         }
12820         if (intr_types & DDI_INTR_TYPE_FIXED) {
12821                 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_FIXED) == DDI_SUCCESS) {
12822                         NDBG0(("Using FIXED interrupt type"));
12823                         mpt->m_intr_type = DDI_INTR_TYPE_FIXED;
12824                         return (TRUE);
12825                 } else {
12826                         NDBG0(("FIXED interrupt registration failed"));
12827                         return (FALSE);
12828                 }
12829         }
12830 
12831         return (FALSE);
12832 }
12833 
12834 static void
12835 mptsas_unregister_intrs(mptsas_t *mpt)
12836 {
12837         mptsas_rem_intrs(mpt);
12838 }
12839 
12840 /*
12841  * mptsas_add_intrs:
12842  *
12843  * Register FIXED or MSI interrupts.
12844  */
12845 static int
12846 mptsas_add_intrs(mptsas_t *mpt, int intr_type)
12847 {
12848         dev_info_t      *dip = mpt->m_dip;
12849         int             avail, actual, count = 0;
12850         int             i, flag, ret;
12851 
12852         NDBG6(("mptsas_add_intrs:interrupt type 0x%x", intr_type));
12853 
12854         /* Get number of interrupts */
12855         ret = ddi_intr_get_nintrs(dip, intr_type, &count);
12856         if ((ret != DDI_SUCCESS) || (count <= 0)) {
12857                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_nintrs() failed, "
12858                     "ret %d count %d\n", ret, count);
12859 
12860                 return (DDI_FAILURE);
12861         }
12862 
12863         /* Get number of available interrupts */
12864         ret = ddi_intr_get_navail(dip, intr_type, &avail);
12865         if ((ret != DDI_SUCCESS) || (avail == 0)) {
12866                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_navail() failed, "
12867                     "ret %d avail %d\n", ret, avail);
12868 
12869                 return (DDI_FAILURE);
12870         }
12871 
12872         if (avail < count) {
12873                 mptsas_log(mpt, CE_NOTE, "ddi_intr_get_nvail returned %d, "
12874                     "navail() returned %d", count, avail);
12875         }
12876 
12877         /* Mpt only have one interrupt routine */
12878         if ((intr_type == DDI_INTR_TYPE_MSI) && (count > 1)) {
12879                 count = 1;
12880         }
12881 
12882         /* Allocate an array of interrupt handles */
12883         mpt->m_intr_size = count * sizeof (ddi_intr_handle_t);
12884         mpt->m_htable = kmem_alloc(mpt->m_intr_size, KM_SLEEP);
12885 
12886         flag = DDI_INTR_ALLOC_NORMAL;
12887 
12888         /* call ddi_intr_alloc() */
12889         ret = ddi_intr_alloc(dip, mpt->m_htable, intr_type, 0,
12890             count, &actual, flag);
12891 
12892         if ((ret != DDI_SUCCESS) || (actual == 0)) {
12893                 mptsas_log(mpt, CE_WARN, "ddi_intr_alloc() failed, ret %d\n",
12894                     ret);
12895                 kmem_free(mpt->m_htable, mpt->m_intr_size);
12896                 return (DDI_FAILURE);
12897         }
12898 
12899         /* use interrupt count returned or abort? */
12900         if (actual < count) {
12901                 mptsas_log(mpt, CE_NOTE, "Requested: %d, Received: %d\n",
12902                     count, actual);
12903         }
12904 
12905         mpt->m_intr_cnt = actual;
12906 
12907         /*
12908          * Get priority for first msi, assume remaining are all the same
12909          */
12910         if ((ret = ddi_intr_get_pri(mpt->m_htable[0],
12911             &mpt->m_intr_pri)) != DDI_SUCCESS) {
12912                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_pri() failed %d\n", ret);
12913 
12914                 /* Free already allocated intr */
12915                 for (i = 0; i < actual; i++) {
12916                         (void) ddi_intr_free(mpt->m_htable[i]);
12917                 }
12918 
12919                 kmem_free(mpt->m_htable, mpt->m_intr_size);
12920                 return (DDI_FAILURE);
12921         }
12922 
12923         /* Test for high level mutex */
12924         if (mpt->m_intr_pri >= ddi_intr_get_hilevel_pri()) {
12925                 mptsas_log(mpt, CE_WARN, "mptsas_add_intrs: "
12926                     "Hi level interrupt not supported\n");
12927 
12928                 /* Free already allocated intr */
12929                 for (i = 0; i < actual; i++) {
12930                         (void) ddi_intr_free(mpt->m_htable[i]);
12931                 }
12932 
12933                 kmem_free(mpt->m_htable, mpt->m_intr_size);
12934                 return (DDI_FAILURE);
12935         }
12936 
12937         /* Call ddi_intr_add_handler() */
12938         for (i = 0; i < actual; i++) {
12939                 if ((ret = ddi_intr_add_handler(mpt->m_htable[i], mptsas_intr,
12940                     (caddr_t)mpt, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
12941                         mptsas_log(mpt, CE_WARN, "ddi_intr_add_handler() "
12942                             "failed %d\n", ret);
12943 
12944                         /* Free already allocated intr */
12945                         for (i = 0; i < actual; i++) {
12946                                 (void) ddi_intr_free(mpt->m_htable[i]);
12947                         }
12948 
12949                         kmem_free(mpt->m_htable, mpt->m_intr_size);
12950                         return (DDI_FAILURE);
12951                 }
12952         }
12953 
12954         if ((ret = ddi_intr_get_cap(mpt->m_htable[0], &mpt->m_intr_cap))
12955             != DDI_SUCCESS) {
12956                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_cap() failed %d\n", ret);
12957 
12958                 /* Free already allocated intr */
12959                 for (i = 0; i < actual; i++) {
12960                         (void) ddi_intr_free(mpt->m_htable[i]);
12961                 }
12962 
12963                 kmem_free(mpt->m_htable, mpt->m_intr_size);
12964                 return (DDI_FAILURE);
12965         }
12966 
12967         /*
12968          * Enable interrupts
12969          */
12970         if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
12971                 /* Call ddi_intr_block_enable() for MSI interrupts */
12972                 (void) ddi_intr_block_enable(mpt->m_htable, mpt->m_intr_cnt);
12973         } else {
12974                 /* Call ddi_intr_enable for MSI or FIXED interrupts */
12975                 for (i = 0; i < mpt->m_intr_cnt; i++) {
12976                         (void) ddi_intr_enable(mpt->m_htable[i]);
12977                 }
12978         }
12979         return (DDI_SUCCESS);
12980 }
12981 
12982 /*
12983  * mptsas_rem_intrs:
12984  *
12985  * Unregister FIXED or MSI interrupts
12986  */
12987 static void
12988 mptsas_rem_intrs(mptsas_t *mpt)
12989 {
12990         int     i;
12991 
12992         NDBG6(("mptsas_rem_intrs"));
12993 
12994         /* Disable all interrupts */
12995         if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
12996                 /* Call ddi_intr_block_disable() */
12997                 (void) ddi_intr_block_disable(mpt->m_htable, mpt->m_intr_cnt);
12998         } else {
12999                 for (i = 0; i < mpt->m_intr_cnt; i++) {
13000                         (void) ddi_intr_disable(mpt->m_htable[i]);
13001                 }
13002         }
13003 
13004         /* Call ddi_intr_remove_handler() */
13005         for (i = 0; i < mpt->m_intr_cnt; i++) {
13006                 (void) ddi_intr_remove_handler(mpt->m_htable[i]);
13007                 (void) ddi_intr_free(mpt->m_htable[i]);
13008         }
13009 
13010         kmem_free(mpt->m_htable, mpt->m_intr_size);
13011 }
13012 
13013 /*
13014  * The IO fault service error handling callback function
13015  */
13016 /*ARGSUSED*/
13017 static int
13018 mptsas_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
13019 {
13020         /*
13021          * as the driver can always deal with an error in any dma or
13022          * access handle, we can just return the fme_status value.
13023          */
13024         pci_ereport_post(dip, err, NULL);
13025         return (err->fme_status);
13026 }
13027 
13028 /*
13029  * mptsas_fm_init - initialize fma capabilities and register with IO
13030  *               fault services.
13031  */
13032 static void
13033 mptsas_fm_init(mptsas_t *mpt)
13034 {
13035         /*
13036          * Need to change iblock to priority for new MSI intr
13037          */
13038         ddi_iblock_cookie_t     fm_ibc;
13039 
13040         /* Only register with IO Fault Services if we have some capability */
13041         if (mpt->m_fm_capabilities) {
13042                 /* Adjust access and dma attributes for FMA */
13043                 mpt->m_reg_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
13044                 mpt->m_msg_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
13045                 mpt->m_io_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
13046 
13047                 /*
13048                  * Register capabilities with IO Fault Services.
13049                  * mpt->m_fm_capabilities will be updated to indicate
13050                  * capabilities actually supported (not requested.)
13051                  */
13052                 ddi_fm_init(mpt->m_dip, &mpt->m_fm_capabilities, &fm_ibc);
13053 
13054                 /*
13055                  * Initialize pci ereport capabilities if ereport
13056                  * capable (should always be.)
13057                  */
13058                 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
13059                     DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13060                         pci_ereport_setup(mpt->m_dip);
13061                 }
13062 
13063                 /*
13064                  * Register error callback if error callback capable.
13065                  */
13066                 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13067                         ddi_fm_handler_register(mpt->m_dip,
13068                             mptsas_fm_error_cb, (void *) mpt);
13069                 }
13070         }
13071 }
13072 
13073 /*
13074  * mptsas_fm_fini - Releases fma capabilities and un-registers with IO
13075  *               fault services.
13076  *
13077  */
13078 static void
13079 mptsas_fm_fini(mptsas_t *mpt)
13080 {
13081         /* Only unregister FMA capabilities if registered */
13082         if (mpt->m_fm_capabilities) {
13083 
13084                 /*
13085                  * Un-register error callback if error callback capable.
13086                  */
13087 
13088                 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13089                         ddi_fm_handler_unregister(mpt->m_dip);
13090                 }
13091 
13092                 /*
13093                  * Release any resources allocated by pci_ereport_setup()
13094                  */
13095 
13096                 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
13097                     DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13098                         pci_ereport_teardown(mpt->m_dip);
13099                 }
13100 
13101                 /* Unregister from IO Fault Services */
13102                 ddi_fm_fini(mpt->m_dip);
13103 
13104                 /* Adjust access and dma attributes for FMA */
13105                 mpt->m_reg_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
13106                 mpt->m_msg_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
13107                 mpt->m_io_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
13108 
13109         }
13110 }
13111 
13112 int
13113 mptsas_check_acc_handle(ddi_acc_handle_t handle)
13114 {
13115         ddi_fm_error_t  de;
13116 
13117         if (handle == NULL)
13118                 return (DDI_FAILURE);
13119         ddi_fm_acc_err_get(handle, &de, DDI_FME_VER0);
13120         return (de.fme_status);
13121 }
13122 
13123 int
13124 mptsas_check_dma_handle(ddi_dma_handle_t handle)
13125 {
13126         ddi_fm_error_t  de;
13127 
13128         if (handle == NULL)
13129                 return (DDI_FAILURE);
13130         ddi_fm_dma_err_get(handle, &de, DDI_FME_VER0);
13131         return (de.fme_status);
13132 }
13133 
13134 void
13135 mptsas_fm_ereport(mptsas_t *mpt, char *detail)
13136 {
13137         uint64_t        ena;
13138         char            buf[FM_MAX_CLASS];
13139 
13140         (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
13141         ena = fm_ena_generate(0, FM_ENA_FMT1);
13142         if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities)) {
13143                 ddi_fm_ereport_post(mpt->m_dip, buf, ena, DDI_NOSLEEP,
13144                     FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
13145         }
13146 }
13147 
13148 static int
13149 mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
13150     uint16_t *dev_handle, mptsas_target_t **pptgt)
13151 {
13152         int             rval;
13153         uint32_t        dev_info;
13154         uint64_t        sas_wwn;
13155         mptsas_phymask_t phymask;
13156         uint8_t         physport, phynum, config, disk;
13157         mptsas_slots_t  *slots = mpt->m_active;
13158         uint64_t        devicename;
13159         uint16_t        pdev_hdl;
13160         mptsas_target_t *tmp_tgt = NULL;
13161         uint16_t        bay_num, enclosure;
13162 
13163         ASSERT(*pptgt == NULL);
13164 
13165         rval = mptsas_get_sas_device_page0(mpt, page_address, dev_handle,
13166             &sas_wwn, &dev_info, &physport, &phynum, &pdev_hdl,
13167             &bay_num, &enclosure);
13168         if (rval != DDI_SUCCESS) {
13169                 rval = DEV_INFO_FAIL_PAGE0;
13170                 return (rval);
13171         }
13172 
13173         if ((dev_info & (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
13174             MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
13175             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) == NULL) {
13176                 rval = DEV_INFO_WRONG_DEVICE_TYPE;
13177                 return (rval);
13178         }
13179 
13180         /*
13181          * Check if the dev handle is for a Phys Disk. If so, set return value
13182          * and exit.  Don't add Phys Disks to hash.
13183          */
13184         for (config = 0; config < slots->m_num_raid_configs; config++) {
13185                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
13186                         if (*dev_handle == slots->m_raidconfig[config].
13187                             m_physdisk_devhdl[disk]) {
13188                                 rval = DEV_INFO_PHYS_DISK;
13189                                 return (rval);
13190                         }
13191                 }
13192         }
13193 
13194         /*
13195          * Get SATA Device Name from SAS device page0 for
13196          * sata device, if device name doesn't exist, set m_sas_wwn to
13197          * 0 for direct attached SATA. For the device behind the expander
13198          * we still can use STP address assigned by expander.
13199          */
13200         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
13201             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
13202                 mutex_exit(&mpt->m_mutex);
13203                 /* alloc a tmp_tgt to send the cmd */
13204                 tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target),
13205                     KM_SLEEP);
13206                 tmp_tgt->m_devhdl = *dev_handle;
13207                 tmp_tgt->m_deviceinfo = dev_info;
13208                 tmp_tgt->m_qfull_retries = QFULL_RETRIES;
13209                 tmp_tgt->m_qfull_retry_interval =
13210                     drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
13211                 tmp_tgt->m_t_throttle = MAX_THROTTLE;
13212                 devicename = mptsas_get_sata_guid(mpt, tmp_tgt, 0);
13213                 kmem_free(tmp_tgt, sizeof (struct mptsas_target));
13214                 mutex_enter(&mpt->m_mutex);
13215                 if (devicename != 0 && (((devicename >> 56) & 0xf0) == 0x50)) {
13216                         sas_wwn = devicename;
13217                 } else if (dev_info & MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH) {
13218                         sas_wwn = 0;
13219                 }
13220         }
13221 
13222         phymask = mptsas_physport_to_phymask(mpt, physport);
13223         *pptgt = mptsas_tgt_alloc(&slots->m_tgttbl, *dev_handle, sas_wwn,
13224             dev_info, phymask, phynum, mpt);
13225         if (*pptgt == NULL) {
13226                 mptsas_log(mpt, CE_WARN, "Failed to allocated target"
13227                     "structure!");
13228                 rval = DEV_INFO_FAIL_ALLOC;
13229                 return (rval);
13230         }
13231         (*pptgt)->m_enclosure = enclosure;
13232         (*pptgt)->m_slot_num = bay_num;
13233         return (DEV_INFO_SUCCESS);
13234 }
13235 
13236 uint64_t
13237 mptsas_get_sata_guid(mptsas_t *mpt, mptsas_target_t *ptgt, int lun)
13238 {
13239         uint64_t        sata_guid = 0, *pwwn = NULL;
13240         int             target = ptgt->m_devhdl;
13241         uchar_t         *inq83 = NULL;
13242         int             inq83_len = 0xFF;
13243         uchar_t         *dblk = NULL;
13244         int             inq83_retry = 3;
13245         int             rval = DDI_FAILURE;
13246 
13247         inq83   = kmem_zalloc(inq83_len, KM_SLEEP);
13248 
13249 inq83_retry:
13250         rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
13251             inq83_len, NULL, 1);
13252         if (rval != DDI_SUCCESS) {
13253                 mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
13254                     "0x83 for target:%x, lun:%x failed!", target, lun);
13255                 goto out;
13256         }
13257         /* According to SAT2, the first descriptor is logic unit name */
13258         dblk = &inq83[4];
13259         if ((dblk[1] & 0x30) != 0) {
13260                 mptsas_log(mpt, CE_WARN, "!Descriptor is not lun associated.");
13261                 goto out;
13262         }
13263         pwwn = (uint64_t *)(void *)(&dblk[4]);
13264         if ((dblk[4] & 0xf0) == 0x50) {
13265                 sata_guid = BE_64(*pwwn);
13266                 goto out;
13267         } else if (dblk[4] == 'A') {
13268                 NDBG20(("SATA drive has no NAA format GUID."));
13269                 goto out;
13270         } else {
13271                 /* The data is not ready, wait and retry */
13272                 inq83_retry--;
13273                 if (inq83_retry <= 0) {
13274                         goto out;
13275                 }
13276                 NDBG20(("The GUID is not ready, retry..."));
13277                 delay(1 * drv_usectohz(1000000));
13278                 goto inq83_retry;
13279         }
13280 out:
13281         kmem_free(inq83, inq83_len);
13282         return (sata_guid);
13283 }
13284 
13285 static int
13286 mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun, uchar_t page,
13287     unsigned char *buf, int len, int *reallen, uchar_t evpd)
13288 {
13289         uchar_t                 cdb[CDB_GROUP0];
13290         struct scsi_address     ap;
13291         struct buf              *data_bp = NULL;
13292         int                     resid = 0;
13293         int                     ret = DDI_FAILURE;
13294 
13295         ASSERT(len <= 0xffff);
13296 
13297         ap.a_target = MPTSAS_INVALID_DEVHDL;
13298         ap.a_lun = (uchar_t)(lun);
13299         ap.a_hba_tran = mpt->m_tran;
13300 
13301         data_bp = scsi_alloc_consistent_buf(&ap,
13302             (struct buf *)NULL, len, B_READ, NULL_FUNC, NULL);
13303         if (data_bp == NULL) {
13304                 return (ret);
13305         }
13306         bzero(cdb, CDB_GROUP0);
13307         cdb[0] = SCMD_INQUIRY;
13308         cdb[1] = evpd;
13309         cdb[2] = page;
13310         cdb[3] = (len & 0xff00) >> 8;
13311         cdb[4] = (len & 0x00ff);
13312         cdb[5] = 0;
13313 
13314         ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP0, data_bp,
13315             &resid);
13316         if (ret == DDI_SUCCESS) {
13317                 if (reallen) {
13318                         *reallen = len - resid;
13319                 }
13320                 bcopy((caddr_t)data_bp->b_un.b_addr, buf, len);
13321         }
13322         if (data_bp) {
13323                 scsi_free_consistent_buf(data_bp);
13324         }
13325         return (ret);
13326 }
13327 
13328 static int
13329 mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
13330     mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
13331     int *resid)
13332 {
13333         struct scsi_pkt         *pktp = NULL;
13334         scsi_hba_tran_t         *tran_clone = NULL;
13335         mptsas_tgt_private_t    *tgt_private = NULL;
13336         int                     ret = DDI_FAILURE;
13337 
13338         /*
13339          * scsi_hba_tran_t->tran_tgt_private is used to pass the address
13340          * information to scsi_init_pkt, allocate a scsi_hba_tran structure
13341          * to simulate the cmds from sd
13342          */
13343         tran_clone = kmem_alloc(
13344             sizeof (scsi_hba_tran_t), KM_SLEEP);
13345         if (tran_clone == NULL) {
13346                 goto out;
13347         }
13348         bcopy((caddr_t)mpt->m_tran,
13349             (caddr_t)tran_clone, sizeof (scsi_hba_tran_t));
13350         tgt_private = kmem_alloc(
13351             sizeof (mptsas_tgt_private_t), KM_SLEEP);
13352         if (tgt_private == NULL) {
13353                 goto out;
13354         }
13355         tgt_private->t_lun = ap->a_lun;
13356         tgt_private->t_private = ptgt;
13357         tran_clone->tran_tgt_private = tgt_private;
13358         ap->a_hba_tran = tran_clone;
13359 
13360         pktp = scsi_init_pkt(ap, (struct scsi_pkt *)NULL,
13361             data_bp, cdblen, sizeof (struct scsi_arq_status),
13362             0, PKT_CONSISTENT, NULL, NULL);
13363         if (pktp == NULL) {
13364                 goto out;
13365         }
13366         bcopy(cdb, pktp->pkt_cdbp, cdblen);
13367         pktp->pkt_flags = FLAG_NOPARITY;
13368         if (scsi_poll(pktp) < 0) {
13369                 goto out;
13370         }
13371         if (((struct scsi_status *)pktp->pkt_scbp)->sts_chk) {
13372                 goto out;
13373         }
13374         if (resid != NULL) {
13375                 *resid = pktp->pkt_resid;
13376         }
13377 
13378         ret = DDI_SUCCESS;
13379 out:
13380         if (pktp) {
13381                 scsi_destroy_pkt(pktp);
13382         }
13383         if (tran_clone) {
13384                 kmem_free(tran_clone, sizeof (scsi_hba_tran_t));
13385         }
13386         if (tgt_private) {
13387                 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
13388         }
13389         return (ret);
13390 }
13391 static int
13392 mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy, int *lun)
13393 {
13394         char    *cp = NULL;
13395         char    *ptr = NULL;
13396         size_t  s = 0;
13397         char    *wwid_str = NULL;
13398         char    *lun_str = NULL;
13399         long    lunnum;
13400         long    phyid = -1;
13401         int     rc = DDI_FAILURE;
13402 
13403         ptr = name;
13404         ASSERT(ptr[0] == 'w' || ptr[0] == 'p');
13405         ptr++;
13406         if ((cp = strchr(ptr, ',')) == NULL) {
13407                 return (DDI_FAILURE);
13408         }
13409 
13410         wwid_str = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13411         s = (uintptr_t)cp - (uintptr_t)ptr;
13412 
13413         bcopy(ptr, wwid_str, s);
13414         wwid_str[s] = '\0';
13415 
13416         ptr = ++cp;
13417 
13418         if ((cp = strchr(ptr, '\0')) == NULL) {
13419                 goto out;
13420         }
13421         lun_str =  kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13422         s = (uintptr_t)cp - (uintptr_t)ptr;
13423 
13424         bcopy(ptr, lun_str, s);
13425         lun_str[s] = '\0';
13426 
13427         if (name[0] == 'p') {
13428                 rc = ddi_strtol(wwid_str, NULL, 0x10, &phyid);
13429         } else {
13430                 rc = scsi_wwnstr_to_wwn(wwid_str, wwid);
13431         }
13432         if (rc != DDI_SUCCESS)
13433                 goto out;
13434 
13435         if (phyid != -1) {
13436                 ASSERT(phyid < MPTSAS_MAX_PHYS);
13437                 *phy = (uint8_t)phyid;
13438         }
13439         rc = ddi_strtol(lun_str, NULL, 0x10, &lunnum);
13440         if (rc != 0)
13441                 goto out;
13442 
13443         *lun = (int)lunnum;
13444         rc = DDI_SUCCESS;
13445 out:
13446         if (wwid_str)
13447                 kmem_free(wwid_str, SCSI_MAXNAMELEN);
13448         if (lun_str)
13449                 kmem_free(lun_str, SCSI_MAXNAMELEN);
13450 
13451         return (rc);
13452 }
13453 
13454 /*
13455  * mptsas_parse_smp_name() is to parse sas wwn string
13456  * which format is "wWWN"
13457  */
13458 static int
13459 mptsas_parse_smp_name(char *name, uint64_t *wwn)
13460 {
13461         char    *ptr = name;
13462 
13463         if (*ptr != 'w') {
13464                 return (DDI_FAILURE);
13465         }
13466 
13467         ptr++;
13468         if (scsi_wwnstr_to_wwn(ptr, wwn)) {
13469                 return (DDI_FAILURE);
13470         }
13471         return (DDI_SUCCESS);
13472 }
13473 
13474 static int
13475 mptsas_bus_config(dev_info_t *pdip, uint_t flag,
13476     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
13477 {
13478         int             ret = NDI_FAILURE;
13479         int             circ = 0;
13480         int             circ1 = 0;
13481         mptsas_t        *mpt;
13482         char            *ptr = NULL;
13483         char            *devnm = NULL;
13484         uint64_t        wwid = 0;
13485         uint8_t         phy = 0xFF;
13486         int             lun = 0;
13487         uint_t          mflags = flag;
13488         int             bconfig = TRUE;
13489 
13490         if (scsi_hba_iport_unit_address(pdip) == 0) {
13491                 return (DDI_FAILURE);
13492         }
13493 
13494         mpt = DIP2MPT(pdip);
13495         if (!mpt) {
13496                 return (DDI_FAILURE);
13497         }
13498         /*
13499          * Hold the nexus across the bus_config
13500          */
13501         ndi_devi_enter(scsi_vhci_dip, &circ);
13502         ndi_devi_enter(pdip, &circ1);
13503         switch (op) {
13504         case BUS_CONFIG_ONE:
13505                 /* parse wwid/target name out of name given */
13506                 if ((ptr = strchr((char *)arg, '@')) == NULL) {
13507                         ret = NDI_FAILURE;
13508                         break;
13509                 }
13510                 ptr++;
13511                 if (strncmp((char *)arg, "smp", 3) == 0) {
13512                         /*
13513                          * This is a SMP target device
13514                          */
13515                         ret = mptsas_parse_smp_name(ptr, &wwid);
13516                         if (ret != DDI_SUCCESS) {
13517                                 ret = NDI_FAILURE;
13518                                 break;
13519                         }
13520                         ret = mptsas_config_smp(pdip, wwid, childp);
13521                 } else if ((ptr[0] == 'w') || (ptr[0] == 'p')) {
13522                         /*
13523                          * OBP could pass down a non-canonical form
13524                          * bootpath without LUN part when LUN is 0.
13525                          * So driver need adjust the string.
13526                          */
13527                         if (strchr(ptr, ',') == NULL) {
13528                                 devnm = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13529                                 (void) sprintf(devnm, "%s,0", (char *)arg);
13530                                 ptr = strchr(devnm, '@');
13531                                 ptr++;
13532                         }
13533 
13534                         /*
13535                          * The device path is wWWID format and the device
13536                          * is not SMP target device.
13537                          */
13538                         ret = mptsas_parse_address(ptr, &wwid, &phy, &lun);
13539                         if (ret != DDI_SUCCESS) {
13540                                 ret = NDI_FAILURE;
13541                                 break;
13542                         }
13543                         *childp = NULL;
13544                         if (ptr[0] == 'w') {
13545                                 ret = mptsas_config_one_addr(pdip, wwid,
13546                                     lun, childp);
13547                         } else if (ptr[0] == 'p') {
13548                                 ret = mptsas_config_one_phy(pdip, phy, lun,
13549                                     childp);
13550                         }
13551 
13552                         /*
13553                          * If this is CD/DVD device in OBP path, the
13554                          * ndi_busop_bus_config can be skipped as config one
13555                          * operation is done above.
13556                          */
13557                         if ((ret == NDI_SUCCESS) && (*childp != NULL) &&
13558                             (strcmp(ddi_node_name(*childp), "cdrom") == 0) &&
13559                             (strncmp((char *)arg, "disk", 4) == 0)) {
13560                                 bconfig = FALSE;
13561                                 ndi_hold_devi(*childp);
13562                         }
13563                 } else {
13564                         ret = NDI_FAILURE;
13565                         break;
13566                 }
13567 
13568                 /*
13569                  * DDI group instructed us to use this flag.
13570                  */
13571                 mflags |= NDI_MDI_FALLBACK;
13572                 break;
13573         case BUS_CONFIG_DRIVER:
13574         case BUS_CONFIG_ALL:
13575                 mptsas_config_all(pdip);
13576                 ret = NDI_SUCCESS;
13577                 break;
13578         }
13579 
13580         if ((ret == NDI_SUCCESS) && bconfig) {
13581                 ret = ndi_busop_bus_config(pdip, mflags, op,
13582                     (devnm == NULL) ? arg : devnm, childp, 0);
13583         }
13584 
13585         ndi_devi_exit(pdip, circ1);
13586         ndi_devi_exit(scsi_vhci_dip, circ);
13587         if (devnm != NULL)
13588                 kmem_free(devnm, SCSI_MAXNAMELEN);
13589         return (ret);
13590 }
13591 
13592 static int
13593 mptsas_probe_lun(dev_info_t *pdip, int lun, dev_info_t **dip,
13594     mptsas_target_t *ptgt)
13595 {
13596         int                     rval = DDI_FAILURE;
13597         struct scsi_inquiry     *sd_inq = NULL;
13598         mptsas_t                *mpt = DIP2MPT(pdip);
13599 
13600         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
13601 
13602         rval = mptsas_inquiry(mpt, ptgt, lun, 0, (uchar_t *)sd_inq,
13603             SUN_INQSIZE, 0, (uchar_t)0);
13604 
13605         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
13606                 rval = mptsas_create_lun(pdip, sd_inq, dip, ptgt, lun);
13607         } else {
13608                 rval = DDI_FAILURE;
13609         }
13610 
13611         kmem_free(sd_inq, SUN_INQSIZE);
13612         return (rval);
13613 }
13614 
13615 static int
13616 mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
13617     dev_info_t **lundip)
13618 {
13619         int             rval;
13620         mptsas_t                *mpt = DIP2MPT(pdip);
13621         int             phymask;
13622         mptsas_target_t *ptgt = NULL;
13623 
13624         /*
13625          * Get the physical port associated to the iport
13626          */
13627         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13628             "phymask", 0);
13629 
13630         ptgt = mptsas_wwid_to_ptgt(mpt, phymask, sasaddr);
13631         if (ptgt == NULL) {
13632                 /*
13633                  * didn't match any device by searching
13634                  */
13635                 return (DDI_FAILURE);
13636         }
13637         /*
13638          * If the LUN already exists and the status is online,
13639          * we just return the pointer to dev_info_t directly.
13640          * For the mdi_pathinfo node, we'll handle it in
13641          * mptsas_create_virt_lun()
13642          * TODO should be also in mptsas_handle_dr
13643          */
13644 
13645         *lundip = mptsas_find_child_addr(pdip, sasaddr, lun);
13646         if (*lundip != NULL) {
13647                 /*
13648                  * TODO Another senario is, we hotplug the same disk
13649                  * on the same slot, the devhdl changed, is this
13650                  * possible?
13651                  * tgt_private->t_private != ptgt
13652                  */
13653                 if (sasaddr != ptgt->m_sas_wwn) {
13654                         /*
13655                          * The device has changed although the devhdl is the
13656                          * same (Enclosure mapping mode, change drive on the
13657                          * same slot)
13658                          */
13659                         return (DDI_FAILURE);
13660                 }
13661                 return (DDI_SUCCESS);
13662         }
13663 
13664         if (phymask == 0) {
13665                 /*
13666                  * Configure IR volume
13667                  */
13668                 rval =  mptsas_config_raid(pdip, ptgt->m_devhdl, lundip);
13669                 return (rval);
13670         }
13671         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
13672 
13673         return (rval);
13674 }
13675 
13676 static int
13677 mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
13678     dev_info_t **lundip)
13679 {
13680         int             rval;
13681         mptsas_t        *mpt = DIP2MPT(pdip);
13682         int             phymask;
13683         mptsas_target_t *ptgt = NULL;
13684 
13685         /*
13686          * Get the physical port associated to the iport
13687          */
13688         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13689             "phymask", 0);
13690 
13691         ptgt = mptsas_phy_to_tgt(mpt, phymask, phy);
13692         if (ptgt == NULL) {
13693                 /*
13694                  * didn't match any device by searching
13695                  */
13696                 return (DDI_FAILURE);
13697         }
13698 
13699         /*
13700          * If the LUN already exists and the status is online,
13701          * we just return the pointer to dev_info_t directly.
13702          * For the mdi_pathinfo node, we'll handle it in
13703          * mptsas_create_virt_lun().
13704          */
13705 
13706         *lundip = mptsas_find_child_phy(pdip, phy);
13707         if (*lundip != NULL) {
13708                 return (DDI_SUCCESS);
13709         }
13710 
13711         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
13712 
13713         return (rval);
13714 }
13715 
13716 static int
13717 mptsas_retrieve_lundata(int lun_cnt, uint8_t *buf, uint16_t *lun_num,
13718     uint8_t *lun_addr_type)
13719 {
13720         uint32_t        lun_idx = 0;
13721 
13722         ASSERT(lun_num != NULL);
13723         ASSERT(lun_addr_type != NULL);
13724 
13725         lun_idx = (lun_cnt + 1) * MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
13726         /* determine report luns addressing type */
13727         switch (buf[lun_idx] & MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) {
13728                 /*
13729                  * Vendors in the field have been found to be concatenating
13730                  * bus/target/lun to equal the complete lun value instead
13731                  * of switching to flat space addressing
13732                  */
13733                 /* 00b - peripheral device addressing method */
13734         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_PERIPHERAL:
13735                 /* FALLTHRU */
13736                 /* 10b - logical unit addressing method */
13737         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT:
13738                 /* FALLTHRU */
13739                 /* 01b - flat space addressing method */
13740         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE:
13741                 /* byte0 bit0-5=msb lun byte1 bit0-7=lsb lun */
13742                 *lun_addr_type = (buf[lun_idx] &
13743                     MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) >> 6;
13744                 *lun_num = (buf[lun_idx] & 0x3F) << 8;
13745                 *lun_num |= buf[lun_idx + 1];
13746                 return (DDI_SUCCESS);
13747         default:
13748                 return (DDI_FAILURE);
13749         }
13750 }
13751 
13752 static int
13753 mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt)
13754 {
13755         struct buf              *repluns_bp = NULL;
13756         struct scsi_address     ap;
13757         uchar_t                 cdb[CDB_GROUP5];
13758         int                     ret = DDI_FAILURE;
13759         int                     retry = 0;
13760         int                     lun_list_len = 0;
13761         uint16_t                lun_num = 0;
13762         uint8_t                 lun_addr_type = 0;
13763         uint32_t                lun_cnt = 0;
13764         uint32_t                lun_total = 0;
13765         dev_info_t              *cdip = NULL;
13766         uint16_t                *saved_repluns = NULL;
13767         char                    *buffer = NULL;
13768         int                     buf_len = 128;
13769         mptsas_t                *mpt = DIP2MPT(pdip);
13770         uint64_t                sas_wwn = 0;
13771         uint8_t                 phy = 0xFF;
13772         uint32_t                dev_info = 0;
13773 
13774         mutex_enter(&mpt->m_mutex);
13775         sas_wwn = ptgt->m_sas_wwn;
13776         phy = ptgt->m_phynum;
13777         dev_info = ptgt->m_deviceinfo;
13778         mutex_exit(&mpt->m_mutex);
13779 
13780         if (sas_wwn == 0) {
13781                 /*
13782                  * It's a SATA without Device Name
13783                  * So don't try multi-LUNs
13784                  */
13785                 if (mptsas_find_child_phy(pdip, phy)) {
13786                         return (DDI_SUCCESS);
13787                 } else {
13788                         /*
13789                          * need configure and create node
13790                          */
13791                         return (DDI_FAILURE);
13792                 }
13793         }
13794 
13795         /*
13796          * WWN (SAS address or Device Name exist)
13797          */
13798         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
13799             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
13800                 /*
13801                  * SATA device with Device Name
13802                  * So don't try multi-LUNs
13803                  */
13804                 if (mptsas_find_child_addr(pdip, sas_wwn, 0)) {
13805                         return (DDI_SUCCESS);
13806                 } else {
13807                         return (DDI_FAILURE);
13808                 }
13809         }
13810 
13811         do {
13812                 ap.a_target = MPTSAS_INVALID_DEVHDL;
13813                 ap.a_lun = 0;
13814                 ap.a_hba_tran = mpt->m_tran;
13815                 repluns_bp = scsi_alloc_consistent_buf(&ap,
13816                     (struct buf *)NULL, buf_len, B_READ, NULL_FUNC, NULL);
13817                 if (repluns_bp == NULL) {
13818                         retry++;
13819                         continue;
13820                 }
13821                 bzero(cdb, CDB_GROUP5);
13822                 cdb[0] = SCMD_REPORT_LUNS;
13823                 cdb[6] = (buf_len & 0xff000000) >> 24;
13824                 cdb[7] = (buf_len & 0x00ff0000) >> 16;
13825                 cdb[8] = (buf_len & 0x0000ff00) >> 8;
13826                 cdb[9] = (buf_len & 0x000000ff);
13827 
13828                 ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP5,
13829                     repluns_bp, NULL);
13830                 if (ret != DDI_SUCCESS) {
13831                         scsi_free_consistent_buf(repluns_bp);
13832                         retry++;
13833                         continue;
13834                 }
13835                 lun_list_len = BE_32(*(int *)((void *)(
13836                     repluns_bp->b_un.b_addr)));
13837                 if (buf_len >= lun_list_len + 8) {
13838                         ret = DDI_SUCCESS;
13839                         break;
13840                 }
13841                 scsi_free_consistent_buf(repluns_bp);
13842                 buf_len = lun_list_len + 8;
13843 
13844         } while (retry < 3);
13845 
13846         if (ret != DDI_SUCCESS)
13847                 return (ret);
13848         buffer = (char *)repluns_bp->b_un.b_addr;
13849         /*
13850          * find out the number of luns returned by the SCSI ReportLun call
13851          * and allocate buffer space
13852          */
13853         lun_total = lun_list_len / MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
13854         saved_repluns = kmem_zalloc(sizeof (uint16_t) * lun_total, KM_SLEEP);
13855         if (saved_repluns == NULL) {
13856                 scsi_free_consistent_buf(repluns_bp);
13857                 return (DDI_FAILURE);
13858         }
13859         for (lun_cnt = 0; lun_cnt < lun_total; lun_cnt++) {
13860                 if (mptsas_retrieve_lundata(lun_cnt, (uint8_t *)(buffer),
13861                     &lun_num, &lun_addr_type) != DDI_SUCCESS) {
13862                         continue;
13863                 }
13864                 saved_repluns[lun_cnt] = lun_num;
13865                 if (cdip = mptsas_find_child_addr(pdip, sas_wwn, lun_num))
13866                         ret = DDI_SUCCESS;
13867                 else
13868                         ret = mptsas_probe_lun(pdip, lun_num, &cdip,
13869                             ptgt);
13870                 if ((ret == DDI_SUCCESS) && (cdip != NULL)) {
13871                         (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip,
13872                             MPTSAS_DEV_GONE);
13873                 }
13874         }
13875         mptsas_offline_missed_luns(pdip, saved_repluns, lun_total, ptgt);
13876         kmem_free(saved_repluns, sizeof (uint16_t) * lun_total);
13877         scsi_free_consistent_buf(repluns_bp);
13878         return (DDI_SUCCESS);
13879 }
13880 
13881 static int
13882 mptsas_config_raid(dev_info_t *pdip, uint16_t target, dev_info_t **dip)
13883 {
13884         int                     rval = DDI_FAILURE;
13885         struct scsi_inquiry     *sd_inq = NULL;
13886         mptsas_t                *mpt = DIP2MPT(pdip);
13887         mptsas_target_t         *ptgt = NULL;
13888 
13889         mutex_enter(&mpt->m_mutex);
13890         ptgt = mptsas_search_by_devhdl(&mpt->m_active->m_tgttbl, target);
13891         mutex_exit(&mpt->m_mutex);
13892         if (ptgt == NULL) {
13893                 mptsas_log(mpt, CE_WARN, "Volume with VolDevHandle of 0x%x "
13894                     "not found.", target);
13895                 return (rval);
13896         }
13897 
13898         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
13899         rval = mptsas_inquiry(mpt, ptgt, 0, 0, (uchar_t *)sd_inq,
13900             SUN_INQSIZE, 0, (uchar_t)0);
13901 
13902         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
13903                 rval = mptsas_create_phys_lun(pdip, sd_inq, NULL, dip, ptgt,
13904                     0);
13905         } else {
13906                 rval = DDI_FAILURE;
13907         }
13908 
13909         kmem_free(sd_inq, SUN_INQSIZE);
13910         return (rval);
13911 }
13912 
13913 /*
13914  * configure all RAID volumes for virtual iport
13915  */
13916 static void
13917 mptsas_config_all_viport(dev_info_t *pdip)
13918 {
13919         mptsas_t        *mpt = DIP2MPT(pdip);
13920         int             config, vol;
13921         int             target;
13922         dev_info_t      *lundip = NULL;
13923         mptsas_slots_t  *slots = mpt->m_active;
13924 
13925         /*
13926          * Get latest RAID info and search for any Volume DevHandles.  If any
13927          * are found, configure the volume.
13928          */
13929         mutex_enter(&mpt->m_mutex);
13930         for (config = 0; config < slots->m_num_raid_configs; config++) {
13931                 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
13932                         if (slots->m_raidconfig[config].m_raidvol[vol].m_israid
13933                             == 1) {
13934                                 target = slots->m_raidconfig[config].
13935                                     m_raidvol[vol].m_raidhandle;
13936                                 mutex_exit(&mpt->m_mutex);
13937                                 (void) mptsas_config_raid(pdip, target,
13938                                     &lundip);
13939                                 mutex_enter(&mpt->m_mutex);
13940                         }
13941                 }
13942         }
13943         mutex_exit(&mpt->m_mutex);
13944 }
13945 
13946 static void
13947 mptsas_offline_missed_luns(dev_info_t *pdip, uint16_t *repluns,
13948     int lun_cnt, mptsas_target_t *ptgt)
13949 {
13950         dev_info_t      *child = NULL, *savechild = NULL;
13951         mdi_pathinfo_t  *pip = NULL, *savepip = NULL;
13952         uint64_t        sas_wwn, wwid;
13953         uint8_t         phy;
13954         int             lun;
13955         int             i;
13956         int             find;
13957         char            *addr;
13958         char            *nodename;
13959         mptsas_t        *mpt = DIP2MPT(pdip);
13960 
13961         mutex_enter(&mpt->m_mutex);
13962         wwid = ptgt->m_sas_wwn;
13963         mutex_exit(&mpt->m_mutex);
13964 
13965         child = ddi_get_child(pdip);
13966         while (child) {
13967                 find = 0;
13968                 savechild = child;
13969                 child = ddi_get_next_sibling(child);
13970 
13971                 nodename = ddi_node_name(savechild);
13972                 if (strcmp(nodename, "smp") == 0) {
13973                         continue;
13974                 }
13975 
13976                 addr = ddi_get_name_addr(savechild);
13977                 if (addr == NULL) {
13978                         continue;
13979                 }
13980 
13981                 if (mptsas_parse_address(addr, &sas_wwn, &phy, &lun) !=
13982                     DDI_SUCCESS) {
13983                         continue;
13984                 }
13985 
13986                 if (wwid == sas_wwn) {
13987                         for (i = 0; i < lun_cnt; i++) {
13988                                 if (repluns[i] == lun) {
13989                                         find = 1;
13990                                         break;
13991                                 }
13992                         }
13993                 } else {
13994                         continue;
13995                 }
13996                 if (find == 0) {
13997                         /*
13998                          * The lun has not been there already
13999                          */
14000                         (void) mptsas_offline_lun(pdip, savechild, NULL,
14001                             NDI_DEVI_REMOVE);
14002                 }
14003         }
14004 
14005         pip = mdi_get_next_client_path(pdip, NULL);
14006         while (pip) {
14007                 find = 0;
14008                 savepip = pip;
14009                 addr = MDI_PI(pip)->pi_addr;
14010 
14011                 pip = mdi_get_next_client_path(pdip, pip);
14012 
14013                 if (addr == NULL) {
14014                         continue;
14015                 }
14016 
14017                 if (mptsas_parse_address(addr, &sas_wwn, &phy,
14018                     &lun) != DDI_SUCCESS) {
14019                         continue;
14020                 }
14021 
14022                 if (sas_wwn == wwid) {
14023                         for (i = 0; i < lun_cnt; i++) {
14024                                 if (repluns[i] == lun) {
14025                                         find = 1;
14026                                         break;
14027                                 }
14028                         }
14029                 } else {
14030                         continue;
14031                 }
14032 
14033                 if (find == 0) {
14034                         /*
14035                          * The lun has not been there already
14036                          */
14037                         (void) mptsas_offline_lun(pdip, NULL, savepip,
14038                             NDI_DEVI_REMOVE);
14039                 }
14040         }
14041 }
14042 
14043 void
14044 mptsas_update_hashtab(struct mptsas *mpt)
14045 {
14046         uint32_t        page_address;
14047         int             rval = 0;
14048         uint16_t        dev_handle;
14049         mptsas_target_t *ptgt = NULL;
14050         mptsas_smp_t    smp_node;
14051 
14052         /*
14053          * Get latest RAID info.
14054          */
14055         (void) mptsas_get_raid_info(mpt);
14056 
14057         dev_handle = mpt->m_smp_devhdl;
14058         for (; mpt->m_done_traverse_smp == 0; ) {
14059                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
14060                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)dev_handle;
14061                 if (mptsas_get_sas_expander_page0(mpt, page_address, &smp_node)
14062                     != DDI_SUCCESS) {
14063                         break;
14064                 }
14065                 mpt->m_smp_devhdl = dev_handle = smp_node.m_devhdl;
14066                 (void) mptsas_smp_alloc(&mpt->m_active->m_smptbl, &smp_node);
14067         }
14068 
14069         /*
14070          * Config target devices
14071          */
14072         dev_handle = mpt->m_dev_handle;
14073 
14074         /*
14075          * Do loop to get sas device page 0 by GetNextHandle till the
14076          * the last handle. If the sas device is a SATA/SSP target,
14077          * we try to config it.
14078          */
14079         for (; mpt->m_done_traverse_dev == 0; ) {
14080                 ptgt = NULL;
14081                 page_address =
14082                     (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
14083                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14084                     (uint32_t)dev_handle;
14085                 rval = mptsas_get_target_device_info(mpt, page_address,
14086                     &dev_handle, &ptgt);
14087                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
14088                     (rval == DEV_INFO_FAIL_ALLOC)) {
14089                         break;
14090                 }
14091 
14092                 mpt->m_dev_handle = dev_handle;
14093         }
14094 
14095 }
14096 
14097 void
14098 mptsas_invalid_hashtab(mptsas_hash_table_t *hashtab)
14099 {
14100         mptsas_hash_data_t *data;
14101         data = mptsas_hash_traverse(hashtab, MPTSAS_HASH_FIRST);
14102         while (data != NULL) {
14103                 data->devhdl = MPTSAS_INVALID_DEVHDL;
14104                 data->device_info = 0;
14105                 /*
14106                  * For tgttbl, clear dr_flag.
14107                  */
14108                 data->dr_flag = MPTSAS_DR_INACTIVE;
14109                 data = mptsas_hash_traverse(hashtab, MPTSAS_HASH_NEXT);
14110         }
14111 }
14112 
14113 void
14114 mptsas_update_driver_data(struct mptsas *mpt)
14115 {
14116         /*
14117          * TODO after hard reset, update the driver data structures
14118          * 1. update port/phymask mapping table mpt->m_phy_info
14119          * 2. invalid all the entries in hash table
14120          *    m_devhdl = 0xffff and m_deviceinfo = 0
14121          * 3. call sas_device_page/expander_page to update hash table
14122          */
14123         mptsas_update_phymask(mpt);
14124         /*
14125          * Invalid the existing entries
14126          */
14127         mptsas_invalid_hashtab(&mpt->m_active->m_tgttbl);
14128         mptsas_invalid_hashtab(&mpt->m_active->m_smptbl);
14129         mpt->m_done_traverse_dev = 0;
14130         mpt->m_done_traverse_smp = 0;
14131         mpt->m_dev_handle = mpt->m_smp_devhdl = MPTSAS_INVALID_DEVHDL;
14132         mptsas_update_hashtab(mpt);
14133 }
14134 
14135 static void
14136 mptsas_config_all(dev_info_t *pdip)
14137 {
14138         dev_info_t      *smpdip = NULL;
14139         mptsas_t        *mpt = DIP2MPT(pdip);
14140         int             phymask = 0;
14141         mptsas_phymask_t phy_mask;
14142         mptsas_target_t *ptgt = NULL;
14143         mptsas_smp_t    *psmp;
14144 
14145         /*
14146          * Get the phymask associated to the iport
14147          */
14148         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
14149             "phymask", 0);
14150 
14151         /*
14152          * Enumerate RAID volumes here (phymask == 0).
14153          */
14154         if (phymask == 0) {
14155                 mptsas_config_all_viport(pdip);
14156                 return;
14157         }
14158 
14159         mutex_enter(&mpt->m_mutex);
14160 
14161         if (!mpt->m_done_traverse_dev || !mpt->m_done_traverse_smp) {
14162                 mptsas_update_hashtab(mpt);
14163         }
14164 
14165         psmp = (mptsas_smp_t *)mptsas_hash_traverse(&mpt->m_active->m_smptbl,
14166             MPTSAS_HASH_FIRST);
14167         while (psmp != NULL) {
14168                 phy_mask = psmp->m_phymask;
14169                 if (phy_mask == phymask) {
14170                         smpdip = NULL;
14171                         mutex_exit(&mpt->m_mutex);
14172                         (void) mptsas_online_smp(pdip, psmp, &smpdip);
14173                         mutex_enter(&mpt->m_mutex);
14174                 }
14175                 psmp = (mptsas_smp_t *)mptsas_hash_traverse(
14176                     &mpt->m_active->m_smptbl, MPTSAS_HASH_NEXT);
14177         }
14178 
14179         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
14180             MPTSAS_HASH_FIRST);
14181         while (ptgt != NULL) {
14182                 phy_mask = ptgt->m_phymask;
14183                 if (phy_mask == phymask) {
14184                         mutex_exit(&mpt->m_mutex);
14185                         (void) mptsas_config_target(pdip, ptgt);
14186                         mutex_enter(&mpt->m_mutex);
14187                 }
14188 
14189                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
14190                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
14191         }
14192         mutex_exit(&mpt->m_mutex);
14193 }
14194 
14195 static int
14196 mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt)
14197 {
14198         int             rval = DDI_FAILURE;
14199         dev_info_t      *tdip;
14200 
14201         rval = mptsas_config_luns(pdip, ptgt);
14202         if (rval != DDI_SUCCESS) {
14203                 /*
14204                  * The return value means the SCMD_REPORT_LUNS
14205                  * did not execute successfully. The target maybe
14206                  * doesn't support such command.
14207                  */
14208                 rval = mptsas_probe_lun(pdip, 0, &tdip, ptgt);
14209         }
14210         return (rval);
14211 }
14212 
14213 /*
14214  * Return fail if not all the childs/paths are freed.
14215  * if there is any path under the HBA, the return value will be always fail
14216  * because we didn't call mdi_pi_free for path
14217  */
14218 static int
14219 mptsas_offline_target(dev_info_t *pdip, char *name)
14220 {
14221         dev_info_t              *child = NULL, *prechild = NULL;
14222         mdi_pathinfo_t          *pip = NULL, *savepip = NULL;
14223         int                     tmp_rval, rval = DDI_SUCCESS;
14224         char                    *addr, *cp;
14225         size_t                  s;
14226         mptsas_t                *mpt = DIP2MPT(pdip);
14227 
14228         child = ddi_get_child(pdip);
14229         while (child) {
14230                 addr = ddi_get_name_addr(child);
14231                 prechild = child;
14232                 child = ddi_get_next_sibling(child);
14233 
14234                 if (addr == NULL) {
14235                         continue;
14236                 }
14237                 if ((cp = strchr(addr, ',')) == NULL) {
14238                         continue;
14239                 }
14240 
14241                 s = (uintptr_t)cp - (uintptr_t)addr;
14242 
14243                 if (strncmp(addr, name, s) != 0) {
14244                         continue;
14245                 }
14246 
14247                 tmp_rval = mptsas_offline_lun(pdip, prechild, NULL,
14248                     NDI_DEVI_REMOVE);
14249                 if (tmp_rval != DDI_SUCCESS) {
14250                         rval = DDI_FAILURE;
14251                         if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
14252                             prechild, MPTSAS_DEV_GONE) !=
14253                             DDI_PROP_SUCCESS) {
14254                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
14255                                     "unable to create property for "
14256                                     "SAS %s (MPTSAS_DEV_GONE)", addr);
14257                         }
14258                 }
14259         }
14260 
14261         pip = mdi_get_next_client_path(pdip, NULL);
14262         while (pip) {
14263                 addr = MDI_PI(pip)->pi_addr;
14264                 savepip = pip;
14265                 pip = mdi_get_next_client_path(pdip, pip);
14266                 if (addr == NULL) {
14267                         continue;
14268                 }
14269 
14270                 if ((cp = strchr(addr, ',')) == NULL) {
14271                         continue;
14272                 }
14273 
14274                 s = (uintptr_t)cp - (uintptr_t)addr;
14275 
14276                 if (strncmp(addr, name, s) != 0) {
14277                         continue;
14278                 }
14279 
14280                 (void) mptsas_offline_lun(pdip, NULL, savepip,
14281                     NDI_DEVI_REMOVE);
14282                 /*
14283                  * driver will not invoke mdi_pi_free, so path will not
14284                  * be freed forever, return DDI_FAILURE.
14285                  */
14286                 rval = DDI_FAILURE;
14287         }
14288         return (rval);
14289 }
14290 
14291 static int
14292 mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
14293     mdi_pathinfo_t *rpip, uint_t flags)
14294 {
14295         int             rval = DDI_FAILURE;
14296         char            *devname;
14297         dev_info_t      *cdip, *parent;
14298 
14299         if (rpip != NULL) {
14300                 parent = scsi_vhci_dip;
14301                 cdip = mdi_pi_get_client(rpip);
14302         } else if (rdip != NULL) {
14303                 parent = pdip;
14304                 cdip = rdip;
14305         } else {
14306                 return (DDI_FAILURE);
14307         }
14308 
14309         /*
14310          * Make sure node is attached otherwise
14311          * it won't have related cache nodes to
14312          * clean up.  i_ddi_devi_attached is
14313          * similiar to i_ddi_node_state(cdip) >=
14314          * DS_ATTACHED.
14315          */
14316         if (i_ddi_devi_attached(cdip)) {
14317 
14318                 /* Get full devname */
14319                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
14320                 (void) ddi_deviname(cdip, devname);
14321                 /* Clean cache */
14322                 (void) devfs_clean(parent, devname + 1,
14323                     DV_CLEAN_FORCE);
14324                 kmem_free(devname, MAXNAMELEN + 1);
14325         }
14326         if (rpip != NULL) {
14327                 if (MDI_PI_IS_OFFLINE(rpip)) {
14328                         rval = DDI_SUCCESS;
14329                 } else {
14330                         rval = mdi_pi_offline(rpip, 0);
14331                 }
14332         } else {
14333                 rval = ndi_devi_offline(cdip, flags);
14334         }
14335 
14336         return (rval);
14337 }
14338 
14339 static dev_info_t *
14340 mptsas_find_smp_child(dev_info_t *parent, char *str_wwn)
14341 {
14342         dev_info_t      *child = NULL;
14343         char            *smp_wwn = NULL;
14344 
14345         child = ddi_get_child(parent);
14346         while (child) {
14347                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
14348                     DDI_PROP_DONTPASS, SMP_WWN, &smp_wwn)
14349                     != DDI_SUCCESS) {
14350                         child = ddi_get_next_sibling(child);
14351                         continue;
14352                 }
14353 
14354                 if (strcmp(smp_wwn, str_wwn) == 0) {
14355                         ddi_prop_free(smp_wwn);
14356                         break;
14357                 }
14358                 child = ddi_get_next_sibling(child);
14359                 ddi_prop_free(smp_wwn);
14360         }
14361         return (child);
14362 }
14363 
14364 static int
14365 mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, uint_t flags)
14366 {
14367         int             rval = DDI_FAILURE;
14368         char            *devname;
14369         char            wwn_str[MPTSAS_WWN_STRLEN];
14370         dev_info_t      *cdip;
14371 
14372         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_sasaddr);
14373 
14374         cdip = mptsas_find_smp_child(pdip, wwn_str);
14375 
14376         if (cdip == NULL)
14377                 return (DDI_SUCCESS);
14378 
14379         /*
14380          * Make sure node is attached otherwise
14381          * it won't have related cache nodes to
14382          * clean up.  i_ddi_devi_attached is
14383          * similiar to i_ddi_node_state(cdip) >=
14384          * DS_ATTACHED.
14385          */
14386         if (i_ddi_devi_attached(cdip)) {
14387 
14388                 /* Get full devname */
14389                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
14390                 (void) ddi_deviname(cdip, devname);
14391                 /* Clean cache */
14392                 (void) devfs_clean(pdip, devname + 1,
14393                     DV_CLEAN_FORCE);
14394                 kmem_free(devname, MAXNAMELEN + 1);
14395         }
14396 
14397         rval = ndi_devi_offline(cdip, flags);
14398 
14399         return (rval);
14400 }
14401 
14402 static dev_info_t *
14403 mptsas_find_child(dev_info_t *pdip, char *name)
14404 {
14405         dev_info_t      *child = NULL;
14406         char            *rname = NULL;
14407         int             rval = DDI_FAILURE;
14408 
14409         rname = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14410 
14411         child = ddi_get_child(pdip);
14412         while (child) {
14413                 rval = mptsas_name_child(child, rname, SCSI_MAXNAMELEN);
14414                 if (rval != DDI_SUCCESS) {
14415                         child = ddi_get_next_sibling(child);
14416                         bzero(rname, SCSI_MAXNAMELEN);
14417                         continue;
14418                 }
14419 
14420                 if (strcmp(rname, name) == 0) {
14421                         break;
14422                 }
14423                 child = ddi_get_next_sibling(child);
14424                 bzero(rname, SCSI_MAXNAMELEN);
14425         }
14426 
14427         kmem_free(rname, SCSI_MAXNAMELEN);
14428 
14429         return (child);
14430 }
14431 
14432 
14433 static dev_info_t *
14434 mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr, int lun)
14435 {
14436         dev_info_t      *child = NULL;
14437         char            *name = NULL;
14438         char            *addr = NULL;
14439 
14440         name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14441         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14442         (void) sprintf(name, "%016"PRIx64, sasaddr);
14443         (void) sprintf(addr, "w%s,%x", name, lun);
14444         child = mptsas_find_child(pdip, addr);
14445         kmem_free(name, SCSI_MAXNAMELEN);
14446         kmem_free(addr, SCSI_MAXNAMELEN);
14447         return (child);
14448 }
14449 
14450 static dev_info_t *
14451 mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy)
14452 {
14453         dev_info_t      *child;
14454         char            *addr;
14455 
14456         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14457         (void) sprintf(addr, "p%x,0", phy);
14458         child = mptsas_find_child(pdip, addr);
14459         kmem_free(addr, SCSI_MAXNAMELEN);
14460         return (child);
14461 }
14462 
14463 static mdi_pathinfo_t *
14464 mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy)
14465 {
14466         mdi_pathinfo_t  *path;
14467         char            *addr = NULL;
14468 
14469         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14470         (void) sprintf(addr, "p%x,0", phy);
14471         path = mdi_pi_find(pdip, NULL, addr);
14472         kmem_free(addr, SCSI_MAXNAMELEN);
14473         return (path);
14474 }
14475 
14476 static mdi_pathinfo_t *
14477 mptsas_find_path_addr(dev_info_t *parent, uint64_t sasaddr, int lun)
14478 {
14479         mdi_pathinfo_t  *path;
14480         char            *name = NULL;
14481         char            *addr = NULL;
14482 
14483         name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14484         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14485         (void) sprintf(name, "%016"PRIx64, sasaddr);
14486         (void) sprintf(addr, "w%s,%x", name, lun);
14487         path = mdi_pi_find(parent, NULL, addr);
14488         kmem_free(name, SCSI_MAXNAMELEN);
14489         kmem_free(addr, SCSI_MAXNAMELEN);
14490 
14491         return (path);
14492 }
14493 
14494 static int
14495 mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
14496     dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
14497 {
14498         int                     i = 0;
14499         uchar_t                 *inq83 = NULL;
14500         int                     inq83_len1 = 0xFF;
14501         int                     inq83_len = 0;
14502         int                     rval = DDI_FAILURE;
14503         ddi_devid_t             devid;
14504         char                    *guid = NULL;
14505         int                     target = ptgt->m_devhdl;
14506         mdi_pathinfo_t          *pip = NULL;
14507         mptsas_t                *mpt = DIP2MPT(pdip);
14508 
14509         /*
14510          * For DVD/CD ROM and tape devices and optical
14511          * devices, we won't try to enumerate them under
14512          * scsi_vhci, so no need to try page83
14513          */
14514         if (sd_inq && (sd_inq->inq_dtype == DTYPE_RODIRECT ||
14515             sd_inq->inq_dtype == DTYPE_OPTICAL ||
14516             sd_inq->inq_dtype == DTYPE_ESI))
14517                 goto create_lun;
14518 
14519         /*
14520          * The LCA returns good SCSI status, but corrupt page 83 data the first
14521          * time it is queried. The solution is to keep trying to request page83
14522          * and verify the GUID is not (DDI_NOT_WELL_FORMED) in
14523          * mptsas_inq83_retry_timeout seconds. If the timeout expires, driver
14524          * give up to get VPD page at this stage and fail the enumeration.
14525          */
14526 
14527         inq83   = kmem_zalloc(inq83_len1, KM_SLEEP);
14528 
14529         for (i = 0; i < mptsas_inq83_retry_timeout; i++) {
14530                 rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
14531                     inq83_len1, &inq83_len, 1);
14532                 if (rval != 0) {
14533                         mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
14534                             "0x83 for target:%x, lun:%x failed!", target, lun);
14535                         if (mptsas_physical_bind_failed_page_83 != B_FALSE)
14536                                 goto create_lun;
14537                         goto out;
14538                 }
14539                 /*
14540                  * create DEVID from inquiry data
14541                  */
14542                 if ((rval = ddi_devid_scsi_encode(
14543                     DEVID_SCSI_ENCODE_VERSION_LATEST, NULL, (uchar_t *)sd_inq,
14544                     sizeof (struct scsi_inquiry), NULL, 0, inq83,
14545                     (size_t)inq83_len, &devid)) == DDI_SUCCESS) {
14546                         /*
14547                          * extract GUID from DEVID
14548                          */
14549                         guid = ddi_devid_to_guid(devid);
14550 
14551                         /*
14552                          * Do not enable MPXIO if the strlen(guid) is greater
14553                          * than MPTSAS_MAX_GUID_LEN, this constrain would be
14554                          * handled by framework later.
14555                          */
14556                         if (guid && (strlen(guid) > MPTSAS_MAX_GUID_LEN)) {
14557                                 ddi_devid_free_guid(guid);
14558                                 guid = NULL;
14559                                 if (mpt->m_mpxio_enable == TRUE) {
14560                                         mptsas_log(mpt, CE_NOTE, "!Target:%x, "
14561                                             "lun:%x doesn't have a valid GUID, "
14562                                             "multipathing for this drive is "
14563                                             "not enabled", target, lun);
14564                                 }
14565                         }
14566 
14567                         /*
14568                          * devid no longer needed
14569                          */
14570                         ddi_devid_free(devid);
14571                         break;
14572                 } else if (rval == DDI_NOT_WELL_FORMED) {
14573                         /*
14574                          * return value of ddi_devid_scsi_encode equal to
14575                          * DDI_NOT_WELL_FORMED means DEVID_RETRY, it worth
14576                          * to retry inquiry page 0x83 and get GUID.
14577                          */
14578                         NDBG20(("Not well formed devid, retry..."));
14579                         delay(1 * drv_usectohz(1000000));
14580                         continue;
14581                 } else {
14582                         mptsas_log(mpt, CE_WARN, "!Encode devid failed for "
14583                             "path target:%x, lun:%x", target, lun);
14584                         rval = DDI_FAILURE;
14585                         goto create_lun;
14586                 }
14587         }
14588 
14589         if (i == mptsas_inq83_retry_timeout) {
14590                 mptsas_log(mpt, CE_WARN, "!Repeated page83 requests timeout "
14591                     "for path target:%x, lun:%x", target, lun);
14592         }
14593 
14594         rval = DDI_FAILURE;
14595 
14596 create_lun:
14597         if ((guid != NULL) && (mpt->m_mpxio_enable == TRUE)) {
14598                 rval = mptsas_create_virt_lun(pdip, sd_inq, guid, lun_dip, &pip,
14599                     ptgt, lun);
14600         }
14601         if (rval != DDI_SUCCESS) {
14602                 rval = mptsas_create_phys_lun(pdip, sd_inq, guid, lun_dip,
14603                     ptgt, lun);
14604 
14605         }
14606 out:
14607         if (guid != NULL) {
14608                 /*
14609                  * guid no longer needed
14610                  */
14611                 ddi_devid_free_guid(guid);
14612         }
14613         if (inq83 != NULL)
14614                 kmem_free(inq83, inq83_len1);
14615         return (rval);
14616 }
14617 
14618 static int
14619 mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *inq, char *guid,
14620     dev_info_t **lun_dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt, int lun)
14621 {
14622         int                     target;
14623         char                    *nodename = NULL;
14624         char                    **compatible = NULL;
14625         int                     ncompatible     = 0;
14626         int                     mdi_rtn = MDI_FAILURE;
14627         int                     rval = DDI_FAILURE;
14628         char                    *old_guid = NULL;
14629         mptsas_t                *mpt = DIP2MPT(pdip);
14630         char                    *lun_addr = NULL;
14631         char                    *wwn_str = NULL;
14632         char                    *attached_wwn_str = NULL;
14633         char                    *component = NULL;
14634         uint8_t                 phy = 0xFF;
14635         uint64_t                sas_wwn;
14636         int64_t                 lun64 = 0;
14637         uint32_t                devinfo;
14638         uint16_t                dev_hdl;
14639         uint16_t                pdev_hdl;
14640         uint64_t                dev_sas_wwn;
14641         uint64_t                pdev_sas_wwn;
14642         uint32_t                pdev_info;
14643         uint8_t                 physport;
14644         uint8_t                 phy_id;
14645         uint32_t                page_address;
14646         uint16_t                bay_num, enclosure;
14647         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
14648         uint32_t                dev_info;
14649 
14650         mutex_enter(&mpt->m_mutex);
14651         target = ptgt->m_devhdl;
14652         sas_wwn = ptgt->m_sas_wwn;
14653         devinfo = ptgt->m_deviceinfo;
14654         phy = ptgt->m_phynum;
14655         mutex_exit(&mpt->m_mutex);
14656 
14657         if (sas_wwn) {
14658                 *pip = mptsas_find_path_addr(pdip, sas_wwn, lun);
14659         } else {
14660                 *pip = mptsas_find_path_phy(pdip, phy);
14661         }
14662 
14663         if (*pip != NULL) {
14664                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14665                 ASSERT(*lun_dip != NULL);
14666                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, *lun_dip,
14667                     (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
14668                     MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
14669                         if (strncmp(guid, old_guid, strlen(guid)) == 0) {
14670                                 /*
14671                                  * Same path back online again.
14672                                  */
14673                                 (void) ddi_prop_free(old_guid);
14674                                 if ((!MDI_PI_IS_ONLINE(*pip)) &&
14675                                     (!MDI_PI_IS_STANDBY(*pip)) &&
14676                                     (ptgt->m_tgt_unconfigured == 0)) {
14677                                         rval = mdi_pi_online(*pip, 0);
14678                                         mutex_enter(&mpt->m_mutex);
14679                                         ptgt->m_led_status = 0;
14680                                         (void) mptsas_flush_led_status(mpt,
14681                                             ptgt);
14682                                         mutex_exit(&mpt->m_mutex);
14683                                 } else {
14684                                         rval = DDI_SUCCESS;
14685                                 }
14686                                 if (rval != DDI_SUCCESS) {
14687                                         mptsas_log(mpt, CE_WARN, "path:target: "
14688                                             "%x, lun:%x online failed!", target,
14689                                             lun);
14690                                         *pip = NULL;
14691                                         *lun_dip = NULL;
14692                                 }
14693                                 return (rval);
14694                         } else {
14695                                 /*
14696                                  * The GUID of the LUN has changed which maybe
14697                                  * because customer mapped another volume to the
14698                                  * same LUN.
14699                                  */
14700                                 mptsas_log(mpt, CE_WARN, "The GUID of the "
14701                                     "target:%x, lun:%x was changed, maybe "
14702                                     "because someone mapped another volume "
14703                                     "to the same LUN", target, lun);
14704                                 (void) ddi_prop_free(old_guid);
14705                                 if (!MDI_PI_IS_OFFLINE(*pip)) {
14706                                         rval = mdi_pi_offline(*pip, 0);
14707                                         if (rval != MDI_SUCCESS) {
14708                                                 mptsas_log(mpt, CE_WARN, "path:"
14709                                                     "target:%x, lun:%x offline "
14710                                                     "failed!", target, lun);
14711                                                 *pip = NULL;
14712                                                 *lun_dip = NULL;
14713                                                 return (DDI_FAILURE);
14714                                         }
14715                                 }
14716                                 if (mdi_pi_free(*pip, 0) != MDI_SUCCESS) {
14717                                         mptsas_log(mpt, CE_WARN, "path:target:"
14718                                             "%x, lun:%x free failed!", target,
14719                                             lun);
14720                                         *pip = NULL;
14721                                         *lun_dip = NULL;
14722                                         return (DDI_FAILURE);
14723                                 }
14724                         }
14725                 } else {
14726                         mptsas_log(mpt, CE_WARN, "Can't get client-guid "
14727                             "property for path:target:%x, lun:%x", target, lun);
14728                         *pip = NULL;
14729                         *lun_dip = NULL;
14730                         return (DDI_FAILURE);
14731                 }
14732         }
14733         scsi_hba_nodename_compatible_get(inq, NULL,
14734             inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
14735 
14736         /*
14737          * if nodename can't be determined then print a message and skip it
14738          */
14739         if (nodename == NULL) {
14740                 mptsas_log(mpt, CE_WARN, "mptsas driver found no compatible "
14741                     "driver for target%d lun %d dtype:0x%02x", target, lun,
14742                     inq->inq_dtype);
14743                 return (DDI_FAILURE);
14744         }
14745 
14746         wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
14747         /* The property is needed by MPAPI */
14748         (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
14749 
14750         lun_addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14751         if (guid) {
14752                 (void) sprintf(lun_addr, "w%s,%x", wwn_str, lun);
14753                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14754         } else {
14755                 (void) sprintf(lun_addr, "p%x,%x", phy, lun);
14756                 (void) sprintf(wwn_str, "p%x", phy);
14757         }
14758 
14759         mdi_rtn = mdi_pi_alloc_compatible(pdip, nodename,
14760             guid, lun_addr, compatible, ncompatible,
14761             0, pip);
14762         if (mdi_rtn == MDI_SUCCESS) {
14763 
14764                 if (mdi_prop_update_string(*pip, MDI_GUID,
14765                     guid) != DDI_SUCCESS) {
14766                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14767                             "create prop for target %d lun %d (MDI_GUID)",
14768                             target, lun);
14769                         mdi_rtn = MDI_FAILURE;
14770                         goto virt_create_done;
14771                 }
14772 
14773                 if (mdi_prop_update_int(*pip, LUN_PROP,
14774                     lun) != DDI_SUCCESS) {
14775                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14776                             "create prop for target %d lun %d (LUN_PROP)",
14777                             target, lun);
14778                         mdi_rtn = MDI_FAILURE;
14779                         goto virt_create_done;
14780                 }
14781                 lun64 = (int64_t)lun;
14782                 if (mdi_prop_update_int64(*pip, LUN64_PROP,
14783                     lun64) != DDI_SUCCESS) {
14784                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14785                             "create prop for target %d (LUN64_PROP)",
14786                             target);
14787                         mdi_rtn = MDI_FAILURE;
14788                         goto virt_create_done;
14789                 }
14790                 if (mdi_prop_update_string_array(*pip, "compatible",
14791                     compatible, ncompatible) !=
14792                     DDI_PROP_SUCCESS) {
14793                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14794                             "create prop for target %d lun %d (COMPATIBLE)",
14795                             target, lun);
14796                         mdi_rtn = MDI_FAILURE;
14797                         goto virt_create_done;
14798                 }
14799                 if (sas_wwn && (mdi_prop_update_string(*pip,
14800                     SCSI_ADDR_PROP_TARGET_PORT, wwn_str) != DDI_PROP_SUCCESS)) {
14801                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14802                             "create prop for target %d lun %d "
14803                             "(target-port)", target, lun);
14804                         mdi_rtn = MDI_FAILURE;
14805                         goto virt_create_done;
14806                 } else if ((sas_wwn == 0) && (mdi_prop_update_int(*pip,
14807                     "sata-phy", phy) != DDI_PROP_SUCCESS)) {
14808                         /*
14809                          * Direct attached SATA device without DeviceName
14810                          */
14811                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14812                             "create prop for SAS target %d lun %d "
14813                             "(sata-phy)", target, lun);
14814                         mdi_rtn = MDI_FAILURE;
14815                         goto virt_create_done;
14816                 }
14817                 mutex_enter(&mpt->m_mutex);
14818 
14819                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14820                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14821                     (uint32_t)ptgt->m_devhdl;
14822                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14823                     &dev_hdl, &dev_sas_wwn, &dev_info, &physport,
14824                     &phy_id, &pdev_hdl, &bay_num, &enclosure);
14825                 if (rval != DDI_SUCCESS) {
14826                         mutex_exit(&mpt->m_mutex);
14827                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
14828                             "parent device for handle %d", page_address);
14829                         mdi_rtn = MDI_FAILURE;
14830                         goto virt_create_done;
14831                 }
14832 
14833                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14834                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
14835                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14836                     &dev_hdl, &pdev_sas_wwn, &pdev_info, &physport,
14837                     &phy_id, &pdev_hdl, &bay_num, &enclosure);
14838                 if (rval != DDI_SUCCESS) {
14839                         mutex_exit(&mpt->m_mutex);
14840                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
14841                             "device info for handle %d", page_address);
14842                         mdi_rtn = MDI_FAILURE;
14843                         goto virt_create_done;
14844                 }
14845 
14846                 mutex_exit(&mpt->m_mutex);
14847 
14848                 /*
14849                  * If this device direct attached to the controller
14850                  * set the attached-port to the base wwid
14851                  */
14852                 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14853                     != DEVINFO_DIRECT_ATTACHED) {
14854                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14855                             pdev_sas_wwn);
14856                 } else {
14857                         /*
14858                          * Update the iport's attached-port to guid
14859                          */
14860                         if (sas_wwn == 0) {
14861                                 (void) sprintf(wwn_str, "p%x", phy);
14862                         } else {
14863                                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14864                         }
14865                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
14866                             pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
14867                             DDI_PROP_SUCCESS) {
14868                                 mptsas_log(mpt, CE_WARN,
14869                                     "mptsas unable to create "
14870                                     "property for iport target-port"
14871                                     " %s (sas_wwn)",
14872                                     wwn_str);
14873                                 mdi_rtn = MDI_FAILURE;
14874                                 goto virt_create_done;
14875                         }
14876 
14877                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14878                             mpt->un.m_base_wwid);
14879                 }
14880 
14881                 if (mdi_prop_update_string(*pip,
14882                     SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
14883                     DDI_PROP_SUCCESS) {
14884                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14885                             "property for iport attached-port %s (sas_wwn)",
14886                             attached_wwn_str);
14887                         mdi_rtn = MDI_FAILURE;
14888                         goto virt_create_done;
14889                 }
14890 
14891 
14892                 if (inq->inq_dtype == 0) {
14893                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
14894                         /*
14895                          * set obp path for pathinfo
14896                          */
14897                         (void) snprintf(component, MAXPATHLEN,
14898                             "disk@%s", lun_addr);
14899 
14900                         if (mdi_pi_pathname_obp_set(*pip, component) !=
14901                             DDI_SUCCESS) {
14902                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
14903                                     "unable to set obp-path for object %s",
14904                                     component);
14905                                 mdi_rtn = MDI_FAILURE;
14906                                 goto virt_create_done;
14907                         }
14908                 }
14909 
14910                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14911                 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
14912                     MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
14913                         if ((ndi_prop_update_int(DDI_DEV_T_NONE, *lun_dip,
14914                             "pm-capable", 1)) !=
14915                             DDI_PROP_SUCCESS) {
14916                                 mptsas_log(mpt, CE_WARN, "mptsas driver"
14917                                     "failed to create pm-capable "
14918                                     "property, target %d", target);
14919                                 mdi_rtn = MDI_FAILURE;
14920                                 goto virt_create_done;
14921                         }
14922                 }
14923                 /*
14924                  * Create the phy-num property
14925                  */
14926                 if (mdi_prop_update_int(*pip, "phy-num",
14927                     ptgt->m_phynum) != DDI_SUCCESS) {
14928                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14929                             "create phy-num property for target %d lun %d",
14930                             target, lun);
14931                         mdi_rtn = MDI_FAILURE;
14932                         goto virt_create_done;
14933                 }
14934                 NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr));
14935                 mdi_rtn = mdi_pi_online(*pip, 0);
14936                 if (mdi_rtn == MDI_SUCCESS) {
14937                         mutex_enter(&mpt->m_mutex);
14938                         ptgt->m_led_status = 0;
14939                         if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) {
14940                                 NDBG14(("mptsas: clear LED for slot %x "
14941                                     "failed", ptgt->m_slot_num));
14942                         }
14943                         mutex_exit(&mpt->m_mutex);
14944                 }
14945                 if (mdi_rtn == MDI_NOT_SUPPORTED) {
14946                         mdi_rtn = MDI_FAILURE;
14947                 }
14948 virt_create_done:
14949                 if (*pip && mdi_rtn != MDI_SUCCESS) {
14950                         (void) mdi_pi_free(*pip, 0);
14951                         *pip = NULL;
14952                         *lun_dip = NULL;
14953                 }
14954         }
14955 
14956         scsi_hba_nodename_compatible_free(nodename, compatible);
14957         if (lun_addr != NULL) {
14958                 kmem_free(lun_addr, SCSI_MAXNAMELEN);
14959         }
14960         if (wwn_str != NULL) {
14961                 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
14962         }
14963         if (component != NULL) {
14964                 kmem_free(component, MAXPATHLEN);
14965         }
14966 
14967         return ((mdi_rtn == MDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
14968 }
14969 
14970 static int
14971 mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *inq,
14972     char *guid, dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
14973 {
14974         int                     target;
14975         int                     rval;
14976         int                     ndi_rtn = NDI_FAILURE;
14977         uint64_t                be_sas_wwn;
14978         char                    *nodename = NULL;
14979         char                    **compatible = NULL;
14980         int                     ncompatible = 0;
14981         int                     instance = 0;
14982         mptsas_t                *mpt = DIP2MPT(pdip);
14983         char                    *wwn_str = NULL;
14984         char                    *component = NULL;
14985         char                    *attached_wwn_str = NULL;
14986         uint8_t                 phy = 0xFF;
14987         uint64_t                sas_wwn;
14988         uint32_t                devinfo;
14989         uint16_t                dev_hdl;
14990         uint16_t                pdev_hdl;
14991         uint64_t                pdev_sas_wwn;
14992         uint64_t                dev_sas_wwn;
14993         uint32_t                pdev_info;
14994         uint8_t                 physport;
14995         uint8_t                 phy_id;
14996         uint32_t                page_address;
14997         uint16_t                bay_num, enclosure;
14998         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
14999         uint32_t                dev_info;
15000         int64_t                 lun64 = 0;
15001 
15002         mutex_enter(&mpt->m_mutex);
15003         target = ptgt->m_devhdl;
15004         sas_wwn = ptgt->m_sas_wwn;
15005         devinfo = ptgt->m_deviceinfo;
15006         phy = ptgt->m_phynum;
15007         mutex_exit(&mpt->m_mutex);
15008 
15009         /*
15010          * generate compatible property with binding-set "mpt"
15011          */
15012         scsi_hba_nodename_compatible_get(inq, NULL, inq->inq_dtype, NULL,
15013             &nodename, &compatible, &ncompatible);
15014 
15015         /*
15016          * if nodename can't be determined then print a message and skip it
15017          */
15018         if (nodename == NULL) {
15019                 mptsas_log(mpt, CE_WARN, "mptsas found no compatible driver "
15020                     "for target %d lun %d", target, lun);
15021                 return (DDI_FAILURE);
15022         }
15023 
15024         ndi_rtn = ndi_devi_alloc(pdip, nodename,
15025             DEVI_SID_NODEID, lun_dip);
15026 
15027         /*
15028          * if lun alloc success, set props
15029          */
15030         if (ndi_rtn == NDI_SUCCESS) {
15031 
15032                 if (ndi_prop_update_int(DDI_DEV_T_NONE,
15033                     *lun_dip, LUN_PROP, lun) !=
15034                     DDI_PROP_SUCCESS) {
15035                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15036                             "property for target %d lun %d (LUN_PROP)",
15037                             target, lun);
15038                         ndi_rtn = NDI_FAILURE;
15039                         goto phys_create_done;
15040                 }
15041 
15042                 lun64 = (int64_t)lun;
15043                 if (ndi_prop_update_int64(DDI_DEV_T_NONE,
15044                     *lun_dip, LUN64_PROP, lun64) !=
15045                     DDI_PROP_SUCCESS) {
15046                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15047                             "property for target %d lun64 %d (LUN64_PROP)",
15048                             target, lun);
15049                         ndi_rtn = NDI_FAILURE;
15050                         goto phys_create_done;
15051                 }
15052                 if (ndi_prop_update_string_array(DDI_DEV_T_NONE,
15053                     *lun_dip, "compatible", compatible, ncompatible)
15054                     != DDI_PROP_SUCCESS) {
15055                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15056                             "property for target %d lun %d (COMPATIBLE)",
15057                             target, lun);
15058                         ndi_rtn = NDI_FAILURE;
15059                         goto phys_create_done;
15060                 }
15061 
15062                 /*
15063                  * We need the SAS WWN for non-multipath devices, so
15064                  * we'll use the same property as that multipathing
15065                  * devices need to present for MPAPI. If we don't have
15066                  * a WWN (e.g. parallel SCSI), don't create the prop.
15067                  */
15068                 wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
15069                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15070                 if (sas_wwn && ndi_prop_update_string(DDI_DEV_T_NONE,
15071                     *lun_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str)
15072                     != DDI_PROP_SUCCESS) {
15073                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15074                             "create property for SAS target %d lun %d "
15075                             "(target-port)", target, lun);
15076                         ndi_rtn = NDI_FAILURE;
15077                         goto phys_create_done;
15078                 }
15079 
15080                 be_sas_wwn = BE_64(sas_wwn);
15081                 if (sas_wwn && ndi_prop_update_byte_array(
15082                     DDI_DEV_T_NONE, *lun_dip, "port-wwn",
15083                     (uchar_t *)&be_sas_wwn, 8) != DDI_PROP_SUCCESS) {
15084                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15085                             "create property for SAS target %d lun %d "
15086                             "(port-wwn)", target, lun);
15087                         ndi_rtn = NDI_FAILURE;
15088                         goto phys_create_done;
15089                 } else if ((sas_wwn == 0) && (ndi_prop_update_int(
15090                     DDI_DEV_T_NONE, *lun_dip, "sata-phy", phy) !=
15091                     DDI_PROP_SUCCESS)) {
15092                         /*
15093                          * Direct attached SATA device without DeviceName
15094                          */
15095                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15096                             "create property for SAS target %d lun %d "
15097                             "(sata-phy)", target, lun);
15098                         ndi_rtn = NDI_FAILURE;
15099                         goto phys_create_done;
15100                 }
15101 
15102                 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
15103                     *lun_dip, SAS_PROP) != DDI_PROP_SUCCESS) {
15104                         mptsas_log(mpt, CE_WARN, "mptsas unable to"
15105                             "create property for SAS target %d lun %d"
15106                             " (SAS_PROP)", target, lun);
15107                         ndi_rtn = NDI_FAILURE;
15108                         goto phys_create_done;
15109                 }
15110                 if (guid && (ndi_prop_update_string(DDI_DEV_T_NONE,
15111                     *lun_dip, NDI_GUID, guid) != DDI_SUCCESS)) {
15112                         mptsas_log(mpt, CE_WARN, "mptsas unable "
15113                             "to create guid property for target %d "
15114                             "lun %d", target, lun);
15115                         ndi_rtn = NDI_FAILURE;
15116                         goto phys_create_done;
15117                 }
15118 
15119                 /*
15120                  * The following code is to set properties for SM-HBA support,
15121                  * it doesn't apply to RAID volumes
15122                  */
15123                 if (ptgt->m_phymask == 0)
15124                         goto phys_raid_lun;
15125 
15126                 mutex_enter(&mpt->m_mutex);
15127 
15128                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15129                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15130                     (uint32_t)ptgt->m_devhdl;
15131                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15132                     &dev_hdl, &dev_sas_wwn, &dev_info,
15133                     &physport, &phy_id, &pdev_hdl,
15134                     &bay_num, &enclosure);
15135                 if (rval != DDI_SUCCESS) {
15136                         mutex_exit(&mpt->m_mutex);
15137                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
15138                             "parent device for handle %d.", page_address);
15139                         ndi_rtn = NDI_FAILURE;
15140                         goto phys_create_done;
15141                 }
15142 
15143                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15144                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
15145                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15146                     &dev_hdl, &pdev_sas_wwn, &pdev_info,
15147                     &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure);
15148                 if (rval != DDI_SUCCESS) {
15149                         mutex_exit(&mpt->m_mutex);
15150                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15151                             "device for handle %d.", page_address);
15152                         ndi_rtn = NDI_FAILURE;
15153                         goto phys_create_done;
15154                 }
15155 
15156                 mutex_exit(&mpt->m_mutex);
15157 
15158                 /*
15159                  * If this device direct attached to the controller
15160                  * set the attached-port to the base wwid
15161                  */
15162                 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15163                     != DEVINFO_DIRECT_ATTACHED) {
15164                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15165                             pdev_sas_wwn);
15166                 } else {
15167                         /*
15168                          * Update the iport's attached-port to guid
15169                          */
15170                         if (sas_wwn == 0) {
15171                                 (void) sprintf(wwn_str, "p%x", phy);
15172                         } else {
15173                                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15174                         }
15175                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
15176                             pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
15177                             DDI_PROP_SUCCESS) {
15178                                 mptsas_log(mpt, CE_WARN,
15179                                     "mptsas unable to create "
15180                                     "property for iport target-port"
15181                                     " %s (sas_wwn)",
15182                                     wwn_str);
15183                                 ndi_rtn = NDI_FAILURE;
15184                                 goto phys_create_done;
15185                         }
15186 
15187                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15188                             mpt->un.m_base_wwid);
15189                 }
15190 
15191                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15192                     *lun_dip, SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
15193                     DDI_PROP_SUCCESS) {
15194                         mptsas_log(mpt, CE_WARN,
15195                             "mptsas unable to create "
15196                             "property for iport attached-port %s (sas_wwn)",
15197                             attached_wwn_str);
15198                         ndi_rtn = NDI_FAILURE;
15199                         goto phys_create_done;
15200                 }
15201 
15202                 if (IS_SATA_DEVICE(dev_info)) {
15203                         if (ndi_prop_update_string(DDI_DEV_T_NONE,
15204                             *lun_dip, MPTSAS_VARIANT, "sata") !=
15205                             DDI_PROP_SUCCESS) {
15206                                 mptsas_log(mpt, CE_WARN,
15207                                     "mptsas unable to create "
15208                                     "property for device variant ");
15209                                 ndi_rtn = NDI_FAILURE;
15210                                 goto phys_create_done;
15211                         }
15212                 }
15213 
15214                 if (IS_ATAPI_DEVICE(dev_info)) {
15215                         if (ndi_prop_update_string(DDI_DEV_T_NONE,
15216                             *lun_dip, MPTSAS_VARIANT, "atapi") !=
15217                             DDI_PROP_SUCCESS) {
15218                                 mptsas_log(mpt, CE_WARN,
15219                                     "mptsas unable to create "
15220                                     "property for device variant ");
15221                                 ndi_rtn = NDI_FAILURE;
15222                                 goto phys_create_done;
15223                         }
15224                 }
15225 
15226 phys_raid_lun:
15227                 /*
15228                  * if this is a SAS controller, and the target is a SATA
15229                  * drive, set the 'pm-capable' property for sd and if on
15230                  * an OPL platform, also check if this is an ATAPI
15231                  * device.
15232                  */
15233                 instance = ddi_get_instance(mpt->m_dip);
15234                 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
15235                     MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
15236                         NDBG2(("mptsas%d: creating pm-capable property, "
15237                             "target %d", instance, target));
15238 
15239                         if ((ndi_prop_update_int(DDI_DEV_T_NONE,
15240                             *lun_dip, "pm-capable", 1)) !=
15241                             DDI_PROP_SUCCESS) {
15242                                 mptsas_log(mpt, CE_WARN, "mptsas "
15243                                     "failed to create pm-capable "
15244                                     "property, target %d", target);
15245                                 ndi_rtn = NDI_FAILURE;
15246                                 goto phys_create_done;
15247                         }
15248 
15249                 }
15250 
15251                 if ((inq->inq_dtype == 0) || (inq->inq_dtype == 5)) {
15252                         /*
15253                          * add 'obp-path' properties for devinfo
15254                          */
15255                         bzero(wwn_str, sizeof (wwn_str));
15256                         (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
15257                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
15258                         if (guid) {
15259                                 (void) snprintf(component, MAXPATHLEN,
15260                                     "disk@w%s,%x", wwn_str, lun);
15261                         } else {
15262                                 (void) snprintf(component, MAXPATHLEN,
15263                                     "disk@p%x,%x", phy, lun);
15264                         }
15265                         if (ddi_pathname_obp_set(*lun_dip, component)
15266                             != DDI_SUCCESS) {
15267                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
15268                                     "unable to set obp-path for SAS "
15269                                     "object %s", component);
15270                                 ndi_rtn = NDI_FAILURE;
15271                                 goto phys_create_done;
15272                         }
15273                 }
15274                 /*
15275                  * Create the phy-num property for non-raid disk
15276                  */
15277                 if (ptgt->m_phymask != 0) {
15278                         if (ndi_prop_update_int(DDI_DEV_T_NONE,
15279                             *lun_dip, "phy-num", ptgt->m_phynum) !=
15280                             DDI_PROP_SUCCESS) {
15281                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
15282                                     "failed to create phy-num property for "
15283                                     "target %d", target);
15284                                 ndi_rtn = NDI_FAILURE;
15285                                 goto phys_create_done;
15286                         }
15287                 }
15288 phys_create_done:
15289                 /*
15290                  * If props were setup ok, online the lun
15291                  */
15292                 if (ndi_rtn == NDI_SUCCESS) {
15293                         /*
15294                          * Try to online the new node
15295                          */
15296                         ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
15297                 }
15298                 if (ndi_rtn == NDI_SUCCESS) {
15299                         mutex_enter(&mpt->m_mutex);
15300                         ptgt->m_led_status = 0;
15301                         if (mptsas_flush_led_status(mpt, ptgt) != DDI_SUCCESS) {
15302                                 NDBG14(("mptsas: clear LED for tgt %x "
15303                                     "failed", ptgt->m_slot_num));
15304                         }
15305                         mutex_exit(&mpt->m_mutex);
15306                 }
15307 
15308                 /*
15309                  * If success set rtn flag, else unwire alloc'd lun
15310                  */
15311                 if (ndi_rtn != NDI_SUCCESS) {
15312                         NDBG12(("mptsas driver unable to online "
15313                             "target %d lun %d", target, lun));
15314                         ndi_prop_remove_all(*lun_dip);
15315                         (void) ndi_devi_free(*lun_dip);
15316                         *lun_dip = NULL;
15317                 }
15318         }
15319 
15320         scsi_hba_nodename_compatible_free(nodename, compatible);
15321 
15322         if (wwn_str != NULL) {
15323                 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
15324         }
15325         if (component != NULL) {
15326                 kmem_free(component, MAXPATHLEN);
15327         }
15328 
15329 
15330         return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
15331 }
15332 
15333 static int
15334 mptsas_probe_smp(dev_info_t *pdip, uint64_t wwn)
15335 {
15336         mptsas_t        *mpt = DIP2MPT(pdip);
15337         struct smp_device smp_sd;
15338 
15339         /* XXX An HBA driver should not be allocating an smp_device. */
15340         bzero(&smp_sd, sizeof (struct smp_device));
15341         smp_sd.smp_sd_address.smp_a_hba_tran = mpt->m_smptran;
15342         bcopy(&wwn, smp_sd.smp_sd_address.smp_a_wwn, SAS_WWN_BYTE_SIZE);
15343 
15344         if (smp_probe(&smp_sd) != DDI_PROBE_SUCCESS)
15345                 return (NDI_FAILURE);
15346         return (NDI_SUCCESS);
15347 }
15348 
15349 static int
15350 mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn, dev_info_t **smp_dip)
15351 {
15352         mptsas_t        *mpt = DIP2MPT(pdip);
15353         mptsas_smp_t    *psmp = NULL;
15354         int             rval;
15355         int             phymask;
15356 
15357         /*
15358          * Get the physical port associated to the iport
15359          * PHYMASK TODO
15360          */
15361         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
15362             "phymask", 0);
15363         /*
15364          * Find the smp node in hash table with specified sas address and
15365          * physical port
15366          */
15367         psmp = mptsas_wwid_to_psmp(mpt, phymask, sas_wwn);
15368         if (psmp == NULL) {
15369                 return (DDI_FAILURE);
15370         }
15371 
15372         rval = mptsas_online_smp(pdip, psmp, smp_dip);
15373 
15374         return (rval);
15375 }
15376 
15377 static int
15378 mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
15379     dev_info_t **smp_dip)
15380 {
15381         char            wwn_str[MPTSAS_WWN_STRLEN];
15382         char            attached_wwn_str[MPTSAS_WWN_STRLEN];
15383         int             ndi_rtn = NDI_FAILURE;
15384         int             rval = 0;
15385         mptsas_smp_t    dev_info;
15386         uint32_t        page_address;
15387         mptsas_t        *mpt = DIP2MPT(pdip);
15388         uint16_t        dev_hdl;
15389         uint64_t        sas_wwn;
15390         uint64_t        smp_sas_wwn;
15391         uint8_t         physport;
15392         uint8_t         phy_id;
15393         uint16_t        pdev_hdl;
15394         uint8_t         numphys = 0;
15395         uint16_t        i = 0;
15396         char            phymask[MPTSAS_MAX_PHYS];
15397         char            *iport = NULL;
15398         mptsas_phymask_t        phy_mask = 0;
15399         uint16_t        attached_devhdl;
15400         uint16_t        bay_num, enclosure;
15401 
15402         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_sasaddr);
15403 
15404         /*
15405          * Probe smp device, prevent the node of removed device from being
15406          * configured succesfully
15407          */
15408         if (mptsas_probe_smp(pdip, smp_node->m_sasaddr) != NDI_SUCCESS) {
15409                 return (DDI_FAILURE);
15410         }
15411 
15412         if ((*smp_dip = mptsas_find_smp_child(pdip, wwn_str)) != NULL) {
15413                 return (DDI_SUCCESS);
15414         }
15415 
15416         ndi_rtn = ndi_devi_alloc(pdip, "smp", DEVI_SID_NODEID, smp_dip);
15417 
15418         /*
15419          * if lun alloc success, set props
15420          */
15421         if (ndi_rtn == NDI_SUCCESS) {
15422                 /*
15423                  * Set the flavor of the child to be SMP flavored
15424                  */
15425                 ndi_flavor_set(*smp_dip, SCSA_FLAVOR_SMP);
15426 
15427                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15428                     *smp_dip, SMP_WWN, wwn_str) !=
15429                     DDI_PROP_SUCCESS) {
15430                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15431                             "property for smp device %s (sas_wwn)",
15432                             wwn_str);
15433                         ndi_rtn = NDI_FAILURE;
15434                         goto smp_create_done;
15435                 }
15436                 (void) sprintf(wwn_str, "w%"PRIx64, smp_node->m_sasaddr);
15437                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15438                     *smp_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str) !=
15439                     DDI_PROP_SUCCESS) {
15440                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15441                             "property for iport target-port %s (sas_wwn)",
15442                             wwn_str);
15443                         ndi_rtn = NDI_FAILURE;
15444                         goto smp_create_done;
15445                 }
15446 
15447                 mutex_enter(&mpt->m_mutex);
15448 
15449                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
15450                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | smp_node->m_devhdl;
15451                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
15452                     &dev_info);
15453                 if (rval != DDI_SUCCESS) {
15454                         mutex_exit(&mpt->m_mutex);
15455                         mptsas_log(mpt, CE_WARN,
15456                             "mptsas unable to get expander "
15457                             "parent device info for %x", page_address);
15458                         ndi_rtn = NDI_FAILURE;
15459                         goto smp_create_done;
15460                 }
15461 
15462                 smp_node->m_pdevhdl = dev_info.m_pdevhdl;
15463                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15464                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15465                     (uint32_t)dev_info.m_pdevhdl;
15466                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15467                     &dev_hdl, &sas_wwn, &smp_node->m_pdevinfo,
15468                     &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure);
15469                 if (rval != DDI_SUCCESS) {
15470                         mutex_exit(&mpt->m_mutex);
15471                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
15472                             "device info for %x", page_address);
15473                         ndi_rtn = NDI_FAILURE;
15474                         goto smp_create_done;
15475                 }
15476 
15477                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15478                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15479                     (uint32_t)dev_info.m_devhdl;
15480                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15481                     &dev_hdl, &smp_sas_wwn, &smp_node->m_deviceinfo,
15482                     &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure);
15483                 if (rval != DDI_SUCCESS) {
15484                         mutex_exit(&mpt->m_mutex);
15485                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
15486                             "device info for %x", page_address);
15487                         ndi_rtn = NDI_FAILURE;
15488                         goto smp_create_done;
15489                 }
15490                 mutex_exit(&mpt->m_mutex);
15491 
15492                 /*
15493                  * If this smp direct attached to the controller
15494                  * set the attached-port to the base wwid
15495                  */
15496                 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15497                     != DEVINFO_DIRECT_ATTACHED) {
15498                         (void) sprintf(attached_wwn_str, "w%016"PRIx64,
15499                             sas_wwn);
15500                 } else {
15501                         (void) sprintf(attached_wwn_str, "w%016"PRIx64,
15502                             mpt->un.m_base_wwid);
15503                 }
15504 
15505                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15506                     *smp_dip, SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwn_str) !=
15507                     DDI_PROP_SUCCESS) {
15508                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15509                             "property for smp attached-port %s (sas_wwn)",
15510                             attached_wwn_str);
15511                         ndi_rtn = NDI_FAILURE;
15512                         goto smp_create_done;
15513                 }
15514 
15515                 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
15516                     *smp_dip, SMP_PROP) != DDI_PROP_SUCCESS) {
15517                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15518                             "create property for SMP %s (SMP_PROP) ",
15519                             wwn_str);
15520                         ndi_rtn = NDI_FAILURE;
15521                         goto smp_create_done;
15522                 }
15523 
15524                 /*
15525                  * check the smp to see whether it direct
15526                  * attached to the controller
15527                  */
15528                 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15529                     != DEVINFO_DIRECT_ATTACHED) {
15530                         goto smp_create_done;
15531                 }
15532                 numphys = ddi_prop_get_int(DDI_DEV_T_ANY, pdip,
15533                     DDI_PROP_DONTPASS, MPTSAS_NUM_PHYS, -1);
15534                 if (numphys > 0) {
15535                         goto smp_create_done;
15536                 }
15537                 /*
15538                  * this iport is an old iport, we need to
15539                  * reconfig the props for it.
15540                  */
15541                 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
15542                     MPTSAS_VIRTUAL_PORT, 0) !=
15543                     DDI_PROP_SUCCESS) {
15544                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
15545                             MPTSAS_VIRTUAL_PORT);
15546                         mptsas_log(mpt, CE_WARN, "mptsas virtual port "
15547                             "prop update failed");
15548                         goto smp_create_done;
15549                 }
15550 
15551                 mutex_enter(&mpt->m_mutex);
15552                 numphys = 0;
15553                 iport = ddi_get_name_addr(pdip);
15554                 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15555                         bzero(phymask, sizeof (phymask));
15556                         (void) sprintf(phymask,
15557                             "%x", mpt->m_phy_info[i].phy_mask);
15558                         if (strcmp(phymask, iport) == 0) {
15559                                 phy_mask = mpt->m_phy_info[i].phy_mask;
15560                                 break;
15561                         }
15562                 }
15563 
15564                 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15565                         if ((phy_mask >> i) & 0x01) {
15566                                 numphys++;
15567                         }
15568                 }
15569                 /*
15570                  * Update PHY info for smhba
15571                  */
15572                 if (mptsas_smhba_phy_init(mpt)) {
15573                         mutex_exit(&mpt->m_mutex);
15574                         mptsas_log(mpt, CE_WARN, "mptsas phy update "
15575                             "failed");
15576                         goto smp_create_done;
15577                 }
15578                 mutex_exit(&mpt->m_mutex);
15579 
15580                 mptsas_smhba_set_phy_props(mpt, iport, pdip,
15581                     numphys, &attached_devhdl);
15582 
15583                 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
15584                     MPTSAS_NUM_PHYS, numphys) !=
15585                     DDI_PROP_SUCCESS) {
15586                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
15587                             MPTSAS_NUM_PHYS);
15588                         mptsas_log(mpt, CE_WARN, "mptsas update "
15589                             "num phys props failed");
15590                         goto smp_create_done;
15591                 }
15592                 /*
15593                  * Add parent's props for SMHBA support
15594                  */
15595                 if (ddi_prop_update_string(DDI_DEV_T_NONE, pdip,
15596                     SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
15597                     DDI_PROP_SUCCESS) {
15598                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
15599                             SCSI_ADDR_PROP_ATTACHED_PORT);
15600                         mptsas_log(mpt, CE_WARN, "mptsas update iport"
15601                             "attached-port failed");
15602                         goto smp_create_done;
15603                 }
15604 
15605 smp_create_done:
15606                 /*
15607                  * If props were setup ok, online the lun
15608                  */
15609                 if (ndi_rtn == NDI_SUCCESS) {
15610                         /*
15611                          * Try to online the new node
15612                          */
15613                         ndi_rtn = ndi_devi_online(*smp_dip, NDI_ONLINE_ATTACH);
15614                 }
15615 
15616                 /*
15617                  * If success set rtn flag, else unwire alloc'd lun
15618                  */
15619                 if (ndi_rtn != NDI_SUCCESS) {
15620                         NDBG12(("mptsas unable to online "
15621                             "SMP target %s", wwn_str));
15622                         ndi_prop_remove_all(*smp_dip);
15623                         (void) ndi_devi_free(*smp_dip);
15624                 }
15625         }
15626 
15627         return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
15628 }
15629 
15630 /* smp transport routine */
15631 static int mptsas_smp_start(struct smp_pkt *smp_pkt)
15632 {
15633         uint64_t                        wwn;
15634         Mpi2SmpPassthroughRequest_t     req;
15635         Mpi2SmpPassthroughReply_t       rep;
15636         uint32_t                        direction = 0;
15637         mptsas_t                        *mpt;
15638         int                             ret;
15639         uint64_t                        tmp64;
15640 
15641         mpt = (mptsas_t *)smp_pkt->smp_pkt_address->
15642             smp_a_hba_tran->smp_tran_hba_private;
15643 
15644         bcopy(smp_pkt->smp_pkt_address->smp_a_wwn, &wwn, SAS_WWN_BYTE_SIZE);
15645         /*
15646          * Need to compose a SMP request message
15647          * and call mptsas_do_passthru() function
15648          */
15649         bzero(&req, sizeof (req));
15650         bzero(&rep, sizeof (rep));
15651         req.PassthroughFlags = 0;
15652         req.PhysicalPort = 0xff;
15653         req.ChainOffset = 0;
15654         req.Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
15655 
15656         if ((smp_pkt->smp_pkt_reqsize & 0xffff0000ul) != 0) {
15657                 smp_pkt->smp_pkt_reason = ERANGE;
15658                 return (DDI_FAILURE);
15659         }
15660         req.RequestDataLength = LE_16((uint16_t)(smp_pkt->smp_pkt_reqsize - 4));
15661 
15662         req.MsgFlags = 0;
15663         tmp64 = LE_64(wwn);
15664         bcopy(&tmp64, &req.SASAddress, SAS_WWN_BYTE_SIZE);
15665         if (smp_pkt->smp_pkt_rspsize > 0) {
15666                 direction |= MPTSAS_PASS_THRU_DIRECTION_READ;
15667         }
15668         if (smp_pkt->smp_pkt_reqsize > 0) {
15669                 direction |= MPTSAS_PASS_THRU_DIRECTION_WRITE;
15670         }
15671 
15672         mutex_enter(&mpt->m_mutex);
15673         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep,
15674             (uint8_t *)smp_pkt->smp_pkt_rsp,
15675             offsetof(Mpi2SmpPassthroughRequest_t, SGL), sizeof (rep),
15676             smp_pkt->smp_pkt_rspsize - 4, direction,
15677             (uint8_t *)smp_pkt->smp_pkt_req, smp_pkt->smp_pkt_reqsize - 4,
15678             smp_pkt->smp_pkt_timeout, FKIOCTL);
15679         mutex_exit(&mpt->m_mutex);
15680         if (ret != 0) {
15681                 cmn_err(CE_WARN, "smp_start do passthru error %d", ret);
15682                 smp_pkt->smp_pkt_reason = (uchar_t)(ret);
15683                 return (DDI_FAILURE);
15684         }
15685         /* do passthrough success, check the smp status */
15686         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
15687                 switch (LE_16(rep.IOCStatus)) {
15688                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
15689                         smp_pkt->smp_pkt_reason = ENODEV;
15690                         break;
15691                 case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
15692                         smp_pkt->smp_pkt_reason = EOVERFLOW;
15693                         break;
15694                 case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
15695                         smp_pkt->smp_pkt_reason = EIO;
15696                         break;
15697                 default:
15698                         mptsas_log(mpt, CE_NOTE, "smp_start: get unknown ioc"
15699                             "status:%x", LE_16(rep.IOCStatus));
15700                         smp_pkt->smp_pkt_reason = EIO;
15701                         break;
15702                 }
15703                 return (DDI_FAILURE);
15704         }
15705         if (rep.SASStatus != MPI2_SASSTATUS_SUCCESS) {
15706                 mptsas_log(mpt, CE_NOTE, "smp_start: get error SAS status:%x",
15707                     rep.SASStatus);
15708                 smp_pkt->smp_pkt_reason = EIO;
15709                 return (DDI_FAILURE);
15710         }
15711 
15712         return (DDI_SUCCESS);
15713 }
15714 
15715 /*
15716  * If we didn't get a match, we need to get sas page0 for each device, and
15717  * untill we get a match. If failed, return NULL
15718  */
15719 static mptsas_target_t *
15720 mptsas_phy_to_tgt(mptsas_t *mpt, int phymask, uint8_t phy)
15721 {
15722         int             i, j = 0;
15723         int             rval = 0;
15724         uint16_t        cur_handle;
15725         uint32_t        page_address;
15726         mptsas_target_t *ptgt = NULL;
15727 
15728         /*
15729          * PHY named device must be direct attached and attaches to
15730          * narrow port, if the iport is not parent of the device which
15731          * we are looking for.
15732          */
15733         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15734                 if ((1 << i) & phymask)
15735                         j++;
15736         }
15737 
15738         if (j > 1)
15739                 return (NULL);
15740 
15741         /*
15742          * Must be a narrow port and single device attached to the narrow port
15743          * So the physical port num of device  which is equal to the iport's
15744          * port num is the device what we are looking for.
15745          */
15746 
15747         if (mpt->m_phy_info[phy].phy_mask != phymask)
15748                 return (NULL);
15749 
15750         mutex_enter(&mpt->m_mutex);
15751 
15752         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
15753             MPTSAS_HASH_FIRST);
15754         while (ptgt != NULL) {
15755                         if ((ptgt->m_sas_wwn == 0) && (ptgt->m_phynum == phy)) {
15756                         mutex_exit(&mpt->m_mutex);
15757                         return (ptgt);
15758                 }
15759 
15760                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
15761                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
15762         }
15763 
15764         if (mpt->m_done_traverse_dev) {
15765                 mutex_exit(&mpt->m_mutex);
15766                 return (NULL);
15767         }
15768 
15769         /* If didn't get a match, come here */
15770         cur_handle = mpt->m_dev_handle;
15771         for (; ; ) {
15772                 ptgt = NULL;
15773                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15774                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15775                 rval = mptsas_get_target_device_info(mpt, page_address,
15776                     &cur_handle, &ptgt);
15777                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15778                     (rval == DEV_INFO_FAIL_ALLOC)) {
15779                         break;
15780                 }
15781                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15782                     (rval == DEV_INFO_PHYS_DISK)) {
15783                         continue;
15784                 }
15785                 mpt->m_dev_handle = cur_handle;
15786 
15787                 if ((ptgt->m_sas_wwn == 0) && (ptgt->m_phynum == phy)) {
15788                         break;
15789                 }
15790         }
15791 
15792         mutex_exit(&mpt->m_mutex);
15793         return (ptgt);
15794 }
15795 
15796 /*
15797  * The ptgt->m_sas_wwn contains the wwid for each disk.
15798  * For Raid volumes, we need to check m_raidvol[x].m_raidwwid
15799  * If we didn't get a match, we need to get sas page0 for each device, and
15800  * untill we get a match
15801  * If failed, return NULL
15802  */
15803 static mptsas_target_t *
15804 mptsas_wwid_to_ptgt(mptsas_t *mpt, int phymask, uint64_t wwid)
15805 {
15806         int             rval = 0;
15807         uint16_t        cur_handle;
15808         uint32_t        page_address;
15809         mptsas_target_t *tmp_tgt = NULL;
15810 
15811         mutex_enter(&mpt->m_mutex);
15812         tmp_tgt = (struct mptsas_target *)mptsas_hash_search(
15813             &mpt->m_active->m_tgttbl, wwid, phymask);
15814         if (tmp_tgt != NULL) {
15815                 mutex_exit(&mpt->m_mutex);
15816                 return (tmp_tgt);
15817         }
15818 
15819         if (phymask == 0) {
15820                 /*
15821                  * It's IR volume
15822                  */
15823                 rval = mptsas_get_raid_info(mpt);
15824                 if (rval) {
15825                         tmp_tgt = (struct mptsas_target *)mptsas_hash_search(
15826                             &mpt->m_active->m_tgttbl, wwid, phymask);
15827                 }
15828                 mutex_exit(&mpt->m_mutex);
15829                 return (tmp_tgt);
15830         }
15831 
15832         if (mpt->m_done_traverse_dev) {
15833                 mutex_exit(&mpt->m_mutex);
15834                 return (NULL);
15835         }
15836 
15837         /* If didn't get a match, come here */
15838         cur_handle = mpt->m_dev_handle;
15839         for (; ; ) {
15840                 tmp_tgt = NULL;
15841                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15842                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | cur_handle;
15843                 rval = mptsas_get_target_device_info(mpt, page_address,
15844                     &cur_handle, &tmp_tgt);
15845                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15846                     (rval == DEV_INFO_FAIL_ALLOC)) {
15847                         tmp_tgt = NULL;
15848                         break;
15849                 }
15850                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15851                     (rval == DEV_INFO_PHYS_DISK)) {
15852                         continue;
15853                 }
15854                 mpt->m_dev_handle = cur_handle;
15855                 if ((tmp_tgt->m_sas_wwn) && (tmp_tgt->m_sas_wwn == wwid) &&
15856                     (tmp_tgt->m_phymask == phymask)) {
15857                         break;
15858                 }
15859         }
15860 
15861         mutex_exit(&mpt->m_mutex);
15862         return (tmp_tgt);
15863 }
15864 
15865 static mptsas_smp_t *
15866 mptsas_wwid_to_psmp(mptsas_t *mpt, int phymask, uint64_t wwid)
15867 {
15868         int             rval = 0;
15869         uint16_t        cur_handle;
15870         uint32_t        page_address;
15871         mptsas_smp_t    smp_node, *psmp = NULL;
15872 
15873         mutex_enter(&mpt->m_mutex);
15874         psmp = (struct mptsas_smp *)mptsas_hash_search(&mpt->m_active->m_smptbl,
15875             wwid, phymask);
15876         if (psmp != NULL) {
15877                 mutex_exit(&mpt->m_mutex);
15878                 return (psmp);
15879         }
15880 
15881         if (mpt->m_done_traverse_smp) {
15882                 mutex_exit(&mpt->m_mutex);
15883                 return (NULL);
15884         }
15885 
15886         /* If didn't get a match, come here */
15887         cur_handle = mpt->m_smp_devhdl;
15888         for (; ; ) {
15889                 psmp = NULL;
15890                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
15891                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15892                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
15893                     &smp_node);
15894                 if (rval != DDI_SUCCESS) {
15895                         break;
15896                 }
15897                 mpt->m_smp_devhdl = cur_handle = smp_node.m_devhdl;
15898                 psmp = mptsas_smp_alloc(&mpt->m_active->m_smptbl, &smp_node);
15899                 ASSERT(psmp);
15900                 if ((psmp->m_sasaddr) && (psmp->m_sasaddr == wwid) &&
15901                     (psmp->m_phymask == phymask)) {
15902                         break;
15903                 }
15904         }
15905 
15906         mutex_exit(&mpt->m_mutex);
15907         return (psmp);
15908 }
15909 
15910 /* helper functions using hash */
15911 
15912 /*
15913  * Can't have duplicate entries for same devhdl,
15914  * if there are invalid entries, the devhdl should be set to 0xffff
15915  */
15916 static void *
15917 mptsas_search_by_devhdl(mptsas_hash_table_t *hashtab, uint16_t devhdl)
15918 {
15919         mptsas_hash_data_t *data;
15920 
15921         data = mptsas_hash_traverse(hashtab, MPTSAS_HASH_FIRST);
15922         while (data != NULL) {
15923                 if (data->devhdl == devhdl) {
15924                         break;
15925                 }
15926                 data = mptsas_hash_traverse(hashtab, MPTSAS_HASH_NEXT);
15927         }
15928         return (data);
15929 }
15930 
15931 mptsas_target_t *
15932 mptsas_tgt_alloc(mptsas_hash_table_t *hashtab, uint16_t devhdl, uint64_t wwid,
15933     uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum, mptsas_t *mpt)
15934 {
15935         mptsas_target_t *tmp_tgt = NULL;
15936 
15937         tmp_tgt = mptsas_hash_search(hashtab, wwid, phymask);
15938         if (tmp_tgt != NULL) {
15939                 NDBG20(("Hash item already exist"));
15940                 tmp_tgt->m_deviceinfo = devinfo;
15941                 tmp_tgt->m_devhdl = devhdl;
15942                 return (tmp_tgt);
15943         }
15944         tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target), KM_SLEEP);
15945         if (tmp_tgt == NULL) {
15946                 cmn_err(CE_WARN, "Fatal, allocated tgt failed");
15947                 return (NULL);
15948         }
15949         tmp_tgt->m_devhdl = devhdl;
15950         tmp_tgt->m_sas_wwn = wwid;
15951         tmp_tgt->m_deviceinfo = devinfo;
15952         tmp_tgt->m_phymask = phymask;
15953         tmp_tgt->m_phynum = phynum;
15954         /* Initialized the tgt structure */
15955         tmp_tgt->m_qfull_retries = QFULL_RETRIES;
15956         tmp_tgt->m_qfull_retry_interval =
15957             drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
15958         tmp_tgt->m_t_throttle = MAX_THROTTLE;
15959         mutex_init(&tmp_tgt->m_tgt_intr_mutex, NULL, MUTEX_DRIVER,
15960             DDI_INTR_PRI(mpt->m_intr_pri));
15961 
15962         mptsas_hash_add(hashtab, tmp_tgt);
15963 
15964         return (tmp_tgt);
15965 }
15966 
15967 static void
15968 mptsas_tgt_free(mptsas_hash_table_t *hashtab, uint64_t wwid,
15969     mptsas_phymask_t phymask)
15970 {
15971         mptsas_target_t *tmp_tgt;
15972         tmp_tgt = mptsas_hash_rem(hashtab, wwid, phymask);
15973         if (tmp_tgt == NULL) {
15974                 cmn_err(CE_WARN, "Tgt not found, nothing to free");
15975         } else {
15976                 mutex_destroy(&tmp_tgt->m_tgt_intr_mutex);
15977                 kmem_free(tmp_tgt, sizeof (struct mptsas_target));
15978         }
15979 }
15980 
15981 /*
15982  * Return the entry in the hash table
15983  */
15984 static mptsas_smp_t *
15985 mptsas_smp_alloc(mptsas_hash_table_t *hashtab, mptsas_smp_t *data)
15986 {
15987         uint64_t key1 = data->m_sasaddr;
15988         mptsas_phymask_t key2 = data->m_phymask;
15989         mptsas_smp_t *ret_data;
15990 
15991         ret_data = mptsas_hash_search(hashtab, key1, key2);
15992         if (ret_data != NULL) {
15993                 bcopy(data, ret_data, sizeof (mptsas_smp_t));
15994                 return (ret_data);
15995         }
15996 
15997         ret_data = kmem_alloc(sizeof (mptsas_smp_t), KM_SLEEP);
15998         bcopy(data, ret_data, sizeof (mptsas_smp_t));
15999         mptsas_hash_add(hashtab, ret_data);
16000         return (ret_data);
16001 }
16002 
16003 static void
16004 mptsas_smp_free(mptsas_hash_table_t *hashtab, uint64_t wwid,
16005     mptsas_phymask_t phymask)
16006 {
16007         mptsas_smp_t *tmp_smp;
16008         tmp_smp = mptsas_hash_rem(hashtab, wwid, phymask);
16009         if (tmp_smp == NULL) {
16010                 cmn_err(CE_WARN, "Smp element not found, nothing to free");
16011         } else {
16012                 kmem_free(tmp_smp, sizeof (struct mptsas_smp));
16013         }
16014 }
16015 
16016 /*
16017  * Hash operation functions
16018  * key1 is the sas_wwn, key2 is the phymask
16019  */
16020 static void
16021 mptsas_hash_init(mptsas_hash_table_t *hashtab)
16022 {
16023         if (hashtab == NULL) {
16024                 return;
16025         }
16026         bzero(hashtab->head, sizeof (mptsas_hash_node_t) *
16027             MPTSAS_HASH_ARRAY_SIZE);
16028         hashtab->cur = NULL;
16029         hashtab->line = 0;
16030 }
16031 
16032 static void
16033 mptsas_hash_uninit(mptsas_hash_table_t *hashtab, size_t datalen)
16034 {
16035         uint16_t line = 0;
16036         mptsas_hash_node_t *cur = NULL, *last = NULL;
16037 
16038         if (hashtab == NULL) {
16039                 return;
16040         }
16041         for (line = 0; line < MPTSAS_HASH_ARRAY_SIZE; line++) {
16042                 cur = hashtab->head[line];
16043                 while (cur != NULL) {
16044                         last = cur;
16045                         cur = cur->next;
16046                         kmem_free(last->data, datalen);
16047                         kmem_free(last, sizeof (mptsas_hash_node_t));
16048                 }
16049         }
16050 }
16051 
16052 /*
16053  * You must guarantee the element doesn't exist in the hash table
16054  * before you call mptsas_hash_add()
16055  */
16056 static void
16057 mptsas_hash_add(mptsas_hash_table_t *hashtab, void *data)
16058 {
16059         uint64_t key1 = ((mptsas_hash_data_t *)data)->key1;
16060         mptsas_phymask_t key2 = ((mptsas_hash_data_t *)data)->key2;
16061         mptsas_hash_node_t **head = NULL;
16062         mptsas_hash_node_t *node = NULL;
16063 
16064         if (hashtab == NULL) {
16065                 return;
16066         }
16067         ASSERT(mptsas_hash_search(hashtab, key1, key2) == NULL);
16068         node = kmem_zalloc(sizeof (mptsas_hash_node_t), KM_NOSLEEP);
16069         node->data = data;
16070 
16071         head = &(hashtab->head[key1 % MPTSAS_HASH_ARRAY_SIZE]);
16072         if (*head == NULL) {
16073                 *head = node;
16074         } else {
16075                 node->next = *head;
16076                 *head = node;
16077         }
16078 }
16079 
16080 static void *
16081 mptsas_hash_rem(mptsas_hash_table_t *hashtab, uint64_t key1,
16082     mptsas_phymask_t key2)
16083 {
16084         mptsas_hash_node_t **head = NULL;
16085         mptsas_hash_node_t *last = NULL, *cur = NULL;
16086         mptsas_hash_data_t *data;
16087         if (hashtab == NULL) {
16088                 return (NULL);
16089         }
16090         head = &(hashtab->head[key1 % MPTSAS_HASH_ARRAY_SIZE]);
16091         cur = *head;
16092         while (cur != NULL) {
16093                 data = cur->data;
16094                 if ((data->key1 == key1) && (data->key2 == key2)) {
16095                         if (last == NULL) {
16096                                 (*head) = cur->next;
16097                         } else {
16098                                 last->next = cur->next;
16099                         }
16100                         kmem_free(cur, sizeof (mptsas_hash_node_t));
16101                         return (data);
16102                 } else {
16103                         last = cur;
16104                         cur = cur->next;
16105                 }
16106         }
16107         return (NULL);
16108 }
16109 
16110 static void *
16111 mptsas_hash_search(mptsas_hash_table_t *hashtab, uint64_t key1,
16112     mptsas_phymask_t key2)
16113 {
16114         mptsas_hash_node_t *cur = NULL;
16115         mptsas_hash_data_t *data;
16116         if (hashtab == NULL) {
16117                 return (NULL);
16118         }
16119         cur = hashtab->head[key1 % MPTSAS_HASH_ARRAY_SIZE];
16120         while (cur != NULL) {
16121                 data = cur->data;
16122                 if ((data->key1 == key1) && (data->key2 == key2)) {
16123                         return (data);
16124                 } else {
16125                         cur = cur->next;
16126                 }
16127         }
16128         return (NULL);
16129 }
16130 
16131 static void *
16132 mptsas_hash_traverse(mptsas_hash_table_t *hashtab, int pos)
16133 {
16134         mptsas_hash_node_t *this = NULL;
16135 
16136         if (hashtab == NULL) {
16137                 return (NULL);
16138         }
16139 
16140         if (pos == MPTSAS_HASH_FIRST) {
16141                 hashtab->line = 0;
16142                 hashtab->cur = NULL;
16143                 this = hashtab->head[0];
16144         } else {
16145                 if (hashtab->cur == NULL) {
16146                         return (NULL);
16147                 } else {
16148                         this = hashtab->cur->next;
16149                 }
16150         }
16151 
16152         while (this == NULL) {
16153                 hashtab->line++;
16154                 if (hashtab->line >= MPTSAS_HASH_ARRAY_SIZE) {
16155                         /* the traverse reaches the end */
16156                         hashtab->cur = NULL;
16157                         return (NULL);
16158                 } else {
16159                         this = hashtab->head[hashtab->line];
16160                 }
16161         }
16162         hashtab->cur = this;
16163         return (this->data);
16164 }
16165 
16166 /*
16167  * Functions for SGPIO LED support
16168  */
16169 static dev_info_t *
16170 mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask)
16171 {
16172         dev_info_t      *dip;
16173         int             prop;
16174         dip = e_ddi_hold_devi_by_dev(dev, 0);
16175         if (dip == NULL)
16176                 return (dip);
16177         prop = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
16178             "phymask", 0);
16179         *phymask = (mptsas_phymask_t)prop;
16180         ddi_release_devi(dip);
16181         return (dip);
16182 }
16183 static mptsas_target_t *
16184 mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
16185 {
16186         uint8_t                 phynum;
16187         uint64_t                wwn;
16188         int                     lun;
16189         mptsas_target_t         *ptgt = NULL;
16190 
16191         if (mptsas_parse_address(addr, &wwn, &phynum, &lun) != DDI_SUCCESS) {
16192                 return (NULL);
16193         }
16194         if (addr[0] == 'w') {
16195                 ptgt = mptsas_wwid_to_ptgt(mpt, (int)phymask, wwn);
16196         } else {
16197                 ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum);
16198         }
16199         return (ptgt);
16200 }
16201 
16202 static int
16203 mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt)
16204 {
16205         uint32_t slotstatus = 0;
16206 
16207         /* Build an MPI2 Slot Status based on our view of the world */
16208         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_IDENT - 1)))
16209                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST;
16210         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_FAIL - 1)))
16211                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT;
16212         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1)))
16213                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
16214 
16215         /* Write it to the controller */
16216         NDBG14(("mptsas_ioctl: set LED status %x for slot %x",
16217             slotstatus, ptgt->m_slot_num));
16218         return (mptsas_send_sep(mpt, ptgt, &slotstatus,
16219             MPI2_SEP_REQ_ACTION_WRITE_STATUS));
16220 }
16221 
16222 /*
16223  *  send sep request, use enclosure/slot addressing
16224  */
16225 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
16226     uint32_t *status, uint8_t act)
16227 {
16228         Mpi2SepRequest_t        req;
16229         Mpi2SepReply_t          rep;
16230         int                     ret;
16231 
16232         ASSERT(mutex_owned(&mpt->m_mutex));
16233 
16234         bzero(&req, sizeof (req));
16235         bzero(&rep, sizeof (rep));
16236 
16237         /* Do nothing for RAID volumes */
16238         if (ptgt->m_phymask == 0) {
16239                 NDBG14(("mptsas_send_sep: Skip RAID volumes"));
16240                 return (DDI_FAILURE);
16241         }
16242 
16243         req.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
16244         req.Action = act;
16245         req.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
16246         req.EnclosureHandle = LE_16(ptgt->m_enclosure);
16247         req.Slot = LE_16(ptgt->m_slot_num);
16248         if (act == MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
16249                 req.SlotStatus = LE_32(*status);
16250         }
16251         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
16252             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
16253         if (ret != 0) {
16254                 mptsas_log(mpt, CE_NOTE, "mptsas_send_sep: passthru SEP "
16255                     "Processor Request message error %d", ret);
16256                 return (DDI_FAILURE);
16257         }
16258         /* do passthrough success, check the ioc status */
16259         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
16260                 if ((LE_16(rep.IOCStatus) & MPI2_IOCSTATUS_MASK) ==
16261                     MPI2_IOCSTATUS_INVALID_FIELD) {
16262                         mptsas_log(mpt, CE_NOTE, "send sep act %x: Not "
16263                             "supported action, loginfo %x", act,
16264                             LE_32(rep.IOCLogInfo));
16265                         return (DDI_FAILURE);
16266                 }
16267                 mptsas_log(mpt, CE_NOTE, "send_sep act %x: ioc "
16268                     "status:%x", act, LE_16(rep.IOCStatus));
16269                 return (DDI_FAILURE);
16270         }
16271         if (act != MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
16272                 *status = LE_32(rep.SlotStatus);
16273         }
16274 
16275         return (DDI_SUCCESS);
16276 }
16277 
16278 int
16279 mptsas_dma_addr_create(mptsas_t *mpt, ddi_dma_attr_t dma_attr,
16280     ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp, caddr_t *dma_memp,
16281     uint32_t alloc_size, ddi_dma_cookie_t *cookiep)
16282 {
16283         ddi_dma_cookie_t        new_cookie;
16284         size_t                  alloc_len;
16285         uint_t                  ncookie;
16286 
16287         if (cookiep == NULL)
16288                 cookiep = &new_cookie;
16289 
16290         if (ddi_dma_alloc_handle(mpt->m_dip, &dma_attr, DDI_DMA_SLEEP,
16291             NULL, dma_hdp) != DDI_SUCCESS) {
16292                 dma_hdp = NULL;
16293                 return (FALSE);
16294         }
16295 
16296         if (ddi_dma_mem_alloc(*dma_hdp, alloc_size, &mpt->m_dev_acc_attr,
16297             DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, dma_memp, &alloc_len,
16298             acc_hdp) != DDI_SUCCESS) {
16299                 ddi_dma_free_handle(dma_hdp);
16300                 dma_hdp = NULL;
16301                 return (FALSE);
16302         }
16303 
16304         if (ddi_dma_addr_bind_handle(*dma_hdp, NULL, *dma_memp, alloc_len,
16305             (DDI_DMA_RDWR | DDI_DMA_CONSISTENT), DDI_DMA_SLEEP, NULL,
16306             cookiep, &ncookie) != DDI_DMA_MAPPED) {
16307                 (void) ddi_dma_mem_free(acc_hdp);
16308                 ddi_dma_free_handle(dma_hdp);
16309                 dma_hdp = NULL;
16310                 return (FALSE);
16311         }
16312 
16313         return (TRUE);
16314 }
16315 
16316 void
16317 mptsas_dma_addr_destroy(ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp)
16318 {
16319         if (*dma_hdp == NULL)
16320                 return;
16321 
16322         (void) ddi_dma_unbind_handle(*dma_hdp);
16323         (void) ddi_dma_mem_free(acc_hdp);
16324         ddi_dma_free_handle(dma_hdp);
16325         dma_hdp = NULL;
16326 }
16327 
16328 static int
16329 mptsas_outstanding_cmds_n(mptsas_t *mpt)
16330 {
16331         int n = 0, i;
16332         for (i = 0; i < mpt->m_slot_freeq_pair_n; i++) {
16333                 mutex_enter(&mpt->m_slot_freeq_pairp[i].
16334                     m_slot_allocq.s.m_fq_mutex);
16335                 mutex_enter(&mpt->m_slot_freeq_pairp[i].
16336                     m_slot_releq.s.m_fq_mutex);
16337                 n += (mpt->m_slot_freeq_pairp[i].m_slot_allocq.s.m_fq_n_init -
16338                     mpt->m_slot_freeq_pairp[i].m_slot_allocq.s.m_fq_n -
16339                     mpt->m_slot_freeq_pairp[i].m_slot_releq.s.m_fq_n);
16340                 mutex_exit(&mpt->m_slot_freeq_pairp[i].
16341                     m_slot_releq.s.m_fq_mutex);
16342                 mutex_exit(&mpt->m_slot_freeq_pairp[i].
16343                     m_slot_allocq.s.m_fq_mutex);
16344         }
16345         if (mpt->m_max_requests - 2 < n)
16346                 panic("mptsas: free slot allocq and releq crazy");
16347         return (n);
16348 }