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 2014 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  26  * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
  27  */
  28 
  29 /*
  30  * Copyright (c) 2000 to 2010, LSI Corporation.
  31  * All rights reserved.
  32  *
  33  * Redistribution and use in source and binary forms of all code within
  34  * this file that is exclusively owned by LSI, with or without
  35  * modification, is permitted provided that, in addition to the CDDL 1.0
  36  * License requirements, the following conditions are met:
  37  *
  38  *    Neither the name of the author nor the names of its contributors may be
  39  *    used to endorse or promote products derived from this software without
  40  *    specific prior written permission.
  41  *
  42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  43  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  45  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  46  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  47  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  48  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  49  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  50  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  51  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  52  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  53  * DAMAGE.
  54  */
  55 
  56 /*
  57  * mptsas - This is a driver based on LSI Logic's MPT2.0 interface.
  58  *
  59  */
  60 
  61 #if defined(lint) || defined(DEBUG)
  62 #define MPTSAS_DEBUG
  63 #endif
  64 
  65 /*
  66  * standard header files.
  67  */
  68 #include <sys/note.h>
  69 #include <sys/scsi/scsi.h>
  70 #include <sys/pci.h>
  71 #include <sys/file.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 #include <sys/scsi/adapters/mpt_sas/mptsas_hash.h>
 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  * autoconfiguration data and routines.
 115  */
 116 static int mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
 117 static int mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
 118 static int mptsas_power(dev_info_t *dip, int component, int level);
 119 
 120 /*
 121  * cb_ops function
 122  */
 123 static int mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
 124         cred_t *credp, int *rval);
 125 #ifdef __sparc
 126 static int mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd);
 127 #else  /* __sparc */
 128 static int mptsas_quiesce(dev_info_t *devi);
 129 #endif  /* __sparc */
 130 
 131 /*
 132  * Resource initilaization for hardware
 133  */
 134 static void mptsas_setup_cmd_reg(mptsas_t *mpt);
 135 static void mptsas_disable_bus_master(mptsas_t *mpt);
 136 static void mptsas_hba_fini(mptsas_t *mpt);
 137 static void mptsas_cfg_fini(mptsas_t *mptsas_blkp);
 138 static int mptsas_hba_setup(mptsas_t *mpt);
 139 static void mptsas_hba_teardown(mptsas_t *mpt);
 140 static int mptsas_config_space_init(mptsas_t *mpt);
 141 static void mptsas_config_space_fini(mptsas_t *mpt);
 142 static void mptsas_iport_register(mptsas_t *mpt);
 143 static int mptsas_smp_setup(mptsas_t *mpt);
 144 static void mptsas_smp_teardown(mptsas_t *mpt);
 145 static int mptsas_cache_create(mptsas_t *mpt);
 146 static void mptsas_cache_destroy(mptsas_t *mpt);
 147 static int mptsas_alloc_request_frames(mptsas_t *mpt);
 148 static int mptsas_alloc_reply_frames(mptsas_t *mpt);
 149 static int mptsas_alloc_free_queue(mptsas_t *mpt);
 150 static int mptsas_alloc_post_queue(mptsas_t *mpt);
 151 static void mptsas_alloc_reply_args(mptsas_t *mpt);
 152 static int mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
 153 static void mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
 154 static int mptsas_init_chip(mptsas_t *mpt, int first_time);
 155 
 156 /*
 157  * SCSA function prototypes
 158  */
 159 static int mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
 160 static int mptsas_scsi_reset(struct scsi_address *ap, int level);
 161 static int mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
 162 static int mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly);
 163 static int mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value,
 164     int tgtonly);
 165 static void mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt);
 166 static struct scsi_pkt *mptsas_scsi_init_pkt(struct scsi_address *ap,
 167     struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen,
 168         int tgtlen, int flags, int (*callback)(), caddr_t arg);
 169 static void mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt);
 170 static void mptsas_scsi_destroy_pkt(struct scsi_address *ap,
 171     struct scsi_pkt *pkt);
 172 static int mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 173     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 174 static void mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 175     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 176 static int mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
 177     void (*callback)(caddr_t), caddr_t arg);
 178 static int mptsas_get_name(struct scsi_device *sd, char *name, int len);
 179 static int mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len);
 180 static int mptsas_scsi_quiesce(dev_info_t *dip);
 181 static int mptsas_scsi_unquiesce(dev_info_t *dip);
 182 static int mptsas_bus_config(dev_info_t *pdip, uint_t flags,
 183     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
 184 
 185 /*
 186  * SMP functions
 187  */
 188 static int mptsas_smp_start(struct smp_pkt *smp_pkt);
 189 
 190 /*
 191  * internal function prototypes.
 192  */
 193 static void mptsas_list_add(mptsas_t *mpt);
 194 static void mptsas_list_del(mptsas_t *mpt);
 195 
 196 static int mptsas_quiesce_bus(mptsas_t *mpt);
 197 static int mptsas_unquiesce_bus(mptsas_t *mpt);
 198 
 199 static int mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size);
 200 static void mptsas_free_handshake_msg(mptsas_t *mpt);
 201 
 202 static void mptsas_ncmds_checkdrain(void *arg);
 203 
 204 static int mptsas_prepare_pkt(mptsas_cmd_t *cmd);
 205 static int mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
 206 static int mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
 207 static void mptsas_accept_tx_waitq(mptsas_t *mpt);
 208 
 209 static int mptsas_do_detach(dev_info_t *dev);
 210 static int mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl);
 211 static int mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun,
 212     struct scsi_pkt *pkt);
 213 static int mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp);
 214 
 215 static void mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd);
 216 static void mptsas_handle_event(void *args);
 217 static int mptsas_handle_event_sync(void *args);
 218 static void mptsas_handle_dr(void *args);
 219 static void mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
 220     dev_info_t *pdip);
 221 
 222 static void mptsas_restart_cmd(void *);
 223 
 224 static void mptsas_flush_hba(mptsas_t *mpt);
 225 static void mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun,
 226         uint8_t tasktype);
 227 static void mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd,
 228     uchar_t reason, uint_t stat);
 229 
 230 static uint_t mptsas_intr(caddr_t arg1, caddr_t arg2);
 231 static void mptsas_process_intr(mptsas_t *mpt,
 232     pMpi2ReplyDescriptorsUnion_t reply_desc_union);
 233 static void mptsas_handle_scsi_io_success(mptsas_t *mpt,
 234     pMpi2ReplyDescriptorsUnion_t reply_desc);
 235 static void mptsas_handle_address_reply(mptsas_t *mpt,
 236     pMpi2ReplyDescriptorsUnion_t reply_desc);
 237 static int mptsas_wait_intr(mptsas_t *mpt, int polltime);
 238 static void mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd,
 239     uint32_t *control, pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl);
 240 
 241 static void mptsas_watch(void *arg);
 242 static void mptsas_watchsubr(mptsas_t *mpt);
 243 static void mptsas_cmd_timeout(mptsas_t *mpt, mptsas_target_t *ptgt);
 244 
 245 static void mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd);
 246 static int mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
 247     uint8_t *data, uint32_t request_size, uint32_t reply_size,
 248     uint32_t data_size, uint32_t direction, uint8_t *dataout,
 249     uint32_t dataout_size, short timeout, int mode);
 250 static int mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl);
 251 
 252 static uint8_t mptsas_get_fw_diag_buffer_number(mptsas_t *mpt,
 253     uint32_t unique_id);
 254 static void mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd);
 255 static int mptsas_post_fw_diag_buffer(mptsas_t *mpt,
 256     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
 257 static int mptsas_release_fw_diag_buffer(mptsas_t *mpt,
 258     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
 259     uint32_t diag_type);
 260 static int mptsas_diag_register(mptsas_t *mpt,
 261     mptsas_fw_diag_register_t *diag_register, uint32_t *return_code);
 262 static int mptsas_diag_unregister(mptsas_t *mpt,
 263     mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code);
 264 static int mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
 265     uint32_t *return_code);
 266 static int mptsas_diag_read_buffer(mptsas_t *mpt,
 267     mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
 268     uint32_t *return_code, int ioctl_mode);
 269 static int mptsas_diag_release(mptsas_t *mpt,
 270     mptsas_fw_diag_release_t *diag_release, uint32_t *return_code);
 271 static int mptsas_do_diag_action(mptsas_t *mpt, uint32_t action,
 272     uint8_t *diag_action, uint32_t length, uint32_t *return_code,
 273     int ioctl_mode);
 274 static int mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *data,
 275     int mode);
 276 
 277 static int mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
 278     int cmdlen, int tgtlen, int statuslen, int kf);
 279 static void mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd);
 280 
 281 static int mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags);
 282 static void mptsas_kmem_cache_destructor(void *buf, void *cdrarg);
 283 
 284 static int mptsas_cache_frames_constructor(void *buf, void *cdrarg,
 285     int kmflags);
 286 static void mptsas_cache_frames_destructor(void *buf, void *cdrarg);
 287 
 288 static void mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
 289     mptsas_cmd_t *cmd);
 290 static void mptsas_check_task_mgt(mptsas_t *mpt,
 291     pMpi2SCSIManagementReply_t reply, mptsas_cmd_t *cmd);
 292 static int mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
 293     mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
 294     int *resid);
 295 
 296 static int mptsas_alloc_active_slots(mptsas_t *mpt, int flag);
 297 static void mptsas_free_active_slots(mptsas_t *mpt);
 298 static int mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 299 
 300 static void mptsas_restart_hba(mptsas_t *mpt);
 301 static void mptsas_restart_waitq(mptsas_t *mpt);
 302 
 303 static void mptsas_deliver_doneq_thread(mptsas_t *mpt);
 304 static void mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd);
 305 static void mptsas_doneq_mv(mptsas_t *mpt, uint64_t t);
 306 
 307 static mptsas_cmd_t *mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t);
 308 static void mptsas_doneq_empty(mptsas_t *mpt);
 309 static void mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg);
 310 
 311 static mptsas_cmd_t *mptsas_waitq_rm(mptsas_t *mpt);
 312 static void mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
 313 static mptsas_cmd_t *mptsas_tx_waitq_rm(mptsas_t *mpt);
 314 static void mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
 315 
 316 
 317 static void mptsas_start_watch_reset_delay();
 318 static void mptsas_setup_bus_reset_delay(mptsas_t *mpt);
 319 static void mptsas_watch_reset_delay(void *arg);
 320 static int mptsas_watch_reset_delay_subr(mptsas_t *mpt);
 321 
 322 /*
 323  * helper functions
 324  */
 325 static void mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 326 
 327 static dev_info_t *mptsas_find_child(dev_info_t *pdip, char *name);
 328 static dev_info_t *mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy);
 329 static dev_info_t *mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr,
 330     int lun);
 331 static mdi_pathinfo_t *mptsas_find_path_addr(dev_info_t *pdip, uint64_t sasaddr,
 332     int lun);
 333 static mdi_pathinfo_t *mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy);
 334 static dev_info_t *mptsas_find_smp_child(dev_info_t *pdip, char *str_wwn);
 335 
 336 static int mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy,
 337     int *lun);
 338 static int mptsas_parse_smp_name(char *name, uint64_t *wwn);
 339 
 340 static mptsas_target_t *mptsas_phy_to_tgt(mptsas_t *mpt,
 341     mptsas_phymask_t phymask, uint8_t phy);
 342 static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt,
 343     mptsas_phymask_t phymask, uint64_t wwid);
 344 static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt,
 345     mptsas_phymask_t phymask, uint64_t wwid);
 346 
 347 static int mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun,
 348     uchar_t page, unsigned char *buf, int len, int *rlen, uchar_t evpd);
 349 
 350 static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
 351     uint16_t *handle, mptsas_target_t **pptgt);
 352 static void mptsas_update_phymask(mptsas_t *mpt);
 353 
 354 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
 355     uint32_t *status, uint8_t cmd);
 356 static dev_info_t *mptsas_get_dip_from_dev(dev_t dev,
 357     mptsas_phymask_t *phymask);
 358 static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr,
 359     mptsas_phymask_t phymask);
 360 static int mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt);
 361 
 362 
 363 /*
 364  * Enumeration / DR functions
 365  */
 366 static void mptsas_config_all(dev_info_t *pdip);
 367 static int mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
 368     dev_info_t **lundip);
 369 static int mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
 370     dev_info_t **lundip);
 371 
 372 static int mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt);
 373 static int mptsas_offline_target(dev_info_t *pdip, char *name);
 374 
 375 static int mptsas_config_raid(dev_info_t *pdip, uint16_t target,
 376     dev_info_t **dip);
 377 
 378 static int mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt);
 379 static int mptsas_probe_lun(dev_info_t *pdip, int lun,
 380     dev_info_t **dip, mptsas_target_t *ptgt);
 381 
 382 static int mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
 383     dev_info_t **dip, mptsas_target_t *ptgt, int lun);
 384 
 385 static int mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
 386     char *guid, dev_info_t **dip, mptsas_target_t *ptgt, int lun);
 387 static int mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
 388     char *guid, dev_info_t **dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt,
 389     int lun);
 390 
 391 static void mptsas_offline_missed_luns(dev_info_t *pdip,
 392     uint16_t *repluns, int lun_cnt, mptsas_target_t *ptgt);
 393 static int mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
 394     mdi_pathinfo_t *rpip, uint_t flags);
 395 
 396 static int mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn,
 397     dev_info_t **smp_dip);
 398 static int mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 399     uint_t flags);
 400 
 401 static int mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data,
 402     int mode, int *rval);
 403 static int mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data,
 404     int mode, int *rval);
 405 static int mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data,
 406     int mode, int *rval);
 407 static void mptsas_record_event(void *args);
 408 static int mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data,
 409     int mode);
 410 
 411 mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t, uint64_t,
 412     uint32_t, mptsas_phymask_t, uint8_t);
 413 static mptsas_smp_t *mptsas_smp_alloc(mptsas_t *, mptsas_smp_t *);
 414 static int mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 415     dev_info_t **smp_dip);
 416 
 417 /*
 418  * Power management functions
 419  */
 420 static int mptsas_get_pci_cap(mptsas_t *mpt);
 421 static int mptsas_init_pm(mptsas_t *mpt);
 422 
 423 /*
 424  * MPT MSI tunable:
 425  *
 426  * By default MSI is enabled on all supported platforms.
 427  */
 428 boolean_t mptsas_enable_msi = B_TRUE;
 429 boolean_t mptsas_physical_bind_failed_page_83 = B_FALSE;
 430 
 431 static int mptsas_register_intrs(mptsas_t *);
 432 static void mptsas_unregister_intrs(mptsas_t *);
 433 static int mptsas_add_intrs(mptsas_t *, int);
 434 static void mptsas_rem_intrs(mptsas_t *);
 435 
 436 /*
 437  * FMA Prototypes
 438  */
 439 static void mptsas_fm_init(mptsas_t *mpt);
 440 static void mptsas_fm_fini(mptsas_t *mpt);
 441 static int mptsas_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *);
 442 
 443 extern pri_t minclsyspri, maxclsyspri;
 444 
 445 /*
 446  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).  It is
 447  * under this device that the paths to a physical device are created when
 448  * MPxIO is used.
 449  */
 450 extern dev_info_t       *scsi_vhci_dip;
 451 
 452 /*
 453  * Tunable timeout value for Inquiry VPD page 0x83
 454  * By default the value is 30 seconds.
 455  */
 456 int mptsas_inq83_retry_timeout = 30;
 457 
 458 /*
 459  * This is used to allocate memory for message frame storage, not for
 460  * data I/O DMA. All message frames must be stored in the first 4G of
 461  * physical memory.
 462  */
 463 ddi_dma_attr_t mptsas_dma_attrs = {
 464         DMA_ATTR_V0,    /* attribute layout version             */
 465         0x0ull,         /* address low - should be 0 (longlong) */
 466         0xffffffffull,  /* address high - 32-bit max range      */
 467         0x00ffffffull,  /* count max - max DMA object size      */
 468         4,              /* allocation alignment requirements    */
 469         0x78,           /* burstsizes - binary encoded values   */
 470         1,              /* minxfer - gran. of DMA engine        */
 471         0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 472         0xffffffffull,  /* max segment size (DMA boundary)      */
 473         MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 474         512,            /* granularity - device transfer size   */
 475         0               /* flags, set to 0                      */
 476 };
 477 
 478 /*
 479  * This is used for data I/O DMA memory allocation. (full 64-bit DMA
 480  * physical addresses are supported.)
 481  */
 482 ddi_dma_attr_t mptsas_dma_attrs64 = {
 483         DMA_ATTR_V0,    /* attribute layout version             */
 484         0x0ull,         /* address low - should be 0 (longlong) */
 485         0xffffffffffffffffull,  /* address high - 64-bit max    */
 486         0x00ffffffull,  /* count max - max DMA object size      */
 487         4,              /* allocation alignment requirements    */
 488         0x78,           /* burstsizes - binary encoded values   */
 489         1,              /* minxfer - gran. of DMA engine        */
 490         0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 491         0xffffffffull,  /* max segment size (DMA boundary)      */
 492         MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 493         512,            /* granularity - device transfer size   */
 494         DDI_DMA_RELAXED_ORDERING        /* flags, enable relaxed ordering */
 495 };
 496 
 497 ddi_device_acc_attr_t mptsas_dev_attr = {
 498         DDI_DEVICE_ATTR_V1,
 499         DDI_STRUCTURE_LE_ACC,
 500         DDI_STRICTORDER_ACC,
 501         DDI_DEFAULT_ACC
 502 };
 503 
 504 static struct cb_ops mptsas_cb_ops = {
 505         scsi_hba_open,          /* open */
 506         scsi_hba_close,         /* close */
 507         nodev,                  /* strategy */
 508         nodev,                  /* print */
 509         nodev,                  /* dump */
 510         nodev,                  /* read */
 511         nodev,                  /* write */
 512         mptsas_ioctl,           /* ioctl */
 513         nodev,                  /* devmap */
 514         nodev,                  /* mmap */
 515         nodev,                  /* segmap */
 516         nochpoll,               /* chpoll */
 517         ddi_prop_op,            /* cb_prop_op */
 518         NULL,                   /* streamtab */
 519         D_MP,                   /* cb_flag */
 520         CB_REV,                 /* rev */
 521         nodev,                  /* aread */
 522         nodev                   /* awrite */
 523 };
 524 
 525 static struct dev_ops mptsas_ops = {
 526         DEVO_REV,               /* devo_rev, */
 527         0,                      /* refcnt  */
 528         ddi_no_info,            /* info */
 529         nulldev,                /* identify */
 530         nulldev,                /* probe */
 531         mptsas_attach,          /* attach */
 532         mptsas_detach,          /* detach */
 533 #ifdef  __sparc
 534         mptsas_reset,
 535 #else
 536         nodev,                  /* reset */
 537 #endif  /* __sparc */
 538         &mptsas_cb_ops,             /* driver operations */
 539         NULL,                   /* bus operations */
 540         mptsas_power,           /* power management */
 541 #ifdef  __sparc
 542         ddi_quiesce_not_needed
 543 #else
 544         mptsas_quiesce          /* quiesce */
 545 #endif  /* __sparc */
 546 };
 547 
 548 
 549 #define MPTSAS_MOD_STRING "MPTSAS HBA Driver 00.00.00.24"
 550 
 551 static struct modldrv modldrv = {
 552         &mod_driverops,     /* Type of module. This one is a driver */
 553         MPTSAS_MOD_STRING, /* Name of the module. */
 554         &mptsas_ops,        /* driver ops */
 555 };
 556 
 557 static struct modlinkage modlinkage = {
 558         MODREV_1, &modldrv, NULL
 559 };
 560 #define TARGET_PROP     "target"
 561 #define LUN_PROP        "lun"
 562 #define LUN64_PROP      "lun64"
 563 #define SAS_PROP        "sas-mpt"
 564 #define MDI_GUID        "wwn"
 565 #define NDI_GUID        "guid"
 566 #define MPTSAS_DEV_GONE "mptsas_dev_gone"
 567 
 568 /*
 569  * Local static data
 570  */
 571 #if defined(MPTSAS_DEBUG)
 572 uint32_t mptsas_debug_flags = 0;
 573 #endif  /* defined(MPTSAS_DEBUG) */
 574 uint32_t mptsas_debug_resets = 0;
 575 
 576 static kmutex_t         mptsas_global_mutex;
 577 static void             *mptsas_state;          /* soft state ptr */
 578 static krwlock_t        mptsas_global_rwlock;
 579 
 580 static kmutex_t         mptsas_log_mutex;
 581 static char             mptsas_log_buf[256];
 582 _NOTE(MUTEX_PROTECTS_DATA(mptsas_log_mutex, mptsas_log_buf))
 583 
 584 static mptsas_t *mptsas_head, *mptsas_tail;
 585 static clock_t mptsas_scsi_watchdog_tick;
 586 static clock_t mptsas_tick;
 587 static timeout_id_t mptsas_reset_watch;
 588 static timeout_id_t mptsas_timeout_id;
 589 static int mptsas_timeouts_enabled = 0;
 590 /*
 591  * warlock directives
 592  */
 593 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt \
 594         mptsas_cmd NcrTableIndirect buf scsi_cdb scsi_status))
 595 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", smp_pkt))
 596 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
 597 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mptsas_tgt_private))
 598 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_hba_tran::tran_tgt_private))
 599 
 600 /*
 601  * SM - HBA statics
 602  */
 603 char    *mptsas_driver_rev = MPTSAS_MOD_STRING;
 604 
 605 #ifdef MPTSAS_DEBUG
 606 void debug_enter(char *);
 607 #endif
 608 
 609 /*
 610  * Notes:
 611  *      - scsi_hba_init(9F) initializes SCSI HBA modules
 612  *      - must call scsi_hba_fini(9F) if modload() fails
 613  */
 614 int
 615 _init(void)
 616 {
 617         int status;
 618         /* CONSTCOND */
 619         ASSERT(NO_COMPETING_THREADS);
 620 
 621         NDBG0(("_init"));
 622 
 623         status = ddi_soft_state_init(&mptsas_state, MPTSAS_SIZE,
 624             MPTSAS_INITIAL_SOFT_SPACE);
 625         if (status != 0) {
 626                 return (status);
 627         }
 628 
 629         if ((status = scsi_hba_init(&modlinkage)) != 0) {
 630                 ddi_soft_state_fini(&mptsas_state);
 631                 return (status);
 632         }
 633 
 634         mutex_init(&mptsas_global_mutex, NULL, MUTEX_DRIVER, NULL);
 635         rw_init(&mptsas_global_rwlock, NULL, RW_DRIVER, NULL);
 636         mutex_init(&mptsas_log_mutex, NULL, MUTEX_DRIVER, NULL);
 637 
 638         if ((status = mod_install(&modlinkage)) != 0) {
 639                 mutex_destroy(&mptsas_log_mutex);
 640                 rw_destroy(&mptsas_global_rwlock);
 641                 mutex_destroy(&mptsas_global_mutex);
 642                 ddi_soft_state_fini(&mptsas_state);
 643                 scsi_hba_fini(&modlinkage);
 644         }
 645 
 646         return (status);
 647 }
 648 
 649 /*
 650  * Notes:
 651  *      - scsi_hba_fini(9F) uninitializes SCSI HBA modules
 652  */
 653 int
 654 _fini(void)
 655 {
 656         int     status;
 657         /* CONSTCOND */
 658         ASSERT(NO_COMPETING_THREADS);
 659 
 660         NDBG0(("_fini"));
 661 
 662         if ((status = mod_remove(&modlinkage)) == 0) {
 663                 ddi_soft_state_fini(&mptsas_state);
 664                 scsi_hba_fini(&modlinkage);
 665                 mutex_destroy(&mptsas_global_mutex);
 666                 rw_destroy(&mptsas_global_rwlock);
 667                 mutex_destroy(&mptsas_log_mutex);
 668         }
 669         return (status);
 670 }
 671 
 672 /*
 673  * The loadable-module _info(9E) entry point
 674  */
 675 int
 676 _info(struct modinfo *modinfop)
 677 {
 678         /* CONSTCOND */
 679         ASSERT(NO_COMPETING_THREADS);
 680         NDBG0(("mptsas _info"));
 681 
 682         return (mod_info(&modlinkage, modinfop));
 683 }
 684 
 685 static int
 686 mptsas_target_eval_devhdl(const void *op, void *arg)
 687 {
 688         uint16_t dh = *(uint16_t *)arg;
 689         const mptsas_target_t *tp = op;
 690 
 691         return ((int)tp->m_devhdl - (int)dh);
 692 }
 693 
 694 static int
 695 mptsas_target_eval_slot(const void *op, void *arg)
 696 {
 697         mptsas_led_control_t *lcp = arg;
 698         const mptsas_target_t *tp = op;
 699 
 700         if (tp->m_enclosure != lcp->Enclosure)
 701                 return ((int)tp->m_enclosure - (int)lcp->Enclosure);
 702 
 703         return ((int)tp->m_slot_num - (int)lcp->Slot);
 704 }
 705 
 706 static int
 707 mptsas_target_eval_nowwn(const void *op, void *arg)
 708 {
 709         uint8_t phy = *(uint8_t *)arg;
 710         const mptsas_target_t *tp = op;
 711 
 712         if (tp->m_addr.mta_wwn != 0)
 713                 return (-1);
 714 
 715         return ((int)tp->m_phynum - (int)phy);
 716 }
 717 
 718 static int
 719 mptsas_smp_eval_devhdl(const void *op, void *arg)
 720 {
 721         uint16_t dh = *(uint16_t *)arg;
 722         const mptsas_smp_t *sp = op;
 723 
 724         return ((int)sp->m_devhdl - (int)dh);
 725 }
 726 
 727 static uint64_t
 728 mptsas_target_addr_hash(const void *tp)
 729 {
 730         const mptsas_target_addr_t *tap = tp;
 731 
 732         return ((tap->mta_wwn & 0xffffffffffffULL) |
 733             ((uint64_t)tap->mta_phymask << 48));
 734 }
 735 
 736 static int
 737 mptsas_target_addr_cmp(const void *a, const void *b)
 738 {
 739         const mptsas_target_addr_t *aap = a;
 740         const mptsas_target_addr_t *bap = b;
 741 
 742         if (aap->mta_wwn < bap->mta_wwn)
 743                 return (-1);
 744         if (aap->mta_wwn > bap->mta_wwn)
 745                 return (1);
 746         return ((int)bap->mta_phymask - (int)aap->mta_phymask);
 747 }
 748 
 749 static void
 750 mptsas_target_free(void *op)
 751 {
 752         kmem_free(op, sizeof (mptsas_target_t));
 753 }
 754 
 755 static void
 756 mptsas_smp_free(void *op)
 757 {
 758         kmem_free(op, sizeof (mptsas_smp_t));
 759 }
 760 
 761 static void
 762 mptsas_destroy_hashes(mptsas_t *mpt)
 763 {
 764         mptsas_target_t *tp;
 765         mptsas_smp_t *sp;
 766 
 767         for (tp = refhash_first(mpt->m_targets); tp != NULL;
 768             tp = refhash_next(mpt->m_targets, tp)) {
 769                 refhash_remove(mpt->m_targets, tp);
 770         }
 771         for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
 772             sp = refhash_next(mpt->m_smp_targets, sp)) {
 773                 refhash_remove(mpt->m_smp_targets, sp);
 774         }
 775         refhash_destroy(mpt->m_targets);
 776         refhash_destroy(mpt->m_smp_targets);
 777         mpt->m_targets = NULL;
 778         mpt->m_smp_targets = NULL;
 779 }
 780 
 781 static int
 782 mptsas_iport_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 783 {
 784         dev_info_t              *pdip;
 785         mptsas_t                *mpt;
 786         scsi_hba_tran_t         *hba_tran;
 787         char                    *iport = NULL;
 788         char                    phymask[MPTSAS_MAX_PHYS];
 789         mptsas_phymask_t        phy_mask = 0;
 790         int                     dynamic_port = 0;
 791         uint32_t                page_address;
 792         char                    initiator_wwnstr[MPTSAS_WWN_STRLEN];
 793         int                     rval = DDI_FAILURE;
 794         int                     i = 0;
 795         uint8_t                 numphys = 0;
 796         uint8_t                 phy_id;
 797         uint8_t                 phy_port = 0;
 798         uint16_t                attached_devhdl = 0;
 799         uint32_t                dev_info;
 800         uint64_t                attached_sas_wwn;
 801         uint16_t                dev_hdl;
 802         uint16_t                pdev_hdl;
 803         uint16_t                bay_num, enclosure;
 804         char                    attached_wwnstr[MPTSAS_WWN_STRLEN];
 805 
 806         /* CONSTCOND */
 807         ASSERT(NO_COMPETING_THREADS);
 808 
 809         switch (cmd) {
 810         case DDI_ATTACH:
 811                 break;
 812 
 813         case DDI_RESUME:
 814                 /*
 815                  * If this a scsi-iport node, nothing to do here.
 816                  */
 817                 return (DDI_SUCCESS);
 818 
 819         default:
 820                 return (DDI_FAILURE);
 821         }
 822 
 823         pdip = ddi_get_parent(dip);
 824 
 825         if ((hba_tran = ndi_flavorv_get(pdip, SCSA_FLAVOR_SCSI_DEVICE)) ==
 826             NULL) {
 827                 cmn_err(CE_WARN, "Failed attach iport because fail to "
 828                     "get tran vector for the HBA node");
 829                 return (DDI_FAILURE);
 830         }
 831 
 832         mpt = TRAN2MPT(hba_tran);
 833         ASSERT(mpt != NULL);
 834         if (mpt == NULL)
 835                 return (DDI_FAILURE);
 836 
 837         if ((hba_tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) ==
 838             NULL) {
 839                 mptsas_log(mpt, CE_WARN, "Failed attach iport because fail to "
 840                     "get tran vector for the iport node");
 841                 return (DDI_FAILURE);
 842         }
 843 
 844         /*
 845          * Overwrite parent's tran_hba_private to iport's tran vector
 846          */
 847         hba_tran->tran_hba_private = mpt;
 848 
 849         ddi_report_dev(dip);
 850 
 851         /*
 852          * Get SAS address for initiator port according dev_handle
 853          */
 854         iport = ddi_get_name_addr(dip);
 855         if (iport && strncmp(iport, "v0", 2) == 0) {
 856                 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 857                     MPTSAS_VIRTUAL_PORT, 1) !=
 858                     DDI_PROP_SUCCESS) {
 859                         (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
 860                             MPTSAS_VIRTUAL_PORT);
 861                         mptsas_log(mpt, CE_WARN, "mptsas virtual port "
 862                             "prop update failed");
 863                         return (DDI_FAILURE);
 864                 }
 865                 return (DDI_SUCCESS);
 866         }
 867 
 868         mutex_enter(&mpt->m_mutex);
 869         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 870                 bzero(phymask, sizeof (phymask));
 871                 (void) sprintf(phymask,
 872                     "%x", mpt->m_phy_info[i].phy_mask);
 873                 if (strcmp(phymask, iport) == 0) {
 874                         break;
 875                 }
 876         }
 877 
 878         if (i == MPTSAS_MAX_PHYS) {
 879                 mptsas_log(mpt, CE_WARN, "Failed attach port %s because port"
 880                     "seems not exist", iport);
 881                 mutex_exit(&mpt->m_mutex);
 882                 return (DDI_FAILURE);
 883         }
 884 
 885         phy_mask = mpt->m_phy_info[i].phy_mask;
 886 
 887         if (mpt->m_phy_info[i].port_flags & AUTO_PORT_CONFIGURATION)
 888                 dynamic_port = 1;
 889         else
 890                 dynamic_port = 0;
 891 
 892         /*
 893          * Update PHY info for smhba
 894          */
 895         if (mptsas_smhba_phy_init(mpt)) {
 896                 mutex_exit(&mpt->m_mutex);
 897                 mptsas_log(mpt, CE_WARN, "mptsas phy update "
 898                     "failed");
 899                 return (DDI_FAILURE);
 900         }
 901 
 902         mutex_exit(&mpt->m_mutex);
 903 
 904         numphys = 0;
 905         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 906                 if ((phy_mask >> i) & 0x01) {
 907                         numphys++;
 908                 }
 909         }
 910 
 911         bzero(initiator_wwnstr, sizeof (initiator_wwnstr));
 912         (void) sprintf(initiator_wwnstr, "w%016"PRIx64,
 913             mpt->un.m_base_wwid);
 914 
 915         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
 916             SCSI_ADDR_PROP_INITIATOR_PORT, initiator_wwnstr) !=
 917             DDI_PROP_SUCCESS) {
 918                 (void) ddi_prop_remove(DDI_DEV_T_NONE,
 919                     dip, SCSI_ADDR_PROP_INITIATOR_PORT);
 920                 mptsas_log(mpt, CE_WARN, "mptsas Initiator port "
 921                     "prop update failed");
 922                 return (DDI_FAILURE);
 923         }
 924         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 925             MPTSAS_NUM_PHYS, numphys) !=
 926             DDI_PROP_SUCCESS) {
 927                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, MPTSAS_NUM_PHYS);
 928                 return (DDI_FAILURE);
 929         }
 930 
 931         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 932             "phymask", phy_mask) !=
 933             DDI_PROP_SUCCESS) {
 934                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "phymask");
 935                 mptsas_log(mpt, CE_WARN, "mptsas phy mask "
 936                     "prop update failed");
 937                 return (DDI_FAILURE);
 938         }
 939 
 940         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 941             "dynamic-port", dynamic_port) !=
 942             DDI_PROP_SUCCESS) {
 943                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "dynamic-port");
 944                 mptsas_log(mpt, CE_WARN, "mptsas dynamic port "
 945                     "prop update failed");
 946                 return (DDI_FAILURE);
 947         }
 948         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 949             MPTSAS_VIRTUAL_PORT, 0) !=
 950             DDI_PROP_SUCCESS) {
 951                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
 952                     MPTSAS_VIRTUAL_PORT);
 953                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
 954                     "prop update failed");
 955                 return (DDI_FAILURE);
 956         }
 957         mptsas_smhba_set_all_phy_props(mpt, dip, numphys, phy_mask,
 958             &attached_devhdl);
 959 
 960         mutex_enter(&mpt->m_mutex);
 961         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
 962             MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)attached_devhdl;
 963         rval = mptsas_get_sas_device_page0(mpt, page_address, &dev_hdl,
 964             &attached_sas_wwn, &dev_info, &phy_port, &phy_id,
 965             &pdev_hdl, &bay_num, &enclosure);
 966         if (rval != DDI_SUCCESS) {
 967                 mptsas_log(mpt, CE_WARN,
 968                     "Failed to get device page0 for handle:%d",
 969                     attached_devhdl);
 970                 mutex_exit(&mpt->m_mutex);
 971                 return (DDI_FAILURE);
 972         }
 973 
 974         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 975                 bzero(phymask, sizeof (phymask));
 976                 (void) sprintf(phymask, "%x", mpt->m_phy_info[i].phy_mask);
 977                 if (strcmp(phymask, iport) == 0) {
 978                         (void) sprintf(&mpt->m_phy_info[i].smhba_info.path[0],
 979                             "%x",
 980                             mpt->m_phy_info[i].phy_mask);
 981                 }
 982         }
 983         mutex_exit(&mpt->m_mutex);
 984 
 985         bzero(attached_wwnstr, sizeof (attached_wwnstr));
 986         (void) sprintf(attached_wwnstr, "w%016"PRIx64,
 987             attached_sas_wwn);
 988         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
 989             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
 990             DDI_PROP_SUCCESS) {
 991                 (void) ddi_prop_remove(DDI_DEV_T_NONE,
 992                     dip, SCSI_ADDR_PROP_ATTACHED_PORT);
 993                 return (DDI_FAILURE);
 994         }
 995 
 996         /* Create kstats for each phy on this iport */
 997 
 998         mptsas_create_phy_stats(mpt, iport, dip);
 999 
1000         /*
1001          * register sas hba iport with mdi (MPxIO/vhci)
1002          */
1003         if (mdi_phci_register(MDI_HCI_CLASS_SCSI,
1004             dip, 0) == MDI_SUCCESS) {
1005                 mpt->m_mpxio_enable = TRUE;
1006         }
1007         return (DDI_SUCCESS);
1008 }
1009 
1010 /*
1011  * Notes:
1012  *      Set up all device state and allocate data structures,
1013  *      mutexes, condition variables, etc. for device operation.
1014  *      Add interrupts needed.
1015  *      Return DDI_SUCCESS if device is ready, else return DDI_FAILURE.
1016  */
1017 static int
1018 mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1019 {
1020         mptsas_t                *mpt = NULL;
1021         int                     instance, i, j;
1022         int                     doneq_thread_num;
1023         char                    intr_added = 0;
1024         char                    map_setup = 0;
1025         char                    config_setup = 0;
1026         char                    hba_attach_setup = 0;
1027         char                    smp_attach_setup = 0;
1028         char                    mutex_init_done = 0;
1029         char                    event_taskq_create = 0;
1030         char                    dr_taskq_create = 0;
1031         char                    doneq_thread_create = 0;
1032         scsi_hba_tran_t         *hba_tran;
1033         uint_t                  mem_bar = MEM_SPACE;
1034         int                     rval = DDI_FAILURE;
1035 
1036         /* CONSTCOND */
1037         ASSERT(NO_COMPETING_THREADS);
1038 
1039         if (scsi_hba_iport_unit_address(dip)) {
1040                 return (mptsas_iport_attach(dip, cmd));
1041         }
1042 
1043         switch (cmd) {
1044         case DDI_ATTACH:
1045                 break;
1046 
1047         case DDI_RESUME:
1048                 if ((hba_tran = ddi_get_driver_private(dip)) == NULL)
1049                         return (DDI_FAILURE);
1050 
1051                 mpt = TRAN2MPT(hba_tran);
1052 
1053                 if (!mpt) {
1054                         return (DDI_FAILURE);
1055                 }
1056 
1057                 /*
1058                  * Reset hardware and softc to "no outstanding commands"
1059                  * Note that a check condition can result on first command
1060                  * to a target.
1061                  */
1062                 mutex_enter(&mpt->m_mutex);
1063 
1064                 /*
1065                  * raise power.
1066                  */
1067                 if (mpt->m_options & MPTSAS_OPT_PM) {
1068                         mutex_exit(&mpt->m_mutex);
1069                         (void) pm_busy_component(dip, 0);
1070                         rval = pm_power_has_changed(dip, 0, PM_LEVEL_D0);
1071                         if (rval == DDI_SUCCESS) {
1072                                 mutex_enter(&mpt->m_mutex);
1073                         } else {
1074                                 /*
1075                                  * The pm_raise_power() call above failed,
1076                                  * and that can only occur if we were unable
1077                                  * to reset the hardware.  This is probably
1078                                  * due to unhealty hardware, and because
1079                                  * important filesystems(such as the root
1080                                  * filesystem) could be on the attached disks,
1081                                  * it would not be a good idea to continue,
1082                                  * as we won't be entirely certain we are
1083                                  * writing correct data.  So we panic() here
1084                                  * to not only prevent possible data corruption,
1085                                  * but to give developers or end users a hope
1086                                  * of identifying and correcting any problems.
1087                                  */
1088                                 fm_panic("mptsas could not reset hardware "
1089                                     "during resume");
1090                         }
1091                 }
1092 
1093                 mpt->m_suspended = 0;
1094 
1095                 /*
1096                  * Reinitialize ioc
1097                  */
1098                 mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1099                 if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
1100                         mutex_exit(&mpt->m_mutex);
1101                         if (mpt->m_options & MPTSAS_OPT_PM) {
1102                                 (void) pm_idle_component(dip, 0);
1103                         }
1104                         fm_panic("mptsas init chip fail during resume");
1105                 }
1106                 /*
1107                  * mptsas_update_driver_data needs interrupts so enable them
1108                  * first.
1109                  */
1110                 MPTSAS_ENABLE_INTR(mpt);
1111                 mptsas_update_driver_data(mpt);
1112 
1113                 /* start requests, if possible */
1114                 mptsas_restart_hba(mpt);
1115 
1116                 mutex_exit(&mpt->m_mutex);
1117 
1118                 /*
1119                  * Restart watch thread
1120                  */
1121                 mutex_enter(&mptsas_global_mutex);
1122                 if (mptsas_timeout_id == 0) {
1123                         mptsas_timeout_id = timeout(mptsas_watch, NULL,
1124                             mptsas_tick);
1125                         mptsas_timeouts_enabled = 1;
1126                 }
1127                 mutex_exit(&mptsas_global_mutex);
1128 
1129                 /* report idle status to pm framework */
1130                 if (mpt->m_options & MPTSAS_OPT_PM) {
1131                         (void) pm_idle_component(dip, 0);
1132                 }
1133 
1134                 return (DDI_SUCCESS);
1135 
1136         default:
1137                 return (DDI_FAILURE);
1138 
1139         }
1140 
1141         instance = ddi_get_instance(dip);
1142 
1143         /*
1144          * Allocate softc information.
1145          */
1146         if (ddi_soft_state_zalloc(mptsas_state, instance) != DDI_SUCCESS) {
1147                 mptsas_log(NULL, CE_WARN,
1148                     "mptsas%d: cannot allocate soft state", instance);
1149                 goto fail;
1150         }
1151 
1152         mpt = ddi_get_soft_state(mptsas_state, instance);
1153 
1154         if (mpt == NULL) {
1155                 mptsas_log(NULL, CE_WARN,
1156                     "mptsas%d: cannot get soft state", instance);
1157                 goto fail;
1158         }
1159 
1160         /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
1161         scsi_size_clean(dip);
1162 
1163         mpt->m_dip = dip;
1164         mpt->m_instance = instance;
1165 
1166         /* Make a per-instance copy of the structures */
1167         mpt->m_io_dma_attr = mptsas_dma_attrs64;
1168         mpt->m_msg_dma_attr = mptsas_dma_attrs;
1169         mpt->m_reg_acc_attr = mptsas_dev_attr;
1170         mpt->m_dev_acc_attr = mptsas_dev_attr;
1171 
1172         /*
1173          * Initialize FMA
1174          */
1175         mpt->m_fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, mpt->m_dip,
1176             DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
1177             DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
1178             DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
1179 
1180         mptsas_fm_init(mpt);
1181 
1182         if (mptsas_alloc_handshake_msg(mpt,
1183             sizeof (Mpi2SCSITaskManagementRequest_t)) == DDI_FAILURE) {
1184                 mptsas_log(mpt, CE_WARN, "cannot initialize handshake msg.");
1185                 goto fail;
1186         }
1187 
1188         /*
1189          * Setup configuration space
1190          */
1191         if (mptsas_config_space_init(mpt) == FALSE) {
1192                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init failed");
1193                 goto fail;
1194         }
1195         config_setup++;
1196 
1197         if (ddi_regs_map_setup(dip, mem_bar, (caddr_t *)&mpt->m_reg,
1198             0, 0, &mpt->m_reg_acc_attr, &mpt->m_datap) != DDI_SUCCESS) {
1199                 mptsas_log(mpt, CE_WARN, "map setup failed");
1200                 goto fail;
1201         }
1202         map_setup++;
1203 
1204         /*
1205          * A taskq is created for dealing with the event handler
1206          */
1207         if ((mpt->m_event_taskq = ddi_taskq_create(dip, "mptsas_event_taskq",
1208             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1209                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create failed");
1210                 goto fail;
1211         }
1212         event_taskq_create++;
1213 
1214         /*
1215          * A taskq is created for dealing with dr events
1216          */
1217         if ((mpt->m_dr_taskq = ddi_taskq_create(dip,
1218             "mptsas_dr_taskq",
1219             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1220                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create for discovery "
1221                     "failed");
1222                 goto fail;
1223         }
1224         dr_taskq_create++;
1225 
1226         mpt->m_doneq_thread_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1227             0, "mptsas_doneq_thread_threshold_prop", 10);
1228         mpt->m_doneq_length_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1229             0, "mptsas_doneq_length_threshold_prop", 8);
1230         mpt->m_doneq_thread_n = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1231             0, "mptsas_doneq_thread_n_prop", 8);
1232 
1233         if (mpt->m_doneq_thread_n) {
1234                 cv_init(&mpt->m_doneq_thread_cv, NULL, CV_DRIVER, NULL);
1235                 mutex_init(&mpt->m_doneq_mutex, NULL, MUTEX_DRIVER, NULL);
1236 
1237                 mutex_enter(&mpt->m_doneq_mutex);
1238                 mpt->m_doneq_thread_id =
1239                     kmem_zalloc(sizeof (mptsas_doneq_thread_list_t)
1240                     * mpt->m_doneq_thread_n, KM_SLEEP);
1241 
1242                 for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1243                         cv_init(&mpt->m_doneq_thread_id[j].cv, NULL,
1244                             CV_DRIVER, NULL);
1245                         mutex_init(&mpt->m_doneq_thread_id[j].mutex, NULL,
1246                             MUTEX_DRIVER, NULL);
1247                         mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1248                         mpt->m_doneq_thread_id[j].flag |=
1249                             MPTSAS_DONEQ_THREAD_ACTIVE;
1250                         mpt->m_doneq_thread_id[j].arg.mpt = mpt;
1251                         mpt->m_doneq_thread_id[j].arg.t = j;
1252                         mpt->m_doneq_thread_id[j].threadp =
1253                             thread_create(NULL, 0, mptsas_doneq_thread,
1254                             &mpt->m_doneq_thread_id[j].arg,
1255                             0, &p0, TS_RUN, minclsyspri);
1256                         mpt->m_doneq_thread_id[j].donetail =
1257                             &mpt->m_doneq_thread_id[j].doneq;
1258                         mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1259                 }
1260                 mutex_exit(&mpt->m_doneq_mutex);
1261                 doneq_thread_create++;
1262         }
1263 
1264         /* Initialize mutex used in interrupt handler */
1265         mutex_init(&mpt->m_mutex, NULL, MUTEX_DRIVER,
1266             DDI_INTR_PRI(mpt->m_intr_pri));
1267         mutex_init(&mpt->m_passthru_mutex, NULL, MUTEX_DRIVER, NULL);
1268         mutex_init(&mpt->m_tx_waitq_mutex, NULL, MUTEX_DRIVER,
1269             DDI_INTR_PRI(mpt->m_intr_pri));
1270         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1271                 mutex_init(&mpt->m_phy_info[i].smhba_info.phy_mutex,
1272                     NULL, MUTEX_DRIVER,
1273                     DDI_INTR_PRI(mpt->m_intr_pri));
1274         }
1275 
1276         cv_init(&mpt->m_cv, NULL, CV_DRIVER, NULL);
1277         cv_init(&mpt->m_passthru_cv, NULL, CV_DRIVER, NULL);
1278         cv_init(&mpt->m_fw_cv, NULL, CV_DRIVER, NULL);
1279         cv_init(&mpt->m_config_cv, NULL, CV_DRIVER, NULL);
1280         cv_init(&mpt->m_fw_diag_cv, NULL, CV_DRIVER, NULL);
1281         mutex_init_done++;
1282 
1283         /*
1284          * Disable hardware interrupt since we're not ready to
1285          * handle it yet.
1286          */
1287         MPTSAS_DISABLE_INTR(mpt);
1288         if (mptsas_register_intrs(mpt) == FALSE)
1289                 goto fail;
1290         intr_added++;
1291 
1292         mutex_enter(&mpt->m_mutex);
1293         /*
1294          * Initialize power management component
1295          */
1296         if (mpt->m_options & MPTSAS_OPT_PM) {
1297                 if (mptsas_init_pm(mpt)) {
1298                         mutex_exit(&mpt->m_mutex);
1299                         mptsas_log(mpt, CE_WARN, "mptsas pm initialization "
1300                             "failed");
1301                         goto fail;
1302                 }
1303         }
1304 
1305         /*
1306          * Initialize chip using Message Unit Reset, if allowed
1307          */
1308         mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1309         if (mptsas_init_chip(mpt, TRUE) == DDI_FAILURE) {
1310                 mutex_exit(&mpt->m_mutex);
1311                 mptsas_log(mpt, CE_WARN, "mptsas chip initialization failed");
1312                 goto fail;
1313         }
1314 
1315         /*
1316          * Fill in the phy_info structure and get the base WWID
1317          */
1318         if (mptsas_get_manufacture_page5(mpt) == DDI_FAILURE) {
1319                 mptsas_log(mpt, CE_WARN,
1320                     "mptsas_get_manufacture_page5 failed!");
1321                 goto fail;
1322         }
1323 
1324         if (mptsas_get_sas_io_unit_page_hndshk(mpt)) {
1325                 mptsas_log(mpt, CE_WARN,
1326                     "mptsas_get_sas_io_unit_page_hndshk failed!");
1327                 goto fail;
1328         }
1329 
1330         if (mptsas_get_manufacture_page0(mpt) == DDI_FAILURE) {
1331                 mptsas_log(mpt, CE_WARN,
1332                     "mptsas_get_manufacture_page0 failed!");
1333                 goto fail;
1334         }
1335 
1336         mutex_exit(&mpt->m_mutex);
1337 
1338         /*
1339          * Register the iport for multiple port HBA
1340          */
1341         mptsas_iport_register(mpt);
1342 
1343         /*
1344          * initialize SCSI HBA transport structure
1345          */
1346         if (mptsas_hba_setup(mpt) == FALSE)
1347                 goto fail;
1348         hba_attach_setup++;
1349 
1350         if (mptsas_smp_setup(mpt) == FALSE)
1351                 goto fail;
1352         smp_attach_setup++;
1353 
1354         if (mptsas_cache_create(mpt) == FALSE)
1355                 goto fail;
1356 
1357         mpt->m_scsi_reset_delay      = ddi_prop_get_int(DDI_DEV_T_ANY,
1358             dip, 0, "scsi-reset-delay", SCSI_DEFAULT_RESET_DELAY);
1359         if (mpt->m_scsi_reset_delay == 0) {
1360                 mptsas_log(mpt, CE_NOTE,
1361                     "scsi_reset_delay of 0 is not recommended,"
1362                     " resetting to SCSI_DEFAULT_RESET_DELAY\n");
1363                 mpt->m_scsi_reset_delay = SCSI_DEFAULT_RESET_DELAY;
1364         }
1365 
1366         /*
1367          * Initialize the wait and done FIFO queue
1368          */
1369         mpt->m_donetail = &mpt->m_doneq;
1370         mpt->m_waitqtail = &mpt->m_waitq;
1371         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
1372         mpt->m_tx_draining = 0;
1373 
1374         /*
1375          * ioc cmd queue initialize
1376          */
1377         mpt->m_ioc_event_cmdtail = &mpt->m_ioc_event_cmdq;
1378         mpt->m_dev_handle = 0xFFFF;
1379 
1380         MPTSAS_ENABLE_INTR(mpt);
1381 
1382         /*
1383          * enable event notification
1384          */
1385         mutex_enter(&mpt->m_mutex);
1386         if (mptsas_ioc_enable_event_notification(mpt)) {
1387                 mutex_exit(&mpt->m_mutex);
1388                 goto fail;
1389         }
1390         mutex_exit(&mpt->m_mutex);
1391 
1392         /*
1393          * Initialize PHY info for smhba
1394          */
1395         if (mptsas_smhba_setup(mpt)) {
1396                 mptsas_log(mpt, CE_WARN, "mptsas phy initialization "
1397                     "failed");
1398                 goto fail;
1399         }
1400 
1401         /* Check all dma handles allocated in attach */
1402         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl)
1403             != DDI_SUCCESS) ||
1404             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl)
1405             != DDI_SUCCESS) ||
1406             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl)
1407             != DDI_SUCCESS) ||
1408             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl)
1409             != DDI_SUCCESS) ||
1410             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl)
1411             != DDI_SUCCESS)) {
1412                 goto fail;
1413         }
1414 
1415         /* Check all acc handles allocated in attach */
1416         if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
1417             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl)
1418             != DDI_SUCCESS) ||
1419             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl)
1420             != DDI_SUCCESS) ||
1421             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl)
1422             != DDI_SUCCESS) ||
1423             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl)
1424             != DDI_SUCCESS) ||
1425             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl)
1426             != DDI_SUCCESS) ||
1427             (mptsas_check_acc_handle(mpt->m_config_handle)
1428             != DDI_SUCCESS)) {
1429                 goto fail;
1430         }
1431 
1432         /*
1433          * After this point, we are not going to fail the attach.
1434          */
1435         /*
1436          * used for mptsas_watch
1437          */
1438         mptsas_list_add(mpt);
1439 
1440         mutex_enter(&mptsas_global_mutex);
1441         if (mptsas_timeouts_enabled == 0) {
1442                 mptsas_scsi_watchdog_tick = ddi_prop_get_int(DDI_DEV_T_ANY,
1443                     dip, 0, "scsi-watchdog-tick", DEFAULT_WD_TICK);
1444 
1445                 mptsas_tick = mptsas_scsi_watchdog_tick *
1446                     drv_usectohz((clock_t)1000000);
1447 
1448                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
1449                 mptsas_timeouts_enabled = 1;
1450         }
1451         mutex_exit(&mptsas_global_mutex);
1452 
1453         /* Print message of HBA present */
1454         ddi_report_dev(dip);
1455 
1456         /* report idle status to pm framework */
1457         if (mpt->m_options & MPTSAS_OPT_PM) {
1458                 (void) pm_idle_component(dip, 0);
1459         }
1460 
1461         return (DDI_SUCCESS);
1462 
1463 fail:
1464         mptsas_log(mpt, CE_WARN, "attach failed");
1465         mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
1466         ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
1467         if (mpt) {
1468                 mutex_enter(&mptsas_global_mutex);
1469 
1470                 if (mptsas_timeout_id && (mptsas_head == NULL)) {
1471                         timeout_id_t tid = mptsas_timeout_id;
1472                         mptsas_timeouts_enabled = 0;
1473                         mptsas_timeout_id = 0;
1474                         mutex_exit(&mptsas_global_mutex);
1475                         (void) untimeout(tid);
1476                         mutex_enter(&mptsas_global_mutex);
1477                 }
1478                 mutex_exit(&mptsas_global_mutex);
1479                 /* deallocate in reverse order */
1480                 mptsas_cache_destroy(mpt);
1481 
1482                 if (smp_attach_setup) {
1483                         mptsas_smp_teardown(mpt);
1484                 }
1485                 if (hba_attach_setup) {
1486                         mptsas_hba_teardown(mpt);
1487                 }
1488 
1489                 if (mpt->m_targets)
1490                         refhash_destroy(mpt->m_targets);
1491                 if (mpt->m_smp_targets)
1492                         refhash_destroy(mpt->m_smp_targets);
1493 
1494                 if (mpt->m_active) {
1495                         mptsas_free_active_slots(mpt);
1496                 }
1497                 if (intr_added) {
1498                         mptsas_unregister_intrs(mpt);
1499                 }
1500 
1501                 if (doneq_thread_create) {
1502                         mutex_enter(&mpt->m_doneq_mutex);
1503                         doneq_thread_num = mpt->m_doneq_thread_n;
1504                         for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1505                                 mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1506                                 mpt->m_doneq_thread_id[j].flag &=
1507                                     (~MPTSAS_DONEQ_THREAD_ACTIVE);
1508                                 cv_signal(&mpt->m_doneq_thread_id[j].cv);
1509                                 mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1510                         }
1511                         while (mpt->m_doneq_thread_n) {
1512                                 cv_wait(&mpt->m_doneq_thread_cv,
1513                                     &mpt->m_doneq_mutex);
1514                         }
1515                         for (j = 0; j < doneq_thread_num; j++) {
1516                                 cv_destroy(&mpt->m_doneq_thread_id[j].cv);
1517                                 mutex_destroy(&mpt->m_doneq_thread_id[j].mutex);
1518                         }
1519                         kmem_free(mpt->m_doneq_thread_id,
1520                             sizeof (mptsas_doneq_thread_list_t)
1521                             * doneq_thread_num);
1522                         mutex_exit(&mpt->m_doneq_mutex);
1523                         cv_destroy(&mpt->m_doneq_thread_cv);
1524                         mutex_destroy(&mpt->m_doneq_mutex);
1525                 }
1526                 if (event_taskq_create) {
1527                         ddi_taskq_destroy(mpt->m_event_taskq);
1528                 }
1529                 if (dr_taskq_create) {
1530                         ddi_taskq_destroy(mpt->m_dr_taskq);
1531                 }
1532                 if (mutex_init_done) {
1533                         mutex_destroy(&mpt->m_tx_waitq_mutex);
1534                         mutex_destroy(&mpt->m_passthru_mutex);
1535                         mutex_destroy(&mpt->m_mutex);
1536                         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1537                                 mutex_destroy(
1538                                     &mpt->m_phy_info[i].smhba_info.phy_mutex);
1539                         }
1540                         cv_destroy(&mpt->m_cv);
1541                         cv_destroy(&mpt->m_passthru_cv);
1542                         cv_destroy(&mpt->m_fw_cv);
1543                         cv_destroy(&mpt->m_config_cv);
1544                         cv_destroy(&mpt->m_fw_diag_cv);
1545                 }
1546 
1547                 if (map_setup) {
1548                         mptsas_cfg_fini(mpt);
1549                 }
1550                 if (config_setup) {
1551                         mptsas_config_space_fini(mpt);
1552                 }
1553                 mptsas_free_handshake_msg(mpt);
1554                 mptsas_hba_fini(mpt);
1555 
1556                 mptsas_fm_fini(mpt);
1557                 ddi_soft_state_free(mptsas_state, instance);
1558                 ddi_prop_remove_all(dip);
1559         }
1560         return (DDI_FAILURE);
1561 }
1562 
1563 static int
1564 mptsas_suspend(dev_info_t *devi)
1565 {
1566         mptsas_t        *mpt, *g;
1567         scsi_hba_tran_t *tran;
1568 
1569         if (scsi_hba_iport_unit_address(devi)) {
1570                 return (DDI_SUCCESS);
1571         }
1572 
1573         if ((tran = ddi_get_driver_private(devi)) == NULL)
1574                 return (DDI_SUCCESS);
1575 
1576         mpt = TRAN2MPT(tran);
1577         if (!mpt) {
1578                 return (DDI_SUCCESS);
1579         }
1580 
1581         mutex_enter(&mpt->m_mutex);
1582 
1583         if (mpt->m_suspended++) {
1584                 mutex_exit(&mpt->m_mutex);
1585                 return (DDI_SUCCESS);
1586         }
1587 
1588         /*
1589          * Cancel timeout threads for this mpt
1590          */
1591         if (mpt->m_quiesce_timeid) {
1592                 timeout_id_t tid = mpt->m_quiesce_timeid;
1593                 mpt->m_quiesce_timeid = 0;
1594                 mutex_exit(&mpt->m_mutex);
1595                 (void) untimeout(tid);
1596                 mutex_enter(&mpt->m_mutex);
1597         }
1598 
1599         if (mpt->m_restart_cmd_timeid) {
1600                 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1601                 mpt->m_restart_cmd_timeid = 0;
1602                 mutex_exit(&mpt->m_mutex);
1603                 (void) untimeout(tid);
1604                 mutex_enter(&mpt->m_mutex);
1605         }
1606 
1607         mutex_exit(&mpt->m_mutex);
1608 
1609         (void) pm_idle_component(mpt->m_dip, 0);
1610 
1611         /*
1612          * Cancel watch threads if all mpts suspended
1613          */
1614         rw_enter(&mptsas_global_rwlock, RW_WRITER);
1615         for (g = mptsas_head; g != NULL; g = g->m_next) {
1616                 if (!g->m_suspended)
1617                         break;
1618         }
1619         rw_exit(&mptsas_global_rwlock);
1620 
1621         mutex_enter(&mptsas_global_mutex);
1622         if (g == NULL) {
1623                 timeout_id_t tid;
1624 
1625                 mptsas_timeouts_enabled = 0;
1626                 if (mptsas_timeout_id) {
1627                         tid = mptsas_timeout_id;
1628                         mptsas_timeout_id = 0;
1629                         mutex_exit(&mptsas_global_mutex);
1630                         (void) untimeout(tid);
1631                         mutex_enter(&mptsas_global_mutex);
1632                 }
1633                 if (mptsas_reset_watch) {
1634                         tid = mptsas_reset_watch;
1635                         mptsas_reset_watch = 0;
1636                         mutex_exit(&mptsas_global_mutex);
1637                         (void) untimeout(tid);
1638                         mutex_enter(&mptsas_global_mutex);
1639                 }
1640         }
1641         mutex_exit(&mptsas_global_mutex);
1642 
1643         mutex_enter(&mpt->m_mutex);
1644 
1645         /*
1646          * If this mpt is not in full power(PM_LEVEL_D0), just return.
1647          */
1648         if ((mpt->m_options & MPTSAS_OPT_PM) &&
1649             (mpt->m_power_level != PM_LEVEL_D0)) {
1650                 mutex_exit(&mpt->m_mutex);
1651                 return (DDI_SUCCESS);
1652         }
1653 
1654         /* Disable HBA interrupts in hardware */
1655         MPTSAS_DISABLE_INTR(mpt);
1656         /*
1657          * Send RAID action system shutdown to sync IR
1658          */
1659         mptsas_raid_action_system_shutdown(mpt);
1660 
1661         mutex_exit(&mpt->m_mutex);
1662 
1663         /* drain the taskq */
1664         ddi_taskq_wait(mpt->m_event_taskq);
1665         ddi_taskq_wait(mpt->m_dr_taskq);
1666 
1667         return (DDI_SUCCESS);
1668 }
1669 
1670 #ifdef  __sparc
1671 /*ARGSUSED*/
1672 static int
1673 mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd)
1674 {
1675         mptsas_t        *mpt;
1676         scsi_hba_tran_t *tran;
1677 
1678         /*
1679          * If this call is for iport, just return.
1680          */
1681         if (scsi_hba_iport_unit_address(devi))
1682                 return (DDI_SUCCESS);
1683 
1684         if ((tran = ddi_get_driver_private(devi)) == NULL)
1685                 return (DDI_SUCCESS);
1686 
1687         if ((mpt = TRAN2MPT(tran)) == NULL)
1688                 return (DDI_SUCCESS);
1689 
1690         /*
1691          * Send RAID action system shutdown to sync IR.  Disable HBA
1692          * interrupts in hardware first.
1693          */
1694         MPTSAS_DISABLE_INTR(mpt);
1695         mptsas_raid_action_system_shutdown(mpt);
1696 
1697         return (DDI_SUCCESS);
1698 }
1699 #else /* __sparc */
1700 /*
1701  * quiesce(9E) entry point.
1702  *
1703  * This function is called when the system is single-threaded at high
1704  * PIL with preemption disabled. Therefore, this function must not be
1705  * blocked.
1706  *
1707  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1708  * DDI_FAILURE indicates an error condition and should almost never happen.
1709  */
1710 static int
1711 mptsas_quiesce(dev_info_t *devi)
1712 {
1713         mptsas_t        *mpt;
1714         scsi_hba_tran_t *tran;
1715 
1716         /*
1717          * If this call is for iport, just return.
1718          */
1719         if (scsi_hba_iport_unit_address(devi))
1720                 return (DDI_SUCCESS);
1721 
1722         if ((tran = ddi_get_driver_private(devi)) == NULL)
1723                 return (DDI_SUCCESS);
1724 
1725         if ((mpt = TRAN2MPT(tran)) == NULL)
1726                 return (DDI_SUCCESS);
1727 
1728         /* Disable HBA interrupts in hardware */
1729         MPTSAS_DISABLE_INTR(mpt);
1730         /* Send RAID action system shutdonw to sync IR */
1731         mptsas_raid_action_system_shutdown(mpt);
1732 
1733         return (DDI_SUCCESS);
1734 }
1735 #endif  /* __sparc */
1736 
1737 /*
1738  * detach(9E).  Remove all device allocations and system resources;
1739  * disable device interrupts.
1740  * Return DDI_SUCCESS if done; DDI_FAILURE if there's a problem.
1741  */
1742 static int
1743 mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1744 {
1745         /* CONSTCOND */
1746         ASSERT(NO_COMPETING_THREADS);
1747         NDBG0(("mptsas_detach: dip=0x%p cmd=0x%p", (void *)devi, (void *)cmd));
1748 
1749         switch (cmd) {
1750         case DDI_DETACH:
1751                 return (mptsas_do_detach(devi));
1752 
1753         case DDI_SUSPEND:
1754                 return (mptsas_suspend(devi));
1755 
1756         default:
1757                 return (DDI_FAILURE);
1758         }
1759         /* NOTREACHED */
1760 }
1761 
1762 static int
1763 mptsas_do_detach(dev_info_t *dip)
1764 {
1765         mptsas_t        *mpt;
1766         scsi_hba_tran_t *tran;
1767         int             circ = 0;
1768         int             circ1 = 0;
1769         mdi_pathinfo_t  *pip = NULL;
1770         int             i;
1771         int             doneq_thread_num = 0;
1772 
1773         NDBG0(("mptsas_do_detach: dip=0x%p", (void *)dip));
1774 
1775         if ((tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) == NULL)
1776                 return (DDI_FAILURE);
1777 
1778         mpt = TRAN2MPT(tran);
1779         if (!mpt) {
1780                 return (DDI_FAILURE);
1781         }
1782         /*
1783          * Still have pathinfo child, should not detach mpt driver
1784          */
1785         if (scsi_hba_iport_unit_address(dip)) {
1786                 if (mpt->m_mpxio_enable) {
1787                         /*
1788                          * MPxIO enabled for the iport
1789                          */
1790                         ndi_devi_enter(scsi_vhci_dip, &circ1);
1791                         ndi_devi_enter(dip, &circ);
1792                         while (pip = mdi_get_next_client_path(dip, NULL)) {
1793                                 if (mdi_pi_free(pip, 0) == MDI_SUCCESS) {
1794                                         continue;
1795                                 }
1796                                 ndi_devi_exit(dip, circ);
1797                                 ndi_devi_exit(scsi_vhci_dip, circ1);
1798                                 NDBG12(("detach failed because of "
1799                                     "outstanding path info"));
1800                                 return (DDI_FAILURE);
1801                         }
1802                         ndi_devi_exit(dip, circ);
1803                         ndi_devi_exit(scsi_vhci_dip, circ1);
1804                         (void) mdi_phci_unregister(dip, 0);
1805                 }
1806 
1807                 ddi_prop_remove_all(dip);
1808 
1809                 return (DDI_SUCCESS);
1810         }
1811 
1812         /* Make sure power level is D0 before accessing registers */
1813         if (mpt->m_options & MPTSAS_OPT_PM) {
1814                 (void) pm_busy_component(dip, 0);
1815                 if (mpt->m_power_level != PM_LEVEL_D0) {
1816                         if (pm_raise_power(dip, 0, PM_LEVEL_D0) !=
1817                             DDI_SUCCESS) {
1818                                 mptsas_log(mpt, CE_WARN,
1819                                     "mptsas%d: Raise power request failed.",
1820                                     mpt->m_instance);
1821                                 (void) pm_idle_component(dip, 0);
1822                                 return (DDI_FAILURE);
1823                         }
1824                 }
1825         }
1826 
1827         /*
1828          * Send RAID action system shutdown to sync IR.  After action, send a
1829          * Message Unit Reset. Since after that DMA resource will be freed,
1830          * set ioc to READY state will avoid HBA initiated DMA operation.
1831          */
1832         mutex_enter(&mpt->m_mutex);
1833         MPTSAS_DISABLE_INTR(mpt);
1834         mptsas_raid_action_system_shutdown(mpt);
1835         mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1836         (void) mptsas_ioc_reset(mpt, FALSE);
1837         mutex_exit(&mpt->m_mutex);
1838         mptsas_rem_intrs(mpt);
1839         ddi_taskq_destroy(mpt->m_event_taskq);
1840         ddi_taskq_destroy(mpt->m_dr_taskq);
1841 
1842         if (mpt->m_doneq_thread_n) {
1843                 mutex_enter(&mpt->m_doneq_mutex);
1844                 doneq_thread_num = mpt->m_doneq_thread_n;
1845                 for (i = 0; i < mpt->m_doneq_thread_n; i++) {
1846                         mutex_enter(&mpt->m_doneq_thread_id[i].mutex);
1847                         mpt->m_doneq_thread_id[i].flag &=
1848                             (~MPTSAS_DONEQ_THREAD_ACTIVE);
1849                         cv_signal(&mpt->m_doneq_thread_id[i].cv);
1850                         mutex_exit(&mpt->m_doneq_thread_id[i].mutex);
1851                 }
1852                 while (mpt->m_doneq_thread_n) {
1853                         cv_wait(&mpt->m_doneq_thread_cv,
1854                             &mpt->m_doneq_mutex);
1855                 }
1856                 for (i = 0;  i < doneq_thread_num; i++) {
1857                         cv_destroy(&mpt->m_doneq_thread_id[i].cv);
1858                         mutex_destroy(&mpt->m_doneq_thread_id[i].mutex);
1859                 }
1860                 kmem_free(mpt->m_doneq_thread_id,
1861                     sizeof (mptsas_doneq_thread_list_t)
1862                     * doneq_thread_num);
1863                 mutex_exit(&mpt->m_doneq_mutex);
1864                 cv_destroy(&mpt->m_doneq_thread_cv);
1865                 mutex_destroy(&mpt->m_doneq_mutex);
1866         }
1867 
1868         scsi_hba_reset_notify_tear_down(mpt->m_reset_notify_listf);
1869 
1870         mptsas_list_del(mpt);
1871 
1872         /*
1873          * Cancel timeout threads for this mpt
1874          */
1875         mutex_enter(&mpt->m_mutex);
1876         if (mpt->m_quiesce_timeid) {
1877                 timeout_id_t tid = mpt->m_quiesce_timeid;
1878                 mpt->m_quiesce_timeid = 0;
1879                 mutex_exit(&mpt->m_mutex);
1880                 (void) untimeout(tid);
1881                 mutex_enter(&mpt->m_mutex);
1882         }
1883 
1884         if (mpt->m_restart_cmd_timeid) {
1885                 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1886                 mpt->m_restart_cmd_timeid = 0;
1887                 mutex_exit(&mpt->m_mutex);
1888                 (void) untimeout(tid);
1889                 mutex_enter(&mpt->m_mutex);
1890         }
1891 
1892         mutex_exit(&mpt->m_mutex);
1893 
1894         /*
1895          * last mpt? ... if active, CANCEL watch threads.
1896          */
1897         mutex_enter(&mptsas_global_mutex);
1898         if (mptsas_head == NULL) {
1899                 timeout_id_t tid;
1900                 /*
1901                  * Clear mptsas_timeouts_enable so that the watch thread
1902                  * gets restarted on DDI_ATTACH
1903                  */
1904                 mptsas_timeouts_enabled = 0;
1905                 if (mptsas_timeout_id) {
1906                         tid = mptsas_timeout_id;
1907                         mptsas_timeout_id = 0;
1908                         mutex_exit(&mptsas_global_mutex);
1909                         (void) untimeout(tid);
1910                         mutex_enter(&mptsas_global_mutex);
1911                 }
1912                 if (mptsas_reset_watch) {
1913                         tid = mptsas_reset_watch;
1914                         mptsas_reset_watch = 0;
1915                         mutex_exit(&mptsas_global_mutex);
1916                         (void) untimeout(tid);
1917                         mutex_enter(&mptsas_global_mutex);
1918                 }
1919         }
1920         mutex_exit(&mptsas_global_mutex);
1921 
1922         /*
1923          * Delete Phy stats
1924          */
1925         mptsas_destroy_phy_stats(mpt);
1926 
1927         mptsas_destroy_hashes(mpt);
1928 
1929         /*
1930          * Delete nt_active.
1931          */
1932         mutex_enter(&mpt->m_mutex);
1933         mptsas_free_active_slots(mpt);
1934         mutex_exit(&mpt->m_mutex);
1935 
1936         /* deallocate everything that was allocated in mptsas_attach */
1937         mptsas_cache_destroy(mpt);
1938 
1939         mptsas_hba_fini(mpt);
1940         mptsas_cfg_fini(mpt);
1941 
1942         /* Lower the power informing PM Framework */
1943         if (mpt->m_options & MPTSAS_OPT_PM) {
1944                 if (pm_lower_power(dip, 0, PM_LEVEL_D3) != DDI_SUCCESS)
1945                         mptsas_log(mpt, CE_WARN,
1946                             "!mptsas%d: Lower power request failed "
1947                             "during detach, ignoring.",
1948                             mpt->m_instance);
1949         }
1950 
1951         mutex_destroy(&mpt->m_tx_waitq_mutex);
1952         mutex_destroy(&mpt->m_passthru_mutex);
1953         mutex_destroy(&mpt->m_mutex);
1954         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1955                 mutex_destroy(&mpt->m_phy_info[i].smhba_info.phy_mutex);
1956         }
1957         cv_destroy(&mpt->m_cv);
1958         cv_destroy(&mpt->m_passthru_cv);
1959         cv_destroy(&mpt->m_fw_cv);
1960         cv_destroy(&mpt->m_config_cv);
1961         cv_destroy(&mpt->m_fw_diag_cv);
1962 
1963 
1964         mptsas_smp_teardown(mpt);
1965         mptsas_hba_teardown(mpt);
1966 
1967         mptsas_config_space_fini(mpt);
1968 
1969         mptsas_free_handshake_msg(mpt);
1970 
1971         mptsas_fm_fini(mpt);
1972         ddi_soft_state_free(mptsas_state, ddi_get_instance(dip));
1973         ddi_prop_remove_all(dip);
1974 
1975         return (DDI_SUCCESS);
1976 }
1977 
1978 static void
1979 mptsas_list_add(mptsas_t *mpt)
1980 {
1981         rw_enter(&mptsas_global_rwlock, RW_WRITER);
1982 
1983         if (mptsas_head == NULL) {
1984                 mptsas_head = mpt;
1985         } else {
1986                 mptsas_tail->m_next = mpt;
1987         }
1988         mptsas_tail = mpt;
1989         rw_exit(&mptsas_global_rwlock);
1990 }
1991 
1992 static void
1993 mptsas_list_del(mptsas_t *mpt)
1994 {
1995         mptsas_t *m;
1996         /*
1997          * Remove device instance from the global linked list
1998          */
1999         rw_enter(&mptsas_global_rwlock, RW_WRITER);
2000         if (mptsas_head == mpt) {
2001                 m = mptsas_head = mpt->m_next;
2002         } else {
2003                 for (m = mptsas_head; m != NULL; m = m->m_next) {
2004                         if (m->m_next == mpt) {
2005                                 m->m_next = mpt->m_next;
2006                                 break;
2007                         }
2008                 }
2009                 if (m == NULL) {
2010                         mptsas_log(mpt, CE_PANIC, "Not in softc list!");
2011                 }
2012         }
2013 
2014         if (mptsas_tail == mpt) {
2015                 mptsas_tail = m;
2016         }
2017         rw_exit(&mptsas_global_rwlock);
2018 }
2019 
2020 static int
2021 mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size)
2022 {
2023         ddi_dma_attr_t  task_dma_attrs;
2024 
2025         mpt->m_hshk_dma_size = 0;
2026         task_dma_attrs = mpt->m_msg_dma_attr;
2027         task_dma_attrs.dma_attr_sgllen = 1;
2028         task_dma_attrs.dma_attr_granular = (uint32_t)(alloc_size);
2029 
2030         /* allocate Task Management ddi_dma resources */
2031         if (mptsas_dma_addr_create(mpt, task_dma_attrs,
2032             &mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl, &mpt->m_hshk_memp,
2033             alloc_size, NULL) == FALSE) {
2034                 return (DDI_FAILURE);
2035         }
2036         mpt->m_hshk_dma_size = alloc_size;
2037 
2038         return (DDI_SUCCESS);
2039 }
2040 
2041 static void
2042 mptsas_free_handshake_msg(mptsas_t *mpt)
2043 {
2044         if (mpt->m_hshk_dma_size == 0)
2045                 return;
2046         mptsas_dma_addr_destroy(&mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl);
2047         mpt->m_hshk_dma_size = 0;
2048 }
2049 
2050 static int
2051 mptsas_hba_setup(mptsas_t *mpt)
2052 {
2053         scsi_hba_tran_t         *hba_tran;
2054         int                     tran_flags;
2055 
2056         /* Allocate a transport structure */
2057         hba_tran = mpt->m_tran = scsi_hba_tran_alloc(mpt->m_dip,
2058             SCSI_HBA_CANSLEEP);
2059         ASSERT(mpt->m_tran != NULL);
2060 
2061         hba_tran->tran_hba_private   = mpt;
2062         hba_tran->tran_tgt_private   = NULL;
2063 
2064         hba_tran->tran_tgt_init              = mptsas_scsi_tgt_init;
2065         hba_tran->tran_tgt_free              = mptsas_scsi_tgt_free;
2066 
2067         hba_tran->tran_start         = mptsas_scsi_start;
2068         hba_tran->tran_reset         = mptsas_scsi_reset;
2069         hba_tran->tran_abort         = mptsas_scsi_abort;
2070         hba_tran->tran_getcap                = mptsas_scsi_getcap;
2071         hba_tran->tran_setcap                = mptsas_scsi_setcap;
2072         hba_tran->tran_init_pkt              = mptsas_scsi_init_pkt;
2073         hba_tran->tran_destroy_pkt   = mptsas_scsi_destroy_pkt;
2074 
2075         hba_tran->tran_dmafree               = mptsas_scsi_dmafree;
2076         hba_tran->tran_sync_pkt              = mptsas_scsi_sync_pkt;
2077         hba_tran->tran_reset_notify  = mptsas_scsi_reset_notify;
2078 
2079         hba_tran->tran_get_bus_addr  = mptsas_get_bus_addr;
2080         hba_tran->tran_get_name              = mptsas_get_name;
2081 
2082         hba_tran->tran_quiesce               = mptsas_scsi_quiesce;
2083         hba_tran->tran_unquiesce     = mptsas_scsi_unquiesce;
2084         hba_tran->tran_bus_reset     = NULL;
2085 
2086         hba_tran->tran_add_eventcall = NULL;
2087         hba_tran->tran_get_eventcookie       = NULL;
2088         hba_tran->tran_post_event    = NULL;
2089         hba_tran->tran_remove_eventcall      = NULL;
2090 
2091         hba_tran->tran_bus_config    = mptsas_bus_config;
2092 
2093         hba_tran->tran_interconnect_type = INTERCONNECT_SAS;
2094 
2095         /*
2096          * All children of the HBA are iports. We need tran was cloned.
2097          * So we pass the flags to SCSA. SCSI_HBA_TRAN_CLONE will be
2098          * inherited to iport's tran vector.
2099          */
2100         tran_flags = (SCSI_HBA_HBA | SCSI_HBA_TRAN_CLONE);
2101 
2102         if (scsi_hba_attach_setup(mpt->m_dip, &mpt->m_msg_dma_attr,
2103             hba_tran, tran_flags) != DDI_SUCCESS) {
2104                 mptsas_log(mpt, CE_WARN, "hba attach setup failed");
2105                 scsi_hba_tran_free(hba_tran);
2106                 mpt->m_tran = NULL;
2107                 return (FALSE);
2108         }
2109         return (TRUE);
2110 }
2111 
2112 static void
2113 mptsas_hba_teardown(mptsas_t *mpt)
2114 {
2115         (void) scsi_hba_detach(mpt->m_dip);
2116         if (mpt->m_tran != NULL) {
2117                 scsi_hba_tran_free(mpt->m_tran);
2118                 mpt->m_tran = NULL;
2119         }
2120 }
2121 
2122 static void
2123 mptsas_iport_register(mptsas_t *mpt)
2124 {
2125         int i, j;
2126         mptsas_phymask_t        mask = 0x0;
2127         /*
2128          * initial value of mask is 0
2129          */
2130         mutex_enter(&mpt->m_mutex);
2131         for (i = 0; i < mpt->m_num_phys; i++) {
2132                 mptsas_phymask_t phy_mask = 0x0;
2133                 char phy_mask_name[MPTSAS_MAX_PHYS];
2134                 uint8_t current_port;
2135 
2136                 if (mpt->m_phy_info[i].attached_devhdl == 0)
2137                         continue;
2138 
2139                 bzero(phy_mask_name, sizeof (phy_mask_name));
2140 
2141                 current_port = mpt->m_phy_info[i].port_num;
2142 
2143                 if ((mask & (1 << i)) != 0)
2144                         continue;
2145 
2146                 for (j = 0; j < mpt->m_num_phys; j++) {
2147                         if (mpt->m_phy_info[j].attached_devhdl &&
2148                             (mpt->m_phy_info[j].port_num == current_port)) {
2149                                 phy_mask |= (1 << j);
2150                         }
2151                 }
2152                 mask = mask | phy_mask;
2153 
2154                 for (j = 0; j < mpt->m_num_phys; j++) {
2155                         if ((phy_mask >> j) & 0x01) {
2156                                 mpt->m_phy_info[j].phy_mask = phy_mask;
2157                         }
2158                 }
2159 
2160                 (void) sprintf(phy_mask_name, "%x", phy_mask);
2161 
2162                 mutex_exit(&mpt->m_mutex);
2163                 /*
2164                  * register a iport
2165                  */
2166                 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
2167                 mutex_enter(&mpt->m_mutex);
2168         }
2169         mutex_exit(&mpt->m_mutex);
2170         /*
2171          * register a virtual port for RAID volume always
2172          */
2173         (void) scsi_hba_iport_register(mpt->m_dip, "v0");
2174 
2175 }
2176 
2177 static int
2178 mptsas_smp_setup(mptsas_t *mpt)
2179 {
2180         mpt->m_smptran = smp_hba_tran_alloc(mpt->m_dip);
2181         ASSERT(mpt->m_smptran != NULL);
2182         mpt->m_smptran->smp_tran_hba_private = mpt;
2183         mpt->m_smptran->smp_tran_start = mptsas_smp_start;
2184         if (smp_hba_attach_setup(mpt->m_dip, mpt->m_smptran) != DDI_SUCCESS) {
2185                 mptsas_log(mpt, CE_WARN, "smp attach setup failed");
2186                 smp_hba_tran_free(mpt->m_smptran);
2187                 mpt->m_smptran = NULL;
2188                 return (FALSE);
2189         }
2190         /*
2191          * Initialize smp hash table
2192          */
2193         mpt->m_smp_targets = refhash_create(MPTSAS_SMP_BUCKET_COUNT,
2194             mptsas_target_addr_hash, mptsas_target_addr_cmp,
2195             mptsas_smp_free, sizeof (mptsas_smp_t),
2196             offsetof(mptsas_smp_t, m_link), offsetof(mptsas_smp_t, m_addr),
2197             KM_SLEEP);
2198         mpt->m_smp_devhdl = 0xFFFF;
2199 
2200         return (TRUE);
2201 }
2202 
2203 static void
2204 mptsas_smp_teardown(mptsas_t *mpt)
2205 {
2206         (void) smp_hba_detach(mpt->m_dip);
2207         if (mpt->m_smptran != NULL) {
2208                 smp_hba_tran_free(mpt->m_smptran);
2209                 mpt->m_smptran = NULL;
2210         }
2211         mpt->m_smp_devhdl = 0;
2212 }
2213 
2214 static int
2215 mptsas_cache_create(mptsas_t *mpt)
2216 {
2217         int instance = mpt->m_instance;
2218         char buf[64];
2219 
2220         /*
2221          * create kmem cache for packets
2222          */
2223         (void) sprintf(buf, "mptsas%d_cache", instance);
2224         mpt->m_kmem_cache = kmem_cache_create(buf,
2225             sizeof (struct mptsas_cmd) + scsi_pkt_size(), 8,
2226             mptsas_kmem_cache_constructor, mptsas_kmem_cache_destructor,
2227             NULL, (void *)mpt, NULL, 0);
2228 
2229         if (mpt->m_kmem_cache == NULL) {
2230                 mptsas_log(mpt, CE_WARN, "creating kmem cache failed");
2231                 return (FALSE);
2232         }
2233 
2234         /*
2235          * create kmem cache for extra SGL frames if SGL cannot
2236          * be accomodated into main request frame.
2237          */
2238         (void) sprintf(buf, "mptsas%d_cache_frames", instance);
2239         mpt->m_cache_frames = kmem_cache_create(buf,
2240             sizeof (mptsas_cache_frames_t), 8,
2241             mptsas_cache_frames_constructor, mptsas_cache_frames_destructor,
2242             NULL, (void *)mpt, NULL, 0);
2243 
2244         if (mpt->m_cache_frames == NULL) {
2245                 mptsas_log(mpt, CE_WARN, "creating cache for frames failed");
2246                 return (FALSE);
2247         }
2248 
2249         return (TRUE);
2250 }
2251 
2252 static void
2253 mptsas_cache_destroy(mptsas_t *mpt)
2254 {
2255         /* deallocate in reverse order */
2256         if (mpt->m_cache_frames) {
2257                 kmem_cache_destroy(mpt->m_cache_frames);
2258                 mpt->m_cache_frames = NULL;
2259         }
2260         if (mpt->m_kmem_cache) {
2261                 kmem_cache_destroy(mpt->m_kmem_cache);
2262                 mpt->m_kmem_cache = NULL;
2263         }
2264 }
2265 
2266 static int
2267 mptsas_power(dev_info_t *dip, int component, int level)
2268 {
2269 #ifndef __lock_lint
2270         _NOTE(ARGUNUSED(component))
2271 #endif
2272         mptsas_t        *mpt;
2273         int             rval = DDI_SUCCESS;
2274         int             polls = 0;
2275         uint32_t        ioc_status;
2276 
2277         if (scsi_hba_iport_unit_address(dip) != 0)
2278                 return (DDI_SUCCESS);
2279 
2280         mpt = ddi_get_soft_state(mptsas_state, ddi_get_instance(dip));
2281         if (mpt == NULL) {
2282                 return (DDI_FAILURE);
2283         }
2284 
2285         mutex_enter(&mpt->m_mutex);
2286 
2287         /*
2288          * If the device is busy, don't lower its power level
2289          */
2290         if (mpt->m_busy && (mpt->m_power_level > level)) {
2291                 mutex_exit(&mpt->m_mutex);
2292                 return (DDI_FAILURE);
2293         }
2294         switch (level) {
2295         case PM_LEVEL_D0:
2296                 NDBG11(("mptsas%d: turning power ON.", mpt->m_instance));
2297                 MPTSAS_POWER_ON(mpt);
2298                 /*
2299                  * Wait up to 30 seconds for IOC to come out of reset.
2300                  */
2301                 while (((ioc_status = ddi_get32(mpt->m_datap,
2302                     &mpt->m_reg->Doorbell)) &
2303                     MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_RESET) {
2304                         if (polls++ > 3000) {
2305                                 break;
2306                         }
2307                         delay(drv_usectohz(10000));
2308                 }
2309                 /*
2310                  * If IOC is not in operational state, try to hard reset it.
2311                  */
2312                 if ((ioc_status & MPI2_IOC_STATE_MASK) !=
2313                     MPI2_IOC_STATE_OPERATIONAL) {
2314                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
2315                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
2316                                 mptsas_log(mpt, CE_WARN,
2317                                     "mptsas_power: hard reset failed");
2318                                 mutex_exit(&mpt->m_mutex);
2319                                 return (DDI_FAILURE);
2320                         }
2321                 }
2322                 mpt->m_power_level = PM_LEVEL_D0;
2323                 break;
2324         case PM_LEVEL_D3:
2325                 NDBG11(("mptsas%d: turning power OFF.", mpt->m_instance));
2326                 MPTSAS_POWER_OFF(mpt);
2327                 break;
2328         default:
2329                 mptsas_log(mpt, CE_WARN, "mptsas%d: unknown power level <%x>.",
2330                     mpt->m_instance, level);
2331                 rval = DDI_FAILURE;
2332                 break;
2333         }
2334         mutex_exit(&mpt->m_mutex);
2335         return (rval);
2336 }
2337 
2338 /*
2339  * Initialize configuration space and figure out which
2340  * chip and revison of the chip the mpt driver is using.
2341  */
2342 static int
2343 mptsas_config_space_init(mptsas_t *mpt)
2344 {
2345         NDBG0(("mptsas_config_space_init"));
2346 
2347         if (mpt->m_config_handle != NULL)
2348                 return (TRUE);
2349 
2350         if (pci_config_setup(mpt->m_dip,
2351             &mpt->m_config_handle) != DDI_SUCCESS) {
2352                 mptsas_log(mpt, CE_WARN, "cannot map configuration space.");
2353                 return (FALSE);
2354         }
2355 
2356         /*
2357          * This is a workaround for a XMITS ASIC bug which does not
2358          * drive the CBE upper bits.
2359          */
2360         if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT) &
2361             PCI_STAT_PERROR) {
2362                 pci_config_put16(mpt->m_config_handle, PCI_CONF_STAT,
2363                     PCI_STAT_PERROR);
2364         }
2365 
2366         mptsas_setup_cmd_reg(mpt);
2367 
2368         /*
2369          * Get the chip device id:
2370          */
2371         mpt->m_devid = pci_config_get16(mpt->m_config_handle, PCI_CONF_DEVID);
2372 
2373         /*
2374          * Save the revision.
2375          */
2376         mpt->m_revid = pci_config_get8(mpt->m_config_handle, PCI_CONF_REVID);
2377 
2378         /*
2379          * Save the SubSystem Vendor and Device IDs
2380          */
2381         mpt->m_svid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBVENID);
2382         mpt->m_ssid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBSYSID);
2383 
2384         /*
2385          * Set the latency timer to 0x40 as specified by the upa -> pci
2386          * bridge chip design team.  This may be done by the sparc pci
2387          * bus nexus driver, but the driver should make sure the latency
2388          * timer is correct for performance reasons.
2389          */
2390         pci_config_put8(mpt->m_config_handle, PCI_CONF_LATENCY_TIMER,
2391             MPTSAS_LATENCY_TIMER);
2392 
2393         (void) mptsas_get_pci_cap(mpt);
2394         return (TRUE);
2395 }
2396 
2397 static void
2398 mptsas_config_space_fini(mptsas_t *mpt)
2399 {
2400         if (mpt->m_config_handle != NULL) {
2401                 mptsas_disable_bus_master(mpt);
2402                 pci_config_teardown(&mpt->m_config_handle);
2403                 mpt->m_config_handle = NULL;
2404         }
2405 }
2406 
2407 static void
2408 mptsas_setup_cmd_reg(mptsas_t *mpt)
2409 {
2410         ushort_t        cmdreg;
2411 
2412         /*
2413          * Set the command register to the needed values.
2414          */
2415         cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2416         cmdreg |= (PCI_COMM_ME | PCI_COMM_SERR_ENABLE |
2417             PCI_COMM_PARITY_DETECT | PCI_COMM_MAE);
2418         cmdreg &= ~PCI_COMM_IO;
2419         pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2420 }
2421 
2422 static void
2423 mptsas_disable_bus_master(mptsas_t *mpt)
2424 {
2425         ushort_t        cmdreg;
2426 
2427         /*
2428          * Clear the master enable bit in the PCI command register.
2429          * This prevents any bus mastering activity like DMA.
2430          */
2431         cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2432         cmdreg &= ~PCI_COMM_ME;
2433         pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2434 }
2435 
2436 int
2437 mptsas_dma_alloc(mptsas_t *mpt, mptsas_dma_alloc_state_t *dma_statep)
2438 {
2439         ddi_dma_attr_t  attrs;
2440 
2441         attrs = mpt->m_io_dma_attr;
2442         attrs.dma_attr_sgllen = 1;
2443 
2444         ASSERT(dma_statep != NULL);
2445 
2446         if (mptsas_dma_addr_create(mpt, attrs, &dma_statep->handle,
2447             &dma_statep->accessp, &dma_statep->memp, dma_statep->size,
2448             &dma_statep->cookie) == FALSE) {
2449                 return (DDI_FAILURE);
2450         }
2451 
2452         return (DDI_SUCCESS);
2453 }
2454 
2455 void
2456 mptsas_dma_free(mptsas_dma_alloc_state_t *dma_statep)
2457 {
2458         ASSERT(dma_statep != NULL);
2459         mptsas_dma_addr_destroy(&dma_statep->handle, &dma_statep->accessp);
2460         dma_statep->size = 0;
2461 }
2462 
2463 int
2464 mptsas_do_dma(mptsas_t *mpt, uint32_t size, int var, int (*callback)())
2465 {
2466         ddi_dma_attr_t          attrs;
2467         ddi_dma_handle_t        dma_handle;
2468         caddr_t                 memp;
2469         ddi_acc_handle_t        accessp;
2470         int                     rval;
2471 
2472         ASSERT(mutex_owned(&mpt->m_mutex));
2473 
2474         attrs = mpt->m_msg_dma_attr;
2475         attrs.dma_attr_sgllen = 1;
2476         attrs.dma_attr_granular = size;
2477 
2478         if (mptsas_dma_addr_create(mpt, attrs, &dma_handle,
2479             &accessp, &memp, size, NULL) == FALSE) {
2480                 return (DDI_FAILURE);
2481         }
2482 
2483         rval = (*callback) (mpt, memp, var, accessp);
2484 
2485         if ((mptsas_check_dma_handle(dma_handle) != DDI_SUCCESS) ||
2486             (mptsas_check_acc_handle(accessp) != DDI_SUCCESS)) {
2487                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2488                 rval = DDI_FAILURE;
2489         }
2490 
2491         mptsas_dma_addr_destroy(&dma_handle, &accessp);
2492         return (rval);
2493 
2494 }
2495 
2496 static int
2497 mptsas_alloc_request_frames(mptsas_t *mpt)
2498 {
2499         ddi_dma_attr_t          frame_dma_attrs;
2500         caddr_t                 memp;
2501         ddi_dma_cookie_t        cookie;
2502         size_t                  mem_size;
2503 
2504         /*
2505          * re-alloc when it has already alloced
2506          */
2507         mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2508             &mpt->m_acc_req_frame_hdl);
2509 
2510         /*
2511          * The size of the request frame pool is:
2512          *   Number of Request Frames * Request Frame Size
2513          */
2514         mem_size = mpt->m_max_requests * mpt->m_req_frame_size;
2515 
2516         /*
2517          * set the DMA attributes.  System Request Message Frames must be
2518          * aligned on a 16-byte boundry.
2519          */
2520         frame_dma_attrs = mpt->m_msg_dma_attr;
2521         frame_dma_attrs.dma_attr_align = 16;
2522         frame_dma_attrs.dma_attr_sgllen = 1;
2523 
2524         /*
2525          * allocate the request frame pool.
2526          */
2527         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2528             &mpt->m_dma_req_frame_hdl, &mpt->m_acc_req_frame_hdl, &memp,
2529             mem_size, &cookie) == FALSE) {
2530                 return (DDI_FAILURE);
2531         }
2532 
2533         /*
2534          * Store the request frame memory address.  This chip uses this
2535          * address to dma to and from the driver's frame.  The second
2536          * address is the address mpt uses to fill in the frame.
2537          */
2538         mpt->m_req_frame_dma_addr = cookie.dmac_laddress;
2539         mpt->m_req_frame = memp;
2540 
2541         /*
2542          * Clear the request frame pool.
2543          */
2544         bzero(mpt->m_req_frame, mem_size);
2545 
2546         return (DDI_SUCCESS);
2547 }
2548 
2549 static int
2550 mptsas_alloc_reply_frames(mptsas_t *mpt)
2551 {
2552         ddi_dma_attr_t          frame_dma_attrs;
2553         caddr_t                 memp;
2554         ddi_dma_cookie_t        cookie;
2555         size_t                  mem_size;
2556 
2557         /*
2558          * re-alloc when it has already alloced
2559          */
2560         mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2561             &mpt->m_acc_reply_frame_hdl);
2562 
2563         /*
2564          * The size of the reply frame pool is:
2565          *   Number of Reply Frames * Reply Frame Size
2566          */
2567         mem_size = mpt->m_max_replies * mpt->m_reply_frame_size;
2568 
2569         /*
2570          * set the DMA attributes.   System Reply Message Frames must be
2571          * aligned on a 4-byte boundry.  This is the default.
2572          */
2573         frame_dma_attrs = mpt->m_msg_dma_attr;
2574         frame_dma_attrs.dma_attr_sgllen = 1;
2575 
2576         /*
2577          * allocate the reply frame pool
2578          */
2579         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2580             &mpt->m_dma_reply_frame_hdl, &mpt->m_acc_reply_frame_hdl, &memp,
2581             mem_size, &cookie) == FALSE) {
2582                 return (DDI_FAILURE);
2583         }
2584 
2585         /*
2586          * Store the reply frame memory address.  This chip uses this
2587          * address to dma to and from the driver's frame.  The second
2588          * address is the address mpt uses to process the frame.
2589          */
2590         mpt->m_reply_frame_dma_addr = cookie.dmac_laddress;
2591         mpt->m_reply_frame = memp;
2592 
2593         /*
2594          * Clear the reply frame pool.
2595          */
2596         bzero(mpt->m_reply_frame, mem_size);
2597 
2598         return (DDI_SUCCESS);
2599 }
2600 
2601 static int
2602 mptsas_alloc_free_queue(mptsas_t *mpt)
2603 {
2604         ddi_dma_attr_t          frame_dma_attrs;
2605         caddr_t                 memp;
2606         ddi_dma_cookie_t        cookie;
2607         size_t                  mem_size;
2608 
2609         /*
2610          * re-alloc when it has already alloced
2611          */
2612         mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2613             &mpt->m_acc_free_queue_hdl);
2614 
2615         /*
2616          * The reply free queue size is:
2617          *   Reply Free Queue Depth * 4
2618          * The "4" is the size of one 32 bit address (low part of 64-bit
2619          *   address)
2620          */
2621         mem_size = mpt->m_free_queue_depth * 4;
2622 
2623         /*
2624          * set the DMA attributes  The Reply Free Queue must be aligned on a
2625          * 16-byte boundry.
2626          */
2627         frame_dma_attrs = mpt->m_msg_dma_attr;
2628         frame_dma_attrs.dma_attr_align = 16;
2629         frame_dma_attrs.dma_attr_sgllen = 1;
2630 
2631         /*
2632          * allocate the reply free queue
2633          */
2634         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2635             &mpt->m_dma_free_queue_hdl, &mpt->m_acc_free_queue_hdl, &memp,
2636             mem_size, &cookie) == FALSE) {
2637                 return (DDI_FAILURE);
2638         }
2639 
2640         /*
2641          * Store the reply free queue memory address.  This chip uses this
2642          * address to read from the reply free queue.  The second address
2643          * is the address mpt uses to manage the queue.
2644          */
2645         mpt->m_free_queue_dma_addr = cookie.dmac_laddress;
2646         mpt->m_free_queue = memp;
2647 
2648         /*
2649          * Clear the reply free queue memory.
2650          */
2651         bzero(mpt->m_free_queue, mem_size);
2652 
2653         return (DDI_SUCCESS);
2654 }
2655 
2656 static int
2657 mptsas_alloc_post_queue(mptsas_t *mpt)
2658 {
2659         ddi_dma_attr_t          frame_dma_attrs;
2660         caddr_t                 memp;
2661         ddi_dma_cookie_t        cookie;
2662         size_t                  mem_size;
2663 
2664         /*
2665          * re-alloc when it has already alloced
2666          */
2667         mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2668             &mpt->m_acc_post_queue_hdl);
2669 
2670         /*
2671          * The reply descriptor post queue size is:
2672          *   Reply Descriptor Post Queue Depth * 8
2673          * The "8" is the size of each descriptor (8 bytes or 64 bits).
2674          */
2675         mem_size = mpt->m_post_queue_depth * 8;
2676 
2677         /*
2678          * set the DMA attributes.  The Reply Descriptor Post Queue must be
2679          * aligned on a 16-byte boundry.
2680          */
2681         frame_dma_attrs = mpt->m_msg_dma_attr;
2682         frame_dma_attrs.dma_attr_align = 16;
2683         frame_dma_attrs.dma_attr_sgllen = 1;
2684 
2685         /*
2686          * allocate the reply post queue
2687          */
2688         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2689             &mpt->m_dma_post_queue_hdl, &mpt->m_acc_post_queue_hdl, &memp,
2690             mem_size, &cookie) == FALSE) {
2691                 return (DDI_FAILURE);
2692         }
2693 
2694         /*
2695          * Store the reply descriptor post queue memory address.  This chip
2696          * uses this address to write to the reply descriptor post queue.  The
2697          * second address is the address mpt uses to manage the queue.
2698          */
2699         mpt->m_post_queue_dma_addr = cookie.dmac_laddress;
2700         mpt->m_post_queue = memp;
2701 
2702         /*
2703          * Clear the reply post queue memory.
2704          */
2705         bzero(mpt->m_post_queue, mem_size);
2706 
2707         return (DDI_SUCCESS);
2708 }
2709 
2710 static void
2711 mptsas_alloc_reply_args(mptsas_t *mpt)
2712 {
2713         if (mpt->m_replyh_args == NULL) {
2714                 mpt->m_replyh_args = kmem_zalloc(sizeof (m_replyh_arg_t) *
2715                     mpt->m_max_replies, KM_SLEEP);
2716         }
2717 }
2718 
2719 static int
2720 mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2721 {
2722         mptsas_cache_frames_t   *frames = NULL;
2723         if (cmd->cmd_extra_frames == NULL) {
2724                 frames = kmem_cache_alloc(mpt->m_cache_frames, KM_NOSLEEP);
2725                 if (frames == NULL) {
2726                         return (DDI_FAILURE);
2727                 }
2728                 cmd->cmd_extra_frames = frames;
2729         }
2730         return (DDI_SUCCESS);
2731 }
2732 
2733 static void
2734 mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2735 {
2736         if (cmd->cmd_extra_frames) {
2737                 kmem_cache_free(mpt->m_cache_frames,
2738                     (void *)cmd->cmd_extra_frames);
2739                 cmd->cmd_extra_frames = NULL;
2740         }
2741 }
2742 
2743 static void
2744 mptsas_cfg_fini(mptsas_t *mpt)
2745 {
2746         NDBG0(("mptsas_cfg_fini"));
2747         ddi_regs_map_free(&mpt->m_datap);
2748 }
2749 
2750 static void
2751 mptsas_hba_fini(mptsas_t *mpt)
2752 {
2753         NDBG0(("mptsas_hba_fini"));
2754 
2755         /*
2756          * Free up any allocated memory
2757          */
2758         mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2759             &mpt->m_acc_req_frame_hdl);
2760 
2761         mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2762             &mpt->m_acc_reply_frame_hdl);
2763 
2764         mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2765             &mpt->m_acc_free_queue_hdl);
2766 
2767         mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2768             &mpt->m_acc_post_queue_hdl);
2769 
2770         if (mpt->m_replyh_args != NULL) {
2771                 kmem_free(mpt->m_replyh_args, sizeof (m_replyh_arg_t)
2772                     * mpt->m_max_replies);
2773         }
2774 }
2775 
2776 static int
2777 mptsas_name_child(dev_info_t *lun_dip, char *name, int len)
2778 {
2779         int             lun = 0;
2780         char            *sas_wwn = NULL;
2781         int             phynum = -1;
2782         int             reallen = 0;
2783 
2784         /* Get the target num */
2785         lun = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip, DDI_PROP_DONTPASS,
2786             LUN_PROP, 0);
2787 
2788         if ((phynum = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip,
2789             DDI_PROP_DONTPASS, "sata-phy", -1)) != -1) {
2790                 /*
2791                  * Stick in the address of form "pPHY,LUN"
2792                  */
2793                 reallen = snprintf(name, len, "p%x,%x", phynum, lun);
2794         } else if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lun_dip,
2795             DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &sas_wwn)
2796             == DDI_PROP_SUCCESS) {
2797                 /*
2798                  * Stick in the address of the form "wWWN,LUN"
2799                  */
2800                 reallen = snprintf(name, len, "%s,%x", sas_wwn, lun);
2801                 ddi_prop_free(sas_wwn);
2802         } else {
2803                 return (DDI_FAILURE);
2804         }
2805 
2806         ASSERT(reallen < len);
2807         if (reallen >= len) {
2808                 mptsas_log(0, CE_WARN, "!mptsas_get_name: name parameter "
2809                     "length too small, it needs to be %d bytes", reallen + 1);
2810         }
2811         return (DDI_SUCCESS);
2812 }
2813 
2814 /*
2815  * tran_tgt_init(9E) - target device instance initialization
2816  */
2817 static int
2818 mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
2819     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
2820 {
2821 #ifndef __lock_lint
2822         _NOTE(ARGUNUSED(hba_tran))
2823 #endif
2824 
2825         /*
2826          * At this point, the scsi_device structure already exists
2827          * and has been initialized.
2828          *
2829          * Use this function to allocate target-private data structures,
2830          * if needed by this HBA.  Add revised flow-control and queue
2831          * properties for child here, if desired and if you can tell they
2832          * support tagged queueing by now.
2833          */
2834         mptsas_t                *mpt;
2835         int                     lun = sd->sd_address.a_lun;
2836         mdi_pathinfo_t          *pip = NULL;
2837         mptsas_tgt_private_t    *tgt_private = NULL;
2838         mptsas_target_t         *ptgt = NULL;
2839         char                    *psas_wwn = NULL;
2840         mptsas_phymask_t        phymask = 0;
2841         uint64_t                sas_wwn = 0;
2842         mptsas_target_addr_t    addr;
2843         mpt = SDEV2MPT(sd);
2844 
2845         ASSERT(scsi_hba_iport_unit_address(hba_dip) != 0);
2846 
2847         NDBG0(("mptsas_scsi_tgt_init: hbadip=0x%p tgtdip=0x%p lun=%d",
2848             (void *)hba_dip, (void *)tgt_dip, lun));
2849 
2850         if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
2851                 (void) ndi_merge_node(tgt_dip, mptsas_name_child);
2852                 ddi_set_name_addr(tgt_dip, NULL);
2853                 return (DDI_FAILURE);
2854         }
2855         /*
2856          * phymask is 0 means the virtual port for RAID
2857          */
2858         phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, hba_dip, 0,
2859             "phymask", 0);
2860         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2861                 if ((pip = (void *)(sd->sd_private)) == NULL) {
2862                         /*
2863                          * Very bad news if this occurs. Somehow scsi_vhci has
2864                          * lost the pathinfo node for this target.
2865                          */
2866                         return (DDI_NOT_WELL_FORMED);
2867                 }
2868 
2869                 if (mdi_prop_lookup_int(pip, LUN_PROP, &lun) !=
2870                     DDI_PROP_SUCCESS) {
2871                         mptsas_log(mpt, CE_WARN, "Get lun property failed\n");
2872                         return (DDI_FAILURE);
2873                 }
2874 
2875                 if (mdi_prop_lookup_string(pip, SCSI_ADDR_PROP_TARGET_PORT,
2876                     &psas_wwn) == MDI_SUCCESS) {
2877                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2878                                 sas_wwn = 0;
2879                         }
2880                         (void) mdi_prop_free(psas_wwn);
2881                 }
2882         } else {
2883                 lun = ddi_prop_get_int(DDI_DEV_T_ANY, tgt_dip,
2884                     DDI_PROP_DONTPASS, LUN_PROP, 0);
2885                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip,
2886                     DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &psas_wwn) ==
2887                     DDI_PROP_SUCCESS) {
2888                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2889                                 sas_wwn = 0;
2890                         }
2891                         ddi_prop_free(psas_wwn);
2892                 } else {
2893                         sas_wwn = 0;
2894                 }
2895         }
2896 
2897         ASSERT((sas_wwn != 0) || (phymask != 0));
2898         addr.mta_wwn = sas_wwn;
2899         addr.mta_phymask = phymask;
2900         mutex_enter(&mpt->m_mutex);
2901         ptgt = refhash_lookup(mpt->m_targets, &addr);
2902         mutex_exit(&mpt->m_mutex);
2903         if (ptgt == NULL) {
2904                 mptsas_log(mpt, CE_WARN, "!tgt_init: target doesn't exist or "
2905                     "gone already! phymask:%x, saswwn %"PRIx64, phymask,
2906                     sas_wwn);
2907                 return (DDI_FAILURE);
2908         }
2909         if (hba_tran->tran_tgt_private == NULL) {
2910                 tgt_private = kmem_zalloc(sizeof (mptsas_tgt_private_t),
2911                     KM_SLEEP);
2912                 tgt_private->t_lun = lun;
2913                 tgt_private->t_private = ptgt;
2914                 hba_tran->tran_tgt_private = tgt_private;
2915         }
2916 
2917         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2918                 return (DDI_SUCCESS);
2919         }
2920         mutex_enter(&mpt->m_mutex);
2921 
2922         if (ptgt->m_deviceinfo &
2923             (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
2924             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
2925                 uchar_t *inq89 = NULL;
2926                 int inq89_len = 0x238;
2927                 int reallen = 0;
2928                 int rval = 0;
2929                 struct sata_id *sid = NULL;
2930                 char model[SATA_ID_MODEL_LEN + 1];
2931                 char fw[SATA_ID_FW_LEN + 1];
2932                 char *vid, *pid;
2933                 int i;
2934 
2935                 mutex_exit(&mpt->m_mutex);
2936                 /*
2937                  * According SCSI/ATA Translation -2 (SAT-2) revision 01a
2938                  * chapter 12.4.2 VPD page 89h includes 512 bytes ATA IDENTIFY
2939                  * DEVICE data or ATA IDENTIFY PACKET DEVICE data.
2940                  */
2941                 inq89 = kmem_zalloc(inq89_len, KM_SLEEP);
2942                 rval = mptsas_inquiry(mpt, ptgt, 0, 0x89,
2943                     inq89, inq89_len, &reallen, 1);
2944 
2945                 if (rval != 0) {
2946                         if (inq89 != NULL) {
2947                                 kmem_free(inq89, inq89_len);
2948                         }
2949 
2950                         mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
2951                             "0x89 for SATA target:%x failed!", ptgt->m_devhdl);
2952                         return (DDI_SUCCESS);
2953                 }
2954                 sid = (void *)(&inq89[60]);
2955 
2956                 swab(sid->ai_model, model, SATA_ID_MODEL_LEN);
2957                 swab(sid->ai_fw, fw, SATA_ID_FW_LEN);
2958 
2959                 model[SATA_ID_MODEL_LEN] = 0;
2960                 fw[SATA_ID_FW_LEN] = 0;
2961 
2962                 /*
2963                  * split model into into vid/pid
2964                  */
2965                 for (i = 0, pid = model; i < SATA_ID_MODEL_LEN; i++, pid++)
2966                         if ((*pid == ' ') || (*pid == '\t'))
2967                                 break;
2968                 if (i < SATA_ID_MODEL_LEN) {
2969                         vid = model;
2970                         /*
2971                          * terminate vid, establish pid
2972                          */
2973                         *pid++ = 0;
2974                 } else {
2975                         /*
2976                          * vid will stay "ATA     ", the rule is same
2977                          * as sata framework implementation.
2978                          */
2979                         vid = NULL;
2980                         /*
2981                          * model is all pid
2982                          */
2983                         pid = model;
2984                 }
2985 
2986                 /*
2987                  * override SCSA "inquiry-*" properties
2988                  */
2989                 if (vid)
2990                         (void) scsi_device_prop_update_inqstring(sd,
2991                             INQUIRY_VENDOR_ID, vid, strlen(vid));
2992                 if (pid)
2993                         (void) scsi_device_prop_update_inqstring(sd,
2994                             INQUIRY_PRODUCT_ID, pid, strlen(pid));
2995                 (void) scsi_device_prop_update_inqstring(sd,
2996                     INQUIRY_REVISION_ID, fw, strlen(fw));
2997 
2998                 if (inq89 != NULL) {
2999                         kmem_free(inq89, inq89_len);
3000                 }
3001         } else {
3002                 mutex_exit(&mpt->m_mutex);
3003         }
3004 
3005         return (DDI_SUCCESS);
3006 }
3007 /*
3008  * tran_tgt_free(9E) - target device instance deallocation
3009  */
3010 static void
3011 mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
3012     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
3013 {
3014 #ifndef __lock_lint
3015         _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran, sd))
3016 #endif
3017 
3018         mptsas_tgt_private_t    *tgt_private = hba_tran->tran_tgt_private;
3019 
3020         if (tgt_private != NULL) {
3021                 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
3022                 hba_tran->tran_tgt_private = NULL;
3023         }
3024 }
3025 
3026 /*
3027  * scsi_pkt handling
3028  *
3029  * Visible to the external world via the transport structure.
3030  */
3031 
3032 /*
3033  * Notes:
3034  *      - transport the command to the addressed SCSI target/lun device
3035  *      - normal operation is to schedule the command to be transported,
3036  *        and return TRAN_ACCEPT if this is successful.
3037  *      - if NO_INTR, tran_start must poll device for command completion
3038  */
3039 static int
3040 mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
3041 {
3042 #ifndef __lock_lint
3043         _NOTE(ARGUNUSED(ap))
3044 #endif
3045         mptsas_t        *mpt = PKT2MPT(pkt);
3046         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
3047         int             rval;
3048         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3049 
3050         NDBG1(("mptsas_scsi_start: pkt=0x%p", (void *)pkt));
3051         ASSERT(ptgt);
3052         if (ptgt == NULL)
3053                 return (TRAN_FATAL_ERROR);
3054 
3055         /*
3056          * prepare the pkt before taking mutex.
3057          */
3058         rval = mptsas_prepare_pkt(cmd);
3059         if (rval != TRAN_ACCEPT) {
3060                 return (rval);
3061         }
3062 
3063         /*
3064          * Send the command to target/lun, however your HBA requires it.
3065          * If busy, return TRAN_BUSY; if there's some other formatting error
3066          * in the packet, return TRAN_BADPKT; otherwise, fall through to the
3067          * return of TRAN_ACCEPT.
3068          *
3069          * Remember that access to shared resources, including the mptsas_t
3070          * data structure and the HBA hardware registers, must be protected
3071          * with mutexes, here and everywhere.
3072          *
3073          * Also remember that at interrupt time, you'll get an argument
3074          * to the interrupt handler which is a pointer to your mptsas_t
3075          * structure; you'll have to remember which commands are outstanding
3076          * and which scsi_pkt is the currently-running command so the
3077          * interrupt handler can refer to the pkt to set completion
3078          * status, call the target driver back through pkt_comp, etc.
3079          *
3080          * If the instance lock is held by other thread, don't spin to wait
3081          * for it. Instead, queue the cmd and next time when the instance lock
3082          * is not held, accept all the queued cmd. A extra tx_waitq is
3083          * introduced to protect the queue.
3084          *
3085          * The polled cmd will not be queud and accepted as usual.
3086          *
3087          * Under the tx_waitq mutex, record whether a thread is draining
3088          * the tx_waitq.  An IO requesting thread that finds the instance
3089          * mutex contended appends to the tx_waitq and while holding the
3090          * tx_wait mutex, if the draining flag is not set, sets it and then
3091          * proceeds to spin for the instance mutex. This scheme ensures that
3092          * the last cmd in a burst be processed.
3093          *
3094          * we enable this feature only when the helper threads are enabled,
3095          * at which we think the loads are heavy.
3096          *
3097          * per instance mutex m_tx_waitq_mutex is introduced to protect the
3098          * m_tx_waitqtail, m_tx_waitq, m_tx_draining.
3099          */
3100 
3101         if (mpt->m_doneq_thread_n) {
3102                 if (mutex_tryenter(&mpt->m_mutex) != 0) {
3103                         rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3104                         mutex_exit(&mpt->m_mutex);
3105                 } else if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3106                         mutex_enter(&mpt->m_mutex);
3107                         rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3108                         mutex_exit(&mpt->m_mutex);
3109                 } else {
3110                         mutex_enter(&mpt->m_tx_waitq_mutex);
3111                         /*
3112                          * ptgt->m_dr_flag is protected by m_mutex or
3113                          * m_tx_waitq_mutex. In this case, m_tx_waitq_mutex
3114                          * is acquired.
3115                          */
3116                         if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3117                                 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3118                                         /*
3119                                          * The command should be allowed to
3120                                          * retry by returning TRAN_BUSY to
3121                                          * to stall the I/O's which come from
3122                                          * scsi_vhci since the device/path is
3123                                          * in unstable state now.
3124                                          */
3125                                         mutex_exit(&mpt->m_tx_waitq_mutex);
3126                                         return (TRAN_BUSY);
3127                                 } else {
3128                                         /*
3129                                          * The device is offline, just fail the
3130                                          * command by returning
3131                                          * TRAN_FATAL_ERROR.
3132                                          */
3133                                         mutex_exit(&mpt->m_tx_waitq_mutex);
3134                                         return (TRAN_FATAL_ERROR);
3135                                 }
3136                         }
3137                         if (mpt->m_tx_draining) {
3138                                 cmd->cmd_flags |= CFLAG_TXQ;
3139                                 *mpt->m_tx_waitqtail = cmd;
3140                                 mpt->m_tx_waitqtail = &cmd->cmd_linkp;
3141                                 mutex_exit(&mpt->m_tx_waitq_mutex);
3142                         } else { /* drain the queue */
3143                                 mpt->m_tx_draining = 1;
3144                                 mutex_exit(&mpt->m_tx_waitq_mutex);
3145                                 mutex_enter(&mpt->m_mutex);
3146                                 rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3147                                 mutex_exit(&mpt->m_mutex);
3148                         }
3149                 }
3150         } else {
3151                 mutex_enter(&mpt->m_mutex);
3152                 /*
3153                  * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
3154                  * in this case, m_mutex is acquired.
3155                  */
3156                 if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3157                         if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3158                                 /*
3159                                  * commands should be allowed to retry by
3160                                  * returning TRAN_BUSY to stall the I/O's
3161                                  * which come from scsi_vhci since the device/
3162                                  * path is in unstable state now.
3163                                  */
3164                                 mutex_exit(&mpt->m_mutex);
3165                                 return (TRAN_BUSY);
3166                         } else {
3167                                 /*
3168                                  * The device is offline, just fail the
3169                                  * command by returning TRAN_FATAL_ERROR.
3170                                  */
3171                                 mutex_exit(&mpt->m_mutex);
3172                                 return (TRAN_FATAL_ERROR);
3173                         }
3174                 }
3175                 rval = mptsas_accept_pkt(mpt, cmd);
3176                 mutex_exit(&mpt->m_mutex);
3177         }
3178 
3179         return (rval);
3180 }
3181 
3182 /*
3183  * Accept all the queued cmds(if any) before accept the current one.
3184  */
3185 static int
3186 mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3187 {
3188         int rval;
3189         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3190 
3191         ASSERT(mutex_owned(&mpt->m_mutex));
3192         /*
3193          * The call to mptsas_accept_tx_waitq() must always be performed
3194          * because that is where mpt->m_tx_draining is cleared.
3195          */
3196         mutex_enter(&mpt->m_tx_waitq_mutex);
3197         mptsas_accept_tx_waitq(mpt);
3198         mutex_exit(&mpt->m_tx_waitq_mutex);
3199         /*
3200          * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
3201          * in this case, m_mutex is acquired.
3202          */
3203         if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3204                 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3205                         /*
3206                          * The command should be allowed to retry by returning
3207                          * TRAN_BUSY to stall the I/O's which come from
3208                          * scsi_vhci since the device/path is in unstable state
3209                          * now.
3210                          */
3211                         return (TRAN_BUSY);
3212                 } else {
3213                         /*
3214                          * The device is offline, just fail the command by
3215                          * return TRAN_FATAL_ERROR.
3216                          */
3217                         return (TRAN_FATAL_ERROR);
3218                 }
3219         }
3220         rval = mptsas_accept_pkt(mpt, cmd);
3221 
3222         return (rval);
3223 }
3224 
3225 static int
3226 mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3227 {
3228         int             rval = TRAN_ACCEPT;
3229         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3230 
3231         NDBG1(("mptsas_accept_pkt: cmd=0x%p", (void *)cmd));
3232 
3233         ASSERT(mutex_owned(&mpt->m_mutex));
3234 
3235         if ((cmd->cmd_flags & CFLAG_PREPARED) == 0) {
3236                 rval = mptsas_prepare_pkt(cmd);
3237                 if (rval != TRAN_ACCEPT) {
3238                         cmd->cmd_flags &= ~CFLAG_TRANFLAG;
3239                         return (rval);
3240                 }
3241         }
3242 
3243         /*
3244          * reset the throttle if we were draining
3245          */
3246         if ((ptgt->m_t_ncmds == 0) &&
3247             (ptgt->m_t_throttle == DRAIN_THROTTLE)) {
3248                 NDBG23(("reset throttle"));
3249                 ASSERT(ptgt->m_reset_delay == 0);
3250                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
3251         }
3252 
3253         /*
3254          * If HBA is being reset, the DevHandles are being re-initialized,
3255          * which means that they could be invalid even if the target is still
3256          * attached.  Check if being reset and if DevHandle is being
3257          * re-initialized.  If this is the case, return BUSY so the I/O can be
3258          * retried later.
3259          */
3260         if ((ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) && mpt->m_in_reset) {
3261                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
3262                 if (cmd->cmd_flags & CFLAG_TXQ) {
3263                         mptsas_doneq_add(mpt, cmd);
3264                         mptsas_doneq_empty(mpt);
3265                         return (rval);
3266                 } else {
3267                         return (TRAN_BUSY);
3268                 }
3269         }
3270 
3271         /*
3272          * If device handle has already been invalidated, just
3273          * fail the command. In theory, command from scsi_vhci
3274          * client is impossible send down command with invalid
3275          * devhdl since devhdl is set after path offline, target
3276          * driver is not suppose to select a offlined path.
3277          */
3278         if (ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) {
3279                 NDBG20(("rejecting command, it might because invalid devhdl "
3280                     "request."));
3281                 mptsas_set_pkt_reason(mpt, cmd, CMD_DEV_GONE, STAT_TERMINATED);
3282                 if (cmd->cmd_flags & CFLAG_TXQ) {
3283                         mptsas_doneq_add(mpt, cmd);
3284                         mptsas_doneq_empty(mpt);
3285                         return (rval);
3286                 } else {
3287                         return (TRAN_FATAL_ERROR);
3288                 }
3289         }
3290         /*
3291          * The first case is the normal case.  mpt gets a command from the
3292          * target driver and starts it.
3293          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
3294          * commands is m_max_requests - 2.
3295          */
3296         if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
3297             (ptgt->m_t_throttle > HOLD_THROTTLE) &&
3298             (ptgt->m_t_ncmds < ptgt->m_t_throttle) &&
3299             (ptgt->m_reset_delay == 0) &&
3300             (ptgt->m_t_nwait == 0) &&
3301             ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0)) {
3302                 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
3303                         (void) mptsas_start_cmd(mpt, cmd);
3304                 } else {
3305                         mptsas_waitq_add(mpt, cmd);
3306                 }
3307         } else {
3308                 /*
3309                  * Add this pkt to the work queue
3310                  */
3311                 mptsas_waitq_add(mpt, cmd);
3312 
3313                 if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3314                         (void) mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
3315 
3316                         /*
3317                          * Only flush the doneq if this is not a TM
3318                          * cmd.  For TM cmds the flushing of the
3319                          * doneq will be done in those routines.
3320                          */
3321                         if ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
3322                                 mptsas_doneq_empty(mpt);
3323                         }
3324                 }
3325         }
3326         return (rval);
3327 }
3328 
3329 int
3330 mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
3331 {
3332         mptsas_slots_t *slots = mpt->m_active;
3333         uint_t slot, start_rotor;
3334         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3335 
3336         ASSERT(MUTEX_HELD(&mpt->m_mutex));
3337 
3338         /*
3339          * Account for reserved TM request slot and reserved SMID of 0.
3340          */
3341         ASSERT(slots->m_n_normal == (mpt->m_max_requests - 2));
3342 
3343         /*
3344          * Find the next available slot, beginning at m_rotor.  If no slot is
3345          * available, we'll return FALSE to indicate that.  This mechanism
3346          * considers only the normal slots, not the reserved slot 0 nor the
3347          * task management slot m_n_normal + 1.  The rotor is left to point to
3348          * the normal slot after the one we select, unless we select the last
3349          * normal slot in which case it returns to slot 1.
3350          */
3351         start_rotor = slots->m_rotor;
3352         do {
3353                 slot = slots->m_rotor++;
3354                 if (slots->m_rotor > slots->m_n_normal)
3355                         slots->m_rotor = 1;
3356 
3357                 if (slots->m_rotor == start_rotor)
3358                         break;
3359         } while (slots->m_slot[slot] != NULL);
3360 
3361         if (slots->m_slot[slot] != NULL)
3362                 return (FALSE);
3363 
3364         ASSERT(slot != 0 && slot <= slots->m_n_normal);
3365 
3366         cmd->cmd_slot = slot;
3367         slots->m_slot[slot] = cmd;
3368         mpt->m_ncmds++;
3369 
3370         /*
3371          * only increment per target ncmds if this is not a
3372          * command that has no target associated with it (i.e. a
3373          * event acknoledgment)
3374          */
3375         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
3376                 /*
3377                  * Expiration time is set in mptsas_start_cmd
3378                  */
3379                 ptgt->m_t_ncmds++;
3380                 cmd->cmd_active_expiration = 0;
3381         } else {
3382                 /*
3383                  * Initialize expiration time for passthrough commands,
3384                  */
3385                 cmd->cmd_active_expiration = gethrtime() +
3386                     (hrtime_t)cmd->cmd_pkt->pkt_time * NANOSEC;
3387         }
3388         return (TRUE);
3389 }
3390 
3391 /*
3392  * prepare the pkt:
3393  * the pkt may have been resubmitted or just reused so
3394  * initialize some fields and do some checks.
3395  */
3396 static int
3397 mptsas_prepare_pkt(mptsas_cmd_t *cmd)
3398 {
3399         struct scsi_pkt *pkt = CMD2PKT(cmd);
3400 
3401         NDBG1(("mptsas_prepare_pkt: cmd=0x%p", (void *)cmd));
3402 
3403         /*
3404          * Reinitialize some fields that need it; the packet may
3405          * have been resubmitted
3406          */
3407         pkt->pkt_reason = CMD_CMPLT;
3408         pkt->pkt_state = 0;
3409         pkt->pkt_statistics = 0;
3410         pkt->pkt_resid = 0;
3411         cmd->cmd_age = 0;
3412         cmd->cmd_pkt_flags = pkt->pkt_flags;
3413 
3414         /*
3415          * zero status byte.
3416          */
3417         *(pkt->pkt_scbp) = 0;
3418 
3419         if (cmd->cmd_flags & CFLAG_DMAVALID) {
3420                 pkt->pkt_resid = cmd->cmd_dmacount;
3421 
3422                 /*
3423                  * consistent packets need to be sync'ed first
3424                  * (only for data going out)
3425                  */
3426                 if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
3427                     (cmd->cmd_flags & CFLAG_DMASEND)) {
3428                         (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
3429                             DDI_DMA_SYNC_FORDEV);
3430                 }
3431         }
3432 
3433         cmd->cmd_flags =
3434             (cmd->cmd_flags & ~(CFLAG_TRANFLAG)) |
3435             CFLAG_PREPARED | CFLAG_IN_TRANSPORT;
3436 
3437         return (TRAN_ACCEPT);
3438 }
3439 
3440 /*
3441  * tran_init_pkt(9E) - allocate scsi_pkt(9S) for command
3442  *
3443  * One of three possibilities:
3444  *      - allocate scsi_pkt
3445  *      - allocate scsi_pkt and DMA resources
3446  *      - allocate DMA resources to an already-allocated pkt
3447  */
3448 static struct scsi_pkt *
3449 mptsas_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
3450     struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
3451     int (*callback)(), caddr_t arg)
3452 {
3453         mptsas_cmd_t            *cmd, *new_cmd;
3454         mptsas_t                *mpt = ADDR2MPT(ap);
3455         int                     failure = 1;
3456         uint_t                  oldcookiec;
3457         mptsas_target_t         *ptgt = NULL;
3458         int                     rval;
3459         mptsas_tgt_private_t    *tgt_private;
3460         int                     kf;
3461 
3462         kf = (callback == SLEEP_FUNC)? KM_SLEEP: KM_NOSLEEP;
3463 
3464         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
3465             tran_tgt_private;
3466         ASSERT(tgt_private != NULL);
3467         if (tgt_private == NULL) {
3468                 return (NULL);
3469         }
3470         ptgt = tgt_private->t_private;
3471         ASSERT(ptgt != NULL);
3472         if (ptgt == NULL)
3473                 return (NULL);
3474         ap->a_target = ptgt->m_devhdl;
3475         ap->a_lun = tgt_private->t_lun;
3476 
3477         ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC);
3478 #ifdef MPTSAS_TEST_EXTRN_ALLOC
3479         statuslen *= 100; tgtlen *= 4;
3480 #endif
3481         NDBG3(("mptsas_scsi_init_pkt:\n"
3482             "\ttgt=%d in=0x%p bp=0x%p clen=%d slen=%d tlen=%d flags=%x",
3483             ap->a_target, (void *)pkt, (void *)bp,
3484             cmdlen, statuslen, tgtlen, flags));
3485 
3486         /*
3487          * Allocate the new packet.
3488          */
3489         if (pkt == NULL) {
3490                 ddi_dma_handle_t        save_dma_handle;
3491                 ddi_dma_handle_t        save_arq_dma_handle;
3492                 struct buf              *save_arq_bp;
3493                 ddi_dma_cookie_t        save_arqcookie;
3494 
3495                 cmd = kmem_cache_alloc(mpt->m_kmem_cache, kf);
3496 
3497                 if (cmd) {
3498                         save_dma_handle = cmd->cmd_dmahandle;
3499                         save_arq_dma_handle = cmd->cmd_arqhandle;
3500                         save_arq_bp = cmd->cmd_arq_buf;
3501                         save_arqcookie = cmd->cmd_arqcookie;
3502                         bzero(cmd, sizeof (*cmd) + scsi_pkt_size());
3503                         cmd->cmd_dmahandle = save_dma_handle;
3504                         cmd->cmd_arqhandle = save_arq_dma_handle;
3505                         cmd->cmd_arq_buf = save_arq_bp;
3506                         cmd->cmd_arqcookie = save_arqcookie;
3507 
3508                         pkt = (void *)((uchar_t *)cmd +
3509                             sizeof (struct mptsas_cmd));
3510                         pkt->pkt_ha_private = (opaque_t)cmd;
3511                         pkt->pkt_address = *ap;
3512                         pkt->pkt_private = (opaque_t)cmd->cmd_pkt_private;
3513                         pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb;
3514                         pkt->pkt_cdbp = (opaque_t)&cmd->cmd_cdb;
3515                         cmd->cmd_pkt = (struct scsi_pkt *)pkt;
3516                         cmd->cmd_cdblen = (uchar_t)cmdlen;
3517                         cmd->cmd_scblen = statuslen;
3518                         cmd->cmd_rqslen = SENSE_LENGTH;
3519                         cmd->cmd_tgt_addr = ptgt;
3520                         failure = 0;
3521                 }
3522 
3523                 if (failure || (cmdlen > sizeof (cmd->cmd_cdb)) ||
3524                     (tgtlen > PKT_PRIV_LEN) ||
3525                     (statuslen > EXTCMDS_STATUS_SIZE)) {
3526                         if (failure == 0) {
3527                                 /*
3528                                  * if extern alloc fails, all will be
3529                                  * deallocated, including cmd
3530                                  */
3531                                 failure = mptsas_pkt_alloc_extern(mpt, cmd,
3532                                     cmdlen, tgtlen, statuslen, kf);
3533                         }
3534                         if (failure) {
3535                                 /*
3536                                  * if extern allocation fails, it will
3537                                  * deallocate the new pkt as well
3538                                  */
3539                                 return (NULL);
3540                         }
3541                 }
3542                 new_cmd = cmd;
3543 
3544         } else {
3545                 cmd = PKT2CMD(pkt);
3546                 new_cmd = NULL;
3547         }
3548 
3549 
3550         /* grab cmd->cmd_cookiec here as oldcookiec */
3551 
3552         oldcookiec = cmd->cmd_cookiec;
3553 
3554         /*
3555          * If the dma was broken up into PARTIAL transfers cmd_nwin will be
3556          * greater than 0 and we'll need to grab the next dma window
3557          */
3558         /*
3559          * SLM-not doing extra command frame right now; may add later
3560          */
3561 
3562         if (cmd->cmd_nwin > 0) {
3563 
3564                 /*
3565                  * Make sure we havn't gone past the the total number
3566                  * of windows
3567                  */
3568                 if (++cmd->cmd_winindex >= cmd->cmd_nwin) {
3569                         return (NULL);
3570                 }
3571                 if (ddi_dma_getwin(cmd->cmd_dmahandle, cmd->cmd_winindex,
3572                     &cmd->cmd_dma_offset, &cmd->cmd_dma_len,
3573                     &cmd->cmd_cookie, &cmd->cmd_cookiec) == DDI_FAILURE) {
3574                         return (NULL);
3575                 }
3576                 goto get_dma_cookies;
3577         }
3578 
3579 
3580         if (flags & PKT_XARQ) {
3581                 cmd->cmd_flags |= CFLAG_XARQ;
3582         }
3583 
3584         /*
3585          * DMA resource allocation.  This version assumes your
3586          * HBA has some sort of bus-mastering or onboard DMA capability, with a
3587          * scatter-gather list of length MPTSAS_MAX_DMA_SEGS, as given in the
3588          * ddi_dma_attr_t structure and passed to scsi_impl_dmaget.
3589          */
3590         if (bp && (bp->b_bcount != 0) &&
3591             (cmd->cmd_flags & CFLAG_DMAVALID) == 0) {
3592 
3593                 int     cnt, dma_flags;
3594                 mptti_t *dmap;          /* ptr to the S/G list */
3595 
3596                 /*
3597                  * Set up DMA memory and position to the next DMA segment.
3598                  */
3599                 ASSERT(cmd->cmd_dmahandle != NULL);
3600 
3601                 if (bp->b_flags & B_READ) {
3602                         dma_flags = DDI_DMA_READ;
3603                         cmd->cmd_flags &= ~CFLAG_DMASEND;
3604                 } else {
3605                         dma_flags = DDI_DMA_WRITE;
3606                         cmd->cmd_flags |= CFLAG_DMASEND;
3607                 }
3608                 if (flags & PKT_CONSISTENT) {
3609                         cmd->cmd_flags |= CFLAG_CMDIOPB;
3610                         dma_flags |= DDI_DMA_CONSISTENT;
3611                 }
3612 
3613                 if (flags & PKT_DMA_PARTIAL) {
3614                         dma_flags |= DDI_DMA_PARTIAL;
3615                 }
3616 
3617                 /*
3618                  * workaround for byte hole issue on psycho and
3619                  * schizo pre 2.1
3620                  */
3621                 if ((bp->b_flags & B_READ) && ((bp->b_flags &
3622                     (B_PAGEIO|B_REMAPPED)) != B_PAGEIO) &&
3623                     ((uintptr_t)bp->b_un.b_addr & 0x7)) {
3624                         dma_flags |= DDI_DMA_CONSISTENT;
3625                 }
3626 
3627                 rval = ddi_dma_buf_bind_handle(cmd->cmd_dmahandle, bp,
3628                     dma_flags, callback, arg,
3629                     &cmd->cmd_cookie, &cmd->cmd_cookiec);
3630                 if (rval == DDI_DMA_PARTIAL_MAP) {
3631                         (void) ddi_dma_numwin(cmd->cmd_dmahandle,
3632                             &cmd->cmd_nwin);
3633                         cmd->cmd_winindex = 0;
3634                         (void) ddi_dma_getwin(cmd->cmd_dmahandle,
3635                             cmd->cmd_winindex, &cmd->cmd_dma_offset,
3636                             &cmd->cmd_dma_len, &cmd->cmd_cookie,
3637                             &cmd->cmd_cookiec);
3638                 } else if (rval && (rval != DDI_DMA_MAPPED)) {
3639                         switch (rval) {
3640                         case DDI_DMA_NORESOURCES:
3641                                 bioerror(bp, 0);
3642                                 break;
3643                         case DDI_DMA_BADATTR:
3644                         case DDI_DMA_NOMAPPING:
3645                                 bioerror(bp, EFAULT);
3646                                 break;
3647                         case DDI_DMA_TOOBIG:
3648                         default:
3649                                 bioerror(bp, EINVAL);
3650                                 break;
3651                         }
3652                         cmd->cmd_flags &= ~CFLAG_DMAVALID;
3653                         if (new_cmd) {
3654                                 mptsas_scsi_destroy_pkt(ap, pkt);
3655                         }
3656                         return ((struct scsi_pkt *)NULL);
3657                 }
3658 
3659 get_dma_cookies:
3660                 cmd->cmd_flags |= CFLAG_DMAVALID;
3661                 ASSERT(cmd->cmd_cookiec > 0);
3662 
3663                 if (cmd->cmd_cookiec > MPTSAS_MAX_CMD_SEGS) {
3664                         mptsas_log(mpt, CE_NOTE, "large cookiec received %d\n",
3665                             cmd->cmd_cookiec);
3666                         bioerror(bp, EINVAL);
3667                         if (new_cmd) {
3668                                 mptsas_scsi_destroy_pkt(ap, pkt);
3669                         }
3670                         return ((struct scsi_pkt *)NULL);
3671                 }
3672 
3673                 /*
3674                  * Allocate extra SGL buffer if needed.
3675                  */
3676                 if ((cmd->cmd_cookiec > MPTSAS_MAX_FRAME_SGES64(mpt)) &&
3677                     (cmd->cmd_extra_frames == NULL)) {
3678                         if (mptsas_alloc_extra_sgl_frame(mpt, cmd) ==
3679                             DDI_FAILURE) {
3680                                 mptsas_log(mpt, CE_WARN, "MPT SGL mem alloc "
3681                                     "failed");
3682                                 bioerror(bp, ENOMEM);
3683                                 if (new_cmd) {
3684                                         mptsas_scsi_destroy_pkt(ap, pkt);
3685                                 }
3686                                 return ((struct scsi_pkt *)NULL);
3687                         }
3688                 }
3689 
3690                 /*
3691                  * Always use scatter-gather transfer
3692                  * Use the loop below to store physical addresses of
3693                  * DMA segments, from the DMA cookies, into your HBA's
3694                  * scatter-gather list.
3695                  * We need to ensure we have enough kmem alloc'd
3696                  * for the sg entries since we are no longer using an
3697                  * array inside mptsas_cmd_t.
3698                  *
3699                  * We check cmd->cmd_cookiec against oldcookiec so
3700                  * the scatter-gather list is correctly allocated
3701                  */
3702 
3703                 if (oldcookiec != cmd->cmd_cookiec) {
3704                         if (cmd->cmd_sg != (mptti_t *)NULL) {
3705                                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) *
3706                                     oldcookiec);
3707                                 cmd->cmd_sg = NULL;
3708                         }
3709                 }
3710 
3711                 if (cmd->cmd_sg == (mptti_t *)NULL) {
3712                         cmd->cmd_sg = kmem_alloc((size_t)(sizeof (mptti_t)*
3713                             cmd->cmd_cookiec), kf);
3714 
3715                         if (cmd->cmd_sg == (mptti_t *)NULL) {
3716                                 mptsas_log(mpt, CE_WARN,
3717                                     "unable to kmem_alloc enough memory "
3718                                     "for scatter/gather list");
3719                 /*
3720                  * if we have an ENOMEM condition we need to behave
3721                  * the same way as the rest of this routine
3722                  */
3723 
3724                                 bioerror(bp, ENOMEM);
3725                                 if (new_cmd) {
3726                                         mptsas_scsi_destroy_pkt(ap, pkt);
3727                                 }
3728                                 return ((struct scsi_pkt *)NULL);
3729                         }
3730                 }
3731 
3732                 dmap = cmd->cmd_sg;
3733 
3734                 ASSERT(cmd->cmd_cookie.dmac_size != 0);
3735 
3736                 /*
3737                  * store the first segment into the S/G list
3738                  */
3739                 dmap->count = cmd->cmd_cookie.dmac_size;
3740                 dmap->addr.address64.Low = (uint32_t)
3741                     (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3742                 dmap->addr.address64.High = (uint32_t)
3743                     (cmd->cmd_cookie.dmac_laddress >> 32);
3744 
3745                 /*
3746                  * dmacount counts the size of the dma for this window
3747                  * (if partial dma is being used).  totaldmacount
3748                  * keeps track of the total amount of dma we have
3749                  * transferred for all the windows (needed to calculate
3750                  * the resid value below).
3751                  */
3752                 cmd->cmd_dmacount = cmd->cmd_cookie.dmac_size;
3753                 cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3754 
3755                 /*
3756                  * We already stored the first DMA scatter gather segment,
3757                  * start at 1 if we need to store more.
3758                  */
3759                 for (cnt = 1; cnt < cmd->cmd_cookiec; cnt++) {
3760                         /*
3761                          * Get next DMA cookie
3762                          */
3763                         ddi_dma_nextcookie(cmd->cmd_dmahandle,
3764                             &cmd->cmd_cookie);
3765                         dmap++;
3766 
3767                         cmd->cmd_dmacount += cmd->cmd_cookie.dmac_size;
3768                         cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3769 
3770                         /*
3771                          * store the segment parms into the S/G list
3772                          */
3773                         dmap->count = cmd->cmd_cookie.dmac_size;
3774                         dmap->addr.address64.Low = (uint32_t)
3775                             (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3776                         dmap->addr.address64.High = (uint32_t)
3777                             (cmd->cmd_cookie.dmac_laddress >> 32);
3778                 }
3779 
3780                 /*
3781                  * If this was partially allocated we set the resid
3782                  * the amount of data NOT transferred in this window
3783                  * If there is only one window, the resid will be 0
3784                  */
3785                 pkt->pkt_resid = (bp->b_bcount - cmd->cmd_totaldmacount);
3786                 NDBG16(("mptsas_dmaget: cmd_dmacount=%d.", cmd->cmd_dmacount));
3787         }
3788         return (pkt);
3789 }
3790 
3791 /*
3792  * tran_destroy_pkt(9E) - scsi_pkt(9s) deallocation
3793  *
3794  * Notes:
3795  *      - also frees DMA resources if allocated
3796  *      - implicit DMA synchonization
3797  */
3798 static void
3799 mptsas_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
3800 {
3801         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
3802         mptsas_t        *mpt = ADDR2MPT(ap);
3803 
3804         NDBG3(("mptsas_scsi_destroy_pkt: target=%d pkt=0x%p",
3805             ap->a_target, (void *)pkt));
3806 
3807         if (cmd->cmd_flags & CFLAG_DMAVALID) {
3808                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
3809                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
3810         }
3811 
3812         if (cmd->cmd_sg) {
3813                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) * cmd->cmd_cookiec);
3814                 cmd->cmd_sg = NULL;
3815         }
3816 
3817         mptsas_free_extra_sgl_frame(mpt, cmd);
3818 
3819         if ((cmd->cmd_flags &
3820             (CFLAG_FREE | CFLAG_CDBEXTERN | CFLAG_PRIVEXTERN |
3821             CFLAG_SCBEXTERN)) == 0) {
3822                 cmd->cmd_flags = CFLAG_FREE;
3823                 kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
3824         } else {
3825                 mptsas_pkt_destroy_extern(mpt, cmd);
3826         }
3827 }
3828 
3829 /*
3830  * kmem cache constructor and destructor:
3831  * When constructing, we bzero the cmd and allocate the dma handle
3832  * When destructing, just free the dma handle
3833  */
3834 static int
3835 mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags)
3836 {
3837         mptsas_cmd_t            *cmd = buf;
3838         mptsas_t                *mpt  = cdrarg;
3839         struct scsi_address     ap;
3840         uint_t                  cookiec;
3841         ddi_dma_attr_t          arq_dma_attr;
3842         int                     (*callback)(caddr_t);
3843 
3844         callback = (kmflags == KM_SLEEP)? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
3845 
3846         NDBG4(("mptsas_kmem_cache_constructor"));
3847 
3848         ap.a_hba_tran = mpt->m_tran;
3849         ap.a_target = 0;
3850         ap.a_lun = 0;
3851 
3852         /*
3853          * allocate a dma handle
3854          */
3855         if ((ddi_dma_alloc_handle(mpt->m_dip, &mpt->m_io_dma_attr, callback,
3856             NULL, &cmd->cmd_dmahandle)) != DDI_SUCCESS) {
3857                 cmd->cmd_dmahandle = NULL;
3858                 return (-1);
3859         }
3860 
3861         cmd->cmd_arq_buf = scsi_alloc_consistent_buf(&ap, (struct buf *)NULL,
3862             SENSE_LENGTH, B_READ, callback, NULL);
3863         if (cmd->cmd_arq_buf == NULL) {
3864                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3865                 cmd->cmd_dmahandle = NULL;
3866                 return (-1);
3867         }
3868 
3869         /*
3870          * allocate a arq handle
3871          */
3872         arq_dma_attr = mpt->m_msg_dma_attr;
3873         arq_dma_attr.dma_attr_sgllen = 1;
3874         if ((ddi_dma_alloc_handle(mpt->m_dip, &arq_dma_attr, callback,
3875             NULL, &cmd->cmd_arqhandle)) != DDI_SUCCESS) {
3876                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3877                 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3878                 cmd->cmd_dmahandle = NULL;
3879                 cmd->cmd_arqhandle = NULL;
3880                 return (-1);
3881         }
3882 
3883         if (ddi_dma_buf_bind_handle(cmd->cmd_arqhandle,
3884             cmd->cmd_arq_buf, (DDI_DMA_READ | DDI_DMA_CONSISTENT),
3885             callback, NULL, &cmd->cmd_arqcookie, &cookiec) != DDI_SUCCESS) {
3886                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3887                 ddi_dma_free_handle(&cmd->cmd_arqhandle);
3888                 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3889                 cmd->cmd_dmahandle = NULL;
3890                 cmd->cmd_arqhandle = NULL;
3891                 cmd->cmd_arq_buf = NULL;
3892                 return (-1);
3893         }
3894 
3895         return (0);
3896 }
3897 
3898 static void
3899 mptsas_kmem_cache_destructor(void *buf, void *cdrarg)
3900 {
3901 #ifndef __lock_lint
3902         _NOTE(ARGUNUSED(cdrarg))
3903 #endif
3904         mptsas_cmd_t    *cmd = buf;
3905 
3906         NDBG4(("mptsas_kmem_cache_destructor"));
3907 
3908         if (cmd->cmd_arqhandle) {
3909                 (void) ddi_dma_unbind_handle(cmd->cmd_arqhandle);
3910                 ddi_dma_free_handle(&cmd->cmd_arqhandle);
3911                 cmd->cmd_arqhandle = NULL;
3912         }
3913         if (cmd->cmd_arq_buf) {
3914                 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3915                 cmd->cmd_arq_buf = NULL;
3916         }
3917         if (cmd->cmd_dmahandle) {
3918                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3919                 cmd->cmd_dmahandle = NULL;
3920         }
3921 }
3922 
3923 static int
3924 mptsas_cache_frames_constructor(void *buf, void *cdrarg, int kmflags)
3925 {
3926         mptsas_cache_frames_t   *p = buf;
3927         mptsas_t                *mpt = cdrarg;
3928         ddi_dma_attr_t          frame_dma_attr;
3929         size_t                  mem_size, alloc_len;
3930         ddi_dma_cookie_t        cookie;
3931         uint_t                  ncookie;
3932         int (*callback)(caddr_t) = (kmflags == KM_SLEEP)
3933             ? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
3934 
3935         frame_dma_attr = mpt->m_msg_dma_attr;
3936         frame_dma_attr.dma_attr_align = 0x10;
3937         frame_dma_attr.dma_attr_sgllen = 1;
3938 
3939         if (ddi_dma_alloc_handle(mpt->m_dip, &frame_dma_attr, callback, NULL,
3940             &p->m_dma_hdl) != DDI_SUCCESS) {
3941                 mptsas_log(mpt, CE_WARN, "Unable to allocate dma handle for"
3942                     " extra SGL.");
3943                 return (DDI_FAILURE);
3944         }
3945 
3946         mem_size = (mpt->m_max_request_frames - 1) * mpt->m_req_frame_size;
3947 
3948         if (ddi_dma_mem_alloc(p->m_dma_hdl, mem_size, &mpt->m_dev_acc_attr,
3949             DDI_DMA_CONSISTENT, callback, NULL, (caddr_t *)&p->m_frames_addr,
3950             &alloc_len, &p->m_acc_hdl) != DDI_SUCCESS) {
3951                 ddi_dma_free_handle(&p->m_dma_hdl);
3952                 p->m_dma_hdl = NULL;
3953                 mptsas_log(mpt, CE_WARN, "Unable to allocate dma memory for"
3954                     " extra SGL.");
3955                 return (DDI_FAILURE);
3956         }
3957 
3958         if (ddi_dma_addr_bind_handle(p->m_dma_hdl, NULL, p->m_frames_addr,
3959             alloc_len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, callback, NULL,
3960             &cookie, &ncookie) != DDI_DMA_MAPPED) {
3961                 (void) ddi_dma_mem_free(&p->m_acc_hdl);
3962                 ddi_dma_free_handle(&p->m_dma_hdl);
3963                 p->m_dma_hdl = NULL;
3964                 mptsas_log(mpt, CE_WARN, "Unable to bind DMA resources for"
3965                     " extra SGL");
3966                 return (DDI_FAILURE);
3967         }
3968 
3969         /*
3970          * Store the SGL memory address.  This chip uses this
3971          * address to dma to and from the driver.  The second
3972          * address is the address mpt uses to fill in the SGL.
3973          */
3974         p->m_phys_addr = cookie.dmac_address;
3975 
3976         return (DDI_SUCCESS);
3977 }
3978 
3979 static void
3980 mptsas_cache_frames_destructor(void *buf, void *cdrarg)
3981 {
3982 #ifndef __lock_lint
3983         _NOTE(ARGUNUSED(cdrarg))
3984 #endif
3985         mptsas_cache_frames_t   *p = buf;
3986         if (p->m_dma_hdl != NULL) {
3987                 (void) ddi_dma_unbind_handle(p->m_dma_hdl);
3988                 (void) ddi_dma_mem_free(&p->m_acc_hdl);
3989                 ddi_dma_free_handle(&p->m_dma_hdl);
3990                 p->m_phys_addr = NULL;
3991                 p->m_frames_addr = NULL;
3992                 p->m_dma_hdl = NULL;
3993                 p->m_acc_hdl = NULL;
3994         }
3995 
3996 }
3997 
3998 /*
3999  * allocate and deallocate external pkt space (ie. not part of mptsas_cmd)
4000  * for non-standard length cdb, pkt_private, status areas
4001  * if allocation fails, then deallocate all external space and the pkt
4002  */
4003 /* ARGSUSED */
4004 static int
4005 mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
4006     int cmdlen, int tgtlen, int statuslen, int kf)
4007 {
4008         caddr_t                 cdbp, scbp, tgt;
4009         int                     (*callback)(caddr_t) = (kf == KM_SLEEP) ?
4010             DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
4011         struct scsi_address     ap;
4012         size_t                  senselength;
4013         ddi_dma_attr_t          ext_arq_dma_attr;
4014         uint_t                  cookiec;
4015 
4016         NDBG3(("mptsas_pkt_alloc_extern: "
4017             "cmd=0x%p cmdlen=%d tgtlen=%d statuslen=%d kf=%x",
4018             (void *)cmd, cmdlen, tgtlen, statuslen, kf));
4019 
4020         tgt = cdbp = scbp = NULL;
4021         cmd->cmd_scblen              = statuslen;
4022         cmd->cmd_privlen     = (uchar_t)tgtlen;
4023 
4024         if (cmdlen > sizeof (cmd->cmd_cdb)) {
4025                 if ((cdbp = kmem_zalloc((size_t)cmdlen, kf)) == NULL) {
4026                         goto fail;
4027                 }
4028                 cmd->cmd_pkt->pkt_cdbp = (opaque_t)cdbp;
4029                 cmd->cmd_flags |= CFLAG_CDBEXTERN;
4030         }
4031         if (tgtlen > PKT_PRIV_LEN) {
4032                 if ((tgt = kmem_zalloc((size_t)tgtlen, kf)) == NULL) {
4033                         goto fail;
4034                 }
4035                 cmd->cmd_flags |= CFLAG_PRIVEXTERN;
4036                 cmd->cmd_pkt->pkt_private = tgt;
4037         }
4038         if (statuslen > EXTCMDS_STATUS_SIZE) {
4039                 if ((scbp = kmem_zalloc((size_t)statuslen, kf)) == NULL) {
4040                         goto fail;
4041                 }
4042                 cmd->cmd_flags |= CFLAG_SCBEXTERN;
4043                 cmd->cmd_pkt->pkt_scbp = (opaque_t)scbp;
4044 
4045                 /* allocate sense data buf for DMA */
4046 
4047                 senselength = statuslen - MPTSAS_GET_ITEM_OFF(
4048                     struct scsi_arq_status, sts_sensedata);
4049                 cmd->cmd_rqslen = (uchar_t)senselength;
4050 
4051                 ap.a_hba_tran = mpt->m_tran;
4052                 ap.a_target = 0;
4053                 ap.a_lun = 0;
4054 
4055                 cmd->cmd_ext_arq_buf = scsi_alloc_consistent_buf(&ap,
4056                     (struct buf *)NULL, senselength, B_READ,
4057                     callback, NULL);
4058 
4059                 if (cmd->cmd_ext_arq_buf == NULL) {
4060                         goto fail;
4061                 }
4062                 /*
4063                  * allocate a extern arq handle and bind the buf
4064                  */
4065                 ext_arq_dma_attr = mpt->m_msg_dma_attr;
4066                 ext_arq_dma_attr.dma_attr_sgllen = 1;
4067                 if ((ddi_dma_alloc_handle(mpt->m_dip,
4068                     &ext_arq_dma_attr, callback,
4069                     NULL, &cmd->cmd_ext_arqhandle)) != DDI_SUCCESS) {
4070                         goto fail;
4071                 }
4072 
4073                 if (ddi_dma_buf_bind_handle(cmd->cmd_ext_arqhandle,
4074                     cmd->cmd_ext_arq_buf, (DDI_DMA_READ | DDI_DMA_CONSISTENT),
4075                     callback, NULL, &cmd->cmd_ext_arqcookie,
4076                     &cookiec)
4077                     != DDI_SUCCESS) {
4078                         goto fail;
4079                 }
4080                 cmd->cmd_flags |= CFLAG_EXTARQBUFVALID;
4081         }
4082         return (0);
4083 fail:
4084         mptsas_pkt_destroy_extern(mpt, cmd);
4085         return (1);
4086 }
4087 
4088 /*
4089  * deallocate external pkt space and deallocate the pkt
4090  */
4091 static void
4092 mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd)
4093 {
4094         NDBG3(("mptsas_pkt_destroy_extern: cmd=0x%p", (void *)cmd));
4095 
4096         if (cmd->cmd_flags & CFLAG_FREE) {
4097                 mptsas_log(mpt, CE_PANIC,
4098                     "mptsas_pkt_destroy_extern: freeing free packet");
4099                 _NOTE(NOT_REACHED)
4100                 /* NOTREACHED */
4101         }
4102         if (cmd->cmd_flags & CFLAG_CDBEXTERN) {
4103                 kmem_free(cmd->cmd_pkt->pkt_cdbp, (size_t)cmd->cmd_cdblen);
4104         }
4105         if (cmd->cmd_flags & CFLAG_SCBEXTERN) {
4106                 kmem_free(cmd->cmd_pkt->pkt_scbp, (size_t)cmd->cmd_scblen);
4107                 if (cmd->cmd_flags & CFLAG_EXTARQBUFVALID) {
4108                         (void) ddi_dma_unbind_handle(cmd->cmd_ext_arqhandle);
4109                 }
4110                 if (cmd->cmd_ext_arqhandle) {
4111                         ddi_dma_free_handle(&cmd->cmd_ext_arqhandle);
4112                         cmd->cmd_ext_arqhandle = NULL;
4113                 }
4114                 if (cmd->cmd_ext_arq_buf)
4115                         scsi_free_consistent_buf(cmd->cmd_ext_arq_buf);
4116         }
4117         if (cmd->cmd_flags & CFLAG_PRIVEXTERN) {
4118                 kmem_free(cmd->cmd_pkt->pkt_private, (size_t)cmd->cmd_privlen);
4119         }
4120         cmd->cmd_flags = CFLAG_FREE;
4121         kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
4122 }
4123 
4124 /*
4125  * tran_sync_pkt(9E) - explicit DMA synchronization
4126  */
4127 /*ARGSUSED*/
4128 static void
4129 mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
4130 {
4131         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
4132 
4133         NDBG3(("mptsas_scsi_sync_pkt: target=%d, pkt=0x%p",
4134             ap->a_target, (void *)pkt));
4135 
4136         if (cmd->cmd_dmahandle) {
4137                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4138                     (cmd->cmd_flags & CFLAG_DMASEND) ?
4139                     DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
4140         }
4141 }
4142 
4143 /*
4144  * tran_dmafree(9E) - deallocate DMA resources allocated for command
4145  */
4146 /*ARGSUSED*/
4147 static void
4148 mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
4149 {
4150         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
4151         mptsas_t        *mpt = ADDR2MPT(ap);
4152 
4153         NDBG3(("mptsas_scsi_dmafree: target=%d pkt=0x%p",
4154             ap->a_target, (void *)pkt));
4155 
4156         if (cmd->cmd_flags & CFLAG_DMAVALID) {
4157                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
4158                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
4159         }
4160 
4161         if (cmd->cmd_flags & CFLAG_EXTARQBUFVALID) {
4162                 (void) ddi_dma_unbind_handle(cmd->cmd_ext_arqhandle);
4163                 cmd->cmd_flags &= ~CFLAG_EXTARQBUFVALID;
4164         }
4165 
4166         mptsas_free_extra_sgl_frame(mpt, cmd);
4167 }
4168 
4169 static void
4170 mptsas_pkt_comp(struct scsi_pkt *pkt, mptsas_cmd_t *cmd)
4171 {
4172         if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
4173             (!(cmd->cmd_flags & CFLAG_DMASEND))) {
4174                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4175                     DDI_DMA_SYNC_FORCPU);
4176         }
4177         (*pkt->pkt_comp)(pkt);
4178 }
4179 
4180 static void
4181 mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd, uint32_t *control,
4182         pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4183 {
4184         uint_t                  cookiec;
4185         mptti_t                 *dmap;
4186         uint32_t                flags;
4187         pMpi2SGESimple64_t      sge;
4188         pMpi2SGEChain64_t       sgechain;
4189         ASSERT(cmd->cmd_flags & CFLAG_DMAVALID);
4190 
4191         /*
4192          * Save the number of entries in the DMA
4193          * Scatter/Gather list
4194          */
4195         cookiec = cmd->cmd_cookiec;
4196 
4197         NDBG1(("mptsas_sge_setup: cookiec=%d", cookiec));
4198 
4199         /*
4200          * Set read/write bit in control.
4201          */
4202         if (cmd->cmd_flags & CFLAG_DMASEND) {
4203                 *control |= MPI2_SCSIIO_CONTROL_WRITE;
4204         } else {
4205                 *control |= MPI2_SCSIIO_CONTROL_READ;
4206         }
4207 
4208         ddi_put32(acc_hdl, &frame->DataLength, cmd->cmd_dmacount);
4209 
4210         /*
4211          * We have 2 cases here.  First where we can fit all the
4212          * SG elements into the main frame, and the case
4213          * where we can't.
4214          * If we have more cookies than we can attach to a frame
4215          * we will need to use a chain element to point
4216          * a location of memory where the rest of the S/G
4217          * elements reside.
4218          */
4219         if (cookiec <= MPTSAS_MAX_FRAME_SGES64(mpt)) {
4220                 dmap = cmd->cmd_sg;
4221                 sge = (pMpi2SGESimple64_t)(&frame->SGL);
4222                 while (cookiec--) {
4223                         ddi_put32(acc_hdl,
4224                             &sge->Address.Low, dmap->addr.address64.Low);
4225                         ddi_put32(acc_hdl,
4226                             &sge->Address.High, dmap->addr.address64.High);
4227                         ddi_put32(acc_hdl, &sge->FlagsLength,
4228                             dmap->count);
4229                         flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4230                         flags |= ((uint32_t)
4231                             (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4232                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4233                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4234                             MPI2_SGE_FLAGS_SHIFT);
4235 
4236                         /*
4237                          * If this is the last cookie, we set the flags
4238                          * to indicate so
4239                          */
4240                         if (cookiec == 0) {
4241                                 flags |=
4242                                     ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT
4243                                     | MPI2_SGE_FLAGS_END_OF_BUFFER
4244                                     | MPI2_SGE_FLAGS_END_OF_LIST) <<
4245                                     MPI2_SGE_FLAGS_SHIFT);
4246                         }
4247                         if (cmd->cmd_flags & CFLAG_DMASEND) {
4248                                 flags |= (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4249                                     MPI2_SGE_FLAGS_SHIFT);
4250                         } else {
4251                                 flags |= (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4252                                     MPI2_SGE_FLAGS_SHIFT);
4253                         }
4254                         ddi_put32(acc_hdl, &sge->FlagsLength, flags);
4255                         dmap++;
4256                         sge++;
4257                 }
4258         } else {
4259                 /*
4260                  * Hereby we start to deal with multiple frames.
4261                  * The process is as follows:
4262                  * 1. Determine how many frames are needed for SGL element
4263                  *    storage; Note that all frames are stored in contiguous
4264                  *    memory space and in 64-bit DMA mode each element is
4265                  *    3 double-words (12 bytes) long.
4266                  * 2. Fill up the main frame. We need to do this separately
4267                  *    since it contains the SCSI IO request header and needs
4268                  *    dedicated processing. Note that the last 4 double-words
4269                  *    of the SCSI IO header is for SGL element storage
4270                  *    (MPI2_SGE_IO_UNION).
4271                  * 3. Fill the chain element in the main frame, so the DMA
4272                  *    engine can use the following frames.
4273                  * 4. Enter a loop to fill the remaining frames. Note that the
4274                  *    last frame contains no chain element.  The remaining
4275                  *    frames go into the mpt SGL buffer allocated on the fly,
4276                  *    not immediately following the main message frame, as in
4277                  *    Gen1.
4278                  * Some restrictions:
4279                  * 1. For 64-bit DMA, the simple element and chain element
4280                  *    are both of 3 double-words (12 bytes) in size, even
4281                  *    though all frames are stored in the first 4G of mem
4282                  *    range and the higher 32-bits of the address are always 0.
4283                  * 2. On some controllers (like the 1064/1068), a frame can
4284                  *    hold SGL elements with the last 1 or 2 double-words
4285                  *    (4 or 8 bytes) un-used. On these controllers, we should
4286                  *    recognize that there's not enough room for another SGL
4287                  *    element and move the sge pointer to the next frame.
4288                  */
4289                 int             i, j, k, l, frames, sgemax;
4290                 int             temp;
4291                 uint8_t         chainflags;
4292                 uint16_t        chainlength;
4293                 mptsas_cache_frames_t *p;
4294 
4295                 /*
4296                  * Sgemax is the number of SGE's that will fit
4297                  * each extra frame and frames is total
4298                  * number of frames we'll need.  1 sge entry per
4299                  * frame is reseverd for the chain element thus the -1 below.
4300                  */
4301                 sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_SGE_SIMPLE64))
4302                     - 1);
4303                 temp = (cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) / sgemax;
4304 
4305                 /*
4306                  * A little check to see if we need to round up the number
4307                  * of frames we need
4308                  */
4309                 if ((cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) - (temp *
4310                     sgemax) > 1) {
4311                         frames = (temp + 1);
4312                 } else {
4313                         frames = temp;
4314                 }
4315                 dmap = cmd->cmd_sg;
4316                 sge = (pMpi2SGESimple64_t)(&frame->SGL);
4317 
4318                 /*
4319                  * First fill in the main frame
4320                  */
4321                 for (j = 1; j < MPTSAS_MAX_FRAME_SGES64(mpt); j++) {
4322                         ddi_put32(acc_hdl, &sge->Address.Low,
4323                             dmap->addr.address64.Low);
4324                         ddi_put32(acc_hdl, &sge->Address.High,
4325                             dmap->addr.address64.High);
4326                         ddi_put32(acc_hdl, &sge->FlagsLength, dmap->count);
4327                         flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4328                         flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4329                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4330                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4331                             MPI2_SGE_FLAGS_SHIFT);
4332 
4333                         /*
4334                          * If this is the last SGE of this frame
4335                          * we set the end of list flag
4336                          */
4337                         if (j == (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) {
4338                                 flags |= ((uint32_t)
4339                                     (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4340                                     MPI2_SGE_FLAGS_SHIFT);
4341                         }
4342                         if (cmd->cmd_flags & CFLAG_DMASEND) {
4343                                 flags |=
4344                                     (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4345                                     MPI2_SGE_FLAGS_SHIFT);
4346                         } else {
4347                                 flags |=
4348                                     (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4349                                     MPI2_SGE_FLAGS_SHIFT);
4350                         }
4351                         ddi_put32(acc_hdl, &sge->FlagsLength, flags);
4352                         dmap++;
4353                         sge++;
4354                 }
4355 
4356                 /*
4357                  * Fill in the chain element in the main frame.
4358                  * About calculation on ChainOffset:
4359                  * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
4360                  *    in the end reserved for SGL element storage
4361                  *    (MPI2_SGE_IO_UNION); we should count it in our
4362                  *    calculation.  See its definition in the header file.
4363                  * 2. Constant j is the counter of the current SGL element
4364                  *    that will be processed, and (j - 1) is the number of
4365                  *    SGL elements that have been processed (stored in the
4366                  *    main frame).
4367                  * 3. ChainOffset value should be in units of double-words (4
4368                  *    bytes) so the last value should be divided by 4.
4369                  */
4370                 ddi_put8(acc_hdl, &frame->ChainOffset,
4371                     (sizeof (MPI2_SCSI_IO_REQUEST) -
4372                     sizeof (MPI2_SGE_IO_UNION) +
4373                     (j - 1) * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4374                 sgechain = (pMpi2SGEChain64_t)sge;
4375                 chainflags = (MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4376                     MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4377                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4378                 ddi_put8(acc_hdl, &sgechain->Flags, chainflags);
4379 
4380                 /*
4381                  * The size of the next frame is the accurate size of space
4382                  * (in bytes) used to store the SGL elements. j is the counter
4383                  * of SGL elements. (j - 1) is the number of SGL elements that
4384                  * have been processed (stored in frames).
4385                  */
4386                 if (frames >= 2) {
4387                         chainlength = mpt->m_req_frame_size /
4388                             sizeof (MPI2_SGE_SIMPLE64) *
4389                             sizeof (MPI2_SGE_SIMPLE64);
4390                 } else {
4391                         chainlength = ((cookiec - (j - 1)) *
4392                             sizeof (MPI2_SGE_SIMPLE64));
4393                 }
4394 
4395                 p = cmd->cmd_extra_frames;
4396 
4397                 ddi_put16(acc_hdl, &sgechain->Length, chainlength);
4398                 ddi_put32(acc_hdl, &sgechain->Address.Low,
4399                     p->m_phys_addr);
4400                 /* SGL is allocated in the first 4G mem range */
4401                 ddi_put32(acc_hdl, &sgechain->Address.High, 0);
4402 
4403                 /*
4404                  * If there are more than 2 frames left we have to
4405                  * fill in the next chain offset to the location of
4406                  * the chain element in the next frame.
4407                  * sgemax is the number of simple elements in an extra
4408                  * frame. Note that the value NextChainOffset should be
4409                  * in double-words (4 bytes).
4410                  */
4411                 if (frames >= 2) {
4412                         ddi_put8(acc_hdl, &sgechain->NextChainOffset,
4413                             (sgemax * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4414                 } else {
4415                         ddi_put8(acc_hdl, &sgechain->NextChainOffset, 0);
4416                 }
4417 
4418                 /*
4419                  * Jump to next frame;
4420                  * Starting here, chain buffers go into the per command SGL.
4421                  * This buffer is allocated when chain buffers are needed.
4422                  */
4423                 sge = (pMpi2SGESimple64_t)p->m_frames_addr;
4424                 i = cookiec;
4425 
4426                 /*
4427                  * Start filling in frames with SGE's.  If we
4428                  * reach the end of frame and still have SGE's
4429                  * to fill we need to add a chain element and
4430                  * use another frame.  j will be our counter
4431                  * for what cookie we are at and i will be
4432                  * the total cookiec. k is the current frame
4433                  */
4434                 for (k = 1; k <= frames; k++) {
4435                         for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
4436 
4437                                 /*
4438                                  * If we have reached the end of frame
4439                                  * and we have more SGE's to fill in
4440                                  * we have to fill the final entry
4441                                  * with a chain element and then
4442                                  * continue to the next frame
4443                                  */
4444                                 if ((l == (sgemax + 1)) && (k != frames)) {
4445                                         sgechain = (pMpi2SGEChain64_t)sge;
4446                                         j--;
4447                                         chainflags = (
4448                                             MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4449                                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4450                                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4451                                         ddi_put8(p->m_acc_hdl,
4452                                             &sgechain->Flags, chainflags);
4453                                         /*
4454                                          * k is the frame counter and (k + 1)
4455                                          * is the number of the next frame.
4456                                          * Note that frames are in contiguous
4457                                          * memory space.
4458                                          */
4459                                         ddi_put32(p->m_acc_hdl,
4460                                             &sgechain->Address.Low,
4461                                             (p->m_phys_addr +
4462                                             (mpt->m_req_frame_size * k)));
4463                                         ddi_put32(p->m_acc_hdl,
4464                                             &sgechain->Address.High, 0);
4465 
4466                                         /*
4467                                          * If there are more than 2 frames left
4468                                          * we have to next chain offset to
4469                                          * the location of the chain element
4470                                          * in the next frame and fill in the
4471                                          * length of the next chain
4472                                          */
4473                                         if ((frames - k) >= 2) {
4474                                                 ddi_put8(p->m_acc_hdl,
4475                                                     &sgechain->NextChainOffset,
4476                                                     (sgemax *
4477                                                     sizeof (MPI2_SGE_SIMPLE64))
4478                                                     >> 2);
4479                                                 ddi_put16(p->m_acc_hdl,
4480                                                     &sgechain->Length,
4481                                                     mpt->m_req_frame_size /
4482                                                     sizeof (MPI2_SGE_SIMPLE64) *
4483                                                     sizeof (MPI2_SGE_SIMPLE64));
4484                                         } else {
4485                                                 /*
4486                                                  * This is the last frame. Set
4487                                                  * the NextChainOffset to 0 and
4488                                                  * Length is the total size of
4489                                                  * all remaining simple elements
4490                                                  */
4491                                                 ddi_put8(p->m_acc_hdl,
4492                                                     &sgechain->NextChainOffset,
4493                                                     0);
4494                                                 ddi_put16(p->m_acc_hdl,
4495                                                     &sgechain->Length,
4496                                                     (cookiec - j) *
4497                                                     sizeof (MPI2_SGE_SIMPLE64));
4498                                         }
4499 
4500                                         /* Jump to the next frame */
4501                                         sge = (pMpi2SGESimple64_t)
4502                                             ((char *)p->m_frames_addr +
4503                                             (int)mpt->m_req_frame_size * k);
4504 
4505                                         continue;
4506                                 }
4507 
4508                                 ddi_put32(p->m_acc_hdl,
4509                                     &sge->Address.Low,
4510                                     dmap->addr.address64.Low);
4511                                 ddi_put32(p->m_acc_hdl,
4512                                     &sge->Address.High,
4513                                     dmap->addr.address64.High);
4514                                 ddi_put32(p->m_acc_hdl,
4515                                     &sge->FlagsLength, dmap->count);
4516                                 flags = ddi_get32(p->m_acc_hdl,
4517                                     &sge->FlagsLength);
4518                                 flags |= ((uint32_t)(
4519                                     MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4520                                     MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4521                                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4522                                     MPI2_SGE_FLAGS_SHIFT);
4523 
4524                                 /*
4525                                  * If we are at the end of the frame and
4526                                  * there is another frame to fill in
4527                                  * we set the last simple element as last
4528                                  * element
4529                                  */
4530                                 if ((l == sgemax) && (k != frames)) {
4531                                         flags |= ((uint32_t)
4532                                             (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4533                                             MPI2_SGE_FLAGS_SHIFT);
4534                                 }
4535 
4536                                 /*
4537                                  * If this is the final cookie we
4538                                  * indicate it by setting the flags
4539                                  */
4540                                 if (j == i) {
4541                                         flags |= ((uint32_t)
4542                                             (MPI2_SGE_FLAGS_LAST_ELEMENT |
4543                                             MPI2_SGE_FLAGS_END_OF_BUFFER |
4544                                             MPI2_SGE_FLAGS_END_OF_LIST) <<
4545                                             MPI2_SGE_FLAGS_SHIFT);
4546                                 }
4547                                 if (cmd->cmd_flags & CFLAG_DMASEND) {
4548                                         flags |=
4549                                             (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4550                                             MPI2_SGE_FLAGS_SHIFT);
4551                                 } else {
4552                                         flags |=
4553                                             (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4554                                             MPI2_SGE_FLAGS_SHIFT);
4555                                 }
4556                                 ddi_put32(p->m_acc_hdl,
4557                                     &sge->FlagsLength, flags);
4558                                 dmap++;
4559                                 sge++;
4560                         }
4561                 }
4562 
4563                 /*
4564                  * Sync DMA with the chain buffers that were just created
4565                  */
4566                 (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
4567         }
4568 }
4569 
4570 /*
4571  * Interrupt handling
4572  * Utility routine.  Poll for status of a command sent to HBA
4573  * without interrupts (a FLAG_NOINTR command).
4574  */
4575 int
4576 mptsas_poll(mptsas_t *mpt, mptsas_cmd_t *poll_cmd, int polltime)
4577 {
4578         int     rval = TRUE;
4579 
4580         NDBG5(("mptsas_poll: cmd=0x%p", (void *)poll_cmd));
4581 
4582         if ((poll_cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
4583                 mptsas_restart_hba(mpt);
4584         }
4585 
4586         /*
4587          * Wait, using drv_usecwait(), long enough for the command to
4588          * reasonably return from the target if the target isn't
4589          * "dead".  A polled command may well be sent from scsi_poll, and
4590          * there are retries built in to scsi_poll if the transport
4591          * accepted the packet (TRAN_ACCEPT).  scsi_poll waits 1 second
4592          * and retries the transport up to scsi_poll_busycnt times
4593          * (currently 60) if
4594          * 1. pkt_reason is CMD_INCOMPLETE and pkt_state is 0, or
4595          * 2. pkt_reason is CMD_CMPLT and *pkt_scbp has STATUS_BUSY
4596          *
4597          * limit the waiting to avoid a hang in the event that the
4598          * cmd never gets started but we are still receiving interrupts
4599          */
4600         while (!(poll_cmd->cmd_flags & CFLAG_FINISHED)) {
4601                 if (mptsas_wait_intr(mpt, polltime) == FALSE) {
4602                         NDBG5(("mptsas_poll: command incomplete"));
4603                         rval = FALSE;
4604                         break;
4605                 }
4606         }
4607 
4608         if (rval == FALSE) {
4609 
4610                 /*
4611                  * this isn't supposed to happen, the hba must be wedged
4612                  * Mark this cmd as a timeout.
4613                  */
4614                 mptsas_set_pkt_reason(mpt, poll_cmd, CMD_TIMEOUT,
4615                     (STAT_TIMEOUT|STAT_ABORTED));
4616 
4617                 if (poll_cmd->cmd_queued == FALSE) {
4618 
4619                         NDBG5(("mptsas_poll: not on waitq"));
4620 
4621                         poll_cmd->cmd_pkt->pkt_state |=
4622                             (STATE_GOT_BUS|STATE_GOT_TARGET|STATE_SENT_CMD);
4623                 } else {
4624 
4625                         /* find and remove it from the waitq */
4626                         NDBG5(("mptsas_poll: delete from waitq"));
4627                         mptsas_waitq_delete(mpt, poll_cmd);
4628                 }
4629 
4630         }
4631         mptsas_fma_check(mpt, poll_cmd);
4632         NDBG5(("mptsas_poll: done"));
4633         return (rval);
4634 }
4635 
4636 /*
4637  * Used for polling cmds and TM function
4638  */
4639 static int
4640 mptsas_wait_intr(mptsas_t *mpt, int polltime)
4641 {
4642         int                             cnt;
4643         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
4644         uint32_t                        int_mask;
4645 
4646         NDBG5(("mptsas_wait_intr"));
4647 
4648         mpt->m_polled_intr = 1;
4649 
4650         /*
4651          * Get the current interrupt mask and disable interrupts.  When
4652          * re-enabling ints, set mask to saved value.
4653          */
4654         int_mask = ddi_get32(mpt->m_datap, &mpt->m_reg->HostInterruptMask);
4655         MPTSAS_DISABLE_INTR(mpt);
4656 
4657         /*
4658          * Keep polling for at least (polltime * 1000) seconds
4659          */
4660         for (cnt = 0; cnt < polltime; cnt++) {
4661                 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
4662                     DDI_DMA_SYNC_FORCPU);
4663 
4664                 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
4665                     MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
4666 
4667                 if (ddi_get32(mpt->m_acc_post_queue_hdl,
4668                     &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
4669                     ddi_get32(mpt->m_acc_post_queue_hdl,
4670                     &reply_desc_union->Words.High) == 0xFFFFFFFF) {
4671                         drv_usecwait(1000);
4672                         continue;
4673                 }
4674 
4675                 /*
4676                  * The reply is valid, process it according to its
4677                  * type.
4678                  */
4679                 mptsas_process_intr(mpt, reply_desc_union);
4680 
4681                 if (++mpt->m_post_index == mpt->m_post_queue_depth) {
4682                         mpt->m_post_index = 0;
4683                 }
4684 
4685                 /*
4686                  * Update the global reply index
4687                  */
4688                 ddi_put32(mpt->m_datap,
4689                     &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
4690                 mpt->m_polled_intr = 0;
4691 
4692                 /*
4693                  * Re-enable interrupts and quit.
4694                  */
4695                 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask,
4696                     int_mask);
4697                 return (TRUE);
4698 
4699         }
4700 
4701         /*
4702          * Clear polling flag, re-enable interrupts and quit.
4703          */
4704         mpt->m_polled_intr = 0;
4705         ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask, int_mask);
4706         return (FALSE);
4707 }
4708 
4709 static void
4710 mptsas_handle_scsi_io_success(mptsas_t *mpt,
4711     pMpi2ReplyDescriptorsUnion_t reply_desc)
4712 {
4713         pMpi2SCSIIOSuccessReplyDescriptor_t     scsi_io_success;
4714         uint16_t                                SMID;
4715         mptsas_slots_t                          *slots = mpt->m_active;
4716         mptsas_cmd_t                            *cmd = NULL;
4717         struct scsi_pkt                         *pkt;
4718 
4719         ASSERT(mutex_owned(&mpt->m_mutex));
4720 
4721         scsi_io_success = (pMpi2SCSIIOSuccessReplyDescriptor_t)reply_desc;
4722         SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &scsi_io_success->SMID);
4723 
4724         /*
4725          * This is a success reply so just complete the IO.  First, do a sanity
4726          * check on the SMID.  The final slot is used for TM requests, which
4727          * would not come into this reply handler.
4728          */
4729         if ((SMID == 0) || (SMID > slots->m_n_normal)) {
4730                 mptsas_log(mpt, CE_WARN, "?Received invalid SMID of %d\n",
4731                     SMID);
4732                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4733                 return;
4734         }
4735 
4736         cmd = slots->m_slot[SMID];
4737 
4738         /*
4739          * print warning and return if the slot is empty
4740          */
4741         if (cmd == NULL) {
4742                 mptsas_log(mpt, CE_WARN, "?NULL command for successful SCSI IO "
4743                     "in slot %d", SMID);
4744                 return;
4745         }
4746 
4747         pkt = CMD2PKT(cmd);
4748         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
4749             STATE_GOT_STATUS);
4750         if (cmd->cmd_flags & CFLAG_DMAVALID) {
4751                 pkt->pkt_state |= STATE_XFERRED_DATA;
4752         }
4753         pkt->pkt_resid = 0;
4754 
4755         if (cmd->cmd_flags & CFLAG_PASSTHRU) {
4756                 cmd->cmd_flags |= CFLAG_FINISHED;
4757                 cv_broadcast(&mpt->m_passthru_cv);
4758                 return;
4759         } else {
4760                 mptsas_remove_cmd(mpt, cmd);
4761         }
4762 
4763         if (cmd->cmd_flags & CFLAG_RETRY) {
4764                 /*
4765                  * The target returned QFULL or busy, do not add tihs
4766                  * pkt to the doneq since the hba will retry
4767                  * this cmd.
4768                  *
4769                  * The pkt has already been resubmitted in
4770                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
4771                  * Remove this cmd_flag here.
4772                  */
4773                 cmd->cmd_flags &= ~CFLAG_RETRY;
4774         } else {
4775                 mptsas_doneq_add(mpt, cmd);
4776         }
4777 }
4778 
4779 static void
4780 mptsas_handle_address_reply(mptsas_t *mpt,
4781     pMpi2ReplyDescriptorsUnion_t reply_desc)
4782 {
4783         pMpi2AddressReplyDescriptor_t   address_reply;
4784         pMPI2DefaultReply_t             reply;
4785         mptsas_fw_diagnostic_buffer_t   *pBuffer;
4786         uint32_t                        reply_addr;
4787         uint16_t                        SMID, iocstatus;
4788         mptsas_slots_t                  *slots = mpt->m_active;
4789         mptsas_cmd_t                    *cmd = NULL;
4790         uint8_t                         function, buffer_type;
4791         m_replyh_arg_t                  *args;
4792         int                             reply_frame_no;
4793 
4794         ASSERT(mutex_owned(&mpt->m_mutex));
4795 
4796         address_reply = (pMpi2AddressReplyDescriptor_t)reply_desc;
4797         reply_addr = ddi_get32(mpt->m_acc_post_queue_hdl,
4798             &address_reply->ReplyFrameAddress);
4799         SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &address_reply->SMID);
4800 
4801         /*
4802          * If reply frame is not in the proper range we should ignore this
4803          * message and exit the interrupt handler.
4804          */
4805         if ((reply_addr < mpt->m_reply_frame_dma_addr) ||
4806             (reply_addr >= (mpt->m_reply_frame_dma_addr +
4807             (mpt->m_reply_frame_size * mpt->m_max_replies))) ||
4808             ((reply_addr - mpt->m_reply_frame_dma_addr) %
4809             mpt->m_reply_frame_size != 0)) {
4810                 mptsas_log(mpt, CE_WARN, "?Received invalid reply frame "
4811                     "address 0x%x\n", reply_addr);
4812                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4813                 return;
4814         }
4815 
4816         (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
4817             DDI_DMA_SYNC_FORCPU);
4818         reply = (pMPI2DefaultReply_t)(mpt->m_reply_frame + (reply_addr -
4819             mpt->m_reply_frame_dma_addr));
4820         function = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->Function);
4821 
4822         /*
4823          * don't get slot information and command for events since these values
4824          * don't exist
4825          */
4826         if ((function != MPI2_FUNCTION_EVENT_NOTIFICATION) &&
4827             (function != MPI2_FUNCTION_DIAG_BUFFER_POST)) {
4828                 /*
4829                  * This could be a TM reply, which use the last allocated SMID,
4830                  * so allow for that.
4831                  */
4832                 if ((SMID == 0) || (SMID > (slots->m_n_normal + 1))) {
4833                         mptsas_log(mpt, CE_WARN, "?Received invalid SMID of "
4834                             "%d\n", SMID);
4835                         ddi_fm_service_impact(mpt->m_dip,
4836                             DDI_SERVICE_UNAFFECTED);
4837                         return;
4838                 }
4839 
4840                 cmd = slots->m_slot[SMID];
4841 
4842                 /*
4843                  * print warning and return if the slot is empty
4844                  */
4845                 if (cmd == NULL) {
4846                         mptsas_log(mpt, CE_WARN, "?NULL command for address "
4847                             "reply in slot %d", SMID);
4848                         return;
4849                 }
4850                 if ((cmd->cmd_flags &
4851                     (CFLAG_PASSTHRU | CFLAG_CONFIG | CFLAG_FW_DIAG))) {
4852                         cmd->cmd_rfm = reply_addr;
4853                         cmd->cmd_flags |= CFLAG_FINISHED;
4854                         cv_broadcast(&mpt->m_passthru_cv);
4855                         cv_broadcast(&mpt->m_config_cv);
4856                         cv_broadcast(&mpt->m_fw_diag_cv);
4857                         return;
4858                 } else if (!(cmd->cmd_flags & CFLAG_FW_CMD)) {
4859                         mptsas_remove_cmd(mpt, cmd);
4860                 }
4861                 NDBG31(("\t\tmptsas_process_intr: slot=%d", SMID));
4862         }
4863         /*
4864          * Depending on the function, we need to handle
4865          * the reply frame (and cmd) differently.
4866          */
4867         switch (function) {
4868         case MPI2_FUNCTION_SCSI_IO_REQUEST:
4869                 mptsas_check_scsi_io_error(mpt, (pMpi2SCSIIOReply_t)reply, cmd);
4870                 break;
4871         case MPI2_FUNCTION_SCSI_TASK_MGMT:
4872                 cmd->cmd_rfm = reply_addr;
4873                 mptsas_check_task_mgt(mpt, (pMpi2SCSIManagementReply_t)reply,
4874                     cmd);
4875                 break;
4876         case MPI2_FUNCTION_FW_DOWNLOAD:
4877                 cmd->cmd_flags |= CFLAG_FINISHED;
4878                 cv_signal(&mpt->m_fw_cv);
4879                 break;
4880         case MPI2_FUNCTION_EVENT_NOTIFICATION:
4881                 reply_frame_no = (reply_addr - mpt->m_reply_frame_dma_addr) /
4882                     mpt->m_reply_frame_size;
4883                 args = &mpt->m_replyh_args[reply_frame_no];
4884                 args->mpt = (void *)mpt;
4885                 args->rfm = reply_addr;
4886 
4887                 /*
4888                  * Record the event if its type is enabled in
4889                  * this mpt instance by ioctl.
4890                  */
4891                 mptsas_record_event(args);
4892 
4893                 /*
4894                  * Handle time critical events
4895                  * NOT_RESPONDING/ADDED only now
4896                  */
4897                 if (mptsas_handle_event_sync(args) == DDI_SUCCESS) {
4898                         /*
4899                          * Would not return main process,
4900                          * just let taskq resolve ack action
4901                          * and ack would be sent in taskq thread
4902                          */
4903                         NDBG20(("send mptsas_handle_event_sync success"));
4904                 }
4905 
4906                 if (mpt->m_in_reset) {
4907                         NDBG20(("dropping event received during reset"));
4908                         return;
4909                 }
4910 
4911                 if ((ddi_taskq_dispatch(mpt->m_event_taskq, mptsas_handle_event,
4912                     (void *)args, DDI_NOSLEEP)) != DDI_SUCCESS) {
4913                         mptsas_log(mpt, CE_WARN, "No memory available"
4914                         "for dispatch taskq");
4915                         /*
4916                          * Return the reply frame to the free queue.
4917                          */
4918                         ddi_put32(mpt->m_acc_free_queue_hdl,
4919                             &((uint32_t *)(void *)
4920                             mpt->m_free_queue)[mpt->m_free_index], reply_addr);
4921                         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
4922                             DDI_DMA_SYNC_FORDEV);
4923                         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
4924                                 mpt->m_free_index = 0;
4925                         }
4926 
4927                         ddi_put32(mpt->m_datap,
4928                             &mpt->m_reg->ReplyFreeHostIndex, mpt->m_free_index);
4929                 }
4930                 return;
4931         case MPI2_FUNCTION_DIAG_BUFFER_POST:
4932                 /*
4933                  * If SMID is 0, this implies that the reply is due to a
4934                  * release function with a status that the buffer has been
4935                  * released.  Set the buffer flags accordingly.
4936                  */
4937                 if (SMID == 0) {
4938                         iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
4939                             &reply->IOCStatus);
4940                         buffer_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
4941                             &(((pMpi2DiagBufferPostReply_t)reply)->BufferType));
4942                         if (iocstatus == MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED) {
4943                                 pBuffer =
4944                                     &mpt->m_fw_diag_buffer_list[buffer_type];
4945                                 pBuffer->valid_data = TRUE;
4946                                 pBuffer->owned_by_firmware = FALSE;
4947                                 pBuffer->immediate = FALSE;
4948                         }
4949                 } else {
4950                         /*
4951                          * Normal handling of diag post reply with SMID.
4952                          */
4953                         cmd = slots->m_slot[SMID];
4954 
4955                         /*
4956                          * print warning and return if the slot is empty
4957                          */
4958                         if (cmd == NULL) {
4959                                 mptsas_log(mpt, CE_WARN, "?NULL command for "
4960                                     "address reply in slot %d", SMID);
4961                                 return;
4962                         }
4963                         cmd->cmd_rfm = reply_addr;
4964                         cmd->cmd_flags |= CFLAG_FINISHED;
4965                         cv_broadcast(&mpt->m_fw_diag_cv);
4966                 }
4967                 return;
4968         default:
4969                 mptsas_log(mpt, CE_WARN, "Unknown function 0x%x ", function);
4970                 break;
4971         }
4972 
4973         /*
4974          * Return the reply frame to the free queue.
4975          */
4976         ddi_put32(mpt->m_acc_free_queue_hdl,
4977             &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
4978             reply_addr);
4979         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
4980             DDI_DMA_SYNC_FORDEV);
4981         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
4982                 mpt->m_free_index = 0;
4983         }
4984         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
4985             mpt->m_free_index);
4986 
4987         if (cmd->cmd_flags & CFLAG_FW_CMD)
4988                 return;
4989 
4990         if (cmd->cmd_flags & CFLAG_RETRY) {
4991                 /*
4992                  * The target returned QFULL or busy, do not add tihs
4993                  * pkt to the doneq since the hba will retry
4994                  * this cmd.
4995                  *
4996                  * The pkt has already been resubmitted in
4997                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
4998                  * Remove this cmd_flag here.
4999                  */
5000                 cmd->cmd_flags &= ~CFLAG_RETRY;
5001         } else {
5002                 mptsas_doneq_add(mpt, cmd);
5003         }
5004 }
5005 
5006 static void
5007 mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
5008     mptsas_cmd_t *cmd)
5009 {
5010         uint8_t                 scsi_status, scsi_state;
5011         uint16_t                ioc_status;
5012         uint32_t                xferred, sensecount, responsedata, loginfo = 0;
5013         struct scsi_pkt         *pkt;
5014         struct scsi_arq_status  *arqstat;
5015         struct buf              *bp;
5016         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
5017         uint8_t                 *sensedata = NULL;
5018         uint64_t                sas_wwn;
5019         uint8_t                 phy;
5020         char                    wwn_str[MPTSAS_WWN_STRLEN];
5021 
5022         if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
5023             (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
5024                 bp = cmd->cmd_ext_arq_buf;
5025         } else {
5026                 bp = cmd->cmd_arq_buf;
5027         }
5028 
5029         scsi_status = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIStatus);
5030         ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5031         scsi_state = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIState);
5032         xferred = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->TransferCount);
5033         sensecount = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->SenseCount);
5034         responsedata = ddi_get32(mpt->m_acc_reply_frame_hdl,
5035             &reply->ResponseInfo);
5036 
5037         if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
5038                 sas_wwn = ptgt->m_addr.mta_wwn;
5039                 phy = ptgt->m_phynum;
5040                 if (sas_wwn == 0) {
5041                         (void) sprintf(wwn_str, "p%x", phy);
5042                 } else {
5043                         (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
5044                 }
5045                 loginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
5046                     &reply->IOCLogInfo);
5047                 mptsas_log(mpt, CE_NOTE,
5048                     "?Log info 0x%x received for target %d %s.\n"
5049                     "\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5050                     loginfo, Tgt(cmd), wwn_str, scsi_status, ioc_status,
5051                     scsi_state);
5052         }
5053 
5054         NDBG31(("\t\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5055             scsi_status, ioc_status, scsi_state));
5056 
5057         pkt = CMD2PKT(cmd);
5058         *(pkt->pkt_scbp) = scsi_status;
5059 
5060         if (loginfo == 0x31170000) {
5061                 /*
5062                  * if loginfo PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY
5063                  * 0x31170000 comes, that means the device missing delay
5064                  * is in progressing, the command need retry later.
5065                  */
5066                 *(pkt->pkt_scbp) = STATUS_BUSY;
5067                 return;
5068         }
5069 
5070         if ((scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) &&
5071             ((ioc_status & MPI2_IOCSTATUS_MASK) ==
5072             MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE)) {
5073                 pkt->pkt_reason = CMD_INCOMPLETE;
5074                 pkt->pkt_state |= STATE_GOT_BUS;
5075                 if (ptgt->m_reset_delay == 0) {
5076                         mptsas_set_throttle(mpt, ptgt,
5077                             DRAIN_THROTTLE);
5078                 }
5079                 return;
5080         }
5081 
5082         if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
5083                 responsedata &= 0x000000FF;
5084                 if (responsedata & MPTSAS_SCSI_RESPONSE_CODE_TLR_OFF) {
5085                         mptsas_log(mpt, CE_NOTE, "Do not support the TLR\n");
5086                         pkt->pkt_reason = CMD_TLR_OFF;
5087                         return;
5088                 }
5089         }
5090 
5091 
5092         switch (scsi_status) {
5093         case MPI2_SCSI_STATUS_CHECK_CONDITION:
5094                 pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5095                 arqstat = (void*)(pkt->pkt_scbp);
5096                 arqstat->sts_rqpkt_status = *((struct scsi_status *)
5097                     (pkt->pkt_scbp));
5098                 pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
5099                     STATE_SENT_CMD | STATE_GOT_STATUS | STATE_ARQ_DONE);
5100                 if (cmd->cmd_flags & CFLAG_XARQ) {
5101                         pkt->pkt_state |= STATE_XARQ_DONE;
5102                 }
5103                 if (pkt->pkt_resid != cmd->cmd_dmacount) {
5104                         pkt->pkt_state |= STATE_XFERRED_DATA;
5105                 }
5106                 arqstat->sts_rqpkt_reason = pkt->pkt_reason;
5107                 arqstat->sts_rqpkt_state  = pkt->pkt_state;
5108                 arqstat->sts_rqpkt_state |= STATE_XFERRED_DATA;
5109                 arqstat->sts_rqpkt_statistics = pkt->pkt_statistics;
5110                 sensedata = (uint8_t *)&arqstat->sts_sensedata;
5111 
5112                 bcopy((uchar_t *)bp->b_un.b_addr, sensedata,
5113                     ((cmd->cmd_rqslen >= sensecount) ? sensecount :
5114                     cmd->cmd_rqslen));
5115                 arqstat->sts_rqpkt_resid = (cmd->cmd_rqslen - sensecount);
5116                 cmd->cmd_flags |= CFLAG_CMDARQ;
5117                 /*
5118                  * Set proper status for pkt if autosense was valid
5119                  */
5120                 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
5121                         struct scsi_status zero_status = { 0 };
5122                         arqstat->sts_rqpkt_status = zero_status;
5123                 }
5124 
5125                 /*
5126                  * ASC=0x47 is parity error
5127                  * ASC=0x48 is initiator detected error received
5128                  */
5129                 if ((scsi_sense_key(sensedata) == KEY_ABORTED_COMMAND) &&
5130                     ((scsi_sense_asc(sensedata) == 0x47) ||
5131                     (scsi_sense_asc(sensedata) == 0x48))) {
5132                         mptsas_log(mpt, CE_NOTE, "Aborted_command!");
5133                 }
5134 
5135                 /*
5136                  * ASC/ASCQ=0x3F/0x0E means report_luns data changed
5137                  * ASC/ASCQ=0x25/0x00 means invalid lun
5138                  */
5139                 if (((scsi_sense_key(sensedata) == KEY_UNIT_ATTENTION) &&
5140                     (scsi_sense_asc(sensedata) == 0x3F) &&
5141                     (scsi_sense_ascq(sensedata) == 0x0E)) ||
5142                     ((scsi_sense_key(sensedata) == KEY_ILLEGAL_REQUEST) &&
5143                     (scsi_sense_asc(sensedata) == 0x25) &&
5144                     (scsi_sense_ascq(sensedata) == 0x00))) {
5145                         mptsas_topo_change_list_t *topo_node = NULL;
5146 
5147                         topo_node = kmem_zalloc(
5148                             sizeof (mptsas_topo_change_list_t),
5149                             KM_NOSLEEP);
5150                         if (topo_node == NULL) {
5151                                 mptsas_log(mpt, CE_NOTE, "No memory"
5152                                     "resource for handle SAS dynamic"
5153                                     "reconfigure.\n");
5154                                 break;
5155                         }
5156                         topo_node->mpt = mpt;
5157                         topo_node->event = MPTSAS_DR_EVENT_RECONFIG_TARGET;
5158                         topo_node->un.phymask = ptgt->m_addr.mta_phymask;
5159                         topo_node->devhdl = ptgt->m_devhdl;
5160                         topo_node->object = (void *)ptgt;
5161                         topo_node->flags = MPTSAS_TOPO_FLAG_LUN_ASSOCIATED;
5162 
5163                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
5164                             mptsas_handle_dr,
5165                             (void *)topo_node,
5166                             DDI_NOSLEEP)) != DDI_SUCCESS) {
5167                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq"
5168                                     "for handle SAS dynamic reconfigure"
5169                                     "failed. \n");
5170                         }
5171                 }
5172                 break;
5173         case MPI2_SCSI_STATUS_GOOD:
5174                 switch (ioc_status & MPI2_IOCSTATUS_MASK) {
5175                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
5176                         pkt->pkt_reason = CMD_DEV_GONE;
5177                         pkt->pkt_state |= STATE_GOT_BUS;
5178                         if (ptgt->m_reset_delay == 0) {
5179                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5180                         }
5181                         NDBG31(("lost disk for target%d, command:%x",
5182                             Tgt(cmd), pkt->pkt_cdbp[0]));
5183                         break;
5184                 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
5185                         NDBG31(("data overrun: xferred=%d", xferred));
5186                         NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5187                         pkt->pkt_reason = CMD_DATA_OVR;
5188                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5189                             | STATE_SENT_CMD | STATE_GOT_STATUS
5190                             | STATE_XFERRED_DATA);
5191                         pkt->pkt_resid = 0;
5192                         break;
5193                 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
5194                 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
5195                         NDBG31(("data underrun: xferred=%d", xferred));
5196                         NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5197                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5198                             | STATE_SENT_CMD | STATE_GOT_STATUS);
5199                         pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5200                         if (pkt->pkt_resid != cmd->cmd_dmacount) {
5201                                 pkt->pkt_state |= STATE_XFERRED_DATA;
5202                         }
5203                         break;
5204                 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
5205                         if (cmd->cmd_active_expiration <= gethrtime()) {
5206                                 /*
5207                                  * When timeout requested, propagate
5208                                  * proper reason and statistics to
5209                                  * target drivers.
5210                                  */
5211                                 mptsas_set_pkt_reason(mpt, cmd, CMD_TIMEOUT,
5212                                     STAT_BUS_RESET | STAT_TIMEOUT);
5213                         } else {
5214                                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
5215                                     STAT_BUS_RESET);
5216                         }
5217                         break;
5218                 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
5219                 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
5220                         mptsas_set_pkt_reason(mpt,
5221                             cmd, CMD_RESET, STAT_DEV_RESET);
5222                         break;
5223                 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
5224                 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
5225                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET);
5226                         mptsas_set_pkt_reason(mpt,
5227                             cmd, CMD_TERMINATED, STAT_TERMINATED);
5228                         break;
5229                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
5230                 case MPI2_IOCSTATUS_BUSY:
5231                         /*
5232                          * set throttles to drain
5233                          */
5234                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
5235                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
5236                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5237                         }
5238 
5239                         /*
5240                          * retry command
5241                          */
5242                         cmd->cmd_flags |= CFLAG_RETRY;
5243                         cmd->cmd_pkt_flags |= FLAG_HEAD;
5244 
5245                         (void) mptsas_accept_pkt(mpt, cmd);
5246                         break;
5247                 default:
5248                         mptsas_log(mpt, CE_WARN,
5249                             "unknown ioc_status = %x\n", ioc_status);
5250                         mptsas_log(mpt, CE_CONT, "scsi_state = %x, transfer "
5251                             "count = %x, scsi_status = %x", scsi_state,
5252                             xferred, scsi_status);
5253                         break;
5254                 }
5255                 break;
5256         case MPI2_SCSI_STATUS_TASK_SET_FULL:
5257                 mptsas_handle_qfull(mpt, cmd);
5258                 break;
5259         case MPI2_SCSI_STATUS_BUSY:
5260                 NDBG31(("scsi_status busy received"));
5261                 break;
5262         case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
5263                 NDBG31(("scsi_status reservation conflict received"));
5264                 break;
5265         default:
5266                 mptsas_log(mpt, CE_WARN, "scsi_status=%x, ioc_status=%x\n",
5267                     scsi_status, ioc_status);
5268                 mptsas_log(mpt, CE_WARN,
5269                     "mptsas_process_intr: invalid scsi status\n");
5270                 break;
5271         }
5272 }
5273 
5274 static void
5275 mptsas_check_task_mgt(mptsas_t *mpt, pMpi2SCSIManagementReply_t reply,
5276         mptsas_cmd_t *cmd)
5277 {
5278         uint8_t         task_type;
5279         uint16_t        ioc_status;
5280         uint32_t        log_info;
5281         uint16_t        dev_handle;
5282         struct scsi_pkt *pkt = CMD2PKT(cmd);
5283 
5284         task_type = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->TaskType);
5285         ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5286         log_info = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->IOCLogInfo);
5287         dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->DevHandle);
5288 
5289         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5290                 mptsas_log(mpt, CE_WARN, "mptsas_check_task_mgt: Task 0x%x "
5291                     "failed. IOCStatus=0x%x IOCLogInfo=0x%x target=%d\n",
5292                     task_type, ioc_status, log_info, dev_handle);
5293                 pkt->pkt_reason = CMD_INCOMPLETE;
5294                 return;
5295         }
5296 
5297         switch (task_type) {
5298         case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
5299         case MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
5300         case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
5301         case MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA:
5302         case MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET:
5303         case MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION:
5304                 break;
5305         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
5306         case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
5307         case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
5308                 /*
5309                  * Check for invalid DevHandle of 0 in case application
5310                  * sends bad command.  DevHandle of 0 could cause problems.
5311                  */
5312                 if (dev_handle == 0) {
5313                         mptsas_log(mpt, CE_WARN, "!Can't flush target with"
5314                             " DevHandle of 0.");
5315                 } else {
5316                         mptsas_flush_target(mpt, dev_handle, Lun(cmd),
5317                             task_type);
5318                 }
5319                 break;
5320         default:
5321                 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
5322                     task_type);
5323                 mptsas_log(mpt, CE_WARN, "ioc status = %x", ioc_status);
5324                 break;
5325         }
5326 }
5327 
5328 static void
5329 mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg)
5330 {
5331         mptsas_t                        *mpt = arg->mpt;
5332         uint64_t                        t = arg->t;
5333         mptsas_cmd_t                    *cmd;
5334         struct scsi_pkt                 *pkt;
5335         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
5336 
5337         mutex_enter(&item->mutex);
5338         while (item->flag & MPTSAS_DONEQ_THREAD_ACTIVE) {
5339                 if (!item->doneq) {
5340                         cv_wait(&item->cv, &item->mutex);
5341                 }
5342                 pkt = NULL;
5343                 if ((cmd = mptsas_doneq_thread_rm(mpt, t)) != NULL) {
5344                         cmd->cmd_flags |= CFLAG_COMPLETED;
5345                         pkt = CMD2PKT(cmd);
5346                 }
5347                 mutex_exit(&item->mutex);
5348                 if (pkt) {
5349                         mptsas_pkt_comp(pkt, cmd);
5350                 }
5351                 mutex_enter(&item->mutex);
5352         }
5353         mutex_exit(&item->mutex);
5354         mutex_enter(&mpt->m_doneq_mutex);
5355         mpt->m_doneq_thread_n--;
5356         cv_broadcast(&mpt->m_doneq_thread_cv);
5357         mutex_exit(&mpt->m_doneq_mutex);
5358 }
5359 
5360 
5361 /*
5362  * mpt interrupt handler.
5363  */
5364 static uint_t
5365 mptsas_intr(caddr_t arg1, caddr_t arg2)
5366 {
5367         mptsas_t                        *mpt = (void *)arg1;
5368         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
5369         uchar_t                         did_reply = FALSE;
5370 
5371         NDBG1(("mptsas_intr: arg1 0x%p arg2 0x%p", (void *)arg1, (void *)arg2));
5372 
5373         mutex_enter(&mpt->m_mutex);
5374 
5375         /*
5376          * If interrupts are shared by two channels then check whether this
5377          * interrupt is genuinely for this channel by making sure first the
5378          * chip is in high power state.
5379          */
5380         if ((mpt->m_options & MPTSAS_OPT_PM) &&
5381             (mpt->m_power_level != PM_LEVEL_D0)) {
5382                 mutex_exit(&mpt->m_mutex);
5383                 return (DDI_INTR_UNCLAIMED);
5384         }
5385 
5386         /*
5387          * If polling, interrupt was triggered by some shared interrupt because
5388          * IOC interrupts are disabled during polling, so polling routine will
5389          * handle any replies.  Considering this, if polling is happening,
5390          * return with interrupt unclaimed.
5391          */
5392         if (mpt->m_polled_intr) {
5393                 mutex_exit(&mpt->m_mutex);
5394                 mptsas_log(mpt, CE_WARN, "mpt_sas: Unclaimed interrupt");
5395                 return (DDI_INTR_UNCLAIMED);
5396         }
5397 
5398         /*
5399          * Read the istat register.
5400          */
5401         if ((INTPENDING(mpt)) != 0) {
5402                 /*
5403                  * read fifo until empty.
5404                  */
5405 #ifndef __lock_lint
5406                 _NOTE(CONSTCOND)
5407 #endif
5408                 while (TRUE) {
5409                         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5410                             DDI_DMA_SYNC_FORCPU);
5411                         reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
5412                             MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
5413 
5414                         if (ddi_get32(mpt->m_acc_post_queue_hdl,
5415                             &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
5416                             ddi_get32(mpt->m_acc_post_queue_hdl,
5417                             &reply_desc_union->Words.High) == 0xFFFFFFFF) {
5418                                 break;
5419                         }
5420 
5421                         /*
5422                          * The reply is valid, process it according to its
5423                          * type.  Also, set a flag for updating the reply index
5424                          * after they've all been processed.
5425                          */
5426                         did_reply = TRUE;
5427 
5428                         mptsas_process_intr(mpt, reply_desc_union);
5429 
5430                         /*
5431                          * Increment post index and roll over if needed.
5432                          */
5433                         if (++mpt->m_post_index == mpt->m_post_queue_depth) {
5434                                 mpt->m_post_index = 0;
5435                         }
5436                 }
5437 
5438                 /*
5439                  * Update the global reply index if at least one reply was
5440                  * processed.
5441                  */
5442                 if (did_reply) {
5443                         ddi_put32(mpt->m_datap,
5444                             &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
5445                 }
5446         } else {
5447                 mutex_exit(&mpt->m_mutex);
5448                 return (DDI_INTR_UNCLAIMED);
5449         }
5450         NDBG1(("mptsas_intr complete"));
5451 
5452         /*
5453          * If no helper threads are created, process the doneq in ISR. If
5454          * helpers are created, use the doneq length as a metric to measure the
5455          * load on the interrupt CPU. If it is long enough, which indicates the
5456          * load is heavy, then we deliver the IO completions to the helpers.
5457          * This measurement has some limitations, although it is simple and
5458          * straightforward and works well for most of the cases at present.
5459          */
5460         if (!mpt->m_doneq_thread_n ||
5461             (mpt->m_doneq_len <= mpt->m_doneq_length_threshold)) {
5462                 mptsas_doneq_empty(mpt);
5463         } else {
5464                 mptsas_deliver_doneq_thread(mpt);
5465         }
5466 
5467         /*
5468          * If there are queued cmd, start them now.
5469          */
5470         if (mpt->m_waitq != NULL) {
5471                 mptsas_restart_waitq(mpt);
5472         }
5473 
5474         mutex_exit(&mpt->m_mutex);
5475         return (DDI_INTR_CLAIMED);
5476 }
5477 
5478 static void
5479 mptsas_process_intr(mptsas_t *mpt,
5480     pMpi2ReplyDescriptorsUnion_t reply_desc_union)
5481 {
5482         uint8_t reply_type;
5483 
5484         ASSERT(mutex_owned(&mpt->m_mutex));
5485 
5486         /*
5487          * The reply is valid, process it according to its
5488          * type.  Also, set a flag for updated the reply index
5489          * after they've all been processed.
5490          */
5491         reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
5492             &reply_desc_union->Default.ReplyFlags);
5493         reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
5494         if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
5495                 mptsas_handle_scsi_io_success(mpt, reply_desc_union);
5496         } else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
5497                 mptsas_handle_address_reply(mpt, reply_desc_union);
5498         } else {
5499                 mptsas_log(mpt, CE_WARN, "?Bad reply type %x", reply_type);
5500                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5501         }
5502 
5503         /*
5504          * Clear the reply descriptor for re-use and increment
5505          * index.
5506          */
5507         ddi_put64(mpt->m_acc_post_queue_hdl,
5508             &((uint64_t *)(void *)mpt->m_post_queue)[mpt->m_post_index],
5509             0xFFFFFFFFFFFFFFFF);
5510         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5511             DDI_DMA_SYNC_FORDEV);
5512 }
5513 
5514 /*
5515  * handle qfull condition
5516  */
5517 static void
5518 mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd)
5519 {
5520         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
5521 
5522         if ((++cmd->cmd_qfull_retries > ptgt->m_qfull_retries) ||
5523             (ptgt->m_qfull_retries == 0)) {
5524                 /*
5525                  * We have exhausted the retries on QFULL, or,
5526                  * the target driver has indicated that it
5527                  * wants to handle QFULL itself by setting
5528                  * qfull-retries capability to 0. In either case
5529                  * we want the target driver's QFULL handling
5530                  * to kick in. We do this by having pkt_reason
5531                  * as CMD_CMPLT and pkt_scbp as STATUS_QFULL.
5532                  */
5533                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5534         } else {
5535                 if (ptgt->m_reset_delay == 0) {
5536                         ptgt->m_t_throttle =
5537                             max((ptgt->m_t_ncmds - 2), 0);
5538                 }
5539 
5540                 cmd->cmd_pkt_flags |= FLAG_HEAD;
5541                 cmd->cmd_flags &= ~(CFLAG_TRANFLAG);
5542                 cmd->cmd_flags |= CFLAG_RETRY;
5543 
5544                 (void) mptsas_accept_pkt(mpt, cmd);
5545 
5546                 /*
5547                  * when target gives queue full status with no commands
5548                  * outstanding (m_t_ncmds == 0), throttle is set to 0
5549                  * (HOLD_THROTTLE), and the queue full handling start
5550                  * (see psarc/1994/313); if there are commands outstanding,
5551                  * throttle is set to (m_t_ncmds - 2)
5552                  */
5553                 if (ptgt->m_t_throttle == HOLD_THROTTLE) {
5554                         /*
5555                          * By setting throttle to QFULL_THROTTLE, we
5556                          * avoid submitting new commands and in
5557                          * mptsas_restart_cmd find out slots which need
5558                          * their throttles to be cleared.
5559                          */
5560                         mptsas_set_throttle(mpt, ptgt, QFULL_THROTTLE);
5561                         if (mpt->m_restart_cmd_timeid == 0) {
5562                                 mpt->m_restart_cmd_timeid =
5563                                     timeout(mptsas_restart_cmd, mpt,
5564                                     ptgt->m_qfull_retry_interval);
5565                         }
5566                 }
5567         }
5568 }
5569 
5570 mptsas_phymask_t
5571 mptsas_physport_to_phymask(mptsas_t *mpt, uint8_t physport)
5572 {
5573         mptsas_phymask_t        phy_mask = 0;
5574         uint8_t                 i = 0;
5575 
5576         NDBG20(("mptsas%d physport_to_phymask enter", mpt->m_instance));
5577 
5578         ASSERT(mutex_owned(&mpt->m_mutex));
5579 
5580         /*
5581          * If physport is 0xFF, this is a RAID volume.  Use phymask of 0.
5582          */
5583         if (physport == 0xFF) {
5584                 return (0);
5585         }
5586 
5587         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
5588                 if (mpt->m_phy_info[i].attached_devhdl &&
5589                     (mpt->m_phy_info[i].phy_mask != 0) &&
5590                     (mpt->m_phy_info[i].port_num == physport)) {
5591                         phy_mask = mpt->m_phy_info[i].phy_mask;
5592                         break;
5593                 }
5594         }
5595         NDBG20(("mptsas%d physport_to_phymask:physport :%x phymask :%x, ",
5596             mpt->m_instance, physport, phy_mask));
5597         return (phy_mask);
5598 }
5599 
5600 /*
5601  * mpt free device handle after device gone, by use of passthrough
5602  */
5603 static int
5604 mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl)
5605 {
5606         Mpi2SasIoUnitControlRequest_t   req;
5607         Mpi2SasIoUnitControlReply_t     rep;
5608         int                             ret;
5609 
5610         ASSERT(mutex_owned(&mpt->m_mutex));
5611 
5612         /*
5613          * Need to compose a SAS IO Unit Control request message
5614          * and call mptsas_do_passthru() function
5615          */
5616         bzero(&req, sizeof (req));
5617         bzero(&rep, sizeof (rep));
5618 
5619         req.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
5620         req.Operation = MPI2_SAS_OP_REMOVE_DEVICE;
5621         req.DevHandle = LE_16(devhdl);
5622 
5623         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
5624             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
5625         if (ret != 0) {
5626                 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
5627                     "Control error %d", ret);
5628                 return (DDI_FAILURE);
5629         }
5630 
5631         /* do passthrough success, check the ioc status */
5632         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
5633                 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
5634                     "Control IOCStatus %d", LE_16(rep.IOCStatus));
5635                 return (DDI_FAILURE);
5636         }
5637 
5638         return (DDI_SUCCESS);
5639 }
5640 
5641 static void
5642 mptsas_update_phymask(mptsas_t *mpt)
5643 {
5644         mptsas_phymask_t mask = 0, phy_mask;
5645         char            *phy_mask_name;
5646         uint8_t         current_port;
5647         int             i, j;
5648 
5649         NDBG20(("mptsas%d update phymask ", mpt->m_instance));
5650 
5651         ASSERT(mutex_owned(&mpt->m_mutex));
5652 
5653         (void) mptsas_get_sas_io_unit_page(mpt);
5654 
5655         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
5656 
5657         for (i = 0; i < mpt->m_num_phys; i++) {
5658                 phy_mask = 0x00;
5659 
5660                 if (mpt->m_phy_info[i].attached_devhdl == 0)
5661                         continue;
5662 
5663                 bzero(phy_mask_name, sizeof (phy_mask_name));
5664 
5665                 current_port = mpt->m_phy_info[i].port_num;
5666 
5667                 if ((mask & (1 << i)) != 0)
5668                         continue;
5669 
5670                 for (j = 0; j < mpt->m_num_phys; j++) {
5671                         if (mpt->m_phy_info[j].attached_devhdl &&
5672                             (mpt->m_phy_info[j].port_num == current_port)) {
5673                                 phy_mask |= (1 << j);
5674                         }
5675                 }
5676                 mask = mask | phy_mask;
5677 
5678                 for (j = 0; j < mpt->m_num_phys; j++) {
5679                         if ((phy_mask >> j) & 0x01) {
5680                                 mpt->m_phy_info[j].phy_mask = phy_mask;
5681                         }
5682                 }
5683 
5684                 (void) sprintf(phy_mask_name, "%x", phy_mask);
5685 
5686                 mutex_exit(&mpt->m_mutex);
5687                 /*
5688                  * register a iport, if the port has already been existed
5689                  * SCSA will do nothing and just return.
5690                  */
5691                 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
5692                 mutex_enter(&mpt->m_mutex);
5693         }
5694         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
5695         NDBG20(("mptsas%d update phymask return", mpt->m_instance));
5696 }
5697 
5698 /*
5699  * mptsas_handle_dr is a task handler for DR, the DR action includes:
5700  * 1. Directly attched Device Added/Removed.
5701  * 2. Expander Device Added/Removed.
5702  * 3. Indirectly Attached Device Added/Expander.
5703  * 4. LUNs of a existing device status change.
5704  * 5. RAID volume created/deleted.
5705  * 6. Member of RAID volume is released because of RAID deletion.
5706  * 7. Physical disks are removed because of RAID creation.
5707  */
5708 static void
5709 mptsas_handle_dr(void *args) {
5710         mptsas_topo_change_list_t       *topo_node = NULL;
5711         mptsas_topo_change_list_t       *save_node = NULL;
5712         mptsas_t                        *mpt;
5713         dev_info_t                      *parent = NULL;
5714         mptsas_phymask_t                phymask = 0;
5715         char                            *phy_mask_name;
5716         uint8_t                         flags = 0, physport = 0xff;
5717         uint8_t                         port_update = 0;
5718         uint_t                          event;
5719 
5720         topo_node = (mptsas_topo_change_list_t *)args;
5721 
5722         mpt = topo_node->mpt;
5723         event = topo_node->event;
5724         flags = topo_node->flags;
5725 
5726         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
5727 
5728         NDBG20(("mptsas%d handle_dr enter", mpt->m_instance));
5729 
5730         switch (event) {
5731         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
5732                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
5733                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE) ||
5734                     (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
5735                         /*
5736                          * Direct attached or expander attached device added
5737                          * into system or a Phys Disk that is being unhidden.
5738                          */
5739                         port_update = 1;
5740                 }
5741                 break;
5742         case MPTSAS_DR_EVENT_RECONFIG_SMP:
5743                 /*
5744                  * New expander added into system, it must be the head
5745                  * of topo_change_list_t
5746                  */
5747                 port_update = 1;
5748                 break;
5749         default:
5750                 port_update = 0;
5751                 break;
5752         }
5753         /*
5754          * All cases port_update == 1 may cause initiator port form change
5755          */
5756         mutex_enter(&mpt->m_mutex);
5757         if (mpt->m_port_chng && port_update) {
5758                 /*
5759                  * mpt->m_port_chng flag indicates some PHYs of initiator
5760                  * port have changed to online. So when expander added or
5761                  * directly attached device online event come, we force to
5762                  * update port information by issueing SAS IO Unit Page and
5763                  * update PHYMASKs.
5764                  */
5765                 (void) mptsas_update_phymask(mpt);
5766                 mpt->m_port_chng = 0;
5767 
5768         }
5769         mutex_exit(&mpt->m_mutex);
5770         while (topo_node) {
5771                 phymask = 0;
5772                 if (parent == NULL) {
5773                         physport = topo_node->un.physport;
5774                         event = topo_node->event;
5775                         flags = topo_node->flags;
5776                         if (event & (MPTSAS_DR_EVENT_OFFLINE_TARGET |
5777                             MPTSAS_DR_EVENT_OFFLINE_SMP)) {
5778                                 /*
5779                                  * For all offline events, phymask is known
5780                                  */
5781                                 phymask = topo_node->un.phymask;
5782                                 goto find_parent;
5783                         }
5784                         if (event & MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
5785                                 goto handle_topo_change;
5786                         }
5787                         if (flags & MPTSAS_TOPO_FLAG_LUN_ASSOCIATED) {
5788                                 phymask = topo_node->un.phymask;
5789                                 goto find_parent;
5790                         }
5791 
5792                         if ((flags ==
5793                             MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) &&
5794                             (event == MPTSAS_DR_EVENT_RECONFIG_TARGET)) {
5795                                 /*
5796                                  * There is no any field in IR_CONFIG_CHANGE
5797                                  * event indicate physport/phynum, let's get
5798                                  * parent after SAS Device Page0 request.
5799                                  */
5800                                 goto handle_topo_change;
5801                         }
5802 
5803                         mutex_enter(&mpt->m_mutex);
5804                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
5805                                 /*
5806                                  * If the direct attached device added or a
5807                                  * phys disk is being unhidden, argument
5808                                  * physport actually is PHY#, so we have to get
5809                                  * phymask according PHY#.
5810                                  */
5811                                 physport = mpt->m_phy_info[physport].port_num;
5812                         }
5813 
5814                         /*
5815                          * Translate physport to phymask so that we can search
5816                          * parent dip.
5817                          */
5818                         phymask = mptsas_physport_to_phymask(mpt,
5819                             physport);
5820                         mutex_exit(&mpt->m_mutex);
5821 
5822 find_parent:
5823                         bzero(phy_mask_name, MPTSAS_MAX_PHYS);
5824                         /*
5825                          * For RAID topology change node, write the iport name
5826                          * as v0.
5827                          */
5828                         if (flags & MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5829                                 (void) sprintf(phy_mask_name, "v0");
5830                         } else {
5831                                 /*
5832                                  * phymask can bo 0 if the drive has been
5833                                  * pulled by the time an add event is
5834                                  * processed.  If phymask is 0, just skip this
5835                                  * event and continue.
5836                                  */
5837                                 if (phymask == 0) {
5838                                         mutex_enter(&mpt->m_mutex);
5839                                         save_node = topo_node;
5840                                         topo_node = topo_node->next;
5841                                         ASSERT(save_node);
5842                                         kmem_free(save_node,
5843                                             sizeof (mptsas_topo_change_list_t));
5844                                         mutex_exit(&mpt->m_mutex);
5845 
5846                                         parent = NULL;
5847                                         continue;
5848                                 }
5849                                 (void) sprintf(phy_mask_name, "%x", phymask);
5850                         }
5851                         parent = scsi_hba_iport_find(mpt->m_dip,
5852                             phy_mask_name);
5853                         if (parent == NULL) {
5854                                 mptsas_log(mpt, CE_WARN, "Failed to find an "
5855                                     "iport, should not happen!");
5856                                 goto out;
5857                         }
5858 
5859                 }
5860                 ASSERT(parent);
5861 handle_topo_change:
5862 
5863                 mutex_enter(&mpt->m_mutex);
5864                 /*
5865                  * If HBA is being reset, don't perform operations depending
5866                  * on the IOC. We must free the topo list, however.
5867                  */
5868                 if (!mpt->m_in_reset)
5869                         mptsas_handle_topo_change(topo_node, parent);
5870                 else
5871                         NDBG20(("skipping topo change received during reset"));
5872                 save_node = topo_node;
5873                 topo_node = topo_node->next;
5874                 ASSERT(save_node);
5875                 kmem_free(save_node, sizeof (mptsas_topo_change_list_t));
5876                 mutex_exit(&mpt->m_mutex);
5877 
5878                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
5879                     (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) ||
5880                     (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED)) {
5881                         /*
5882                          * If direct attached device associated, make sure
5883                          * reset the parent before start the next one. But
5884                          * all devices associated with expander shares the
5885                          * parent.  Also, reset parent if this is for RAID.
5886                          */
5887                         parent = NULL;
5888                 }
5889         }
5890 out:
5891         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
5892 }
5893 
5894 static void
5895 mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
5896     dev_info_t *parent)
5897 {
5898         mptsas_target_t *ptgt = NULL;
5899         mptsas_smp_t    *psmp = NULL;
5900         mptsas_t        *mpt = (void *)topo_node->mpt;
5901         uint16_t        devhdl;
5902         uint16_t        attached_devhdl;
5903         uint64_t        sas_wwn = 0;
5904         int             rval = 0;
5905         uint32_t        page_address;
5906         uint8_t         phy, flags;
5907         char            *addr = NULL;
5908         dev_info_t      *lundip;
5909         int             circ = 0, circ1 = 0;
5910         char            attached_wwnstr[MPTSAS_WWN_STRLEN];
5911 
5912         NDBG20(("mptsas%d handle_topo_change enter", mpt->m_instance));
5913 
5914         ASSERT(mutex_owned(&mpt->m_mutex));
5915 
5916         switch (topo_node->event) {
5917         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
5918         {
5919                 char *phy_mask_name;
5920                 mptsas_phymask_t phymask = 0;
5921 
5922                 if (topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5923                         /*
5924                          * Get latest RAID info.
5925                          */
5926                         (void) mptsas_get_raid_info(mpt);
5927                         ptgt = refhash_linear_search(mpt->m_targets,
5928                             mptsas_target_eval_devhdl, &topo_node->devhdl);
5929                         if (ptgt == NULL)
5930                                 break;
5931                 } else {
5932                         ptgt = (void *)topo_node->object;
5933                 }
5934 
5935                 if (ptgt == NULL) {
5936                         /*
5937                          * If a Phys Disk was deleted, RAID info needs to be
5938                          * updated to reflect the new topology.
5939                          */
5940                         (void) mptsas_get_raid_info(mpt);
5941 
5942                         /*
5943                          * Get sas device page 0 by DevHandle to make sure if
5944                          * SSP/SATA end device exist.
5945                          */
5946                         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
5947                             MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
5948                             topo_node->devhdl;
5949 
5950                         rval = mptsas_get_target_device_info(mpt, page_address,
5951                             &devhdl, &ptgt);
5952                         if (rval == DEV_INFO_WRONG_DEVICE_TYPE) {
5953                                 mptsas_log(mpt, CE_NOTE,
5954                                     "mptsas_handle_topo_change: target %d is "
5955                                     "not a SAS/SATA device. \n",
5956                                     topo_node->devhdl);
5957                         } else if (rval == DEV_INFO_FAIL_ALLOC) {
5958                                 mptsas_log(mpt, CE_NOTE,
5959                                     "mptsas_handle_topo_change: could not "
5960                                     "allocate memory. \n");
5961                         }
5962                         /*
5963                          * If rval is DEV_INFO_PHYS_DISK than there is nothing
5964                          * else to do, just leave.
5965                          */
5966                         if (rval != DEV_INFO_SUCCESS) {
5967                                 return;
5968                         }
5969                 }
5970 
5971                 ASSERT(ptgt->m_devhdl == topo_node->devhdl);
5972 
5973                 mutex_exit(&mpt->m_mutex);
5974                 flags = topo_node->flags;
5975 
5976                 if (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) {
5977                         phymask = ptgt->m_addr.mta_phymask;
5978                         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
5979                         (void) sprintf(phy_mask_name, "%x", phymask);
5980                         parent = scsi_hba_iport_find(mpt->m_dip,
5981                             phy_mask_name);
5982                         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
5983                         if (parent == NULL) {
5984                                 mptsas_log(mpt, CE_WARN, "Failed to find a "
5985                                     "iport for PD, should not happen!");
5986                                 mutex_enter(&mpt->m_mutex);
5987                                 break;
5988                         }
5989                 }
5990 
5991                 if (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5992                         ndi_devi_enter(parent, &circ1);
5993                         (void) mptsas_config_raid(parent, topo_node->devhdl,
5994                             &lundip);
5995                         ndi_devi_exit(parent, circ1);
5996                 } else {
5997                         /*
5998                          * hold nexus for bus configure
5999                          */
6000                         ndi_devi_enter(scsi_vhci_dip, &circ);
6001                         ndi_devi_enter(parent, &circ1);
6002                         rval = mptsas_config_target(parent, ptgt);
6003                         /*
6004                          * release nexus for bus configure
6005                          */
6006                         ndi_devi_exit(parent, circ1);
6007                         ndi_devi_exit(scsi_vhci_dip, circ);
6008 
6009                         /*
6010                          * Add parent's props for SMHBA support
6011                          */
6012                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6013                                 bzero(attached_wwnstr,
6014                                     sizeof (attached_wwnstr));
6015                                 (void) sprintf(attached_wwnstr, "w%016"PRIx64,
6016                                     ptgt->m_addr.mta_wwn);
6017                                 if (ddi_prop_update_string(DDI_DEV_T_NONE,
6018                                     parent,
6019                                     SCSI_ADDR_PROP_ATTACHED_PORT,
6020                                     attached_wwnstr)
6021                                     != DDI_PROP_SUCCESS) {
6022                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6023                                             parent,
6024                                             SCSI_ADDR_PROP_ATTACHED_PORT);
6025                                         mptsas_log(mpt, CE_WARN, "Failed to"
6026                                             "attached-port props");
6027                                         return;
6028                                 }
6029                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6030                                     MPTSAS_NUM_PHYS, 1) !=
6031                                     DDI_PROP_SUCCESS) {
6032                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6033                                             parent, MPTSAS_NUM_PHYS);
6034                                         mptsas_log(mpt, CE_WARN, "Failed to"
6035                                             " create num-phys props");
6036                                         return;
6037                                 }
6038 
6039                                 /*
6040                                  * Update PHY info for smhba
6041                                  */
6042                                 mutex_enter(&mpt->m_mutex);
6043                                 if (mptsas_smhba_phy_init(mpt)) {
6044                                         mutex_exit(&mpt->m_mutex);
6045                                         mptsas_log(mpt, CE_WARN, "mptsas phy"
6046                                             " update failed");
6047                                         return;
6048                                 }
6049                                 mutex_exit(&mpt->m_mutex);
6050 
6051                                 /*
6052                                  * topo_node->un.physport is really the PHY#
6053                                  * for direct attached devices
6054                                  */
6055                                 mptsas_smhba_set_one_phy_props(mpt, parent,
6056                                     topo_node->un.physport, &attached_devhdl);
6057 
6058                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6059                                     MPTSAS_VIRTUAL_PORT, 0) !=
6060                                     DDI_PROP_SUCCESS) {
6061                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6062                                             parent, MPTSAS_VIRTUAL_PORT);
6063                                         mptsas_log(mpt, CE_WARN,
6064                                             "mptsas virtual-port"
6065                                             "port prop update failed");
6066                                         return;
6067                                 }
6068                         }
6069                 }
6070                 mutex_enter(&mpt->m_mutex);
6071 
6072                 NDBG20(("mptsas%d handle_topo_change to online devhdl:%x, "
6073                     "phymask:%x.", mpt->m_instance, ptgt->m_devhdl,
6074                     ptgt->m_addr.mta_phymask));
6075                 break;
6076         }
6077         case MPTSAS_DR_EVENT_OFFLINE_TARGET:
6078         {
6079                 devhdl = topo_node->devhdl;
6080                 ptgt = refhash_linear_search(mpt->m_targets,
6081                     mptsas_target_eval_devhdl, &devhdl);
6082                 if (ptgt == NULL)
6083                         break;
6084 
6085                 sas_wwn = ptgt->m_addr.mta_wwn;
6086                 phy = ptgt->m_phynum;
6087 
6088                 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
6089 
6090                 if (sas_wwn) {
6091                         (void) sprintf(addr, "w%016"PRIx64, sas_wwn);
6092                 } else {
6093                         (void) sprintf(addr, "p%x", phy);
6094                 }
6095                 ASSERT(ptgt->m_devhdl == devhdl);
6096 
6097                 if ((topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) ||
6098                     (topo_node->flags ==
6099                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6100                         /*
6101                          * Get latest RAID info if RAID volume status changes
6102                          * or Phys Disk status changes
6103                          */
6104                         (void) mptsas_get_raid_info(mpt);
6105                 }
6106                 /*
6107                  * Abort all outstanding command on the device
6108                  */
6109                 rval = mptsas_do_scsi_reset(mpt, devhdl);
6110                 if (rval) {
6111                         NDBG20(("mptsas%d handle_topo_change to reset target "
6112                             "before offline devhdl:%x, phymask:%x, rval:%x",
6113                             mpt->m_instance, ptgt->m_devhdl,
6114                             ptgt->m_addr.mta_phymask, rval));
6115                 }
6116 
6117                 mutex_exit(&mpt->m_mutex);
6118 
6119                 ndi_devi_enter(scsi_vhci_dip, &circ);
6120                 ndi_devi_enter(parent, &circ1);
6121                 rval = mptsas_offline_target(parent, addr);
6122                 ndi_devi_exit(parent, circ1);
6123                 ndi_devi_exit(scsi_vhci_dip, circ);
6124                 NDBG20(("mptsas%d handle_topo_change to offline devhdl:%x, "
6125                     "phymask:%x, rval:%x", mpt->m_instance,
6126                     ptgt->m_devhdl, ptgt->m_addr.mta_phymask, rval));
6127 
6128                 kmem_free(addr, SCSI_MAXNAMELEN);
6129 
6130                 /*
6131                  * Clear parent's props for SMHBA support
6132                  */
6133                 flags = topo_node->flags;
6134                 if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6135                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6136                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6137                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6138                             DDI_PROP_SUCCESS) {
6139                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6140                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6141                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6142                                     "prop update failed");
6143                                 break;
6144                         }
6145                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6146                             MPTSAS_NUM_PHYS, 0) !=
6147                             DDI_PROP_SUCCESS) {
6148                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6149                                     MPTSAS_NUM_PHYS);
6150                                 mptsas_log(mpt, CE_WARN, "mptsas num phys "
6151                                     "prop update failed");
6152                                 break;
6153                         }
6154                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6155                             MPTSAS_VIRTUAL_PORT, 1) !=
6156                             DDI_PROP_SUCCESS) {
6157                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6158                                     MPTSAS_VIRTUAL_PORT);
6159                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6160                                     "prop update failed");
6161                                 break;
6162                         }
6163                 }
6164 
6165                 mutex_enter(&mpt->m_mutex);
6166                 ptgt->m_led_status = 0;
6167                 (void) mptsas_flush_led_status(mpt, ptgt);
6168                 if (rval == DDI_SUCCESS) {
6169                         refhash_remove(mpt->m_targets, ptgt);
6170                         ptgt = NULL;
6171                 } else {
6172                         /*
6173                          * clean DR_INTRANSITION flag to allow I/O down to
6174                          * PHCI driver since failover finished.
6175                          * Invalidate the devhdl
6176                          */
6177                         ptgt->m_devhdl = MPTSAS_INVALID_DEVHDL;
6178                         ptgt->m_tgt_unconfigured = 0;
6179                         mutex_enter(&mpt->m_tx_waitq_mutex);
6180                         ptgt->m_dr_flag = MPTSAS_DR_INACTIVE;
6181                         mutex_exit(&mpt->m_tx_waitq_mutex);
6182                 }
6183 
6184                 /*
6185                  * Send SAS IO Unit Control to free the dev handle
6186                  */
6187                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6188                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE)) {
6189                         rval = mptsas_free_devhdl(mpt, devhdl);
6190 
6191                         NDBG20(("mptsas%d handle_topo_change to remove "
6192                             "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6193                             rval));
6194                 }
6195 
6196                 break;
6197         }
6198         case MPTSAS_TOPO_FLAG_REMOVE_HANDLE:
6199         {
6200                 devhdl = topo_node->devhdl;
6201                 /*
6202                  * If this is the remove handle event, do a reset first.
6203                  */
6204                 if (topo_node->event == MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
6205                         rval = mptsas_do_scsi_reset(mpt, devhdl);
6206                         if (rval) {
6207                                 NDBG20(("mpt%d reset target before remove "
6208                                     "devhdl:%x, rval:%x", mpt->m_instance,
6209                                     devhdl, rval));
6210                         }
6211                 }
6212 
6213                 /*
6214                  * Send SAS IO Unit Control to free the dev handle
6215                  */
6216                 rval = mptsas_free_devhdl(mpt, devhdl);
6217                 NDBG20(("mptsas%d handle_topo_change to remove "
6218                     "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6219                     rval));
6220                 break;
6221         }
6222         case MPTSAS_DR_EVENT_RECONFIG_SMP:
6223         {
6224                 mptsas_smp_t smp;
6225                 dev_info_t *smpdip;
6226 
6227                 devhdl = topo_node->devhdl;
6228 
6229                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
6230                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)devhdl;
6231                 rval = mptsas_get_sas_expander_page0(mpt, page_address, &smp);
6232                 if (rval != DDI_SUCCESS) {
6233                         mptsas_log(mpt, CE_WARN, "failed to online smp, "
6234                             "handle %x", devhdl);
6235                         return;
6236                 }
6237 
6238                 psmp = mptsas_smp_alloc(mpt, &smp);
6239                 if (psmp == NULL) {
6240                         return;
6241                 }
6242 
6243                 mutex_exit(&mpt->m_mutex);
6244                 ndi_devi_enter(parent, &circ1);
6245                 (void) mptsas_online_smp(parent, psmp, &smpdip);
6246                 ndi_devi_exit(parent, circ1);
6247 
6248                 mutex_enter(&mpt->m_mutex);
6249                 break;
6250         }
6251         case MPTSAS_DR_EVENT_OFFLINE_SMP:
6252         {
6253                 devhdl = topo_node->devhdl;
6254                 uint32_t dev_info;
6255 
6256                 psmp = refhash_linear_search(mpt->m_smp_targets,
6257                     mptsas_smp_eval_devhdl, &devhdl);
6258                 if (psmp == NULL)
6259                         break;
6260                 /*
6261                  * The mptsas_smp_t data is released only if the dip is offlined
6262                  * successfully.
6263                  */
6264                 mutex_exit(&mpt->m_mutex);
6265 
6266                 ndi_devi_enter(parent, &circ1);
6267                 rval = mptsas_offline_smp(parent, psmp, NDI_DEVI_REMOVE);
6268                 ndi_devi_exit(parent, circ1);
6269 
6270                 dev_info = psmp->m_deviceinfo;
6271                 if ((dev_info & DEVINFO_DIRECT_ATTACHED) ==
6272                     DEVINFO_DIRECT_ATTACHED) {
6273                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6274                             MPTSAS_VIRTUAL_PORT, 1) !=
6275                             DDI_PROP_SUCCESS) {
6276                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6277                                     MPTSAS_VIRTUAL_PORT);
6278                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6279                                     "prop update failed");
6280                                 return;
6281                         }
6282                         /*
6283                          * Check whether the smp connected to the iport,
6284                          */
6285                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6286                             MPTSAS_NUM_PHYS, 0) !=
6287                             DDI_PROP_SUCCESS) {
6288                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6289                                     MPTSAS_NUM_PHYS);
6290                                 mptsas_log(mpt, CE_WARN, "mptsas num phys"
6291                                     "prop update failed");
6292                                 return;
6293                         }
6294                         /*
6295                          * Clear parent's attached-port props
6296                          */
6297                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6298                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6299                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6300                             DDI_PROP_SUCCESS) {
6301                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6302                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6303                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6304                                     "prop update failed");
6305                                 return;
6306                         }
6307                 }
6308 
6309                 mutex_enter(&mpt->m_mutex);
6310                 NDBG20(("mptsas%d handle_topo_change to remove devhdl:%x, "
6311                     "rval:%x", mpt->m_instance, psmp->m_devhdl, rval));
6312                 if (rval == DDI_SUCCESS) {
6313                         refhash_remove(mpt->m_smp_targets, psmp);
6314                 } else {
6315                         psmp->m_devhdl = MPTSAS_INVALID_DEVHDL;
6316                 }
6317 
6318                 bzero(attached_wwnstr, sizeof (attached_wwnstr));
6319 
6320                 break;
6321         }
6322         default:
6323                 return;
6324         }
6325 }
6326 
6327 /*
6328  * Record the event if its type is enabled in mpt instance by ioctl.
6329  */
6330 static void
6331 mptsas_record_event(void *args)
6332 {
6333         m_replyh_arg_t                  *replyh_arg;
6334         pMpi2EventNotificationReply_t   eventreply;
6335         uint32_t                        event, rfm;
6336         mptsas_t                        *mpt;
6337         int                             i, j;
6338         uint16_t                        event_data_len;
6339         boolean_t                       sendAEN = FALSE;
6340 
6341         replyh_arg = (m_replyh_arg_t *)args;
6342         rfm = replyh_arg->rfm;
6343         mpt = replyh_arg->mpt;
6344 
6345         eventreply = (pMpi2EventNotificationReply_t)
6346             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
6347         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6348 
6349 
6350         /*
6351          * Generate a system event to let anyone who cares know that a
6352          * LOG_ENTRY_ADDED event has occurred.  This is sent no matter what the
6353          * event mask is set to.
6354          */
6355         if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
6356                 sendAEN = TRUE;
6357         }
6358 
6359         /*
6360          * Record the event only if it is not masked.  Determine which dword
6361          * and bit of event mask to test.
6362          */
6363         i = (uint8_t)(event / 32);
6364         j = (uint8_t)(event % 32);
6365         if ((i < 4) && ((1 << j) & mpt->m_event_mask[i])) {
6366                 i = mpt->m_event_index;
6367                 mpt->m_events[i].Type = event;
6368                 mpt->m_events[i].Number = ++mpt->m_event_number;
6369                 bzero(mpt->m_events[i].Data, MPTSAS_MAX_EVENT_DATA_LENGTH * 4);
6370                 event_data_len = ddi_get16(mpt->m_acc_reply_frame_hdl,
6371                     &eventreply->EventDataLength);
6372 
6373                 if (event_data_len > 0) {
6374                         /*
6375                          * Limit data to size in m_event entry
6376                          */
6377                         if (event_data_len > MPTSAS_MAX_EVENT_DATA_LENGTH) {
6378                                 event_data_len = MPTSAS_MAX_EVENT_DATA_LENGTH;
6379                         }
6380                         for (j = 0; j < event_data_len; j++) {
6381                                 mpt->m_events[i].Data[j] =
6382                                     ddi_get32(mpt->m_acc_reply_frame_hdl,
6383                                     &(eventreply->EventData[j]));
6384                         }
6385 
6386                         /*
6387                          * check for index wrap-around
6388                          */
6389                         if (++i == MPTSAS_EVENT_QUEUE_SIZE) {
6390                                 i = 0;
6391                         }
6392                         mpt->m_event_index = (uint8_t)i;
6393 
6394                         /*
6395                          * Set flag to send the event.
6396                          */
6397                         sendAEN = TRUE;
6398                 }
6399         }
6400 
6401         /*
6402          * Generate a system event if flag is set to let anyone who cares know
6403          * that an event has occurred.
6404          */
6405         if (sendAEN) {
6406                 (void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS",
6407                     "SAS", NULL, NULL, DDI_NOSLEEP);
6408         }
6409 }
6410 
6411 #define SMP_RESET_IN_PROGRESS MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS
6412 /*
6413  * handle sync events from ioc in interrupt
6414  * return value:
6415  * DDI_SUCCESS: The event is handled by this func
6416  * DDI_FAILURE: Event is not handled
6417  */
6418 static int
6419 mptsas_handle_event_sync(void *args)
6420 {
6421         m_replyh_arg_t                  *replyh_arg;
6422         pMpi2EventNotificationReply_t   eventreply;
6423         uint32_t                        event, rfm;
6424         mptsas_t                        *mpt;
6425         uint_t                          iocstatus;
6426 
6427         replyh_arg = (m_replyh_arg_t *)args;
6428         rfm = replyh_arg->rfm;
6429         mpt = replyh_arg->mpt;
6430 
6431         ASSERT(mutex_owned(&mpt->m_mutex));
6432 
6433         eventreply = (pMpi2EventNotificationReply_t)
6434             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
6435         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6436 
6437         if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
6438             &eventreply->IOCStatus)) {
6439                 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
6440                         mptsas_log(mpt, CE_WARN,
6441                             "!mptsas_handle_event_sync: IOCStatus=0x%x, "
6442                             "IOCLogInfo=0x%x", iocstatus,
6443                             ddi_get32(mpt->m_acc_reply_frame_hdl,
6444                             &eventreply->IOCLogInfo));
6445                 } else {
6446                         mptsas_log(mpt, CE_WARN,
6447                             "mptsas_handle_event_sync: IOCStatus=0x%x, "
6448                             "IOCLogInfo=0x%x", iocstatus,
6449                             ddi_get32(mpt->m_acc_reply_frame_hdl,
6450                             &eventreply->IOCLogInfo));
6451                 }
6452         }
6453 
6454         /*
6455          * figure out what kind of event we got and handle accordingly
6456          */
6457         switch (event) {
6458         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
6459         {
6460                 pMpi2EventDataSasTopologyChangeList_t   sas_topo_change_list;
6461                 uint8_t                         num_entries, expstatus, phy;
6462                 uint8_t                         phystatus, physport, state, i;
6463                 uint8_t                         start_phy_num, link_rate;
6464                 uint16_t                        dev_handle, reason_code;
6465                 uint16_t                        enc_handle, expd_handle;
6466                 char                            string[80], curr[80], prev[80];
6467                 mptsas_topo_change_list_t       *topo_head = NULL;
6468                 mptsas_topo_change_list_t       *topo_tail = NULL;
6469                 mptsas_topo_change_list_t       *topo_node = NULL;
6470                 mptsas_target_t                 *ptgt;
6471                 mptsas_smp_t                    *psmp;
6472                 uint8_t                         flags = 0, exp_flag;
6473                 smhba_info_t                    *pSmhba = NULL;
6474 
6475                 NDBG20(("mptsas_handle_event_sync: SAS topology change"));
6476 
6477                 sas_topo_change_list = (pMpi2EventDataSasTopologyChangeList_t)
6478                     eventreply->EventData;
6479 
6480                 enc_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6481                     &sas_topo_change_list->EnclosureHandle);
6482                 expd_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6483                     &sas_topo_change_list->ExpanderDevHandle);
6484                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6485                     &sas_topo_change_list->NumEntries);
6486                 start_phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
6487                     &sas_topo_change_list->StartPhyNum);
6488                 expstatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6489                     &sas_topo_change_list->ExpStatus);
6490                 physport = ddi_get8(mpt->m_acc_reply_frame_hdl,
6491                     &sas_topo_change_list->PhysicalPort);
6492 
6493                 string[0] = 0;
6494                 if (expd_handle) {
6495                         flags = MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED;
6496                         switch (expstatus) {
6497                         case MPI2_EVENT_SAS_TOPO_ES_ADDED:
6498                                 (void) sprintf(string, " added");
6499                                 /*
6500                                  * New expander device added
6501                                  */
6502                                 mpt->m_port_chng = 1;
6503                                 topo_node = kmem_zalloc(
6504                                     sizeof (mptsas_topo_change_list_t),
6505                                     KM_SLEEP);
6506                                 topo_node->mpt = mpt;
6507                                 topo_node->event = MPTSAS_DR_EVENT_RECONFIG_SMP;
6508                                 topo_node->un.physport = physport;
6509                                 topo_node->devhdl = expd_handle;
6510                                 topo_node->flags = flags;
6511                                 topo_node->object = NULL;
6512                                 if (topo_head == NULL) {
6513                                         topo_head = topo_tail = topo_node;
6514                                 } else {
6515                                         topo_tail->next = topo_node;
6516                                         topo_tail = topo_node;
6517                                 }
6518                                 break;
6519                         case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
6520                                 (void) sprintf(string, " not responding, "
6521                                     "removed");
6522                                 psmp = refhash_linear_search(mpt->m_smp_targets,
6523                                     mptsas_smp_eval_devhdl, &expd_handle);
6524                                 if (psmp == NULL)
6525                                         break;
6526 
6527                                 topo_node = kmem_zalloc(
6528                                     sizeof (mptsas_topo_change_list_t),
6529                                     KM_SLEEP);
6530                                 topo_node->mpt = mpt;
6531                                 topo_node->un.phymask =
6532                                     psmp->m_addr.mta_phymask;
6533                                 topo_node->event = MPTSAS_DR_EVENT_OFFLINE_SMP;
6534                                 topo_node->devhdl = expd_handle;
6535                                 topo_node->flags = flags;
6536                                 topo_node->object = NULL;
6537                                 if (topo_head == NULL) {
6538                                         topo_head = topo_tail = topo_node;
6539                                 } else {
6540                                         topo_tail->next = topo_node;
6541                                         topo_tail = topo_node;
6542                                 }
6543                                 break;
6544                         case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
6545                                 break;
6546                         case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
6547                                 (void) sprintf(string, " not responding, "
6548                                     "delaying removal");
6549                                 break;
6550                         default:
6551                                 break;
6552                         }
6553                 } else {
6554                         flags = MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE;
6555                 }
6556 
6557                 NDBG20(("SAS TOPOLOGY CHANGE for enclosure %x expander %x%s\n",
6558                     enc_handle, expd_handle, string));
6559                 for (i = 0; i < num_entries; i++) {
6560                         phy = i + start_phy_num;
6561                         phystatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6562                             &sas_topo_change_list->PHY[i].PhyStatus);
6563                         dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6564                             &sas_topo_change_list->PHY[i].AttachedDevHandle);
6565                         reason_code = phystatus & MPI2_EVENT_SAS_TOPO_RC_MASK;
6566                         /*
6567                          * Filter out processing of Phy Vacant Status unless
6568                          * the reason code is "Not Responding".  Process all
6569                          * other combinations of Phy Status and Reason Codes.
6570                          */
6571                         if ((phystatus &
6572                             MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) &&
6573                             (reason_code !=
6574                             MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) {
6575                                 continue;
6576                         }
6577                         curr[0] = 0;
6578                         prev[0] = 0;
6579                         string[0] = 0;
6580                         switch (reason_code) {
6581                         case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
6582                         {
6583                                 NDBG20(("mptsas%d phy %d physical_port %d "
6584                                     "dev_handle %d added", mpt->m_instance, phy,
6585                                     physport, dev_handle));
6586                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
6587                                     &sas_topo_change_list->PHY[i].LinkRate);
6588                                 state = (link_rate &
6589                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
6590                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
6591                                 switch (state) {
6592                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
6593                                         (void) sprintf(curr, "is disabled");
6594                                         break;
6595                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
6596                                         (void) sprintf(curr, "is offline, "
6597                                             "failed speed negotiation");
6598                                         break;
6599                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
6600                                         (void) sprintf(curr, "SATA OOB "
6601                                             "complete");
6602                                         break;
6603                                 case SMP_RESET_IN_PROGRESS:
6604                                         (void) sprintf(curr, "SMP reset in "
6605                                             "progress");
6606                                         break;
6607                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
6608                                         (void) sprintf(curr, "is online at "
6609                                             "1.5 Gbps");
6610                                         break;
6611                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
6612                                         (void) sprintf(curr, "is online at 3.0 "
6613                                             "Gbps");
6614                                         break;
6615                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
6616                                         (void) sprintf(curr, "is online at 6.0 "
6617                                             "Gbps");
6618                                         break;
6619                                 default:
6620                                         (void) sprintf(curr, "state is "
6621                                             "unknown");
6622                                         break;
6623                                 }
6624                                 /*
6625                                  * New target device added into the system.
6626                                  * Set association flag according to if an
6627                                  * expander is used or not.
6628                                  */
6629                                 exp_flag =
6630                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
6631                                 if (flags ==
6632                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
6633                                         flags = exp_flag;
6634                                 }
6635                                 topo_node = kmem_zalloc(
6636                                     sizeof (mptsas_topo_change_list_t),
6637                                     KM_SLEEP);
6638                                 topo_node->mpt = mpt;
6639                                 topo_node->event =
6640                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
6641                                 if (expd_handle == 0) {
6642                                         /*
6643                                          * Per MPI 2, if expander dev handle
6644                                          * is 0, it's a directly attached
6645                                          * device. So driver use PHY to decide
6646                                          * which iport is associated
6647                                          */
6648                                         physport = phy;
6649                                         mpt->m_port_chng = 1;
6650                                 }
6651                                 topo_node->un.physport = physport;
6652                                 topo_node->devhdl = dev_handle;
6653                                 topo_node->flags = flags;
6654                                 topo_node->object = NULL;
6655                                 if (topo_head == NULL) {
6656                                         topo_head = topo_tail = topo_node;
6657                                 } else {
6658                                         topo_tail->next = topo_node;
6659                                         topo_tail = topo_node;
6660                                 }
6661                                 break;
6662                         }
6663                         case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
6664                         {
6665                                 NDBG20(("mptsas%d phy %d physical_port %d "
6666                                     "dev_handle %d removed", mpt->m_instance,
6667                                     phy, physport, dev_handle));
6668                                 /*
6669                                  * Set association flag according to if an
6670                                  * expander is used or not.
6671                                  */
6672                                 exp_flag =
6673                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
6674                                 if (flags ==
6675                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
6676                                         flags = exp_flag;
6677                                 }
6678                                 /*
6679                                  * Target device is removed from the system
6680                                  * Before the device is really offline from
6681                                  * from system.
6682                                  */
6683                                 ptgt = refhash_linear_search(mpt->m_targets,
6684                                     mptsas_target_eval_devhdl, &dev_handle);
6685                                 /*
6686                                  * If ptgt is NULL here, it means that the
6687                                  * DevHandle is not in the hash table.  This is
6688                                  * reasonable sometimes.  For example, if a
6689                                  * disk was pulled, then added, then pulled
6690                                  * again, the disk will not have been put into
6691                                  * the hash table because the add event will
6692                                  * have an invalid phymask.  BUT, this does not
6693                                  * mean that the DevHandle is invalid.  The
6694                                  * controller will still have a valid DevHandle
6695                                  * that must be removed.  To do this, use the
6696                                  * MPTSAS_TOPO_FLAG_REMOVE_HANDLE event.
6697                                  */
6698                                 if (ptgt == NULL) {
6699                                         topo_node = kmem_zalloc(
6700                                             sizeof (mptsas_topo_change_list_t),
6701                                             KM_SLEEP);
6702                                         topo_node->mpt = mpt;
6703                                         topo_node->un.phymask = 0;
6704                                         topo_node->event =
6705                                             MPTSAS_TOPO_FLAG_REMOVE_HANDLE;
6706                                         topo_node->devhdl = dev_handle;
6707                                         topo_node->flags = flags;
6708                                         topo_node->object = NULL;
6709                                         if (topo_head == NULL) {
6710                                                 topo_head = topo_tail =
6711                                                     topo_node;
6712                                         } else {
6713                                                 topo_tail->next = topo_node;
6714                                                 topo_tail = topo_node;
6715                                         }
6716                                         break;
6717                                 }
6718 
6719                                 /*
6720                                  * Update DR flag immediately avoid I/O failure
6721                                  * before failover finish. Pay attention to the
6722                                  * mutex protect, we need grab m_tx_waitq_mutex
6723                                  * during set m_dr_flag because we won't add
6724                                  * the following command into waitq, instead,
6725                                  * we need return TRAN_BUSY in the tran_start
6726                                  * context.
6727                                  */
6728                                 mutex_enter(&mpt->m_tx_waitq_mutex);
6729                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6730                                 mutex_exit(&mpt->m_tx_waitq_mutex);
6731 
6732                                 topo_node = kmem_zalloc(
6733                                     sizeof (mptsas_topo_change_list_t),
6734                                     KM_SLEEP);
6735                                 topo_node->mpt = mpt;
6736                                 topo_node->un.phymask =
6737                                     ptgt->m_addr.mta_phymask;
6738                                 topo_node->event =
6739                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
6740                                 topo_node->devhdl = dev_handle;
6741                                 topo_node->flags = flags;
6742                                 topo_node->object = NULL;
6743                                 if (topo_head == NULL) {
6744                                         topo_head = topo_tail = topo_node;
6745                                 } else {
6746                                         topo_tail->next = topo_node;
6747                                         topo_tail = topo_node;
6748                                 }
6749                                 break;
6750                         }
6751                         case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
6752                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
6753                                     &sas_topo_change_list->PHY[i].LinkRate);
6754                                 state = (link_rate &
6755                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
6756                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
6757                                 pSmhba = &mpt->m_phy_info[i].smhba_info;
6758                                 pSmhba->negotiated_link_rate = state;
6759                                 switch (state) {
6760                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
6761                                         (void) sprintf(curr, "is disabled");
6762                                         mptsas_smhba_log_sysevent(mpt,
6763                                             ESC_SAS_PHY_EVENT,
6764                                             SAS_PHY_REMOVE,
6765                                             &mpt->m_phy_info[i].smhba_info);
6766                                         mpt->m_phy_info[i].smhba_info.
6767                                             negotiated_link_rate
6768                                             = 0x1;
6769                                         break;
6770                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
6771                                         (void) sprintf(curr, "is offline, "
6772                                             "failed speed negotiation");
6773                                         mptsas_smhba_log_sysevent(mpt,
6774                                             ESC_SAS_PHY_EVENT,
6775                                             SAS_PHY_OFFLINE,
6776                                             &mpt->m_phy_info[i].smhba_info);
6777                                         break;
6778                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
6779                                         (void) sprintf(curr, "SATA OOB "
6780                                             "complete");
6781                                         break;
6782                                 case SMP_RESET_IN_PROGRESS:
6783                                         (void) sprintf(curr, "SMP reset in "
6784                                             "progress");
6785                                         break;
6786                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
6787                                         (void) sprintf(curr, "is online at "
6788                                             "1.5 Gbps");
6789                                         if ((expd_handle == 0) &&
6790                                             (enc_handle == 1)) {
6791                                                 mpt->m_port_chng = 1;
6792                                         }
6793                                         mptsas_smhba_log_sysevent(mpt,
6794                                             ESC_SAS_PHY_EVENT,
6795                                             SAS_PHY_ONLINE,
6796                                             &mpt->m_phy_info[i].smhba_info);
6797                                         break;
6798                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
6799                                         (void) sprintf(curr, "is online at 3.0 "
6800                                             "Gbps");
6801                                         if ((expd_handle == 0) &&
6802                                             (enc_handle == 1)) {
6803                                                 mpt->m_port_chng = 1;
6804                                         }
6805                                         mptsas_smhba_log_sysevent(mpt,
6806                                             ESC_SAS_PHY_EVENT,
6807                                             SAS_PHY_ONLINE,
6808                                             &mpt->m_phy_info[i].smhba_info);
6809                                         break;
6810                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
6811                                         (void) sprintf(curr, "is online at "
6812                                             "6.0 Gbps");
6813                                         if ((expd_handle == 0) &&
6814                                             (enc_handle == 1)) {
6815                                                 mpt->m_port_chng = 1;
6816                                         }
6817                                         mptsas_smhba_log_sysevent(mpt,
6818                                             ESC_SAS_PHY_EVENT,
6819                                             SAS_PHY_ONLINE,
6820                                             &mpt->m_phy_info[i].smhba_info);
6821                                         break;
6822                                 default:
6823                                         (void) sprintf(curr, "state is "
6824                                             "unknown");
6825                                         break;
6826                                 }
6827 
6828                                 state = (link_rate &
6829                                     MPI2_EVENT_SAS_TOPO_LR_PREV_MASK) >>
6830                                     MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT;
6831                                 switch (state) {
6832                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
6833                                         (void) sprintf(prev, ", was disabled");
6834                                         break;
6835                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
6836                                         (void) sprintf(prev, ", was offline, "
6837                                             "failed speed negotiation");
6838                                         break;
6839                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
6840                                         (void) sprintf(prev, ", was SATA OOB "
6841                                             "complete");
6842                                         break;
6843                                 case SMP_RESET_IN_PROGRESS:
6844                                         (void) sprintf(prev, ", was SMP reset "
6845                                             "in progress");
6846                                         break;
6847                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
6848                                         (void) sprintf(prev, ", was online at "
6849                                             "1.5 Gbps");
6850                                         break;
6851                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
6852                                         (void) sprintf(prev, ", was online at "
6853                                             "3.0 Gbps");
6854                                         break;
6855                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
6856                                         (void) sprintf(prev, ", was online at "
6857                                             "6.0 Gbps");
6858                                         break;
6859                                 default:
6860                                 break;
6861                                 }
6862                                 (void) sprintf(&string[strlen(string)], "link "
6863                                     "changed, ");
6864                                 break;
6865                         case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
6866                                 continue;
6867                         case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
6868                                 (void) sprintf(&string[strlen(string)],
6869                                     "target not responding, delaying "
6870                                     "removal");
6871                                 break;
6872                         }
6873                         NDBG20(("mptsas%d phy %d DevHandle %x, %s%s%s\n",
6874                             mpt->m_instance, phy, dev_handle, string, curr,
6875                             prev));
6876                 }
6877                 if (topo_head != NULL) {
6878                         /*
6879                          * Launch DR taskq to handle topology change
6880                          */
6881                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
6882                             mptsas_handle_dr, (void *)topo_head,
6883                             DDI_NOSLEEP)) != DDI_SUCCESS) {
6884                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
6885                                     "for handle SAS DR event failed. \n");
6886                         }
6887                 }
6888                 break;
6889         }
6890         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
6891         {
6892                 Mpi2EventDataIrConfigChangeList_t       *irChangeList;
6893                 mptsas_topo_change_list_t               *topo_head = NULL;
6894                 mptsas_topo_change_list_t               *topo_tail = NULL;
6895                 mptsas_topo_change_list_t               *topo_node = NULL;
6896                 mptsas_target_t                         *ptgt;
6897                 uint8_t                                 num_entries, i, reason;
6898                 uint16_t                                volhandle, diskhandle;
6899 
6900                 irChangeList = (pMpi2EventDataIrConfigChangeList_t)
6901                     eventreply->EventData;
6902                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6903                     &irChangeList->NumElements);
6904 
6905                 NDBG20(("mptsas%d IR_CONFIGURATION_CHANGE_LIST event received",
6906                     mpt->m_instance));
6907 
6908                 for (i = 0; i < num_entries; i++) {
6909                         reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
6910                             &irChangeList->ConfigElement[i].ReasonCode);
6911                         volhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6912                             &irChangeList->ConfigElement[i].VolDevHandle);
6913                         diskhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6914                             &irChangeList->ConfigElement[i].PhysDiskDevHandle);
6915 
6916                         switch (reason) {
6917                         case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6918                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6919                         {
6920                                 NDBG20(("mptsas %d volume added\n",
6921                                     mpt->m_instance));
6922 
6923                                 topo_node = kmem_zalloc(
6924                                     sizeof (mptsas_topo_change_list_t),
6925                                     KM_SLEEP);
6926 
6927                                 topo_node->mpt = mpt;
6928                                 topo_node->event =
6929                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
6930                                 topo_node->un.physport = 0xff;
6931                                 topo_node->devhdl = volhandle;
6932                                 topo_node->flags =
6933                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
6934                                 topo_node->object = NULL;
6935                                 if (topo_head == NULL) {
6936                                         topo_head = topo_tail = topo_node;
6937                                 } else {
6938                                         topo_tail->next = topo_node;
6939                                         topo_tail = topo_node;
6940                                 }
6941                                 break;
6942                         }
6943                         case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6944                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6945                         {
6946                                 NDBG20(("mptsas %d volume deleted\n",
6947                                     mpt->m_instance));
6948                                 ptgt = refhash_linear_search(mpt->m_targets,
6949                                     mptsas_target_eval_devhdl, &volhandle);
6950                                 if (ptgt == NULL)
6951                                         break;
6952 
6953                                 /*
6954                                  * Clear any flags related to volume
6955                                  */
6956                                 (void) mptsas_delete_volume(mpt, volhandle);
6957 
6958                                 /*
6959                                  * Update DR flag immediately avoid I/O failure
6960                                  */
6961                                 mutex_enter(&mpt->m_tx_waitq_mutex);
6962                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6963                                 mutex_exit(&mpt->m_tx_waitq_mutex);
6964 
6965                                 topo_node = kmem_zalloc(
6966                                     sizeof (mptsas_topo_change_list_t),
6967                                     KM_SLEEP);
6968                                 topo_node->mpt = mpt;
6969                                 topo_node->un.phymask =
6970                                     ptgt->m_addr.mta_phymask;
6971                                 topo_node->event =
6972                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
6973                                 topo_node->devhdl = volhandle;
6974                                 topo_node->flags =
6975                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
6976                                 topo_node->object = (void *)ptgt;
6977                                 if (topo_head == NULL) {
6978                                         topo_head = topo_tail = topo_node;
6979                                 } else {
6980                                         topo_tail->next = topo_node;
6981                                         topo_tail = topo_node;
6982                                 }
6983                                 break;
6984                         }
6985                         case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
6986                         case MPI2_EVENT_IR_CHANGE_RC_HIDE:
6987                         {
6988                                 ptgt = refhash_linear_search(mpt->m_targets,
6989                                     mptsas_target_eval_devhdl, &diskhandle);
6990                                 if (ptgt == NULL)
6991                                         break;
6992 
6993                                 /*
6994                                  * Update DR flag immediately avoid I/O failure
6995                                  */
6996                                 mutex_enter(&mpt->m_tx_waitq_mutex);
6997                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6998                                 mutex_exit(&mpt->m_tx_waitq_mutex);
6999 
7000                                 topo_node = kmem_zalloc(
7001                                     sizeof (mptsas_topo_change_list_t),
7002                                     KM_SLEEP);
7003                                 topo_node->mpt = mpt;
7004                                 topo_node->un.phymask =
7005                                     ptgt->m_addr.mta_phymask;
7006                                 topo_node->event =
7007                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7008                                 topo_node->devhdl = diskhandle;
7009                                 topo_node->flags =
7010                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
7011                                 topo_node->object = (void *)ptgt;
7012                                 if (topo_head == NULL) {
7013                                         topo_head = topo_tail = topo_node;
7014                                 } else {
7015                                         topo_tail->next = topo_node;
7016                                         topo_tail = topo_node;
7017                                 }
7018                                 break;
7019                         }
7020                         case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
7021                         case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
7022                         {
7023                                 /*
7024                                  * The physical drive is released by a IR
7025                                  * volume. But we cannot get the the physport
7026                                  * or phynum from the event data, so we only
7027                                  * can get the physport/phynum after SAS
7028                                  * Device Page0 request for the devhdl.
7029                                  */
7030                                 topo_node = kmem_zalloc(
7031                                     sizeof (mptsas_topo_change_list_t),
7032                                     KM_SLEEP);
7033                                 topo_node->mpt = mpt;
7034                                 topo_node->un.phymask = 0;
7035                                 topo_node->event =
7036                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
7037                                 topo_node->devhdl = diskhandle;
7038                                 topo_node->flags =
7039                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
7040                                 topo_node->object = NULL;
7041                                 mpt->m_port_chng = 1;
7042                                 if (topo_head == NULL) {
7043                                         topo_head = topo_tail = topo_node;
7044                                 } else {
7045                                         topo_tail->next = topo_node;
7046                                         topo_tail = topo_node;
7047                                 }
7048                                 break;
7049                         }
7050                         default:
7051                                 break;
7052                         }
7053                 }
7054 
7055                 if (topo_head != NULL) {
7056                         /*
7057                          * Launch DR taskq to handle topology change
7058                          */
7059                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
7060                             mptsas_handle_dr, (void *)topo_head,
7061                             DDI_NOSLEEP)) != DDI_SUCCESS) {
7062                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
7063                                     "for handle SAS DR event failed. \n");
7064                         }
7065                 }
7066                 break;
7067         }
7068         default:
7069                 return (DDI_FAILURE);
7070         }
7071 
7072         return (DDI_SUCCESS);
7073 }
7074 
7075 /*
7076  * handle events from ioc
7077  */
7078 static void
7079 mptsas_handle_event(void *args)
7080 {
7081         m_replyh_arg_t                  *replyh_arg;
7082         pMpi2EventNotificationReply_t   eventreply;
7083         uint32_t                        event, iocloginfo, rfm;
7084         uint32_t                        status;
7085         uint8_t                         port;
7086         mptsas_t                        *mpt;
7087         uint_t                          iocstatus;
7088 
7089         replyh_arg = (m_replyh_arg_t *)args;
7090         rfm = replyh_arg->rfm;
7091         mpt = replyh_arg->mpt;
7092 
7093         mutex_enter(&mpt->m_mutex);
7094         /*
7095          * If HBA is being reset, drop incoming event.
7096          */
7097         if (mpt->m_in_reset) {
7098                 NDBG20(("dropping event received prior to reset"));
7099                 mutex_exit(&mpt->m_mutex);
7100                 return;
7101         }
7102 
7103         eventreply = (pMpi2EventNotificationReply_t)
7104             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
7105         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
7106 
7107         if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
7108             &eventreply->IOCStatus)) {
7109                 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
7110                         mptsas_log(mpt, CE_WARN,
7111                             "!mptsas_handle_event: IOCStatus=0x%x, "
7112                             "IOCLogInfo=0x%x", iocstatus,
7113                             ddi_get32(mpt->m_acc_reply_frame_hdl,
7114                             &eventreply->IOCLogInfo));
7115                 } else {
7116                         mptsas_log(mpt, CE_WARN,
7117                             "mptsas_handle_event: IOCStatus=0x%x, "
7118                             "IOCLogInfo=0x%x", iocstatus,
7119                             ddi_get32(mpt->m_acc_reply_frame_hdl,
7120                             &eventreply->IOCLogInfo));
7121                 }
7122         }
7123 
7124         /*
7125          * figure out what kind of event we got and handle accordingly
7126          */
7127         switch (event) {
7128         case MPI2_EVENT_LOG_ENTRY_ADDED:
7129                 break;
7130         case MPI2_EVENT_LOG_DATA:
7131                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7132                     &eventreply->IOCLogInfo);
7133                 NDBG20(("mptsas %d log info %x received.\n", mpt->m_instance,
7134                     iocloginfo));
7135                 break;
7136         case MPI2_EVENT_STATE_CHANGE:
7137                 NDBG20(("mptsas%d state change.", mpt->m_instance));
7138                 break;
7139         case MPI2_EVENT_HARD_RESET_RECEIVED:
7140                 NDBG20(("mptsas%d event change.", mpt->m_instance));
7141                 break;
7142         case MPI2_EVENT_SAS_DISCOVERY:
7143         {
7144                 MPI2_EVENT_DATA_SAS_DISCOVERY   *sasdiscovery;
7145                 char                            string[80];
7146                 uint8_t                         rc;
7147 
7148                 sasdiscovery =
7149                     (pMpi2EventDataSasDiscovery_t)eventreply->EventData;
7150 
7151                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7152                     &sasdiscovery->ReasonCode);
7153                 port = ddi_get8(mpt->m_acc_reply_frame_hdl,
7154                     &sasdiscovery->PhysicalPort);
7155                 status = ddi_get32(mpt->m_acc_reply_frame_hdl,
7156                     &sasdiscovery->DiscoveryStatus);
7157 
7158                 string[0] = 0;
7159                 switch (rc) {
7160                 case MPI2_EVENT_SAS_DISC_RC_STARTED:
7161                         (void) sprintf(string, "STARTING");
7162                         break;
7163                 case MPI2_EVENT_SAS_DISC_RC_COMPLETED:
7164                         (void) sprintf(string, "COMPLETED");
7165                         break;
7166                 default:
7167                         (void) sprintf(string, "UNKNOWN");
7168                         break;
7169                 }
7170 
7171                 NDBG20(("SAS DISCOVERY is %s for port %d, status %x", string,
7172                     port, status));
7173 
7174                 break;
7175         }
7176         case MPI2_EVENT_EVENT_CHANGE:
7177                 NDBG20(("mptsas%d event change.", mpt->m_instance));
7178                 break;
7179         case MPI2_EVENT_TASK_SET_FULL:
7180         {
7181                 pMpi2EventDataTaskSetFull_t     taskfull;
7182 
7183                 taskfull = (pMpi2EventDataTaskSetFull_t)eventreply->EventData;
7184 
7185                 NDBG20(("TASK_SET_FULL received for mptsas%d, depth %d\n",
7186                     mpt->m_instance,  ddi_get16(mpt->m_acc_reply_frame_hdl,
7187                     &taskfull->CurrentDepth)));
7188                 break;
7189         }
7190         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7191         {
7192                 /*
7193                  * SAS TOPOLOGY CHANGE LIST Event has already been handled
7194                  * in mptsas_handle_event_sync() of interrupt context
7195                  */
7196                 break;
7197         }
7198         case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7199         {
7200                 pMpi2EventDataSasEnclDevStatusChange_t  encstatus;
7201                 uint8_t                                 rc;
7202                 char                                    string[80];
7203 
7204                 encstatus = (pMpi2EventDataSasEnclDevStatusChange_t)
7205                     eventreply->EventData;
7206 
7207                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7208                     &encstatus->ReasonCode);
7209                 switch (rc) {
7210                 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
7211                         (void) sprintf(string, "added");
7212                         break;
7213                 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
7214                         (void) sprintf(string, ", not responding");
7215                         break;
7216                 default:
7217                 break;
7218                 }
7219                 NDBG20(("mptsas%d ENCLOSURE STATUS CHANGE for enclosure %x%s\n",
7220                     mpt->m_instance, ddi_get16(mpt->m_acc_reply_frame_hdl,
7221                     &encstatus->EnclosureHandle), string));
7222                 break;
7223         }
7224 
7225         /*
7226          * MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE is handled by
7227          * mptsas_handle_event_sync,in here just send ack message.
7228          */
7229         case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7230         {
7231                 pMpi2EventDataSasDeviceStatusChange_t   statuschange;
7232                 uint8_t                                 rc;
7233                 uint16_t                                devhdl;
7234                 uint64_t                                wwn = 0;
7235                 uint32_t                                wwn_lo, wwn_hi;
7236 
7237                 statuschange = (pMpi2EventDataSasDeviceStatusChange_t)
7238                     eventreply->EventData;
7239                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7240                     &statuschange->ReasonCode);
7241                 wwn_lo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7242                     (uint32_t *)(void *)&statuschange->SASAddress);
7243                 wwn_hi = ddi_get32(mpt->m_acc_reply_frame_hdl,
7244                     (uint32_t *)(void *)&statuschange->SASAddress + 1);
7245                 wwn = ((uint64_t)wwn_hi << 32) | wwn_lo;
7246                 devhdl =  ddi_get16(mpt->m_acc_reply_frame_hdl,
7247                     &statuschange->DevHandle);
7248 
7249                 NDBG13(("MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE wwn is %"PRIx64,
7250                     wwn));
7251 
7252                 switch (rc) {
7253                 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
7254                         NDBG20(("SMART data received, ASC/ASCQ = %02x/%02x",
7255                             ddi_get8(mpt->m_acc_reply_frame_hdl,
7256                             &statuschange->ASC),
7257                             ddi_get8(mpt->m_acc_reply_frame_hdl,
7258                             &statuschange->ASCQ)));
7259                         break;
7260 
7261                 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
7262                         NDBG20(("Device not supported"));
7263                         break;
7264 
7265                 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
7266                         NDBG20(("IOC internally generated the Target Reset "
7267                             "for devhdl:%x", devhdl));
7268                         break;
7269 
7270                 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
7271                         NDBG20(("IOC's internally generated Target Reset "
7272                             "completed for devhdl:%x", devhdl));
7273                         break;
7274 
7275                 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
7276                         NDBG20(("IOC internally generated Abort Task"));
7277                         break;
7278 
7279                 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
7280                         NDBG20(("IOC's internally generated Abort Task "
7281                             "completed"));
7282                         break;
7283 
7284                 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
7285                         NDBG20(("IOC internally generated Abort Task Set"));
7286                         break;
7287 
7288                 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
7289                         NDBG20(("IOC internally generated Clear Task Set"));
7290                         break;
7291 
7292                 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
7293                         NDBG20(("IOC internally generated Query Task"));
7294                         break;
7295 
7296                 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
7297                         NDBG20(("Device sent an Asynchronous Notification"));
7298                         break;
7299 
7300                 default:
7301                         break;
7302                 }
7303                 break;
7304         }
7305         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7306         {
7307                 /*
7308                  * IR TOPOLOGY CHANGE LIST Event has already been handled
7309                  * in mpt_handle_event_sync() of interrupt context
7310                  */
7311                 break;
7312         }
7313         case MPI2_EVENT_IR_OPERATION_STATUS:
7314         {
7315                 Mpi2EventDataIrOperationStatus_t        *irOpStatus;
7316                 char                                    reason_str[80];
7317                 uint8_t                                 rc, percent;
7318                 uint16_t                                handle;
7319 
7320                 irOpStatus = (pMpi2EventDataIrOperationStatus_t)
7321                     eventreply->EventData;
7322                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7323                     &irOpStatus->RAIDOperation);
7324                 percent = ddi_get8(mpt->m_acc_reply_frame_hdl,
7325                     &irOpStatus->PercentComplete);
7326                 handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7327                     &irOpStatus->VolDevHandle);
7328 
7329                 switch (rc) {
7330                         case MPI2_EVENT_IR_RAIDOP_RESYNC:
7331                                 (void) sprintf(reason_str, "resync");
7332                                 break;
7333                         case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
7334                                 (void) sprintf(reason_str, "online capacity "
7335                                     "expansion");
7336                                 break;
7337                         case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
7338                                 (void) sprintf(reason_str, "consistency check");
7339                                 break;
7340                         default:
7341                                 (void) sprintf(reason_str, "unknown reason %x",
7342                                     rc);
7343                 }
7344 
7345                 NDBG20(("mptsas%d raid operational status: (%s)"
7346                     "\thandle(0x%04x), percent complete(%d)\n",
7347                     mpt->m_instance, reason_str, handle, percent));
7348                 break;
7349         }
7350         case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7351         {
7352                 pMpi2EventDataSasBroadcastPrimitive_t   sas_broadcast;
7353                 uint8_t                                 phy_num;
7354                 uint8_t                                 primitive;
7355 
7356                 sas_broadcast = (pMpi2EventDataSasBroadcastPrimitive_t)
7357                     eventreply->EventData;
7358 
7359                 phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
7360                     &sas_broadcast->PhyNum);
7361                 primitive = ddi_get8(mpt->m_acc_reply_frame_hdl,
7362                     &sas_broadcast->Primitive);
7363 
7364                 switch (primitive) {
7365                 case MPI2_EVENT_PRIMITIVE_CHANGE:
7366                         mptsas_smhba_log_sysevent(mpt,
7367                             ESC_SAS_HBA_PORT_BROADCAST,
7368                             SAS_PORT_BROADCAST_CHANGE,
7369                             &mpt->m_phy_info[phy_num].smhba_info);
7370                         break;
7371                 case MPI2_EVENT_PRIMITIVE_SES:
7372                         mptsas_smhba_log_sysevent(mpt,
7373                             ESC_SAS_HBA_PORT_BROADCAST,
7374                             SAS_PORT_BROADCAST_SES,
7375                             &mpt->m_phy_info[phy_num].smhba_info);
7376                         break;
7377                 case MPI2_EVENT_PRIMITIVE_EXPANDER:
7378                         mptsas_smhba_log_sysevent(mpt,
7379                             ESC_SAS_HBA_PORT_BROADCAST,
7380                             SAS_PORT_BROADCAST_D01_4,
7381                             &mpt->m_phy_info[phy_num].smhba_info);
7382                         break;
7383                 case MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT:
7384                         mptsas_smhba_log_sysevent(mpt,
7385                             ESC_SAS_HBA_PORT_BROADCAST,
7386                             SAS_PORT_BROADCAST_D04_7,
7387                             &mpt->m_phy_info[phy_num].smhba_info);
7388                         break;
7389                 case MPI2_EVENT_PRIMITIVE_RESERVED3:
7390                         mptsas_smhba_log_sysevent(mpt,
7391                             ESC_SAS_HBA_PORT_BROADCAST,
7392                             SAS_PORT_BROADCAST_D16_7,
7393                             &mpt->m_phy_info[phy_num].smhba_info);
7394                         break;
7395                 case MPI2_EVENT_PRIMITIVE_RESERVED4:
7396                         mptsas_smhba_log_sysevent(mpt,
7397                             ESC_SAS_HBA_PORT_BROADCAST,
7398                             SAS_PORT_BROADCAST_D29_7,
7399                             &mpt->m_phy_info[phy_num].smhba_info);
7400                         break;
7401                 case MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED:
7402                         mptsas_smhba_log_sysevent(mpt,
7403                             ESC_SAS_HBA_PORT_BROADCAST,
7404                             SAS_PORT_BROADCAST_D24_0,
7405                             &mpt->m_phy_info[phy_num].smhba_info);
7406                         break;
7407                 case MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED:
7408                         mptsas_smhba_log_sysevent(mpt,
7409                             ESC_SAS_HBA_PORT_BROADCAST,
7410                             SAS_PORT_BROADCAST_D27_4,
7411                             &mpt->m_phy_info[phy_num].smhba_info);
7412                         break;
7413                 default:
7414                         NDBG20(("mptsas%d: unknown BROADCAST PRIMITIVE"
7415                             " %x received",
7416                             mpt->m_instance, primitive));
7417                         break;
7418                 }
7419                 NDBG20(("mptsas%d sas broadcast primitive: "
7420                     "\tprimitive(0x%04x), phy(%d) complete\n",
7421                     mpt->m_instance, primitive, phy_num));
7422                 break;
7423         }
7424         case MPI2_EVENT_IR_VOLUME:
7425         {
7426                 Mpi2EventDataIrVolume_t         *irVolume;
7427                 uint16_t                        devhandle;
7428                 uint32_t                        state;
7429                 int                             config, vol;
7430                 uint8_t                         found = FALSE;
7431 
7432                 irVolume = (pMpi2EventDataIrVolume_t)eventreply->EventData;
7433                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7434                     &irVolume->NewValue);
7435                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7436                     &irVolume->VolDevHandle);
7437 
7438                 NDBG20(("EVENT_IR_VOLUME event is received"));
7439 
7440                 /*
7441                  * Get latest RAID info and then find the DevHandle for this
7442                  * event in the configuration.  If the DevHandle is not found
7443                  * just exit the event.
7444                  */
7445                 (void) mptsas_get_raid_info(mpt);
7446                 for (config = 0; (config < mpt->m_num_raid_configs) &&
7447                     (!found); config++) {
7448                         for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
7449                                 if (mpt->m_raidconfig[config].m_raidvol[vol].
7450                                     m_raidhandle == devhandle) {
7451                                         found = TRUE;
7452                                         break;
7453                                 }
7454                         }
7455                 }
7456                 if (!found) {
7457                         break;
7458                 }
7459 
7460                 switch (irVolume->ReasonCode) {
7461                 case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
7462                 {
7463                         uint32_t i;
7464                         mpt->m_raidconfig[config].m_raidvol[vol].m_settings =
7465                             state;
7466 
7467                         i = state & MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING;
7468                         mptsas_log(mpt, CE_NOTE, " Volume %d settings changed"
7469                             ", auto-config of hot-swap drives is %s"
7470                             ", write caching is %s"
7471                             ", hot-spare pool mask is %02x\n",
7472                             vol, state &
7473                             MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE
7474                             ? "disabled" : "enabled",
7475                             i == MPI2_RAIDVOL0_SETTING_UNCHANGED
7476                             ? "controlled by member disks" :
7477                             i == MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING
7478                             ? "disabled" :
7479                             i == MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING
7480                             ? "enabled" :
7481                             "incorrectly set",
7482                             (state >> 16) & 0xff);
7483                                 break;
7484                 }
7485                 case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
7486                 {
7487                         mpt->m_raidconfig[config].m_raidvol[vol].m_state =
7488                             (uint8_t)state;
7489 
7490                         mptsas_log(mpt, CE_NOTE,
7491                             "Volume %d is now %s\n", vol,
7492                             state == MPI2_RAID_VOL_STATE_OPTIMAL
7493                             ? "optimal" :
7494                             state == MPI2_RAID_VOL_STATE_DEGRADED
7495                             ? "degraded" :
7496                             state == MPI2_RAID_VOL_STATE_ONLINE
7497                             ? "online" :
7498                             state == MPI2_RAID_VOL_STATE_INITIALIZING
7499                             ? "initializing" :
7500                             state == MPI2_RAID_VOL_STATE_FAILED
7501                             ? "failed" :
7502                             state == MPI2_RAID_VOL_STATE_MISSING
7503                             ? "missing" :
7504                             "state unknown");
7505                         break;
7506                 }
7507                 case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
7508                 {
7509                         mpt->m_raidconfig[config].m_raidvol[vol].
7510                             m_statusflags = state;
7511 
7512                         mptsas_log(mpt, CE_NOTE,
7513                             " Volume %d is now %s%s%s%s%s%s%s%s%s\n",
7514                             vol,
7515                             state & MPI2_RAIDVOL0_STATUS_FLAG_ENABLED
7516                             ? ", enabled" : ", disabled",
7517                             state & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED
7518                             ? ", quiesced" : "",
7519                             state & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE
7520                             ? ", inactive" : ", active",
7521                             state &
7522                             MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL
7523                             ? ", bad block table is full" : "",
7524                             state &
7525                             MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
7526                             ? ", resync in progress" : "",
7527                             state & MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT
7528                             ? ", background initialization in progress" : "",
7529                             state &
7530                             MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION
7531                             ? ", capacity expansion in progress" : "",
7532                             state &
7533                             MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK
7534                             ? ", consistency check in progress" : "",
7535                             state & MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB
7536                             ? ", data scrub in progress" : "");
7537                         break;
7538                 }
7539                 default:
7540                         break;
7541                 }
7542                 break;
7543         }
7544         case MPI2_EVENT_IR_PHYSICAL_DISK:
7545         {
7546                 Mpi2EventDataIrPhysicalDisk_t   *irPhysDisk;
7547                 uint16_t                        devhandle, enchandle, slot;
7548                 uint32_t                        status, state;
7549                 uint8_t                         physdisknum, reason;
7550 
7551                 irPhysDisk = (Mpi2EventDataIrPhysicalDisk_t *)
7552                     eventreply->EventData;
7553                 physdisknum = ddi_get8(mpt->m_acc_reply_frame_hdl,
7554                     &irPhysDisk->PhysDiskNum);
7555                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7556                     &irPhysDisk->PhysDiskDevHandle);
7557                 enchandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7558                     &irPhysDisk->EnclosureHandle);
7559                 slot = ddi_get16(mpt->m_acc_reply_frame_hdl,
7560                     &irPhysDisk->Slot);
7561                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7562                     &irPhysDisk->NewValue);
7563                 reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
7564                     &irPhysDisk->ReasonCode);
7565 
7566                 NDBG20(("EVENT_IR_PHYSICAL_DISK event is received"));
7567 
7568                 switch (reason) {
7569                 case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
7570                         mptsas_log(mpt, CE_NOTE,
7571                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7572                             "for enclosure with handle 0x%x is now in hot "
7573                             "spare pool %d",
7574                             physdisknum, devhandle, slot, enchandle,
7575                             (state >> 16) & 0xff);
7576                         break;
7577 
7578                 case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
7579                         status = state;
7580                         mptsas_log(mpt, CE_NOTE,
7581                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7582                             "for enclosure with handle 0x%x is now "
7583                             "%s%s%s%s%s\n", physdisknum, devhandle, slot,
7584                             enchandle,
7585                             status & MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME
7586                             ? ", inactive" : ", active",
7587                             status & MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
7588                             ? ", out of sync" : "",
7589                             status & MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED
7590                             ? ", quiesced" : "",
7591                             status &
7592                             MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED
7593                             ? ", write cache enabled" : "",
7594                             status & MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET
7595                             ? ", capacity expansion target" : "");
7596                         break;
7597 
7598                 case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
7599                         mptsas_log(mpt, CE_NOTE,
7600                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7601                             "for enclosure with handle 0x%x is now %s\n",
7602                             physdisknum, devhandle, slot, enchandle,
7603                             state == MPI2_RAID_PD_STATE_OPTIMAL
7604                             ? "optimal" :
7605                             state == MPI2_RAID_PD_STATE_REBUILDING
7606                             ? "rebuilding" :
7607                             state == MPI2_RAID_PD_STATE_DEGRADED
7608                             ? "degraded" :
7609                             state == MPI2_RAID_PD_STATE_HOT_SPARE
7610                             ? "a hot spare" :
7611                             state == MPI2_RAID_PD_STATE_ONLINE
7612                             ? "online" :
7613                             state == MPI2_RAID_PD_STATE_OFFLINE
7614                             ? "offline" :
7615                             state == MPI2_RAID_PD_STATE_NOT_COMPATIBLE
7616                             ? "not compatible" :
7617                             state == MPI2_RAID_PD_STATE_NOT_CONFIGURED
7618                             ? "not configured" :
7619                             "state unknown");
7620                         break;
7621                 }
7622                 break;
7623         }
7624         default:
7625                 NDBG20(("mptsas%d: unknown event %x received",
7626                     mpt->m_instance, event));
7627                 break;
7628         }
7629 
7630         /*
7631          * Return the reply frame to the free queue.
7632          */
7633         ddi_put32(mpt->m_acc_free_queue_hdl,
7634             &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index], rfm);
7635         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
7636             DDI_DMA_SYNC_FORDEV);
7637         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
7638                 mpt->m_free_index = 0;
7639         }
7640         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
7641             mpt->m_free_index);
7642         mutex_exit(&mpt->m_mutex);
7643 }
7644 
7645 /*
7646  * invoked from timeout() to restart qfull cmds with throttle == 0
7647  */
7648 static void
7649 mptsas_restart_cmd(void *arg)
7650 {
7651         mptsas_t        *mpt = arg;
7652         mptsas_target_t *ptgt = NULL;
7653 
7654         mutex_enter(&mpt->m_mutex);
7655 
7656         mpt->m_restart_cmd_timeid = 0;
7657 
7658         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
7659             ptgt = refhash_next(mpt->m_targets, ptgt)) {
7660                 if (ptgt->m_reset_delay == 0) {
7661                         if (ptgt->m_t_throttle == QFULL_THROTTLE) {
7662                                 mptsas_set_throttle(mpt, ptgt,
7663                                     MAX_THROTTLE);
7664                         }
7665                 }
7666         }
7667         mptsas_restart_hba(mpt);
7668         mutex_exit(&mpt->m_mutex);
7669 }
7670 
7671 void
7672 mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
7673 {
7674         int             slot;
7675         mptsas_slots_t  *slots = mpt->m_active;
7676         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
7677 
7678         ASSERT(cmd != NULL);
7679         ASSERT(cmd->cmd_queued == FALSE);
7680 
7681         /*
7682          * Task Management cmds are removed in their own routines.  Also,
7683          * we don't want to modify timeout based on TM cmds.
7684          */
7685         if (cmd->cmd_flags & CFLAG_TM_CMD) {
7686                 return;
7687         }
7688 
7689         slot = cmd->cmd_slot;
7690 
7691         /*
7692          * remove the cmd.
7693          */
7694         if (cmd == slots->m_slot[slot]) {
7695                 NDBG31(("mptsas_remove_cmd: removing cmd=0x%p", (void *)cmd));
7696                 slots->m_slot[slot] = NULL;
7697                 mpt->m_ncmds--;
7698 
7699                 /*
7700                  * only decrement per target ncmds if command
7701                  * has a target associated with it.
7702                  */
7703                 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
7704                         ptgt->m_t_ncmds--;
7705                         /*
7706                          * reset throttle if we just ran an untagged command
7707                          * to a tagged target
7708                          */
7709                         if ((ptgt->m_t_ncmds == 0) &&
7710                             ((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0)) {
7711                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
7712                         }
7713 
7714                         /*
7715                          * Remove this command from the active queue.
7716                          */
7717                         if (cmd->cmd_active_expiration != 0) {
7718                                 TAILQ_REMOVE(&ptgt->m_active_cmdq, cmd,
7719                                     cmd_active_link);
7720                                 cmd->cmd_active_expiration = 0;
7721                         }
7722                 }
7723         }
7724 
7725         /*
7726          * This is all we need to do for ioc commands.
7727          */
7728         if (cmd->cmd_flags & CFLAG_CMDIOC) {
7729                 mptsas_return_to_pool(mpt, cmd);
7730                 return;
7731         }
7732 
7733         ASSERT(cmd != slots->m_slot[cmd->cmd_slot]);
7734 }
7735 
7736 /*
7737  * accept all cmds on the tx_waitq if any and then
7738  * start a fresh request from the top of the device queue.
7739  *
7740  * since there are always cmds queued on the tx_waitq, and rare cmds on
7741  * the instance waitq, so this function should not be invoked in the ISR,
7742  * the mptsas_restart_waitq() is invoked in the ISR instead. otherwise, the
7743  * burden belongs to the IO dispatch CPUs is moved the interrupt CPU.
7744  */
7745 static void
7746 mptsas_restart_hba(mptsas_t *mpt)
7747 {
7748         ASSERT(mutex_owned(&mpt->m_mutex));
7749 
7750         mutex_enter(&mpt->m_tx_waitq_mutex);
7751         if (mpt->m_tx_waitq) {
7752                 mptsas_accept_tx_waitq(mpt);
7753         }
7754         mutex_exit(&mpt->m_tx_waitq_mutex);
7755         mptsas_restart_waitq(mpt);
7756 }
7757 
7758 /*
7759  * start a fresh request from the top of the device queue
7760  */
7761 static void
7762 mptsas_restart_waitq(mptsas_t *mpt)
7763 {
7764         mptsas_cmd_t    *cmd, *next_cmd;
7765         mptsas_target_t *ptgt = NULL;
7766 
7767         NDBG1(("mptsas_restart_waitq: mpt=0x%p", (void *)mpt));
7768 
7769         ASSERT(mutex_owned(&mpt->m_mutex));
7770 
7771         /*
7772          * If there is a reset delay, don't start any cmds.  Otherwise, start
7773          * as many cmds as possible.
7774          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
7775          * commands is m_max_requests - 2.
7776          */
7777         cmd = mpt->m_waitq;
7778 
7779         while (cmd != NULL) {
7780                 next_cmd = cmd->cmd_linkp;
7781                 if (cmd->cmd_flags & CFLAG_PASSTHRU) {
7782                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
7783                                 /*
7784                                  * passthru command get slot need
7785                                  * set CFLAG_PREPARED.
7786                                  */
7787                                 cmd->cmd_flags |= CFLAG_PREPARED;
7788                                 mptsas_waitq_delete(mpt, cmd);
7789                                 mptsas_start_passthru(mpt, cmd);
7790                         }
7791                         cmd = next_cmd;
7792                         continue;
7793                 }
7794                 if (cmd->cmd_flags & CFLAG_CONFIG) {
7795                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
7796                                 /*
7797                                  * Send the config page request and delete it
7798                                  * from the waitq.
7799                                  */
7800                                 cmd->cmd_flags |= CFLAG_PREPARED;
7801                                 mptsas_waitq_delete(mpt, cmd);
7802                                 mptsas_start_config_page_access(mpt, cmd);
7803                         }
7804                         cmd = next_cmd;
7805                         continue;
7806                 }
7807                 if (cmd->cmd_flags & CFLAG_FW_DIAG) {
7808                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
7809                                 /*
7810                                  * Send the FW Diag request and delete if from
7811                                  * the waitq.
7812                                  */
7813                                 cmd->cmd_flags |= CFLAG_PREPARED;
7814                                 mptsas_waitq_delete(mpt, cmd);
7815                                 mptsas_start_diag(mpt, cmd);
7816                         }
7817                         cmd = next_cmd;
7818                         continue;
7819                 }
7820 
7821                 ptgt = cmd->cmd_tgt_addr;
7822                 if (ptgt && (ptgt->m_t_throttle == DRAIN_THROTTLE) &&
7823                     (ptgt->m_t_ncmds == 0)) {
7824                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
7825                 }
7826                 if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
7827                     (ptgt && (ptgt->m_reset_delay == 0)) &&
7828                     (ptgt && (ptgt->m_t_ncmds <
7829                     ptgt->m_t_throttle))) {
7830                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
7831                                 mptsas_waitq_delete(mpt, cmd);
7832                                 (void) mptsas_start_cmd(mpt, cmd);
7833                         }
7834                 }
7835                 cmd = next_cmd;
7836         }
7837 }
7838 /*
7839  * Cmds are queued if tran_start() doesn't get the m_mutexlock(no wait).
7840  * Accept all those queued cmds before new cmd is accept so that the
7841  * cmds are sent in order.
7842  */
7843 static void
7844 mptsas_accept_tx_waitq(mptsas_t *mpt)
7845 {
7846         mptsas_cmd_t *cmd;
7847 
7848         ASSERT(mutex_owned(&mpt->m_mutex));
7849         ASSERT(mutex_owned(&mpt->m_tx_waitq_mutex));
7850 
7851         /*
7852          * A Bus Reset could occur at any time and flush the tx_waitq,
7853          * so we cannot count on the tx_waitq to contain even one cmd.
7854          * And when the m_tx_waitq_mutex is released and run
7855          * mptsas_accept_pkt(), the tx_waitq may be flushed.
7856          */
7857         cmd = mpt->m_tx_waitq;
7858         for (;;) {
7859                 if ((cmd = mpt->m_tx_waitq) == NULL) {
7860                         mpt->m_tx_draining = 0;
7861                         break;
7862                 }
7863                 if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL) {
7864                         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
7865                 }
7866                 cmd->cmd_linkp = NULL;
7867                 mutex_exit(&mpt->m_tx_waitq_mutex);
7868                 if (mptsas_accept_pkt(mpt, cmd) != TRAN_ACCEPT)
7869                         cmn_err(CE_WARN, "mpt: mptsas_accept_tx_waitq: failed "
7870                             "to accept cmd on queue\n");
7871                 mutex_enter(&mpt->m_tx_waitq_mutex);
7872         }
7873 }
7874 
7875 
7876 /*
7877  * mpt tag type lookup
7878  */
7879 static char mptsas_tag_lookup[] =
7880         {0, MSG_HEAD_QTAG, MSG_ORDERED_QTAG, 0, MSG_SIMPLE_QTAG};
7881 
7882 static int
7883 mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
7884 {
7885         struct scsi_pkt         *pkt = CMD2PKT(cmd);
7886         uint32_t                control = 0;
7887         caddr_t                 mem;
7888         pMpi2SCSIIORequest_t    io_request;
7889         ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
7890         ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
7891         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
7892         uint16_t                SMID, io_flags = 0;
7893         uint32_t                request_desc_low, request_desc_high;
7894         mptsas_cmd_t            *c;
7895 
7896         NDBG1(("mptsas_start_cmd: cmd=0x%p", (void *)cmd));
7897 
7898         /*
7899          * Set SMID and increment index.  Rollover to 1 instead of 0 if index
7900          * is at the max.  0 is an invalid SMID, so we call the first index 1.
7901          */
7902         SMID = cmd->cmd_slot;
7903 
7904         /*
7905          * It is possible for back to back device reset to
7906          * happen before the reset delay has expired.  That's
7907          * ok, just let the device reset go out on the bus.
7908          */
7909         if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
7910                 ASSERT(ptgt->m_reset_delay == 0);
7911         }
7912 
7913         /*
7914          * if a non-tagged cmd is submitted to an active tagged target
7915          * then drain before submitting this cmd; SCSI-2 allows RQSENSE
7916          * to be untagged
7917          */
7918         if (((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0) &&
7919             (ptgt->m_t_ncmds > 1) &&
7920             ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) &&
7921             (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE)) {
7922                 if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
7923                         NDBG23(("target=%d, untagged cmd, start draining\n",
7924                             ptgt->m_devhdl));
7925 
7926                         if (ptgt->m_reset_delay == 0) {
7927                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
7928                         }
7929 
7930                         mptsas_remove_cmd(mpt, cmd);
7931                         cmd->cmd_pkt_flags |= FLAG_HEAD;
7932                         mptsas_waitq_add(mpt, cmd);
7933                 }
7934                 return (DDI_FAILURE);
7935         }
7936 
7937         /*
7938          * Set correct tag bits.
7939          */
7940         if (cmd->cmd_pkt_flags & FLAG_TAGMASK) {
7941                 switch (mptsas_tag_lookup[((cmd->cmd_pkt_flags &
7942                     FLAG_TAGMASK) >> 12)]) {
7943                 case MSG_SIMPLE_QTAG:
7944                         control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
7945                         break;
7946                 case MSG_HEAD_QTAG:
7947                         control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
7948                         break;
7949                 case MSG_ORDERED_QTAG:
7950                         control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
7951                         break;
7952                 default:
7953                         mptsas_log(mpt, CE_WARN, "mpt: Invalid tag type\n");
7954                         break;
7955                 }
7956         } else {
7957                 if (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE) {
7958                                 ptgt->m_t_throttle = 1;
7959                 }
7960                 control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
7961         }
7962 
7963         if (cmd->cmd_pkt_flags & FLAG_TLR) {
7964                 control |= MPI2_SCSIIO_CONTROL_TLR_ON;
7965         }
7966 
7967         mem = mpt->m_req_frame + (mpt->m_req_frame_size * SMID);
7968         io_request = (pMpi2SCSIIORequest_t)mem;
7969 
7970         bzero(io_request, sizeof (Mpi2SCSIIORequest_t));
7971         ddi_put8(acc_hdl, &io_request->SGLOffset0, offsetof
7972             (MPI2_SCSI_IO_REQUEST, SGL) / 4);
7973         mptsas_init_std_hdr(acc_hdl, io_request, ptgt->m_devhdl, Lun(cmd), 0,
7974             MPI2_FUNCTION_SCSI_IO_REQUEST);
7975 
7976         (void) ddi_rep_put8(acc_hdl, (uint8_t *)pkt->pkt_cdbp,
7977             io_request->CDB.CDB32, cmd->cmd_cdblen, DDI_DEV_AUTOINCR);
7978 
7979         io_flags = cmd->cmd_cdblen;
7980         ddi_put16(acc_hdl, &io_request->IoFlags, io_flags);
7981         /*
7982          * setup the Scatter/Gather DMA list for this request
7983          */
7984         if (cmd->cmd_cookiec > 0) {
7985                 mptsas_sge_setup(mpt, cmd, &control, io_request, acc_hdl);
7986         } else {
7987                 ddi_put32(acc_hdl, &io_request->SGL.MpiSimple.FlagsLength,
7988                     ((uint32_t)MPI2_SGE_FLAGS_LAST_ELEMENT |
7989                     MPI2_SGE_FLAGS_END_OF_BUFFER |
7990                     MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
7991                     MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
7992         }
7993 
7994         /*
7995          * save ARQ information
7996          */
7997         ddi_put8(acc_hdl, &io_request->SenseBufferLength, cmd->cmd_rqslen);
7998         if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
7999             (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
8000                 ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
8001                     cmd->cmd_ext_arqcookie.dmac_address);
8002         } else {
8003                 ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
8004                     cmd->cmd_arqcookie.dmac_address);
8005         }
8006 
8007         ddi_put32(acc_hdl, &io_request->Control, control);
8008 
8009         NDBG31(("starting message=0x%p, with cmd=0x%p",
8010             (void *)(uintptr_t)mpt->m_req_frame_dma_addr, (void *)cmd));
8011 
8012         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
8013 
8014         /*
8015          * Build request descriptor and write it to the request desc post reg.
8016          */
8017         request_desc_low = (SMID << 16) + MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
8018         request_desc_high = ptgt->m_devhdl << 16;
8019         MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
8020 
8021         /*
8022          * Start timeout.
8023          */
8024         cmd->cmd_active_expiration =
8025             gethrtime() + (hrtime_t)pkt->pkt_time * NANOSEC;
8026 #ifdef MPTSAS_TEST
8027         /*
8028          * Force timeouts to happen immediately.
8029          */
8030         if (mptsas_test_timeouts)
8031                 cmd->cmd_active_expiration = gethrtime();
8032 #endif
8033         c = TAILQ_FIRST(&ptgt->m_active_cmdq);
8034         if (c == NULL ||
8035             c->cmd_active_expiration < cmd->cmd_active_expiration) {
8036                 /*
8037                  * Common case is that this is the last pending expiration
8038                  * (or queue is empty). Insert at head of the queue.
8039                  */
8040                 TAILQ_INSERT_HEAD(&ptgt->m_active_cmdq, cmd, cmd_active_link);
8041         } else {
8042                 /*
8043                  * Queue is not empty and first element expires later than
8044                  * this command. Search for element expiring sooner.
8045                  */
8046                 while ((c = TAILQ_NEXT(c, cmd_active_link)) != NULL) {
8047                         if (c->cmd_active_expiration <
8048                             cmd->cmd_active_expiration) {
8049                                 TAILQ_INSERT_BEFORE(c, cmd, cmd_active_link);
8050                                 break;
8051                         }
8052                 }
8053                 if (c == NULL) {
8054                         /*
8055                          * No element found expiring sooner, append to
8056                          * non-empty queue.
8057                          */
8058                         TAILQ_INSERT_TAIL(&ptgt->m_active_cmdq, cmd,
8059                             cmd_active_link);
8060                 }
8061         }
8062 
8063         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
8064             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
8065                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8066                 return (DDI_FAILURE);
8067         }
8068         return (DDI_SUCCESS);
8069 }
8070 
8071 /*
8072  * Select a helper thread to handle current doneq
8073  */
8074 static void
8075 mptsas_deliver_doneq_thread(mptsas_t *mpt)
8076 {
8077         uint64_t                        t, i;
8078         uint32_t                        min = 0xffffffff;
8079         mptsas_doneq_thread_list_t      *item;
8080 
8081         for (i = 0; i < mpt->m_doneq_thread_n; i++) {
8082                 item = &mpt->m_doneq_thread_id[i];
8083                 /*
8084                  * If the completed command on help thread[i] less than
8085                  * doneq_thread_threshold, then pick the thread[i]. Otherwise
8086                  * pick a thread which has least completed command.
8087                  */
8088 
8089                 mutex_enter(&item->mutex);
8090                 if (item->len < mpt->m_doneq_thread_threshold) {
8091                         t = i;
8092                         mutex_exit(&item->mutex);
8093                         break;
8094                 }
8095                 if (item->len < min) {
8096                         min = item->len;
8097                         t = i;
8098                 }
8099                 mutex_exit(&item->mutex);
8100         }
8101         mutex_enter(&mpt->m_doneq_thread_id[t].mutex);
8102         mptsas_doneq_mv(mpt, t);
8103         cv_signal(&mpt->m_doneq_thread_id[t].cv);
8104         mutex_exit(&mpt->m_doneq_thread_id[t].mutex);
8105 }
8106 
8107 /*
8108  * move the current global doneq to the doneq of thead[t]
8109  */
8110 static void
8111 mptsas_doneq_mv(mptsas_t *mpt, uint64_t t)
8112 {
8113         mptsas_cmd_t                    *cmd;
8114         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
8115 
8116         ASSERT(mutex_owned(&item->mutex));
8117         while ((cmd = mpt->m_doneq) != NULL) {
8118                 if ((mpt->m_doneq = cmd->cmd_linkp) == NULL) {
8119                         mpt->m_donetail = &mpt->m_doneq;
8120                 }
8121                 cmd->cmd_linkp = NULL;
8122                 *item->donetail = cmd;
8123                 item->donetail = &cmd->cmd_linkp;
8124                 mpt->m_doneq_len--;
8125                 item->len++;
8126         }
8127 }
8128 
8129 void
8130 mptsas_fma_check(mptsas_t *mpt, mptsas_cmd_t *cmd)
8131 {
8132         struct scsi_pkt *pkt = CMD2PKT(cmd);
8133 
8134         /* Check all acc and dma handles */
8135         if ((mptsas_check_acc_handle(mpt->m_datap) !=
8136             DDI_SUCCESS) ||
8137             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
8138             DDI_SUCCESS) ||
8139             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
8140             DDI_SUCCESS) ||
8141             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
8142             DDI_SUCCESS) ||
8143             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
8144             DDI_SUCCESS) ||
8145             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
8146             DDI_SUCCESS) ||
8147             (mptsas_check_acc_handle(mpt->m_config_handle) !=
8148             DDI_SUCCESS)) {
8149                 ddi_fm_service_impact(mpt->m_dip,
8150                     DDI_SERVICE_UNAFFECTED);
8151                 ddi_fm_acc_err_clear(mpt->m_config_handle,
8152                     DDI_FME_VER0);
8153                 pkt->pkt_reason = CMD_TRAN_ERR;
8154                 pkt->pkt_statistics = 0;
8155         }
8156         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
8157             DDI_SUCCESS) ||
8158             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
8159             DDI_SUCCESS) ||
8160             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
8161             DDI_SUCCESS) ||
8162             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
8163             DDI_SUCCESS) ||
8164             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
8165             DDI_SUCCESS)) {
8166                 ddi_fm_service_impact(mpt->m_dip,
8167                     DDI_SERVICE_UNAFFECTED);
8168                 pkt->pkt_reason = CMD_TRAN_ERR;
8169                 pkt->pkt_statistics = 0;
8170         }
8171         if (cmd->cmd_dmahandle &&
8172             (mptsas_check_dma_handle(cmd->cmd_dmahandle) != DDI_SUCCESS)) {
8173                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8174                 pkt->pkt_reason = CMD_TRAN_ERR;
8175                 pkt->pkt_statistics = 0;
8176         }
8177         if ((cmd->cmd_extra_frames &&
8178             ((mptsas_check_dma_handle(cmd->cmd_extra_frames->m_dma_hdl) !=
8179             DDI_SUCCESS) ||
8180             (mptsas_check_acc_handle(cmd->cmd_extra_frames->m_acc_hdl) !=
8181             DDI_SUCCESS)))) {
8182                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8183                 pkt->pkt_reason = CMD_TRAN_ERR;
8184                 pkt->pkt_statistics = 0;
8185         }
8186         if (cmd->cmd_arqhandle &&
8187             (mptsas_check_dma_handle(cmd->cmd_arqhandle) != DDI_SUCCESS)) {
8188                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8189                 pkt->pkt_reason = CMD_TRAN_ERR;
8190                 pkt->pkt_statistics = 0;
8191         }
8192         if (cmd->cmd_ext_arqhandle &&
8193             (mptsas_check_dma_handle(cmd->cmd_ext_arqhandle) != DDI_SUCCESS)) {
8194                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8195                 pkt->pkt_reason = CMD_TRAN_ERR;
8196                 pkt->pkt_statistics = 0;
8197         }
8198 }
8199 
8200 /*
8201  * These routines manipulate the queue of commands that
8202  * are waiting for their completion routines to be called.
8203  * The queue is usually in FIFO order but on an MP system
8204  * it's possible for the completion routines to get out
8205  * of order. If that's a problem you need to add a global
8206  * mutex around the code that calls the completion routine
8207  * in the interrupt handler.
8208  */
8209 static void
8210 mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8211 {
8212         struct scsi_pkt *pkt = CMD2PKT(cmd);
8213 
8214         NDBG31(("mptsas_doneq_add: cmd=0x%p", (void *)cmd));
8215 
8216         ASSERT((cmd->cmd_flags & CFLAG_COMPLETED) == 0);
8217         cmd->cmd_linkp = NULL;
8218         cmd->cmd_flags |= CFLAG_FINISHED;
8219         cmd->cmd_flags &= ~CFLAG_IN_TRANSPORT;
8220 
8221         mptsas_fma_check(mpt, cmd);
8222 
8223         /*
8224          * only add scsi pkts that have completion routines to
8225          * the doneq.  no intr cmds do not have callbacks.
8226          */
8227         if (pkt && (pkt->pkt_comp)) {
8228                 *mpt->m_donetail = cmd;
8229                 mpt->m_donetail = &cmd->cmd_linkp;
8230                 mpt->m_doneq_len++;
8231         }
8232 }
8233 
8234 static mptsas_cmd_t *
8235 mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t)
8236 {
8237         mptsas_cmd_t                    *cmd;
8238         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
8239 
8240         /* pop one off the done queue */
8241         if ((cmd = item->doneq) != NULL) {
8242                 /* if the queue is now empty fix the tail pointer */
8243                 NDBG31(("mptsas_doneq_thread_rm: cmd=0x%p", (void *)cmd));
8244                 if ((item->doneq = cmd->cmd_linkp) == NULL) {
8245                         item->donetail = &item->doneq;
8246                 }
8247                 cmd->cmd_linkp = NULL;
8248                 item->len--;
8249         }
8250         return (cmd);
8251 }
8252 
8253 static void
8254 mptsas_doneq_empty(mptsas_t *mpt)
8255 {
8256         if (mpt->m_doneq && !mpt->m_in_callback) {
8257                 mptsas_cmd_t    *cmd, *next;
8258                 struct scsi_pkt *pkt;
8259 
8260                 mpt->m_in_callback = 1;
8261                 cmd = mpt->m_doneq;
8262                 mpt->m_doneq = NULL;
8263                 mpt->m_donetail = &mpt->m_doneq;
8264                 mpt->m_doneq_len = 0;
8265 
8266                 mutex_exit(&mpt->m_mutex);
8267                 /*
8268                  * run the completion routines of all the
8269                  * completed commands
8270                  */
8271                 while (cmd != NULL) {
8272                         next = cmd->cmd_linkp;
8273                         cmd->cmd_linkp = NULL;
8274                         /* run this command's completion routine */
8275                         cmd->cmd_flags |= CFLAG_COMPLETED;
8276                         pkt = CMD2PKT(cmd);
8277                         mptsas_pkt_comp(pkt, cmd);
8278                         cmd = next;
8279                 }
8280                 mutex_enter(&mpt->m_mutex);
8281                 mpt->m_in_callback = 0;
8282         }
8283 }
8284 
8285 /*
8286  * These routines manipulate the target's queue of pending requests
8287  */
8288 void
8289 mptsas_waitq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8290 {
8291         NDBG7(("mptsas_waitq_add: cmd=0x%p", (void *)cmd));
8292         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8293         cmd->cmd_queued = TRUE;
8294         if (ptgt)
8295                 ptgt->m_t_nwait++;
8296         if (cmd->cmd_pkt_flags & FLAG_HEAD) {
8297                 if ((cmd->cmd_linkp = mpt->m_waitq) == NULL) {
8298                         mpt->m_waitqtail = &cmd->cmd_linkp;
8299                 }
8300                 mpt->m_waitq = cmd;
8301         } else {
8302                 cmd->cmd_linkp = NULL;
8303                 *(mpt->m_waitqtail) = cmd;
8304                 mpt->m_waitqtail = &cmd->cmd_linkp;
8305         }
8306 }
8307 
8308 static mptsas_cmd_t *
8309 mptsas_waitq_rm(mptsas_t *mpt)
8310 {
8311         mptsas_cmd_t    *cmd;
8312         mptsas_target_t *ptgt;
8313         NDBG7(("mptsas_waitq_rm"));
8314 
8315         MPTSAS_WAITQ_RM(mpt, cmd);
8316 
8317         NDBG7(("mptsas_waitq_rm: cmd=0x%p", (void *)cmd));
8318         if (cmd) {
8319                 ptgt = cmd->cmd_tgt_addr;
8320                 if (ptgt) {
8321                         ptgt->m_t_nwait--;
8322                         ASSERT(ptgt->m_t_nwait >= 0);
8323                 }
8324         }
8325         return (cmd);
8326 }
8327 
8328 /*
8329  * remove specified cmd from the middle of the wait queue.
8330  */
8331 static void
8332 mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8333 {
8334         mptsas_cmd_t    *prevp = mpt->m_waitq;
8335         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8336 
8337         NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8338             (void *)mpt, (void *)cmd));
8339         if (ptgt) {
8340                 ptgt->m_t_nwait--;
8341                 ASSERT(ptgt->m_t_nwait >= 0);
8342         }
8343 
8344         if (prevp == cmd) {
8345                 if ((mpt->m_waitq = cmd->cmd_linkp) == NULL)
8346                         mpt->m_waitqtail = &mpt->m_waitq;
8347 
8348                 cmd->cmd_linkp = NULL;
8349                 cmd->cmd_queued = FALSE;
8350                 NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8351                     (void *)mpt, (void *)cmd));
8352                 return;
8353         }
8354 
8355         while (prevp != NULL) {
8356                 if (prevp->cmd_linkp == cmd) {
8357                         if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8358                                 mpt->m_waitqtail = &prevp->cmd_linkp;
8359 
8360                         cmd->cmd_linkp = NULL;
8361                         cmd->cmd_queued = FALSE;
8362                         NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8363                             (void *)mpt, (void *)cmd));
8364                         return;
8365                 }
8366                 prevp = prevp->cmd_linkp;
8367         }
8368         cmn_err(CE_PANIC, "mpt: mptsas_waitq_delete: queue botch");
8369 }
8370 
8371 static mptsas_cmd_t *
8372 mptsas_tx_waitq_rm(mptsas_t *mpt)
8373 {
8374         mptsas_cmd_t *cmd;
8375         NDBG7(("mptsas_tx_waitq_rm"));
8376 
8377         MPTSAS_TX_WAITQ_RM(mpt, cmd);
8378 
8379         NDBG7(("mptsas_tx_waitq_rm: cmd=0x%p", (void *)cmd));
8380 
8381         return (cmd);
8382 }
8383 
8384 /*
8385  * remove specified cmd from the middle of the tx_waitq.
8386  */
8387 static void
8388 mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8389 {
8390         mptsas_cmd_t *prevp = mpt->m_tx_waitq;
8391 
8392         NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8393             (void *)mpt, (void *)cmd));
8394 
8395         if (prevp == cmd) {
8396                 if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL)
8397                         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
8398 
8399                 cmd->cmd_linkp = NULL;
8400                 cmd->cmd_queued = FALSE;
8401                 NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8402                     (void *)mpt, (void *)cmd));
8403                 return;
8404         }
8405 
8406         while (prevp != NULL) {
8407                 if (prevp->cmd_linkp == cmd) {
8408                         if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8409                                 mpt->m_tx_waitqtail = &prevp->cmd_linkp;
8410 
8411                         cmd->cmd_linkp = NULL;
8412                         cmd->cmd_queued = FALSE;
8413                         NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8414                             (void *)mpt, (void *)cmd));
8415                         return;
8416                 }
8417                 prevp = prevp->cmd_linkp;
8418         }
8419         cmn_err(CE_PANIC, "mpt: mptsas_tx_waitq_delete: queue botch");
8420 }
8421 
8422 /*
8423  * device and bus reset handling
8424  *
8425  * Notes:
8426  *      - RESET_ALL:    reset the controller
8427  *      - RESET_TARGET: reset the target specified in scsi_address
8428  */
8429 static int
8430 mptsas_scsi_reset(struct scsi_address *ap, int level)
8431 {
8432         mptsas_t                *mpt = ADDR2MPT(ap);
8433         int                     rval;
8434         mptsas_tgt_private_t    *tgt_private;
8435         mptsas_target_t         *ptgt = NULL;
8436 
8437         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->tran_tgt_private;
8438         ptgt = tgt_private->t_private;
8439         if (ptgt == NULL) {
8440                 return (FALSE);
8441         }
8442         NDBG22(("mptsas_scsi_reset: target=%d level=%d", ptgt->m_devhdl,
8443             level));
8444 
8445         mutex_enter(&mpt->m_mutex);
8446         /*
8447          * if we are not in panic set up a reset delay for this target
8448          */
8449         if (!ddi_in_panic()) {
8450                 mptsas_setup_bus_reset_delay(mpt);
8451         } else {
8452                 drv_usecwait(mpt->m_scsi_reset_delay * 1000);
8453         }
8454         rval = mptsas_do_scsi_reset(mpt, ptgt->m_devhdl);
8455         mutex_exit(&mpt->m_mutex);
8456 
8457         /*
8458          * The transport layer expect to only see TRUE and
8459          * FALSE. Therefore, we will adjust the return value
8460          * if mptsas_do_scsi_reset returns FAILED.
8461          */
8462         if (rval == FAILED)
8463                 rval = FALSE;
8464         return (rval);
8465 }
8466 
8467 static int
8468 mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl)
8469 {
8470         int             rval = FALSE;
8471         uint8_t         config, disk;
8472 
8473         ASSERT(mutex_owned(&mpt->m_mutex));
8474 
8475         if (mptsas_debug_resets) {
8476                 mptsas_log(mpt, CE_WARN, "mptsas_do_scsi_reset: target=%d",
8477                     devhdl);
8478         }
8479 
8480         /*
8481          * Issue a Target Reset message to the target specified but not to a
8482          * disk making up a raid volume.  Just look through the RAID config
8483          * Phys Disk list of DevHandles.  If the target's DevHandle is in this
8484          * list, then don't reset this target.
8485          */
8486         for (config = 0; config < mpt->m_num_raid_configs; config++) {
8487                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
8488                         if (devhdl == mpt->m_raidconfig[config].
8489                             m_physdisk_devhdl[disk]) {
8490                                 return (TRUE);
8491                         }
8492                 }
8493         }
8494 
8495         rval = mptsas_ioc_task_management(mpt,
8496             MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, devhdl, 0, NULL, 0, 0);
8497 
8498         mptsas_doneq_empty(mpt);
8499         return (rval);
8500 }
8501 
8502 static int
8503 mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
8504         void (*callback)(caddr_t), caddr_t arg)
8505 {
8506         mptsas_t        *mpt = ADDR2MPT(ap);
8507 
8508         NDBG22(("mptsas_scsi_reset_notify: tgt=%d", ap->a_target));
8509 
8510         return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
8511             &mpt->m_mutex, &mpt->m_reset_notify_listf));
8512 }
8513 
8514 static int
8515 mptsas_get_name(struct scsi_device *sd, char *name, int len)
8516 {
8517         dev_info_t      *lun_dip = NULL;
8518 
8519         ASSERT(sd != NULL);
8520         ASSERT(name != NULL);
8521         lun_dip = sd->sd_dev;
8522         ASSERT(lun_dip != NULL);
8523 
8524         if (mptsas_name_child(lun_dip, name, len) == DDI_SUCCESS) {
8525                 return (1);
8526         } else {
8527                 return (0);
8528         }
8529 }
8530 
8531 static int
8532 mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len)
8533 {
8534         return (mptsas_get_name(sd, name, len));
8535 }
8536 
8537 void
8538 mptsas_set_throttle(mptsas_t *mpt, mptsas_target_t *ptgt, int what)
8539 {
8540 
8541         NDBG25(("mptsas_set_throttle: throttle=%x", what));
8542 
8543         /*
8544          * if the bus is draining/quiesced, no changes to the throttles
8545          * are allowed. Not allowing change of throttles during draining
8546          * limits error recovery but will reduce draining time
8547          *
8548          * all throttles should have been set to HOLD_THROTTLE
8549          */
8550         if (mpt->m_softstate & (MPTSAS_SS_QUIESCED | MPTSAS_SS_DRAINING)) {
8551                 return;
8552         }
8553 
8554         if (what == HOLD_THROTTLE) {
8555                 ptgt->m_t_throttle = HOLD_THROTTLE;
8556         } else if (ptgt->m_reset_delay == 0) {
8557                 ptgt->m_t_throttle = what;
8558         }
8559 }
8560 
8561 /*
8562  * Clean up from a device reset.
8563  * For the case of target reset, this function clears the waitq of all
8564  * commands for a particular target.   For the case of abort task set, this
8565  * function clears the waitq of all commonds for a particular target/lun.
8566  */
8567 static void
8568 mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun, uint8_t tasktype)
8569 {
8570         mptsas_slots_t  *slots = mpt->m_active;
8571         mptsas_cmd_t    *cmd, *next_cmd;
8572         int             slot;
8573         uchar_t         reason;
8574         uint_t          stat;
8575         hrtime_t        timestamp;
8576 
8577         NDBG25(("mptsas_flush_target: target=%d lun=%d", target, lun));
8578 
8579         timestamp = gethrtime();
8580 
8581         /*
8582          * Make sure the I/O Controller has flushed all cmds
8583          * that are associated with this target for a target reset
8584          * and target/lun for abort task set.
8585          * Account for TM requests, which use the last SMID.
8586          */
8587         for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
8588                 if ((cmd = slots->m_slot[slot]) == NULL)
8589                         continue;
8590                 reason = CMD_RESET;
8591                 stat = STAT_DEV_RESET;
8592                 switch (tasktype) {
8593                 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
8594                         if (Tgt(cmd) == target) {
8595                                 if (cmd->cmd_active_expiration <= timestamp) {
8596                                         /*
8597                                          * When timeout requested, propagate
8598                                          * proper reason and statistics to
8599                                          * target drivers.
8600                                          */
8601                                         reason = CMD_TIMEOUT;
8602                                         stat |= STAT_TIMEOUT;
8603                                 }
8604                                 NDBG25(("mptsas_flush_target discovered non-"
8605                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
8606                                     tasktype));
8607                                 mptsas_dump_cmd(mpt, cmd);
8608                                 mptsas_remove_cmd(mpt, cmd);
8609                                 mptsas_set_pkt_reason(mpt, cmd, reason, stat);
8610                                 mptsas_doneq_add(mpt, cmd);
8611                         }
8612                         break;
8613                 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
8614                         reason = CMD_ABORTED;
8615                         stat = STAT_ABORTED;
8616                         /*FALLTHROUGH*/
8617                 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
8618                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
8619 
8620                                 NDBG25(("mptsas_flush_target discovered non-"
8621                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
8622                                     tasktype));
8623                                 mptsas_dump_cmd(mpt, cmd);
8624                                 mptsas_remove_cmd(mpt, cmd);
8625                                 mptsas_set_pkt_reason(mpt, cmd, reason,
8626                                     stat);
8627                                 mptsas_doneq_add(mpt, cmd);
8628                         }
8629                         break;
8630                 default:
8631                         break;
8632                 }
8633         }
8634 
8635         /*
8636          * Flush the waitq and tx_waitq of this target's cmds
8637          */
8638         cmd = mpt->m_waitq;
8639 
8640         reason = CMD_RESET;
8641         stat = STAT_DEV_RESET;
8642 
8643         switch (tasktype) {
8644         case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
8645                 while (cmd != NULL) {
8646                         next_cmd = cmd->cmd_linkp;
8647                         if (Tgt(cmd) == target) {
8648                                 mptsas_waitq_delete(mpt, cmd);
8649                                 mptsas_set_pkt_reason(mpt, cmd,
8650                                     reason, stat);
8651                                 mptsas_doneq_add(mpt, cmd);
8652                         }
8653                         cmd = next_cmd;
8654                 }
8655                 mutex_enter(&mpt->m_tx_waitq_mutex);
8656                 cmd = mpt->m_tx_waitq;
8657                 while (cmd != NULL) {
8658                         next_cmd = cmd->cmd_linkp;
8659                         if (Tgt(cmd) == target) {
8660                                 mptsas_tx_waitq_delete(mpt, cmd);
8661                                 mutex_exit(&mpt->m_tx_waitq_mutex);
8662                                 mptsas_set_pkt_reason(mpt, cmd,
8663                                     reason, stat);
8664                                 mptsas_doneq_add(mpt, cmd);
8665                                 mutex_enter(&mpt->m_tx_waitq_mutex);
8666                         }
8667                         cmd = next_cmd;
8668                 }
8669                 mutex_exit(&mpt->m_tx_waitq_mutex);
8670                 break;
8671         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
8672                 reason = CMD_ABORTED;
8673                 stat =  STAT_ABORTED;
8674                 /*FALLTHROUGH*/
8675         case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
8676                 while (cmd != NULL) {
8677                         next_cmd = cmd->cmd_linkp;
8678                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
8679                                 mptsas_waitq_delete(mpt, cmd);
8680                                 mptsas_set_pkt_reason(mpt, cmd,
8681                                     reason, stat);
8682                                 mptsas_doneq_add(mpt, cmd);
8683                         }
8684                         cmd = next_cmd;
8685                 }
8686                 mutex_enter(&mpt->m_tx_waitq_mutex);
8687                 cmd = mpt->m_tx_waitq;
8688                 while (cmd != NULL) {
8689                         next_cmd = cmd->cmd_linkp;
8690                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
8691                                 mptsas_tx_waitq_delete(mpt, cmd);
8692                                 mutex_exit(&mpt->m_tx_waitq_mutex);
8693                                 mptsas_set_pkt_reason(mpt, cmd,
8694                                     reason, stat);
8695                                 mptsas_doneq_add(mpt, cmd);
8696                                 mutex_enter(&mpt->m_tx_waitq_mutex);
8697                         }
8698                         cmd = next_cmd;
8699                 }
8700                 mutex_exit(&mpt->m_tx_waitq_mutex);
8701                 break;
8702         default:
8703                 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
8704                     tasktype);
8705                 break;
8706         }
8707 }
8708 
8709 /*
8710  * Clean up hba state, abort all outstanding command and commands in waitq
8711  * reset timeout of all targets.
8712  */
8713 static void
8714 mptsas_flush_hba(mptsas_t *mpt)
8715 {
8716         mptsas_slots_t  *slots = mpt->m_active;
8717         mptsas_cmd_t    *cmd;
8718         int             slot;
8719 
8720         NDBG25(("mptsas_flush_hba"));
8721 
8722         /*
8723          * The I/O Controller should have already sent back
8724          * all commands via the scsi I/O reply frame.  Make
8725          * sure all commands have been flushed.
8726          * Account for TM request, which use the last SMID.
8727          */
8728         for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
8729                 if ((cmd = slots->m_slot[slot]) == NULL)
8730                         continue;
8731 
8732                 if (cmd->cmd_flags & CFLAG_CMDIOC) {
8733                         /*
8734                          * Need to make sure to tell everyone that might be
8735                          * waiting on this command that it's going to fail.  If
8736                          * we get here, this command will never timeout because
8737                          * the active command table is going to be re-allocated,
8738                          * so there will be nothing to check against a time out.
8739                          * Instead, mark the command as failed due to reset.
8740                          */
8741                         mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
8742                             STAT_BUS_RESET);
8743                         if ((cmd->cmd_flags &
8744                             (CFLAG_PASSTHRU | CFLAG_CONFIG | CFLAG_FW_DIAG))) {
8745                                 cmd->cmd_flags |= CFLAG_FINISHED;
8746                                 cv_broadcast(&mpt->m_passthru_cv);
8747                                 cv_broadcast(&mpt->m_config_cv);
8748                                 cv_broadcast(&mpt->m_fw_diag_cv);
8749                         }
8750                         continue;
8751                 }
8752 
8753                 NDBG25(("mptsas_flush_hba discovered non-NULL cmd in slot %d",
8754                     slot));
8755                 mptsas_dump_cmd(mpt, cmd);
8756 
8757                 mptsas_remove_cmd(mpt, cmd);
8758                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
8759                 mptsas_doneq_add(mpt, cmd);
8760         }
8761 
8762         /*
8763          * Flush the waitq.
8764          */
8765         while ((cmd = mptsas_waitq_rm(mpt)) != NULL) {
8766                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
8767                 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
8768                     (cmd->cmd_flags & CFLAG_CONFIG) ||
8769                     (cmd->cmd_flags & CFLAG_FW_DIAG)) {
8770                         cmd->cmd_flags |= CFLAG_FINISHED;
8771                         cv_broadcast(&mpt->m_passthru_cv);
8772                         cv_broadcast(&mpt->m_config_cv);
8773                         cv_broadcast(&mpt->m_fw_diag_cv);
8774                 } else {
8775                         mptsas_doneq_add(mpt, cmd);
8776                 }
8777         }
8778 
8779         /*
8780          * Flush the tx_waitq
8781          */
8782         mutex_enter(&mpt->m_tx_waitq_mutex);
8783         while ((cmd = mptsas_tx_waitq_rm(mpt)) != NULL) {
8784                 mutex_exit(&mpt->m_tx_waitq_mutex);
8785                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
8786                 mptsas_doneq_add(mpt, cmd);
8787                 mutex_enter(&mpt->m_tx_waitq_mutex);
8788         }
8789         mutex_exit(&mpt->m_tx_waitq_mutex);
8790 
8791         /*
8792          * Drain the taskqs prior to reallocating resources.
8793          */
8794         mutex_exit(&mpt->m_mutex);
8795         ddi_taskq_wait(mpt->m_event_taskq);
8796         ddi_taskq_wait(mpt->m_dr_taskq);
8797         mutex_enter(&mpt->m_mutex);
8798 }
8799 
8800 /*
8801  * set pkt_reason and OR in pkt_statistics flag
8802  */
8803 static void
8804 mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd, uchar_t reason,
8805     uint_t stat)
8806 {
8807 #ifndef __lock_lint
8808         _NOTE(ARGUNUSED(mpt))
8809 #endif
8810 
8811         NDBG25(("mptsas_set_pkt_reason: cmd=0x%p reason=%x stat=%x",
8812             (void *)cmd, reason, stat));
8813 
8814         if (cmd) {
8815                 if (cmd->cmd_pkt->pkt_reason == CMD_CMPLT) {
8816                         cmd->cmd_pkt->pkt_reason = reason;
8817                 }
8818                 cmd->cmd_pkt->pkt_statistics |= stat;
8819         }
8820 }
8821 
8822 static void
8823 mptsas_start_watch_reset_delay()
8824 {
8825         NDBG22(("mptsas_start_watch_reset_delay"));
8826 
8827         mutex_enter(&mptsas_global_mutex);
8828         if (mptsas_reset_watch == NULL && mptsas_timeouts_enabled) {
8829                 mptsas_reset_watch = timeout(mptsas_watch_reset_delay, NULL,
8830                     drv_usectohz((clock_t)
8831                     MPTSAS_WATCH_RESET_DELAY_TICK * 1000));
8832                 ASSERT(mptsas_reset_watch != NULL);
8833         }
8834         mutex_exit(&mptsas_global_mutex);
8835 }
8836 
8837 static void
8838 mptsas_setup_bus_reset_delay(mptsas_t *mpt)
8839 {
8840         mptsas_target_t *ptgt = NULL;
8841 
8842         ASSERT(MUTEX_HELD(&mpt->m_mutex));
8843 
8844         NDBG22(("mptsas_setup_bus_reset_delay"));
8845         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
8846             ptgt = refhash_next(mpt->m_targets, ptgt)) {
8847                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
8848                 ptgt->m_reset_delay = mpt->m_scsi_reset_delay;
8849         }
8850 
8851         mptsas_start_watch_reset_delay();
8852 }
8853 
8854 /*
8855  * mptsas_watch_reset_delay(_subr) is invoked by timeout() and checks every
8856  * mpt instance for active reset delays
8857  */
8858 static void
8859 mptsas_watch_reset_delay(void *arg)
8860 {
8861 #ifndef __lock_lint
8862         _NOTE(ARGUNUSED(arg))
8863 #endif
8864 
8865         mptsas_t        *mpt;
8866         int             not_done = 0;
8867 
8868         NDBG22(("mptsas_watch_reset_delay"));
8869 
8870         mutex_enter(&mptsas_global_mutex);
8871         mptsas_reset_watch = 0;
8872         mutex_exit(&mptsas_global_mutex);
8873         rw_enter(&mptsas_global_rwlock, RW_READER);
8874         for (mpt = mptsas_head; mpt != NULL; mpt = mpt->m_next) {
8875                 if (mpt->m_tran == 0) {
8876                         continue;
8877                 }
8878                 mutex_enter(&mpt->m_mutex);
8879                 not_done += mptsas_watch_reset_delay_subr(mpt);
8880                 mutex_exit(&mpt->m_mutex);
8881         }
8882         rw_exit(&mptsas_global_rwlock);
8883 
8884         if (not_done) {
8885                 mptsas_start_watch_reset_delay();
8886         }
8887 }
8888 
8889 static int
8890 mptsas_watch_reset_delay_subr(mptsas_t *mpt)
8891 {
8892         int             done = 0;
8893         int             restart = 0;
8894         mptsas_target_t *ptgt = NULL;
8895 
8896         NDBG22(("mptsas_watch_reset_delay_subr: mpt=0x%p", (void *)mpt));
8897 
8898         ASSERT(mutex_owned(&mpt->m_mutex));
8899 
8900         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
8901             ptgt = refhash_next(mpt->m_targets, ptgt)) {
8902                 if (ptgt->m_reset_delay != 0) {
8903                         ptgt->m_reset_delay -=
8904                             MPTSAS_WATCH_RESET_DELAY_TICK;
8905                         if (ptgt->m_reset_delay <= 0) {
8906                                 ptgt->m_reset_delay = 0;
8907                                 mptsas_set_throttle(mpt, ptgt,
8908                                     MAX_THROTTLE);
8909                                 restart++;
8910                         } else {
8911                                 done = -1;
8912                         }
8913                 }
8914         }
8915 
8916         if (restart > 0) {
8917                 mptsas_restart_hba(mpt);
8918         }
8919         return (done);
8920 }
8921 
8922 #ifdef MPTSAS_TEST
8923 static void
8924 mptsas_test_reset(mptsas_t *mpt, int target)
8925 {
8926         mptsas_target_t    *ptgt = NULL;
8927 
8928         if (mptsas_rtest == target) {
8929                 if (mptsas_do_scsi_reset(mpt, target) == TRUE) {
8930                         mptsas_rtest = -1;
8931                 }
8932                 if (mptsas_rtest == -1) {
8933                         NDBG22(("mptsas_test_reset success"));
8934                 }
8935         }
8936 }
8937 #endif
8938 
8939 /*
8940  * abort handling:
8941  *
8942  * Notes:
8943  *      - if pkt is not NULL, abort just that command
8944  *      - if pkt is NULL, abort all outstanding commands for target
8945  */
8946 static int
8947 mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
8948 {
8949         mptsas_t                *mpt = ADDR2MPT(ap);
8950         int                     rval;
8951         mptsas_tgt_private_t    *tgt_private;
8952         int                     target, lun;
8953 
8954         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
8955             tran_tgt_private;
8956         ASSERT(tgt_private != NULL);
8957         target = tgt_private->t_private->m_devhdl;
8958         lun = tgt_private->t_lun;
8959 
8960         NDBG23(("mptsas_scsi_abort: target=%d.%d", target, lun));
8961 
8962         mutex_enter(&mpt->m_mutex);
8963         rval = mptsas_do_scsi_abort(mpt, target, lun, pkt);
8964         mutex_exit(&mpt->m_mutex);
8965         return (rval);
8966 }
8967 
8968 static int
8969 mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun, struct scsi_pkt *pkt)
8970 {
8971         mptsas_cmd_t    *sp = NULL;
8972         mptsas_slots_t  *slots = mpt->m_active;
8973         int             rval = FALSE;
8974 
8975         ASSERT(mutex_owned(&mpt->m_mutex));
8976 
8977         /*
8978          * Abort the command pkt on the target/lun in ap.  If pkt is
8979          * NULL, abort all outstanding commands on that target/lun.
8980          * If you can abort them, return 1, else return 0.
8981          * Each packet that's aborted should be sent back to the target
8982          * driver through the callback routine, with pkt_reason set to
8983          * CMD_ABORTED.
8984          *
8985          * abort cmd pkt on HBA hardware; clean out of outstanding
8986          * command lists, etc.
8987          */
8988         if (pkt != NULL) {
8989                 /* abort the specified packet */
8990                 sp = PKT2CMD(pkt);
8991 
8992                 if (sp->cmd_queued) {
8993                         NDBG23(("mptsas_do_scsi_abort: queued sp=0x%p aborted",
8994                             (void *)sp));
8995                         mptsas_waitq_delete(mpt, sp);
8996                         mptsas_set_pkt_reason(mpt, sp, CMD_ABORTED,
8997                             STAT_ABORTED);
8998                         mptsas_doneq_add(mpt, sp);
8999                         rval = TRUE;
9000                         goto done;
9001                 }
9002 
9003                 /*
9004                  * Have mpt firmware abort this command
9005                  */
9006 
9007                 if (slots->m_slot[sp->cmd_slot] != NULL) {
9008                         rval = mptsas_ioc_task_management(mpt,
9009                             MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, target,
9010                             lun, NULL, 0, 0);
9011 
9012                         /*
9013                          * The transport layer expects only TRUE and FALSE.
9014                          * Therefore, if mptsas_ioc_task_management returns
9015                          * FAILED we will return FALSE.
9016                          */
9017                         if (rval == FAILED)
9018                                 rval = FALSE;
9019                         goto done;
9020                 }
9021         }
9022 
9023         /*
9024          * If pkt is NULL then abort task set
9025          */
9026         rval = mptsas_ioc_task_management(mpt,
9027             MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, target, lun, NULL, 0, 0);
9028 
9029         /*
9030          * The transport layer expects only TRUE and FALSE.
9031          * Therefore, if mptsas_ioc_task_management returns
9032          * FAILED we will return FALSE.
9033          */
9034         if (rval == FAILED)
9035                 rval = FALSE;
9036 
9037 #ifdef MPTSAS_TEST
9038         if (rval && mptsas_test_stop) {
9039                 debug_enter("mptsas_do_scsi_abort");
9040         }
9041 #endif
9042 
9043 done:
9044         mptsas_doneq_empty(mpt);
9045         return (rval);
9046 }
9047 
9048 /*
9049  * capability handling:
9050  * (*tran_getcap).  Get the capability named, and return its value.
9051  */
9052 static int
9053 mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly)
9054 {
9055         mptsas_t        *mpt = ADDR2MPT(ap);
9056         int             ckey;
9057         int             rval = FALSE;
9058 
9059         NDBG24(("mptsas_scsi_getcap: target=%d, cap=%s tgtonly=%x",
9060             ap->a_target, cap, tgtonly));
9061 
9062         mutex_enter(&mpt->m_mutex);
9063 
9064         if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9065                 mutex_exit(&mpt->m_mutex);
9066                 return (UNDEFINED);
9067         }
9068 
9069         switch (ckey) {
9070         case SCSI_CAP_DMA_MAX:
9071                 rval = (int)mpt->m_msg_dma_attr.dma_attr_maxxfer;
9072                 break;
9073         case SCSI_CAP_ARQ:
9074                 rval = TRUE;
9075                 break;
9076         case SCSI_CAP_MSG_OUT:
9077         case SCSI_CAP_PARITY:
9078         case SCSI_CAP_UNTAGGED_QING:
9079                 rval = TRUE;
9080                 break;
9081         case SCSI_CAP_TAGGED_QING:
9082                 rval = TRUE;
9083                 break;
9084         case SCSI_CAP_RESET_NOTIFICATION:
9085                 rval = TRUE;
9086                 break;
9087         case SCSI_CAP_LINKED_CMDS:
9088                 rval = FALSE;
9089                 break;
9090         case SCSI_CAP_QFULL_RETRIES:
9091                 rval = ((mptsas_tgt_private_t *)(ap->a_hba_tran->
9092                     tran_tgt_private))->t_private->m_qfull_retries;
9093                 break;
9094         case SCSI_CAP_QFULL_RETRY_INTERVAL:
9095                 rval = drv_hztousec(((mptsas_tgt_private_t *)
9096                     (ap->a_hba_tran->tran_tgt_private))->
9097                     t_private->m_qfull_retry_interval) / 1000;
9098                 break;
9099         case SCSI_CAP_CDB_LEN:
9100                 rval = CDB_GROUP4;
9101                 break;
9102         case SCSI_CAP_INTERCONNECT_TYPE:
9103                 rval = INTERCONNECT_SAS;
9104                 break;
9105         case SCSI_CAP_TRAN_LAYER_RETRIES:
9106                 if (mpt->m_ioc_capabilities &
9107                     MPI2_IOCFACTS_CAPABILITY_TLR)
9108                         rval = TRUE;
9109                 else
9110                         rval = FALSE;
9111                 break;
9112         default:
9113                 rval = UNDEFINED;
9114                 break;
9115         }
9116 
9117         NDBG24(("mptsas_scsi_getcap: %s, rval=%x", cap, rval));
9118 
9119         mutex_exit(&mpt->m_mutex);
9120         return (rval);
9121 }
9122 
9123 /*
9124  * (*tran_setcap).  Set the capability named to the value given.
9125  */
9126 static int
9127 mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value, int tgtonly)
9128 {
9129         mptsas_t        *mpt = ADDR2MPT(ap);
9130         int             ckey;
9131         int             rval = FALSE;
9132 
9133         NDBG24(("mptsas_scsi_setcap: target=%d, cap=%s value=%x tgtonly=%x",
9134             ap->a_target, cap, value, tgtonly));
9135 
9136         if (!tgtonly) {
9137                 return (rval);
9138         }
9139 
9140         mutex_enter(&mpt->m_mutex);
9141 
9142         if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9143                 mutex_exit(&mpt->m_mutex);
9144                 return (UNDEFINED);
9145         }
9146 
9147         switch (ckey) {
9148         case SCSI_CAP_DMA_MAX:
9149         case SCSI_CAP_MSG_OUT:
9150         case SCSI_CAP_PARITY:
9151         case SCSI_CAP_INITIATOR_ID:
9152         case SCSI_CAP_LINKED_CMDS:
9153         case SCSI_CAP_UNTAGGED_QING:
9154         case SCSI_CAP_RESET_NOTIFICATION:
9155                 /*
9156                  * None of these are settable via
9157                  * the capability interface.
9158                  */
9159                 break;
9160         case SCSI_CAP_ARQ:
9161                 /*
9162                  * We cannot turn off arq so return false if asked to
9163                  */
9164                 if (value) {
9165                         rval = TRUE;
9166                 } else {
9167                         rval = FALSE;
9168                 }
9169                 break;
9170         case SCSI_CAP_TAGGED_QING:
9171                 mptsas_set_throttle(mpt, ((mptsas_tgt_private_t *)
9172                     (ap->a_hba_tran->tran_tgt_private))->t_private,
9173                     MAX_THROTTLE);
9174                 rval = TRUE;
9175                 break;
9176         case SCSI_CAP_QFULL_RETRIES:
9177                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9178                     t_private->m_qfull_retries = (uchar_t)value;
9179                 rval = TRUE;
9180                 break;
9181         case SCSI_CAP_QFULL_RETRY_INTERVAL:
9182                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9183                     t_private->m_qfull_retry_interval =
9184                     drv_usectohz(value * 1000);
9185                 rval = TRUE;
9186                 break;
9187         default:
9188                 rval = UNDEFINED;
9189                 break;
9190         }
9191         mutex_exit(&mpt->m_mutex);
9192         return (rval);
9193 }
9194 
9195 /*
9196  * Utility routine for mptsas_ifsetcap/ifgetcap
9197  */
9198 /*ARGSUSED*/
9199 static int
9200 mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp)
9201 {
9202         NDBG24(("mptsas_scsi_capchk: cap=%s", cap));
9203 
9204         if (!cap)
9205                 return (FALSE);
9206 
9207         *cidxp = scsi_hba_lookup_capstr(cap);
9208         return (TRUE);
9209 }
9210 
9211 static int
9212 mptsas_alloc_active_slots(mptsas_t *mpt, int flag)
9213 {
9214         mptsas_slots_t  *old_active = mpt->m_active;
9215         mptsas_slots_t  *new_active;
9216         size_t          size;
9217 
9218         /*
9219          * if there are active commands, then we cannot
9220          * change size of active slots array.
9221          */
9222         ASSERT(mpt->m_ncmds == 0);
9223 
9224         size = MPTSAS_SLOTS_SIZE(mpt);
9225         new_active = kmem_zalloc(size, flag);
9226         if (new_active == NULL) {
9227                 NDBG1(("new active alloc failed"));
9228                 return (-1);
9229         }
9230         /*
9231          * Since SMID 0 is reserved and the TM slot is reserved, the
9232          * number of slots that can be used at any one time is
9233          * m_max_requests - 2.
9234          */
9235         new_active->m_n_normal = (mpt->m_max_requests - 2);
9236         new_active->m_size = size;
9237         new_active->m_rotor = 1;
9238         if (old_active)
9239                 mptsas_free_active_slots(mpt);
9240         mpt->m_active = new_active;
9241 
9242         return (0);
9243 }
9244 
9245 static void
9246 mptsas_free_active_slots(mptsas_t *mpt)
9247 {
9248         mptsas_slots_t  *active = mpt->m_active;
9249         size_t          size;
9250 
9251         if (active == NULL)
9252                 return;
9253         size = active->m_size;
9254         kmem_free(active, size);
9255         mpt->m_active = NULL;
9256 }
9257 
9258 /*
9259  * Error logging, printing, and debug print routines.
9260  */
9261 static char *mptsas_label = "mpt_sas";
9262 
9263 /*PRINTFLIKE3*/
9264 void
9265 mptsas_log(mptsas_t *mpt, int level, char *fmt, ...)
9266 {
9267         dev_info_t      *dev;
9268         va_list         ap;
9269 
9270         if (mpt) {
9271                 dev = mpt->m_dip;
9272         } else {
9273                 dev = 0;
9274         }
9275 
9276         mutex_enter(&mptsas_log_mutex);
9277 
9278         va_start(ap, fmt);
9279         (void) vsprintf(mptsas_log_buf, fmt, ap);
9280         va_end(ap);
9281 
9282         if (level == CE_CONT) {
9283                 scsi_log(dev, mptsas_label, level, "%s\n", mptsas_log_buf);
9284         } else {
9285                 scsi_log(dev, mptsas_label, level, "%s", mptsas_log_buf);
9286         }
9287 
9288         mutex_exit(&mptsas_log_mutex);
9289 }
9290 
9291 #ifdef MPTSAS_DEBUG
9292 /*PRINTFLIKE1*/
9293 void
9294 mptsas_printf(char *fmt, ...)
9295 {
9296         dev_info_t      *dev = 0;
9297         va_list         ap;
9298 
9299         mutex_enter(&mptsas_log_mutex);
9300 
9301         va_start(ap, fmt);
9302         (void) vsprintf(mptsas_log_buf, fmt, ap);
9303         va_end(ap);
9304 
9305 #ifdef PROM_PRINTF
9306         prom_printf("%s:\t%s\n", mptsas_label, mptsas_log_buf);
9307 #else
9308         scsi_log(dev, mptsas_label, SCSI_DEBUG, "%s\n", mptsas_log_buf);
9309 #endif
9310         mutex_exit(&mptsas_log_mutex);
9311 }
9312 #endif
9313 
9314 /*
9315  * timeout handling
9316  */
9317 static void
9318 mptsas_watch(void *arg)
9319 {
9320 #ifndef __lock_lint
9321         _NOTE(ARGUNUSED(arg))
9322 #endif
9323 
9324         mptsas_t        *mpt;
9325         uint32_t        doorbell;
9326 
9327         NDBG30(("mptsas_watch"));
9328 
9329         rw_enter(&mptsas_global_rwlock, RW_READER);
9330         for (mpt = mptsas_head; mpt != (mptsas_t *)NULL; mpt = mpt->m_next) {
9331 
9332                 mutex_enter(&mpt->m_mutex);
9333 
9334                 /* Skip device if not powered on */
9335                 if (mpt->m_options & MPTSAS_OPT_PM) {
9336                         if (mpt->m_power_level == PM_LEVEL_D0) {
9337                                 (void) pm_busy_component(mpt->m_dip, 0);
9338                                 mpt->m_busy = 1;
9339                         } else {
9340                                 mutex_exit(&mpt->m_mutex);
9341                                 continue;
9342                         }
9343                 }
9344 
9345                 /*
9346                  * Check if controller is in a FAULT state. If so, reset it.
9347                  */
9348                 doorbell = ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell);
9349                 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
9350                         doorbell &= MPI2_DOORBELL_DATA_MASK;
9351                         mptsas_log(mpt, CE_WARN, "MPT Firmware Fault, "
9352                             "code: %04x", doorbell);
9353                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
9354                         if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
9355                                 mptsas_log(mpt, CE_WARN, "Reset failed"
9356                                     "after fault was detected");
9357                         }
9358                 }
9359 
9360                 /*
9361                  * For now, always call mptsas_watchsubr.
9362                  */
9363                 mptsas_watchsubr(mpt);
9364 
9365                 if (mpt->m_options & MPTSAS_OPT_PM) {
9366                         mpt->m_busy = 0;
9367                         (void) pm_idle_component(mpt->m_dip, 0);
9368                 }
9369 
9370                 mutex_exit(&mpt->m_mutex);
9371         }
9372         rw_exit(&mptsas_global_rwlock);
9373 
9374         mutex_enter(&mptsas_global_mutex);
9375         if (mptsas_timeouts_enabled)
9376                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
9377         mutex_exit(&mptsas_global_mutex);
9378 }
9379 
9380 static void
9381 mptsas_watchsubr(mptsas_t *mpt)
9382 {
9383         int             i;
9384         mptsas_cmd_t    *cmd;
9385         mptsas_target_t *ptgt = NULL;
9386         hrtime_t        timestamp = gethrtime();
9387 
9388         ASSERT(MUTEX_HELD(&mpt->m_mutex));
9389 
9390         NDBG30(("mptsas_watchsubr: mpt=0x%p", (void *)mpt));
9391 
9392 #ifdef MPTSAS_TEST
9393         if (mptsas_enable_untagged) {
9394                 mptsas_test_untagged++;
9395         }
9396 #endif
9397 
9398         /*
9399          * Check for commands stuck in active slot
9400          * Account for TM requests, which use the last SMID.
9401          */
9402         for (i = 0; i <= mpt->m_active->m_n_normal; i++) {
9403                 if ((cmd = mpt->m_active->m_slot[i]) != NULL) {
9404                         if (cmd->cmd_active_expiration <= timestamp) {
9405                                 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
9406                                         /*
9407                                          * There seems to be a command stuck
9408                                          * in the active slot.  Drain throttle.
9409                                          */
9410                                         mptsas_set_throttle(mpt,
9411                                             cmd->cmd_tgt_addr,
9412                                             DRAIN_THROTTLE);
9413                                 } else if (cmd->cmd_flags &
9414                                     (CFLAG_PASSTHRU | CFLAG_CONFIG |
9415                                     CFLAG_FW_DIAG)) {
9416                                         /*
9417                                          * passthrough command timeout
9418                                          */
9419                                         cmd->cmd_flags |= (CFLAG_FINISHED |
9420                                             CFLAG_TIMEOUT);
9421                                         cv_broadcast(&mpt->m_passthru_cv);
9422                                         cv_broadcast(&mpt->m_config_cv);
9423                                         cv_broadcast(&mpt->m_fw_diag_cv);
9424                                 }
9425                         }
9426                 }
9427         }
9428 
9429         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9430             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9431                 /*
9432                  * If we were draining due to a qfull condition,
9433                  * go back to full throttle.
9434                  */
9435                 if ((ptgt->m_t_throttle < MAX_THROTTLE) &&
9436                     (ptgt->m_t_throttle > HOLD_THROTTLE) &&
9437                     (ptgt->m_t_ncmds < ptgt->m_t_throttle)) {
9438                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9439                         mptsas_restart_hba(mpt);
9440                 }
9441 
9442                 cmd = TAILQ_LAST(&ptgt->m_active_cmdq, mptsas_active_cmdq);
9443                 if (cmd == NULL)
9444                         continue;
9445 
9446                 if (cmd->cmd_active_expiration <= timestamp) {
9447                         /*
9448                          * Earliest command timeout expired. Drain throttle.
9449                          */
9450                         mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
9451 
9452                         /*
9453                          * Check for remaining commands.
9454                          */
9455                         cmd = TAILQ_FIRST(&ptgt->m_active_cmdq);
9456                         if (cmd->cmd_active_expiration > timestamp) {
9457                                 /*
9458                                  * Wait for remaining commands to complete or
9459                                  * time out.
9460                                  */
9461                                 NDBG23(("command timed out, pending drain"));
9462                                 continue;
9463                         }
9464 
9465                         /*
9466                          * All command timeouts expired.
9467                          */
9468                         mptsas_log(mpt, CE_NOTE, "Timeout of %d seconds "
9469                             "expired with %d commands on target %d lun %d.",
9470                             cmd->cmd_pkt->pkt_time, ptgt->m_t_ncmds,
9471                             ptgt->m_devhdl, Lun(cmd));
9472 
9473                         mptsas_cmd_timeout(mpt, ptgt);
9474                 } else if (cmd->cmd_active_expiration <=
9475                     timestamp + (hrtime_t)mptsas_scsi_watchdog_tick * NANOSEC) {
9476                         NDBG23(("pending timeout"));
9477                         mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
9478                 }
9479         }
9480 }
9481 
9482 /*
9483  * timeout recovery
9484  */
9485 static void
9486 mptsas_cmd_timeout(mptsas_t *mpt, mptsas_target_t *ptgt)
9487 {
9488         uint16_t        devhdl;
9489         uint64_t        sas_wwn;
9490         uint8_t         phy;
9491         char            wwn_str[MPTSAS_WWN_STRLEN];
9492 
9493         devhdl = ptgt->m_devhdl;
9494         sas_wwn = ptgt->m_addr.mta_wwn;
9495         phy = ptgt->m_phynum;
9496         if (sas_wwn == 0) {
9497                 (void) sprintf(wwn_str, "p%x", phy);
9498         } else {
9499                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
9500         }
9501 
9502         NDBG29(("mptsas_cmd_timeout: target=%d", devhdl));
9503         mptsas_log(mpt, CE_WARN, "Disconnected command timeout for "
9504             "target %d %s.", devhdl, wwn_str);
9505 
9506         /*
9507          * Abort all outstanding commands on the device.
9508          */
9509         NDBG29(("mptsas_cmd_timeout: device reset"));
9510         if (mptsas_do_scsi_reset(mpt, devhdl) != TRUE) {
9511                 mptsas_log(mpt, CE_WARN, "Target %d reset for command timeout "
9512                     "recovery failed!", devhdl);
9513         }
9514 }
9515 
9516 /*
9517  * Device / Hotplug control
9518  */
9519 static int
9520 mptsas_scsi_quiesce(dev_info_t *dip)
9521 {
9522         mptsas_t        *mpt;
9523         scsi_hba_tran_t *tran;
9524 
9525         tran = ddi_get_driver_private(dip);
9526         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
9527                 return (-1);
9528 
9529         return (mptsas_quiesce_bus(mpt));
9530 }
9531 
9532 static int
9533 mptsas_scsi_unquiesce(dev_info_t *dip)
9534 {
9535         mptsas_t                *mpt;
9536         scsi_hba_tran_t *tran;
9537 
9538         tran = ddi_get_driver_private(dip);
9539         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
9540                 return (-1);
9541 
9542         return (mptsas_unquiesce_bus(mpt));
9543 }
9544 
9545 static int
9546 mptsas_quiesce_bus(mptsas_t *mpt)
9547 {
9548         mptsas_target_t *ptgt = NULL;
9549 
9550         NDBG28(("mptsas_quiesce_bus"));
9551         mutex_enter(&mpt->m_mutex);
9552 
9553         /* Set all the throttles to zero */
9554         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9555             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9556                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9557         }
9558 
9559         /* If there are any outstanding commands in the queue */
9560         if (mpt->m_ncmds) {
9561                 mpt->m_softstate |= MPTSAS_SS_DRAINING;
9562                 mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
9563                     mpt, (MPTSAS_QUIESCE_TIMEOUT * drv_usectohz(1000000)));
9564                 if (cv_wait_sig(&mpt->m_cv, &mpt->m_mutex) == 0) {
9565                         /*
9566                          * Quiesce has been interrupted
9567                          */
9568                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
9569                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9570                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9571                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9572                         }
9573                         mptsas_restart_hba(mpt);
9574                         if (mpt->m_quiesce_timeid != 0) {
9575                                 timeout_id_t tid = mpt->m_quiesce_timeid;
9576                                 mpt->m_quiesce_timeid = 0;
9577                                 mutex_exit(&mpt->m_mutex);
9578                                 (void) untimeout(tid);
9579                                 return (-1);
9580                         }
9581                         mutex_exit(&mpt->m_mutex);
9582                         return (-1);
9583                 } else {
9584                         /* Bus has been quiesced */
9585                         ASSERT(mpt->m_quiesce_timeid == 0);
9586                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
9587                         mpt->m_softstate |= MPTSAS_SS_QUIESCED;
9588                         mutex_exit(&mpt->m_mutex);
9589                         return (0);
9590                 }
9591         }
9592         /* Bus was not busy - QUIESCED */
9593         mutex_exit(&mpt->m_mutex);
9594 
9595         return (0);
9596 }
9597 
9598 static int
9599 mptsas_unquiesce_bus(mptsas_t *mpt)
9600 {
9601         mptsas_target_t *ptgt = NULL;
9602 
9603         NDBG28(("mptsas_unquiesce_bus"));
9604         mutex_enter(&mpt->m_mutex);
9605         mpt->m_softstate &= ~MPTSAS_SS_QUIESCED;
9606         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9607             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9608                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9609         }
9610         mptsas_restart_hba(mpt);
9611         mutex_exit(&mpt->m_mutex);
9612         return (0);
9613 }
9614 
9615 static void
9616 mptsas_ncmds_checkdrain(void *arg)
9617 {
9618         mptsas_t        *mpt = arg;
9619         mptsas_target_t *ptgt = NULL;
9620 
9621         mutex_enter(&mpt->m_mutex);
9622         if (mpt->m_softstate & MPTSAS_SS_DRAINING) {
9623                 mpt->m_quiesce_timeid = 0;
9624                 if (mpt->m_ncmds == 0) {
9625                         /* Command queue has been drained */
9626                         cv_signal(&mpt->m_cv);
9627                 } else {
9628                         /*
9629                          * The throttle may have been reset because
9630                          * of a SCSI bus reset
9631                          */
9632                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9633                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9634                                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9635                         }
9636 
9637                         mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
9638                             mpt, (MPTSAS_QUIESCE_TIMEOUT *
9639                             drv_usectohz(1000000)));
9640                 }
9641         }
9642         mutex_exit(&mpt->m_mutex);
9643 }
9644 
9645 /*ARGSUSED*/
9646 static void
9647 mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
9648 {
9649         int     i;
9650         uint8_t *cp = (uchar_t *)cmd->cmd_pkt->pkt_cdbp;
9651         char    buf[128];
9652 
9653         buf[0] = '\0';
9654         NDBG25(("?Cmd (0x%p) dump for Target %d Lun %d:\n", (void *)cmd,
9655             Tgt(cmd), Lun(cmd)));
9656         (void) sprintf(&buf[0], "\tcdb=[");
9657         for (i = 0; i < (int)cmd->cmd_cdblen; i++) {
9658                 (void) sprintf(&buf[strlen(buf)], " 0x%x", *cp++);
9659         }
9660         (void) sprintf(&buf[strlen(buf)], " ]");
9661         NDBG25(("?%s\n", buf));
9662         NDBG25(("?pkt_flags=0x%x pkt_statistics=0x%x pkt_state=0x%x\n",
9663             cmd->cmd_pkt->pkt_flags, cmd->cmd_pkt->pkt_statistics,
9664             cmd->cmd_pkt->pkt_state));
9665         NDBG25(("?pkt_scbp=0x%x cmd_flags=0x%x\n", cmd->cmd_pkt->pkt_scbp ?
9666             *(cmd->cmd_pkt->pkt_scbp) : 0, cmd->cmd_flags));
9667 }
9668 
9669 static void
9670 mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd)
9671 {
9672         caddr_t                 memp;
9673         pMPI2RequestHeader_t    request_hdrp;
9674         struct scsi_pkt         *pkt = cmd->cmd_pkt;
9675         mptsas_pt_request_t     *pt = pkt->pkt_ha_private;
9676         uint32_t                request_size, data_size, dataout_size;
9677         uint32_t                direction;
9678         ddi_dma_cookie_t        data_cookie;
9679         ddi_dma_cookie_t        dataout_cookie;
9680         uint32_t                request_desc_low, request_desc_high = 0;
9681         uint32_t                i, sense_bufp;
9682         uint8_t                 desc_type;
9683         uint8_t                 *request, function;
9684         ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
9685         ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
9686 
9687         desc_type = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
9688 
9689         request = pt->request;
9690         direction = pt->direction;
9691         request_size = pt->request_size;
9692         data_size = pt->data_size;
9693         dataout_size = pt->dataout_size;
9694         data_cookie = pt->data_cookie;
9695         dataout_cookie = pt->dataout_cookie;
9696 
9697         /*
9698          * Store the passthrough message in memory location
9699          * corresponding to our slot number
9700          */
9701         memp = mpt->m_req_frame + (mpt->m_req_frame_size * cmd->cmd_slot);
9702         request_hdrp = (pMPI2RequestHeader_t)memp;
9703         bzero(memp, mpt->m_req_frame_size);
9704 
9705         for (i = 0; i < request_size; i++) {
9706                 bcopy(request + i, memp + i, 1);
9707         }
9708 
9709         if (data_size || dataout_size) {
9710                 pMpi2SGESimple64_t      sgep;
9711                 uint32_t                sge_flags;
9712 
9713                 sgep = (pMpi2SGESimple64_t)((uint8_t *)request_hdrp +
9714                     request_size);
9715                 if (dataout_size) {
9716 
9717                         sge_flags = dataout_size |
9718                             ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
9719                             MPI2_SGE_FLAGS_END_OF_BUFFER |
9720                             MPI2_SGE_FLAGS_HOST_TO_IOC |
9721                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
9722                             MPI2_SGE_FLAGS_SHIFT);
9723                         ddi_put32(acc_hdl, &sgep->FlagsLength, sge_flags);
9724                         ddi_put32(acc_hdl, &sgep->Address.Low,
9725                             (uint32_t)(dataout_cookie.dmac_laddress &
9726                             0xffffffffull));
9727                         ddi_put32(acc_hdl, &sgep->Address.High,
9728                             (uint32_t)(dataout_cookie.dmac_laddress
9729                             >> 32));
9730                         sgep++;
9731                 }
9732                 sge_flags = data_size;
9733                 sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
9734                     MPI2_SGE_FLAGS_LAST_ELEMENT |
9735                     MPI2_SGE_FLAGS_END_OF_BUFFER |
9736                     MPI2_SGE_FLAGS_END_OF_LIST |
9737                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
9738                     MPI2_SGE_FLAGS_SHIFT);
9739                 if (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
9740                         sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_HOST_TO_IOC) <<
9741                             MPI2_SGE_FLAGS_SHIFT);
9742                 } else {
9743                         sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_IOC_TO_HOST) <<
9744                             MPI2_SGE_FLAGS_SHIFT);
9745                 }
9746                 ddi_put32(acc_hdl, &sgep->FlagsLength,
9747                     sge_flags);
9748                 ddi_put32(acc_hdl, &sgep->Address.Low,
9749                     (uint32_t)(data_cookie.dmac_laddress &
9750                     0xffffffffull));
9751                 ddi_put32(acc_hdl, &sgep->Address.High,
9752                     (uint32_t)(data_cookie.dmac_laddress >> 32));
9753         }
9754 
9755         function = request_hdrp->Function;
9756         if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
9757             (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
9758                 pMpi2SCSIIORequest_t    scsi_io_req;
9759 
9760                 scsi_io_req = (pMpi2SCSIIORequest_t)request_hdrp;
9761                 /*
9762                  * Put SGE for data and data_out buffer at the end of
9763                  * scsi_io_request message header.(64 bytes in total)
9764                  * Following above SGEs, the residual space will be
9765                  * used by sense data.
9766                  */
9767                 ddi_put8(acc_hdl,
9768                     &scsi_io_req->SenseBufferLength,
9769                     (uint8_t)(request_size - 64));
9770 
9771                 sense_bufp = mpt->m_req_frame_dma_addr +
9772                     (mpt->m_req_frame_size * cmd->cmd_slot);
9773                 sense_bufp += 64;
9774                 ddi_put32(acc_hdl,
9775                     &scsi_io_req->SenseBufferLowAddress, sense_bufp);
9776 
9777                 /*
9778                  * Set SGLOffset0 value
9779                  */
9780                 ddi_put8(acc_hdl, &scsi_io_req->SGLOffset0,
9781                     offsetof(MPI2_SCSI_IO_REQUEST, SGL) / 4);
9782 
9783                 /*
9784                  * Setup descriptor info.  RAID passthrough must use the
9785                  * default request descriptor which is already set, so if this
9786                  * is a SCSI IO request, change the descriptor to SCSI IO.
9787                  */
9788                 if (function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
9789                         desc_type = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
9790                         request_desc_high = (ddi_get16(acc_hdl,
9791                             &scsi_io_req->DevHandle) << 16);
9792                 }
9793         }
9794 
9795         /*
9796          * We must wait till the message has been completed before
9797          * beginning the next message so we wait for this one to
9798          * finish.
9799          */
9800         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
9801         request_desc_low = (cmd->cmd_slot << 16) + desc_type;
9802         cmd->cmd_rfm = NULL;
9803         MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
9804         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
9805             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
9806                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
9807         }
9808 }
9809 
9810 
9811 
9812 static int
9813 mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
9814     uint8_t *data, uint32_t request_size, uint32_t reply_size,
9815     uint32_t data_size, uint32_t direction, uint8_t *dataout,
9816     uint32_t dataout_size, short timeout, int mode)
9817 {
9818         mptsas_pt_request_t             pt;
9819         mptsas_dma_alloc_state_t        data_dma_state;
9820         mptsas_dma_alloc_state_t        dataout_dma_state;
9821         caddr_t                         memp;
9822         mptsas_cmd_t                    *cmd = NULL;
9823         struct scsi_pkt                 *pkt;
9824         uint32_t                        reply_len = 0, sense_len = 0;
9825         pMPI2RequestHeader_t            request_hdrp;
9826         pMPI2RequestHeader_t            request_msg;
9827         pMPI2DefaultReply_t             reply_msg;
9828         Mpi2SCSIIOReply_t               rep_msg;
9829         int                             i, status = 0, pt_flags = 0, rv = 0;
9830         int                             rvalue;
9831         uint8_t                         function;
9832 
9833         ASSERT(mutex_owned(&mpt->m_mutex));
9834 
9835         reply_msg = (pMPI2DefaultReply_t)(&rep_msg);
9836         bzero(reply_msg, sizeof (MPI2_DEFAULT_REPLY));
9837         request_msg = kmem_zalloc(request_size, KM_SLEEP);
9838 
9839         mutex_exit(&mpt->m_mutex);
9840         /*
9841          * copy in the request buffer since it could be used by
9842          * another thread when the pt request into waitq
9843          */
9844         if (ddi_copyin(request, request_msg, request_size, mode)) {
9845                 mutex_enter(&mpt->m_mutex);
9846                 status = EFAULT;
9847                 mptsas_log(mpt, CE_WARN, "failed to copy request data");
9848                 goto out;
9849         }
9850         mutex_enter(&mpt->m_mutex);
9851 
9852         function = request_msg->Function;
9853         if (function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
9854                 pMpi2SCSITaskManagementRequest_t        task;
9855                 task = (pMpi2SCSITaskManagementRequest_t)request_msg;
9856                 mptsas_setup_bus_reset_delay(mpt);
9857                 rv = mptsas_ioc_task_management(mpt, task->TaskType,
9858                     task->DevHandle, (int)task->LUN[1], reply, reply_size,
9859                     mode);
9860 
9861                 if (rv != TRUE) {
9862                         status = EIO;
9863                         mptsas_log(mpt, CE_WARN, "task management failed");
9864                 }
9865                 goto out;
9866         }
9867 
9868         if (data_size != 0) {
9869                 data_dma_state.size = data_size;
9870                 if (mptsas_dma_alloc(mpt, &data_dma_state) != DDI_SUCCESS) {
9871                         status = ENOMEM;
9872                         mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
9873                             "resource");
9874                         goto out;
9875                 }
9876                 pt_flags |= MPTSAS_DATA_ALLOCATED;
9877                 if (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
9878                         mutex_exit(&mpt->m_mutex);
9879                         for (i = 0; i < data_size; i++) {
9880                                 if (ddi_copyin(data + i, (uint8_t *)
9881                                     data_dma_state.memp + i, 1, mode)) {
9882                                         mutex_enter(&mpt->m_mutex);
9883                                         status = EFAULT;
9884                                         mptsas_log(mpt, CE_WARN, "failed to "
9885                                             "copy read data");
9886                                         goto out;
9887                                 }
9888                         }
9889                         mutex_enter(&mpt->m_mutex);
9890                 }
9891         }
9892 
9893         if (dataout_size != 0) {
9894                 dataout_dma_state.size = dataout_size;
9895                 if (mptsas_dma_alloc(mpt, &dataout_dma_state) != DDI_SUCCESS) {
9896                         status = ENOMEM;
9897                         mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
9898                             "resource");
9899                         goto out;
9900                 }
9901                 pt_flags |= MPTSAS_DATAOUT_ALLOCATED;
9902                 mutex_exit(&mpt->m_mutex);
9903                 for (i = 0; i < dataout_size; i++) {
9904                         if (ddi_copyin(dataout + i, (uint8_t *)
9905                             dataout_dma_state.memp + i, 1, mode)) {
9906                                 mutex_enter(&mpt->m_mutex);
9907                                 mptsas_log(mpt, CE_WARN, "failed to copy out"
9908                                     " data");
9909                                 status = EFAULT;
9910                                 goto out;
9911                         }
9912                 }
9913                 mutex_enter(&mpt->m_mutex);
9914         }
9915 
9916         if ((rvalue = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
9917                 status = EAGAIN;
9918                 mptsas_log(mpt, CE_NOTE, "event ack command pool is full");
9919                 goto out;
9920         }
9921         pt_flags |= MPTSAS_REQUEST_POOL_CMD;
9922 
9923         bzero((caddr_t)cmd, sizeof (*cmd));
9924         bzero((caddr_t)pkt, scsi_pkt_size());
9925         bzero((caddr_t)&pt, sizeof (pt));
9926 
9927         cmd->ioc_cmd_slot = (uint32_t)(rvalue);
9928 
9929         pt.request = (uint8_t *)request_msg;
9930         pt.direction = direction;
9931         pt.request_size = request_size;
9932         pt.data_size = data_size;
9933         pt.dataout_size = dataout_size;
9934         pt.data_cookie = data_dma_state.cookie;
9935         pt.dataout_cookie = dataout_dma_state.cookie;
9936 
9937         /*
9938          * Form a blank cmd/pkt to store the acknowledgement message
9939          */
9940         pkt->pkt_cdbp                = (opaque_t)&cmd->cmd_cdb[0];
9941         pkt->pkt_scbp                = (opaque_t)&cmd->cmd_scb;
9942         pkt->pkt_ha_private  = (opaque_t)&pt;
9943         pkt->pkt_flags               = FLAG_HEAD;
9944         pkt->pkt_time                = timeout;
9945         cmd->cmd_pkt         = pkt;
9946         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_PASSTHRU;
9947 
9948         /*
9949          * Save the command in a slot
9950          */
9951         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
9952                 /*
9953                  * Once passthru command get slot, set cmd_flags
9954                  * CFLAG_PREPARED.
9955                  */
9956                 cmd->cmd_flags |= CFLAG_PREPARED;
9957                 mptsas_start_passthru(mpt, cmd);
9958         } else {
9959                 mptsas_waitq_add(mpt, cmd);
9960         }
9961 
9962         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
9963                 cv_wait(&mpt->m_passthru_cv, &mpt->m_mutex);
9964         }
9965 
9966         if (cmd->cmd_flags & CFLAG_PREPARED) {
9967                 memp = mpt->m_req_frame + (mpt->m_req_frame_size *
9968                     cmd->cmd_slot);
9969                 request_hdrp = (pMPI2RequestHeader_t)memp;
9970         }
9971 
9972         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
9973                 status = ETIMEDOUT;
9974                 mptsas_log(mpt, CE_WARN, "passthrough command timeout");
9975                 pt_flags |= MPTSAS_CMD_TIMEOUT;
9976                 goto out;
9977         }
9978 
9979         if (cmd->cmd_rfm) {
9980                 /*
9981                  * cmd_rfm is zero means the command reply is a CONTEXT
9982                  * reply and no PCI Write to post the free reply SMFA
9983                  * because no reply message frame is used.
9984                  * cmd_rfm is non-zero means the reply is a ADDRESS
9985                  * reply and reply message frame is used.
9986                  */
9987                 pt_flags |= MPTSAS_ADDRESS_REPLY;
9988                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
9989                     DDI_DMA_SYNC_FORCPU);
9990                 reply_msg = (pMPI2DefaultReply_t)
9991                     (mpt->m_reply_frame + (cmd->cmd_rfm -
9992                     mpt->m_reply_frame_dma_addr));
9993         }
9994 
9995         mptsas_fma_check(mpt, cmd);
9996         if (pkt->pkt_reason == CMD_TRAN_ERR) {
9997                 status = EAGAIN;
9998                 mptsas_log(mpt, CE_WARN, "passthru fma error");
9999                 goto out;
10000         }
10001         if (pkt->pkt_reason == CMD_RESET) {
10002                 status = EAGAIN;
10003                 mptsas_log(mpt, CE_WARN, "ioc reset abort passthru");
10004                 goto out;
10005         }
10006 
10007         if (pkt->pkt_reason == CMD_INCOMPLETE) {
10008                 status = EIO;
10009                 mptsas_log(mpt, CE_WARN, "passthrough command incomplete");
10010                 goto out;
10011         }
10012 
10013         mutex_exit(&mpt->m_mutex);
10014         if (cmd->cmd_flags & CFLAG_PREPARED) {
10015                 function = request_hdrp->Function;
10016                 if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
10017                     (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
10018                         reply_len = sizeof (MPI2_SCSI_IO_REPLY);
10019                         sense_len = reply_size - reply_len;
10020                 } else {
10021                         reply_len = reply_size;
10022                         sense_len = 0;
10023                 }
10024 
10025                 for (i = 0; i < reply_len; i++) {
10026                         if (ddi_copyout((uint8_t *)reply_msg + i, reply + i, 1,
10027                             mode)) {
10028                                 mutex_enter(&mpt->m_mutex);
10029                                 status = EFAULT;
10030                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
10031                                     "reply data");
10032                                 goto out;
10033                         }
10034                 }
10035                 for (i = 0; i < sense_len; i++) {
10036                         if (ddi_copyout((uint8_t *)request_hdrp + 64 + i,
10037                             reply + reply_len + i, 1, mode)) {
10038                                 mutex_enter(&mpt->m_mutex);
10039                                 status = EFAULT;
10040                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
10041                                     "sense data");
10042                                 goto out;
10043                         }
10044                 }
10045         }
10046 
10047         if (data_size) {
10048                 if (direction != MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10049                         (void) ddi_dma_sync(data_dma_state.handle, 0, 0,
10050                             DDI_DMA_SYNC_FORCPU);
10051                         for (i = 0; i < data_size; i++) {
10052                                 if (ddi_copyout((uint8_t *)(
10053                                     data_dma_state.memp + i), data + i,  1,
10054                                     mode)) {
10055                                         mutex_enter(&mpt->m_mutex);
10056                                         status = EFAULT;
10057                                         mptsas_log(mpt, CE_WARN, "failed to "
10058                                             "copy out the reply data");
10059                                         goto out;
10060                                 }
10061                         }
10062                 }
10063         }
10064         mutex_enter(&mpt->m_mutex);
10065 out:
10066         /*
10067          * Put the reply frame back on the free queue, increment the free
10068          * index, and write the new index to the free index register.  But only
10069          * if this reply is an ADDRESS reply.
10070          */
10071         if (pt_flags & MPTSAS_ADDRESS_REPLY) {
10072                 ddi_put32(mpt->m_acc_free_queue_hdl,
10073                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
10074                     cmd->cmd_rfm);
10075                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
10076                     DDI_DMA_SYNC_FORDEV);
10077                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
10078                         mpt->m_free_index = 0;
10079                 }
10080                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
10081                     mpt->m_free_index);
10082         }
10083         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
10084                 mptsas_remove_cmd(mpt, cmd);
10085                 pt_flags &= (~MPTSAS_REQUEST_POOL_CMD);
10086         }
10087         if (pt_flags & MPTSAS_REQUEST_POOL_CMD)
10088                 mptsas_return_to_pool(mpt, cmd);
10089         if (pt_flags & MPTSAS_DATA_ALLOCATED) {
10090                 if (mptsas_check_dma_handle(data_dma_state.handle) !=
10091                     DDI_SUCCESS) {
10092                         ddi_fm_service_impact(mpt->m_dip,
10093                             DDI_SERVICE_UNAFFECTED);
10094                         status = EFAULT;
10095                 }
10096                 mptsas_dma_free(&data_dma_state);
10097         }
10098         if (pt_flags & MPTSAS_DATAOUT_ALLOCATED) {
10099                 if (mptsas_check_dma_handle(dataout_dma_state.handle) !=
10100                     DDI_SUCCESS) {
10101                         ddi_fm_service_impact(mpt->m_dip,
10102                             DDI_SERVICE_UNAFFECTED);
10103                         status = EFAULT;
10104                 }
10105                 mptsas_dma_free(&dataout_dma_state);
10106         }
10107         if (pt_flags & MPTSAS_CMD_TIMEOUT) {
10108                 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
10109                         mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
10110                 }
10111         }
10112         if (request_msg)
10113                 kmem_free(request_msg, request_size);
10114 
10115         return (status);
10116 }
10117 
10118 static int
10119 mptsas_pass_thru(mptsas_t *mpt, mptsas_pass_thru_t *data, int mode)
10120 {
10121         /*
10122          * If timeout is 0, set timeout to default of 60 seconds.
10123          */
10124         if (data->Timeout == 0) {
10125                 data->Timeout = MPTSAS_PASS_THRU_TIME_DEFAULT;
10126         }
10127 
10128         if (((data->DataSize == 0) &&
10129             (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_NONE)) ||
10130             ((data->DataSize != 0) &&
10131             ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_READ) ||
10132             (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_WRITE) ||
10133             ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) &&
10134             (data->DataOutSize != 0))))) {
10135                 if (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) {
10136                         data->DataDirection = MPTSAS_PASS_THRU_DIRECTION_READ;
10137                 } else {
10138                         data->DataOutSize = 0;
10139                 }
10140                 /*
10141                  * Send passthru request messages
10142                  */
10143                 return (mptsas_do_passthru(mpt,
10144                     (uint8_t *)((uintptr_t)data->PtrRequest),
10145                     (uint8_t *)((uintptr_t)data->PtrReply),
10146                     (uint8_t *)((uintptr_t)data->PtrData),
10147                     data->RequestSize, data->ReplySize,
10148                     data->DataSize, data->DataDirection,
10149                     (uint8_t *)((uintptr_t)data->PtrDataOut),
10150                     data->DataOutSize, data->Timeout, mode));
10151         } else {
10152                 return (EINVAL);
10153         }
10154 }
10155 
10156 static uint8_t
10157 mptsas_get_fw_diag_buffer_number(mptsas_t *mpt, uint32_t unique_id)
10158 {
10159         uint8_t index;
10160 
10161         for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
10162                 if (mpt->m_fw_diag_buffer_list[index].unique_id == unique_id) {
10163                         return (index);
10164                 }
10165         }
10166 
10167         return (MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND);
10168 }
10169 
10170 static void
10171 mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd)
10172 {
10173         pMpi2DiagBufferPostRequest_t    pDiag_post_msg;
10174         pMpi2DiagReleaseRequest_t       pDiag_release_msg;
10175         struct scsi_pkt                 *pkt = cmd->cmd_pkt;
10176         mptsas_diag_request_t           *diag = pkt->pkt_ha_private;
10177         uint32_t                        request_desc_low, i;
10178 
10179         ASSERT(mutex_owned(&mpt->m_mutex));
10180 
10181         /*
10182          * Form the diag message depending on the post or release function.
10183          */
10184         if (diag->function == MPI2_FUNCTION_DIAG_BUFFER_POST) {
10185                 pDiag_post_msg = (pMpi2DiagBufferPostRequest_t)
10186                     (mpt->m_req_frame + (mpt->m_req_frame_size *
10187                     cmd->cmd_slot));
10188                 bzero(pDiag_post_msg, mpt->m_req_frame_size);
10189                 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->Function,
10190                     diag->function);
10191                 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->BufferType,
10192                     diag->pBuffer->buffer_type);
10193                 ddi_put8(mpt->m_acc_req_frame_hdl,
10194                     &pDiag_post_msg->ExtendedType,
10195                     diag->pBuffer->extended_type);
10196                 ddi_put32(mpt->m_acc_req_frame_hdl,
10197                     &pDiag_post_msg->BufferLength,
10198                     diag->pBuffer->buffer_data.size);
10199                 for (i = 0; i < (sizeof (pDiag_post_msg->ProductSpecific) / 4);
10200                     i++) {
10201                         ddi_put32(mpt->m_acc_req_frame_hdl,
10202                             &pDiag_post_msg->ProductSpecific[i],
10203                             diag->pBuffer->product_specific[i]);
10204                 }
10205                 ddi_put32(mpt->m_acc_req_frame_hdl,
10206                     &pDiag_post_msg->BufferAddress.Low,
10207                     (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
10208                     & 0xffffffffull));
10209                 ddi_put32(mpt->m_acc_req_frame_hdl,
10210                     &pDiag_post_msg->BufferAddress.High,
10211                     (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
10212                     >> 32));
10213         } else {
10214                 pDiag_release_msg = (pMpi2DiagReleaseRequest_t)
10215                     (mpt->m_req_frame + (mpt->m_req_frame_size *
10216                     cmd->cmd_slot));
10217                 bzero(pDiag_release_msg, mpt->m_req_frame_size);
10218                 ddi_put8(mpt->m_acc_req_frame_hdl,
10219                     &pDiag_release_msg->Function, diag->function);
10220                 ddi_put8(mpt->m_acc_req_frame_hdl,
10221                     &pDiag_release_msg->BufferType,
10222                     diag->pBuffer->buffer_type);
10223         }
10224 
10225         /*
10226          * Send the message
10227          */
10228         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
10229             DDI_DMA_SYNC_FORDEV);
10230         request_desc_low = (cmd->cmd_slot << 16) +
10231             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
10232         cmd->cmd_rfm = NULL;
10233         MPTSAS_START_CMD(mpt, request_desc_low, 0);
10234         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
10235             DDI_SUCCESS) ||
10236             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
10237             DDI_SUCCESS)) {
10238                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
10239         }
10240 }
10241 
10242 static int
10243 mptsas_post_fw_diag_buffer(mptsas_t *mpt,
10244     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
10245 {
10246         mptsas_diag_request_t           diag;
10247         int                             status, slot_num, post_flags = 0;
10248         mptsas_cmd_t                    *cmd = NULL;
10249         struct scsi_pkt                 *pkt;
10250         pMpi2DiagBufferPostReply_t      reply;
10251         uint16_t                        iocstatus;
10252         uint32_t                        iocloginfo, transfer_length;
10253 
10254         /*
10255          * If buffer is not enabled, just leave.
10256          */
10257         *return_code = MPTSAS_FW_DIAG_ERROR_POST_FAILED;
10258         if (!pBuffer->enabled) {
10259                 status = DDI_FAILURE;
10260                 goto out;
10261         }
10262 
10263         /*
10264          * Clear some flags initially.
10265          */
10266         pBuffer->force_release = FALSE;
10267         pBuffer->valid_data = FALSE;
10268         pBuffer->owned_by_firmware = FALSE;
10269 
10270         /*
10271          * Get a cmd buffer from the cmd buffer pool
10272          */
10273         if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
10274                 status = DDI_FAILURE;
10275                 mptsas_log(mpt, CE_NOTE, "command pool is full: Post FW Diag");
10276                 goto out;
10277         }
10278         post_flags |= MPTSAS_REQUEST_POOL_CMD;
10279 
10280         bzero((caddr_t)cmd, sizeof (*cmd));
10281         bzero((caddr_t)pkt, scsi_pkt_size());
10282 
10283         cmd->ioc_cmd_slot = (uint32_t)(slot_num);
10284 
10285         diag.pBuffer = pBuffer;
10286         diag.function = MPI2_FUNCTION_DIAG_BUFFER_POST;
10287 
10288         /*
10289          * Form a blank cmd/pkt to store the acknowledgement message
10290          */
10291         pkt->pkt_ha_private  = (opaque_t)&diag;
10292         pkt->pkt_flags               = FLAG_HEAD;
10293         pkt->pkt_time                = 60;
10294         cmd->cmd_pkt         = pkt;
10295         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_DIAG;
10296 
10297         /*
10298          * Save the command in a slot
10299          */
10300         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
10301                 /*
10302                  * Once passthru command get slot, set cmd_flags
10303                  * CFLAG_PREPARED.
10304                  */
10305                 cmd->cmd_flags |= CFLAG_PREPARED;
10306                 mptsas_start_diag(mpt, cmd);
10307         } else {
10308                 mptsas_waitq_add(mpt, cmd);
10309         }
10310 
10311         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
10312                 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
10313         }
10314 
10315         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
10316                 status = DDI_FAILURE;
10317                 mptsas_log(mpt, CE_WARN, "Post FW Diag command timeout");
10318                 goto out;
10319         }
10320 
10321         /*
10322          * cmd_rfm points to the reply message if a reply was given.  Check the
10323          * IOCStatus to make sure everything went OK with the FW diag request
10324          * and set buffer flags.
10325          */
10326         if (cmd->cmd_rfm) {
10327                 post_flags |= MPTSAS_ADDRESS_REPLY;
10328                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
10329                     DDI_DMA_SYNC_FORCPU);
10330                 reply = (pMpi2DiagBufferPostReply_t)(mpt->m_reply_frame +
10331                     (cmd->cmd_rfm - mpt->m_reply_frame_dma_addr));
10332 
10333                 /*
10334                  * Get the reply message data
10335                  */
10336                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
10337                     &reply->IOCStatus);
10338                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
10339                     &reply->IOCLogInfo);
10340                 transfer_length = ddi_get32(mpt->m_acc_reply_frame_hdl,
10341                     &reply->TransferLength);
10342 
10343                 /*
10344                  * If post failed quit.
10345                  */
10346                 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
10347                         status = DDI_FAILURE;
10348                         NDBG13(("post FW Diag Buffer failed: IOCStatus=0x%x, "
10349                             "IOCLogInfo=0x%x, TransferLength=0x%x", iocstatus,
10350                             iocloginfo, transfer_length));
10351                         goto out;
10352                 }
10353 
10354                 /*
10355                  * Post was successful.
10356                  */
10357                 pBuffer->valid_data = TRUE;
10358                 pBuffer->owned_by_firmware = TRUE;
10359                 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
10360                 status = DDI_SUCCESS;
10361         }
10362 
10363 out:
10364         /*
10365          * Put the reply frame back on the free queue, increment the free
10366          * index, and write the new index to the free index register.  But only
10367          * if this reply is an ADDRESS reply.
10368          */
10369         if (post_flags & MPTSAS_ADDRESS_REPLY) {
10370                 ddi_put32(mpt->m_acc_free_queue_hdl,
10371                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
10372                     cmd->cmd_rfm);
10373                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
10374                     DDI_DMA_SYNC_FORDEV);
10375                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
10376                         mpt->m_free_index = 0;
10377                 }
10378                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
10379                     mpt->m_free_index);
10380         }
10381         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
10382                 mptsas_remove_cmd(mpt, cmd);
10383                 post_flags &= (~MPTSAS_REQUEST_POOL_CMD);
10384         }
10385         if (post_flags & MPTSAS_REQUEST_POOL_CMD) {
10386                 mptsas_return_to_pool(mpt, cmd);
10387         }
10388 
10389         return (status);
10390 }
10391 
10392 static int
10393 mptsas_release_fw_diag_buffer(mptsas_t *mpt,
10394     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
10395     uint32_t diag_type)
10396 {
10397         mptsas_diag_request_t   diag;
10398         int                     status, slot_num, rel_flags = 0;
10399         mptsas_cmd_t            *cmd = NULL;
10400         struct scsi_pkt         *pkt;
10401         pMpi2DiagReleaseReply_t reply;
10402         uint16_t                iocstatus;
10403         uint32_t                iocloginfo;
10404 
10405         /*
10406          * If buffer is not enabled, just leave.
10407          */
10408         *return_code = MPTSAS_FW_DIAG_ERROR_RELEASE_FAILED;
10409         if (!pBuffer->enabled) {
10410                 mptsas_log(mpt, CE_NOTE, "This buffer type is not supported "
10411                     "by the IOC");
10412                 status = DDI_FAILURE;
10413                 goto out;
10414         }
10415 
10416         /*
10417          * Clear some flags initially.
10418          */
10419         pBuffer->force_release = FALSE;
10420         pBuffer->valid_data = FALSE;
10421         pBuffer->owned_by_firmware = FALSE;
10422 
10423         /*
10424          * Get a cmd buffer from the cmd buffer pool
10425          */
10426         if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
10427                 status = DDI_FAILURE;
10428                 mptsas_log(mpt, CE_NOTE, "command pool is full: Release FW "
10429                     "Diag");
10430                 goto out;
10431         }
10432         rel_flags |= MPTSAS_REQUEST_POOL_CMD;
10433 
10434         bzero((caddr_t)cmd, sizeof (*cmd));
10435         bzero((caddr_t)pkt, scsi_pkt_size());
10436 
10437         cmd->ioc_cmd_slot = (uint32_t)(slot_num);
10438 
10439         diag.pBuffer = pBuffer;
10440         diag.function = MPI2_FUNCTION_DIAG_RELEASE;
10441 
10442         /*
10443          * Form a blank cmd/pkt to store the acknowledgement message
10444          */
10445         pkt->pkt_ha_private  = (opaque_t)&diag;
10446         pkt->pkt_flags               = FLAG_HEAD;
10447         pkt->pkt_time                = 60;
10448         cmd->cmd_pkt         = pkt;
10449         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_DIAG;
10450 
10451         /*
10452          * Save the command in a slot
10453          */
10454         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
10455                 /*
10456                  * Once passthru command get slot, set cmd_flags
10457                  * CFLAG_PREPARED.
10458                  */
10459                 cmd->cmd_flags |= CFLAG_PREPARED;
10460                 mptsas_start_diag(mpt, cmd);
10461         } else {
10462                 mptsas_waitq_add(mpt, cmd);
10463         }
10464 
10465         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
10466                 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
10467         }
10468 
10469         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
10470                 status = DDI_FAILURE;
10471                 mptsas_log(mpt, CE_WARN, "Release FW Diag command timeout");
10472                 goto out;
10473         }
10474 
10475         /*
10476          * cmd_rfm points to the reply message if a reply was given.  Check the
10477          * IOCStatus to make sure everything went OK with the FW diag request
10478          * and set buffer flags.
10479          */
10480         if (cmd->cmd_rfm) {
10481                 rel_flags |= MPTSAS_ADDRESS_REPLY;
10482                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
10483                     DDI_DMA_SYNC_FORCPU);
10484                 reply = (pMpi2DiagReleaseReply_t)(mpt->m_reply_frame +
10485                     (cmd->cmd_rfm - mpt->m_reply_frame_dma_addr));
10486 
10487                 /*
10488                  * Get the reply message data
10489                  */
10490                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
10491                     &reply->IOCStatus);
10492                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
10493                     &reply->IOCLogInfo);
10494 
10495                 /*
10496                  * If release failed quit.
10497                  */
10498                 if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) ||
10499                     pBuffer->owned_by_firmware) {
10500                         status = DDI_FAILURE;
10501                         NDBG13(("release FW Diag Buffer failed: "
10502                             "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
10503                             iocloginfo));
10504                         goto out;
10505                 }
10506 
10507                 /*
10508                  * Release was successful.
10509                  */
10510                 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
10511                 status = DDI_SUCCESS;
10512 
10513                 /*
10514                  * If this was for an UNREGISTER diag type command, clear the
10515                  * unique ID.
10516                  */
10517                 if (diag_type == MPTSAS_FW_DIAG_TYPE_UNREGISTER) {
10518                         pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
10519                 }
10520         }
10521 
10522 out:
10523         /*
10524          * Put the reply frame back on the free queue, increment the free
10525          * index, and write the new index to the free index register.  But only
10526          * if this reply is an ADDRESS reply.
10527          */
10528         if (rel_flags & MPTSAS_ADDRESS_REPLY) {
10529                 ddi_put32(mpt->m_acc_free_queue_hdl,
10530                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
10531                     cmd->cmd_rfm);
10532                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
10533                     DDI_DMA_SYNC_FORDEV);
10534                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
10535                         mpt->m_free_index = 0;
10536                 }
10537                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
10538                     mpt->m_free_index);
10539         }
10540         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
10541                 mptsas_remove_cmd(mpt, cmd);
10542                 rel_flags &= (~MPTSAS_REQUEST_POOL_CMD);
10543         }
10544         if (rel_flags & MPTSAS_REQUEST_POOL_CMD) {
10545                 mptsas_return_to_pool(mpt, cmd);
10546         }
10547 
10548         return (status);
10549 }
10550 
10551 static int
10552 mptsas_diag_register(mptsas_t *mpt, mptsas_fw_diag_register_t *diag_register,
10553     uint32_t *return_code)
10554 {
10555         mptsas_fw_diagnostic_buffer_t   *pBuffer;
10556         uint8_t                         extended_type, buffer_type, i;
10557         uint32_t                        buffer_size;
10558         uint32_t                        unique_id;
10559         int                             status;
10560 
10561         ASSERT(mutex_owned(&mpt->m_mutex));
10562 
10563         extended_type = diag_register->ExtendedType;
10564         buffer_type = diag_register->BufferType;
10565         buffer_size = diag_register->RequestedBufferSize;
10566         unique_id = diag_register->UniqueId;
10567 
10568         /*
10569          * Check for valid buffer type
10570          */
10571         if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) {
10572                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10573                 return (DDI_FAILURE);
10574         }
10575 
10576         /*
10577          * Get the current buffer and look up the unique ID.  The unique ID
10578          * should not be found.  If it is, the ID is already in use.
10579          */
10580         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10581         pBuffer = &mpt->m_fw_diag_buffer_list[buffer_type];
10582         if (i != MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10583                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10584                 return (DDI_FAILURE);
10585         }
10586 
10587         /*
10588          * The buffer's unique ID should not be registered yet, and the given
10589          * unique ID cannot be 0.
10590          */
10591         if ((pBuffer->unique_id != MPTSAS_FW_DIAG_INVALID_UID) ||
10592             (unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
10593                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10594                 return (DDI_FAILURE);
10595         }
10596 
10597         /*
10598          * If this buffer is already posted as immediate, just change owner.
10599          */
10600         if (pBuffer->immediate && pBuffer->owned_by_firmware &&
10601             (pBuffer->unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
10602                 pBuffer->immediate = FALSE;
10603                 pBuffer->unique_id = unique_id;
10604                 return (DDI_SUCCESS);
10605         }
10606 
10607         /*
10608          * Post a new buffer after checking if it's enabled.  The DMA buffer
10609          * that is allocated will be contiguous (sgl_len = 1).
10610          */
10611         if (!pBuffer->enabled) {
10612                 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
10613                 return (DDI_FAILURE);
10614         }
10615         bzero(&pBuffer->buffer_data, sizeof (mptsas_dma_alloc_state_t));
10616         pBuffer->buffer_data.size = buffer_size;
10617         if (mptsas_dma_alloc(mpt, &pBuffer->buffer_data) != DDI_SUCCESS) {
10618                 mptsas_log(mpt, CE_WARN, "failed to alloc DMA resource for "
10619                     "diag buffer: size = %d bytes", buffer_size);
10620                 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
10621                 return (DDI_FAILURE);
10622         }
10623 
10624         /*
10625          * Copy the given info to the diag buffer and post the buffer.
10626          */
10627         pBuffer->buffer_type = buffer_type;
10628         pBuffer->immediate = FALSE;
10629         if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) {
10630                 for (i = 0; i < (sizeof (pBuffer->product_specific) / 4);
10631                     i++) {
10632                         pBuffer->product_specific[i] =
10633                             diag_register->ProductSpecific[i];
10634                 }
10635         }
10636         pBuffer->extended_type = extended_type;
10637         pBuffer->unique_id = unique_id;
10638         status = mptsas_post_fw_diag_buffer(mpt, pBuffer, return_code);
10639 
10640         if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
10641             DDI_SUCCESS) {
10642                 mptsas_log(mpt, CE_WARN, "Check of DMA handle failed in "
10643                     "mptsas_diag_register.");
10644                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
10645                         status = DDI_FAILURE;
10646         }
10647 
10648         /*
10649          * In case there was a failure, free the DMA buffer.
10650          */
10651         if (status == DDI_FAILURE) {
10652                 mptsas_dma_free(&pBuffer->buffer_data);
10653         }
10654 
10655         return (status);
10656 }
10657 
10658 static int
10659 mptsas_diag_unregister(mptsas_t *mpt,
10660     mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
10661 {
10662         mptsas_fw_diagnostic_buffer_t   *pBuffer;
10663         uint8_t                         i;
10664         uint32_t                        unique_id;
10665         int                             status;
10666 
10667         ASSERT(mutex_owned(&mpt->m_mutex));
10668 
10669         unique_id = diag_unregister->UniqueId;
10670 
10671         /*
10672          * Get the current buffer and look up the unique ID.  The unique ID
10673          * should be there.
10674          */
10675         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10676         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10677                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10678                 return (DDI_FAILURE);
10679         }
10680 
10681         pBuffer = &mpt->m_fw_diag_buffer_list[i];
10682 
10683         /*
10684          * Try to release the buffer from FW before freeing it.  If release
10685          * fails, don't free the DMA buffer in case FW tries to access it
10686          * later.  If buffer is not owned by firmware, can't release it.
10687          */
10688         if (!pBuffer->owned_by_firmware) {
10689                 status = DDI_SUCCESS;
10690         } else {
10691                 status = mptsas_release_fw_diag_buffer(mpt, pBuffer,
10692                     return_code, MPTSAS_FW_DIAG_TYPE_UNREGISTER);
10693         }
10694 
10695         /*
10696          * At this point, return the current status no matter what happens with
10697          * the DMA buffer.
10698          */
10699         pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
10700         if (status == DDI_SUCCESS) {
10701                 if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
10702                     DDI_SUCCESS) {
10703                         mptsas_log(mpt, CE_WARN, "Check of DMA handle failed "
10704                             "in mptsas_diag_unregister.");
10705                         ddi_fm_service_impact(mpt->m_dip,
10706                             DDI_SERVICE_UNAFFECTED);
10707                 }
10708                 mptsas_dma_free(&pBuffer->buffer_data);
10709         }
10710 
10711         return (status);
10712 }
10713 
10714 static int
10715 mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
10716     uint32_t *return_code)
10717 {
10718         mptsas_fw_diagnostic_buffer_t   *pBuffer;
10719         uint8_t                         i;
10720         uint32_t                        unique_id;
10721 
10722         ASSERT(mutex_owned(&mpt->m_mutex));
10723 
10724         unique_id = diag_query->UniqueId;
10725 
10726         /*
10727          * If ID is valid, query on ID.
10728          * If ID is invalid, query on buffer type.
10729          */
10730         if (unique_id == MPTSAS_FW_DIAG_INVALID_UID) {
10731                 i = diag_query->BufferType;
10732                 if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
10733                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10734                         return (DDI_FAILURE);
10735                 }
10736         } else {
10737                 i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10738                 if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10739                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10740                         return (DDI_FAILURE);
10741                 }
10742         }
10743 
10744         /*
10745          * Fill query structure with the diag buffer info.
10746          */
10747         pBuffer = &mpt->m_fw_diag_buffer_list[i];
10748         diag_query->BufferType = pBuffer->buffer_type;
10749         diag_query->ExtendedType = pBuffer->extended_type;
10750         if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) {
10751                 for (i = 0; i < (sizeof (diag_query->ProductSpecific) / 4);
10752                     i++) {
10753                         diag_query->ProductSpecific[i] =
10754                             pBuffer->product_specific[i];
10755                 }
10756         }
10757         diag_query->TotalBufferSize = pBuffer->buffer_data.size;
10758         diag_query->DriverAddedBufferSize = 0;
10759         diag_query->UniqueId = pBuffer->unique_id;
10760         diag_query->ApplicationFlags = 0;
10761         diag_query->DiagnosticFlags = 0;
10762 
10763         /*
10764          * Set/Clear application flags
10765          */
10766         if (pBuffer->immediate) {
10767                 diag_query->ApplicationFlags &= ~MPTSAS_FW_DIAG_FLAG_APP_OWNED;
10768         } else {
10769                 diag_query->ApplicationFlags |= MPTSAS_FW_DIAG_FLAG_APP_OWNED;
10770         }
10771         if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
10772                 diag_query->ApplicationFlags |=
10773                     MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
10774         } else {
10775                 diag_query->ApplicationFlags &=
10776                     ~MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
10777         }
10778         if (pBuffer->owned_by_firmware) {
10779                 diag_query->ApplicationFlags |=
10780                     MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
10781         } else {
10782                 diag_query->ApplicationFlags &=
10783                     ~MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
10784         }
10785 
10786         return (DDI_SUCCESS);
10787 }
10788 
10789 static int
10790 mptsas_diag_read_buffer(mptsas_t *mpt,
10791     mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
10792     uint32_t *return_code, int ioctl_mode)
10793 {
10794         mptsas_fw_diagnostic_buffer_t   *pBuffer;
10795         uint8_t                         i, *pData;
10796         uint32_t                        unique_id, byte;
10797         int                             status;
10798 
10799         ASSERT(mutex_owned(&mpt->m_mutex));
10800 
10801         unique_id = diag_read_buffer->UniqueId;
10802 
10803         /*
10804          * Get the current buffer and look up the unique ID.  The unique ID
10805          * should be there.
10806          */
10807         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10808         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10809                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10810                 return (DDI_FAILURE);
10811         }
10812 
10813         pBuffer = &mpt->m_fw_diag_buffer_list[i];
10814 
10815         /*
10816          * Make sure requested read is within limits
10817          */
10818         if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
10819             pBuffer->buffer_data.size) {
10820                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10821                 return (DDI_FAILURE);
10822         }
10823 
10824         /*
10825          * Copy the requested data from DMA to the diag_read_buffer.  The DMA
10826          * buffer that was allocated is one contiguous buffer.
10827          */
10828         pData = (uint8_t *)(pBuffer->buffer_data.memp +
10829             diag_read_buffer->StartingOffset);
10830         (void) ddi_dma_sync(pBuffer->buffer_data.handle, 0, 0,
10831             DDI_DMA_SYNC_FORCPU);
10832         for (byte = 0; byte < diag_read_buffer->BytesToRead; byte++) {
10833                 if (ddi_copyout(pData + byte, ioctl_buf + byte, 1, ioctl_mode)
10834                     != 0) {
10835                         return (DDI_FAILURE);
10836                 }
10837         }
10838         diag_read_buffer->Status = 0;
10839 
10840         /*
10841          * Set or clear the Force Release flag.
10842          */
10843         if (pBuffer->force_release) {
10844                 diag_read_buffer->Flags |= MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
10845         } else {
10846                 diag_read_buffer->Flags &= ~MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
10847         }
10848 
10849         /*
10850          * If buffer is to be reregistered, make sure it's not already owned by
10851          * firmware first.
10852          */
10853         status = DDI_SUCCESS;
10854         if (!pBuffer->owned_by_firmware) {
10855                 if (diag_read_buffer->Flags & MPTSAS_FW_DIAG_FLAG_REREGISTER) {
10856                         status = mptsas_post_fw_diag_buffer(mpt, pBuffer,
10857                             return_code);
10858                 }
10859         }
10860 
10861         return (status);
10862 }
10863 
10864 static int
10865 mptsas_diag_release(mptsas_t *mpt, mptsas_fw_diag_release_t *diag_release,
10866     uint32_t *return_code)
10867 {
10868         mptsas_fw_diagnostic_buffer_t   *pBuffer;
10869         uint8_t                         i;
10870         uint32_t                        unique_id;
10871         int                             status;
10872 
10873         ASSERT(mutex_owned(&mpt->m_mutex));
10874 
10875         unique_id = diag_release->UniqueId;
10876 
10877         /*
10878          * Get the current buffer and look up the unique ID.  The unique ID
10879          * should be there.
10880          */
10881         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10882         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10883                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10884                 return (DDI_FAILURE);
10885         }
10886 
10887         pBuffer = &mpt->m_fw_diag_buffer_list[i];
10888 
10889         /*
10890          * If buffer is not owned by firmware, it's already been released.
10891          */
10892         if (!pBuffer->owned_by_firmware) {
10893                 *return_code = MPTSAS_FW_DIAG_ERROR_ALREADY_RELEASED;
10894                 return (DDI_FAILURE);
10895         }
10896 
10897         /*
10898          * Release the buffer.
10899          */
10900         status = mptsas_release_fw_diag_buffer(mpt, pBuffer, return_code,
10901             MPTSAS_FW_DIAG_TYPE_RELEASE);
10902         return (status);
10903 }
10904 
10905 static int
10906 mptsas_do_diag_action(mptsas_t *mpt, uint32_t action, uint8_t *diag_action,
10907     uint32_t length, uint32_t *return_code, int ioctl_mode)
10908 {
10909         mptsas_fw_diag_register_t       diag_register;
10910         mptsas_fw_diag_unregister_t     diag_unregister;
10911         mptsas_fw_diag_query_t          diag_query;
10912         mptsas_diag_read_buffer_t       diag_read_buffer;
10913         mptsas_fw_diag_release_t        diag_release;
10914         int                             status = DDI_SUCCESS;
10915         uint32_t                        original_return_code, read_buf_len;
10916 
10917         ASSERT(mutex_owned(&mpt->m_mutex));
10918 
10919         original_return_code = *return_code;
10920         *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
10921 
10922         switch (action) {
10923                 case MPTSAS_FW_DIAG_TYPE_REGISTER:
10924                         if (!length) {
10925                                 *return_code =
10926                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10927                                 status = DDI_FAILURE;
10928                                 break;
10929                         }
10930                         if (ddi_copyin(diag_action, &diag_register,
10931                             sizeof (diag_register), ioctl_mode) != 0) {
10932                                 return (DDI_FAILURE);
10933                         }
10934                         status = mptsas_diag_register(mpt, &diag_register,
10935                             return_code);
10936                         break;
10937 
10938                 case MPTSAS_FW_DIAG_TYPE_UNREGISTER:
10939                         if (length < sizeof (diag_unregister)) {
10940                                 *return_code =
10941                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10942                                 status = DDI_FAILURE;
10943                                 break;
10944                         }
10945                         if (ddi_copyin(diag_action, &diag_unregister,
10946                             sizeof (diag_unregister), ioctl_mode) != 0) {
10947                                 return (DDI_FAILURE);
10948                         }
10949                         status = mptsas_diag_unregister(mpt, &diag_unregister,
10950                             return_code);
10951                         break;
10952 
10953                 case MPTSAS_FW_DIAG_TYPE_QUERY:
10954                         if (length < sizeof (diag_query)) {
10955                                 *return_code =
10956                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10957                                 status = DDI_FAILURE;
10958                                 break;
10959                         }
10960                         if (ddi_copyin(diag_action, &diag_query,
10961                             sizeof (diag_query), ioctl_mode) != 0) {
10962                                 return (DDI_FAILURE);
10963                         }
10964                         status = mptsas_diag_query(mpt, &diag_query,
10965                             return_code);
10966                         if (status == DDI_SUCCESS) {
10967                                 if (ddi_copyout(&diag_query, diag_action,
10968                                     sizeof (diag_query), ioctl_mode) != 0) {
10969                                         return (DDI_FAILURE);
10970                                 }
10971                         }
10972                         break;
10973 
10974                 case MPTSAS_FW_DIAG_TYPE_READ_BUFFER:
10975                         if (ddi_copyin(diag_action, &diag_read_buffer,
10976                             sizeof (diag_read_buffer) - 4, ioctl_mode) != 0) {
10977                                 return (DDI_FAILURE);
10978                         }
10979                         read_buf_len = sizeof (diag_read_buffer) -
10980                             sizeof (diag_read_buffer.DataBuffer) +
10981                             diag_read_buffer.BytesToRead;
10982                         if (length < read_buf_len) {
10983                                 *return_code =
10984                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10985                                 status = DDI_FAILURE;
10986                                 break;
10987                         }
10988                         status = mptsas_diag_read_buffer(mpt,
10989                             &diag_read_buffer, diag_action +
10990                             sizeof (diag_read_buffer) - 4, return_code,
10991                             ioctl_mode);
10992                         if (status == DDI_SUCCESS) {
10993                                 if (ddi_copyout(&diag_read_buffer, diag_action,
10994                                     sizeof (diag_read_buffer) - 4, ioctl_mode)
10995                                     != 0) {
10996                                         return (DDI_FAILURE);
10997                                 }
10998                         }
10999                         break;
11000 
11001                 case MPTSAS_FW_DIAG_TYPE_RELEASE:
11002                         if (length < sizeof (diag_release)) {
11003                                 *return_code =
11004                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11005                                 status = DDI_FAILURE;
11006                                 break;
11007                         }
11008                         if (ddi_copyin(diag_action, &diag_release,
11009                             sizeof (diag_release), ioctl_mode) != 0) {
11010                                 return (DDI_FAILURE);
11011                         }
11012                         status = mptsas_diag_release(mpt, &diag_release,
11013                             return_code);
11014                         break;
11015 
11016                 default:
11017                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11018                         status = DDI_FAILURE;
11019                         break;
11020         }
11021 
11022         if ((status == DDI_FAILURE) &&
11023             (original_return_code == MPTSAS_FW_DIAG_NEW) &&
11024             (*return_code != MPTSAS_FW_DIAG_ERROR_SUCCESS)) {
11025                 status = DDI_SUCCESS;
11026         }
11027 
11028         return (status);
11029 }
11030 
11031 static int
11032 mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *user_data, int mode)
11033 {
11034         int                     status;
11035         mptsas_diag_action_t    driver_data;
11036 
11037         ASSERT(mutex_owned(&mpt->m_mutex));
11038 
11039         /*
11040          * Copy the user data to a driver data buffer.
11041          */
11042         if (ddi_copyin(user_data, &driver_data, sizeof (mptsas_diag_action_t),
11043             mode) == 0) {
11044                 /*
11045                  * Send diag action request if Action is valid
11046                  */
11047                 if (driver_data.Action == MPTSAS_FW_DIAG_TYPE_REGISTER ||
11048                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_UNREGISTER ||
11049                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_QUERY ||
11050                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_READ_BUFFER ||
11051                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_RELEASE) {
11052                         status = mptsas_do_diag_action(mpt, driver_data.Action,
11053                             (void *)(uintptr_t)driver_data.PtrDiagAction,
11054                             driver_data.Length, &driver_data.ReturnCode,
11055                             mode);
11056                         if (status == DDI_SUCCESS) {
11057                                 if (ddi_copyout(&driver_data.ReturnCode,
11058                                     &user_data->ReturnCode,
11059                                     sizeof (user_data->ReturnCode), mode)
11060                                     != 0) {
11061                                         status = EFAULT;
11062                                 } else {
11063                                         status = 0;
11064                                 }
11065                         } else {
11066                                 status = EIO;
11067                         }
11068                 } else {
11069                         status = EINVAL;
11070                 }
11071         } else {
11072                 status = EFAULT;
11073         }
11074 
11075         return (status);
11076 }
11077 
11078 /*
11079  * This routine handles the "event query" ioctl.
11080  */
11081 static int
11082 mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data, int mode,
11083     int *rval)
11084 {
11085         int                     status;
11086         mptsas_event_query_t    driverdata;
11087         uint8_t                 i;
11088 
11089         driverdata.Entries = MPTSAS_EVENT_QUEUE_SIZE;
11090 
11091         mutex_enter(&mpt->m_mutex);
11092         for (i = 0; i < 4; i++) {
11093                 driverdata.Types[i] = mpt->m_event_mask[i];
11094         }
11095         mutex_exit(&mpt->m_mutex);
11096 
11097         if (ddi_copyout(&driverdata, data, sizeof (driverdata), mode) != 0) {
11098                 status = EFAULT;
11099         } else {
11100                 *rval = MPTIOCTL_STATUS_GOOD;
11101                 status = 0;
11102         }
11103 
11104         return (status);
11105 }
11106 
11107 /*
11108  * This routine handles the "event enable" ioctl.
11109  */
11110 static int
11111 mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data, int mode,
11112     int *rval)
11113 {
11114         int                     status;
11115         mptsas_event_enable_t   driverdata;
11116         uint8_t                 i;
11117 
11118         if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
11119                 mutex_enter(&mpt->m_mutex);
11120                 for (i = 0; i < 4; i++) {
11121                         mpt->m_event_mask[i] = driverdata.Types[i];
11122                 }
11123                 mutex_exit(&mpt->m_mutex);
11124 
11125                 *rval = MPTIOCTL_STATUS_GOOD;
11126                 status = 0;
11127         } else {
11128                 status = EFAULT;
11129         }
11130         return (status);
11131 }
11132 
11133 /*
11134  * This routine handles the "event report" ioctl.
11135  */
11136 static int
11137 mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data, int mode,
11138     int *rval)
11139 {
11140         int                     status;
11141         mptsas_event_report_t   driverdata;
11142 
11143         mutex_enter(&mpt->m_mutex);
11144 
11145         if (ddi_copyin(&data->Size, &driverdata.Size, sizeof (driverdata.Size),
11146             mode) == 0) {
11147                 if (driverdata.Size >= sizeof (mpt->m_events)) {
11148                         if (ddi_copyout(mpt->m_events, data->Events,
11149                             sizeof (mpt->m_events), mode) != 0) {
11150                                 status = EFAULT;
11151                         } else {
11152                                 if (driverdata.Size > sizeof (mpt->m_events)) {
11153                                         driverdata.Size =
11154                                             sizeof (mpt->m_events);
11155                                         if (ddi_copyout(&driverdata.Size,
11156                                             &data->Size,
11157                                             sizeof (driverdata.Size),
11158                                             mode) != 0) {
11159                                                 status = EFAULT;
11160                                         } else {
11161                                                 *rval = MPTIOCTL_STATUS_GOOD;
11162                                                 status = 0;
11163                                         }
11164                                 } else {
11165                                         *rval = MPTIOCTL_STATUS_GOOD;
11166                                         status = 0;
11167                                 }
11168                         }
11169                 } else {
11170                         *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
11171                         status = 0;
11172                 }
11173         } else {
11174                 status = EFAULT;
11175         }
11176 
11177         mutex_exit(&mpt->m_mutex);
11178         return (status);
11179 }
11180 
11181 static void
11182 mptsas_lookup_pci_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
11183 {
11184         int     *reg_data;
11185         uint_t  reglen;
11186 
11187         /*
11188          * Lookup the 'reg' property and extract the other data
11189          */
11190         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
11191             DDI_PROP_DONTPASS, "reg", &reg_data, &reglen) ==
11192             DDI_PROP_SUCCESS) {
11193                 /*
11194                  * Extract the PCI data from the 'reg' property first DWORD.
11195                  * The entry looks like the following:
11196                  * First DWORD:
11197                  * Bits 0 - 7 8-bit Register number
11198                  * Bits 8 - 10 3-bit Function number
11199                  * Bits 11 - 15 5-bit Device number
11200                  * Bits 16 - 23 8-bit Bus number
11201                  * Bits 24 - 25 2-bit Address Space type identifier
11202                  *
11203                  */
11204                 adapter_data->PciInformation.u.bits.BusNumber =
11205                     (reg_data[0] & 0x00FF0000) >> 16;
11206                 adapter_data->PciInformation.u.bits.DeviceNumber =
11207                     (reg_data[0] & 0x0000F800) >> 11;
11208                 adapter_data->PciInformation.u.bits.FunctionNumber =
11209                     (reg_data[0] & 0x00000700) >> 8;
11210                 ddi_prop_free((void *)reg_data);
11211         } else {
11212                 /*
11213                  * If we can't determine the PCI data then we fill in FF's for
11214                  * the data to indicate this.
11215                  */
11216                 adapter_data->PCIDeviceHwId = 0xFFFFFFFF;
11217                 adapter_data->MpiPortNumber = 0xFFFFFFFF;
11218                 adapter_data->PciInformation.u.AsDWORD = 0xFFFFFFFF;
11219         }
11220 
11221         /*
11222          * Saved in the mpt->m_fwversion
11223          */
11224         adapter_data->MpiFirmwareVersion = mpt->m_fwversion;
11225 }
11226 
11227 static void
11228 mptsas_read_adapter_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
11229 {
11230         char    *driver_verstr = MPTSAS_MOD_STRING;
11231 
11232         mptsas_lookup_pci_data(mpt, adapter_data);
11233         adapter_data->AdapterType = MPTIOCTL_ADAPTER_TYPE_SAS2;
11234         adapter_data->PCIDeviceHwId = (uint32_t)mpt->m_devid;
11235         adapter_data->PCIDeviceHwRev = (uint32_t)mpt->m_revid;
11236         adapter_data->SubSystemId = (uint32_t)mpt->m_ssid;
11237         adapter_data->SubsystemVendorId = (uint32_t)mpt->m_svid;
11238         (void) strcpy((char *)&adapter_data->DriverVersion[0], driver_verstr);
11239         adapter_data->BiosVersion = 0;
11240         (void) mptsas_get_bios_page3(mpt, &adapter_data->BiosVersion);
11241 }
11242 
11243 static void
11244 mptsas_read_pci_info(mptsas_t *mpt, mptsas_pci_info_t *pci_info)
11245 {
11246         int     *reg_data, i;
11247         uint_t  reglen;
11248 
11249         /*
11250          * Lookup the 'reg' property and extract the other data
11251          */
11252         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
11253             DDI_PROP_DONTPASS, "reg", &reg_data, &reglen) ==
11254             DDI_PROP_SUCCESS) {
11255                 /*
11256                  * Extract the PCI data from the 'reg' property first DWORD.
11257                  * The entry looks like the following:
11258                  * First DWORD:
11259                  * Bits 8 - 10 3-bit Function number
11260                  * Bits 11 - 15 5-bit Device number
11261                  * Bits 16 - 23 8-bit Bus number
11262                  */
11263                 pci_info->BusNumber = (reg_data[0] & 0x00FF0000) >> 16;
11264                 pci_info->DeviceNumber = (reg_data[0] & 0x0000F800) >> 11;
11265                 pci_info->FunctionNumber = (reg_data[0] & 0x00000700) >> 8;
11266                 ddi_prop_free((void *)reg_data);
11267         } else {
11268                 /*
11269                  * If we can't determine the PCI info then we fill in FF's for
11270                  * the data to indicate this.
11271                  */
11272                 pci_info->BusNumber = 0xFFFFFFFF;
11273                 pci_info->DeviceNumber = 0xFF;
11274                 pci_info->FunctionNumber = 0xFF;
11275         }
11276 
11277         /*
11278          * Now get the interrupt vector and the pci header.  The vector can
11279          * only be 0 right now.  The header is the first 256 bytes of config
11280          * space.
11281          */
11282         pci_info->InterruptVector = 0;
11283         for (i = 0; i < sizeof (pci_info->PciHeader); i++) {
11284                 pci_info->PciHeader[i] = pci_config_get8(mpt->m_config_handle,
11285                     i);
11286         }
11287 }
11288 
11289 static int
11290 mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data, int mode)
11291 {
11292         int                     status = 0;
11293         mptsas_reg_access_t     driverdata;
11294 
11295         mutex_enter(&mpt->m_mutex);
11296         if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
11297                 switch (driverdata.Command) {
11298                         /*
11299                          * IO access is not supported.
11300                          */
11301                         case REG_IO_READ:
11302                         case REG_IO_WRITE:
11303                                 mptsas_log(mpt, CE_WARN, "IO access is not "
11304                                     "supported.  Use memory access.");
11305                                 status = EINVAL;
11306                                 break;
11307 
11308                         case REG_MEM_READ:
11309                                 driverdata.RegData = ddi_get32(mpt->m_datap,
11310                                     (uint32_t *)(void *)mpt->m_reg +
11311                                     driverdata.RegOffset);
11312                                 if (ddi_copyout(&driverdata.RegData,
11313                                     &data->RegData,
11314                                     sizeof (driverdata.RegData), mode) != 0) {
11315                                         mptsas_log(mpt, CE_WARN, "Register "
11316                                             "Read Failed");
11317                                         status = EFAULT;
11318                                 }
11319                                 break;
11320 
11321                         case REG_MEM_WRITE:
11322                                 ddi_put32(mpt->m_datap,
11323                                     (uint32_t *)(void *)mpt->m_reg +
11324                                     driverdata.RegOffset,
11325                                     driverdata.RegData);
11326                                 break;
11327 
11328                         default:
11329                                 status = EINVAL;
11330                                 break;
11331                 }
11332         } else {
11333                 status = EFAULT;
11334         }
11335 
11336         mutex_exit(&mpt->m_mutex);
11337         return (status);
11338 }
11339 
11340 static int
11341 led_control(mptsas_t *mpt, intptr_t data, int mode)
11342 {
11343         int ret = 0;
11344         mptsas_led_control_t lc;
11345         mptsas_target_t *ptgt;
11346 
11347         if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) {
11348                 return (EFAULT);
11349         }
11350 
11351         if ((lc.Command != MPTSAS_LEDCTL_FLAG_SET &&
11352             lc.Command != MPTSAS_LEDCTL_FLAG_GET) ||
11353             lc.Led < MPTSAS_LEDCTL_LED_MIN ||
11354             lc.Led > MPTSAS_LEDCTL_LED_MAX ||
11355             (lc.Command == MPTSAS_LEDCTL_FLAG_SET && lc.LedStatus != 0 &&
11356             lc.LedStatus != 1)) {
11357                 return (EINVAL);
11358         }
11359 
11360         if ((lc.Command == MPTSAS_LEDCTL_FLAG_SET && (mode & FWRITE) == 0) ||
11361             (lc.Command == MPTSAS_LEDCTL_FLAG_GET && (mode & FREAD) == 0))
11362                 return (EACCES);
11363 
11364         /* Locate the target we're interrogating... */
11365         mutex_enter(&mpt->m_mutex);
11366         ptgt = refhash_linear_search(mpt->m_targets,
11367             mptsas_target_eval_slot, &lc);
11368         if (ptgt == NULL) {
11369                 /* We could not find a target for that enclosure/slot. */
11370                 mutex_exit(&mpt->m_mutex);
11371                 return (ENOENT);
11372         }
11373 
11374         if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) {
11375                 /* Update our internal LED state. */
11376                 ptgt->m_led_status &= ~(1 << (lc.Led - 1));
11377                 ptgt->m_led_status |= lc.LedStatus << (lc.Led - 1);
11378 
11379                 /* Flush it to the controller. */
11380                 ret = mptsas_flush_led_status(mpt, ptgt);
11381                 mutex_exit(&mpt->m_mutex);
11382                 return (ret);
11383         }
11384 
11385         /* Return our internal LED state. */
11386         lc.LedStatus = (ptgt->m_led_status >> (lc.Led - 1)) & 1;
11387         mutex_exit(&mpt->m_mutex);
11388 
11389         if (ddi_copyout(&lc, (void *)data, sizeof (lc), mode) != 0) {
11390                 return (EFAULT);
11391         }
11392 
11393         return (0);
11394 }
11395 
11396 static int
11397 get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
11398 {
11399         uint16_t i = 0;
11400         uint16_t count = 0;
11401         int ret = 0;
11402         mptsas_target_t *ptgt;
11403         mptsas_disk_info_t *di;
11404         STRUCT_DECL(mptsas_get_disk_info, gdi);
11405 
11406         if ((mode & FREAD) == 0)
11407                 return (EACCES);
11408 
11409         STRUCT_INIT(gdi, get_udatamodel());
11410 
11411         if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi),
11412             mode) != 0) {
11413                 return (EFAULT);
11414         }
11415 
11416         /* Find out how many targets there are. */
11417         mutex_enter(&mpt->m_mutex);
11418         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11419             ptgt = refhash_next(mpt->m_targets, ptgt)) {
11420                 count++;
11421         }
11422         mutex_exit(&mpt->m_mutex);
11423 
11424         /*
11425          * If we haven't been asked to copy out information on each target,
11426          * then just return the count.
11427          */
11428         STRUCT_FSET(gdi, DiskCount, count);
11429         if (STRUCT_FGETP(gdi, PtrDiskInfoArray) == NULL)
11430                 goto copy_out;
11431 
11432         /*
11433          * If we haven't been given a large enough buffer to copy out into,
11434          * let the caller know.
11435          */
11436         if (STRUCT_FGET(gdi, DiskInfoArraySize) <
11437             count * sizeof (mptsas_disk_info_t)) {
11438                 ret = ENOSPC;
11439                 goto copy_out;
11440         }
11441 
11442         di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP);
11443 
11444         mutex_enter(&mpt->m_mutex);
11445         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11446             ptgt = refhash_next(mpt->m_targets, ptgt)) {
11447                 if (i >= count) {
11448                         /*
11449                          * The number of targets changed while we weren't
11450                          * looking, so give up.
11451                          */
11452                         refhash_rele(mpt->m_targets, ptgt);
11453                         mutex_exit(&mpt->m_mutex);
11454                         kmem_free(di, count * sizeof (mptsas_disk_info_t));
11455                         return (EAGAIN);
11456                 }
11457                 di[i].Instance = mpt->m_instance;
11458                 di[i].Enclosure = ptgt->m_enclosure;
11459                 di[i].Slot = ptgt->m_slot_num;
11460                 di[i].SasAddress = ptgt->m_addr.mta_wwn;
11461                 i++;
11462         }
11463         mutex_exit(&mpt->m_mutex);
11464         STRUCT_FSET(gdi, DiskCount, i);
11465 
11466         /* Copy out the disk information to the caller. */
11467         if (ddi_copyout((void *)di, STRUCT_FGETP(gdi, PtrDiskInfoArray),
11468             i * sizeof (mptsas_disk_info_t), mode) != 0) {
11469                 ret = EFAULT;
11470         }
11471 
11472         kmem_free(di, count * sizeof (mptsas_disk_info_t));
11473 
11474 copy_out:
11475         if (ddi_copyout(STRUCT_BUF(gdi), (void *)data, STRUCT_SIZE(gdi),
11476             mode) != 0) {
11477                 ret = EFAULT;
11478         }
11479 
11480         return (ret);
11481 }
11482 
11483 static int
11484 mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
11485     int *rval)
11486 {
11487         int                     status = 0;
11488         mptsas_t                *mpt;
11489         mptsas_update_flash_t   flashdata;
11490         mptsas_pass_thru_t      passthru_data;
11491         mptsas_adapter_data_t   adapter_data;
11492         mptsas_pci_info_t       pci_info;
11493         int                     copylen;
11494 
11495         int                     iport_flag = 0;
11496         dev_info_t              *dip = NULL;
11497         mptsas_phymask_t        phymask = 0;
11498         struct devctl_iocdata   *dcp = NULL;
11499         char                    *addr = NULL;
11500         mptsas_target_t         *ptgt = NULL;
11501 
11502         *rval = MPTIOCTL_STATUS_GOOD;
11503         if (secpolicy_sys_config(credp, B_FALSE) != 0) {
11504                 return (EPERM);
11505         }
11506 
11507         mpt = ddi_get_soft_state(mptsas_state, MINOR2INST(getminor(dev)));
11508         if (mpt == NULL) {
11509                 /*
11510                  * Called from iport node, get the states
11511                  */
11512                 iport_flag = 1;
11513                 dip = mptsas_get_dip_from_dev(dev, &phymask);
11514                 if (dip == NULL) {
11515                         return (ENXIO);
11516                 }
11517                 mpt = DIP2MPT(dip);
11518         }
11519         /* Make sure power level is D0 before accessing registers */
11520         mutex_enter(&mpt->m_mutex);
11521         if (mpt->m_options & MPTSAS_OPT_PM) {
11522                 (void) pm_busy_component(mpt->m_dip, 0);
11523                 if (mpt->m_power_level != PM_LEVEL_D0) {
11524                         mutex_exit(&mpt->m_mutex);
11525                         if (pm_raise_power(mpt->m_dip, 0, PM_LEVEL_D0) !=
11526                             DDI_SUCCESS) {
11527                                 mptsas_log(mpt, CE_WARN,
11528                                     "mptsas%d: mptsas_ioctl: Raise power "
11529                                     "request failed.", mpt->m_instance);
11530                                 (void) pm_idle_component(mpt->m_dip, 0);
11531                                 return (ENXIO);
11532                         }
11533                 } else {
11534                         mutex_exit(&mpt->m_mutex);
11535                 }
11536         } else {
11537                 mutex_exit(&mpt->m_mutex);
11538         }
11539 
11540         if (iport_flag) {
11541                 status = scsi_hba_ioctl(dev, cmd, data, mode, credp, rval);
11542                 if (status != 0) {
11543                         goto out;
11544                 }
11545                 /*
11546                  * The following code control the OK2RM LED, it doesn't affect
11547                  * the ioctl return status.
11548                  */
11549                 if ((cmd == DEVCTL_DEVICE_ONLINE) ||
11550                     (cmd == DEVCTL_DEVICE_OFFLINE)) {
11551                         if (ndi_dc_allochdl((void *)data, &dcp) !=
11552                             NDI_SUCCESS) {
11553                                 goto out;
11554                         }
11555                         addr = ndi_dc_getaddr(dcp);
11556                         ptgt = mptsas_addr_to_ptgt(mpt, addr, phymask);
11557                         if (ptgt == NULL) {
11558                                 NDBG14(("mptsas_ioctl led control: tgt %s not "
11559                                     "found", addr));
11560                                 ndi_dc_freehdl(dcp);
11561                                 goto out;
11562                         }
11563                         mutex_enter(&mpt->m_mutex);
11564                         if (cmd == DEVCTL_DEVICE_ONLINE) {
11565                                 ptgt->m_tgt_unconfigured = 0;
11566                         } else if (cmd == DEVCTL_DEVICE_OFFLINE) {
11567                                 ptgt->m_tgt_unconfigured = 1;
11568                         }
11569                         if (cmd == DEVCTL_DEVICE_OFFLINE) {
11570                                 ptgt->m_led_status |=
11571                                     (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
11572                         } else {
11573                                 ptgt->m_led_status &=
11574                                     ~(1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
11575                         }
11576                         (void) mptsas_flush_led_status(mpt, ptgt);
11577                         mutex_exit(&mpt->m_mutex);
11578                         ndi_dc_freehdl(dcp);
11579                 }
11580                 goto out;
11581         }
11582         switch (cmd) {
11583                 case MPTIOCTL_GET_DISK_INFO:
11584                         status = get_disk_info(mpt, data, mode);
11585                         break;
11586                 case MPTIOCTL_LED_CONTROL:
11587                         status = led_control(mpt, data, mode);
11588                         break;
11589                 case MPTIOCTL_UPDATE_FLASH:
11590                         if (ddi_copyin((void *)data, &flashdata,
11591                                 sizeof (struct mptsas_update_flash), mode)) {
11592                                 status = EFAULT;
11593                                 break;
11594                         }
11595 
11596                         mutex_enter(&mpt->m_mutex);
11597                         if (mptsas_update_flash(mpt,
11598                             (caddr_t)(long)flashdata.PtrBuffer,
11599                             flashdata.ImageSize, flashdata.ImageType, mode)) {
11600                                 status = EFAULT;
11601                         }
11602 
11603                         /*
11604                          * Reset the chip to start using the new
11605                          * firmware.  Reset if failed also.
11606                          */
11607                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
11608                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
11609                                 status = EFAULT;
11610                         }
11611                         mutex_exit(&mpt->m_mutex);
11612                         break;
11613                 case MPTIOCTL_PASS_THRU:
11614                         /*
11615                          * The user has requested to pass through a command to
11616                          * be executed by the MPT firmware.  Call our routine
11617                          * which does this.  Only allow one passthru IOCTL at
11618                          * one time. Other threads will block on
11619                          * m_passthru_mutex, which is of adaptive variant.
11620                          */
11621                         if (ddi_copyin((void *)data, &passthru_data,
11622                             sizeof (mptsas_pass_thru_t), mode)) {
11623                                 status = EFAULT;
11624                                 break;
11625                         }
11626                         mutex_enter(&mpt->m_passthru_mutex);
11627                         mutex_enter(&mpt->m_mutex);
11628                         status = mptsas_pass_thru(mpt, &passthru_data, mode);
11629                         mutex_exit(&mpt->m_mutex);
11630                         mutex_exit(&mpt->m_passthru_mutex);
11631 
11632                         break;
11633                 case MPTIOCTL_GET_ADAPTER_DATA:
11634                         /*
11635                          * The user has requested to read adapter data.  Call
11636                          * our routine which does this.
11637                          */
11638                         bzero(&adapter_data, sizeof (mptsas_adapter_data_t));
11639                         if (ddi_copyin((void *)data, (void *)&adapter_data,
11640                             sizeof (mptsas_adapter_data_t), mode)) {
11641                                 status = EFAULT;
11642                                 break;
11643                         }
11644                         if (adapter_data.StructureLength >=
11645                             sizeof (mptsas_adapter_data_t)) {
11646                                 adapter_data.StructureLength = (uint32_t)
11647                                     sizeof (mptsas_adapter_data_t);
11648                                 copylen = sizeof (mptsas_adapter_data_t);
11649                                 mutex_enter(&mpt->m_mutex);
11650                                 mptsas_read_adapter_data(mpt, &adapter_data);
11651                                 mutex_exit(&mpt->m_mutex);
11652                         } else {
11653                                 adapter_data.StructureLength = (uint32_t)
11654                                     sizeof (mptsas_adapter_data_t);
11655                                 copylen = sizeof (adapter_data.StructureLength);
11656                                 *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
11657                         }
11658                         if (ddi_copyout((void *)(&adapter_data), (void *)data,
11659                             copylen, mode) != 0) {
11660                                 status = EFAULT;
11661                         }
11662                         break;
11663                 case MPTIOCTL_GET_PCI_INFO:
11664                         /*
11665                          * The user has requested to read pci info.  Call
11666                          * our routine which does this.
11667                          */
11668                         bzero(&pci_info, sizeof (mptsas_pci_info_t));
11669                         mutex_enter(&mpt->m_mutex);
11670                         mptsas_read_pci_info(mpt, &pci_info);
11671                         mutex_exit(&mpt->m_mutex);
11672                         if (ddi_copyout((void *)(&pci_info), (void *)data,
11673                             sizeof (mptsas_pci_info_t), mode) != 0) {
11674                                 status = EFAULT;
11675                         }
11676                         break;
11677                 case MPTIOCTL_RESET_ADAPTER:
11678                         mutex_enter(&mpt->m_mutex);
11679                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
11680                         if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
11681                                 mptsas_log(mpt, CE_WARN, "reset adapter IOCTL "
11682                                     "failed");
11683                                 status = EFAULT;
11684                         }
11685                         mutex_exit(&mpt->m_mutex);
11686                         break;
11687                 case MPTIOCTL_DIAG_ACTION:
11688                         /*
11689                          * The user has done a diag buffer action.  Call our
11690                          * routine which does this.  Only allow one diag action
11691                          * at one time.
11692                          */
11693                         mutex_enter(&mpt->m_mutex);
11694                         if (mpt->m_diag_action_in_progress) {
11695                                 mutex_exit(&mpt->m_mutex);
11696                                 return (EBUSY);
11697                         }
11698                         mpt->m_diag_action_in_progress = 1;
11699                         status = mptsas_diag_action(mpt,
11700                             (mptsas_diag_action_t *)data, mode);
11701                         mpt->m_diag_action_in_progress = 0;
11702                         mutex_exit(&mpt->m_mutex);
11703                         break;
11704                 case MPTIOCTL_EVENT_QUERY:
11705                         /*
11706                          * The user has done an event query. Call our routine
11707                          * which does this.
11708                          */
11709                         status = mptsas_event_query(mpt,
11710                             (mptsas_event_query_t *)data, mode, rval);
11711                         break;
11712                 case MPTIOCTL_EVENT_ENABLE:
11713                         /*
11714                          * The user has done an event enable. Call our routine
11715                          * which does this.
11716                          */
11717                         status = mptsas_event_enable(mpt,
11718                             (mptsas_event_enable_t *)data, mode, rval);
11719                         break;
11720                 case MPTIOCTL_EVENT_REPORT:
11721                         /*
11722                          * The user has done an event report. Call our routine
11723                          * which does this.
11724                          */
11725                         status = mptsas_event_report(mpt,
11726                             (mptsas_event_report_t *)data, mode, rval);
11727                         break;
11728                 case MPTIOCTL_REG_ACCESS:
11729                         /*
11730                          * The user has requested register access.  Call our
11731                          * routine which does this.
11732                          */
11733                         status = mptsas_reg_access(mpt,
11734                             (mptsas_reg_access_t *)data, mode);
11735                         break;
11736                 default:
11737                         status = scsi_hba_ioctl(dev, cmd, data, mode, credp,
11738                             rval);
11739                         break;
11740         }
11741 
11742 out:
11743         return (status);
11744 }
11745 
11746 int
11747 mptsas_restart_ioc(mptsas_t *mpt)
11748 {
11749         int             rval = DDI_SUCCESS;
11750         mptsas_target_t *ptgt = NULL;
11751 
11752         ASSERT(mutex_owned(&mpt->m_mutex));
11753 
11754         /*
11755          * Set a flag telling I/O path that we're processing a reset.  This is
11756          * needed because after the reset is complete, the hash table still
11757          * needs to be rebuilt.  If I/Os are started before the hash table is
11758          * rebuilt, I/O errors will occur.  This flag allows I/Os to be marked
11759          * so that they can be retried.
11760          */
11761         mpt->m_in_reset = TRUE;
11762 
11763         /*
11764          * Set all throttles to HOLD
11765          */
11766         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11767             ptgt = refhash_next(mpt->m_targets, ptgt)) {
11768                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
11769         }
11770 
11771         /*
11772          * Disable interrupts
11773          */
11774         MPTSAS_DISABLE_INTR(mpt);
11775 
11776         /*
11777          * Abort all commands: outstanding commands, commands in waitq and
11778          * tx_waitq.
11779          */
11780         mptsas_flush_hba(mpt);
11781 
11782         /*
11783          * Reinitialize the chip.
11784          */
11785         if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
11786                 rval = DDI_FAILURE;
11787         }
11788 
11789         /*
11790          * Enable interrupts again
11791          */
11792         MPTSAS_ENABLE_INTR(mpt);
11793 
11794         /*
11795          * If mptsas_init_chip was successful, update the driver data.
11796          */
11797         if (rval == DDI_SUCCESS) {
11798                 mptsas_update_driver_data(mpt);
11799         }
11800 
11801         /*
11802          * Reset the throttles
11803          */
11804         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11805             ptgt = refhash_next(mpt->m_targets, ptgt)) {
11806                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
11807         }
11808 
11809         mptsas_doneq_empty(mpt);
11810         mptsas_restart_hba(mpt);
11811 
11812         if (rval != DDI_SUCCESS) {
11813                 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
11814                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
11815         }
11816 
11817         /*
11818          * Clear the reset flag so that I/Os can continue.
11819          */
11820         mpt->m_in_reset = FALSE;
11821 
11822         return (rval);
11823 }
11824 
11825 static int
11826 mptsas_init_chip(mptsas_t *mpt, int first_time)
11827 {
11828         ddi_dma_cookie_t        cookie;
11829         uint32_t                i;
11830         int                     rval;
11831 
11832         /*
11833          * Check to see if the firmware image is valid
11834          */
11835         if (ddi_get32(mpt->m_datap, &mpt->m_reg->HostDiagnostic) &
11836             MPI2_DIAG_FLASH_BAD_SIG) {
11837                 mptsas_log(mpt, CE_WARN, "mptsas bad flash signature!");
11838                 goto fail;
11839         }
11840 
11841         /*
11842          * Reset the chip
11843          */
11844         rval = mptsas_ioc_reset(mpt, first_time);
11845         if (rval == MPTSAS_RESET_FAIL) {
11846                 mptsas_log(mpt, CE_WARN, "hard reset failed!");
11847                 goto fail;
11848         }
11849 
11850         if ((rval == MPTSAS_SUCCESS_MUR) && (!first_time)) {
11851                 goto mur;
11852         }
11853         /*
11854          * Setup configuration space
11855          */
11856         if (mptsas_config_space_init(mpt) == FALSE) {
11857                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init "
11858                     "failed!");
11859                 goto fail;
11860         }
11861 
11862         /*
11863          * IOC facts can change after a diag reset so all buffers that are
11864          * based on these numbers must be de-allocated and re-allocated.  Get
11865          * new IOC facts each time chip is initialized.
11866          */
11867         if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
11868                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed");
11869                 goto fail;
11870         }
11871 
11872         mpt->m_targets = refhash_create(MPTSAS_TARGET_BUCKET_COUNT,
11873             mptsas_target_addr_hash, mptsas_target_addr_cmp,
11874             mptsas_target_free, sizeof (mptsas_target_t),
11875             offsetof(mptsas_target_t, m_link),
11876             offsetof(mptsas_target_t, m_addr), KM_SLEEP);
11877 
11878         if (mptsas_alloc_active_slots(mpt, KM_SLEEP)) {
11879                 goto fail;
11880         }
11881         /*
11882          * Allocate request message frames, reply free queue, reply descriptor
11883          * post queue, and reply message frames using latest IOC facts.
11884          */
11885         if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) {
11886                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames failed");
11887                 goto fail;
11888         }
11889         if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) {
11890                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue failed!");
11891                 goto fail;
11892         }
11893         if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) {
11894                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue failed!");
11895                 goto fail;
11896         }
11897         if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) {
11898                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_reply_frames failed!");
11899                 goto fail;
11900         }
11901 
11902 mur:
11903         /*
11904          * Re-Initialize ioc to operational state
11905          */
11906         if (mptsas_ioc_init(mpt) == DDI_FAILURE) {
11907                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_init failed");
11908                 goto fail;
11909         }
11910 
11911         mptsas_alloc_reply_args(mpt);
11912 
11913         /*
11914          * Initialize reply post index.  Reply free index is initialized after
11915          * the next loop.
11916          */
11917         mpt->m_post_index = 0;
11918 
11919         /*
11920          * Initialize the Reply Free Queue with the physical addresses of our
11921          * reply frames.
11922          */
11923         cookie.dmac_address = mpt->m_reply_frame_dma_addr;
11924         for (i = 0; i < mpt->m_max_replies; i++) {
11925                 ddi_put32(mpt->m_acc_free_queue_hdl,
11926                     &((uint32_t *)(void *)mpt->m_free_queue)[i],
11927                     cookie.dmac_address);
11928                 cookie.dmac_address += mpt->m_reply_frame_size;
11929         }
11930         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
11931             DDI_DMA_SYNC_FORDEV);
11932 
11933         /*
11934          * Initialize the reply free index to one past the last frame on the
11935          * queue.  This will signify that the queue is empty to start with.
11936          */
11937         mpt->m_free_index = i;
11938         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex, i);
11939 
11940         /*
11941          * Initialize the reply post queue to 0xFFFFFFFF,0xFFFFFFFF's.
11942          */
11943         for (i = 0; i < mpt->m_post_queue_depth; i++) {
11944                 ddi_put64(mpt->m_acc_post_queue_hdl,
11945                     &((uint64_t *)(void *)mpt->m_post_queue)[i],
11946                     0xFFFFFFFFFFFFFFFF);
11947         }
11948         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
11949             DDI_DMA_SYNC_FORDEV);
11950 
11951         /*
11952          * Enable ports
11953          */
11954         if (mptsas_ioc_enable_port(mpt) == DDI_FAILURE) {
11955                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_enable_port failed");
11956                 goto fail;
11957         }
11958 
11959         /*
11960          * enable events
11961          */
11962         if (mptsas_ioc_enable_event_notification(mpt)) {
11963                 goto fail;
11964         }
11965 
11966         /*
11967          * We need checks in attach and these.
11968          * chip_init is called in mult. places
11969          */
11970 
11971         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
11972             DDI_SUCCESS) ||
11973             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
11974             DDI_SUCCESS) ||
11975             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
11976             DDI_SUCCESS) ||
11977             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
11978             DDI_SUCCESS) ||
11979             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
11980             DDI_SUCCESS)) {
11981                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
11982                 goto fail;
11983         }
11984 
11985         /* Check all acc handles */
11986         if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
11987             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
11988             DDI_SUCCESS) ||
11989             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
11990             DDI_SUCCESS) ||
11991             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
11992             DDI_SUCCESS) ||
11993             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
11994             DDI_SUCCESS) ||
11995             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
11996             DDI_SUCCESS) ||
11997             (mptsas_check_acc_handle(mpt->m_config_handle) !=
11998             DDI_SUCCESS)) {
11999                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
12000                 goto fail;
12001         }
12002 
12003         return (DDI_SUCCESS);
12004 
12005 fail:
12006         return (DDI_FAILURE);
12007 }
12008 
12009 static int
12010 mptsas_get_pci_cap(mptsas_t *mpt)
12011 {
12012         ushort_t caps_ptr, cap, cap_count;
12013 
12014         if (mpt->m_config_handle == NULL)
12015                 return (FALSE);
12016         /*
12017          * Check if capabilities list is supported and if so,
12018          * get initial capabilities pointer and clear bits 0,1.
12019          */
12020         if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT)
12021             & PCI_STAT_CAP) {
12022                 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
12023                     PCI_CONF_CAP_PTR), 4);
12024         } else {
12025                 caps_ptr = PCI_CAP_NEXT_PTR_NULL;
12026         }
12027 
12028         /*
12029          * Walk capabilities if supported.
12030          */
12031         for (cap_count = 0; caps_ptr != PCI_CAP_NEXT_PTR_NULL; ) {
12032 
12033                 /*
12034                  * Check that we haven't exceeded the maximum number of
12035                  * capabilities and that the pointer is in a valid range.
12036                  */
12037                 if (++cap_count > 48) {
12038                         mptsas_log(mpt, CE_WARN,
12039                             "too many device capabilities.\n");
12040                         break;
12041                 }
12042                 if (caps_ptr < 64) {
12043                         mptsas_log(mpt, CE_WARN,
12044                             "capabilities pointer 0x%x out of range.\n",
12045                             caps_ptr);
12046                         break;
12047                 }
12048 
12049                 /*
12050                  * Get next capability and check that it is valid.
12051                  * For now, we only support power management.
12052                  */
12053                 cap = pci_config_get8(mpt->m_config_handle, caps_ptr);
12054                 switch (cap) {
12055                         case PCI_CAP_ID_PM:
12056                                 mptsas_log(mpt, CE_NOTE,
12057                                     "?mptsas%d supports power management.\n",
12058                                     mpt->m_instance);
12059                                 mpt->m_options |= MPTSAS_OPT_PM;
12060 
12061                                 /* Save PMCSR offset */
12062                                 mpt->m_pmcsr_offset = caps_ptr + PCI_PMCSR;
12063                                 break;
12064                         /*
12065                          * The following capabilities are valid.  Any others
12066                          * will cause a message to be logged.
12067                          */
12068                         case PCI_CAP_ID_VPD:
12069                         case PCI_CAP_ID_MSI:
12070                         case PCI_CAP_ID_PCIX:
12071                         case PCI_CAP_ID_PCI_E:
12072                         case PCI_CAP_ID_MSI_X:
12073                                 break;
12074                         default:
12075                                 mptsas_log(mpt, CE_NOTE,
12076                                     "?mptsas%d unrecognized capability "
12077                                     "0x%x.\n", mpt->m_instance, cap);
12078                                 break;
12079                 }
12080 
12081                 /*
12082                  * Get next capabilities pointer and clear bits 0,1.
12083                  */
12084                 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
12085                     (caps_ptr + PCI_CAP_NEXT_PTR)), 4);
12086         }
12087         return (TRUE);
12088 }
12089 
12090 static int
12091 mptsas_init_pm(mptsas_t *mpt)
12092 {
12093         char            pmc_name[16];
12094         char            *pmc[] = {
12095                                 NULL,
12096                                 "0=Off (PCI D3 State)",
12097                                 "3=On (PCI D0 State)",
12098                                 NULL
12099                         };
12100         uint16_t        pmcsr_stat;
12101 
12102         if (mptsas_get_pci_cap(mpt) == FALSE) {
12103                 return (DDI_FAILURE);
12104         }
12105         /*
12106          * If PCI's capability does not support PM, then don't need
12107          * to registe the pm-components
12108          */
12109         if (!(mpt->m_options & MPTSAS_OPT_PM))
12110                 return (DDI_SUCCESS);
12111         /*
12112          * If power management is supported by this chip, create
12113          * pm-components property for the power management framework
12114          */
12115         (void) sprintf(pmc_name, "NAME=mptsas%d", mpt->m_instance);
12116         pmc[0] = pmc_name;
12117         if (ddi_prop_update_string_array(DDI_DEV_T_NONE, mpt->m_dip,
12118             "pm-components", pmc, 3) != DDI_PROP_SUCCESS) {
12119                 mpt->m_options &= ~MPTSAS_OPT_PM;
12120                 mptsas_log(mpt, CE_WARN,
12121                     "mptsas%d: pm-component property creation failed.",
12122                     mpt->m_instance);
12123                 return (DDI_FAILURE);
12124         }
12125 
12126         /*
12127          * Power on device.
12128          */
12129         (void) pm_busy_component(mpt->m_dip, 0);
12130         pmcsr_stat = pci_config_get16(mpt->m_config_handle,
12131             mpt->m_pmcsr_offset);
12132         if ((pmcsr_stat & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_D0) {
12133                 mptsas_log(mpt, CE_WARN, "mptsas%d: Power up the device",
12134                     mpt->m_instance);
12135                 pci_config_put16(mpt->m_config_handle, mpt->m_pmcsr_offset,
12136                     PCI_PMCSR_D0);
12137         }
12138         if (pm_power_has_changed(mpt->m_dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) {
12139                 mptsas_log(mpt, CE_WARN, "pm_power_has_changed failed");
12140                 return (DDI_FAILURE);
12141         }
12142         mpt->m_power_level = PM_LEVEL_D0;
12143         /*
12144          * Set pm idle delay.
12145          */
12146         mpt->m_pm_idle_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
12147             mpt->m_dip, 0, "mptsas-pm-idle-delay", MPTSAS_PM_IDLE_TIMEOUT);
12148 
12149         return (DDI_SUCCESS);
12150 }
12151 
12152 static int
12153 mptsas_register_intrs(mptsas_t *mpt)
12154 {
12155         dev_info_t *dip;
12156         int intr_types;
12157 
12158         dip = mpt->m_dip;
12159 
12160         /* Get supported interrupt types */
12161         if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) {
12162                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_supported_types "
12163                     "failed\n");
12164                 return (FALSE);
12165         }
12166 
12167         NDBG6(("ddi_intr_get_supported_types() returned: 0x%x", intr_types));
12168 
12169         /*
12170          * Try MSI, but fall back to FIXED
12171          */
12172         if (mptsas_enable_msi && (intr_types & DDI_INTR_TYPE_MSI)) {
12173                 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_MSI) == DDI_SUCCESS) {
12174                         NDBG0(("Using MSI interrupt type"));
12175                         mpt->m_intr_type = DDI_INTR_TYPE_MSI;
12176                         return (TRUE);
12177                 }
12178         }
12179         if (intr_types & DDI_INTR_TYPE_FIXED) {
12180                 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_FIXED) == DDI_SUCCESS) {
12181                         NDBG0(("Using FIXED interrupt type"));
12182                         mpt->m_intr_type = DDI_INTR_TYPE_FIXED;
12183                         return (TRUE);
12184                 } else {
12185                         NDBG0(("FIXED interrupt registration failed"));
12186                         return (FALSE);
12187                 }
12188         }
12189 
12190         return (FALSE);
12191 }
12192 
12193 static void
12194 mptsas_unregister_intrs(mptsas_t *mpt)
12195 {
12196         mptsas_rem_intrs(mpt);
12197 }
12198 
12199 /*
12200  * mptsas_add_intrs:
12201  *
12202  * Register FIXED or MSI interrupts.
12203  */
12204 static int
12205 mptsas_add_intrs(mptsas_t *mpt, int intr_type)
12206 {
12207         dev_info_t      *dip = mpt->m_dip;
12208         int             avail, actual, count = 0;
12209         int             i, flag, ret;
12210 
12211         NDBG6(("mptsas_add_intrs:interrupt type 0x%x", intr_type));
12212 
12213         /* Get number of interrupts */
12214         ret = ddi_intr_get_nintrs(dip, intr_type, &count);
12215         if ((ret != DDI_SUCCESS) || (count <= 0)) {
12216                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_nintrs() failed, "
12217                     "ret %d count %d\n", ret, count);
12218 
12219                 return (DDI_FAILURE);
12220         }
12221 
12222         /* Get number of available interrupts */
12223         ret = ddi_intr_get_navail(dip, intr_type, &avail);
12224         if ((ret != DDI_SUCCESS) || (avail == 0)) {
12225                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_navail() failed, "
12226                     "ret %d avail %d\n", ret, avail);
12227 
12228                 return (DDI_FAILURE);
12229         }
12230 
12231         if (avail < count) {
12232                 mptsas_log(mpt, CE_NOTE, "ddi_intr_get_nvail returned %d, "
12233                     "navail() returned %d", count, avail);
12234         }
12235 
12236         /* Mpt only have one interrupt routine */
12237         if ((intr_type == DDI_INTR_TYPE_MSI) && (count > 1)) {
12238                 count = 1;
12239         }
12240 
12241         /* Allocate an array of interrupt handles */
12242         mpt->m_intr_size = count * sizeof (ddi_intr_handle_t);
12243         mpt->m_htable = kmem_alloc(mpt->m_intr_size, KM_SLEEP);
12244 
12245         flag = DDI_INTR_ALLOC_NORMAL;
12246 
12247         /* call ddi_intr_alloc() */
12248         ret = ddi_intr_alloc(dip, mpt->m_htable, intr_type, 0,
12249             count, &actual, flag);
12250 
12251         if ((ret != DDI_SUCCESS) || (actual == 0)) {
12252                 mptsas_log(mpt, CE_WARN, "ddi_intr_alloc() failed, ret %d\n",
12253                     ret);
12254                 kmem_free(mpt->m_htable, mpt->m_intr_size);
12255                 return (DDI_FAILURE);
12256         }
12257 
12258         /* use interrupt count returned or abort? */
12259         if (actual < count) {
12260                 mptsas_log(mpt, CE_NOTE, "Requested: %d, Received: %d\n",
12261                     count, actual);
12262         }
12263 
12264         mpt->m_intr_cnt = actual;
12265 
12266         /*
12267          * Get priority for first msi, assume remaining are all the same
12268          */
12269         if ((ret = ddi_intr_get_pri(mpt->m_htable[0],
12270             &mpt->m_intr_pri)) != DDI_SUCCESS) {
12271                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_pri() failed %d\n", ret);
12272 
12273                 /* Free already allocated intr */
12274                 for (i = 0; i < actual; i++) {
12275                         (void) ddi_intr_free(mpt->m_htable[i]);
12276                 }
12277 
12278                 kmem_free(mpt->m_htable, mpt->m_intr_size);
12279                 return (DDI_FAILURE);
12280         }
12281 
12282         /* Test for high level mutex */
12283         if (mpt->m_intr_pri >= ddi_intr_get_hilevel_pri()) {
12284                 mptsas_log(mpt, CE_WARN, "mptsas_add_intrs: "
12285                     "Hi level interrupt not supported\n");
12286 
12287                 /* Free already allocated intr */
12288                 for (i = 0; i < actual; i++) {
12289                         (void) ddi_intr_free(mpt->m_htable[i]);
12290                 }
12291 
12292                 kmem_free(mpt->m_htable, mpt->m_intr_size);
12293                 return (DDI_FAILURE);
12294         }
12295 
12296         /* Call ddi_intr_add_handler() */
12297         for (i = 0; i < actual; i++) {
12298                 if ((ret = ddi_intr_add_handler(mpt->m_htable[i], mptsas_intr,
12299                     (caddr_t)mpt, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
12300                         mptsas_log(mpt, CE_WARN, "ddi_intr_add_handler() "
12301                             "failed %d\n", ret);
12302 
12303                         /* Free already allocated intr */
12304                         for (i = 0; i < actual; i++) {
12305                                 (void) ddi_intr_free(mpt->m_htable[i]);
12306                         }
12307 
12308                         kmem_free(mpt->m_htable, mpt->m_intr_size);
12309                         return (DDI_FAILURE);
12310                 }
12311         }
12312 
12313         if ((ret = ddi_intr_get_cap(mpt->m_htable[0], &mpt->m_intr_cap))
12314             != DDI_SUCCESS) {
12315                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_cap() failed %d\n", ret);
12316 
12317                 /* Free already allocated intr */
12318                 for (i = 0; i < actual; i++) {
12319                         (void) ddi_intr_free(mpt->m_htable[i]);
12320                 }
12321 
12322                 kmem_free(mpt->m_htable, mpt->m_intr_size);
12323                 return (DDI_FAILURE);
12324         }
12325 
12326         /*
12327          * Enable interrupts
12328          */
12329         if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
12330                 /* Call ddi_intr_block_enable() for MSI interrupts */
12331                 (void) ddi_intr_block_enable(mpt->m_htable, mpt->m_intr_cnt);
12332         } else {
12333                 /* Call ddi_intr_enable for MSI or FIXED interrupts */
12334                 for (i = 0; i < mpt->m_intr_cnt; i++) {
12335                         (void) ddi_intr_enable(mpt->m_htable[i]);
12336                 }
12337         }
12338         return (DDI_SUCCESS);
12339 }
12340 
12341 /*
12342  * mptsas_rem_intrs:
12343  *
12344  * Unregister FIXED or MSI interrupts
12345  */
12346 static void
12347 mptsas_rem_intrs(mptsas_t *mpt)
12348 {
12349         int     i;
12350 
12351         NDBG6(("mptsas_rem_intrs"));
12352 
12353         /* Disable all interrupts */
12354         if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
12355                 /* Call ddi_intr_block_disable() */
12356                 (void) ddi_intr_block_disable(mpt->m_htable, mpt->m_intr_cnt);
12357         } else {
12358                 for (i = 0; i < mpt->m_intr_cnt; i++) {
12359                         (void) ddi_intr_disable(mpt->m_htable[i]);
12360                 }
12361         }
12362 
12363         /* Call ddi_intr_remove_handler() */
12364         for (i = 0; i < mpt->m_intr_cnt; i++) {
12365                 (void) ddi_intr_remove_handler(mpt->m_htable[i]);
12366                 (void) ddi_intr_free(mpt->m_htable[i]);
12367         }
12368 
12369         kmem_free(mpt->m_htable, mpt->m_intr_size);
12370 }
12371 
12372 /*
12373  * The IO fault service error handling callback function
12374  */
12375 /*ARGSUSED*/
12376 static int
12377 mptsas_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
12378 {
12379         /*
12380          * as the driver can always deal with an error in any dma or
12381          * access handle, we can just return the fme_status value.
12382          */
12383         pci_ereport_post(dip, err, NULL);
12384         return (err->fme_status);
12385 }
12386 
12387 /*
12388  * mptsas_fm_init - initialize fma capabilities and register with IO
12389  *               fault services.
12390  */
12391 static void
12392 mptsas_fm_init(mptsas_t *mpt)
12393 {
12394         /*
12395          * Need to change iblock to priority for new MSI intr
12396          */
12397         ddi_iblock_cookie_t     fm_ibc;
12398 
12399         /* Only register with IO Fault Services if we have some capability */
12400         if (mpt->m_fm_capabilities) {
12401                 /* Adjust access and dma attributes for FMA */
12402                 mpt->m_reg_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
12403                 mpt->m_msg_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
12404                 mpt->m_io_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
12405 
12406                 /*
12407                  * Register capabilities with IO Fault Services.
12408                  * mpt->m_fm_capabilities will be updated to indicate
12409                  * capabilities actually supported (not requested.)
12410                  */
12411                 ddi_fm_init(mpt->m_dip, &mpt->m_fm_capabilities, &fm_ibc);
12412 
12413                 /*
12414                  * Initialize pci ereport capabilities if ereport
12415                  * capable (should always be.)
12416                  */
12417                 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
12418                     DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
12419                         pci_ereport_setup(mpt->m_dip);
12420                 }
12421 
12422                 /*
12423                  * Register error callback if error callback capable.
12424                  */
12425                 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
12426                         ddi_fm_handler_register(mpt->m_dip,
12427                             mptsas_fm_error_cb, (void *) mpt);
12428                 }
12429         }
12430 }
12431 
12432 /*
12433  * mptsas_fm_fini - Releases fma capabilities and un-registers with IO
12434  *               fault services.
12435  *
12436  */
12437 static void
12438 mptsas_fm_fini(mptsas_t *mpt)
12439 {
12440         /* Only unregister FMA capabilities if registered */
12441         if (mpt->m_fm_capabilities) {
12442 
12443                 /*
12444                  * Un-register error callback if error callback capable.
12445                  */
12446 
12447                 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
12448                         ddi_fm_handler_unregister(mpt->m_dip);
12449                 }
12450 
12451                 /*
12452                  * Release any resources allocated by pci_ereport_setup()
12453                  */
12454 
12455                 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
12456                     DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
12457                         pci_ereport_teardown(mpt->m_dip);
12458                 }
12459 
12460                 /* Unregister from IO Fault Services */
12461                 ddi_fm_fini(mpt->m_dip);
12462 
12463                 /* Adjust access and dma attributes for FMA */
12464                 mpt->m_reg_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
12465                 mpt->m_msg_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12466                 mpt->m_io_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12467 
12468         }
12469 }
12470 
12471 int
12472 mptsas_check_acc_handle(ddi_acc_handle_t handle)
12473 {
12474         ddi_fm_error_t  de;
12475 
12476         if (handle == NULL)
12477                 return (DDI_FAILURE);
12478         ddi_fm_acc_err_get(handle, &de, DDI_FME_VER0);
12479         return (de.fme_status);
12480 }
12481 
12482 int
12483 mptsas_check_dma_handle(ddi_dma_handle_t handle)
12484 {
12485         ddi_fm_error_t  de;
12486 
12487         if (handle == NULL)
12488                 return (DDI_FAILURE);
12489         ddi_fm_dma_err_get(handle, &de, DDI_FME_VER0);
12490         return (de.fme_status);
12491 }
12492 
12493 void
12494 mptsas_fm_ereport(mptsas_t *mpt, char *detail)
12495 {
12496         uint64_t        ena;
12497         char            buf[FM_MAX_CLASS];
12498 
12499         (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
12500         ena = fm_ena_generate(0, FM_ENA_FMT1);
12501         if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities)) {
12502                 ddi_fm_ereport_post(mpt->m_dip, buf, ena, DDI_NOSLEEP,
12503                     FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
12504         }
12505 }
12506 
12507 static int
12508 mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
12509     uint16_t *dev_handle, mptsas_target_t **pptgt)
12510 {
12511         int             rval;
12512         uint32_t        dev_info;
12513         uint64_t        sas_wwn;
12514         mptsas_phymask_t phymask;
12515         uint8_t         physport, phynum, config, disk;
12516         uint64_t        devicename;
12517         uint16_t        pdev_hdl;
12518         mptsas_target_t *tmp_tgt = NULL;
12519         uint16_t        bay_num, enclosure;
12520 
12521         ASSERT(*pptgt == NULL);
12522 
12523         rval = mptsas_get_sas_device_page0(mpt, page_address, dev_handle,
12524             &sas_wwn, &dev_info, &physport, &phynum, &pdev_hdl,
12525             &bay_num, &enclosure);
12526         if (rval != DDI_SUCCESS) {
12527                 rval = DEV_INFO_FAIL_PAGE0;
12528                 return (rval);
12529         }
12530 
12531         if ((dev_info & (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
12532             MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
12533             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) == NULL) {
12534                 rval = DEV_INFO_WRONG_DEVICE_TYPE;
12535                 return (rval);
12536         }
12537 
12538         /*
12539          * Check if the dev handle is for a Phys Disk. If so, set return value
12540          * and exit.  Don't add Phys Disks to hash.
12541          */
12542         for (config = 0; config < mpt->m_num_raid_configs; config++) {
12543                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
12544                         if (*dev_handle == mpt->m_raidconfig[config].
12545                             m_physdisk_devhdl[disk]) {
12546                                 rval = DEV_INFO_PHYS_DISK;
12547                                 return (rval);
12548                         }
12549                 }
12550         }
12551 
12552         /*
12553          * Get SATA Device Name from SAS device page0 for
12554          * sata device, if device name doesn't exist, set mta_wwn to
12555          * 0 for direct attached SATA. For the device behind the expander
12556          * we still can use STP address assigned by expander.
12557          */
12558         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
12559             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
12560                 mutex_exit(&mpt->m_mutex);
12561                 /* alloc a tmp_tgt to send the cmd */
12562                 tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target),
12563                     KM_SLEEP);
12564                 tmp_tgt->m_devhdl = *dev_handle;
12565                 tmp_tgt->m_deviceinfo = dev_info;
12566                 tmp_tgt->m_qfull_retries = QFULL_RETRIES;
12567                 tmp_tgt->m_qfull_retry_interval =
12568                     drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
12569                 tmp_tgt->m_t_throttle = MAX_THROTTLE;
12570                 devicename = mptsas_get_sata_guid(mpt, tmp_tgt, 0);
12571                 kmem_free(tmp_tgt, sizeof (struct mptsas_target));
12572                 mutex_enter(&mpt->m_mutex);
12573                 if (devicename != 0 && (((devicename >> 56) & 0xf0) == 0x50)) {
12574                         sas_wwn = devicename;
12575                 } else if (dev_info & MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH) {
12576                         sas_wwn = 0;
12577                 }
12578         }
12579 
12580         phymask = mptsas_physport_to_phymask(mpt, physport);
12581         *pptgt = mptsas_tgt_alloc(mpt, *dev_handle, sas_wwn,
12582             dev_info, phymask, phynum);
12583         if (*pptgt == NULL) {
12584                 mptsas_log(mpt, CE_WARN, "Failed to allocated target"
12585                     "structure!");
12586                 rval = DEV_INFO_FAIL_ALLOC;
12587                 return (rval);
12588         }
12589         (*pptgt)->m_enclosure = enclosure;
12590         (*pptgt)->m_slot_num = bay_num;
12591         return (DEV_INFO_SUCCESS);
12592 }
12593 
12594 uint64_t
12595 mptsas_get_sata_guid(mptsas_t *mpt, mptsas_target_t *ptgt, int lun)
12596 {
12597         uint64_t        sata_guid = 0, *pwwn = NULL;
12598         int             target = ptgt->m_devhdl;
12599         uchar_t         *inq83 = NULL;
12600         int             inq83_len = 0xFF;
12601         uchar_t         *dblk = NULL;
12602         int             inq83_retry = 3;
12603         int             rval = DDI_FAILURE;
12604 
12605         inq83   = kmem_zalloc(inq83_len, KM_SLEEP);
12606 
12607 inq83_retry:
12608         rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
12609             inq83_len, NULL, 1);
12610         if (rval != DDI_SUCCESS) {
12611                 mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
12612                     "0x83 for target:%x, lun:%x failed!", target, lun);
12613                 goto out;
12614         }
12615         /* According to SAT2, the first descriptor is logic unit name */
12616         dblk = &inq83[4];
12617         if ((dblk[1] & 0x30) != 0) {
12618                 mptsas_log(mpt, CE_WARN, "!Descriptor is not lun associated.");
12619                 goto out;
12620         }
12621         pwwn = (uint64_t *)(void *)(&dblk[4]);
12622         if ((dblk[4] & 0xf0) == 0x50) {
12623                 sata_guid = BE_64(*pwwn);
12624                 goto out;
12625         } else if (dblk[4] == 'A') {
12626                 NDBG20(("SATA drive has no NAA format GUID."));
12627                 goto out;
12628         } else {
12629                 /* The data is not ready, wait and retry */
12630                 inq83_retry--;
12631                 if (inq83_retry <= 0) {
12632                         goto out;
12633                 }
12634                 NDBG20(("The GUID is not ready, retry..."));
12635                 delay(1 * drv_usectohz(1000000));
12636                 goto inq83_retry;
12637         }
12638 out:
12639         kmem_free(inq83, inq83_len);
12640         return (sata_guid);
12641 }
12642 
12643 static int
12644 mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun, uchar_t page,
12645     unsigned char *buf, int len, int *reallen, uchar_t evpd)
12646 {
12647         uchar_t                 cdb[CDB_GROUP0];
12648         struct scsi_address     ap;
12649         struct buf              *data_bp = NULL;
12650         int                     resid = 0;
12651         int                     ret = DDI_FAILURE;
12652 
12653         ASSERT(len <= 0xffff);
12654 
12655         ap.a_target = MPTSAS_INVALID_DEVHDL;
12656         ap.a_lun = (uchar_t)(lun);
12657         ap.a_hba_tran = mpt->m_tran;
12658 
12659         data_bp = scsi_alloc_consistent_buf(&ap,
12660             (struct buf *)NULL, len, B_READ, NULL_FUNC, NULL);
12661         if (data_bp == NULL) {
12662                 return (ret);
12663         }
12664         bzero(cdb, CDB_GROUP0);
12665         cdb[0] = SCMD_INQUIRY;
12666         cdb[1] = evpd;
12667         cdb[2] = page;
12668         cdb[3] = (len & 0xff00) >> 8;
12669         cdb[4] = (len & 0x00ff);
12670         cdb[5] = 0;
12671 
12672         ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP0, data_bp,
12673             &resid);
12674         if (ret == DDI_SUCCESS) {
12675                 if (reallen) {
12676                         *reallen = len - resid;
12677                 }
12678                 bcopy((caddr_t)data_bp->b_un.b_addr, buf, len);
12679         }
12680         if (data_bp) {
12681                 scsi_free_consistent_buf(data_bp);
12682         }
12683         return (ret);
12684 }
12685 
12686 static int
12687 mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
12688     mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
12689     int *resid)
12690 {
12691         struct scsi_pkt         *pktp = NULL;
12692         scsi_hba_tran_t         *tran_clone = NULL;
12693         mptsas_tgt_private_t    *tgt_private = NULL;
12694         int                     ret = DDI_FAILURE;
12695 
12696         /*
12697          * scsi_hba_tran_t->tran_tgt_private is used to pass the address
12698          * information to scsi_init_pkt, allocate a scsi_hba_tran structure
12699          * to simulate the cmds from sd
12700          */
12701         tran_clone = kmem_alloc(
12702             sizeof (scsi_hba_tran_t), KM_SLEEP);
12703         if (tran_clone == NULL) {
12704                 goto out;
12705         }
12706         bcopy((caddr_t)mpt->m_tran,
12707             (caddr_t)tran_clone, sizeof (scsi_hba_tran_t));
12708         tgt_private = kmem_alloc(
12709             sizeof (mptsas_tgt_private_t), KM_SLEEP);
12710         if (tgt_private == NULL) {
12711                 goto out;
12712         }
12713         tgt_private->t_lun = ap->a_lun;
12714         tgt_private->t_private = ptgt;
12715         tran_clone->tran_tgt_private = tgt_private;
12716         ap->a_hba_tran = tran_clone;
12717 
12718         pktp = scsi_init_pkt(ap, (struct scsi_pkt *)NULL,
12719             data_bp, cdblen, sizeof (struct scsi_arq_status),
12720             0, PKT_CONSISTENT, NULL, NULL);
12721         if (pktp == NULL) {
12722                 goto out;
12723         }
12724         bcopy(cdb, pktp->pkt_cdbp, cdblen);
12725         pktp->pkt_flags = FLAG_NOPARITY;
12726         if (scsi_poll(pktp) < 0) {
12727                 goto out;
12728         }
12729         if (((struct scsi_status *)pktp->pkt_scbp)->sts_chk) {
12730                 goto out;
12731         }
12732         if (resid != NULL) {
12733                 *resid = pktp->pkt_resid;
12734         }
12735 
12736         ret = DDI_SUCCESS;
12737 out:
12738         if (pktp) {
12739                 scsi_destroy_pkt(pktp);
12740         }
12741         if (tran_clone) {
12742                 kmem_free(tran_clone, sizeof (scsi_hba_tran_t));
12743         }
12744         if (tgt_private) {
12745                 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
12746         }
12747         return (ret);
12748 }
12749 static int
12750 mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy, int *lun)
12751 {
12752         char    *cp = NULL;
12753         char    *ptr = NULL;
12754         size_t  s = 0;
12755         char    *wwid_str = NULL;
12756         char    *lun_str = NULL;
12757         long    lunnum;
12758         long    phyid = -1;
12759         int     rc = DDI_FAILURE;
12760 
12761         ptr = name;
12762         ASSERT(ptr[0] == 'w' || ptr[0] == 'p');
12763         ptr++;
12764         if ((cp = strchr(ptr, ',')) == NULL) {
12765                 return (DDI_FAILURE);
12766         }
12767 
12768         wwid_str = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
12769         s = (uintptr_t)cp - (uintptr_t)ptr;
12770 
12771         bcopy(ptr, wwid_str, s);
12772         wwid_str[s] = '\0';
12773 
12774         ptr = ++cp;
12775 
12776         if ((cp = strchr(ptr, '\0')) == NULL) {
12777                 goto out;
12778         }
12779         lun_str =  kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
12780         s = (uintptr_t)cp - (uintptr_t)ptr;
12781 
12782         bcopy(ptr, lun_str, s);
12783         lun_str[s] = '\0';
12784 
12785         if (name[0] == 'p') {
12786                 rc = ddi_strtol(wwid_str, NULL, 0x10, &phyid);
12787         } else {
12788                 rc = scsi_wwnstr_to_wwn(wwid_str, wwid);
12789         }
12790         if (rc != DDI_SUCCESS)
12791                 goto out;
12792 
12793         if (phyid != -1) {
12794                 ASSERT(phyid < MPTSAS_MAX_PHYS);
12795                 *phy = (uint8_t)phyid;
12796         }
12797         rc = ddi_strtol(lun_str, NULL, 0x10, &lunnum);
12798         if (rc != 0)
12799                 goto out;
12800 
12801         *lun = (int)lunnum;
12802         rc = DDI_SUCCESS;
12803 out:
12804         if (wwid_str)
12805                 kmem_free(wwid_str, SCSI_MAXNAMELEN);
12806         if (lun_str)
12807                 kmem_free(lun_str, SCSI_MAXNAMELEN);
12808 
12809         return (rc);
12810 }
12811 
12812 /*
12813  * mptsas_parse_smp_name() is to parse sas wwn string
12814  * which format is "wWWN"
12815  */
12816 static int
12817 mptsas_parse_smp_name(char *name, uint64_t *wwn)
12818 {
12819         char    *ptr = name;
12820 
12821         if (*ptr != 'w') {
12822                 return (DDI_FAILURE);
12823         }
12824 
12825         ptr++;
12826         if (scsi_wwnstr_to_wwn(ptr, wwn)) {
12827                 return (DDI_FAILURE);
12828         }
12829         return (DDI_SUCCESS);
12830 }
12831 
12832 static int
12833 mptsas_bus_config(dev_info_t *pdip, uint_t flag,
12834     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
12835 {
12836         int             ret = NDI_FAILURE;
12837         int             circ = 0;
12838         int             circ1 = 0;
12839         mptsas_t        *mpt;
12840         char            *ptr = NULL;
12841         char            *devnm = NULL;
12842         uint64_t        wwid = 0;
12843         uint8_t         phy = 0xFF;
12844         int             lun = 0;
12845         uint_t          mflags = flag;
12846         int             bconfig = TRUE;
12847 
12848         if (scsi_hba_iport_unit_address(pdip) == 0) {
12849                 return (DDI_FAILURE);
12850         }
12851 
12852         mpt = DIP2MPT(pdip);
12853         if (!mpt) {
12854                 return (DDI_FAILURE);
12855         }
12856         /*
12857          * Hold the nexus across the bus_config
12858          */
12859         ndi_devi_enter(scsi_vhci_dip, &circ);
12860         ndi_devi_enter(pdip, &circ1);
12861         switch (op) {
12862         case BUS_CONFIG_ONE:
12863                 /* parse wwid/target name out of name given */
12864                 if ((ptr = strchr((char *)arg, '@')) == NULL) {
12865                         ret = NDI_FAILURE;
12866                         break;
12867                 }
12868                 ptr++;
12869                 if (strncmp((char *)arg, "smp", 3) == 0) {
12870                         /*
12871                          * This is a SMP target device
12872                          */
12873                         ret = mptsas_parse_smp_name(ptr, &wwid);
12874                         if (ret != DDI_SUCCESS) {
12875                                 ret = NDI_FAILURE;
12876                                 break;
12877                         }
12878                         ret = mptsas_config_smp(pdip, wwid, childp);
12879                 } else if ((ptr[0] == 'w') || (ptr[0] == 'p')) {
12880                         /*
12881                          * OBP could pass down a non-canonical form
12882                          * bootpath without LUN part when LUN is 0.
12883                          * So driver need adjust the string.
12884                          */
12885                         if (strchr(ptr, ',') == NULL) {
12886                                 devnm = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
12887                                 (void) sprintf(devnm, "%s,0", (char *)arg);
12888                                 ptr = strchr(devnm, '@');
12889                                 ptr++;
12890                         }
12891 
12892                         /*
12893                          * The device path is wWWID format and the device
12894                          * is not SMP target device.
12895                          */
12896                         ret = mptsas_parse_address(ptr, &wwid, &phy, &lun);
12897                         if (ret != DDI_SUCCESS) {
12898                                 ret = NDI_FAILURE;
12899                                 break;
12900                         }
12901                         *childp = NULL;
12902                         if (ptr[0] == 'w') {
12903                                 ret = mptsas_config_one_addr(pdip, wwid,
12904                                     lun, childp);
12905                         } else if (ptr[0] == 'p') {
12906                                 ret = mptsas_config_one_phy(pdip, phy, lun,
12907                                     childp);
12908                         }
12909 
12910                         /*
12911                          * If this is CD/DVD device in OBP path, the
12912                          * ndi_busop_bus_config can be skipped as config one
12913                          * operation is done above.
12914                          */
12915                         if ((ret == NDI_SUCCESS) && (*childp != NULL) &&
12916                             (strcmp(ddi_node_name(*childp), "cdrom") == 0) &&
12917                             (strncmp((char *)arg, "disk", 4) == 0)) {
12918                                 bconfig = FALSE;
12919                                 ndi_hold_devi(*childp);
12920                         }
12921                 } else {
12922                         ret = NDI_FAILURE;
12923                         break;
12924                 }
12925 
12926                 /*
12927                  * DDI group instructed us to use this flag.
12928                  */
12929                 mflags |= NDI_MDI_FALLBACK;
12930                 break;
12931         case BUS_CONFIG_DRIVER:
12932         case BUS_CONFIG_ALL:
12933                 mptsas_config_all(pdip);
12934                 ret = NDI_SUCCESS;
12935                 break;
12936         }
12937 
12938         if ((ret == NDI_SUCCESS) && bconfig) {
12939                 ret = ndi_busop_bus_config(pdip, mflags, op,
12940                     (devnm == NULL) ? arg : devnm, childp, 0);
12941         }
12942 
12943         ndi_devi_exit(pdip, circ1);
12944         ndi_devi_exit(scsi_vhci_dip, circ);
12945         if (devnm != NULL)
12946                 kmem_free(devnm, SCSI_MAXNAMELEN);
12947         return (ret);
12948 }
12949 
12950 static int
12951 mptsas_probe_lun(dev_info_t *pdip, int lun, dev_info_t **dip,
12952     mptsas_target_t *ptgt)
12953 {
12954         int                     rval = DDI_FAILURE;
12955         struct scsi_inquiry     *sd_inq = NULL;
12956         mptsas_t                *mpt = DIP2MPT(pdip);
12957 
12958         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
12959 
12960         rval = mptsas_inquiry(mpt, ptgt, lun, 0, (uchar_t *)sd_inq,
12961             SUN_INQSIZE, 0, (uchar_t)0);
12962 
12963         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
12964                 rval = mptsas_create_lun(pdip, sd_inq, dip, ptgt, lun);
12965         } else {
12966                 rval = DDI_FAILURE;
12967         }
12968 
12969         kmem_free(sd_inq, SUN_INQSIZE);
12970         return (rval);
12971 }
12972 
12973 static int
12974 mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
12975     dev_info_t **lundip)
12976 {
12977         int             rval;
12978         mptsas_t                *mpt = DIP2MPT(pdip);
12979         int             phymask;
12980         mptsas_target_t *ptgt = NULL;
12981 
12982         /*
12983          * Get the physical port associated to the iport
12984          */
12985         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
12986             "phymask", 0);
12987 
12988         ptgt = mptsas_wwid_to_ptgt(mpt, phymask, sasaddr);
12989         if (ptgt == NULL) {
12990                 /*
12991                  * didn't match any device by searching
12992                  */
12993                 return (DDI_FAILURE);
12994         }
12995         /*
12996          * If the LUN already exists and the status is online,
12997          * we just return the pointer to dev_info_t directly.
12998          * For the mdi_pathinfo node, we'll handle it in
12999          * mptsas_create_virt_lun()
13000          * TODO should be also in mptsas_handle_dr
13001          */
13002 
13003         *lundip = mptsas_find_child_addr(pdip, sasaddr, lun);
13004         if (*lundip != NULL) {
13005                 /*
13006                  * TODO Another senario is, we hotplug the same disk
13007                  * on the same slot, the devhdl changed, is this
13008                  * possible?
13009                  * tgt_private->t_private != ptgt
13010                  */
13011                 if (sasaddr != ptgt->m_addr.mta_wwn) {
13012                         /*
13013                          * The device has changed although the devhdl is the
13014                          * same (Enclosure mapping mode, change drive on the
13015                          * same slot)
13016                          */
13017                         return (DDI_FAILURE);
13018                 }
13019                 return (DDI_SUCCESS);
13020         }
13021 
13022         if (phymask == 0) {
13023                 /*
13024                  * Configure IR volume
13025                  */
13026                 rval =  mptsas_config_raid(pdip, ptgt->m_devhdl, lundip);
13027                 return (rval);
13028         }
13029         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
13030 
13031         return (rval);
13032 }
13033 
13034 static int
13035 mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
13036     dev_info_t **lundip)
13037 {
13038         int             rval;
13039         mptsas_t        *mpt = DIP2MPT(pdip);
13040         mptsas_phymask_t phymask;
13041         mptsas_target_t *ptgt = NULL;
13042 
13043         /*
13044          * Get the physical port associated to the iport
13045          */
13046         phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13047             "phymask", 0);
13048 
13049         ptgt = mptsas_phy_to_tgt(mpt, phymask, phy);
13050         if (ptgt == NULL) {
13051                 /*
13052                  * didn't match any device by searching
13053                  */
13054                 return (DDI_FAILURE);
13055         }
13056 
13057         /*
13058          * If the LUN already exists and the status is online,
13059          * we just return the pointer to dev_info_t directly.
13060          * For the mdi_pathinfo node, we'll handle it in
13061          * mptsas_create_virt_lun().
13062          */
13063 
13064         *lundip = mptsas_find_child_phy(pdip, phy);
13065         if (*lundip != NULL) {
13066                 return (DDI_SUCCESS);
13067         }
13068 
13069         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
13070 
13071         return (rval);
13072 }
13073 
13074 static int
13075 mptsas_retrieve_lundata(int lun_cnt, uint8_t *buf, uint16_t *lun_num,
13076     uint8_t *lun_addr_type)
13077 {
13078         uint32_t        lun_idx = 0;
13079 
13080         ASSERT(lun_num != NULL);
13081         ASSERT(lun_addr_type != NULL);
13082 
13083         lun_idx = (lun_cnt + 1) * MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
13084         /* determine report luns addressing type */
13085         switch (buf[lun_idx] & MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) {
13086                 /*
13087                  * Vendors in the field have been found to be concatenating
13088                  * bus/target/lun to equal the complete lun value instead
13089                  * of switching to flat space addressing
13090                  */
13091                 /* 00b - peripheral device addressing method */
13092         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_PERIPHERAL:
13093                 /* FALLTHRU */
13094                 /* 10b - logical unit addressing method */
13095         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT:
13096                 /* FALLTHRU */
13097                 /* 01b - flat space addressing method */
13098         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE:
13099                 /* byte0 bit0-5=msb lun byte1 bit0-7=lsb lun */
13100                 *lun_addr_type = (buf[lun_idx] &
13101                     MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) >> 6;
13102                 *lun_num = (buf[lun_idx] & 0x3F) << 8;
13103                 *lun_num |= buf[lun_idx + 1];
13104                 return (DDI_SUCCESS);
13105         default:
13106                 return (DDI_FAILURE);
13107         }
13108 }
13109 
13110 static int
13111 mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt)
13112 {
13113         struct buf              *repluns_bp = NULL;
13114         struct scsi_address     ap;
13115         uchar_t                 cdb[CDB_GROUP5];
13116         int                     ret = DDI_FAILURE;
13117         int                     retry = 0;
13118         int                     lun_list_len = 0;
13119         uint16_t                lun_num = 0;
13120         uint8_t                 lun_addr_type = 0;
13121         uint32_t                lun_cnt = 0;
13122         uint32_t                lun_total = 0;
13123         dev_info_t              *cdip = NULL;
13124         uint16_t                *saved_repluns = NULL;
13125         char                    *buffer = NULL;
13126         int                     buf_len = 128;
13127         mptsas_t                *mpt = DIP2MPT(pdip);
13128         uint64_t                sas_wwn = 0;
13129         uint8_t                 phy = 0xFF;
13130         uint32_t                dev_info = 0;
13131 
13132         mutex_enter(&mpt->m_mutex);
13133         sas_wwn = ptgt->m_addr.mta_wwn;
13134         phy = ptgt->m_phynum;
13135         dev_info = ptgt->m_deviceinfo;
13136         mutex_exit(&mpt->m_mutex);
13137 
13138         if (sas_wwn == 0) {
13139                 /*
13140                  * It's a SATA without Device Name
13141                  * So don't try multi-LUNs
13142                  */
13143                 if (mptsas_find_child_phy(pdip, phy)) {
13144                         return (DDI_SUCCESS);
13145                 } else {
13146                         /*
13147                          * need configure and create node
13148                          */
13149                         return (DDI_FAILURE);
13150                 }
13151         }
13152 
13153         /*
13154          * WWN (SAS address or Device Name exist)
13155          */
13156         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
13157             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
13158                 /*
13159                  * SATA device with Device Name
13160                  * So don't try multi-LUNs
13161                  */
13162                 if (mptsas_find_child_addr(pdip, sas_wwn, 0)) {
13163                         return (DDI_SUCCESS);
13164                 } else {
13165                         return (DDI_FAILURE);
13166                 }
13167         }
13168 
13169         do {
13170                 ap.a_target = MPTSAS_INVALID_DEVHDL;
13171                 ap.a_lun = 0;
13172                 ap.a_hba_tran = mpt->m_tran;
13173                 repluns_bp = scsi_alloc_consistent_buf(&ap,
13174                     (struct buf *)NULL, buf_len, B_READ, NULL_FUNC, NULL);
13175                 if (repluns_bp == NULL) {
13176                         retry++;
13177                         continue;
13178                 }
13179                 bzero(cdb, CDB_GROUP5);
13180                 cdb[0] = SCMD_REPORT_LUNS;
13181                 cdb[6] = (buf_len & 0xff000000) >> 24;
13182                 cdb[7] = (buf_len & 0x00ff0000) >> 16;
13183                 cdb[8] = (buf_len & 0x0000ff00) >> 8;
13184                 cdb[9] = (buf_len & 0x000000ff);
13185 
13186                 ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP5,
13187                     repluns_bp, NULL);
13188                 if (ret != DDI_SUCCESS) {
13189                         scsi_free_consistent_buf(repluns_bp);
13190                         retry++;
13191                         continue;
13192                 }
13193                 lun_list_len = BE_32(*(int *)((void *)(
13194                     repluns_bp->b_un.b_addr)));
13195                 if (buf_len >= lun_list_len + 8) {
13196                         ret = DDI_SUCCESS;
13197                         break;
13198                 }
13199                 scsi_free_consistent_buf(repluns_bp);
13200                 buf_len = lun_list_len + 8;
13201 
13202         } while (retry < 3);
13203 
13204         if (ret != DDI_SUCCESS)
13205                 return (ret);
13206         buffer = (char *)repluns_bp->b_un.b_addr;
13207         /*
13208          * find out the number of luns returned by the SCSI ReportLun call
13209          * and allocate buffer space
13210          */
13211         lun_total = lun_list_len / MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
13212         saved_repluns = kmem_zalloc(sizeof (uint16_t) * lun_total, KM_SLEEP);
13213         if (saved_repluns == NULL) {
13214                 scsi_free_consistent_buf(repluns_bp);
13215                 return (DDI_FAILURE);
13216         }
13217         for (lun_cnt = 0; lun_cnt < lun_total; lun_cnt++) {
13218                 if (mptsas_retrieve_lundata(lun_cnt, (uint8_t *)(buffer),
13219                     &lun_num, &lun_addr_type) != DDI_SUCCESS) {
13220                         continue;
13221                 }
13222                 saved_repluns[lun_cnt] = lun_num;
13223                 if (cdip = mptsas_find_child_addr(pdip, sas_wwn, lun_num))
13224                         ret = DDI_SUCCESS;
13225                 else
13226                         ret = mptsas_probe_lun(pdip, lun_num, &cdip,
13227                             ptgt);
13228                 if ((ret == DDI_SUCCESS) && (cdip != NULL)) {
13229                         (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip,
13230                             MPTSAS_DEV_GONE);
13231                 }
13232         }
13233         mptsas_offline_missed_luns(pdip, saved_repluns, lun_total, ptgt);
13234         kmem_free(saved_repluns, sizeof (uint16_t) * lun_total);
13235         scsi_free_consistent_buf(repluns_bp);
13236         return (DDI_SUCCESS);
13237 }
13238 
13239 static int
13240 mptsas_config_raid(dev_info_t *pdip, uint16_t target, dev_info_t **dip)
13241 {
13242         int                     rval = DDI_FAILURE;
13243         struct scsi_inquiry     *sd_inq = NULL;
13244         mptsas_t                *mpt = DIP2MPT(pdip);
13245         mptsas_target_t         *ptgt = NULL;
13246 
13247         mutex_enter(&mpt->m_mutex);
13248         ptgt = refhash_linear_search(mpt->m_targets,
13249             mptsas_target_eval_devhdl, &target);
13250         mutex_exit(&mpt->m_mutex);
13251         if (ptgt == NULL) {
13252                 mptsas_log(mpt, CE_WARN, "Volume with VolDevHandle of 0x%x "
13253                     "not found.", target);
13254                 return (rval);
13255         }
13256 
13257         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
13258         rval = mptsas_inquiry(mpt, ptgt, 0, 0, (uchar_t *)sd_inq,
13259             SUN_INQSIZE, 0, (uchar_t)0);
13260 
13261         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
13262                 rval = mptsas_create_phys_lun(pdip, sd_inq, NULL, dip, ptgt,
13263                     0);
13264         } else {
13265                 rval = DDI_FAILURE;
13266         }
13267 
13268         kmem_free(sd_inq, SUN_INQSIZE);
13269         return (rval);
13270 }
13271 
13272 /*
13273  * configure all RAID volumes for virtual iport
13274  */
13275 static void
13276 mptsas_config_all_viport(dev_info_t *pdip)
13277 {
13278         mptsas_t        *mpt = DIP2MPT(pdip);
13279         int             config, vol;
13280         int             target;
13281         dev_info_t      *lundip = NULL;
13282 
13283         /*
13284          * Get latest RAID info and search for any Volume DevHandles.  If any
13285          * are found, configure the volume.
13286          */
13287         mutex_enter(&mpt->m_mutex);
13288         for (config = 0; config < mpt->m_num_raid_configs; config++) {
13289                 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
13290                         if (mpt->m_raidconfig[config].m_raidvol[vol].m_israid
13291                             == 1) {
13292                                 target = mpt->m_raidconfig[config].
13293                                     m_raidvol[vol].m_raidhandle;
13294                                 mutex_exit(&mpt->m_mutex);
13295                                 (void) mptsas_config_raid(pdip, target,
13296                                     &lundip);
13297                                 mutex_enter(&mpt->m_mutex);
13298                         }
13299                 }
13300         }
13301         mutex_exit(&mpt->m_mutex);
13302 }
13303 
13304 static void
13305 mptsas_offline_missed_luns(dev_info_t *pdip, uint16_t *repluns,
13306     int lun_cnt, mptsas_target_t *ptgt)
13307 {
13308         dev_info_t      *child = NULL, *savechild = NULL;
13309         mdi_pathinfo_t  *pip = NULL, *savepip = NULL;
13310         uint64_t        sas_wwn, wwid;
13311         uint8_t         phy;
13312         int             lun;
13313         int             i;
13314         int             find;
13315         char            *addr;
13316         char            *nodename;
13317         mptsas_t        *mpt = DIP2MPT(pdip);
13318 
13319         mutex_enter(&mpt->m_mutex);
13320         wwid = ptgt->m_addr.mta_wwn;
13321         mutex_exit(&mpt->m_mutex);
13322 
13323         child = ddi_get_child(pdip);
13324         while (child) {
13325                 find = 0;
13326                 savechild = child;
13327                 child = ddi_get_next_sibling(child);
13328 
13329                 nodename = ddi_node_name(savechild);
13330                 if (strcmp(nodename, "smp") == 0) {
13331                         continue;
13332                 }
13333 
13334                 addr = ddi_get_name_addr(savechild);
13335                 if (addr == NULL) {
13336                         continue;
13337                 }
13338 
13339                 if (mptsas_parse_address(addr, &sas_wwn, &phy, &lun) !=
13340                     DDI_SUCCESS) {
13341                         continue;
13342                 }
13343 
13344                 if (wwid == sas_wwn) {
13345                         for (i = 0; i < lun_cnt; i++) {
13346                                 if (repluns[i] == lun) {
13347                                         find = 1;
13348                                         break;
13349                                 }
13350                         }
13351                 } else {
13352                         continue;
13353                 }
13354                 if (find == 0) {
13355                         /*
13356                          * The lun has not been there already
13357                          */
13358                         (void) mptsas_offline_lun(pdip, savechild, NULL,
13359                             NDI_DEVI_REMOVE);
13360                 }
13361         }
13362 
13363         pip = mdi_get_next_client_path(pdip, NULL);
13364         while (pip) {
13365                 find = 0;
13366                 savepip = pip;
13367                 addr = MDI_PI(pip)->pi_addr;
13368 
13369                 pip = mdi_get_next_client_path(pdip, pip);
13370 
13371                 if (addr == NULL) {
13372                         continue;
13373                 }
13374 
13375                 if (mptsas_parse_address(addr, &sas_wwn, &phy,
13376                     &lun) != DDI_SUCCESS) {
13377                         continue;
13378                 }
13379 
13380                 if (sas_wwn == wwid) {
13381                         for (i = 0; i < lun_cnt; i++) {
13382                                 if (repluns[i] == lun) {
13383                                         find = 1;
13384                                         break;
13385                                 }
13386                         }
13387                 } else {
13388                         continue;
13389                 }
13390 
13391                 if (find == 0) {
13392                         /*
13393                          * The lun has not been there already
13394                          */
13395                         (void) mptsas_offline_lun(pdip, NULL, savepip,
13396                             NDI_DEVI_REMOVE);
13397                 }
13398         }
13399 }
13400 
13401 void
13402 mptsas_update_hashtab(struct mptsas *mpt)
13403 {
13404         uint32_t        page_address;
13405         int             rval = 0;
13406         uint16_t        dev_handle;
13407         mptsas_target_t *ptgt = NULL;
13408         mptsas_smp_t    smp_node;
13409 
13410         /*
13411          * Get latest RAID info.
13412          */
13413         (void) mptsas_get_raid_info(mpt);
13414 
13415         dev_handle = mpt->m_smp_devhdl;
13416         for (; mpt->m_done_traverse_smp == 0; ) {
13417                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
13418                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)dev_handle;
13419                 if (mptsas_get_sas_expander_page0(mpt, page_address, &smp_node)
13420                     != DDI_SUCCESS) {
13421                         break;
13422                 }
13423                 mpt->m_smp_devhdl = dev_handle = smp_node.m_devhdl;
13424                 (void) mptsas_smp_alloc(mpt, &smp_node);
13425         }
13426 
13427         /*
13428          * Config target devices
13429          */
13430         dev_handle = mpt->m_dev_handle;
13431 
13432         /*
13433          * Do loop to get sas device page 0 by GetNextHandle till the
13434          * the last handle. If the sas device is a SATA/SSP target,
13435          * we try to config it.
13436          */
13437         for (; mpt->m_done_traverse_dev == 0; ) {
13438                 ptgt = NULL;
13439                 page_address =
13440                     (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
13441                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
13442                     (uint32_t)dev_handle;
13443                 rval = mptsas_get_target_device_info(mpt, page_address,
13444                     &dev_handle, &ptgt);
13445                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
13446                     (rval == DEV_INFO_FAIL_ALLOC)) {
13447                         break;
13448                 }
13449 
13450                 mpt->m_dev_handle = dev_handle;
13451         }
13452 
13453 }
13454 
13455 void
13456 mptsas_update_driver_data(struct mptsas *mpt)
13457 {
13458         mptsas_target_t *tp;
13459         mptsas_smp_t *sp;
13460 
13461         ASSERT(MUTEX_HELD(&mpt->m_mutex));
13462 
13463         /*
13464          * TODO after hard reset, update the driver data structures
13465          * 1. update port/phymask mapping table mpt->m_phy_info
13466          * 2. invalid all the entries in hash table
13467          *    m_devhdl = 0xffff and m_deviceinfo = 0
13468          * 3. call sas_device_page/expander_page to update hash table
13469          */
13470         mptsas_update_phymask(mpt);
13471         /*
13472          * Invalid the existing entries
13473          *
13474          * XXX - It seems like we should just delete everything here.  We are
13475          * holding the lock and are about to refresh all the targets in both
13476          * hashes anyway.  Given the path we're in, what outstanding async
13477          * event could possibly be trying to reference one of these things
13478          * without taking the lock, and how would that be useful anyway?
13479          */
13480         for (tp = refhash_first(mpt->m_targets); tp != NULL;
13481             tp = refhash_next(mpt->m_targets, tp)) {
13482                 tp->m_devhdl = MPTSAS_INVALID_DEVHDL;
13483                 tp->m_deviceinfo = 0;
13484                 tp->m_dr_flag = MPTSAS_DR_INACTIVE;
13485         }
13486         for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
13487             sp = refhash_next(mpt->m_smp_targets, sp)) {
13488                 sp->m_devhdl = MPTSAS_INVALID_DEVHDL;
13489                 sp->m_deviceinfo = 0;
13490         }
13491         mpt->m_done_traverse_dev = 0;
13492         mpt->m_done_traverse_smp = 0;
13493         mpt->m_dev_handle = mpt->m_smp_devhdl = MPTSAS_INVALID_DEVHDL;
13494         mptsas_update_hashtab(mpt);
13495 }
13496 
13497 static void
13498 mptsas_config_all(dev_info_t *pdip)
13499 {
13500         dev_info_t      *smpdip = NULL;
13501         mptsas_t        *mpt = DIP2MPT(pdip);
13502         int             phymask = 0;
13503         mptsas_phymask_t phy_mask;
13504         mptsas_target_t *ptgt = NULL;
13505         mptsas_smp_t    *psmp;
13506 
13507         /*
13508          * Get the phymask associated to the iport
13509          */
13510         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13511             "phymask", 0);
13512 
13513         /*
13514          * Enumerate RAID volumes here (phymask == 0).
13515          */
13516         if (phymask == 0) {
13517                 mptsas_config_all_viport(pdip);
13518                 return;
13519         }
13520 
13521         mutex_enter(&mpt->m_mutex);
13522 
13523         if (!mpt->m_done_traverse_dev || !mpt->m_done_traverse_smp) {
13524                 mptsas_update_hashtab(mpt);
13525         }
13526 
13527         for (psmp = refhash_first(mpt->m_smp_targets); psmp != NULL;
13528             psmp = refhash_next(mpt->m_smp_targets, psmp)) {
13529                 phy_mask = psmp->m_addr.mta_phymask;
13530                 if (phy_mask == phymask) {
13531                         smpdip = NULL;
13532                         mutex_exit(&mpt->m_mutex);
13533                         (void) mptsas_online_smp(pdip, psmp, &smpdip);
13534                         mutex_enter(&mpt->m_mutex);
13535                 }
13536         }
13537 
13538         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
13539             ptgt = refhash_next(mpt->m_targets, ptgt)) {
13540                 phy_mask = ptgt->m_addr.mta_phymask;
13541                 if (phy_mask == phymask) {
13542                         mutex_exit(&mpt->m_mutex);
13543                         (void) mptsas_config_target(pdip, ptgt);
13544                         mutex_enter(&mpt->m_mutex);
13545                 }
13546         }
13547         mutex_exit(&mpt->m_mutex);
13548 }
13549 
13550 static int
13551 mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt)
13552 {
13553         int             rval = DDI_FAILURE;
13554         dev_info_t      *tdip;
13555 
13556         rval = mptsas_config_luns(pdip, ptgt);
13557         if (rval != DDI_SUCCESS) {
13558                 /*
13559                  * The return value means the SCMD_REPORT_LUNS
13560                  * did not execute successfully. The target maybe
13561                  * doesn't support such command.
13562                  */
13563                 rval = mptsas_probe_lun(pdip, 0, &tdip, ptgt);
13564         }
13565         return (rval);
13566 }
13567 
13568 /*
13569  * Return fail if not all the childs/paths are freed.
13570  * if there is any path under the HBA, the return value will be always fail
13571  * because we didn't call mdi_pi_free for path
13572  */
13573 static int
13574 mptsas_offline_target(dev_info_t *pdip, char *name)
13575 {
13576         dev_info_t              *child = NULL, *prechild = NULL;
13577         mdi_pathinfo_t          *pip = NULL, *savepip = NULL;
13578         int                     tmp_rval, rval = DDI_SUCCESS;
13579         char                    *addr, *cp;
13580         size_t                  s;
13581         mptsas_t                *mpt = DIP2MPT(pdip);
13582 
13583         child = ddi_get_child(pdip);
13584         while (child) {
13585                 addr = ddi_get_name_addr(child);
13586                 prechild = child;
13587                 child = ddi_get_next_sibling(child);
13588 
13589                 if (addr == NULL) {
13590                         continue;
13591                 }
13592                 if ((cp = strchr(addr, ',')) == NULL) {
13593                         continue;
13594                 }
13595 
13596                 s = (uintptr_t)cp - (uintptr_t)addr;
13597 
13598                 if (strncmp(addr, name, s) != 0) {
13599                         continue;
13600                 }
13601 
13602                 tmp_rval = mptsas_offline_lun(pdip, prechild, NULL,
13603                     NDI_DEVI_REMOVE);
13604                 if (tmp_rval != DDI_SUCCESS) {
13605                         rval = DDI_FAILURE;
13606                         if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
13607                             prechild, MPTSAS_DEV_GONE) !=
13608                             DDI_PROP_SUCCESS) {
13609                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
13610                                     "unable to create property for "
13611                                     "SAS %s (MPTSAS_DEV_GONE)", addr);
13612                         }
13613                 }
13614         }
13615 
13616         pip = mdi_get_next_client_path(pdip, NULL);
13617         while (pip) {
13618                 addr = MDI_PI(pip)->pi_addr;
13619                 savepip = pip;
13620                 pip = mdi_get_next_client_path(pdip, pip);
13621                 if (addr == NULL) {
13622                         continue;
13623                 }
13624 
13625                 if ((cp = strchr(addr, ',')) == NULL) {
13626                         continue;
13627                 }
13628 
13629                 s = (uintptr_t)cp - (uintptr_t)addr;
13630 
13631                 if (strncmp(addr, name, s) != 0) {
13632                         continue;
13633                 }
13634 
13635                 (void) mptsas_offline_lun(pdip, NULL, savepip,
13636                     NDI_DEVI_REMOVE);
13637                 /*
13638                  * driver will not invoke mdi_pi_free, so path will not
13639                  * be freed forever, return DDI_FAILURE.
13640                  */
13641                 rval = DDI_FAILURE;
13642         }
13643         return (rval);
13644 }
13645 
13646 static int
13647 mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
13648     mdi_pathinfo_t *rpip, uint_t flags)
13649 {
13650         int             rval = DDI_FAILURE;
13651         char            *devname;
13652         dev_info_t      *cdip, *parent;
13653 
13654         if (rpip != NULL) {
13655                 parent = scsi_vhci_dip;
13656                 cdip = mdi_pi_get_client(rpip);
13657         } else if (rdip != NULL) {
13658                 parent = pdip;
13659                 cdip = rdip;
13660         } else {
13661                 return (DDI_FAILURE);
13662         }
13663 
13664         /*
13665          * Make sure node is attached otherwise
13666          * it won't have related cache nodes to
13667          * clean up.  i_ddi_devi_attached is
13668          * similiar to i_ddi_node_state(cdip) >=
13669          * DS_ATTACHED.
13670          */
13671         if (i_ddi_devi_attached(cdip)) {
13672 
13673                 /* Get full devname */
13674                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
13675                 (void) ddi_deviname(cdip, devname);
13676                 /* Clean cache */
13677                 (void) devfs_clean(parent, devname + 1,
13678                     DV_CLEAN_FORCE);
13679                 kmem_free(devname, MAXNAMELEN + 1);
13680         }
13681         if (rpip != NULL) {
13682                 if (MDI_PI_IS_OFFLINE(rpip)) {
13683                         rval = DDI_SUCCESS;
13684                 } else {
13685                         rval = mdi_pi_offline(rpip, 0);
13686                 }
13687         } else {
13688                 rval = ndi_devi_offline(cdip, flags);
13689         }
13690 
13691         return (rval);
13692 }
13693 
13694 static dev_info_t *
13695 mptsas_find_smp_child(dev_info_t *parent, char *str_wwn)
13696 {
13697         dev_info_t      *child = NULL;
13698         char            *smp_wwn = NULL;
13699 
13700         child = ddi_get_child(parent);
13701         while (child) {
13702                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
13703                     DDI_PROP_DONTPASS, SMP_WWN, &smp_wwn)
13704                     != DDI_SUCCESS) {
13705                         child = ddi_get_next_sibling(child);
13706                         continue;
13707                 }
13708 
13709                 if (strcmp(smp_wwn, str_wwn) == 0) {
13710                         ddi_prop_free(smp_wwn);
13711                         break;
13712                 }
13713                 child = ddi_get_next_sibling(child);
13714                 ddi_prop_free(smp_wwn);
13715         }
13716         return (child);
13717 }
13718 
13719 static int
13720 mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, uint_t flags)
13721 {
13722         int             rval = DDI_FAILURE;
13723         char            *devname;
13724         char            wwn_str[MPTSAS_WWN_STRLEN];
13725         dev_info_t      *cdip;
13726 
13727         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
13728 
13729         cdip = mptsas_find_smp_child(pdip, wwn_str);
13730 
13731         if (cdip == NULL)
13732                 return (DDI_SUCCESS);
13733 
13734         /*
13735          * Make sure node is attached otherwise
13736          * it won't have related cache nodes to
13737          * clean up.  i_ddi_devi_attached is
13738          * similiar to i_ddi_node_state(cdip) >=
13739          * DS_ATTACHED.
13740          */
13741         if (i_ddi_devi_attached(cdip)) {
13742 
13743                 /* Get full devname */
13744                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
13745                 (void) ddi_deviname(cdip, devname);
13746                 /* Clean cache */
13747                 (void) devfs_clean(pdip, devname + 1,
13748                     DV_CLEAN_FORCE);
13749                 kmem_free(devname, MAXNAMELEN + 1);
13750         }
13751 
13752         rval = ndi_devi_offline(cdip, flags);
13753 
13754         return (rval);
13755 }
13756 
13757 static dev_info_t *
13758 mptsas_find_child(dev_info_t *pdip, char *name)
13759 {
13760         dev_info_t      *child = NULL;
13761         char            *rname = NULL;
13762         int             rval = DDI_FAILURE;
13763 
13764         rname = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13765 
13766         child = ddi_get_child(pdip);
13767         while (child) {
13768                 rval = mptsas_name_child(child, rname, SCSI_MAXNAMELEN);
13769                 if (rval != DDI_SUCCESS) {
13770                         child = ddi_get_next_sibling(child);
13771                         bzero(rname, SCSI_MAXNAMELEN);
13772                         continue;
13773                 }
13774 
13775                 if (strcmp(rname, name) == 0) {
13776                         break;
13777                 }
13778                 child = ddi_get_next_sibling(child);
13779                 bzero(rname, SCSI_MAXNAMELEN);
13780         }
13781 
13782         kmem_free(rname, SCSI_MAXNAMELEN);
13783 
13784         return (child);
13785 }
13786 
13787 
13788 static dev_info_t *
13789 mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr, int lun)
13790 {
13791         dev_info_t      *child = NULL;
13792         char            *name = NULL;
13793         char            *addr = NULL;
13794 
13795         name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13796         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13797         (void) sprintf(name, "%016"PRIx64, sasaddr);
13798         (void) sprintf(addr, "w%s,%x", name, lun);
13799         child = mptsas_find_child(pdip, addr);
13800         kmem_free(name, SCSI_MAXNAMELEN);
13801         kmem_free(addr, SCSI_MAXNAMELEN);
13802         return (child);
13803 }
13804 
13805 static dev_info_t *
13806 mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy)
13807 {
13808         dev_info_t      *child;
13809         char            *addr;
13810 
13811         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13812         (void) sprintf(addr, "p%x,0", phy);
13813         child = mptsas_find_child(pdip, addr);
13814         kmem_free(addr, SCSI_MAXNAMELEN);
13815         return (child);
13816 }
13817 
13818 static mdi_pathinfo_t *
13819 mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy)
13820 {
13821         mdi_pathinfo_t  *path;
13822         char            *addr = NULL;
13823 
13824         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13825         (void) sprintf(addr, "p%x,0", phy);
13826         path = mdi_pi_find(pdip, NULL, addr);
13827         kmem_free(addr, SCSI_MAXNAMELEN);
13828         return (path);
13829 }
13830 
13831 static mdi_pathinfo_t *
13832 mptsas_find_path_addr(dev_info_t *parent, uint64_t sasaddr, int lun)
13833 {
13834         mdi_pathinfo_t  *path;
13835         char            *name = NULL;
13836         char            *addr = NULL;
13837 
13838         name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13839         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13840         (void) sprintf(name, "%016"PRIx64, sasaddr);
13841         (void) sprintf(addr, "w%s,%x", name, lun);
13842         path = mdi_pi_find(parent, NULL, addr);
13843         kmem_free(name, SCSI_MAXNAMELEN);
13844         kmem_free(addr, SCSI_MAXNAMELEN);
13845 
13846         return (path);
13847 }
13848 
13849 static int
13850 mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
13851     dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
13852 {
13853         int                     i = 0;
13854         uchar_t                 *inq83 = NULL;
13855         int                     inq83_len1 = 0xFF;
13856         int                     inq83_len = 0;
13857         int                     rval = DDI_FAILURE;
13858         ddi_devid_t             devid;
13859         char                    *guid = NULL;
13860         int                     target = ptgt->m_devhdl;
13861         mdi_pathinfo_t          *pip = NULL;
13862         mptsas_t                *mpt = DIP2MPT(pdip);
13863 
13864         /*
13865          * For DVD/CD ROM and tape devices and optical
13866          * devices, we won't try to enumerate them under
13867          * scsi_vhci, so no need to try page83
13868          */
13869         if (sd_inq && (sd_inq->inq_dtype == DTYPE_RODIRECT ||
13870             sd_inq->inq_dtype == DTYPE_OPTICAL ||
13871             sd_inq->inq_dtype == DTYPE_ESI))
13872                 goto create_lun;
13873 
13874         /*
13875          * The LCA returns good SCSI status, but corrupt page 83 data the first
13876          * time it is queried. The solution is to keep trying to request page83
13877          * and verify the GUID is not (DDI_NOT_WELL_FORMED) in
13878          * mptsas_inq83_retry_timeout seconds. If the timeout expires, driver
13879          * give up to get VPD page at this stage and fail the enumeration.
13880          */
13881 
13882         inq83   = kmem_zalloc(inq83_len1, KM_SLEEP);
13883 
13884         for (i = 0; i < mptsas_inq83_retry_timeout; i++) {
13885                 rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
13886                     inq83_len1, &inq83_len, 1);
13887                 if (rval != 0) {
13888                         mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
13889                             "0x83 for target:%x, lun:%x failed!", target, lun);
13890                         if (mptsas_physical_bind_failed_page_83 != B_FALSE)
13891                                 goto create_lun;
13892                         goto out;
13893                 }
13894                 /*
13895                  * create DEVID from inquiry data
13896                  */
13897                 if ((rval = ddi_devid_scsi_encode(
13898                     DEVID_SCSI_ENCODE_VERSION_LATEST, NULL, (uchar_t *)sd_inq,
13899                     sizeof (struct scsi_inquiry), NULL, 0, inq83,
13900                     (size_t)inq83_len, &devid)) == DDI_SUCCESS) {
13901                         /*
13902                          * extract GUID from DEVID
13903                          */
13904                         guid = ddi_devid_to_guid(devid);
13905 
13906                         /*
13907                          * Do not enable MPXIO if the strlen(guid) is greater
13908                          * than MPTSAS_MAX_GUID_LEN, this constrain would be
13909                          * handled by framework later.
13910                          */
13911                         if (guid && (strlen(guid) > MPTSAS_MAX_GUID_LEN)) {
13912                                 ddi_devid_free_guid(guid);
13913                                 guid = NULL;
13914                                 if (mpt->m_mpxio_enable == TRUE) {
13915                                         mptsas_log(mpt, CE_NOTE, "!Target:%x, "
13916                                             "lun:%x doesn't have a valid GUID, "
13917                                             "multipathing for this drive is "
13918                                             "not enabled", target, lun);
13919                                 }
13920                         }
13921 
13922                         /*
13923                          * devid no longer needed
13924                          */
13925                         ddi_devid_free(devid);
13926                         break;
13927                 } else if (rval == DDI_NOT_WELL_FORMED) {
13928                         /*
13929                          * return value of ddi_devid_scsi_encode equal to
13930                          * DDI_NOT_WELL_FORMED means DEVID_RETRY, it worth
13931                          * to retry inquiry page 0x83 and get GUID.
13932                          */
13933                         NDBG20(("Not well formed devid, retry..."));
13934                         delay(1 * drv_usectohz(1000000));
13935                         continue;
13936                 } else {
13937                         mptsas_log(mpt, CE_WARN, "!Encode devid failed for "
13938                             "path target:%x, lun:%x", target, lun);
13939                         rval = DDI_FAILURE;
13940                         goto create_lun;
13941                 }
13942         }
13943 
13944         if (i == mptsas_inq83_retry_timeout) {
13945                 mptsas_log(mpt, CE_WARN, "!Repeated page83 requests timeout "
13946                     "for path target:%x, lun:%x", target, lun);
13947         }
13948 
13949         rval = DDI_FAILURE;
13950 
13951 create_lun:
13952         if ((guid != NULL) && (mpt->m_mpxio_enable == TRUE)) {
13953                 rval = mptsas_create_virt_lun(pdip, sd_inq, guid, lun_dip, &pip,
13954                     ptgt, lun);
13955         }
13956         if (rval != DDI_SUCCESS) {
13957                 rval = mptsas_create_phys_lun(pdip, sd_inq, guid, lun_dip,
13958                     ptgt, lun);
13959 
13960         }
13961 out:
13962         if (guid != NULL) {
13963                 /*
13964                  * guid no longer needed
13965                  */
13966                 ddi_devid_free_guid(guid);
13967         }
13968         if (inq83 != NULL)
13969                 kmem_free(inq83, inq83_len1);
13970         return (rval);
13971 }
13972 
13973 static int
13974 mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *inq, char *guid,
13975     dev_info_t **lun_dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt, int lun)
13976 {
13977         int                     target;
13978         char                    *nodename = NULL;
13979         char                    **compatible = NULL;
13980         int                     ncompatible     = 0;
13981         int                     mdi_rtn = MDI_FAILURE;
13982         int                     rval = DDI_FAILURE;
13983         char                    *old_guid = NULL;
13984         mptsas_t                *mpt = DIP2MPT(pdip);
13985         char                    *lun_addr = NULL;
13986         char                    *wwn_str = NULL;
13987         char                    *attached_wwn_str = NULL;
13988         char                    *component = NULL;
13989         uint8_t                 phy = 0xFF;
13990         uint64_t                sas_wwn;
13991         int64_t                 lun64 = 0;
13992         uint32_t                devinfo;
13993         uint16_t                dev_hdl;
13994         uint16_t                pdev_hdl;
13995         uint64_t                dev_sas_wwn;
13996         uint64_t                pdev_sas_wwn;
13997         uint32_t                pdev_info;
13998         uint8_t                 physport;
13999         uint8_t                 phy_id;
14000         uint32_t                page_address;
14001         uint16_t                bay_num, enclosure;
14002         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
14003         uint32_t                dev_info;
14004 
14005         mutex_enter(&mpt->m_mutex);
14006         target = ptgt->m_devhdl;
14007         sas_wwn = ptgt->m_addr.mta_wwn;
14008         devinfo = ptgt->m_deviceinfo;
14009         phy = ptgt->m_phynum;
14010         mutex_exit(&mpt->m_mutex);
14011 
14012         if (sas_wwn) {
14013                 *pip = mptsas_find_path_addr(pdip, sas_wwn, lun);
14014         } else {
14015                 *pip = mptsas_find_path_phy(pdip, phy);
14016         }
14017 
14018         if (*pip != NULL) {
14019                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14020                 ASSERT(*lun_dip != NULL);
14021                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, *lun_dip,
14022                     (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
14023                     MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
14024                         if (strncmp(guid, old_guid, strlen(guid)) == 0) {
14025                                 /*
14026                                  * Same path back online again.
14027                                  */
14028                                 (void) ddi_prop_free(old_guid);
14029                                 if ((!MDI_PI_IS_ONLINE(*pip)) &&
14030                                     (!MDI_PI_IS_STANDBY(*pip)) &&
14031                                     (ptgt->m_tgt_unconfigured == 0)) {
14032                                         rval = mdi_pi_online(*pip, 0);
14033                                         mutex_enter(&mpt->m_mutex);
14034                                         ptgt->m_led_status = 0;
14035                                         (void) mptsas_flush_led_status(mpt,
14036                                             ptgt);
14037                                         mutex_exit(&mpt->m_mutex);
14038                                 } else {
14039                                         rval = DDI_SUCCESS;
14040                                 }
14041                                 if (rval != DDI_SUCCESS) {
14042                                         mptsas_log(mpt, CE_WARN, "path:target: "
14043                                             "%x, lun:%x online failed!", target,
14044                                             lun);
14045                                         *pip = NULL;
14046                                         *lun_dip = NULL;
14047                                 }
14048                                 return (rval);
14049                         } else {
14050                                 /*
14051                                  * The GUID of the LUN has changed which maybe
14052                                  * because customer mapped another volume to the
14053                                  * same LUN.
14054                                  */
14055                                 mptsas_log(mpt, CE_WARN, "The GUID of the "
14056                                     "target:%x, lun:%x was changed, maybe "
14057                                     "because someone mapped another volume "
14058                                     "to the same LUN", target, lun);
14059                                 (void) ddi_prop_free(old_guid);
14060                                 if (!MDI_PI_IS_OFFLINE(*pip)) {
14061                                         rval = mdi_pi_offline(*pip, 0);
14062                                         if (rval != MDI_SUCCESS) {
14063                                                 mptsas_log(mpt, CE_WARN, "path:"
14064                                                     "target:%x, lun:%x offline "
14065                                                     "failed!", target, lun);
14066                                                 *pip = NULL;
14067                                                 *lun_dip = NULL;
14068                                                 return (DDI_FAILURE);
14069                                         }
14070                                 }
14071                                 if (mdi_pi_free(*pip, 0) != MDI_SUCCESS) {
14072                                         mptsas_log(mpt, CE_WARN, "path:target:"
14073                                             "%x, lun:%x free failed!", target,
14074                                             lun);
14075                                         *pip = NULL;
14076                                         *lun_dip = NULL;
14077                                         return (DDI_FAILURE);
14078                                 }
14079                         }
14080                 } else {
14081                         mptsas_log(mpt, CE_WARN, "Can't get client-guid "
14082                             "property for path:target:%x, lun:%x", target, lun);
14083                         *pip = NULL;
14084                         *lun_dip = NULL;
14085                         return (DDI_FAILURE);
14086                 }
14087         }
14088         scsi_hba_nodename_compatible_get(inq, NULL,
14089             inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
14090 
14091         /*
14092          * if nodename can't be determined then print a message and skip it
14093          */
14094         if (nodename == NULL) {
14095                 mptsas_log(mpt, CE_WARN, "mptsas driver found no compatible "
14096                     "driver for target%d lun %d dtype:0x%02x", target, lun,
14097                     inq->inq_dtype);
14098                 return (DDI_FAILURE);
14099         }
14100 
14101         wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
14102         /* The property is needed by MPAPI */
14103         (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
14104 
14105         lun_addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14106         if (guid) {
14107                 (void) sprintf(lun_addr, "w%s,%x", wwn_str, lun);
14108                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14109         } else {
14110                 (void) sprintf(lun_addr, "p%x,%x", phy, lun);
14111                 (void) sprintf(wwn_str, "p%x", phy);
14112         }
14113 
14114         mdi_rtn = mdi_pi_alloc_compatible(pdip, nodename,
14115             guid, lun_addr, compatible, ncompatible,
14116             0, pip);
14117         if (mdi_rtn == MDI_SUCCESS) {
14118 
14119                 if (mdi_prop_update_string(*pip, MDI_GUID,
14120                     guid) != DDI_SUCCESS) {
14121                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14122                             "create prop for target %d lun %d (MDI_GUID)",
14123                             target, lun);
14124                         mdi_rtn = MDI_FAILURE;
14125                         goto virt_create_done;
14126                 }
14127 
14128                 if (mdi_prop_update_int(*pip, LUN_PROP,
14129                     lun) != DDI_SUCCESS) {
14130                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14131                             "create prop for target %d lun %d (LUN_PROP)",
14132                             target, lun);
14133                         mdi_rtn = MDI_FAILURE;
14134                         goto virt_create_done;
14135                 }
14136                 lun64 = (int64_t)lun;
14137                 if (mdi_prop_update_int64(*pip, LUN64_PROP,
14138                     lun64) != DDI_SUCCESS) {
14139                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14140                             "create prop for target %d (LUN64_PROP)",
14141                             target);
14142                         mdi_rtn = MDI_FAILURE;
14143                         goto virt_create_done;
14144                 }
14145                 if (mdi_prop_update_string_array(*pip, "compatible",
14146                     compatible, ncompatible) !=
14147                     DDI_PROP_SUCCESS) {
14148                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14149                             "create prop for target %d lun %d (COMPATIBLE)",
14150                             target, lun);
14151                         mdi_rtn = MDI_FAILURE;
14152                         goto virt_create_done;
14153                 }
14154                 if (sas_wwn && (mdi_prop_update_string(*pip,
14155                     SCSI_ADDR_PROP_TARGET_PORT, wwn_str) != DDI_PROP_SUCCESS)) {
14156                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14157                             "create prop for target %d lun %d "
14158                             "(target-port)", target, lun);
14159                         mdi_rtn = MDI_FAILURE;
14160                         goto virt_create_done;
14161                 } else if ((sas_wwn == 0) && (mdi_prop_update_int(*pip,
14162                     "sata-phy", phy) != DDI_PROP_SUCCESS)) {
14163                         /*
14164                          * Direct attached SATA device without DeviceName
14165                          */
14166                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14167                             "create prop for SAS target %d lun %d "
14168                             "(sata-phy)", target, lun);
14169                         mdi_rtn = MDI_FAILURE;
14170                         goto virt_create_done;
14171                 }
14172                 mutex_enter(&mpt->m_mutex);
14173 
14174                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14175                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14176                     (uint32_t)ptgt->m_devhdl;
14177                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14178                     &dev_hdl, &dev_sas_wwn, &dev_info, &physport,
14179                     &phy_id, &pdev_hdl, &bay_num, &enclosure);
14180                 if (rval != DDI_SUCCESS) {
14181                         mutex_exit(&mpt->m_mutex);
14182                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
14183                             "parent device for handle %d", page_address);
14184                         mdi_rtn = MDI_FAILURE;
14185                         goto virt_create_done;
14186                 }
14187 
14188                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14189                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
14190                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14191                     &dev_hdl, &pdev_sas_wwn, &pdev_info, &physport,
14192                     &phy_id, &pdev_hdl, &bay_num, &enclosure);
14193                 if (rval != DDI_SUCCESS) {
14194                         mutex_exit(&mpt->m_mutex);
14195                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
14196                             "device info for handle %d", page_address);
14197                         mdi_rtn = MDI_FAILURE;
14198                         goto virt_create_done;
14199                 }
14200 
14201                 mutex_exit(&mpt->m_mutex);
14202 
14203                 /*
14204                  * If this device direct attached to the controller
14205                  * set the attached-port to the base wwid
14206                  */
14207                 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14208                     != DEVINFO_DIRECT_ATTACHED) {
14209                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14210                             pdev_sas_wwn);
14211                 } else {
14212                         /*
14213                          * Update the iport's attached-port to guid
14214                          */
14215                         if (sas_wwn == 0) {
14216                                 (void) sprintf(wwn_str, "p%x", phy);
14217                         } else {
14218                                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14219                         }
14220                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
14221                             pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
14222                             DDI_PROP_SUCCESS) {
14223                                 mptsas_log(mpt, CE_WARN,
14224                                     "mptsas unable to create "
14225                                     "property for iport target-port"
14226                                     " %s (sas_wwn)",
14227                                     wwn_str);
14228                                 mdi_rtn = MDI_FAILURE;
14229                                 goto virt_create_done;
14230                         }
14231 
14232                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14233                             mpt->un.m_base_wwid);
14234                 }
14235 
14236                 if (mdi_prop_update_string(*pip,
14237                     SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
14238                     DDI_PROP_SUCCESS) {
14239                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14240                             "property for iport attached-port %s (sas_wwn)",
14241                             attached_wwn_str);
14242                         mdi_rtn = MDI_FAILURE;
14243                         goto virt_create_done;
14244                 }
14245 
14246 
14247                 if (inq->inq_dtype == 0) {
14248                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
14249                         /*
14250                          * set obp path for pathinfo
14251                          */
14252                         (void) snprintf(component, MAXPATHLEN,
14253                             "disk@%s", lun_addr);
14254 
14255                         if (mdi_pi_pathname_obp_set(*pip, component) !=
14256                             DDI_SUCCESS) {
14257                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
14258                                     "unable to set obp-path for object %s",
14259                                     component);
14260                                 mdi_rtn = MDI_FAILURE;
14261                                 goto virt_create_done;
14262                         }
14263                 }
14264 
14265                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14266                 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
14267                     MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
14268                         if ((ndi_prop_update_int(DDI_DEV_T_NONE, *lun_dip,
14269                             "pm-capable", 1)) !=
14270                             DDI_PROP_SUCCESS) {
14271                                 mptsas_log(mpt, CE_WARN, "mptsas driver"
14272                                     "failed to create pm-capable "
14273                                     "property, target %d", target);
14274                                 mdi_rtn = MDI_FAILURE;
14275                                 goto virt_create_done;
14276                         }
14277                 }
14278                 /*
14279                  * Create the phy-num property
14280                  */
14281                 if (mdi_prop_update_int(*pip, "phy-num",
14282                     ptgt->m_phynum) != DDI_SUCCESS) {
14283                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14284                             "create phy-num property for target %d lun %d",
14285                             target, lun);
14286                         mdi_rtn = MDI_FAILURE;
14287                         goto virt_create_done;
14288                 }
14289                 NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr));
14290                 mdi_rtn = mdi_pi_online(*pip, 0);
14291                 if (mdi_rtn == MDI_SUCCESS) {
14292                         mutex_enter(&mpt->m_mutex);
14293                         ptgt->m_led_status = 0;
14294                         (void) mptsas_flush_led_status(mpt, ptgt);
14295                         mutex_exit(&mpt->m_mutex);
14296                 }
14297                 if (mdi_rtn == MDI_NOT_SUPPORTED) {
14298                         mdi_rtn = MDI_FAILURE;
14299                 }
14300 virt_create_done:
14301                 if (*pip && mdi_rtn != MDI_SUCCESS) {
14302                         (void) mdi_pi_free(*pip, 0);
14303                         *pip = NULL;
14304                         *lun_dip = NULL;
14305                 }
14306         }
14307 
14308         scsi_hba_nodename_compatible_free(nodename, compatible);
14309         if (lun_addr != NULL) {
14310                 kmem_free(lun_addr, SCSI_MAXNAMELEN);
14311         }
14312         if (wwn_str != NULL) {
14313                 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
14314         }
14315         if (component != NULL) {
14316                 kmem_free(component, MAXPATHLEN);
14317         }
14318 
14319         return ((mdi_rtn == MDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
14320 }
14321 
14322 static int
14323 mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *inq,
14324     char *guid, dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
14325 {
14326         int                     target;
14327         int                     rval;
14328         int                     ndi_rtn = NDI_FAILURE;
14329         uint64_t                be_sas_wwn;
14330         char                    *nodename = NULL;
14331         char                    **compatible = NULL;
14332         int                     ncompatible = 0;
14333         int                     instance = 0;
14334         mptsas_t                *mpt = DIP2MPT(pdip);
14335         char                    *wwn_str = NULL;
14336         char                    *component = NULL;
14337         char                    *attached_wwn_str = NULL;
14338         uint8_t                 phy = 0xFF;
14339         uint64_t                sas_wwn;
14340         uint32_t                devinfo;
14341         uint16_t                dev_hdl;
14342         uint16_t                pdev_hdl;
14343         uint64_t                pdev_sas_wwn;
14344         uint64_t                dev_sas_wwn;
14345         uint32_t                pdev_info;
14346         uint8_t                 physport;
14347         uint8_t                 phy_id;
14348         uint32_t                page_address;
14349         uint16_t                bay_num, enclosure;
14350         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
14351         uint32_t                dev_info;
14352         int64_t                 lun64 = 0;
14353 
14354         mutex_enter(&mpt->m_mutex);
14355         target = ptgt->m_devhdl;
14356         sas_wwn = ptgt->m_addr.mta_wwn;
14357         devinfo = ptgt->m_deviceinfo;
14358         phy = ptgt->m_phynum;
14359         mutex_exit(&mpt->m_mutex);
14360 
14361         /*
14362          * generate compatible property with binding-set "mpt"
14363          */
14364         scsi_hba_nodename_compatible_get(inq, NULL, inq->inq_dtype, NULL,
14365             &nodename, &compatible, &ncompatible);
14366 
14367         /*
14368          * if nodename can't be determined then print a message and skip it
14369          */
14370         if (nodename == NULL) {
14371                 mptsas_log(mpt, CE_WARN, "mptsas found no compatible driver "
14372                     "for target %d lun %d", target, lun);
14373                 return (DDI_FAILURE);
14374         }
14375 
14376         ndi_rtn = ndi_devi_alloc(pdip, nodename,
14377             DEVI_SID_NODEID, lun_dip);
14378 
14379         /*
14380          * if lun alloc success, set props
14381          */
14382         if (ndi_rtn == NDI_SUCCESS) {
14383 
14384                 if (ndi_prop_update_int(DDI_DEV_T_NONE,
14385                     *lun_dip, LUN_PROP, lun) !=
14386                     DDI_PROP_SUCCESS) {
14387                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14388                             "property for target %d lun %d (LUN_PROP)",
14389                             target, lun);
14390                         ndi_rtn = NDI_FAILURE;
14391                         goto phys_create_done;
14392                 }
14393 
14394                 lun64 = (int64_t)lun;
14395                 if (ndi_prop_update_int64(DDI_DEV_T_NONE,
14396                     *lun_dip, LUN64_PROP, lun64) !=
14397                     DDI_PROP_SUCCESS) {
14398                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14399                             "property for target %d lun64 %d (LUN64_PROP)",
14400                             target, lun);
14401                         ndi_rtn = NDI_FAILURE;
14402                         goto phys_create_done;
14403                 }
14404                 if (ndi_prop_update_string_array(DDI_DEV_T_NONE,
14405                     *lun_dip, "compatible", compatible, ncompatible)
14406                     != DDI_PROP_SUCCESS) {
14407                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14408                             "property for target %d lun %d (COMPATIBLE)",
14409                             target, lun);
14410                         ndi_rtn = NDI_FAILURE;
14411                         goto phys_create_done;
14412                 }
14413 
14414                 /*
14415                  * We need the SAS WWN for non-multipath devices, so
14416                  * we'll use the same property as that multipathing
14417                  * devices need to present for MPAPI. If we don't have
14418                  * a WWN (e.g. parallel SCSI), don't create the prop.
14419                  */
14420                 wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
14421                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14422                 if (sas_wwn && ndi_prop_update_string(DDI_DEV_T_NONE,
14423                     *lun_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str)
14424                     != DDI_PROP_SUCCESS) {
14425                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
14426                             "create property for SAS target %d lun %d "
14427                             "(target-port)", target, lun);
14428                         ndi_rtn = NDI_FAILURE;
14429                         goto phys_create_done;
14430                 }
14431 
14432                 be_sas_wwn = BE_64(sas_wwn);
14433                 if (sas_wwn && ndi_prop_update_byte_array(
14434                     DDI_DEV_T_NONE, *lun_dip, "port-wwn",
14435                     (uchar_t *)&be_sas_wwn, 8) != DDI_PROP_SUCCESS) {
14436                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
14437                             "create property for SAS target %d lun %d "
14438                             "(port-wwn)", target, lun);
14439                         ndi_rtn = NDI_FAILURE;
14440                         goto phys_create_done;
14441                 } else if ((sas_wwn == 0) && (ndi_prop_update_int(
14442                     DDI_DEV_T_NONE, *lun_dip, "sata-phy", phy) !=
14443                     DDI_PROP_SUCCESS)) {
14444                         /*
14445                          * Direct attached SATA device without DeviceName
14446                          */
14447                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
14448                             "create property for SAS target %d lun %d "
14449                             "(sata-phy)", target, lun);
14450                         ndi_rtn = NDI_FAILURE;
14451                         goto phys_create_done;
14452                 }
14453 
14454                 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
14455                     *lun_dip, SAS_PROP) != DDI_PROP_SUCCESS) {
14456                         mptsas_log(mpt, CE_WARN, "mptsas unable to"
14457                             "create property for SAS target %d lun %d"
14458                             " (SAS_PROP)", target, lun);
14459                         ndi_rtn = NDI_FAILURE;
14460                         goto phys_create_done;
14461                 }
14462                 if (guid && (ndi_prop_update_string(DDI_DEV_T_NONE,
14463                     *lun_dip, NDI_GUID, guid) != DDI_SUCCESS)) {
14464                         mptsas_log(mpt, CE_WARN, "mptsas unable "
14465                             "to create guid property for target %d "
14466                             "lun %d", target, lun);
14467                         ndi_rtn = NDI_FAILURE;
14468                         goto phys_create_done;
14469                 }
14470 
14471                 /*
14472                  * The following code is to set properties for SM-HBA support,
14473                  * it doesn't apply to RAID volumes
14474                  */
14475                 if (ptgt->m_addr.mta_phymask == 0)
14476                         goto phys_raid_lun;
14477 
14478                 mutex_enter(&mpt->m_mutex);
14479 
14480                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14481                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14482                     (uint32_t)ptgt->m_devhdl;
14483                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14484                     &dev_hdl, &dev_sas_wwn, &dev_info,
14485                     &physport, &phy_id, &pdev_hdl,
14486                     &bay_num, &enclosure);
14487                 if (rval != DDI_SUCCESS) {
14488                         mutex_exit(&mpt->m_mutex);
14489                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
14490                             "parent device for handle %d.", page_address);
14491                         ndi_rtn = NDI_FAILURE;
14492                         goto phys_create_done;
14493                 }
14494 
14495                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14496                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
14497                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14498                     &dev_hdl, &pdev_sas_wwn, &pdev_info,
14499                     &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure);
14500                 if (rval != DDI_SUCCESS) {
14501                         mutex_exit(&mpt->m_mutex);
14502                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14503                             "device for handle %d.", page_address);
14504                         ndi_rtn = NDI_FAILURE;
14505                         goto phys_create_done;
14506                 }
14507 
14508                 mutex_exit(&mpt->m_mutex);
14509 
14510                 /*
14511                  * If this device direct attached to the controller
14512                  * set the attached-port to the base wwid
14513                  */
14514                 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14515                     != DEVINFO_DIRECT_ATTACHED) {
14516                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14517                             pdev_sas_wwn);
14518                 } else {
14519                         /*
14520                          * Update the iport's attached-port to guid
14521                          */
14522                         if (sas_wwn == 0) {
14523                                 (void) sprintf(wwn_str, "p%x", phy);
14524                         } else {
14525                                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14526                         }
14527                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
14528                             pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
14529                             DDI_PROP_SUCCESS) {
14530                                 mptsas_log(mpt, CE_WARN,
14531                                     "mptsas unable to create "
14532                                     "property for iport target-port"
14533                                     " %s (sas_wwn)",
14534                                     wwn_str);
14535                                 ndi_rtn = NDI_FAILURE;
14536                                 goto phys_create_done;
14537                         }
14538 
14539                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14540                             mpt->un.m_base_wwid);
14541                 }
14542 
14543                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14544                     *lun_dip, SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
14545                     DDI_PROP_SUCCESS) {
14546                         mptsas_log(mpt, CE_WARN,
14547                             "mptsas unable to create "
14548                             "property for iport attached-port %s (sas_wwn)",
14549                             attached_wwn_str);
14550                         ndi_rtn = NDI_FAILURE;
14551                         goto phys_create_done;
14552                 }
14553 
14554                 if (IS_SATA_DEVICE(dev_info)) {
14555                         if (ndi_prop_update_string(DDI_DEV_T_NONE,
14556                             *lun_dip, MPTSAS_VARIANT, "sata") !=
14557                             DDI_PROP_SUCCESS) {
14558                                 mptsas_log(mpt, CE_WARN,
14559                                     "mptsas unable to create "
14560                                     "property for device variant ");
14561                                 ndi_rtn = NDI_FAILURE;
14562                                 goto phys_create_done;
14563                         }
14564                 }
14565 
14566                 if (IS_ATAPI_DEVICE(dev_info)) {
14567                         if (ndi_prop_update_string(DDI_DEV_T_NONE,
14568                             *lun_dip, MPTSAS_VARIANT, "atapi") !=
14569                             DDI_PROP_SUCCESS) {
14570                                 mptsas_log(mpt, CE_WARN,
14571                                     "mptsas unable to create "
14572                                     "property for device variant ");
14573                                 ndi_rtn = NDI_FAILURE;
14574                                 goto phys_create_done;
14575                         }
14576                 }
14577 
14578 phys_raid_lun:
14579                 /*
14580                  * if this is a SAS controller, and the target is a SATA
14581                  * drive, set the 'pm-capable' property for sd and if on
14582                  * an OPL platform, also check if this is an ATAPI
14583                  * device.
14584                  */
14585                 instance = ddi_get_instance(mpt->m_dip);
14586                 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
14587                     MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
14588                         NDBG2(("mptsas%d: creating pm-capable property, "
14589                             "target %d", instance, target));
14590 
14591                         if ((ndi_prop_update_int(DDI_DEV_T_NONE,
14592                             *lun_dip, "pm-capable", 1)) !=
14593                             DDI_PROP_SUCCESS) {
14594                                 mptsas_log(mpt, CE_WARN, "mptsas "
14595                                     "failed to create pm-capable "
14596                                     "property, target %d", target);
14597                                 ndi_rtn = NDI_FAILURE;
14598                                 goto phys_create_done;
14599                         }
14600 
14601                 }
14602 
14603                 if ((inq->inq_dtype == 0) || (inq->inq_dtype == 5)) {
14604                         /*
14605                          * add 'obp-path' properties for devinfo
14606                          */
14607                         bzero(wwn_str, sizeof (wwn_str));
14608                         (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
14609                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
14610                         if (guid) {
14611                                 (void) snprintf(component, MAXPATHLEN,
14612                                     "disk@w%s,%x", wwn_str, lun);
14613                         } else {
14614                                 (void) snprintf(component, MAXPATHLEN,
14615                                     "disk@p%x,%x", phy, lun);
14616                         }
14617                         if (ddi_pathname_obp_set(*lun_dip, component)
14618                             != DDI_SUCCESS) {
14619                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
14620                                     "unable to set obp-path for SAS "
14621                                     "object %s", component);
14622                                 ndi_rtn = NDI_FAILURE;
14623                                 goto phys_create_done;
14624                         }
14625                 }
14626                 /*
14627                  * Create the phy-num property for non-raid disk
14628                  */
14629                 if (ptgt->m_addr.mta_phymask != 0) {
14630                         if (ndi_prop_update_int(DDI_DEV_T_NONE,
14631                             *lun_dip, "phy-num", ptgt->m_phynum) !=
14632                             DDI_PROP_SUCCESS) {
14633                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
14634                                     "failed to create phy-num property for "
14635                                     "target %d", target);
14636                                 ndi_rtn = NDI_FAILURE;
14637                                 goto phys_create_done;
14638                         }
14639                 }
14640 phys_create_done:
14641                 /*
14642                  * If props were setup ok, online the lun
14643                  */
14644                 if (ndi_rtn == NDI_SUCCESS) {
14645                         /*
14646                          * Try to online the new node
14647                          */
14648                         ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
14649                 }
14650                 if (ndi_rtn == NDI_SUCCESS) {
14651                         mutex_enter(&mpt->m_mutex);
14652                         ptgt->m_led_status = 0;
14653                         (void) mptsas_flush_led_status(mpt, ptgt);
14654                         mutex_exit(&mpt->m_mutex);
14655                 }
14656 
14657                 /*
14658                  * If success set rtn flag, else unwire alloc'd lun
14659                  */
14660                 if (ndi_rtn != NDI_SUCCESS) {
14661                         NDBG12(("mptsas driver unable to online "
14662                             "target %d lun %d", target, lun));
14663                         ndi_prop_remove_all(*lun_dip);
14664                         (void) ndi_devi_free(*lun_dip);
14665                         *lun_dip = NULL;
14666                 }
14667         }
14668 
14669         scsi_hba_nodename_compatible_free(nodename, compatible);
14670 
14671         if (wwn_str != NULL) {
14672                 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
14673         }
14674         if (component != NULL) {
14675                 kmem_free(component, MAXPATHLEN);
14676         }
14677 
14678 
14679         return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
14680 }
14681 
14682 static int
14683 mptsas_probe_smp(dev_info_t *pdip, uint64_t wwn)
14684 {
14685         mptsas_t        *mpt = DIP2MPT(pdip);
14686         struct smp_device smp_sd;
14687 
14688         /* XXX An HBA driver should not be allocating an smp_device. */
14689         bzero(&smp_sd, sizeof (struct smp_device));
14690         smp_sd.smp_sd_address.smp_a_hba_tran = mpt->m_smptran;
14691         bcopy(&wwn, smp_sd.smp_sd_address.smp_a_wwn, SAS_WWN_BYTE_SIZE);
14692 
14693         if (smp_probe(&smp_sd) != DDI_PROBE_SUCCESS)
14694                 return (NDI_FAILURE);
14695         return (NDI_SUCCESS);
14696 }
14697 
14698 static int
14699 mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn, dev_info_t **smp_dip)
14700 {
14701         mptsas_t        *mpt = DIP2MPT(pdip);
14702         mptsas_smp_t    *psmp = NULL;
14703         int             rval;
14704         int             phymask;
14705 
14706         /*
14707          * Get the physical port associated to the iport
14708          * PHYMASK TODO
14709          */
14710         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
14711             "phymask", 0);
14712         /*
14713          * Find the smp node in hash table with specified sas address and
14714          * physical port
14715          */
14716         psmp = mptsas_wwid_to_psmp(mpt, phymask, sas_wwn);
14717         if (psmp == NULL) {
14718                 return (DDI_FAILURE);
14719         }
14720 
14721         rval = mptsas_online_smp(pdip, psmp, smp_dip);
14722 
14723         return (rval);
14724 }
14725 
14726 static int
14727 mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
14728     dev_info_t **smp_dip)
14729 {
14730         char            wwn_str[MPTSAS_WWN_STRLEN];
14731         char            attached_wwn_str[MPTSAS_WWN_STRLEN];
14732         int             ndi_rtn = NDI_FAILURE;
14733         int             rval = 0;
14734         mptsas_smp_t    dev_info;
14735         uint32_t        page_address;
14736         mptsas_t        *mpt = DIP2MPT(pdip);
14737         uint16_t        dev_hdl;
14738         uint64_t        sas_wwn;
14739         uint64_t        smp_sas_wwn;
14740         uint8_t         physport;
14741         uint8_t         phy_id;
14742         uint16_t        pdev_hdl;
14743         uint8_t         numphys = 0;
14744         uint16_t        i = 0;
14745         char            phymask[MPTSAS_MAX_PHYS];
14746         char            *iport = NULL;
14747         mptsas_phymask_t        phy_mask = 0;
14748         uint16_t        attached_devhdl;
14749         uint16_t        bay_num, enclosure;
14750 
14751         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
14752 
14753         /*
14754          * Probe smp device, prevent the node of removed device from being
14755          * configured succesfully
14756          */
14757         if (mptsas_probe_smp(pdip, smp_node->m_addr.mta_wwn) != NDI_SUCCESS) {
14758                 return (DDI_FAILURE);
14759         }
14760 
14761         if ((*smp_dip = mptsas_find_smp_child(pdip, wwn_str)) != NULL) {
14762                 return (DDI_SUCCESS);
14763         }
14764 
14765         ndi_rtn = ndi_devi_alloc(pdip, "smp", DEVI_SID_NODEID, smp_dip);
14766 
14767         /*
14768          * if lun alloc success, set props
14769          */
14770         if (ndi_rtn == NDI_SUCCESS) {
14771                 /*
14772                  * Set the flavor of the child to be SMP flavored
14773                  */
14774                 ndi_flavor_set(*smp_dip, SCSA_FLAVOR_SMP);
14775 
14776                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14777                     *smp_dip, SMP_WWN, wwn_str) !=
14778                     DDI_PROP_SUCCESS) {
14779                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14780                             "property for smp device %s (sas_wwn)",
14781                             wwn_str);
14782                         ndi_rtn = NDI_FAILURE;
14783                         goto smp_create_done;
14784                 }
14785                 (void) sprintf(wwn_str, "w%"PRIx64, smp_node->m_addr.mta_wwn);
14786                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14787                     *smp_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str) !=
14788                     DDI_PROP_SUCCESS) {
14789                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14790                             "property for iport target-port %s (sas_wwn)",
14791                             wwn_str);
14792                         ndi_rtn = NDI_FAILURE;
14793                         goto smp_create_done;
14794                 }
14795 
14796                 mutex_enter(&mpt->m_mutex);
14797 
14798                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
14799                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | smp_node->m_devhdl;
14800                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
14801                     &dev_info);
14802                 if (rval != DDI_SUCCESS) {
14803                         mutex_exit(&mpt->m_mutex);
14804                         mptsas_log(mpt, CE_WARN,
14805                             "mptsas unable to get expander "
14806                             "parent device info for %x", page_address);
14807                         ndi_rtn = NDI_FAILURE;
14808                         goto smp_create_done;
14809                 }
14810 
14811                 smp_node->m_pdevhdl = dev_info.m_pdevhdl;
14812                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14813                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14814                     (uint32_t)dev_info.m_pdevhdl;
14815                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14816                     &dev_hdl, &sas_wwn, &smp_node->m_pdevinfo,
14817                     &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure);
14818                 if (rval != DDI_SUCCESS) {
14819                         mutex_exit(&mpt->m_mutex);
14820                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
14821                             "device info for %x", page_address);
14822                         ndi_rtn = NDI_FAILURE;
14823                         goto smp_create_done;
14824                 }
14825 
14826                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14827                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14828                     (uint32_t)dev_info.m_devhdl;
14829                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14830                     &dev_hdl, &smp_sas_wwn, &smp_node->m_deviceinfo,
14831                     &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure);
14832                 if (rval != DDI_SUCCESS) {
14833                         mutex_exit(&mpt->m_mutex);
14834                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
14835                             "device info for %x", page_address);
14836                         ndi_rtn = NDI_FAILURE;
14837                         goto smp_create_done;
14838                 }
14839                 mutex_exit(&mpt->m_mutex);
14840 
14841                 /*
14842                  * If this smp direct attached to the controller
14843                  * set the attached-port to the base wwid
14844                  */
14845                 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14846                     != DEVINFO_DIRECT_ATTACHED) {
14847                         (void) sprintf(attached_wwn_str, "w%016"PRIx64,
14848                             sas_wwn);
14849                 } else {
14850                         (void) sprintf(attached_wwn_str, "w%016"PRIx64,
14851                             mpt->un.m_base_wwid);
14852                 }
14853 
14854                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14855                     *smp_dip, SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwn_str) !=
14856                     DDI_PROP_SUCCESS) {
14857                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14858                             "property for smp attached-port %s (sas_wwn)",
14859                             attached_wwn_str);
14860                         ndi_rtn = NDI_FAILURE;
14861                         goto smp_create_done;
14862                 }
14863 
14864                 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
14865                     *smp_dip, SMP_PROP) != DDI_PROP_SUCCESS) {
14866                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
14867                             "create property for SMP %s (SMP_PROP) ",
14868                             wwn_str);
14869                         ndi_rtn = NDI_FAILURE;
14870                         goto smp_create_done;
14871                 }
14872 
14873                 /*
14874                  * check the smp to see whether it direct
14875                  * attached to the controller
14876                  */
14877                 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14878                     != DEVINFO_DIRECT_ATTACHED) {
14879                         goto smp_create_done;
14880                 }
14881                 numphys = ddi_prop_get_int(DDI_DEV_T_ANY, pdip,
14882                     DDI_PROP_DONTPASS, MPTSAS_NUM_PHYS, -1);
14883                 if (numphys > 0) {
14884                         goto smp_create_done;
14885                 }
14886                 /*
14887                  * this iport is an old iport, we need to
14888                  * reconfig the props for it.
14889                  */
14890                 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
14891                     MPTSAS_VIRTUAL_PORT, 0) !=
14892                     DDI_PROP_SUCCESS) {
14893                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
14894                             MPTSAS_VIRTUAL_PORT);
14895                         mptsas_log(mpt, CE_WARN, "mptsas virtual port "
14896                             "prop update failed");
14897                         goto smp_create_done;
14898                 }
14899 
14900                 mutex_enter(&mpt->m_mutex);
14901                 numphys = 0;
14902                 iport = ddi_get_name_addr(pdip);
14903                 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
14904                         bzero(phymask, sizeof (phymask));
14905                         (void) sprintf(phymask,
14906                             "%x", mpt->m_phy_info[i].phy_mask);
14907                         if (strcmp(phymask, iport) == 0) {
14908                                 phy_mask = mpt->m_phy_info[i].phy_mask;
14909                                 break;
14910                         }
14911                 }
14912 
14913                 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
14914                         if ((phy_mask >> i) & 0x01) {
14915                                 numphys++;
14916                         }
14917                 }
14918                 /*
14919                  * Update PHY info for smhba
14920                  */
14921                 if (mptsas_smhba_phy_init(mpt)) {
14922                         mutex_exit(&mpt->m_mutex);
14923                         mptsas_log(mpt, CE_WARN, "mptsas phy update "
14924                             "failed");
14925                         goto smp_create_done;
14926                 }
14927                 mutex_exit(&mpt->m_mutex);
14928 
14929                 mptsas_smhba_set_all_phy_props(mpt, pdip, numphys, phy_mask,
14930                     &attached_devhdl);
14931 
14932                 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
14933                     MPTSAS_NUM_PHYS, numphys) !=
14934                     DDI_PROP_SUCCESS) {
14935                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
14936                             MPTSAS_NUM_PHYS);
14937                         mptsas_log(mpt, CE_WARN, "mptsas update "
14938                             "num phys props failed");
14939                         goto smp_create_done;
14940                 }
14941                 /*
14942                  * Add parent's props for SMHBA support
14943                  */
14944                 if (ddi_prop_update_string(DDI_DEV_T_NONE, pdip,
14945                     SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
14946                     DDI_PROP_SUCCESS) {
14947                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
14948                             SCSI_ADDR_PROP_ATTACHED_PORT);
14949                         mptsas_log(mpt, CE_WARN, "mptsas update iport"
14950                             "attached-port failed");
14951                         goto smp_create_done;
14952                 }
14953 
14954 smp_create_done:
14955                 /*
14956                  * If props were setup ok, online the lun
14957                  */
14958                 if (ndi_rtn == NDI_SUCCESS) {
14959                         /*
14960                          * Try to online the new node
14961                          */
14962                         ndi_rtn = ndi_devi_online(*smp_dip, NDI_ONLINE_ATTACH);
14963                 }
14964 
14965                 /*
14966                  * If success set rtn flag, else unwire alloc'd lun
14967                  */
14968                 if (ndi_rtn != NDI_SUCCESS) {
14969                         NDBG12(("mptsas unable to online "
14970                             "SMP target %s", wwn_str));
14971                         ndi_prop_remove_all(*smp_dip);
14972                         (void) ndi_devi_free(*smp_dip);
14973                 }
14974         }
14975 
14976         return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
14977 }
14978 
14979 /* smp transport routine */
14980 static int mptsas_smp_start(struct smp_pkt *smp_pkt)
14981 {
14982         uint64_t                        wwn;
14983         Mpi2SmpPassthroughRequest_t     req;
14984         Mpi2SmpPassthroughReply_t       rep;
14985         uint32_t                        direction = 0;
14986         mptsas_t                        *mpt;
14987         int                             ret;
14988         uint64_t                        tmp64;
14989 
14990         mpt = (mptsas_t *)smp_pkt->smp_pkt_address->
14991             smp_a_hba_tran->smp_tran_hba_private;
14992 
14993         bcopy(smp_pkt->smp_pkt_address->smp_a_wwn, &wwn, SAS_WWN_BYTE_SIZE);
14994         /*
14995          * Need to compose a SMP request message
14996          * and call mptsas_do_passthru() function
14997          */
14998         bzero(&req, sizeof (req));
14999         bzero(&rep, sizeof (rep));
15000         req.PassthroughFlags = 0;
15001         req.PhysicalPort = 0xff;
15002         req.ChainOffset = 0;
15003         req.Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
15004 
15005         if ((smp_pkt->smp_pkt_reqsize & 0xffff0000ul) != 0) {
15006                 smp_pkt->smp_pkt_reason = ERANGE;
15007                 return (DDI_FAILURE);
15008         }
15009         req.RequestDataLength = LE_16((uint16_t)(smp_pkt->smp_pkt_reqsize - 4));
15010 
15011         req.MsgFlags = 0;
15012         tmp64 = LE_64(wwn);
15013         bcopy(&tmp64, &req.SASAddress, SAS_WWN_BYTE_SIZE);
15014         if (smp_pkt->smp_pkt_rspsize > 0) {
15015                 direction |= MPTSAS_PASS_THRU_DIRECTION_READ;
15016         }
15017         if (smp_pkt->smp_pkt_reqsize > 0) {
15018                 direction |= MPTSAS_PASS_THRU_DIRECTION_WRITE;
15019         }
15020 
15021         mutex_enter(&mpt->m_mutex);
15022         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep,
15023             (uint8_t *)smp_pkt->smp_pkt_rsp,
15024             offsetof(Mpi2SmpPassthroughRequest_t, SGL), sizeof (rep),
15025             smp_pkt->smp_pkt_rspsize - 4, direction,
15026             (uint8_t *)smp_pkt->smp_pkt_req, smp_pkt->smp_pkt_reqsize - 4,
15027             smp_pkt->smp_pkt_timeout, FKIOCTL);
15028         mutex_exit(&mpt->m_mutex);
15029         if (ret != 0) {
15030                 cmn_err(CE_WARN, "smp_start do passthru error %d", ret);
15031                 smp_pkt->smp_pkt_reason = (uchar_t)(ret);
15032                 return (DDI_FAILURE);
15033         }
15034         /* do passthrough success, check the smp status */
15035         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
15036                 switch (LE_16(rep.IOCStatus)) {
15037                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
15038                         smp_pkt->smp_pkt_reason = ENODEV;
15039                         break;
15040                 case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
15041                         smp_pkt->smp_pkt_reason = EOVERFLOW;
15042                         break;
15043                 case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
15044                         smp_pkt->smp_pkt_reason = EIO;
15045                         break;
15046                 default:
15047                         mptsas_log(mpt, CE_NOTE, "smp_start: get unknown ioc"
15048                             "status:%x", LE_16(rep.IOCStatus));
15049                         smp_pkt->smp_pkt_reason = EIO;
15050                         break;
15051                 }
15052                 return (DDI_FAILURE);
15053         }
15054         if (rep.SASStatus != MPI2_SASSTATUS_SUCCESS) {
15055                 mptsas_log(mpt, CE_NOTE, "smp_start: get error SAS status:%x",
15056                     rep.SASStatus);
15057                 smp_pkt->smp_pkt_reason = EIO;
15058                 return (DDI_FAILURE);
15059         }
15060 
15061         return (DDI_SUCCESS);
15062 }
15063 
15064 /*
15065  * If we didn't get a match, we need to get sas page0 for each device, and
15066  * untill we get a match. If failed, return NULL
15067  */
15068 static mptsas_target_t *
15069 mptsas_phy_to_tgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint8_t phy)
15070 {
15071         int             i, j = 0;
15072         int             rval = 0;
15073         uint16_t        cur_handle;
15074         uint32_t        page_address;
15075         mptsas_target_t *ptgt = NULL;
15076 
15077         /*
15078          * PHY named device must be direct attached and attaches to
15079          * narrow port, if the iport is not parent of the device which
15080          * we are looking for.
15081          */
15082         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15083                 if ((1 << i) & phymask)
15084                         j++;
15085         }
15086 
15087         if (j > 1)
15088                 return (NULL);
15089 
15090         /*
15091          * Must be a narrow port and single device attached to the narrow port
15092          * So the physical port num of device  which is equal to the iport's
15093          * port num is the device what we are looking for.
15094          */
15095 
15096         if (mpt->m_phy_info[phy].phy_mask != phymask)
15097                 return (NULL);
15098 
15099         mutex_enter(&mpt->m_mutex);
15100 
15101         ptgt = refhash_linear_search(mpt->m_targets, mptsas_target_eval_nowwn,
15102             &phy);
15103         if (ptgt != NULL) {
15104                 mutex_exit(&mpt->m_mutex);
15105                 return (ptgt);
15106         }
15107 
15108         if (mpt->m_done_traverse_dev) {
15109                 mutex_exit(&mpt->m_mutex);
15110                 return (NULL);
15111         }
15112 
15113         /* If didn't get a match, come here */
15114         cur_handle = mpt->m_dev_handle;
15115         for (; ; ) {
15116                 ptgt = NULL;
15117                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15118                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15119                 rval = mptsas_get_target_device_info(mpt, page_address,
15120                     &cur_handle, &ptgt);
15121                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15122                     (rval == DEV_INFO_FAIL_ALLOC)) {
15123                         break;
15124                 }
15125                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15126                     (rval == DEV_INFO_PHYS_DISK)) {
15127                         continue;
15128                 }
15129                 mpt->m_dev_handle = cur_handle;
15130 
15131                 if ((ptgt->m_addr.mta_wwn == 0) && (ptgt->m_phynum == phy)) {
15132                         break;
15133                 }
15134         }
15135 
15136         mutex_exit(&mpt->m_mutex);
15137         return (ptgt);
15138 }
15139 
15140 /*
15141  * The ptgt->m_addr.mta_wwn contains the wwid for each disk.
15142  * For Raid volumes, we need to check m_raidvol[x].m_raidwwid
15143  * If we didn't get a match, we need to get sas page0 for each device, and
15144  * untill we get a match
15145  * If failed, return NULL
15146  */
15147 static mptsas_target_t *
15148 mptsas_wwid_to_ptgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
15149 {
15150         int             rval = 0;
15151         uint16_t        cur_handle;
15152         uint32_t        page_address;
15153         mptsas_target_t *tmp_tgt = NULL;
15154         mptsas_target_addr_t addr;
15155 
15156         addr.mta_wwn = wwid;
15157         addr.mta_phymask = phymask;
15158         mutex_enter(&mpt->m_mutex);
15159         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
15160         if (tmp_tgt != NULL) {
15161                 mutex_exit(&mpt->m_mutex);
15162                 return (tmp_tgt);
15163         }
15164 
15165         if (phymask == 0) {
15166                 /*
15167                  * It's IR volume
15168                  */
15169                 rval = mptsas_get_raid_info(mpt);
15170                 if (rval) {
15171                         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
15172                 }
15173                 mutex_exit(&mpt->m_mutex);
15174                 return (tmp_tgt);
15175         }
15176 
15177         if (mpt->m_done_traverse_dev) {
15178                 mutex_exit(&mpt->m_mutex);
15179                 return (NULL);
15180         }
15181 
15182         /* If didn't get a match, come here */
15183         cur_handle = mpt->m_dev_handle;
15184         for (;;) {
15185                 tmp_tgt = NULL;
15186                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15187                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | cur_handle;
15188                 rval = mptsas_get_target_device_info(mpt, page_address,
15189                     &cur_handle, &tmp_tgt);
15190                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15191                     (rval == DEV_INFO_FAIL_ALLOC)) {
15192                         tmp_tgt = NULL;
15193                         break;
15194                 }
15195                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15196                     (rval == DEV_INFO_PHYS_DISK)) {
15197                         continue;
15198                 }
15199                 mpt->m_dev_handle = cur_handle;
15200                 if ((tmp_tgt->m_addr.mta_wwn) &&
15201                     (tmp_tgt->m_addr.mta_wwn == wwid) &&
15202                     (tmp_tgt->m_addr.mta_phymask == phymask)) {
15203                         break;
15204                 }
15205         }
15206 
15207         mutex_exit(&mpt->m_mutex);
15208         return (tmp_tgt);
15209 }
15210 
15211 static mptsas_smp_t *
15212 mptsas_wwid_to_psmp(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
15213 {
15214         int             rval = 0;
15215         uint16_t        cur_handle;
15216         uint32_t        page_address;
15217         mptsas_smp_t    smp_node, *psmp = NULL;
15218         mptsas_target_addr_t addr;
15219 
15220         addr.mta_wwn = wwid;
15221         addr.mta_phymask = phymask;
15222         mutex_enter(&mpt->m_mutex);
15223         psmp = refhash_lookup(mpt->m_smp_targets, &addr);
15224         if (psmp != NULL) {
15225                 mutex_exit(&mpt->m_mutex);
15226                 return (psmp);
15227         }
15228 
15229         if (mpt->m_done_traverse_smp) {
15230                 mutex_exit(&mpt->m_mutex);
15231                 return (NULL);
15232         }
15233 
15234         /* If didn't get a match, come here */
15235         cur_handle = mpt->m_smp_devhdl;
15236         for (;;) {
15237                 psmp = NULL;
15238                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
15239                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15240                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
15241                     &smp_node);
15242                 if (rval != DDI_SUCCESS) {
15243                         break;
15244                 }
15245                 mpt->m_smp_devhdl = cur_handle = smp_node.m_devhdl;
15246                 psmp = mptsas_smp_alloc(mpt, &smp_node);
15247                 ASSERT(psmp);
15248                 if ((psmp->m_addr.mta_wwn) && (psmp->m_addr.mta_wwn == wwid) &&
15249                     (psmp->m_addr.mta_phymask == phymask)) {
15250                         break;
15251                 }
15252         }
15253 
15254         mutex_exit(&mpt->m_mutex);
15255         return (psmp);
15256 }
15257 
15258 mptsas_target_t *
15259 mptsas_tgt_alloc(mptsas_t *mpt, uint16_t devhdl, uint64_t wwid,
15260     uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum)
15261 {
15262         mptsas_target_t *tmp_tgt = NULL;
15263         mptsas_target_addr_t addr;
15264 
15265         addr.mta_wwn = wwid;
15266         addr.mta_phymask = phymask;
15267         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
15268         if (tmp_tgt != NULL) {
15269                 NDBG20(("Hash item already exist"));
15270                 tmp_tgt->m_deviceinfo = devinfo;
15271                 tmp_tgt->m_devhdl = devhdl;  /* XXX - duplicate? */
15272                 return (tmp_tgt);
15273         }
15274         tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target), KM_SLEEP);
15275         if (tmp_tgt == NULL) {
15276                 cmn_err(CE_WARN, "Fatal, allocated tgt failed");
15277                 return (NULL);
15278         }
15279         tmp_tgt->m_devhdl = devhdl;
15280         tmp_tgt->m_addr.mta_wwn = wwid;
15281         tmp_tgt->m_deviceinfo = devinfo;
15282         tmp_tgt->m_addr.mta_phymask = phymask;
15283         tmp_tgt->m_phynum = phynum;
15284         /* Initialized the tgt structure */
15285         tmp_tgt->m_qfull_retries = QFULL_RETRIES;
15286         tmp_tgt->m_qfull_retry_interval =
15287             drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
15288         tmp_tgt->m_t_throttle = MAX_THROTTLE;
15289         TAILQ_INIT(&tmp_tgt->m_active_cmdq);
15290 
15291         refhash_insert(mpt->m_targets, tmp_tgt);
15292 
15293         return (tmp_tgt);
15294 }
15295 
15296 static void
15297 mptsas_smp_target_copy(mptsas_smp_t *src, mptsas_smp_t *dst)
15298 {
15299         dst->m_devhdl = src->m_devhdl;
15300         dst->m_deviceinfo = src->m_deviceinfo;
15301         dst->m_pdevhdl = src->m_pdevhdl;
15302         dst->m_pdevinfo = src->m_pdevinfo;
15303 }
15304 
15305 static mptsas_smp_t *
15306 mptsas_smp_alloc(mptsas_t *mpt, mptsas_smp_t *data)
15307 {
15308         mptsas_target_addr_t addr;
15309         mptsas_smp_t *ret_data;
15310 
15311         addr.mta_wwn = data->m_addr.mta_wwn;
15312         addr.mta_phymask = data->m_addr.mta_phymask;
15313         ret_data = refhash_lookup(mpt->m_smp_targets, &addr);
15314         /*
15315          * If there's already a matching SMP target, update its fields
15316          * in place.  Since the address is not changing, it's safe to do
15317          * this.  We cannot just bcopy() here because the structure we've
15318          * been given has invalid hash links.
15319          */
15320         if (ret_data != NULL) {
15321                 mptsas_smp_target_copy(data, ret_data);
15322                 return (ret_data);
15323         }
15324 
15325         ret_data = kmem_alloc(sizeof (mptsas_smp_t), KM_SLEEP);
15326         bcopy(data, ret_data, sizeof (mptsas_smp_t));
15327         refhash_insert(mpt->m_smp_targets, ret_data);
15328         return (ret_data);
15329 }
15330 
15331 /*
15332  * Functions for SGPIO LED support
15333  */
15334 static dev_info_t *
15335 mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask)
15336 {
15337         dev_info_t      *dip;
15338         int             prop;
15339         dip = e_ddi_hold_devi_by_dev(dev, 0);
15340         if (dip == NULL)
15341                 return (dip);
15342         prop = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
15343             "phymask", 0);
15344         *phymask = (mptsas_phymask_t)prop;
15345         ddi_release_devi(dip);
15346         return (dip);
15347 }
15348 static mptsas_target_t *
15349 mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
15350 {
15351         uint8_t                 phynum;
15352         uint64_t                wwn;
15353         int                     lun;
15354         mptsas_target_t         *ptgt = NULL;
15355 
15356         if (mptsas_parse_address(addr, &wwn, &phynum, &lun) != DDI_SUCCESS) {
15357                 return (NULL);
15358         }
15359         if (addr[0] == 'w') {
15360                 ptgt = mptsas_wwid_to_ptgt(mpt, (int)phymask, wwn);
15361         } else {
15362                 ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum);
15363         }
15364         return (ptgt);
15365 }
15366 
15367 static int
15368 mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt)
15369 {
15370         uint32_t slotstatus = 0;
15371 
15372         /* Build an MPI2 Slot Status based on our view of the world */
15373         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_IDENT - 1)))
15374                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST;
15375         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_FAIL - 1)))
15376                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT;
15377         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1)))
15378                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
15379 
15380         /* Write it to the controller */
15381         NDBG14(("mptsas_ioctl: set LED status %x for slot %x",
15382             slotstatus, ptgt->m_slot_num));
15383         return (mptsas_send_sep(mpt, ptgt, &slotstatus,
15384             MPI2_SEP_REQ_ACTION_WRITE_STATUS));
15385 }
15386 
15387 /*
15388  *  send sep request, use enclosure/slot addressing
15389  */
15390 static int
15391 mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
15392     uint32_t *status, uint8_t act)
15393 {
15394         Mpi2SepRequest_t        req;
15395         Mpi2SepReply_t          rep;
15396         int                     ret;
15397 
15398         ASSERT(mutex_owned(&mpt->m_mutex));
15399 
15400         /*
15401          * We only support SEP control of directly-attached targets, in which
15402          * case the "SEP" we're talking to is a virtual one contained within
15403          * the HBA itself.  This is necessary because DA targets typically have
15404          * no other mechanism for LED control.  Targets for which a separate
15405          * enclosure service processor exists should be controlled via ses(7d)
15406          * or sgen(7d).  Furthermore, since such requests can time out, they
15407          * should be made in user context rather than in response to
15408          * asynchronous fabric changes.
15409          *
15410          * In addition, we do not support this operation for RAID volumes,
15411          * since there is no slot associated with them.
15412          */
15413         if (!(ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED) ||
15414             ptgt->m_addr.mta_phymask == 0) {
15415                 return (ENOTTY);
15416         }
15417 
15418         bzero(&req, sizeof (req));
15419         bzero(&rep, sizeof (rep));
15420 
15421         req.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
15422         req.Action = act;
15423         req.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
15424         req.EnclosureHandle = LE_16(ptgt->m_enclosure);
15425         req.Slot = LE_16(ptgt->m_slot_num);
15426         if (act == MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
15427                 req.SlotStatus = LE_32(*status);
15428         }
15429         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
15430             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
15431         if (ret != 0) {
15432                 mptsas_log(mpt, CE_NOTE, "mptsas_send_sep: passthru SEP "
15433                     "Processor Request message error %d", ret);
15434                 return (ret);
15435         }
15436         /* do passthrough success, check the ioc status */
15437         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
15438                 mptsas_log(mpt, CE_NOTE, "send_sep act %x: ioc "
15439                     "status:%x loginfo %x", act, LE_16(rep.IOCStatus),
15440                     LE_32(rep.IOCLogInfo));
15441                 switch (LE_16(rep.IOCStatus) & MPI2_IOCSTATUS_MASK) {
15442                 case MPI2_IOCSTATUS_INVALID_FUNCTION:
15443                 case MPI2_IOCSTATUS_INVALID_VPID:
15444                 case MPI2_IOCSTATUS_INVALID_FIELD:
15445                 case MPI2_IOCSTATUS_INVALID_STATE:
15446                 case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
15447                 case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
15448                 case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
15449                 case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
15450                 case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
15451                 case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
15452                         return (EINVAL);
15453                 case MPI2_IOCSTATUS_BUSY:
15454                         return (EBUSY);
15455                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
15456                         return (EAGAIN);
15457                 case MPI2_IOCSTATUS_INVALID_SGL:
15458                 case MPI2_IOCSTATUS_INTERNAL_ERROR:
15459                 case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
15460                 default:
15461                         return (EIO);
15462                 }
15463         }
15464         if (act != MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
15465                 *status = LE_32(rep.SlotStatus);
15466         }
15467 
15468         return (0);
15469 }
15470 
15471 int
15472 mptsas_dma_addr_create(mptsas_t *mpt, ddi_dma_attr_t dma_attr,
15473     ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp, caddr_t *dma_memp,
15474     uint32_t alloc_size, ddi_dma_cookie_t *cookiep)
15475 {
15476         ddi_dma_cookie_t        new_cookie;
15477         size_t                  alloc_len;
15478         uint_t                  ncookie;
15479 
15480         if (cookiep == NULL)
15481                 cookiep = &new_cookie;
15482 
15483         if (ddi_dma_alloc_handle(mpt->m_dip, &dma_attr, DDI_DMA_SLEEP,
15484             NULL, dma_hdp) != DDI_SUCCESS) {
15485                 return (FALSE);
15486         }
15487 
15488         if (ddi_dma_mem_alloc(*dma_hdp, alloc_size, &mpt->m_dev_acc_attr,
15489             DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, dma_memp, &alloc_len,
15490             acc_hdp) != DDI_SUCCESS) {
15491                 ddi_dma_free_handle(dma_hdp);
15492                 return (FALSE);
15493         }
15494 
15495         if (ddi_dma_addr_bind_handle(*dma_hdp, NULL, *dma_memp, alloc_len,
15496             (DDI_DMA_RDWR | DDI_DMA_CONSISTENT), DDI_DMA_SLEEP, NULL,
15497             cookiep, &ncookie) != DDI_DMA_MAPPED) {
15498                 (void) ddi_dma_mem_free(acc_hdp);
15499                 ddi_dma_free_handle(dma_hdp);
15500                 return (FALSE);
15501         }
15502 
15503         return (TRUE);
15504 }
15505 
15506 void
15507 mptsas_dma_addr_destroy(ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp)
15508 {
15509         if (*dma_hdp == NULL)
15510                 return;
15511 
15512         (void) ddi_dma_unbind_handle(*dma_hdp);
15513         (void) ddi_dma_mem_free(acc_hdp);
15514         ddi_dma_free_handle(dma_hdp);
15515 }