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  * Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
  28  */
  29 
  30 /*
  31  * Copyright (c) 2000 to 2010, LSI Corporation.
  32  * All rights reserved.
  33  *
  34  * Redistribution and use in source and binary forms of all code within
  35  * this file that is exclusively owned by LSI, with or without
  36  * modification, is permitted provided that, in addition to the CDDL 1.0
  37  * License requirements, the following conditions are met:
  38  *
  39  *    Neither the name of the author nor the names of its contributors may be
  40  *    used to endorse or promote products derived from this software without
  41  *    specific prior written permission.
  42  *
  43  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  44  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  45  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  46  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  47  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  48  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  49  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  50  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  51  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  52  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  53  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  54  * DAMAGE.
  55  */
  56 
  57 /*
  58  * mptsas - This is a driver based on LSI Logic's MPT2.0/2.5 interface.
  59  *
  60  */
  61 
  62 #if defined(lint) || defined(DEBUG)
  63 #define MPTSAS_DEBUG
  64 #endif
  65 
  66 /*
  67  * standard header files.
  68  */
  69 #include <sys/note.h>
  70 #include <sys/scsi/scsi.h>
  71 #include <sys/pci.h>
  72 #include <sys/file.h>
  73 #include <sys/policy.h>
  74 #include <sys/model.h>
  75 #include <sys/sysevent.h>
  76 #include <sys/sysevent/eventdefs.h>
  77 #include <sys/sysevent/dr.h>
  78 #include <sys/sata/sata_defs.h>
  79 #include <sys/scsi/generic/sas.h>
  80 #include <sys/scsi/impl/scsi_sas.h>
  81 
  82 #pragma pack(1)
  83 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
  84 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
  85 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
  86 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
  87 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
  88 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
  89 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
  90 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
  91 #pragma pack()
  92 
  93 /*
  94  * private header files.
  95  *
  96  */
  97 #include <sys/scsi/impl/scsi_reset_notify.h>
  98 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
  99 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
 100 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
 101 #include <sys/scsi/adapters/mpt_sas/mptsas_hash.h>
 102 #include <sys/raidioctl.h>
 103 
 104 #include <sys/fs/dv_node.h>       /* devfs_clean */
 105 
 106 /*
 107  * FMA header files
 108  */
 109 #include <sys/ddifm.h>
 110 #include <sys/fm/protocol.h>
 111 #include <sys/fm/util.h>
 112 #include <sys/fm/io/ddi.h>
 113 
 114 /*
 115  * autoconfiguration data and routines.
 116  */
 117 static int mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
 118 static int mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
 119 static int mptsas_power(dev_info_t *dip, int component, int level);
 120 
 121 /*
 122  * cb_ops function
 123  */
 124 static int mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
 125         cred_t *credp, int *rval);
 126 #ifdef __sparc
 127 static int mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd);
 128 #else  /* __sparc */
 129 static int mptsas_quiesce(dev_info_t *devi);
 130 #endif  /* __sparc */
 131 
 132 /*
 133  * Resource initilaization for hardware
 134  */
 135 static void mptsas_setup_cmd_reg(mptsas_t *mpt);
 136 static void mptsas_disable_bus_master(mptsas_t *mpt);
 137 static void mptsas_hba_fini(mptsas_t *mpt);
 138 static void mptsas_cfg_fini(mptsas_t *mptsas_blkp);
 139 static int mptsas_hba_setup(mptsas_t *mpt);
 140 static void mptsas_hba_teardown(mptsas_t *mpt);
 141 static int mptsas_config_space_init(mptsas_t *mpt);
 142 static void mptsas_config_space_fini(mptsas_t *mpt);
 143 static void mptsas_iport_register(mptsas_t *mpt);
 144 static int mptsas_smp_setup(mptsas_t *mpt);
 145 static void mptsas_smp_teardown(mptsas_t *mpt);
 146 static int mptsas_cache_create(mptsas_t *mpt);
 147 static void mptsas_cache_destroy(mptsas_t *mpt);
 148 static int mptsas_alloc_request_frames(mptsas_t *mpt);
 149 static int mptsas_alloc_sense_bufs(mptsas_t *mpt);
 150 static int mptsas_alloc_reply_frames(mptsas_t *mpt);
 151 static int mptsas_alloc_free_queue(mptsas_t *mpt);
 152 static int mptsas_alloc_post_queue(mptsas_t *mpt);
 153 static void mptsas_alloc_reply_args(mptsas_t *mpt);
 154 static int mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
 155 static void mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
 156 static int mptsas_init_chip(mptsas_t *mpt, int first_time);
 157 
 158 /*
 159  * SCSA function prototypes
 160  */
 161 static int mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
 162 static int mptsas_scsi_reset(struct scsi_address *ap, int level);
 163 static int mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
 164 static int mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly);
 165 static int mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value,
 166     int tgtonly);
 167 static void mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt);
 168 static struct scsi_pkt *mptsas_scsi_init_pkt(struct scsi_address *ap,
 169     struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen,
 170         int tgtlen, int flags, int (*callback)(), caddr_t arg);
 171 static void mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt);
 172 static void mptsas_scsi_destroy_pkt(struct scsi_address *ap,
 173     struct scsi_pkt *pkt);
 174 static int mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 175     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 176 static void mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 177     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 178 static int mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
 179     void (*callback)(caddr_t), caddr_t arg);
 180 static int mptsas_get_name(struct scsi_device *sd, char *name, int len);
 181 static int mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len);
 182 static int mptsas_scsi_quiesce(dev_info_t *dip);
 183 static int mptsas_scsi_unquiesce(dev_info_t *dip);
 184 static int mptsas_bus_config(dev_info_t *pdip, uint_t flags,
 185     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
 186 
 187 /*
 188  * SMP functions
 189  */
 190 static int mptsas_smp_start(struct smp_pkt *smp_pkt);
 191 
 192 /*
 193  * internal function prototypes.
 194  */
 195 static void mptsas_list_add(mptsas_t *mpt);
 196 static void mptsas_list_del(mptsas_t *mpt);
 197 
 198 static int mptsas_quiesce_bus(mptsas_t *mpt);
 199 static int mptsas_unquiesce_bus(mptsas_t *mpt);
 200 
 201 static int mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size);
 202 static void mptsas_free_handshake_msg(mptsas_t *mpt);
 203 
 204 static void mptsas_ncmds_checkdrain(void *arg);
 205 
 206 static int mptsas_prepare_pkt(mptsas_cmd_t *cmd);
 207 static int mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
 208 static int mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
 209 static void mptsas_accept_tx_waitq(mptsas_t *mpt);
 210 
 211 static int mptsas_do_detach(dev_info_t *dev);
 212 static int mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl);
 213 static int mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun,
 214     struct scsi_pkt *pkt);
 215 static int mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp);
 216 
 217 static void mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd);
 218 static void mptsas_handle_event(void *args);
 219 static int mptsas_handle_event_sync(void *args);
 220 static void mptsas_handle_dr(void *args);
 221 static void mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
 222     dev_info_t *pdip);
 223 
 224 static void mptsas_restart_cmd(void *);
 225 
 226 static void mptsas_flush_hba(mptsas_t *mpt);
 227 static void mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun,
 228         uint8_t tasktype);
 229 static void mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd,
 230     uchar_t reason, uint_t stat);
 231 
 232 static uint_t mptsas_intr(caddr_t arg1, caddr_t arg2);
 233 static void mptsas_process_intr(mptsas_t *mpt,
 234     pMpi2ReplyDescriptorsUnion_t reply_desc_union);
 235 static void mptsas_handle_scsi_io_success(mptsas_t *mpt,
 236     pMpi2ReplyDescriptorsUnion_t reply_desc);
 237 static void mptsas_handle_address_reply(mptsas_t *mpt,
 238     pMpi2ReplyDescriptorsUnion_t reply_desc);
 239 static int mptsas_wait_intr(mptsas_t *mpt, int polltime);
 240 static void mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd,
 241     uint32_t *control, pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl);
 242 
 243 static void mptsas_watch(void *arg);
 244 static void mptsas_watchsubr(mptsas_t *mpt);
 245 static void mptsas_cmd_timeout(mptsas_t *mpt, mptsas_target_t *ptgt);
 246 
 247 static void mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd);
 248 static int mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
 249     uint8_t *data, uint32_t request_size, uint32_t reply_size,
 250     uint32_t data_size, uint32_t direction, uint8_t *dataout,
 251     uint32_t dataout_size, short timeout, int mode);
 252 static int mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl);
 253 
 254 static uint8_t mptsas_get_fw_diag_buffer_number(mptsas_t *mpt,
 255     uint32_t unique_id);
 256 static void mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd);
 257 static int mptsas_post_fw_diag_buffer(mptsas_t *mpt,
 258     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
 259 static int mptsas_release_fw_diag_buffer(mptsas_t *mpt,
 260     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
 261     uint32_t diag_type);
 262 static int mptsas_diag_register(mptsas_t *mpt,
 263     mptsas_fw_diag_register_t *diag_register, uint32_t *return_code);
 264 static int mptsas_diag_unregister(mptsas_t *mpt,
 265     mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code);
 266 static int mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
 267     uint32_t *return_code);
 268 static int mptsas_diag_read_buffer(mptsas_t *mpt,
 269     mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
 270     uint32_t *return_code, int ioctl_mode);
 271 static int mptsas_diag_release(mptsas_t *mpt,
 272     mptsas_fw_diag_release_t *diag_release, uint32_t *return_code);
 273 static int mptsas_do_diag_action(mptsas_t *mpt, uint32_t action,
 274     uint8_t *diag_action, uint32_t length, uint32_t *return_code,
 275     int ioctl_mode);
 276 static int mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *data,
 277     int mode);
 278 
 279 static int mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
 280     int cmdlen, int tgtlen, int statuslen, int kf);
 281 static void mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd);
 282 
 283 static int mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags);
 284 static void mptsas_kmem_cache_destructor(void *buf, void *cdrarg);
 285 
 286 static int mptsas_cache_frames_constructor(void *buf, void *cdrarg,
 287     int kmflags);
 288 static void mptsas_cache_frames_destructor(void *buf, void *cdrarg);
 289 
 290 static void mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
 291     mptsas_cmd_t *cmd);
 292 static void mptsas_check_task_mgt(mptsas_t *mpt,
 293     pMpi2SCSIManagementReply_t reply, mptsas_cmd_t *cmd);
 294 static int mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
 295     mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
 296     int *resid);
 297 
 298 static int mptsas_alloc_active_slots(mptsas_t *mpt, int flag);
 299 static void mptsas_free_active_slots(mptsas_t *mpt);
 300 static int mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 301 
 302 static void mptsas_restart_hba(mptsas_t *mpt);
 303 static void mptsas_restart_waitq(mptsas_t *mpt);
 304 
 305 static void mptsas_deliver_doneq_thread(mptsas_t *mpt);
 306 static void mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd);
 307 static void mptsas_doneq_mv(mptsas_t *mpt, uint64_t t);
 308 
 309 static mptsas_cmd_t *mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t);
 310 static void mptsas_doneq_empty(mptsas_t *mpt);
 311 static void mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg);
 312 
 313 static mptsas_cmd_t *mptsas_waitq_rm(mptsas_t *mpt);
 314 static void mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
 315 static mptsas_cmd_t *mptsas_tx_waitq_rm(mptsas_t *mpt);
 316 static void mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
 317 
 318 
 319 static void mptsas_start_watch_reset_delay();
 320 static void mptsas_setup_bus_reset_delay(mptsas_t *mpt);
 321 static void mptsas_watch_reset_delay(void *arg);
 322 static int mptsas_watch_reset_delay_subr(mptsas_t *mpt);
 323 
 324 /*
 325  * helper functions
 326  */
 327 static void mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 328 
 329 static dev_info_t *mptsas_find_child(dev_info_t *pdip, char *name);
 330 static dev_info_t *mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy);
 331 static dev_info_t *mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr,
 332     int lun);
 333 static mdi_pathinfo_t *mptsas_find_path_addr(dev_info_t *pdip, uint64_t sasaddr,
 334     int lun);
 335 static mdi_pathinfo_t *mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy);
 336 static dev_info_t *mptsas_find_smp_child(dev_info_t *pdip, char *str_wwn);
 337 
 338 static int mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy,
 339     int *lun);
 340 static int mptsas_parse_smp_name(char *name, uint64_t *wwn);
 341 
 342 static mptsas_target_t *mptsas_phy_to_tgt(mptsas_t *mpt,
 343     mptsas_phymask_t phymask, uint8_t phy);
 344 static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt,
 345     mptsas_phymask_t phymask, uint64_t wwid);
 346 static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt,
 347     mptsas_phymask_t phymask, uint64_t wwid);
 348 
 349 static int mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun,
 350     uchar_t page, unsigned char *buf, int len, int *rlen, uchar_t evpd);
 351 
 352 static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
 353     uint16_t *handle, mptsas_target_t **pptgt);
 354 static void mptsas_update_phymask(mptsas_t *mpt);
 355 
 356 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
 357     uint32_t *status, uint8_t cmd);
 358 static dev_info_t *mptsas_get_dip_from_dev(dev_t dev,
 359     mptsas_phymask_t *phymask);
 360 static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr,
 361     mptsas_phymask_t phymask);
 362 static int mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt);
 363 
 364 
 365 /*
 366  * Enumeration / DR functions
 367  */
 368 static void mptsas_config_all(dev_info_t *pdip);
 369 static int mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
 370     dev_info_t **lundip);
 371 static int mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
 372     dev_info_t **lundip);
 373 
 374 static int mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt);
 375 static int mptsas_offline_target(dev_info_t *pdip, char *name);
 376 
 377 static int mptsas_config_raid(dev_info_t *pdip, uint16_t target,
 378     dev_info_t **dip);
 379 
 380 static int mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt);
 381 static int mptsas_probe_lun(dev_info_t *pdip, int lun,
 382     dev_info_t **dip, mptsas_target_t *ptgt);
 383 
 384 static int mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
 385     dev_info_t **dip, mptsas_target_t *ptgt, int lun);
 386 
 387 static int mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
 388     char *guid, dev_info_t **dip, mptsas_target_t *ptgt, int lun);
 389 static int mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
 390     char *guid, dev_info_t **dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt,
 391     int lun);
 392 
 393 static void mptsas_offline_missed_luns(dev_info_t *pdip,
 394     uint16_t *repluns, int lun_cnt, mptsas_target_t *ptgt);
 395 static int mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
 396     mdi_pathinfo_t *rpip, uint_t flags);
 397 
 398 static int mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn,
 399     dev_info_t **smp_dip);
 400 static int mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 401     uint_t flags);
 402 
 403 static int mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data,
 404     int mode, int *rval);
 405 static int mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data,
 406     int mode, int *rval);
 407 static int mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data,
 408     int mode, int *rval);
 409 static void mptsas_record_event(void *args);
 410 static int mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data,
 411     int mode);
 412 
 413 mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t, uint64_t,
 414     uint32_t, mptsas_phymask_t, uint8_t);
 415 static mptsas_smp_t *mptsas_smp_alloc(mptsas_t *, mptsas_smp_t *);
 416 static int mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 417     dev_info_t **smp_dip);
 418 
 419 /*
 420  * Power management functions
 421  */
 422 static int mptsas_get_pci_cap(mptsas_t *mpt);
 423 static int mptsas_init_pm(mptsas_t *mpt);
 424 
 425 /*
 426  * MPT MSI tunable:
 427  *
 428  * By default MSI is enabled on all supported platforms.
 429  */
 430 boolean_t mptsas_enable_msi = B_TRUE;
 431 boolean_t mptsas_physical_bind_failed_page_83 = B_FALSE;
 432 
 433 /*
 434  * Global switch for use of MPI2.5 FAST PATH.
 435  * We don't really know what FAST PATH actually does, so if it is suspected
 436  * to cause problems it can be turned off by setting this variable to B_FALSE.
 437  */
 438 boolean_t mptsas_use_fastpath = B_TRUE;
 439 
 440 static int mptsas_register_intrs(mptsas_t *);
 441 static void mptsas_unregister_intrs(mptsas_t *);
 442 static int mptsas_add_intrs(mptsas_t *, int);
 443 static void mptsas_rem_intrs(mptsas_t *);
 444 
 445 /*
 446  * FMA Prototypes
 447  */
 448 static void mptsas_fm_init(mptsas_t *mpt);
 449 static void mptsas_fm_fini(mptsas_t *mpt);
 450 static int mptsas_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *);
 451 
 452 extern pri_t minclsyspri, maxclsyspri;
 453 
 454 /*
 455  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).  It is
 456  * under this device that the paths to a physical device are created when
 457  * MPxIO is used.
 458  */
 459 extern dev_info_t       *scsi_vhci_dip;
 460 
 461 /*
 462  * Tunable timeout value for Inquiry VPD page 0x83
 463  * By default the value is 30 seconds.
 464  */
 465 int mptsas_inq83_retry_timeout = 30;
 466 
 467 /*
 468  * This is used to allocate memory for message frame storage, not for
 469  * data I/O DMA. All message frames must be stored in the first 4G of
 470  * physical memory.
 471  */
 472 ddi_dma_attr_t mptsas_dma_attrs = {
 473         DMA_ATTR_V0,    /* attribute layout version             */
 474         0x0ull,         /* address low - should be 0 (longlong) */
 475         0xffffffffull,  /* address high - 32-bit max range      */
 476         0x00ffffffull,  /* count max - max DMA object size      */
 477         4,              /* allocation alignment requirements    */
 478         0x78,           /* burstsizes - binary encoded values   */
 479         1,              /* minxfer - gran. of DMA engine        */
 480         0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 481         0xffffffffull,  /* max segment size (DMA boundary)      */
 482         MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 483         512,            /* granularity - device transfer size   */
 484         0               /* flags, set to 0                      */
 485 };
 486 
 487 /*
 488  * This is used for data I/O DMA memory allocation. (full 64-bit DMA
 489  * physical addresses are supported.)
 490  */
 491 ddi_dma_attr_t mptsas_dma_attrs64 = {
 492         DMA_ATTR_V0,    /* attribute layout version             */
 493         0x0ull,         /* address low - should be 0 (longlong) */
 494         0xffffffffffffffffull,  /* address high - 64-bit max    */
 495         0x00ffffffull,  /* count max - max DMA object size      */
 496         4,              /* allocation alignment requirements    */
 497         0x78,           /* burstsizes - binary encoded values   */
 498         1,              /* minxfer - gran. of DMA engine        */
 499         0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 500         0xffffffffull,  /* max segment size (DMA boundary)      */
 501         MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 502         512,            /* granularity - device transfer size   */
 503         0               /* flags, set to 0 */
 504 };
 505 
 506 ddi_device_acc_attr_t mptsas_dev_attr = {
 507         DDI_DEVICE_ATTR_V1,
 508         DDI_STRUCTURE_LE_ACC,
 509         DDI_STRICTORDER_ACC,
 510         DDI_DEFAULT_ACC
 511 };
 512 
 513 static struct cb_ops mptsas_cb_ops = {
 514         scsi_hba_open,          /* open */
 515         scsi_hba_close,         /* close */
 516         nodev,                  /* strategy */
 517         nodev,                  /* print */
 518         nodev,                  /* dump */
 519         nodev,                  /* read */
 520         nodev,                  /* write */
 521         mptsas_ioctl,           /* ioctl */
 522         nodev,                  /* devmap */
 523         nodev,                  /* mmap */
 524         nodev,                  /* segmap */
 525         nochpoll,               /* chpoll */
 526         ddi_prop_op,            /* cb_prop_op */
 527         NULL,                   /* streamtab */
 528         D_MP,                   /* cb_flag */
 529         CB_REV,                 /* rev */
 530         nodev,                  /* aread */
 531         nodev                   /* awrite */
 532 };
 533 
 534 static struct dev_ops mptsas_ops = {
 535         DEVO_REV,               /* devo_rev, */
 536         0,                      /* refcnt  */
 537         ddi_no_info,            /* info */
 538         nulldev,                /* identify */
 539         nulldev,                /* probe */
 540         mptsas_attach,          /* attach */
 541         mptsas_detach,          /* detach */
 542 #ifdef  __sparc
 543         mptsas_reset,
 544 #else
 545         nodev,                  /* reset */
 546 #endif  /* __sparc */
 547         &mptsas_cb_ops,             /* driver operations */
 548         NULL,                   /* bus operations */
 549         mptsas_power,           /* power management */
 550 #ifdef  __sparc
 551         ddi_quiesce_not_needed
 552 #else
 553         mptsas_quiesce          /* quiesce */
 554 #endif  /* __sparc */
 555 };
 556 
 557 
 558 #define MPTSAS_MOD_STRING "MPTSAS HBA Driver 00.00.00.24"
 559 
 560 static struct modldrv modldrv = {
 561         &mod_driverops,     /* Type of module. This one is a driver */
 562         MPTSAS_MOD_STRING, /* Name of the module. */
 563         &mptsas_ops,        /* driver ops */
 564 };
 565 
 566 static struct modlinkage modlinkage = {
 567         MODREV_1, &modldrv, NULL
 568 };
 569 #define TARGET_PROP     "target"
 570 #define LUN_PROP        "lun"
 571 #define LUN64_PROP      "lun64"
 572 #define SAS_PROP        "sas-mpt"
 573 #define MDI_GUID        "wwn"
 574 #define NDI_GUID        "guid"
 575 #define MPTSAS_DEV_GONE "mptsas_dev_gone"
 576 
 577 /*
 578  * Local static data
 579  */
 580 #if defined(MPTSAS_DEBUG)
 581 /*
 582  * Flags to indicate which debug messages are to be printed and which go to the
 583  * debug log ring buffer. Default is to not print anything, and to log
 584  * everything except the watchsubr() output which normally happens every second.
 585  */
 586 uint32_t mptsas_debugprt_flags = 0x0;
 587 uint32_t mptsas_debuglog_flags = ~(1U << 30);
 588 #endif  /* defined(MPTSAS_DEBUG) */
 589 uint32_t mptsas_debug_resets = 0;
 590 
 591 static kmutex_t         mptsas_global_mutex;
 592 static void             *mptsas_state;          /* soft state ptr */
 593 static krwlock_t        mptsas_global_rwlock;
 594 
 595 static kmutex_t         mptsas_log_mutex;
 596 static char             mptsas_log_buf[256];
 597 _NOTE(MUTEX_PROTECTS_DATA(mptsas_log_mutex, mptsas_log_buf))
 598 
 599 static mptsas_t *mptsas_head, *mptsas_tail;
 600 static clock_t mptsas_scsi_watchdog_tick;
 601 static clock_t mptsas_tick;
 602 static timeout_id_t mptsas_reset_watch;
 603 static timeout_id_t mptsas_timeout_id;
 604 static int mptsas_timeouts_enabled = 0;
 605 
 606 /*
 607  * Default length for extended auto request sense buffers.
 608  * All sense buffers need to be under the same alloc because there
 609  * is only one common top 32bits (of 64bits) address register.
 610  * Most requests only require 32 bytes, but some request >256.
 611  * We use rmalloc()/rmfree() on this additional memory to manage the
 612  * "extended" requests.
 613  */
 614 int mptsas_extreq_sense_bufsize = 256*64;
 615 
 616 /*
 617  * We believe that all software resrictions of having to run with DMA
 618  * attributes to limit allocation to the first 4G are removed.
 619  * However, this flag remains to enable quick switchback should suspicious
 620  * problems emerge.
 621  * Note that scsi_alloc_consistent_buf() does still adhere to allocating
 622  * 32 bit addressable memory, but we can cope if that is changed now.
 623  */
 624 int mptsas_use_64bit_msgaddr = 1;
 625 
 626 /*
 627  * warlock directives
 628  */
 629 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt \
 630         mptsas_cmd NcrTableIndirect buf scsi_cdb scsi_status))
 631 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", smp_pkt))
 632 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
 633 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mptsas_tgt_private))
 634 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_hba_tran::tran_tgt_private))
 635 
 636 /*
 637  * SM - HBA statics
 638  */
 639 char    *mptsas_driver_rev = MPTSAS_MOD_STRING;
 640 
 641 #ifdef MPTSAS_DEBUG
 642 void debug_enter(char *);
 643 #endif
 644 
 645 /*
 646  * Notes:
 647  *      - scsi_hba_init(9F) initializes SCSI HBA modules
 648  *      - must call scsi_hba_fini(9F) if modload() fails
 649  */
 650 int
 651 _init(void)
 652 {
 653         int status;
 654         /* CONSTCOND */
 655         ASSERT(NO_COMPETING_THREADS);
 656 
 657         NDBG0(("_init"));
 658 
 659         status = ddi_soft_state_init(&mptsas_state, MPTSAS_SIZE,
 660             MPTSAS_INITIAL_SOFT_SPACE);
 661         if (status != 0) {
 662                 return (status);
 663         }
 664 
 665         if ((status = scsi_hba_init(&modlinkage)) != 0) {
 666                 ddi_soft_state_fini(&mptsas_state);
 667                 return (status);
 668         }
 669 
 670         mutex_init(&mptsas_global_mutex, NULL, MUTEX_DRIVER, NULL);
 671         rw_init(&mptsas_global_rwlock, NULL, RW_DRIVER, NULL);
 672         mutex_init(&mptsas_log_mutex, NULL, MUTEX_DRIVER, NULL);
 673 
 674         if ((status = mod_install(&modlinkage)) != 0) {
 675                 mutex_destroy(&mptsas_log_mutex);
 676                 rw_destroy(&mptsas_global_rwlock);
 677                 mutex_destroy(&mptsas_global_mutex);
 678                 ddi_soft_state_fini(&mptsas_state);
 679                 scsi_hba_fini(&modlinkage);
 680         }
 681 
 682         return (status);
 683 }
 684 
 685 /*
 686  * Notes:
 687  *      - scsi_hba_fini(9F) uninitializes SCSI HBA modules
 688  */
 689 int
 690 _fini(void)
 691 {
 692         int     status;
 693         /* CONSTCOND */
 694         ASSERT(NO_COMPETING_THREADS);
 695 
 696         NDBG0(("_fini"));
 697 
 698         if ((status = mod_remove(&modlinkage)) == 0) {
 699                 ddi_soft_state_fini(&mptsas_state);
 700                 scsi_hba_fini(&modlinkage);
 701                 mutex_destroy(&mptsas_global_mutex);
 702                 rw_destroy(&mptsas_global_rwlock);
 703                 mutex_destroy(&mptsas_log_mutex);
 704         }
 705         return (status);
 706 }
 707 
 708 /*
 709  * The loadable-module _info(9E) entry point
 710  */
 711 int
 712 _info(struct modinfo *modinfop)
 713 {
 714         /* CONSTCOND */
 715         ASSERT(NO_COMPETING_THREADS);
 716         NDBG0(("mptsas _info"));
 717 
 718         return (mod_info(&modlinkage, modinfop));
 719 }
 720 
 721 static int
 722 mptsas_target_eval_devhdl(const void *op, void *arg)
 723 {
 724         uint16_t dh = *(uint16_t *)arg;
 725         const mptsas_target_t *tp = op;
 726 
 727         return ((int)tp->m_devhdl - (int)dh);
 728 }
 729 
 730 static int
 731 mptsas_target_eval_slot(const void *op, void *arg)
 732 {
 733         mptsas_led_control_t *lcp = arg;
 734         const mptsas_target_t *tp = op;
 735 
 736         if (tp->m_enclosure != lcp->Enclosure)
 737                 return ((int)tp->m_enclosure - (int)lcp->Enclosure);
 738 
 739         return ((int)tp->m_slot_num - (int)lcp->Slot);
 740 }
 741 
 742 static int
 743 mptsas_target_eval_nowwn(const void *op, void *arg)
 744 {
 745         uint8_t phy = *(uint8_t *)arg;
 746         const mptsas_target_t *tp = op;
 747 
 748         if (tp->m_addr.mta_wwn != 0)
 749                 return (-1);
 750 
 751         return ((int)tp->m_phynum - (int)phy);
 752 }
 753 
 754 static int
 755 mptsas_smp_eval_devhdl(const void *op, void *arg)
 756 {
 757         uint16_t dh = *(uint16_t *)arg;
 758         const mptsas_smp_t *sp = op;
 759 
 760         return ((int)sp->m_devhdl - (int)dh);
 761 }
 762 
 763 static uint64_t
 764 mptsas_target_addr_hash(const void *tp)
 765 {
 766         const mptsas_target_addr_t *tap = tp;
 767 
 768         return ((tap->mta_wwn & 0xffffffffffffULL) |
 769             ((uint64_t)tap->mta_phymask << 48));
 770 }
 771 
 772 static int
 773 mptsas_target_addr_cmp(const void *a, const void *b)
 774 {
 775         const mptsas_target_addr_t *aap = a;
 776         const mptsas_target_addr_t *bap = b;
 777 
 778         if (aap->mta_wwn < bap->mta_wwn)
 779                 return (-1);
 780         if (aap->mta_wwn > bap->mta_wwn)
 781                 return (1);
 782         return ((int)bap->mta_phymask - (int)aap->mta_phymask);
 783 }
 784 
 785 static void
 786 mptsas_target_free(void *op)
 787 {
 788         kmem_free(op, sizeof (mptsas_target_t));
 789 }
 790 
 791 static void
 792 mptsas_smp_free(void *op)
 793 {
 794         kmem_free(op, sizeof (mptsas_smp_t));
 795 }
 796 
 797 static void
 798 mptsas_destroy_hashes(mptsas_t *mpt)
 799 {
 800         mptsas_target_t *tp;
 801         mptsas_smp_t *sp;
 802 
 803         for (tp = refhash_first(mpt->m_targets); tp != NULL;
 804             tp = refhash_next(mpt->m_targets, tp)) {
 805                 refhash_remove(mpt->m_targets, tp);
 806         }
 807         for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
 808             sp = refhash_next(mpt->m_smp_targets, sp)) {
 809                 refhash_remove(mpt->m_smp_targets, sp);
 810         }
 811         refhash_destroy(mpt->m_targets);
 812         refhash_destroy(mpt->m_smp_targets);
 813         mpt->m_targets = NULL;
 814         mpt->m_smp_targets = NULL;
 815 }
 816 
 817 static int
 818 mptsas_iport_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 819 {
 820         dev_info_t              *pdip;
 821         mptsas_t                *mpt;
 822         scsi_hba_tran_t         *hba_tran;
 823         char                    *iport = NULL;
 824         char                    phymask[MPTSAS_MAX_PHYS];
 825         mptsas_phymask_t        phy_mask = 0;
 826         int                     dynamic_port = 0;
 827         uint32_t                page_address;
 828         char                    initiator_wwnstr[MPTSAS_WWN_STRLEN];
 829         int                     rval = DDI_FAILURE;
 830         int                     i = 0;
 831         uint8_t                 numphys = 0;
 832         uint8_t                 phy_id;
 833         uint8_t                 phy_port = 0;
 834         uint16_t                attached_devhdl = 0;
 835         uint32_t                dev_info;
 836         uint64_t                attached_sas_wwn;
 837         uint16_t                dev_hdl;
 838         uint16_t                pdev_hdl;
 839         uint16_t                bay_num, enclosure, io_flags;
 840         char                    attached_wwnstr[MPTSAS_WWN_STRLEN];
 841 
 842         /* CONSTCOND */
 843         ASSERT(NO_COMPETING_THREADS);
 844 
 845         switch (cmd) {
 846         case DDI_ATTACH:
 847                 break;
 848 
 849         case DDI_RESUME:
 850                 /*
 851                  * If this a scsi-iport node, nothing to do here.
 852                  */
 853                 return (DDI_SUCCESS);
 854 
 855         default:
 856                 return (DDI_FAILURE);
 857         }
 858 
 859         pdip = ddi_get_parent(dip);
 860 
 861         if ((hba_tran = ndi_flavorv_get(pdip, SCSA_FLAVOR_SCSI_DEVICE)) ==
 862             NULL) {
 863                 cmn_err(CE_WARN, "Failed attach iport because fail to "
 864                     "get tran vector for the HBA node");
 865                 return (DDI_FAILURE);
 866         }
 867 
 868         mpt = TRAN2MPT(hba_tran);
 869         ASSERT(mpt != NULL);
 870         if (mpt == NULL)
 871                 return (DDI_FAILURE);
 872 
 873         if ((hba_tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) ==
 874             NULL) {
 875                 mptsas_log(mpt, CE_WARN, "Failed attach iport because fail to "
 876                     "get tran vector for the iport node");
 877                 return (DDI_FAILURE);
 878         }
 879 
 880         /*
 881          * Overwrite parent's tran_hba_private to iport's tran vector
 882          */
 883         hba_tran->tran_hba_private = mpt;
 884 
 885         ddi_report_dev(dip);
 886 
 887         /*
 888          * Get SAS address for initiator port according dev_handle
 889          */
 890         iport = ddi_get_name_addr(dip);
 891         if (iport && strncmp(iport, "v0", 2) == 0) {
 892                 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 893                     MPTSAS_VIRTUAL_PORT, 1) !=
 894                     DDI_PROP_SUCCESS) {
 895                         (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
 896                             MPTSAS_VIRTUAL_PORT);
 897                         mptsas_log(mpt, CE_WARN, "mptsas virtual port "
 898                             "prop update failed");
 899                         return (DDI_FAILURE);
 900                 }
 901                 return (DDI_SUCCESS);
 902         }
 903 
 904         mutex_enter(&mpt->m_mutex);
 905         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 906                 bzero(phymask, sizeof (phymask));
 907                 (void) sprintf(phymask,
 908                     "%x", mpt->m_phy_info[i].phy_mask);
 909                 if (strcmp(phymask, iport) == 0) {
 910                         break;
 911                 }
 912         }
 913 
 914         if (i == MPTSAS_MAX_PHYS) {
 915                 mptsas_log(mpt, CE_WARN, "Failed attach port %s because port"
 916                     "seems not exist", iport);
 917                 mutex_exit(&mpt->m_mutex);
 918                 return (DDI_FAILURE);
 919         }
 920 
 921         phy_mask = mpt->m_phy_info[i].phy_mask;
 922 
 923         if (mpt->m_phy_info[i].port_flags & AUTO_PORT_CONFIGURATION)
 924                 dynamic_port = 1;
 925         else
 926                 dynamic_port = 0;
 927 
 928         /*
 929          * Update PHY info for smhba
 930          */
 931         if (mptsas_smhba_phy_init(mpt)) {
 932                 mutex_exit(&mpt->m_mutex);
 933                 mptsas_log(mpt, CE_WARN, "mptsas phy update "
 934                     "failed");
 935                 return (DDI_FAILURE);
 936         }
 937 
 938         mutex_exit(&mpt->m_mutex);
 939 
 940         numphys = 0;
 941         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 942                 if ((phy_mask >> i) & 0x01) {
 943                         numphys++;
 944                 }
 945         }
 946 
 947         bzero(initiator_wwnstr, sizeof (initiator_wwnstr));
 948         (void) sprintf(initiator_wwnstr, "w%016"PRIx64,
 949             mpt->un.m_base_wwid);
 950 
 951         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
 952             SCSI_ADDR_PROP_INITIATOR_PORT, initiator_wwnstr) !=
 953             DDI_PROP_SUCCESS) {
 954                 (void) ddi_prop_remove(DDI_DEV_T_NONE,
 955                     dip, SCSI_ADDR_PROP_INITIATOR_PORT);
 956                 mptsas_log(mpt, CE_WARN, "mptsas Initiator port "
 957                     "prop update failed");
 958                 return (DDI_FAILURE);
 959         }
 960         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 961             MPTSAS_NUM_PHYS, numphys) !=
 962             DDI_PROP_SUCCESS) {
 963                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, MPTSAS_NUM_PHYS);
 964                 return (DDI_FAILURE);
 965         }
 966 
 967         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 968             "phymask", phy_mask) !=
 969             DDI_PROP_SUCCESS) {
 970                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "phymask");
 971                 mptsas_log(mpt, CE_WARN, "mptsas phy mask "
 972                     "prop update failed");
 973                 return (DDI_FAILURE);
 974         }
 975 
 976         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 977             "dynamic-port", dynamic_port) !=
 978             DDI_PROP_SUCCESS) {
 979                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "dynamic-port");
 980                 mptsas_log(mpt, CE_WARN, "mptsas dynamic port "
 981                     "prop update failed");
 982                 return (DDI_FAILURE);
 983         }
 984         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 985             MPTSAS_VIRTUAL_PORT, 0) !=
 986             DDI_PROP_SUCCESS) {
 987                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
 988                     MPTSAS_VIRTUAL_PORT);
 989                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
 990                     "prop update failed");
 991                 return (DDI_FAILURE);
 992         }
 993         mptsas_smhba_set_all_phy_props(mpt, dip, numphys, phy_mask,
 994             &attached_devhdl);
 995 
 996         mutex_enter(&mpt->m_mutex);
 997         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
 998             MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)attached_devhdl;
 999         rval = mptsas_get_sas_device_page0(mpt, page_address, &dev_hdl,
1000             &attached_sas_wwn, &dev_info, &phy_port, &phy_id,
1001             &pdev_hdl, &bay_num, &enclosure, &io_flags);
1002         if (rval != DDI_SUCCESS) {
1003                 mptsas_log(mpt, CE_WARN,
1004                     "Failed to get device page0 for handle:%d",
1005                     attached_devhdl);
1006                 mutex_exit(&mpt->m_mutex);
1007                 return (DDI_FAILURE);
1008         }
1009 
1010         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1011                 bzero(phymask, sizeof (phymask));
1012                 (void) sprintf(phymask, "%x", mpt->m_phy_info[i].phy_mask);
1013                 if (strcmp(phymask, iport) == 0) {
1014                         (void) sprintf(&mpt->m_phy_info[i].smhba_info.path[0],
1015                             "%x",
1016                             mpt->m_phy_info[i].phy_mask);
1017                 }
1018         }
1019         mutex_exit(&mpt->m_mutex);
1020 
1021         bzero(attached_wwnstr, sizeof (attached_wwnstr));
1022         (void) sprintf(attached_wwnstr, "w%016"PRIx64,
1023             attached_sas_wwn);
1024         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
1025             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
1026             DDI_PROP_SUCCESS) {
1027                 (void) ddi_prop_remove(DDI_DEV_T_NONE,
1028                     dip, SCSI_ADDR_PROP_ATTACHED_PORT);
1029                 return (DDI_FAILURE);
1030         }
1031 
1032         /* Create kstats for each phy on this iport */
1033 
1034         mptsas_create_phy_stats(mpt, iport, dip);
1035 
1036         /*
1037          * register sas hba iport with mdi (MPxIO/vhci)
1038          */
1039         if (mdi_phci_register(MDI_HCI_CLASS_SCSI,
1040             dip, 0) == MDI_SUCCESS) {
1041                 mpt->m_mpxio_enable = TRUE;
1042         }
1043         return (DDI_SUCCESS);
1044 }
1045 
1046 /*
1047  * Notes:
1048  *      Set up all device state and allocate data structures,
1049  *      mutexes, condition variables, etc. for device operation.
1050  *      Add interrupts needed.
1051  *      Return DDI_SUCCESS if device is ready, else return DDI_FAILURE.
1052  */
1053 static int
1054 mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1055 {
1056         mptsas_t                *mpt = NULL;
1057         int                     instance, i, j;
1058         int                     doneq_thread_num;
1059         char                    intr_added = 0;
1060         char                    map_setup = 0;
1061         char                    config_setup = 0;
1062         char                    hba_attach_setup = 0;
1063         char                    smp_attach_setup = 0;
1064         char                    mutex_init_done = 0;
1065         char                    event_taskq_create = 0;
1066         char                    reset_taskq_create = 0;
1067         char                    dr_taskq_create = 0;
1068         char                    doneq_thread_create = 0;
1069         char                    added_watchdog = 0;
1070         scsi_hba_tran_t         *hba_tran;
1071         uint_t                  mem_bar = MEM_SPACE;
1072         int                     rval = DDI_FAILURE;
1073 
1074         /* CONSTCOND */
1075         ASSERT(NO_COMPETING_THREADS);
1076 
1077         if (scsi_hba_iport_unit_address(dip)) {
1078                 return (mptsas_iport_attach(dip, cmd));
1079         }
1080 
1081         switch (cmd) {
1082         case DDI_ATTACH:
1083                 break;
1084 
1085         case DDI_RESUME:
1086                 if ((hba_tran = ddi_get_driver_private(dip)) == NULL)
1087                         return (DDI_FAILURE);
1088 
1089                 mpt = TRAN2MPT(hba_tran);
1090 
1091                 if (!mpt) {
1092                         return (DDI_FAILURE);
1093                 }
1094 
1095                 /*
1096                  * Reset hardware and softc to "no outstanding commands"
1097                  * Note that a check condition can result on first command
1098                  * to a target.
1099                  */
1100                 mutex_enter(&mpt->m_mutex);
1101 
1102                 /*
1103                  * raise power.
1104                  */
1105                 if (mpt->m_options & MPTSAS_OPT_PM) {
1106                         mutex_exit(&mpt->m_mutex);
1107                         (void) pm_busy_component(dip, 0);
1108                         rval = pm_power_has_changed(dip, 0, PM_LEVEL_D0);
1109                         if (rval == DDI_SUCCESS) {
1110                                 mutex_enter(&mpt->m_mutex);
1111                         } else {
1112                                 /*
1113                                  * The pm_raise_power() call above failed,
1114                                  * and that can only occur if we were unable
1115                                  * to reset the hardware.  This is probably
1116                                  * due to unhealty hardware, and because
1117                                  * important filesystems(such as the root
1118                                  * filesystem) could be on the attached disks,
1119                                  * it would not be a good idea to continue,
1120                                  * as we won't be entirely certain we are
1121                                  * writing correct data.  So we panic() here
1122                                  * to not only prevent possible data corruption,
1123                                  * but to give developers or end users a hope
1124                                  * of identifying and correcting any problems.
1125                                  */
1126                                 fm_panic("mptsas could not reset hardware "
1127                                     "during resume");
1128                         }
1129                 }
1130 
1131                 mpt->m_suspended = 0;
1132 
1133                 /*
1134                  * Reinitialize ioc
1135                  */
1136                 mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1137                 if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
1138                         mutex_exit(&mpt->m_mutex);
1139                         if (mpt->m_options & MPTSAS_OPT_PM) {
1140                                 (void) pm_idle_component(dip, 0);
1141                         }
1142                         fm_panic("mptsas init chip fail during resume");
1143                 }
1144                 /*
1145                  * mptsas_update_driver_data needs interrupts so enable them
1146                  * first.
1147                  */
1148                 MPTSAS_ENABLE_INTR(mpt);
1149                 mptsas_update_driver_data(mpt);
1150 
1151                 /* start requests, if possible */
1152                 mptsas_restart_hba(mpt);
1153 
1154                 mutex_exit(&mpt->m_mutex);
1155 
1156                 /*
1157                  * Restart watch thread
1158                  */
1159                 mutex_enter(&mptsas_global_mutex);
1160                 if (mptsas_timeout_id == 0) {
1161                         mptsas_timeout_id = timeout(mptsas_watch, NULL,
1162                             mptsas_tick);
1163                         mptsas_timeouts_enabled = 1;
1164                 }
1165                 mutex_exit(&mptsas_global_mutex);
1166 
1167                 /* report idle status to pm framework */
1168                 if (mpt->m_options & MPTSAS_OPT_PM) {
1169                         (void) pm_idle_component(dip, 0);
1170                 }
1171 
1172                 return (DDI_SUCCESS);
1173 
1174         default:
1175                 return (DDI_FAILURE);
1176 
1177         }
1178 
1179         instance = ddi_get_instance(dip);
1180 
1181         /*
1182          * Allocate softc information.
1183          */
1184         if (ddi_soft_state_zalloc(mptsas_state, instance) != DDI_SUCCESS) {
1185                 mptsas_log(NULL, CE_WARN,
1186                     "mptsas%d: cannot allocate soft state", instance);
1187                 goto fail;
1188         }
1189 
1190         mpt = ddi_get_soft_state(mptsas_state, instance);
1191 
1192         if (mpt == NULL) {
1193                 mptsas_log(NULL, CE_WARN,
1194                     "mptsas%d: cannot get soft state", instance);
1195                 goto fail;
1196         }
1197 
1198         /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
1199         scsi_size_clean(dip);
1200 
1201         mpt->m_dip = dip;
1202         mpt->m_instance = instance;
1203 
1204         /* Make a per-instance copy of the structures */
1205         mpt->m_io_dma_attr = mptsas_dma_attrs64;
1206         if (mptsas_use_64bit_msgaddr) {
1207                 mpt->m_msg_dma_attr = mptsas_dma_attrs64;
1208         } else {
1209                 mpt->m_msg_dma_attr = mptsas_dma_attrs;
1210         }
1211         mpt->m_reg_acc_attr = mptsas_dev_attr;
1212         mpt->m_dev_acc_attr = mptsas_dev_attr;
1213 
1214         /*
1215          * Size of individual request sense buffer
1216          */
1217         mpt->m_req_sense_size = EXTCMDS_STATUS_SIZE;
1218 
1219         /*
1220          * Initialize FMA
1221          */
1222         mpt->m_fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, mpt->m_dip,
1223             DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
1224             DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
1225             DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
1226 
1227         mptsas_fm_init(mpt);
1228 
1229         if (mptsas_alloc_handshake_msg(mpt,
1230             sizeof (Mpi2SCSITaskManagementRequest_t)) == DDI_FAILURE) {
1231                 mptsas_log(mpt, CE_WARN, "cannot initialize handshake msg.");
1232                 goto fail;
1233         }
1234 
1235         /*
1236          * Setup configuration space
1237          */
1238         if (mptsas_config_space_init(mpt) == FALSE) {
1239                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init failed");
1240                 goto fail;
1241         }
1242         config_setup++;
1243 
1244         if (ddi_regs_map_setup(dip, mem_bar, (caddr_t *)&mpt->m_reg,
1245             0, 0, &mpt->m_reg_acc_attr, &mpt->m_datap) != DDI_SUCCESS) {
1246                 mptsas_log(mpt, CE_WARN, "map setup failed");
1247                 goto fail;
1248         }
1249         map_setup++;
1250 
1251         /*
1252          * A taskq is created for dealing with the event handler
1253          */
1254         if ((mpt->m_event_taskq = ddi_taskq_create(dip, "mptsas_event_taskq",
1255             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1256                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create failed");
1257                 goto fail;
1258         }
1259         event_taskq_create++;
1260 
1261         /*
1262          * A taskq is created for dealing with dr events
1263          */
1264         if ((mpt->m_dr_taskq = ddi_taskq_create(dip,
1265             "mptsas_dr_taskq",
1266             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1267                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create for discovery "
1268                     "failed");
1269                 goto fail;
1270         }
1271         dr_taskq_create++;
1272 
1273         /*
1274          * A taskq is created for dealing with reset events
1275          */
1276         if ((mpt->m_reset_taskq = ddi_taskq_create(dip,
1277             "mptsas_reset_taskq",
1278             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1279                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create for reset "
1280                     "failed");
1281                 goto fail;
1282         }
1283         reset_taskq_create++;
1284 
1285         mpt->m_doneq_thread_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1286             0, "mptsas_doneq_thread_threshold_prop", 10);
1287         mpt->m_doneq_length_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1288             0, "mptsas_doneq_length_threshold_prop", 8);
1289         mpt->m_doneq_thread_n = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1290             0, "mptsas_doneq_thread_n_prop", 8);
1291 
1292         if (mpt->m_doneq_thread_n) {
1293                 cv_init(&mpt->m_doneq_thread_cv, NULL, CV_DRIVER, NULL);
1294                 mutex_init(&mpt->m_doneq_mutex, NULL, MUTEX_DRIVER, NULL);
1295 
1296                 mutex_enter(&mpt->m_doneq_mutex);
1297                 mpt->m_doneq_thread_id =
1298                     kmem_zalloc(sizeof (mptsas_doneq_thread_list_t)
1299                     * mpt->m_doneq_thread_n, KM_SLEEP);
1300 
1301                 for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1302                         cv_init(&mpt->m_doneq_thread_id[j].cv, NULL,
1303                             CV_DRIVER, NULL);
1304                         mutex_init(&mpt->m_doneq_thread_id[j].mutex, NULL,
1305                             MUTEX_DRIVER, NULL);
1306                         mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1307                         mpt->m_doneq_thread_id[j].flag |=
1308                             MPTSAS_DONEQ_THREAD_ACTIVE;
1309                         mpt->m_doneq_thread_id[j].arg.mpt = mpt;
1310                         mpt->m_doneq_thread_id[j].arg.t = j;
1311                         mpt->m_doneq_thread_id[j].threadp =
1312                             thread_create(NULL, 0, mptsas_doneq_thread,
1313                             &mpt->m_doneq_thread_id[j].arg,
1314                             0, &p0, TS_RUN, minclsyspri);
1315                         mpt->m_doneq_thread_id[j].donetail =
1316                             &mpt->m_doneq_thread_id[j].doneq;
1317                         mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1318                 }
1319                 mutex_exit(&mpt->m_doneq_mutex);
1320                 doneq_thread_create++;
1321         }
1322 
1323         /*
1324          * Disable hardware interrupt since we're not ready to
1325          * handle it yet.
1326          */
1327         MPTSAS_DISABLE_INTR(mpt);
1328         if (mptsas_register_intrs(mpt) == FALSE)
1329                 goto fail;
1330         intr_added++;
1331 
1332         /* Initialize mutex used in interrupt handler */
1333         mutex_init(&mpt->m_mutex, NULL, MUTEX_DRIVER,
1334             DDI_INTR_PRI(mpt->m_intr_pri));
1335         mutex_init(&mpt->m_passthru_mutex, NULL, MUTEX_DRIVER, NULL);
1336         mutex_init(&mpt->m_tx_waitq_mutex, NULL, MUTEX_DRIVER,
1337             DDI_INTR_PRI(mpt->m_intr_pri));
1338         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1339                 mutex_init(&mpt->m_phy_info[i].smhba_info.phy_mutex,
1340                     NULL, MUTEX_DRIVER,
1341                     DDI_INTR_PRI(mpt->m_intr_pri));
1342         }
1343 
1344         cv_init(&mpt->m_cv, NULL, CV_DRIVER, NULL);
1345         cv_init(&mpt->m_passthru_cv, NULL, CV_DRIVER, NULL);
1346         cv_init(&mpt->m_fw_cv, NULL, CV_DRIVER, NULL);
1347         cv_init(&mpt->m_config_cv, NULL, CV_DRIVER, NULL);
1348         cv_init(&mpt->m_fw_diag_cv, NULL, CV_DRIVER, NULL);
1349         mutex_init_done++;
1350 
1351         mutex_enter(&mpt->m_mutex);
1352         /*
1353          * Initialize power management component
1354          */
1355         if (mpt->m_options & MPTSAS_OPT_PM) {
1356                 if (mptsas_init_pm(mpt)) {
1357                         mutex_exit(&mpt->m_mutex);
1358                         mptsas_log(mpt, CE_WARN, "mptsas pm initialization "
1359                             "failed");
1360                         goto fail;
1361                 }
1362         }
1363 
1364         /*
1365          * Initialize chip using Message Unit Reset, if allowed
1366          */
1367         mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1368         if (mptsas_init_chip(mpt, TRUE) == DDI_FAILURE) {
1369                 mutex_exit(&mpt->m_mutex);
1370                 mptsas_log(mpt, CE_WARN, "mptsas chip initialization failed");
1371                 goto fail;
1372         }
1373 
1374         mpt->m_targets = refhash_create(MPTSAS_TARGET_BUCKET_COUNT,
1375             mptsas_target_addr_hash, mptsas_target_addr_cmp,
1376             mptsas_target_free, sizeof (mptsas_target_t),
1377             offsetof(mptsas_target_t, m_link),
1378             offsetof(mptsas_target_t, m_addr), KM_SLEEP);
1379 
1380         /*
1381          * Fill in the phy_info structure and get the base WWID
1382          */
1383         if (mptsas_get_manufacture_page5(mpt) == DDI_FAILURE) {
1384                 mptsas_log(mpt, CE_WARN,
1385                     "mptsas_get_manufacture_page5 failed!");
1386                 goto fail;
1387         }
1388 
1389         if (mptsas_get_sas_io_unit_page_hndshk(mpt)) {
1390                 mptsas_log(mpt, CE_WARN,
1391                     "mptsas_get_sas_io_unit_page_hndshk failed!");
1392                 goto fail;
1393         }
1394 
1395         if (mptsas_get_manufacture_page0(mpt) == DDI_FAILURE) {
1396                 mptsas_log(mpt, CE_WARN,
1397                     "mptsas_get_manufacture_page0 failed!");
1398                 goto fail;
1399         }
1400 
1401         mutex_exit(&mpt->m_mutex);
1402 
1403         /*
1404          * Register the iport for multiple port HBA
1405          */
1406         mptsas_iport_register(mpt);
1407 
1408         /*
1409          * initialize SCSI HBA transport structure
1410          */
1411         if (mptsas_hba_setup(mpt) == FALSE)
1412                 goto fail;
1413         hba_attach_setup++;
1414 
1415         if (mptsas_smp_setup(mpt) == FALSE)
1416                 goto fail;
1417         smp_attach_setup++;
1418 
1419         if (mptsas_cache_create(mpt) == FALSE)
1420                 goto fail;
1421 
1422         mpt->m_scsi_reset_delay      = ddi_prop_get_int(DDI_DEV_T_ANY,
1423             dip, 0, "scsi-reset-delay", SCSI_DEFAULT_RESET_DELAY);
1424         if (mpt->m_scsi_reset_delay == 0) {
1425                 mptsas_log(mpt, CE_NOTE,
1426                     "scsi_reset_delay of 0 is not recommended,"
1427                     " resetting to SCSI_DEFAULT_RESET_DELAY\n");
1428                 mpt->m_scsi_reset_delay = SCSI_DEFAULT_RESET_DELAY;
1429         }
1430 
1431         /*
1432          * Initialize the wait and done FIFO queue
1433          */
1434         mpt->m_donetail = &mpt->m_doneq;
1435         mpt->m_waitqtail = &mpt->m_waitq;
1436         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
1437         mpt->m_tx_draining = 0;
1438 
1439         /*
1440          * ioc cmd queue initialize
1441          */
1442         mpt->m_ioc_event_cmdtail = &mpt->m_ioc_event_cmdq;
1443         mpt->m_dev_handle = 0xFFFF;
1444 
1445         MPTSAS_ENABLE_INTR(mpt);
1446 
1447         /*
1448          * enable event notification
1449          */
1450         mutex_enter(&mpt->m_mutex);
1451         if (mptsas_ioc_enable_event_notification(mpt)) {
1452                 mutex_exit(&mpt->m_mutex);
1453                 goto fail;
1454         }
1455         mutex_exit(&mpt->m_mutex);
1456 
1457         /*
1458          * used for mptsas_watch
1459          */
1460         mptsas_list_add(mpt);
1461 
1462         mutex_enter(&mptsas_global_mutex);
1463         if (mptsas_timeouts_enabled == 0) {
1464                 mptsas_scsi_watchdog_tick = ddi_prop_get_int(DDI_DEV_T_ANY,
1465                     dip, 0, "scsi-watchdog-tick", DEFAULT_WD_TICK);
1466 
1467                 mptsas_tick = mptsas_scsi_watchdog_tick *
1468                     drv_usectohz((clock_t)1000000);
1469 
1470                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
1471                 mptsas_timeouts_enabled = 1;
1472         }
1473         mutex_exit(&mptsas_global_mutex);
1474         added_watchdog++;
1475 
1476         /*
1477          * Initialize PHY info for smhba.
1478          * This requires watchdog to be enabled otherwise if interrupts
1479          * don't work the system will hang.
1480          */
1481         if (mptsas_smhba_setup(mpt)) {
1482                 mptsas_log(mpt, CE_WARN, "mptsas phy initialization "
1483                     "failed");
1484                 goto fail;
1485         }
1486 
1487         /* Check all dma handles allocated in attach */
1488         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl)
1489             != DDI_SUCCESS) ||
1490             (mptsas_check_dma_handle(mpt->m_dma_req_sense_hdl)
1491             != DDI_SUCCESS) ||
1492             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl)
1493             != DDI_SUCCESS) ||
1494             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl)
1495             != DDI_SUCCESS) ||
1496             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl)
1497             != DDI_SUCCESS) ||
1498             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl)
1499             != DDI_SUCCESS)) {
1500                 goto fail;
1501         }
1502 
1503         /* Check all acc handles allocated in attach */
1504         if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
1505             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl)
1506             != DDI_SUCCESS) ||
1507             (mptsas_check_acc_handle(mpt->m_acc_req_sense_hdl)
1508             != DDI_SUCCESS) ||
1509             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl)
1510             != DDI_SUCCESS) ||
1511             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl)
1512             != DDI_SUCCESS) ||
1513             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl)
1514             != DDI_SUCCESS) ||
1515             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl)
1516             != DDI_SUCCESS) ||
1517             (mptsas_check_acc_handle(mpt->m_config_handle)
1518             != DDI_SUCCESS)) {
1519                 goto fail;
1520         }
1521 
1522         /*
1523          * After this point, we are not going to fail the attach.
1524          */
1525 
1526         /* Print message of HBA present */
1527         ddi_report_dev(dip);
1528 
1529         /* report idle status to pm framework */
1530         if (mpt->m_options & MPTSAS_OPT_PM) {
1531                 (void) pm_idle_component(dip, 0);
1532         }
1533 
1534         return (DDI_SUCCESS);
1535 
1536 fail:
1537         mptsas_log(mpt, CE_WARN, "attach failed");
1538         mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
1539         ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
1540         if (mpt) {
1541                 /* deallocate in reverse order */
1542                 if (added_watchdog) {
1543                         mptsas_list_del(mpt);
1544                         mutex_enter(&mptsas_global_mutex);
1545 
1546                         if (mptsas_timeout_id && (mptsas_head == NULL)) {
1547                                 timeout_id_t tid = mptsas_timeout_id;
1548                                 mptsas_timeouts_enabled = 0;
1549                                 mptsas_timeout_id = 0;
1550                                 mutex_exit(&mptsas_global_mutex);
1551                                 (void) untimeout(tid);
1552                                 mutex_enter(&mptsas_global_mutex);
1553                         }
1554                         mutex_exit(&mptsas_global_mutex);
1555                 }
1556 
1557                 mptsas_cache_destroy(mpt);
1558 
1559                 if (smp_attach_setup) {
1560                         mptsas_smp_teardown(mpt);
1561                 }
1562                 if (hba_attach_setup) {
1563                         mptsas_hba_teardown(mpt);
1564                 }
1565 
1566                 if (mpt->m_targets)
1567                         refhash_destroy(mpt->m_targets);
1568                 if (mpt->m_smp_targets)
1569                         refhash_destroy(mpt->m_smp_targets);
1570 
1571                 if (mpt->m_active) {
1572                         mptsas_free_active_slots(mpt);
1573                 }
1574                 if (intr_added) {
1575                         mptsas_unregister_intrs(mpt);
1576                 }
1577 
1578                 if (doneq_thread_create) {
1579                         mutex_enter(&mpt->m_doneq_mutex);
1580                         doneq_thread_num = mpt->m_doneq_thread_n;
1581                         for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1582                                 mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1583                                 mpt->m_doneq_thread_id[j].flag &=
1584                                     (~MPTSAS_DONEQ_THREAD_ACTIVE);
1585                                 cv_signal(&mpt->m_doneq_thread_id[j].cv);
1586                                 mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1587                         }
1588                         while (mpt->m_doneq_thread_n) {
1589                                 cv_wait(&mpt->m_doneq_thread_cv,
1590                                     &mpt->m_doneq_mutex);
1591                         }
1592                         for (j = 0; j < doneq_thread_num; j++) {
1593                                 cv_destroy(&mpt->m_doneq_thread_id[j].cv);
1594                                 mutex_destroy(&mpt->m_doneq_thread_id[j].mutex);
1595                         }
1596                         kmem_free(mpt->m_doneq_thread_id,
1597                             sizeof (mptsas_doneq_thread_list_t)
1598                             * doneq_thread_num);
1599                         mutex_exit(&mpt->m_doneq_mutex);
1600                         cv_destroy(&mpt->m_doneq_thread_cv);
1601                         mutex_destroy(&mpt->m_doneq_mutex);
1602                 }
1603                 if (event_taskq_create) {
1604                         ddi_taskq_destroy(mpt->m_event_taskq);
1605                 }
1606                 if (dr_taskq_create) {
1607                         ddi_taskq_destroy(mpt->m_dr_taskq);
1608                 }
1609                 if (reset_taskq_create) {
1610                         ddi_taskq_destroy(mpt->m_reset_taskq);
1611                 }
1612                 if (mutex_init_done) {
1613                         mutex_destroy(&mpt->m_tx_waitq_mutex);
1614                         mutex_destroy(&mpt->m_passthru_mutex);
1615                         mutex_destroy(&mpt->m_mutex);
1616                         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1617                                 mutex_destroy(
1618                                     &mpt->m_phy_info[i].smhba_info.phy_mutex);
1619                         }
1620                         cv_destroy(&mpt->m_cv);
1621                         cv_destroy(&mpt->m_passthru_cv);
1622                         cv_destroy(&mpt->m_fw_cv);
1623                         cv_destroy(&mpt->m_config_cv);
1624                         cv_destroy(&mpt->m_fw_diag_cv);
1625                 }
1626 
1627                 if (map_setup) {
1628                         mptsas_cfg_fini(mpt);
1629                 }
1630                 if (config_setup) {
1631                         mptsas_config_space_fini(mpt);
1632                 }
1633                 mptsas_free_handshake_msg(mpt);
1634                 mptsas_hba_fini(mpt);
1635 
1636                 mptsas_fm_fini(mpt);
1637                 ddi_soft_state_free(mptsas_state, instance);
1638                 ddi_prop_remove_all(dip);
1639         }
1640         return (DDI_FAILURE);
1641 }
1642 
1643 static int
1644 mptsas_suspend(dev_info_t *devi)
1645 {
1646         mptsas_t        *mpt, *g;
1647         scsi_hba_tran_t *tran;
1648 
1649         if (scsi_hba_iport_unit_address(devi)) {
1650                 return (DDI_SUCCESS);
1651         }
1652 
1653         if ((tran = ddi_get_driver_private(devi)) == NULL)
1654                 return (DDI_SUCCESS);
1655 
1656         mpt = TRAN2MPT(tran);
1657         if (!mpt) {
1658                 return (DDI_SUCCESS);
1659         }
1660 
1661         mutex_enter(&mpt->m_mutex);
1662 
1663         if (mpt->m_suspended++) {
1664                 mutex_exit(&mpt->m_mutex);
1665                 return (DDI_SUCCESS);
1666         }
1667 
1668         /*
1669          * Cancel timeout threads for this mpt
1670          */
1671         if (mpt->m_quiesce_timeid) {
1672                 timeout_id_t tid = mpt->m_quiesce_timeid;
1673                 mpt->m_quiesce_timeid = 0;
1674                 mutex_exit(&mpt->m_mutex);
1675                 (void) untimeout(tid);
1676                 mutex_enter(&mpt->m_mutex);
1677         }
1678 
1679         if (mpt->m_restart_cmd_timeid) {
1680                 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1681                 mpt->m_restart_cmd_timeid = 0;
1682                 mutex_exit(&mpt->m_mutex);
1683                 (void) untimeout(tid);
1684                 mutex_enter(&mpt->m_mutex);
1685         }
1686 
1687         mutex_exit(&mpt->m_mutex);
1688 
1689         (void) pm_idle_component(mpt->m_dip, 0);
1690 
1691         /*
1692          * Cancel watch threads if all mpts suspended
1693          */
1694         rw_enter(&mptsas_global_rwlock, RW_WRITER);
1695         for (g = mptsas_head; g != NULL; g = g->m_next) {
1696                 if (!g->m_suspended)
1697                         break;
1698         }
1699         rw_exit(&mptsas_global_rwlock);
1700 
1701         mutex_enter(&mptsas_global_mutex);
1702         if (g == NULL) {
1703                 timeout_id_t tid;
1704 
1705                 mptsas_timeouts_enabled = 0;
1706                 if (mptsas_timeout_id) {
1707                         tid = mptsas_timeout_id;
1708                         mptsas_timeout_id = 0;
1709                         mutex_exit(&mptsas_global_mutex);
1710                         (void) untimeout(tid);
1711                         mutex_enter(&mptsas_global_mutex);
1712                 }
1713                 if (mptsas_reset_watch) {
1714                         tid = mptsas_reset_watch;
1715                         mptsas_reset_watch = 0;
1716                         mutex_exit(&mptsas_global_mutex);
1717                         (void) untimeout(tid);
1718                         mutex_enter(&mptsas_global_mutex);
1719                 }
1720         }
1721         mutex_exit(&mptsas_global_mutex);
1722 
1723         mutex_enter(&mpt->m_mutex);
1724 
1725         /*
1726          * If this mpt is not in full power(PM_LEVEL_D0), just return.
1727          */
1728         if ((mpt->m_options & MPTSAS_OPT_PM) &&
1729             (mpt->m_power_level != PM_LEVEL_D0)) {
1730                 mutex_exit(&mpt->m_mutex);
1731                 return (DDI_SUCCESS);
1732         }
1733 
1734         /* Disable HBA interrupts in hardware */
1735         MPTSAS_DISABLE_INTR(mpt);
1736         /*
1737          * Send RAID action system shutdown to sync IR
1738          */
1739         mptsas_raid_action_system_shutdown(mpt);
1740 
1741         mutex_exit(&mpt->m_mutex);
1742 
1743         /* drain the taskq */
1744         ddi_taskq_wait(mpt->m_reset_taskq);
1745         ddi_taskq_wait(mpt->m_event_taskq);
1746         ddi_taskq_wait(mpt->m_dr_taskq);
1747 
1748         return (DDI_SUCCESS);
1749 }
1750 
1751 #ifdef  __sparc
1752 /*ARGSUSED*/
1753 static int
1754 mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd)
1755 {
1756         mptsas_t        *mpt;
1757         scsi_hba_tran_t *tran;
1758 
1759         /*
1760          * If this call is for iport, just return.
1761          */
1762         if (scsi_hba_iport_unit_address(devi))
1763                 return (DDI_SUCCESS);
1764 
1765         if ((tran = ddi_get_driver_private(devi)) == NULL)
1766                 return (DDI_SUCCESS);
1767 
1768         if ((mpt = TRAN2MPT(tran)) == NULL)
1769                 return (DDI_SUCCESS);
1770 
1771         /*
1772          * Send RAID action system shutdown to sync IR.  Disable HBA
1773          * interrupts in hardware first.
1774          */
1775         MPTSAS_DISABLE_INTR(mpt);
1776         mptsas_raid_action_system_shutdown(mpt);
1777 
1778         return (DDI_SUCCESS);
1779 }
1780 #else /* __sparc */
1781 /*
1782  * quiesce(9E) entry point.
1783  *
1784  * This function is called when the system is single-threaded at high
1785  * PIL with preemption disabled. Therefore, this function must not be
1786  * blocked.
1787  *
1788  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1789  * DDI_FAILURE indicates an error condition and should almost never happen.
1790  */
1791 static int
1792 mptsas_quiesce(dev_info_t *devi)
1793 {
1794         mptsas_t        *mpt;
1795         scsi_hba_tran_t *tran;
1796 
1797         /*
1798          * If this call is for iport, just return.
1799          */
1800         if (scsi_hba_iport_unit_address(devi))
1801                 return (DDI_SUCCESS);
1802 
1803         if ((tran = ddi_get_driver_private(devi)) == NULL)
1804                 return (DDI_SUCCESS);
1805 
1806         if ((mpt = TRAN2MPT(tran)) == NULL)
1807                 return (DDI_SUCCESS);
1808 
1809         /* Disable HBA interrupts in hardware */
1810         MPTSAS_DISABLE_INTR(mpt);
1811         /* Send RAID action system shutdonw to sync IR */
1812         mptsas_raid_action_system_shutdown(mpt);
1813 
1814         return (DDI_SUCCESS);
1815 }
1816 #endif  /* __sparc */
1817 
1818 /*
1819  * detach(9E).  Remove all device allocations and system resources;
1820  * disable device interrupts.
1821  * Return DDI_SUCCESS if done; DDI_FAILURE if there's a problem.
1822  */
1823 static int
1824 mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1825 {
1826         /* CONSTCOND */
1827         ASSERT(NO_COMPETING_THREADS);
1828         NDBG0(("mptsas_detach: dip=0x%p cmd=0x%p", (void *)devi, (void *)cmd));
1829 
1830         switch (cmd) {
1831         case DDI_DETACH:
1832                 return (mptsas_do_detach(devi));
1833 
1834         case DDI_SUSPEND:
1835                 return (mptsas_suspend(devi));
1836 
1837         default:
1838                 return (DDI_FAILURE);
1839         }
1840         /* NOTREACHED */
1841 }
1842 
1843 static int
1844 mptsas_do_detach(dev_info_t *dip)
1845 {
1846         mptsas_t        *mpt;
1847         scsi_hba_tran_t *tran;
1848         int             circ = 0;
1849         int             circ1 = 0;
1850         mdi_pathinfo_t  *pip = NULL;
1851         int             i;
1852         int             doneq_thread_num = 0;
1853 
1854         NDBG0(("mptsas_do_detach: dip=0x%p", (void *)dip));
1855 
1856         if ((tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) == NULL)
1857                 return (DDI_FAILURE);
1858 
1859         mpt = TRAN2MPT(tran);
1860         if (!mpt) {
1861                 return (DDI_FAILURE);
1862         }
1863         /*
1864          * Still have pathinfo child, should not detach mpt driver
1865          */
1866         if (scsi_hba_iport_unit_address(dip)) {
1867                 if (mpt->m_mpxio_enable) {
1868                         /*
1869                          * MPxIO enabled for the iport
1870                          */
1871                         ndi_devi_enter(scsi_vhci_dip, &circ1);
1872                         ndi_devi_enter(dip, &circ);
1873                         while (pip = mdi_get_next_client_path(dip, NULL)) {
1874                                 if (mdi_pi_free(pip, 0) == MDI_SUCCESS) {
1875                                         continue;
1876                                 }
1877                                 ndi_devi_exit(dip, circ);
1878                                 ndi_devi_exit(scsi_vhci_dip, circ1);
1879                                 NDBG12(("detach failed because of "
1880                                     "outstanding path info"));
1881                                 return (DDI_FAILURE);
1882                         }
1883                         ndi_devi_exit(dip, circ);
1884                         ndi_devi_exit(scsi_vhci_dip, circ1);
1885                         (void) mdi_phci_unregister(dip, 0);
1886                 }
1887 
1888                 ddi_prop_remove_all(dip);
1889 
1890                 return (DDI_SUCCESS);
1891         }
1892 
1893         /* Make sure power level is D0 before accessing registers */
1894         if (mpt->m_options & MPTSAS_OPT_PM) {
1895                 (void) pm_busy_component(dip, 0);
1896                 if (mpt->m_power_level != PM_LEVEL_D0) {
1897                         if (pm_raise_power(dip, 0, PM_LEVEL_D0) !=
1898                             DDI_SUCCESS) {
1899                                 mptsas_log(mpt, CE_WARN,
1900                                     "mptsas%d: Raise power request failed.",
1901                                     mpt->m_instance);
1902                                 (void) pm_idle_component(dip, 0);
1903                                 return (DDI_FAILURE);
1904                         }
1905                 }
1906         }
1907 
1908         /*
1909          * Send RAID action system shutdown to sync IR.  After action, send a
1910          * Message Unit Reset. Since after that DMA resource will be freed,
1911          * set ioc to READY state will avoid HBA initiated DMA operation.
1912          */
1913         mutex_enter(&mpt->m_mutex);
1914         MPTSAS_DISABLE_INTR(mpt);
1915         mptsas_raid_action_system_shutdown(mpt);
1916         mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1917         (void) mptsas_ioc_reset(mpt, FALSE);
1918         mutex_exit(&mpt->m_mutex);
1919         mptsas_rem_intrs(mpt);
1920         ddi_taskq_destroy(mpt->m_reset_taskq);
1921         ddi_taskq_destroy(mpt->m_event_taskq);
1922         ddi_taskq_destroy(mpt->m_dr_taskq);
1923 
1924         if (mpt->m_doneq_thread_n) {
1925                 mutex_enter(&mpt->m_doneq_mutex);
1926                 doneq_thread_num = mpt->m_doneq_thread_n;
1927                 for (i = 0; i < mpt->m_doneq_thread_n; i++) {
1928                         mutex_enter(&mpt->m_doneq_thread_id[i].mutex);
1929                         mpt->m_doneq_thread_id[i].flag &=
1930                             (~MPTSAS_DONEQ_THREAD_ACTIVE);
1931                         cv_signal(&mpt->m_doneq_thread_id[i].cv);
1932                         mutex_exit(&mpt->m_doneq_thread_id[i].mutex);
1933                 }
1934                 while (mpt->m_doneq_thread_n) {
1935                         cv_wait(&mpt->m_doneq_thread_cv,
1936                             &mpt->m_doneq_mutex);
1937                 }
1938                 for (i = 0;  i < doneq_thread_num; i++) {
1939                         cv_destroy(&mpt->m_doneq_thread_id[i].cv);
1940                         mutex_destroy(&mpt->m_doneq_thread_id[i].mutex);
1941                 }
1942                 kmem_free(mpt->m_doneq_thread_id,
1943                     sizeof (mptsas_doneq_thread_list_t)
1944                     * doneq_thread_num);
1945                 mutex_exit(&mpt->m_doneq_mutex);
1946                 cv_destroy(&mpt->m_doneq_thread_cv);
1947                 mutex_destroy(&mpt->m_doneq_mutex);
1948         }
1949 
1950         scsi_hba_reset_notify_tear_down(mpt->m_reset_notify_listf);
1951 
1952         mptsas_list_del(mpt);
1953 
1954         /*
1955          * Cancel timeout threads for this mpt
1956          */
1957         mutex_enter(&mpt->m_mutex);
1958         if (mpt->m_quiesce_timeid) {
1959                 timeout_id_t tid = mpt->m_quiesce_timeid;
1960                 mpt->m_quiesce_timeid = 0;
1961                 mutex_exit(&mpt->m_mutex);
1962                 (void) untimeout(tid);
1963                 mutex_enter(&mpt->m_mutex);
1964         }
1965 
1966         if (mpt->m_restart_cmd_timeid) {
1967                 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1968                 mpt->m_restart_cmd_timeid = 0;
1969                 mutex_exit(&mpt->m_mutex);
1970                 (void) untimeout(tid);
1971                 mutex_enter(&mpt->m_mutex);
1972         }
1973 
1974         mutex_exit(&mpt->m_mutex);
1975 
1976         /*
1977          * last mpt? ... if active, CANCEL watch threads.
1978          */
1979         mutex_enter(&mptsas_global_mutex);
1980         if (mptsas_head == NULL) {
1981                 timeout_id_t tid;
1982                 /*
1983                  * Clear mptsas_timeouts_enable so that the watch thread
1984                  * gets restarted on DDI_ATTACH
1985                  */
1986                 mptsas_timeouts_enabled = 0;
1987                 if (mptsas_timeout_id) {
1988                         tid = mptsas_timeout_id;
1989                         mptsas_timeout_id = 0;
1990                         mutex_exit(&mptsas_global_mutex);
1991                         (void) untimeout(tid);
1992                         mutex_enter(&mptsas_global_mutex);
1993                 }
1994                 if (mptsas_reset_watch) {
1995                         tid = mptsas_reset_watch;
1996                         mptsas_reset_watch = 0;
1997                         mutex_exit(&mptsas_global_mutex);
1998                         (void) untimeout(tid);
1999                         mutex_enter(&mptsas_global_mutex);
2000                 }
2001         }
2002         mutex_exit(&mptsas_global_mutex);
2003 
2004         /*
2005          * Delete Phy stats
2006          */
2007         mptsas_destroy_phy_stats(mpt);
2008 
2009         mptsas_destroy_hashes(mpt);
2010 
2011         /*
2012          * Delete nt_active.
2013          */
2014         mutex_enter(&mpt->m_mutex);
2015         mptsas_free_active_slots(mpt);
2016         mutex_exit(&mpt->m_mutex);
2017 
2018         /* deallocate everything that was allocated in mptsas_attach */
2019         mptsas_cache_destroy(mpt);
2020 
2021         mptsas_hba_fini(mpt);
2022         mptsas_cfg_fini(mpt);
2023 
2024         /* Lower the power informing PM Framework */
2025         if (mpt->m_options & MPTSAS_OPT_PM) {
2026                 if (pm_lower_power(dip, 0, PM_LEVEL_D3) != DDI_SUCCESS)
2027                         mptsas_log(mpt, CE_WARN,
2028                             "!mptsas%d: Lower power request failed "
2029                             "during detach, ignoring.",
2030                             mpt->m_instance);
2031         }
2032 
2033         mutex_destroy(&mpt->m_tx_waitq_mutex);
2034         mutex_destroy(&mpt->m_passthru_mutex);
2035         mutex_destroy(&mpt->m_mutex);
2036         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
2037                 mutex_destroy(&mpt->m_phy_info[i].smhba_info.phy_mutex);
2038         }
2039         cv_destroy(&mpt->m_cv);
2040         cv_destroy(&mpt->m_passthru_cv);
2041         cv_destroy(&mpt->m_fw_cv);
2042         cv_destroy(&mpt->m_config_cv);
2043         cv_destroy(&mpt->m_fw_diag_cv);
2044 
2045 
2046         mptsas_smp_teardown(mpt);
2047         mptsas_hba_teardown(mpt);
2048 
2049         mptsas_config_space_fini(mpt);
2050 
2051         mptsas_free_handshake_msg(mpt);
2052 
2053         mptsas_fm_fini(mpt);
2054         ddi_soft_state_free(mptsas_state, ddi_get_instance(dip));
2055         ddi_prop_remove_all(dip);
2056 
2057         return (DDI_SUCCESS);
2058 }
2059 
2060 static void
2061 mptsas_list_add(mptsas_t *mpt)
2062 {
2063         rw_enter(&mptsas_global_rwlock, RW_WRITER);
2064 
2065         if (mptsas_head == NULL) {
2066                 mptsas_head = mpt;
2067         } else {
2068                 mptsas_tail->m_next = mpt;
2069         }
2070         mptsas_tail = mpt;
2071         rw_exit(&mptsas_global_rwlock);
2072 }
2073 
2074 static void
2075 mptsas_list_del(mptsas_t *mpt)
2076 {
2077         mptsas_t *m;
2078         /*
2079          * Remove device instance from the global linked list
2080          */
2081         rw_enter(&mptsas_global_rwlock, RW_WRITER);
2082         if (mptsas_head == mpt) {
2083                 m = mptsas_head = mpt->m_next;
2084         } else {
2085                 for (m = mptsas_head; m != NULL; m = m->m_next) {
2086                         if (m->m_next == mpt) {
2087                                 m->m_next = mpt->m_next;
2088                                 break;
2089                         }
2090                 }
2091                 if (m == NULL) {
2092                         mptsas_log(mpt, CE_PANIC, "Not in softc list!");
2093                 }
2094         }
2095 
2096         if (mptsas_tail == mpt) {
2097                 mptsas_tail = m;
2098         }
2099         rw_exit(&mptsas_global_rwlock);
2100 }
2101 
2102 static int
2103 mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size)
2104 {
2105         ddi_dma_attr_t  task_dma_attrs;
2106 
2107         mpt->m_hshk_dma_size = 0;
2108         task_dma_attrs = mpt->m_msg_dma_attr;
2109         task_dma_attrs.dma_attr_sgllen = 1;
2110         task_dma_attrs.dma_attr_granular = (uint32_t)(alloc_size);
2111 
2112         /* allocate Task Management ddi_dma resources */
2113         if (mptsas_dma_addr_create(mpt, task_dma_attrs,
2114             &mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl, &mpt->m_hshk_memp,
2115             alloc_size, NULL) == FALSE) {
2116                 return (DDI_FAILURE);
2117         }
2118         mpt->m_hshk_dma_size = alloc_size;
2119 
2120         return (DDI_SUCCESS);
2121 }
2122 
2123 static void
2124 mptsas_free_handshake_msg(mptsas_t *mpt)
2125 {
2126         if (mpt->m_hshk_dma_size == 0)
2127                 return;
2128         mptsas_dma_addr_destroy(&mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl);
2129         mpt->m_hshk_dma_size = 0;
2130 }
2131 
2132 static int
2133 mptsas_hba_setup(mptsas_t *mpt)
2134 {
2135         scsi_hba_tran_t         *hba_tran;
2136         int                     tran_flags;
2137 
2138         /* Allocate a transport structure */
2139         hba_tran = mpt->m_tran = scsi_hba_tran_alloc(mpt->m_dip,
2140             SCSI_HBA_CANSLEEP);
2141         ASSERT(mpt->m_tran != NULL);
2142 
2143         hba_tran->tran_hba_private   = mpt;
2144         hba_tran->tran_tgt_private   = NULL;
2145 
2146         hba_tran->tran_tgt_init              = mptsas_scsi_tgt_init;
2147         hba_tran->tran_tgt_free              = mptsas_scsi_tgt_free;
2148 
2149         hba_tran->tran_start         = mptsas_scsi_start;
2150         hba_tran->tran_reset         = mptsas_scsi_reset;
2151         hba_tran->tran_abort         = mptsas_scsi_abort;
2152         hba_tran->tran_getcap                = mptsas_scsi_getcap;
2153         hba_tran->tran_setcap                = mptsas_scsi_setcap;
2154         hba_tran->tran_init_pkt              = mptsas_scsi_init_pkt;
2155         hba_tran->tran_destroy_pkt   = mptsas_scsi_destroy_pkt;
2156 
2157         hba_tran->tran_dmafree               = mptsas_scsi_dmafree;
2158         hba_tran->tran_sync_pkt              = mptsas_scsi_sync_pkt;
2159         hba_tran->tran_reset_notify  = mptsas_scsi_reset_notify;
2160 
2161         hba_tran->tran_get_bus_addr  = mptsas_get_bus_addr;
2162         hba_tran->tran_get_name              = mptsas_get_name;
2163 
2164         hba_tran->tran_quiesce               = mptsas_scsi_quiesce;
2165         hba_tran->tran_unquiesce     = mptsas_scsi_unquiesce;
2166         hba_tran->tran_bus_reset     = NULL;
2167 
2168         hba_tran->tran_add_eventcall = NULL;
2169         hba_tran->tran_get_eventcookie       = NULL;
2170         hba_tran->tran_post_event    = NULL;
2171         hba_tran->tran_remove_eventcall      = NULL;
2172 
2173         hba_tran->tran_bus_config    = mptsas_bus_config;
2174 
2175         hba_tran->tran_interconnect_type = INTERCONNECT_SAS;
2176 
2177         /*
2178          * All children of the HBA are iports. We need tran was cloned.
2179          * So we pass the flags to SCSA. SCSI_HBA_TRAN_CLONE will be
2180          * inherited to iport's tran vector.
2181          */
2182         tran_flags = (SCSI_HBA_HBA | SCSI_HBA_TRAN_CLONE);
2183 
2184         if (scsi_hba_attach_setup(mpt->m_dip, &mpt->m_msg_dma_attr,
2185             hba_tran, tran_flags) != DDI_SUCCESS) {
2186                 mptsas_log(mpt, CE_WARN, "hba attach setup failed");
2187                 scsi_hba_tran_free(hba_tran);
2188                 mpt->m_tran = NULL;
2189                 return (FALSE);
2190         }
2191         return (TRUE);
2192 }
2193 
2194 static void
2195 mptsas_hba_teardown(mptsas_t *mpt)
2196 {
2197         (void) scsi_hba_detach(mpt->m_dip);
2198         if (mpt->m_tran != NULL) {
2199                 scsi_hba_tran_free(mpt->m_tran);
2200                 mpt->m_tran = NULL;
2201         }
2202 }
2203 
2204 static void
2205 mptsas_iport_register(mptsas_t *mpt)
2206 {
2207         int i, j;
2208         mptsas_phymask_t        mask = 0x0;
2209         /*
2210          * initial value of mask is 0
2211          */
2212         mutex_enter(&mpt->m_mutex);
2213         for (i = 0; i < mpt->m_num_phys; i++) {
2214                 mptsas_phymask_t phy_mask = 0x0;
2215                 char phy_mask_name[MPTSAS_MAX_PHYS];
2216                 uint8_t current_port;
2217 
2218                 if (mpt->m_phy_info[i].attached_devhdl == 0)
2219                         continue;
2220 
2221                 bzero(phy_mask_name, sizeof (phy_mask_name));
2222 
2223                 current_port = mpt->m_phy_info[i].port_num;
2224 
2225                 if ((mask & (1 << i)) != 0)
2226                         continue;
2227 
2228                 for (j = 0; j < mpt->m_num_phys; j++) {
2229                         if (mpt->m_phy_info[j].attached_devhdl &&
2230                             (mpt->m_phy_info[j].port_num == current_port)) {
2231                                 phy_mask |= (1 << j);
2232                         }
2233                 }
2234                 mask = mask | phy_mask;
2235 
2236                 for (j = 0; j < mpt->m_num_phys; j++) {
2237                         if ((phy_mask >> j) & 0x01) {
2238                                 mpt->m_phy_info[j].phy_mask = phy_mask;
2239                         }
2240                 }
2241 
2242                 (void) sprintf(phy_mask_name, "%x", phy_mask);
2243 
2244                 mutex_exit(&mpt->m_mutex);
2245                 /*
2246                  * register a iport
2247                  */
2248                 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
2249                 mutex_enter(&mpt->m_mutex);
2250         }
2251         mutex_exit(&mpt->m_mutex);
2252         /*
2253          * register a virtual port for RAID volume always
2254          */
2255         (void) scsi_hba_iport_register(mpt->m_dip, "v0");
2256 
2257 }
2258 
2259 static int
2260 mptsas_smp_setup(mptsas_t *mpt)
2261 {
2262         mpt->m_smptran = smp_hba_tran_alloc(mpt->m_dip);
2263         ASSERT(mpt->m_smptran != NULL);
2264         mpt->m_smptran->smp_tran_hba_private = mpt;
2265         mpt->m_smptran->smp_tran_start = mptsas_smp_start;
2266         if (smp_hba_attach_setup(mpt->m_dip, mpt->m_smptran) != DDI_SUCCESS) {
2267                 mptsas_log(mpt, CE_WARN, "smp attach setup failed");
2268                 smp_hba_tran_free(mpt->m_smptran);
2269                 mpt->m_smptran = NULL;
2270                 return (FALSE);
2271         }
2272         /*
2273          * Initialize smp hash table
2274          */
2275         mpt->m_smp_targets = refhash_create(MPTSAS_SMP_BUCKET_COUNT,
2276             mptsas_target_addr_hash, mptsas_target_addr_cmp,
2277             mptsas_smp_free, sizeof (mptsas_smp_t),
2278             offsetof(mptsas_smp_t, m_link), offsetof(mptsas_smp_t, m_addr),
2279             KM_SLEEP);
2280         mpt->m_smp_devhdl = 0xFFFF;
2281 
2282         return (TRUE);
2283 }
2284 
2285 static void
2286 mptsas_smp_teardown(mptsas_t *mpt)
2287 {
2288         (void) smp_hba_detach(mpt->m_dip);
2289         if (mpt->m_smptran != NULL) {
2290                 smp_hba_tran_free(mpt->m_smptran);
2291                 mpt->m_smptran = NULL;
2292         }
2293         mpt->m_smp_devhdl = 0;
2294 }
2295 
2296 static int
2297 mptsas_cache_create(mptsas_t *mpt)
2298 {
2299         int instance = mpt->m_instance;
2300         char buf[64];
2301 
2302         /*
2303          * create kmem cache for packets
2304          */
2305         (void) sprintf(buf, "mptsas%d_cache", instance);
2306         mpt->m_kmem_cache = kmem_cache_create(buf,
2307             sizeof (struct mptsas_cmd) + scsi_pkt_size(), 8,
2308             mptsas_kmem_cache_constructor, mptsas_kmem_cache_destructor,
2309             NULL, (void *)mpt, NULL, 0);
2310 
2311         if (mpt->m_kmem_cache == NULL) {
2312                 mptsas_log(mpt, CE_WARN, "creating kmem cache failed");
2313                 return (FALSE);
2314         }
2315 
2316         /*
2317          * create kmem cache for extra SGL frames if SGL cannot
2318          * be accomodated into main request frame.
2319          */
2320         (void) sprintf(buf, "mptsas%d_cache_frames", instance);
2321         mpt->m_cache_frames = kmem_cache_create(buf,
2322             sizeof (mptsas_cache_frames_t), 8,
2323             mptsas_cache_frames_constructor, mptsas_cache_frames_destructor,
2324             NULL, (void *)mpt, NULL, 0);
2325 
2326         if (mpt->m_cache_frames == NULL) {
2327                 mptsas_log(mpt, CE_WARN, "creating cache for frames failed");
2328                 return (FALSE);
2329         }
2330 
2331         return (TRUE);
2332 }
2333 
2334 static void
2335 mptsas_cache_destroy(mptsas_t *mpt)
2336 {
2337         /* deallocate in reverse order */
2338         if (mpt->m_cache_frames) {
2339                 kmem_cache_destroy(mpt->m_cache_frames);
2340                 mpt->m_cache_frames = NULL;
2341         }
2342         if (mpt->m_kmem_cache) {
2343                 kmem_cache_destroy(mpt->m_kmem_cache);
2344                 mpt->m_kmem_cache = NULL;
2345         }
2346 }
2347 
2348 static int
2349 mptsas_power(dev_info_t *dip, int component, int level)
2350 {
2351 #ifndef __lock_lint
2352         _NOTE(ARGUNUSED(component))
2353 #endif
2354         mptsas_t        *mpt;
2355         int             rval = DDI_SUCCESS;
2356         int             polls = 0;
2357         uint32_t        ioc_status;
2358 
2359         if (scsi_hba_iport_unit_address(dip) != 0)
2360                 return (DDI_SUCCESS);
2361 
2362         mpt = ddi_get_soft_state(mptsas_state, ddi_get_instance(dip));
2363         if (mpt == NULL) {
2364                 return (DDI_FAILURE);
2365         }
2366 
2367         mutex_enter(&mpt->m_mutex);
2368 
2369         /*
2370          * If the device is busy, don't lower its power level
2371          */
2372         if (mpt->m_busy && (mpt->m_power_level > level)) {
2373                 mutex_exit(&mpt->m_mutex);
2374                 return (DDI_FAILURE);
2375         }
2376         switch (level) {
2377         case PM_LEVEL_D0:
2378                 NDBG11(("mptsas%d: turning power ON.", mpt->m_instance));
2379                 MPTSAS_POWER_ON(mpt);
2380                 /*
2381                  * Wait up to 30 seconds for IOC to come out of reset.
2382                  */
2383                 while (((ioc_status = ddi_get32(mpt->m_datap,
2384                     &mpt->m_reg->Doorbell)) &
2385                     MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_RESET) {
2386                         if (polls++ > 3000) {
2387                                 break;
2388                         }
2389                         delay(drv_usectohz(10000));
2390                 }
2391                 /*
2392                  * If IOC is not in operational state, try to hard reset it.
2393                  */
2394                 if ((ioc_status & MPI2_IOC_STATE_MASK) !=
2395                     MPI2_IOC_STATE_OPERATIONAL) {
2396                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
2397                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
2398                                 mptsas_log(mpt, CE_WARN,
2399                                     "mptsas_power: hard reset failed");
2400                                 mutex_exit(&mpt->m_mutex);
2401                                 return (DDI_FAILURE);
2402                         }
2403                 }
2404                 mpt->m_power_level = PM_LEVEL_D0;
2405                 break;
2406         case PM_LEVEL_D3:
2407                 NDBG11(("mptsas%d: turning power OFF.", mpt->m_instance));
2408                 MPTSAS_POWER_OFF(mpt);
2409                 break;
2410         default:
2411                 mptsas_log(mpt, CE_WARN, "mptsas%d: unknown power level <%x>.",
2412                     mpt->m_instance, level);
2413                 rval = DDI_FAILURE;
2414                 break;
2415         }
2416         mutex_exit(&mpt->m_mutex);
2417         return (rval);
2418 }
2419 
2420 /*
2421  * Initialize configuration space and figure out which
2422  * chip and revison of the chip the mpt driver is using.
2423  */
2424 static int
2425 mptsas_config_space_init(mptsas_t *mpt)
2426 {
2427         NDBG0(("mptsas_config_space_init"));
2428 
2429         if (mpt->m_config_handle != NULL)
2430                 return (TRUE);
2431 
2432         if (pci_config_setup(mpt->m_dip,
2433             &mpt->m_config_handle) != DDI_SUCCESS) {
2434                 mptsas_log(mpt, CE_WARN, "cannot map configuration space.");
2435                 return (FALSE);
2436         }
2437 
2438         /*
2439          * This is a workaround for a XMITS ASIC bug which does not
2440          * drive the CBE upper bits.
2441          */
2442         if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT) &
2443             PCI_STAT_PERROR) {
2444                 pci_config_put16(mpt->m_config_handle, PCI_CONF_STAT,
2445                     PCI_STAT_PERROR);
2446         }
2447 
2448         mptsas_setup_cmd_reg(mpt);
2449 
2450         /*
2451          * Get the chip device id:
2452          */
2453         mpt->m_devid = pci_config_get16(mpt->m_config_handle, PCI_CONF_DEVID);
2454 
2455         /*
2456          * Save the revision.
2457          */
2458         mpt->m_revid = pci_config_get8(mpt->m_config_handle, PCI_CONF_REVID);
2459 
2460         /*
2461          * Save the SubSystem Vendor and Device IDs
2462          */
2463         mpt->m_svid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBVENID);
2464         mpt->m_ssid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBSYSID);
2465 
2466         /*
2467          * Set the latency timer to 0x40 as specified by the upa -> pci
2468          * bridge chip design team.  This may be done by the sparc pci
2469          * bus nexus driver, but the driver should make sure the latency
2470          * timer is correct for performance reasons.
2471          */
2472         pci_config_put8(mpt->m_config_handle, PCI_CONF_LATENCY_TIMER,
2473             MPTSAS_LATENCY_TIMER);
2474 
2475         (void) mptsas_get_pci_cap(mpt);
2476         return (TRUE);
2477 }
2478 
2479 static void
2480 mptsas_config_space_fini(mptsas_t *mpt)
2481 {
2482         if (mpt->m_config_handle != NULL) {
2483                 mptsas_disable_bus_master(mpt);
2484                 pci_config_teardown(&mpt->m_config_handle);
2485                 mpt->m_config_handle = NULL;
2486         }
2487 }
2488 
2489 static void
2490 mptsas_setup_cmd_reg(mptsas_t *mpt)
2491 {
2492         ushort_t        cmdreg;
2493 
2494         /*
2495          * Set the command register to the needed values.
2496          */
2497         cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2498         cmdreg |= (PCI_COMM_ME | PCI_COMM_SERR_ENABLE |
2499             PCI_COMM_PARITY_DETECT | PCI_COMM_MAE);
2500         cmdreg &= ~PCI_COMM_IO;
2501         pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2502 }
2503 
2504 static void
2505 mptsas_disable_bus_master(mptsas_t *mpt)
2506 {
2507         ushort_t        cmdreg;
2508 
2509         /*
2510          * Clear the master enable bit in the PCI command register.
2511          * This prevents any bus mastering activity like DMA.
2512          */
2513         cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2514         cmdreg &= ~PCI_COMM_ME;
2515         pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2516 }
2517 
2518 int
2519 mptsas_dma_alloc(mptsas_t *mpt, mptsas_dma_alloc_state_t *dma_statep)
2520 {
2521         ddi_dma_attr_t  attrs;
2522 
2523         attrs = mpt->m_io_dma_attr;
2524         attrs.dma_attr_sgllen = 1;
2525 
2526         ASSERT(dma_statep != NULL);
2527 
2528         if (mptsas_dma_addr_create(mpt, attrs, &dma_statep->handle,
2529             &dma_statep->accessp, &dma_statep->memp, dma_statep->size,
2530             &dma_statep->cookie) == FALSE) {
2531                 return (DDI_FAILURE);
2532         }
2533 
2534         return (DDI_SUCCESS);
2535 }
2536 
2537 void
2538 mptsas_dma_free(mptsas_dma_alloc_state_t *dma_statep)
2539 {
2540         ASSERT(dma_statep != NULL);
2541         mptsas_dma_addr_destroy(&dma_statep->handle, &dma_statep->accessp);
2542         dma_statep->size = 0;
2543 }
2544 
2545 int
2546 mptsas_do_dma(mptsas_t *mpt, uint32_t size, int var, int (*callback)())
2547 {
2548         ddi_dma_attr_t          attrs;
2549         ddi_dma_handle_t        dma_handle;
2550         caddr_t                 memp;
2551         ddi_acc_handle_t        accessp;
2552         int                     rval;
2553 
2554         ASSERT(mutex_owned(&mpt->m_mutex));
2555 
2556         attrs = mpt->m_msg_dma_attr;
2557         attrs.dma_attr_sgllen = 1;
2558         attrs.dma_attr_granular = size;
2559 
2560         if (mptsas_dma_addr_create(mpt, attrs, &dma_handle,
2561             &accessp, &memp, size, NULL) == FALSE) {
2562                 return (DDI_FAILURE);
2563         }
2564 
2565         rval = (*callback) (mpt, memp, var, accessp);
2566 
2567         if ((mptsas_check_dma_handle(dma_handle) != DDI_SUCCESS) ||
2568             (mptsas_check_acc_handle(accessp) != DDI_SUCCESS)) {
2569                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2570                 rval = DDI_FAILURE;
2571         }
2572 
2573         mptsas_dma_addr_destroy(&dma_handle, &accessp);
2574         return (rval);
2575 
2576 }
2577 
2578 static int
2579 mptsas_alloc_request_frames(mptsas_t *mpt)
2580 {
2581         ddi_dma_attr_t          frame_dma_attrs;
2582         caddr_t                 memp;
2583         ddi_dma_cookie_t        cookie;
2584         size_t                  mem_size;
2585 
2586         /*
2587          * re-alloc when it has already alloced
2588          */
2589         if (mpt->m_dma_req_frame_hdl)
2590                 mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2591                     &mpt->m_acc_req_frame_hdl);
2592 
2593         /*
2594          * The size of the request frame pool is:
2595          *   Number of Request Frames * Request Frame Size
2596          */
2597         mem_size = mpt->m_max_requests * mpt->m_req_frame_size;
2598 
2599         /*
2600          * set the DMA attributes.  System Request Message Frames must be
2601          * aligned on a 16-byte boundry.
2602          */
2603         frame_dma_attrs = mpt->m_msg_dma_attr;
2604         frame_dma_attrs.dma_attr_align = 16;
2605         frame_dma_attrs.dma_attr_sgllen = 1;
2606 
2607         /*
2608          * allocate the request frame pool.
2609          */
2610         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2611             &mpt->m_dma_req_frame_hdl, &mpt->m_acc_req_frame_hdl, &memp,
2612             mem_size, &cookie) == FALSE) {
2613                 return (DDI_FAILURE);
2614         }
2615 
2616         /*
2617          * Store the request frame memory address.  This chip uses this
2618          * address to dma to and from the driver's frame.  The second
2619          * address is the address mpt uses to fill in the frame.
2620          */
2621         mpt->m_req_frame_dma_addr = cookie.dmac_laddress;
2622         mpt->m_req_frame = memp;
2623 
2624         /*
2625          * Clear the request frame pool.
2626          */
2627         bzero(mpt->m_req_frame, mem_size);
2628 
2629         return (DDI_SUCCESS);
2630 }
2631 
2632 static int
2633 mptsas_alloc_sense_bufs(mptsas_t *mpt)
2634 {
2635         ddi_dma_attr_t          sense_dma_attrs;
2636         caddr_t                 memp;
2637         ddi_dma_cookie_t        cookie;
2638         size_t                  mem_size;
2639         int                     num_extrqsense_bufs;
2640 
2641         /*
2642          * re-alloc when it has already alloced
2643          */
2644         if (mpt->m_dma_req_sense_hdl) {
2645                 rmfreemap(mpt->m_erqsense_map);
2646                 mptsas_dma_addr_destroy(&mpt->m_dma_req_sense_hdl,
2647                     &mpt->m_acc_req_sense_hdl);
2648         }
2649 
2650         /*
2651          * The size of the request sense pool is:
2652          *   (Number of Request Frames - 2 ) * Request Sense Size +
2653          *   extra memory for extended sense requests.
2654          */
2655         mem_size = ((mpt->m_max_requests - 2) * mpt->m_req_sense_size) +
2656             mptsas_extreq_sense_bufsize;
2657 
2658         /*
2659          * set the DMA attributes.  ARQ buffers
2660          * aligned on a 16-byte boundry.
2661          */
2662         sense_dma_attrs = mpt->m_msg_dma_attr;
2663         sense_dma_attrs.dma_attr_align = 16;
2664         sense_dma_attrs.dma_attr_sgllen = 1;
2665 
2666         /*
2667          * allocate the request sense buffer pool.
2668          */
2669         if (mptsas_dma_addr_create(mpt, sense_dma_attrs,
2670             &mpt->m_dma_req_sense_hdl, &mpt->m_acc_req_sense_hdl, &memp,
2671             mem_size, &cookie) == FALSE) {
2672                 return (DDI_FAILURE);
2673         }
2674 
2675         /*
2676          * Store the request sense base memory address.  This chip uses this
2677          * address to dma the request sense data.  The second
2678          * address is the address mpt uses to access the data.
2679          * The third is the base for the extended rqsense buffers.
2680          */
2681         mpt->m_req_sense_dma_addr = cookie.dmac_laddress;
2682         mpt->m_req_sense = memp;
2683         memp += (mpt->m_max_requests - 2) * mpt->m_req_sense_size;
2684         mpt->m_extreq_sense = memp;
2685 
2686         /*
2687          * The extra memory is divided up into multiples of the base
2688          * buffer size in order to allocate via rmalloc().
2689          * Note that the rmallocmap cannot start at zero!
2690          */
2691         num_extrqsense_bufs = mptsas_extreq_sense_bufsize /
2692             mpt->m_req_sense_size;
2693         mpt->m_erqsense_map = rmallocmap_wait(num_extrqsense_bufs);
2694         rmfree(mpt->m_erqsense_map, num_extrqsense_bufs, 1);
2695 
2696         /*
2697          * Clear the pool.
2698          */
2699         bzero(mpt->m_req_sense, mem_size);
2700 
2701         return (DDI_SUCCESS);
2702 }
2703 
2704 static int
2705 mptsas_alloc_reply_frames(mptsas_t *mpt)
2706 {
2707         ddi_dma_attr_t          frame_dma_attrs;
2708         caddr_t                 memp;
2709         ddi_dma_cookie_t        cookie;
2710         size_t                  mem_size;
2711 
2712         /*
2713          * re-alloc when it has already alloced
2714          */
2715         if (mpt->m_dma_reply_frame_hdl) {
2716                 mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2717                     &mpt->m_acc_reply_frame_hdl);
2718         }
2719 
2720         /*
2721          * The size of the reply frame pool is:
2722          *   Number of Reply Frames * Reply Frame Size
2723          */
2724         mem_size = mpt->m_max_replies * mpt->m_reply_frame_size;
2725 
2726         /*
2727          * set the DMA attributes.   System Reply Message Frames must be
2728          * aligned on a 4-byte boundry.  This is the default.
2729          */
2730         frame_dma_attrs = mpt->m_msg_dma_attr;
2731         frame_dma_attrs.dma_attr_sgllen = 1;
2732 
2733         /*
2734          * allocate the reply frame pool
2735          */
2736         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2737             &mpt->m_dma_reply_frame_hdl, &mpt->m_acc_reply_frame_hdl, &memp,
2738             mem_size, &cookie) == FALSE) {
2739                 return (DDI_FAILURE);
2740         }
2741 
2742         /*
2743          * Store the reply frame memory address.  This chip uses this
2744          * address to dma to and from the driver's frame.  The second
2745          * address is the address mpt uses to process the frame.
2746          */
2747         mpt->m_reply_frame_dma_addr = cookie.dmac_laddress;
2748         mpt->m_reply_frame = memp;
2749 
2750         /*
2751          * Clear the reply frame pool.
2752          */
2753         bzero(mpt->m_reply_frame, mem_size);
2754 
2755         return (DDI_SUCCESS);
2756 }
2757 
2758 static int
2759 mptsas_alloc_free_queue(mptsas_t *mpt)
2760 {
2761         ddi_dma_attr_t          frame_dma_attrs;
2762         caddr_t                 memp;
2763         ddi_dma_cookie_t        cookie;
2764         size_t                  mem_size;
2765 
2766         /*
2767          * re-alloc when it has already alloced
2768          */
2769         if (mpt->m_dma_free_queue_hdl) {
2770                 mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2771                     &mpt->m_acc_free_queue_hdl);
2772         }
2773 
2774         /*
2775          * The reply free queue size is:
2776          *   Reply Free Queue Depth * 4
2777          * The "4" is the size of one 32 bit address (low part of 64-bit
2778          *   address)
2779          */
2780         mem_size = mpt->m_free_queue_depth * 4;
2781 
2782         /*
2783          * set the DMA attributes  The Reply Free Queue must be aligned on a
2784          * 16-byte boundry.
2785          */
2786         frame_dma_attrs = mpt->m_msg_dma_attr;
2787         frame_dma_attrs.dma_attr_align = 16;
2788         frame_dma_attrs.dma_attr_sgllen = 1;
2789 
2790         /*
2791          * allocate the reply free queue
2792          */
2793         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2794             &mpt->m_dma_free_queue_hdl, &mpt->m_acc_free_queue_hdl, &memp,
2795             mem_size, &cookie) == FALSE) {
2796                 return (DDI_FAILURE);
2797         }
2798 
2799         /*
2800          * Store the reply free queue memory address.  This chip uses this
2801          * address to read from the reply free queue.  The second address
2802          * is the address mpt uses to manage the queue.
2803          */
2804         mpt->m_free_queue_dma_addr = cookie.dmac_laddress;
2805         mpt->m_free_queue = memp;
2806 
2807         /*
2808          * Clear the reply free queue memory.
2809          */
2810         bzero(mpt->m_free_queue, mem_size);
2811 
2812         return (DDI_SUCCESS);
2813 }
2814 
2815 static int
2816 mptsas_alloc_post_queue(mptsas_t *mpt)
2817 {
2818         ddi_dma_attr_t          frame_dma_attrs;
2819         caddr_t                 memp;
2820         ddi_dma_cookie_t        cookie;
2821         size_t                  mem_size;
2822 
2823         /*
2824          * re-alloc when it has already alloced
2825          */
2826         if (mpt->m_dma_post_queue_hdl) {
2827                 mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2828                     &mpt->m_acc_post_queue_hdl);
2829         }
2830 
2831         /*
2832          * The reply descriptor post queue size is:
2833          *   Reply Descriptor Post Queue Depth * 8
2834          * The "8" is the size of each descriptor (8 bytes or 64 bits).
2835          */
2836         mem_size = mpt->m_post_queue_depth * 8;
2837 
2838         /*
2839          * set the DMA attributes.  The Reply Descriptor Post Queue must be
2840          * aligned on a 16-byte boundry.
2841          */
2842         frame_dma_attrs = mpt->m_msg_dma_attr;
2843         frame_dma_attrs.dma_attr_align = 16;
2844         frame_dma_attrs.dma_attr_sgllen = 1;
2845 
2846         /*
2847          * allocate the reply post queue
2848          */
2849         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2850             &mpt->m_dma_post_queue_hdl, &mpt->m_acc_post_queue_hdl, &memp,
2851             mem_size, &cookie) == FALSE) {
2852                 return (DDI_FAILURE);
2853         }
2854 
2855         /*
2856          * Store the reply descriptor post queue memory address.  This chip
2857          * uses this address to write to the reply descriptor post queue.  The
2858          * second address is the address mpt uses to manage the queue.
2859          */
2860         mpt->m_post_queue_dma_addr = cookie.dmac_laddress;
2861         mpt->m_post_queue = memp;
2862 
2863         /*
2864          * Clear the reply post queue memory.
2865          */
2866         bzero(mpt->m_post_queue, mem_size);
2867 
2868         return (DDI_SUCCESS);
2869 }
2870 
2871 static void
2872 mptsas_alloc_reply_args(mptsas_t *mpt)
2873 {
2874         if (mpt->m_replyh_args == NULL) {
2875                 mpt->m_replyh_args = kmem_zalloc(sizeof (m_replyh_arg_t) *
2876                     mpt->m_max_replies, KM_SLEEP);
2877         }
2878 }
2879 
2880 static int
2881 mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2882 {
2883         mptsas_cache_frames_t   *frames = NULL;
2884         if (cmd->cmd_extra_frames == NULL) {
2885                 frames = kmem_cache_alloc(mpt->m_cache_frames, KM_NOSLEEP);
2886                 if (frames == NULL) {
2887                         return (DDI_FAILURE);
2888                 }
2889                 cmd->cmd_extra_frames = frames;
2890         }
2891         return (DDI_SUCCESS);
2892 }
2893 
2894 static void
2895 mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2896 {
2897         if (cmd->cmd_extra_frames) {
2898                 kmem_cache_free(mpt->m_cache_frames,
2899                     (void *)cmd->cmd_extra_frames);
2900                 cmd->cmd_extra_frames = NULL;
2901         }
2902 }
2903 
2904 static void
2905 mptsas_cfg_fini(mptsas_t *mpt)
2906 {
2907         NDBG0(("mptsas_cfg_fini"));
2908         ddi_regs_map_free(&mpt->m_datap);
2909 }
2910 
2911 static void
2912 mptsas_hba_fini(mptsas_t *mpt)
2913 {
2914         NDBG0(("mptsas_hba_fini"));
2915 
2916         /*
2917          * Free up any allocated memory
2918          */
2919         if (mpt->m_dma_req_frame_hdl) {
2920                 mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2921                     &mpt->m_acc_req_frame_hdl);
2922         }
2923 
2924         if (mpt->m_dma_req_sense_hdl) {
2925                 rmfreemap(mpt->m_erqsense_map);
2926                 mptsas_dma_addr_destroy(&mpt->m_dma_req_sense_hdl,
2927                     &mpt->m_acc_req_sense_hdl);
2928         }
2929 
2930         if (mpt->m_dma_reply_frame_hdl) {
2931                 mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2932                     &mpt->m_acc_reply_frame_hdl);
2933         }
2934 
2935         if (mpt->m_dma_free_queue_hdl) {
2936                 mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2937                     &mpt->m_acc_free_queue_hdl);
2938         }
2939 
2940         if (mpt->m_dma_post_queue_hdl) {
2941                 mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2942                     &mpt->m_acc_post_queue_hdl);
2943         }
2944 
2945         if (mpt->m_replyh_args != NULL) {
2946                 kmem_free(mpt->m_replyh_args, sizeof (m_replyh_arg_t)
2947                     * mpt->m_max_replies);
2948         }
2949 }
2950 
2951 static int
2952 mptsas_name_child(dev_info_t *lun_dip, char *name, int len)
2953 {
2954         int             lun = 0;
2955         char            *sas_wwn = NULL;
2956         int             phynum = -1;
2957         int             reallen = 0;
2958 
2959         /* Get the target num */
2960         lun = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip, DDI_PROP_DONTPASS,
2961             LUN_PROP, 0);
2962 
2963         if ((phynum = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip,
2964             DDI_PROP_DONTPASS, "sata-phy", -1)) != -1) {
2965                 /*
2966                  * Stick in the address of form "pPHY,LUN"
2967                  */
2968                 reallen = snprintf(name, len, "p%x,%x", phynum, lun);
2969         } else if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lun_dip,
2970             DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &sas_wwn)
2971             == DDI_PROP_SUCCESS) {
2972                 /*
2973                  * Stick in the address of the form "wWWN,LUN"
2974                  */
2975                 reallen = snprintf(name, len, "%s,%x", sas_wwn, lun);
2976                 ddi_prop_free(sas_wwn);
2977         } else {
2978                 return (DDI_FAILURE);
2979         }
2980 
2981         ASSERT(reallen < len);
2982         if (reallen >= len) {
2983                 mptsas_log(0, CE_WARN, "!mptsas_get_name: name parameter "
2984                     "length too small, it needs to be %d bytes", reallen + 1);
2985         }
2986         return (DDI_SUCCESS);
2987 }
2988 
2989 /*
2990  * tran_tgt_init(9E) - target device instance initialization
2991  */
2992 static int
2993 mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
2994     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
2995 {
2996 #ifndef __lock_lint
2997         _NOTE(ARGUNUSED(hba_tran))
2998 #endif
2999 
3000         /*
3001          * At this point, the scsi_device structure already exists
3002          * and has been initialized.
3003          *
3004          * Use this function to allocate target-private data structures,
3005          * if needed by this HBA.  Add revised flow-control and queue
3006          * properties for child here, if desired and if you can tell they
3007          * support tagged queueing by now.
3008          */
3009         mptsas_t                *mpt;
3010         int                     lun = sd->sd_address.a_lun;
3011         mdi_pathinfo_t          *pip = NULL;
3012         mptsas_tgt_private_t    *tgt_private = NULL;
3013         mptsas_target_t         *ptgt = NULL;
3014         char                    *psas_wwn = NULL;
3015         mptsas_phymask_t        phymask = 0;
3016         uint64_t                sas_wwn = 0;
3017         mptsas_target_addr_t    addr;
3018         mpt = SDEV2MPT(sd);
3019 
3020         ASSERT(scsi_hba_iport_unit_address(hba_dip) != 0);
3021 
3022         NDBG0(("mptsas_scsi_tgt_init: hbadip=0x%p tgtdip=0x%p lun=%d",
3023             (void *)hba_dip, (void *)tgt_dip, lun));
3024 
3025         if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
3026                 (void) ndi_merge_node(tgt_dip, mptsas_name_child);
3027                 ddi_set_name_addr(tgt_dip, NULL);
3028                 return (DDI_FAILURE);
3029         }
3030         /*
3031          * phymask is 0 means the virtual port for RAID
3032          */
3033         phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, hba_dip, 0,
3034             "phymask", 0);
3035         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
3036                 if ((pip = (void *)(sd->sd_private)) == NULL) {
3037                         /*
3038                          * Very bad news if this occurs. Somehow scsi_vhci has
3039                          * lost the pathinfo node for this target.
3040                          */
3041                         return (DDI_NOT_WELL_FORMED);
3042                 }
3043 
3044                 if (mdi_prop_lookup_int(pip, LUN_PROP, &lun) !=
3045                     DDI_PROP_SUCCESS) {
3046                         mptsas_log(mpt, CE_WARN, "Get lun property failed\n");
3047                         return (DDI_FAILURE);
3048                 }
3049 
3050                 if (mdi_prop_lookup_string(pip, SCSI_ADDR_PROP_TARGET_PORT,
3051                     &psas_wwn) == MDI_SUCCESS) {
3052                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
3053                                 sas_wwn = 0;
3054                         }
3055                         (void) mdi_prop_free(psas_wwn);
3056                 }
3057         } else {
3058                 lun = ddi_prop_get_int(DDI_DEV_T_ANY, tgt_dip,
3059                     DDI_PROP_DONTPASS, LUN_PROP, 0);
3060                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip,
3061                     DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &psas_wwn) ==
3062                     DDI_PROP_SUCCESS) {
3063                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
3064                                 sas_wwn = 0;
3065                         }
3066                         ddi_prop_free(psas_wwn);
3067                 } else {
3068                         sas_wwn = 0;
3069                 }
3070         }
3071 
3072         ASSERT((sas_wwn != 0) || (phymask != 0));
3073         addr.mta_wwn = sas_wwn;
3074         addr.mta_phymask = phymask;
3075         mutex_enter(&mpt->m_mutex);
3076         ptgt = refhash_lookup(mpt->m_targets, &addr);
3077         mutex_exit(&mpt->m_mutex);
3078         if (ptgt == NULL) {
3079                 mptsas_log(mpt, CE_WARN, "!tgt_init: target doesn't exist or "
3080                     "gone already! phymask:%x, saswwn %"PRIx64, phymask,
3081                     sas_wwn);
3082                 return (DDI_FAILURE);
3083         }
3084         if (hba_tran->tran_tgt_private == NULL) {
3085                 tgt_private = kmem_zalloc(sizeof (mptsas_tgt_private_t),
3086                     KM_SLEEP);
3087                 tgt_private->t_lun = lun;
3088                 tgt_private->t_private = ptgt;
3089                 hba_tran->tran_tgt_private = tgt_private;
3090         }
3091 
3092         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
3093                 return (DDI_SUCCESS);
3094         }
3095         mutex_enter(&mpt->m_mutex);
3096 
3097         if (ptgt->m_deviceinfo &
3098             (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
3099             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
3100                 uchar_t *inq89 = NULL;
3101                 int inq89_len = 0x238;
3102                 int reallen = 0;
3103                 int rval = 0;
3104                 struct sata_id *sid = NULL;
3105                 char model[SATA_ID_MODEL_LEN + 1];
3106                 char fw[SATA_ID_FW_LEN + 1];
3107                 char *vid, *pid;
3108                 int i;
3109 
3110                 mutex_exit(&mpt->m_mutex);
3111                 /*
3112                  * According SCSI/ATA Translation -2 (SAT-2) revision 01a
3113                  * chapter 12.4.2 VPD page 89h includes 512 bytes ATA IDENTIFY
3114                  * DEVICE data or ATA IDENTIFY PACKET DEVICE data.
3115                  */
3116                 inq89 = kmem_zalloc(inq89_len, KM_SLEEP);
3117                 rval = mptsas_inquiry(mpt, ptgt, 0, 0x89,
3118                     inq89, inq89_len, &reallen, 1);
3119 
3120                 if (rval != 0) {
3121                         if (inq89 != NULL) {
3122                                 kmem_free(inq89, inq89_len);
3123                         }
3124 
3125                         mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
3126                             "0x89 for SATA target:%x failed!", ptgt->m_devhdl);
3127                         return (DDI_SUCCESS);
3128                 }
3129                 sid = (void *)(&inq89[60]);
3130 
3131                 swab(sid->ai_model, model, SATA_ID_MODEL_LEN);
3132                 swab(sid->ai_fw, fw, SATA_ID_FW_LEN);
3133 
3134                 model[SATA_ID_MODEL_LEN] = 0;
3135                 fw[SATA_ID_FW_LEN] = 0;
3136 
3137                 /*
3138                  * split model into into vid/pid
3139                  */
3140                 for (i = 0, pid = model; i < SATA_ID_MODEL_LEN; i++, pid++)
3141                         if ((*pid == ' ') || (*pid == '\t'))
3142                                 break;
3143                 if (i < SATA_ID_MODEL_LEN) {
3144                         vid = model;
3145                         /*
3146                          * terminate vid, establish pid
3147                          */
3148                         *pid++ = 0;
3149                 } else {
3150                         /*
3151                          * vid will stay "ATA     ", the rule is same
3152                          * as sata framework implementation.
3153                          */
3154                         vid = NULL;
3155                         /*
3156                          * model is all pid
3157                          */
3158                         pid = model;
3159                 }
3160 
3161                 /*
3162                  * override SCSA "inquiry-*" properties
3163                  */
3164                 if (vid)
3165                         (void) scsi_device_prop_update_inqstring(sd,
3166                             INQUIRY_VENDOR_ID, vid, strlen(vid));
3167                 if (pid)
3168                         (void) scsi_device_prop_update_inqstring(sd,
3169                             INQUIRY_PRODUCT_ID, pid, strlen(pid));
3170                 (void) scsi_device_prop_update_inqstring(sd,
3171                     INQUIRY_REVISION_ID, fw, strlen(fw));
3172 
3173                 if (inq89 != NULL) {
3174                         kmem_free(inq89, inq89_len);
3175                 }
3176         } else {
3177                 mutex_exit(&mpt->m_mutex);
3178         }
3179 
3180         return (DDI_SUCCESS);
3181 }
3182 /*
3183  * tran_tgt_free(9E) - target device instance deallocation
3184  */
3185 static void
3186 mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
3187     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
3188 {
3189 #ifndef __lock_lint
3190         _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran, sd))
3191 #endif
3192 
3193         mptsas_tgt_private_t    *tgt_private = hba_tran->tran_tgt_private;
3194 
3195         if (tgt_private != NULL) {
3196                 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
3197                 hba_tran->tran_tgt_private = NULL;
3198         }
3199 }
3200 
3201 /*
3202  * scsi_pkt handling
3203  *
3204  * Visible to the external world via the transport structure.
3205  */
3206 
3207 /*
3208  * Notes:
3209  *      - transport the command to the addressed SCSI target/lun device
3210  *      - normal operation is to schedule the command to be transported,
3211  *        and return TRAN_ACCEPT if this is successful.
3212  *      - if NO_INTR, tran_start must poll device for command completion
3213  */
3214 static int
3215 mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
3216 {
3217 #ifndef __lock_lint
3218         _NOTE(ARGUNUSED(ap))
3219 #endif
3220         mptsas_t        *mpt = PKT2MPT(pkt);
3221         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
3222         int             rval;
3223         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3224 
3225         NDBG1(("mptsas_scsi_start: pkt=0x%p", (void *)pkt));
3226         ASSERT(ptgt);
3227         if (ptgt == NULL)
3228                 return (TRAN_FATAL_ERROR);
3229 
3230         /*
3231          * prepare the pkt before taking mutex.
3232          */
3233         rval = mptsas_prepare_pkt(cmd);
3234         if (rval != TRAN_ACCEPT) {
3235                 return (rval);
3236         }
3237 
3238         /*
3239          * Send the command to target/lun, however your HBA requires it.
3240          * If busy, return TRAN_BUSY; if there's some other formatting error
3241          * in the packet, return TRAN_BADPKT; otherwise, fall through to the
3242          * return of TRAN_ACCEPT.
3243          *
3244          * Remember that access to shared resources, including the mptsas_t
3245          * data structure and the HBA hardware registers, must be protected
3246          * with mutexes, here and everywhere.
3247          *
3248          * Also remember that at interrupt time, you'll get an argument
3249          * to the interrupt handler which is a pointer to your mptsas_t
3250          * structure; you'll have to remember which commands are outstanding
3251          * and which scsi_pkt is the currently-running command so the
3252          * interrupt handler can refer to the pkt to set completion
3253          * status, call the target driver back through pkt_comp, etc.
3254          *
3255          * If the instance lock is held by other thread, don't spin to wait
3256          * for it. Instead, queue the cmd and next time when the instance lock
3257          * is not held, accept all the queued cmd. A extra tx_waitq is
3258          * introduced to protect the queue.
3259          *
3260          * The polled cmd will not be queud and accepted as usual.
3261          *
3262          * Under the tx_waitq mutex, record whether a thread is draining
3263          * the tx_waitq.  An IO requesting thread that finds the instance
3264          * mutex contended appends to the tx_waitq and while holding the
3265          * tx_wait mutex, if the draining flag is not set, sets it and then
3266          * proceeds to spin for the instance mutex. This scheme ensures that
3267          * the last cmd in a burst be processed.
3268          *
3269          * we enable this feature only when the helper threads are enabled,
3270          * at which we think the loads are heavy.
3271          *
3272          * per instance mutex m_tx_waitq_mutex is introduced to protect the
3273          * m_tx_waitqtail, m_tx_waitq, m_tx_draining.
3274          */
3275 
3276         if (mpt->m_doneq_thread_n) {
3277                 if (mutex_tryenter(&mpt->m_mutex) != 0) {
3278                         rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3279                         mutex_exit(&mpt->m_mutex);
3280                 } else if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3281                         mutex_enter(&mpt->m_mutex);
3282                         rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3283                         mutex_exit(&mpt->m_mutex);
3284                 } else {
3285                         mutex_enter(&mpt->m_tx_waitq_mutex);
3286                         /*
3287                          * ptgt->m_dr_flag is protected by m_mutex or
3288                          * m_tx_waitq_mutex. In this case, m_tx_waitq_mutex
3289                          * is acquired.
3290                          */
3291                         if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3292                                 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3293                                         /*
3294                                          * The command should be allowed to
3295                                          * retry by returning TRAN_BUSY to
3296                                          * to stall the I/O's which come from
3297                                          * scsi_vhci since the device/path is
3298                                          * in unstable state now.
3299                                          */
3300                                         mutex_exit(&mpt->m_tx_waitq_mutex);
3301                                         return (TRAN_BUSY);
3302                                 } else {
3303                                         /*
3304                                          * The device is offline, just fail the
3305                                          * command by returning
3306                                          * TRAN_FATAL_ERROR.
3307                                          */
3308                                         mutex_exit(&mpt->m_tx_waitq_mutex);
3309                                         return (TRAN_FATAL_ERROR);
3310                                 }
3311                         }
3312                         if (mpt->m_tx_draining) {
3313                                 cmd->cmd_flags |= CFLAG_TXQ;
3314                                 *mpt->m_tx_waitqtail = cmd;
3315                                 mpt->m_tx_waitqtail = &cmd->cmd_linkp;
3316                                 mutex_exit(&mpt->m_tx_waitq_mutex);
3317                         } else { /* drain the queue */
3318                                 mpt->m_tx_draining = 1;
3319                                 mutex_exit(&mpt->m_tx_waitq_mutex);
3320                                 mutex_enter(&mpt->m_mutex);
3321                                 rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3322                                 mutex_exit(&mpt->m_mutex);
3323                         }
3324                 }
3325         } else {
3326                 mutex_enter(&mpt->m_mutex);
3327                 /*
3328                  * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
3329                  * in this case, m_mutex is acquired.
3330                  */
3331                 if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3332                         if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3333                                 /*
3334                                  * commands should be allowed to retry by
3335                                  * returning TRAN_BUSY to stall the I/O's
3336                                  * which come from scsi_vhci since the device/
3337                                  * path is in unstable state now.
3338                                  */
3339                                 mutex_exit(&mpt->m_mutex);
3340                                 return (TRAN_BUSY);
3341                         } else {
3342                                 /*
3343                                  * The device is offline, just fail the
3344                                  * command by returning TRAN_FATAL_ERROR.
3345                                  */
3346                                 mutex_exit(&mpt->m_mutex);
3347                                 return (TRAN_FATAL_ERROR);
3348                         }
3349                 }
3350                 rval = mptsas_accept_pkt(mpt, cmd);
3351                 mutex_exit(&mpt->m_mutex);
3352         }
3353 
3354         return (rval);
3355 }
3356 
3357 /*
3358  * Accept all the queued cmds(if any) before accept the current one.
3359  */
3360 static int
3361 mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3362 {
3363         int rval;
3364         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3365 
3366         ASSERT(mutex_owned(&mpt->m_mutex));
3367         /*
3368          * The call to mptsas_accept_tx_waitq() must always be performed
3369          * because that is where mpt->m_tx_draining is cleared.
3370          */
3371         mutex_enter(&mpt->m_tx_waitq_mutex);
3372         mptsas_accept_tx_waitq(mpt);
3373         mutex_exit(&mpt->m_tx_waitq_mutex);
3374         /*
3375          * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
3376          * in this case, m_mutex is acquired.
3377          */
3378         if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3379                 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3380                         /*
3381                          * The command should be allowed to retry by returning
3382                          * TRAN_BUSY to stall the I/O's which come from
3383                          * scsi_vhci since the device/path is in unstable state
3384                          * now.
3385                          */
3386                         return (TRAN_BUSY);
3387                 } else {
3388                         /*
3389                          * The device is offline, just fail the command by
3390                          * return TRAN_FATAL_ERROR.
3391                          */
3392                         return (TRAN_FATAL_ERROR);
3393                 }
3394         }
3395         rval = mptsas_accept_pkt(mpt, cmd);
3396 
3397         return (rval);
3398 }
3399 
3400 static int
3401 mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3402 {
3403         int             rval = TRAN_ACCEPT;
3404         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3405 
3406         NDBG1(("mptsas_accept_pkt: cmd=0x%p", (void *)cmd));
3407 
3408         ASSERT(mutex_owned(&mpt->m_mutex));
3409 
3410         if ((cmd->cmd_flags & CFLAG_PREPARED) == 0) {
3411                 rval = mptsas_prepare_pkt(cmd);
3412                 if (rval != TRAN_ACCEPT) {
3413                         cmd->cmd_flags &= ~CFLAG_TRANFLAG;
3414                         return (rval);
3415                 }
3416         }
3417 
3418         /*
3419          * reset the throttle if we were draining
3420          */
3421         if ((ptgt->m_t_ncmds == 0) &&
3422             (ptgt->m_t_throttle == DRAIN_THROTTLE)) {
3423                 NDBG23(("reset throttle"));
3424                 ASSERT(ptgt->m_reset_delay == 0);
3425                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
3426         }
3427 
3428         /*
3429          * If HBA is being reset, the DevHandles are being re-initialized,
3430          * which means that they could be invalid even if the target is still
3431          * attached.  Check if being reset and if DevHandle is being
3432          * re-initialized.  If this is the case, return BUSY so the I/O can be
3433          * retried later.
3434          */
3435         if ((ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) && mpt->m_in_reset) {
3436                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
3437                 if (cmd->cmd_flags & CFLAG_TXQ) {
3438                         mptsas_doneq_add(mpt, cmd);
3439                         mptsas_doneq_empty(mpt);
3440                         return (rval);
3441                 } else {
3442                         return (TRAN_BUSY);
3443                 }
3444         }
3445 
3446         /*
3447          * If device handle has already been invalidated, just
3448          * fail the command. In theory, command from scsi_vhci
3449          * client is impossible send down command with invalid
3450          * devhdl since devhdl is set after path offline, target
3451          * driver is not suppose to select a offlined path.
3452          */
3453         if (ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) {
3454                 NDBG3(("rejecting command, it might because invalid devhdl "
3455                     "request."));
3456                 mptsas_set_pkt_reason(mpt, cmd, CMD_DEV_GONE, STAT_TERMINATED);
3457                 if (cmd->cmd_flags & CFLAG_TXQ) {
3458                         mptsas_doneq_add(mpt, cmd);
3459                         mptsas_doneq_empty(mpt);
3460                         return (rval);
3461                 } else {
3462                         return (TRAN_FATAL_ERROR);
3463                 }
3464         }
3465         /*
3466          * The first case is the normal case.  mpt gets a command from the
3467          * target driver and starts it.
3468          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
3469          * commands is m_max_requests - 2.
3470          */
3471         if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
3472             (ptgt->m_t_throttle > HOLD_THROTTLE) &&
3473             (ptgt->m_t_ncmds < ptgt->m_t_throttle) &&
3474             (ptgt->m_reset_delay == 0) &&
3475             (ptgt->m_t_nwait == 0) &&
3476             ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0)) {
3477                 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
3478                         (void) mptsas_start_cmd(mpt, cmd);
3479                 } else {
3480                         mptsas_waitq_add(mpt, cmd);
3481                 }
3482         } else {
3483                 /*
3484                  * Add this pkt to the work queue
3485                  */
3486                 mptsas_waitq_add(mpt, cmd);
3487 
3488                 if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3489                         (void) mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
3490 
3491                         /*
3492                          * Only flush the doneq if this is not a TM
3493                          * cmd.  For TM cmds the flushing of the
3494                          * doneq will be done in those routines.
3495                          */
3496                         if ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
3497                                 mptsas_doneq_empty(mpt);
3498                         }
3499                 }
3500         }
3501         return (rval);
3502 }
3503 
3504 int
3505 mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
3506 {
3507         mptsas_slots_t *slots = mpt->m_active;
3508         uint_t slot, start_rotor;
3509         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3510 
3511         ASSERT(MUTEX_HELD(&mpt->m_mutex));
3512 
3513         /*
3514          * Account for reserved TM request slot and reserved SMID of 0.
3515          */
3516         ASSERT(slots->m_n_normal == (mpt->m_max_requests - 2));
3517 
3518         /*
3519          * Find the next available slot, beginning at m_rotor.  If no slot is
3520          * available, we'll return FALSE to indicate that.  This mechanism
3521          * considers only the normal slots, not the reserved slot 0 nor the
3522          * task management slot m_n_normal + 1.  The rotor is left to point to
3523          * the normal slot after the one we select, unless we select the last
3524          * normal slot in which case it returns to slot 1.
3525          */
3526         start_rotor = slots->m_rotor;
3527         do {
3528                 slot = slots->m_rotor++;
3529                 if (slots->m_rotor > slots->m_n_normal)
3530                         slots->m_rotor = 1;
3531 
3532                 if (slots->m_rotor == start_rotor)
3533                         break;
3534         } while (slots->m_slot[slot] != NULL);
3535 
3536         if (slots->m_slot[slot] != NULL)
3537                 return (FALSE);
3538 
3539         ASSERT(slot != 0 && slot <= slots->m_n_normal);
3540 
3541         cmd->cmd_slot = slot;
3542         slots->m_slot[slot] = cmd;
3543         mpt->m_ncmds++;
3544 
3545         /*
3546          * only increment per target ncmds if this is not a
3547          * command that has no target associated with it (i.e. a
3548          * event acknoledgment)
3549          */
3550         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
3551                 /*
3552                  * Expiration time is set in mptsas_start_cmd
3553                  */
3554                 ptgt->m_t_ncmds++;
3555                 cmd->cmd_active_expiration = 0;
3556         } else {
3557                 /*
3558                  * Initialize expiration time for passthrough commands,
3559                  */
3560                 cmd->cmd_active_expiration = gethrtime() +
3561                     (hrtime_t)cmd->cmd_pkt->pkt_time * NANOSEC;
3562         }
3563         return (TRUE);
3564 }
3565 
3566 /*
3567  * prepare the pkt:
3568  * the pkt may have been resubmitted or just reused so
3569  * initialize some fields and do some checks.
3570  */
3571 static int
3572 mptsas_prepare_pkt(mptsas_cmd_t *cmd)
3573 {
3574         struct scsi_pkt *pkt = CMD2PKT(cmd);
3575 
3576         NDBG1(("mptsas_prepare_pkt: cmd=0x%p", (void *)cmd));
3577 
3578         /*
3579          * Reinitialize some fields that need it; the packet may
3580          * have been resubmitted
3581          */
3582         pkt->pkt_reason = CMD_CMPLT;
3583         pkt->pkt_state = 0;
3584         pkt->pkt_statistics = 0;
3585         pkt->pkt_resid = 0;
3586         cmd->cmd_age = 0;
3587         cmd->cmd_pkt_flags = pkt->pkt_flags;
3588 
3589         /*
3590          * zero status byte.
3591          */
3592         *(pkt->pkt_scbp) = 0;
3593 
3594         if (cmd->cmd_flags & CFLAG_DMAVALID) {
3595                 pkt->pkt_resid = cmd->cmd_dmacount;
3596 
3597                 /*
3598                  * consistent packets need to be sync'ed first
3599                  * (only for data going out)
3600                  */
3601                 if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
3602                     (cmd->cmd_flags & CFLAG_DMASEND)) {
3603                         (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
3604                             DDI_DMA_SYNC_FORDEV);
3605                 }
3606         }
3607 
3608         cmd->cmd_flags =
3609             (cmd->cmd_flags & ~(CFLAG_TRANFLAG)) |
3610             CFLAG_PREPARED | CFLAG_IN_TRANSPORT;
3611 
3612         return (TRAN_ACCEPT);
3613 }
3614 
3615 /*
3616  * tran_init_pkt(9E) - allocate scsi_pkt(9S) for command
3617  *
3618  * One of three possibilities:
3619  *      - allocate scsi_pkt
3620  *      - allocate scsi_pkt and DMA resources
3621  *      - allocate DMA resources to an already-allocated pkt
3622  */
3623 static struct scsi_pkt *
3624 mptsas_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
3625     struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
3626     int (*callback)(), caddr_t arg)
3627 {
3628         mptsas_cmd_t            *cmd, *new_cmd;
3629         mptsas_t                *mpt = ADDR2MPT(ap);
3630         int                     failure = 1;
3631         uint_t                  oldcookiec;
3632         mptsas_target_t         *ptgt = NULL;
3633         int                     rval;
3634         mptsas_tgt_private_t    *tgt_private;
3635         int                     kf;
3636 
3637         kf = (callback == SLEEP_FUNC)? KM_SLEEP: KM_NOSLEEP;
3638 
3639         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
3640             tran_tgt_private;
3641         ASSERT(tgt_private != NULL);
3642         if (tgt_private == NULL) {
3643                 return (NULL);
3644         }
3645         ptgt = tgt_private->t_private;
3646         ASSERT(ptgt != NULL);
3647         if (ptgt == NULL)
3648                 return (NULL);
3649         ap->a_target = ptgt->m_devhdl;
3650         ap->a_lun = tgt_private->t_lun;
3651 
3652         ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC);
3653 #ifdef MPTSAS_TEST_EXTRN_ALLOC
3654         statuslen *= 100; tgtlen *= 4;
3655 #endif
3656         NDBG3(("mptsas_scsi_init_pkt:\n"
3657             "\ttgt=%d in=0x%p bp=0x%p clen=%d slen=%d tlen=%d flags=%x",
3658             ap->a_target, (void *)pkt, (void *)bp,
3659             cmdlen, statuslen, tgtlen, flags));
3660 
3661         /*
3662          * Allocate the new packet.
3663          */
3664         if (pkt == NULL) {
3665                 ddi_dma_handle_t        save_dma_handle;
3666 
3667                 cmd = kmem_cache_alloc(mpt->m_kmem_cache, kf);
3668 
3669                 if (cmd) {
3670                         save_dma_handle = cmd->cmd_dmahandle;
3671                         bzero(cmd, sizeof (*cmd) + scsi_pkt_size());
3672                         cmd->cmd_dmahandle = save_dma_handle;
3673 
3674                         pkt = (void *)((uchar_t *)cmd +
3675                             sizeof (struct mptsas_cmd));
3676                         pkt->pkt_ha_private = (opaque_t)cmd;
3677                         pkt->pkt_address = *ap;
3678                         pkt->pkt_private = (opaque_t)cmd->cmd_pkt_private;
3679                         pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb;
3680                         pkt->pkt_cdbp = (opaque_t)&cmd->cmd_cdb;
3681                         cmd->cmd_pkt = (struct scsi_pkt *)pkt;
3682                         cmd->cmd_cdblen = (uchar_t)cmdlen;
3683                         cmd->cmd_scblen = statuslen;
3684                         cmd->cmd_rqslen = SENSE_LENGTH;
3685                         cmd->cmd_tgt_addr = ptgt;
3686                         failure = 0;
3687                 }
3688 
3689                 if (failure || (cmdlen > sizeof (cmd->cmd_cdb)) ||
3690                     (tgtlen > PKT_PRIV_LEN) ||
3691                     (statuslen > EXTCMDS_STATUS_SIZE)) {
3692                         if (failure == 0) {
3693                                 /*
3694                                  * if extern alloc fails, all will be
3695                                  * deallocated, including cmd
3696                                  */
3697                                 failure = mptsas_pkt_alloc_extern(mpt, cmd,
3698                                     cmdlen, tgtlen, statuslen, kf);
3699                         }
3700                         if (failure) {
3701                                 /*
3702                                  * if extern allocation fails, it will
3703                                  * deallocate the new pkt as well
3704                                  */
3705                                 return (NULL);
3706                         }
3707                 }
3708                 new_cmd = cmd;
3709 
3710         } else {
3711                 cmd = PKT2CMD(pkt);
3712                 new_cmd = NULL;
3713         }
3714 
3715 
3716         /* grab cmd->cmd_cookiec here as oldcookiec */
3717 
3718         oldcookiec = cmd->cmd_cookiec;
3719 
3720         /*
3721          * If the dma was broken up into PARTIAL transfers cmd_nwin will be
3722          * greater than 0 and we'll need to grab the next dma window
3723          */
3724         /*
3725          * SLM-not doing extra command frame right now; may add later
3726          */
3727 
3728         if (cmd->cmd_nwin > 0) {
3729 
3730                 /*
3731                  * Make sure we havn't gone past the the total number
3732                  * of windows
3733                  */
3734                 if (++cmd->cmd_winindex >= cmd->cmd_nwin) {
3735                         return (NULL);
3736                 }
3737                 if (ddi_dma_getwin(cmd->cmd_dmahandle, cmd->cmd_winindex,
3738                     &cmd->cmd_dma_offset, &cmd->cmd_dma_len,
3739                     &cmd->cmd_cookie, &cmd->cmd_cookiec) == DDI_FAILURE) {
3740                         return (NULL);
3741                 }
3742                 goto get_dma_cookies;
3743         }
3744 
3745 
3746         if (flags & PKT_XARQ) {
3747                 cmd->cmd_flags |= CFLAG_XARQ;
3748         }
3749 
3750         /*
3751          * DMA resource allocation.  This version assumes your
3752          * HBA has some sort of bus-mastering or onboard DMA capability, with a
3753          * scatter-gather list of length MPTSAS_MAX_DMA_SEGS, as given in the
3754          * ddi_dma_attr_t structure and passed to scsi_impl_dmaget.
3755          */
3756         if (bp && (bp->b_bcount != 0) &&
3757             (cmd->cmd_flags & CFLAG_DMAVALID) == 0) {
3758 
3759                 int     cnt, dma_flags;
3760                 mptti_t *dmap;          /* ptr to the S/G list */
3761 
3762                 /*
3763                  * Set up DMA memory and position to the next DMA segment.
3764                  */
3765                 ASSERT(cmd->cmd_dmahandle != NULL);
3766 
3767                 if (bp->b_flags & B_READ) {
3768                         dma_flags = DDI_DMA_READ;
3769                         cmd->cmd_flags &= ~CFLAG_DMASEND;
3770                 } else {
3771                         dma_flags = DDI_DMA_WRITE;
3772                         cmd->cmd_flags |= CFLAG_DMASEND;
3773                 }
3774                 if (flags & PKT_CONSISTENT) {
3775                         cmd->cmd_flags |= CFLAG_CMDIOPB;
3776                         dma_flags |= DDI_DMA_CONSISTENT;
3777                 }
3778 
3779                 if (flags & PKT_DMA_PARTIAL) {
3780                         dma_flags |= DDI_DMA_PARTIAL;
3781                 }
3782 
3783                 /*
3784                  * workaround for byte hole issue on psycho and
3785                  * schizo pre 2.1
3786                  */
3787                 if ((bp->b_flags & B_READ) && ((bp->b_flags &
3788                     (B_PAGEIO|B_REMAPPED)) != B_PAGEIO) &&
3789                     ((uintptr_t)bp->b_un.b_addr & 0x7)) {
3790                         dma_flags |= DDI_DMA_CONSISTENT;
3791                 }
3792 
3793                 rval = ddi_dma_buf_bind_handle(cmd->cmd_dmahandle, bp,
3794                     dma_flags, callback, arg,
3795                     &cmd->cmd_cookie, &cmd->cmd_cookiec);
3796                 if (rval == DDI_DMA_PARTIAL_MAP) {
3797                         (void) ddi_dma_numwin(cmd->cmd_dmahandle,
3798                             &cmd->cmd_nwin);
3799                         cmd->cmd_winindex = 0;
3800                         (void) ddi_dma_getwin(cmd->cmd_dmahandle,
3801                             cmd->cmd_winindex, &cmd->cmd_dma_offset,
3802                             &cmd->cmd_dma_len, &cmd->cmd_cookie,
3803                             &cmd->cmd_cookiec);
3804                 } else if (rval && (rval != DDI_DMA_MAPPED)) {
3805                         switch (rval) {
3806                         case DDI_DMA_NORESOURCES:
3807                                 bioerror(bp, 0);
3808                                 break;
3809                         case DDI_DMA_BADATTR:
3810                         case DDI_DMA_NOMAPPING:
3811                                 bioerror(bp, EFAULT);
3812                                 break;
3813                         case DDI_DMA_TOOBIG:
3814                         default:
3815                                 bioerror(bp, EINVAL);
3816                                 break;
3817                         }
3818                         cmd->cmd_flags &= ~CFLAG_DMAVALID;
3819                         if (new_cmd) {
3820                                 mptsas_scsi_destroy_pkt(ap, pkt);
3821                         }
3822                         return ((struct scsi_pkt *)NULL);
3823                 }
3824 
3825 get_dma_cookies:
3826                 cmd->cmd_flags |= CFLAG_DMAVALID;
3827                 ASSERT(cmd->cmd_cookiec > 0);
3828 
3829                 if (cmd->cmd_cookiec > MPTSAS_MAX_CMD_SEGS) {
3830                         mptsas_log(mpt, CE_NOTE, "large cookiec received %d\n",
3831                             cmd->cmd_cookiec);
3832                         bioerror(bp, EINVAL);
3833                         if (new_cmd) {
3834                                 mptsas_scsi_destroy_pkt(ap, pkt);
3835                         }
3836                         return ((struct scsi_pkt *)NULL);
3837                 }
3838 
3839                 /*
3840                  * Allocate extra SGL buffer if needed.
3841                  */
3842                 if ((cmd->cmd_cookiec > MPTSAS_MAX_FRAME_SGES64(mpt)) &&
3843                     (cmd->cmd_extra_frames == NULL)) {
3844                         if (mptsas_alloc_extra_sgl_frame(mpt, cmd) ==
3845                             DDI_FAILURE) {
3846                                 mptsas_log(mpt, CE_WARN, "MPT SGL mem alloc "
3847                                     "failed");
3848                                 bioerror(bp, ENOMEM);
3849                                 if (new_cmd) {
3850                                         mptsas_scsi_destroy_pkt(ap, pkt);
3851                                 }
3852                                 return ((struct scsi_pkt *)NULL);
3853                         }
3854                 }
3855 
3856                 /*
3857                  * Always use scatter-gather transfer
3858                  * Use the loop below to store physical addresses of
3859                  * DMA segments, from the DMA cookies, into your HBA's
3860                  * scatter-gather list.
3861                  * We need to ensure we have enough kmem alloc'd
3862                  * for the sg entries since we are no longer using an
3863                  * array inside mptsas_cmd_t.
3864                  *
3865                  * We check cmd->cmd_cookiec against oldcookiec so
3866                  * the scatter-gather list is correctly allocated
3867                  */
3868 
3869                 if (oldcookiec != cmd->cmd_cookiec) {
3870                         if (cmd->cmd_sg != (mptti_t *)NULL) {
3871                                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) *
3872                                     oldcookiec);
3873                                 cmd->cmd_sg = NULL;
3874                         }
3875                 }
3876 
3877                 if (cmd->cmd_sg == (mptti_t *)NULL) {
3878                         cmd->cmd_sg = kmem_alloc((size_t)(sizeof (mptti_t)*
3879                             cmd->cmd_cookiec), kf);
3880 
3881                         if (cmd->cmd_sg == (mptti_t *)NULL) {
3882                                 mptsas_log(mpt, CE_WARN,
3883                                     "unable to kmem_alloc enough memory "
3884                                     "for scatter/gather list");
3885                 /*
3886                  * if we have an ENOMEM condition we need to behave
3887                  * the same way as the rest of this routine
3888                  */
3889 
3890                                 bioerror(bp, ENOMEM);
3891                                 if (new_cmd) {
3892                                         mptsas_scsi_destroy_pkt(ap, pkt);
3893                                 }
3894                                 return ((struct scsi_pkt *)NULL);
3895                         }
3896                 }
3897 
3898                 dmap = cmd->cmd_sg;
3899 
3900                 ASSERT(cmd->cmd_cookie.dmac_size != 0);
3901 
3902                 /*
3903                  * store the first segment into the S/G list
3904                  */
3905                 dmap->count = cmd->cmd_cookie.dmac_size;
3906                 dmap->addr.address64.Low = (uint32_t)
3907                     (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3908                 dmap->addr.address64.High = (uint32_t)
3909                     (cmd->cmd_cookie.dmac_laddress >> 32);
3910 
3911                 /*
3912                  * dmacount counts the size of the dma for this window
3913                  * (if partial dma is being used).  totaldmacount
3914                  * keeps track of the total amount of dma we have
3915                  * transferred for all the windows (needed to calculate
3916                  * the resid value below).
3917                  */
3918                 cmd->cmd_dmacount = cmd->cmd_cookie.dmac_size;
3919                 cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3920 
3921                 /*
3922                  * We already stored the first DMA scatter gather segment,
3923                  * start at 1 if we need to store more.
3924                  */
3925                 for (cnt = 1; cnt < cmd->cmd_cookiec; cnt++) {
3926                         /*
3927                          * Get next DMA cookie
3928                          */
3929                         ddi_dma_nextcookie(cmd->cmd_dmahandle,
3930                             &cmd->cmd_cookie);
3931                         dmap++;
3932 
3933                         cmd->cmd_dmacount += cmd->cmd_cookie.dmac_size;
3934                         cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3935 
3936                         /*
3937                          * store the segment parms into the S/G list
3938                          */
3939                         dmap->count = cmd->cmd_cookie.dmac_size;
3940                         dmap->addr.address64.Low = (uint32_t)
3941                             (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3942                         dmap->addr.address64.High = (uint32_t)
3943                             (cmd->cmd_cookie.dmac_laddress >> 32);
3944                 }
3945 
3946                 /*
3947                  * If this was partially allocated we set the resid
3948                  * the amount of data NOT transferred in this window
3949                  * If there is only one window, the resid will be 0
3950                  */
3951                 pkt->pkt_resid = (bp->b_bcount - cmd->cmd_totaldmacount);
3952                 NDBG3(("mptsas_scsi_init_pkt: cmd_dmacount=%d.",
3953                     cmd->cmd_dmacount));
3954         }
3955         return (pkt);
3956 }
3957 
3958 /*
3959  * tran_destroy_pkt(9E) - scsi_pkt(9s) deallocation
3960  *
3961  * Notes:
3962  *      - also frees DMA resources if allocated
3963  *      - implicit DMA synchonization
3964  */
3965 static void
3966 mptsas_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
3967 {
3968         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
3969         mptsas_t        *mpt = ADDR2MPT(ap);
3970 
3971         NDBG3(("mptsas_scsi_destroy_pkt: target=%d pkt=0x%p",
3972             ap->a_target, (void *)pkt));
3973 
3974         if (cmd->cmd_flags & CFLAG_DMAVALID) {
3975                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
3976                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
3977         }
3978 
3979         if (cmd->cmd_sg) {
3980                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) * cmd->cmd_cookiec);
3981                 cmd->cmd_sg = NULL;
3982         }
3983 
3984         mptsas_free_extra_sgl_frame(mpt, cmd);
3985 
3986         if ((cmd->cmd_flags &
3987             (CFLAG_FREE | CFLAG_CDBEXTERN | CFLAG_PRIVEXTERN |
3988             CFLAG_SCBEXTERN)) == 0) {
3989                 cmd->cmd_flags = CFLAG_FREE;
3990                 kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
3991         } else {
3992                 mptsas_pkt_destroy_extern(mpt, cmd);
3993         }
3994 }
3995 
3996 /*
3997  * kmem cache constructor and destructor:
3998  * When constructing, we bzero the cmd and allocate the dma handle
3999  * When destructing, just free the dma handle
4000  */
4001 static int
4002 mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags)
4003 {
4004         mptsas_cmd_t            *cmd = buf;
4005         mptsas_t                *mpt  = cdrarg;
4006         int                     (*callback)(caddr_t);
4007 
4008         callback = (kmflags == KM_SLEEP)? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
4009 
4010         NDBG4(("mptsas_kmem_cache_constructor"));
4011 
4012         /*
4013          * allocate a dma handle
4014          */
4015         if ((ddi_dma_alloc_handle(mpt->m_dip, &mpt->m_io_dma_attr, callback,
4016             NULL, &cmd->cmd_dmahandle)) != DDI_SUCCESS) {
4017                 cmd->cmd_dmahandle = NULL;
4018                 return (-1);
4019         }
4020         return (0);
4021 }
4022 
4023 static void
4024 mptsas_kmem_cache_destructor(void *buf, void *cdrarg)
4025 {
4026 #ifndef __lock_lint
4027         _NOTE(ARGUNUSED(cdrarg))
4028 #endif
4029         mptsas_cmd_t    *cmd = buf;
4030 
4031         NDBG4(("mptsas_kmem_cache_destructor"));
4032 
4033         if (cmd->cmd_dmahandle) {
4034                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
4035                 cmd->cmd_dmahandle = NULL;
4036         }
4037 }
4038 
4039 static int
4040 mptsas_cache_frames_constructor(void *buf, void *cdrarg, int kmflags)
4041 {
4042         mptsas_cache_frames_t   *p = buf;
4043         mptsas_t                *mpt = cdrarg;
4044         ddi_dma_attr_t          frame_dma_attr;
4045         size_t                  mem_size, alloc_len;
4046         ddi_dma_cookie_t        cookie;
4047         uint_t                  ncookie;
4048         int (*callback)(caddr_t) = (kmflags == KM_SLEEP)
4049             ? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
4050 
4051         frame_dma_attr = mpt->m_msg_dma_attr;
4052         frame_dma_attr.dma_attr_align = 0x10;
4053         frame_dma_attr.dma_attr_sgllen = 1;
4054 
4055         if (ddi_dma_alloc_handle(mpt->m_dip, &frame_dma_attr, callback, NULL,
4056             &p->m_dma_hdl) != DDI_SUCCESS) {
4057                 mptsas_log(mpt, CE_WARN, "Unable to allocate dma handle for"
4058                     " extra SGL.");
4059                 return (DDI_FAILURE);
4060         }
4061 
4062         mem_size = (mpt->m_max_request_frames - 1) * mpt->m_req_frame_size;
4063 
4064         if (ddi_dma_mem_alloc(p->m_dma_hdl, mem_size, &mpt->m_dev_acc_attr,
4065             DDI_DMA_CONSISTENT, callback, NULL, (caddr_t *)&p->m_frames_addr,
4066             &alloc_len, &p->m_acc_hdl) != DDI_SUCCESS) {
4067                 ddi_dma_free_handle(&p->m_dma_hdl);
4068                 p->m_dma_hdl = NULL;
4069                 mptsas_log(mpt, CE_WARN, "Unable to allocate dma memory for"
4070                     " extra SGL.");
4071                 return (DDI_FAILURE);
4072         }
4073 
4074         if (ddi_dma_addr_bind_handle(p->m_dma_hdl, NULL, p->m_frames_addr,
4075             alloc_len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, callback, NULL,
4076             &cookie, &ncookie) != DDI_DMA_MAPPED) {
4077                 (void) ddi_dma_mem_free(&p->m_acc_hdl);
4078                 ddi_dma_free_handle(&p->m_dma_hdl);
4079                 p->m_dma_hdl = NULL;
4080                 mptsas_log(mpt, CE_WARN, "Unable to bind DMA resources for"
4081                     " extra SGL");
4082                 return (DDI_FAILURE);
4083         }
4084 
4085         /*
4086          * Store the SGL memory address.  This chip uses this
4087          * address to dma to and from the driver.  The second
4088          * address is the address mpt uses to fill in the SGL.
4089          */
4090         p->m_phys_addr = cookie.dmac_laddress;
4091 
4092         return (DDI_SUCCESS);
4093 }
4094 
4095 static void
4096 mptsas_cache_frames_destructor(void *buf, void *cdrarg)
4097 {
4098 #ifndef __lock_lint
4099         _NOTE(ARGUNUSED(cdrarg))
4100 #endif
4101         mptsas_cache_frames_t   *p = buf;
4102         if (p->m_dma_hdl != NULL) {
4103                 (void) ddi_dma_unbind_handle(p->m_dma_hdl);
4104                 (void) ddi_dma_mem_free(&p->m_acc_hdl);
4105                 ddi_dma_free_handle(&p->m_dma_hdl);
4106                 p->m_phys_addr = NULL;
4107                 p->m_frames_addr = NULL;
4108                 p->m_dma_hdl = NULL;
4109                 p->m_acc_hdl = NULL;
4110         }
4111 
4112 }
4113 
4114 /*
4115  * Figure out if we need to use a different method for the request
4116  * sense buffer and allocate from the map if necessary.
4117  */
4118 static boolean_t
4119 mptsas_cmdarqsize(mptsas_t *mpt, mptsas_cmd_t *cmd, size_t senselength, int kf)
4120 {
4121         if (senselength > mpt->m_req_sense_size) {
4122                 unsigned long i;
4123 
4124                 /* Sense length is limited to an 8 bit value in MPI Spec. */
4125                 if (senselength > 255)
4126                         senselength = 255;
4127                 cmd->cmd_extrqschunks = (senselength +
4128                     (mpt->m_req_sense_size - 1))/mpt->m_req_sense_size;
4129                 i = (kf == KM_SLEEP ? rmalloc_wait : rmalloc)
4130                     (mpt->m_erqsense_map, cmd->cmd_extrqschunks);
4131 
4132                 if (i == 0)
4133                         return (B_FALSE);
4134 
4135                 cmd->cmd_extrqslen = (uint16_t)senselength;
4136                 cmd->cmd_extrqsidx = i - 1;
4137                 cmd->cmd_arq_buf = mpt->m_extreq_sense +
4138                     (cmd->cmd_extrqsidx * mpt->m_req_sense_size);
4139         } else {
4140                 cmd->cmd_rqslen = (uchar_t)senselength;
4141         }
4142 
4143         return (B_TRUE);
4144 }
4145 
4146 /*
4147  * allocate and deallocate external pkt space (ie. not part of mptsas_cmd)
4148  * for non-standard length cdb, pkt_private, status areas
4149  * if allocation fails, then deallocate all external space and the pkt
4150  */
4151 /* ARGSUSED */
4152 static int
4153 mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
4154     int cmdlen, int tgtlen, int statuslen, int kf)
4155 {
4156         caddr_t                 cdbp, scbp, tgt;
4157 
4158         NDBG3(("mptsas_pkt_alloc_extern: "
4159             "cmd=0x%p cmdlen=%d tgtlen=%d statuslen=%d kf=%x",
4160             (void *)cmd, cmdlen, tgtlen, statuslen, kf));
4161 
4162         tgt = cdbp = scbp = NULL;
4163         cmd->cmd_scblen              = statuslen;
4164         cmd->cmd_privlen     = (uchar_t)tgtlen;
4165 
4166         if (cmdlen > sizeof (cmd->cmd_cdb)) {
4167                 if ((cdbp = kmem_zalloc((size_t)cmdlen, kf)) == NULL) {
4168                         goto fail;
4169                 }
4170                 cmd->cmd_pkt->pkt_cdbp = (opaque_t)cdbp;
4171                 cmd->cmd_flags |= CFLAG_CDBEXTERN;
4172         }
4173         if (tgtlen > PKT_PRIV_LEN) {
4174                 if ((tgt = kmem_zalloc((size_t)tgtlen, kf)) == NULL) {
4175                         goto fail;
4176                 }
4177                 cmd->cmd_flags |= CFLAG_PRIVEXTERN;
4178                 cmd->cmd_pkt->pkt_private = tgt;
4179         }
4180         if (statuslen > EXTCMDS_STATUS_SIZE) {
4181                 if ((scbp = kmem_zalloc((size_t)statuslen, kf)) == NULL) {
4182                         goto fail;
4183                 }
4184                 cmd->cmd_flags |= CFLAG_SCBEXTERN;
4185                 cmd->cmd_pkt->pkt_scbp = (opaque_t)scbp;
4186 
4187                 /* allocate sense data buf for DMA */
4188                 if (mptsas_cmdarqsize(mpt, cmd, statuslen -
4189                     MPTSAS_GET_ITEM_OFF(struct scsi_arq_status, sts_sensedata),
4190                     kf) == B_FALSE)
4191                         goto fail;
4192         }
4193         return (0);
4194 fail:
4195         mptsas_pkt_destroy_extern(mpt, cmd);
4196         return (1);
4197 }
4198 
4199 /*
4200  * deallocate external pkt space and deallocate the pkt
4201  */
4202 static void
4203 mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd)
4204 {
4205         NDBG3(("mptsas_pkt_destroy_extern: cmd=0x%p", (void *)cmd));
4206 
4207         if (cmd->cmd_flags & CFLAG_FREE) {
4208                 mptsas_log(mpt, CE_PANIC,
4209                     "mptsas_pkt_destroy_extern: freeing free packet");
4210                 _NOTE(NOT_REACHED)
4211                 /* NOTREACHED */
4212         }
4213         if (cmd->cmd_extrqslen != 0) {
4214                 rmfree(mpt->m_erqsense_map, cmd->cmd_extrqschunks,
4215                     cmd->cmd_extrqsidx + 1);
4216         }
4217         if (cmd->cmd_flags & CFLAG_CDBEXTERN) {
4218                 kmem_free(cmd->cmd_pkt->pkt_cdbp, (size_t)cmd->cmd_cdblen);
4219         }
4220         if (cmd->cmd_flags & CFLAG_SCBEXTERN) {
4221                 kmem_free(cmd->cmd_pkt->pkt_scbp, (size_t)cmd->cmd_scblen);
4222         }
4223         if (cmd->cmd_flags & CFLAG_PRIVEXTERN) {
4224                 kmem_free(cmd->cmd_pkt->pkt_private, (size_t)cmd->cmd_privlen);
4225         }
4226         cmd->cmd_flags = CFLAG_FREE;
4227         kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
4228 }
4229 
4230 /*
4231  * tran_sync_pkt(9E) - explicit DMA synchronization
4232  */
4233 /*ARGSUSED*/
4234 static void
4235 mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
4236 {
4237         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
4238 
4239         NDBG3(("mptsas_scsi_sync_pkt: target=%d, pkt=0x%p",
4240             ap->a_target, (void *)pkt));
4241 
4242         if (cmd->cmd_dmahandle) {
4243                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4244                     (cmd->cmd_flags & CFLAG_DMASEND) ?
4245                     DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
4246         }
4247 }
4248 
4249 /*
4250  * tran_dmafree(9E) - deallocate DMA resources allocated for command
4251  */
4252 /*ARGSUSED*/
4253 static void
4254 mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
4255 {
4256         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
4257         mptsas_t        *mpt = ADDR2MPT(ap);
4258 
4259         NDBG3(("mptsas_scsi_dmafree: target=%d pkt=0x%p",
4260             ap->a_target, (void *)pkt));
4261 
4262         if (cmd->cmd_flags & CFLAG_DMAVALID) {
4263                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
4264                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
4265         }
4266 
4267         mptsas_free_extra_sgl_frame(mpt, cmd);
4268 }
4269 
4270 static void
4271 mptsas_pkt_comp(struct scsi_pkt *pkt, mptsas_cmd_t *cmd)
4272 {
4273         if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
4274             (!(cmd->cmd_flags & CFLAG_DMASEND))) {
4275                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4276                     DDI_DMA_SYNC_FORCPU);
4277         }
4278         (*pkt->pkt_comp)(pkt);
4279 }
4280 
4281 static void
4282 mptsas_sge_mainframe(mptsas_cmd_t *cmd, pMpi2SCSIIORequest_t frame,
4283     ddi_acc_handle_t acc_hdl, uint_t cookiec, uint32_t end_flags)
4284 {
4285         pMpi2SGESimple64_t      sge;
4286         mptti_t                 *dmap;
4287         uint32_t                flags;
4288 
4289         dmap = cmd->cmd_sg;
4290 
4291         sge = (pMpi2SGESimple64_t)(&frame->SGL);
4292         while (cookiec--) {
4293                 ddi_put32(acc_hdl,
4294                     &sge->Address.Low, dmap->addr.address64.Low);
4295                 ddi_put32(acc_hdl,
4296                     &sge->Address.High, dmap->addr.address64.High);
4297                 ddi_put32(acc_hdl, &sge->FlagsLength,
4298                     dmap->count);
4299                 flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4300                 flags |= ((uint32_t)
4301                     (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4302                     MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4303                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4304                     MPI2_SGE_FLAGS_SHIFT);
4305 
4306                 /*
4307                  * If this is the last cookie, we set the flags
4308                  * to indicate so
4309                  */
4310                 if (cookiec == 0) {
4311                         flags |= end_flags;
4312                 }
4313                 if (cmd->cmd_flags & CFLAG_DMASEND) {
4314                         flags |= (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4315                             MPI2_SGE_FLAGS_SHIFT);
4316                 } else {
4317                         flags |= (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4318                             MPI2_SGE_FLAGS_SHIFT);
4319                 }
4320                 ddi_put32(acc_hdl, &sge->FlagsLength, flags);
4321                 dmap++;
4322                 sge++;
4323         }
4324 }
4325 
4326 static void
4327 mptsas_sge_chain(mptsas_t *mpt, mptsas_cmd_t *cmd,
4328     pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4329 {
4330         pMpi2SGESimple64_t      sge;
4331         pMpi2SGEChain64_t       sgechain;
4332         uint64_t                nframe_phys_addr;
4333         uint_t                  cookiec;
4334         mptti_t                 *dmap;
4335         uint32_t                flags;
4336 
4337         /*
4338          * Save the number of entries in the DMA
4339          * Scatter/Gather list
4340          */
4341         cookiec = cmd->cmd_cookiec;
4342 
4343         /*
4344          * Hereby we start to deal with multiple frames.
4345          * The process is as follows:
4346          * 1. Determine how many frames are needed for SGL element
4347          *    storage; Note that all frames are stored in contiguous
4348          *    memory space and in 64-bit DMA mode each element is
4349          *    3 double-words (12 bytes) long.
4350          * 2. Fill up the main frame. We need to do this separately
4351          *    since it contains the SCSI IO request header and needs
4352          *    dedicated processing. Note that the last 4 double-words
4353          *    of the SCSI IO header is for SGL element storage
4354          *    (MPI2_SGE_IO_UNION).
4355          * 3. Fill the chain element in the main frame, so the DMA
4356          *    engine can use the following frames.
4357          * 4. Enter a loop to fill the remaining frames. Note that the
4358          *    last frame contains no chain element.  The remaining
4359          *    frames go into the mpt SGL buffer allocated on the fly,
4360          *    not immediately following the main message frame, as in
4361          *    Gen1.
4362          * Some restrictions:
4363          * 1. For 64-bit DMA, the simple element and chain element
4364          *    are both of 3 double-words (12 bytes) in size, even
4365          *    though all frames are stored in the first 4G of mem
4366          *    range and the higher 32-bits of the address are always 0.
4367          * 2. On some controllers (like the 1064/1068), a frame can
4368          *    hold SGL elements with the last 1 or 2 double-words
4369          *    (4 or 8 bytes) un-used. On these controllers, we should
4370          *    recognize that there's not enough room for another SGL
4371          *    element and move the sge pointer to the next frame.
4372          */
4373         int                     i, j, k, l, frames, sgemax;
4374         int                     temp;
4375         uint8_t                 chainflags;
4376         uint16_t                chainlength;
4377         mptsas_cache_frames_t   *p;
4378 
4379         /*
4380          * Sgemax is the number of SGE's that will fit
4381          * each extra frame and frames is total
4382          * number of frames we'll need.  1 sge entry per
4383          * frame is reseverd for the chain element thus the -1 below.
4384          */
4385         sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_SGE_SIMPLE64))
4386             - 1);
4387         temp = (cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) / sgemax;
4388 
4389         /*
4390          * A little check to see if we need to round up the number
4391          * of frames we need
4392          */
4393         if ((cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) - (temp *
4394             sgemax) > 1) {
4395                 frames = (temp + 1);
4396         } else {
4397                 frames = temp;
4398         }
4399         dmap = cmd->cmd_sg;
4400         sge = (pMpi2SGESimple64_t)(&frame->SGL);
4401 
4402         /*
4403          * First fill in the main frame
4404          */
4405         j = MPTSAS_MAX_FRAME_SGES64(mpt) - 1;
4406         mptsas_sge_mainframe(cmd, frame, acc_hdl, j,
4407             ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4408             MPI2_SGE_FLAGS_SHIFT));
4409         dmap += j;
4410         sge += j;
4411         j++;
4412 
4413         /*
4414          * Fill in the chain element in the main frame.
4415          * About calculation on ChainOffset:
4416          * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
4417          *    in the end reserved for SGL element storage
4418          *    (MPI2_SGE_IO_UNION); we should count it in our
4419          *    calculation.  See its definition in the header file.
4420          * 2. Constant j is the counter of the current SGL element
4421          *    that will be processed, and (j - 1) is the number of
4422          *    SGL elements that have been processed (stored in the
4423          *    main frame).
4424          * 3. ChainOffset value should be in units of double-words (4
4425          *    bytes) so the last value should be divided by 4.
4426          */
4427         ddi_put8(acc_hdl, &frame->ChainOffset,
4428             (sizeof (MPI2_SCSI_IO_REQUEST) -
4429             sizeof (MPI2_SGE_IO_UNION) +
4430             (j - 1) * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4431         sgechain = (pMpi2SGEChain64_t)sge;
4432         chainflags = (MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4433             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4434             MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4435         ddi_put8(acc_hdl, &sgechain->Flags, chainflags);
4436 
4437         /*
4438          * The size of the next frame is the accurate size of space
4439          * (in bytes) used to store the SGL elements. j is the counter
4440          * of SGL elements. (j - 1) is the number of SGL elements that
4441          * have been processed (stored in frames).
4442          */
4443         if (frames >= 2) {
4444                 ASSERT(mpt->m_req_frame_size >= sizeof (MPI2_SGE_SIMPLE64));
4445                 chainlength = mpt->m_req_frame_size /
4446                     sizeof (MPI2_SGE_SIMPLE64) *
4447                     sizeof (MPI2_SGE_SIMPLE64);
4448         } else {
4449                 chainlength = ((cookiec - (j - 1)) *
4450                     sizeof (MPI2_SGE_SIMPLE64));
4451         }
4452 
4453         p = cmd->cmd_extra_frames;
4454 
4455         ddi_put16(acc_hdl, &sgechain->Length, chainlength);
4456         ddi_put32(acc_hdl, &sgechain->Address.Low, p->m_phys_addr);
4457         ddi_put32(acc_hdl, &sgechain->Address.High, p->m_phys_addr >> 32);
4458 
4459         /*
4460          * If there are more than 2 frames left we have to
4461          * fill in the next chain offset to the location of
4462          * the chain element in the next frame.
4463          * sgemax is the number of simple elements in an extra
4464          * frame. Note that the value NextChainOffset should be
4465          * in double-words (4 bytes).
4466          */
4467         if (frames >= 2) {
4468                 ddi_put8(acc_hdl, &sgechain->NextChainOffset,
4469                     (sgemax * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4470         } else {
4471                 ddi_put8(acc_hdl, &sgechain->NextChainOffset, 0);
4472         }
4473 
4474         /*
4475          * Jump to next frame;
4476          * Starting here, chain buffers go into the per command SGL.
4477          * This buffer is allocated when chain buffers are needed.
4478          */
4479         sge = (pMpi2SGESimple64_t)p->m_frames_addr;
4480         i = cookiec;
4481 
4482         /*
4483          * Start filling in frames with SGE's.  If we
4484          * reach the end of frame and still have SGE's
4485          * to fill we need to add a chain element and
4486          * use another frame.  j will be our counter
4487          * for what cookie we are at and i will be
4488          * the total cookiec. k is the current frame
4489          */
4490         for (k = 1; k <= frames; k++) {
4491                 for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
4492 
4493                         /*
4494                          * If we have reached the end of frame
4495                          * and we have more SGE's to fill in
4496                          * we have to fill the final entry
4497                          * with a chain element and then
4498                          * continue to the next frame
4499                          */
4500                         if ((l == (sgemax + 1)) && (k != frames)) {
4501                                 sgechain = (pMpi2SGEChain64_t)sge;
4502                                 j--;
4503                                 chainflags = (
4504                                     MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4505                                     MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4506                                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4507                                 ddi_put8(p->m_acc_hdl,
4508                                     &sgechain->Flags, chainflags);
4509                                 /*
4510                                  * k is the frame counter and (k + 1)
4511                                  * is the number of the next frame.
4512                                  * Note that frames are in contiguous
4513                                  * memory space.
4514                                  */
4515                                 nframe_phys_addr = p->m_phys_addr +
4516                                     (mpt->m_req_frame_size * k);
4517                                 ddi_put32(p->m_acc_hdl,
4518                                     &sgechain->Address.Low,
4519                                     nframe_phys_addr);
4520                                 ddi_put32(p->m_acc_hdl,
4521                                     &sgechain->Address.High,
4522                                     nframe_phys_addr >> 32);
4523 
4524                                 /*
4525                                  * If there are more than 2 frames left
4526                                  * we have to next chain offset to
4527                                  * the location of the chain element
4528                                  * in the next frame and fill in the
4529                                  * length of the next chain
4530                                  */
4531                                 if ((frames - k) >= 2) {
4532                                         ddi_put8(p->m_acc_hdl,
4533                                             &sgechain->NextChainOffset,
4534                                             (sgemax *
4535                                             sizeof (MPI2_SGE_SIMPLE64))
4536                                             >> 2);
4537                                         ddi_put16(p->m_acc_hdl,
4538                                             &sgechain->Length,
4539                                             mpt->m_req_frame_size /
4540                                             sizeof (MPI2_SGE_SIMPLE64) *
4541                                             sizeof (MPI2_SGE_SIMPLE64));
4542                                 } else {
4543                                         /*
4544                                          * This is the last frame. Set
4545                                          * the NextChainOffset to 0 and
4546                                          * Length is the total size of
4547                                          * all remaining simple elements
4548                                          */
4549                                         ddi_put8(p->m_acc_hdl,
4550                                             &sgechain->NextChainOffset,
4551                                             0);
4552                                         ddi_put16(p->m_acc_hdl,
4553                                             &sgechain->Length,
4554                                             (cookiec - j) *
4555                                             sizeof (MPI2_SGE_SIMPLE64));
4556                                 }
4557 
4558                                 /* Jump to the next frame */
4559                                 sge = (pMpi2SGESimple64_t)
4560                                     ((char *)p->m_frames_addr +
4561                                     (int)mpt->m_req_frame_size * k);
4562 
4563                                 continue;
4564                         }
4565 
4566                         ddi_put32(p->m_acc_hdl,
4567                             &sge->Address.Low,
4568                             dmap->addr.address64.Low);
4569                         ddi_put32(p->m_acc_hdl,
4570                             &sge->Address.High,
4571                             dmap->addr.address64.High);
4572                         ddi_put32(p->m_acc_hdl,
4573                             &sge->FlagsLength, dmap->count);
4574                         flags = ddi_get32(p->m_acc_hdl,
4575                             &sge->FlagsLength);
4576                         flags |= ((uint32_t)(
4577                             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4578                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4579                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4580                             MPI2_SGE_FLAGS_SHIFT);
4581 
4582                         /*
4583                          * If we are at the end of the frame and
4584                          * there is another frame to fill in
4585                          * we set the last simple element as last
4586                          * element
4587                          */
4588                         if ((l == sgemax) && (k != frames)) {
4589                                 flags |= ((uint32_t)
4590                                     (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4591                                     MPI2_SGE_FLAGS_SHIFT);
4592                         }
4593 
4594                         /*
4595                          * If this is the final cookie we
4596                          * indicate it by setting the flags
4597                          */
4598                         if (j == i) {
4599                                 flags |= ((uint32_t)
4600                                     (MPI2_SGE_FLAGS_LAST_ELEMENT |
4601                                     MPI2_SGE_FLAGS_END_OF_BUFFER |
4602                                     MPI2_SGE_FLAGS_END_OF_LIST) <<
4603                                     MPI2_SGE_FLAGS_SHIFT);
4604                         }
4605                         if (cmd->cmd_flags & CFLAG_DMASEND) {
4606                                 flags |=
4607                                     (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4608                                     MPI2_SGE_FLAGS_SHIFT);
4609                         } else {
4610                                 flags |=
4611                                     (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4612                                     MPI2_SGE_FLAGS_SHIFT);
4613                         }
4614                         ddi_put32(p->m_acc_hdl,
4615                             &sge->FlagsLength, flags);
4616                         dmap++;
4617                         sge++;
4618                 }
4619         }
4620 
4621         /*
4622          * Sync DMA with the chain buffers that were just created
4623          */
4624         (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
4625 }
4626 
4627 static void
4628 mptsas_ieee_sge_mainframe(mptsas_cmd_t *cmd, pMpi2SCSIIORequest_t frame,
4629     ddi_acc_handle_t acc_hdl, uint_t cookiec, uint8_t end_flag)
4630 {
4631         pMpi2IeeeSgeSimple64_t  ieeesge;
4632         mptti_t                 *dmap;
4633         uint8_t                 flags;
4634 
4635         dmap = cmd->cmd_sg;
4636 
4637         NDBG1(("mptsas_ieee_sge_mainframe: cookiec=%d, %s", cookiec,
4638             cmd->cmd_flags & CFLAG_DMASEND?"Out":"In"));
4639 
4640         ieeesge = (pMpi2IeeeSgeSimple64_t)(&frame->SGL);
4641         while (cookiec--) {
4642                 ddi_put32(acc_hdl,
4643                     &ieeesge->Address.Low, dmap->addr.address64.Low);
4644                 ddi_put32(acc_hdl,
4645                     &ieeesge->Address.High, dmap->addr.address64.High);
4646                 ddi_put32(acc_hdl, &ieeesge->Length,
4647                     dmap->count);
4648                 NDBG1(("mptsas_ieee_sge_mainframe: len=%d", dmap->count));
4649                 flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
4650                     MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
4651 
4652                 /*
4653                  * If this is the last cookie, we set the flags
4654                  * to indicate so
4655                  */
4656                 if (cookiec == 0) {
4657                         flags |= end_flag;
4658                 }
4659 
4660                 ddi_put8(acc_hdl, &ieeesge->Flags, flags);
4661                 dmap++;
4662                 ieeesge++;
4663         }
4664 }
4665 
4666 static void
4667 mptsas_ieee_sge_chain(mptsas_t *mpt, mptsas_cmd_t *cmd,
4668     pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4669 {
4670         pMpi2IeeeSgeSimple64_t  ieeesge;
4671         pMpi25IeeeSgeChain64_t  ieeesgechain;
4672         uint64_t                nframe_phys_addr;
4673         uint_t                  cookiec;
4674         mptti_t                 *dmap;
4675         uint8_t                 flags;
4676 
4677         /*
4678          * Save the number of entries in the DMA
4679          * Scatter/Gather list
4680          */
4681         cookiec = cmd->cmd_cookiec;
4682 
4683         NDBG1(("mptsas_ieee_sge_chain: cookiec=%d", cookiec));
4684 
4685         /*
4686          * Hereby we start to deal with multiple frames.
4687          * The process is as follows:
4688          * 1. Determine how many frames are needed for SGL element
4689          *    storage; Note that all frames are stored in contiguous
4690          *    memory space and in 64-bit DMA mode each element is
4691          *    4 double-words (16 bytes) long.
4692          * 2. Fill up the main frame. We need to do this separately
4693          *    since it contains the SCSI IO request header and needs
4694          *    dedicated processing. Note that the last 4 double-words
4695          *    of the SCSI IO header is for SGL element storage
4696          *    (MPI2_SGE_IO_UNION).
4697          * 3. Fill the chain element in the main frame, so the DMA
4698          *    engine can use the following frames.
4699          * 4. Enter a loop to fill the remaining frames. Note that the
4700          *    last frame contains no chain element.  The remaining
4701          *    frames go into the mpt SGL buffer allocated on the fly,
4702          *    not immediately following the main message frame, as in
4703          *    Gen1.
4704          * Restrictions:
4705          *    For 64-bit DMA, the simple element and chain element
4706          *    are both of 4 double-words (16 bytes) in size, even
4707          *    though all frames are stored in the first 4G of mem
4708          *    range and the higher 32-bits of the address are always 0.
4709          */
4710         int                     i, j, k, l, frames, sgemax;
4711         int                     temp;
4712         uint8_t                 chainflags;
4713         uint32_t                chainlength;
4714         mptsas_cache_frames_t   *p;
4715 
4716         /*
4717          * Sgemax is the number of SGE's that will fit
4718          * each extra frame and frames is total
4719          * number of frames we'll need.  1 sge entry per
4720          * frame is reseverd for the chain element thus the -1 below.
4721          */
4722         sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_IEEE_SGE_SIMPLE64))
4723             - 1);
4724         temp = (cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) / sgemax;
4725 
4726         /*
4727          * A little check to see if we need to round up the number
4728          * of frames we need
4729          */
4730         if ((cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) - (temp *
4731             sgemax) > 1) {
4732                 frames = (temp + 1);
4733         } else {
4734                 frames = temp;
4735         }
4736         NDBG1(("mptsas_ieee_sge_chain: temp=%d, frames=%d", temp, frames));
4737         dmap = cmd->cmd_sg;
4738         ieeesge = (pMpi2IeeeSgeSimple64_t)(&frame->SGL);
4739 
4740         /*
4741          * First fill in the main frame
4742          */
4743         j = MPTSAS_MAX_FRAME_SGES64(mpt) - 1;
4744         mptsas_ieee_sge_mainframe(cmd, frame, acc_hdl, j, 0);
4745         dmap += j;
4746         ieeesge += j;
4747         j++;
4748 
4749         /*
4750          * Fill in the chain element in the main frame.
4751          * About calculation on ChainOffset:
4752          * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
4753          *    in the end reserved for SGL element storage
4754          *    (MPI2_SGE_IO_UNION); we should count it in our
4755          *    calculation.  See its definition in the header file.
4756          * 2. Constant j is the counter of the current SGL element
4757          *    that will be processed, and (j - 1) is the number of
4758          *    SGL elements that have been processed (stored in the
4759          *    main frame).
4760          * 3. ChainOffset value should be in units of quad-words (16
4761          *    bytes) so the last value should be divided by 16.
4762          */
4763         ddi_put8(acc_hdl, &frame->ChainOffset,
4764             (sizeof (MPI2_SCSI_IO_REQUEST) -
4765             sizeof (MPI2_SGE_IO_UNION) +
4766             (j - 1) * sizeof (MPI2_IEEE_SGE_SIMPLE64)) >> 4);
4767         ieeesgechain = (pMpi25IeeeSgeChain64_t)ieeesge;
4768         chainflags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
4769             MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
4770         ddi_put8(acc_hdl, &ieeesgechain->Flags, chainflags);
4771 
4772         /*
4773          * The size of the next frame is the accurate size of space
4774          * (in bytes) used to store the SGL elements. j is the counter
4775          * of SGL elements. (j - 1) is the number of SGL elements that
4776          * have been processed (stored in frames).
4777          */
4778         if (frames >= 2) {
4779                 ASSERT(mpt->m_req_frame_size >=
4780                     sizeof (MPI2_IEEE_SGE_SIMPLE64));
4781                 chainlength = mpt->m_req_frame_size /
4782                     sizeof (MPI2_IEEE_SGE_SIMPLE64) *
4783                     sizeof (MPI2_IEEE_SGE_SIMPLE64);
4784         } else {
4785                 chainlength = ((cookiec - (j - 1)) *
4786                     sizeof (MPI2_IEEE_SGE_SIMPLE64));
4787         }
4788 
4789         p = cmd->cmd_extra_frames;
4790 
4791         ddi_put32(acc_hdl, &ieeesgechain->Length, chainlength);
4792         ddi_put32(acc_hdl, &ieeesgechain->Address.Low, p->m_phys_addr);
4793         ddi_put32(acc_hdl, &ieeesgechain->Address.High, p->m_phys_addr >> 32);
4794 
4795         /*
4796          * If there are more than 2 frames left we have to
4797          * fill in the next chain offset to the location of
4798          * the chain element in the next frame.
4799          * sgemax is the number of simple elements in an extra
4800          * frame. Note that the value NextChainOffset should be
4801          * in double-words (4 bytes).
4802          */
4803         if (frames >= 2) {
4804                 ddi_put8(acc_hdl, &ieeesgechain->NextChainOffset,
4805                     (sgemax * sizeof (MPI2_IEEE_SGE_SIMPLE64)) >> 4);
4806         } else {
4807                 ddi_put8(acc_hdl, &ieeesgechain->NextChainOffset, 0);
4808         }
4809 
4810         /*
4811          * Jump to next frame;
4812          * Starting here, chain buffers go into the per command SGL.
4813          * This buffer is allocated when chain buffers are needed.
4814          */
4815         ieeesge = (pMpi2IeeeSgeSimple64_t)p->m_frames_addr;
4816         i = cookiec;
4817 
4818         /*
4819          * Start filling in frames with SGE's.  If we
4820          * reach the end of frame and still have SGE's
4821          * to fill we need to add a chain element and
4822          * use another frame.  j will be our counter
4823          * for what cookie we are at and i will be
4824          * the total cookiec. k is the current frame
4825          */
4826         for (k = 1; k <= frames; k++) {
4827                 for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
4828 
4829                         /*
4830                          * If we have reached the end of frame
4831                          * and we have more SGE's to fill in
4832                          * we have to fill the final entry
4833                          * with a chain element and then
4834                          * continue to the next frame
4835                          */
4836                         if ((l == (sgemax + 1)) && (k != frames)) {
4837                                 ieeesgechain = (pMpi25IeeeSgeChain64_t)ieeesge;
4838                                 j--;
4839                                 chainflags =
4840                                     MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
4841                                     MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
4842                                 ddi_put8(p->m_acc_hdl,
4843                                     &ieeesgechain->Flags, chainflags);
4844                                 /*
4845                                  * k is the frame counter and (k + 1)
4846                                  * is the number of the next frame.
4847                                  * Note that frames are in contiguous
4848                                  * memory space.
4849                                  */
4850                                 nframe_phys_addr = p->m_phys_addr +
4851                                     (mpt->m_req_frame_size * k);
4852                                 ddi_put32(p->m_acc_hdl,
4853                                     &ieeesgechain->Address.Low,
4854                                     nframe_phys_addr);
4855                                 ddi_put32(p->m_acc_hdl,
4856                                     &ieeesgechain->Address.High,
4857                                     nframe_phys_addr >> 32);
4858 
4859                                 /*
4860                                  * If there are more than 2 frames left
4861                                  * we have to next chain offset to
4862                                  * the location of the chain element
4863                                  * in the next frame and fill in the
4864                                  * length of the next chain
4865                                  */
4866                                 if ((frames - k) >= 2) {
4867                                         ddi_put8(p->m_acc_hdl,
4868                                             &ieeesgechain->NextChainOffset,
4869                                             (sgemax *
4870                                             sizeof (MPI2_IEEE_SGE_SIMPLE64))
4871                                             >> 4);
4872                                         ASSERT(mpt->m_req_frame_size >=
4873                                             sizeof (MPI2_IEEE_SGE_SIMPLE64));
4874                                         ddi_put32(p->m_acc_hdl,
4875                                             &ieeesgechain->Length,
4876                                             mpt->m_req_frame_size /
4877                                             sizeof (MPI2_IEEE_SGE_SIMPLE64) *
4878                                             sizeof (MPI2_IEEE_SGE_SIMPLE64));
4879                                 } else {
4880                                         /*
4881                                          * This is the last frame. Set
4882                                          * the NextChainOffset to 0 and
4883                                          * Length is the total size of
4884                                          * all remaining simple elements
4885                                          */
4886                                         ddi_put8(p->m_acc_hdl,
4887                                             &ieeesgechain->NextChainOffset,
4888                                             0);
4889                                         ddi_put32(p->m_acc_hdl,
4890                                             &ieeesgechain->Length,
4891                                             (cookiec - j) *
4892                                             sizeof (MPI2_IEEE_SGE_SIMPLE64));
4893                                 }
4894 
4895                                 /* Jump to the next frame */
4896                                 ieeesge = (pMpi2IeeeSgeSimple64_t)
4897                                     ((char *)p->m_frames_addr +
4898                                     (int)mpt->m_req_frame_size * k);
4899 
4900                                 continue;
4901                         }
4902 
4903                         ddi_put32(p->m_acc_hdl,
4904                             &ieeesge->Address.Low,
4905                             dmap->addr.address64.Low);
4906                         ddi_put32(p->m_acc_hdl,
4907                             &ieeesge->Address.High,
4908                             dmap->addr.address64.High);
4909                         ddi_put32(p->m_acc_hdl,
4910                             &ieeesge->Length, dmap->count);
4911                         flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
4912                             MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
4913 
4914                         /*
4915                          * If we are at the end of the frame and
4916                          * there is another frame to fill in
4917                          * do we need to do anything?
4918                          * if ((l == sgemax) && (k != frames)) {
4919                          * }
4920                          */
4921 
4922                         /*
4923                          * If this is the final cookie set end of list.
4924                          */
4925                         if (j == i) {
4926                                 flags |= MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
4927                         }
4928 
4929                         ddi_put8(p->m_acc_hdl, &ieeesge->Flags, flags);
4930                         dmap++;
4931                         ieeesge++;
4932                 }
4933         }
4934 
4935         /*
4936          * Sync DMA with the chain buffers that were just created
4937          */
4938         (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
4939 }
4940 
4941 static void
4942 mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd, uint32_t *control,
4943     pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4944 {
4945         ASSERT(cmd->cmd_flags & CFLAG_DMAVALID);
4946 
4947         NDBG1(("mptsas_sge_setup: cookiec=%d", cmd->cmd_cookiec));
4948 
4949         /*
4950          * Set read/write bit in control.
4951          */
4952         if (cmd->cmd_flags & CFLAG_DMASEND) {
4953                 *control |= MPI2_SCSIIO_CONTROL_WRITE;
4954         } else {
4955                 *control |= MPI2_SCSIIO_CONTROL_READ;
4956         }
4957 
4958         ddi_put32(acc_hdl, &frame->DataLength, cmd->cmd_dmacount);
4959 
4960         /*
4961          * We have 4 cases here.  First where we can fit all the
4962          * SG elements into the main frame, and the case
4963          * where we can't. The SG element is also different when using
4964          * MPI2.5 interface.
4965          * If we have more cookies than we can attach to a frame
4966          * we will need to use a chain element to point
4967          * a location of memory where the rest of the S/G
4968          * elements reside.
4969          */
4970         if (cmd->cmd_cookiec <= MPTSAS_MAX_FRAME_SGES64(mpt)) {
4971                 if (mpt->m_MPI25) {
4972                         mptsas_ieee_sge_mainframe(cmd, frame, acc_hdl,
4973                             cmd->cmd_cookiec,
4974                             MPI25_IEEE_SGE_FLAGS_END_OF_LIST);
4975                 } else {
4976                         mptsas_sge_mainframe(cmd, frame, acc_hdl,
4977                             cmd->cmd_cookiec,
4978                             ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT
4979                             | MPI2_SGE_FLAGS_END_OF_BUFFER
4980                             | MPI2_SGE_FLAGS_END_OF_LIST) <<
4981                             MPI2_SGE_FLAGS_SHIFT));
4982                 }
4983         } else {
4984                 if (mpt->m_MPI25) {
4985                         mptsas_ieee_sge_chain(mpt, cmd, frame, acc_hdl);
4986                 } else {
4987                         mptsas_sge_chain(mpt, cmd, frame, acc_hdl);
4988                 }
4989         }
4990 }
4991 
4992 /*
4993  * Interrupt handling
4994  * Utility routine.  Poll for status of a command sent to HBA
4995  * without interrupts (a FLAG_NOINTR command).
4996  */
4997 int
4998 mptsas_poll(mptsas_t *mpt, mptsas_cmd_t *poll_cmd, int polltime)
4999 {
5000         int     rval = TRUE;
5001 
5002         NDBG5(("mptsas_poll: cmd=0x%p", (void *)poll_cmd));
5003 
5004         if ((poll_cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
5005                 mptsas_restart_hba(mpt);
5006         }
5007 
5008         /*
5009          * Wait, using drv_usecwait(), long enough for the command to
5010          * reasonably return from the target if the target isn't
5011          * "dead".  A polled command may well be sent from scsi_poll, and
5012          * there are retries built in to scsi_poll if the transport
5013          * accepted the packet (TRAN_ACCEPT).  scsi_poll waits 1 second
5014          * and retries the transport up to scsi_poll_busycnt times
5015          * (currently 60) if
5016          * 1. pkt_reason is CMD_INCOMPLETE and pkt_state is 0, or
5017          * 2. pkt_reason is CMD_CMPLT and *pkt_scbp has STATUS_BUSY
5018          *
5019          * limit the waiting to avoid a hang in the event that the
5020          * cmd never gets started but we are still receiving interrupts
5021          */
5022         while (!(poll_cmd->cmd_flags & CFLAG_FINISHED)) {
5023                 if (mptsas_wait_intr(mpt, polltime) == FALSE) {
5024                         NDBG5(("mptsas_poll: command incomplete"));
5025                         rval = FALSE;
5026                         break;
5027                 }
5028         }
5029 
5030         if (rval == FALSE) {
5031 
5032                 /*
5033                  * this isn't supposed to happen, the hba must be wedged
5034                  * Mark this cmd as a timeout.
5035                  */
5036                 mptsas_set_pkt_reason(mpt, poll_cmd, CMD_TIMEOUT,
5037                     (STAT_TIMEOUT|STAT_ABORTED));
5038 
5039                 if (poll_cmd->cmd_queued == FALSE) {
5040 
5041                         NDBG5(("mptsas_poll: not on waitq"));
5042 
5043                         poll_cmd->cmd_pkt->pkt_state |=
5044                             (STATE_GOT_BUS|STATE_GOT_TARGET|STATE_SENT_CMD);
5045                 } else {
5046 
5047                         /* find and remove it from the waitq */
5048                         NDBG5(("mptsas_poll: delete from waitq"));
5049                         mptsas_waitq_delete(mpt, poll_cmd);
5050                 }
5051 
5052         }
5053         mptsas_fma_check(mpt, poll_cmd);
5054         NDBG5(("mptsas_poll: done"));
5055         return (rval);
5056 }
5057 
5058 /*
5059  * Used for polling cmds and TM function
5060  */
5061 static int
5062 mptsas_wait_intr(mptsas_t *mpt, int polltime)
5063 {
5064         int                             cnt;
5065         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
5066         uint32_t                        int_mask;
5067 
5068         NDBG5(("mptsas_wait_intr"));
5069 
5070         mpt->m_polled_intr = 1;
5071 
5072         /*
5073          * Get the current interrupt mask and disable interrupts.  When
5074          * re-enabling ints, set mask to saved value.
5075          */
5076         int_mask = ddi_get32(mpt->m_datap, &mpt->m_reg->HostInterruptMask);
5077         MPTSAS_DISABLE_INTR(mpt);
5078 
5079         /*
5080          * Keep polling for at least (polltime * 1000) seconds
5081          */
5082         for (cnt = 0; cnt < polltime; cnt++) {
5083                 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5084                     DDI_DMA_SYNC_FORCPU);
5085 
5086                 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
5087                     MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
5088 
5089                 if (ddi_get32(mpt->m_acc_post_queue_hdl,
5090                     &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
5091                     ddi_get32(mpt->m_acc_post_queue_hdl,
5092                     &reply_desc_union->Words.High) == 0xFFFFFFFF) {
5093                         drv_usecwait(1000);
5094                         continue;
5095                 }
5096 
5097                 /*
5098                  * The reply is valid, process it according to its
5099                  * type.
5100                  */
5101                 mptsas_process_intr(mpt, reply_desc_union);
5102 
5103                 if (++mpt->m_post_index == mpt->m_post_queue_depth) {
5104                         mpt->m_post_index = 0;
5105                 }
5106 
5107                 /*
5108                  * Update the global reply index
5109                  */
5110                 ddi_put32(mpt->m_datap,
5111                     &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
5112                 mpt->m_polled_intr = 0;
5113 
5114                 /*
5115                  * Re-enable interrupts and quit.
5116                  */
5117                 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask,
5118                     int_mask);
5119                 return (TRUE);
5120 
5121         }
5122 
5123         /*
5124          * Clear polling flag, re-enable interrupts and quit.
5125          */
5126         mpt->m_polled_intr = 0;
5127         ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask, int_mask);
5128         return (FALSE);
5129 }
5130 
5131 static void
5132 mptsas_handle_scsi_io_success(mptsas_t *mpt,
5133     pMpi2ReplyDescriptorsUnion_t reply_desc)
5134 {
5135         pMpi2SCSIIOSuccessReplyDescriptor_t     scsi_io_success;
5136         uint16_t                                SMID;
5137         mptsas_slots_t                          *slots = mpt->m_active;
5138         mptsas_cmd_t                            *cmd = NULL;
5139         struct scsi_pkt                         *pkt;
5140 
5141         ASSERT(mutex_owned(&mpt->m_mutex));
5142 
5143         scsi_io_success = (pMpi2SCSIIOSuccessReplyDescriptor_t)reply_desc;
5144         SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &scsi_io_success->SMID);
5145 
5146         /*
5147          * This is a success reply so just complete the IO.  First, do a sanity
5148          * check on the SMID.  The final slot is used for TM requests, which
5149          * would not come into this reply handler.
5150          */
5151         if ((SMID == 0) || (SMID > slots->m_n_normal)) {
5152                 mptsas_log(mpt, CE_WARN, "?Received invalid SMID of %d\n",
5153                     SMID);
5154                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5155                 return;
5156         }
5157 
5158         cmd = slots->m_slot[SMID];
5159 
5160         /*
5161          * print warning and return if the slot is empty
5162          */
5163         if (cmd == NULL) {
5164                 mptsas_log(mpt, CE_WARN, "?NULL command for successful SCSI IO "
5165                     "in slot %d", SMID);
5166                 return;
5167         }
5168 
5169         pkt = CMD2PKT(cmd);
5170         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
5171             STATE_GOT_STATUS);
5172         if (cmd->cmd_flags & CFLAG_DMAVALID) {
5173                 pkt->pkt_state |= STATE_XFERRED_DATA;
5174         }
5175         pkt->pkt_resid = 0;
5176 
5177         if (cmd->cmd_flags & CFLAG_PASSTHRU) {
5178                 cmd->cmd_flags |= CFLAG_FINISHED;
5179                 cv_broadcast(&mpt->m_passthru_cv);
5180                 return;
5181         } else {
5182                 mptsas_remove_cmd(mpt, cmd);
5183         }
5184 
5185         if (cmd->cmd_flags & CFLAG_RETRY) {
5186                 /*
5187                  * The target returned QFULL or busy, do not add tihs
5188                  * pkt to the doneq since the hba will retry
5189                  * this cmd.
5190                  *
5191                  * The pkt has already been resubmitted in
5192                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
5193                  * Remove this cmd_flag here.
5194                  */
5195                 cmd->cmd_flags &= ~CFLAG_RETRY;
5196         } else {
5197                 mptsas_doneq_add(mpt, cmd);
5198         }
5199 }
5200 
5201 static void
5202 mptsas_handle_address_reply(mptsas_t *mpt,
5203     pMpi2ReplyDescriptorsUnion_t reply_desc)
5204 {
5205         pMpi2AddressReplyDescriptor_t   address_reply;
5206         pMPI2DefaultReply_t             reply;
5207         mptsas_fw_diagnostic_buffer_t   *pBuffer;
5208         uint32_t                        reply_addr, reply_frame_dma_baseaddr;
5209         uint16_t                        SMID, iocstatus;
5210         mptsas_slots_t                  *slots = mpt->m_active;
5211         mptsas_cmd_t                    *cmd = NULL;
5212         uint8_t                         function, buffer_type;
5213         m_replyh_arg_t                  *args;
5214         int                             reply_frame_no;
5215 
5216         ASSERT(mutex_owned(&mpt->m_mutex));
5217 
5218         address_reply = (pMpi2AddressReplyDescriptor_t)reply_desc;
5219         reply_addr = ddi_get32(mpt->m_acc_post_queue_hdl,
5220             &address_reply->ReplyFrameAddress);
5221         SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &address_reply->SMID);
5222 
5223         /*
5224          * If reply frame is not in the proper range we should ignore this
5225          * message and exit the interrupt handler.
5226          */
5227         reply_frame_dma_baseaddr = mpt->m_reply_frame_dma_addr & 0xffffffffu;
5228         if ((reply_addr < reply_frame_dma_baseaddr) ||
5229             (reply_addr >= (reply_frame_dma_baseaddr +
5230             (mpt->m_reply_frame_size * mpt->m_max_replies))) ||
5231             ((reply_addr - reply_frame_dma_baseaddr) %
5232             mpt->m_reply_frame_size != 0)) {
5233                 mptsas_log(mpt, CE_WARN, "?Received invalid reply frame "
5234                     "address 0x%x\n", reply_addr);
5235                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5236                 return;
5237         }
5238 
5239         (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
5240             DDI_DMA_SYNC_FORCPU);
5241         reply = (pMPI2DefaultReply_t)(mpt->m_reply_frame + (reply_addr -
5242             reply_frame_dma_baseaddr));
5243         function = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->Function);
5244 
5245         NDBG31(("mptsas_handle_address_reply: function 0x%x, reply_addr=0x%x",
5246             function, reply_addr));
5247 
5248         /*
5249          * don't get slot information and command for events since these values
5250          * don't exist
5251          */
5252         if ((function != MPI2_FUNCTION_EVENT_NOTIFICATION) &&
5253             (function != MPI2_FUNCTION_DIAG_BUFFER_POST)) {
5254                 /*
5255                  * This could be a TM reply, which use the last allocated SMID,
5256                  * so allow for that.
5257                  */
5258                 if ((SMID == 0) || (SMID > (slots->m_n_normal + 1))) {
5259                         mptsas_log(mpt, CE_WARN, "?Received invalid SMID of "
5260                             "%d\n", SMID);
5261                         ddi_fm_service_impact(mpt->m_dip,
5262                             DDI_SERVICE_UNAFFECTED);
5263                         return;
5264                 }
5265 
5266                 cmd = slots->m_slot[SMID];
5267 
5268                 /*
5269                  * print warning and return if the slot is empty
5270                  */
5271                 if (cmd == NULL) {
5272                         mptsas_log(mpt, CE_WARN, "?NULL command for address "
5273                             "reply in slot %d", SMID);
5274                         return;
5275                 }
5276                 if ((cmd->cmd_flags &
5277                     (CFLAG_PASSTHRU | CFLAG_CONFIG | CFLAG_FW_DIAG))) {
5278                         cmd->cmd_rfm = reply_addr;
5279                         cmd->cmd_flags |= CFLAG_FINISHED;
5280                         cv_broadcast(&mpt->m_passthru_cv);
5281                         cv_broadcast(&mpt->m_config_cv);
5282                         cv_broadcast(&mpt->m_fw_diag_cv);
5283                         return;
5284                 } else if (!(cmd->cmd_flags & CFLAG_FW_CMD)) {
5285                         mptsas_remove_cmd(mpt, cmd);
5286                 }
5287                 NDBG31(("\t\tmptsas_process_intr: slot=%d", SMID));
5288         }
5289         /*
5290          * Depending on the function, we need to handle
5291          * the reply frame (and cmd) differently.
5292          */
5293         switch (function) {
5294         case MPI2_FUNCTION_SCSI_IO_REQUEST:
5295                 mptsas_check_scsi_io_error(mpt, (pMpi2SCSIIOReply_t)reply, cmd);
5296                 break;
5297         case MPI2_FUNCTION_SCSI_TASK_MGMT:
5298                 cmd->cmd_rfm = reply_addr;
5299                 mptsas_check_task_mgt(mpt, (pMpi2SCSIManagementReply_t)reply,
5300                     cmd);
5301                 break;
5302         case MPI2_FUNCTION_FW_DOWNLOAD:
5303                 cmd->cmd_flags |= CFLAG_FINISHED;
5304                 cv_signal(&mpt->m_fw_cv);
5305                 break;
5306         case MPI2_FUNCTION_EVENT_NOTIFICATION:
5307                 reply_frame_no = (reply_addr - reply_frame_dma_baseaddr) /
5308                     mpt->m_reply_frame_size;
5309                 args = &mpt->m_replyh_args[reply_frame_no];
5310                 args->mpt = (void *)mpt;
5311                 args->rfm = reply_addr;
5312 
5313                 /*
5314                  * Record the event if its type is enabled in
5315                  * this mpt instance by ioctl.
5316                  */
5317                 mptsas_record_event(args);
5318 
5319                 /*
5320                  * Handle time critical events
5321                  * NOT_RESPONDING/ADDED only now
5322                  */
5323                 if (mptsas_handle_event_sync(args) == DDI_SUCCESS) {
5324                         /*
5325                          * Would not return main process,
5326                          * just let taskq resolve ack action
5327                          * and ack would be sent in taskq thread
5328                          */
5329                         NDBG20(("send mptsas_handle_event_sync success"));
5330                 }
5331 
5332                 if (mpt->m_in_reset) {
5333                         NDBG20(("dropping event received during reset"));
5334                         return;
5335                 }
5336 
5337                 if ((ddi_taskq_dispatch(mpt->m_event_taskq, mptsas_handle_event,
5338                     (void *)args, DDI_NOSLEEP)) != DDI_SUCCESS) {
5339                         mptsas_log(mpt, CE_WARN, "No memory available"
5340                         "for dispatch taskq");
5341                         /*
5342                          * Return the reply frame to the free queue.
5343                          */
5344                         ddi_put32(mpt->m_acc_free_queue_hdl,
5345                             &((uint32_t *)(void *)
5346                             mpt->m_free_queue)[mpt->m_free_index], reply_addr);
5347                         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
5348                             DDI_DMA_SYNC_FORDEV);
5349                         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
5350                                 mpt->m_free_index = 0;
5351                         }
5352 
5353                         ddi_put32(mpt->m_datap,
5354                             &mpt->m_reg->ReplyFreeHostIndex, mpt->m_free_index);
5355                 }
5356                 return;
5357         case MPI2_FUNCTION_DIAG_BUFFER_POST:
5358                 /*
5359                  * If SMID is 0, this implies that the reply is due to a
5360                  * release function with a status that the buffer has been
5361                  * released.  Set the buffer flags accordingly.
5362                  */
5363                 if (SMID == 0) {
5364                         iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
5365                             &reply->IOCStatus);
5366                         buffer_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
5367                             &(((pMpi2DiagBufferPostReply_t)reply)->BufferType));
5368                         if (iocstatus == MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED) {
5369                                 pBuffer =
5370                                     &mpt->m_fw_diag_buffer_list[buffer_type];
5371                                 pBuffer->valid_data = TRUE;
5372                                 pBuffer->owned_by_firmware = FALSE;
5373                                 pBuffer->immediate = FALSE;
5374                         }
5375                 } else {
5376                         /*
5377                          * Normal handling of diag post reply with SMID.
5378                          */
5379                         cmd = slots->m_slot[SMID];
5380 
5381                         /*
5382                          * print warning and return if the slot is empty
5383                          */
5384                         if (cmd == NULL) {
5385                                 mptsas_log(mpt, CE_WARN, "?NULL command for "
5386                                     "address reply in slot %d", SMID);
5387                                 return;
5388                         }
5389                         cmd->cmd_rfm = reply_addr;
5390                         cmd->cmd_flags |= CFLAG_FINISHED;
5391                         cv_broadcast(&mpt->m_fw_diag_cv);
5392                 }
5393                 return;
5394         default:
5395                 mptsas_log(mpt, CE_WARN, "Unknown function 0x%x ", function);
5396                 break;
5397         }
5398 
5399         /*
5400          * Return the reply frame to the free queue.
5401          */
5402         ddi_put32(mpt->m_acc_free_queue_hdl,
5403             &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
5404             reply_addr);
5405         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
5406             DDI_DMA_SYNC_FORDEV);
5407         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
5408                 mpt->m_free_index = 0;
5409         }
5410         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
5411             mpt->m_free_index);
5412 
5413         if (cmd->cmd_flags & CFLAG_FW_CMD)
5414                 return;
5415 
5416         if (cmd->cmd_flags & CFLAG_RETRY) {
5417                 /*
5418                  * The target returned QFULL or busy, do not add this
5419                  * pkt to the doneq since the hba will retry
5420                  * this cmd.
5421                  *
5422                  * The pkt has already been resubmitted in
5423                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
5424                  * Remove this cmd_flag here.
5425                  */
5426                 cmd->cmd_flags &= ~CFLAG_RETRY;
5427         } else {
5428                 mptsas_doneq_add(mpt, cmd);
5429         }
5430 }
5431 
5432 #ifdef MPTSAS_DEBUG
5433 static uint8_t mptsas_last_sense[256];
5434 #endif
5435 
5436 static void
5437 mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
5438     mptsas_cmd_t *cmd)
5439 {
5440         uint8_t                 scsi_status, scsi_state;
5441         uint16_t                ioc_status, cmd_rqs_len;
5442         uint32_t                xferred, sensecount, responsedata, loginfo = 0;
5443         struct scsi_pkt         *pkt;
5444         struct scsi_arq_status  *arqstat;
5445         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
5446         uint8_t                 *sensedata = NULL;
5447         uint64_t                sas_wwn;
5448         uint8_t                 phy;
5449         char                    wwn_str[MPTSAS_WWN_STRLEN];
5450 
5451         scsi_status = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIStatus);
5452         ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5453         scsi_state = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIState);
5454         xferred = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->TransferCount);
5455         sensecount = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->SenseCount);
5456         responsedata = ddi_get32(mpt->m_acc_reply_frame_hdl,
5457             &reply->ResponseInfo);
5458 
5459         if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
5460                 sas_wwn = ptgt->m_addr.mta_wwn;
5461                 phy = ptgt->m_phynum;
5462                 if (sas_wwn == 0) {
5463                         (void) sprintf(wwn_str, "p%x", phy);
5464                 } else {
5465                         (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
5466                 }
5467                 loginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
5468                     &reply->IOCLogInfo);
5469                 mptsas_log(mpt, CE_NOTE,
5470                     "?Log info 0x%x received for target %d %s.\n"
5471                     "\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5472                     loginfo, Tgt(cmd), wwn_str, scsi_status, ioc_status,
5473                     scsi_state);
5474         }
5475 
5476         NDBG31(("\t\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5477             scsi_status, ioc_status, scsi_state));
5478 
5479         pkt = CMD2PKT(cmd);
5480         *(pkt->pkt_scbp) = scsi_status;
5481 
5482         if (loginfo == 0x31170000) {
5483                 /*
5484                  * if loginfo PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY
5485                  * 0x31170000 comes, that means the device missing delay
5486                  * is in progressing, the command need retry later.
5487                  */
5488                 *(pkt->pkt_scbp) = STATUS_BUSY;
5489                 return;
5490         }
5491 
5492         if ((scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) &&
5493             ((ioc_status & MPI2_IOCSTATUS_MASK) ==
5494             MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE)) {
5495                 pkt->pkt_reason = CMD_INCOMPLETE;
5496                 pkt->pkt_state |= STATE_GOT_BUS;
5497                 if (ptgt->m_reset_delay == 0) {
5498                         mptsas_set_throttle(mpt, ptgt,
5499                             DRAIN_THROTTLE);
5500                 }
5501                 return;
5502         }
5503 
5504         if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
5505                 responsedata &= 0x000000FF;
5506                 if (responsedata & MPTSAS_SCSI_RESPONSE_CODE_TLR_OFF) {
5507                         mptsas_log(mpt, CE_NOTE, "Do not support the TLR\n");
5508                         pkt->pkt_reason = CMD_TLR_OFF;
5509                         return;
5510                 }
5511         }
5512 
5513 
5514         switch (scsi_status) {
5515         case MPI2_SCSI_STATUS_CHECK_CONDITION:
5516                 pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5517                 arqstat = (void*)(pkt->pkt_scbp);
5518                 arqstat->sts_rqpkt_status = *((struct scsi_status *)
5519                     (pkt->pkt_scbp));
5520                 pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
5521                     STATE_SENT_CMD | STATE_GOT_STATUS | STATE_ARQ_DONE);
5522                 if (cmd->cmd_flags & CFLAG_XARQ) {
5523                         pkt->pkt_state |= STATE_XARQ_DONE;
5524                 }
5525                 if (pkt->pkt_resid != cmd->cmd_dmacount) {
5526                         pkt->pkt_state |= STATE_XFERRED_DATA;
5527                 }
5528                 arqstat->sts_rqpkt_reason = pkt->pkt_reason;
5529                 arqstat->sts_rqpkt_state  = pkt->pkt_state;
5530                 arqstat->sts_rqpkt_state |= STATE_XFERRED_DATA;
5531                 arqstat->sts_rqpkt_statistics = pkt->pkt_statistics;
5532                 sensedata = (uint8_t *)&arqstat->sts_sensedata;
5533                 cmd_rqs_len = cmd->cmd_extrqslen ?
5534                     cmd->cmd_extrqslen : cmd->cmd_rqslen;
5535                 (void) ddi_dma_sync(mpt->m_dma_req_sense_hdl, 0, 0,
5536                     DDI_DMA_SYNC_FORKERNEL);
5537 #ifdef MPTSAS_DEBUG
5538                 bcopy(cmd->cmd_arq_buf, mptsas_last_sense,
5539                     ((cmd_rqs_len >= sizeof (mptsas_last_sense)) ?
5540                     sizeof (mptsas_last_sense):cmd_rqs_len));
5541 #endif
5542                 bcopy((uchar_t *)cmd->cmd_arq_buf, sensedata,
5543                     ((cmd_rqs_len >= sensecount) ? sensecount :
5544                     cmd_rqs_len));
5545                 arqstat->sts_rqpkt_resid = (cmd_rqs_len - sensecount);
5546                 cmd->cmd_flags |= CFLAG_CMDARQ;
5547                 /*
5548                  * Set proper status for pkt if autosense was valid
5549                  */
5550                 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
5551                         struct scsi_status zero_status = { 0 };
5552                         arqstat->sts_rqpkt_status = zero_status;
5553                 }
5554 
5555                 /*
5556                  * ASC=0x47 is parity error
5557                  * ASC=0x48 is initiator detected error received
5558                  */
5559                 if ((scsi_sense_key(sensedata) == KEY_ABORTED_COMMAND) &&
5560                     ((scsi_sense_asc(sensedata) == 0x47) ||
5561                     (scsi_sense_asc(sensedata) == 0x48))) {
5562                         mptsas_log(mpt, CE_NOTE, "Aborted_command!");
5563                 }
5564 
5565                 /*
5566                  * ASC/ASCQ=0x3F/0x0E means report_luns data changed
5567                  * ASC/ASCQ=0x25/0x00 means invalid lun
5568                  */
5569                 if (((scsi_sense_key(sensedata) == KEY_UNIT_ATTENTION) &&
5570                     (scsi_sense_asc(sensedata) == 0x3F) &&
5571                     (scsi_sense_ascq(sensedata) == 0x0E)) ||
5572                     ((scsi_sense_key(sensedata) == KEY_ILLEGAL_REQUEST) &&
5573                     (scsi_sense_asc(sensedata) == 0x25) &&
5574                     (scsi_sense_ascq(sensedata) == 0x00))) {
5575                         mptsas_topo_change_list_t *topo_node = NULL;
5576 
5577                         topo_node = kmem_zalloc(
5578                             sizeof (mptsas_topo_change_list_t),
5579                             KM_NOSLEEP);
5580                         if (topo_node == NULL) {
5581                                 mptsas_log(mpt, CE_NOTE, "No memory"
5582                                     "resource for handle SAS dynamic"
5583                                     "reconfigure.\n");
5584                                 break;
5585                         }
5586                         topo_node->mpt = mpt;
5587                         topo_node->event = MPTSAS_DR_EVENT_RECONFIG_TARGET;
5588                         topo_node->un.phymask = ptgt->m_addr.mta_phymask;
5589                         topo_node->devhdl = ptgt->m_devhdl;
5590                         topo_node->object = (void *)ptgt;
5591                         topo_node->flags = MPTSAS_TOPO_FLAG_LUN_ASSOCIATED;
5592 
5593                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
5594                             mptsas_handle_dr,
5595                             (void *)topo_node,
5596                             DDI_NOSLEEP)) != DDI_SUCCESS) {
5597                                 kmem_free(topo_node,
5598                                     sizeof (mptsas_topo_change_list_t));
5599                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq"
5600                                     "for handle SAS dynamic reconfigure"
5601                                     "failed. \n");
5602                         }
5603                 }
5604                 break;
5605         case MPI2_SCSI_STATUS_GOOD:
5606                 switch (ioc_status & MPI2_IOCSTATUS_MASK) {
5607                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
5608                         pkt->pkt_reason = CMD_DEV_GONE;
5609                         pkt->pkt_state |= STATE_GOT_BUS;
5610                         if (ptgt->m_reset_delay == 0) {
5611                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5612                         }
5613                         NDBG31(("lost disk for target%d, command:%x",
5614                             Tgt(cmd), pkt->pkt_cdbp[0]));
5615                         break;
5616                 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
5617                         NDBG31(("data overrun: xferred=%d", xferred));
5618                         NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5619                         pkt->pkt_reason = CMD_DATA_OVR;
5620                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5621                             | STATE_SENT_CMD | STATE_GOT_STATUS
5622                             | STATE_XFERRED_DATA);
5623                         pkt->pkt_resid = 0;
5624                         break;
5625                 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
5626                 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
5627                         NDBG31(("data underrun: xferred=%d", xferred));
5628                         NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5629                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5630                             | STATE_SENT_CMD | STATE_GOT_STATUS);
5631                         pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5632                         if (pkt->pkt_resid != cmd->cmd_dmacount) {
5633                                 pkt->pkt_state |= STATE_XFERRED_DATA;
5634                         }
5635                         break;
5636                 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
5637                         if (cmd->cmd_active_expiration <= gethrtime()) {
5638                                 /*
5639                                  * When timeout requested, propagate
5640                                  * proper reason and statistics to
5641                                  * target drivers.
5642                                  */
5643                                 mptsas_set_pkt_reason(mpt, cmd, CMD_TIMEOUT,
5644                                     STAT_BUS_RESET | STAT_TIMEOUT);
5645                         } else {
5646                                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
5647                                     STAT_BUS_RESET);
5648                         }
5649                         break;
5650                 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
5651                 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
5652                         mptsas_set_pkt_reason(mpt,
5653                             cmd, CMD_RESET, STAT_DEV_RESET);
5654                         break;
5655                 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
5656                 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
5657                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET);
5658                         mptsas_set_pkt_reason(mpt,
5659                             cmd, CMD_TERMINATED, STAT_TERMINATED);
5660                         break;
5661                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
5662                 case MPI2_IOCSTATUS_BUSY:
5663                         /*
5664                          * set throttles to drain
5665                          */
5666                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
5667                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
5668                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5669                         }
5670 
5671                         /*
5672                          * retry command
5673                          */
5674                         cmd->cmd_flags |= CFLAG_RETRY;
5675                         cmd->cmd_pkt_flags |= FLAG_HEAD;
5676 
5677                         (void) mptsas_accept_pkt(mpt, cmd);
5678                         break;
5679                 default:
5680                         mptsas_log(mpt, CE_WARN,
5681                             "unknown ioc_status = %x\n", ioc_status);
5682                         mptsas_log(mpt, CE_CONT, "scsi_state = %x, transfer "
5683                             "count = %x, scsi_status = %x", scsi_state,
5684                             xferred, scsi_status);
5685                         break;
5686                 }
5687                 break;
5688         case MPI2_SCSI_STATUS_TASK_SET_FULL:
5689                 mptsas_handle_qfull(mpt, cmd);
5690                 break;
5691         case MPI2_SCSI_STATUS_BUSY:
5692                 NDBG31(("scsi_status busy received"));
5693                 break;
5694         case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
5695                 NDBG31(("scsi_status reservation conflict received"));
5696                 break;
5697         default:
5698                 mptsas_log(mpt, CE_WARN, "scsi_status=%x, ioc_status=%x\n",
5699                     scsi_status, ioc_status);
5700                 mptsas_log(mpt, CE_WARN,
5701                     "mptsas_process_intr: invalid scsi status\n");
5702                 break;
5703         }
5704 }
5705 
5706 static void
5707 mptsas_check_task_mgt(mptsas_t *mpt, pMpi2SCSIManagementReply_t reply,
5708         mptsas_cmd_t *cmd)
5709 {
5710         uint8_t         task_type;
5711         uint16_t        ioc_status;
5712         uint32_t        log_info;
5713         uint16_t        dev_handle;
5714         struct scsi_pkt *pkt = CMD2PKT(cmd);
5715 
5716         task_type = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->TaskType);
5717         ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5718         log_info = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->IOCLogInfo);
5719         dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->DevHandle);
5720 
5721         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5722                 mptsas_log(mpt, CE_WARN, "mptsas_check_task_mgt: Task 0x%x "
5723                     "failed. IOCStatus=0x%x IOCLogInfo=0x%x target=%d\n",
5724                     task_type, ioc_status, log_info, dev_handle);
5725                 pkt->pkt_reason = CMD_INCOMPLETE;
5726                 return;
5727         }
5728 
5729         switch (task_type) {
5730         case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
5731         case MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
5732         case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
5733         case MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA:
5734         case MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET:
5735         case MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION:
5736                 break;
5737         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
5738         case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
5739         case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
5740                 /*
5741                  * Check for invalid DevHandle of 0 in case application
5742                  * sends bad command.  DevHandle of 0 could cause problems.
5743                  */
5744                 if (dev_handle == 0) {
5745                         mptsas_log(mpt, CE_WARN, "!Can't flush target with"
5746                             " DevHandle of 0.");
5747                 } else {
5748                         mptsas_flush_target(mpt, dev_handle, Lun(cmd),
5749                             task_type);
5750                 }
5751                 break;
5752         default:
5753                 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
5754                     task_type);
5755                 mptsas_log(mpt, CE_WARN, "ioc status = %x", ioc_status);
5756                 break;
5757         }
5758 }
5759 
5760 static void
5761 mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg)
5762 {
5763         mptsas_t                        *mpt = arg->mpt;
5764         uint64_t                        t = arg->t;
5765         mptsas_cmd_t                    *cmd;
5766         struct scsi_pkt                 *pkt;
5767         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
5768 
5769         mutex_enter(&item->mutex);
5770         while (item->flag & MPTSAS_DONEQ_THREAD_ACTIVE) {
5771                 if (!item->doneq) {
5772                         cv_wait(&item->cv, &item->mutex);
5773                 }
5774                 pkt = NULL;
5775                 if ((cmd = mptsas_doneq_thread_rm(mpt, t)) != NULL) {
5776                         cmd->cmd_flags |= CFLAG_COMPLETED;
5777                         pkt = CMD2PKT(cmd);
5778                 }
5779                 mutex_exit(&item->mutex);
5780                 if (pkt) {
5781                         mptsas_pkt_comp(pkt, cmd);
5782                 }
5783                 mutex_enter(&item->mutex);
5784         }
5785         mutex_exit(&item->mutex);
5786         mutex_enter(&mpt->m_doneq_mutex);
5787         mpt->m_doneq_thread_n--;
5788         cv_broadcast(&mpt->m_doneq_thread_cv);
5789         mutex_exit(&mpt->m_doneq_mutex);
5790 }
5791 
5792 
5793 /*
5794  * mpt interrupt handler.
5795  */
5796 static uint_t
5797 mptsas_intr(caddr_t arg1, caddr_t arg2)
5798 {
5799         mptsas_t                        *mpt = (void *)arg1;
5800         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
5801         uchar_t                         did_reply = FALSE;
5802 
5803         NDBG1(("mptsas_intr: arg1 0x%p arg2 0x%p", (void *)arg1, (void *)arg2));
5804 
5805         mutex_enter(&mpt->m_mutex);
5806 
5807         /*
5808          * If interrupts are shared by two channels then check whether this
5809          * interrupt is genuinely for this channel by making sure first the
5810          * chip is in high power state.
5811          */
5812         if ((mpt->m_options & MPTSAS_OPT_PM) &&
5813             (mpt->m_power_level != PM_LEVEL_D0)) {
5814                 mutex_exit(&mpt->m_mutex);
5815                 return (DDI_INTR_UNCLAIMED);
5816         }
5817 
5818         /*
5819          * If polling, interrupt was triggered by some shared interrupt because
5820          * IOC interrupts are disabled during polling, so polling routine will
5821          * handle any replies.  Considering this, if polling is happening,
5822          * return with interrupt unclaimed.
5823          */
5824         if (mpt->m_polled_intr) {
5825                 mutex_exit(&mpt->m_mutex);
5826                 mptsas_log(mpt, CE_WARN, "mpt_sas: Unclaimed interrupt");
5827                 return (DDI_INTR_UNCLAIMED);
5828         }
5829 
5830         /*
5831          * Read the istat register.
5832          */
5833         if ((INTPENDING(mpt)) != 0) {
5834                 /*
5835                  * read fifo until empty.
5836                  */
5837 #ifndef __lock_lint
5838                 _NOTE(CONSTCOND)
5839 #endif
5840                 while (TRUE) {
5841                         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5842                             DDI_DMA_SYNC_FORCPU);
5843                         reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
5844                             MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
5845 
5846                         if (ddi_get32(mpt->m_acc_post_queue_hdl,
5847                             &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
5848                             ddi_get32(mpt->m_acc_post_queue_hdl,
5849                             &reply_desc_union->Words.High) == 0xFFFFFFFF) {
5850                                 break;
5851                         }
5852 
5853                         /*
5854                          * The reply is valid, process it according to its
5855                          * type.  Also, set a flag for updating the reply index
5856                          * after they've all been processed.
5857                          */
5858                         did_reply = TRUE;
5859 
5860                         mptsas_process_intr(mpt, reply_desc_union);
5861 
5862                         /*
5863                          * Increment post index and roll over if needed.
5864                          */
5865                         if (++mpt->m_post_index == mpt->m_post_queue_depth) {
5866                                 mpt->m_post_index = 0;
5867                         }
5868                 }
5869 
5870                 /*
5871                  * Update the global reply index if at least one reply was
5872                  * processed.
5873                  */
5874                 if (did_reply) {
5875                         ddi_put32(mpt->m_datap,
5876                             &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
5877                 }
5878         } else {
5879                 mutex_exit(&mpt->m_mutex);
5880                 return (DDI_INTR_UNCLAIMED);
5881         }
5882         NDBG1(("mptsas_intr complete"));
5883 
5884         /*
5885          * If no helper threads are created, process the doneq in ISR. If
5886          * helpers are created, use the doneq length as a metric to measure the
5887          * load on the interrupt CPU. If it is long enough, which indicates the
5888          * load is heavy, then we deliver the IO completions to the helpers.
5889          * This measurement has some limitations, although it is simple and
5890          * straightforward and works well for most of the cases at present.
5891          */
5892         if (!mpt->m_doneq_thread_n ||
5893             (mpt->m_doneq_len <= mpt->m_doneq_length_threshold)) {
5894                 mptsas_doneq_empty(mpt);
5895         } else {
5896                 mptsas_deliver_doneq_thread(mpt);
5897         }
5898 
5899         /*
5900          * If there are queued cmd, start them now.
5901          */
5902         if (mpt->m_waitq != NULL) {
5903                 mptsas_restart_waitq(mpt);
5904         }
5905 
5906         mutex_exit(&mpt->m_mutex);
5907         return (DDI_INTR_CLAIMED);
5908 }
5909 
5910 static void
5911 mptsas_process_intr(mptsas_t *mpt,
5912     pMpi2ReplyDescriptorsUnion_t reply_desc_union)
5913 {
5914         uint8_t reply_type;
5915 
5916         ASSERT(mutex_owned(&mpt->m_mutex));
5917 
5918         /*
5919          * The reply is valid, process it according to its
5920          * type.  Also, set a flag for updated the reply index
5921          * after they've all been processed.
5922          */
5923         reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
5924             &reply_desc_union->Default.ReplyFlags);
5925         reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
5926         if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS ||
5927             reply_type == MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS) {
5928                 mptsas_handle_scsi_io_success(mpt, reply_desc_union);
5929         } else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
5930                 mptsas_handle_address_reply(mpt, reply_desc_union);
5931         } else {
5932                 mptsas_log(mpt, CE_WARN, "?Bad reply type %x", reply_type);
5933                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5934         }
5935 
5936         /*
5937          * Clear the reply descriptor for re-use and increment
5938          * index.
5939          */
5940         ddi_put64(mpt->m_acc_post_queue_hdl,
5941             &((uint64_t *)(void *)mpt->m_post_queue)[mpt->m_post_index],
5942             0xFFFFFFFFFFFFFFFF);
5943         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5944             DDI_DMA_SYNC_FORDEV);
5945 }
5946 
5947 /*
5948  * handle qfull condition
5949  */
5950 static void
5951 mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd)
5952 {
5953         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
5954 
5955         if ((++cmd->cmd_qfull_retries > ptgt->m_qfull_retries) ||
5956             (ptgt->m_qfull_retries == 0)) {
5957                 /*
5958                  * We have exhausted the retries on QFULL, or,
5959                  * the target driver has indicated that it
5960                  * wants to handle QFULL itself by setting
5961                  * qfull-retries capability to 0. In either case
5962                  * we want the target driver's QFULL handling
5963                  * to kick in. We do this by having pkt_reason
5964                  * as CMD_CMPLT and pkt_scbp as STATUS_QFULL.
5965                  */
5966                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5967         } else {
5968                 if (ptgt->m_reset_delay == 0) {
5969                         ptgt->m_t_throttle =
5970                             max((ptgt->m_t_ncmds - 2), 0);
5971                 }
5972 
5973                 cmd->cmd_pkt_flags |= FLAG_HEAD;
5974                 cmd->cmd_flags &= ~(CFLAG_TRANFLAG);
5975                 cmd->cmd_flags |= CFLAG_RETRY;
5976 
5977                 (void) mptsas_accept_pkt(mpt, cmd);
5978 
5979                 /*
5980                  * when target gives queue full status with no commands
5981                  * outstanding (m_t_ncmds == 0), throttle is set to 0
5982                  * (HOLD_THROTTLE), and the queue full handling start
5983                  * (see psarc/1994/313); if there are commands outstanding,
5984                  * throttle is set to (m_t_ncmds - 2)
5985                  */
5986                 if (ptgt->m_t_throttle == HOLD_THROTTLE) {
5987                         /*
5988                          * By setting throttle to QFULL_THROTTLE, we
5989                          * avoid submitting new commands and in
5990                          * mptsas_restart_cmd find out slots which need
5991                          * their throttles to be cleared.
5992                          */
5993                         mptsas_set_throttle(mpt, ptgt, QFULL_THROTTLE);
5994                         if (mpt->m_restart_cmd_timeid == 0) {
5995                                 mpt->m_restart_cmd_timeid =
5996                                     timeout(mptsas_restart_cmd, mpt,
5997                                     ptgt->m_qfull_retry_interval);
5998                         }
5999                 }
6000         }
6001 }
6002 
6003 mptsas_phymask_t
6004 mptsas_physport_to_phymask(mptsas_t *mpt, uint8_t physport)
6005 {
6006         mptsas_phymask_t        phy_mask = 0;
6007         uint8_t                 i = 0;
6008 
6009         NDBG20(("mptsas%d physport_to_phymask enter", mpt->m_instance));
6010 
6011         ASSERT(mutex_owned(&mpt->m_mutex));
6012 
6013         /*
6014          * If physport is 0xFF, this is a RAID volume.  Use phymask of 0.
6015          */
6016         if (physport == 0xFF) {
6017                 return (0);
6018         }
6019 
6020         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
6021                 if (mpt->m_phy_info[i].attached_devhdl &&
6022                     (mpt->m_phy_info[i].phy_mask != 0) &&
6023                     (mpt->m_phy_info[i].port_num == physport)) {
6024                         phy_mask = mpt->m_phy_info[i].phy_mask;
6025                         break;
6026                 }
6027         }
6028         NDBG20(("mptsas%d physport_to_phymask:physport :%x phymask :%x, ",
6029             mpt->m_instance, physport, phy_mask));
6030         return (phy_mask);
6031 }
6032 
6033 /*
6034  * mpt free device handle after device gone, by use of passthrough
6035  */
6036 static int
6037 mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl)
6038 {
6039         Mpi2SasIoUnitControlRequest_t   req;
6040         Mpi2SasIoUnitControlReply_t     rep;
6041         int                             ret;
6042 
6043         ASSERT(mutex_owned(&mpt->m_mutex));
6044 
6045         /*
6046          * Need to compose a SAS IO Unit Control request message
6047          * and call mptsas_do_passthru() function
6048          */
6049         bzero(&req, sizeof (req));
6050         bzero(&rep, sizeof (rep));
6051 
6052         req.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
6053         req.Operation = MPI2_SAS_OP_REMOVE_DEVICE;
6054         req.DevHandle = LE_16(devhdl);
6055 
6056         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
6057             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
6058         if (ret != 0) {
6059                 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
6060                     "Control error %d", ret);
6061                 return (DDI_FAILURE);
6062         }
6063 
6064         /* do passthrough success, check the ioc status */
6065         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
6066                 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
6067                     "Control IOCStatus %d", LE_16(rep.IOCStatus));
6068                 return (DDI_FAILURE);
6069         }
6070 
6071         return (DDI_SUCCESS);
6072 }
6073 
6074 static void
6075 mptsas_update_phymask(mptsas_t *mpt)
6076 {
6077         mptsas_phymask_t mask = 0, phy_mask;
6078         char            *phy_mask_name;
6079         uint8_t         current_port;
6080         int             i, j;
6081 
6082         NDBG20(("mptsas%d update phymask ", mpt->m_instance));
6083 
6084         ASSERT(mutex_owned(&mpt->m_mutex));
6085 
6086         (void) mptsas_get_sas_io_unit_page(mpt);
6087 
6088         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
6089 
6090         for (i = 0; i < mpt->m_num_phys; i++) {
6091                 phy_mask = 0x00;
6092 
6093                 if (mpt->m_phy_info[i].attached_devhdl == 0)
6094                         continue;
6095 
6096                 bzero(phy_mask_name, sizeof (phy_mask_name));
6097 
6098                 current_port = mpt->m_phy_info[i].port_num;
6099 
6100                 if ((mask & (1 << i)) != 0)
6101                         continue;
6102 
6103                 for (j = 0; j < mpt->m_num_phys; j++) {
6104                         if (mpt->m_phy_info[j].attached_devhdl &&
6105                             (mpt->m_phy_info[j].port_num == current_port)) {
6106                                 phy_mask |= (1 << j);
6107                         }
6108                 }
6109                 mask = mask | phy_mask;
6110 
6111                 for (j = 0; j < mpt->m_num_phys; j++) {
6112                         if ((phy_mask >> j) & 0x01) {
6113                                 mpt->m_phy_info[j].phy_mask = phy_mask;
6114                         }
6115                 }
6116 
6117                 (void) sprintf(phy_mask_name, "%x", phy_mask);
6118 
6119                 mutex_exit(&mpt->m_mutex);
6120                 /*
6121                  * register a iport, if the port has already been existed
6122                  * SCSA will do nothing and just return.
6123                  */
6124                 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
6125                 mutex_enter(&mpt->m_mutex);
6126         }
6127         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
6128         NDBG20(("mptsas%d update phymask return", mpt->m_instance));
6129 }
6130 
6131 /*
6132  * mptsas_handle_dr is a task handler for DR, the DR action includes:
6133  * 1. Directly attched Device Added/Removed.
6134  * 2. Expander Device Added/Removed.
6135  * 3. Indirectly Attached Device Added/Expander.
6136  * 4. LUNs of a existing device status change.
6137  * 5. RAID volume created/deleted.
6138  * 6. Member of RAID volume is released because of RAID deletion.
6139  * 7. Physical disks are removed because of RAID creation.
6140  */
6141 static void
6142 mptsas_handle_dr(void *args) {
6143         mptsas_topo_change_list_t       *topo_node = NULL;
6144         mptsas_topo_change_list_t       *save_node = NULL;
6145         mptsas_t                        *mpt;
6146         dev_info_t                      *parent = NULL;
6147         mptsas_phymask_t                phymask = 0;
6148         char                            *phy_mask_name;
6149         uint8_t                         flags = 0, physport = 0xff;
6150         uint8_t                         port_update = 0;
6151         uint_t                          event;
6152 
6153         topo_node = (mptsas_topo_change_list_t *)args;
6154 
6155         mpt = topo_node->mpt;
6156         event = topo_node->event;
6157         flags = topo_node->flags;
6158 
6159         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
6160 
6161         NDBG20(("mptsas%d handle_dr enter", mpt->m_instance));
6162 
6163         switch (event) {
6164         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
6165                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6166                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE) ||
6167                     (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6168                         /*
6169                          * Direct attached or expander attached device added
6170                          * into system or a Phys Disk that is being unhidden.
6171                          */
6172                         port_update = 1;
6173                 }
6174                 break;
6175         case MPTSAS_DR_EVENT_RECONFIG_SMP:
6176                 /*
6177                  * New expander added into system, it must be the head
6178                  * of topo_change_list_t
6179                  */
6180                 port_update = 1;
6181                 break;
6182         default:
6183                 port_update = 0;
6184                 break;
6185         }
6186         /*
6187          * All cases port_update == 1 may cause initiator port form change
6188          */
6189         mutex_enter(&mpt->m_mutex);
6190         if (mpt->m_port_chng && port_update) {
6191                 /*
6192                  * mpt->m_port_chng flag indicates some PHYs of initiator
6193                  * port have changed to online. So when expander added or
6194                  * directly attached device online event come, we force to
6195                  * update port information by issueing SAS IO Unit Page and
6196                  * update PHYMASKs.
6197                  */
6198                 (void) mptsas_update_phymask(mpt);
6199                 mpt->m_port_chng = 0;
6200 
6201         }
6202         mutex_exit(&mpt->m_mutex);
6203         while (topo_node) {
6204                 phymask = 0;
6205                 if (parent == NULL) {
6206                         physport = topo_node->un.physport;
6207                         event = topo_node->event;
6208                         flags = topo_node->flags;
6209                         if (event & (MPTSAS_DR_EVENT_OFFLINE_TARGET |
6210                             MPTSAS_DR_EVENT_OFFLINE_SMP)) {
6211                                 /*
6212                                  * For all offline events, phymask is known
6213                                  */
6214                                 phymask = topo_node->un.phymask;
6215                                 goto find_parent;
6216                         }
6217                         if (event & MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
6218                                 goto handle_topo_change;
6219                         }
6220                         if (flags & MPTSAS_TOPO_FLAG_LUN_ASSOCIATED) {
6221                                 phymask = topo_node->un.phymask;
6222                                 goto find_parent;
6223                         }
6224 
6225                         if ((flags ==
6226                             MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) &&
6227                             (event == MPTSAS_DR_EVENT_RECONFIG_TARGET)) {
6228                                 /*
6229                                  * There is no any field in IR_CONFIG_CHANGE
6230                                  * event indicate physport/phynum, let's get
6231                                  * parent after SAS Device Page0 request.
6232                                  */
6233                                 goto handle_topo_change;
6234                         }
6235 
6236                         mutex_enter(&mpt->m_mutex);
6237                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6238                                 /*
6239                                  * If the direct attached device added or a
6240                                  * phys disk is being unhidden, argument
6241                                  * physport actually is PHY#, so we have to get
6242                                  * phymask according PHY#.
6243                                  */
6244                                 physport = mpt->m_phy_info[physport].port_num;
6245                         }
6246 
6247                         /*
6248                          * Translate physport to phymask so that we can search
6249                          * parent dip.
6250                          */
6251                         phymask = mptsas_physport_to_phymask(mpt,
6252                             physport);
6253                         mutex_exit(&mpt->m_mutex);
6254 
6255 find_parent:
6256                         bzero(phy_mask_name, MPTSAS_MAX_PHYS);
6257                         /*
6258                          * For RAID topology change node, write the iport name
6259                          * as v0.
6260                          */
6261                         if (flags & MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
6262                                 (void) sprintf(phy_mask_name, "v0");
6263                         } else {
6264                                 /*
6265                                  * phymask can bo 0 if the drive has been
6266                                  * pulled by the time an add event is
6267                                  * processed.  If phymask is 0, just skip this
6268                                  * event and continue.
6269                                  */
6270                                 if (phymask == 0) {
6271                                         mutex_enter(&mpt->m_mutex);
6272                                         save_node = topo_node;
6273                                         topo_node = topo_node->next;
6274                                         ASSERT(save_node);
6275                                         kmem_free(save_node,
6276                                             sizeof (mptsas_topo_change_list_t));
6277                                         mutex_exit(&mpt->m_mutex);
6278 
6279                                         parent = NULL;
6280                                         continue;
6281                                 }
6282                                 (void) sprintf(phy_mask_name, "%x", phymask);
6283                         }
6284                         parent = scsi_hba_iport_find(mpt->m_dip,
6285                             phy_mask_name);
6286                         if (parent == NULL) {
6287                                 mptsas_log(mpt, CE_WARN, "Failed to find an "
6288                                     "iport, should not happen!");
6289                                 goto out;
6290                         }
6291 
6292                 }
6293                 ASSERT(parent);
6294 handle_topo_change:
6295 
6296                 mutex_enter(&mpt->m_mutex);
6297                 /*
6298                  * If HBA is being reset, don't perform operations depending
6299                  * on the IOC. We must free the topo list, however.
6300                  */
6301                 if (!mpt->m_in_reset)
6302                         mptsas_handle_topo_change(topo_node, parent);
6303                 else
6304                         NDBG20(("skipping topo change received during reset"));
6305                 save_node = topo_node;
6306                 topo_node = topo_node->next;
6307                 ASSERT(save_node);
6308                 kmem_free(save_node, sizeof (mptsas_topo_change_list_t));
6309                 mutex_exit(&mpt->m_mutex);
6310 
6311                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6312                     (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) ||
6313                     (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED)) {
6314                         /*
6315                          * If direct attached device associated, make sure
6316                          * reset the parent before start the next one. But
6317                          * all devices associated with expander shares the
6318                          * parent.  Also, reset parent if this is for RAID.
6319                          */
6320                         parent = NULL;
6321                 }
6322         }
6323 out:
6324         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
6325 }
6326 
6327 static void
6328 mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
6329     dev_info_t *parent)
6330 {
6331         mptsas_target_t *ptgt = NULL;
6332         mptsas_smp_t    *psmp = NULL;
6333         mptsas_t        *mpt = (void *)topo_node->mpt;
6334         uint16_t        devhdl;
6335         uint16_t        attached_devhdl;
6336         uint64_t        sas_wwn = 0;
6337         int             rval = 0;
6338         uint32_t        page_address;
6339         uint8_t         phy, flags;
6340         char            *addr = NULL;
6341         dev_info_t      *lundip;
6342         int             circ = 0, circ1 = 0;
6343         char            attached_wwnstr[MPTSAS_WWN_STRLEN];
6344 
6345         NDBG20(("mptsas%d handle_topo_change enter, devhdl 0x%x,"
6346             "event 0x%x, flags 0x%x", mpt->m_instance, topo_node->devhdl,
6347             topo_node->event, topo_node->flags));
6348 
6349         ASSERT(mutex_owned(&mpt->m_mutex));
6350 
6351         switch (topo_node->event) {
6352         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
6353         {
6354                 char *phy_mask_name;
6355                 mptsas_phymask_t phymask = 0;
6356 
6357                 if (topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
6358                         /*
6359                          * Get latest RAID info.
6360                          */
6361                         (void) mptsas_get_raid_info(mpt);
6362                         ptgt = refhash_linear_search(mpt->m_targets,
6363                             mptsas_target_eval_devhdl, &topo_node->devhdl);
6364                         if (ptgt == NULL)
6365                                 break;
6366                 } else {
6367                         ptgt = (void *)topo_node->object;
6368                 }
6369 
6370                 if (ptgt == NULL) {
6371                         /*
6372                          * If a Phys Disk was deleted, RAID info needs to be
6373                          * updated to reflect the new topology.
6374                          */
6375                         (void) mptsas_get_raid_info(mpt);
6376 
6377                         /*
6378                          * Get sas device page 0 by DevHandle to make sure if
6379                          * SSP/SATA end device exist.
6380                          */
6381                         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
6382                             MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
6383                             topo_node->devhdl;
6384 
6385                         rval = mptsas_get_target_device_info(mpt, page_address,
6386                             &devhdl, &ptgt);
6387                         if (rval == DEV_INFO_WRONG_DEVICE_TYPE) {
6388                                 mptsas_log(mpt, CE_NOTE,
6389                                     "mptsas_handle_topo_change: target %d is "
6390                                     "not a SAS/SATA device. \n",
6391                                     topo_node->devhdl);
6392                         } else if (rval == DEV_INFO_FAIL_ALLOC) {
6393                                 mptsas_log(mpt, CE_NOTE,
6394                                     "mptsas_handle_topo_change: could not "
6395                                     "allocate memory. \n");
6396                         }
6397                         /*
6398                          * If rval is DEV_INFO_PHYS_DISK than there is nothing
6399                          * else to do, just leave.
6400                          */
6401                         if (rval != DEV_INFO_SUCCESS) {
6402                                 return;
6403                         }
6404                 }
6405 
6406                 ASSERT(ptgt->m_devhdl == topo_node->devhdl);
6407 
6408                 mutex_exit(&mpt->m_mutex);
6409                 flags = topo_node->flags;
6410 
6411                 if (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) {
6412                         phymask = ptgt->m_addr.mta_phymask;
6413                         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
6414                         (void) sprintf(phy_mask_name, "%x", phymask);
6415                         parent = scsi_hba_iport_find(mpt->m_dip,
6416                             phy_mask_name);
6417                         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
6418                         if (parent == NULL) {
6419                                 mptsas_log(mpt, CE_WARN, "Failed to find a "
6420                                     "iport for PD, should not happen!");
6421                                 mutex_enter(&mpt->m_mutex);
6422                                 break;
6423                         }
6424                 }
6425 
6426                 if (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
6427                         ndi_devi_enter(parent, &circ1);
6428                         (void) mptsas_config_raid(parent, topo_node->devhdl,
6429                             &lundip);
6430                         ndi_devi_exit(parent, circ1);
6431                 } else {
6432                         /*
6433                          * hold nexus for bus configure
6434                          */
6435                         ndi_devi_enter(scsi_vhci_dip, &circ);
6436                         ndi_devi_enter(parent, &circ1);
6437                         rval = mptsas_config_target(parent, ptgt);
6438                         /*
6439                          * release nexus for bus configure
6440                          */
6441                         ndi_devi_exit(parent, circ1);
6442                         ndi_devi_exit(scsi_vhci_dip, circ);
6443 
6444                         /*
6445                          * Add parent's props for SMHBA support
6446                          */
6447                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6448                                 bzero(attached_wwnstr,
6449                                     sizeof (attached_wwnstr));
6450                                 (void) sprintf(attached_wwnstr, "w%016"PRIx64,
6451                                     ptgt->m_addr.mta_wwn);
6452                                 if (ddi_prop_update_string(DDI_DEV_T_NONE,
6453                                     parent,
6454                                     SCSI_ADDR_PROP_ATTACHED_PORT,
6455                                     attached_wwnstr)
6456                                     != DDI_PROP_SUCCESS) {
6457                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6458                                             parent,
6459                                             SCSI_ADDR_PROP_ATTACHED_PORT);
6460                                         mptsas_log(mpt, CE_WARN, "Failed to"
6461                                             "attached-port props");
6462                                         return;
6463                                 }
6464                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6465                                     MPTSAS_NUM_PHYS, 1) !=
6466                                     DDI_PROP_SUCCESS) {
6467                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6468                                             parent, MPTSAS_NUM_PHYS);
6469                                         mptsas_log(mpt, CE_WARN, "Failed to"
6470                                             " create num-phys props");
6471                                         return;
6472                                 }
6473 
6474                                 /*
6475                                  * Update PHY info for smhba
6476                                  */
6477                                 mutex_enter(&mpt->m_mutex);
6478                                 if (mptsas_smhba_phy_init(mpt)) {
6479                                         mutex_exit(&mpt->m_mutex);
6480                                         mptsas_log(mpt, CE_WARN, "mptsas phy"
6481                                             " update failed");
6482                                         return;
6483                                 }
6484                                 mutex_exit(&mpt->m_mutex);
6485 
6486                                 /*
6487                                  * topo_node->un.physport is really the PHY#
6488                                  * for direct attached devices
6489                                  */
6490                                 mptsas_smhba_set_one_phy_props(mpt, parent,
6491                                     topo_node->un.physport, &attached_devhdl);
6492 
6493                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6494                                     MPTSAS_VIRTUAL_PORT, 0) !=
6495                                     DDI_PROP_SUCCESS) {
6496                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6497                                             parent, MPTSAS_VIRTUAL_PORT);
6498                                         mptsas_log(mpt, CE_WARN,
6499                                             "mptsas virtual-port"
6500                                             "port prop update failed");
6501                                         return;
6502                                 }
6503                         }
6504                 }
6505                 mutex_enter(&mpt->m_mutex);
6506 
6507                 NDBG20(("mptsas%d handle_topo_change to online devhdl:%x, "
6508                     "phymask:%x.", mpt->m_instance, ptgt->m_devhdl,
6509                     ptgt->m_addr.mta_phymask));
6510                 break;
6511         }
6512         case MPTSAS_DR_EVENT_OFFLINE_TARGET:
6513         {
6514                 devhdl = topo_node->devhdl;
6515                 ptgt = refhash_linear_search(mpt->m_targets,
6516                     mptsas_target_eval_devhdl, &devhdl);
6517                 if (ptgt == NULL)
6518                         break;
6519 
6520                 sas_wwn = ptgt->m_addr.mta_wwn;
6521                 phy = ptgt->m_phynum;
6522 
6523                 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
6524 
6525                 if (sas_wwn) {
6526                         (void) sprintf(addr, "w%016"PRIx64, sas_wwn);
6527                 } else {
6528                         (void) sprintf(addr, "p%x", phy);
6529                 }
6530                 ASSERT(ptgt->m_devhdl == devhdl);
6531 
6532                 if ((topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) ||
6533                     (topo_node->flags ==
6534                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6535                         /*
6536                          * Get latest RAID info if RAID volume status changes
6537                          * or Phys Disk status changes
6538                          */
6539                         (void) mptsas_get_raid_info(mpt);
6540                 }
6541                 /*
6542                  * Abort all outstanding command on the device
6543                  */
6544                 rval = mptsas_do_scsi_reset(mpt, devhdl);
6545                 if (rval) {
6546                         NDBG20(("mptsas%d handle_topo_change to reset target "
6547                             "before offline devhdl:%x, phymask:%x, rval:%x",
6548                             mpt->m_instance, ptgt->m_devhdl,
6549                             ptgt->m_addr.mta_phymask, rval));
6550                 }
6551 
6552                 mutex_exit(&mpt->m_mutex);
6553 
6554                 ndi_devi_enter(scsi_vhci_dip, &circ);
6555                 ndi_devi_enter(parent, &circ1);
6556                 rval = mptsas_offline_target(parent, addr);
6557                 ndi_devi_exit(parent, circ1);
6558                 ndi_devi_exit(scsi_vhci_dip, circ);
6559                 NDBG20(("mptsas%d handle_topo_change to offline devhdl:%x, "
6560                     "phymask:%x, rval:%x", mpt->m_instance,
6561                     ptgt->m_devhdl, ptgt->m_addr.mta_phymask, rval));
6562 
6563                 kmem_free(addr, SCSI_MAXNAMELEN);
6564 
6565                 /*
6566                  * Clear parent's props for SMHBA support
6567                  */
6568                 flags = topo_node->flags;
6569                 if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6570                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6571                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6572                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6573                             DDI_PROP_SUCCESS) {
6574                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6575                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6576                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6577                                     "prop update failed");
6578                                 break;
6579                         }
6580                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6581                             MPTSAS_NUM_PHYS, 0) !=
6582                             DDI_PROP_SUCCESS) {
6583                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6584                                     MPTSAS_NUM_PHYS);
6585                                 mptsas_log(mpt, CE_WARN, "mptsas num phys "
6586                                     "prop update failed");
6587                                 break;
6588                         }
6589                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6590                             MPTSAS_VIRTUAL_PORT, 1) !=
6591                             DDI_PROP_SUCCESS) {
6592                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6593                                     MPTSAS_VIRTUAL_PORT);
6594                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6595                                     "prop update failed");
6596                                 break;
6597                         }
6598                 }
6599 
6600                 mutex_enter(&mpt->m_mutex);
6601                 ptgt->m_led_status = 0;
6602                 (void) mptsas_flush_led_status(mpt, ptgt);
6603                 if (rval == DDI_SUCCESS) {
6604                         refhash_remove(mpt->m_targets, ptgt);
6605                         ptgt = NULL;
6606                 } else {
6607                         /*
6608                          * clean DR_INTRANSITION flag to allow I/O down to
6609                          * PHCI driver since failover finished.
6610                          * Invalidate the devhdl
6611                          */
6612                         ptgt->m_devhdl = MPTSAS_INVALID_DEVHDL;
6613                         ptgt->m_tgt_unconfigured = 0;
6614                         mutex_enter(&mpt->m_tx_waitq_mutex);
6615                         ptgt->m_dr_flag = MPTSAS_DR_INACTIVE;
6616                         mutex_exit(&mpt->m_tx_waitq_mutex);
6617                 }
6618 
6619                 /*
6620                  * Send SAS IO Unit Control to free the dev handle
6621                  */
6622                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6623                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE)) {
6624                         rval = mptsas_free_devhdl(mpt, devhdl);
6625 
6626                         NDBG20(("mptsas%d handle_topo_change to remove "
6627                             "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6628                             rval));
6629                 }
6630 
6631                 break;
6632         }
6633         case MPTSAS_TOPO_FLAG_REMOVE_HANDLE:
6634         {
6635                 devhdl = topo_node->devhdl;
6636                 /*
6637                  * If this is the remove handle event, do a reset first.
6638                  */
6639                 if (topo_node->event == MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
6640                         rval = mptsas_do_scsi_reset(mpt, devhdl);
6641                         if (rval) {
6642                                 NDBG20(("mpt%d reset target before remove "
6643                                     "devhdl:%x, rval:%x", mpt->m_instance,
6644                                     devhdl, rval));
6645                         }
6646                 }
6647 
6648                 /*
6649                  * Send SAS IO Unit Control to free the dev handle
6650                  */
6651                 rval = mptsas_free_devhdl(mpt, devhdl);
6652                 NDBG20(("mptsas%d handle_topo_change to remove "
6653                     "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6654                     rval));
6655                 break;
6656         }
6657         case MPTSAS_DR_EVENT_RECONFIG_SMP:
6658         {
6659                 mptsas_smp_t smp;
6660                 dev_info_t *smpdip;
6661 
6662                 devhdl = topo_node->devhdl;
6663 
6664                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
6665                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)devhdl;
6666                 rval = mptsas_get_sas_expander_page0(mpt, page_address, &smp);
6667                 if (rval != DDI_SUCCESS) {
6668                         mptsas_log(mpt, CE_WARN, "failed to online smp, "
6669                             "handle %x", devhdl);
6670                         return;
6671                 }
6672 
6673                 psmp = mptsas_smp_alloc(mpt, &smp);
6674                 if (psmp == NULL) {
6675                         return;
6676                 }
6677 
6678                 mutex_exit(&mpt->m_mutex);
6679                 ndi_devi_enter(parent, &circ1);
6680                 (void) mptsas_online_smp(parent, psmp, &smpdip);
6681                 ndi_devi_exit(parent, circ1);
6682 
6683                 mutex_enter(&mpt->m_mutex);
6684                 break;
6685         }
6686         case MPTSAS_DR_EVENT_OFFLINE_SMP:
6687         {
6688                 devhdl = topo_node->devhdl;
6689                 uint32_t dev_info;
6690 
6691                 psmp = refhash_linear_search(mpt->m_smp_targets,
6692                     mptsas_smp_eval_devhdl, &devhdl);
6693                 if (psmp == NULL)
6694                         break;
6695                 /*
6696                  * The mptsas_smp_t data is released only if the dip is offlined
6697                  * successfully.
6698                  */
6699                 mutex_exit(&mpt->m_mutex);
6700 
6701                 ndi_devi_enter(parent, &circ1);
6702                 rval = mptsas_offline_smp(parent, psmp, NDI_DEVI_REMOVE);
6703                 ndi_devi_exit(parent, circ1);
6704 
6705                 dev_info = psmp->m_deviceinfo;
6706                 if ((dev_info & DEVINFO_DIRECT_ATTACHED) ==
6707                     DEVINFO_DIRECT_ATTACHED) {
6708                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6709                             MPTSAS_VIRTUAL_PORT, 1) !=
6710                             DDI_PROP_SUCCESS) {
6711                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6712                                     MPTSAS_VIRTUAL_PORT);
6713                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6714                                     "prop update failed");
6715                                 return;
6716                         }
6717                         /*
6718                          * Check whether the smp connected to the iport,
6719                          */
6720                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6721                             MPTSAS_NUM_PHYS, 0) !=
6722                             DDI_PROP_SUCCESS) {
6723                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6724                                     MPTSAS_NUM_PHYS);
6725                                 mptsas_log(mpt, CE_WARN, "mptsas num phys"
6726                                     "prop update failed");
6727                                 return;
6728                         }
6729                         /*
6730                          * Clear parent's attached-port props
6731                          */
6732                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6733                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6734                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6735                             DDI_PROP_SUCCESS) {
6736                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6737                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6738                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6739                                     "prop update failed");
6740                                 return;
6741                         }
6742                 }
6743 
6744                 mutex_enter(&mpt->m_mutex);
6745                 NDBG20(("mptsas%d handle_topo_change to remove devhdl:%x, "
6746                     "rval:%x", mpt->m_instance, psmp->m_devhdl, rval));
6747                 if (rval == DDI_SUCCESS) {
6748                         refhash_remove(mpt->m_smp_targets, psmp);
6749                 } else {
6750                         psmp->m_devhdl = MPTSAS_INVALID_DEVHDL;
6751                 }
6752 
6753                 bzero(attached_wwnstr, sizeof (attached_wwnstr));
6754 
6755                 break;
6756         }
6757         default:
6758                 return;
6759         }
6760 }
6761 
6762 /*
6763  * Record the event if its type is enabled in mpt instance by ioctl.
6764  */
6765 static void
6766 mptsas_record_event(void *args)
6767 {
6768         m_replyh_arg_t                  *replyh_arg;
6769         pMpi2EventNotificationReply_t   eventreply;
6770         uint32_t                        event, rfm;
6771         mptsas_t                        *mpt;
6772         int                             i, j;
6773         uint16_t                        event_data_len;
6774         boolean_t                       sendAEN = FALSE;
6775 
6776         replyh_arg = (m_replyh_arg_t *)args;
6777         rfm = replyh_arg->rfm;
6778         mpt = replyh_arg->mpt;
6779 
6780         eventreply = (pMpi2EventNotificationReply_t)
6781             (mpt->m_reply_frame + (rfm -
6782             (mpt->m_reply_frame_dma_addr & 0xffffffffu)));
6783         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6784 
6785 
6786         /*
6787          * Generate a system event to let anyone who cares know that a
6788          * LOG_ENTRY_ADDED event has occurred.  This is sent no matter what the
6789          * event mask is set to.
6790          */
6791         if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
6792                 sendAEN = TRUE;
6793         }
6794 
6795         /*
6796          * Record the event only if it is not masked.  Determine which dword
6797          * and bit of event mask to test.
6798          */
6799         i = (uint8_t)(event / 32);
6800         j = (uint8_t)(event % 32);
6801         if ((i < 4) && ((1 << j) & mpt->m_event_mask[i])) {
6802                 i = mpt->m_event_index;
6803                 mpt->m_events[i].Type = event;
6804                 mpt->m_events[i].Number = ++mpt->m_event_number;
6805                 bzero(mpt->m_events[i].Data, MPTSAS_MAX_EVENT_DATA_LENGTH * 4);
6806                 event_data_len = ddi_get16(mpt->m_acc_reply_frame_hdl,
6807                     &eventreply->EventDataLength);
6808 
6809                 if (event_data_len > 0) {
6810                         /*
6811                          * Limit data to size in m_event entry
6812                          */
6813                         if (event_data_len > MPTSAS_MAX_EVENT_DATA_LENGTH) {
6814                                 event_data_len = MPTSAS_MAX_EVENT_DATA_LENGTH;
6815                         }
6816                         for (j = 0; j < event_data_len; j++) {
6817                                 mpt->m_events[i].Data[j] =
6818                                     ddi_get32(mpt->m_acc_reply_frame_hdl,
6819                                     &(eventreply->EventData[j]));
6820                         }
6821 
6822                         /*
6823                          * check for index wrap-around
6824                          */
6825                         if (++i == MPTSAS_EVENT_QUEUE_SIZE) {
6826                                 i = 0;
6827                         }
6828                         mpt->m_event_index = (uint8_t)i;
6829 
6830                         /*
6831                          * Set flag to send the event.
6832                          */
6833                         sendAEN = TRUE;
6834                 }
6835         }
6836 
6837         /*
6838          * Generate a system event if flag is set to let anyone who cares know
6839          * that an event has occurred.
6840          */
6841         if (sendAEN) {
6842                 (void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS",
6843                     "SAS", NULL, NULL, DDI_NOSLEEP);
6844         }
6845 }
6846 
6847 #define SMP_RESET_IN_PROGRESS MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS
6848 /*
6849  * handle sync events from ioc in interrupt
6850  * return value:
6851  * DDI_SUCCESS: The event is handled by this func
6852  * DDI_FAILURE: Event is not handled
6853  */
6854 static int
6855 mptsas_handle_event_sync(void *args)
6856 {
6857         m_replyh_arg_t                  *replyh_arg;
6858         pMpi2EventNotificationReply_t   eventreply;
6859         uint32_t                        event, rfm;
6860         mptsas_t                        *mpt;
6861         uint_t                          iocstatus;
6862 
6863         replyh_arg = (m_replyh_arg_t *)args;
6864         rfm = replyh_arg->rfm;
6865         mpt = replyh_arg->mpt;
6866 
6867         ASSERT(mutex_owned(&mpt->m_mutex));
6868 
6869         eventreply = (pMpi2EventNotificationReply_t)
6870             (mpt->m_reply_frame + (rfm -
6871             (mpt->m_reply_frame_dma_addr & 0xffffffffu)));
6872         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6873 
6874         if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
6875             &eventreply->IOCStatus)) {
6876                 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
6877                         mptsas_log(mpt, CE_WARN,
6878                             "!mptsas_handle_event_sync: event 0x%x, "
6879                             "IOCStatus=0x%x, "
6880                             "IOCLogInfo=0x%x", event, iocstatus,
6881                             ddi_get32(mpt->m_acc_reply_frame_hdl,
6882                             &eventreply->IOCLogInfo));
6883                 } else {
6884                         mptsas_log(mpt, CE_WARN,
6885                             "mptsas_handle_event_sync: event 0x%x, "
6886                             "IOCStatus=0x%x, "
6887                             "(IOCLogInfo=0x%x)", event, iocstatus,
6888                             ddi_get32(mpt->m_acc_reply_frame_hdl,
6889                             &eventreply->IOCLogInfo));
6890                 }
6891         }
6892 
6893         /*
6894          * figure out what kind of event we got and handle accordingly
6895          */
6896         switch (event) {
6897         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
6898         {
6899                 pMpi2EventDataSasTopologyChangeList_t   sas_topo_change_list;
6900                 uint8_t                         num_entries, expstatus, phy;
6901                 uint8_t                         phystatus, physport, state, i;
6902                 uint8_t                         start_phy_num, link_rate;
6903                 uint16_t                        dev_handle, reason_code;
6904                 uint16_t                        enc_handle, expd_handle;
6905                 char                            string[80], curr[80], prev[80];
6906                 mptsas_topo_change_list_t       *topo_head = NULL;
6907                 mptsas_topo_change_list_t       *topo_tail = NULL;
6908                 mptsas_topo_change_list_t       *topo_node = NULL;
6909                 mptsas_target_t                 *ptgt;
6910                 mptsas_smp_t                    *psmp;
6911                 uint8_t                         flags = 0, exp_flag;
6912                 smhba_info_t                    *pSmhba = NULL;
6913 
6914                 NDBG20(("mptsas_handle_event_sync: SAS topology change"));
6915 
6916                 sas_topo_change_list = (pMpi2EventDataSasTopologyChangeList_t)
6917                     eventreply->EventData;
6918 
6919                 enc_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6920                     &sas_topo_change_list->EnclosureHandle);
6921                 expd_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6922                     &sas_topo_change_list->ExpanderDevHandle);
6923                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6924                     &sas_topo_change_list->NumEntries);
6925                 start_phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
6926                     &sas_topo_change_list->StartPhyNum);
6927                 expstatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6928                     &sas_topo_change_list->ExpStatus);
6929                 physport = ddi_get8(mpt->m_acc_reply_frame_hdl,
6930                     &sas_topo_change_list->PhysicalPort);
6931 
6932                 string[0] = 0;
6933                 if (expd_handle) {
6934                         flags = MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED;
6935                         switch (expstatus) {
6936                         case MPI2_EVENT_SAS_TOPO_ES_ADDED:
6937                                 (void) sprintf(string, " added");
6938                                 /*
6939                                  * New expander device added
6940                                  */
6941                                 mpt->m_port_chng = 1;
6942                                 topo_node = kmem_zalloc(
6943                                     sizeof (mptsas_topo_change_list_t),
6944                                     KM_SLEEP);
6945                                 topo_node->mpt = mpt;
6946                                 topo_node->event = MPTSAS_DR_EVENT_RECONFIG_SMP;
6947                                 topo_node->un.physport = physport;
6948                                 topo_node->devhdl = expd_handle;
6949                                 topo_node->flags = flags;
6950                                 topo_node->object = NULL;
6951                                 if (topo_head == NULL) {
6952                                         topo_head = topo_tail = topo_node;
6953                                 } else {
6954                                         topo_tail->next = topo_node;
6955                                         topo_tail = topo_node;
6956                                 }
6957                                 break;
6958                         case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
6959                                 (void) sprintf(string, " not responding, "
6960                                     "removed");
6961                                 psmp = refhash_linear_search(mpt->m_smp_targets,
6962                                     mptsas_smp_eval_devhdl, &expd_handle);
6963                                 if (psmp == NULL)
6964                                         break;
6965 
6966                                 topo_node = kmem_zalloc(
6967                                     sizeof (mptsas_topo_change_list_t),
6968                                     KM_SLEEP);
6969                                 topo_node->mpt = mpt;
6970                                 topo_node->un.phymask =
6971                                     psmp->m_addr.mta_phymask;
6972                                 topo_node->event = MPTSAS_DR_EVENT_OFFLINE_SMP;
6973                                 topo_node->devhdl = expd_handle;
6974                                 topo_node->flags = flags;
6975                                 topo_node->object = NULL;
6976                                 if (topo_head == NULL) {
6977                                         topo_head = topo_tail = topo_node;
6978                                 } else {
6979                                         topo_tail->next = topo_node;
6980                                         topo_tail = topo_node;
6981                                 }
6982                                 break;
6983                         case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
6984                                 break;
6985                         case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
6986                                 (void) sprintf(string, " not responding, "
6987                                     "delaying removal");
6988                                 break;
6989                         default:
6990                                 break;
6991                         }
6992                 } else {
6993                         flags = MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE;
6994                 }
6995 
6996                 NDBG20(("SAS TOPOLOGY CHANGE for enclosure %x expander %x%s\n",
6997                     enc_handle, expd_handle, string));
6998                 for (i = 0; i < num_entries; i++) {
6999                         phy = i + start_phy_num;
7000                         phystatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
7001                             &sas_topo_change_list->PHY[i].PhyStatus);
7002                         dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7003                             &sas_topo_change_list->PHY[i].AttachedDevHandle);
7004                         reason_code = phystatus & MPI2_EVENT_SAS_TOPO_RC_MASK;
7005                         /*
7006                          * Filter out processing of Phy Vacant Status unless
7007                          * the reason code is "Not Responding".  Process all
7008                          * other combinations of Phy Status and Reason Codes.
7009                          */
7010                         if ((phystatus &
7011                             MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) &&
7012                             (reason_code !=
7013                             MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) {
7014                                 continue;
7015                         }
7016                         curr[0] = 0;
7017                         prev[0] = 0;
7018                         string[0] = 0;
7019                         switch (reason_code) {
7020                         case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
7021                         {
7022                                 NDBG20(("mptsas%d phy %d physical_port %d "
7023                                     "dev_handle %d added", mpt->m_instance, phy,
7024                                     physport, dev_handle));
7025                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
7026                                     &sas_topo_change_list->PHY[i].LinkRate);
7027                                 state = (link_rate &
7028                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
7029                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
7030                                 switch (state) {
7031                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
7032                                         (void) sprintf(curr, "is disabled");
7033                                         break;
7034                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
7035                                         (void) sprintf(curr, "is offline, "
7036                                             "failed speed negotiation");
7037                                         break;
7038                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
7039                                         (void) sprintf(curr, "SATA OOB "
7040                                             "complete");
7041                                         break;
7042                                 case SMP_RESET_IN_PROGRESS:
7043                                         (void) sprintf(curr, "SMP reset in "
7044                                             "progress");
7045                                         break;
7046                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
7047                                         (void) sprintf(curr, "is online at "
7048                                             "1.5 Gbps");
7049                                         break;
7050                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
7051                                         (void) sprintf(curr, "is online at 3.0 "
7052                                             "Gbps");
7053                                         break;
7054                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
7055                                         (void) sprintf(curr, "is online at 6.0 "
7056                                             "Gbps");
7057                                         break;
7058                                 case MPI25_EVENT_SAS_TOPO_LR_RATE_12_0:
7059                                         (void) sprintf(curr,
7060                                             "is online at 12.0 Gbps");
7061                                         break;
7062                                 default:
7063                                         (void) sprintf(curr, "state is "
7064                                             "unknown");
7065                                         break;
7066                                 }
7067                                 /*
7068                                  * New target device added into the system.
7069                                  * Set association flag according to if an
7070                                  * expander is used or not.
7071                                  */
7072                                 exp_flag =
7073                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
7074                                 if (flags ==
7075                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
7076                                         flags = exp_flag;
7077                                 }
7078                                 topo_node = kmem_zalloc(
7079                                     sizeof (mptsas_topo_change_list_t),
7080                                     KM_SLEEP);
7081                                 topo_node->mpt = mpt;
7082                                 topo_node->event =
7083                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
7084                                 if (expd_handle == 0) {
7085                                         /*
7086                                          * Per MPI 2, if expander dev handle
7087                                          * is 0, it's a directly attached
7088                                          * device. So driver use PHY to decide
7089                                          * which iport is associated
7090                                          */
7091                                         physport = phy;
7092                                         mpt->m_port_chng = 1;
7093                                 }
7094                                 topo_node->un.physport = physport;
7095                                 topo_node->devhdl = dev_handle;
7096                                 topo_node->flags = flags;
7097                                 topo_node->object = NULL;
7098                                 if (topo_head == NULL) {
7099                                         topo_head = topo_tail = topo_node;
7100                                 } else {
7101                                         topo_tail->next = topo_node;
7102                                         topo_tail = topo_node;
7103                                 }
7104                                 break;
7105                         }
7106                         case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
7107                         {
7108                                 NDBG20(("mptsas%d phy %d physical_port %d "
7109                                     "dev_handle %d removed", mpt->m_instance,
7110                                     phy, physport, dev_handle));
7111                                 /*
7112                                  * Set association flag according to if an
7113                                  * expander is used or not.
7114                                  */
7115                                 exp_flag =
7116                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
7117                                 if (flags ==
7118                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
7119                                         flags = exp_flag;
7120                                 }
7121                                 /*
7122                                  * Target device is removed from the system
7123                                  * Before the device is really offline from
7124                                  * from system.
7125                                  */
7126                                 ptgt = refhash_linear_search(mpt->m_targets,
7127                                     mptsas_target_eval_devhdl, &dev_handle);
7128                                 /*
7129                                  * If ptgt is NULL here, it means that the
7130                                  * DevHandle is not in the hash table.  This is
7131                                  * reasonable sometimes.  For example, if a
7132                                  * disk was pulled, then added, then pulled
7133                                  * again, the disk will not have been put into
7134                                  * the hash table because the add event will
7135                                  * have an invalid phymask.  BUT, this does not
7136                                  * mean that the DevHandle is invalid.  The
7137                                  * controller will still have a valid DevHandle
7138                                  * that must be removed.  To do this, use the
7139                                  * MPTSAS_TOPO_FLAG_REMOVE_HANDLE event.
7140                                  */
7141                                 if (ptgt == NULL) {
7142                                         topo_node = kmem_zalloc(
7143                                             sizeof (mptsas_topo_change_list_t),
7144                                             KM_SLEEP);
7145                                         topo_node->mpt = mpt;
7146                                         topo_node->un.phymask = 0;
7147                                         topo_node->event =
7148                                             MPTSAS_TOPO_FLAG_REMOVE_HANDLE;
7149                                         topo_node->devhdl = dev_handle;
7150                                         topo_node->flags = flags;
7151                                         topo_node->object = NULL;
7152                                         if (topo_head == NULL) {
7153                                                 topo_head = topo_tail =
7154                                                     topo_node;
7155                                         } else {
7156                                                 topo_tail->next = topo_node;
7157                                                 topo_tail = topo_node;
7158                                         }
7159                                         break;
7160                                 }
7161 
7162                                 /*
7163                                  * Update DR flag immediately avoid I/O failure
7164                                  * before failover finish. Pay attention to the
7165                                  * mutex protect, we need grab m_tx_waitq_mutex
7166                                  * during set m_dr_flag because we won't add
7167                                  * the following command into waitq, instead,
7168                                  * we need return TRAN_BUSY in the tran_start
7169                                  * context.
7170                                  */
7171                                 mutex_enter(&mpt->m_tx_waitq_mutex);
7172                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
7173                                 mutex_exit(&mpt->m_tx_waitq_mutex);
7174 
7175                                 topo_node = kmem_zalloc(
7176                                     sizeof (mptsas_topo_change_list_t),
7177                                     KM_SLEEP);
7178                                 topo_node->mpt = mpt;
7179                                 topo_node->un.phymask =
7180                                     ptgt->m_addr.mta_phymask;
7181                                 topo_node->event =
7182                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7183                                 topo_node->devhdl = dev_handle;
7184                                 topo_node->flags = flags;
7185                                 topo_node->object = NULL;
7186                                 if (topo_head == NULL) {
7187                                         topo_head = topo_tail = topo_node;
7188                                 } else {
7189                                         topo_tail->next = topo_node;
7190                                         topo_tail = topo_node;
7191                                 }
7192                                 break;
7193                         }
7194                         case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
7195                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
7196                                     &sas_topo_change_list->PHY[i].LinkRate);
7197                                 state = (link_rate &
7198                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
7199                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
7200                                 pSmhba = &mpt->m_phy_info[i].smhba_info;
7201                                 pSmhba->negotiated_link_rate = state;
7202                                 switch (state) {
7203                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
7204                                         (void) sprintf(curr, "is disabled");
7205                                         mptsas_smhba_log_sysevent(mpt,
7206                                             ESC_SAS_PHY_EVENT,
7207                                             SAS_PHY_REMOVE,
7208                                             &mpt->m_phy_info[i].smhba_info);
7209                                         mpt->m_phy_info[i].smhba_info.
7210                                             negotiated_link_rate
7211                                             = 0x1;
7212                                         break;
7213                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
7214                                         (void) sprintf(curr, "is offline, "
7215                                             "failed speed negotiation");
7216                                         mptsas_smhba_log_sysevent(mpt,
7217                                             ESC_SAS_PHY_EVENT,
7218                                             SAS_PHY_OFFLINE,
7219                                             &mpt->m_phy_info[i].smhba_info);
7220                                         break;
7221                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
7222                                         (void) sprintf(curr, "SATA OOB "
7223                                             "complete");
7224                                         break;
7225                                 case SMP_RESET_IN_PROGRESS:
7226                                         (void) sprintf(curr, "SMP reset in "
7227                                             "progress");
7228                                         break;
7229                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
7230                                         (void) sprintf(curr, "is online at "
7231                                             "1.5 Gbps");
7232                                         if ((expd_handle == 0) &&
7233                                             (enc_handle == 1)) {
7234                                                 mpt->m_port_chng = 1;
7235                                         }
7236                                         mptsas_smhba_log_sysevent(mpt,
7237                                             ESC_SAS_PHY_EVENT,
7238                                             SAS_PHY_ONLINE,
7239                                             &mpt->m_phy_info[i].smhba_info);
7240                                         break;
7241                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
7242                                         (void) sprintf(curr, "is online at 3.0 "
7243                                             "Gbps");
7244                                         if ((expd_handle == 0) &&
7245                                             (enc_handle == 1)) {
7246                                                 mpt->m_port_chng = 1;
7247                                         }
7248                                         mptsas_smhba_log_sysevent(mpt,
7249                                             ESC_SAS_PHY_EVENT,
7250                                             SAS_PHY_ONLINE,
7251                                             &mpt->m_phy_info[i].smhba_info);
7252                                         break;
7253                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
7254                                         (void) sprintf(curr, "is online at "
7255                                             "6.0 Gbps");
7256                                         if ((expd_handle == 0) &&
7257                                             (enc_handle == 1)) {
7258                                                 mpt->m_port_chng = 1;
7259                                         }
7260                                         mptsas_smhba_log_sysevent(mpt,
7261                                             ESC_SAS_PHY_EVENT,
7262                                             SAS_PHY_ONLINE,
7263                                             &mpt->m_phy_info[i].smhba_info);
7264                                         break;
7265                                 case MPI25_EVENT_SAS_TOPO_LR_RATE_12_0:
7266                                         (void) sprintf(curr, "is online at "
7267                                             "12.0 Gbps");
7268                                         if ((expd_handle == 0) &&
7269                                             (enc_handle == 1)) {
7270                                                 mpt->m_port_chng = 1;
7271                                         }
7272                                         mptsas_smhba_log_sysevent(mpt,
7273                                             ESC_SAS_PHY_EVENT,
7274                                             SAS_PHY_ONLINE,
7275                                             &mpt->m_phy_info[i].smhba_info);
7276                                         break;
7277                                 default:
7278                                         (void) sprintf(curr, "state is "
7279                                             "unknown");
7280                                         break;
7281                                 }
7282 
7283                                 state = (link_rate &
7284                                     MPI2_EVENT_SAS_TOPO_LR_PREV_MASK) >>
7285                                     MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT;
7286                                 switch (state) {
7287                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
7288                                         (void) sprintf(prev, ", was disabled");
7289                                         break;
7290                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
7291                                         (void) sprintf(prev, ", was offline, "
7292                                             "failed speed negotiation");
7293                                         break;
7294                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
7295                                         (void) sprintf(prev, ", was SATA OOB "
7296                                             "complete");
7297                                         break;
7298                                 case SMP_RESET_IN_PROGRESS:
7299                                         (void) sprintf(prev, ", was SMP reset "
7300                                             "in progress");
7301                                         break;
7302                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
7303                                         (void) sprintf(prev, ", was online at "
7304                                             "1.5 Gbps");
7305                                         break;
7306                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
7307                                         (void) sprintf(prev, ", was online at "
7308                                             "3.0 Gbps");
7309                                         break;
7310                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
7311                                         (void) sprintf(prev, ", was online at "
7312                                             "6.0 Gbps");
7313                                         break;
7314                                 case MPI25_EVENT_SAS_TOPO_LR_RATE_12_0:
7315                                         (void) sprintf(prev, ", was online at "
7316                                             "12.0 Gbps");
7317                                         break;
7318                                 default:
7319                                 break;
7320                                 }
7321                                 (void) sprintf(&string[strlen(string)], "link "
7322                                     "changed, ");
7323                                 break;
7324                         case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
7325                                 continue;
7326                         case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
7327                                 (void) sprintf(&string[strlen(string)],
7328                                     "target not responding, delaying "
7329                                     "removal");
7330                                 break;
7331                         }
7332                         NDBG20(("mptsas%d phy %d DevHandle %x, %s%s%s\n",
7333                             mpt->m_instance, phy, dev_handle, string, curr,
7334                             prev));
7335                 }
7336                 if (topo_head != NULL) {
7337                         /*
7338                          * Launch DR taskq to handle topology change
7339                          */
7340                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
7341                             mptsas_handle_dr, (void *)topo_head,
7342                             DDI_NOSLEEP)) != DDI_SUCCESS) {
7343                                 while (topo_head != NULL) {
7344                                         topo_node = topo_head;
7345                                         topo_head = topo_head->next;
7346                                         kmem_free(topo_node,
7347                                             sizeof (mptsas_topo_change_list_t));
7348                                 }
7349                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
7350                                     "for handle SAS DR event failed. \n");
7351                         }
7352                 }
7353                 break;
7354         }
7355         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7356         {
7357                 Mpi2EventDataIrConfigChangeList_t       *irChangeList;
7358                 mptsas_topo_change_list_t               *topo_head = NULL;
7359                 mptsas_topo_change_list_t               *topo_tail = NULL;
7360                 mptsas_topo_change_list_t               *topo_node = NULL;
7361                 mptsas_target_t                         *ptgt;
7362                 uint8_t                                 num_entries, i, reason;
7363                 uint16_t                                volhandle, diskhandle;
7364 
7365                 irChangeList = (pMpi2EventDataIrConfigChangeList_t)
7366                     eventreply->EventData;
7367                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
7368                     &irChangeList->NumElements);
7369 
7370                 NDBG20(("mptsas%d IR_CONFIGURATION_CHANGE_LIST event received",
7371                     mpt->m_instance));
7372 
7373                 for (i = 0; i < num_entries; i++) {
7374                         reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
7375                             &irChangeList->ConfigElement[i].ReasonCode);
7376                         volhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7377                             &irChangeList->ConfigElement[i].VolDevHandle);
7378                         diskhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7379                             &irChangeList->ConfigElement[i].PhysDiskDevHandle);
7380 
7381                         switch (reason) {
7382                         case MPI2_EVENT_IR_CHANGE_RC_ADDED:
7383                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
7384                         {
7385                                 NDBG20(("mptsas %d volume added\n",
7386                                     mpt->m_instance));
7387 
7388                                 topo_node = kmem_zalloc(
7389                                     sizeof (mptsas_topo_change_list_t),
7390                                     KM_SLEEP);
7391 
7392                                 topo_node->mpt = mpt;
7393                                 topo_node->event =
7394                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
7395                                 topo_node->un.physport = 0xff;
7396                                 topo_node->devhdl = volhandle;
7397                                 topo_node->flags =
7398                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
7399                                 topo_node->object = NULL;
7400                                 if (topo_head == NULL) {
7401                                         topo_head = topo_tail = topo_node;
7402                                 } else {
7403                                         topo_tail->next = topo_node;
7404                                         topo_tail = topo_node;
7405                                 }
7406                                 break;
7407                         }
7408                         case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
7409                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
7410                         {
7411                                 NDBG20(("mptsas %d volume deleted\n",
7412                                     mpt->m_instance));
7413                                 ptgt = refhash_linear_search(mpt->m_targets,
7414                                     mptsas_target_eval_devhdl, &volhandle);
7415                                 if (ptgt == NULL)
7416                                         break;
7417 
7418                                 /*
7419                                  * Clear any flags related to volume
7420                                  */
7421                                 (void) mptsas_delete_volume(mpt, volhandle);
7422 
7423                                 /*
7424                                  * Update DR flag immediately avoid I/O failure
7425                                  */
7426                                 mutex_enter(&mpt->m_tx_waitq_mutex);
7427                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
7428                                 mutex_exit(&mpt->m_tx_waitq_mutex);
7429 
7430                                 topo_node = kmem_zalloc(
7431                                     sizeof (mptsas_topo_change_list_t),
7432                                     KM_SLEEP);
7433                                 topo_node->mpt = mpt;
7434                                 topo_node->un.phymask =
7435                                     ptgt->m_addr.mta_phymask;
7436                                 topo_node->event =
7437                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7438                                 topo_node->devhdl = volhandle;
7439                                 topo_node->flags =
7440                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
7441                                 topo_node->object = (void *)ptgt;
7442                                 if (topo_head == NULL) {
7443                                         topo_head = topo_tail = topo_node;
7444                                 } else {
7445                                         topo_tail->next = topo_node;
7446                                         topo_tail = topo_node;
7447                                 }
7448                                 break;
7449                         }
7450                         case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
7451                         case MPI2_EVENT_IR_CHANGE_RC_HIDE:
7452                         {
7453                                 ptgt = refhash_linear_search(mpt->m_targets,
7454                                     mptsas_target_eval_devhdl, &diskhandle);
7455                                 if (ptgt == NULL)
7456                                         break;
7457 
7458                                 /*
7459                                  * Update DR flag immediately avoid I/O failure
7460                                  */
7461                                 mutex_enter(&mpt->m_tx_waitq_mutex);
7462                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
7463                                 mutex_exit(&mpt->m_tx_waitq_mutex);
7464 
7465                                 topo_node = kmem_zalloc(
7466                                     sizeof (mptsas_topo_change_list_t),
7467                                     KM_SLEEP);
7468                                 topo_node->mpt = mpt;
7469                                 topo_node->un.phymask =
7470                                     ptgt->m_addr.mta_phymask;
7471                                 topo_node->event =
7472                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7473                                 topo_node->devhdl = diskhandle;
7474                                 topo_node->flags =
7475                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
7476                                 topo_node->object = (void *)ptgt;
7477                                 if (topo_head == NULL) {
7478                                         topo_head = topo_tail = topo_node;
7479                                 } else {
7480                                         topo_tail->next = topo_node;
7481                                         topo_tail = topo_node;
7482                                 }
7483                                 break;
7484                         }
7485                         case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
7486                         case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
7487                         {
7488                                 /*
7489                                  * The physical drive is released by a IR
7490                                  * volume. But we cannot get the the physport
7491                                  * or phynum from the event data, so we only
7492                                  * can get the physport/phynum after SAS
7493                                  * Device Page0 request for the devhdl.
7494                                  */
7495                                 topo_node = kmem_zalloc(
7496                                     sizeof (mptsas_topo_change_list_t),
7497                                     KM_SLEEP);
7498                                 topo_node->mpt = mpt;
7499                                 topo_node->un.phymask = 0;
7500                                 topo_node->event =
7501                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
7502                                 topo_node->devhdl = diskhandle;
7503                                 topo_node->flags =
7504                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
7505                                 topo_node->object = NULL;
7506                                 mpt->m_port_chng = 1;
7507                                 if (topo_head == NULL) {
7508                                         topo_head = topo_tail = topo_node;
7509                                 } else {
7510                                         topo_tail->next = topo_node;
7511                                         topo_tail = topo_node;
7512                                 }
7513                                 break;
7514                         }
7515                         default:
7516                                 break;
7517                         }
7518                 }
7519 
7520                 if (topo_head != NULL) {
7521                         /*
7522                          * Launch DR taskq to handle topology change
7523                          */
7524                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
7525                             mptsas_handle_dr, (void *)topo_head,
7526                             DDI_NOSLEEP)) != DDI_SUCCESS) {
7527                                 while (topo_head != NULL) {
7528                                         topo_node = topo_head;
7529                                         topo_head = topo_head->next;
7530                                         kmem_free(topo_node,
7531                                             sizeof (mptsas_topo_change_list_t));
7532                                 }
7533                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
7534                                     "for handle SAS DR event failed. \n");
7535                         }
7536                 }
7537                 break;
7538         }
7539         default:
7540                 return (DDI_FAILURE);
7541         }
7542 
7543         return (DDI_SUCCESS);
7544 }
7545 
7546 /*
7547  * handle events from ioc
7548  */
7549 static void
7550 mptsas_handle_event(void *args)
7551 {
7552         m_replyh_arg_t                  *replyh_arg;
7553         pMpi2EventNotificationReply_t   eventreply;
7554         uint32_t                        event, iocloginfo, rfm;
7555         uint32_t                        status;
7556         uint8_t                         port;
7557         mptsas_t                        *mpt;
7558         uint_t                          iocstatus;
7559 
7560         replyh_arg = (m_replyh_arg_t *)args;
7561         rfm = replyh_arg->rfm;
7562         mpt = replyh_arg->mpt;
7563 
7564         mutex_enter(&mpt->m_mutex);
7565         /*
7566          * If HBA is being reset, drop incoming event.
7567          */
7568         if (mpt->m_in_reset) {
7569                 NDBG20(("dropping event received prior to reset"));
7570                 mutex_exit(&mpt->m_mutex);
7571                 return;
7572         }
7573 
7574         eventreply = (pMpi2EventNotificationReply_t)
7575             (mpt->m_reply_frame + (rfm -
7576             (mpt->m_reply_frame_dma_addr & 0xffffffffu)));
7577         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
7578 
7579         if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
7580             &eventreply->IOCStatus)) {
7581                 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
7582                         mptsas_log(mpt, CE_WARN,
7583                             "!mptsas_handle_event: IOCStatus=0x%x, "
7584                             "IOCLogInfo=0x%x", iocstatus,
7585                             ddi_get32(mpt->m_acc_reply_frame_hdl,
7586                             &eventreply->IOCLogInfo));
7587                 } else {
7588                         mptsas_log(mpt, CE_WARN,
7589                             "mptsas_handle_event: IOCStatus=0x%x, "
7590                             "IOCLogInfo=0x%x", iocstatus,
7591                             ddi_get32(mpt->m_acc_reply_frame_hdl,
7592                             &eventreply->IOCLogInfo));
7593                 }
7594         }
7595 
7596         /*
7597          * figure out what kind of event we got and handle accordingly
7598          */
7599         switch (event) {
7600         case MPI2_EVENT_LOG_ENTRY_ADDED:
7601                 break;
7602         case MPI2_EVENT_LOG_DATA:
7603                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7604                     &eventreply->IOCLogInfo);
7605                 NDBG20(("mptsas %d log info %x received.\n", mpt->m_instance,
7606                     iocloginfo));
7607                 break;
7608         case MPI2_EVENT_STATE_CHANGE:
7609                 NDBG20(("mptsas%d state change.", mpt->m_instance));
7610                 break;
7611         case MPI2_EVENT_HARD_RESET_RECEIVED:
7612                 NDBG20(("mptsas%d event change.", mpt->m_instance));
7613                 break;
7614         case MPI2_EVENT_SAS_DISCOVERY:
7615         {
7616                 MPI2_EVENT_DATA_SAS_DISCOVERY   *sasdiscovery;
7617                 char                            string[80];
7618                 uint8_t                         rc;
7619 
7620                 sasdiscovery =
7621                     (pMpi2EventDataSasDiscovery_t)eventreply->EventData;
7622 
7623                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7624                     &sasdiscovery->ReasonCode);
7625                 port = ddi_get8(mpt->m_acc_reply_frame_hdl,
7626                     &sasdiscovery->PhysicalPort);
7627                 status = ddi_get32(mpt->m_acc_reply_frame_hdl,
7628                     &sasdiscovery->DiscoveryStatus);
7629 
7630                 string[0] = 0;
7631                 switch (rc) {
7632                 case MPI2_EVENT_SAS_DISC_RC_STARTED:
7633                         (void) sprintf(string, "STARTING");
7634                         break;
7635                 case MPI2_EVENT_SAS_DISC_RC_COMPLETED:
7636                         (void) sprintf(string, "COMPLETED");
7637                         break;
7638                 default:
7639                         (void) sprintf(string, "UNKNOWN");
7640                         break;
7641                 }
7642 
7643                 NDBG20(("SAS DISCOVERY is %s for port %d, status %x", string,
7644                     port, status));
7645 
7646                 break;
7647         }
7648         case MPI2_EVENT_EVENT_CHANGE:
7649                 NDBG20(("mptsas%d event change.", mpt->m_instance));
7650                 break;
7651         case MPI2_EVENT_TASK_SET_FULL:
7652         {
7653                 pMpi2EventDataTaskSetFull_t     taskfull;
7654 
7655                 taskfull = (pMpi2EventDataTaskSetFull_t)eventreply->EventData;
7656 
7657                 NDBG20(("TASK_SET_FULL received for mptsas%d, depth %d\n",
7658                     mpt->m_instance,  ddi_get16(mpt->m_acc_reply_frame_hdl,
7659                     &taskfull->CurrentDepth)));
7660                 break;
7661         }
7662         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7663         {
7664                 /*
7665                  * SAS TOPOLOGY CHANGE LIST Event has already been handled
7666                  * in mptsas_handle_event_sync() of interrupt context
7667                  */
7668                 break;
7669         }
7670         case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7671         {
7672                 pMpi2EventDataSasEnclDevStatusChange_t  encstatus;
7673                 uint8_t                                 rc;
7674                 char                                    string[80];
7675 
7676                 encstatus = (pMpi2EventDataSasEnclDevStatusChange_t)
7677                     eventreply->EventData;
7678 
7679                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7680                     &encstatus->ReasonCode);
7681                 switch (rc) {
7682                 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
7683                         (void) sprintf(string, "added");
7684                         break;
7685                 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
7686                         (void) sprintf(string, ", not responding");
7687                         break;
7688                 default:
7689                 break;
7690                 }
7691                 NDBG20(("mptsas%d ENCLOSURE STATUS CHANGE for enclosure "
7692                     "%x%s\n", mpt->m_instance,
7693                     ddi_get16(mpt->m_acc_reply_frame_hdl,
7694                     &encstatus->EnclosureHandle), string));
7695                 break;
7696         }
7697 
7698         /*
7699          * MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE is handled by
7700          * mptsas_handle_event_sync,in here just send ack message.
7701          */
7702         case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7703         {
7704                 pMpi2EventDataSasDeviceStatusChange_t   statuschange;
7705                 uint8_t                                 rc;
7706                 uint16_t                                devhdl;
7707                 uint64_t                                wwn = 0;
7708                 uint32_t                                wwn_lo, wwn_hi;
7709 
7710                 statuschange = (pMpi2EventDataSasDeviceStatusChange_t)
7711                     eventreply->EventData;
7712                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7713                     &statuschange->ReasonCode);
7714                 wwn_lo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7715                     (uint32_t *)(void *)&statuschange->SASAddress);
7716                 wwn_hi = ddi_get32(mpt->m_acc_reply_frame_hdl,
7717                     (uint32_t *)(void *)&statuschange->SASAddress + 1);
7718                 wwn = ((uint64_t)wwn_hi << 32) | wwn_lo;
7719                 devhdl =  ddi_get16(mpt->m_acc_reply_frame_hdl,
7720                     &statuschange->DevHandle);
7721 
7722                 NDBG13(("MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE wwn is %"PRIx64,
7723                     wwn));
7724 
7725                 switch (rc) {
7726                 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
7727                         NDBG20(("SMART data received, ASC/ASCQ = %02x/%02x",
7728                             ddi_get8(mpt->m_acc_reply_frame_hdl,
7729                             &statuschange->ASC),
7730                             ddi_get8(mpt->m_acc_reply_frame_hdl,
7731                             &statuschange->ASCQ)));
7732                         break;
7733 
7734                 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
7735                         NDBG20(("Device not supported"));
7736                         break;
7737 
7738                 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
7739                         NDBG20(("IOC internally generated the Target Reset "
7740                             "for devhdl:%x", devhdl));
7741                         break;
7742 
7743                 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
7744                         NDBG20(("IOC's internally generated Target Reset "
7745                             "completed for devhdl:%x", devhdl));
7746                         break;
7747 
7748                 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
7749                         NDBG20(("IOC internally generated Abort Task"));
7750                         break;
7751 
7752                 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
7753                         NDBG20(("IOC's internally generated Abort Task "
7754                             "completed"));
7755                         break;
7756 
7757                 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
7758                         NDBG20(("IOC internally generated Abort Task Set"));
7759                         break;
7760 
7761                 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
7762                         NDBG20(("IOC internally generated Clear Task Set"));
7763                         break;
7764 
7765                 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
7766                         NDBG20(("IOC internally generated Query Task"));
7767                         break;
7768 
7769                 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
7770                         NDBG20(("Device sent an Asynchronous Notification"));
7771                         break;
7772 
7773                 default:
7774                         break;
7775                 }
7776                 break;
7777         }
7778         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7779         {
7780                 /*
7781                  * IR TOPOLOGY CHANGE LIST Event has already been handled
7782                  * in mpt_handle_event_sync() of interrupt context
7783                  */
7784                 break;
7785         }
7786         case MPI2_EVENT_IR_OPERATION_STATUS:
7787         {
7788                 Mpi2EventDataIrOperationStatus_t        *irOpStatus;
7789                 char                                    reason_str[80];
7790                 uint8_t                                 rc, percent;
7791                 uint16_t                                handle;
7792 
7793                 irOpStatus = (pMpi2EventDataIrOperationStatus_t)
7794                     eventreply->EventData;
7795                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7796                     &irOpStatus->RAIDOperation);
7797                 percent = ddi_get8(mpt->m_acc_reply_frame_hdl,
7798                     &irOpStatus->PercentComplete);
7799                 handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7800                     &irOpStatus->VolDevHandle);
7801 
7802                 switch (rc) {
7803                         case MPI2_EVENT_IR_RAIDOP_RESYNC:
7804                                 (void) sprintf(reason_str, "resync");
7805                                 break;
7806                         case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
7807                                 (void) sprintf(reason_str, "online capacity "
7808                                     "expansion");
7809                                 break;
7810                         case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
7811                                 (void) sprintf(reason_str, "consistency check");
7812                                 break;
7813                         default:
7814                                 (void) sprintf(reason_str, "unknown reason %x",
7815                                     rc);
7816                 }
7817 
7818                 NDBG20(("mptsas%d raid operational status: (%s)"
7819                     "\thandle(0x%04x), percent complete(%d)\n",
7820                     mpt->m_instance, reason_str, handle, percent));
7821                 break;
7822         }
7823         case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7824         {
7825                 pMpi2EventDataSasBroadcastPrimitive_t   sas_broadcast;
7826                 uint8_t                                 phy_num;
7827                 uint8_t                                 primitive;
7828 
7829                 sas_broadcast = (pMpi2EventDataSasBroadcastPrimitive_t)
7830                     eventreply->EventData;
7831 
7832                 phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
7833                     &sas_broadcast->PhyNum);
7834                 primitive = ddi_get8(mpt->m_acc_reply_frame_hdl,
7835                     &sas_broadcast->Primitive);
7836 
7837                 switch (primitive) {
7838                 case MPI2_EVENT_PRIMITIVE_CHANGE:
7839                         mptsas_smhba_log_sysevent(mpt,
7840                             ESC_SAS_HBA_PORT_BROADCAST,
7841                             SAS_PORT_BROADCAST_CHANGE,
7842                             &mpt->m_phy_info[phy_num].smhba_info);
7843                         break;
7844                 case MPI2_EVENT_PRIMITIVE_SES:
7845                         mptsas_smhba_log_sysevent(mpt,
7846                             ESC_SAS_HBA_PORT_BROADCAST,
7847                             SAS_PORT_BROADCAST_SES,
7848                             &mpt->m_phy_info[phy_num].smhba_info);
7849                         break;
7850                 case MPI2_EVENT_PRIMITIVE_EXPANDER:
7851                         mptsas_smhba_log_sysevent(mpt,
7852                             ESC_SAS_HBA_PORT_BROADCAST,
7853                             SAS_PORT_BROADCAST_D01_4,
7854                             &mpt->m_phy_info[phy_num].smhba_info);
7855                         break;
7856                 case MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT:
7857                         mptsas_smhba_log_sysevent(mpt,
7858                             ESC_SAS_HBA_PORT_BROADCAST,
7859                             SAS_PORT_BROADCAST_D04_7,
7860                             &mpt->m_phy_info[phy_num].smhba_info);
7861                         break;
7862                 case MPI2_EVENT_PRIMITIVE_RESERVED3:
7863                         mptsas_smhba_log_sysevent(mpt,
7864                             ESC_SAS_HBA_PORT_BROADCAST,
7865                             SAS_PORT_BROADCAST_D16_7,
7866                             &mpt->m_phy_info[phy_num].smhba_info);
7867                         break;
7868                 case MPI2_EVENT_PRIMITIVE_RESERVED4:
7869                         mptsas_smhba_log_sysevent(mpt,
7870                             ESC_SAS_HBA_PORT_BROADCAST,
7871                             SAS_PORT_BROADCAST_D29_7,
7872                             &mpt->m_phy_info[phy_num].smhba_info);
7873                         break;
7874                 case MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED:
7875                         mptsas_smhba_log_sysevent(mpt,
7876                             ESC_SAS_HBA_PORT_BROADCAST,
7877                             SAS_PORT_BROADCAST_D24_0,
7878                             &mpt->m_phy_info[phy_num].smhba_info);
7879                         break;
7880                 case MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED:
7881                         mptsas_smhba_log_sysevent(mpt,
7882                             ESC_SAS_HBA_PORT_BROADCAST,
7883                             SAS_PORT_BROADCAST_D27_4,
7884                             &mpt->m_phy_info[phy_num].smhba_info);
7885                         break;
7886                 default:
7887                         NDBG16(("mptsas%d: unknown BROADCAST PRIMITIVE"
7888                             " %x received",
7889                             mpt->m_instance, primitive));
7890                         break;
7891                 }
7892                 NDBG16(("mptsas%d sas broadcast primitive: "
7893                     "\tprimitive(0x%04x), phy(%d) complete\n",
7894                     mpt->m_instance, primitive, phy_num));
7895                 break;
7896         }
7897         case MPI2_EVENT_IR_VOLUME:
7898         {
7899                 Mpi2EventDataIrVolume_t         *irVolume;
7900                 uint16_t                        devhandle;
7901                 uint32_t                        state;
7902                 int                             config, vol;
7903                 uint8_t                         found = FALSE;
7904 
7905                 irVolume = (pMpi2EventDataIrVolume_t)eventreply->EventData;
7906                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7907                     &irVolume->NewValue);
7908                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7909                     &irVolume->VolDevHandle);
7910 
7911                 NDBG20(("EVENT_IR_VOLUME event is received"));
7912 
7913                 /*
7914                  * Get latest RAID info and then find the DevHandle for this
7915                  * event in the configuration.  If the DevHandle is not found
7916                  * just exit the event.
7917                  */
7918                 (void) mptsas_get_raid_info(mpt);
7919                 for (config = 0; (config < mpt->m_num_raid_configs) &&
7920                     (!found); config++) {
7921                         for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
7922                                 if (mpt->m_raidconfig[config].m_raidvol[vol].
7923                                     m_raidhandle == devhandle) {
7924                                         found = TRUE;
7925                                         break;
7926                                 }
7927                         }
7928                 }
7929                 if (!found) {
7930                         break;
7931                 }
7932 
7933                 switch (irVolume->ReasonCode) {
7934                 case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
7935                 {
7936                         uint32_t i;
7937                         mpt->m_raidconfig[config].m_raidvol[vol].m_settings =
7938                             state;
7939 
7940                         i = state & MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING;
7941                         mptsas_log(mpt, CE_NOTE, " Volume %d settings changed"
7942                             ", auto-config of hot-swap drives is %s"
7943                             ", write caching is %s"
7944                             ", hot-spare pool mask is %02x\n",
7945                             vol, state &
7946                             MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE
7947                             ? "disabled" : "enabled",
7948                             i == MPI2_RAIDVOL0_SETTING_UNCHANGED
7949                             ? "controlled by member disks" :
7950                             i == MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING
7951                             ? "disabled" :
7952                             i == MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING
7953                             ? "enabled" :
7954                             "incorrectly set",
7955                             (state >> 16) & 0xff);
7956                                 break;
7957                 }
7958                 case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
7959                 {
7960                         mpt->m_raidconfig[config].m_raidvol[vol].m_state =
7961                             (uint8_t)state;
7962 
7963                         mptsas_log(mpt, CE_NOTE,
7964                             "Volume %d is now %s\n", vol,
7965                             state == MPI2_RAID_VOL_STATE_OPTIMAL
7966                             ? "optimal" :
7967                             state == MPI2_RAID_VOL_STATE_DEGRADED
7968                             ? "degraded" :
7969                             state == MPI2_RAID_VOL_STATE_ONLINE
7970                             ? "online" :
7971                             state == MPI2_RAID_VOL_STATE_INITIALIZING
7972                             ? "initializing" :
7973                             state == MPI2_RAID_VOL_STATE_FAILED
7974                             ? "failed" :
7975                             state == MPI2_RAID_VOL_STATE_MISSING
7976                             ? "missing" :
7977                             "state unknown");
7978                         break;
7979                 }
7980                 case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
7981                 {
7982                         mpt->m_raidconfig[config].m_raidvol[vol].
7983                             m_statusflags = state;
7984 
7985                         mptsas_log(mpt, CE_NOTE,
7986                             " Volume %d is now %s%s%s%s%s%s%s%s%s\n",
7987                             vol,
7988                             state & MPI2_RAIDVOL0_STATUS_FLAG_ENABLED
7989                             ? ", enabled" : ", disabled",
7990                             state & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED
7991                             ? ", quiesced" : "",
7992                             state & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE
7993                             ? ", inactive" : ", active",
7994                             state &
7995                             MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL
7996                             ? ", bad block table is full" : "",
7997                             state &
7998                             MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
7999                             ? ", resync in progress" : "",
8000                             state & MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT
8001                             ? ", background initialization in progress" : "",
8002                             state &
8003                             MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION
8004                             ? ", capacity expansion in progress" : "",
8005                             state &
8006                             MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK
8007                             ? ", consistency check in progress" : "",
8008                             state & MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB
8009                             ? ", data scrub in progress" : "");
8010                         break;
8011                 }
8012                 default:
8013                         break;
8014                 }
8015                 break;
8016         }
8017         case MPI2_EVENT_IR_PHYSICAL_DISK:
8018         {
8019                 Mpi2EventDataIrPhysicalDisk_t   *irPhysDisk;
8020                 uint16_t                        devhandle, enchandle, slot;
8021                 uint32_t                        status, state;
8022                 uint8_t                         physdisknum, reason;
8023 
8024                 irPhysDisk = (Mpi2EventDataIrPhysicalDisk_t *)
8025                     eventreply->EventData;
8026                 physdisknum = ddi_get8(mpt->m_acc_reply_frame_hdl,
8027                     &irPhysDisk->PhysDiskNum);
8028                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
8029                     &irPhysDisk->PhysDiskDevHandle);
8030                 enchandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
8031                     &irPhysDisk->EnclosureHandle);
8032                 slot = ddi_get16(mpt->m_acc_reply_frame_hdl,
8033                     &irPhysDisk->Slot);
8034                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
8035                     &irPhysDisk->NewValue);
8036                 reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
8037                     &irPhysDisk->ReasonCode);
8038 
8039                 NDBG20(("EVENT_IR_PHYSICAL_DISK event is received"));
8040 
8041                 switch (reason) {
8042                 case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
8043                         mptsas_log(mpt, CE_NOTE,
8044                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
8045                             "for enclosure with handle 0x%x is now in hot "
8046                             "spare pool %d",
8047                             physdisknum, devhandle, slot, enchandle,
8048                             (state >> 16) & 0xff);
8049                         break;
8050 
8051                 case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
8052                         status = state;
8053                         mptsas_log(mpt, CE_NOTE,
8054                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
8055                             "for enclosure with handle 0x%x is now "
8056                             "%s%s%s%s%s\n", physdisknum, devhandle, slot,
8057                             enchandle,
8058                             status & MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME
8059                             ? ", inactive" : ", active",
8060                             status & MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
8061                             ? ", out of sync" : "",
8062                             status & MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED
8063                             ? ", quiesced" : "",
8064                             status &
8065                             MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED
8066                             ? ", write cache enabled" : "",
8067                             status & MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET
8068                             ? ", capacity expansion target" : "");
8069                         break;
8070 
8071                 case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
8072                         mptsas_log(mpt, CE_NOTE,
8073                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
8074                             "for enclosure with handle 0x%x is now %s\n",
8075                             physdisknum, devhandle, slot, enchandle,
8076                             state == MPI2_RAID_PD_STATE_OPTIMAL
8077                             ? "optimal" :
8078                             state == MPI2_RAID_PD_STATE_REBUILDING
8079                             ? "rebuilding" :
8080                             state == MPI2_RAID_PD_STATE_DEGRADED
8081                             ? "degraded" :
8082                             state == MPI2_RAID_PD_STATE_HOT_SPARE
8083                             ? "a hot spare" :
8084                             state == MPI2_RAID_PD_STATE_ONLINE
8085                             ? "online" :
8086                             state == MPI2_RAID_PD_STATE_OFFLINE
8087                             ? "offline" :
8088                             state == MPI2_RAID_PD_STATE_NOT_COMPATIBLE
8089                             ? "not compatible" :
8090                             state == MPI2_RAID_PD_STATE_NOT_CONFIGURED
8091                             ? "not configured" :
8092                             "state unknown");
8093                         break;
8094                 }
8095                 break;
8096         }
8097         default:
8098                 NDBG20(("mptsas%d: unknown event %x received",
8099                     mpt->m_instance, event));
8100                 break;
8101         }
8102 
8103         /*
8104          * Return the reply frame to the free queue.
8105          */
8106         ddi_put32(mpt->m_acc_free_queue_hdl,
8107             &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index], rfm);
8108         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
8109             DDI_DMA_SYNC_FORDEV);
8110         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
8111                 mpt->m_free_index = 0;
8112         }
8113         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
8114             mpt->m_free_index);
8115         mutex_exit(&mpt->m_mutex);
8116 }
8117 
8118 /*
8119  * invoked from timeout() to restart qfull cmds with throttle == 0
8120  */
8121 static void
8122 mptsas_restart_cmd(void *arg)
8123 {
8124         mptsas_t        *mpt = arg;
8125         mptsas_target_t *ptgt = NULL;
8126 
8127         mutex_enter(&mpt->m_mutex);
8128 
8129         mpt->m_restart_cmd_timeid = 0;
8130 
8131         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
8132             ptgt = refhash_next(mpt->m_targets, ptgt)) {
8133                 if (ptgt->m_reset_delay == 0) {
8134                         if (ptgt->m_t_throttle == QFULL_THROTTLE) {
8135                                 mptsas_set_throttle(mpt, ptgt,
8136                                     MAX_THROTTLE);
8137                         }
8138                 }
8139         }
8140         mptsas_restart_hba(mpt);
8141         mutex_exit(&mpt->m_mutex);
8142 }
8143 
8144 void
8145 mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
8146 {
8147         int             slot;
8148         mptsas_slots_t  *slots = mpt->m_active;
8149         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8150 
8151         ASSERT(cmd != NULL);
8152         ASSERT(cmd->cmd_queued == FALSE);
8153 
8154         /*
8155          * Task Management cmds are removed in their own routines.  Also,
8156          * we don't want to modify timeout based on TM cmds.
8157          */
8158         if (cmd->cmd_flags & CFLAG_TM_CMD) {
8159                 return;
8160         }
8161 
8162         slot = cmd->cmd_slot;
8163 
8164         /*
8165          * remove the cmd.
8166          */
8167         if (cmd == slots->m_slot[slot]) {
8168                 NDBG31(("mptsas_remove_cmd: removing cmd=0x%p, flags "
8169                     "0x%x", (void *)cmd, cmd->cmd_flags));
8170                 slots->m_slot[slot] = NULL;
8171                 mpt->m_ncmds--;
8172 
8173                 /*
8174                  * only decrement per target ncmds if command
8175                  * has a target associated with it.
8176                  */
8177                 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
8178                         ptgt->m_t_ncmds--;
8179                         /*
8180                          * reset throttle if we just ran an untagged command
8181                          * to a tagged target
8182                          */
8183                         if ((ptgt->m_t_ncmds == 0) &&
8184                             ((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0)) {
8185                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
8186                         }
8187 
8188                         /*
8189                          * Remove this command from the active queue.
8190                          */
8191                         if (cmd->cmd_active_expiration != 0) {
8192                                 TAILQ_REMOVE(&ptgt->m_active_cmdq, cmd,
8193                                     cmd_active_link);
8194                                 cmd->cmd_active_expiration = 0;
8195                         }
8196                 }
8197         }
8198 
8199         /*
8200          * This is all we need to do for ioc commands.
8201          */
8202         if (cmd->cmd_flags & CFLAG_CMDIOC) {
8203                 mptsas_return_to_pool(mpt, cmd);
8204                 return;
8205         }
8206 
8207         ASSERT(cmd != slots->m_slot[cmd->cmd_slot]);
8208 }
8209 
8210 /*
8211  * accept all cmds on the tx_waitq if any and then
8212  * start a fresh request from the top of the device queue.
8213  *
8214  * since there are always cmds queued on the tx_waitq, and rare cmds on
8215  * the instance waitq, so this function should not be invoked in the ISR,
8216  * the mptsas_restart_waitq() is invoked in the ISR instead. otherwise, the
8217  * burden belongs to the IO dispatch CPUs is moved the interrupt CPU.
8218  */
8219 static void
8220 mptsas_restart_hba(mptsas_t *mpt)
8221 {
8222         ASSERT(mutex_owned(&mpt->m_mutex));
8223 
8224         mutex_enter(&mpt->m_tx_waitq_mutex);
8225         if (mpt->m_tx_waitq) {
8226                 mptsas_accept_tx_waitq(mpt);
8227         }
8228         mutex_exit(&mpt->m_tx_waitq_mutex);
8229         mptsas_restart_waitq(mpt);
8230 }
8231 
8232 /*
8233  * start a fresh request from the top of the device queue
8234  */
8235 static void
8236 mptsas_restart_waitq(mptsas_t *mpt)
8237 {
8238         mptsas_cmd_t    *cmd, *next_cmd;
8239         mptsas_target_t *ptgt = NULL;
8240 
8241         NDBG1(("mptsas_restart_waitq: mpt=0x%p", (void *)mpt));
8242 
8243         ASSERT(mutex_owned(&mpt->m_mutex));
8244 
8245         /*
8246          * If there is a reset delay, don't start any cmds.  Otherwise, start
8247          * as many cmds as possible.
8248          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
8249          * commands is m_max_requests - 2.
8250          */
8251         cmd = mpt->m_waitq;
8252 
8253         while (cmd != NULL) {
8254                 next_cmd = cmd->cmd_linkp;
8255                 if (cmd->cmd_flags & CFLAG_PASSTHRU) {
8256                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8257                                 /*
8258                                  * passthru command get slot need
8259                                  * set CFLAG_PREPARED.
8260                                  */
8261                                 cmd->cmd_flags |= CFLAG_PREPARED;
8262                                 mptsas_waitq_delete(mpt, cmd);
8263                                 mptsas_start_passthru(mpt, cmd);
8264                         }
8265                         cmd = next_cmd;
8266                         continue;
8267                 }
8268                 if (cmd->cmd_flags & CFLAG_CONFIG) {
8269                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8270                                 /*
8271                                  * Send the config page request and delete it
8272                                  * from the waitq.
8273                                  */
8274                                 cmd->cmd_flags |= CFLAG_PREPARED;
8275                                 mptsas_waitq_delete(mpt, cmd);
8276                                 mptsas_start_config_page_access(mpt, cmd);
8277                         }
8278                         cmd = next_cmd;
8279                         continue;
8280                 }
8281                 if (cmd->cmd_flags & CFLAG_FW_DIAG) {
8282                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8283                                 /*
8284                                  * Send the FW Diag request and delete if from
8285                                  * the waitq.
8286                                  */
8287                                 cmd->cmd_flags |= CFLAG_PREPARED;
8288                                 mptsas_waitq_delete(mpt, cmd);
8289                                 mptsas_start_diag(mpt, cmd);
8290                         }
8291                         cmd = next_cmd;
8292                         continue;
8293                 }
8294 
8295                 ptgt = cmd->cmd_tgt_addr;
8296                 if (ptgt && (ptgt->m_t_throttle == DRAIN_THROTTLE) &&
8297                     (ptgt->m_t_ncmds == 0)) {
8298                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
8299                 }
8300                 if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
8301                     (ptgt && (ptgt->m_reset_delay == 0)) &&
8302                     (ptgt && (ptgt->m_t_ncmds <
8303                     ptgt->m_t_throttle))) {
8304                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8305                                 mptsas_waitq_delete(mpt, cmd);
8306                                 (void) mptsas_start_cmd(mpt, cmd);
8307                         }
8308                 }
8309                 cmd = next_cmd;
8310         }
8311 }
8312 /*
8313  * Cmds are queued if tran_start() doesn't get the m_mutexlock(no wait).
8314  * Accept all those queued cmds before new cmd is accept so that the
8315  * cmds are sent in order.
8316  */
8317 static void
8318 mptsas_accept_tx_waitq(mptsas_t *mpt)
8319 {
8320         mptsas_cmd_t *cmd;
8321 
8322         ASSERT(mutex_owned(&mpt->m_mutex));
8323         ASSERT(mutex_owned(&mpt->m_tx_waitq_mutex));
8324 
8325         /*
8326          * A Bus Reset could occur at any time and flush the tx_waitq,
8327          * so we cannot count on the tx_waitq to contain even one cmd.
8328          * And when the m_tx_waitq_mutex is released and run
8329          * mptsas_accept_pkt(), the tx_waitq may be flushed.
8330          */
8331         cmd = mpt->m_tx_waitq;
8332         for (;;) {
8333                 if ((cmd = mpt->m_tx_waitq) == NULL) {
8334                         mpt->m_tx_draining = 0;
8335                         break;
8336                 }
8337                 if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL) {
8338                         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
8339                 }
8340                 cmd->cmd_linkp = NULL;
8341                 mutex_exit(&mpt->m_tx_waitq_mutex);
8342                 if (mptsas_accept_pkt(mpt, cmd) != TRAN_ACCEPT)
8343                         cmn_err(CE_WARN, "mpt: mptsas_accept_tx_waitq: failed "
8344                             "to accept cmd on queue\n");
8345                 mutex_enter(&mpt->m_tx_waitq_mutex);
8346         }
8347 }
8348 
8349 
8350 /*
8351  * mpt tag type lookup
8352  */
8353 static char mptsas_tag_lookup[] =
8354         {0, MSG_HEAD_QTAG, MSG_ORDERED_QTAG, 0, MSG_SIMPLE_QTAG};
8355 
8356 static int
8357 mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
8358 {
8359         struct scsi_pkt         *pkt = CMD2PKT(cmd);
8360         uint32_t                control = 0;
8361         caddr_t                 mem, arsbuf;
8362         pMpi2SCSIIORequest_t    io_request;
8363         ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
8364         ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
8365         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
8366         uint16_t                SMID, io_flags = 0;
8367         uint8_t                 ars_size;
8368         uint64_t                request_desc;
8369         uint32_t                ars_dmaaddrlow;
8370         mptsas_cmd_t            *c;
8371 
8372         NDBG1(("mptsas_start_cmd: cmd=0x%p, flags 0x%x", (void *)cmd,
8373             cmd->cmd_flags));
8374 
8375         /*
8376          * Set SMID and increment index.  Rollover to 1 instead of 0 if index
8377          * is at the max.  0 is an invalid SMID, so we call the first index 1.
8378          */
8379         SMID = cmd->cmd_slot;
8380 
8381         /*
8382          * It is possible for back to back device reset to
8383          * happen before the reset delay has expired.  That's
8384          * ok, just let the device reset go out on the bus.
8385          */
8386         if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
8387                 ASSERT(ptgt->m_reset_delay == 0);
8388         }
8389 
8390         /*
8391          * if a non-tagged cmd is submitted to an active tagged target
8392          * then drain before submitting this cmd; SCSI-2 allows RQSENSE
8393          * to be untagged
8394          */
8395         if (((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0) &&
8396             (ptgt->m_t_ncmds > 1) &&
8397             ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) &&
8398             (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE)) {
8399                 if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
8400                         NDBG23(("target=%d, untagged cmd, start draining\n",
8401                             ptgt->m_devhdl));
8402 
8403                         if (ptgt->m_reset_delay == 0) {
8404                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
8405                         }
8406 
8407                         mptsas_remove_cmd(mpt, cmd);
8408                         cmd->cmd_pkt_flags |= FLAG_HEAD;
8409                         mptsas_waitq_add(mpt, cmd);
8410                 }
8411                 return (DDI_FAILURE);
8412         }
8413 
8414         /*
8415          * Set correct tag bits.
8416          */
8417         if (cmd->cmd_pkt_flags & FLAG_TAGMASK) {
8418                 switch (mptsas_tag_lookup[((cmd->cmd_pkt_flags &
8419                     FLAG_TAGMASK) >> 12)]) {
8420                 case MSG_SIMPLE_QTAG:
8421                         control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
8422                         break;
8423                 case MSG_HEAD_QTAG:
8424                         control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
8425                         break;
8426                 case MSG_ORDERED_QTAG:
8427                         control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
8428                         break;
8429                 default:
8430                         mptsas_log(mpt, CE_WARN, "mpt: Invalid tag type\n");
8431                         break;
8432                 }
8433         } else {
8434                 if (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE) {
8435                                 ptgt->m_t_throttle = 1;
8436                 }
8437                 control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
8438         }
8439 
8440         if (cmd->cmd_pkt_flags & FLAG_TLR) {
8441                 control |= MPI2_SCSIIO_CONTROL_TLR_ON;
8442         }
8443 
8444         mem = mpt->m_req_frame + (mpt->m_req_frame_size * SMID);
8445         io_request = (pMpi2SCSIIORequest_t)mem;
8446         if (cmd->cmd_extrqslen != 0) {
8447                 /*
8448                  * Mapping of the buffer was done in mptsas_pkt_alloc_extern().
8449                  * Calculate the DMA address with the same offset.
8450                  */
8451                 arsbuf = cmd->cmd_arq_buf;
8452                 ars_size = cmd->cmd_extrqslen;
8453                 ars_dmaaddrlow = (mpt->m_req_sense_dma_addr +
8454                     ((uintptr_t)arsbuf - (uintptr_t)mpt->m_req_sense)) &
8455                     0xffffffffu;
8456         } else {
8457                 arsbuf = mpt->m_req_sense + (mpt->m_req_sense_size * (SMID-1));
8458                 cmd->cmd_arq_buf = arsbuf;
8459                 ars_size = mpt->m_req_sense_size;
8460                 ars_dmaaddrlow = (mpt->m_req_sense_dma_addr +
8461                     (mpt->m_req_sense_size * (SMID-1))) &
8462                     0xffffffffu;
8463         }
8464         bzero(io_request, sizeof (Mpi2SCSIIORequest_t));
8465         bzero(arsbuf, ars_size);
8466 
8467         ddi_put8(acc_hdl, &io_request->SGLOffset0, offsetof
8468             (MPI2_SCSI_IO_REQUEST, SGL) / 4);
8469         mptsas_init_std_hdr(acc_hdl, io_request, ptgt->m_devhdl, Lun(cmd), 0,
8470             MPI2_FUNCTION_SCSI_IO_REQUEST);
8471 
8472         (void) ddi_rep_put8(acc_hdl, (uint8_t *)pkt->pkt_cdbp,
8473             io_request->CDB.CDB32, cmd->cmd_cdblen, DDI_DEV_AUTOINCR);
8474 
8475         io_flags = cmd->cmd_cdblen;
8476         if (mptsas_use_fastpath &&
8477             ptgt->m_io_flags & MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) {
8478                 io_flags |= MPI25_SCSIIO_IOFLAGS_FAST_PATH;
8479                 request_desc = MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
8480         } else {
8481                 request_desc = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
8482         }
8483         ddi_put16(acc_hdl, &io_request->IoFlags, io_flags);
8484         /*
8485          * setup the Scatter/Gather DMA list for this request
8486          */
8487         if (cmd->cmd_cookiec > 0) {
8488                 mptsas_sge_setup(mpt, cmd, &control, io_request, acc_hdl);
8489         } else {
8490                 ddi_put32(acc_hdl, &io_request->SGL.MpiSimple.FlagsLength,
8491                     ((uint32_t)MPI2_SGE_FLAGS_LAST_ELEMENT |
8492                     MPI2_SGE_FLAGS_END_OF_BUFFER |
8493                     MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
8494                     MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
8495         }
8496 
8497         /*
8498          * save ARQ information
8499          */
8500         ddi_put8(acc_hdl, &io_request->SenseBufferLength, ars_size);
8501         ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress, ars_dmaaddrlow);
8502 
8503         ddi_put32(acc_hdl, &io_request->Control, control);
8504 
8505         NDBG31(("starting message=%d(0x%p), with cmd=0x%p",
8506             SMID, (void *)io_request, (void *)cmd));
8507 
8508         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
8509         (void) ddi_dma_sync(mpt->m_dma_req_sense_hdl, 0, 0,
8510             DDI_DMA_SYNC_FORDEV);
8511 
8512         /*
8513          * Build request descriptor and write it to the request desc post reg.
8514          */
8515         request_desc |= (SMID << 16);
8516         request_desc |= (uint64_t)ptgt->m_devhdl << 48;
8517         MPTSAS_START_CMD(mpt, request_desc);
8518 
8519         /*
8520          * Start timeout.
8521          */
8522         cmd->cmd_active_expiration =
8523             gethrtime() + (hrtime_t)pkt->pkt_time * NANOSEC;
8524 #ifdef MPTSAS_TEST
8525         /*
8526          * Force timeouts to happen immediately.
8527          */
8528         if (mptsas_test_timeouts)
8529                 cmd->cmd_active_expiration = gethrtime();
8530 #endif
8531         c = TAILQ_FIRST(&ptgt->m_active_cmdq);
8532         if (c == NULL ||
8533             c->cmd_active_expiration < cmd->cmd_active_expiration) {
8534                 /*
8535                  * Common case is that this is the last pending expiration
8536                  * (or queue is empty). Insert at head of the queue.
8537                  */
8538                 TAILQ_INSERT_HEAD(&ptgt->m_active_cmdq, cmd, cmd_active_link);
8539         } else {
8540                 /*
8541                  * Queue is not empty and first element expires later than
8542                  * this command. Search for element expiring sooner.
8543                  */
8544                 while ((c = TAILQ_NEXT(c, cmd_active_link)) != NULL) {
8545                         if (c->cmd_active_expiration <
8546                             cmd->cmd_active_expiration) {
8547                                 TAILQ_INSERT_BEFORE(c, cmd, cmd_active_link);
8548                                 break;
8549                         }
8550                 }
8551                 if (c == NULL) {
8552                         /*
8553                          * No element found expiring sooner, append to
8554                          * non-empty queue.
8555                          */
8556                         TAILQ_INSERT_TAIL(&ptgt->m_active_cmdq, cmd,
8557                             cmd_active_link);
8558                 }
8559         }
8560 
8561         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
8562             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
8563                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8564                 return (DDI_FAILURE);
8565         }
8566         return (DDI_SUCCESS);
8567 }
8568 
8569 /*
8570  * Select a helper thread to handle current doneq
8571  */
8572 static void
8573 mptsas_deliver_doneq_thread(mptsas_t *mpt)
8574 {
8575         uint64_t                        t, i;
8576         uint32_t                        min = 0xffffffff;
8577         mptsas_doneq_thread_list_t      *item;
8578 
8579         for (i = 0; i < mpt->m_doneq_thread_n; i++) {
8580                 item = &mpt->m_doneq_thread_id[i];
8581                 /*
8582                  * If the completed command on help thread[i] less than
8583                  * doneq_thread_threshold, then pick the thread[i]. Otherwise
8584                  * pick a thread which has least completed command.
8585                  */
8586 
8587                 mutex_enter(&item->mutex);
8588                 if (item->len < mpt->m_doneq_thread_threshold) {
8589                         t = i;
8590                         mutex_exit(&item->mutex);
8591                         break;
8592                 }
8593                 if (item->len < min) {
8594                         min = item->len;
8595                         t = i;
8596                 }
8597                 mutex_exit(&item->mutex);
8598         }
8599         mutex_enter(&mpt->m_doneq_thread_id[t].mutex);
8600         mptsas_doneq_mv(mpt, t);
8601         cv_signal(&mpt->m_doneq_thread_id[t].cv);
8602         mutex_exit(&mpt->m_doneq_thread_id[t].mutex);
8603 }
8604 
8605 /*
8606  * move the current global doneq to the doneq of thead[t]
8607  */
8608 static void
8609 mptsas_doneq_mv(mptsas_t *mpt, uint64_t t)
8610 {
8611         mptsas_cmd_t                    *cmd;
8612         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
8613 
8614         ASSERT(mutex_owned(&item->mutex));
8615         while ((cmd = mpt->m_doneq) != NULL) {
8616                 if ((mpt->m_doneq = cmd->cmd_linkp) == NULL) {
8617                         mpt->m_donetail = &mpt->m_doneq;
8618                 }
8619                 cmd->cmd_linkp = NULL;
8620                 *item->donetail = cmd;
8621                 item->donetail = &cmd->cmd_linkp;
8622                 mpt->m_doneq_len--;
8623                 item->len++;
8624         }
8625 }
8626 
8627 void
8628 mptsas_fma_check(mptsas_t *mpt, mptsas_cmd_t *cmd)
8629 {
8630         struct scsi_pkt *pkt = CMD2PKT(cmd);
8631 
8632         /* Check all acc and dma handles */
8633         if ((mptsas_check_acc_handle(mpt->m_datap) !=
8634             DDI_SUCCESS) ||
8635             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
8636             DDI_SUCCESS) ||
8637             (mptsas_check_acc_handle(mpt->m_acc_req_sense_hdl) !=
8638             DDI_SUCCESS) ||
8639             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
8640             DDI_SUCCESS) ||
8641             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
8642             DDI_SUCCESS) ||
8643             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
8644             DDI_SUCCESS) ||
8645             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
8646             DDI_SUCCESS) ||
8647             (mptsas_check_acc_handle(mpt->m_config_handle) !=
8648             DDI_SUCCESS)) {
8649                 ddi_fm_service_impact(mpt->m_dip,
8650                     DDI_SERVICE_UNAFFECTED);
8651                 ddi_fm_acc_err_clear(mpt->m_config_handle,
8652                     DDI_FME_VER0);
8653                 pkt->pkt_reason = CMD_TRAN_ERR;
8654                 pkt->pkt_statistics = 0;
8655         }
8656         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
8657             DDI_SUCCESS) ||
8658             (mptsas_check_dma_handle(mpt->m_dma_req_sense_hdl) !=
8659             DDI_SUCCESS) ||
8660             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
8661             DDI_SUCCESS) ||
8662             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
8663             DDI_SUCCESS) ||
8664             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
8665             DDI_SUCCESS) ||
8666             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
8667             DDI_SUCCESS)) {
8668                 ddi_fm_service_impact(mpt->m_dip,
8669                     DDI_SERVICE_UNAFFECTED);
8670                 pkt->pkt_reason = CMD_TRAN_ERR;
8671                 pkt->pkt_statistics = 0;
8672         }
8673         if (cmd->cmd_dmahandle &&
8674             (mptsas_check_dma_handle(cmd->cmd_dmahandle) != DDI_SUCCESS)) {
8675                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8676                 pkt->pkt_reason = CMD_TRAN_ERR;
8677                 pkt->pkt_statistics = 0;
8678         }
8679         if ((cmd->cmd_extra_frames &&
8680             ((mptsas_check_dma_handle(cmd->cmd_extra_frames->m_dma_hdl) !=
8681             DDI_SUCCESS) ||
8682             (mptsas_check_acc_handle(cmd->cmd_extra_frames->m_acc_hdl) !=
8683             DDI_SUCCESS)))) {
8684                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8685                 pkt->pkt_reason = CMD_TRAN_ERR;
8686                 pkt->pkt_statistics = 0;
8687         }
8688 }
8689 
8690 /*
8691  * These routines manipulate the queue of commands that
8692  * are waiting for their completion routines to be called.
8693  * The queue is usually in FIFO order but on an MP system
8694  * it's possible for the completion routines to get out
8695  * of order. If that's a problem you need to add a global
8696  * mutex around the code that calls the completion routine
8697  * in the interrupt handler.
8698  */
8699 static void
8700 mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8701 {
8702         struct scsi_pkt *pkt = CMD2PKT(cmd);
8703 
8704         NDBG31(("mptsas_doneq_add: cmd=0x%p", (void *)cmd));
8705 
8706         ASSERT((cmd->cmd_flags & CFLAG_COMPLETED) == 0);
8707         cmd->cmd_linkp = NULL;
8708         cmd->cmd_flags |= CFLAG_FINISHED;
8709         cmd->cmd_flags &= ~CFLAG_IN_TRANSPORT;
8710 
8711         mptsas_fma_check(mpt, cmd);
8712 
8713         /*
8714          * only add scsi pkts that have completion routines to
8715          * the doneq.  no intr cmds do not have callbacks.
8716          */
8717         if (pkt && (pkt->pkt_comp)) {
8718                 *mpt->m_donetail = cmd;
8719                 mpt->m_donetail = &cmd->cmd_linkp;
8720                 mpt->m_doneq_len++;
8721         }
8722 }
8723 
8724 static mptsas_cmd_t *
8725 mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t)
8726 {
8727         mptsas_cmd_t                    *cmd;
8728         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
8729 
8730         /* pop one off the done queue */
8731         if ((cmd = item->doneq) != NULL) {
8732                 /* if the queue is now empty fix the tail pointer */
8733                 NDBG31(("mptsas_doneq_thread_rm: cmd=0x%p", (void *)cmd));
8734                 if ((item->doneq = cmd->cmd_linkp) == NULL) {
8735                         item->donetail = &item->doneq;
8736                 }
8737                 cmd->cmd_linkp = NULL;
8738                 item->len--;
8739         }
8740         return (cmd);
8741 }
8742 
8743 static void
8744 mptsas_doneq_empty(mptsas_t *mpt)
8745 {
8746         if (mpt->m_doneq && !mpt->m_in_callback) {
8747                 mptsas_cmd_t    *cmd, *next;
8748                 struct scsi_pkt *pkt;
8749 
8750                 mpt->m_in_callback = 1;
8751                 cmd = mpt->m_doneq;
8752                 mpt->m_doneq = NULL;
8753                 mpt->m_donetail = &mpt->m_doneq;
8754                 mpt->m_doneq_len = 0;
8755 
8756                 mutex_exit(&mpt->m_mutex);
8757                 /*
8758                  * run the completion routines of all the
8759                  * completed commands
8760                  */
8761                 while (cmd != NULL) {
8762                         next = cmd->cmd_linkp;
8763                         cmd->cmd_linkp = NULL;
8764                         /* run this command's completion routine */
8765                         cmd->cmd_flags |= CFLAG_COMPLETED;
8766                         pkt = CMD2PKT(cmd);
8767                         mptsas_pkt_comp(pkt, cmd);
8768                         cmd = next;
8769                 }
8770                 mutex_enter(&mpt->m_mutex);
8771                 mpt->m_in_callback = 0;
8772         }
8773 }
8774 
8775 /*
8776  * These routines manipulate the target's queue of pending requests
8777  */
8778 void
8779 mptsas_waitq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8780 {
8781         NDBG7(("mptsas_waitq_add: cmd=0x%p", (void *)cmd));
8782         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8783         cmd->cmd_queued = TRUE;
8784         if (ptgt)
8785                 ptgt->m_t_nwait++;
8786         if (cmd->cmd_pkt_flags & FLAG_HEAD) {
8787                 if ((cmd->cmd_linkp = mpt->m_waitq) == NULL) {
8788                         mpt->m_waitqtail = &cmd->cmd_linkp;
8789                 }
8790                 mpt->m_waitq = cmd;
8791         } else {
8792                 cmd->cmd_linkp = NULL;
8793                 *(mpt->m_waitqtail) = cmd;
8794                 mpt->m_waitqtail = &cmd->cmd_linkp;
8795         }
8796 }
8797 
8798 static mptsas_cmd_t *
8799 mptsas_waitq_rm(mptsas_t *mpt)
8800 {
8801         mptsas_cmd_t    *cmd;
8802         mptsas_target_t *ptgt;
8803         NDBG7(("mptsas_waitq_rm"));
8804 
8805         MPTSAS_WAITQ_RM(mpt, cmd);
8806 
8807         NDBG7(("mptsas_waitq_rm: cmd=0x%p", (void *)cmd));
8808         if (cmd) {
8809                 ptgt = cmd->cmd_tgt_addr;
8810                 if (ptgt) {
8811                         ptgt->m_t_nwait--;
8812                         ASSERT(ptgt->m_t_nwait >= 0);
8813                 }
8814         }
8815         return (cmd);
8816 }
8817 
8818 /*
8819  * remove specified cmd from the middle of the wait queue.
8820  */
8821 static void
8822 mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8823 {
8824         mptsas_cmd_t    *prevp = mpt->m_waitq;
8825         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8826 
8827         NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8828             (void *)mpt, (void *)cmd));
8829         if (ptgt) {
8830                 ptgt->m_t_nwait--;
8831                 ASSERT(ptgt->m_t_nwait >= 0);
8832         }
8833 
8834         if (prevp == cmd) {
8835                 if ((mpt->m_waitq = cmd->cmd_linkp) == NULL)
8836                         mpt->m_waitqtail = &mpt->m_waitq;
8837 
8838                 cmd->cmd_linkp = NULL;
8839                 cmd->cmd_queued = FALSE;
8840                 NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8841                     (void *)mpt, (void *)cmd));
8842                 return;
8843         }
8844 
8845         while (prevp != NULL) {
8846                 if (prevp->cmd_linkp == cmd) {
8847                         if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8848                                 mpt->m_waitqtail = &prevp->cmd_linkp;
8849 
8850                         cmd->cmd_linkp = NULL;
8851                         cmd->cmd_queued = FALSE;
8852                         NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8853                             (void *)mpt, (void *)cmd));
8854                         return;
8855                 }
8856                 prevp = prevp->cmd_linkp;
8857         }
8858         cmn_err(CE_PANIC, "mpt: mptsas_waitq_delete: queue botch");
8859 }
8860 
8861 static mptsas_cmd_t *
8862 mptsas_tx_waitq_rm(mptsas_t *mpt)
8863 {
8864         mptsas_cmd_t *cmd;
8865         NDBG7(("mptsas_tx_waitq_rm"));
8866 
8867         MPTSAS_TX_WAITQ_RM(mpt, cmd);
8868 
8869         NDBG7(("mptsas_tx_waitq_rm: cmd=0x%p", (void *)cmd));
8870 
8871         return (cmd);
8872 }
8873 
8874 /*
8875  * remove specified cmd from the middle of the tx_waitq.
8876  */
8877 static void
8878 mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8879 {
8880         mptsas_cmd_t *prevp = mpt->m_tx_waitq;
8881 
8882         NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8883             (void *)mpt, (void *)cmd));
8884 
8885         if (prevp == cmd) {
8886                 if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL)
8887                         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
8888 
8889                 cmd->cmd_linkp = NULL;
8890                 cmd->cmd_queued = FALSE;
8891                 NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8892                     (void *)mpt, (void *)cmd));
8893                 return;
8894         }
8895 
8896         while (prevp != NULL) {
8897                 if (prevp->cmd_linkp == cmd) {
8898                         if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8899                                 mpt->m_tx_waitqtail = &prevp->cmd_linkp;
8900 
8901                         cmd->cmd_linkp = NULL;
8902                         cmd->cmd_queued = FALSE;
8903                         NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8904                             (void *)mpt, (void *)cmd));
8905                         return;
8906                 }
8907                 prevp = prevp->cmd_linkp;
8908         }
8909         cmn_err(CE_PANIC, "mpt: mptsas_tx_waitq_delete: queue botch");
8910 }
8911 
8912 /*
8913  * device and bus reset handling
8914  *
8915  * Notes:
8916  *      - RESET_ALL:    reset the controller
8917  *      - RESET_TARGET: reset the target specified in scsi_address
8918  */
8919 static int
8920 mptsas_scsi_reset(struct scsi_address *ap, int level)
8921 {
8922         mptsas_t                *mpt = ADDR2MPT(ap);
8923         int                     rval;
8924         mptsas_tgt_private_t    *tgt_private;
8925         mptsas_target_t         *ptgt = NULL;
8926 
8927         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->tran_tgt_private;
8928         ptgt = tgt_private->t_private;
8929         if (ptgt == NULL) {
8930                 return (FALSE);
8931         }
8932         NDBG22(("mptsas_scsi_reset: target=%d level=%d", ptgt->m_devhdl,
8933             level));
8934 
8935         mutex_enter(&mpt->m_mutex);
8936         /*
8937          * if we are not in panic set up a reset delay for this target
8938          */
8939         if (!ddi_in_panic()) {
8940                 mptsas_setup_bus_reset_delay(mpt);
8941         } else {
8942                 drv_usecwait(mpt->m_scsi_reset_delay * 1000);
8943         }
8944         rval = mptsas_do_scsi_reset(mpt, ptgt->m_devhdl);
8945         mutex_exit(&mpt->m_mutex);
8946 
8947         /*
8948          * The transport layer expect to only see TRUE and
8949          * FALSE. Therefore, we will adjust the return value
8950          * if mptsas_do_scsi_reset returns FAILED.
8951          */
8952         if (rval == FAILED)
8953                 rval = FALSE;
8954         return (rval);
8955 }
8956 
8957 static int
8958 mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl)
8959 {
8960         int             rval = FALSE;
8961         uint8_t         config, disk;
8962 
8963         ASSERT(mutex_owned(&mpt->m_mutex));
8964 
8965         if (mptsas_debug_resets) {
8966                 mptsas_log(mpt, CE_WARN, "mptsas_do_scsi_reset: target=%d",
8967                     devhdl);
8968         }
8969 
8970         /*
8971          * Issue a Target Reset message to the target specified but not to a
8972          * disk making up a raid volume.  Just look through the RAID config
8973          * Phys Disk list of DevHandles.  If the target's DevHandle is in this
8974          * list, then don't reset this target.
8975          */
8976         for (config = 0; config < mpt->m_num_raid_configs; config++) {
8977                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
8978                         if (devhdl == mpt->m_raidconfig[config].
8979                             m_physdisk_devhdl[disk]) {
8980                                 return (TRUE);
8981                         }
8982                 }
8983         }
8984 
8985         rval = mptsas_ioc_task_management(mpt,
8986             MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, devhdl, 0, NULL, 0, 0);
8987 
8988         mptsas_doneq_empty(mpt);
8989         return (rval);
8990 }
8991 
8992 static int
8993 mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
8994         void (*callback)(caddr_t), caddr_t arg)
8995 {
8996         mptsas_t        *mpt = ADDR2MPT(ap);
8997 
8998         NDBG22(("mptsas_scsi_reset_notify: tgt=%d", ap->a_target));
8999 
9000         return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
9001             &mpt->m_mutex, &mpt->m_reset_notify_listf));
9002 }
9003 
9004 static int
9005 mptsas_get_name(struct scsi_device *sd, char *name, int len)
9006 {
9007         dev_info_t      *lun_dip = NULL;
9008 
9009         ASSERT(sd != NULL);
9010         ASSERT(name != NULL);
9011         lun_dip = sd->sd_dev;
9012         ASSERT(lun_dip != NULL);
9013 
9014         if (mptsas_name_child(lun_dip, name, len) == DDI_SUCCESS) {
9015                 return (1);
9016         } else {
9017                 return (0);
9018         }
9019 }
9020 
9021 static int
9022 mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len)
9023 {
9024         return (mptsas_get_name(sd, name, len));
9025 }
9026 
9027 void
9028 mptsas_set_throttle(mptsas_t *mpt, mptsas_target_t *ptgt, int what)
9029 {
9030 
9031         NDBG25(("mptsas_set_throttle: throttle=%x", what));
9032 
9033         /*
9034          * if the bus is draining/quiesced, no changes to the throttles
9035          * are allowed. Not allowing change of throttles during draining
9036          * limits error recovery but will reduce draining time
9037          *
9038          * all throttles should have been set to HOLD_THROTTLE
9039          */
9040         if (mpt->m_softstate & (MPTSAS_SS_QUIESCED | MPTSAS_SS_DRAINING)) {
9041                 return;
9042         }
9043 
9044         if (what == HOLD_THROTTLE) {
9045                 ptgt->m_t_throttle = HOLD_THROTTLE;
9046         } else if (ptgt->m_reset_delay == 0) {
9047                 ptgt->m_t_throttle = what;
9048         }
9049 }
9050 
9051 /*
9052  * Clean up from a device reset.
9053  * For the case of target reset, this function clears the waitq of all
9054  * commands for a particular target.   For the case of abort task set, this
9055  * function clears the waitq of all commonds for a particular target/lun.
9056  */
9057 static void
9058 mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun, uint8_t tasktype)
9059 {
9060         mptsas_slots_t  *slots = mpt->m_active;
9061         mptsas_cmd_t    *cmd, *next_cmd;
9062         int             slot;
9063         uchar_t         reason;
9064         uint_t          stat;
9065         hrtime_t        timestamp;
9066 
9067         NDBG25(("mptsas_flush_target: target=%d lun=%d", target, lun));
9068 
9069         timestamp = gethrtime();
9070 
9071         /*
9072          * Make sure the I/O Controller has flushed all cmds
9073          * that are associated with this target for a target reset
9074          * and target/lun for abort task set.
9075          * Account for TM requests, which use the last SMID.
9076          */
9077         for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
9078                 if ((cmd = slots->m_slot[slot]) == NULL)
9079                         continue;
9080                 reason = CMD_RESET;
9081                 stat = STAT_DEV_RESET;
9082                 switch (tasktype) {
9083                 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
9084                         if (Tgt(cmd) == target) {
9085                                 if (cmd->cmd_active_expiration <= timestamp) {
9086                                         /*
9087                                          * When timeout requested, propagate
9088                                          * proper reason and statistics to
9089                                          * target drivers.
9090                                          */
9091                                         reason = CMD_TIMEOUT;
9092                                         stat |= STAT_TIMEOUT;
9093                                 }
9094                                 NDBG25(("mptsas_flush_target discovered non-"
9095                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
9096                                     tasktype));
9097                                 mptsas_dump_cmd(mpt, cmd);
9098                                 mptsas_remove_cmd(mpt, cmd);
9099                                 mptsas_set_pkt_reason(mpt, cmd, reason, stat);
9100                                 mptsas_doneq_add(mpt, cmd);
9101                         }
9102                         break;
9103                 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
9104                         reason = CMD_ABORTED;
9105                         stat = STAT_ABORTED;
9106                         /*FALLTHROUGH*/
9107                 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
9108                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
9109 
9110                                 NDBG25(("mptsas_flush_target discovered non-"
9111                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
9112                                     tasktype));
9113                                 mptsas_dump_cmd(mpt, cmd);
9114                                 mptsas_remove_cmd(mpt, cmd);
9115                                 mptsas_set_pkt_reason(mpt, cmd, reason,
9116                                     stat);
9117                                 mptsas_doneq_add(mpt, cmd);
9118                         }
9119                         break;
9120                 default:
9121                         break;
9122                 }
9123         }
9124 
9125         /*
9126          * Flush the waitq and tx_waitq of this target's cmds
9127          */
9128         cmd = mpt->m_waitq;
9129 
9130         reason = CMD_RESET;
9131         stat = STAT_DEV_RESET;
9132 
9133         switch (tasktype) {
9134         case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
9135                 while (cmd != NULL) {
9136                         next_cmd = cmd->cmd_linkp;
9137                         if (Tgt(cmd) == target) {
9138                                 mptsas_waitq_delete(mpt, cmd);
9139                                 mptsas_set_pkt_reason(mpt, cmd,
9140                                     reason, stat);
9141                                 mptsas_doneq_add(mpt, cmd);
9142                         }
9143                         cmd = next_cmd;
9144                 }
9145                 mutex_enter(&mpt->m_tx_waitq_mutex);
9146                 cmd = mpt->m_tx_waitq;
9147                 while (cmd != NULL) {
9148                         next_cmd = cmd->cmd_linkp;
9149                         if (Tgt(cmd) == target) {
9150                                 mptsas_tx_waitq_delete(mpt, cmd);
9151                                 mutex_exit(&mpt->m_tx_waitq_mutex);
9152                                 mptsas_set_pkt_reason(mpt, cmd,
9153                                     reason, stat);
9154                                 mptsas_doneq_add(mpt, cmd);
9155                                 mutex_enter(&mpt->m_tx_waitq_mutex);
9156                         }
9157                         cmd = next_cmd;
9158                 }
9159                 mutex_exit(&mpt->m_tx_waitq_mutex);
9160                 break;
9161         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
9162                 reason = CMD_ABORTED;
9163                 stat =  STAT_ABORTED;
9164                 /*FALLTHROUGH*/
9165         case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
9166                 while (cmd != NULL) {
9167                         next_cmd = cmd->cmd_linkp;
9168                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
9169                                 mptsas_waitq_delete(mpt, cmd);
9170                                 mptsas_set_pkt_reason(mpt, cmd,
9171                                     reason, stat);
9172                                 mptsas_doneq_add(mpt, cmd);
9173                         }
9174                         cmd = next_cmd;
9175                 }
9176                 mutex_enter(&mpt->m_tx_waitq_mutex);
9177                 cmd = mpt->m_tx_waitq;
9178                 while (cmd != NULL) {
9179                         next_cmd = cmd->cmd_linkp;
9180                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
9181                                 mptsas_tx_waitq_delete(mpt, cmd);
9182                                 mutex_exit(&mpt->m_tx_waitq_mutex);
9183                                 mptsas_set_pkt_reason(mpt, cmd,
9184                                     reason, stat);
9185                                 mptsas_doneq_add(mpt, cmd);
9186                                 mutex_enter(&mpt->m_tx_waitq_mutex);
9187                         }
9188                         cmd = next_cmd;
9189                 }
9190                 mutex_exit(&mpt->m_tx_waitq_mutex);
9191                 break;
9192         default:
9193                 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
9194                     tasktype);
9195                 break;
9196         }
9197 }
9198 
9199 /*
9200  * Clean up hba state, abort all outstanding command and commands in waitq
9201  * reset timeout of all targets.
9202  */
9203 static void
9204 mptsas_flush_hba(mptsas_t *mpt)
9205 {
9206         mptsas_slots_t  *slots = mpt->m_active;
9207         mptsas_cmd_t    *cmd;
9208         int             slot;
9209 
9210         NDBG25(("mptsas_flush_hba"));
9211 
9212         /*
9213          * The I/O Controller should have already sent back
9214          * all commands via the scsi I/O reply frame.  Make
9215          * sure all commands have been flushed.
9216          * Account for TM request, which use the last SMID.
9217          */
9218         for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
9219                 if ((cmd = slots->m_slot[slot]) == NULL)
9220                         continue;
9221 
9222                 if (cmd->cmd_flags & CFLAG_CMDIOC) {
9223                         /*
9224                          * Need to make sure to tell everyone that might be
9225                          * waiting on this command that it's going to fail.  If
9226                          * we get here, this command will never timeout because
9227                          * the active command table is going to be re-allocated,
9228                          * so there will be nothing to check against a time out.
9229                          * Instead, mark the command as failed due to reset.
9230                          */
9231                         mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
9232                             STAT_BUS_RESET);
9233                         if ((cmd->cmd_flags &
9234                             (CFLAG_PASSTHRU | CFLAG_CONFIG | CFLAG_FW_DIAG))) {
9235                                 cmd->cmd_flags |= CFLAG_FINISHED;
9236                                 cv_broadcast(&mpt->m_passthru_cv);
9237                                 cv_broadcast(&mpt->m_config_cv);
9238                                 cv_broadcast(&mpt->m_fw_diag_cv);
9239                         }
9240                         continue;
9241                 }
9242 
9243                 NDBG25(("mptsas_flush_hba discovered non-NULL cmd in slot %d",
9244                     slot));
9245                 mptsas_dump_cmd(mpt, cmd);
9246 
9247                 mptsas_remove_cmd(mpt, cmd);
9248                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
9249                 mptsas_doneq_add(mpt, cmd);
9250         }
9251 
9252         /*
9253          * Flush the waitq.
9254          */
9255         while ((cmd = mptsas_waitq_rm(mpt)) != NULL) {
9256                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
9257                 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
9258                     (cmd->cmd_flags & CFLAG_CONFIG) ||
9259                     (cmd->cmd_flags & CFLAG_FW_DIAG)) {
9260                         cmd->cmd_flags |= CFLAG_FINISHED;
9261                         cv_broadcast(&mpt->m_passthru_cv);
9262                         cv_broadcast(&mpt->m_config_cv);
9263                         cv_broadcast(&mpt->m_fw_diag_cv);
9264                 } else {
9265                         mptsas_doneq_add(mpt, cmd);
9266                 }
9267         }
9268 
9269         /*
9270          * Flush the tx_waitq
9271          */
9272         mutex_enter(&mpt->m_tx_waitq_mutex);
9273         while ((cmd = mptsas_tx_waitq_rm(mpt)) != NULL) {
9274                 mutex_exit(&mpt->m_tx_waitq_mutex);
9275                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
9276                 mptsas_doneq_add(mpt, cmd);
9277                 mutex_enter(&mpt->m_tx_waitq_mutex);
9278         }
9279         mutex_exit(&mpt->m_tx_waitq_mutex);
9280 
9281         /*
9282          * Drain the taskqs prior to reallocating resources.
9283          */
9284         mutex_exit(&mpt->m_mutex);
9285         ddi_taskq_wait(mpt->m_event_taskq);
9286         ddi_taskq_wait(mpt->m_dr_taskq);
9287         mutex_enter(&mpt->m_mutex);
9288 }
9289 
9290 /*
9291  * set pkt_reason and OR in pkt_statistics flag
9292  */
9293 static void
9294 mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd, uchar_t reason,
9295     uint_t stat)
9296 {
9297 #ifndef __lock_lint
9298         _NOTE(ARGUNUSED(mpt))
9299 #endif
9300 
9301         NDBG25(("mptsas_set_pkt_reason: cmd=0x%p reason=%x stat=%x",
9302             (void *)cmd, reason, stat));
9303 
9304         if (cmd) {
9305                 if (cmd->cmd_pkt->pkt_reason == CMD_CMPLT) {
9306                         cmd->cmd_pkt->pkt_reason = reason;
9307                 }
9308                 cmd->cmd_pkt->pkt_statistics |= stat;
9309         }
9310 }
9311 
9312 static void
9313 mptsas_start_watch_reset_delay()
9314 {
9315         NDBG22(("mptsas_start_watch_reset_delay"));
9316 
9317         mutex_enter(&mptsas_global_mutex);
9318         if (mptsas_reset_watch == NULL && mptsas_timeouts_enabled) {
9319                 mptsas_reset_watch = timeout(mptsas_watch_reset_delay, NULL,
9320                     drv_usectohz((clock_t)
9321                     MPTSAS_WATCH_RESET_DELAY_TICK * 1000));
9322                 ASSERT(mptsas_reset_watch != NULL);
9323         }
9324         mutex_exit(&mptsas_global_mutex);
9325 }
9326 
9327 static void
9328 mptsas_setup_bus_reset_delay(mptsas_t *mpt)
9329 {
9330         mptsas_target_t *ptgt = NULL;
9331 
9332         ASSERT(MUTEX_HELD(&mpt->m_mutex));
9333 
9334         NDBG22(("mptsas_setup_bus_reset_delay"));
9335         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9336             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9337                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9338                 ptgt->m_reset_delay = mpt->m_scsi_reset_delay;
9339         }
9340 
9341         mptsas_start_watch_reset_delay();
9342 }
9343 
9344 /*
9345  * mptsas_watch_reset_delay(_subr) is invoked by timeout() and checks every
9346  * mpt instance for active reset delays
9347  */
9348 static void
9349 mptsas_watch_reset_delay(void *arg)
9350 {
9351 #ifndef __lock_lint
9352         _NOTE(ARGUNUSED(arg))
9353 #endif
9354 
9355         mptsas_t        *mpt;
9356         int             not_done = 0;
9357 
9358         NDBG22(("mptsas_watch_reset_delay"));
9359 
9360         mutex_enter(&mptsas_global_mutex);
9361         mptsas_reset_watch = 0;
9362         mutex_exit(&mptsas_global_mutex);
9363         rw_enter(&mptsas_global_rwlock, RW_READER);
9364         for (mpt = mptsas_head; mpt != NULL; mpt = mpt->m_next) {
9365                 if (mpt->m_tran == 0) {
9366                         continue;
9367                 }
9368                 mutex_enter(&mpt->m_mutex);
9369                 not_done += mptsas_watch_reset_delay_subr(mpt);
9370                 mutex_exit(&mpt->m_mutex);
9371         }
9372         rw_exit(&mptsas_global_rwlock);
9373 
9374         if (not_done) {
9375                 mptsas_start_watch_reset_delay();
9376         }
9377 }
9378 
9379 static int
9380 mptsas_watch_reset_delay_subr(mptsas_t *mpt)
9381 {
9382         int             done = 0;
9383         int             restart = 0;
9384         mptsas_target_t *ptgt = NULL;
9385 
9386         NDBG22(("mptsas_watch_reset_delay_subr: mpt=0x%p", (void *)mpt));
9387 
9388         ASSERT(mutex_owned(&mpt->m_mutex));
9389 
9390         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9391             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9392                 if (ptgt->m_reset_delay != 0) {
9393                         ptgt->m_reset_delay -=
9394                             MPTSAS_WATCH_RESET_DELAY_TICK;
9395                         if (ptgt->m_reset_delay <= 0) {
9396                                 ptgt->m_reset_delay = 0;
9397                                 mptsas_set_throttle(mpt, ptgt,
9398                                     MAX_THROTTLE);
9399                                 restart++;
9400                         } else {
9401                                 done = -1;
9402                         }
9403                 }
9404         }
9405 
9406         if (restart > 0) {
9407                 mptsas_restart_hba(mpt);
9408         }
9409         return (done);
9410 }
9411 
9412 #ifdef MPTSAS_TEST
9413 static void
9414 mptsas_test_reset(mptsas_t *mpt, int target)
9415 {
9416         mptsas_target_t    *ptgt = NULL;
9417 
9418         if (mptsas_rtest == target) {
9419                 if (mptsas_do_scsi_reset(mpt, target) == TRUE) {
9420                         mptsas_rtest = -1;
9421                 }
9422                 if (mptsas_rtest == -1) {
9423                         NDBG22(("mptsas_test_reset success"));
9424                 }
9425         }
9426 }
9427 #endif
9428 
9429 /*
9430  * abort handling:
9431  *
9432  * Notes:
9433  *      - if pkt is not NULL, abort just that command
9434  *      - if pkt is NULL, abort all outstanding commands for target
9435  */
9436 static int
9437 mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
9438 {
9439         mptsas_t                *mpt = ADDR2MPT(ap);
9440         int                     rval;
9441         mptsas_tgt_private_t    *tgt_private;
9442         int                     target, lun;
9443 
9444         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
9445             tran_tgt_private;
9446         ASSERT(tgt_private != NULL);
9447         target = tgt_private->t_private->m_devhdl;
9448         lun = tgt_private->t_lun;
9449 
9450         NDBG23(("mptsas_scsi_abort: target=%d.%d", target, lun));
9451 
9452         mutex_enter(&mpt->m_mutex);
9453         rval = mptsas_do_scsi_abort(mpt, target, lun, pkt);
9454         mutex_exit(&mpt->m_mutex);
9455         return (rval);
9456 }
9457 
9458 static int
9459 mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun, struct scsi_pkt *pkt)
9460 {
9461         mptsas_cmd_t    *sp = NULL;
9462         mptsas_slots_t  *slots = mpt->m_active;
9463         int             rval = FALSE;
9464 
9465         ASSERT(mutex_owned(&mpt->m_mutex));
9466 
9467         /*
9468          * Abort the command pkt on the target/lun in ap.  If pkt is
9469          * NULL, abort all outstanding commands on that target/lun.
9470          * If you can abort them, return 1, else return 0.
9471          * Each packet that's aborted should be sent back to the target
9472          * driver through the callback routine, with pkt_reason set to
9473          * CMD_ABORTED.
9474          *
9475          * abort cmd pkt on HBA hardware; clean out of outstanding
9476          * command lists, etc.
9477          */
9478         if (pkt != NULL) {
9479                 /* abort the specified packet */
9480                 sp = PKT2CMD(pkt);
9481 
9482                 if (sp->cmd_queued) {
9483                         NDBG23(("mptsas_do_scsi_abort: queued sp=0x%p aborted",
9484                             (void *)sp));
9485                         mptsas_waitq_delete(mpt, sp);
9486                         mptsas_set_pkt_reason(mpt, sp, CMD_ABORTED,
9487                             STAT_ABORTED);
9488                         mptsas_doneq_add(mpt, sp);
9489                         rval = TRUE;
9490                         goto done;
9491                 }
9492 
9493                 /*
9494                  * Have mpt firmware abort this command
9495                  */
9496 
9497                 if (slots->m_slot[sp->cmd_slot] != NULL) {
9498                         rval = mptsas_ioc_task_management(mpt,
9499                             MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, target,
9500                             lun, NULL, 0, 0);
9501 
9502                         /*
9503                          * The transport layer expects only TRUE and FALSE.
9504                          * Therefore, if mptsas_ioc_task_management returns
9505                          * FAILED we will return FALSE.
9506                          */
9507                         if (rval == FAILED)
9508                                 rval = FALSE;
9509                         goto done;
9510                 }
9511         }
9512 
9513         /*
9514          * If pkt is NULL then abort task set
9515          */
9516         rval = mptsas_ioc_task_management(mpt,
9517             MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, target, lun, NULL, 0, 0);
9518 
9519         /*
9520          * The transport layer expects only TRUE and FALSE.
9521          * Therefore, if mptsas_ioc_task_management returns
9522          * FAILED we will return FALSE.
9523          */
9524         if (rval == FAILED)
9525                 rval = FALSE;
9526 
9527 #ifdef MPTSAS_TEST
9528         if (rval && mptsas_test_stop) {
9529                 debug_enter("mptsas_do_scsi_abort");
9530         }
9531 #endif
9532 
9533 done:
9534         mptsas_doneq_empty(mpt);
9535         return (rval);
9536 }
9537 
9538 /*
9539  * capability handling:
9540  * (*tran_getcap).  Get the capability named, and return its value.
9541  */
9542 static int
9543 mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly)
9544 {
9545         mptsas_t        *mpt = ADDR2MPT(ap);
9546         int             ckey;
9547         int             rval = FALSE;
9548 
9549         NDBG24(("mptsas_scsi_getcap: target=%d, cap=%s tgtonly=%x",
9550             ap->a_target, cap, tgtonly));
9551 
9552         mutex_enter(&mpt->m_mutex);
9553 
9554         if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9555                 mutex_exit(&mpt->m_mutex);
9556                 return (UNDEFINED);
9557         }
9558 
9559         switch (ckey) {
9560         case SCSI_CAP_DMA_MAX:
9561                 rval = (int)mpt->m_msg_dma_attr.dma_attr_maxxfer;
9562                 break;
9563         case SCSI_CAP_ARQ:
9564                 rval = TRUE;
9565                 break;
9566         case SCSI_CAP_MSG_OUT:
9567         case SCSI_CAP_PARITY:
9568         case SCSI_CAP_UNTAGGED_QING:
9569                 rval = TRUE;
9570                 break;
9571         case SCSI_CAP_TAGGED_QING:
9572                 rval = TRUE;
9573                 break;
9574         case SCSI_CAP_RESET_NOTIFICATION:
9575                 rval = TRUE;
9576                 break;
9577         case SCSI_CAP_LINKED_CMDS:
9578                 rval = FALSE;
9579                 break;
9580         case SCSI_CAP_QFULL_RETRIES:
9581                 rval = ((mptsas_tgt_private_t *)(ap->a_hba_tran->
9582                     tran_tgt_private))->t_private->m_qfull_retries;
9583                 break;
9584         case SCSI_CAP_QFULL_RETRY_INTERVAL:
9585                 rval = drv_hztousec(((mptsas_tgt_private_t *)
9586                     (ap->a_hba_tran->tran_tgt_private))->
9587                     t_private->m_qfull_retry_interval) / 1000;
9588                 break;
9589         case SCSI_CAP_CDB_LEN:
9590                 rval = CDB_GROUP4;
9591                 break;
9592         case SCSI_CAP_INTERCONNECT_TYPE:
9593                 rval = INTERCONNECT_SAS;
9594                 break;
9595         case SCSI_CAP_TRAN_LAYER_RETRIES:
9596                 if (mpt->m_ioc_capabilities &
9597                     MPI2_IOCFACTS_CAPABILITY_TLR)
9598                         rval = TRUE;
9599                 else
9600                         rval = FALSE;
9601                 break;
9602         default:
9603                 rval = UNDEFINED;
9604                 break;
9605         }
9606 
9607         NDBG24(("mptsas_scsi_getcap: %s, rval=%x", cap, rval));
9608 
9609         mutex_exit(&mpt->m_mutex);
9610         return (rval);
9611 }
9612 
9613 /*
9614  * (*tran_setcap).  Set the capability named to the value given.
9615  */
9616 static int
9617 mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value, int tgtonly)
9618 {
9619         mptsas_t        *mpt = ADDR2MPT(ap);
9620         int             ckey;
9621         int             rval = FALSE;
9622 
9623         NDBG24(("mptsas_scsi_setcap: target=%d, cap=%s value=%x tgtonly=%x",
9624             ap->a_target, cap, value, tgtonly));
9625 
9626         if (!tgtonly) {
9627                 return (rval);
9628         }
9629 
9630         mutex_enter(&mpt->m_mutex);
9631 
9632         if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9633                 mutex_exit(&mpt->m_mutex);
9634                 return (UNDEFINED);
9635         }
9636 
9637         switch (ckey) {
9638         case SCSI_CAP_DMA_MAX:
9639         case SCSI_CAP_MSG_OUT:
9640         case SCSI_CAP_PARITY:
9641         case SCSI_CAP_INITIATOR_ID:
9642         case SCSI_CAP_LINKED_CMDS:
9643         case SCSI_CAP_UNTAGGED_QING:
9644         case SCSI_CAP_RESET_NOTIFICATION:
9645                 /*
9646                  * None of these are settable via
9647                  * the capability interface.
9648                  */
9649                 break;
9650         case SCSI_CAP_ARQ:
9651                 /*
9652                  * We cannot turn off arq so return false if asked to
9653                  */
9654                 if (value) {
9655                         rval = TRUE;
9656                 } else {
9657                         rval = FALSE;
9658                 }
9659                 break;
9660         case SCSI_CAP_TAGGED_QING:
9661                 mptsas_set_throttle(mpt, ((mptsas_tgt_private_t *)
9662                     (ap->a_hba_tran->tran_tgt_private))->t_private,
9663                     MAX_THROTTLE);
9664                 rval = TRUE;
9665                 break;
9666         case SCSI_CAP_QFULL_RETRIES:
9667                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9668                     t_private->m_qfull_retries = (uchar_t)value;
9669                 rval = TRUE;
9670                 break;
9671         case SCSI_CAP_QFULL_RETRY_INTERVAL:
9672                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9673                     t_private->m_qfull_retry_interval =
9674                     drv_usectohz(value * 1000);
9675                 rval = TRUE;
9676                 break;
9677         default:
9678                 rval = UNDEFINED;
9679                 break;
9680         }
9681         mutex_exit(&mpt->m_mutex);
9682         return (rval);
9683 }
9684 
9685 /*
9686  * Utility routine for mptsas_ifsetcap/ifgetcap
9687  */
9688 /*ARGSUSED*/
9689 static int
9690 mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp)
9691 {
9692         NDBG24(("mptsas_scsi_capchk: cap=%s", cap));
9693 
9694         if (!cap)
9695                 return (FALSE);
9696 
9697         *cidxp = scsi_hba_lookup_capstr(cap);
9698         return (TRUE);
9699 }
9700 
9701 static int
9702 mptsas_alloc_active_slots(mptsas_t *mpt, int flag)
9703 {
9704         mptsas_slots_t  *old_active = mpt->m_active;
9705         mptsas_slots_t  *new_active;
9706         size_t          size;
9707 
9708         /*
9709          * if there are active commands, then we cannot
9710          * change size of active slots array.
9711          */
9712         ASSERT(mpt->m_ncmds == 0);
9713 
9714         size = MPTSAS_SLOTS_SIZE(mpt);
9715         new_active = kmem_zalloc(size, flag);
9716         if (new_active == NULL) {
9717                 NDBG1(("new active alloc failed"));
9718                 return (-1);
9719         }
9720         /*
9721          * Since SMID 0 is reserved and the TM slot is reserved, the
9722          * number of slots that can be used at any one time is
9723          * m_max_requests - 2.
9724          */
9725         new_active->m_n_normal = (mpt->m_max_requests - 2);
9726         new_active->m_size = size;
9727         new_active->m_rotor = 1;
9728         if (old_active)
9729                 mptsas_free_active_slots(mpt);
9730         mpt->m_active = new_active;
9731 
9732         return (0);
9733 }
9734 
9735 static void
9736 mptsas_free_active_slots(mptsas_t *mpt)
9737 {
9738         mptsas_slots_t  *active = mpt->m_active;
9739         size_t          size;
9740 
9741         if (active == NULL)
9742                 return;
9743         size = active->m_size;
9744         kmem_free(active, size);
9745         mpt->m_active = NULL;
9746 }
9747 
9748 /*
9749  * Error logging, printing, and debug print routines.
9750  */
9751 static char *mptsas_label = "mpt_sas";
9752 
9753 /*PRINTFLIKE3*/
9754 void
9755 mptsas_log(mptsas_t *mpt, int level, char *fmt, ...)
9756 {
9757         dev_info_t      *dev;
9758         va_list         ap;
9759 
9760         if (mpt) {
9761                 dev = mpt->m_dip;
9762         } else {
9763                 dev = 0;
9764         }
9765 
9766         mutex_enter(&mptsas_log_mutex);
9767 
9768         va_start(ap, fmt);
9769         (void) vsprintf(mptsas_log_buf, fmt, ap);
9770         va_end(ap);
9771 
9772         if (level == CE_CONT) {
9773                 scsi_log(dev, mptsas_label, level, "%s\n", mptsas_log_buf);
9774         } else {
9775                 scsi_log(dev, mptsas_label, level, "%s", mptsas_log_buf);
9776         }
9777 
9778         mutex_exit(&mptsas_log_mutex);
9779 }
9780 
9781 #ifdef MPTSAS_DEBUG
9782 /*
9783  * Use a circular buffer to log messages to private memory.
9784  * Increment idx atomically to minimize risk to miss lines.
9785  * It's fast and does not hold up the proceedings too much.
9786  */
9787 static const size_t mptsas_dbglog_linecnt = MPTSAS_DBGLOG_LINECNT;
9788 static const size_t mptsas_dbglog_linelen = MPTSAS_DBGLOG_LINELEN;
9789 static char mptsas_dbglog_bufs[MPTSAS_DBGLOG_LINECNT][MPTSAS_DBGLOG_LINELEN];
9790 static uint32_t mptsas_dbglog_idx = 0;
9791 
9792 /*PRINTFLIKE1*/
9793 void
9794 mptsas_debug_log(char *fmt, ...)
9795 {
9796         va_list         ap;
9797         uint32_t        idx;
9798 
9799         idx = atomic_inc_32_nv(&mptsas_dbglog_idx) &
9800             (mptsas_dbglog_linecnt - 1);
9801 
9802         va_start(ap, fmt);
9803         (void) vsnprintf(mptsas_dbglog_bufs[idx],
9804             mptsas_dbglog_linelen, fmt, ap);
9805         va_end(ap);
9806 }
9807 
9808 /*PRINTFLIKE1*/
9809 void
9810 mptsas_printf(char *fmt, ...)
9811 {
9812         dev_info_t      *dev = 0;
9813         va_list         ap;
9814 
9815         mutex_enter(&mptsas_log_mutex);
9816 
9817         va_start(ap, fmt);
9818         (void) vsprintf(mptsas_log_buf, fmt, ap);
9819         va_end(ap);
9820 
9821 #ifdef PROM_PRINTF
9822         prom_printf("%s:\t%s\n", mptsas_label, mptsas_log_buf);
9823 #else
9824         scsi_log(dev, mptsas_label, CE_CONT, "!%s\n", mptsas_log_buf);
9825 #endif
9826         mutex_exit(&mptsas_log_mutex);
9827 }
9828 #endif
9829 
9830 /*
9831  * timeout handling
9832  */
9833 static void
9834 mptsas_watch(void *arg)
9835 {
9836 #ifndef __lock_lint
9837         _NOTE(ARGUNUSED(arg))
9838 #endif
9839 
9840         mptsas_t        *mpt;
9841         uint32_t        doorbell;
9842 
9843         NDBG30(("mptsas_watch"));
9844 
9845         rw_enter(&mptsas_global_rwlock, RW_READER);
9846         for (mpt = mptsas_head; mpt != (mptsas_t *)NULL; mpt = mpt->m_next) {
9847 
9848                 mutex_enter(&mpt->m_mutex);
9849 
9850                 /* Skip device if not powered on */
9851                 if (mpt->m_options & MPTSAS_OPT_PM) {
9852                         if (mpt->m_power_level == PM_LEVEL_D0) {
9853                                 (void) pm_busy_component(mpt->m_dip, 0);
9854                                 mpt->m_busy = 1;
9855                         } else {
9856                                 mutex_exit(&mpt->m_mutex);
9857                                 continue;
9858                         }
9859                 }
9860 
9861                 /*
9862                  * Check if controller is in a FAULT state. If so, reset it.
9863                  */
9864                 doorbell = ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell);
9865                 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
9866                         doorbell &= MPI2_DOORBELL_DATA_MASK;
9867                         mptsas_log(mpt, CE_WARN, "MPT Firmware Fault, "
9868                             "code: %04x", doorbell);
9869                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
9870                         if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
9871                                 mptsas_log(mpt, CE_WARN, "Reset failed"
9872                                     "after fault was detected");
9873                         }
9874                 }
9875 
9876                 /*
9877                  * For now, always call mptsas_watchsubr.
9878                  */
9879                 mptsas_watchsubr(mpt);
9880 
9881                 if (mpt->m_options & MPTSAS_OPT_PM) {
9882                         mpt->m_busy = 0;
9883                         (void) pm_idle_component(mpt->m_dip, 0);
9884                 }
9885 
9886                 mutex_exit(&mpt->m_mutex);
9887         }
9888         rw_exit(&mptsas_global_rwlock);
9889 
9890         mutex_enter(&mptsas_global_mutex);
9891         if (mptsas_timeouts_enabled)
9892                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
9893         mutex_exit(&mptsas_global_mutex);
9894 }
9895 
9896 static void
9897 mptsas_watchsubr(mptsas_t *mpt)
9898 {
9899         int             i;
9900         mptsas_cmd_t    *cmd;
9901         mptsas_target_t *ptgt = NULL;
9902         hrtime_t        timestamp = gethrtime();
9903 
9904         ASSERT(MUTEX_HELD(&mpt->m_mutex));
9905 
9906         NDBG30(("mptsas_watchsubr: mpt=0x%p", (void *)mpt));
9907 
9908 #ifdef MPTSAS_TEST
9909         if (mptsas_enable_untagged) {
9910                 mptsas_test_untagged++;
9911         }
9912 #endif
9913 
9914         /*
9915          * Check for commands stuck in active slot
9916          * Account for TM requests, which use the last SMID.
9917          */
9918         for (i = 0; i <= mpt->m_active->m_n_normal; i++) {
9919                 if ((cmd = mpt->m_active->m_slot[i]) != NULL) {
9920                         if (cmd->cmd_active_expiration <= timestamp) {
9921                                 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
9922                                         /*
9923                                          * There seems to be a command stuck
9924                                          * in the active slot.  Drain throttle.
9925                                          */
9926                                         mptsas_set_throttle(mpt,
9927                                             cmd->cmd_tgt_addr,
9928                                             DRAIN_THROTTLE);
9929                                 } else if (cmd->cmd_flags &
9930                                     (CFLAG_PASSTHRU | CFLAG_CONFIG |
9931                                     CFLAG_FW_DIAG)) {
9932                                         /*
9933                                          * passthrough command timeout
9934                                          */
9935                                         cmd->cmd_flags |= (CFLAG_FINISHED |
9936                                             CFLAG_TIMEOUT);
9937                                         cv_broadcast(&mpt->m_passthru_cv);
9938                                         cv_broadcast(&mpt->m_config_cv);
9939                                         cv_broadcast(&mpt->m_fw_diag_cv);
9940                                 }
9941                         }
9942                 }
9943         }
9944 
9945         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9946             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9947                 /*
9948                  * If we were draining due to a qfull condition,
9949                  * go back to full throttle.
9950                  */
9951                 if ((ptgt->m_t_throttle < MAX_THROTTLE) &&
9952                     (ptgt->m_t_throttle > HOLD_THROTTLE) &&
9953                     (ptgt->m_t_ncmds < ptgt->m_t_throttle)) {
9954                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9955                         mptsas_restart_hba(mpt);
9956                 }
9957 
9958                 cmd = TAILQ_LAST(&ptgt->m_active_cmdq, mptsas_active_cmdq);
9959                 if (cmd == NULL)
9960                         continue;
9961 
9962                 if (cmd->cmd_active_expiration <= timestamp) {
9963                         /*
9964                          * Earliest command timeout expired. Drain throttle.
9965                          */
9966                         mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
9967 
9968                         /*
9969                          * Check for remaining commands.
9970                          */
9971                         cmd = TAILQ_FIRST(&ptgt->m_active_cmdq);
9972                         if (cmd->cmd_active_expiration > timestamp) {
9973                                 /*
9974                                  * Wait for remaining commands to complete or
9975                                  * time out.
9976                                  */
9977                                 NDBG23(("command timed out, pending drain"));
9978                                 continue;
9979                         }
9980 
9981                         /*
9982                          * All command timeouts expired.
9983                          */
9984                         mptsas_log(mpt, CE_NOTE, "Timeout of %d seconds "
9985                             "expired with %d commands on target %d lun %d.",
9986                             cmd->cmd_pkt->pkt_time, ptgt->m_t_ncmds,
9987                             ptgt->m_devhdl, Lun(cmd));
9988 
9989                         mptsas_cmd_timeout(mpt, ptgt);
9990                 } else if (cmd->cmd_active_expiration <=
9991                     timestamp + (hrtime_t)mptsas_scsi_watchdog_tick * NANOSEC) {
9992                         NDBG23(("pending timeout"));
9993                         mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
9994                 }
9995         }
9996 }
9997 
9998 /*
9999  * timeout recovery
10000  */
10001 static void
10002 mptsas_cmd_timeout(mptsas_t *mpt, mptsas_target_t *ptgt)
10003 {
10004         uint16_t        devhdl;
10005         uint64_t        sas_wwn;
10006         uint8_t         phy;
10007         char            wwn_str[MPTSAS_WWN_STRLEN];
10008 
10009         devhdl = ptgt->m_devhdl;
10010         sas_wwn = ptgt->m_addr.mta_wwn;
10011         phy = ptgt->m_phynum;
10012         if (sas_wwn == 0) {
10013                 (void) sprintf(wwn_str, "p%x", phy);
10014         } else {
10015                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
10016         }
10017 
10018         NDBG29(("mptsas_cmd_timeout: target=%d", devhdl));
10019         mptsas_log(mpt, CE_WARN, "Disconnected command timeout for "
10020             "target %d %s, enclosure %u", devhdl, wwn_str,
10021             ptgt->m_enclosure);
10022 
10023         /*
10024          * Abort all outstanding commands on the device.
10025          */
10026         NDBG29(("mptsas_cmd_timeout: device reset"));
10027         if (mptsas_do_scsi_reset(mpt, devhdl) != TRUE) {
10028                 mptsas_log(mpt, CE_WARN, "Target %d reset for command timeout "
10029                     "recovery failed!", devhdl);
10030         }
10031 }
10032 
10033 /*
10034  * Device / Hotplug control
10035  */
10036 static int
10037 mptsas_scsi_quiesce(dev_info_t *dip)
10038 {
10039         mptsas_t        *mpt;
10040         scsi_hba_tran_t *tran;
10041 
10042         tran = ddi_get_driver_private(dip);
10043         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
10044                 return (-1);
10045 
10046         return (mptsas_quiesce_bus(mpt));
10047 }
10048 
10049 static int
10050 mptsas_scsi_unquiesce(dev_info_t *dip)
10051 {
10052         mptsas_t                *mpt;
10053         scsi_hba_tran_t *tran;
10054 
10055         tran = ddi_get_driver_private(dip);
10056         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
10057                 return (-1);
10058 
10059         return (mptsas_unquiesce_bus(mpt));
10060 }
10061 
10062 static int
10063 mptsas_quiesce_bus(mptsas_t *mpt)
10064 {
10065         mptsas_target_t *ptgt = NULL;
10066 
10067         NDBG28(("mptsas_quiesce_bus"));
10068         mutex_enter(&mpt->m_mutex);
10069 
10070         /* Set all the throttles to zero */
10071         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
10072             ptgt = refhash_next(mpt->m_targets, ptgt)) {
10073                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
10074         }
10075 
10076         /* If there are any outstanding commands in the queue */
10077         if (mpt->m_ncmds) {
10078                 mpt->m_softstate |= MPTSAS_SS_DRAINING;
10079                 mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
10080                     mpt, (MPTSAS_QUIESCE_TIMEOUT * drv_usectohz(1000000)));
10081                 if (cv_wait_sig(&mpt->m_cv, &mpt->m_mutex) == 0) {
10082                         /*
10083                          * Quiesce has been interrupted
10084                          */
10085                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
10086                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
10087                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
10088                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
10089                         }
10090                         mptsas_restart_hba(mpt);
10091                         if (mpt->m_quiesce_timeid != 0) {
10092                                 timeout_id_t tid = mpt->m_quiesce_timeid;
10093                                 mpt->m_quiesce_timeid = 0;
10094                                 mutex_exit(&mpt->m_mutex);
10095                                 (void) untimeout(tid);
10096                                 return (-1);
10097                         }
10098                         mutex_exit(&mpt->m_mutex);
10099                         return (-1);
10100                 } else {
10101                         /* Bus has been quiesced */
10102                         ASSERT(mpt->m_quiesce_timeid == 0);
10103                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
10104                         mpt->m_softstate |= MPTSAS_SS_QUIESCED;
10105                         mutex_exit(&mpt->m_mutex);
10106                         return (0);
10107                 }
10108         }
10109         /* Bus was not busy - QUIESCED */
10110         mutex_exit(&mpt->m_mutex);
10111 
10112         return (0);
10113 }
10114 
10115 static int
10116 mptsas_unquiesce_bus(mptsas_t *mpt)
10117 {
10118         mptsas_target_t *ptgt = NULL;
10119 
10120         NDBG28(("mptsas_unquiesce_bus"));
10121         mutex_enter(&mpt->m_mutex);
10122         mpt->m_softstate &= ~MPTSAS_SS_QUIESCED;
10123         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
10124             ptgt = refhash_next(mpt->m_targets, ptgt)) {
10125                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
10126         }
10127         mptsas_restart_hba(mpt);
10128         mutex_exit(&mpt->m_mutex);
10129         return (0);
10130 }
10131 
10132 static void
10133 mptsas_ncmds_checkdrain(void *arg)
10134 {
10135         mptsas_t        *mpt = arg;
10136         mptsas_target_t *ptgt = NULL;
10137 
10138         mutex_enter(&mpt->m_mutex);
10139         if (mpt->m_softstate & MPTSAS_SS_DRAINING) {
10140                 mpt->m_quiesce_timeid = 0;
10141                 if (mpt->m_ncmds == 0) {
10142                         /* Command queue has been drained */
10143                         cv_signal(&mpt->m_cv);
10144                 } else {
10145                         /*
10146                          * The throttle may have been reset because
10147                          * of a SCSI bus reset
10148                          */
10149                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
10150                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
10151                                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
10152                         }
10153 
10154                         mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
10155                             mpt, (MPTSAS_QUIESCE_TIMEOUT *
10156                             drv_usectohz(1000000)));
10157                 }
10158         }
10159         mutex_exit(&mpt->m_mutex);
10160 }
10161 
10162 /*ARGSUSED*/
10163 static void
10164 mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
10165 {
10166         int     i;
10167         uint8_t *cp = (uchar_t *)cmd->cmd_pkt->pkt_cdbp;
10168         char    buf[128];
10169 
10170         buf[0] = '\0';
10171         NDBG25(("?Cmd (0x%p) dump for Target %d Lun %d:\n", (void *)cmd,
10172             Tgt(cmd), Lun(cmd)));
10173         (void) sprintf(&buf[0], "\tcdb=[");
10174         for (i = 0; i < (int)cmd->cmd_cdblen; i++) {
10175                 (void) sprintf(&buf[strlen(buf)], " 0x%x", *cp++);
10176         }
10177         (void) sprintf(&buf[strlen(buf)], " ]");
10178         NDBG25(("?%s\n", buf));
10179         NDBG25(("?pkt_flags=0x%x pkt_statistics=0x%x pkt_state=0x%x\n",
10180             cmd->cmd_pkt->pkt_flags, cmd->cmd_pkt->pkt_statistics,
10181             cmd->cmd_pkt->pkt_state));
10182         NDBG25(("?pkt_scbp=0x%x cmd_flags=0x%x\n", cmd->cmd_pkt->pkt_scbp ?
10183             *(cmd->cmd_pkt->pkt_scbp) : 0, cmd->cmd_flags));
10184 }
10185 
10186 static void
10187 mptsas_passthru_sge(ddi_acc_handle_t acc_hdl, mptsas_pt_request_t *pt,
10188     pMpi2SGESimple64_t sgep)
10189 {
10190         uint32_t                sge_flags;
10191         uint32_t                data_size, dataout_size;
10192         ddi_dma_cookie_t        data_cookie;
10193         ddi_dma_cookie_t        dataout_cookie;
10194 
10195         data_size = pt->data_size;
10196         dataout_size = pt->dataout_size;
10197         data_cookie = pt->data_cookie;
10198         dataout_cookie = pt->dataout_cookie;
10199 
10200         if (dataout_size) {
10201                 sge_flags = dataout_size |
10202                     ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
10203                     MPI2_SGE_FLAGS_END_OF_BUFFER |
10204                     MPI2_SGE_FLAGS_HOST_TO_IOC |
10205                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
10206                     MPI2_SGE_FLAGS_SHIFT);
10207                 ddi_put32(acc_hdl, &sgep->FlagsLength, sge_flags);
10208                 ddi_put32(acc_hdl, &sgep->Address.Low,
10209                     (uint32_t)(dataout_cookie.dmac_laddress &
10210                     0xffffffffull));
10211                 ddi_put32(acc_hdl, &sgep->Address.High,
10212                     (uint32_t)(dataout_cookie.dmac_laddress
10213                     >> 32));
10214                 sgep++;
10215         }
10216         sge_flags = data_size;
10217         sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
10218             MPI2_SGE_FLAGS_LAST_ELEMENT |
10219             MPI2_SGE_FLAGS_END_OF_BUFFER |
10220             MPI2_SGE_FLAGS_END_OF_LIST |
10221             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
10222             MPI2_SGE_FLAGS_SHIFT);
10223         if (pt->direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10224                 sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_HOST_TO_IOC) <<
10225                     MPI2_SGE_FLAGS_SHIFT);
10226         } else {
10227                 sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_IOC_TO_HOST) <<
10228                     MPI2_SGE_FLAGS_SHIFT);
10229         }
10230         ddi_put32(acc_hdl, &sgep->FlagsLength,
10231             sge_flags);
10232         ddi_put32(acc_hdl, &sgep->Address.Low,
10233             (uint32_t)(data_cookie.dmac_laddress &
10234             0xffffffffull));
10235         ddi_put32(acc_hdl, &sgep->Address.High,
10236             (uint32_t)(data_cookie.dmac_laddress >> 32));
10237 }
10238 
10239 static void
10240 mptsas_passthru_ieee_sge(ddi_acc_handle_t acc_hdl, mptsas_pt_request_t *pt,
10241     pMpi2IeeeSgeSimple64_t ieeesgep)
10242 {
10243         uint8_t                 sge_flags;
10244         uint32_t                data_size, dataout_size;
10245         ddi_dma_cookie_t        data_cookie;
10246         ddi_dma_cookie_t        dataout_cookie;
10247 
10248         data_size = pt->data_size;
10249         dataout_size = pt->dataout_size;
10250         data_cookie = pt->data_cookie;
10251         dataout_cookie = pt->dataout_cookie;
10252 
10253         sge_flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
10254             MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
10255         if (dataout_size) {
10256                 ddi_put32(acc_hdl, &ieeesgep->Length, dataout_size);
10257                 ddi_put32(acc_hdl, &ieeesgep->Address.Low,
10258                     (uint32_t)(dataout_cookie.dmac_laddress &
10259                     0xffffffffull));
10260                 ddi_put32(acc_hdl, &ieeesgep->Address.High,
10261                     (uint32_t)(dataout_cookie.dmac_laddress >> 32));
10262                 ddi_put8(acc_hdl, &ieeesgep->Flags, sge_flags);
10263                 ieeesgep++;
10264         }
10265         sge_flags |= MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
10266         ddi_put32(acc_hdl, &ieeesgep->Length, data_size);
10267         ddi_put32(acc_hdl, &ieeesgep->Address.Low,
10268             (uint32_t)(data_cookie.dmac_laddress & 0xffffffffull));
10269         ddi_put32(acc_hdl, &ieeesgep->Address.High,
10270             (uint32_t)(data_cookie.dmac_laddress >> 32));
10271         ddi_put8(acc_hdl, &ieeesgep->Flags, sge_flags);
10272 }
10273 
10274 static void
10275 mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd)
10276 {
10277         caddr_t                 memp;
10278         pMPI2RequestHeader_t    request_hdrp;
10279         struct scsi_pkt         *pkt = cmd->cmd_pkt;
10280         mptsas_pt_request_t     *pt = pkt->pkt_ha_private;
10281         uint32_t                request_size;
10282         uint32_t                i;
10283         uint64_t                request_desc = 0;
10284         uint8_t                 desc_type;
10285         uint16_t                SMID;
10286         uint8_t                 *request, function;
10287         ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
10288         ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
10289 
10290         desc_type = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
10291 
10292         request = pt->request;
10293         request_size = pt->request_size;
10294 
10295         SMID = cmd->cmd_slot;
10296 
10297         /*
10298          * Store the passthrough message in memory location
10299          * corresponding to our slot number
10300          */
10301         memp = mpt->m_req_frame + (mpt->m_req_frame_size * SMID);
10302         request_hdrp = (pMPI2RequestHeader_t)memp;
10303         bzero(memp, mpt->m_req_frame_size);
10304 
10305         for (i = 0; i < request_size; i++) {
10306                 bcopy(request + i, memp + i, 1);
10307         }
10308 
10309         NDBG15(("mptsas_start_passthru: Func 0x%x, MsgFlags 0x%x, "
10310             "size=%d, in %d, out %d, SMID %d", request_hdrp->Function,
10311             request_hdrp->MsgFlags, request_size,
10312             pt->data_size, pt->dataout_size, SMID));
10313 
10314         /*
10315          * Add an SGE, even if the length is zero.
10316          */
10317         if (mpt->m_MPI25 && pt->simple == 0) {
10318                 mptsas_passthru_ieee_sge(acc_hdl, pt,
10319                     (pMpi2IeeeSgeSimple64_t)
10320                     ((uint8_t *)request_hdrp + pt->sgl_offset));
10321         } else {
10322                 mptsas_passthru_sge(acc_hdl, pt,
10323                     (pMpi2SGESimple64_t)
10324                     ((uint8_t *)request_hdrp + pt->sgl_offset));
10325         }
10326 
10327         function = request_hdrp->Function;
10328         if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
10329             (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
10330                 pMpi2SCSIIORequest_t    scsi_io_req;
10331                 caddr_t                 arsbuf;
10332                 uint8_t                 ars_size;
10333                 uint32_t                ars_dmaaddrlow;
10334 
10335                 NDBG15(("mptsas_start_passthru: Is SCSI IO Req"));
10336                 scsi_io_req = (pMpi2SCSIIORequest_t)request_hdrp;
10337 
10338                 if (cmd->cmd_extrqslen != 0) {
10339                         /*
10340                          * Mapping of the buffer was done in
10341                          * mptsas_do_passthru().
10342                          * Calculate the DMA address with the same offset.
10343                          */
10344                         arsbuf = cmd->cmd_arq_buf;
10345                         ars_size = cmd->cmd_extrqslen;
10346                         ars_dmaaddrlow = (mpt->m_req_sense_dma_addr +
10347                             ((uintptr_t)arsbuf - (uintptr_t)mpt->m_req_sense)) &
10348                             0xffffffffu;
10349                 } else {
10350                         arsbuf = mpt->m_req_sense +
10351                             (mpt->m_req_sense_size * (SMID-1));
10352                         cmd->cmd_arq_buf = arsbuf;
10353                         ars_size = mpt->m_req_sense_size;
10354                         ars_dmaaddrlow = (mpt->m_req_sense_dma_addr +
10355                             (mpt->m_req_sense_size * (SMID-1))) &
10356                             0xffffffffu;
10357                 }
10358                 bzero(arsbuf, ars_size);
10359 
10360                 ddi_put8(acc_hdl, &scsi_io_req->SenseBufferLength, ars_size);
10361                 ddi_put32(acc_hdl, &scsi_io_req->SenseBufferLowAddress,
10362                     ars_dmaaddrlow);
10363 
10364                 /*
10365                  * Put SGE for data and data_out buffer at the end of
10366                  * scsi_io_request message header.(64 bytes in total)
10367                  * Set SGLOffset0 value
10368                  */
10369                 ddi_put8(acc_hdl, &scsi_io_req->SGLOffset0,
10370                     offsetof(MPI2_SCSI_IO_REQUEST, SGL) / 4);
10371 
10372                 /*
10373                  * Setup descriptor info.  RAID passthrough must use the
10374                  * default request descriptor which is already set, so if this
10375                  * is a SCSI IO request, change the descriptor to SCSI IO.
10376                  */
10377                 if (function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
10378                         desc_type = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
10379                         request_desc = ((uint64_t)ddi_get16(acc_hdl,
10380                             &scsi_io_req->DevHandle) << 48);
10381                 }
10382                 (void) ddi_dma_sync(mpt->m_dma_req_sense_hdl, 0, 0,
10383                     DDI_DMA_SYNC_FORDEV);
10384         }
10385 
10386         /*
10387          * We must wait till the message has been completed before
10388          * beginning the next message so we wait for this one to
10389          * finish.
10390          */
10391         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
10392         request_desc |= (SMID << 16) + desc_type;
10393         cmd->cmd_rfm = NULL;
10394         MPTSAS_START_CMD(mpt, request_desc);
10395         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
10396             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
10397                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
10398         }
10399 }
10400 
10401 typedef void (mptsas_pre_f)(mptsas_t *, mptsas_pt_request_t *);
10402 static mptsas_pre_f     mpi_pre_ioc_facts;
10403 static mptsas_pre_f     mpi_pre_port_facts;
10404 static mptsas_pre_f     mpi_pre_fw_download;
10405 static mptsas_pre_f     mpi_pre_fw_25_download;
10406 static mptsas_pre_f     mpi_pre_fw_upload;
10407 static mptsas_pre_f     mpi_pre_fw_25_upload;
10408 static mptsas_pre_f     mpi_pre_sata_passthrough;
10409 static mptsas_pre_f     mpi_pre_smp_passthrough;
10410 static mptsas_pre_f     mpi_pre_config;
10411 static mptsas_pre_f     mpi_pre_sas_io_unit_control;
10412 static mptsas_pre_f     mpi_pre_scsi_io_req;
10413 
10414 /*
10415  * Prepare the pt for a SAS2 FW_DOWNLOAD request.
10416  */
10417 static void
10418 mpi_pre_fw_download(mptsas_t *mpt, mptsas_pt_request_t *pt)
10419 {
10420         pMpi2FWDownloadTCSGE_t tcsge;
10421         pMpi2FWDownloadRequest req;
10422 
10423         /*
10424          * If SAS3, call separate function.
10425          */
10426         if (mpt->m_MPI25) {
10427                 mpi_pre_fw_25_download(mpt, pt);
10428                 return;
10429         }
10430 
10431         /*
10432          * User requests should come in with the Transaction
10433          * context element where the SGL will go. Putting the
10434          * SGL after that seems to work, but don't really know
10435          * why. Other drivers tend to create an extra SGL and
10436          * refer to the TCE through that.
10437          */
10438         req = (pMpi2FWDownloadRequest)pt->request;
10439         tcsge = (pMpi2FWDownloadTCSGE_t)&req->SGL;
10440         if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
10441             tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
10442                 mptsas_log(mpt, CE_WARN, "FW Download tce invalid!");
10443         }
10444 
10445         pt->sgl_offset = offsetof(MPI2_FW_DOWNLOAD_REQUEST, SGL) +
10446             sizeof (*tcsge);
10447         if (pt->request_size != pt->sgl_offset)
10448                 NDBG15(("mpi_pre_fw_download(): Incorrect req size, "
10449                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10450                     (int)pt->request_size, (int)pt->sgl_offset,
10451                     (int)pt->dataout_size));
10452         if (pt->data_size < sizeof (MPI2_FW_DOWNLOAD_REPLY))
10453                 NDBG15(("mpi_pre_fw_download(): Incorrect rep size, "
10454                     "0x%x, should be 0x%x", pt->data_size,
10455                     (int)sizeof (MPI2_FW_DOWNLOAD_REPLY)));
10456 }
10457 
10458 /*
10459  * Prepare the pt for a SAS3 FW_DOWNLOAD request.
10460  */
10461 static void
10462 mpi_pre_fw_25_download(mptsas_t *mpt, mptsas_pt_request_t *pt)
10463 {
10464         pMpi2FWDownloadTCSGE_t tcsge;
10465         pMpi2FWDownloadRequest req2;
10466         pMpi25FWDownloadRequest req25;
10467 
10468         /*
10469          * User requests should come in with the Transaction
10470          * context element where the SGL will go. The new firmware
10471          * Doesn't use TCE and has space in the main request for
10472          * this information. So move to the right place.
10473          */
10474         req2 = (pMpi2FWDownloadRequest)pt->request;
10475         req25 = (pMpi25FWDownloadRequest)pt->request;
10476         tcsge = (pMpi2FWDownloadTCSGE_t)&req2->SGL;
10477         if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
10478             tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
10479                 mptsas_log(mpt, CE_WARN, "FW Download tce invalid!");
10480         }
10481         req25->ImageOffset = tcsge->ImageOffset;
10482         req25->ImageSize = tcsge->ImageSize;
10483 
10484         pt->sgl_offset = offsetof(MPI25_FW_DOWNLOAD_REQUEST, SGL);
10485         if (pt->request_size != pt->sgl_offset)
10486                 NDBG15(("mpi_pre_fw_25_download(): Incorrect req size, "
10487                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10488                     pt->request_size, pt->sgl_offset,
10489                     pt->dataout_size));
10490         if (pt->data_size < sizeof (MPI2_FW_DOWNLOAD_REPLY))
10491                 NDBG15(("mpi_pre_fw_25_download(): Incorrect rep size, "
10492                     "0x%x, should be 0x%x", pt->data_size,
10493                     (int)sizeof (MPI2_FW_UPLOAD_REPLY)));
10494 }
10495 
10496 /*
10497  * Prepare the pt for a SAS2 FW_UPLOAD request.
10498  */
10499 static void
10500 mpi_pre_fw_upload(mptsas_t *mpt, mptsas_pt_request_t *pt)
10501 {
10502         pMpi2FWUploadTCSGE_t tcsge;
10503         pMpi2FWUploadRequest_t req;
10504 
10505         /*
10506          * If SAS3, call separate function.
10507          */
10508         if (mpt->m_MPI25) {
10509                 mpi_pre_fw_25_upload(mpt, pt);
10510                 return;
10511         }
10512 
10513         /*
10514          * User requests should come in with the Transaction
10515          * context element where the SGL will go. Putting the
10516          * SGL after that seems to work, but don't really know
10517          * why. Other drivers tend to create an extra SGL and
10518          * refer to the TCE through that.
10519          */
10520         req = (pMpi2FWUploadRequest_t)pt->request;
10521         tcsge = (pMpi2FWUploadTCSGE_t)&req->SGL;
10522         if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
10523             tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
10524                 mptsas_log(mpt, CE_WARN, "FW Upload tce invalid!");
10525         }
10526 
10527         pt->sgl_offset = offsetof(MPI2_FW_UPLOAD_REQUEST, SGL) +
10528             sizeof (*tcsge);
10529         if (pt->request_size != pt->sgl_offset)
10530                 NDBG15(("mpi_pre_fw_upload(): Incorrect req size, "
10531                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10532                     pt->request_size, pt->sgl_offset,
10533                     pt->dataout_size));
10534         if (pt->data_size < sizeof (MPI2_FW_UPLOAD_REPLY))
10535                 NDBG15(("mpi_pre_fw_upload(): Incorrect rep size, "
10536                     "0x%x, should be 0x%x", pt->data_size,
10537                     (int)sizeof (MPI2_FW_UPLOAD_REPLY)));
10538 }
10539 
10540 /*
10541  * Prepare the pt a SAS3 FW_UPLOAD request.
10542  */
10543 static void
10544 mpi_pre_fw_25_upload(mptsas_t *mpt, mptsas_pt_request_t *pt)
10545 {
10546         pMpi2FWUploadTCSGE_t tcsge;
10547         pMpi2FWUploadRequest_t req2;
10548         pMpi25FWUploadRequest_t req25;
10549 
10550         /*
10551          * User requests should come in with the Transaction
10552          * context element where the SGL will go. The new firmware
10553          * Doesn't use TCE and has space in the main request for
10554          * this information. So move to the right place.
10555          */
10556         req2 = (pMpi2FWUploadRequest_t)pt->request;
10557         req25 = (pMpi25FWUploadRequest_t)pt->request;
10558         tcsge = (pMpi2FWUploadTCSGE_t)&req2->SGL;
10559         if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
10560             tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
10561                 mptsas_log(mpt, CE_WARN, "FW Upload tce invalid!");
10562         }
10563         req25->ImageOffset = tcsge->ImageOffset;
10564         req25->ImageSize = tcsge->ImageSize;
10565 
10566         pt->sgl_offset = offsetof(MPI25_FW_UPLOAD_REQUEST, SGL);
10567         if (pt->request_size != pt->sgl_offset)
10568                 NDBG15(("mpi_pre_fw_25_upload(): Incorrect req size, "
10569                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10570                     pt->request_size, pt->sgl_offset,
10571                     pt->dataout_size));
10572         if (pt->data_size < sizeof (MPI2_FW_UPLOAD_REPLY))
10573                 NDBG15(("mpi_pre_fw_25_upload(): Incorrect rep size, "
10574                     "0x%x, should be 0x%x", pt->data_size,
10575                     (int)sizeof (MPI2_FW_UPLOAD_REPLY)));
10576 }
10577 
10578 /*
10579  * Prepare the pt for an IOC_FACTS request.
10580  */
10581 static void
10582 mpi_pre_ioc_facts(mptsas_t *mpt, mptsas_pt_request_t *pt)
10583 {
10584 #ifndef __lock_lint
10585         _NOTE(ARGUNUSED(mpt))
10586 #endif
10587         if (pt->request_size != sizeof (MPI2_IOC_FACTS_REQUEST))
10588                 NDBG15(("mpi_pre_ioc_facts(): Incorrect req size, "
10589                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10590                     pt->request_size,
10591                     (int)sizeof (MPI2_IOC_FACTS_REQUEST),
10592                     pt->dataout_size));
10593         if (pt->data_size != sizeof (MPI2_IOC_FACTS_REPLY))
10594                 NDBG15(("mpi_pre_ioc_facts(): Incorrect rep size, "
10595                     "0x%x, should be 0x%x", pt->data_size,
10596                     (int)sizeof (MPI2_IOC_FACTS_REPLY)));
10597         pt->sgl_offset = (uint16_t)pt->request_size;
10598 }
10599 
10600 /*
10601  * Prepare the pt for a PORT_FACTS request.
10602  */
10603 static void
10604 mpi_pre_port_facts(mptsas_t *mpt, mptsas_pt_request_t *pt)
10605 {
10606 #ifndef __lock_lint
10607         _NOTE(ARGUNUSED(mpt))
10608 #endif
10609         if (pt->request_size != sizeof (MPI2_PORT_FACTS_REQUEST))
10610                 NDBG15(("mpi_pre_port_facts(): Incorrect req size, "
10611                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10612                     pt->request_size,
10613                     (int)sizeof (MPI2_PORT_FACTS_REQUEST),
10614                     pt->dataout_size));
10615         if (pt->data_size != sizeof (MPI2_PORT_FACTS_REPLY))
10616                 NDBG15(("mpi_pre_port_facts(): Incorrect rep size, "
10617                     "0x%x, should be 0x%x", pt->data_size,
10618                     (int)sizeof (MPI2_PORT_FACTS_REPLY)));
10619         pt->sgl_offset = (uint16_t)pt->request_size;
10620 }
10621 
10622 /*
10623  * Prepare pt for a SATA_PASSTHROUGH request.
10624  */
10625 static void
10626 mpi_pre_sata_passthrough(mptsas_t *mpt, mptsas_pt_request_t *pt)
10627 {
10628 #ifndef __lock_lint
10629         _NOTE(ARGUNUSED(mpt))
10630 #endif
10631         pt->sgl_offset = offsetof(MPI2_SATA_PASSTHROUGH_REQUEST, SGL);
10632         if (pt->request_size != pt->sgl_offset)
10633                 NDBG15(("mpi_pre_sata_passthrough(): Incorrect req size, "
10634                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10635                     pt->request_size, pt->sgl_offset,
10636                     pt->dataout_size));
10637         if (pt->data_size != sizeof (MPI2_SATA_PASSTHROUGH_REPLY))
10638                 NDBG15(("mpi_pre_sata_passthrough(): Incorrect rep size, "
10639                     "0x%x, should be 0x%x", pt->data_size,
10640                     (int)sizeof (MPI2_SATA_PASSTHROUGH_REPLY)));
10641 }
10642 
10643 static void
10644 mpi_pre_smp_passthrough(mptsas_t *mpt, mptsas_pt_request_t *pt)
10645 {
10646 #ifndef __lock_lint
10647         _NOTE(ARGUNUSED(mpt))
10648 #endif
10649         pt->sgl_offset = offsetof(MPI2_SMP_PASSTHROUGH_REQUEST, SGL);
10650         if (pt->request_size != pt->sgl_offset)
10651                 NDBG15(("mpi_pre_smp_passthrough(): Incorrect req size, "
10652                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10653                     pt->request_size, pt->sgl_offset,
10654                     pt->dataout_size));
10655         if (pt->data_size != sizeof (MPI2_SMP_PASSTHROUGH_REPLY))
10656                 NDBG15(("mpi_pre_smp_passthrough(): Incorrect rep size, "
10657                     "0x%x, should be 0x%x", pt->data_size,
10658                     (int)sizeof (MPI2_SMP_PASSTHROUGH_REPLY)));
10659 }
10660 
10661 /*
10662  * Prepare pt for a CONFIG request.
10663  */
10664 static void
10665 mpi_pre_config(mptsas_t *mpt, mptsas_pt_request_t *pt)
10666 {
10667 #ifndef __lock_lint
10668         _NOTE(ARGUNUSED(mpt))
10669 #endif
10670         pt->sgl_offset = offsetof(MPI2_CONFIG_REQUEST, PageBufferSGE);
10671         if (pt->request_size != pt->sgl_offset)
10672                 NDBG15(("mpi_pre_config(): Incorrect req size, 0x%x, "
10673                     "should be 0x%x, dataoutsz 0x%x", pt->request_size,
10674                     pt->sgl_offset, pt->dataout_size));
10675         if (pt->data_size != sizeof (MPI2_CONFIG_REPLY))
10676                 NDBG15(("mpi_pre_config(): Incorrect rep size, 0x%x, "
10677                     "should be 0x%x", pt->data_size,
10678                     (int)sizeof (MPI2_CONFIG_REPLY)));
10679         pt->simple = 1;
10680 }
10681 
10682 /*
10683  * Prepare pt for a SCSI_IO_REQ request.
10684  */
10685 static void
10686 mpi_pre_scsi_io_req(mptsas_t *mpt, mptsas_pt_request_t *pt)
10687 {
10688 #ifndef __lock_lint
10689         _NOTE(ARGUNUSED(mpt))
10690 #endif
10691         pt->sgl_offset = offsetof(MPI2_SCSI_IO_REQUEST, SGL);
10692         if (pt->request_size != pt->sgl_offset)
10693                 NDBG15(("mpi_pre_config(): Incorrect req size, 0x%x, "
10694                     "should be 0x%x, dataoutsz 0x%x", pt->request_size,
10695                     pt->sgl_offset,
10696                     pt->dataout_size));
10697         if (pt->data_size != sizeof (MPI2_SCSI_IO_REPLY))
10698                 NDBG15(("mpi_pre_config(): Incorrect rep size, 0x%x, "
10699                     "should be 0x%x", pt->data_size,
10700                     (int)sizeof (MPI2_SCSI_IO_REPLY)));
10701 }
10702 
10703 /*
10704  * Prepare the mptsas_cmd for a SAS_IO_UNIT_CONTROL request.
10705  */
10706 static void
10707 mpi_pre_sas_io_unit_control(mptsas_t *mpt, mptsas_pt_request_t *pt)
10708 {
10709 #ifndef __lock_lint
10710         _NOTE(ARGUNUSED(mpt))
10711 #endif
10712         pt->sgl_offset = (uint16_t)pt->request_size;
10713 }
10714 
10715 /*
10716  * A set of functions to prepare an mptsas_cmd for the various
10717  * supported requests.
10718  */
10719 static struct mptsas_func {
10720         U8              Function;
10721         char            *Name;
10722         mptsas_pre_f    *f_pre;
10723 } mptsas_func_list[] = {
10724         { MPI2_FUNCTION_IOC_FACTS, "IOC_FACTS",         mpi_pre_ioc_facts },
10725         { MPI2_FUNCTION_PORT_FACTS, "PORT_FACTS",       mpi_pre_port_facts },
10726         { MPI2_FUNCTION_FW_DOWNLOAD, "FW_DOWNLOAD",     mpi_pre_fw_download },
10727         { MPI2_FUNCTION_FW_UPLOAD, "FW_UPLOAD",         mpi_pre_fw_upload },
10728         { MPI2_FUNCTION_SATA_PASSTHROUGH, "SATA_PASSTHROUGH",
10729             mpi_pre_sata_passthrough },
10730         { MPI2_FUNCTION_SMP_PASSTHROUGH, "SMP_PASSTHROUGH",
10731             mpi_pre_smp_passthrough},
10732         { MPI2_FUNCTION_SCSI_IO_REQUEST, "SCSI_IO_REQUEST",
10733             mpi_pre_scsi_io_req},
10734         { MPI2_FUNCTION_CONFIG, "CONFIG",               mpi_pre_config},
10735         { MPI2_FUNCTION_SAS_IO_UNIT_CONTROL, "SAS_IO_UNIT_CONTROL",
10736             mpi_pre_sas_io_unit_control },
10737         { 0xFF, NULL,                           NULL } /* list end */
10738 };
10739 
10740 static void
10741 mptsas_prep_sgl_offset(mptsas_t *mpt, mptsas_pt_request_t *pt)
10742 {
10743         pMPI2RequestHeader_t    hdr;
10744         struct mptsas_func      *f;
10745 
10746         hdr = (pMPI2RequestHeader_t)pt->request;
10747 
10748         for (f = mptsas_func_list; f->f_pre != NULL; f++) {
10749                 if (hdr->Function == f->Function) {
10750                         f->f_pre(mpt, pt);
10751                         NDBG15(("mptsas_prep_sgl_offset: Function %s,"
10752                             " sgl_offset 0x%x", f->Name,
10753                             pt->sgl_offset));
10754                         return;
10755                 }
10756         }
10757         NDBG15(("mptsas_prep_sgl_offset: Unknown Function 0x%02x,"
10758             " returning req_size 0x%x for sgl_offset",
10759             hdr->Function, pt->request_size));
10760         pt->sgl_offset = (uint16_t)pt->request_size;
10761 }
10762 
10763 
10764 static int
10765 mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
10766     uint8_t *data, uint32_t request_size, uint32_t reply_size,
10767     uint32_t data_size, uint32_t direction, uint8_t *dataout,
10768     uint32_t dataout_size, short timeout, int mode)
10769 {
10770         mptsas_pt_request_t             pt;
10771         mptsas_dma_alloc_state_t        data_dma_state;
10772         mptsas_dma_alloc_state_t        dataout_dma_state;
10773         caddr_t                         memp;
10774         mptsas_cmd_t                    *cmd = NULL;
10775         struct scsi_pkt                 *pkt;
10776         uint32_t                        reply_len = 0, sense_len = 0;
10777         pMPI2RequestHeader_t            request_hdrp;
10778         pMPI2RequestHeader_t            request_msg;
10779         pMPI2DefaultReply_t             reply_msg;
10780         Mpi2SCSIIOReply_t               rep_msg;
10781         int                             rvalue;
10782         int                             i, status = 0, pt_flags = 0, rv = 0;
10783         uint8_t                         function;
10784 
10785         ASSERT(mutex_owned(&mpt->m_mutex));
10786 
10787         reply_msg = (pMPI2DefaultReply_t)(&rep_msg);
10788         bzero(reply_msg, sizeof (MPI2_DEFAULT_REPLY));
10789         request_msg = kmem_zalloc(request_size, KM_SLEEP);
10790 
10791         mutex_exit(&mpt->m_mutex);
10792         /*
10793          * copy in the request buffer since it could be used by
10794          * another thread when the pt request into waitq
10795          */
10796         if (ddi_copyin(request, request_msg, request_size, mode)) {
10797                 mutex_enter(&mpt->m_mutex);
10798                 status = EFAULT;
10799                 mptsas_log(mpt, CE_WARN, "failed to copy request data");
10800                 goto out;
10801         }
10802         NDBG27(("mptsas_do_passthru: mode 0x%x, size 0x%x, Func 0x%x",
10803             mode, request_size, request_msg->Function));
10804         mutex_enter(&mpt->m_mutex);
10805 
10806         function = request_msg->Function;
10807         if (function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
10808                 pMpi2SCSITaskManagementRequest_t        task;
10809                 task = (pMpi2SCSITaskManagementRequest_t)request_msg;
10810                 mptsas_setup_bus_reset_delay(mpt);
10811                 rv = mptsas_ioc_task_management(mpt, task->TaskType,
10812                     task->DevHandle, (int)task->LUN[1], reply, reply_size,
10813                     mode);
10814 
10815                 if (rv != TRUE) {
10816                         status = EIO;
10817                         mptsas_log(mpt, CE_WARN, "task management failed");
10818                 }
10819                 goto out;
10820         }
10821 
10822         if (data_size != 0) {
10823                 data_dma_state.size = data_size;
10824                 if (mptsas_dma_alloc(mpt, &data_dma_state) != DDI_SUCCESS) {
10825                         status = ENOMEM;
10826                         mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
10827                             "resource");
10828                         goto out;
10829                 }
10830                 pt_flags |= MPTSAS_DATA_ALLOCATED;
10831                 if (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10832                         mutex_exit(&mpt->m_mutex);
10833                         for (i = 0; i < data_size; i++) {
10834                                 if (ddi_copyin(data + i, (uint8_t *)
10835                                     data_dma_state.memp + i, 1, mode)) {
10836                                         mutex_enter(&mpt->m_mutex);
10837                                         status = EFAULT;
10838                                         mptsas_log(mpt, CE_WARN, "failed to "
10839                                             "copy read data");
10840                                         goto out;
10841                                 }
10842                         }
10843                         mutex_enter(&mpt->m_mutex);
10844                 }
10845         } else {
10846                 bzero(&data_dma_state, sizeof (data_dma_state));
10847         }
10848 
10849         if (dataout_size != 0) {
10850                 dataout_dma_state.size = dataout_size;
10851                 if (mptsas_dma_alloc(mpt, &dataout_dma_state) != DDI_SUCCESS) {
10852                         status = ENOMEM;
10853                         mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
10854                             "resource");
10855                         goto out;
10856                 }
10857                 pt_flags |= MPTSAS_DATAOUT_ALLOCATED;
10858                 mutex_exit(&mpt->m_mutex);
10859                 for (i = 0; i < dataout_size; i++) {
10860                         if (ddi_copyin(dataout + i, (uint8_t *)
10861                             dataout_dma_state.memp + i, 1, mode)) {
10862                                 mutex_enter(&mpt->m_mutex);
10863                                 mptsas_log(mpt, CE_WARN, "failed to copy out"
10864                                     " data");
10865                                 status = EFAULT;
10866                                 goto out;
10867                         }
10868                 }
10869                 mutex_enter(&mpt->m_mutex);
10870         } else {
10871                 bzero(&dataout_dma_state, sizeof (dataout_dma_state));
10872         }
10873 
10874         if ((rvalue = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
10875                 status = EAGAIN;
10876                 mptsas_log(mpt, CE_NOTE, "event ack command pool is full");
10877                 goto out;
10878         }
10879         pt_flags |= MPTSAS_REQUEST_POOL_CMD;
10880 
10881         bzero((caddr_t)cmd, sizeof (*cmd));
10882         bzero((caddr_t)pkt, scsi_pkt_size());
10883         bzero((caddr_t)&pt, sizeof (pt));
10884 
10885         cmd->ioc_cmd_slot = (uint32_t)(rvalue);
10886 
10887         pt.request = (uint8_t *)request_msg;
10888         pt.direction = direction;
10889         pt.simple = 0;
10890         pt.request_size = request_size;
10891         pt.data_size = data_size;
10892         pt.dataout_size = dataout_size;
10893         pt.data_cookie = data_dma_state.cookie;
10894         pt.dataout_cookie = dataout_dma_state.cookie;
10895         mptsas_prep_sgl_offset(mpt, &pt);
10896 
10897         /*
10898          * Form a blank cmd/pkt to store the acknowledgement message
10899          */
10900         pkt->pkt_cdbp                = (opaque_t)&cmd->cmd_cdb[0];
10901         pkt->pkt_scbp                = (opaque_t)&cmd->cmd_scb;
10902         pkt->pkt_ha_private  = (opaque_t)&pt;
10903         pkt->pkt_flags               = FLAG_HEAD;
10904         pkt->pkt_time                = timeout;
10905         cmd->cmd_pkt         = pkt;
10906         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_PASSTHRU;
10907 
10908         if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
10909             (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
10910                 uint8_t                 com, cdb_group_id;
10911                 boolean_t               ret;
10912 
10913                 pkt->pkt_cdbp = ((pMpi2SCSIIORequest_t)request_msg)->CDB.CDB32;
10914                 com = pkt->pkt_cdbp[0];
10915                 cdb_group_id = CDB_GROUPID(com);
10916                 switch (cdb_group_id) {
10917                 case CDB_GROUPID_0: cmd->cmd_cdblen = CDB_GROUP0; break;
10918                 case CDB_GROUPID_1: cmd->cmd_cdblen = CDB_GROUP1; break;
10919                 case CDB_GROUPID_2: cmd->cmd_cdblen = CDB_GROUP2; break;
10920                 case CDB_GROUPID_4: cmd->cmd_cdblen = CDB_GROUP4; break;
10921                 case CDB_GROUPID_5: cmd->cmd_cdblen = CDB_GROUP5; break;
10922                 default:
10923                         NDBG27(("mptsas_do_passthru: SCSI_IO, reserved "
10924                             "CDBGROUP 0x%x requested!", cdb_group_id));
10925                         break;
10926                 }
10927 
10928                 reply_len = sizeof (MPI2_SCSI_IO_REPLY);
10929                 sense_len = reply_size - reply_len;
10930                 ret = mptsas_cmdarqsize(mpt, cmd, sense_len, KM_SLEEP);
10931                 VERIFY(ret == B_TRUE);
10932         } else {
10933                 reply_len = reply_size;
10934                 sense_len = 0;
10935         }
10936 
10937         NDBG27(("mptsas_do_passthru: %s, dsz 0x%x, dosz 0x%x, replen 0x%x, "
10938             "snslen 0x%x",
10939             (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE)?"Write":"Read",
10940             data_size, dataout_size, reply_len, sense_len));
10941 
10942         /*
10943          * Save the command in a slot
10944          */
10945         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
10946                 /*
10947                  * Once passthru command get slot, set cmd_flags
10948                  * CFLAG_PREPARED.
10949                  */
10950                 cmd->cmd_flags |= CFLAG_PREPARED;
10951                 mptsas_start_passthru(mpt, cmd);
10952         } else {
10953                 mptsas_waitq_add(mpt, cmd);
10954         }
10955 
10956         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
10957                 cv_wait(&mpt->m_passthru_cv, &mpt->m_mutex);
10958         }
10959 
10960         NDBG27(("mptsas_do_passthru: Cmd complete, flags 0x%x, rfm 0x%x "
10961             "pktreason 0x%x", cmd->cmd_flags, cmd->cmd_rfm,
10962             pkt->pkt_reason));
10963 
10964         if (cmd->cmd_flags & CFLAG_PREPARED) {
10965                 memp = mpt->m_req_frame + (mpt->m_req_frame_size *
10966                     cmd->cmd_slot);
10967                 request_hdrp = (pMPI2RequestHeader_t)memp;
10968         }
10969 
10970         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
10971                 status = ETIMEDOUT;
10972                 mptsas_log(mpt, CE_WARN, "passthrough command timeout");
10973                 pt_flags |= MPTSAS_CMD_TIMEOUT;
10974                 goto out;
10975         }
10976 
10977         if (cmd->cmd_rfm) {
10978                 /*
10979                  * cmd_rfm is zero means the command reply is a CONTEXT
10980                  * reply and no PCI Write to post the free reply SMFA
10981                  * because no reply message frame is used.
10982                  * cmd_rfm is non-zero means the reply is a ADDRESS
10983                  * reply and reply message frame is used.
10984                  */
10985                 pt_flags |= MPTSAS_ADDRESS_REPLY;
10986                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
10987                     DDI_DMA_SYNC_FORCPU);
10988                 reply_msg = (pMPI2DefaultReply_t)
10989                     (mpt->m_reply_frame + (cmd->cmd_rfm -
10990                     (mpt->m_reply_frame_dma_addr & 0xffffffffu)));
10991         }
10992 
10993         mptsas_fma_check(mpt, cmd);
10994         if (pkt->pkt_reason == CMD_TRAN_ERR) {
10995                 status = EAGAIN;
10996                 mptsas_log(mpt, CE_WARN, "passthru fma error");
10997                 goto out;
10998         }
10999         if (pkt->pkt_reason == CMD_RESET) {
11000                 status = EAGAIN;
11001                 mptsas_log(mpt, CE_WARN, "ioc reset abort passthru");
11002                 goto out;
11003         }
11004 
11005         if (pkt->pkt_reason == CMD_INCOMPLETE) {
11006                 status = EIO;
11007                 mptsas_log(mpt, CE_WARN, "passthrough command incomplete");
11008                 goto out;
11009         }
11010 
11011         mutex_exit(&mpt->m_mutex);
11012         if (cmd->cmd_flags & CFLAG_PREPARED) {
11013                 function = request_hdrp->Function;
11014                 if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
11015                     (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
11016                         reply_len = sizeof (MPI2_SCSI_IO_REPLY);
11017                         sense_len = cmd->cmd_extrqslen ?
11018                             min(sense_len, cmd->cmd_extrqslen) :
11019                             min(sense_len, cmd->cmd_rqslen);
11020                 } else {
11021                         reply_len = reply_size;
11022                         sense_len = 0;
11023                 }
11024 
11025                 for (i = 0; i < reply_len; i++) {
11026                         if (ddi_copyout((uint8_t *)reply_msg + i, reply + i, 1,
11027                             mode)) {
11028                                 mutex_enter(&mpt->m_mutex);
11029                                 status = EFAULT;
11030                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
11031                                     "reply data");
11032                                 goto out;
11033                         }
11034                 }
11035                 for (i = 0; i < sense_len; i++) {
11036                         if (ddi_copyout((uint8_t *)request_hdrp + 64 + i,
11037                             reply + reply_len + i, 1, mode)) {
11038                                 mutex_enter(&mpt->m_mutex);
11039                                 status = EFAULT;
11040                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
11041                                     "sense data");
11042                                 goto out;
11043                         }
11044                 }
11045         }
11046 
11047         if (data_size) {
11048                 if (direction != MPTSAS_PASS_THRU_DIRECTION_WRITE) {
11049                         (void) ddi_dma_sync(data_dma_state.handle, 0, 0,
11050                             DDI_DMA_SYNC_FORCPU);
11051                         for (i = 0; i < data_size; i++) {
11052                                 if (ddi_copyout((uint8_t *)(
11053                                     data_dma_state.memp + i), data + i,  1,
11054                                     mode)) {
11055                                         mutex_enter(&mpt->m_mutex);
11056                                         status = EFAULT;
11057                                         mptsas_log(mpt, CE_WARN, "failed to "
11058                                             "copy out the reply data");
11059                                         goto out;
11060                                 }
11061                         }
11062                 }
11063         }
11064         mutex_enter(&mpt->m_mutex);
11065 out:
11066         /*
11067          * Put the reply frame back on the free queue, increment the free
11068          * index, and write the new index to the free index register.  But only
11069          * if this reply is an ADDRESS reply.
11070          */
11071         if (pt_flags & MPTSAS_ADDRESS_REPLY) {
11072                 ddi_put32(mpt->m_acc_free_queue_hdl,
11073                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
11074                     cmd->cmd_rfm);
11075                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
11076                     DDI_DMA_SYNC_FORDEV);
11077                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
11078                         mpt->m_free_index = 0;
11079                 }
11080                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
11081                     mpt->m_free_index);
11082         }
11083         if (cmd) {
11084                 if (cmd->cmd_extrqslen != 0) {
11085                         rmfree(mpt->m_erqsense_map, cmd->cmd_extrqschunks,
11086                             cmd->cmd_extrqsidx + 1);
11087                 }
11088                 if (cmd->cmd_flags & CFLAG_PREPARED) {
11089                         mptsas_remove_cmd(mpt, cmd);
11090                         pt_flags &= (~MPTSAS_REQUEST_POOL_CMD);
11091                 }
11092         }
11093         if (pt_flags & MPTSAS_REQUEST_POOL_CMD)
11094                 mptsas_return_to_pool(mpt, cmd);
11095         if (pt_flags & MPTSAS_DATA_ALLOCATED) {
11096                 if (mptsas_check_dma_handle(data_dma_state.handle) !=
11097                     DDI_SUCCESS) {
11098                         ddi_fm_service_impact(mpt->m_dip,
11099                             DDI_SERVICE_UNAFFECTED);
11100                         status = EFAULT;
11101                 }
11102                 mptsas_dma_free(&data_dma_state);
11103         }
11104         if (pt_flags & MPTSAS_DATAOUT_ALLOCATED) {
11105                 if (mptsas_check_dma_handle(dataout_dma_state.handle) !=
11106                     DDI_SUCCESS) {
11107                         ddi_fm_service_impact(mpt->m_dip,
11108                             DDI_SERVICE_UNAFFECTED);
11109                         status = EFAULT;
11110                 }
11111                 mptsas_dma_free(&dataout_dma_state);
11112         }
11113         if (pt_flags & MPTSAS_CMD_TIMEOUT) {
11114                 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
11115                         mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
11116                 }
11117         }
11118         if (request_msg)
11119                 kmem_free(request_msg, request_size);
11120         NDBG27(("mptsas_do_passthru: Done status 0x%x", status));
11121 
11122         return (status);
11123 }
11124 
11125 static int
11126 mptsas_pass_thru(mptsas_t *mpt, mptsas_pass_thru_t *data, int mode)
11127 {
11128         /*
11129          * If timeout is 0, set timeout to default of 60 seconds.
11130          */
11131         if (data->Timeout == 0) {
11132                 data->Timeout = MPTSAS_PASS_THRU_TIME_DEFAULT;
11133         }
11134 
11135         if (((data->DataSize == 0) &&
11136             (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_NONE)) ||
11137             ((data->DataSize != 0) &&
11138             ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_READ) ||
11139             (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_WRITE) ||
11140             ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) &&
11141             (data->DataOutSize != 0))))) {
11142                 if (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) {
11143                         data->DataDirection = MPTSAS_PASS_THRU_DIRECTION_READ;
11144                 } else {
11145                         data->DataOutSize = 0;
11146                 }
11147                 /*
11148                  * Send passthru request messages
11149                  */
11150                 return (mptsas_do_passthru(mpt,
11151                     (uint8_t *)((uintptr_t)data->PtrRequest),
11152                     (uint8_t *)((uintptr_t)data->PtrReply),
11153                     (uint8_t *)((uintptr_t)data->PtrData),
11154                     data->RequestSize, data->ReplySize,
11155                     data->DataSize, data->DataDirection,
11156                     (uint8_t *)((uintptr_t)data->PtrDataOut),
11157                     data->DataOutSize, data->Timeout, mode));
11158         } else {
11159                 return (EINVAL);
11160         }
11161 }
11162 
11163 static uint8_t
11164 mptsas_get_fw_diag_buffer_number(mptsas_t *mpt, uint32_t unique_id)
11165 {
11166         uint8_t index;
11167 
11168         for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
11169                 if (mpt->m_fw_diag_buffer_list[index].unique_id == unique_id) {
11170                         return (index);
11171                 }
11172         }
11173 
11174         return (MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND);
11175 }
11176 
11177 static void
11178 mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd)
11179 {
11180         pMpi2DiagBufferPostRequest_t    pDiag_post_msg;
11181         pMpi2DiagReleaseRequest_t       pDiag_release_msg;
11182         struct scsi_pkt                 *pkt = cmd->cmd_pkt;
11183         mptsas_diag_request_t           *diag = pkt->pkt_ha_private;
11184         uint32_t                        i;
11185         uint64_t                        request_desc;
11186 
11187         ASSERT(mutex_owned(&mpt->m_mutex));
11188 
11189         /*
11190          * Form the diag message depending on the post or release function.
11191          */
11192         if (diag->function == MPI2_FUNCTION_DIAG_BUFFER_POST) {
11193                 pDiag_post_msg = (pMpi2DiagBufferPostRequest_t)
11194                     (mpt->m_req_frame + (mpt->m_req_frame_size *
11195                     cmd->cmd_slot));
11196                 bzero(pDiag_post_msg, mpt->m_req_frame_size);
11197                 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->Function,
11198                     diag->function);
11199                 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->BufferType,
11200                     diag->pBuffer->buffer_type);
11201                 ddi_put8(mpt->m_acc_req_frame_hdl,
11202                     &pDiag_post_msg->ExtendedType,
11203                     diag->pBuffer->extended_type);
11204                 ddi_put32(mpt->m_acc_req_frame_hdl,
11205                     &pDiag_post_msg->BufferLength,
11206                     diag->pBuffer->buffer_data.size);
11207                 for (i = 0; i < (sizeof (pDiag_post_msg->ProductSpecific) / 4);
11208                     i++) {
11209                         ddi_put32(mpt->m_acc_req_frame_hdl,
11210                             &pDiag_post_msg->ProductSpecific[i],
11211                             diag->pBuffer->product_specific[i]);
11212                 }
11213                 ddi_put32(mpt->m_acc_req_frame_hdl,
11214                     &pDiag_post_msg->BufferAddress.Low,
11215                     (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
11216                     & 0xffffffffull));
11217                 ddi_put32(mpt->m_acc_req_frame_hdl,
11218                     &pDiag_post_msg->BufferAddress.High,
11219                     (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
11220                     >> 32));
11221         } else {
11222                 pDiag_release_msg = (pMpi2DiagReleaseRequest_t)
11223                     (mpt->m_req_frame + (mpt->m_req_frame_size *
11224                     cmd->cmd_slot));
11225                 bzero(pDiag_release_msg, mpt->m_req_frame_size);
11226                 ddi_put8(mpt->m_acc_req_frame_hdl,
11227                     &pDiag_release_msg->Function, diag->function);
11228                 ddi_put8(mpt->m_acc_req_frame_hdl,
11229                     &pDiag_release_msg->BufferType,
11230                     diag->pBuffer->buffer_type);
11231         }
11232 
11233         /*
11234          * Send the message
11235          */
11236         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
11237             DDI_DMA_SYNC_FORDEV);
11238         request_desc = (cmd->cmd_slot << 16) +
11239             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
11240         cmd->cmd_rfm = NULL;
11241         MPTSAS_START_CMD(mpt, request_desc);
11242         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
11243             DDI_SUCCESS) ||
11244             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
11245             DDI_SUCCESS)) {
11246                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
11247         }
11248 }
11249 
11250 static int
11251 mptsas_post_fw_diag_buffer(mptsas_t *mpt,
11252     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
11253 {
11254         mptsas_diag_request_t           diag;
11255         int                             status, slot_num, post_flags = 0;
11256         mptsas_cmd_t                    *cmd = NULL;
11257         struct scsi_pkt                 *pkt;
11258         pMpi2DiagBufferPostReply_t      reply;
11259         uint16_t                        iocstatus;
11260         uint32_t                        iocloginfo, transfer_length;
11261 
11262         /*
11263          * If buffer is not enabled, just leave.
11264          */
11265         *return_code = MPTSAS_FW_DIAG_ERROR_POST_FAILED;
11266         if (!pBuffer->enabled) {
11267                 status = DDI_FAILURE;
11268                 goto out;
11269         }
11270 
11271         /*
11272          * Clear some flags initially.
11273          */
11274         pBuffer->force_release = FALSE;
11275         pBuffer->valid_data = FALSE;
11276         pBuffer->owned_by_firmware = FALSE;
11277 
11278         /*
11279          * Get a cmd buffer from the cmd buffer pool
11280          */
11281         if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
11282                 status = DDI_FAILURE;
11283                 mptsas_log(mpt, CE_NOTE, "command pool is full: Post FW Diag");
11284                 goto out;
11285         }
11286         post_flags |= MPTSAS_REQUEST_POOL_CMD;
11287 
11288         bzero((caddr_t)cmd, sizeof (*cmd));
11289         bzero((caddr_t)pkt, scsi_pkt_size());
11290 
11291         cmd->ioc_cmd_slot = (uint32_t)(slot_num);
11292 
11293         diag.pBuffer = pBuffer;
11294         diag.function = MPI2_FUNCTION_DIAG_BUFFER_POST;
11295 
11296         /*
11297          * Form a blank cmd/pkt to store the acknowledgement message
11298          */
11299         pkt->pkt_ha_private  = (opaque_t)&diag;
11300         pkt->pkt_flags               = FLAG_HEAD;
11301         pkt->pkt_time                = 60;
11302         cmd->cmd_pkt         = pkt;
11303         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_DIAG;
11304 
11305         /*
11306          * Save the command in a slot
11307          */
11308         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
11309                 /*
11310                  * Once passthru command get slot, set cmd_flags
11311                  * CFLAG_PREPARED.
11312                  */
11313                 cmd->cmd_flags |= CFLAG_PREPARED;
11314                 mptsas_start_diag(mpt, cmd);
11315         } else {
11316                 mptsas_waitq_add(mpt, cmd);
11317         }
11318 
11319         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
11320                 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
11321         }
11322 
11323         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
11324                 status = DDI_FAILURE;
11325                 mptsas_log(mpt, CE_WARN, "Post FW Diag command timeout");
11326                 goto out;
11327         }
11328 
11329         /*
11330          * cmd_rfm points to the reply message if a reply was given.  Check the
11331          * IOCStatus to make sure everything went OK with the FW diag request
11332          * and set buffer flags.
11333          */
11334         if (cmd->cmd_rfm) {
11335                 post_flags |= MPTSAS_ADDRESS_REPLY;
11336                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
11337                     DDI_DMA_SYNC_FORCPU);
11338                 reply = (pMpi2DiagBufferPostReply_t)(mpt->m_reply_frame +
11339                     (cmd->cmd_rfm -
11340                     (mpt->m_reply_frame_dma_addr & 0xffffffffu)));
11341 
11342                 /*
11343                  * Get the reply message data
11344                  */
11345                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
11346                     &reply->IOCStatus);
11347                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
11348                     &reply->IOCLogInfo);
11349                 transfer_length = ddi_get32(mpt->m_acc_reply_frame_hdl,
11350                     &reply->TransferLength);
11351 
11352                 /*
11353                  * If post failed quit.
11354                  */
11355                 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
11356                         status = DDI_FAILURE;
11357                         NDBG13(("post FW Diag Buffer failed: IOCStatus=0x%x, "
11358                             "IOCLogInfo=0x%x, TransferLength=0x%x", iocstatus,
11359                             iocloginfo, transfer_length));
11360                         goto out;
11361                 }
11362 
11363                 /*
11364                  * Post was successful.
11365                  */
11366                 pBuffer->valid_data = TRUE;
11367                 pBuffer->owned_by_firmware = TRUE;
11368                 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
11369                 status = DDI_SUCCESS;
11370         }
11371 
11372 out:
11373         /*
11374          * Put the reply frame back on the free queue, increment the free
11375          * index, and write the new index to the free index register.  But only
11376          * if this reply is an ADDRESS reply.
11377          */
11378         if (post_flags & MPTSAS_ADDRESS_REPLY) {
11379                 ddi_put32(mpt->m_acc_free_queue_hdl,
11380                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
11381                     cmd->cmd_rfm);
11382                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
11383                     DDI_DMA_SYNC_FORDEV);
11384                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
11385                         mpt->m_free_index = 0;
11386                 }
11387                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
11388                     mpt->m_free_index);
11389         }
11390         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
11391                 mptsas_remove_cmd(mpt, cmd);
11392                 post_flags &= (~MPTSAS_REQUEST_POOL_CMD);
11393         }
11394         if (post_flags & MPTSAS_REQUEST_POOL_CMD) {
11395                 mptsas_return_to_pool(mpt, cmd);
11396         }
11397 
11398         return (status);
11399 }
11400 
11401 static int
11402 mptsas_release_fw_diag_buffer(mptsas_t *mpt,
11403     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
11404     uint32_t diag_type)
11405 {
11406         mptsas_diag_request_t   diag;
11407         int                     status, slot_num, rel_flags = 0;
11408         mptsas_cmd_t            *cmd = NULL;
11409         struct scsi_pkt         *pkt;
11410         pMpi2DiagReleaseReply_t reply;
11411         uint16_t                iocstatus;
11412         uint32_t                iocloginfo;
11413 
11414         /*
11415          * If buffer is not enabled, just leave.
11416          */
11417         *return_code = MPTSAS_FW_DIAG_ERROR_RELEASE_FAILED;
11418         if (!pBuffer->enabled) {
11419                 mptsas_log(mpt, CE_NOTE, "This buffer type is not supported "
11420                     "by the IOC");
11421                 status = DDI_FAILURE;
11422                 goto out;
11423         }
11424 
11425         /*
11426          * Clear some flags initially.
11427          */
11428         pBuffer->force_release = FALSE;
11429         pBuffer->valid_data = FALSE;
11430         pBuffer->owned_by_firmware = FALSE;
11431 
11432         /*
11433          * Get a cmd buffer from the cmd buffer pool
11434          */
11435         if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
11436                 status = DDI_FAILURE;
11437                 mptsas_log(mpt, CE_NOTE, "command pool is full: Release FW "
11438                     "Diag");
11439                 goto out;
11440         }
11441         rel_flags |= MPTSAS_REQUEST_POOL_CMD;
11442 
11443         bzero((caddr_t)cmd, sizeof (*cmd));
11444         bzero((caddr_t)pkt, scsi_pkt_size());
11445 
11446         cmd->ioc_cmd_slot = (uint32_t)(slot_num);
11447 
11448         diag.pBuffer = pBuffer;
11449         diag.function = MPI2_FUNCTION_DIAG_RELEASE;
11450 
11451         /*
11452          * Form a blank cmd/pkt to store the acknowledgement message
11453          */
11454         pkt->pkt_ha_private  = (opaque_t)&diag;
11455         pkt->pkt_flags               = FLAG_HEAD;
11456         pkt->pkt_time                = 60;
11457         cmd->cmd_pkt         = pkt;
11458         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_DIAG;
11459 
11460         /*
11461          * Save the command in a slot
11462          */
11463         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
11464                 /*
11465                  * Once passthru command get slot, set cmd_flags
11466                  * CFLAG_PREPARED.
11467                  */
11468                 cmd->cmd_flags |= CFLAG_PREPARED;
11469                 mptsas_start_diag(mpt, cmd);
11470         } else {
11471                 mptsas_waitq_add(mpt, cmd);
11472         }
11473 
11474         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
11475                 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
11476         }
11477 
11478         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
11479                 status = DDI_FAILURE;
11480                 mptsas_log(mpt, CE_WARN, "Release FW Diag command timeout");
11481                 goto out;
11482         }
11483 
11484         /*
11485          * cmd_rfm points to the reply message if a reply was given.  Check the
11486          * IOCStatus to make sure everything went OK with the FW diag request
11487          * and set buffer flags.
11488          */
11489         if (cmd->cmd_rfm) {
11490                 rel_flags |= MPTSAS_ADDRESS_REPLY;
11491                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
11492                     DDI_DMA_SYNC_FORCPU);
11493                 reply = (pMpi2DiagReleaseReply_t)(mpt->m_reply_frame +
11494                     (cmd->cmd_rfm -
11495                     (mpt->m_reply_frame_dma_addr & 0xffffffffu)));
11496 
11497                 /*
11498                  * Get the reply message data
11499                  */
11500                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
11501                     &reply->IOCStatus);
11502                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
11503                     &reply->IOCLogInfo);
11504 
11505                 /*
11506                  * If release failed quit.
11507                  */
11508                 if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) ||
11509                     pBuffer->owned_by_firmware) {
11510                         status = DDI_FAILURE;
11511                         NDBG13(("release FW Diag Buffer failed: "
11512                             "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
11513                             iocloginfo));
11514                         goto out;
11515                 }
11516 
11517                 /*
11518                  * Release was successful.
11519                  */
11520                 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
11521                 status = DDI_SUCCESS;
11522 
11523                 /*
11524                  * If this was for an UNREGISTER diag type command, clear the
11525                  * unique ID.
11526                  */
11527                 if (diag_type == MPTSAS_FW_DIAG_TYPE_UNREGISTER) {
11528                         pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
11529                 }
11530         }
11531 
11532 out:
11533         /*
11534          * Put the reply frame back on the free queue, increment the free
11535          * index, and write the new index to the free index register.  But only
11536          * if this reply is an ADDRESS reply.
11537          */
11538         if (rel_flags & MPTSAS_ADDRESS_REPLY) {
11539                 ddi_put32(mpt->m_acc_free_queue_hdl,
11540                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
11541                     cmd->cmd_rfm);
11542                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
11543                     DDI_DMA_SYNC_FORDEV);
11544                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
11545                         mpt->m_free_index = 0;
11546                 }
11547                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
11548                     mpt->m_free_index);
11549         }
11550         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
11551                 mptsas_remove_cmd(mpt, cmd);
11552                 rel_flags &= (~MPTSAS_REQUEST_POOL_CMD);
11553         }
11554         if (rel_flags & MPTSAS_REQUEST_POOL_CMD) {
11555                 mptsas_return_to_pool(mpt, cmd);
11556         }
11557 
11558         return (status);
11559 }
11560 
11561 static int
11562 mptsas_diag_register(mptsas_t *mpt, mptsas_fw_diag_register_t *diag_register,
11563     uint32_t *return_code)
11564 {
11565         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11566         uint8_t                         extended_type, buffer_type, i;
11567         uint32_t                        buffer_size;
11568         uint32_t                        unique_id;
11569         int                             status;
11570 
11571         ASSERT(mutex_owned(&mpt->m_mutex));
11572 
11573         extended_type = diag_register->ExtendedType;
11574         buffer_type = diag_register->BufferType;
11575         buffer_size = diag_register->RequestedBufferSize;
11576         unique_id = diag_register->UniqueId;
11577 
11578         /*
11579          * Check for valid buffer type
11580          */
11581         if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) {
11582                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11583                 return (DDI_FAILURE);
11584         }
11585 
11586         /*
11587          * Get the current buffer and look up the unique ID.  The unique ID
11588          * should not be found.  If it is, the ID is already in use.
11589          */
11590         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11591         pBuffer = &mpt->m_fw_diag_buffer_list[buffer_type];
11592         if (i != MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11593                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11594                 return (DDI_FAILURE);
11595         }
11596 
11597         /*
11598          * The buffer's unique ID should not be registered yet, and the given
11599          * unique ID cannot be 0.
11600          */
11601         if ((pBuffer->unique_id != MPTSAS_FW_DIAG_INVALID_UID) ||
11602             (unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
11603                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11604                 return (DDI_FAILURE);
11605         }
11606 
11607         /*
11608          * If this buffer is already posted as immediate, just change owner.
11609          */
11610         if (pBuffer->immediate && pBuffer->owned_by_firmware &&
11611             (pBuffer->unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
11612                 pBuffer->immediate = FALSE;
11613                 pBuffer->unique_id = unique_id;
11614                 return (DDI_SUCCESS);
11615         }
11616 
11617         /*
11618          * Post a new buffer after checking if it's enabled.  The DMA buffer
11619          * that is allocated will be contiguous (sgl_len = 1).
11620          */
11621         if (!pBuffer->enabled) {
11622                 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
11623                 return (DDI_FAILURE);
11624         }
11625         bzero(&pBuffer->buffer_data, sizeof (mptsas_dma_alloc_state_t));
11626         pBuffer->buffer_data.size = buffer_size;
11627         if (mptsas_dma_alloc(mpt, &pBuffer->buffer_data) != DDI_SUCCESS) {
11628                 mptsas_log(mpt, CE_WARN, "failed to alloc DMA resource for "
11629                     "diag buffer: size = %d bytes", buffer_size);
11630                 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
11631                 return (DDI_FAILURE);
11632         }
11633 
11634         /*
11635          * Copy the given info to the diag buffer and post the buffer.
11636          */
11637         pBuffer->buffer_type = buffer_type;
11638         pBuffer->immediate = FALSE;
11639         if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) {
11640                 for (i = 0; i < (sizeof (pBuffer->product_specific) / 4);
11641                     i++) {
11642                         pBuffer->product_specific[i] =
11643                             diag_register->ProductSpecific[i];
11644                 }
11645         }
11646         pBuffer->extended_type = extended_type;
11647         pBuffer->unique_id = unique_id;
11648         status = mptsas_post_fw_diag_buffer(mpt, pBuffer, return_code);
11649 
11650         if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
11651             DDI_SUCCESS) {
11652                 mptsas_log(mpt, CE_WARN, "Check of DMA handle failed in "
11653                     "mptsas_diag_register.");
11654                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
11655                         status = DDI_FAILURE;
11656         }
11657 
11658         /*
11659          * In case there was a failure, free the DMA buffer.
11660          */
11661         if (status == DDI_FAILURE) {
11662                 mptsas_dma_free(&pBuffer->buffer_data);
11663         }
11664 
11665         return (status);
11666 }
11667 
11668 static int
11669 mptsas_diag_unregister(mptsas_t *mpt,
11670     mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
11671 {
11672         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11673         uint8_t                         i;
11674         uint32_t                        unique_id;
11675         int                             status;
11676 
11677         ASSERT(mutex_owned(&mpt->m_mutex));
11678 
11679         unique_id = diag_unregister->UniqueId;
11680 
11681         /*
11682          * Get the current buffer and look up the unique ID.  The unique ID
11683          * should be there.
11684          */
11685         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11686         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11687                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11688                 return (DDI_FAILURE);
11689         }
11690 
11691         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11692 
11693         /*
11694          * Try to release the buffer from FW before freeing it.  If release
11695          * fails, don't free the DMA buffer in case FW tries to access it
11696          * later.  If buffer is not owned by firmware, can't release it.
11697          */
11698         if (!pBuffer->owned_by_firmware) {
11699                 status = DDI_SUCCESS;
11700         } else {
11701                 status = mptsas_release_fw_diag_buffer(mpt, pBuffer,
11702                     return_code, MPTSAS_FW_DIAG_TYPE_UNREGISTER);
11703         }
11704 
11705         /*
11706          * At this point, return the current status no matter what happens with
11707          * the DMA buffer.
11708          */
11709         pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
11710         if (status == DDI_SUCCESS) {
11711                 if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
11712                     DDI_SUCCESS) {
11713                         mptsas_log(mpt, CE_WARN, "Check of DMA handle failed "
11714                             "in mptsas_diag_unregister.");
11715                         ddi_fm_service_impact(mpt->m_dip,
11716                             DDI_SERVICE_UNAFFECTED);
11717                 }
11718                 mptsas_dma_free(&pBuffer->buffer_data);
11719         }
11720 
11721         return (status);
11722 }
11723 
11724 static int
11725 mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
11726     uint32_t *return_code)
11727 {
11728         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11729         uint8_t                         i;
11730         uint32_t                        unique_id;
11731 
11732         ASSERT(mutex_owned(&mpt->m_mutex));
11733 
11734         unique_id = diag_query->UniqueId;
11735 
11736         /*
11737          * If ID is valid, query on ID.
11738          * If ID is invalid, query on buffer type.
11739          */
11740         if (unique_id == MPTSAS_FW_DIAG_INVALID_UID) {
11741                 i = diag_query->BufferType;
11742                 if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
11743                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11744                         return (DDI_FAILURE);
11745                 }
11746         } else {
11747                 i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11748                 if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11749                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11750                         return (DDI_FAILURE);
11751                 }
11752         }
11753 
11754         /*
11755          * Fill query structure with the diag buffer info.
11756          */
11757         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11758         diag_query->BufferType = pBuffer->buffer_type;
11759         diag_query->ExtendedType = pBuffer->extended_type;
11760         if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) {
11761                 for (i = 0; i < (sizeof (diag_query->ProductSpecific) / 4);
11762                     i++) {
11763                         diag_query->ProductSpecific[i] =
11764                             pBuffer->product_specific[i];
11765                 }
11766         }
11767         diag_query->TotalBufferSize = pBuffer->buffer_data.size;
11768         diag_query->DriverAddedBufferSize = 0;
11769         diag_query->UniqueId = pBuffer->unique_id;
11770         diag_query->ApplicationFlags = 0;
11771         diag_query->DiagnosticFlags = 0;
11772 
11773         /*
11774          * Set/Clear application flags
11775          */
11776         if (pBuffer->immediate) {
11777                 diag_query->ApplicationFlags &= ~MPTSAS_FW_DIAG_FLAG_APP_OWNED;
11778         } else {
11779                 diag_query->ApplicationFlags |= MPTSAS_FW_DIAG_FLAG_APP_OWNED;
11780         }
11781         if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
11782                 diag_query->ApplicationFlags |=
11783                     MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
11784         } else {
11785                 diag_query->ApplicationFlags &=
11786                     ~MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
11787         }
11788         if (pBuffer->owned_by_firmware) {
11789                 diag_query->ApplicationFlags |=
11790                     MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
11791         } else {
11792                 diag_query->ApplicationFlags &=
11793                     ~MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
11794         }
11795 
11796         return (DDI_SUCCESS);
11797 }
11798 
11799 static int
11800 mptsas_diag_read_buffer(mptsas_t *mpt,
11801     mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
11802     uint32_t *return_code, int ioctl_mode)
11803 {
11804         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11805         uint8_t                         i, *pData;
11806         uint32_t                        unique_id, byte;
11807         int                             status;
11808 
11809         ASSERT(mutex_owned(&mpt->m_mutex));
11810 
11811         unique_id = diag_read_buffer->UniqueId;
11812 
11813         /*
11814          * Get the current buffer and look up the unique ID.  The unique ID
11815          * should be there.
11816          */
11817         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11818         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11819                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11820                 return (DDI_FAILURE);
11821         }
11822 
11823         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11824 
11825         /*
11826          * Make sure requested read is within limits
11827          */
11828         if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
11829             pBuffer->buffer_data.size) {
11830                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11831                 return (DDI_FAILURE);
11832         }
11833 
11834         /*
11835          * Copy the requested data from DMA to the diag_read_buffer.  The DMA
11836          * buffer that was allocated is one contiguous buffer.
11837          */
11838         pData = (uint8_t *)(pBuffer->buffer_data.memp +
11839             diag_read_buffer->StartingOffset);
11840         (void) ddi_dma_sync(pBuffer->buffer_data.handle, 0, 0,
11841             DDI_DMA_SYNC_FORCPU);
11842         for (byte = 0; byte < diag_read_buffer->BytesToRead; byte++) {
11843                 if (ddi_copyout(pData + byte, ioctl_buf + byte, 1, ioctl_mode)
11844                     != 0) {
11845                         return (DDI_FAILURE);
11846                 }
11847         }
11848         diag_read_buffer->Status = 0;
11849 
11850         /*
11851          * Set or clear the Force Release flag.
11852          */
11853         if (pBuffer->force_release) {
11854                 diag_read_buffer->Flags |= MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
11855         } else {
11856                 diag_read_buffer->Flags &= ~MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
11857         }
11858 
11859         /*
11860          * If buffer is to be reregistered, make sure it's not already owned by
11861          * firmware first.
11862          */
11863         status = DDI_SUCCESS;
11864         if (!pBuffer->owned_by_firmware) {
11865                 if (diag_read_buffer->Flags & MPTSAS_FW_DIAG_FLAG_REREGISTER) {
11866                         status = mptsas_post_fw_diag_buffer(mpt, pBuffer,
11867                             return_code);
11868                 }
11869         }
11870 
11871         return (status);
11872 }
11873 
11874 static int
11875 mptsas_diag_release(mptsas_t *mpt, mptsas_fw_diag_release_t *diag_release,
11876     uint32_t *return_code)
11877 {
11878         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11879         uint8_t                         i;
11880         uint32_t                        unique_id;
11881         int                             status;
11882 
11883         ASSERT(mutex_owned(&mpt->m_mutex));
11884 
11885         unique_id = diag_release->UniqueId;
11886 
11887         /*
11888          * Get the current buffer and look up the unique ID.  The unique ID
11889          * should be there.
11890          */
11891         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11892         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11893                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11894                 return (DDI_FAILURE);
11895         }
11896 
11897         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11898 
11899         /*
11900          * If buffer is not owned by firmware, it's already been released.
11901          */
11902         if (!pBuffer->owned_by_firmware) {
11903                 *return_code = MPTSAS_FW_DIAG_ERROR_ALREADY_RELEASED;
11904                 return (DDI_FAILURE);
11905         }
11906 
11907         /*
11908          * Release the buffer.
11909          */
11910         status = mptsas_release_fw_diag_buffer(mpt, pBuffer, return_code,
11911             MPTSAS_FW_DIAG_TYPE_RELEASE);
11912         return (status);
11913 }
11914 
11915 static int
11916 mptsas_do_diag_action(mptsas_t *mpt, uint32_t action, uint8_t *diag_action,
11917     uint32_t length, uint32_t *return_code, int ioctl_mode)
11918 {
11919         mptsas_fw_diag_register_t       diag_register;
11920         mptsas_fw_diag_unregister_t     diag_unregister;
11921         mptsas_fw_diag_query_t          diag_query;
11922         mptsas_diag_read_buffer_t       diag_read_buffer;
11923         mptsas_fw_diag_release_t        diag_release;
11924         int                             status = DDI_SUCCESS;
11925         uint32_t                        original_return_code, read_buf_len;
11926 
11927         ASSERT(mutex_owned(&mpt->m_mutex));
11928 
11929         original_return_code = *return_code;
11930         *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
11931 
11932         switch (action) {
11933                 case MPTSAS_FW_DIAG_TYPE_REGISTER:
11934                         if (!length) {
11935                                 *return_code =
11936                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11937                                 status = DDI_FAILURE;
11938                                 break;
11939                         }
11940                         if (ddi_copyin(diag_action, &diag_register,
11941                             sizeof (diag_register), ioctl_mode) != 0) {
11942                                 return (DDI_FAILURE);
11943                         }
11944                         status = mptsas_diag_register(mpt, &diag_register,
11945                             return_code);
11946                         break;
11947 
11948                 case MPTSAS_FW_DIAG_TYPE_UNREGISTER:
11949                         if (length < sizeof (diag_unregister)) {
11950                                 *return_code =
11951                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11952                                 status = DDI_FAILURE;
11953                                 break;
11954                         }
11955                         if (ddi_copyin(diag_action, &diag_unregister,
11956                             sizeof (diag_unregister), ioctl_mode) != 0) {
11957                                 return (DDI_FAILURE);
11958                         }
11959                         status = mptsas_diag_unregister(mpt, &diag_unregister,
11960                             return_code);
11961                         break;
11962 
11963                 case MPTSAS_FW_DIAG_TYPE_QUERY:
11964                         if (length < sizeof (diag_query)) {
11965                                 *return_code =
11966                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11967                                 status = DDI_FAILURE;
11968                                 break;
11969                         }
11970                         if (ddi_copyin(diag_action, &diag_query,
11971                             sizeof (diag_query), ioctl_mode) != 0) {
11972                                 return (DDI_FAILURE);
11973                         }
11974                         status = mptsas_diag_query(mpt, &diag_query,
11975                             return_code);
11976                         if (status == DDI_SUCCESS) {
11977                                 if (ddi_copyout(&diag_query, diag_action,
11978                                     sizeof (diag_query), ioctl_mode) != 0) {
11979                                         return (DDI_FAILURE);
11980                                 }
11981                         }
11982                         break;
11983 
11984                 case MPTSAS_FW_DIAG_TYPE_READ_BUFFER:
11985                         if (ddi_copyin(diag_action, &diag_read_buffer,
11986                             sizeof (diag_read_buffer) - 4, ioctl_mode) != 0) {
11987                                 return (DDI_FAILURE);
11988                         }
11989                         read_buf_len = sizeof (diag_read_buffer) -
11990                             sizeof (diag_read_buffer.DataBuffer) +
11991                             diag_read_buffer.BytesToRead;
11992                         if (length < read_buf_len) {
11993                                 *return_code =
11994                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11995                                 status = DDI_FAILURE;
11996                                 break;
11997                         }
11998                         status = mptsas_diag_read_buffer(mpt,
11999                             &diag_read_buffer, diag_action +
12000                             sizeof (diag_read_buffer) - 4, return_code,
12001                             ioctl_mode);
12002                         if (status == DDI_SUCCESS) {
12003                                 if (ddi_copyout(&diag_read_buffer, diag_action,
12004                                     sizeof (diag_read_buffer) - 4, ioctl_mode)
12005                                     != 0) {
12006                                         return (DDI_FAILURE);
12007                                 }
12008                         }
12009                         break;
12010 
12011                 case MPTSAS_FW_DIAG_TYPE_RELEASE:
12012                         if (length < sizeof (diag_release)) {
12013                                 *return_code =
12014                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
12015                                 status = DDI_FAILURE;
12016                                 break;
12017                         }
12018                         if (ddi_copyin(diag_action, &diag_release,
12019                             sizeof (diag_release), ioctl_mode) != 0) {
12020                                 return (DDI_FAILURE);
12021                         }
12022                         status = mptsas_diag_release(mpt, &diag_release,
12023                             return_code);
12024                         break;
12025 
12026                 default:
12027                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
12028                         status = DDI_FAILURE;
12029                         break;
12030         }
12031 
12032         if ((status == DDI_FAILURE) &&
12033             (original_return_code == MPTSAS_FW_DIAG_NEW) &&
12034             (*return_code != MPTSAS_FW_DIAG_ERROR_SUCCESS)) {
12035                 status = DDI_SUCCESS;
12036         }
12037 
12038         return (status);
12039 }
12040 
12041 static int
12042 mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *user_data, int mode)
12043 {
12044         int                     status;
12045         mptsas_diag_action_t    driver_data;
12046 
12047         ASSERT(mutex_owned(&mpt->m_mutex));
12048 
12049         /*
12050          * Copy the user data to a driver data buffer.
12051          */
12052         if (ddi_copyin(user_data, &driver_data, sizeof (mptsas_diag_action_t),
12053             mode) == 0) {
12054                 /*
12055                  * Send diag action request if Action is valid
12056                  */
12057                 if (driver_data.Action == MPTSAS_FW_DIAG_TYPE_REGISTER ||
12058                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_UNREGISTER ||
12059                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_QUERY ||
12060                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_READ_BUFFER ||
12061                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_RELEASE) {
12062                         status = mptsas_do_diag_action(mpt, driver_data.Action,
12063                             (void *)(uintptr_t)driver_data.PtrDiagAction,
12064                             driver_data.Length, &driver_data.ReturnCode,
12065                             mode);
12066                         if (status == DDI_SUCCESS) {
12067                                 if (ddi_copyout(&driver_data.ReturnCode,
12068                                     &user_data->ReturnCode,
12069                                     sizeof (user_data->ReturnCode), mode)
12070                                     != 0) {
12071                                         status = EFAULT;
12072                                 } else {
12073                                         status = 0;
12074                                 }
12075                         } else {
12076                                 status = EIO;
12077                         }
12078                 } else {
12079                         status = EINVAL;
12080                 }
12081         } else {
12082                 status = EFAULT;
12083         }
12084 
12085         return (status);
12086 }
12087 
12088 /*
12089  * This routine handles the "event query" ioctl.
12090  */
12091 static int
12092 mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data, int mode,
12093     int *rval)
12094 {
12095         int                     status;
12096         mptsas_event_query_t    driverdata;
12097         uint8_t                 i;
12098 
12099         driverdata.Entries = MPTSAS_EVENT_QUEUE_SIZE;
12100 
12101         mutex_enter(&mpt->m_mutex);
12102         for (i = 0; i < 4; i++) {
12103                 driverdata.Types[i] = mpt->m_event_mask[i];
12104         }
12105         mutex_exit(&mpt->m_mutex);
12106 
12107         if (ddi_copyout(&driverdata, data, sizeof (driverdata), mode) != 0) {
12108                 status = EFAULT;
12109         } else {
12110                 *rval = MPTIOCTL_STATUS_GOOD;
12111                 status = 0;
12112         }
12113 
12114         return (status);
12115 }
12116 
12117 /*
12118  * This routine handles the "event enable" ioctl.
12119  */
12120 static int
12121 mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data, int mode,
12122     int *rval)
12123 {
12124         int                     status;
12125         mptsas_event_enable_t   driverdata;
12126         uint8_t                 i;
12127 
12128         if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
12129                 mutex_enter(&mpt->m_mutex);
12130                 for (i = 0; i < 4; i++) {
12131                         mpt->m_event_mask[i] = driverdata.Types[i];
12132                 }
12133                 mutex_exit(&mpt->m_mutex);
12134 
12135                 *rval = MPTIOCTL_STATUS_GOOD;
12136                 status = 0;
12137         } else {
12138                 status = EFAULT;
12139         }
12140         return (status);
12141 }
12142 
12143 /*
12144  * This routine handles the "event report" ioctl.
12145  */
12146 static int
12147 mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data, int mode,
12148     int *rval)
12149 {
12150         int                     status;
12151         mptsas_event_report_t   driverdata;
12152 
12153         mutex_enter(&mpt->m_mutex);
12154 
12155         if (ddi_copyin(&data->Size, &driverdata.Size, sizeof (driverdata.Size),
12156             mode) == 0) {
12157                 if (driverdata.Size >= sizeof (mpt->m_events)) {
12158                         if (ddi_copyout(mpt->m_events, data->Events,
12159                             sizeof (mpt->m_events), mode) != 0) {
12160                                 status = EFAULT;
12161                         } else {
12162                                 if (driverdata.Size > sizeof (mpt->m_events)) {
12163                                         driverdata.Size =
12164                                             sizeof (mpt->m_events);
12165                                         if (ddi_copyout(&driverdata.Size,
12166                                             &data->Size,
12167                                             sizeof (driverdata.Size),
12168                                             mode) != 0) {
12169                                                 status = EFAULT;
12170                                         } else {
12171                                                 *rval = MPTIOCTL_STATUS_GOOD;
12172                                                 status = 0;
12173                                         }
12174                                 } else {
12175                                         *rval = MPTIOCTL_STATUS_GOOD;
12176                                         status = 0;
12177                                 }
12178                         }
12179                 } else {
12180                         *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
12181                         status = 0;
12182                 }
12183         } else {
12184                 status = EFAULT;
12185         }
12186 
12187         mutex_exit(&mpt->m_mutex);
12188         return (status);
12189 }
12190 
12191 static void
12192 mptsas_lookup_pci_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
12193 {
12194         int     *reg_data;
12195         uint_t  reglen;
12196 
12197         /*
12198          * Lookup the 'reg' property and extract the other data
12199          */
12200         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
12201             DDI_PROP_DONTPASS, "reg", &reg_data, &reglen) ==
12202             DDI_PROP_SUCCESS) {
12203                 /*
12204                  * Extract the PCI data from the 'reg' property first DWORD.
12205                  * The entry looks like the following:
12206                  * First DWORD:
12207                  * Bits 0 - 7 8-bit Register number
12208                  * Bits 8 - 10 3-bit Function number
12209                  * Bits 11 - 15 5-bit Device number
12210                  * Bits 16 - 23 8-bit Bus number
12211                  * Bits 24 - 25 2-bit Address Space type identifier
12212                  *
12213                  */
12214                 adapter_data->PciInformation.u.bits.BusNumber =
12215                     (reg_data[0] & 0x00FF0000) >> 16;
12216                 adapter_data->PciInformation.u.bits.DeviceNumber =
12217                     (reg_data[0] & 0x0000F800) >> 11;
12218                 adapter_data->PciInformation.u.bits.FunctionNumber =
12219                     (reg_data[0] & 0x00000700) >> 8;
12220                 ddi_prop_free((void *)reg_data);
12221         } else {
12222                 /*
12223                  * If we can't determine the PCI data then we fill in FF's for
12224                  * the data to indicate this.
12225                  */
12226                 adapter_data->PCIDeviceHwId = 0xFFFFFFFF;
12227                 adapter_data->MpiPortNumber = 0xFFFFFFFF;
12228                 adapter_data->PciInformation.u.AsDWORD = 0xFFFFFFFF;
12229         }
12230 
12231         /*
12232          * Saved in the mpt->m_fwversion
12233          */
12234         adapter_data->MpiFirmwareVersion = mpt->m_fwversion;
12235 }
12236 
12237 static void
12238 mptsas_read_adapter_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
12239 {
12240         char    *driver_verstr = MPTSAS_MOD_STRING;
12241 
12242         mptsas_lookup_pci_data(mpt, adapter_data);
12243         adapter_data->AdapterType = mpt->m_MPI25 ?
12244             MPTIOCTL_ADAPTER_TYPE_SAS3 :
12245             MPTIOCTL_ADAPTER_TYPE_SAS2;
12246         adapter_data->PCIDeviceHwId = (uint32_t)mpt->m_devid;
12247         adapter_data->PCIDeviceHwRev = (uint32_t)mpt->m_revid;
12248         adapter_data->SubSystemId = (uint32_t)mpt->m_ssid;
12249         adapter_data->SubsystemVendorId = (uint32_t)mpt->m_svid;
12250         (void) strcpy((char *)&adapter_data->DriverVersion[0], driver_verstr);
12251         adapter_data->BiosVersion = 0;
12252         (void) mptsas_get_bios_page3(mpt, &adapter_data->BiosVersion);
12253 }
12254 
12255 static void
12256 mptsas_read_pci_info(mptsas_t *mpt, mptsas_pci_info_t *pci_info)
12257 {
12258         int     *reg_data, i;
12259         uint_t  reglen;
12260 
12261         /*
12262          * Lookup the 'reg' property and extract the other data
12263          */
12264         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
12265             DDI_PROP_DONTPASS, "reg", &reg_data, &reglen) ==
12266             DDI_PROP_SUCCESS) {
12267                 /*
12268                  * Extract the PCI data from the 'reg' property first DWORD.
12269                  * The entry looks like the following:
12270                  * First DWORD:
12271                  * Bits 8 - 10 3-bit Function number
12272                  * Bits 11 - 15 5-bit Device number
12273                  * Bits 16 - 23 8-bit Bus number
12274                  */
12275                 pci_info->BusNumber = (reg_data[0] & 0x00FF0000) >> 16;
12276                 pci_info->DeviceNumber = (reg_data[0] & 0x0000F800) >> 11;
12277                 pci_info->FunctionNumber = (reg_data[0] & 0x00000700) >> 8;
12278                 ddi_prop_free((void *)reg_data);
12279         } else {
12280                 /*
12281                  * If we can't determine the PCI info then we fill in FF's for
12282                  * the data to indicate this.
12283                  */
12284                 pci_info->BusNumber = 0xFFFFFFFF;
12285                 pci_info->DeviceNumber = 0xFF;
12286                 pci_info->FunctionNumber = 0xFF;
12287         }
12288 
12289         /*
12290          * Now get the interrupt vector and the pci header.  The vector can
12291          * only be 0 right now.  The header is the first 256 bytes of config
12292          * space.
12293          */
12294         pci_info->InterruptVector = 0;
12295         for (i = 0; i < sizeof (pci_info->PciHeader); i++) {
12296                 pci_info->PciHeader[i] = pci_config_get8(mpt->m_config_handle,
12297                     i);
12298         }
12299 }
12300 
12301 static int
12302 mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data, int mode)
12303 {
12304         int                     status = 0;
12305         mptsas_reg_access_t     driverdata;
12306 
12307         mutex_enter(&mpt->m_mutex);
12308         if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
12309                 switch (driverdata.Command) {
12310                         /*
12311                          * IO access is not supported.
12312                          */
12313                         case REG_IO_READ:
12314                         case REG_IO_WRITE:
12315                                 mptsas_log(mpt, CE_WARN, "IO access is not "
12316                                     "supported.  Use memory access.");
12317                                 status = EINVAL;
12318                                 break;
12319 
12320                         case REG_MEM_READ:
12321                                 driverdata.RegData = ddi_get32(mpt->m_datap,
12322                                     (uint32_t *)(void *)mpt->m_reg +
12323                                     driverdata.RegOffset);
12324                                 if (ddi_copyout(&driverdata.RegData,
12325                                     &data->RegData,
12326                                     sizeof (driverdata.RegData), mode) != 0) {
12327                                         mptsas_log(mpt, CE_WARN, "Register "
12328                                             "Read Failed");
12329                                         status = EFAULT;
12330                                 }
12331                                 break;
12332 
12333                         case REG_MEM_WRITE:
12334                                 ddi_put32(mpt->m_datap,
12335                                     (uint32_t *)(void *)mpt->m_reg +
12336                                     driverdata.RegOffset,
12337                                     driverdata.RegData);
12338                                 break;
12339 
12340                         default:
12341                                 status = EINVAL;
12342                                 break;
12343                 }
12344         } else {
12345                 status = EFAULT;
12346         }
12347 
12348         mutex_exit(&mpt->m_mutex);
12349         return (status);
12350 }
12351 
12352 static int
12353 led_control(mptsas_t *mpt, intptr_t data, int mode)
12354 {
12355         int ret = 0;
12356         mptsas_led_control_t lc;
12357         mptsas_target_t *ptgt;
12358 
12359         if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) {
12360                 return (EFAULT);
12361         }
12362 
12363         if ((lc.Command != MPTSAS_LEDCTL_FLAG_SET &&
12364             lc.Command != MPTSAS_LEDCTL_FLAG_GET) ||
12365             lc.Led < MPTSAS_LEDCTL_LED_MIN ||
12366             lc.Led > MPTSAS_LEDCTL_LED_MAX ||
12367             (lc.Command == MPTSAS_LEDCTL_FLAG_SET && lc.LedStatus != 0 &&
12368             lc.LedStatus != 1)) {
12369                 return (EINVAL);
12370         }
12371 
12372         if ((lc.Command == MPTSAS_LEDCTL_FLAG_SET && (mode & FWRITE) == 0) ||
12373             (lc.Command == MPTSAS_LEDCTL_FLAG_GET && (mode & FREAD) == 0))
12374                 return (EACCES);
12375 
12376         /* Locate the target we're interrogating... */
12377         mutex_enter(&mpt->m_mutex);
12378         ptgt = refhash_linear_search(mpt->m_targets,
12379             mptsas_target_eval_slot, &lc);
12380         if (ptgt == NULL) {
12381                 /* We could not find a target for that enclosure/slot. */
12382                 mutex_exit(&mpt->m_mutex);
12383                 return (ENOENT);
12384         }
12385 
12386         if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) {
12387                 /* Update our internal LED state. */
12388                 ptgt->m_led_status &= ~(1 << (lc.Led - 1));
12389                 ptgt->m_led_status |= lc.LedStatus << (lc.Led - 1);
12390 
12391                 /* Flush it to the controller. */
12392                 ret = mptsas_flush_led_status(mpt, ptgt);
12393                 mutex_exit(&mpt->m_mutex);
12394                 return (ret);
12395         }
12396 
12397         /* Return our internal LED state. */
12398         lc.LedStatus = (ptgt->m_led_status >> (lc.Led - 1)) & 1;
12399         mutex_exit(&mpt->m_mutex);
12400 
12401         if (ddi_copyout(&lc, (void *)data, sizeof (lc), mode) != 0) {
12402                 return (EFAULT);
12403         }
12404 
12405         return (0);
12406 }
12407 
12408 static int
12409 get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
12410 {
12411         uint16_t i = 0;
12412         uint16_t count = 0;
12413         int ret = 0;
12414         mptsas_target_t *ptgt;
12415         mptsas_disk_info_t *di;
12416         STRUCT_DECL(mptsas_get_disk_info, gdi);
12417 
12418         if ((mode & FREAD) == 0)
12419                 return (EACCES);
12420 
12421         STRUCT_INIT(gdi, get_udatamodel());
12422 
12423         if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi),
12424             mode) != 0) {
12425                 return (EFAULT);
12426         }
12427 
12428         /* Find out how many targets there are. */
12429         mutex_enter(&mpt->m_mutex);
12430         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
12431             ptgt = refhash_next(mpt->m_targets, ptgt)) {
12432                 count++;
12433         }
12434         mutex_exit(&mpt->m_mutex);
12435 
12436         /*
12437          * If we haven't been asked to copy out information on each target,
12438          * then just return the count.
12439          */
12440         STRUCT_FSET(gdi, DiskCount, count);
12441         if (STRUCT_FGETP(gdi, PtrDiskInfoArray) == NULL)
12442                 goto copy_out;
12443 
12444         /*
12445          * If we haven't been given a large enough buffer to copy out into,
12446          * let the caller know.
12447          */
12448         if (STRUCT_FGET(gdi, DiskInfoArraySize) <
12449             count * sizeof (mptsas_disk_info_t)) {
12450                 ret = ENOSPC;
12451                 goto copy_out;
12452         }
12453 
12454         di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP);
12455 
12456         mutex_enter(&mpt->m_mutex);
12457         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
12458             ptgt = refhash_next(mpt->m_targets, ptgt)) {
12459                 if (i >= count) {
12460                         /*
12461                          * The number of targets changed while we weren't
12462                          * looking, so give up.
12463                          */
12464                         refhash_rele(mpt->m_targets, ptgt);
12465                         mutex_exit(&mpt->m_mutex);
12466                         kmem_free(di, count * sizeof (mptsas_disk_info_t));
12467                         return (EAGAIN);
12468                 }
12469                 di[i].Instance = mpt->m_instance;
12470                 di[i].Enclosure = ptgt->m_enclosure;
12471                 di[i].Slot = ptgt->m_slot_num;
12472                 di[i].SasAddress = ptgt->m_addr.mta_wwn;
12473                 i++;
12474         }
12475         mutex_exit(&mpt->m_mutex);
12476         STRUCT_FSET(gdi, DiskCount, i);
12477 
12478         /* Copy out the disk information to the caller. */
12479         if (ddi_copyout((void *)di, STRUCT_FGETP(gdi, PtrDiskInfoArray),
12480             i * sizeof (mptsas_disk_info_t), mode) != 0) {
12481                 ret = EFAULT;
12482         }
12483 
12484         kmem_free(di, count * sizeof (mptsas_disk_info_t));
12485 
12486 copy_out:
12487         if (ddi_copyout(STRUCT_BUF(gdi), (void *)data, STRUCT_SIZE(gdi),
12488             mode) != 0) {
12489                 ret = EFAULT;
12490         }
12491 
12492         return (ret);
12493 }
12494 
12495 static int
12496 mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
12497     int *rval)
12498 {
12499         int                     status = 0;
12500         mptsas_t                *mpt;
12501         mptsas_update_flash_t   flashdata;
12502         mptsas_pass_thru_t      passthru_data;
12503         mptsas_adapter_data_t   adapter_data;
12504         mptsas_pci_info_t       pci_info;
12505         int                     copylen;
12506 
12507         int                     iport_flag = 0;
12508         dev_info_t              *dip = NULL;
12509         mptsas_phymask_t        phymask = 0;
12510         struct devctl_iocdata   *dcp = NULL;
12511         char                    *addr = NULL;
12512         mptsas_target_t         *ptgt = NULL;
12513 
12514         *rval = MPTIOCTL_STATUS_GOOD;
12515         if (secpolicy_sys_config(credp, B_FALSE) != 0) {
12516                 return (EPERM);
12517         }
12518 
12519         mpt = ddi_get_soft_state(mptsas_state, MINOR2INST(getminor(dev)));
12520         if (mpt == NULL) {
12521                 /*
12522                  * Called from iport node, get the states
12523                  */
12524                 iport_flag = 1;
12525                 dip = mptsas_get_dip_from_dev(dev, &phymask);
12526                 if (dip == NULL) {
12527                         return (ENXIO);
12528                 }
12529                 mpt = DIP2MPT(dip);
12530         }
12531         /* Make sure power level is D0 before accessing registers */
12532         mutex_enter(&mpt->m_mutex);
12533         if (mpt->m_options & MPTSAS_OPT_PM) {
12534                 (void) pm_busy_component(mpt->m_dip, 0);
12535                 if (mpt->m_power_level != PM_LEVEL_D0) {
12536                         mutex_exit(&mpt->m_mutex);
12537                         if (pm_raise_power(mpt->m_dip, 0, PM_LEVEL_D0) !=
12538                             DDI_SUCCESS) {
12539                                 mptsas_log(mpt, CE_WARN,
12540                                     "mptsas%d: mptsas_ioctl: Raise power "
12541                                     "request failed.", mpt->m_instance);
12542                                 (void) pm_idle_component(mpt->m_dip, 0);
12543                                 return (ENXIO);
12544                         }
12545                 } else {
12546                         mutex_exit(&mpt->m_mutex);
12547                 }
12548         } else {
12549                 mutex_exit(&mpt->m_mutex);
12550         }
12551 
12552         if (iport_flag) {
12553                 status = scsi_hba_ioctl(dev, cmd, data, mode, credp, rval);
12554                 if (status != 0) {
12555                         goto out;
12556                 }
12557                 /*
12558                  * The following code control the OK2RM LED, it doesn't affect
12559                  * the ioctl return status.
12560                  */
12561                 if ((cmd == DEVCTL_DEVICE_ONLINE) ||
12562                     (cmd == DEVCTL_DEVICE_OFFLINE)) {
12563                         if (ndi_dc_allochdl((void *)data, &dcp) !=
12564                             NDI_SUCCESS) {
12565                                 goto out;
12566                         }
12567                         addr = ndi_dc_getaddr(dcp);
12568                         ptgt = mptsas_addr_to_ptgt(mpt, addr, phymask);
12569                         if (ptgt == NULL) {
12570                                 NDBG14(("mptsas_ioctl led control: tgt %s not "
12571                                     "found", addr));
12572                                 ndi_dc_freehdl(dcp);
12573                                 goto out;
12574                         }
12575                         mutex_enter(&mpt->m_mutex);
12576                         if (cmd == DEVCTL_DEVICE_ONLINE) {
12577                                 ptgt->m_tgt_unconfigured = 0;
12578                         } else if (cmd == DEVCTL_DEVICE_OFFLINE) {
12579                                 ptgt->m_tgt_unconfigured = 1;
12580                         }
12581                         if (cmd == DEVCTL_DEVICE_OFFLINE) {
12582                                 ptgt->m_led_status |=
12583                                     (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
12584                         } else {
12585                                 ptgt->m_led_status &=
12586                                     ~(1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
12587                         }
12588                         (void) mptsas_flush_led_status(mpt, ptgt);
12589                         mutex_exit(&mpt->m_mutex);
12590                         ndi_dc_freehdl(dcp);
12591                 }
12592                 goto out;
12593         }
12594         switch (cmd) {
12595                 case MPTIOCTL_GET_DISK_INFO:
12596                         status = get_disk_info(mpt, data, mode);
12597                         break;
12598                 case MPTIOCTL_LED_CONTROL:
12599                         status = led_control(mpt, data, mode);
12600                         break;
12601                 case MPTIOCTL_UPDATE_FLASH:
12602                         if (ddi_copyin((void *)data, &flashdata,
12603                                 sizeof (struct mptsas_update_flash), mode)) {
12604                                 status = EFAULT;
12605                                 break;
12606                         }
12607 
12608                         mutex_enter(&mpt->m_mutex);
12609                         if (mptsas_update_flash(mpt,
12610                             (caddr_t)(long)flashdata.PtrBuffer,
12611                             flashdata.ImageSize, flashdata.ImageType, mode)) {
12612                                 status = EFAULT;
12613                         }
12614 
12615                         /*
12616                          * Reset the chip to start using the new
12617                          * firmware.  Reset if failed also.
12618                          */
12619                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
12620                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
12621                                 status = EFAULT;
12622                         }
12623                         mutex_exit(&mpt->m_mutex);
12624                         break;
12625                 case MPTIOCTL_PASS_THRU:
12626                         /*
12627                          * The user has requested to pass through a command to
12628                          * be executed by the MPT firmware.  Call our routine
12629                          * which does this.  Only allow one passthru IOCTL at
12630                          * one time. Other threads will block on
12631                          * m_passthru_mutex, which is of adaptive variant.
12632                          */
12633                         if (ddi_copyin((void *)data, &passthru_data,
12634                             sizeof (mptsas_pass_thru_t), mode)) {
12635                                 status = EFAULT;
12636                                 break;
12637                         }
12638                         mutex_enter(&mpt->m_passthru_mutex);
12639                         mutex_enter(&mpt->m_mutex);
12640                         status = mptsas_pass_thru(mpt, &passthru_data, mode);
12641                         mutex_exit(&mpt->m_mutex);
12642                         mutex_exit(&mpt->m_passthru_mutex);
12643 
12644                         break;
12645                 case MPTIOCTL_GET_ADAPTER_DATA:
12646                         /*
12647                          * The user has requested to read adapter data.  Call
12648                          * our routine which does this.
12649                          */
12650                         bzero(&adapter_data, sizeof (mptsas_adapter_data_t));
12651                         if (ddi_copyin((void *)data, (void *)&adapter_data,
12652                             sizeof (mptsas_adapter_data_t), mode)) {
12653                                 status = EFAULT;
12654                                 break;
12655                         }
12656                         if (adapter_data.StructureLength >=
12657                             sizeof (mptsas_adapter_data_t)) {
12658                                 adapter_data.StructureLength = (uint32_t)
12659                                     sizeof (mptsas_adapter_data_t);
12660                                 copylen = sizeof (mptsas_adapter_data_t);
12661                                 mutex_enter(&mpt->m_mutex);
12662                                 mptsas_read_adapter_data(mpt, &adapter_data);
12663                                 mutex_exit(&mpt->m_mutex);
12664                         } else {
12665                                 adapter_data.StructureLength = (uint32_t)
12666                                     sizeof (mptsas_adapter_data_t);
12667                                 copylen = sizeof (adapter_data.StructureLength);
12668                                 *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
12669                         }
12670                         if (ddi_copyout((void *)(&adapter_data), (void *)data,
12671                             copylen, mode) != 0) {
12672                                 status = EFAULT;
12673                         }
12674                         break;
12675                 case MPTIOCTL_GET_PCI_INFO:
12676                         /*
12677                          * The user has requested to read pci info.  Call
12678                          * our routine which does this.
12679                          */
12680                         bzero(&pci_info, sizeof (mptsas_pci_info_t));
12681                         mutex_enter(&mpt->m_mutex);
12682                         mptsas_read_pci_info(mpt, &pci_info);
12683                         mutex_exit(&mpt->m_mutex);
12684                         if (ddi_copyout((void *)(&pci_info), (void *)data,
12685                             sizeof (mptsas_pci_info_t), mode) != 0) {
12686                                 status = EFAULT;
12687                         }
12688                         break;
12689                 case MPTIOCTL_RESET_ADAPTER:
12690                         mutex_enter(&mpt->m_mutex);
12691                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
12692                         if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
12693                                 mptsas_log(mpt, CE_WARN, "reset adapter IOCTL "
12694                                     "failed");
12695                                 status = EFAULT;
12696                         }
12697                         mutex_exit(&mpt->m_mutex);
12698                         break;
12699                 case MPTIOCTL_DIAG_ACTION:
12700                         /*
12701                          * The user has done a diag buffer action.  Call our
12702                          * routine which does this.  Only allow one diag action
12703                          * at one time.
12704                          */
12705                         mutex_enter(&mpt->m_mutex);
12706                         if (mpt->m_diag_action_in_progress) {
12707                                 mutex_exit(&mpt->m_mutex);
12708                                 return (EBUSY);
12709                         }
12710                         mpt->m_diag_action_in_progress = 1;
12711                         status = mptsas_diag_action(mpt,
12712                             (mptsas_diag_action_t *)data, mode);
12713                         mpt->m_diag_action_in_progress = 0;
12714                         mutex_exit(&mpt->m_mutex);
12715                         break;
12716                 case MPTIOCTL_EVENT_QUERY:
12717                         /*
12718                          * The user has done an event query. Call our routine
12719                          * which does this.
12720                          */
12721                         status = mptsas_event_query(mpt,
12722                             (mptsas_event_query_t *)data, mode, rval);
12723                         break;
12724                 case MPTIOCTL_EVENT_ENABLE:
12725                         /*
12726                          * The user has done an event enable. Call our routine
12727                          * which does this.
12728                          */
12729                         status = mptsas_event_enable(mpt,
12730                             (mptsas_event_enable_t *)data, mode, rval);
12731                         break;
12732                 case MPTIOCTL_EVENT_REPORT:
12733                         /*
12734                          * The user has done an event report. Call our routine
12735                          * which does this.
12736                          */
12737                         status = mptsas_event_report(mpt,
12738                             (mptsas_event_report_t *)data, mode, rval);
12739                         break;
12740                 case MPTIOCTL_REG_ACCESS:
12741                         /*
12742                          * The user has requested register access.  Call our
12743                          * routine which does this.
12744                          */
12745                         status = mptsas_reg_access(mpt,
12746                             (mptsas_reg_access_t *)data, mode);
12747                         break;
12748                 default:
12749                         status = scsi_hba_ioctl(dev, cmd, data, mode, credp,
12750                             rval);
12751                         break;
12752         }
12753 
12754 out:
12755         return (status);
12756 }
12757 
12758 /* Dirty wrapper for taskq */
12759 void
12760 mptsas_handle_restart_ioc(void *mpt) {
12761     mptsas_restart_ioc((mptsas_t *) mpt);
12762 }
12763 
12764 int
12765 mptsas_restart_ioc(mptsas_t *mpt)
12766 {
12767         int             rval = DDI_SUCCESS;
12768         mptsas_target_t *ptgt = NULL;
12769 
12770         ASSERT(mutex_owned(&mpt->m_mutex));
12771 
12772         /*
12773          * Set a flag telling I/O path that we're processing a reset.  This is
12774          * needed because after the reset is complete, the hash table still
12775          * needs to be rebuilt.  If I/Os are started before the hash table is
12776          * rebuilt, I/O errors will occur.  This flag allows I/Os to be marked
12777          * so that they can be retried.
12778          */
12779         mpt->m_in_reset = TRUE;
12780 
12781         /*
12782          * Set all throttles to HOLD
12783          */
12784         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
12785             ptgt = refhash_next(mpt->m_targets, ptgt)) {
12786                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
12787         }
12788 
12789         /*
12790          * Disable interrupts
12791          */
12792         MPTSAS_DISABLE_INTR(mpt);
12793 
12794         /*
12795          * Abort all commands: outstanding commands, commands in waitq and
12796          * tx_waitq.
12797          */
12798         mptsas_flush_hba(mpt);
12799 
12800         /*
12801          * Reinitialize the chip.
12802          */
12803         if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
12804                 rval = DDI_FAILURE;
12805         }
12806 
12807         /*
12808          * Enable interrupts again
12809          */
12810         MPTSAS_ENABLE_INTR(mpt);
12811 
12812         /*
12813          * If mptsas_init_chip was successful, update the driver data.
12814          */
12815         if (rval == DDI_SUCCESS) {
12816                 mptsas_update_driver_data(mpt);
12817         }
12818 
12819         /*
12820          * Reset the throttles
12821          */
12822         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
12823             ptgt = refhash_next(mpt->m_targets, ptgt)) {
12824                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
12825         }
12826 
12827         mptsas_doneq_empty(mpt);
12828         mptsas_restart_hba(mpt);
12829 
12830         if (rval != DDI_SUCCESS) {
12831                 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
12832                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
12833         }
12834 
12835         /*
12836          * Clear the reset flag so that I/Os can continue.
12837          */
12838         mpt->m_in_reset = FALSE;
12839 
12840         return (rval);
12841 }
12842 
12843 static int
12844 mptsas_init_chip(mptsas_t *mpt, int first_time)
12845 {
12846         ddi_dma_cookie_t        cookie;
12847         uint32_t                i;
12848         int                     rval;
12849 
12850         /*
12851          * Check to see if the firmware image is valid
12852          */
12853         if (ddi_get32(mpt->m_datap, &mpt->m_reg->HostDiagnostic) &
12854             MPI2_DIAG_FLASH_BAD_SIG) {
12855                 mptsas_log(mpt, CE_WARN, "mptsas bad flash signature!");
12856                 goto fail;
12857         }
12858 
12859         /*
12860          * Reset the chip
12861          */
12862         rval = mptsas_ioc_reset(mpt, first_time);
12863         if (rval == MPTSAS_RESET_FAIL) {
12864                 mptsas_log(mpt, CE_WARN, "hard reset failed!");
12865                 goto fail;
12866         }
12867 
12868         if ((rval == MPTSAS_SUCCESS_MUR) && (!first_time)) {
12869                 goto mur;
12870         }
12871         /*
12872          * Setup configuration space
12873          */
12874         if (mptsas_config_space_init(mpt) == FALSE) {
12875                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init "
12876                     "failed!");
12877                 goto fail;
12878         }
12879 
12880         /*
12881          * IOC facts can change after a diag reset so all buffers that are
12882          * based on these numbers must be de-allocated and re-allocated.  Get
12883          * new IOC facts each time chip is initialized.
12884          */
12885         if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
12886                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed");
12887                 goto fail;
12888         }
12889 
12890         if (mptsas_alloc_active_slots(mpt, KM_SLEEP)) {
12891                 goto fail;
12892         }
12893         /*
12894          * Allocate request message frames, reply free queue, reply descriptor
12895          * post queue, and reply message frames using latest IOC facts.
12896          */
12897         if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) {
12898                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames failed");
12899                 goto fail;
12900         }
12901         if (mptsas_alloc_sense_bufs(mpt) == DDI_FAILURE) {
12902                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_sense_bufs failed");
12903                 goto fail;
12904         }
12905         if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) {
12906                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue failed!");
12907                 goto fail;
12908         }
12909         if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) {
12910                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue failed!");
12911                 goto fail;
12912         }
12913         if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) {
12914                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_reply_frames failed!");
12915                 goto fail;
12916         }
12917 
12918 mur:
12919         /*
12920          * Re-Initialize ioc to operational state
12921          */
12922         if (mptsas_ioc_init(mpt) == DDI_FAILURE) {
12923                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_init failed");
12924                 goto fail;
12925         }
12926 
12927         mptsas_alloc_reply_args(mpt);
12928 
12929         /*
12930          * Initialize reply post index.  Reply free index is initialized after
12931          * the next loop.
12932          */
12933         mpt->m_post_index = 0;
12934 
12935         /*
12936          * Initialize the Reply Free Queue with the physical addresses of our
12937          * reply frames.
12938          */
12939         cookie.dmac_address = mpt->m_reply_frame_dma_addr & 0xffffffffu;
12940         for (i = 0; i < mpt->m_max_replies; i++) {
12941                 ddi_put32(mpt->m_acc_free_queue_hdl,
12942                     &((uint32_t *)(void *)mpt->m_free_queue)[i],
12943                     cookie.dmac_address);
12944                 cookie.dmac_address += mpt->m_reply_frame_size;
12945         }
12946         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
12947             DDI_DMA_SYNC_FORDEV);
12948 
12949         /*
12950          * Initialize the reply free index to one past the last frame on the
12951          * queue.  This will signify that the queue is empty to start with.
12952          */
12953         mpt->m_free_index = i;
12954         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex, i);
12955 
12956         /*
12957          * Initialize the reply post queue to 0xFFFFFFFF,0xFFFFFFFF's.
12958          */
12959         for (i = 0; i < mpt->m_post_queue_depth; i++) {
12960                 ddi_put64(mpt->m_acc_post_queue_hdl,
12961                     &((uint64_t *)(void *)mpt->m_post_queue)[i],
12962                     0xFFFFFFFFFFFFFFFF);
12963         }
12964         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
12965             DDI_DMA_SYNC_FORDEV);
12966 
12967         /*
12968          * Enable ports
12969          */
12970         if (mptsas_ioc_enable_port(mpt) == DDI_FAILURE) {
12971                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_enable_port failed");
12972                 goto fail;
12973         }
12974 
12975         /*
12976          * enable events
12977          */
12978         if (mptsas_ioc_enable_event_notification(mpt)) {
12979                 mptsas_log(mpt, CE_WARN,
12980                     "mptsas_ioc_enable_event_notification failed");
12981                 goto fail;
12982         }
12983 
12984         /*
12985          * We need checks in attach and these.
12986          * chip_init is called in mult. places
12987          */
12988 
12989         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
12990             DDI_SUCCESS) ||
12991             (mptsas_check_dma_handle(mpt->m_dma_req_sense_hdl) !=
12992             DDI_SUCCESS) ||
12993             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
12994             DDI_SUCCESS) ||
12995             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
12996             DDI_SUCCESS) ||
12997             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
12998             DDI_SUCCESS) ||
12999             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
13000             DDI_SUCCESS)) {
13001                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
13002                 goto fail;
13003         }
13004 
13005         /* Check all acc handles */
13006         if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
13007             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
13008             DDI_SUCCESS) ||
13009             (mptsas_check_acc_handle(mpt->m_acc_req_sense_hdl) !=
13010             DDI_SUCCESS) ||
13011             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
13012             DDI_SUCCESS) ||
13013             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
13014             DDI_SUCCESS) ||
13015             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
13016             DDI_SUCCESS) ||
13017             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
13018             DDI_SUCCESS) ||
13019             (mptsas_check_acc_handle(mpt->m_config_handle) !=
13020             DDI_SUCCESS)) {
13021                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
13022                 goto fail;
13023         }
13024 
13025         return (DDI_SUCCESS);
13026 
13027 fail:
13028         return (DDI_FAILURE);
13029 }
13030 
13031 static int
13032 mptsas_get_pci_cap(mptsas_t *mpt)
13033 {
13034         ushort_t caps_ptr, cap, cap_count;
13035 
13036         if (mpt->m_config_handle == NULL)
13037                 return (FALSE);
13038         /*
13039          * Check if capabilities list is supported and if so,
13040          * get initial capabilities pointer and clear bits 0,1.
13041          */
13042         if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT)
13043             & PCI_STAT_CAP) {
13044                 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
13045                     PCI_CONF_CAP_PTR), 4);
13046         } else {
13047                 caps_ptr = PCI_CAP_NEXT_PTR_NULL;
13048         }
13049 
13050         /*
13051          * Walk capabilities if supported.
13052          */
13053         for (cap_count = 0; caps_ptr != PCI_CAP_NEXT_PTR_NULL; ) {
13054 
13055                 /*
13056                  * Check that we haven't exceeded the maximum number of
13057                  * capabilities and that the pointer is in a valid range.
13058                  */
13059                 if (++cap_count > 48) {
13060                         mptsas_log(mpt, CE_WARN,
13061                             "too many device capabilities.\n");
13062                         break;
13063                 }
13064                 if (caps_ptr < 64) {
13065                         mptsas_log(mpt, CE_WARN,
13066                             "capabilities pointer 0x%x out of range.\n",
13067                             caps_ptr);
13068                         break;
13069                 }
13070 
13071                 /*
13072                  * Get next capability and check that it is valid.
13073                  * For now, we only support power management.
13074                  */
13075                 cap = pci_config_get8(mpt->m_config_handle, caps_ptr);
13076                 switch (cap) {
13077                         case PCI_CAP_ID_PM:
13078                                 mptsas_log(mpt, CE_NOTE,
13079                                     "?mptsas%d supports power management.\n",
13080                                     mpt->m_instance);
13081                                 mpt->m_options |= MPTSAS_OPT_PM;
13082 
13083                                 /* Save PMCSR offset */
13084                                 mpt->m_pmcsr_offset = caps_ptr + PCI_PMCSR;
13085                                 break;
13086                         /*
13087                          * The following capabilities are valid.  Any others
13088                          * will cause a message to be logged.
13089                          */
13090                         case PCI_CAP_ID_VPD:
13091                         case PCI_CAP_ID_MSI:
13092                         case PCI_CAP_ID_PCIX:
13093                         case PCI_CAP_ID_PCI_E:
13094                         case PCI_CAP_ID_MSI_X:
13095                                 break;
13096                         default:
13097                                 mptsas_log(mpt, CE_NOTE,
13098                                     "?mptsas%d unrecognized capability "
13099                                     "0x%x.\n", mpt->m_instance, cap);
13100                                 break;
13101                 }
13102 
13103                 /*
13104                  * Get next capabilities pointer and clear bits 0,1.
13105                  */
13106                 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
13107                     (caps_ptr + PCI_CAP_NEXT_PTR)), 4);
13108         }
13109         return (TRUE);
13110 }
13111 
13112 static int
13113 mptsas_init_pm(mptsas_t *mpt)
13114 {
13115         char            pmc_name[16];
13116         char            *pmc[] = {
13117                                 NULL,
13118                                 "0=Off (PCI D3 State)",
13119                                 "3=On (PCI D0 State)",
13120                                 NULL
13121                         };
13122         uint16_t        pmcsr_stat;
13123 
13124         if (mptsas_get_pci_cap(mpt) == FALSE) {
13125                 return (DDI_FAILURE);
13126         }
13127         /*
13128          * If PCI's capability does not support PM, then don't need
13129          * to registe the pm-components
13130          */
13131         if (!(mpt->m_options & MPTSAS_OPT_PM))
13132                 return (DDI_SUCCESS);
13133         /*
13134          * If power management is supported by this chip, create
13135          * pm-components property for the power management framework
13136          */
13137         (void) sprintf(pmc_name, "NAME=mptsas%d", mpt->m_instance);
13138         pmc[0] = pmc_name;
13139         if (ddi_prop_update_string_array(DDI_DEV_T_NONE, mpt->m_dip,
13140             "pm-components", pmc, 3) != DDI_PROP_SUCCESS) {
13141                 mpt->m_options &= ~MPTSAS_OPT_PM;
13142                 mptsas_log(mpt, CE_WARN,
13143                     "mptsas%d: pm-component property creation failed.",
13144                     mpt->m_instance);
13145                 return (DDI_FAILURE);
13146         }
13147 
13148         /*
13149          * Power on device.
13150          */
13151         (void) pm_busy_component(mpt->m_dip, 0);
13152         pmcsr_stat = pci_config_get16(mpt->m_config_handle,
13153             mpt->m_pmcsr_offset);
13154         if ((pmcsr_stat & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_D0) {
13155                 mptsas_log(mpt, CE_WARN, "mptsas%d: Power up the device",
13156                     mpt->m_instance);
13157                 pci_config_put16(mpt->m_config_handle, mpt->m_pmcsr_offset,
13158                     PCI_PMCSR_D0);
13159         }
13160         if (pm_power_has_changed(mpt->m_dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) {
13161                 mptsas_log(mpt, CE_WARN, "pm_power_has_changed failed");
13162                 return (DDI_FAILURE);
13163         }
13164         mpt->m_power_level = PM_LEVEL_D0;
13165         /*
13166          * Set pm idle delay.
13167          */
13168         mpt->m_pm_idle_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
13169             mpt->m_dip, 0, "mptsas-pm-idle-delay", MPTSAS_PM_IDLE_TIMEOUT);
13170 
13171         return (DDI_SUCCESS);
13172 }
13173 
13174 static int
13175 mptsas_register_intrs(mptsas_t *mpt)
13176 {
13177         dev_info_t *dip;
13178         int intr_types;
13179 
13180         dip = mpt->m_dip;
13181 
13182         /* Get supported interrupt types */
13183         if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) {
13184                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_supported_types "
13185                     "failed\n");
13186                 return (FALSE);
13187         }
13188 
13189         NDBG6(("ddi_intr_get_supported_types() returned: 0x%x", intr_types));
13190 
13191         /*
13192          * Try MSI, but fall back to FIXED
13193          */
13194         if (mptsas_enable_msi && (intr_types & DDI_INTR_TYPE_MSI)) {
13195                 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_MSI) == DDI_SUCCESS) {
13196                         NDBG0(("Using MSI interrupt type"));
13197                         mpt->m_intr_type = DDI_INTR_TYPE_MSI;
13198                         return (TRUE);
13199                 }
13200         }
13201         if (intr_types & DDI_INTR_TYPE_FIXED) {
13202                 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_FIXED) == DDI_SUCCESS) {
13203                         NDBG0(("Using FIXED interrupt type"));
13204                         mpt->m_intr_type = DDI_INTR_TYPE_FIXED;
13205                         return (TRUE);
13206                 } else {
13207                         NDBG0(("FIXED interrupt registration failed"));
13208                         return (FALSE);
13209                 }
13210         }
13211 
13212         return (FALSE);
13213 }
13214 
13215 static void
13216 mptsas_unregister_intrs(mptsas_t *mpt)
13217 {
13218         mptsas_rem_intrs(mpt);
13219 }
13220 
13221 /*
13222  * mptsas_add_intrs:
13223  *
13224  * Register FIXED or MSI interrupts.
13225  */
13226 static int
13227 mptsas_add_intrs(mptsas_t *mpt, int intr_type)
13228 {
13229         dev_info_t      *dip = mpt->m_dip;
13230         int             avail, actual, count = 0;
13231         int             i, flag, ret;
13232 
13233         NDBG6(("mptsas_add_intrs:interrupt type 0x%x", intr_type));
13234 
13235         /* Get number of interrupts */
13236         ret = ddi_intr_get_nintrs(dip, intr_type, &count);
13237         if ((ret != DDI_SUCCESS) || (count <= 0)) {
13238                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_nintrs() failed, "
13239                     "ret %d count %d\n", ret, count);
13240 
13241                 return (DDI_FAILURE);
13242         }
13243 
13244         /* Get number of available interrupts */
13245         ret = ddi_intr_get_navail(dip, intr_type, &avail);
13246         if ((ret != DDI_SUCCESS) || (avail == 0)) {
13247                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_navail() failed, "
13248                     "ret %d avail %d\n", ret, avail);
13249 
13250                 return (DDI_FAILURE);
13251         }
13252 
13253         if (avail < count) {
13254                 mptsas_log(mpt, CE_NOTE, "ddi_intr_get_nvail returned %d, "
13255                     "navail() returned %d", count, avail);
13256         }
13257 
13258         /* Mpt only have one interrupt routine */
13259         if ((intr_type == DDI_INTR_TYPE_MSI) && (count > 1)) {
13260                 count = 1;
13261         }
13262 
13263         /* Allocate an array of interrupt handles */
13264         mpt->m_intr_size = count * sizeof (ddi_intr_handle_t);
13265         mpt->m_htable = kmem_alloc(mpt->m_intr_size, KM_SLEEP);
13266 
13267         flag = DDI_INTR_ALLOC_NORMAL;
13268 
13269         /* call ddi_intr_alloc() */
13270         ret = ddi_intr_alloc(dip, mpt->m_htable, intr_type, 0,
13271             count, &actual, flag);
13272 
13273         if ((ret != DDI_SUCCESS) || (actual == 0)) {
13274                 mptsas_log(mpt, CE_WARN, "ddi_intr_alloc() failed, ret %d\n",
13275                     ret);
13276                 kmem_free(mpt->m_htable, mpt->m_intr_size);
13277                 return (DDI_FAILURE);
13278         }
13279 
13280         /* use interrupt count returned or abort? */
13281         if (actual < count) {
13282                 mptsas_log(mpt, CE_NOTE, "Requested: %d, Received: %d\n",
13283                     count, actual);
13284         }
13285 
13286         mpt->m_intr_cnt = actual;
13287 
13288         /*
13289          * Get priority for first msi, assume remaining are all the same
13290          */
13291         if ((ret = ddi_intr_get_pri(mpt->m_htable[0],
13292             &mpt->m_intr_pri)) != DDI_SUCCESS) {
13293                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_pri() failed %d\n", ret);
13294 
13295                 /* Free already allocated intr */
13296                 for (i = 0; i < actual; i++) {
13297                         (void) ddi_intr_free(mpt->m_htable[i]);
13298                 }
13299 
13300                 kmem_free(mpt->m_htable, mpt->m_intr_size);
13301                 return (DDI_FAILURE);
13302         }
13303 
13304         /* Test for high level mutex */
13305         if (mpt->m_intr_pri >= ddi_intr_get_hilevel_pri()) {
13306                 mptsas_log(mpt, CE_WARN, "mptsas_add_intrs: "
13307                     "Hi level interrupt not supported\n");
13308 
13309                 /* Free already allocated intr */
13310                 for (i = 0; i < actual; i++) {
13311                         (void) ddi_intr_free(mpt->m_htable[i]);
13312                 }
13313 
13314                 kmem_free(mpt->m_htable, mpt->m_intr_size);
13315                 return (DDI_FAILURE);
13316         }
13317 
13318         /* Call ddi_intr_add_handler() */
13319         for (i = 0; i < actual; i++) {
13320                 if ((ret = ddi_intr_add_handler(mpt->m_htable[i], mptsas_intr,
13321                     (caddr_t)mpt, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
13322                         mptsas_log(mpt, CE_WARN, "ddi_intr_add_handler() "
13323                             "failed %d\n", ret);
13324 
13325                         /* Free already allocated intr */
13326                         for (i = 0; i < actual; i++) {
13327                                 (void) ddi_intr_free(mpt->m_htable[i]);
13328                         }
13329 
13330                         kmem_free(mpt->m_htable, mpt->m_intr_size);
13331                         return (DDI_FAILURE);
13332                 }
13333         }
13334 
13335         if ((ret = ddi_intr_get_cap(mpt->m_htable[0], &mpt->m_intr_cap))
13336             != DDI_SUCCESS) {
13337                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_cap() failed %d\n", ret);
13338 
13339                 /* Free already allocated intr */
13340                 for (i = 0; i < actual; i++) {
13341                         (void) ddi_intr_free(mpt->m_htable[i]);
13342                 }
13343 
13344                 kmem_free(mpt->m_htable, mpt->m_intr_size);
13345                 return (DDI_FAILURE);
13346         }
13347 
13348         /*
13349          * Enable interrupts
13350          */
13351         if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
13352                 /* Call ddi_intr_block_enable() for MSI interrupts */
13353                 (void) ddi_intr_block_enable(mpt->m_htable, mpt->m_intr_cnt);
13354         } else {
13355                 /* Call ddi_intr_enable for MSI or FIXED interrupts */
13356                 for (i = 0; i < mpt->m_intr_cnt; i++) {
13357                         (void) ddi_intr_enable(mpt->m_htable[i]);
13358                 }
13359         }
13360         return (DDI_SUCCESS);
13361 }
13362 
13363 /*
13364  * mptsas_rem_intrs:
13365  *
13366  * Unregister FIXED or MSI interrupts
13367  */
13368 static void
13369 mptsas_rem_intrs(mptsas_t *mpt)
13370 {
13371         int     i;
13372 
13373         NDBG6(("mptsas_rem_intrs"));
13374 
13375         /* Disable all interrupts */
13376         if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
13377                 /* Call ddi_intr_block_disable() */
13378                 (void) ddi_intr_block_disable(mpt->m_htable, mpt->m_intr_cnt);
13379         } else {
13380                 for (i = 0; i < mpt->m_intr_cnt; i++) {
13381                         (void) ddi_intr_disable(mpt->m_htable[i]);
13382                 }
13383         }
13384 
13385         /* Call ddi_intr_remove_handler() */
13386         for (i = 0; i < mpt->m_intr_cnt; i++) {
13387                 (void) ddi_intr_remove_handler(mpt->m_htable[i]);
13388                 (void) ddi_intr_free(mpt->m_htable[i]);
13389         }
13390 
13391         kmem_free(mpt->m_htable, mpt->m_intr_size);
13392 }
13393 
13394 /*
13395  * The IO fault service error handling callback function
13396  */
13397 /*ARGSUSED*/
13398 static int
13399 mptsas_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
13400 {
13401         /*
13402          * as the driver can always deal with an error in any dma or
13403          * access handle, we can just return the fme_status value.
13404          */
13405         pci_ereport_post(dip, err, NULL);
13406         return (err->fme_status);
13407 }
13408 
13409 /*
13410  * mptsas_fm_init - initialize fma capabilities and register with IO
13411  *               fault services.
13412  */
13413 static void
13414 mptsas_fm_init(mptsas_t *mpt)
13415 {
13416         /*
13417          * Need to change iblock to priority for new MSI intr
13418          */
13419         ddi_iblock_cookie_t     fm_ibc;
13420 
13421         /* Only register with IO Fault Services if we have some capability */
13422         if (mpt->m_fm_capabilities) {
13423                 /* Adjust access and dma attributes for FMA */
13424                 mpt->m_reg_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
13425                 mpt->m_msg_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
13426                 mpt->m_io_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
13427 
13428                 /*
13429                  * Register capabilities with IO Fault Services.
13430                  * mpt->m_fm_capabilities will be updated to indicate
13431                  * capabilities actually supported (not requested.)
13432                  */
13433                 ddi_fm_init(mpt->m_dip, &mpt->m_fm_capabilities, &fm_ibc);
13434 
13435                 /*
13436                  * Initialize pci ereport capabilities if ereport
13437                  * capable (should always be.)
13438                  */
13439                 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
13440                     DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13441                         pci_ereport_setup(mpt->m_dip);
13442                 }
13443 
13444                 /*
13445                  * Register error callback if error callback capable.
13446                  */
13447                 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13448                         ddi_fm_handler_register(mpt->m_dip,
13449                             mptsas_fm_error_cb, (void *) mpt);
13450                 }
13451         }
13452 }
13453 
13454 /*
13455  * mptsas_fm_fini - Releases fma capabilities and un-registers with IO
13456  *               fault services.
13457  *
13458  */
13459 static void
13460 mptsas_fm_fini(mptsas_t *mpt)
13461 {
13462         /* Only unregister FMA capabilities if registered */
13463         if (mpt->m_fm_capabilities) {
13464 
13465                 /*
13466                  * Un-register error callback if error callback capable.
13467                  */
13468 
13469                 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13470                         ddi_fm_handler_unregister(mpt->m_dip);
13471                 }
13472 
13473                 /*
13474                  * Release any resources allocated by pci_ereport_setup()
13475                  */
13476 
13477                 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
13478                     DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13479                         pci_ereport_teardown(mpt->m_dip);
13480                 }
13481 
13482                 /* Unregister from IO Fault Services */
13483                 ddi_fm_fini(mpt->m_dip);
13484 
13485                 /* Adjust access and dma attributes for FMA */
13486                 mpt->m_reg_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
13487                 mpt->m_msg_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
13488                 mpt->m_io_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
13489 
13490         }
13491 }
13492 
13493 int
13494 mptsas_check_acc_handle(ddi_acc_handle_t handle)
13495 {
13496         ddi_fm_error_t  de;
13497 
13498         if (handle == NULL)
13499                 return (DDI_FAILURE);
13500         ddi_fm_acc_err_get(handle, &de, DDI_FME_VER0);
13501         return (de.fme_status);
13502 }
13503 
13504 int
13505 mptsas_check_dma_handle(ddi_dma_handle_t handle)
13506 {
13507         ddi_fm_error_t  de;
13508 
13509         if (handle == NULL)
13510                 return (DDI_FAILURE);
13511         ddi_fm_dma_err_get(handle, &de, DDI_FME_VER0);
13512         return (de.fme_status);
13513 }
13514 
13515 void
13516 mptsas_fm_ereport(mptsas_t *mpt, char *detail)
13517 {
13518         uint64_t        ena;
13519         char            buf[FM_MAX_CLASS];
13520 
13521         (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
13522         ena = fm_ena_generate(0, FM_ENA_FMT1);
13523         if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities)) {
13524                 ddi_fm_ereport_post(mpt->m_dip, buf, ena, DDI_NOSLEEP,
13525                     FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
13526         }
13527 }
13528 
13529 static int
13530 mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
13531     uint16_t *dev_handle, mptsas_target_t **pptgt)
13532 {
13533         int             rval;
13534         uint32_t        dev_info;
13535         uint64_t        sas_wwn;
13536         mptsas_phymask_t phymask;
13537         uint8_t         physport, phynum, config, disk;
13538         uint64_t        devicename;
13539         uint16_t        pdev_hdl;
13540         mptsas_target_t *tmp_tgt = NULL;
13541         uint16_t        bay_num, enclosure, io_flags;
13542 
13543         ASSERT(*pptgt == NULL);
13544 
13545         rval = mptsas_get_sas_device_page0(mpt, page_address, dev_handle,
13546             &sas_wwn, &dev_info, &physport, &phynum, &pdev_hdl,
13547             &bay_num, &enclosure, &io_flags);
13548         if (rval != DDI_SUCCESS) {
13549                 rval = DEV_INFO_FAIL_PAGE0;
13550                 return (rval);
13551         }
13552 
13553         if ((dev_info & (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
13554             MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
13555             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) == NULL) {
13556                 rval = DEV_INFO_WRONG_DEVICE_TYPE;
13557                 return (rval);
13558         }
13559 
13560         /*
13561          * Check if the dev handle is for a Phys Disk. If so, set return value
13562          * and exit.  Don't add Phys Disks to hash.
13563          */
13564         for (config = 0; config < mpt->m_num_raid_configs; config++) {
13565                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
13566                         if (*dev_handle == mpt->m_raidconfig[config].
13567                             m_physdisk_devhdl[disk]) {
13568                                 rval = DEV_INFO_PHYS_DISK;
13569                                 return (rval);
13570                         }
13571                 }
13572         }
13573 
13574         /*
13575          * Get SATA Device Name from SAS device page0 for
13576          * sata device, if device name doesn't exist, set mta_wwn to
13577          * 0 for direct attached SATA. For the device behind the expander
13578          * we still can use STP address assigned by expander.
13579          */
13580         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
13581             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
13582                 mutex_exit(&mpt->m_mutex);
13583                 /* alloc a tmp_tgt to send the cmd */
13584                 tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target),
13585                     KM_SLEEP);
13586                 tmp_tgt->m_devhdl = *dev_handle;
13587                 tmp_tgt->m_deviceinfo = dev_info;
13588                 tmp_tgt->m_qfull_retries = QFULL_RETRIES;
13589                 tmp_tgt->m_qfull_retry_interval =
13590                     drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
13591                 tmp_tgt->m_t_throttle = MAX_THROTTLE;
13592                 devicename = mptsas_get_sata_guid(mpt, tmp_tgt, 0);
13593                 kmem_free(tmp_tgt, sizeof (struct mptsas_target));
13594                 mutex_enter(&mpt->m_mutex);
13595                 if (devicename != 0 && (((devicename >> 56) & 0xf0) == 0x50)) {
13596                         sas_wwn = devicename;
13597                 } else if (dev_info & MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH) {
13598                         sas_wwn = 0;
13599                 }
13600         }
13601 
13602         phymask = mptsas_physport_to_phymask(mpt, physport);
13603         *pptgt = mptsas_tgt_alloc(mpt, *dev_handle, sas_wwn,
13604             dev_info, phymask, phynum);
13605         if (*pptgt == NULL) {
13606                 mptsas_log(mpt, CE_WARN, "Failed to allocated target"
13607                     "structure!");
13608                 rval = DEV_INFO_FAIL_ALLOC;
13609                 return (rval);
13610         }
13611         (*pptgt)->m_io_flags = io_flags;
13612         (*pptgt)->m_enclosure = enclosure;
13613         (*pptgt)->m_slot_num = bay_num;
13614         return (DEV_INFO_SUCCESS);
13615 }
13616 
13617 uint64_t
13618 mptsas_get_sata_guid(mptsas_t *mpt, mptsas_target_t *ptgt, int lun)
13619 {
13620         uint64_t        sata_guid = 0, *pwwn = NULL;
13621         int             target = ptgt->m_devhdl;
13622         uchar_t         *inq83 = NULL;
13623         int             inq83_len = 0xFF;
13624         uchar_t         *dblk = NULL;
13625         int             inq83_retry = 3;
13626         int             rval = DDI_FAILURE;
13627 
13628         inq83   = kmem_zalloc(inq83_len, KM_SLEEP);
13629 
13630 inq83_retry:
13631         rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
13632             inq83_len, NULL, 1);
13633         if (rval != DDI_SUCCESS) {
13634                 mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
13635                     "0x83 for target:%x, lun:%x failed!", target, lun);
13636                 goto out;
13637         }
13638         /* According to SAT2, the first descriptor is logic unit name */
13639         dblk = &inq83[4];
13640         if ((dblk[1] & 0x30) != 0) {
13641                 mptsas_log(mpt, CE_WARN, "!Descriptor is not lun associated.");
13642                 goto out;
13643         }
13644         pwwn = (uint64_t *)(void *)(&dblk[4]);
13645         if ((dblk[4] & 0xf0) == 0x50) {
13646                 sata_guid = BE_64(*pwwn);
13647                 goto out;
13648         } else if (dblk[4] == 'A') {
13649                 NDBG20(("SATA drive has no NAA format GUID."));
13650                 goto out;
13651         } else {
13652                 /* The data is not ready, wait and retry */
13653                 inq83_retry--;
13654                 if (inq83_retry <= 0) {
13655                         goto out;
13656                 }
13657                 NDBG20(("The GUID is not ready, retry..."));
13658                 delay(1 * drv_usectohz(1000000));
13659                 goto inq83_retry;
13660         }
13661 out:
13662         kmem_free(inq83, inq83_len);
13663         return (sata_guid);
13664 }
13665 
13666 static int
13667 mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun, uchar_t page,
13668     unsigned char *buf, int len, int *reallen, uchar_t evpd)
13669 {
13670         uchar_t                 cdb[CDB_GROUP0];
13671         struct scsi_address     ap;
13672         struct buf              *data_bp = NULL;
13673         int                     resid = 0;
13674         int                     ret = DDI_FAILURE;
13675 
13676         ASSERT(len <= 0xffff);
13677 
13678         ap.a_target = MPTSAS_INVALID_DEVHDL;
13679         ap.a_lun = (uchar_t)(lun);
13680         ap.a_hba_tran = mpt->m_tran;
13681 
13682         data_bp = scsi_alloc_consistent_buf(&ap,
13683             (struct buf *)NULL, len, B_READ, NULL_FUNC, NULL);
13684         if (data_bp == NULL) {
13685                 return (ret);
13686         }
13687         bzero(cdb, CDB_GROUP0);
13688         cdb[0] = SCMD_INQUIRY;
13689         cdb[1] = evpd;
13690         cdb[2] = page;
13691         cdb[3] = (len & 0xff00) >> 8;
13692         cdb[4] = (len & 0x00ff);
13693         cdb[5] = 0;
13694 
13695         ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP0, data_bp,
13696             &resid);
13697         if (ret == DDI_SUCCESS) {
13698                 if (reallen) {
13699                         *reallen = len - resid;
13700                 }
13701                 bcopy((caddr_t)data_bp->b_un.b_addr, buf, len);
13702         }
13703         if (data_bp) {
13704                 scsi_free_consistent_buf(data_bp);
13705         }
13706         return (ret);
13707 }
13708 
13709 static int
13710 mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
13711     mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
13712     int *resid)
13713 {
13714         struct scsi_pkt         *pktp = NULL;
13715         scsi_hba_tran_t         *tran_clone = NULL;
13716         mptsas_tgt_private_t    *tgt_private = NULL;
13717         int                     ret = DDI_FAILURE;
13718 
13719         /*
13720          * scsi_hba_tran_t->tran_tgt_private is used to pass the address
13721          * information to scsi_init_pkt, allocate a scsi_hba_tran structure
13722          * to simulate the cmds from sd
13723          */
13724         tran_clone = kmem_alloc(
13725             sizeof (scsi_hba_tran_t), KM_SLEEP);
13726         if (tran_clone == NULL) {
13727                 goto out;
13728         }
13729         bcopy((caddr_t)mpt->m_tran,
13730             (caddr_t)tran_clone, sizeof (scsi_hba_tran_t));
13731         tgt_private = kmem_alloc(
13732             sizeof (mptsas_tgt_private_t), KM_SLEEP);
13733         if (tgt_private == NULL) {
13734                 goto out;
13735         }
13736         tgt_private->t_lun = ap->a_lun;
13737         tgt_private->t_private = ptgt;
13738         tran_clone->tran_tgt_private = tgt_private;
13739         ap->a_hba_tran = tran_clone;
13740 
13741         pktp = scsi_init_pkt(ap, (struct scsi_pkt *)NULL,
13742             data_bp, cdblen, sizeof (struct scsi_arq_status),
13743             0, PKT_CONSISTENT, NULL, NULL);
13744         if (pktp == NULL) {
13745                 goto out;
13746         }
13747         bcopy(cdb, pktp->pkt_cdbp, cdblen);
13748         pktp->pkt_flags = FLAG_NOPARITY;
13749         if (scsi_poll(pktp) < 0) {
13750                 goto out;
13751         }
13752         if (((struct scsi_status *)pktp->pkt_scbp)->sts_chk) {
13753                 goto out;
13754         }
13755         if (resid != NULL) {
13756                 *resid = pktp->pkt_resid;
13757         }
13758 
13759         ret = DDI_SUCCESS;
13760 out:
13761         if (pktp) {
13762                 scsi_destroy_pkt(pktp);
13763         }
13764         if (tran_clone) {
13765                 kmem_free(tran_clone, sizeof (scsi_hba_tran_t));
13766         }
13767         if (tgt_private) {
13768                 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
13769         }
13770         return (ret);
13771 }
13772 static int
13773 mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy, int *lun)
13774 {
13775         char    *cp = NULL;
13776         char    *ptr = NULL;
13777         size_t  s = 0;
13778         char    *wwid_str = NULL;
13779         char    *lun_str = NULL;
13780         long    lunnum;
13781         long    phyid = -1;
13782         int     rc = DDI_FAILURE;
13783 
13784         ptr = name;
13785         ASSERT(ptr[0] == 'w' || ptr[0] == 'p');
13786         ptr++;
13787         if ((cp = strchr(ptr, ',')) == NULL) {
13788                 return (DDI_FAILURE);
13789         }
13790 
13791         wwid_str = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13792         s = (uintptr_t)cp - (uintptr_t)ptr;
13793 
13794         bcopy(ptr, wwid_str, s);
13795         wwid_str[s] = '\0';
13796 
13797         ptr = ++cp;
13798 
13799         if ((cp = strchr(ptr, '\0')) == NULL) {
13800                 goto out;
13801         }
13802         lun_str =  kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13803         s = (uintptr_t)cp - (uintptr_t)ptr;
13804 
13805         bcopy(ptr, lun_str, s);
13806         lun_str[s] = '\0';
13807 
13808         if (name[0] == 'p') {
13809                 rc = ddi_strtol(wwid_str, NULL, 0x10, &phyid);
13810         } else {
13811                 rc = scsi_wwnstr_to_wwn(wwid_str, wwid);
13812         }
13813         if (rc != DDI_SUCCESS)
13814                 goto out;
13815 
13816         if (phyid != -1) {
13817                 ASSERT(phyid < MPTSAS_MAX_PHYS);
13818                 *phy = (uint8_t)phyid;
13819         }
13820         rc = ddi_strtol(lun_str, NULL, 0x10, &lunnum);
13821         if (rc != 0)
13822                 goto out;
13823 
13824         *lun = (int)lunnum;
13825         rc = DDI_SUCCESS;
13826 out:
13827         if (wwid_str)
13828                 kmem_free(wwid_str, SCSI_MAXNAMELEN);
13829         if (lun_str)
13830                 kmem_free(lun_str, SCSI_MAXNAMELEN);
13831 
13832         return (rc);
13833 }
13834 
13835 /*
13836  * mptsas_parse_smp_name() is to parse sas wwn string
13837  * which format is "wWWN"
13838  */
13839 static int
13840 mptsas_parse_smp_name(char *name, uint64_t *wwn)
13841 {
13842         char    *ptr = name;
13843 
13844         if (*ptr != 'w') {
13845                 return (DDI_FAILURE);
13846         }
13847 
13848         ptr++;
13849         if (scsi_wwnstr_to_wwn(ptr, wwn)) {
13850                 return (DDI_FAILURE);
13851         }
13852         return (DDI_SUCCESS);
13853 }
13854 
13855 static int
13856 mptsas_bus_config(dev_info_t *pdip, uint_t flag,
13857     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
13858 {
13859         int             ret = NDI_FAILURE;
13860         int             circ = 0;
13861         int             circ1 = 0;
13862         mptsas_t        *mpt;
13863         char            *ptr = NULL;
13864         char            *devnm = NULL;
13865         uint64_t        wwid = 0;
13866         uint8_t         phy = 0xFF;
13867         int             lun = 0;
13868         uint_t          mflags = flag;
13869         int             bconfig = TRUE;
13870 
13871         if (scsi_hba_iport_unit_address(pdip) == 0) {
13872                 return (DDI_FAILURE);
13873         }
13874 
13875         mpt = DIP2MPT(pdip);
13876         if (!mpt) {
13877                 return (DDI_FAILURE);
13878         }
13879         /*
13880          * Hold the nexus across the bus_config
13881          */
13882         ndi_devi_enter(scsi_vhci_dip, &circ);
13883         ndi_devi_enter(pdip, &circ1);
13884         switch (op) {
13885         case BUS_CONFIG_ONE:
13886                 /* parse wwid/target name out of name given */
13887                 if ((ptr = strchr((char *)arg, '@')) == NULL) {
13888                         ret = NDI_FAILURE;
13889                         break;
13890                 }
13891                 ptr++;
13892                 if (strncmp((char *)arg, "smp", 3) == 0) {
13893                         /*
13894                          * This is a SMP target device
13895                          */
13896                         ret = mptsas_parse_smp_name(ptr, &wwid);
13897                         if (ret != DDI_SUCCESS) {
13898                                 ret = NDI_FAILURE;
13899                                 break;
13900                         }
13901                         ret = mptsas_config_smp(pdip, wwid, childp);
13902                 } else if ((ptr[0] == 'w') || (ptr[0] == 'p')) {
13903                         /*
13904                          * OBP could pass down a non-canonical form
13905                          * bootpath without LUN part when LUN is 0.
13906                          * So driver need adjust the string.
13907                          */
13908                         if (strchr(ptr, ',') == NULL) {
13909                                 devnm = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13910                                 (void) sprintf(devnm, "%s,0", (char *)arg);
13911                                 ptr = strchr(devnm, '@');
13912                                 ptr++;
13913                         }
13914 
13915                         /*
13916                          * The device path is wWWID format and the device
13917                          * is not SMP target device.
13918                          */
13919                         ret = mptsas_parse_address(ptr, &wwid, &phy, &lun);
13920                         if (ret != DDI_SUCCESS) {
13921                                 ret = NDI_FAILURE;
13922                                 break;
13923                         }
13924                         *childp = NULL;
13925                         if (ptr[0] == 'w') {
13926                                 ret = mptsas_config_one_addr(pdip, wwid,
13927                                     lun, childp);
13928                         } else if (ptr[0] == 'p') {
13929                                 ret = mptsas_config_one_phy(pdip, phy, lun,
13930                                     childp);
13931                         }
13932 
13933                         /*
13934                          * If this is CD/DVD device in OBP path, the
13935                          * ndi_busop_bus_config can be skipped as config one
13936                          * operation is done above.
13937                          */
13938                         if ((ret == NDI_SUCCESS) && (*childp != NULL) &&
13939                             (strcmp(ddi_node_name(*childp), "cdrom") == 0) &&
13940                             (strncmp((char *)arg, "disk", 4) == 0)) {
13941                                 bconfig = FALSE;
13942                                 ndi_hold_devi(*childp);
13943                         }
13944                 } else {
13945                         ret = NDI_FAILURE;
13946                         break;
13947                 }
13948 
13949                 /*
13950                  * DDI group instructed us to use this flag.
13951                  */
13952                 mflags |= NDI_MDI_FALLBACK;
13953                 break;
13954         case BUS_CONFIG_DRIVER:
13955         case BUS_CONFIG_ALL:
13956                 mptsas_config_all(pdip);
13957                 ret = NDI_SUCCESS;
13958                 break;
13959         }
13960 
13961         if ((ret == NDI_SUCCESS) && bconfig) {
13962                 ret = ndi_busop_bus_config(pdip, mflags, op,
13963                     (devnm == NULL) ? arg : devnm, childp, 0);
13964         }
13965 
13966         ndi_devi_exit(pdip, circ1);
13967         ndi_devi_exit(scsi_vhci_dip, circ);
13968         if (devnm != NULL)
13969                 kmem_free(devnm, SCSI_MAXNAMELEN);
13970         return (ret);
13971 }
13972 
13973 static int
13974 mptsas_probe_lun(dev_info_t *pdip, int lun, dev_info_t **dip,
13975     mptsas_target_t *ptgt)
13976 {
13977         int                     rval = DDI_FAILURE;
13978         struct scsi_inquiry     *sd_inq = NULL;
13979         mptsas_t                *mpt = DIP2MPT(pdip);
13980 
13981         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
13982 
13983         rval = mptsas_inquiry(mpt, ptgt, lun, 0, (uchar_t *)sd_inq,
13984             SUN_INQSIZE, 0, (uchar_t)0);
13985 
13986         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
13987                 rval = mptsas_create_lun(pdip, sd_inq, dip, ptgt, lun);
13988         } else {
13989                 rval = DDI_FAILURE;
13990         }
13991 
13992         kmem_free(sd_inq, SUN_INQSIZE);
13993         return (rval);
13994 }
13995 
13996 static int
13997 mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
13998     dev_info_t **lundip)
13999 {
14000         int             rval;
14001         mptsas_t                *mpt = DIP2MPT(pdip);
14002         int             phymask;
14003         mptsas_target_t *ptgt = NULL;
14004 
14005         /*
14006          * Get the physical port associated to the iport
14007          */
14008         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
14009             "phymask", 0);
14010 
14011         ptgt = mptsas_wwid_to_ptgt(mpt, phymask, sasaddr);
14012         if (ptgt == NULL) {
14013                 /*
14014                  * didn't match any device by searching
14015                  */
14016                 return (DDI_FAILURE);
14017         }
14018         /*
14019          * If the LUN already exists and the status is online,
14020          * we just return the pointer to dev_info_t directly.
14021          * For the mdi_pathinfo node, we'll handle it in
14022          * mptsas_create_virt_lun()
14023          * TODO should be also in mptsas_handle_dr
14024          */
14025 
14026         *lundip = mptsas_find_child_addr(pdip, sasaddr, lun);
14027         if (*lundip != NULL) {
14028                 /*
14029                  * TODO Another senario is, we hotplug the same disk
14030                  * on the same slot, the devhdl changed, is this
14031                  * possible?
14032                  * tgt_private->t_private != ptgt
14033                  */
14034                 if (sasaddr != ptgt->m_addr.mta_wwn) {
14035                         /*
14036                          * The device has changed although the devhdl is the
14037                          * same (Enclosure mapping mode, change drive on the
14038                          * same slot)
14039                          */
14040                         return (DDI_FAILURE);
14041                 }
14042                 return (DDI_SUCCESS);
14043         }
14044 
14045         if (phymask == 0) {
14046                 /*
14047                  * Configure IR volume
14048                  */
14049                 rval =  mptsas_config_raid(pdip, ptgt->m_devhdl, lundip);
14050                 return (rval);
14051         }
14052         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
14053 
14054         return (rval);
14055 }
14056 
14057 static int
14058 mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
14059     dev_info_t **lundip)
14060 {
14061         int             rval;
14062         mptsas_t        *mpt = DIP2MPT(pdip);
14063         mptsas_phymask_t phymask;
14064         mptsas_target_t *ptgt = NULL;
14065 
14066         /*
14067          * Get the physical port associated to the iport
14068          */
14069         phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
14070             "phymask", 0);
14071 
14072         ptgt = mptsas_phy_to_tgt(mpt, phymask, phy);
14073         if (ptgt == NULL) {
14074                 /*
14075                  * didn't match any device by searching
14076                  */
14077                 return (DDI_FAILURE);
14078         }
14079 
14080         /*
14081          * If the LUN already exists and the status is online,
14082          * we just return the pointer to dev_info_t directly.
14083          * For the mdi_pathinfo node, we'll handle it in
14084          * mptsas_create_virt_lun().
14085          */
14086 
14087         *lundip = mptsas_find_child_phy(pdip, phy);
14088         if (*lundip != NULL) {
14089                 return (DDI_SUCCESS);
14090         }
14091 
14092         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
14093 
14094         return (rval);
14095 }
14096 
14097 static int
14098 mptsas_retrieve_lundata(int lun_cnt, uint8_t *buf, uint16_t *lun_num,
14099     uint8_t *lun_addr_type)
14100 {
14101         uint32_t        lun_idx = 0;
14102 
14103         ASSERT(lun_num != NULL);
14104         ASSERT(lun_addr_type != NULL);
14105 
14106         lun_idx = (lun_cnt + 1) * MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
14107         /* determine report luns addressing type */
14108         switch (buf[lun_idx] & MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) {
14109                 /*
14110                  * Vendors in the field have been found to be concatenating
14111                  * bus/target/lun to equal the complete lun value instead
14112                  * of switching to flat space addressing
14113                  */
14114                 /* 00b - peripheral device addressing method */
14115         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_PERIPHERAL:
14116                 /* FALLTHRU */
14117                 /* 10b - logical unit addressing method */
14118         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT:
14119                 /* FALLTHRU */
14120                 /* 01b - flat space addressing method */
14121         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE:
14122                 /* byte0 bit0-5=msb lun byte1 bit0-7=lsb lun */
14123                 *lun_addr_type = (buf[lun_idx] &
14124                     MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) >> 6;
14125                 *lun_num = (buf[lun_idx] & 0x3F) << 8;
14126                 *lun_num |= buf[lun_idx + 1];
14127                 return (DDI_SUCCESS);
14128         default:
14129                 return (DDI_FAILURE);
14130         }
14131 }
14132 
14133 static int
14134 mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt)
14135 {
14136         struct buf              *repluns_bp = NULL;
14137         struct scsi_address     ap;
14138         uchar_t                 cdb[CDB_GROUP5];
14139         int                     ret = DDI_FAILURE;
14140         int                     retry = 0;
14141         int                     lun_list_len = 0;
14142         uint16_t                lun_num = 0;
14143         uint8_t                 lun_addr_type = 0;
14144         uint32_t                lun_cnt = 0;
14145         uint32_t                lun_total = 0;
14146         dev_info_t              *cdip = NULL;
14147         uint16_t                *saved_repluns = NULL;
14148         char                    *buffer = NULL;
14149         int                     buf_len = 128;
14150         mptsas_t                *mpt = DIP2MPT(pdip);
14151         uint64_t                sas_wwn = 0;
14152         uint8_t                 phy = 0xFF;
14153         uint32_t                dev_info = 0;
14154 
14155         mutex_enter(&mpt->m_mutex);
14156         sas_wwn = ptgt->m_addr.mta_wwn;
14157         phy = ptgt->m_phynum;
14158         dev_info = ptgt->m_deviceinfo;
14159         mutex_exit(&mpt->m_mutex);
14160 
14161         if (sas_wwn == 0) {
14162                 /*
14163                  * It's a SATA without Device Name
14164                  * So don't try multi-LUNs
14165                  */
14166                 if (mptsas_find_child_phy(pdip, phy)) {
14167                         return (DDI_SUCCESS);
14168                 } else {
14169                         /*
14170                          * need configure and create node
14171                          */
14172                         return (DDI_FAILURE);
14173                 }
14174         }
14175 
14176         /*
14177          * WWN (SAS address or Device Name exist)
14178          */
14179         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
14180             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
14181                 /*
14182                  * SATA device with Device Name
14183                  * So don't try multi-LUNs
14184                  */
14185                 if (mptsas_find_child_addr(pdip, sas_wwn, 0)) {
14186                         return (DDI_SUCCESS);
14187                 } else {
14188                         return (DDI_FAILURE);
14189                 }
14190         }
14191 
14192         do {
14193                 ap.a_target = MPTSAS_INVALID_DEVHDL;
14194                 ap.a_lun = 0;
14195                 ap.a_hba_tran = mpt->m_tran;
14196                 repluns_bp = scsi_alloc_consistent_buf(&ap,
14197                     (struct buf *)NULL, buf_len, B_READ, NULL_FUNC, NULL);
14198                 if (repluns_bp == NULL) {
14199                         retry++;
14200                         continue;
14201                 }
14202                 bzero(cdb, CDB_GROUP5);
14203                 cdb[0] = SCMD_REPORT_LUNS;
14204                 cdb[6] = (buf_len & 0xff000000) >> 24;
14205                 cdb[7] = (buf_len & 0x00ff0000) >> 16;
14206                 cdb[8] = (buf_len & 0x0000ff00) >> 8;
14207                 cdb[9] = (buf_len & 0x000000ff);
14208 
14209                 ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP5,
14210                     repluns_bp, NULL);
14211                 if (ret != DDI_SUCCESS) {
14212                         scsi_free_consistent_buf(repluns_bp);
14213                         retry++;
14214                         continue;
14215                 }
14216                 lun_list_len = BE_32(*(int *)((void *)(
14217                     repluns_bp->b_un.b_addr)));
14218                 if (buf_len >= lun_list_len + 8) {
14219                         ret = DDI_SUCCESS;
14220                         break;
14221                 }
14222                 scsi_free_consistent_buf(repluns_bp);
14223                 buf_len = lun_list_len + 8;
14224 
14225         } while (retry < 3);
14226 
14227         if (ret != DDI_SUCCESS)
14228                 return (ret);
14229         buffer = (char *)repluns_bp->b_un.b_addr;
14230         /*
14231          * find out the number of luns returned by the SCSI ReportLun call
14232          * and allocate buffer space
14233          */
14234         lun_total = lun_list_len / MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
14235         saved_repluns = kmem_zalloc(sizeof (uint16_t) * lun_total, KM_SLEEP);
14236         if (saved_repluns == NULL) {
14237                 scsi_free_consistent_buf(repluns_bp);
14238                 return (DDI_FAILURE);
14239         }
14240         for (lun_cnt = 0; lun_cnt < lun_total; lun_cnt++) {
14241                 if (mptsas_retrieve_lundata(lun_cnt, (uint8_t *)(buffer),
14242                     &lun_num, &lun_addr_type) != DDI_SUCCESS) {
14243                         continue;
14244                 }
14245                 saved_repluns[lun_cnt] = lun_num;
14246                 if (cdip = mptsas_find_child_addr(pdip, sas_wwn, lun_num))
14247                         ret = DDI_SUCCESS;
14248                 else
14249                         ret = mptsas_probe_lun(pdip, lun_num, &cdip,
14250                             ptgt);
14251                 if ((ret == DDI_SUCCESS) && (cdip != NULL)) {
14252                         (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip,
14253                             MPTSAS_DEV_GONE);
14254                 }
14255         }
14256         mptsas_offline_missed_luns(pdip, saved_repluns, lun_total, ptgt);
14257         kmem_free(saved_repluns, sizeof (uint16_t) * lun_total);
14258         scsi_free_consistent_buf(repluns_bp);
14259         return (DDI_SUCCESS);
14260 }
14261 
14262 static int
14263 mptsas_config_raid(dev_info_t *pdip, uint16_t target, dev_info_t **dip)
14264 {
14265         int                     rval = DDI_FAILURE;
14266         struct scsi_inquiry     *sd_inq = NULL;
14267         mptsas_t                *mpt = DIP2MPT(pdip);
14268         mptsas_target_t         *ptgt = NULL;
14269 
14270         mutex_enter(&mpt->m_mutex);
14271         ptgt = refhash_linear_search(mpt->m_targets,
14272             mptsas_target_eval_devhdl, &target);
14273         mutex_exit(&mpt->m_mutex);
14274         if (ptgt == NULL) {
14275                 mptsas_log(mpt, CE_WARN, "Volume with VolDevHandle of 0x%x "
14276                     "not found.", target);
14277                 return (rval);
14278         }
14279 
14280         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
14281         rval = mptsas_inquiry(mpt, ptgt, 0, 0, (uchar_t *)sd_inq,
14282             SUN_INQSIZE, 0, (uchar_t)0);
14283 
14284         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
14285                 rval = mptsas_create_phys_lun(pdip, sd_inq, NULL, dip, ptgt,
14286                     0);
14287         } else {
14288                 rval = DDI_FAILURE;
14289         }
14290 
14291         kmem_free(sd_inq, SUN_INQSIZE);
14292         return (rval);
14293 }
14294 
14295 /*
14296  * configure all RAID volumes for virtual iport
14297  */
14298 static void
14299 mptsas_config_all_viport(dev_info_t *pdip)
14300 {
14301         mptsas_t        *mpt = DIP2MPT(pdip);
14302         int             config, vol;
14303         int             target;
14304         dev_info_t      *lundip = NULL;
14305 
14306         /*
14307          * Get latest RAID info and search for any Volume DevHandles.  If any
14308          * are found, configure the volume.
14309          */
14310         mutex_enter(&mpt->m_mutex);
14311         for (config = 0; config < mpt->m_num_raid_configs; config++) {
14312                 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
14313                         if (mpt->m_raidconfig[config].m_raidvol[vol].m_israid
14314                             == 1) {
14315                                 target = mpt->m_raidconfig[config].
14316                                     m_raidvol[vol].m_raidhandle;
14317                                 mutex_exit(&mpt->m_mutex);
14318                                 (void) mptsas_config_raid(pdip, target,
14319                                     &lundip);
14320                                 mutex_enter(&mpt->m_mutex);
14321                         }
14322                 }
14323         }
14324         mutex_exit(&mpt->m_mutex);
14325 }
14326 
14327 static void
14328 mptsas_offline_missed_luns(dev_info_t *pdip, uint16_t *repluns,
14329     int lun_cnt, mptsas_target_t *ptgt)
14330 {
14331         dev_info_t      *child = NULL, *savechild = NULL;
14332         mdi_pathinfo_t  *pip = NULL, *savepip = NULL;
14333         uint64_t        sas_wwn, wwid;
14334         uint8_t         phy;
14335         int             lun;
14336         int             i;
14337         int             find;
14338         char            *addr;
14339         char            *nodename;
14340         mptsas_t        *mpt = DIP2MPT(pdip);
14341 
14342         mutex_enter(&mpt->m_mutex);
14343         wwid = ptgt->m_addr.mta_wwn;
14344         mutex_exit(&mpt->m_mutex);
14345 
14346         child = ddi_get_child(pdip);
14347         while (child) {
14348                 find = 0;
14349                 savechild = child;
14350                 child = ddi_get_next_sibling(child);
14351 
14352                 nodename = ddi_node_name(savechild);
14353                 if (strcmp(nodename, "smp") == 0) {
14354                         continue;
14355                 }
14356 
14357                 addr = ddi_get_name_addr(savechild);
14358                 if (addr == NULL) {
14359                         continue;
14360                 }
14361 
14362                 if (mptsas_parse_address(addr, &sas_wwn, &phy, &lun) !=
14363                     DDI_SUCCESS) {
14364                         continue;
14365                 }
14366 
14367                 if (wwid == sas_wwn) {
14368                         for (i = 0; i < lun_cnt; i++) {
14369                                 if (repluns[i] == lun) {
14370                                         find = 1;
14371                                         break;
14372                                 }
14373                         }
14374                 } else {
14375                         continue;
14376                 }
14377                 if (find == 0) {
14378                         /*
14379                          * The lun has not been there already
14380                          */
14381                         (void) mptsas_offline_lun(pdip, savechild, NULL,
14382                             NDI_DEVI_REMOVE);
14383                 }
14384         }
14385 
14386         pip = mdi_get_next_client_path(pdip, NULL);
14387         while (pip) {
14388                 find = 0;
14389                 savepip = pip;
14390                 addr = MDI_PI(pip)->pi_addr;
14391 
14392                 pip = mdi_get_next_client_path(pdip, pip);
14393 
14394                 if (addr == NULL) {
14395                         continue;
14396                 }
14397 
14398                 if (mptsas_parse_address(addr, &sas_wwn, &phy,
14399                     &lun) != DDI_SUCCESS) {
14400                         continue;
14401                 }
14402 
14403                 if (sas_wwn == wwid) {
14404                         for (i = 0; i < lun_cnt; i++) {
14405                                 if (repluns[i] == lun) {
14406                                         find = 1;
14407                                         break;
14408                                 }
14409                         }
14410                 } else {
14411                         continue;
14412                 }
14413 
14414                 if (find == 0) {
14415                         /*
14416                          * The lun has not been there already
14417                          */
14418                         (void) mptsas_offline_lun(pdip, NULL, savepip,
14419                             NDI_DEVI_REMOVE);
14420                 }
14421         }
14422 }
14423 
14424 void
14425 mptsas_update_hashtab(struct mptsas *mpt)
14426 {
14427         uint32_t        page_address;
14428         int             rval = 0;
14429         uint16_t        dev_handle;
14430         mptsas_target_t *ptgt = NULL;
14431         mptsas_smp_t    smp_node;
14432 
14433         /*
14434          * Get latest RAID info.
14435          */
14436         (void) mptsas_get_raid_info(mpt);
14437 
14438         dev_handle = mpt->m_smp_devhdl;
14439         for (; mpt->m_done_traverse_smp == 0; ) {
14440                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
14441                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)dev_handle;
14442                 if (mptsas_get_sas_expander_page0(mpt, page_address, &smp_node)
14443                     != DDI_SUCCESS) {
14444                         break;
14445                 }
14446                 mpt->m_smp_devhdl = dev_handle = smp_node.m_devhdl;
14447                 (void) mptsas_smp_alloc(mpt, &smp_node);
14448         }
14449 
14450         /*
14451          * Config target devices
14452          */
14453         dev_handle = mpt->m_dev_handle;
14454 
14455         /*
14456          * Do loop to get sas device page 0 by GetNextHandle till the
14457          * the last handle. If the sas device is a SATA/SSP target,
14458          * we try to config it.
14459          */
14460         for (; mpt->m_done_traverse_dev == 0; ) {
14461                 ptgt = NULL;
14462                 page_address =
14463                     (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
14464                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14465                     (uint32_t)dev_handle;
14466                 rval = mptsas_get_target_device_info(mpt, page_address,
14467                     &dev_handle, &ptgt);
14468                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
14469                     (rval == DEV_INFO_FAIL_ALLOC)) {
14470                         break;
14471                 }
14472 
14473                 mpt->m_dev_handle = dev_handle;
14474         }
14475 
14476 }
14477 
14478 void
14479 mptsas_update_driver_data(struct mptsas *mpt)
14480 {
14481         mptsas_target_t *tp;
14482         mptsas_smp_t *sp;
14483 
14484         ASSERT(MUTEX_HELD(&mpt->m_mutex));
14485 
14486         /*
14487          * TODO after hard reset, update the driver data structures
14488          * 1. update port/phymask mapping table mpt->m_phy_info
14489          * 2. invalid all the entries in hash table
14490          *    m_devhdl = 0xffff and m_deviceinfo = 0
14491          * 3. call sas_device_page/expander_page to update hash table
14492          */
14493         mptsas_update_phymask(mpt);
14494 
14495         /*
14496          * Remove all the devhdls for existing entries but leave their
14497          * addresses alone.  In update_hashtab() below, we'll find all
14498          * targets that are still present and reassociate them with
14499          * their potentially new devhdls.  Leaving the targets around in
14500          * this fashion allows them to be used on the tx waitq even
14501          * while IOC reset is occurring.
14502          */
14503         for (tp = refhash_first(mpt->m_targets); tp != NULL;
14504             tp = refhash_next(mpt->m_targets, tp)) {
14505                 tp->m_devhdl = MPTSAS_INVALID_DEVHDL;
14506                 tp->m_deviceinfo = 0;
14507                 tp->m_dr_flag = MPTSAS_DR_INACTIVE;
14508         }
14509         for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
14510             sp = refhash_next(mpt->m_smp_targets, sp)) {
14511                 sp->m_devhdl = MPTSAS_INVALID_DEVHDL;
14512                 sp->m_deviceinfo = 0;
14513         }
14514         mpt->m_done_traverse_dev = 0;
14515         mpt->m_done_traverse_smp = 0;
14516         mpt->m_dev_handle = mpt->m_smp_devhdl = MPTSAS_INVALID_DEVHDL;
14517         mptsas_update_hashtab(mpt);
14518 }
14519 
14520 static void
14521 mptsas_config_all(dev_info_t *pdip)
14522 {
14523         dev_info_t      *smpdip = NULL;
14524         mptsas_t        *mpt = DIP2MPT(pdip);
14525         int             phymask = 0;
14526         mptsas_phymask_t phy_mask;
14527         mptsas_target_t *ptgt = NULL;
14528         mptsas_smp_t    *psmp;
14529 
14530         /*
14531          * Get the phymask associated to the iport
14532          */
14533         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
14534             "phymask", 0);
14535 
14536         /*
14537          * Enumerate RAID volumes here (phymask == 0).
14538          */
14539         if (phymask == 0) {
14540                 mptsas_config_all_viport(pdip);
14541                 return;
14542         }
14543 
14544         mutex_enter(&mpt->m_mutex);
14545 
14546         if (!mpt->m_done_traverse_dev || !mpt->m_done_traverse_smp) {
14547                 mptsas_update_hashtab(mpt);
14548         }
14549 
14550         for (psmp = refhash_first(mpt->m_smp_targets); psmp != NULL;
14551             psmp = refhash_next(mpt->m_smp_targets, psmp)) {
14552                 phy_mask = psmp->m_addr.mta_phymask;
14553                 if (phy_mask == phymask) {
14554                         smpdip = NULL;
14555                         mutex_exit(&mpt->m_mutex);
14556                         (void) mptsas_online_smp(pdip, psmp, &smpdip);
14557                         mutex_enter(&mpt->m_mutex);
14558                 }
14559         }
14560 
14561         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
14562             ptgt = refhash_next(mpt->m_targets, ptgt)) {
14563                 phy_mask = ptgt->m_addr.mta_phymask;
14564                 if (phy_mask == phymask) {
14565                         mutex_exit(&mpt->m_mutex);
14566                         (void) mptsas_config_target(pdip, ptgt);
14567                         mutex_enter(&mpt->m_mutex);
14568                 }
14569         }
14570         mutex_exit(&mpt->m_mutex);
14571 }
14572 
14573 static int
14574 mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt)
14575 {
14576         int             rval = DDI_FAILURE;
14577         dev_info_t      *tdip;
14578 
14579         rval = mptsas_config_luns(pdip, ptgt);
14580         if (rval != DDI_SUCCESS) {
14581                 /*
14582                  * The return value means the SCMD_REPORT_LUNS
14583                  * did not execute successfully. The target maybe
14584                  * doesn't support such command.
14585                  */
14586                 rval = mptsas_probe_lun(pdip, 0, &tdip, ptgt);
14587         }
14588         return (rval);
14589 }
14590 
14591 /*
14592  * Return fail if not all the childs/paths are freed.
14593  * if there is any path under the HBA, the return value will be always fail
14594  * because we didn't call mdi_pi_free for path
14595  */
14596 static int
14597 mptsas_offline_target(dev_info_t *pdip, char *name)
14598 {
14599         dev_info_t              *child = NULL, *prechild = NULL;
14600         mdi_pathinfo_t          *pip = NULL, *savepip = NULL;
14601         int                     tmp_rval, rval = DDI_SUCCESS;
14602         char                    *addr, *cp;
14603         size_t                  s;
14604         mptsas_t                *mpt = DIP2MPT(pdip);
14605 
14606         child = ddi_get_child(pdip);
14607         while (child) {
14608                 addr = ddi_get_name_addr(child);
14609                 prechild = child;
14610                 child = ddi_get_next_sibling(child);
14611 
14612                 if (addr == NULL) {
14613                         continue;
14614                 }
14615                 if ((cp = strchr(addr, ',')) == NULL) {
14616                         continue;
14617                 }
14618 
14619                 s = (uintptr_t)cp - (uintptr_t)addr;
14620 
14621                 if (strncmp(addr, name, s) != 0) {
14622                         continue;
14623                 }
14624 
14625                 tmp_rval = mptsas_offline_lun(pdip, prechild, NULL,
14626                     NDI_DEVI_REMOVE);
14627                 if (tmp_rval != DDI_SUCCESS) {
14628                         rval = DDI_FAILURE;
14629                         if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
14630                             prechild, MPTSAS_DEV_GONE) !=
14631                             DDI_PROP_SUCCESS) {
14632                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
14633                                     "unable to create property for "
14634                                     "SAS %s (MPTSAS_DEV_GONE)", addr);
14635                         }
14636                 }
14637         }
14638 
14639         pip = mdi_get_next_client_path(pdip, NULL);
14640         while (pip) {
14641                 addr = MDI_PI(pip)->pi_addr;
14642                 savepip = pip;
14643                 pip = mdi_get_next_client_path(pdip, pip);
14644                 if (addr == NULL) {
14645                         continue;
14646                 }
14647 
14648                 if ((cp = strchr(addr, ',')) == NULL) {
14649                         continue;
14650                 }
14651 
14652                 s = (uintptr_t)cp - (uintptr_t)addr;
14653 
14654                 if (strncmp(addr, name, s) != 0) {
14655                         continue;
14656                 }
14657 
14658                 (void) mptsas_offline_lun(pdip, NULL, savepip,
14659                     NDI_DEVI_REMOVE);
14660                 /*
14661                  * driver will not invoke mdi_pi_free, so path will not
14662                  * be freed forever, return DDI_FAILURE.
14663                  */
14664                 rval = DDI_FAILURE;
14665         }
14666         return (rval);
14667 }
14668 
14669 static int
14670 mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
14671     mdi_pathinfo_t *rpip, uint_t flags)
14672 {
14673         int             rval = DDI_FAILURE;
14674         char            *devname;
14675         dev_info_t      *cdip, *parent;
14676 
14677         if (rpip != NULL) {
14678                 parent = scsi_vhci_dip;
14679                 cdip = mdi_pi_get_client(rpip);
14680         } else if (rdip != NULL) {
14681                 parent = pdip;
14682                 cdip = rdip;
14683         } else {
14684                 return (DDI_FAILURE);
14685         }
14686 
14687         /*
14688          * Make sure node is attached otherwise
14689          * it won't have related cache nodes to
14690          * clean up.  i_ddi_devi_attached is
14691          * similiar to i_ddi_node_state(cdip) >=
14692          * DS_ATTACHED.
14693          */
14694         if (i_ddi_devi_attached(cdip)) {
14695 
14696                 /* Get full devname */
14697                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
14698                 (void) ddi_deviname(cdip, devname);
14699                 /* Clean cache */
14700                 (void) devfs_clean(parent, devname + 1,
14701                     DV_CLEAN_FORCE);
14702                 kmem_free(devname, MAXNAMELEN + 1);
14703         }
14704         if (rpip != NULL) {
14705                 if (MDI_PI_IS_OFFLINE(rpip)) {
14706                         rval = DDI_SUCCESS;
14707                 } else {
14708                         rval = mdi_pi_offline(rpip, 0);
14709                 }
14710         } else {
14711                 rval = ndi_devi_offline(cdip, flags);
14712         }
14713 
14714         return (rval);
14715 }
14716 
14717 static dev_info_t *
14718 mptsas_find_smp_child(dev_info_t *parent, char *str_wwn)
14719 {
14720         dev_info_t      *child = NULL;
14721         char            *smp_wwn = NULL;
14722 
14723         child = ddi_get_child(parent);
14724         while (child) {
14725                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
14726                     DDI_PROP_DONTPASS, SMP_WWN, &smp_wwn)
14727                     != DDI_SUCCESS) {
14728                         child = ddi_get_next_sibling(child);
14729                         continue;
14730                 }
14731 
14732                 if (strcmp(smp_wwn, str_wwn) == 0) {
14733                         ddi_prop_free(smp_wwn);
14734                         break;
14735                 }
14736                 child = ddi_get_next_sibling(child);
14737                 ddi_prop_free(smp_wwn);
14738         }
14739         return (child);
14740 }
14741 
14742 static int
14743 mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, uint_t flags)
14744 {
14745         int             rval = DDI_FAILURE;
14746         char            *devname;
14747         char            wwn_str[MPTSAS_WWN_STRLEN];
14748         dev_info_t      *cdip;
14749 
14750         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
14751 
14752         cdip = mptsas_find_smp_child(pdip, wwn_str);
14753 
14754         if (cdip == NULL)
14755                 return (DDI_SUCCESS);
14756 
14757         /*
14758          * Make sure node is attached otherwise
14759          * it won't have related cache nodes to
14760          * clean up.  i_ddi_devi_attached is
14761          * similiar to i_ddi_node_state(cdip) >=
14762          * DS_ATTACHED.
14763          */
14764         if (i_ddi_devi_attached(cdip)) {
14765 
14766                 /* Get full devname */
14767                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
14768                 (void) ddi_deviname(cdip, devname);
14769                 /* Clean cache */
14770                 (void) devfs_clean(pdip, devname + 1,
14771                     DV_CLEAN_FORCE);
14772                 kmem_free(devname, MAXNAMELEN + 1);
14773         }
14774 
14775         rval = ndi_devi_offline(cdip, flags);
14776 
14777         return (rval);
14778 }
14779 
14780 static dev_info_t *
14781 mptsas_find_child(dev_info_t *pdip, char *name)
14782 {
14783         dev_info_t      *child = NULL;
14784         char            *rname = NULL;
14785         int             rval = DDI_FAILURE;
14786 
14787         rname = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14788 
14789         child = ddi_get_child(pdip);
14790         while (child) {
14791                 rval = mptsas_name_child(child, rname, SCSI_MAXNAMELEN);
14792                 if (rval != DDI_SUCCESS) {
14793                         child = ddi_get_next_sibling(child);
14794                         bzero(rname, SCSI_MAXNAMELEN);
14795                         continue;
14796                 }
14797 
14798                 if (strcmp(rname, name) == 0) {
14799                         break;
14800                 }
14801                 child = ddi_get_next_sibling(child);
14802                 bzero(rname, SCSI_MAXNAMELEN);
14803         }
14804 
14805         kmem_free(rname, SCSI_MAXNAMELEN);
14806 
14807         return (child);
14808 }
14809 
14810 
14811 static dev_info_t *
14812 mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr, int lun)
14813 {
14814         dev_info_t      *child = NULL;
14815         char            *name = NULL;
14816         char            *addr = NULL;
14817 
14818         name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14819         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14820         (void) sprintf(name, "%016"PRIx64, sasaddr);
14821         (void) sprintf(addr, "w%s,%x", name, lun);
14822         child = mptsas_find_child(pdip, addr);
14823         kmem_free(name, SCSI_MAXNAMELEN);
14824         kmem_free(addr, SCSI_MAXNAMELEN);
14825         return (child);
14826 }
14827 
14828 static dev_info_t *
14829 mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy)
14830 {
14831         dev_info_t      *child;
14832         char            *addr;
14833 
14834         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14835         (void) sprintf(addr, "p%x,0", phy);
14836         child = mptsas_find_child(pdip, addr);
14837         kmem_free(addr, SCSI_MAXNAMELEN);
14838         return (child);
14839 }
14840 
14841 static mdi_pathinfo_t *
14842 mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy)
14843 {
14844         mdi_pathinfo_t  *path;
14845         char            *addr = NULL;
14846 
14847         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14848         (void) sprintf(addr, "p%x,0", phy);
14849         path = mdi_pi_find(pdip, NULL, addr);
14850         kmem_free(addr, SCSI_MAXNAMELEN);
14851         return (path);
14852 }
14853 
14854 static mdi_pathinfo_t *
14855 mptsas_find_path_addr(dev_info_t *parent, uint64_t sasaddr, int lun)
14856 {
14857         mdi_pathinfo_t  *path;
14858         char            *name = NULL;
14859         char            *addr = NULL;
14860 
14861         name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14862         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14863         (void) sprintf(name, "%016"PRIx64, sasaddr);
14864         (void) sprintf(addr, "w%s,%x", name, lun);
14865         path = mdi_pi_find(parent, NULL, addr);
14866         kmem_free(name, SCSI_MAXNAMELEN);
14867         kmem_free(addr, SCSI_MAXNAMELEN);
14868 
14869         return (path);
14870 }
14871 
14872 static int
14873 mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
14874     dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
14875 {
14876         int                     i = 0;
14877         uchar_t                 *inq83 = NULL;
14878         int                     inq83_len1 = 0xFF;
14879         int                     inq83_len = 0;
14880         int                     rval = DDI_FAILURE;
14881         ddi_devid_t             devid;
14882         char                    *guid = NULL;
14883         int                     target = ptgt->m_devhdl;
14884         mdi_pathinfo_t          *pip = NULL;
14885         mptsas_t                *mpt = DIP2MPT(pdip);
14886 
14887         /*
14888          * For DVD/CD ROM and tape devices and optical
14889          * devices, we won't try to enumerate them under
14890          * scsi_vhci, so no need to try page83
14891          */
14892         if (sd_inq && (sd_inq->inq_dtype == DTYPE_RODIRECT ||
14893             sd_inq->inq_dtype == DTYPE_OPTICAL ||
14894             sd_inq->inq_dtype == DTYPE_ESI))
14895                 goto create_lun;
14896 
14897         /*
14898          * The LCA returns good SCSI status, but corrupt page 83 data the first
14899          * time it is queried. The solution is to keep trying to request page83
14900          * and verify the GUID is not (DDI_NOT_WELL_FORMED) in
14901          * mptsas_inq83_retry_timeout seconds. If the timeout expires, driver
14902          * give up to get VPD page at this stage and fail the enumeration.
14903          */
14904 
14905         inq83   = kmem_zalloc(inq83_len1, KM_SLEEP);
14906 
14907         for (i = 0; i < mptsas_inq83_retry_timeout; i++) {
14908                 rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
14909                     inq83_len1, &inq83_len, 1);
14910                 if (rval != 0) {
14911                         mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
14912                             "0x83 for target:%x, lun:%x failed!", target, lun);
14913                         if (mptsas_physical_bind_failed_page_83 != B_FALSE)
14914                                 goto create_lun;
14915                         goto out;
14916                 }
14917                 /*
14918                  * create DEVID from inquiry data
14919                  */
14920                 if ((rval = ddi_devid_scsi_encode(
14921                     DEVID_SCSI_ENCODE_VERSION_LATEST, NULL, (uchar_t *)sd_inq,
14922                     sizeof (struct scsi_inquiry), NULL, 0, inq83,
14923                     (size_t)inq83_len, &devid)) == DDI_SUCCESS) {
14924                         /*
14925                          * extract GUID from DEVID
14926                          */
14927                         guid = ddi_devid_to_guid(devid);
14928 
14929                         /*
14930                          * Do not enable MPXIO if the strlen(guid) is greater
14931                          * than MPTSAS_MAX_GUID_LEN, this constrain would be
14932                          * handled by framework later.
14933                          */
14934                         if (guid && (strlen(guid) > MPTSAS_MAX_GUID_LEN)) {
14935                                 ddi_devid_free_guid(guid);
14936                                 guid = NULL;
14937                                 if (mpt->m_mpxio_enable == TRUE) {
14938                                         mptsas_log(mpt, CE_NOTE, "!Target:%x, "
14939                                             "lun:%x doesn't have a valid GUID, "
14940                                             "multipathing for this drive is "
14941                                             "not enabled", target, lun);
14942                                 }
14943                         }
14944 
14945                         /*
14946                          * devid no longer needed
14947                          */
14948                         ddi_devid_free(devid);
14949                         break;
14950                 } else if (rval == DDI_NOT_WELL_FORMED) {
14951                         /*
14952                          * return value of ddi_devid_scsi_encode equal to
14953                          * DDI_NOT_WELL_FORMED means DEVID_RETRY, it worth
14954                          * to retry inquiry page 0x83 and get GUID.
14955                          */
14956                         NDBG20(("Not well formed devid, retry..."));
14957                         delay(1 * drv_usectohz(1000000));
14958                         continue;
14959                 } else {
14960                         mptsas_log(mpt, CE_WARN, "!Encode devid failed for "
14961                             "path target:%x, lun:%x", target, lun);
14962                         rval = DDI_FAILURE;
14963                         goto create_lun;
14964                 }
14965         }
14966 
14967         if (i == mptsas_inq83_retry_timeout) {
14968                 mptsas_log(mpt, CE_WARN, "!Repeated page83 requests timeout "
14969                     "for path target:%x, lun:%x", target, lun);
14970         }
14971 
14972         rval = DDI_FAILURE;
14973 
14974 create_lun:
14975         if ((guid != NULL) && (mpt->m_mpxio_enable == TRUE)) {
14976                 rval = mptsas_create_virt_lun(pdip, sd_inq, guid, lun_dip, &pip,
14977                     ptgt, lun);
14978         }
14979         if (rval != DDI_SUCCESS) {
14980                 rval = mptsas_create_phys_lun(pdip, sd_inq, guid, lun_dip,
14981                     ptgt, lun);
14982 
14983         }
14984 out:
14985         if (guid != NULL) {
14986                 /*
14987                  * guid no longer needed
14988                  */
14989                 ddi_devid_free_guid(guid);
14990         }
14991         if (inq83 != NULL)
14992                 kmem_free(inq83, inq83_len1);
14993         return (rval);
14994 }
14995 
14996 static int
14997 mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *inq, char *guid,
14998     dev_info_t **lun_dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt, int lun)
14999 {
15000         int                     target;
15001         char                    *nodename = NULL;
15002         char                    **compatible = NULL;
15003         int                     ncompatible     = 0;
15004         int                     mdi_rtn = MDI_FAILURE;
15005         int                     rval = DDI_FAILURE;
15006         char                    *old_guid = NULL;
15007         mptsas_t                *mpt = DIP2MPT(pdip);
15008         char                    *lun_addr = NULL;
15009         char                    *wwn_str = NULL;
15010         char                    *attached_wwn_str = NULL;
15011         char                    *component = NULL;
15012         uint8_t                 phy = 0xFF;
15013         uint64_t                sas_wwn;
15014         int64_t                 lun64 = 0;
15015         uint32_t                devinfo;
15016         uint16_t                dev_hdl;
15017         uint16_t                pdev_hdl;
15018         uint64_t                dev_sas_wwn;
15019         uint64_t                pdev_sas_wwn;
15020         uint32_t                pdev_info;
15021         uint8_t                 physport;
15022         uint8_t                 phy_id;
15023         uint32_t                page_address;
15024         uint16_t                bay_num, enclosure, io_flags;
15025         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
15026         uint32_t                dev_info;
15027 
15028         mutex_enter(&mpt->m_mutex);
15029         target = ptgt->m_devhdl;
15030         sas_wwn = ptgt->m_addr.mta_wwn;
15031         devinfo = ptgt->m_deviceinfo;
15032         phy = ptgt->m_phynum;
15033         mutex_exit(&mpt->m_mutex);
15034 
15035         if (sas_wwn) {
15036                 *pip = mptsas_find_path_addr(pdip, sas_wwn, lun);
15037         } else {
15038                 *pip = mptsas_find_path_phy(pdip, phy);
15039         }
15040 
15041         if (*pip != NULL) {
15042                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
15043                 ASSERT(*lun_dip != NULL);
15044                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, *lun_dip,
15045                     (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
15046                     MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
15047                         if (strncmp(guid, old_guid, strlen(guid)) == 0) {
15048                                 /*
15049                                  * Same path back online again.
15050                                  */
15051                                 (void) ddi_prop_free(old_guid);
15052                                 if ((!MDI_PI_IS_ONLINE(*pip)) &&
15053                                     (!MDI_PI_IS_STANDBY(*pip)) &&
15054                                     (ptgt->m_tgt_unconfigured == 0)) {
15055                                         rval = mdi_pi_online(*pip, 0);
15056                                         mutex_enter(&mpt->m_mutex);
15057                                         ptgt->m_led_status = 0;
15058                                         (void) mptsas_flush_led_status(mpt,
15059                                             ptgt);
15060                                         mutex_exit(&mpt->m_mutex);
15061                                 } else {
15062                                         rval = DDI_SUCCESS;
15063                                 }
15064                                 if (rval != DDI_SUCCESS) {
15065                                         mptsas_log(mpt, CE_WARN, "path:target: "
15066                                             "%x, lun:%x online failed!", target,
15067                                             lun);
15068                                         *pip = NULL;
15069                                         *lun_dip = NULL;
15070                                 }
15071                                 return (rval);
15072                         } else {
15073                                 /*
15074                                  * The GUID of the LUN has changed which maybe
15075                                  * because customer mapped another volume to the
15076                                  * same LUN.
15077                                  */
15078                                 mptsas_log(mpt, CE_WARN, "The GUID of the "
15079                                     "target:%x, lun:%x was changed, maybe "
15080                                     "because someone mapped another volume "
15081                                     "to the same LUN", target, lun);
15082                                 (void) ddi_prop_free(old_guid);
15083                                 if (!MDI_PI_IS_OFFLINE(*pip)) {
15084                                         rval = mdi_pi_offline(*pip, 0);
15085                                         if (rval != MDI_SUCCESS) {
15086                                                 mptsas_log(mpt, CE_WARN, "path:"
15087                                                     "target:%x, lun:%x offline "
15088                                                     "failed!", target, lun);
15089                                                 *pip = NULL;
15090                                                 *lun_dip = NULL;
15091                                                 return (DDI_FAILURE);
15092                                         }
15093                                 }
15094                                 if (mdi_pi_free(*pip, 0) != MDI_SUCCESS) {
15095                                         mptsas_log(mpt, CE_WARN, "path:target:"
15096                                             "%x, lun:%x free failed!", target,
15097                                             lun);
15098                                         *pip = NULL;
15099                                         *lun_dip = NULL;
15100                                         return (DDI_FAILURE);
15101                                 }
15102                         }
15103                 } else {
15104                         mptsas_log(mpt, CE_WARN, "Can't get client-guid "
15105                             "property for path:target:%x, lun:%x", target, lun);
15106                         *pip = NULL;
15107                         *lun_dip = NULL;
15108                         return (DDI_FAILURE);
15109                 }
15110         }
15111         scsi_hba_nodename_compatible_get(inq, NULL,
15112             inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
15113 
15114         /*
15115          * if nodename can't be determined then print a message and skip it
15116          */
15117         if (nodename == NULL) {
15118                 mptsas_log(mpt, CE_WARN, "mptsas driver found no compatible "
15119                     "driver for target%d lun %d dtype:0x%02x", target, lun,
15120                     inq->inq_dtype);
15121                 return (DDI_FAILURE);
15122         }
15123 
15124         wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
15125         /* The property is needed by MPAPI */
15126         (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
15127 
15128         lun_addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
15129         if (guid) {
15130                 (void) sprintf(lun_addr, "w%s,%x", wwn_str, lun);
15131                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15132         } else {
15133                 (void) sprintf(lun_addr, "p%x,%x", phy, lun);
15134                 (void) sprintf(wwn_str, "p%x", phy);
15135         }
15136 
15137         mdi_rtn = mdi_pi_alloc_compatible(pdip, nodename,
15138             guid, lun_addr, compatible, ncompatible,
15139             0, pip);
15140         if (mdi_rtn == MDI_SUCCESS) {
15141 
15142                 if (mdi_prop_update_string(*pip, MDI_GUID,
15143                     guid) != DDI_SUCCESS) {
15144                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15145                             "create prop for target %d lun %d (MDI_GUID)",
15146                             target, lun);
15147                         mdi_rtn = MDI_FAILURE;
15148                         goto virt_create_done;
15149                 }
15150 
15151                 if (mdi_prop_update_int(*pip, LUN_PROP,
15152                     lun) != DDI_SUCCESS) {
15153                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15154                             "create prop for target %d lun %d (LUN_PROP)",
15155                             target, lun);
15156                         mdi_rtn = MDI_FAILURE;
15157                         goto virt_create_done;
15158                 }
15159                 lun64 = (int64_t)lun;
15160                 if (mdi_prop_update_int64(*pip, LUN64_PROP,
15161                     lun64) != DDI_SUCCESS) {
15162                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15163                             "create prop for target %d (LUN64_PROP)",
15164                             target);
15165                         mdi_rtn = MDI_FAILURE;
15166                         goto virt_create_done;
15167                 }
15168                 if (mdi_prop_update_string_array(*pip, "compatible",
15169                     compatible, ncompatible) !=
15170                     DDI_PROP_SUCCESS) {
15171                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15172                             "create prop for target %d lun %d (COMPATIBLE)",
15173                             target, lun);
15174                         mdi_rtn = MDI_FAILURE;
15175                         goto virt_create_done;
15176                 }
15177                 if (sas_wwn && (mdi_prop_update_string(*pip,
15178                     SCSI_ADDR_PROP_TARGET_PORT, wwn_str) != DDI_PROP_SUCCESS)) {
15179                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15180                             "create prop for target %d lun %d "
15181                             "(target-port)", target, lun);
15182                         mdi_rtn = MDI_FAILURE;
15183                         goto virt_create_done;
15184                 } else if ((sas_wwn == 0) && (mdi_prop_update_int(*pip,
15185                     "sata-phy", phy) != DDI_PROP_SUCCESS)) {
15186                         /*
15187                          * Direct attached SATA device without DeviceName
15188                          */
15189                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15190                             "create prop for SAS target %d lun %d "
15191                             "(sata-phy)", target, lun);
15192                         mdi_rtn = MDI_FAILURE;
15193                         goto virt_create_done;
15194                 }
15195                 mutex_enter(&mpt->m_mutex);
15196 
15197                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15198                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15199                     (uint32_t)ptgt->m_devhdl;
15200                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15201                     &dev_hdl, &dev_sas_wwn, &dev_info, &physport,
15202                     &phy_id, &pdev_hdl, &bay_num, &enclosure, &io_flags);
15203                 if (rval != DDI_SUCCESS) {
15204                         mutex_exit(&mpt->m_mutex);
15205                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
15206                             "parent device for handle %d", page_address);
15207                         mdi_rtn = MDI_FAILURE;
15208                         goto virt_create_done;
15209                 }
15210 
15211                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15212                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
15213                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15214                     &dev_hdl, &pdev_sas_wwn, &pdev_info, &physport,
15215                     &phy_id, &pdev_hdl, &bay_num, &enclosure, &io_flags);
15216                 if (rval != DDI_SUCCESS) {
15217                         mutex_exit(&mpt->m_mutex);
15218                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
15219                             "device info for handle %d", page_address);
15220                         mdi_rtn = MDI_FAILURE;
15221                         goto virt_create_done;
15222                 }
15223 
15224                 mutex_exit(&mpt->m_mutex);
15225 
15226                 /*
15227                  * If this device direct attached to the controller
15228                  * set the attached-port to the base wwid
15229                  */
15230                 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15231                     != DEVINFO_DIRECT_ATTACHED) {
15232                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15233                             pdev_sas_wwn);
15234                 } else {
15235                         /*
15236                          * Update the iport's attached-port to guid
15237                          */
15238                         if (sas_wwn == 0) {
15239                                 (void) sprintf(wwn_str, "p%x", phy);
15240                         } else {
15241                                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15242                         }
15243                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
15244                             pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
15245                             DDI_PROP_SUCCESS) {
15246                                 mptsas_log(mpt, CE_WARN,
15247                                     "mptsas unable to create "
15248                                     "property for iport target-port"
15249                                     " %s (sas_wwn)",
15250                                     wwn_str);
15251                                 mdi_rtn = MDI_FAILURE;
15252                                 goto virt_create_done;
15253                         }
15254 
15255                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15256                             mpt->un.m_base_wwid);
15257                 }
15258 
15259                 if (mdi_prop_update_string(*pip,
15260                     SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
15261                     DDI_PROP_SUCCESS) {
15262                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15263                             "property for iport attached-port %s (sas_wwn)",
15264                             attached_wwn_str);
15265                         mdi_rtn = MDI_FAILURE;
15266                         goto virt_create_done;
15267                 }
15268 
15269 
15270                 if (inq->inq_dtype == 0) {
15271                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
15272                         /*
15273                          * set obp path for pathinfo
15274                          */
15275                         (void) snprintf(component, MAXPATHLEN,
15276                             "disk@%s", lun_addr);
15277 
15278                         if (mdi_pi_pathname_obp_set(*pip, component) !=
15279                             DDI_SUCCESS) {
15280                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
15281                                     "unable to set obp-path for object %s",
15282                                     component);
15283                                 mdi_rtn = MDI_FAILURE;
15284                                 goto virt_create_done;
15285                         }
15286                 }
15287 
15288                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
15289                 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
15290                     MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
15291                         if ((ndi_prop_update_int(DDI_DEV_T_NONE, *lun_dip,
15292                             "pm-capable", 1)) !=
15293                             DDI_PROP_SUCCESS) {
15294                                 mptsas_log(mpt, CE_WARN, "mptsas driver"
15295                                     "failed to create pm-capable "
15296                                     "property, target %d", target);
15297                                 mdi_rtn = MDI_FAILURE;
15298                                 goto virt_create_done;
15299                         }
15300                 }
15301                 /*
15302                  * Create the phy-num property
15303                  */
15304                 if (mdi_prop_update_int(*pip, "phy-num",
15305                     ptgt->m_phynum) != DDI_SUCCESS) {
15306                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15307                             "create phy-num property for target %d lun %d",
15308                             target, lun);
15309                         mdi_rtn = MDI_FAILURE;
15310                         goto virt_create_done;
15311                 }
15312                 NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr));
15313                 mdi_rtn = mdi_pi_online(*pip, 0);
15314                 if (mdi_rtn == MDI_SUCCESS) {
15315                         mutex_enter(&mpt->m_mutex);
15316                         ptgt->m_led_status = 0;
15317                         (void) mptsas_flush_led_status(mpt, ptgt);
15318                         mutex_exit(&mpt->m_mutex);
15319                 }
15320                 if (mdi_rtn == MDI_NOT_SUPPORTED) {
15321                         mdi_rtn = MDI_FAILURE;
15322                 }
15323 virt_create_done:
15324                 if (*pip && mdi_rtn != MDI_SUCCESS) {
15325                         (void) mdi_pi_free(*pip, 0);
15326                         *pip = NULL;
15327                         *lun_dip = NULL;
15328                 }
15329         }
15330 
15331         scsi_hba_nodename_compatible_free(nodename, compatible);
15332         if (lun_addr != NULL) {
15333                 kmem_free(lun_addr, SCSI_MAXNAMELEN);
15334         }
15335         if (wwn_str != NULL) {
15336                 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
15337         }
15338         if (component != NULL) {
15339                 kmem_free(component, MAXPATHLEN);
15340         }
15341 
15342         return ((mdi_rtn == MDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
15343 }
15344 
15345 static int
15346 mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *inq,
15347     char *guid, dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
15348 {
15349         int                     target;
15350         int                     rval;
15351         int                     ndi_rtn = NDI_FAILURE;
15352         uint64_t                be_sas_wwn;
15353         char                    *nodename = NULL;
15354         char                    **compatible = NULL;
15355         int                     ncompatible = 0;
15356         int                     instance = 0;
15357         mptsas_t                *mpt = DIP2MPT(pdip);
15358         char                    *wwn_str = NULL;
15359         char                    *component = NULL;
15360         char                    *attached_wwn_str = NULL;
15361         uint8_t                 phy = 0xFF;
15362         uint64_t                sas_wwn;
15363         uint32_t                devinfo;
15364         uint16_t                dev_hdl;
15365         uint16_t                pdev_hdl;
15366         uint64_t                pdev_sas_wwn;
15367         uint64_t                dev_sas_wwn;
15368         uint32_t                pdev_info;
15369         uint8_t                 physport;
15370         uint8_t                 phy_id;
15371         uint32_t                page_address;
15372         uint16_t                bay_num, enclosure, io_flags;
15373         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
15374         uint32_t                dev_info;
15375         int64_t                 lun64 = 0;
15376 
15377         mutex_enter(&mpt->m_mutex);
15378         target = ptgt->m_devhdl;
15379         sas_wwn = ptgt->m_addr.mta_wwn;
15380         devinfo = ptgt->m_deviceinfo;
15381         phy = ptgt->m_phynum;
15382         mutex_exit(&mpt->m_mutex);
15383 
15384         /*
15385          * generate compatible property with binding-set "mpt"
15386          */
15387         scsi_hba_nodename_compatible_get(inq, NULL, inq->inq_dtype, NULL,
15388             &nodename, &compatible, &ncompatible);
15389 
15390         /*
15391          * if nodename can't be determined then print a message and skip it
15392          */
15393         if (nodename == NULL) {
15394                 mptsas_log(mpt, CE_WARN, "mptsas found no compatible driver "
15395                     "for target %d lun %d", target, lun);
15396                 return (DDI_FAILURE);
15397         }
15398 
15399         ndi_rtn = ndi_devi_alloc(pdip, nodename,
15400             DEVI_SID_NODEID, lun_dip);
15401 
15402         /*
15403          * if lun alloc success, set props
15404          */
15405         if (ndi_rtn == NDI_SUCCESS) {
15406 
15407                 if (ndi_prop_update_int(DDI_DEV_T_NONE,
15408                     *lun_dip, LUN_PROP, lun) !=
15409                     DDI_PROP_SUCCESS) {
15410                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15411                             "property for target %d lun %d (LUN_PROP)",
15412                             target, lun);
15413                         ndi_rtn = NDI_FAILURE;
15414                         goto phys_create_done;
15415                 }
15416 
15417                 lun64 = (int64_t)lun;
15418                 if (ndi_prop_update_int64(DDI_DEV_T_NONE,
15419                     *lun_dip, LUN64_PROP, lun64) !=
15420                     DDI_PROP_SUCCESS) {
15421                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15422                             "property for target %d lun64 %d (LUN64_PROP)",
15423                             target, lun);
15424                         ndi_rtn = NDI_FAILURE;
15425                         goto phys_create_done;
15426                 }
15427                 if (ndi_prop_update_string_array(DDI_DEV_T_NONE,
15428                     *lun_dip, "compatible", compatible, ncompatible)
15429                     != DDI_PROP_SUCCESS) {
15430                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15431                             "property for target %d lun %d (COMPATIBLE)",
15432                             target, lun);
15433                         ndi_rtn = NDI_FAILURE;
15434                         goto phys_create_done;
15435                 }
15436 
15437                 /*
15438                  * We need the SAS WWN for non-multipath devices, so
15439                  * we'll use the same property as that multipathing
15440                  * devices need to present for MPAPI. If we don't have
15441                  * a WWN (e.g. parallel SCSI), don't create the prop.
15442                  */
15443                 wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
15444                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15445                 if (sas_wwn && ndi_prop_update_string(DDI_DEV_T_NONE,
15446                     *lun_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str)
15447                     != DDI_PROP_SUCCESS) {
15448                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15449                             "create property for SAS target %d lun %d "
15450                             "(target-port)", target, lun);
15451                         ndi_rtn = NDI_FAILURE;
15452                         goto phys_create_done;
15453                 }
15454 
15455                 be_sas_wwn = BE_64(sas_wwn);
15456                 if (sas_wwn && ndi_prop_update_byte_array(
15457                     DDI_DEV_T_NONE, *lun_dip, "port-wwn",
15458                     (uchar_t *)&be_sas_wwn, 8) != DDI_PROP_SUCCESS) {
15459                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15460                             "create property for SAS target %d lun %d "
15461                             "(port-wwn)", target, lun);
15462                         ndi_rtn = NDI_FAILURE;
15463                         goto phys_create_done;
15464                 } else if ((sas_wwn == 0) && (ndi_prop_update_int(
15465                     DDI_DEV_T_NONE, *lun_dip, "sata-phy", phy) !=
15466                     DDI_PROP_SUCCESS)) {
15467                         /*
15468                          * Direct attached SATA device without DeviceName
15469                          */
15470                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15471                             "create property for SAS target %d lun %d "
15472                             "(sata-phy)", target, lun);
15473                         ndi_rtn = NDI_FAILURE;
15474                         goto phys_create_done;
15475                 }
15476 
15477                 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
15478                     *lun_dip, SAS_PROP) != DDI_PROP_SUCCESS) {
15479                         mptsas_log(mpt, CE_WARN, "mptsas unable to"
15480                             "create property for SAS target %d lun %d"
15481                             " (SAS_PROP)", target, lun);
15482                         ndi_rtn = NDI_FAILURE;
15483                         goto phys_create_done;
15484                 }
15485                 if (guid && (ndi_prop_update_string(DDI_DEV_T_NONE,
15486                     *lun_dip, NDI_GUID, guid) != DDI_SUCCESS)) {
15487                         mptsas_log(mpt, CE_WARN, "mptsas unable "
15488                             "to create guid property for target %d "
15489                             "lun %d", target, lun);
15490                         ndi_rtn = NDI_FAILURE;
15491                         goto phys_create_done;
15492                 }
15493 
15494                 /*
15495                  * The following code is to set properties for SM-HBA support,
15496                  * it doesn't apply to RAID volumes
15497                  */
15498                 if (ptgt->m_addr.mta_phymask == 0)
15499                         goto phys_raid_lun;
15500 
15501                 mutex_enter(&mpt->m_mutex);
15502 
15503                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15504                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15505                     (uint32_t)ptgt->m_devhdl;
15506                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15507                     &dev_hdl, &dev_sas_wwn, &dev_info,
15508                     &physport, &phy_id, &pdev_hdl,
15509                     &bay_num, &enclosure, &io_flags);
15510                 if (rval != DDI_SUCCESS) {
15511                         mutex_exit(&mpt->m_mutex);
15512                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
15513                             "parent device for handle %d.", page_address);
15514                         ndi_rtn = NDI_FAILURE;
15515                         goto phys_create_done;
15516                 }
15517 
15518                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15519                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
15520                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15521                     &dev_hdl, &pdev_sas_wwn, &pdev_info, &physport,
15522                     &phy_id, &pdev_hdl, &bay_num, &enclosure, &io_flags);
15523                 if (rval != DDI_SUCCESS) {
15524                         mutex_exit(&mpt->m_mutex);
15525                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15526                             "device for handle %d.", page_address);
15527                         ndi_rtn = NDI_FAILURE;
15528                         goto phys_create_done;
15529                 }
15530 
15531                 mutex_exit(&mpt->m_mutex);
15532 
15533                 /*
15534                  * If this device direct attached to the controller
15535                  * set the attached-port to the base wwid
15536                  */
15537                 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15538                     != DEVINFO_DIRECT_ATTACHED) {
15539                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15540                             pdev_sas_wwn);
15541                 } else {
15542                         /*
15543                          * Update the iport's attached-port to guid
15544                          */
15545                         if (sas_wwn == 0) {
15546                                 (void) sprintf(wwn_str, "p%x", phy);
15547                         } else {
15548                                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15549                         }
15550                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
15551                             pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
15552                             DDI_PROP_SUCCESS) {
15553                                 mptsas_log(mpt, CE_WARN,
15554                                     "mptsas unable to create "
15555                                     "property for iport target-port"
15556                                     " %s (sas_wwn)",
15557                                     wwn_str);
15558                                 ndi_rtn = NDI_FAILURE;
15559                                 goto phys_create_done;
15560                         }
15561 
15562                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15563                             mpt->un.m_base_wwid);
15564                 }
15565 
15566                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15567                     *lun_dip, SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
15568                     DDI_PROP_SUCCESS) {
15569                         mptsas_log(mpt, CE_WARN,
15570                             "mptsas unable to create "
15571                             "property for iport attached-port %s (sas_wwn)",
15572                             attached_wwn_str);
15573                         ndi_rtn = NDI_FAILURE;
15574                         goto phys_create_done;
15575                 }
15576 
15577                 if (IS_SATA_DEVICE(dev_info)) {
15578                         if (ndi_prop_update_string(DDI_DEV_T_NONE,
15579                             *lun_dip, MPTSAS_VARIANT, "sata") !=
15580                             DDI_PROP_SUCCESS) {
15581                                 mptsas_log(mpt, CE_WARN,
15582                                     "mptsas unable to create "
15583                                     "property for device variant ");
15584                                 ndi_rtn = NDI_FAILURE;
15585                                 goto phys_create_done;
15586                         }
15587                 }
15588 
15589                 if (IS_ATAPI_DEVICE(dev_info)) {
15590                         if (ndi_prop_update_string(DDI_DEV_T_NONE,
15591                             *lun_dip, MPTSAS_VARIANT, "atapi") !=
15592                             DDI_PROP_SUCCESS) {
15593                                 mptsas_log(mpt, CE_WARN,
15594                                     "mptsas unable to create "
15595                                     "property for device variant ");
15596                                 ndi_rtn = NDI_FAILURE;
15597                                 goto phys_create_done;
15598                         }
15599                 }
15600 
15601 phys_raid_lun:
15602                 /*
15603                  * if this is a SAS controller, and the target is a SATA
15604                  * drive, set the 'pm-capable' property for sd and if on
15605                  * an OPL platform, also check if this is an ATAPI
15606                  * device.
15607                  */
15608                 instance = ddi_get_instance(mpt->m_dip);
15609                 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
15610                     MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
15611                         NDBG2(("mptsas%d: creating pm-capable property, "
15612                             "target %d", instance, target));
15613 
15614                         if ((ndi_prop_update_int(DDI_DEV_T_NONE,
15615                             *lun_dip, "pm-capable", 1)) !=
15616                             DDI_PROP_SUCCESS) {
15617                                 mptsas_log(mpt, CE_WARN, "mptsas "
15618                                     "failed to create pm-capable "
15619                                     "property, target %d", target);
15620                                 ndi_rtn = NDI_FAILURE;
15621                                 goto phys_create_done;
15622                         }
15623 
15624                 }
15625 
15626                 if ((inq->inq_dtype == 0) || (inq->inq_dtype == 5)) {
15627                         /*
15628                          * add 'obp-path' properties for devinfo
15629                          */
15630                         bzero(wwn_str, sizeof (wwn_str));
15631                         (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
15632                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
15633                         if (guid) {
15634                                 (void) snprintf(component, MAXPATHLEN,
15635                                     "disk@w%s,%x", wwn_str, lun);
15636                         } else {
15637                                 (void) snprintf(component, MAXPATHLEN,
15638                                     "disk@p%x,%x", phy, lun);
15639                         }
15640                         if (ddi_pathname_obp_set(*lun_dip, component)
15641                             != DDI_SUCCESS) {
15642                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
15643                                     "unable to set obp-path for SAS "
15644                                     "object %s", component);
15645                                 ndi_rtn = NDI_FAILURE;
15646                                 goto phys_create_done;
15647                         }
15648                 }
15649                 /*
15650                  * Create the phy-num property for non-raid disk
15651                  */
15652                 if (ptgt->m_addr.mta_phymask != 0) {
15653                         if (ndi_prop_update_int(DDI_DEV_T_NONE,
15654                             *lun_dip, "phy-num", ptgt->m_phynum) !=
15655                             DDI_PROP_SUCCESS) {
15656                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
15657                                     "failed to create phy-num property for "
15658                                     "target %d", target);
15659                                 ndi_rtn = NDI_FAILURE;
15660                                 goto phys_create_done;
15661                         }
15662                 }
15663 phys_create_done:
15664                 /*
15665                  * If props were setup ok, online the lun
15666                  */
15667                 if (ndi_rtn == NDI_SUCCESS) {
15668                         /*
15669                          * Try to online the new node
15670                          */
15671                         ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
15672                 }
15673                 if (ndi_rtn == NDI_SUCCESS) {
15674                         mutex_enter(&mpt->m_mutex);
15675                         ptgt->m_led_status = 0;
15676                         (void) mptsas_flush_led_status(mpt, ptgt);
15677                         mutex_exit(&mpt->m_mutex);
15678                 }
15679 
15680                 /*
15681                  * If success set rtn flag, else unwire alloc'd lun
15682                  */
15683                 if (ndi_rtn != NDI_SUCCESS) {
15684                         NDBG12(("mptsas driver unable to online "
15685                             "target %d lun %d", target, lun));
15686                         ndi_prop_remove_all(*lun_dip);
15687                         (void) ndi_devi_free(*lun_dip);
15688                         *lun_dip = NULL;
15689                 }
15690         }
15691 
15692         scsi_hba_nodename_compatible_free(nodename, compatible);
15693 
15694         if (wwn_str != NULL) {
15695                 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
15696         }
15697         if (component != NULL) {
15698                 kmem_free(component, MAXPATHLEN);
15699         }
15700 
15701 
15702         return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
15703 }
15704 
15705 static int
15706 mptsas_probe_smp(dev_info_t *pdip, uint64_t wwn)
15707 {
15708         mptsas_t        *mpt = DIP2MPT(pdip);
15709         struct smp_device smp_sd;
15710 
15711         /* XXX An HBA driver should not be allocating an smp_device. */
15712         bzero(&smp_sd, sizeof (struct smp_device));
15713         smp_sd.smp_sd_address.smp_a_hba_tran = mpt->m_smptran;
15714         bcopy(&wwn, smp_sd.smp_sd_address.smp_a_wwn, SAS_WWN_BYTE_SIZE);
15715 
15716         if (smp_probe(&smp_sd) != DDI_PROBE_SUCCESS)
15717                 return (NDI_FAILURE);
15718         return (NDI_SUCCESS);
15719 }
15720 
15721 static int
15722 mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn, dev_info_t **smp_dip)
15723 {
15724         mptsas_t        *mpt = DIP2MPT(pdip);
15725         mptsas_smp_t    *psmp = NULL;
15726         int             rval;
15727         int             phymask;
15728 
15729         /*
15730          * Get the physical port associated to the iport
15731          * PHYMASK TODO
15732          */
15733         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
15734             "phymask", 0);
15735         /*
15736          * Find the smp node in hash table with specified sas address and
15737          * physical port
15738          */
15739         psmp = mptsas_wwid_to_psmp(mpt, phymask, sas_wwn);
15740         if (psmp == NULL) {
15741                 return (DDI_FAILURE);
15742         }
15743 
15744         rval = mptsas_online_smp(pdip, psmp, smp_dip);
15745 
15746         return (rval);
15747 }
15748 
15749 static int
15750 mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
15751     dev_info_t **smp_dip)
15752 {
15753         char            wwn_str[MPTSAS_WWN_STRLEN];
15754         char            attached_wwn_str[MPTSAS_WWN_STRLEN];
15755         int             ndi_rtn = NDI_FAILURE;
15756         int             rval = 0;
15757         mptsas_smp_t    dev_info;
15758         uint32_t        page_address;
15759         mptsas_t        *mpt = DIP2MPT(pdip);
15760         uint16_t        dev_hdl;
15761         uint64_t        sas_wwn;
15762         uint64_t        smp_sas_wwn;
15763         uint8_t         physport;
15764         uint8_t         phy_id;
15765         uint16_t        pdev_hdl;
15766         uint8_t         numphys = 0;
15767         uint16_t        i = 0;
15768         char            phymask[MPTSAS_MAX_PHYS];
15769         char            *iport = NULL;
15770         mptsas_phymask_t        phy_mask = 0;
15771         uint16_t        attached_devhdl;
15772         uint16_t        bay_num, enclosure, io_flags;
15773 
15774         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
15775 
15776         /*
15777          * Probe smp device, prevent the node of removed device from being
15778          * configured succesfully
15779          */
15780         if (mptsas_probe_smp(pdip, smp_node->m_addr.mta_wwn) != NDI_SUCCESS) {
15781                 return (DDI_FAILURE);
15782         }
15783 
15784         if ((*smp_dip = mptsas_find_smp_child(pdip, wwn_str)) != NULL) {
15785                 return (DDI_SUCCESS);
15786         }
15787 
15788         ndi_rtn = ndi_devi_alloc(pdip, "smp", DEVI_SID_NODEID, smp_dip);
15789 
15790         /*
15791          * if lun alloc success, set props
15792          */
15793         if (ndi_rtn == NDI_SUCCESS) {
15794                 /*
15795                  * Set the flavor of the child to be SMP flavored
15796                  */
15797                 ndi_flavor_set(*smp_dip, SCSA_FLAVOR_SMP);
15798 
15799                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15800                     *smp_dip, SMP_WWN, wwn_str) !=
15801                     DDI_PROP_SUCCESS) {
15802                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15803                             "property for smp device %s (sas_wwn)",
15804                             wwn_str);
15805                         ndi_rtn = NDI_FAILURE;
15806                         goto smp_create_done;
15807                 }
15808                 (void) sprintf(wwn_str, "w%"PRIx64, smp_node->m_addr.mta_wwn);
15809                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15810                     *smp_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str) !=
15811                     DDI_PROP_SUCCESS) {
15812                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15813                             "property for iport target-port %s (sas_wwn)",
15814                             wwn_str);
15815                         ndi_rtn = NDI_FAILURE;
15816                         goto smp_create_done;
15817                 }
15818 
15819                 mutex_enter(&mpt->m_mutex);
15820 
15821                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
15822                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | smp_node->m_devhdl;
15823                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
15824                     &dev_info);
15825                 if (rval != DDI_SUCCESS) {
15826                         mutex_exit(&mpt->m_mutex);
15827                         mptsas_log(mpt, CE_WARN,
15828                             "mptsas unable to get expander "
15829                             "parent device info for %x", page_address);
15830                         ndi_rtn = NDI_FAILURE;
15831                         goto smp_create_done;
15832                 }
15833 
15834                 smp_node->m_pdevhdl = dev_info.m_pdevhdl;
15835                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15836                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15837                     (uint32_t)dev_info.m_pdevhdl;
15838                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15839                     &dev_hdl, &sas_wwn, &smp_node->m_pdevinfo, &physport,
15840                     &phy_id, &pdev_hdl, &bay_num, &enclosure, &io_flags);
15841                 if (rval != DDI_SUCCESS) {
15842                         mutex_exit(&mpt->m_mutex);
15843                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
15844                             "device info for %x", page_address);
15845                         ndi_rtn = NDI_FAILURE;
15846                         goto smp_create_done;
15847                 }
15848 
15849                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15850                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15851                     (uint32_t)dev_info.m_devhdl;
15852                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15853                     &dev_hdl, &smp_sas_wwn, &smp_node->m_deviceinfo,
15854                     &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure,
15855                     &io_flags);
15856                 if (rval != DDI_SUCCESS) {
15857                         mutex_exit(&mpt->m_mutex);
15858                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
15859                             "device info for %x", page_address);
15860                         ndi_rtn = NDI_FAILURE;
15861                         goto smp_create_done;
15862                 }
15863                 mutex_exit(&mpt->m_mutex);
15864 
15865                 /*
15866                  * If this smp direct attached to the controller
15867                  * set the attached-port to the base wwid
15868                  */
15869                 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15870                     != DEVINFO_DIRECT_ATTACHED) {
15871                         (void) sprintf(attached_wwn_str, "w%016"PRIx64,
15872                             sas_wwn);
15873                 } else {
15874                         (void) sprintf(attached_wwn_str, "w%016"PRIx64,
15875                             mpt->un.m_base_wwid);
15876                 }
15877 
15878                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15879                     *smp_dip, SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwn_str) !=
15880                     DDI_PROP_SUCCESS) {
15881                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15882                             "property for smp attached-port %s (sas_wwn)",
15883                             attached_wwn_str);
15884                         ndi_rtn = NDI_FAILURE;
15885                         goto smp_create_done;
15886                 }
15887 
15888                 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
15889                     *smp_dip, SMP_PROP) != DDI_PROP_SUCCESS) {
15890                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15891                             "create property for SMP %s (SMP_PROP) ",
15892                             wwn_str);
15893                         ndi_rtn = NDI_FAILURE;
15894                         goto smp_create_done;
15895                 }
15896 
15897                 /*
15898                  * check the smp to see whether it direct
15899                  * attached to the controller
15900                  */
15901                 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15902                     != DEVINFO_DIRECT_ATTACHED) {
15903                         goto smp_create_done;
15904                 }
15905                 numphys = ddi_prop_get_int(DDI_DEV_T_ANY, pdip,
15906                     DDI_PROP_DONTPASS, MPTSAS_NUM_PHYS, -1);
15907                 if (numphys > 0) {
15908                         goto smp_create_done;
15909                 }
15910                 /*
15911                  * this iport is an old iport, we need to
15912                  * reconfig the props for it.
15913                  */
15914                 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
15915                     MPTSAS_VIRTUAL_PORT, 0) !=
15916                     DDI_PROP_SUCCESS) {
15917                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
15918                             MPTSAS_VIRTUAL_PORT);
15919                         mptsas_log(mpt, CE_WARN, "mptsas virtual port "
15920                             "prop update failed");
15921                         goto smp_create_done;
15922                 }
15923 
15924                 mutex_enter(&mpt->m_mutex);
15925                 numphys = 0;
15926                 iport = ddi_get_name_addr(pdip);
15927                 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15928                         bzero(phymask, sizeof (phymask));
15929                         (void) sprintf(phymask,
15930                             "%x", mpt->m_phy_info[i].phy_mask);
15931                         if (strcmp(phymask, iport) == 0) {
15932                                 phy_mask = mpt->m_phy_info[i].phy_mask;
15933                                 break;
15934                         }
15935                 }
15936 
15937                 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15938                         if ((phy_mask >> i) & 0x01) {
15939                                 numphys++;
15940                         }
15941                 }
15942                 /*
15943                  * Update PHY info for smhba
15944                  */
15945                 if (mptsas_smhba_phy_init(mpt)) {
15946                         mutex_exit(&mpt->m_mutex);
15947                         mptsas_log(mpt, CE_WARN, "mptsas phy update "
15948                             "failed");
15949                         goto smp_create_done;
15950                 }
15951                 mutex_exit(&mpt->m_mutex);
15952 
15953                 mptsas_smhba_set_all_phy_props(mpt, pdip, numphys, phy_mask,
15954                     &attached_devhdl);
15955 
15956                 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
15957                     MPTSAS_NUM_PHYS, numphys) !=
15958                     DDI_PROP_SUCCESS) {
15959                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
15960                             MPTSAS_NUM_PHYS);
15961                         mptsas_log(mpt, CE_WARN, "mptsas update "
15962                             "num phys props failed");
15963                         goto smp_create_done;
15964                 }
15965                 /*
15966                  * Add parent's props for SMHBA support
15967                  */
15968                 if (ddi_prop_update_string(DDI_DEV_T_NONE, pdip,
15969                     SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
15970                     DDI_PROP_SUCCESS) {
15971                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
15972                             SCSI_ADDR_PROP_ATTACHED_PORT);
15973                         mptsas_log(mpt, CE_WARN, "mptsas update iport"
15974                             "attached-port failed");
15975                         goto smp_create_done;
15976                 }
15977 
15978 smp_create_done:
15979                 /*
15980                  * If props were setup ok, online the lun
15981                  */
15982                 if (ndi_rtn == NDI_SUCCESS) {
15983                         /*
15984                          * Try to online the new node
15985                          */
15986                         ndi_rtn = ndi_devi_online(*smp_dip, NDI_ONLINE_ATTACH);
15987                 }
15988 
15989                 /*
15990                  * If success set rtn flag, else unwire alloc'd lun
15991                  */
15992                 if (ndi_rtn != NDI_SUCCESS) {
15993                         NDBG12(("mptsas unable to online "
15994                             "SMP target %s", wwn_str));
15995                         ndi_prop_remove_all(*smp_dip);
15996                         (void) ndi_devi_free(*smp_dip);
15997                 }
15998         }
15999 
16000         return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
16001 }
16002 
16003 /* smp transport routine */
16004 static int mptsas_smp_start(struct smp_pkt *smp_pkt)
16005 {
16006         uint64_t                        wwn;
16007         Mpi2SmpPassthroughRequest_t     req;
16008         Mpi2SmpPassthroughReply_t       rep;
16009         uint32_t                        direction = 0;
16010         mptsas_t                        *mpt;
16011         int                             ret;
16012         uint64_t                        tmp64;
16013 
16014         mpt = (mptsas_t *)smp_pkt->smp_pkt_address->
16015             smp_a_hba_tran->smp_tran_hba_private;
16016 
16017         bcopy(smp_pkt->smp_pkt_address->smp_a_wwn, &wwn, SAS_WWN_BYTE_SIZE);
16018         /*
16019          * Need to compose a SMP request message
16020          * and call mptsas_do_passthru() function
16021          */
16022         bzero(&req, sizeof (req));
16023         bzero(&rep, sizeof (rep));
16024         req.PassthroughFlags = 0;
16025         req.PhysicalPort = 0xff;
16026         req.ChainOffset = 0;
16027         req.Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
16028 
16029         if ((smp_pkt->smp_pkt_reqsize & 0xffff0000ul) != 0) {
16030                 smp_pkt->smp_pkt_reason = ERANGE;
16031                 return (DDI_FAILURE);
16032         }
16033         req.RequestDataLength = LE_16((uint16_t)(smp_pkt->smp_pkt_reqsize - 4));
16034 
16035         req.MsgFlags = 0;
16036         tmp64 = LE_64(wwn);
16037         bcopy(&tmp64, &req.SASAddress, SAS_WWN_BYTE_SIZE);
16038         if (smp_pkt->smp_pkt_rspsize > 0) {
16039                 direction |= MPTSAS_PASS_THRU_DIRECTION_READ;
16040         }
16041         if (smp_pkt->smp_pkt_reqsize > 0) {
16042                 direction |= MPTSAS_PASS_THRU_DIRECTION_WRITE;
16043         }
16044 
16045         mutex_enter(&mpt->m_mutex);
16046         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep,
16047             (uint8_t *)smp_pkt->smp_pkt_rsp,
16048             offsetof(Mpi2SmpPassthroughRequest_t, SGL), sizeof (rep),
16049             smp_pkt->smp_pkt_rspsize - 4, direction,
16050             (uint8_t *)smp_pkt->smp_pkt_req, smp_pkt->smp_pkt_reqsize - 4,
16051             smp_pkt->smp_pkt_timeout, FKIOCTL);
16052         mutex_exit(&mpt->m_mutex);
16053         if (ret != 0) {
16054                 cmn_err(CE_WARN, "smp_start do passthru error %d", ret);
16055                 smp_pkt->smp_pkt_reason = (uchar_t)(ret);
16056                 return (DDI_FAILURE);
16057         }
16058         /* do passthrough success, check the smp status */
16059         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
16060                 switch (LE_16(rep.IOCStatus)) {
16061                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
16062                         smp_pkt->smp_pkt_reason = ENODEV;
16063                         break;
16064                 case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
16065                         smp_pkt->smp_pkt_reason = EOVERFLOW;
16066                         break;
16067                 case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
16068                         smp_pkt->smp_pkt_reason = EIO;
16069                         break;
16070                 default:
16071                         mptsas_log(mpt, CE_NOTE, "smp_start: get unknown ioc"
16072                             "status:%x", LE_16(rep.IOCStatus));
16073                         smp_pkt->smp_pkt_reason = EIO;
16074                         break;
16075                 }
16076                 return (DDI_FAILURE);
16077         }
16078         if (rep.SASStatus != MPI2_SASSTATUS_SUCCESS) {
16079                 mptsas_log(mpt, CE_NOTE, "smp_start: get error SAS status:%x",
16080                     rep.SASStatus);
16081                 smp_pkt->smp_pkt_reason = EIO;
16082                 return (DDI_FAILURE);
16083         }
16084 
16085         return (DDI_SUCCESS);
16086 }
16087 
16088 /*
16089  * If we didn't get a match, we need to get sas page0 for each device, and
16090  * untill we get a match. If failed, return NULL
16091  */
16092 static mptsas_target_t *
16093 mptsas_phy_to_tgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint8_t phy)
16094 {
16095         int             i, j = 0;
16096         int             rval = 0;
16097         uint16_t        cur_handle;
16098         uint32_t        page_address;
16099         mptsas_target_t *ptgt = NULL;
16100 
16101         /*
16102          * PHY named device must be direct attached and attaches to
16103          * narrow port, if the iport is not parent of the device which
16104          * we are looking for.
16105          */
16106         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
16107                 if ((1 << i) & phymask)
16108                         j++;
16109         }
16110 
16111         if (j > 1)
16112                 return (NULL);
16113 
16114         /*
16115          * Must be a narrow port and single device attached to the narrow port
16116          * So the physical port num of device  which is equal to the iport's
16117          * port num is the device what we are looking for.
16118          */
16119 
16120         if (mpt->m_phy_info[phy].phy_mask != phymask)
16121                 return (NULL);
16122 
16123         mutex_enter(&mpt->m_mutex);
16124 
16125         ptgt = refhash_linear_search(mpt->m_targets, mptsas_target_eval_nowwn,
16126             &phy);
16127         if (ptgt != NULL) {
16128                 mutex_exit(&mpt->m_mutex);
16129                 return (ptgt);
16130         }
16131 
16132         if (mpt->m_done_traverse_dev) {
16133                 mutex_exit(&mpt->m_mutex);
16134                 return (NULL);
16135         }
16136 
16137         /* If didn't get a match, come here */
16138         cur_handle = mpt->m_dev_handle;
16139         for (; ; ) {
16140                 ptgt = NULL;
16141                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
16142                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)cur_handle;
16143                 rval = mptsas_get_target_device_info(mpt, page_address,
16144                     &cur_handle, &ptgt);
16145                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
16146                     (rval == DEV_INFO_FAIL_ALLOC)) {
16147                         break;
16148                 }
16149                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
16150                     (rval == DEV_INFO_PHYS_DISK)) {
16151                         continue;
16152                 }
16153                 mpt->m_dev_handle = cur_handle;
16154 
16155                 if ((ptgt->m_addr.mta_wwn == 0) && (ptgt->m_phynum == phy)) {
16156                         break;
16157                 }
16158         }
16159 
16160         mutex_exit(&mpt->m_mutex);
16161         return (ptgt);
16162 }
16163 
16164 /*
16165  * The ptgt->m_addr.mta_wwn contains the wwid for each disk.
16166  * For Raid volumes, we need to check m_raidvol[x].m_raidwwid
16167  * If we didn't get a match, we need to get sas page0 for each device, and
16168  * untill we get a match
16169  * If failed, return NULL
16170  */
16171 static mptsas_target_t *
16172 mptsas_wwid_to_ptgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
16173 {
16174         int             rval = 0;
16175         uint16_t        cur_handle;
16176         uint32_t        page_address;
16177         mptsas_target_t *tmp_tgt = NULL;
16178         mptsas_target_addr_t addr;
16179 
16180         addr.mta_wwn = wwid;
16181         addr.mta_phymask = phymask;
16182         mutex_enter(&mpt->m_mutex);
16183         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
16184         if (tmp_tgt != NULL) {
16185                 mutex_exit(&mpt->m_mutex);
16186                 return (tmp_tgt);
16187         }
16188 
16189         if (phymask == 0) {
16190                 /*
16191                  * It's IR volume
16192                  */
16193                 rval = mptsas_get_raid_info(mpt);
16194                 if (rval) {
16195                         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
16196                 }
16197                 mutex_exit(&mpt->m_mutex);
16198                 return (tmp_tgt);
16199         }
16200 
16201         if (mpt->m_done_traverse_dev) {
16202                 mutex_exit(&mpt->m_mutex);
16203                 return (NULL);
16204         }
16205 
16206         /* If didn't get a match, come here */
16207         cur_handle = mpt->m_dev_handle;
16208         for (;;) {
16209                 tmp_tgt = NULL;
16210                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
16211                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | cur_handle;
16212                 rval = mptsas_get_target_device_info(mpt, page_address,
16213                     &cur_handle, &tmp_tgt);
16214                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
16215                     (rval == DEV_INFO_FAIL_ALLOC)) {
16216                         tmp_tgt = NULL;
16217                         break;
16218                 }
16219                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
16220                     (rval == DEV_INFO_PHYS_DISK)) {
16221                         continue;
16222                 }
16223                 mpt->m_dev_handle = cur_handle;
16224                 if ((tmp_tgt->m_addr.mta_wwn) &&
16225                     (tmp_tgt->m_addr.mta_wwn == wwid) &&
16226                     (tmp_tgt->m_addr.mta_phymask == phymask)) {
16227                         break;
16228                 }
16229         }
16230 
16231         mutex_exit(&mpt->m_mutex);
16232         return (tmp_tgt);
16233 }
16234 
16235 static mptsas_smp_t *
16236 mptsas_wwid_to_psmp(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
16237 {
16238         int             rval = 0;
16239         uint16_t        cur_handle;
16240         uint32_t        page_address;
16241         mptsas_smp_t    smp_node, *psmp = NULL;
16242         mptsas_target_addr_t addr;
16243 
16244         addr.mta_wwn = wwid;
16245         addr.mta_phymask = phymask;
16246         mutex_enter(&mpt->m_mutex);
16247         psmp = refhash_lookup(mpt->m_smp_targets, &addr);
16248         if (psmp != NULL) {
16249                 mutex_exit(&mpt->m_mutex);
16250                 return (psmp);
16251         }
16252 
16253         if (mpt->m_done_traverse_smp) {
16254                 mutex_exit(&mpt->m_mutex);
16255                 return (NULL);
16256         }
16257 
16258         /* If didn't get a match, come here */
16259         cur_handle = mpt->m_smp_devhdl;
16260         for (;;) {
16261                 psmp = NULL;
16262                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
16263                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)cur_handle;
16264                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
16265                     &smp_node);
16266                 if (rval != DDI_SUCCESS) {
16267                         break;
16268                 }
16269                 mpt->m_smp_devhdl = cur_handle = smp_node.m_devhdl;
16270                 psmp = mptsas_smp_alloc(mpt, &smp_node);
16271                 ASSERT(psmp);
16272                 if ((psmp->m_addr.mta_wwn) && (psmp->m_addr.mta_wwn == wwid) &&
16273                     (psmp->m_addr.mta_phymask == phymask)) {
16274                         break;
16275                 }
16276         }
16277 
16278         mutex_exit(&mpt->m_mutex);
16279         return (psmp);
16280 }
16281 
16282 mptsas_target_t *
16283 mptsas_tgt_alloc(mptsas_t *mpt, uint16_t devhdl, uint64_t wwid,
16284     uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum)
16285 {
16286         mptsas_target_t *tmp_tgt = NULL;
16287         mptsas_target_addr_t addr;
16288 
16289         addr.mta_wwn = wwid;
16290         addr.mta_phymask = phymask;
16291         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
16292         if (tmp_tgt != NULL) {
16293                 NDBG20(("Hash item already exist"));
16294                 tmp_tgt->m_deviceinfo = devinfo;
16295                 tmp_tgt->m_devhdl = devhdl;  /* XXX - duplicate? */
16296                 return (tmp_tgt);
16297         }
16298         tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target), KM_SLEEP);
16299         if (tmp_tgt == NULL) {
16300                 cmn_err(CE_WARN, "Fatal, allocated tgt failed");
16301                 return (NULL);
16302         }
16303         tmp_tgt->m_devhdl = devhdl;
16304         tmp_tgt->m_addr.mta_wwn = wwid;
16305         tmp_tgt->m_deviceinfo = devinfo;
16306         tmp_tgt->m_addr.mta_phymask = phymask;
16307         tmp_tgt->m_phynum = phynum;
16308         /* Initialized the tgt structure */
16309         tmp_tgt->m_qfull_retries = QFULL_RETRIES;
16310         tmp_tgt->m_qfull_retry_interval =
16311             drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
16312         tmp_tgt->m_t_throttle = MAX_THROTTLE;
16313         TAILQ_INIT(&tmp_tgt->m_active_cmdq);
16314 
16315         refhash_insert(mpt->m_targets, tmp_tgt);
16316 
16317         return (tmp_tgt);
16318 }
16319 
16320 static void
16321 mptsas_smp_target_copy(mptsas_smp_t *src, mptsas_smp_t *dst)
16322 {
16323         dst->m_devhdl = src->m_devhdl;
16324         dst->m_deviceinfo = src->m_deviceinfo;
16325         dst->m_pdevhdl = src->m_pdevhdl;
16326         dst->m_pdevinfo = src->m_pdevinfo;
16327 }
16328 
16329 static mptsas_smp_t *
16330 mptsas_smp_alloc(mptsas_t *mpt, mptsas_smp_t *data)
16331 {
16332         mptsas_target_addr_t addr;
16333         mptsas_smp_t *ret_data;
16334 
16335         addr.mta_wwn = data->m_addr.mta_wwn;
16336         addr.mta_phymask = data->m_addr.mta_phymask;
16337         ret_data = refhash_lookup(mpt->m_smp_targets, &addr);
16338         /*
16339          * If there's already a matching SMP target, update its fields
16340          * in place.  Since the address is not changing, it's safe to do
16341          * this.  We cannot just bcopy() here because the structure we've
16342          * been given has invalid hash links.
16343          */
16344         if (ret_data != NULL) {
16345                 mptsas_smp_target_copy(data, ret_data);
16346                 return (ret_data);
16347         }
16348 
16349         ret_data = kmem_alloc(sizeof (mptsas_smp_t), KM_SLEEP);
16350         bcopy(data, ret_data, sizeof (mptsas_smp_t));
16351         refhash_insert(mpt->m_smp_targets, ret_data);
16352         return (ret_data);
16353 }
16354 
16355 /*
16356  * Functions for SGPIO LED support
16357  */
16358 static dev_info_t *
16359 mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask)
16360 {
16361         dev_info_t      *dip;
16362         int             prop;
16363         dip = e_ddi_hold_devi_by_dev(dev, 0);
16364         if (dip == NULL)
16365                 return (dip);
16366         prop = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
16367             "phymask", 0);
16368         *phymask = (mptsas_phymask_t)prop;
16369         ddi_release_devi(dip);
16370         return (dip);
16371 }
16372 static mptsas_target_t *
16373 mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
16374 {
16375         uint8_t                 phynum;
16376         uint64_t                wwn;
16377         int                     lun;
16378         mptsas_target_t         *ptgt = NULL;
16379 
16380         if (mptsas_parse_address(addr, &wwn, &phynum, &lun) != DDI_SUCCESS) {
16381                 return (NULL);
16382         }
16383         if (addr[0] == 'w') {
16384                 ptgt = mptsas_wwid_to_ptgt(mpt, (int)phymask, wwn);
16385         } else {
16386                 ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum);
16387         }
16388         return (ptgt);
16389 }
16390 
16391 static int
16392 mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt)
16393 {
16394         uint32_t slotstatus = 0;
16395 
16396         /* Build an MPI2 Slot Status based on our view of the world */
16397         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_IDENT - 1)))
16398                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST;
16399         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_FAIL - 1)))
16400                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT;
16401         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1)))
16402                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
16403 
16404         /* Write it to the controller */
16405         NDBG14(("mptsas_ioctl: set LED status %x for slot %x",
16406             slotstatus, ptgt->m_slot_num));
16407         return (mptsas_send_sep(mpt, ptgt, &slotstatus,
16408             MPI2_SEP_REQ_ACTION_WRITE_STATUS));
16409 }
16410 
16411 /*
16412  *  send sep request, use enclosure/slot addressing
16413  */
16414 static int
16415 mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
16416     uint32_t *status, uint8_t act)
16417 {
16418         Mpi2SepRequest_t        req;
16419         Mpi2SepReply_t          rep;
16420         int                     ret;
16421 
16422         ASSERT(mutex_owned(&mpt->m_mutex));
16423 
16424         /*
16425          * We only support SEP control of directly-attached targets, in which
16426          * case the "SEP" we're talking to is a virtual one contained within
16427          * the HBA itself.  This is necessary because DA targets typically have
16428          * no other mechanism for LED control.  Targets for which a separate
16429          * enclosure service processor exists should be controlled via ses(7d)
16430          * or sgen(7d).  Furthermore, since such requests can time out, they
16431          * should be made in user context rather than in response to
16432          * asynchronous fabric changes.
16433          *
16434          * In addition, we do not support this operation for RAID volumes,
16435          * since there is no slot associated with them.
16436          */
16437         if (!(ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED) ||
16438             ptgt->m_addr.mta_phymask == 0) {
16439                 return (ENOTTY);
16440         }
16441 
16442         bzero(&req, sizeof (req));
16443         bzero(&rep, sizeof (rep));
16444 
16445         req.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
16446         req.Action = act;
16447         req.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
16448         req.EnclosureHandle = LE_16(ptgt->m_enclosure);
16449         req.Slot = LE_16(ptgt->m_slot_num);
16450         if (act == MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
16451                 req.SlotStatus = LE_32(*status);
16452         }
16453         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
16454             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
16455         if (ret != 0) {
16456                 mptsas_log(mpt, CE_NOTE, "mptsas_send_sep: passthru SEP "
16457                     "Processor Request message error %d", ret);
16458                 return (ret);
16459         }
16460         /* do passthrough success, check the ioc status */
16461         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
16462                 mptsas_log(mpt, CE_NOTE, "send_sep act %x: ioc "
16463                     "status:%x loginfo %x", act, LE_16(rep.IOCStatus),
16464                     LE_32(rep.IOCLogInfo));
16465                 switch (LE_16(rep.IOCStatus) & MPI2_IOCSTATUS_MASK) {
16466                 case MPI2_IOCSTATUS_INVALID_FUNCTION:
16467                 case MPI2_IOCSTATUS_INVALID_VPID:
16468                 case MPI2_IOCSTATUS_INVALID_FIELD:
16469                 case MPI2_IOCSTATUS_INVALID_STATE:
16470                 case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
16471                 case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
16472                 case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
16473                 case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
16474                 case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
16475                 case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
16476                         return (EINVAL);
16477                 case MPI2_IOCSTATUS_BUSY:
16478                         return (EBUSY);
16479                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
16480                         return (EAGAIN);
16481                 case MPI2_IOCSTATUS_INVALID_SGL:
16482                 case MPI2_IOCSTATUS_INTERNAL_ERROR:
16483                 case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
16484                 default:
16485                         return (EIO);
16486                 }
16487         }
16488         if (act != MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
16489                 *status = LE_32(rep.SlotStatus);
16490         }
16491 
16492         return (0);
16493 }
16494 
16495 int
16496 mptsas_dma_addr_create(mptsas_t *mpt, ddi_dma_attr_t dma_attr,
16497     ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp, caddr_t *dma_memp,
16498     uint32_t alloc_size, ddi_dma_cookie_t *cookiep)
16499 {
16500         ddi_dma_cookie_t        new_cookie;
16501         size_t                  alloc_len;
16502         uint_t                  ncookie;
16503 
16504         if (cookiep == NULL)
16505                 cookiep = &new_cookie;
16506 
16507         if (ddi_dma_alloc_handle(mpt->m_dip, &dma_attr, DDI_DMA_SLEEP,
16508             NULL, dma_hdp) != DDI_SUCCESS) {
16509                 return (FALSE);
16510         }
16511 
16512         if (ddi_dma_mem_alloc(*dma_hdp, alloc_size, &mpt->m_dev_acc_attr,
16513             DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, dma_memp, &alloc_len,
16514             acc_hdp) != DDI_SUCCESS) {
16515                 ddi_dma_free_handle(dma_hdp);
16516                 *dma_hdp = NULL;
16517                 return (FALSE);
16518         }
16519 
16520         if (ddi_dma_addr_bind_handle(*dma_hdp, NULL, *dma_memp, alloc_len,
16521             (DDI_DMA_RDWR | DDI_DMA_CONSISTENT), DDI_DMA_SLEEP, NULL,
16522             cookiep, &ncookie) != DDI_DMA_MAPPED) {
16523                 (void) ddi_dma_mem_free(acc_hdp);
16524                 ddi_dma_free_handle(dma_hdp);
16525                 *dma_hdp = NULL;
16526                 return (FALSE);
16527         }
16528 
16529         return (TRUE);
16530 }
16531 
16532 void
16533 mptsas_dma_addr_destroy(ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp)
16534 {
16535         if (*dma_hdp == NULL)
16536                 return;
16537 
16538         (void) ddi_dma_unbind_handle(*dma_hdp);
16539         (void) ddi_dma_mem_free(acc_hdp);
16540         ddi_dma_free_handle(dma_hdp);
16541         *dma_hdp = NULL;
16542 }