1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  26  */
  27 
  28 /*
  29  * Copyright (c) 2000 to 2010, LSI Corporation.
  30  * All rights reserved.
  31  *
  32  * Redistribution and use in source and binary forms of all code within
  33  * this file that is exclusively owned by LSI, with or without
  34  * modification, is permitted provided that, in addition to the CDDL 1.0
  35  * License requirements, the following conditions are met:
  36  *
  37  *    Neither the name of the author nor the names of its contributors may be
  38  *    used to endorse or promote products derived from this software without
  39  *    specific prior written permission.
  40  *
  41  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  42  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  43  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  44  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  45  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  46  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  47  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  48  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  49  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  50  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  51  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  52  * DAMAGE.
  53  */
  54 
  55 /*
  56  * mptsas - This is a driver based on LSI Logic's MPT2.0 interface.
  57  *
  58  */
  59 
  60 #if defined(lint) || defined(DEBUG)
  61 #define MPTSAS_DEBUG
  62 #endif
  63 
  64 /*
  65  * standard header files.
  66  */
  67 #include <sys/note.h>
  68 #include <sys/scsi/scsi.h>
  69 #include <sys/pci.h>
  70 #include <sys/file.h>
  71 #include <sys/policy.h>
  72 #include <sys/model.h>
  73 #include <sys/sysevent.h>
  74 #include <sys/sysevent/eventdefs.h>
  75 #include <sys/sysevent/dr.h>
  76 #include <sys/sata/sata_defs.h>
  77 #include <sys/scsi/generic/sas.h>
  78 #include <sys/scsi/impl/scsi_sas.h>
  79 
  80 #pragma pack(1)
  81 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
  82 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
  83 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
  84 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
  85 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
  86 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
  87 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
  88 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
  89 #pragma pack()
  90 
  91 /*
  92  * private header files.
  93  *
  94  */
  95 #include <sys/scsi/impl/scsi_reset_notify.h>
  96 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
  97 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
  98 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
  99 #include <sys/scsi/adapters/mpt_sas/mptsas_hash.h>
 100 #include <sys/raidioctl.h>
 101 
 102 #include <sys/fs/dv_node.h>       /* devfs_clean */
 103 
 104 /*
 105  * FMA header files
 106  */
 107 #include <sys/ddifm.h>
 108 #include <sys/fm/protocol.h>
 109 #include <sys/fm/util.h>
 110 #include <sys/fm/io/ddi.h>
 111 
 112 /*
 113  * autoconfiguration data and routines.
 114  */
 115 static int mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
 116 static int mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
 117 static int mptsas_power(dev_info_t *dip, int component, int level);
 118 
 119 /*
 120  * cb_ops function
 121  */
 122 static int mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
 123         cred_t *credp, int *rval);
 124 #ifdef __sparc
 125 static int mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd);
 126 #else  /* __sparc */
 127 static int mptsas_quiesce(dev_info_t *devi);
 128 #endif  /* __sparc */
 129 
 130 /*
 131  * Resource initilaization for hardware
 132  */
 133 static void mptsas_setup_cmd_reg(mptsas_t *mpt);
 134 static void mptsas_disable_bus_master(mptsas_t *mpt);
 135 static void mptsas_hba_fini(mptsas_t *mpt);
 136 static void mptsas_cfg_fini(mptsas_t *mptsas_blkp);
 137 static int mptsas_hba_setup(mptsas_t *mpt);
 138 static void mptsas_hba_teardown(mptsas_t *mpt);
 139 static int mptsas_config_space_init(mptsas_t *mpt);
 140 static void mptsas_config_space_fini(mptsas_t *mpt);
 141 static void mptsas_iport_register(mptsas_t *mpt);
 142 static int mptsas_smp_setup(mptsas_t *mpt);
 143 static void mptsas_smp_teardown(mptsas_t *mpt);
 144 static int mptsas_cache_create(mptsas_t *mpt);
 145 static void mptsas_cache_destroy(mptsas_t *mpt);
 146 static int mptsas_alloc_request_frames(mptsas_t *mpt);
 147 static int mptsas_alloc_reply_frames(mptsas_t *mpt);
 148 static int mptsas_alloc_free_queue(mptsas_t *mpt);
 149 static int mptsas_alloc_post_queue(mptsas_t *mpt);
 150 static void mptsas_alloc_reply_args(mptsas_t *mpt);
 151 static int mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
 152 static void mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
 153 static int mptsas_init_chip(mptsas_t *mpt, int first_time);
 154 
 155 /*
 156  * SCSA function prototypes
 157  */
 158 static int mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
 159 static int mptsas_scsi_reset(struct scsi_address *ap, int level);
 160 static int mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
 161 static int mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly);
 162 static int mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value,
 163     int tgtonly);
 164 static void mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt);
 165 static struct scsi_pkt *mptsas_scsi_init_pkt(struct scsi_address *ap,
 166     struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen,
 167         int tgtlen, int flags, int (*callback)(), caddr_t arg);
 168 static void mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt);
 169 static void mptsas_scsi_destroy_pkt(struct scsi_address *ap,
 170     struct scsi_pkt *pkt);
 171 static int mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 172     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 173 static void mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 174     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 175 static int mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
 176     void (*callback)(caddr_t), caddr_t arg);
 177 static int mptsas_get_name(struct scsi_device *sd, char *name, int len);
 178 static int mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len);
 179 static int mptsas_scsi_quiesce(dev_info_t *dip);
 180 static int mptsas_scsi_unquiesce(dev_info_t *dip);
 181 static int mptsas_bus_config(dev_info_t *pdip, uint_t flags,
 182     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
 183 
 184 /*
 185  * SMP functions
 186  */
 187 static int mptsas_smp_start(struct smp_pkt *smp_pkt);
 188 
 189 /*
 190  * internal function prototypes.
 191  */
 192 static void mptsas_list_add(mptsas_t *mpt);
 193 static void mptsas_list_del(mptsas_t *mpt);
 194 
 195 static int mptsas_quiesce_bus(mptsas_t *mpt);
 196 static int mptsas_unquiesce_bus(mptsas_t *mpt);
 197 
 198 static int mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size);
 199 static void mptsas_free_handshake_msg(mptsas_t *mpt);
 200 
 201 static void mptsas_ncmds_checkdrain(void *arg);
 202 
 203 static int mptsas_prepare_pkt(mptsas_cmd_t *cmd);
 204 static int mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
 205 static int mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
 206 static void mptsas_accept_tx_waitq(mptsas_t *mpt);
 207 
 208 static int mptsas_do_detach(dev_info_t *dev);
 209 static int mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl);
 210 static int mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun,
 211     struct scsi_pkt *pkt);
 212 static int mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp);
 213 
 214 static void mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd);
 215 static void mptsas_handle_event(void *args);
 216 static int mptsas_handle_event_sync(void *args);
 217 static void mptsas_handle_dr(void *args);
 218 static void mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
 219     dev_info_t *pdip);
 220 
 221 static void mptsas_restart_cmd(void *);
 222 
 223 static void mptsas_flush_hba(mptsas_t *mpt);
 224 static void mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun,
 225         uint8_t tasktype);
 226 static void mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd,
 227     uchar_t reason, uint_t stat);
 228 
 229 static uint_t mptsas_intr(caddr_t arg1, caddr_t arg2);
 230 static void mptsas_process_intr(mptsas_t *mpt,
 231     pMpi2ReplyDescriptorsUnion_t reply_desc_union);
 232 static void mptsas_handle_scsi_io_success(mptsas_t *mpt,
 233     pMpi2ReplyDescriptorsUnion_t reply_desc);
 234 static void mptsas_handle_address_reply(mptsas_t *mpt,
 235     pMpi2ReplyDescriptorsUnion_t reply_desc);
 236 static int mptsas_wait_intr(mptsas_t *mpt, int polltime);
 237 static void mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd,
 238     uint32_t *control, pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl);
 239 
 240 static void mptsas_watch(void *arg);
 241 static void mptsas_watchsubr(mptsas_t *mpt);
 242 static void mptsas_cmd_timeout(mptsas_t *mpt, uint16_t devhdl);
 243 
 244 static void mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd);
 245 static int mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
 246     uint8_t *data, uint32_t request_size, uint32_t reply_size,
 247     uint32_t data_size, uint32_t direction, uint8_t *dataout,
 248     uint32_t dataout_size, short timeout, int mode);
 249 static int mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl);
 250 
 251 static uint8_t mptsas_get_fw_diag_buffer_number(mptsas_t *mpt,
 252     uint32_t unique_id);
 253 static void mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd);
 254 static int mptsas_post_fw_diag_buffer(mptsas_t *mpt,
 255     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
 256 static int mptsas_release_fw_diag_buffer(mptsas_t *mpt,
 257     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
 258     uint32_t diag_type);
 259 static int mptsas_diag_register(mptsas_t *mpt,
 260     mptsas_fw_diag_register_t *diag_register, uint32_t *return_code);
 261 static int mptsas_diag_unregister(mptsas_t *mpt,
 262     mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code);
 263 static int mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
 264     uint32_t *return_code);
 265 static int mptsas_diag_read_buffer(mptsas_t *mpt,
 266     mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
 267     uint32_t *return_code, int ioctl_mode);
 268 static int mptsas_diag_release(mptsas_t *mpt,
 269     mptsas_fw_diag_release_t *diag_release, uint32_t *return_code);
 270 static int mptsas_do_diag_action(mptsas_t *mpt, uint32_t action,
 271     uint8_t *diag_action, uint32_t length, uint32_t *return_code,
 272     int ioctl_mode);
 273 static int mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *data,
 274     int mode);
 275 
 276 static int mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
 277     int cmdlen, int tgtlen, int statuslen, int kf);
 278 static void mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd);
 279 
 280 static int mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags);
 281 static void mptsas_kmem_cache_destructor(void *buf, void *cdrarg);
 282 
 283 static int mptsas_cache_frames_constructor(void *buf, void *cdrarg,
 284     int kmflags);
 285 static void mptsas_cache_frames_destructor(void *buf, void *cdrarg);
 286 
 287 static void mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
 288     mptsas_cmd_t *cmd);
 289 static void mptsas_check_task_mgt(mptsas_t *mpt,
 290     pMpi2SCSIManagementReply_t reply, mptsas_cmd_t *cmd);
 291 static int mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
 292     mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
 293     int *resid);
 294 
 295 static int mptsas_alloc_active_slots(mptsas_t *mpt, int flag);
 296 static void mptsas_free_active_slots(mptsas_t *mpt);
 297 static int mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 298 
 299 static void mptsas_restart_hba(mptsas_t *mpt);
 300 static void mptsas_restart_waitq(mptsas_t *mpt);
 301 
 302 static void mptsas_deliver_doneq_thread(mptsas_t *mpt);
 303 static void mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd);
 304 static void mptsas_doneq_mv(mptsas_t *mpt, uint64_t t);
 305 
 306 static mptsas_cmd_t *mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t);
 307 static void mptsas_doneq_empty(mptsas_t *mpt);
 308 static void mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg);
 309 
 310 static mptsas_cmd_t *mptsas_waitq_rm(mptsas_t *mpt);
 311 static void mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
 312 static mptsas_cmd_t *mptsas_tx_waitq_rm(mptsas_t *mpt);
 313 static void mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
 314 
 315 
 316 static void mptsas_start_watch_reset_delay();
 317 static void mptsas_setup_bus_reset_delay(mptsas_t *mpt);
 318 static void mptsas_watch_reset_delay(void *arg);
 319 static int mptsas_watch_reset_delay_subr(mptsas_t *mpt);
 320 
 321 /*
 322  * helper functions
 323  */
 324 static void mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 325 
 326 static dev_info_t *mptsas_find_child(dev_info_t *pdip, char *name);
 327 static dev_info_t *mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy);
 328 static dev_info_t *mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr,
 329     int lun);
 330 static mdi_pathinfo_t *mptsas_find_path_addr(dev_info_t *pdip, uint64_t sasaddr,
 331     int lun);
 332 static mdi_pathinfo_t *mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy);
 333 static dev_info_t *mptsas_find_smp_child(dev_info_t *pdip, char *str_wwn);
 334 
 335 static int mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy,
 336     int *lun);
 337 static int mptsas_parse_smp_name(char *name, uint64_t *wwn);
 338 
 339 static mptsas_target_t *mptsas_phy_to_tgt(mptsas_t *mpt,
 340     mptsas_phymask_t phymask, uint8_t phy);
 341 static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt,
 342     mptsas_phymask_t phymask, uint64_t wwid);
 343 static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt,
 344     mptsas_phymask_t phymask, uint64_t wwid);
 345 
 346 static int mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun,
 347     uchar_t page, unsigned char *buf, int len, int *rlen, uchar_t evpd);
 348 
 349 static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
 350     uint16_t *handle, mptsas_target_t **pptgt);
 351 static void mptsas_update_phymask(mptsas_t *mpt);
 352 
 353 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
 354     uint32_t *status, uint8_t cmd);
 355 static dev_info_t *mptsas_get_dip_from_dev(dev_t dev,
 356     mptsas_phymask_t *phymask);
 357 static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr,
 358     mptsas_phymask_t phymask);
 359 static int mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt);
 360 
 361 
 362 /*
 363  * Enumeration / DR functions
 364  */
 365 static void mptsas_config_all(dev_info_t *pdip);
 366 static int mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
 367     dev_info_t **lundip);
 368 static int mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
 369     dev_info_t **lundip);
 370 
 371 static int mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt);
 372 static int mptsas_offline_target(dev_info_t *pdip, char *name);
 373 
 374 static int mptsas_config_raid(dev_info_t *pdip, uint16_t target,
 375     dev_info_t **dip);
 376 
 377 static int mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt);
 378 static int mptsas_probe_lun(dev_info_t *pdip, int lun,
 379     dev_info_t **dip, mptsas_target_t *ptgt);
 380 
 381 static int mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
 382     dev_info_t **dip, mptsas_target_t *ptgt, int lun);
 383 
 384 static int mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
 385     char *guid, dev_info_t **dip, mptsas_target_t *ptgt, int lun);
 386 static int mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
 387     char *guid, dev_info_t **dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt,
 388     int lun);
 389 
 390 static void mptsas_offline_missed_luns(dev_info_t *pdip,
 391     uint16_t *repluns, int lun_cnt, mptsas_target_t *ptgt);
 392 static int mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
 393     mdi_pathinfo_t *rpip, uint_t flags);
 394 
 395 static int mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn,
 396     dev_info_t **smp_dip);
 397 static int mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 398     uint_t flags);
 399 
 400 static int mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data,
 401     int mode, int *rval);
 402 static int mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data,
 403     int mode, int *rval);
 404 static int mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data,
 405     int mode, int *rval);
 406 static void mptsas_record_event(void *args);
 407 static int mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data,
 408     int mode);
 409 
 410 mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t, uint64_t,
 411     uint32_t, mptsas_phymask_t, uint8_t);
 412 static mptsas_smp_t *mptsas_smp_alloc(mptsas_t *, mptsas_smp_t *);
 413 static int mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 414     dev_info_t **smp_dip);
 415 
 416 /*
 417  * Power management functions
 418  */
 419 static int mptsas_get_pci_cap(mptsas_t *mpt);
 420 static int mptsas_init_pm(mptsas_t *mpt);
 421 
 422 /*
 423  * MPT MSI tunable:
 424  *
 425  * By default MSI is enabled on all supported platforms.
 426  */
 427 boolean_t mptsas_enable_msi = B_TRUE;
 428 boolean_t mptsas_physical_bind_failed_page_83 = B_FALSE;
 429 
 430 static int mptsas_register_intrs(mptsas_t *);
 431 static void mptsas_unregister_intrs(mptsas_t *);
 432 static int mptsas_add_intrs(mptsas_t *, int);
 433 static void mptsas_rem_intrs(mptsas_t *);
 434 
 435 /*
 436  * FMA Prototypes
 437  */
 438 static void mptsas_fm_init(mptsas_t *mpt);
 439 static void mptsas_fm_fini(mptsas_t *mpt);
 440 static int mptsas_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *);
 441 
 442 extern pri_t minclsyspri, maxclsyspri;
 443 
 444 /*
 445  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).  It is
 446  * under this device that the paths to a physical device are created when
 447  * MPxIO is used.
 448  */
 449 extern dev_info_t       *scsi_vhci_dip;
 450 
 451 /*
 452  * Tunable timeout value for Inquiry VPD page 0x83
 453  * By default the value is 30 seconds.
 454  */
 455 int mptsas_inq83_retry_timeout = 30;
 456 
 457 /*
 458  * This is used to allocate memory for message frame storage, not for
 459  * data I/O DMA. All message frames must be stored in the first 4G of
 460  * physical memory.
 461  */
 462 ddi_dma_attr_t mptsas_dma_attrs = {
 463         DMA_ATTR_V0,    /* attribute layout version             */
 464         0x0ull,         /* address low - should be 0 (longlong) */
 465         0xffffffffull,  /* address high - 32-bit max range      */
 466         0x00ffffffull,  /* count max - max DMA object size      */
 467         4,              /* allocation alignment requirements    */
 468         0x78,           /* burstsizes - binary encoded values   */
 469         1,              /* minxfer - gran. of DMA engine        */
 470         0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 471         0xffffffffull,  /* max segment size (DMA boundary)      */
 472         MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 473         512,            /* granularity - device transfer size   */
 474         0               /* flags, set to 0                      */
 475 };
 476 
 477 /*
 478  * This is used for data I/O DMA memory allocation. (full 64-bit DMA
 479  * physical addresses are supported.)
 480  */
 481 ddi_dma_attr_t mptsas_dma_attrs64 = {
 482         DMA_ATTR_V0,    /* attribute layout version             */
 483         0x0ull,         /* address low - should be 0 (longlong) */
 484         0xffffffffffffffffull,  /* address high - 64-bit max    */
 485         0x00ffffffull,  /* count max - max DMA object size      */
 486         4,              /* allocation alignment requirements    */
 487         0x78,           /* burstsizes - binary encoded values   */
 488         1,              /* minxfer - gran. of DMA engine        */
 489         0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 490         0xffffffffull,  /* max segment size (DMA boundary)      */
 491         MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 492         512,            /* granularity - device transfer size   */
 493         DDI_DMA_RELAXED_ORDERING        /* flags, enable relaxed ordering */
 494 };
 495 
 496 ddi_device_acc_attr_t mptsas_dev_attr = {
 497         DDI_DEVICE_ATTR_V1,
 498         DDI_STRUCTURE_LE_ACC,
 499         DDI_STRICTORDER_ACC,
 500         DDI_DEFAULT_ACC
 501 };
 502 
 503 static struct cb_ops mptsas_cb_ops = {
 504         scsi_hba_open,          /* open */
 505         scsi_hba_close,         /* close */
 506         nodev,                  /* strategy */
 507         nodev,                  /* print */
 508         nodev,                  /* dump */
 509         nodev,                  /* read */
 510         nodev,                  /* write */
 511         mptsas_ioctl,           /* ioctl */
 512         nodev,                  /* devmap */
 513         nodev,                  /* mmap */
 514         nodev,                  /* segmap */
 515         nochpoll,               /* chpoll */
 516         ddi_prop_op,            /* cb_prop_op */
 517         NULL,                   /* streamtab */
 518         D_MP,                   /* cb_flag */
 519         CB_REV,                 /* rev */
 520         nodev,                  /* aread */
 521         nodev                   /* awrite */
 522 };
 523 
 524 static struct dev_ops mptsas_ops = {
 525         DEVO_REV,               /* devo_rev, */
 526         0,                      /* refcnt  */
 527         ddi_no_info,            /* info */
 528         nulldev,                /* identify */
 529         nulldev,                /* probe */
 530         mptsas_attach,          /* attach */
 531         mptsas_detach,          /* detach */
 532 #ifdef  __sparc
 533         mptsas_reset,
 534 #else
 535         nodev,                  /* reset */
 536 #endif  /* __sparc */
 537         &mptsas_cb_ops,             /* driver operations */
 538         NULL,                   /* bus operations */
 539         mptsas_power,           /* power management */
 540 #ifdef  __sparc
 541         ddi_quiesce_not_needed
 542 #else
 543         mptsas_quiesce          /* quiesce */
 544 #endif  /* __sparc */
 545 };
 546 
 547 
 548 #define MPTSAS_MOD_STRING "MPTSAS HBA Driver 00.00.00.24"
 549 
 550 static struct modldrv modldrv = {
 551         &mod_driverops,     /* Type of module. This one is a driver */
 552         MPTSAS_MOD_STRING, /* Name of the module. */
 553         &mptsas_ops,        /* driver ops */
 554 };
 555 
 556 static struct modlinkage modlinkage = {
 557         MODREV_1, &modldrv, NULL
 558 };
 559 #define TARGET_PROP     "target"
 560 #define LUN_PROP        "lun"
 561 #define LUN64_PROP      "lun64"
 562 #define SAS_PROP        "sas-mpt"
 563 #define MDI_GUID        "wwn"
 564 #define NDI_GUID        "guid"
 565 #define MPTSAS_DEV_GONE "mptsas_dev_gone"
 566 
 567 /*
 568  * Local static data
 569  */
 570 #if defined(MPTSAS_DEBUG)
 571 uint32_t mptsas_debug_flags = 0;
 572 #endif  /* defined(MPTSAS_DEBUG) */
 573 uint32_t mptsas_debug_resets = 0;
 574 
 575 static kmutex_t         mptsas_global_mutex;
 576 static void             *mptsas_state;          /* soft state ptr */
 577 static krwlock_t        mptsas_global_rwlock;
 578 
 579 static kmutex_t         mptsas_log_mutex;
 580 static char             mptsas_log_buf[256];
 581 _NOTE(MUTEX_PROTECTS_DATA(mptsas_log_mutex, mptsas_log_buf))
 582 
 583 static mptsas_t *mptsas_head, *mptsas_tail;
 584 static clock_t mptsas_scsi_watchdog_tick;
 585 static clock_t mptsas_tick;
 586 static timeout_id_t mptsas_reset_watch;
 587 static timeout_id_t mptsas_timeout_id;
 588 static int mptsas_timeouts_enabled = 0;
 589 /*
 590  * warlock directives
 591  */
 592 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt \
 593         mptsas_cmd NcrTableIndirect buf scsi_cdb scsi_status))
 594 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", smp_pkt))
 595 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
 596 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mptsas_tgt_private))
 597 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_hba_tran::tran_tgt_private))
 598 
 599 /*
 600  * SM - HBA statics
 601  */
 602 char    *mptsas_driver_rev = MPTSAS_MOD_STRING;
 603 
 604 #ifdef MPTSAS_DEBUG
 605 void debug_enter(char *);
 606 #endif
 607 
 608 /*
 609  * Notes:
 610  *      - scsi_hba_init(9F) initializes SCSI HBA modules
 611  *      - must call scsi_hba_fini(9F) if modload() fails
 612  */
 613 int
 614 _init(void)
 615 {
 616         int status;
 617         /* CONSTCOND */
 618         ASSERT(NO_COMPETING_THREADS);
 619 
 620         NDBG0(("_init"));
 621 
 622         status = ddi_soft_state_init(&mptsas_state, MPTSAS_SIZE,
 623             MPTSAS_INITIAL_SOFT_SPACE);
 624         if (status != 0) {
 625                 return (status);
 626         }
 627 
 628         if ((status = scsi_hba_init(&modlinkage)) != 0) {
 629                 ddi_soft_state_fini(&mptsas_state);
 630                 return (status);
 631         }
 632 
 633         mutex_init(&mptsas_global_mutex, NULL, MUTEX_DRIVER, NULL);
 634         rw_init(&mptsas_global_rwlock, NULL, RW_DRIVER, NULL);
 635         mutex_init(&mptsas_log_mutex, NULL, MUTEX_DRIVER, NULL);
 636 
 637         if ((status = mod_install(&modlinkage)) != 0) {
 638                 mutex_destroy(&mptsas_log_mutex);
 639                 rw_destroy(&mptsas_global_rwlock);
 640                 mutex_destroy(&mptsas_global_mutex);
 641                 ddi_soft_state_fini(&mptsas_state);
 642                 scsi_hba_fini(&modlinkage);
 643         }
 644 
 645         return (status);
 646 }
 647 
 648 /*
 649  * Notes:
 650  *      - scsi_hba_fini(9F) uninitializes SCSI HBA modules
 651  */
 652 int
 653 _fini(void)
 654 {
 655         int     status;
 656         /* CONSTCOND */
 657         ASSERT(NO_COMPETING_THREADS);
 658 
 659         NDBG0(("_fini"));
 660 
 661         if ((status = mod_remove(&modlinkage)) == 0) {
 662                 ddi_soft_state_fini(&mptsas_state);
 663                 scsi_hba_fini(&modlinkage);
 664                 mutex_destroy(&mptsas_global_mutex);
 665                 rw_destroy(&mptsas_global_rwlock);
 666                 mutex_destroy(&mptsas_log_mutex);
 667         }
 668         return (status);
 669 }
 670 
 671 /*
 672  * The loadable-module _info(9E) entry point
 673  */
 674 int
 675 _info(struct modinfo *modinfop)
 676 {
 677         /* CONSTCOND */
 678         ASSERT(NO_COMPETING_THREADS);
 679         NDBG0(("mptsas _info"));
 680 
 681         return (mod_info(&modlinkage, modinfop));
 682 }
 683 
 684 static int
 685 mptsas_target_eval_devhdl(const void *op, void *arg)
 686 {
 687         uint16_t dh = *(uint16_t *)arg;
 688         const mptsas_target_t *tp = op;
 689 
 690         return ((int)tp->m_devhdl - (int)dh);
 691 }
 692 
 693 static int
 694 mptsas_target_eval_slot(const void *op, void *arg)
 695 {
 696         mptsas_led_control_t *lcp = arg;
 697         const mptsas_target_t *tp = op;
 698 
 699         if (tp->m_enclosure != lcp->Enclosure)
 700                 return ((int)tp->m_enclosure - (int)lcp->Enclosure);
 701 
 702         return ((int)tp->m_slot_num - (int)lcp->Slot);
 703 }
 704 
 705 static int
 706 mptsas_target_eval_nowwn(const void *op, void *arg)
 707 {
 708         uint8_t phy = *(uint8_t *)arg;
 709         const mptsas_target_t *tp = op;
 710 
 711         if (tp->m_addr.mta_wwn != 0)
 712                 return (-1);
 713 
 714         return ((int)tp->m_phynum - (int)phy);
 715 }
 716 
 717 static int
 718 mptsas_smp_eval_devhdl(const void *op, void *arg)
 719 {
 720         uint16_t dh = *(uint16_t *)arg;
 721         const mptsas_smp_t *sp = op;
 722 
 723         return ((int)sp->m_devhdl - (int)dh);
 724 }
 725 
 726 static uint64_t
 727 mptsas_target_addr_hash(const void *tp)
 728 {
 729         const mptsas_target_addr_t *tap = tp;
 730 
 731         return ((tap->mta_wwn & 0xffffffffffffULL) |
 732             ((uint64_t)tap->mta_phymask << 48));
 733 }
 734 
 735 static int
 736 mptsas_target_addr_cmp(const void *a, const void *b)
 737 {
 738         const mptsas_target_addr_t *aap = a;
 739         const mptsas_target_addr_t *bap = b;
 740 
 741         if (aap->mta_wwn < bap->mta_wwn)
 742                 return (-1);
 743         if (aap->mta_wwn > bap->mta_wwn)
 744                 return (1);
 745         return ((int)bap->mta_phymask - (int)aap->mta_phymask);
 746 }
 747 
 748 static void
 749 mptsas_target_free(void *op)
 750 {
 751         kmem_free(op, sizeof (mptsas_target_t));
 752 }
 753 
 754 static void
 755 mptsas_smp_free(void *op)
 756 {
 757         kmem_free(op, sizeof (mptsas_smp_t));
 758 }
 759 
 760 static void
 761 mptsas_destroy_hashes(mptsas_t *mpt)
 762 {
 763         mptsas_target_t *tp;
 764         mptsas_smp_t *sp;
 765 
 766         for (tp = refhash_first(mpt->m_targets); tp != NULL;
 767             tp = refhash_next(mpt->m_targets, tp)) {
 768                 refhash_remove(mpt->m_targets, tp);
 769         }
 770         for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
 771             sp = refhash_next(mpt->m_smp_targets, sp)) {
 772                 refhash_remove(mpt->m_smp_targets, sp);
 773         }
 774         refhash_destroy(mpt->m_targets);
 775         refhash_destroy(mpt->m_smp_targets);
 776         mpt->m_targets = NULL;
 777         mpt->m_smp_targets = NULL;
 778 }
 779 
 780 static int
 781 mptsas_iport_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 782 {
 783         dev_info_t              *pdip;
 784         mptsas_t                *mpt;
 785         scsi_hba_tran_t         *hba_tran;
 786         char                    *iport = NULL;
 787         char                    phymask[MPTSAS_MAX_PHYS];
 788         mptsas_phymask_t        phy_mask = 0;
 789         int                     dynamic_port = 0;
 790         uint32_t                page_address;
 791         char                    initiator_wwnstr[MPTSAS_WWN_STRLEN];
 792         int                     rval = DDI_FAILURE;
 793         int                     i = 0;
 794         uint8_t                 numphys = 0;
 795         uint8_t                 phy_id;
 796         uint8_t                 phy_port = 0;
 797         uint16_t                attached_devhdl = 0;
 798         uint32_t                dev_info;
 799         uint64_t                attached_sas_wwn;
 800         uint16_t                dev_hdl;
 801         uint16_t                pdev_hdl;
 802         uint16_t                bay_num, enclosure;
 803         char                    attached_wwnstr[MPTSAS_WWN_STRLEN];
 804 
 805         /* CONSTCOND */
 806         ASSERT(NO_COMPETING_THREADS);
 807 
 808         switch (cmd) {
 809         case DDI_ATTACH:
 810                 break;
 811 
 812         case DDI_RESUME:
 813                 /*
 814                  * If this a scsi-iport node, nothing to do here.
 815                  */
 816                 return (DDI_SUCCESS);
 817 
 818         default:
 819                 return (DDI_FAILURE);
 820         }
 821 
 822         pdip = ddi_get_parent(dip);
 823 
 824         if ((hba_tran = ndi_flavorv_get(pdip, SCSA_FLAVOR_SCSI_DEVICE)) ==
 825             NULL) {
 826                 cmn_err(CE_WARN, "Failed attach iport because fail to "
 827                     "get tran vector for the HBA node");
 828                 return (DDI_FAILURE);
 829         }
 830 
 831         mpt = TRAN2MPT(hba_tran);
 832         ASSERT(mpt != NULL);
 833         if (mpt == NULL)
 834                 return (DDI_FAILURE);
 835 
 836         if ((hba_tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) ==
 837             NULL) {
 838                 mptsas_log(mpt, CE_WARN, "Failed attach iport because fail to "
 839                     "get tran vector for the iport node");
 840                 return (DDI_FAILURE);
 841         }
 842 
 843         /*
 844          * Overwrite parent's tran_hba_private to iport's tran vector
 845          */
 846         hba_tran->tran_hba_private = mpt;
 847 
 848         ddi_report_dev(dip);
 849 
 850         /*
 851          * Get SAS address for initiator port according dev_handle
 852          */
 853         iport = ddi_get_name_addr(dip);
 854         if (iport && strncmp(iport, "v0", 2) == 0) {
 855                 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 856                     MPTSAS_VIRTUAL_PORT, 1) !=
 857                     DDI_PROP_SUCCESS) {
 858                         (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
 859                             MPTSAS_VIRTUAL_PORT);
 860                         mptsas_log(mpt, CE_WARN, "mptsas virtual port "
 861                             "prop update failed");
 862                         return (DDI_FAILURE);
 863                 }
 864                 return (DDI_SUCCESS);
 865         }
 866 
 867         mutex_enter(&mpt->m_mutex);
 868         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 869                 bzero(phymask, sizeof (phymask));
 870                 (void) sprintf(phymask,
 871                     "%x", mpt->m_phy_info[i].phy_mask);
 872                 if (strcmp(phymask, iport) == 0) {
 873                         break;
 874                 }
 875         }
 876 
 877         if (i == MPTSAS_MAX_PHYS) {
 878                 mptsas_log(mpt, CE_WARN, "Failed attach port %s because port"
 879                     "seems not exist", iport);
 880                 mutex_exit(&mpt->m_mutex);
 881                 return (DDI_FAILURE);
 882         }
 883 
 884         phy_mask = mpt->m_phy_info[i].phy_mask;
 885 
 886         if (mpt->m_phy_info[i].port_flags & AUTO_PORT_CONFIGURATION)
 887                 dynamic_port = 1;
 888         else
 889                 dynamic_port = 0;
 890 
 891         /*
 892          * Update PHY info for smhba
 893          */
 894         if (mptsas_smhba_phy_init(mpt)) {
 895                 mutex_exit(&mpt->m_mutex);
 896                 mptsas_log(mpt, CE_WARN, "mptsas phy update "
 897                     "failed");
 898                 return (DDI_FAILURE);
 899         }
 900 
 901         mutex_exit(&mpt->m_mutex);
 902 
 903         numphys = 0;
 904         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 905                 if ((phy_mask >> i) & 0x01) {
 906                         numphys++;
 907                 }
 908         }
 909 
 910         bzero(initiator_wwnstr, sizeof (initiator_wwnstr));
 911         (void) sprintf(initiator_wwnstr, "w%016"PRIx64,
 912             mpt->un.m_base_wwid);
 913 
 914         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
 915             SCSI_ADDR_PROP_INITIATOR_PORT, initiator_wwnstr) !=
 916             DDI_PROP_SUCCESS) {
 917                 (void) ddi_prop_remove(DDI_DEV_T_NONE,
 918                     dip, SCSI_ADDR_PROP_INITIATOR_PORT);
 919                 mptsas_log(mpt, CE_WARN, "mptsas Initiator port "
 920                     "prop update failed");
 921                 return (DDI_FAILURE);
 922         }
 923         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 924             MPTSAS_NUM_PHYS, numphys) !=
 925             DDI_PROP_SUCCESS) {
 926                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, MPTSAS_NUM_PHYS);
 927                 return (DDI_FAILURE);
 928         }
 929 
 930         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 931             "phymask", phy_mask) !=
 932             DDI_PROP_SUCCESS) {
 933                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "phymask");
 934                 mptsas_log(mpt, CE_WARN, "mptsas phy mask "
 935                     "prop update failed");
 936                 return (DDI_FAILURE);
 937         }
 938 
 939         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 940             "dynamic-port", dynamic_port) !=
 941             DDI_PROP_SUCCESS) {
 942                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "dynamic-port");
 943                 mptsas_log(mpt, CE_WARN, "mptsas dynamic port "
 944                     "prop update failed");
 945                 return (DDI_FAILURE);
 946         }
 947         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 948             MPTSAS_VIRTUAL_PORT, 0) !=
 949             DDI_PROP_SUCCESS) {
 950                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
 951                     MPTSAS_VIRTUAL_PORT);
 952                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
 953                     "prop update failed");
 954                 return (DDI_FAILURE);
 955         }
 956         mptsas_smhba_set_all_phy_props(mpt, dip, numphys, phy_mask,
 957             &attached_devhdl);
 958 
 959         mutex_enter(&mpt->m_mutex);
 960         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
 961             MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)attached_devhdl;
 962         rval = mptsas_get_sas_device_page0(mpt, page_address, &dev_hdl,
 963             &attached_sas_wwn, &dev_info, &phy_port, &phy_id,
 964             &pdev_hdl, &bay_num, &enclosure);
 965         if (rval != DDI_SUCCESS) {
 966                 mptsas_log(mpt, CE_WARN,
 967                     "Failed to get device page0 for handle:%d",
 968                     attached_devhdl);
 969                 mutex_exit(&mpt->m_mutex);
 970                 return (DDI_FAILURE);
 971         }
 972 
 973         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 974                 bzero(phymask, sizeof (phymask));
 975                 (void) sprintf(phymask, "%x", mpt->m_phy_info[i].phy_mask);
 976                 if (strcmp(phymask, iport) == 0) {
 977                         (void) sprintf(&mpt->m_phy_info[i].smhba_info.path[0],
 978                             "%x",
 979                             mpt->m_phy_info[i].phy_mask);
 980                 }
 981         }
 982         mutex_exit(&mpt->m_mutex);
 983 
 984         bzero(attached_wwnstr, sizeof (attached_wwnstr));
 985         (void) sprintf(attached_wwnstr, "w%016"PRIx64,
 986             attached_sas_wwn);
 987         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
 988             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
 989             DDI_PROP_SUCCESS) {
 990                 (void) ddi_prop_remove(DDI_DEV_T_NONE,
 991                     dip, SCSI_ADDR_PROP_ATTACHED_PORT);
 992                 return (DDI_FAILURE);
 993         }
 994 
 995         /* Create kstats for each phy on this iport */
 996 
 997         mptsas_create_phy_stats(mpt, iport, dip);
 998 
 999         /*
1000          * register sas hba iport with mdi (MPxIO/vhci)
1001          */
1002         if (mdi_phci_register(MDI_HCI_CLASS_SCSI,
1003             dip, 0) == MDI_SUCCESS) {
1004                 mpt->m_mpxio_enable = TRUE;
1005         }
1006         return (DDI_SUCCESS);
1007 }
1008 
1009 /*
1010  * Notes:
1011  *      Set up all device state and allocate data structures,
1012  *      mutexes, condition variables, etc. for device operation.
1013  *      Add interrupts needed.
1014  *      Return DDI_SUCCESS if device is ready, else return DDI_FAILURE.
1015  */
1016 static int
1017 mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1018 {
1019         mptsas_t                *mpt = NULL;
1020         int                     instance, i, j;
1021         int                     doneq_thread_num;
1022         char                    intr_added = 0;
1023         char                    map_setup = 0;
1024         char                    config_setup = 0;
1025         char                    hba_attach_setup = 0;
1026         char                    smp_attach_setup = 0;
1027         char                    mutex_init_done = 0;
1028         char                    event_taskq_create = 0;
1029         char                    dr_taskq_create = 0;
1030         char                    doneq_thread_create = 0;
1031         scsi_hba_tran_t         *hba_tran;
1032         uint_t                  mem_bar = MEM_SPACE;
1033         int                     rval = DDI_FAILURE;
1034 
1035         /* CONSTCOND */
1036         ASSERT(NO_COMPETING_THREADS);
1037 
1038         if (scsi_hba_iport_unit_address(dip)) {
1039                 return (mptsas_iport_attach(dip, cmd));
1040         }
1041 
1042         switch (cmd) {
1043         case DDI_ATTACH:
1044                 break;
1045 
1046         case DDI_RESUME:
1047                 if ((hba_tran = ddi_get_driver_private(dip)) == NULL)
1048                         return (DDI_FAILURE);
1049 
1050                 mpt = TRAN2MPT(hba_tran);
1051 
1052                 if (!mpt) {
1053                         return (DDI_FAILURE);
1054                 }
1055 
1056                 /*
1057                  * Reset hardware and softc to "no outstanding commands"
1058                  * Note that a check condition can result on first command
1059                  * to a target.
1060                  */
1061                 mutex_enter(&mpt->m_mutex);
1062 
1063                 /*
1064                  * raise power.
1065                  */
1066                 if (mpt->m_options & MPTSAS_OPT_PM) {
1067                         mutex_exit(&mpt->m_mutex);
1068                         (void) pm_busy_component(dip, 0);
1069                         rval = pm_power_has_changed(dip, 0, PM_LEVEL_D0);
1070                         if (rval == DDI_SUCCESS) {
1071                                 mutex_enter(&mpt->m_mutex);
1072                         } else {
1073                                 /*
1074                                  * The pm_raise_power() call above failed,
1075                                  * and that can only occur if we were unable
1076                                  * to reset the hardware.  This is probably
1077                                  * due to unhealty hardware, and because
1078                                  * important filesystems(such as the root
1079                                  * filesystem) could be on the attached disks,
1080                                  * it would not be a good idea to continue,
1081                                  * as we won't be entirely certain we are
1082                                  * writing correct data.  So we panic() here
1083                                  * to not only prevent possible data corruption,
1084                                  * but to give developers or end users a hope
1085                                  * of identifying and correcting any problems.
1086                                  */
1087                                 fm_panic("mptsas could not reset hardware "
1088                                     "during resume");
1089                         }
1090                 }
1091 
1092                 mpt->m_suspended = 0;
1093 
1094                 /*
1095                  * Reinitialize ioc
1096                  */
1097                 mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1098                 if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
1099                         mutex_exit(&mpt->m_mutex);
1100                         if (mpt->m_options & MPTSAS_OPT_PM) {
1101                                 (void) pm_idle_component(dip, 0);
1102                         }
1103                         fm_panic("mptsas init chip fail during resume");
1104                 }
1105                 /*
1106                  * mptsas_update_driver_data needs interrupts so enable them
1107                  * first.
1108                  */
1109                 MPTSAS_ENABLE_INTR(mpt);
1110                 mptsas_update_driver_data(mpt);
1111 
1112                 /* start requests, if possible */
1113                 mptsas_restart_hba(mpt);
1114 
1115                 mutex_exit(&mpt->m_mutex);
1116 
1117                 /*
1118                  * Restart watch thread
1119                  */
1120                 mutex_enter(&mptsas_global_mutex);
1121                 if (mptsas_timeout_id == 0) {
1122                         mptsas_timeout_id = timeout(mptsas_watch, NULL,
1123                             mptsas_tick);
1124                         mptsas_timeouts_enabled = 1;
1125                 }
1126                 mutex_exit(&mptsas_global_mutex);
1127 
1128                 /* report idle status to pm framework */
1129                 if (mpt->m_options & MPTSAS_OPT_PM) {
1130                         (void) pm_idle_component(dip, 0);
1131                 }
1132 
1133                 return (DDI_SUCCESS);
1134 
1135         default:
1136                 return (DDI_FAILURE);
1137 
1138         }
1139 
1140         instance = ddi_get_instance(dip);
1141 
1142         /*
1143          * Allocate softc information.
1144          */
1145         if (ddi_soft_state_zalloc(mptsas_state, instance) != DDI_SUCCESS) {
1146                 mptsas_log(NULL, CE_WARN,
1147                     "mptsas%d: cannot allocate soft state", instance);
1148                 goto fail;
1149         }
1150 
1151         mpt = ddi_get_soft_state(mptsas_state, instance);
1152 
1153         if (mpt == NULL) {
1154                 mptsas_log(NULL, CE_WARN,
1155                     "mptsas%d: cannot get soft state", instance);
1156                 goto fail;
1157         }
1158 
1159         /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
1160         scsi_size_clean(dip);
1161 
1162         mpt->m_dip = dip;
1163         mpt->m_instance = instance;
1164 
1165         /* Make a per-instance copy of the structures */
1166         mpt->m_io_dma_attr = mptsas_dma_attrs64;
1167         mpt->m_msg_dma_attr = mptsas_dma_attrs;
1168         mpt->m_reg_acc_attr = mptsas_dev_attr;
1169         mpt->m_dev_acc_attr = mptsas_dev_attr;
1170 
1171         /*
1172          * Initialize FMA
1173          */
1174         mpt->m_fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, mpt->m_dip,
1175             DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
1176             DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
1177             DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
1178 
1179         mptsas_fm_init(mpt);
1180 
1181         if (mptsas_alloc_handshake_msg(mpt,
1182             sizeof (Mpi2SCSITaskManagementRequest_t)) == DDI_FAILURE) {
1183                 mptsas_log(mpt, CE_WARN, "cannot initialize handshake msg.");
1184                 goto fail;
1185         }
1186 
1187         /*
1188          * Setup configuration space
1189          */
1190         if (mptsas_config_space_init(mpt) == FALSE) {
1191                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init failed");
1192                 goto fail;
1193         }
1194         config_setup++;
1195 
1196         if (ddi_regs_map_setup(dip, mem_bar, (caddr_t *)&mpt->m_reg,
1197             0, 0, &mpt->m_reg_acc_attr, &mpt->m_datap) != DDI_SUCCESS) {
1198                 mptsas_log(mpt, CE_WARN, "map setup failed");
1199                 goto fail;
1200         }
1201         map_setup++;
1202 
1203         /*
1204          * A taskq is created for dealing with the event handler
1205          */
1206         if ((mpt->m_event_taskq = ddi_taskq_create(dip, "mptsas_event_taskq",
1207             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1208                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create failed");
1209                 goto fail;
1210         }
1211         event_taskq_create++;
1212 
1213         /*
1214          * A taskq is created for dealing with dr events
1215          */
1216         if ((mpt->m_dr_taskq = ddi_taskq_create(dip,
1217             "mptsas_dr_taskq",
1218             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1219                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create for discovery "
1220                     "failed");
1221                 goto fail;
1222         }
1223         dr_taskq_create++;
1224 
1225         mpt->m_doneq_thread_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1226             0, "mptsas_doneq_thread_threshold_prop", 10);
1227         mpt->m_doneq_length_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1228             0, "mptsas_doneq_length_threshold_prop", 8);
1229         mpt->m_doneq_thread_n = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1230             0, "mptsas_doneq_thread_n_prop", 8);
1231 
1232         if (mpt->m_doneq_thread_n) {
1233                 cv_init(&mpt->m_doneq_thread_cv, NULL, CV_DRIVER, NULL);
1234                 mutex_init(&mpt->m_doneq_mutex, NULL, MUTEX_DRIVER, NULL);
1235 
1236                 mutex_enter(&mpt->m_doneq_mutex);
1237                 mpt->m_doneq_thread_id =
1238                     kmem_zalloc(sizeof (mptsas_doneq_thread_list_t)
1239                     * mpt->m_doneq_thread_n, KM_SLEEP);
1240 
1241                 for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1242                         cv_init(&mpt->m_doneq_thread_id[j].cv, NULL,
1243                             CV_DRIVER, NULL);
1244                         mutex_init(&mpt->m_doneq_thread_id[j].mutex, NULL,
1245                             MUTEX_DRIVER, NULL);
1246                         mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1247                         mpt->m_doneq_thread_id[j].flag |=
1248                             MPTSAS_DONEQ_THREAD_ACTIVE;
1249                         mpt->m_doneq_thread_id[j].arg.mpt = mpt;
1250                         mpt->m_doneq_thread_id[j].arg.t = j;
1251                         mpt->m_doneq_thread_id[j].threadp =
1252                             thread_create(NULL, 0, mptsas_doneq_thread,
1253                             &mpt->m_doneq_thread_id[j].arg,
1254                             0, &p0, TS_RUN, minclsyspri);
1255                         mpt->m_doneq_thread_id[j].donetail =
1256                             &mpt->m_doneq_thread_id[j].doneq;
1257                         mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1258                 }
1259                 mutex_exit(&mpt->m_doneq_mutex);
1260                 doneq_thread_create++;
1261         }
1262 
1263         /* Initialize mutex used in interrupt handler */
1264         mutex_init(&mpt->m_mutex, NULL, MUTEX_DRIVER,
1265             DDI_INTR_PRI(mpt->m_intr_pri));
1266         mutex_init(&mpt->m_passthru_mutex, NULL, MUTEX_DRIVER, NULL);
1267         mutex_init(&mpt->m_tx_waitq_mutex, NULL, MUTEX_DRIVER,
1268             DDI_INTR_PRI(mpt->m_intr_pri));
1269         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1270                 mutex_init(&mpt->m_phy_info[i].smhba_info.phy_mutex,
1271                     NULL, MUTEX_DRIVER,
1272                     DDI_INTR_PRI(mpt->m_intr_pri));
1273         }
1274 
1275         cv_init(&mpt->m_cv, NULL, CV_DRIVER, NULL);
1276         cv_init(&mpt->m_passthru_cv, NULL, CV_DRIVER, NULL);
1277         cv_init(&mpt->m_fw_cv, NULL, CV_DRIVER, NULL);
1278         cv_init(&mpt->m_config_cv, NULL, CV_DRIVER, NULL);
1279         cv_init(&mpt->m_fw_diag_cv, NULL, CV_DRIVER, NULL);
1280         mutex_init_done++;
1281 
1282         /*
1283          * Disable hardware interrupt since we're not ready to
1284          * handle it yet.
1285          */
1286         MPTSAS_DISABLE_INTR(mpt);
1287         if (mptsas_register_intrs(mpt) == FALSE)
1288                 goto fail;
1289         intr_added++;
1290 
1291         mutex_enter(&mpt->m_mutex);
1292         /*
1293          * Initialize power management component
1294          */
1295         if (mpt->m_options & MPTSAS_OPT_PM) {
1296                 if (mptsas_init_pm(mpt)) {
1297                         mutex_exit(&mpt->m_mutex);
1298                         mptsas_log(mpt, CE_WARN, "mptsas pm initialization "
1299                             "failed");
1300                         goto fail;
1301                 }
1302         }
1303 
1304         /*
1305          * Initialize chip using Message Unit Reset, if allowed
1306          */
1307         mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1308         if (mptsas_init_chip(mpt, TRUE) == DDI_FAILURE) {
1309                 mutex_exit(&mpt->m_mutex);
1310                 mptsas_log(mpt, CE_WARN, "mptsas chip initialization failed");
1311                 goto fail;
1312         }
1313 
1314         /*
1315          * Fill in the phy_info structure and get the base WWID
1316          */
1317         if (mptsas_get_manufacture_page5(mpt) == DDI_FAILURE) {
1318                 mptsas_log(mpt, CE_WARN,
1319                     "mptsas_get_manufacture_page5 failed!");
1320                 goto fail;
1321         }
1322 
1323         if (mptsas_get_sas_io_unit_page_hndshk(mpt)) {
1324                 mptsas_log(mpt, CE_WARN,
1325                     "mptsas_get_sas_io_unit_page_hndshk failed!");
1326                 goto fail;
1327         }
1328 
1329         if (mptsas_get_manufacture_page0(mpt) == DDI_FAILURE) {
1330                 mptsas_log(mpt, CE_WARN,
1331                     "mptsas_get_manufacture_page0 failed!");
1332                 goto fail;
1333         }
1334 
1335         mutex_exit(&mpt->m_mutex);
1336 
1337         /*
1338          * Register the iport for multiple port HBA
1339          */
1340         mptsas_iport_register(mpt);
1341 
1342         /*
1343          * initialize SCSI HBA transport structure
1344          */
1345         if (mptsas_hba_setup(mpt) == FALSE)
1346                 goto fail;
1347         hba_attach_setup++;
1348 
1349         if (mptsas_smp_setup(mpt) == FALSE)
1350                 goto fail;
1351         smp_attach_setup++;
1352 
1353         if (mptsas_cache_create(mpt) == FALSE)
1354                 goto fail;
1355 
1356         mpt->m_scsi_reset_delay      = ddi_prop_get_int(DDI_DEV_T_ANY,
1357             dip, 0, "scsi-reset-delay", SCSI_DEFAULT_RESET_DELAY);
1358         if (mpt->m_scsi_reset_delay == 0) {
1359                 mptsas_log(mpt, CE_NOTE,
1360                     "scsi_reset_delay of 0 is not recommended,"
1361                     " resetting to SCSI_DEFAULT_RESET_DELAY\n");
1362                 mpt->m_scsi_reset_delay = SCSI_DEFAULT_RESET_DELAY;
1363         }
1364 
1365         /*
1366          * Initialize the wait and done FIFO queue
1367          */
1368         mpt->m_donetail = &mpt->m_doneq;
1369         mpt->m_waitqtail = &mpt->m_waitq;
1370         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
1371         mpt->m_tx_draining = 0;
1372 
1373         /*
1374          * ioc cmd queue initialize
1375          */
1376         mpt->m_ioc_event_cmdtail = &mpt->m_ioc_event_cmdq;
1377         mpt->m_dev_handle = 0xFFFF;
1378 
1379         MPTSAS_ENABLE_INTR(mpt);
1380 
1381         /*
1382          * enable event notification
1383          */
1384         mutex_enter(&mpt->m_mutex);
1385         if (mptsas_ioc_enable_event_notification(mpt)) {
1386                 mutex_exit(&mpt->m_mutex);
1387                 goto fail;
1388         }
1389         mutex_exit(&mpt->m_mutex);
1390 
1391         /*
1392          * Initialize PHY info for smhba
1393          */
1394         if (mptsas_smhba_setup(mpt)) {
1395                 mptsas_log(mpt, CE_WARN, "mptsas phy initialization "
1396                     "failed");
1397                 goto fail;
1398         }
1399 
1400         /* Check all dma handles allocated in attach */
1401         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl)
1402             != DDI_SUCCESS) ||
1403             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl)
1404             != DDI_SUCCESS) ||
1405             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl)
1406             != DDI_SUCCESS) ||
1407             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl)
1408             != DDI_SUCCESS) ||
1409             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl)
1410             != DDI_SUCCESS)) {
1411                 goto fail;
1412         }
1413 
1414         /* Check all acc handles allocated in attach */
1415         if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
1416             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl)
1417             != DDI_SUCCESS) ||
1418             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl)
1419             != DDI_SUCCESS) ||
1420             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl)
1421             != DDI_SUCCESS) ||
1422             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl)
1423             != DDI_SUCCESS) ||
1424             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl)
1425             != DDI_SUCCESS) ||
1426             (mptsas_check_acc_handle(mpt->m_config_handle)
1427             != DDI_SUCCESS)) {
1428                 goto fail;
1429         }
1430 
1431         /*
1432          * After this point, we are not going to fail the attach.
1433          */
1434         /*
1435          * used for mptsas_watch
1436          */
1437         mptsas_list_add(mpt);
1438 
1439         mutex_enter(&mptsas_global_mutex);
1440         if (mptsas_timeouts_enabled == 0) {
1441                 mptsas_scsi_watchdog_tick = ddi_prop_get_int(DDI_DEV_T_ANY,
1442                     dip, 0, "scsi-watchdog-tick", DEFAULT_WD_TICK);
1443 
1444                 mptsas_tick = mptsas_scsi_watchdog_tick *
1445                     drv_usectohz((clock_t)1000000);
1446 
1447                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
1448                 mptsas_timeouts_enabled = 1;
1449         }
1450         mutex_exit(&mptsas_global_mutex);
1451 
1452         /* Print message of HBA present */
1453         ddi_report_dev(dip);
1454 
1455         /* report idle status to pm framework */
1456         if (mpt->m_options & MPTSAS_OPT_PM) {
1457                 (void) pm_idle_component(dip, 0);
1458         }
1459 
1460         return (DDI_SUCCESS);
1461 
1462 fail:
1463         mptsas_log(mpt, CE_WARN, "attach failed");
1464         mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
1465         ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
1466         if (mpt) {
1467                 mutex_enter(&mptsas_global_mutex);
1468 
1469                 if (mptsas_timeout_id && (mptsas_head == NULL)) {
1470                         timeout_id_t tid = mptsas_timeout_id;
1471                         mptsas_timeouts_enabled = 0;
1472                         mptsas_timeout_id = 0;
1473                         mutex_exit(&mptsas_global_mutex);
1474                         (void) untimeout(tid);
1475                         mutex_enter(&mptsas_global_mutex);
1476                 }
1477                 mutex_exit(&mptsas_global_mutex);
1478                 /* deallocate in reverse order */
1479                 mptsas_cache_destroy(mpt);
1480 
1481                 if (smp_attach_setup) {
1482                         mptsas_smp_teardown(mpt);
1483                 }
1484                 if (hba_attach_setup) {
1485                         mptsas_hba_teardown(mpt);
1486                 }
1487 
1488                 if (mpt->m_targets)
1489                         refhash_destroy(mpt->m_targets);
1490                 if (mpt->m_smp_targets)
1491                         refhash_destroy(mpt->m_smp_targets);
1492 
1493                 if (mpt->m_active) {
1494                         mptsas_free_active_slots(mpt);
1495                 }
1496                 if (intr_added) {
1497                         mptsas_unregister_intrs(mpt);
1498                 }
1499 
1500                 if (doneq_thread_create) {
1501                         mutex_enter(&mpt->m_doneq_mutex);
1502                         doneq_thread_num = mpt->m_doneq_thread_n;
1503                         for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1504                                 mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1505                                 mpt->m_doneq_thread_id[j].flag &=
1506                                     (~MPTSAS_DONEQ_THREAD_ACTIVE);
1507                                 cv_signal(&mpt->m_doneq_thread_id[j].cv);
1508                                 mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1509                         }
1510                         while (mpt->m_doneq_thread_n) {
1511                                 cv_wait(&mpt->m_doneq_thread_cv,
1512                                     &mpt->m_doneq_mutex);
1513                         }
1514                         for (j = 0; j < doneq_thread_num; j++) {
1515                                 cv_destroy(&mpt->m_doneq_thread_id[j].cv);
1516                                 mutex_destroy(&mpt->m_doneq_thread_id[j].mutex);
1517                         }
1518                         kmem_free(mpt->m_doneq_thread_id,
1519                             sizeof (mptsas_doneq_thread_list_t)
1520                             * doneq_thread_num);
1521                         mutex_exit(&mpt->m_doneq_mutex);
1522                         cv_destroy(&mpt->m_doneq_thread_cv);
1523                         mutex_destroy(&mpt->m_doneq_mutex);
1524                 }
1525                 if (event_taskq_create) {
1526                         ddi_taskq_destroy(mpt->m_event_taskq);
1527                 }
1528                 if (dr_taskq_create) {
1529                         ddi_taskq_destroy(mpt->m_dr_taskq);
1530                 }
1531                 if (mutex_init_done) {
1532                         mutex_destroy(&mpt->m_tx_waitq_mutex);
1533                         mutex_destroy(&mpt->m_passthru_mutex);
1534                         mutex_destroy(&mpt->m_mutex);
1535                         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1536                                 mutex_destroy(
1537                                     &mpt->m_phy_info[i].smhba_info.phy_mutex);
1538                         }
1539                         cv_destroy(&mpt->m_cv);
1540                         cv_destroy(&mpt->m_passthru_cv);
1541                         cv_destroy(&mpt->m_fw_cv);
1542                         cv_destroy(&mpt->m_config_cv);
1543                         cv_destroy(&mpt->m_fw_diag_cv);
1544                 }
1545 
1546                 if (map_setup) {
1547                         mptsas_cfg_fini(mpt);
1548                 }
1549                 if (config_setup) {
1550                         mptsas_config_space_fini(mpt);
1551                 }
1552                 mptsas_free_handshake_msg(mpt);
1553                 mptsas_hba_fini(mpt);
1554 
1555                 mptsas_fm_fini(mpt);
1556                 ddi_soft_state_free(mptsas_state, instance);
1557                 ddi_prop_remove_all(dip);
1558         }
1559         return (DDI_FAILURE);
1560 }
1561 
1562 static int
1563 mptsas_suspend(dev_info_t *devi)
1564 {
1565         mptsas_t        *mpt, *g;
1566         scsi_hba_tran_t *tran;
1567 
1568         if (scsi_hba_iport_unit_address(devi)) {
1569                 return (DDI_SUCCESS);
1570         }
1571 
1572         if ((tran = ddi_get_driver_private(devi)) == NULL)
1573                 return (DDI_SUCCESS);
1574 
1575         mpt = TRAN2MPT(tran);
1576         if (!mpt) {
1577                 return (DDI_SUCCESS);
1578         }
1579 
1580         mutex_enter(&mpt->m_mutex);
1581 
1582         if (mpt->m_suspended++) {
1583                 mutex_exit(&mpt->m_mutex);
1584                 return (DDI_SUCCESS);
1585         }
1586 
1587         /*
1588          * Cancel timeout threads for this mpt
1589          */
1590         if (mpt->m_quiesce_timeid) {
1591                 timeout_id_t tid = mpt->m_quiesce_timeid;
1592                 mpt->m_quiesce_timeid = 0;
1593                 mutex_exit(&mpt->m_mutex);
1594                 (void) untimeout(tid);
1595                 mutex_enter(&mpt->m_mutex);
1596         }
1597 
1598         if (mpt->m_restart_cmd_timeid) {
1599                 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1600                 mpt->m_restart_cmd_timeid = 0;
1601                 mutex_exit(&mpt->m_mutex);
1602                 (void) untimeout(tid);
1603                 mutex_enter(&mpt->m_mutex);
1604         }
1605 
1606         mutex_exit(&mpt->m_mutex);
1607 
1608         (void) pm_idle_component(mpt->m_dip, 0);
1609 
1610         /*
1611          * Cancel watch threads if all mpts suspended
1612          */
1613         rw_enter(&mptsas_global_rwlock, RW_WRITER);
1614         for (g = mptsas_head; g != NULL; g = g->m_next) {
1615                 if (!g->m_suspended)
1616                         break;
1617         }
1618         rw_exit(&mptsas_global_rwlock);
1619 
1620         mutex_enter(&mptsas_global_mutex);
1621         if (g == NULL) {
1622                 timeout_id_t tid;
1623 
1624                 mptsas_timeouts_enabled = 0;
1625                 if (mptsas_timeout_id) {
1626                         tid = mptsas_timeout_id;
1627                         mptsas_timeout_id = 0;
1628                         mutex_exit(&mptsas_global_mutex);
1629                         (void) untimeout(tid);
1630                         mutex_enter(&mptsas_global_mutex);
1631                 }
1632                 if (mptsas_reset_watch) {
1633                         tid = mptsas_reset_watch;
1634                         mptsas_reset_watch = 0;
1635                         mutex_exit(&mptsas_global_mutex);
1636                         (void) untimeout(tid);
1637                         mutex_enter(&mptsas_global_mutex);
1638                 }
1639         }
1640         mutex_exit(&mptsas_global_mutex);
1641 
1642         mutex_enter(&mpt->m_mutex);
1643 
1644         /*
1645          * If this mpt is not in full power(PM_LEVEL_D0), just return.
1646          */
1647         if ((mpt->m_options & MPTSAS_OPT_PM) &&
1648             (mpt->m_power_level != PM_LEVEL_D0)) {
1649                 mutex_exit(&mpt->m_mutex);
1650                 return (DDI_SUCCESS);
1651         }
1652 
1653         /* Disable HBA interrupts in hardware */
1654         MPTSAS_DISABLE_INTR(mpt);
1655         /*
1656          * Send RAID action system shutdown to sync IR
1657          */
1658         mptsas_raid_action_system_shutdown(mpt);
1659 
1660         mutex_exit(&mpt->m_mutex);
1661 
1662         /* drain the taskq */
1663         ddi_taskq_wait(mpt->m_event_taskq);
1664         ddi_taskq_wait(mpt->m_dr_taskq);
1665 
1666         return (DDI_SUCCESS);
1667 }
1668 
1669 #ifdef  __sparc
1670 /*ARGSUSED*/
1671 static int
1672 mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd)
1673 {
1674         mptsas_t        *mpt;
1675         scsi_hba_tran_t *tran;
1676 
1677         /*
1678          * If this call is for iport, just return.
1679          */
1680         if (scsi_hba_iport_unit_address(devi))
1681                 return (DDI_SUCCESS);
1682 
1683         if ((tran = ddi_get_driver_private(devi)) == NULL)
1684                 return (DDI_SUCCESS);
1685 
1686         if ((mpt = TRAN2MPT(tran)) == NULL)
1687                 return (DDI_SUCCESS);
1688 
1689         /*
1690          * Send RAID action system shutdown to sync IR.  Disable HBA
1691          * interrupts in hardware first.
1692          */
1693         MPTSAS_DISABLE_INTR(mpt);
1694         mptsas_raid_action_system_shutdown(mpt);
1695 
1696         return (DDI_SUCCESS);
1697 }
1698 #else /* __sparc */
1699 /*
1700  * quiesce(9E) entry point.
1701  *
1702  * This function is called when the system is single-threaded at high
1703  * PIL with preemption disabled. Therefore, this function must not be
1704  * blocked.
1705  *
1706  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1707  * DDI_FAILURE indicates an error condition and should almost never happen.
1708  */
1709 static int
1710 mptsas_quiesce(dev_info_t *devi)
1711 {
1712         mptsas_t        *mpt;
1713         scsi_hba_tran_t *tran;
1714 
1715         /*
1716          * If this call is for iport, just return.
1717          */
1718         if (scsi_hba_iport_unit_address(devi))
1719                 return (DDI_SUCCESS);
1720 
1721         if ((tran = ddi_get_driver_private(devi)) == NULL)
1722                 return (DDI_SUCCESS);
1723 
1724         if ((mpt = TRAN2MPT(tran)) == NULL)
1725                 return (DDI_SUCCESS);
1726 
1727         /* Disable HBA interrupts in hardware */
1728         MPTSAS_DISABLE_INTR(mpt);
1729         /* Send RAID action system shutdonw to sync IR */
1730         mptsas_raid_action_system_shutdown(mpt);
1731 
1732         return (DDI_SUCCESS);
1733 }
1734 #endif  /* __sparc */
1735 
1736 /*
1737  * detach(9E).  Remove all device allocations and system resources;
1738  * disable device interrupts.
1739  * Return DDI_SUCCESS if done; DDI_FAILURE if there's a problem.
1740  */
1741 static int
1742 mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1743 {
1744         /* CONSTCOND */
1745         ASSERT(NO_COMPETING_THREADS);
1746         NDBG0(("mptsas_detach: dip=0x%p cmd=0x%p", (void *)devi, (void *)cmd));
1747 
1748         switch (cmd) {
1749         case DDI_DETACH:
1750                 return (mptsas_do_detach(devi));
1751 
1752         case DDI_SUSPEND:
1753                 return (mptsas_suspend(devi));
1754 
1755         default:
1756                 return (DDI_FAILURE);
1757         }
1758         /* NOTREACHED */
1759 }
1760 
1761 static int
1762 mptsas_do_detach(dev_info_t *dip)
1763 {
1764         mptsas_t        *mpt;
1765         scsi_hba_tran_t *tran;
1766         int             circ = 0;
1767         int             circ1 = 0;
1768         mdi_pathinfo_t  *pip = NULL;
1769         int             i;
1770         int             doneq_thread_num = 0;
1771 
1772         NDBG0(("mptsas_do_detach: dip=0x%p", (void *)dip));
1773 
1774         if ((tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) == NULL)
1775                 return (DDI_FAILURE);
1776 
1777         mpt = TRAN2MPT(tran);
1778         if (!mpt) {
1779                 return (DDI_FAILURE);
1780         }
1781         /*
1782          * Still have pathinfo child, should not detach mpt driver
1783          */
1784         if (scsi_hba_iport_unit_address(dip)) {
1785                 if (mpt->m_mpxio_enable) {
1786                         /*
1787                          * MPxIO enabled for the iport
1788                          */
1789                         ndi_devi_enter(scsi_vhci_dip, &circ1);
1790                         ndi_devi_enter(dip, &circ);
1791                         while (pip = mdi_get_next_client_path(dip, NULL)) {
1792                                 if (mdi_pi_free(pip, 0) == MDI_SUCCESS) {
1793                                         continue;
1794                                 }
1795                                 ndi_devi_exit(dip, circ);
1796                                 ndi_devi_exit(scsi_vhci_dip, circ1);
1797                                 NDBG12(("detach failed because of "
1798                                     "outstanding path info"));
1799                                 return (DDI_FAILURE);
1800                         }
1801                         ndi_devi_exit(dip, circ);
1802                         ndi_devi_exit(scsi_vhci_dip, circ1);
1803                         (void) mdi_phci_unregister(dip, 0);
1804                 }
1805 
1806                 ddi_prop_remove_all(dip);
1807 
1808                 return (DDI_SUCCESS);
1809         }
1810 
1811         /* Make sure power level is D0 before accessing registers */
1812         if (mpt->m_options & MPTSAS_OPT_PM) {
1813                 (void) pm_busy_component(dip, 0);
1814                 if (mpt->m_power_level != PM_LEVEL_D0) {
1815                         if (pm_raise_power(dip, 0, PM_LEVEL_D0) !=
1816                             DDI_SUCCESS) {
1817                                 mptsas_log(mpt, CE_WARN,
1818                                     "mptsas%d: Raise power request failed.",
1819                                     mpt->m_instance);
1820                                 (void) pm_idle_component(dip, 0);
1821                                 return (DDI_FAILURE);
1822                         }
1823                 }
1824         }
1825 
1826         /*
1827          * Send RAID action system shutdown to sync IR.  After action, send a
1828          * Message Unit Reset. Since after that DMA resource will be freed,
1829          * set ioc to READY state will avoid HBA initiated DMA operation.
1830          */
1831         mutex_enter(&mpt->m_mutex);
1832         MPTSAS_DISABLE_INTR(mpt);
1833         mptsas_raid_action_system_shutdown(mpt);
1834         mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1835         (void) mptsas_ioc_reset(mpt, FALSE);
1836         mutex_exit(&mpt->m_mutex);
1837         mptsas_rem_intrs(mpt);
1838         ddi_taskq_destroy(mpt->m_event_taskq);
1839         ddi_taskq_destroy(mpt->m_dr_taskq);
1840 
1841         if (mpt->m_doneq_thread_n) {
1842                 mutex_enter(&mpt->m_doneq_mutex);
1843                 doneq_thread_num = mpt->m_doneq_thread_n;
1844                 for (i = 0; i < mpt->m_doneq_thread_n; i++) {
1845                         mutex_enter(&mpt->m_doneq_thread_id[i].mutex);
1846                         mpt->m_doneq_thread_id[i].flag &=
1847                             (~MPTSAS_DONEQ_THREAD_ACTIVE);
1848                         cv_signal(&mpt->m_doneq_thread_id[i].cv);
1849                         mutex_exit(&mpt->m_doneq_thread_id[i].mutex);
1850                 }
1851                 while (mpt->m_doneq_thread_n) {
1852                         cv_wait(&mpt->m_doneq_thread_cv,
1853                             &mpt->m_doneq_mutex);
1854                 }
1855                 for (i = 0;  i < doneq_thread_num; i++) {
1856                         cv_destroy(&mpt->m_doneq_thread_id[i].cv);
1857                         mutex_destroy(&mpt->m_doneq_thread_id[i].mutex);
1858                 }
1859                 kmem_free(mpt->m_doneq_thread_id,
1860                     sizeof (mptsas_doneq_thread_list_t)
1861                     * doneq_thread_num);
1862                 mutex_exit(&mpt->m_doneq_mutex);
1863                 cv_destroy(&mpt->m_doneq_thread_cv);
1864                 mutex_destroy(&mpt->m_doneq_mutex);
1865         }
1866 
1867         scsi_hba_reset_notify_tear_down(mpt->m_reset_notify_listf);
1868 
1869         mptsas_list_del(mpt);
1870 
1871         /*
1872          * Cancel timeout threads for this mpt
1873          */
1874         mutex_enter(&mpt->m_mutex);
1875         if (mpt->m_quiesce_timeid) {
1876                 timeout_id_t tid = mpt->m_quiesce_timeid;
1877                 mpt->m_quiesce_timeid = 0;
1878                 mutex_exit(&mpt->m_mutex);
1879                 (void) untimeout(tid);
1880                 mutex_enter(&mpt->m_mutex);
1881         }
1882 
1883         if (mpt->m_restart_cmd_timeid) {
1884                 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1885                 mpt->m_restart_cmd_timeid = 0;
1886                 mutex_exit(&mpt->m_mutex);
1887                 (void) untimeout(tid);
1888                 mutex_enter(&mpt->m_mutex);
1889         }
1890 
1891         mutex_exit(&mpt->m_mutex);
1892 
1893         /*
1894          * last mpt? ... if active, CANCEL watch threads.
1895          */
1896         mutex_enter(&mptsas_global_mutex);
1897         if (mptsas_head == NULL) {
1898                 timeout_id_t tid;
1899                 /*
1900                  * Clear mptsas_timeouts_enable so that the watch thread
1901                  * gets restarted on DDI_ATTACH
1902                  */
1903                 mptsas_timeouts_enabled = 0;
1904                 if (mptsas_timeout_id) {
1905                         tid = mptsas_timeout_id;
1906                         mptsas_timeout_id = 0;
1907                         mutex_exit(&mptsas_global_mutex);
1908                         (void) untimeout(tid);
1909                         mutex_enter(&mptsas_global_mutex);
1910                 }
1911                 if (mptsas_reset_watch) {
1912                         tid = mptsas_reset_watch;
1913                         mptsas_reset_watch = 0;
1914                         mutex_exit(&mptsas_global_mutex);
1915                         (void) untimeout(tid);
1916                         mutex_enter(&mptsas_global_mutex);
1917                 }
1918         }
1919         mutex_exit(&mptsas_global_mutex);
1920 
1921         /*
1922          * Delete Phy stats
1923          */
1924         mptsas_destroy_phy_stats(mpt);
1925 
1926         mptsas_destroy_hashes(mpt);
1927 
1928         /*
1929          * Delete nt_active.
1930          */
1931         mutex_enter(&mpt->m_mutex);
1932         mptsas_free_active_slots(mpt);
1933         mutex_exit(&mpt->m_mutex);
1934 
1935         /* deallocate everything that was allocated in mptsas_attach */
1936         mptsas_cache_destroy(mpt);
1937 
1938         mptsas_hba_fini(mpt);
1939         mptsas_cfg_fini(mpt);
1940 
1941         /* Lower the power informing PM Framework */
1942         if (mpt->m_options & MPTSAS_OPT_PM) {
1943                 if (pm_lower_power(dip, 0, PM_LEVEL_D3) != DDI_SUCCESS)
1944                         mptsas_log(mpt, CE_WARN,
1945                             "!mptsas%d: Lower power request failed "
1946                             "during detach, ignoring.",
1947                             mpt->m_instance);
1948         }
1949 
1950         mutex_destroy(&mpt->m_tx_waitq_mutex);
1951         mutex_destroy(&mpt->m_passthru_mutex);
1952         mutex_destroy(&mpt->m_mutex);
1953         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1954                 mutex_destroy(&mpt->m_phy_info[i].smhba_info.phy_mutex);
1955         }
1956         cv_destroy(&mpt->m_cv);
1957         cv_destroy(&mpt->m_passthru_cv);
1958         cv_destroy(&mpt->m_fw_cv);
1959         cv_destroy(&mpt->m_config_cv);
1960         cv_destroy(&mpt->m_fw_diag_cv);
1961 
1962 
1963         mptsas_smp_teardown(mpt);
1964         mptsas_hba_teardown(mpt);
1965 
1966         mptsas_config_space_fini(mpt);
1967 
1968         mptsas_free_handshake_msg(mpt);
1969 
1970         mptsas_fm_fini(mpt);
1971         ddi_soft_state_free(mptsas_state, ddi_get_instance(dip));
1972         ddi_prop_remove_all(dip);
1973 
1974         return (DDI_SUCCESS);
1975 }
1976 
1977 static void
1978 mptsas_list_add(mptsas_t *mpt)
1979 {
1980         rw_enter(&mptsas_global_rwlock, RW_WRITER);
1981 
1982         if (mptsas_head == NULL) {
1983                 mptsas_head = mpt;
1984         } else {
1985                 mptsas_tail->m_next = mpt;
1986         }
1987         mptsas_tail = mpt;
1988         rw_exit(&mptsas_global_rwlock);
1989 }
1990 
1991 static void
1992 mptsas_list_del(mptsas_t *mpt)
1993 {
1994         mptsas_t *m;
1995         /*
1996          * Remove device instance from the global linked list
1997          */
1998         rw_enter(&mptsas_global_rwlock, RW_WRITER);
1999         if (mptsas_head == mpt) {
2000                 m = mptsas_head = mpt->m_next;
2001         } else {
2002                 for (m = mptsas_head; m != NULL; m = m->m_next) {
2003                         if (m->m_next == mpt) {
2004                                 m->m_next = mpt->m_next;
2005                                 break;
2006                         }
2007                 }
2008                 if (m == NULL) {
2009                         mptsas_log(mpt, CE_PANIC, "Not in softc list!");
2010                 }
2011         }
2012 
2013         if (mptsas_tail == mpt) {
2014                 mptsas_tail = m;
2015         }
2016         rw_exit(&mptsas_global_rwlock);
2017 }
2018 
2019 static int
2020 mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size)
2021 {
2022         ddi_dma_attr_t  task_dma_attrs;
2023 
2024         mpt->m_hshk_dma_size = 0;
2025         task_dma_attrs = mpt->m_msg_dma_attr;
2026         task_dma_attrs.dma_attr_sgllen = 1;
2027         task_dma_attrs.dma_attr_granular = (uint32_t)(alloc_size);
2028 
2029         /* allocate Task Management ddi_dma resources */
2030         if (mptsas_dma_addr_create(mpt, task_dma_attrs,
2031             &mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl, &mpt->m_hshk_memp,
2032             alloc_size, NULL) == FALSE) {
2033                 return (DDI_FAILURE);
2034         }
2035         mpt->m_hshk_dma_size = alloc_size;
2036 
2037         return (DDI_SUCCESS);
2038 }
2039 
2040 static void
2041 mptsas_free_handshake_msg(mptsas_t *mpt)
2042 {
2043         if (mpt->m_hshk_dma_size == 0)
2044                 return;
2045         mptsas_dma_addr_destroy(&mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl);
2046         mpt->m_hshk_dma_size = 0;
2047 }
2048 
2049 static int
2050 mptsas_hba_setup(mptsas_t *mpt)
2051 {
2052         scsi_hba_tran_t         *hba_tran;
2053         int                     tran_flags;
2054 
2055         /* Allocate a transport structure */
2056         hba_tran = mpt->m_tran = scsi_hba_tran_alloc(mpt->m_dip,
2057             SCSI_HBA_CANSLEEP);
2058         ASSERT(mpt->m_tran != NULL);
2059 
2060         hba_tran->tran_hba_private   = mpt;
2061         hba_tran->tran_tgt_private   = NULL;
2062 
2063         hba_tran->tran_tgt_init              = mptsas_scsi_tgt_init;
2064         hba_tran->tran_tgt_free              = mptsas_scsi_tgt_free;
2065 
2066         hba_tran->tran_start         = mptsas_scsi_start;
2067         hba_tran->tran_reset         = mptsas_scsi_reset;
2068         hba_tran->tran_abort         = mptsas_scsi_abort;
2069         hba_tran->tran_getcap                = mptsas_scsi_getcap;
2070         hba_tran->tran_setcap                = mptsas_scsi_setcap;
2071         hba_tran->tran_init_pkt              = mptsas_scsi_init_pkt;
2072         hba_tran->tran_destroy_pkt   = mptsas_scsi_destroy_pkt;
2073 
2074         hba_tran->tran_dmafree               = mptsas_scsi_dmafree;
2075         hba_tran->tran_sync_pkt              = mptsas_scsi_sync_pkt;
2076         hba_tran->tran_reset_notify  = mptsas_scsi_reset_notify;
2077 
2078         hba_tran->tran_get_bus_addr  = mptsas_get_bus_addr;
2079         hba_tran->tran_get_name              = mptsas_get_name;
2080 
2081         hba_tran->tran_quiesce               = mptsas_scsi_quiesce;
2082         hba_tran->tran_unquiesce     = mptsas_scsi_unquiesce;
2083         hba_tran->tran_bus_reset     = NULL;
2084 
2085         hba_tran->tran_add_eventcall = NULL;
2086         hba_tran->tran_get_eventcookie       = NULL;
2087         hba_tran->tran_post_event    = NULL;
2088         hba_tran->tran_remove_eventcall      = NULL;
2089 
2090         hba_tran->tran_bus_config    = mptsas_bus_config;
2091 
2092         hba_tran->tran_interconnect_type = INTERCONNECT_SAS;
2093 
2094         /*
2095          * All children of the HBA are iports. We need tran was cloned.
2096          * So we pass the flags to SCSA. SCSI_HBA_TRAN_CLONE will be
2097          * inherited to iport's tran vector.
2098          */
2099         tran_flags = (SCSI_HBA_HBA | SCSI_HBA_TRAN_CLONE);
2100 
2101         if (scsi_hba_attach_setup(mpt->m_dip, &mpt->m_msg_dma_attr,
2102             hba_tran, tran_flags) != DDI_SUCCESS) {
2103                 mptsas_log(mpt, CE_WARN, "hba attach setup failed");
2104                 scsi_hba_tran_free(hba_tran);
2105                 mpt->m_tran = NULL;
2106                 return (FALSE);
2107         }
2108         return (TRUE);
2109 }
2110 
2111 static void
2112 mptsas_hba_teardown(mptsas_t *mpt)
2113 {
2114         (void) scsi_hba_detach(mpt->m_dip);
2115         if (mpt->m_tran != NULL) {
2116                 scsi_hba_tran_free(mpt->m_tran);
2117                 mpt->m_tran = NULL;
2118         }
2119 }
2120 
2121 static void
2122 mptsas_iport_register(mptsas_t *mpt)
2123 {
2124         int i, j;
2125         mptsas_phymask_t        mask = 0x0;
2126         /*
2127          * initial value of mask is 0
2128          */
2129         mutex_enter(&mpt->m_mutex);
2130         for (i = 0; i < mpt->m_num_phys; i++) {
2131                 mptsas_phymask_t phy_mask = 0x0;
2132                 char phy_mask_name[MPTSAS_MAX_PHYS];
2133                 uint8_t current_port;
2134 
2135                 if (mpt->m_phy_info[i].attached_devhdl == 0)
2136                         continue;
2137 
2138                 bzero(phy_mask_name, sizeof (phy_mask_name));
2139 
2140                 current_port = mpt->m_phy_info[i].port_num;
2141 
2142                 if ((mask & (1 << i)) != 0)
2143                         continue;
2144 
2145                 for (j = 0; j < mpt->m_num_phys; j++) {
2146                         if (mpt->m_phy_info[j].attached_devhdl &&
2147                             (mpt->m_phy_info[j].port_num == current_port)) {
2148                                 phy_mask |= (1 << j);
2149                         }
2150                 }
2151                 mask = mask | phy_mask;
2152 
2153                 for (j = 0; j < mpt->m_num_phys; j++) {
2154                         if ((phy_mask >> j) & 0x01) {
2155                                 mpt->m_phy_info[j].phy_mask = phy_mask;
2156                         }
2157                 }
2158 
2159                 (void) sprintf(phy_mask_name, "%x", phy_mask);
2160 
2161                 mutex_exit(&mpt->m_mutex);
2162                 /*
2163                  * register a iport
2164                  */
2165                 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
2166                 mutex_enter(&mpt->m_mutex);
2167         }
2168         mutex_exit(&mpt->m_mutex);
2169         /*
2170          * register a virtual port for RAID volume always
2171          */
2172         (void) scsi_hba_iport_register(mpt->m_dip, "v0");
2173 
2174 }
2175 
2176 static int
2177 mptsas_smp_setup(mptsas_t *mpt)
2178 {
2179         mpt->m_smptran = smp_hba_tran_alloc(mpt->m_dip);
2180         ASSERT(mpt->m_smptran != NULL);
2181         mpt->m_smptran->smp_tran_hba_private = mpt;
2182         mpt->m_smptran->smp_tran_start = mptsas_smp_start;
2183         if (smp_hba_attach_setup(mpt->m_dip, mpt->m_smptran) != DDI_SUCCESS) {
2184                 mptsas_log(mpt, CE_WARN, "smp attach setup failed");
2185                 smp_hba_tran_free(mpt->m_smptran);
2186                 mpt->m_smptran = NULL;
2187                 return (FALSE);
2188         }
2189         /*
2190          * Initialize smp hash table
2191          */
2192         mpt->m_smp_targets = refhash_create(MPTSAS_SMP_BUCKET_COUNT,
2193             mptsas_target_addr_hash, mptsas_target_addr_cmp,
2194             mptsas_smp_free, sizeof (mptsas_smp_t),
2195             offsetof(mptsas_smp_t, m_link), offsetof(mptsas_smp_t, m_addr),
2196             KM_SLEEP);
2197         mpt->m_smp_devhdl = 0xFFFF;
2198 
2199         return (TRUE);
2200 }
2201 
2202 static void
2203 mptsas_smp_teardown(mptsas_t *mpt)
2204 {
2205         (void) smp_hba_detach(mpt->m_dip);
2206         if (mpt->m_smptran != NULL) {
2207                 smp_hba_tran_free(mpt->m_smptran);
2208                 mpt->m_smptran = NULL;
2209         }
2210         mpt->m_smp_devhdl = 0;
2211 }
2212 
2213 static int
2214 mptsas_cache_create(mptsas_t *mpt)
2215 {
2216         int instance = mpt->m_instance;
2217         char buf[64];
2218 
2219         /*
2220          * create kmem cache for packets
2221          */
2222         (void) sprintf(buf, "mptsas%d_cache", instance);
2223         mpt->m_kmem_cache = kmem_cache_create(buf,
2224             sizeof (struct mptsas_cmd) + scsi_pkt_size(), 8,
2225             mptsas_kmem_cache_constructor, mptsas_kmem_cache_destructor,
2226             NULL, (void *)mpt, NULL, 0);
2227 
2228         if (mpt->m_kmem_cache == NULL) {
2229                 mptsas_log(mpt, CE_WARN, "creating kmem cache failed");
2230                 return (FALSE);
2231         }
2232 
2233         /*
2234          * create kmem cache for extra SGL frames if SGL cannot
2235          * be accomodated into main request frame.
2236          */
2237         (void) sprintf(buf, "mptsas%d_cache_frames", instance);
2238         mpt->m_cache_frames = kmem_cache_create(buf,
2239             sizeof (mptsas_cache_frames_t), 8,
2240             mptsas_cache_frames_constructor, mptsas_cache_frames_destructor,
2241             NULL, (void *)mpt, NULL, 0);
2242 
2243         if (mpt->m_cache_frames == NULL) {
2244                 mptsas_log(mpt, CE_WARN, "creating cache for frames failed");
2245                 return (FALSE);
2246         }
2247 
2248         return (TRUE);
2249 }
2250 
2251 static void
2252 mptsas_cache_destroy(mptsas_t *mpt)
2253 {
2254         /* deallocate in reverse order */
2255         if (mpt->m_cache_frames) {
2256                 kmem_cache_destroy(mpt->m_cache_frames);
2257                 mpt->m_cache_frames = NULL;
2258         }
2259         if (mpt->m_kmem_cache) {
2260                 kmem_cache_destroy(mpt->m_kmem_cache);
2261                 mpt->m_kmem_cache = NULL;
2262         }
2263 }
2264 
2265 static int
2266 mptsas_power(dev_info_t *dip, int component, int level)
2267 {
2268 #ifndef __lock_lint
2269         _NOTE(ARGUNUSED(component))
2270 #endif
2271         mptsas_t        *mpt;
2272         int             rval = DDI_SUCCESS;
2273         int             polls = 0;
2274         uint32_t        ioc_status;
2275 
2276         if (scsi_hba_iport_unit_address(dip) != 0)
2277                 return (DDI_SUCCESS);
2278 
2279         mpt = ddi_get_soft_state(mptsas_state, ddi_get_instance(dip));
2280         if (mpt == NULL) {
2281                 return (DDI_FAILURE);
2282         }
2283 
2284         mutex_enter(&mpt->m_mutex);
2285 
2286         /*
2287          * If the device is busy, don't lower its power level
2288          */
2289         if (mpt->m_busy && (mpt->m_power_level > level)) {
2290                 mutex_exit(&mpt->m_mutex);
2291                 return (DDI_FAILURE);
2292         }
2293         switch (level) {
2294         case PM_LEVEL_D0:
2295                 NDBG11(("mptsas%d: turning power ON.", mpt->m_instance));
2296                 MPTSAS_POWER_ON(mpt);
2297                 /*
2298                  * Wait up to 30 seconds for IOC to come out of reset.
2299                  */
2300                 while (((ioc_status = ddi_get32(mpt->m_datap,
2301                     &mpt->m_reg->Doorbell)) &
2302                     MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_RESET) {
2303                         if (polls++ > 3000) {
2304                                 break;
2305                         }
2306                         delay(drv_usectohz(10000));
2307                 }
2308                 /*
2309                  * If IOC is not in operational state, try to hard reset it.
2310                  */
2311                 if ((ioc_status & MPI2_IOC_STATE_MASK) !=
2312                     MPI2_IOC_STATE_OPERATIONAL) {
2313                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
2314                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
2315                                 mptsas_log(mpt, CE_WARN,
2316                                     "mptsas_power: hard reset failed");
2317                                 mutex_exit(&mpt->m_mutex);
2318                                 return (DDI_FAILURE);
2319                         }
2320                 }
2321                 mpt->m_power_level = PM_LEVEL_D0;
2322                 break;
2323         case PM_LEVEL_D3:
2324                 NDBG11(("mptsas%d: turning power OFF.", mpt->m_instance));
2325                 MPTSAS_POWER_OFF(mpt);
2326                 break;
2327         default:
2328                 mptsas_log(mpt, CE_WARN, "mptsas%d: unknown power level <%x>.",
2329                     mpt->m_instance, level);
2330                 rval = DDI_FAILURE;
2331                 break;
2332         }
2333         mutex_exit(&mpt->m_mutex);
2334         return (rval);
2335 }
2336 
2337 /*
2338  * Initialize configuration space and figure out which
2339  * chip and revison of the chip the mpt driver is using.
2340  */
2341 static int
2342 mptsas_config_space_init(mptsas_t *mpt)
2343 {
2344         NDBG0(("mptsas_config_space_init"));
2345 
2346         if (mpt->m_config_handle != NULL)
2347                 return (TRUE);
2348 
2349         if (pci_config_setup(mpt->m_dip,
2350             &mpt->m_config_handle) != DDI_SUCCESS) {
2351                 mptsas_log(mpt, CE_WARN, "cannot map configuration space.");
2352                 return (FALSE);
2353         }
2354 
2355         /*
2356          * This is a workaround for a XMITS ASIC bug which does not
2357          * drive the CBE upper bits.
2358          */
2359         if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT) &
2360             PCI_STAT_PERROR) {
2361                 pci_config_put16(mpt->m_config_handle, PCI_CONF_STAT,
2362                     PCI_STAT_PERROR);
2363         }
2364 
2365         mptsas_setup_cmd_reg(mpt);
2366 
2367         /*
2368          * Get the chip device id:
2369          */
2370         mpt->m_devid = pci_config_get16(mpt->m_config_handle, PCI_CONF_DEVID);
2371 
2372         /*
2373          * Save the revision.
2374          */
2375         mpt->m_revid = pci_config_get8(mpt->m_config_handle, PCI_CONF_REVID);
2376 
2377         /*
2378          * Save the SubSystem Vendor and Device IDs
2379          */
2380         mpt->m_svid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBVENID);
2381         mpt->m_ssid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBSYSID);
2382 
2383         /*
2384          * Set the latency timer to 0x40 as specified by the upa -> pci
2385          * bridge chip design team.  This may be done by the sparc pci
2386          * bus nexus driver, but the driver should make sure the latency
2387          * timer is correct for performance reasons.
2388          */
2389         pci_config_put8(mpt->m_config_handle, PCI_CONF_LATENCY_TIMER,
2390             MPTSAS_LATENCY_TIMER);
2391 
2392         (void) mptsas_get_pci_cap(mpt);
2393         return (TRUE);
2394 }
2395 
2396 static void
2397 mptsas_config_space_fini(mptsas_t *mpt)
2398 {
2399         if (mpt->m_config_handle != NULL) {
2400                 mptsas_disable_bus_master(mpt);
2401                 pci_config_teardown(&mpt->m_config_handle);
2402                 mpt->m_config_handle = NULL;
2403         }
2404 }
2405 
2406 static void
2407 mptsas_setup_cmd_reg(mptsas_t *mpt)
2408 {
2409         ushort_t        cmdreg;
2410 
2411         /*
2412          * Set the command register to the needed values.
2413          */
2414         cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2415         cmdreg |= (PCI_COMM_ME | PCI_COMM_SERR_ENABLE |
2416             PCI_COMM_PARITY_DETECT | PCI_COMM_MAE);
2417         cmdreg &= ~PCI_COMM_IO;
2418         pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2419 }
2420 
2421 static void
2422 mptsas_disable_bus_master(mptsas_t *mpt)
2423 {
2424         ushort_t        cmdreg;
2425 
2426         /*
2427          * Clear the master enable bit in the PCI command register.
2428          * This prevents any bus mastering activity like DMA.
2429          */
2430         cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2431         cmdreg &= ~PCI_COMM_ME;
2432         pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2433 }
2434 
2435 int
2436 mptsas_dma_alloc(mptsas_t *mpt, mptsas_dma_alloc_state_t *dma_statep)
2437 {
2438         ddi_dma_attr_t  attrs;
2439 
2440         attrs = mpt->m_io_dma_attr;
2441         attrs.dma_attr_sgllen = 1;
2442 
2443         ASSERT(dma_statep != NULL);
2444 
2445         if (mptsas_dma_addr_create(mpt, attrs, &dma_statep->handle,
2446             &dma_statep->accessp, &dma_statep->memp, dma_statep->size,
2447             &dma_statep->cookie) == FALSE) {
2448                 return (DDI_FAILURE);
2449         }
2450 
2451         return (DDI_SUCCESS);
2452 }
2453 
2454 void
2455 mptsas_dma_free(mptsas_dma_alloc_state_t *dma_statep)
2456 {
2457         ASSERT(dma_statep != NULL);
2458         mptsas_dma_addr_destroy(&dma_statep->handle, &dma_statep->accessp);
2459         dma_statep->size = 0;
2460 }
2461 
2462 int
2463 mptsas_do_dma(mptsas_t *mpt, uint32_t size, int var, int (*callback)())
2464 {
2465         ddi_dma_attr_t          attrs;
2466         ddi_dma_handle_t        dma_handle;
2467         caddr_t                 memp;
2468         ddi_acc_handle_t        accessp;
2469         int                     rval;
2470 
2471         ASSERT(mutex_owned(&mpt->m_mutex));
2472 
2473         attrs = mpt->m_msg_dma_attr;
2474         attrs.dma_attr_sgllen = 1;
2475         attrs.dma_attr_granular = size;
2476 
2477         if (mptsas_dma_addr_create(mpt, attrs, &dma_handle,
2478             &accessp, &memp, size, NULL) == FALSE) {
2479                 return (DDI_FAILURE);
2480         }
2481 
2482         rval = (*callback) (mpt, memp, var, accessp);
2483 
2484         if ((mptsas_check_dma_handle(dma_handle) != DDI_SUCCESS) ||
2485             (mptsas_check_acc_handle(accessp) != DDI_SUCCESS)) {
2486                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2487                 rval = DDI_FAILURE;
2488         }
2489 
2490         mptsas_dma_addr_destroy(&dma_handle, &accessp);
2491         return (rval);
2492 
2493 }
2494 
2495 static int
2496 mptsas_alloc_request_frames(mptsas_t *mpt)
2497 {
2498         ddi_dma_attr_t          frame_dma_attrs;
2499         caddr_t                 memp;
2500         ddi_dma_cookie_t        cookie;
2501         size_t                  mem_size;
2502 
2503         /*
2504          * re-alloc when it has already alloced
2505          */
2506         mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2507             &mpt->m_acc_req_frame_hdl);
2508 
2509         /*
2510          * The size of the request frame pool is:
2511          *   Number of Request Frames * Request Frame Size
2512          */
2513         mem_size = mpt->m_max_requests * mpt->m_req_frame_size;
2514 
2515         /*
2516          * set the DMA attributes.  System Request Message Frames must be
2517          * aligned on a 16-byte boundry.
2518          */
2519         frame_dma_attrs = mpt->m_msg_dma_attr;
2520         frame_dma_attrs.dma_attr_align = 16;
2521         frame_dma_attrs.dma_attr_sgllen = 1;
2522 
2523         /*
2524          * allocate the request frame pool.
2525          */
2526         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2527             &mpt->m_dma_req_frame_hdl, &mpt->m_acc_req_frame_hdl, &memp,
2528             mem_size, &cookie) == FALSE) {
2529                 return (DDI_FAILURE);
2530         }
2531 
2532         /*
2533          * Store the request frame memory address.  This chip uses this
2534          * address to dma to and from the driver's frame.  The second
2535          * address is the address mpt uses to fill in the frame.
2536          */
2537         mpt->m_req_frame_dma_addr = cookie.dmac_laddress;
2538         mpt->m_req_frame = memp;
2539 
2540         /*
2541          * Clear the request frame pool.
2542          */
2543         bzero(mpt->m_req_frame, mem_size);
2544 
2545         return (DDI_SUCCESS);
2546 }
2547 
2548 static int
2549 mptsas_alloc_reply_frames(mptsas_t *mpt)
2550 {
2551         ddi_dma_attr_t          frame_dma_attrs;
2552         caddr_t                 memp;
2553         ddi_dma_cookie_t        cookie;
2554         size_t                  mem_size;
2555 
2556         /*
2557          * re-alloc when it has already alloced
2558          */
2559         mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2560             &mpt->m_acc_reply_frame_hdl);
2561 
2562         /*
2563          * The size of the reply frame pool is:
2564          *   Number of Reply Frames * Reply Frame Size
2565          */
2566         mem_size = mpt->m_max_replies * mpt->m_reply_frame_size;
2567 
2568         /*
2569          * set the DMA attributes.   System Reply Message Frames must be
2570          * aligned on a 4-byte boundry.  This is the default.
2571          */
2572         frame_dma_attrs = mpt->m_msg_dma_attr;
2573         frame_dma_attrs.dma_attr_sgllen = 1;
2574 
2575         /*
2576          * allocate the reply frame pool
2577          */
2578         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2579             &mpt->m_dma_reply_frame_hdl, &mpt->m_acc_reply_frame_hdl, &memp,
2580             mem_size, &cookie) == FALSE) {
2581                 return (DDI_FAILURE);
2582         }
2583 
2584         /*
2585          * Store the reply frame memory address.  This chip uses this
2586          * address to dma to and from the driver's frame.  The second
2587          * address is the address mpt uses to process the frame.
2588          */
2589         mpt->m_reply_frame_dma_addr = cookie.dmac_laddress;
2590         mpt->m_reply_frame = memp;
2591 
2592         /*
2593          * Clear the reply frame pool.
2594          */
2595         bzero(mpt->m_reply_frame, mem_size);
2596 
2597         return (DDI_SUCCESS);
2598 }
2599 
2600 static int
2601 mptsas_alloc_free_queue(mptsas_t *mpt)
2602 {
2603         ddi_dma_attr_t          frame_dma_attrs;
2604         caddr_t                 memp;
2605         ddi_dma_cookie_t        cookie;
2606         size_t                  mem_size;
2607 
2608         /*
2609          * re-alloc when it has already alloced
2610          */
2611         mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2612             &mpt->m_acc_free_queue_hdl);
2613 
2614         /*
2615          * The reply free queue size is:
2616          *   Reply Free Queue Depth * 4
2617          * The "4" is the size of one 32 bit address (low part of 64-bit
2618          *   address)
2619          */
2620         mem_size = mpt->m_free_queue_depth * 4;
2621 
2622         /*
2623          * set the DMA attributes  The Reply Free Queue must be aligned on a
2624          * 16-byte boundry.
2625          */
2626         frame_dma_attrs = mpt->m_msg_dma_attr;
2627         frame_dma_attrs.dma_attr_align = 16;
2628         frame_dma_attrs.dma_attr_sgllen = 1;
2629 
2630         /*
2631          * allocate the reply free queue
2632          */
2633         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2634             &mpt->m_dma_free_queue_hdl, &mpt->m_acc_free_queue_hdl, &memp,
2635             mem_size, &cookie) == FALSE) {
2636                 return (DDI_FAILURE);
2637         }
2638 
2639         /*
2640          * Store the reply free queue memory address.  This chip uses this
2641          * address to read from the reply free queue.  The second address
2642          * is the address mpt uses to manage the queue.
2643          */
2644         mpt->m_free_queue_dma_addr = cookie.dmac_laddress;
2645         mpt->m_free_queue = memp;
2646 
2647         /*
2648          * Clear the reply free queue memory.
2649          */
2650         bzero(mpt->m_free_queue, mem_size);
2651 
2652         return (DDI_SUCCESS);
2653 }
2654 
2655 static int
2656 mptsas_alloc_post_queue(mptsas_t *mpt)
2657 {
2658         ddi_dma_attr_t          frame_dma_attrs;
2659         caddr_t                 memp;
2660         ddi_dma_cookie_t        cookie;
2661         size_t                  mem_size;
2662 
2663         /*
2664          * re-alloc when it has already alloced
2665          */
2666         mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2667             &mpt->m_acc_post_queue_hdl);
2668 
2669         /*
2670          * The reply descriptor post queue size is:
2671          *   Reply Descriptor Post Queue Depth * 8
2672          * The "8" is the size of each descriptor (8 bytes or 64 bits).
2673          */
2674         mem_size = mpt->m_post_queue_depth * 8;
2675 
2676         /*
2677          * set the DMA attributes.  The Reply Descriptor Post Queue must be
2678          * aligned on a 16-byte boundry.
2679          */
2680         frame_dma_attrs = mpt->m_msg_dma_attr;
2681         frame_dma_attrs.dma_attr_align = 16;
2682         frame_dma_attrs.dma_attr_sgllen = 1;
2683 
2684         /*
2685          * allocate the reply post queue
2686          */
2687         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2688             &mpt->m_dma_post_queue_hdl, &mpt->m_acc_post_queue_hdl, &memp,
2689             mem_size, &cookie) == FALSE) {
2690                 return (DDI_FAILURE);
2691         }
2692 
2693         /*
2694          * Store the reply descriptor post queue memory address.  This chip
2695          * uses this address to write to the reply descriptor post queue.  The
2696          * second address is the address mpt uses to manage the queue.
2697          */
2698         mpt->m_post_queue_dma_addr = cookie.dmac_laddress;
2699         mpt->m_post_queue = memp;
2700 
2701         /*
2702          * Clear the reply post queue memory.
2703          */
2704         bzero(mpt->m_post_queue, mem_size);
2705 
2706         return (DDI_SUCCESS);
2707 }
2708 
2709 static void
2710 mptsas_alloc_reply_args(mptsas_t *mpt)
2711 {
2712         if (mpt->m_replyh_args == NULL) {
2713                 mpt->m_replyh_args = kmem_zalloc(sizeof (m_replyh_arg_t) *
2714                     mpt->m_max_replies, KM_SLEEP);
2715         }
2716 }
2717 
2718 static int
2719 mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2720 {
2721         mptsas_cache_frames_t   *frames = NULL;
2722         if (cmd->cmd_extra_frames == NULL) {
2723                 frames = kmem_cache_alloc(mpt->m_cache_frames, KM_NOSLEEP);
2724                 if (frames == NULL) {
2725                         return (DDI_FAILURE);
2726                 }
2727                 cmd->cmd_extra_frames = frames;
2728         }
2729         return (DDI_SUCCESS);
2730 }
2731 
2732 static void
2733 mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2734 {
2735         if (cmd->cmd_extra_frames) {
2736                 kmem_cache_free(mpt->m_cache_frames,
2737                     (void *)cmd->cmd_extra_frames);
2738                 cmd->cmd_extra_frames = NULL;
2739         }
2740 }
2741 
2742 static void
2743 mptsas_cfg_fini(mptsas_t *mpt)
2744 {
2745         NDBG0(("mptsas_cfg_fini"));
2746         ddi_regs_map_free(&mpt->m_datap);
2747 }
2748 
2749 static void
2750 mptsas_hba_fini(mptsas_t *mpt)
2751 {
2752         NDBG0(("mptsas_hba_fini"));
2753 
2754         /*
2755          * Free up any allocated memory
2756          */
2757         mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2758             &mpt->m_acc_req_frame_hdl);
2759 
2760         mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2761             &mpt->m_acc_reply_frame_hdl);
2762 
2763         mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2764             &mpt->m_acc_free_queue_hdl);
2765 
2766         mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2767             &mpt->m_acc_post_queue_hdl);
2768 
2769         if (mpt->m_replyh_args != NULL) {
2770                 kmem_free(mpt->m_replyh_args, sizeof (m_replyh_arg_t)
2771                     * mpt->m_max_replies);
2772         }
2773 }
2774 
2775 static int
2776 mptsas_name_child(dev_info_t *lun_dip, char *name, int len)
2777 {
2778         int             lun = 0;
2779         char            *sas_wwn = NULL;
2780         int             phynum = -1;
2781         int             reallen = 0;
2782 
2783         /* Get the target num */
2784         lun = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip, DDI_PROP_DONTPASS,
2785             LUN_PROP, 0);
2786 
2787         if ((phynum = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip,
2788             DDI_PROP_DONTPASS, "sata-phy", -1)) != -1) {
2789                 /*
2790                  * Stick in the address of form "pPHY,LUN"
2791                  */
2792                 reallen = snprintf(name, len, "p%x,%x", phynum, lun);
2793         } else if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lun_dip,
2794             DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &sas_wwn)
2795             == DDI_PROP_SUCCESS) {
2796                 /*
2797                  * Stick in the address of the form "wWWN,LUN"
2798                  */
2799                 reallen = snprintf(name, len, "%s,%x", sas_wwn, lun);
2800                 ddi_prop_free(sas_wwn);
2801         } else {
2802                 return (DDI_FAILURE);
2803         }
2804 
2805         ASSERT(reallen < len);
2806         if (reallen >= len) {
2807                 mptsas_log(0, CE_WARN, "!mptsas_get_name: name parameter "
2808                     "length too small, it needs to be %d bytes", reallen + 1);
2809         }
2810         return (DDI_SUCCESS);
2811 }
2812 
2813 /*
2814  * tran_tgt_init(9E) - target device instance initialization
2815  */
2816 static int
2817 mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
2818     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
2819 {
2820 #ifndef __lock_lint
2821         _NOTE(ARGUNUSED(hba_tran))
2822 #endif
2823 
2824         /*
2825          * At this point, the scsi_device structure already exists
2826          * and has been initialized.
2827          *
2828          * Use this function to allocate target-private data structures,
2829          * if needed by this HBA.  Add revised flow-control and queue
2830          * properties for child here, if desired and if you can tell they
2831          * support tagged queueing by now.
2832          */
2833         mptsas_t                *mpt;
2834         int                     lun = sd->sd_address.a_lun;
2835         mdi_pathinfo_t          *pip = NULL;
2836         mptsas_tgt_private_t    *tgt_private = NULL;
2837         mptsas_target_t         *ptgt = NULL;
2838         char                    *psas_wwn = NULL;
2839         mptsas_phymask_t        phymask = 0;
2840         uint64_t                sas_wwn = 0;
2841         mptsas_target_addr_t    addr;
2842         mpt = SDEV2MPT(sd);
2843 
2844         ASSERT(scsi_hba_iport_unit_address(hba_dip) != 0);
2845 
2846         NDBG0(("mptsas_scsi_tgt_init: hbadip=0x%p tgtdip=0x%p lun=%d",
2847             (void *)hba_dip, (void *)tgt_dip, lun));
2848 
2849         if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
2850                 (void) ndi_merge_node(tgt_dip, mptsas_name_child);
2851                 ddi_set_name_addr(tgt_dip, NULL);
2852                 return (DDI_FAILURE);
2853         }
2854         /*
2855          * phymask is 0 means the virtual port for RAID
2856          */
2857         phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, hba_dip, 0,
2858             "phymask", 0);
2859         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2860                 if ((pip = (void *)(sd->sd_private)) == NULL) {
2861                         /*
2862                          * Very bad news if this occurs. Somehow scsi_vhci has
2863                          * lost the pathinfo node for this target.
2864                          */
2865                         return (DDI_NOT_WELL_FORMED);
2866                 }
2867 
2868                 if (mdi_prop_lookup_int(pip, LUN_PROP, &lun) !=
2869                     DDI_PROP_SUCCESS) {
2870                         mptsas_log(mpt, CE_WARN, "Get lun property failed\n");
2871                         return (DDI_FAILURE);
2872                 }
2873 
2874                 if (mdi_prop_lookup_string(pip, SCSI_ADDR_PROP_TARGET_PORT,
2875                     &psas_wwn) == MDI_SUCCESS) {
2876                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2877                                 sas_wwn = 0;
2878                         }
2879                         (void) mdi_prop_free(psas_wwn);
2880                 }
2881         } else {
2882                 lun = ddi_prop_get_int(DDI_DEV_T_ANY, tgt_dip,
2883                     DDI_PROP_DONTPASS, LUN_PROP, 0);
2884                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip,
2885                     DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &psas_wwn) ==
2886                     DDI_PROP_SUCCESS) {
2887                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2888                                 sas_wwn = 0;
2889                         }
2890                         ddi_prop_free(psas_wwn);
2891                 } else {
2892                         sas_wwn = 0;
2893                 }
2894         }
2895 
2896         ASSERT((sas_wwn != 0) || (phymask != 0));
2897         addr.mta_wwn = sas_wwn;
2898         addr.mta_phymask = phymask;
2899         mutex_enter(&mpt->m_mutex);
2900         ptgt = refhash_lookup(mpt->m_targets, &addr);
2901         mutex_exit(&mpt->m_mutex);
2902         if (ptgt == NULL) {
2903                 mptsas_log(mpt, CE_WARN, "!tgt_init: target doesn't exist or "
2904                     "gone already! phymask:%x, saswwn %"PRIx64, phymask,
2905                     sas_wwn);
2906                 return (DDI_FAILURE);
2907         }
2908         if (hba_tran->tran_tgt_private == NULL) {
2909                 tgt_private = kmem_zalloc(sizeof (mptsas_tgt_private_t),
2910                     KM_SLEEP);
2911                 tgt_private->t_lun = lun;
2912                 tgt_private->t_private = ptgt;
2913                 hba_tran->tran_tgt_private = tgt_private;
2914         }
2915 
2916         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2917                 return (DDI_SUCCESS);
2918         }
2919         mutex_enter(&mpt->m_mutex);
2920 
2921         if (ptgt->m_deviceinfo &
2922             (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
2923             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
2924                 uchar_t *inq89 = NULL;
2925                 int inq89_len = 0x238;
2926                 int reallen = 0;
2927                 int rval = 0;
2928                 struct sata_id *sid = NULL;
2929                 char model[SATA_ID_MODEL_LEN + 1];
2930                 char fw[SATA_ID_FW_LEN + 1];
2931                 char *vid, *pid;
2932                 int i;
2933 
2934                 mutex_exit(&mpt->m_mutex);
2935                 /*
2936                  * According SCSI/ATA Translation -2 (SAT-2) revision 01a
2937                  * chapter 12.4.2 VPD page 89h includes 512 bytes ATA IDENTIFY
2938                  * DEVICE data or ATA IDENTIFY PACKET DEVICE data.
2939                  */
2940                 inq89 = kmem_zalloc(inq89_len, KM_SLEEP);
2941                 rval = mptsas_inquiry(mpt, ptgt, 0, 0x89,
2942                     inq89, inq89_len, &reallen, 1);
2943 
2944                 if (rval != 0) {
2945                         if (inq89 != NULL) {
2946                                 kmem_free(inq89, inq89_len);
2947                         }
2948 
2949                         mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
2950                             "0x89 for SATA target:%x failed!", ptgt->m_devhdl);
2951                         return (DDI_SUCCESS);
2952                 }
2953                 sid = (void *)(&inq89[60]);
2954 
2955                 swab(sid->ai_model, model, SATA_ID_MODEL_LEN);
2956                 swab(sid->ai_fw, fw, SATA_ID_FW_LEN);
2957 
2958                 model[SATA_ID_MODEL_LEN] = 0;
2959                 fw[SATA_ID_FW_LEN] = 0;
2960 
2961                 /*
2962                  * split model into into vid/pid
2963                  */
2964                 for (i = 0, pid = model; i < SATA_ID_MODEL_LEN; i++, pid++)
2965                         if ((*pid == ' ') || (*pid == '\t'))
2966                                 break;
2967                 if (i < SATA_ID_MODEL_LEN) {
2968                         vid = model;
2969                         /*
2970                          * terminate vid, establish pid
2971                          */
2972                         *pid++ = 0;
2973                 } else {
2974                         /*
2975                          * vid will stay "ATA     ", the rule is same
2976                          * as sata framework implementation.
2977                          */
2978                         vid = NULL;
2979                         /*
2980                          * model is all pid
2981                          */
2982                         pid = model;
2983                 }
2984 
2985                 /*
2986                  * override SCSA "inquiry-*" properties
2987                  */
2988                 if (vid)
2989                         (void) scsi_device_prop_update_inqstring(sd,
2990                             INQUIRY_VENDOR_ID, vid, strlen(vid));
2991                 if (pid)
2992                         (void) scsi_device_prop_update_inqstring(sd,
2993                             INQUIRY_PRODUCT_ID, pid, strlen(pid));
2994                 (void) scsi_device_prop_update_inqstring(sd,
2995                     INQUIRY_REVISION_ID, fw, strlen(fw));
2996 
2997                 if (inq89 != NULL) {
2998                         kmem_free(inq89, inq89_len);
2999                 }
3000         } else {
3001                 mutex_exit(&mpt->m_mutex);
3002         }
3003 
3004         return (DDI_SUCCESS);
3005 }
3006 /*
3007  * tran_tgt_free(9E) - target device instance deallocation
3008  */
3009 static void
3010 mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
3011     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
3012 {
3013 #ifndef __lock_lint
3014         _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran, sd))
3015 #endif
3016 
3017         mptsas_tgt_private_t    *tgt_private = hba_tran->tran_tgt_private;
3018 
3019         if (tgt_private != NULL) {
3020                 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
3021                 hba_tran->tran_tgt_private = NULL;
3022         }
3023 }
3024 
3025 /*
3026  * scsi_pkt handling
3027  *
3028  * Visible to the external world via the transport structure.
3029  */
3030 
3031 /*
3032  * Notes:
3033  *      - transport the command to the addressed SCSI target/lun device
3034  *      - normal operation is to schedule the command to be transported,
3035  *        and return TRAN_ACCEPT if this is successful.
3036  *      - if NO_INTR, tran_start must poll device for command completion
3037  */
3038 static int
3039 mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
3040 {
3041 #ifndef __lock_lint
3042         _NOTE(ARGUNUSED(ap))
3043 #endif
3044         mptsas_t        *mpt = PKT2MPT(pkt);
3045         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
3046         int             rval;
3047         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3048 
3049         NDBG1(("mptsas_scsi_start: pkt=0x%p", (void *)pkt));
3050         ASSERT(ptgt);
3051         if (ptgt == NULL)
3052                 return (TRAN_FATAL_ERROR);
3053 
3054         /*
3055          * prepare the pkt before taking mutex.
3056          */
3057         rval = mptsas_prepare_pkt(cmd);
3058         if (rval != TRAN_ACCEPT) {
3059                 return (rval);
3060         }
3061 
3062         /*
3063          * Send the command to target/lun, however your HBA requires it.
3064          * If busy, return TRAN_BUSY; if there's some other formatting error
3065          * in the packet, return TRAN_BADPKT; otherwise, fall through to the
3066          * return of TRAN_ACCEPT.
3067          *
3068          * Remember that access to shared resources, including the mptsas_t
3069          * data structure and the HBA hardware registers, must be protected
3070          * with mutexes, here and everywhere.
3071          *
3072          * Also remember that at interrupt time, you'll get an argument
3073          * to the interrupt handler which is a pointer to your mptsas_t
3074          * structure; you'll have to remember which commands are outstanding
3075          * and which scsi_pkt is the currently-running command so the
3076          * interrupt handler can refer to the pkt to set completion
3077          * status, call the target driver back through pkt_comp, etc.
3078          *
3079          * If the instance lock is held by other thread, don't spin to wait
3080          * for it. Instead, queue the cmd and next time when the instance lock
3081          * is not held, accept all the queued cmd. A extra tx_waitq is
3082          * introduced to protect the queue.
3083          *
3084          * The polled cmd will not be queud and accepted as usual.
3085          *
3086          * Under the tx_waitq mutex, record whether a thread is draining
3087          * the tx_waitq.  An IO requesting thread that finds the instance
3088          * mutex contended appends to the tx_waitq and while holding the
3089          * tx_wait mutex, if the draining flag is not set, sets it and then
3090          * proceeds to spin for the instance mutex. This scheme ensures that
3091          * the last cmd in a burst be processed.
3092          *
3093          * we enable this feature only when the helper threads are enabled,
3094          * at which we think the loads are heavy.
3095          *
3096          * per instance mutex m_tx_waitq_mutex is introduced to protect the
3097          * m_tx_waitqtail, m_tx_waitq, m_tx_draining.
3098          */
3099 
3100         if (mpt->m_doneq_thread_n) {
3101                 if (mutex_tryenter(&mpt->m_mutex) != 0) {
3102                         rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3103                         mutex_exit(&mpt->m_mutex);
3104                 } else if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3105                         mutex_enter(&mpt->m_mutex);
3106                         rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3107                         mutex_exit(&mpt->m_mutex);
3108                 } else {
3109                         mutex_enter(&mpt->m_tx_waitq_mutex);
3110                         /*
3111                          * ptgt->m_dr_flag is protected by m_mutex or
3112                          * m_tx_waitq_mutex. In this case, m_tx_waitq_mutex
3113                          * is acquired.
3114                          */
3115                         if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3116                                 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3117                                         /*
3118                                          * The command should be allowed to
3119                                          * retry by returning TRAN_BUSY to
3120                                          * to stall the I/O's which come from
3121                                          * scsi_vhci since the device/path is
3122                                          * in unstable state now.
3123                                          */
3124                                         mutex_exit(&mpt->m_tx_waitq_mutex);
3125                                         return (TRAN_BUSY);
3126                                 } else {
3127                                         /*
3128                                          * The device is offline, just fail the
3129                                          * command by returning
3130                                          * TRAN_FATAL_ERROR.
3131                                          */
3132                                         mutex_exit(&mpt->m_tx_waitq_mutex);
3133                                         return (TRAN_FATAL_ERROR);
3134                                 }
3135                         }
3136                         if (mpt->m_tx_draining) {
3137                                 cmd->cmd_flags |= CFLAG_TXQ;
3138                                 *mpt->m_tx_waitqtail = cmd;
3139                                 mpt->m_tx_waitqtail = &cmd->cmd_linkp;
3140                                 mutex_exit(&mpt->m_tx_waitq_mutex);
3141                         } else { /* drain the queue */
3142                                 mpt->m_tx_draining = 1;
3143                                 mutex_exit(&mpt->m_tx_waitq_mutex);
3144                                 mutex_enter(&mpt->m_mutex);
3145                                 rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3146                                 mutex_exit(&mpt->m_mutex);
3147                         }
3148                 }
3149         } else {
3150                 mutex_enter(&mpt->m_mutex);
3151                 /*
3152                  * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
3153                  * in this case, m_mutex is acquired.
3154                  */
3155                 if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3156                         if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3157                                 /*
3158                                  * commands should be allowed to retry by
3159                                  * returning TRAN_BUSY to stall the I/O's
3160                                  * which come from scsi_vhci since the device/
3161                                  * path is in unstable state now.
3162                                  */
3163                                 mutex_exit(&mpt->m_mutex);
3164                                 return (TRAN_BUSY);
3165                         } else {
3166                                 /*
3167                                  * The device is offline, just fail the
3168                                  * command by returning TRAN_FATAL_ERROR.
3169                                  */
3170                                 mutex_exit(&mpt->m_mutex);
3171                                 return (TRAN_FATAL_ERROR);
3172                         }
3173                 }
3174                 rval = mptsas_accept_pkt(mpt, cmd);
3175                 mutex_exit(&mpt->m_mutex);
3176         }
3177 
3178         return (rval);
3179 }
3180 
3181 /*
3182  * Accept all the queued cmds(if any) before accept the current one.
3183  */
3184 static int
3185 mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3186 {
3187         int rval;
3188         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3189 
3190         ASSERT(mutex_owned(&mpt->m_mutex));
3191         /*
3192          * The call to mptsas_accept_tx_waitq() must always be performed
3193          * because that is where mpt->m_tx_draining is cleared.
3194          */
3195         mutex_enter(&mpt->m_tx_waitq_mutex);
3196         mptsas_accept_tx_waitq(mpt);
3197         mutex_exit(&mpt->m_tx_waitq_mutex);
3198         /*
3199          * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
3200          * in this case, m_mutex is acquired.
3201          */
3202         if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3203                 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3204                         /*
3205                          * The command should be allowed to retry by returning
3206                          * TRAN_BUSY to stall the I/O's which come from
3207                          * scsi_vhci since the device/path is in unstable state
3208                          * now.
3209                          */
3210                         return (TRAN_BUSY);
3211                 } else {
3212                         /*
3213                          * The device is offline, just fail the command by
3214                          * return TRAN_FATAL_ERROR.
3215                          */
3216                         return (TRAN_FATAL_ERROR);
3217                 }
3218         }
3219         rval = mptsas_accept_pkt(mpt, cmd);
3220 
3221         return (rval);
3222 }
3223 
3224 static int
3225 mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3226 {
3227         int             rval = TRAN_ACCEPT;
3228         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3229 
3230         NDBG1(("mptsas_accept_pkt: cmd=0x%p", (void *)cmd));
3231 
3232         ASSERT(mutex_owned(&mpt->m_mutex));
3233 
3234         if ((cmd->cmd_flags & CFLAG_PREPARED) == 0) {
3235                 rval = mptsas_prepare_pkt(cmd);
3236                 if (rval != TRAN_ACCEPT) {
3237                         cmd->cmd_flags &= ~CFLAG_TRANFLAG;
3238                         return (rval);
3239                 }
3240         }
3241 
3242         /*
3243          * reset the throttle if we were draining
3244          */
3245         if ((ptgt->m_t_ncmds == 0) &&
3246             (ptgt->m_t_throttle == DRAIN_THROTTLE)) {
3247                 NDBG23(("reset throttle"));
3248                 ASSERT(ptgt->m_reset_delay == 0);
3249                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
3250         }
3251 
3252         /*
3253          * If HBA is being reset, the DevHandles are being re-initialized,
3254          * which means that they could be invalid even if the target is still
3255          * attached.  Check if being reset and if DevHandle is being
3256          * re-initialized.  If this is the case, return BUSY so the I/O can be
3257          * retried later.
3258          */
3259         if ((ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) && mpt->m_in_reset) {
3260                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
3261                 if (cmd->cmd_flags & CFLAG_TXQ) {
3262                         mptsas_doneq_add(mpt, cmd);
3263                         mptsas_doneq_empty(mpt);
3264                         return (rval);
3265                 } else {
3266                         return (TRAN_BUSY);
3267                 }
3268         }
3269 
3270         /*
3271          * If device handle has already been invalidated, just
3272          * fail the command. In theory, command from scsi_vhci
3273          * client is impossible send down command with invalid
3274          * devhdl since devhdl is set after path offline, target
3275          * driver is not suppose to select a offlined path.
3276          */
3277         if (ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) {
3278                 NDBG20(("rejecting command, it might because invalid devhdl "
3279                     "request."));
3280                 mptsas_set_pkt_reason(mpt, cmd, CMD_DEV_GONE, STAT_TERMINATED);
3281                 if (cmd->cmd_flags & CFLAG_TXQ) {
3282                         mptsas_doneq_add(mpt, cmd);
3283                         mptsas_doneq_empty(mpt);
3284                         return (rval);
3285                 } else {
3286                         return (TRAN_FATAL_ERROR);
3287                 }
3288         }
3289         /*
3290          * The first case is the normal case.  mpt gets a command from the
3291          * target driver and starts it.
3292          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
3293          * commands is m_max_requests - 2.
3294          */
3295         if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
3296             (ptgt->m_t_throttle > HOLD_THROTTLE) &&
3297             (ptgt->m_t_ncmds < ptgt->m_t_throttle) &&
3298             (ptgt->m_reset_delay == 0) &&
3299             (ptgt->m_t_nwait == 0) &&
3300             ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0)) {
3301                 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
3302                         (void) mptsas_start_cmd(mpt, cmd);
3303                 } else {
3304                         mptsas_waitq_add(mpt, cmd);
3305                 }
3306         } else {
3307                 /*
3308                  * Add this pkt to the work queue
3309                  */
3310                 mptsas_waitq_add(mpt, cmd);
3311 
3312                 if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3313                         (void) mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
3314 
3315                         /*
3316                          * Only flush the doneq if this is not a TM
3317                          * cmd.  For TM cmds the flushing of the
3318                          * doneq will be done in those routines.
3319                          */
3320                         if ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
3321                                 mptsas_doneq_empty(mpt);
3322                         }
3323                 }
3324         }
3325         return (rval);
3326 }
3327 
3328 int
3329 mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
3330 {
3331         mptsas_slots_t *slots = mpt->m_active;
3332         uint_t slot, start_rotor;
3333         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3334 
3335         ASSERT(MUTEX_HELD(&mpt->m_mutex));
3336 
3337         /*
3338          * Account for reserved TM request slot and reserved SMID of 0.
3339          */
3340         ASSERT(slots->m_n_normal == (mpt->m_max_requests - 2));
3341 
3342         /*
3343          * Find the next available slot, beginning at m_rotor.  If no slot is
3344          * available, we'll return FALSE to indicate that.  This mechanism
3345          * considers only the normal slots, not the reserved slot 0 nor the
3346          * task management slot m_n_normal + 1.  The rotor is left to point to
3347          * the normal slot after the one we select, unless we select the last
3348          * normal slot in which case it returns to slot 1.
3349          */
3350         start_rotor = slots->m_rotor;
3351         do {
3352                 slot = slots->m_rotor++;
3353                 if (slots->m_rotor > slots->m_n_normal)
3354                         slots->m_rotor = 1;
3355 
3356                 if (slots->m_rotor == start_rotor)
3357                         break;
3358         } while (slots->m_slot[slot] != NULL);
3359 
3360         if (slots->m_slot[slot] != NULL)
3361                 return (FALSE);
3362 
3363         ASSERT(slot != 0 && slot <= slots->m_n_normal);
3364 
3365         cmd->cmd_slot = slot;
3366         slots->m_slot[slot] = cmd;
3367         mpt->m_ncmds++;
3368 
3369         /*
3370          * only increment per target ncmds if this is not a
3371          * command that has no target associated with it (i.e. a
3372          * event acknoledgment)
3373          */
3374         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
3375                 ptgt->m_t_ncmds++;
3376         }
3377         cmd->cmd_active_timeout = cmd->cmd_pkt->pkt_time;
3378 
3379         /*
3380          * If initial timout is less than or equal to one tick, bump
3381          * the timeout by a tick so that command doesn't timeout before
3382          * its allotted time.
3383          */
3384         if (cmd->cmd_active_timeout <= mptsas_scsi_watchdog_tick) {
3385                 cmd->cmd_active_timeout += mptsas_scsi_watchdog_tick;
3386         }
3387         return (TRUE);
3388 }
3389 
3390 /*
3391  * prepare the pkt:
3392  * the pkt may have been resubmitted or just reused so
3393  * initialize some fields and do some checks.
3394  */
3395 static int
3396 mptsas_prepare_pkt(mptsas_cmd_t *cmd)
3397 {
3398         struct scsi_pkt *pkt = CMD2PKT(cmd);
3399 
3400         NDBG1(("mptsas_prepare_pkt: cmd=0x%p", (void *)cmd));
3401 
3402         /*
3403          * Reinitialize some fields that need it; the packet may
3404          * have been resubmitted
3405          */
3406         pkt->pkt_reason = CMD_CMPLT;
3407         pkt->pkt_state = 0;
3408         pkt->pkt_statistics = 0;
3409         pkt->pkt_resid = 0;
3410         cmd->cmd_age = 0;
3411         cmd->cmd_pkt_flags = pkt->pkt_flags;
3412 
3413         /*
3414          * zero status byte.
3415          */
3416         *(pkt->pkt_scbp) = 0;
3417 
3418         if (cmd->cmd_flags & CFLAG_DMAVALID) {
3419                 pkt->pkt_resid = cmd->cmd_dmacount;
3420 
3421                 /*
3422                  * consistent packets need to be sync'ed first
3423                  * (only for data going out)
3424                  */
3425                 if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
3426                     (cmd->cmd_flags & CFLAG_DMASEND)) {
3427                         (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
3428                             DDI_DMA_SYNC_FORDEV);
3429                 }
3430         }
3431 
3432         cmd->cmd_flags =
3433             (cmd->cmd_flags & ~(CFLAG_TRANFLAG)) |
3434             CFLAG_PREPARED | CFLAG_IN_TRANSPORT;
3435 
3436         return (TRAN_ACCEPT);
3437 }
3438 
3439 /*
3440  * tran_init_pkt(9E) - allocate scsi_pkt(9S) for command
3441  *
3442  * One of three possibilities:
3443  *      - allocate scsi_pkt
3444  *      - allocate scsi_pkt and DMA resources
3445  *      - allocate DMA resources to an already-allocated pkt
3446  */
3447 static struct scsi_pkt *
3448 mptsas_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
3449     struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
3450     int (*callback)(), caddr_t arg)
3451 {
3452         mptsas_cmd_t            *cmd, *new_cmd;
3453         mptsas_t                *mpt = ADDR2MPT(ap);
3454         int                     failure = 1;
3455         uint_t                  oldcookiec;
3456         mptsas_target_t         *ptgt = NULL;
3457         int                     rval;
3458         mptsas_tgt_private_t    *tgt_private;
3459         int                     kf;
3460 
3461         kf = (callback == SLEEP_FUNC)? KM_SLEEP: KM_NOSLEEP;
3462 
3463         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
3464             tran_tgt_private;
3465         ASSERT(tgt_private != NULL);
3466         if (tgt_private == NULL) {
3467                 return (NULL);
3468         }
3469         ptgt = tgt_private->t_private;
3470         ASSERT(ptgt != NULL);
3471         if (ptgt == NULL)
3472                 return (NULL);
3473         ap->a_target = ptgt->m_devhdl;
3474         ap->a_lun = tgt_private->t_lun;
3475 
3476         ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC);
3477 #ifdef MPTSAS_TEST_EXTRN_ALLOC
3478         statuslen *= 100; tgtlen *= 4;
3479 #endif
3480         NDBG3(("mptsas_scsi_init_pkt:\n"
3481             "\ttgt=%d in=0x%p bp=0x%p clen=%d slen=%d tlen=%d flags=%x",
3482             ap->a_target, (void *)pkt, (void *)bp,
3483             cmdlen, statuslen, tgtlen, flags));
3484 
3485         /*
3486          * Allocate the new packet.
3487          */
3488         if (pkt == NULL) {
3489                 ddi_dma_handle_t        save_dma_handle;
3490                 ddi_dma_handle_t        save_arq_dma_handle;
3491                 struct buf              *save_arq_bp;
3492                 ddi_dma_cookie_t        save_arqcookie;
3493 
3494                 cmd = kmem_cache_alloc(mpt->m_kmem_cache, kf);
3495 
3496                 if (cmd) {
3497                         save_dma_handle = cmd->cmd_dmahandle;
3498                         save_arq_dma_handle = cmd->cmd_arqhandle;
3499                         save_arq_bp = cmd->cmd_arq_buf;
3500                         save_arqcookie = cmd->cmd_arqcookie;
3501                         bzero(cmd, sizeof (*cmd) + scsi_pkt_size());
3502                         cmd->cmd_dmahandle = save_dma_handle;
3503                         cmd->cmd_arqhandle = save_arq_dma_handle;
3504                         cmd->cmd_arq_buf = save_arq_bp;
3505                         cmd->cmd_arqcookie = save_arqcookie;
3506 
3507                         pkt = (void *)((uchar_t *)cmd +
3508                             sizeof (struct mptsas_cmd));
3509                         pkt->pkt_ha_private = (opaque_t)cmd;
3510                         pkt->pkt_address = *ap;
3511                         pkt->pkt_private = (opaque_t)cmd->cmd_pkt_private;
3512                         pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb;
3513                         pkt->pkt_cdbp = (opaque_t)&cmd->cmd_cdb;
3514                         cmd->cmd_pkt = (struct scsi_pkt *)pkt;
3515                         cmd->cmd_cdblen = (uchar_t)cmdlen;
3516                         cmd->cmd_scblen = statuslen;
3517                         cmd->cmd_rqslen = SENSE_LENGTH;
3518                         cmd->cmd_tgt_addr = ptgt;
3519                         failure = 0;
3520                 }
3521 
3522                 if (failure || (cmdlen > sizeof (cmd->cmd_cdb)) ||
3523                     (tgtlen > PKT_PRIV_LEN) ||
3524                     (statuslen > EXTCMDS_STATUS_SIZE)) {
3525                         if (failure == 0) {
3526                                 /*
3527                                  * if extern alloc fails, all will be
3528                                  * deallocated, including cmd
3529                                  */
3530                                 failure = mptsas_pkt_alloc_extern(mpt, cmd,
3531                                     cmdlen, tgtlen, statuslen, kf);
3532                         }
3533                         if (failure) {
3534                                 /*
3535                                  * if extern allocation fails, it will
3536                                  * deallocate the new pkt as well
3537                                  */
3538                                 return (NULL);
3539                         }
3540                 }
3541                 new_cmd = cmd;
3542 
3543         } else {
3544                 cmd = PKT2CMD(pkt);
3545                 new_cmd = NULL;
3546         }
3547 
3548 
3549         /* grab cmd->cmd_cookiec here as oldcookiec */
3550 
3551         oldcookiec = cmd->cmd_cookiec;
3552 
3553         /*
3554          * If the dma was broken up into PARTIAL transfers cmd_nwin will be
3555          * greater than 0 and we'll need to grab the next dma window
3556          */
3557         /*
3558          * SLM-not doing extra command frame right now; may add later
3559          */
3560 
3561         if (cmd->cmd_nwin > 0) {
3562 
3563                 /*
3564                  * Make sure we havn't gone past the the total number
3565                  * of windows
3566                  */
3567                 if (++cmd->cmd_winindex >= cmd->cmd_nwin) {
3568                         return (NULL);
3569                 }
3570                 if (ddi_dma_getwin(cmd->cmd_dmahandle, cmd->cmd_winindex,
3571                     &cmd->cmd_dma_offset, &cmd->cmd_dma_len,
3572                     &cmd->cmd_cookie, &cmd->cmd_cookiec) == DDI_FAILURE) {
3573                         return (NULL);
3574                 }
3575                 goto get_dma_cookies;
3576         }
3577 
3578 
3579         if (flags & PKT_XARQ) {
3580                 cmd->cmd_flags |= CFLAG_XARQ;
3581         }
3582 
3583         /*
3584          * DMA resource allocation.  This version assumes your
3585          * HBA has some sort of bus-mastering or onboard DMA capability, with a
3586          * scatter-gather list of length MPTSAS_MAX_DMA_SEGS, as given in the
3587          * ddi_dma_attr_t structure and passed to scsi_impl_dmaget.
3588          */
3589         if (bp && (bp->b_bcount != 0) &&
3590             (cmd->cmd_flags & CFLAG_DMAVALID) == 0) {
3591 
3592                 int     cnt, dma_flags;
3593                 mptti_t *dmap;          /* ptr to the S/G list */
3594 
3595                 /*
3596                  * Set up DMA memory and position to the next DMA segment.
3597                  */
3598                 ASSERT(cmd->cmd_dmahandle != NULL);
3599 
3600                 if (bp->b_flags & B_READ) {
3601                         dma_flags = DDI_DMA_READ;
3602                         cmd->cmd_flags &= ~CFLAG_DMASEND;
3603                 } else {
3604                         dma_flags = DDI_DMA_WRITE;
3605                         cmd->cmd_flags |= CFLAG_DMASEND;
3606                 }
3607                 if (flags & PKT_CONSISTENT) {
3608                         cmd->cmd_flags |= CFLAG_CMDIOPB;
3609                         dma_flags |= DDI_DMA_CONSISTENT;
3610                 }
3611 
3612                 if (flags & PKT_DMA_PARTIAL) {
3613                         dma_flags |= DDI_DMA_PARTIAL;
3614                 }
3615 
3616                 /*
3617                  * workaround for byte hole issue on psycho and
3618                  * schizo pre 2.1
3619                  */
3620                 if ((bp->b_flags & B_READ) && ((bp->b_flags &
3621                     (B_PAGEIO|B_REMAPPED)) != B_PAGEIO) &&
3622                     ((uintptr_t)bp->b_un.b_addr & 0x7)) {
3623                         dma_flags |= DDI_DMA_CONSISTENT;
3624                 }
3625 
3626                 rval = ddi_dma_buf_bind_handle(cmd->cmd_dmahandle, bp,
3627                     dma_flags, callback, arg,
3628                     &cmd->cmd_cookie, &cmd->cmd_cookiec);
3629                 if (rval == DDI_DMA_PARTIAL_MAP) {
3630                         (void) ddi_dma_numwin(cmd->cmd_dmahandle,
3631                             &cmd->cmd_nwin);
3632                         cmd->cmd_winindex = 0;
3633                         (void) ddi_dma_getwin(cmd->cmd_dmahandle,
3634                             cmd->cmd_winindex, &cmd->cmd_dma_offset,
3635                             &cmd->cmd_dma_len, &cmd->cmd_cookie,
3636                             &cmd->cmd_cookiec);
3637                 } else if (rval && (rval != DDI_DMA_MAPPED)) {
3638                         switch (rval) {
3639                         case DDI_DMA_NORESOURCES:
3640                                 bioerror(bp, 0);
3641                                 break;
3642                         case DDI_DMA_BADATTR:
3643                         case DDI_DMA_NOMAPPING:
3644                                 bioerror(bp, EFAULT);
3645                                 break;
3646                         case DDI_DMA_TOOBIG:
3647                         default:
3648                                 bioerror(bp, EINVAL);
3649                                 break;
3650                         }
3651                         cmd->cmd_flags &= ~CFLAG_DMAVALID;
3652                         if (new_cmd) {
3653                                 mptsas_scsi_destroy_pkt(ap, pkt);
3654                         }
3655                         return ((struct scsi_pkt *)NULL);
3656                 }
3657 
3658 get_dma_cookies:
3659                 cmd->cmd_flags |= CFLAG_DMAVALID;
3660                 ASSERT(cmd->cmd_cookiec > 0);
3661 
3662                 if (cmd->cmd_cookiec > MPTSAS_MAX_CMD_SEGS) {
3663                         mptsas_log(mpt, CE_NOTE, "large cookiec received %d\n",
3664                             cmd->cmd_cookiec);
3665                         bioerror(bp, EINVAL);
3666                         if (new_cmd) {
3667                                 mptsas_scsi_destroy_pkt(ap, pkt);
3668                         }
3669                         return ((struct scsi_pkt *)NULL);
3670                 }
3671 
3672                 /*
3673                  * Allocate extra SGL buffer if needed.
3674                  */
3675                 if ((cmd->cmd_cookiec > MPTSAS_MAX_FRAME_SGES64(mpt)) &&
3676                     (cmd->cmd_extra_frames == NULL)) {
3677                         if (mptsas_alloc_extra_sgl_frame(mpt, cmd) ==
3678                             DDI_FAILURE) {
3679                                 mptsas_log(mpt, CE_WARN, "MPT SGL mem alloc "
3680                                     "failed");
3681                                 bioerror(bp, ENOMEM);
3682                                 if (new_cmd) {
3683                                         mptsas_scsi_destroy_pkt(ap, pkt);
3684                                 }
3685                                 return ((struct scsi_pkt *)NULL);
3686                         }
3687                 }
3688 
3689                 /*
3690                  * Always use scatter-gather transfer
3691                  * Use the loop below to store physical addresses of
3692                  * DMA segments, from the DMA cookies, into your HBA's
3693                  * scatter-gather list.
3694                  * We need to ensure we have enough kmem alloc'd
3695                  * for the sg entries since we are no longer using an
3696                  * array inside mptsas_cmd_t.
3697                  *
3698                  * We check cmd->cmd_cookiec against oldcookiec so
3699                  * the scatter-gather list is correctly allocated
3700                  */
3701 
3702                 if (oldcookiec != cmd->cmd_cookiec) {
3703                         if (cmd->cmd_sg != (mptti_t *)NULL) {
3704                                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) *
3705                                     oldcookiec);
3706                                 cmd->cmd_sg = NULL;
3707                         }
3708                 }
3709 
3710                 if (cmd->cmd_sg == (mptti_t *)NULL) {
3711                         cmd->cmd_sg = kmem_alloc((size_t)(sizeof (mptti_t)*
3712                             cmd->cmd_cookiec), kf);
3713 
3714                         if (cmd->cmd_sg == (mptti_t *)NULL) {
3715                                 mptsas_log(mpt, CE_WARN,
3716                                     "unable to kmem_alloc enough memory "
3717                                     "for scatter/gather list");
3718                 /*
3719                  * if we have an ENOMEM condition we need to behave
3720                  * the same way as the rest of this routine
3721                  */
3722 
3723                                 bioerror(bp, ENOMEM);
3724                                 if (new_cmd) {
3725                                         mptsas_scsi_destroy_pkt(ap, pkt);
3726                                 }
3727                                 return ((struct scsi_pkt *)NULL);
3728                         }
3729                 }
3730 
3731                 dmap = cmd->cmd_sg;
3732 
3733                 ASSERT(cmd->cmd_cookie.dmac_size != 0);
3734 
3735                 /*
3736                  * store the first segment into the S/G list
3737                  */
3738                 dmap->count = cmd->cmd_cookie.dmac_size;
3739                 dmap->addr.address64.Low = (uint32_t)
3740                     (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3741                 dmap->addr.address64.High = (uint32_t)
3742                     (cmd->cmd_cookie.dmac_laddress >> 32);
3743 
3744                 /*
3745                  * dmacount counts the size of the dma for this window
3746                  * (if partial dma is being used).  totaldmacount
3747                  * keeps track of the total amount of dma we have
3748                  * transferred for all the windows (needed to calculate
3749                  * the resid value below).
3750                  */
3751                 cmd->cmd_dmacount = cmd->cmd_cookie.dmac_size;
3752                 cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3753 
3754                 /*
3755                  * We already stored the first DMA scatter gather segment,
3756                  * start at 1 if we need to store more.
3757                  */
3758                 for (cnt = 1; cnt < cmd->cmd_cookiec; cnt++) {
3759                         /*
3760                          * Get next DMA cookie
3761                          */
3762                         ddi_dma_nextcookie(cmd->cmd_dmahandle,
3763                             &cmd->cmd_cookie);
3764                         dmap++;
3765 
3766                         cmd->cmd_dmacount += cmd->cmd_cookie.dmac_size;
3767                         cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3768 
3769                         /*
3770                          * store the segment parms into the S/G list
3771                          */
3772                         dmap->count = cmd->cmd_cookie.dmac_size;
3773                         dmap->addr.address64.Low = (uint32_t)
3774                             (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3775                         dmap->addr.address64.High = (uint32_t)
3776                             (cmd->cmd_cookie.dmac_laddress >> 32);
3777                 }
3778 
3779                 /*
3780                  * If this was partially allocated we set the resid
3781                  * the amount of data NOT transferred in this window
3782                  * If there is only one window, the resid will be 0
3783                  */
3784                 pkt->pkt_resid = (bp->b_bcount - cmd->cmd_totaldmacount);
3785                 NDBG16(("mptsas_dmaget: cmd_dmacount=%d.", cmd->cmd_dmacount));
3786         }
3787         return (pkt);
3788 }
3789 
3790 /*
3791  * tran_destroy_pkt(9E) - scsi_pkt(9s) deallocation
3792  *
3793  * Notes:
3794  *      - also frees DMA resources if allocated
3795  *      - implicit DMA synchonization
3796  */
3797 static void
3798 mptsas_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
3799 {
3800         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
3801         mptsas_t        *mpt = ADDR2MPT(ap);
3802 
3803         NDBG3(("mptsas_scsi_destroy_pkt: target=%d pkt=0x%p",
3804             ap->a_target, (void *)pkt));
3805 
3806         if (cmd->cmd_flags & CFLAG_DMAVALID) {
3807                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
3808                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
3809         }
3810 
3811         if (cmd->cmd_sg) {
3812                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) * cmd->cmd_cookiec);
3813                 cmd->cmd_sg = NULL;
3814         }
3815 
3816         mptsas_free_extra_sgl_frame(mpt, cmd);
3817 
3818         if ((cmd->cmd_flags &
3819             (CFLAG_FREE | CFLAG_CDBEXTERN | CFLAG_PRIVEXTERN |
3820             CFLAG_SCBEXTERN)) == 0) {
3821                 cmd->cmd_flags = CFLAG_FREE;
3822                 kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
3823         } else {
3824                 mptsas_pkt_destroy_extern(mpt, cmd);
3825         }
3826 }
3827 
3828 /*
3829  * kmem cache constructor and destructor:
3830  * When constructing, we bzero the cmd and allocate the dma handle
3831  * When destructing, just free the dma handle
3832  */
3833 static int
3834 mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags)
3835 {
3836         mptsas_cmd_t            *cmd = buf;
3837         mptsas_t                *mpt  = cdrarg;
3838         struct scsi_address     ap;
3839         uint_t                  cookiec;
3840         ddi_dma_attr_t          arq_dma_attr;
3841         int                     (*callback)(caddr_t);
3842 
3843         callback = (kmflags == KM_SLEEP)? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
3844 
3845         NDBG4(("mptsas_kmem_cache_constructor"));
3846 
3847         ap.a_hba_tran = mpt->m_tran;
3848         ap.a_target = 0;
3849         ap.a_lun = 0;
3850 
3851         /*
3852          * allocate a dma handle
3853          */
3854         if ((ddi_dma_alloc_handle(mpt->m_dip, &mpt->m_io_dma_attr, callback,
3855             NULL, &cmd->cmd_dmahandle)) != DDI_SUCCESS) {
3856                 cmd->cmd_dmahandle = NULL;
3857                 return (-1);
3858         }
3859 
3860         cmd->cmd_arq_buf = scsi_alloc_consistent_buf(&ap, (struct buf *)NULL,
3861             SENSE_LENGTH, B_READ, callback, NULL);
3862         if (cmd->cmd_arq_buf == NULL) {
3863                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3864                 cmd->cmd_dmahandle = NULL;
3865                 return (-1);
3866         }
3867 
3868         /*
3869          * allocate a arq handle
3870          */
3871         arq_dma_attr = mpt->m_msg_dma_attr;
3872         arq_dma_attr.dma_attr_sgllen = 1;
3873         if ((ddi_dma_alloc_handle(mpt->m_dip, &arq_dma_attr, callback,
3874             NULL, &cmd->cmd_arqhandle)) != DDI_SUCCESS) {
3875                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3876                 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3877                 cmd->cmd_dmahandle = NULL;
3878                 cmd->cmd_arqhandle = NULL;
3879                 return (-1);
3880         }
3881 
3882         if (ddi_dma_buf_bind_handle(cmd->cmd_arqhandle,
3883             cmd->cmd_arq_buf, (DDI_DMA_READ | DDI_DMA_CONSISTENT),
3884             callback, NULL, &cmd->cmd_arqcookie, &cookiec) != DDI_SUCCESS) {
3885                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3886                 ddi_dma_free_handle(&cmd->cmd_arqhandle);
3887                 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3888                 cmd->cmd_dmahandle = NULL;
3889                 cmd->cmd_arqhandle = NULL;
3890                 cmd->cmd_arq_buf = NULL;
3891                 return (-1);
3892         }
3893 
3894         return (0);
3895 }
3896 
3897 static void
3898 mptsas_kmem_cache_destructor(void *buf, void *cdrarg)
3899 {
3900 #ifndef __lock_lint
3901         _NOTE(ARGUNUSED(cdrarg))
3902 #endif
3903         mptsas_cmd_t    *cmd = buf;
3904 
3905         NDBG4(("mptsas_kmem_cache_destructor"));
3906 
3907         if (cmd->cmd_arqhandle) {
3908                 (void) ddi_dma_unbind_handle(cmd->cmd_arqhandle);
3909                 ddi_dma_free_handle(&cmd->cmd_arqhandle);
3910                 cmd->cmd_arqhandle = NULL;
3911         }
3912         if (cmd->cmd_arq_buf) {
3913                 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3914                 cmd->cmd_arq_buf = NULL;
3915         }
3916         if (cmd->cmd_dmahandle) {
3917                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3918                 cmd->cmd_dmahandle = NULL;
3919         }
3920 }
3921 
3922 static int
3923 mptsas_cache_frames_constructor(void *buf, void *cdrarg, int kmflags)
3924 {
3925         mptsas_cache_frames_t   *p = buf;
3926         mptsas_t                *mpt = cdrarg;
3927         ddi_dma_attr_t          frame_dma_attr;
3928         size_t                  mem_size, alloc_len;
3929         ddi_dma_cookie_t        cookie;
3930         uint_t                  ncookie;
3931         int (*callback)(caddr_t) = (kmflags == KM_SLEEP)
3932             ? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
3933 
3934         frame_dma_attr = mpt->m_msg_dma_attr;
3935         frame_dma_attr.dma_attr_align = 0x10;
3936         frame_dma_attr.dma_attr_sgllen = 1;
3937 
3938         if (ddi_dma_alloc_handle(mpt->m_dip, &frame_dma_attr, callback, NULL,
3939             &p->m_dma_hdl) != DDI_SUCCESS) {
3940                 mptsas_log(mpt, CE_WARN, "Unable to allocate dma handle for"
3941                     " extra SGL.");
3942                 return (DDI_FAILURE);
3943         }
3944 
3945         mem_size = (mpt->m_max_request_frames - 1) * mpt->m_req_frame_size;
3946 
3947         if (ddi_dma_mem_alloc(p->m_dma_hdl, mem_size, &mpt->m_dev_acc_attr,
3948             DDI_DMA_CONSISTENT, callback, NULL, (caddr_t *)&p->m_frames_addr,
3949             &alloc_len, &p->m_acc_hdl) != DDI_SUCCESS) {
3950                 ddi_dma_free_handle(&p->m_dma_hdl);
3951                 p->m_dma_hdl = NULL;
3952                 mptsas_log(mpt, CE_WARN, "Unable to allocate dma memory for"
3953                     " extra SGL.");
3954                 return (DDI_FAILURE);
3955         }
3956 
3957         if (ddi_dma_addr_bind_handle(p->m_dma_hdl, NULL, p->m_frames_addr,
3958             alloc_len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, callback, NULL,
3959             &cookie, &ncookie) != DDI_DMA_MAPPED) {
3960                 (void) ddi_dma_mem_free(&p->m_acc_hdl);
3961                 ddi_dma_free_handle(&p->m_dma_hdl);
3962                 p->m_dma_hdl = NULL;
3963                 mptsas_log(mpt, CE_WARN, "Unable to bind DMA resources for"
3964                     " extra SGL");
3965                 return (DDI_FAILURE);
3966         }
3967 
3968         /*
3969          * Store the SGL memory address.  This chip uses this
3970          * address to dma to and from the driver.  The second
3971          * address is the address mpt uses to fill in the SGL.
3972          */
3973         p->m_phys_addr = cookie.dmac_address;
3974 
3975         return (DDI_SUCCESS);
3976 }
3977 
3978 static void
3979 mptsas_cache_frames_destructor(void *buf, void *cdrarg)
3980 {
3981 #ifndef __lock_lint
3982         _NOTE(ARGUNUSED(cdrarg))
3983 #endif
3984         mptsas_cache_frames_t   *p = buf;
3985         if (p->m_dma_hdl != NULL) {
3986                 (void) ddi_dma_unbind_handle(p->m_dma_hdl);
3987                 (void) ddi_dma_mem_free(&p->m_acc_hdl);
3988                 ddi_dma_free_handle(&p->m_dma_hdl);
3989                 p->m_phys_addr = NULL;
3990                 p->m_frames_addr = NULL;
3991                 p->m_dma_hdl = NULL;
3992                 p->m_acc_hdl = NULL;
3993         }
3994 
3995 }
3996 
3997 /*
3998  * allocate and deallocate external pkt space (ie. not part of mptsas_cmd)
3999  * for non-standard length cdb, pkt_private, status areas
4000  * if allocation fails, then deallocate all external space and the pkt
4001  */
4002 /* ARGSUSED */
4003 static int
4004 mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
4005     int cmdlen, int tgtlen, int statuslen, int kf)
4006 {
4007         caddr_t                 cdbp, scbp, tgt;
4008         int                     (*callback)(caddr_t) = (kf == KM_SLEEP) ?
4009             DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
4010         struct scsi_address     ap;
4011         size_t                  senselength;
4012         ddi_dma_attr_t          ext_arq_dma_attr;
4013         uint_t                  cookiec;
4014 
4015         NDBG3(("mptsas_pkt_alloc_extern: "
4016             "cmd=0x%p cmdlen=%d tgtlen=%d statuslen=%d kf=%x",
4017             (void *)cmd, cmdlen, tgtlen, statuslen, kf));
4018 
4019         tgt = cdbp = scbp = NULL;
4020         cmd->cmd_scblen              = statuslen;
4021         cmd->cmd_privlen     = (uchar_t)tgtlen;
4022 
4023         if (cmdlen > sizeof (cmd->cmd_cdb)) {
4024                 if ((cdbp = kmem_zalloc((size_t)cmdlen, kf)) == NULL) {
4025                         goto fail;
4026                 }
4027                 cmd->cmd_pkt->pkt_cdbp = (opaque_t)cdbp;
4028                 cmd->cmd_flags |= CFLAG_CDBEXTERN;
4029         }
4030         if (tgtlen > PKT_PRIV_LEN) {
4031                 if ((tgt = kmem_zalloc((size_t)tgtlen, kf)) == NULL) {
4032                         goto fail;
4033                 }
4034                 cmd->cmd_flags |= CFLAG_PRIVEXTERN;
4035                 cmd->cmd_pkt->pkt_private = tgt;
4036         }
4037         if (statuslen > EXTCMDS_STATUS_SIZE) {
4038                 if ((scbp = kmem_zalloc((size_t)statuslen, kf)) == NULL) {
4039                         goto fail;
4040                 }
4041                 cmd->cmd_flags |= CFLAG_SCBEXTERN;
4042                 cmd->cmd_pkt->pkt_scbp = (opaque_t)scbp;
4043 
4044                 /* allocate sense data buf for DMA */
4045 
4046                 senselength = statuslen - MPTSAS_GET_ITEM_OFF(
4047                     struct scsi_arq_status, sts_sensedata);
4048                 cmd->cmd_rqslen = (uchar_t)senselength;
4049 
4050                 ap.a_hba_tran = mpt->m_tran;
4051                 ap.a_target = 0;
4052                 ap.a_lun = 0;
4053 
4054                 cmd->cmd_ext_arq_buf = scsi_alloc_consistent_buf(&ap,
4055                     (struct buf *)NULL, senselength, B_READ,
4056                     callback, NULL);
4057 
4058                 if (cmd->cmd_ext_arq_buf == NULL) {
4059                         goto fail;
4060                 }
4061                 /*
4062                  * allocate a extern arq handle and bind the buf
4063                  */
4064                 ext_arq_dma_attr = mpt->m_msg_dma_attr;
4065                 ext_arq_dma_attr.dma_attr_sgllen = 1;
4066                 if ((ddi_dma_alloc_handle(mpt->m_dip,
4067                     &ext_arq_dma_attr, callback,
4068                     NULL, &cmd->cmd_ext_arqhandle)) != DDI_SUCCESS) {
4069                         goto fail;
4070                 }
4071 
4072                 if (ddi_dma_buf_bind_handle(cmd->cmd_ext_arqhandle,
4073                     cmd->cmd_ext_arq_buf, (DDI_DMA_READ | DDI_DMA_CONSISTENT),
4074                     callback, NULL, &cmd->cmd_ext_arqcookie,
4075                     &cookiec)
4076                     != DDI_SUCCESS) {
4077                         goto fail;
4078                 }
4079                 cmd->cmd_flags |= CFLAG_EXTARQBUFVALID;
4080         }
4081         return (0);
4082 fail:
4083         mptsas_pkt_destroy_extern(mpt, cmd);
4084         return (1);
4085 }
4086 
4087 /*
4088  * deallocate external pkt space and deallocate the pkt
4089  */
4090 static void
4091 mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd)
4092 {
4093         NDBG3(("mptsas_pkt_destroy_extern: cmd=0x%p", (void *)cmd));
4094 
4095         if (cmd->cmd_flags & CFLAG_FREE) {
4096                 mptsas_log(mpt, CE_PANIC,
4097                     "mptsas_pkt_destroy_extern: freeing free packet");
4098                 _NOTE(NOT_REACHED)
4099                 /* NOTREACHED */
4100         }
4101         if (cmd->cmd_flags & CFLAG_CDBEXTERN) {
4102                 kmem_free(cmd->cmd_pkt->pkt_cdbp, (size_t)cmd->cmd_cdblen);
4103         }
4104         if (cmd->cmd_flags & CFLAG_SCBEXTERN) {
4105                 kmem_free(cmd->cmd_pkt->pkt_scbp, (size_t)cmd->cmd_scblen);
4106                 if (cmd->cmd_flags & CFLAG_EXTARQBUFVALID) {
4107                         (void) ddi_dma_unbind_handle(cmd->cmd_ext_arqhandle);
4108                 }
4109                 if (cmd->cmd_ext_arqhandle) {
4110                         ddi_dma_free_handle(&cmd->cmd_ext_arqhandle);
4111                         cmd->cmd_ext_arqhandle = NULL;
4112                 }
4113                 if (cmd->cmd_ext_arq_buf)
4114                         scsi_free_consistent_buf(cmd->cmd_ext_arq_buf);
4115         }
4116         if (cmd->cmd_flags & CFLAG_PRIVEXTERN) {
4117                 kmem_free(cmd->cmd_pkt->pkt_private, (size_t)cmd->cmd_privlen);
4118         }
4119         cmd->cmd_flags = CFLAG_FREE;
4120         kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
4121 }
4122 
4123 /*
4124  * tran_sync_pkt(9E) - explicit DMA synchronization
4125  */
4126 /*ARGSUSED*/
4127 static void
4128 mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
4129 {
4130         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
4131 
4132         NDBG3(("mptsas_scsi_sync_pkt: target=%d, pkt=0x%p",
4133             ap->a_target, (void *)pkt));
4134 
4135         if (cmd->cmd_dmahandle) {
4136                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4137                     (cmd->cmd_flags & CFLAG_DMASEND) ?
4138                     DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
4139         }
4140 }
4141 
4142 /*
4143  * tran_dmafree(9E) - deallocate DMA resources allocated for command
4144  */
4145 /*ARGSUSED*/
4146 static void
4147 mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
4148 {
4149         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
4150         mptsas_t        *mpt = ADDR2MPT(ap);
4151 
4152         NDBG3(("mptsas_scsi_dmafree: target=%d pkt=0x%p",
4153             ap->a_target, (void *)pkt));
4154 
4155         if (cmd->cmd_flags & CFLAG_DMAVALID) {
4156                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
4157                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
4158         }
4159 
4160         if (cmd->cmd_flags & CFLAG_EXTARQBUFVALID) {
4161                 (void) ddi_dma_unbind_handle(cmd->cmd_ext_arqhandle);
4162                 cmd->cmd_flags &= ~CFLAG_EXTARQBUFVALID;
4163         }
4164 
4165         mptsas_free_extra_sgl_frame(mpt, cmd);
4166 }
4167 
4168 static void
4169 mptsas_pkt_comp(struct scsi_pkt *pkt, mptsas_cmd_t *cmd)
4170 {
4171         if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
4172             (!(cmd->cmd_flags & CFLAG_DMASEND))) {
4173                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4174                     DDI_DMA_SYNC_FORCPU);
4175         }
4176         (*pkt->pkt_comp)(pkt);
4177 }
4178 
4179 static void
4180 mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd, uint32_t *control,
4181         pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4182 {
4183         uint_t                  cookiec;
4184         mptti_t                 *dmap;
4185         uint32_t                flags;
4186         pMpi2SGESimple64_t      sge;
4187         pMpi2SGEChain64_t       sgechain;
4188         ASSERT(cmd->cmd_flags & CFLAG_DMAVALID);
4189 
4190         /*
4191          * Save the number of entries in the DMA
4192          * Scatter/Gather list
4193          */
4194         cookiec = cmd->cmd_cookiec;
4195 
4196         NDBG1(("mptsas_sge_setup: cookiec=%d", cookiec));
4197 
4198         /*
4199          * Set read/write bit in control.
4200          */
4201         if (cmd->cmd_flags & CFLAG_DMASEND) {
4202                 *control |= MPI2_SCSIIO_CONTROL_WRITE;
4203         } else {
4204                 *control |= MPI2_SCSIIO_CONTROL_READ;
4205         }
4206 
4207         ddi_put32(acc_hdl, &frame->DataLength, cmd->cmd_dmacount);
4208 
4209         /*
4210          * We have 2 cases here.  First where we can fit all the
4211          * SG elements into the main frame, and the case
4212          * where we can't.
4213          * If we have more cookies than we can attach to a frame
4214          * we will need to use a chain element to point
4215          * a location of memory where the rest of the S/G
4216          * elements reside.
4217          */
4218         if (cookiec <= MPTSAS_MAX_FRAME_SGES64(mpt)) {
4219                 dmap = cmd->cmd_sg;
4220                 sge = (pMpi2SGESimple64_t)(&frame->SGL);
4221                 while (cookiec--) {
4222                         ddi_put32(acc_hdl,
4223                             &sge->Address.Low, dmap->addr.address64.Low);
4224                         ddi_put32(acc_hdl,
4225                             &sge->Address.High, dmap->addr.address64.High);
4226                         ddi_put32(acc_hdl, &sge->FlagsLength,
4227                             dmap->count);
4228                         flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4229                         flags |= ((uint32_t)
4230                             (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4231                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4232                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4233                             MPI2_SGE_FLAGS_SHIFT);
4234 
4235                         /*
4236                          * If this is the last cookie, we set the flags
4237                          * to indicate so
4238                          */
4239                         if (cookiec == 0) {
4240                                 flags |=
4241                                     ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT
4242                                     | MPI2_SGE_FLAGS_END_OF_BUFFER
4243                                     | MPI2_SGE_FLAGS_END_OF_LIST) <<
4244                                     MPI2_SGE_FLAGS_SHIFT);
4245                         }
4246                         if (cmd->cmd_flags & CFLAG_DMASEND) {
4247                                 flags |= (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4248                                     MPI2_SGE_FLAGS_SHIFT);
4249                         } else {
4250                                 flags |= (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4251                                     MPI2_SGE_FLAGS_SHIFT);
4252                         }
4253                         ddi_put32(acc_hdl, &sge->FlagsLength, flags);
4254                         dmap++;
4255                         sge++;
4256                 }
4257         } else {
4258                 /*
4259                  * Hereby we start to deal with multiple frames.
4260                  * The process is as follows:
4261                  * 1. Determine how many frames are needed for SGL element
4262                  *    storage; Note that all frames are stored in contiguous
4263                  *    memory space and in 64-bit DMA mode each element is
4264                  *    3 double-words (12 bytes) long.
4265                  * 2. Fill up the main frame. We need to do this separately
4266                  *    since it contains the SCSI IO request header and needs
4267                  *    dedicated processing. Note that the last 4 double-words
4268                  *    of the SCSI IO header is for SGL element storage
4269                  *    (MPI2_SGE_IO_UNION).
4270                  * 3. Fill the chain element in the main frame, so the DMA
4271                  *    engine can use the following frames.
4272                  * 4. Enter a loop to fill the remaining frames. Note that the
4273                  *    last frame contains no chain element.  The remaining
4274                  *    frames go into the mpt SGL buffer allocated on the fly,
4275                  *    not immediately following the main message frame, as in
4276                  *    Gen1.
4277                  * Some restrictions:
4278                  * 1. For 64-bit DMA, the simple element and chain element
4279                  *    are both of 3 double-words (12 bytes) in size, even
4280                  *    though all frames are stored in the first 4G of mem
4281                  *    range and the higher 32-bits of the address are always 0.
4282                  * 2. On some controllers (like the 1064/1068), a frame can
4283                  *    hold SGL elements with the last 1 or 2 double-words
4284                  *    (4 or 8 bytes) un-used. On these controllers, we should
4285                  *    recognize that there's not enough room for another SGL
4286                  *    element and move the sge pointer to the next frame.
4287                  */
4288                 int             i, j, k, l, frames, sgemax;
4289                 int             temp;
4290                 uint8_t         chainflags;
4291                 uint16_t        chainlength;
4292                 mptsas_cache_frames_t *p;
4293 
4294                 /*
4295                  * Sgemax is the number of SGE's that will fit
4296                  * each extra frame and frames is total
4297                  * number of frames we'll need.  1 sge entry per
4298                  * frame is reseverd for the chain element thus the -1 below.
4299                  */
4300                 sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_SGE_SIMPLE64))
4301                     - 1);
4302                 temp = (cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) / sgemax;
4303 
4304                 /*
4305                  * A little check to see if we need to round up the number
4306                  * of frames we need
4307                  */
4308                 if ((cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) - (temp *
4309                     sgemax) > 1) {
4310                         frames = (temp + 1);
4311                 } else {
4312                         frames = temp;
4313                 }
4314                 dmap = cmd->cmd_sg;
4315                 sge = (pMpi2SGESimple64_t)(&frame->SGL);
4316 
4317                 /*
4318                  * First fill in the main frame
4319                  */
4320                 for (j = 1; j < MPTSAS_MAX_FRAME_SGES64(mpt); j++) {
4321                         ddi_put32(acc_hdl, &sge->Address.Low,
4322                             dmap->addr.address64.Low);
4323                         ddi_put32(acc_hdl, &sge->Address.High,
4324                             dmap->addr.address64.High);
4325                         ddi_put32(acc_hdl, &sge->FlagsLength, dmap->count);
4326                         flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4327                         flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4328                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4329                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4330                             MPI2_SGE_FLAGS_SHIFT);
4331 
4332                         /*
4333                          * If this is the last SGE of this frame
4334                          * we set the end of list flag
4335                          */
4336                         if (j == (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) {
4337                                 flags |= ((uint32_t)
4338                                     (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4339                                     MPI2_SGE_FLAGS_SHIFT);
4340                         }
4341                         if (cmd->cmd_flags & CFLAG_DMASEND) {
4342                                 flags |=
4343                                     (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4344                                     MPI2_SGE_FLAGS_SHIFT);
4345                         } else {
4346                                 flags |=
4347                                     (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4348                                     MPI2_SGE_FLAGS_SHIFT);
4349                         }
4350                         ddi_put32(acc_hdl, &sge->FlagsLength, flags);
4351                         dmap++;
4352                         sge++;
4353                 }
4354 
4355                 /*
4356                  * Fill in the chain element in the main frame.
4357                  * About calculation on ChainOffset:
4358                  * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
4359                  *    in the end reserved for SGL element storage
4360                  *    (MPI2_SGE_IO_UNION); we should count it in our
4361                  *    calculation.  See its definition in the header file.
4362                  * 2. Constant j is the counter of the current SGL element
4363                  *    that will be processed, and (j - 1) is the number of
4364                  *    SGL elements that have been processed (stored in the
4365                  *    main frame).
4366                  * 3. ChainOffset value should be in units of double-words (4
4367                  *    bytes) so the last value should be divided by 4.
4368                  */
4369                 ddi_put8(acc_hdl, &frame->ChainOffset,
4370                     (sizeof (MPI2_SCSI_IO_REQUEST) -
4371                     sizeof (MPI2_SGE_IO_UNION) +
4372                     (j - 1) * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4373                 sgechain = (pMpi2SGEChain64_t)sge;
4374                 chainflags = (MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4375                     MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4376                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4377                 ddi_put8(acc_hdl, &sgechain->Flags, chainflags);
4378 
4379                 /*
4380                  * The size of the next frame is the accurate size of space
4381                  * (in bytes) used to store the SGL elements. j is the counter
4382                  * of SGL elements. (j - 1) is the number of SGL elements that
4383                  * have been processed (stored in frames).
4384                  */
4385                 if (frames >= 2) {
4386                         chainlength = mpt->m_req_frame_size /
4387                             sizeof (MPI2_SGE_SIMPLE64) *
4388                             sizeof (MPI2_SGE_SIMPLE64);
4389                 } else {
4390                         chainlength = ((cookiec - (j - 1)) *
4391                             sizeof (MPI2_SGE_SIMPLE64));
4392                 }
4393 
4394                 p = cmd->cmd_extra_frames;
4395 
4396                 ddi_put16(acc_hdl, &sgechain->Length, chainlength);
4397                 ddi_put32(acc_hdl, &sgechain->Address.Low,
4398                     p->m_phys_addr);
4399                 /* SGL is allocated in the first 4G mem range */
4400                 ddi_put32(acc_hdl, &sgechain->Address.High, 0);
4401 
4402                 /*
4403                  * If there are more than 2 frames left we have to
4404                  * fill in the next chain offset to the location of
4405                  * the chain element in the next frame.
4406                  * sgemax is the number of simple elements in an extra
4407                  * frame. Note that the value NextChainOffset should be
4408                  * in double-words (4 bytes).
4409                  */
4410                 if (frames >= 2) {
4411                         ddi_put8(acc_hdl, &sgechain->NextChainOffset,
4412                             (sgemax * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4413                 } else {
4414                         ddi_put8(acc_hdl, &sgechain->NextChainOffset, 0);
4415                 }
4416 
4417                 /*
4418                  * Jump to next frame;
4419                  * Starting here, chain buffers go into the per command SGL.
4420                  * This buffer is allocated when chain buffers are needed.
4421                  */
4422                 sge = (pMpi2SGESimple64_t)p->m_frames_addr;
4423                 i = cookiec;
4424 
4425                 /*
4426                  * Start filling in frames with SGE's.  If we
4427                  * reach the end of frame and still have SGE's
4428                  * to fill we need to add a chain element and
4429                  * use another frame.  j will be our counter
4430                  * for what cookie we are at and i will be
4431                  * the total cookiec. k is the current frame
4432                  */
4433                 for (k = 1; k <= frames; k++) {
4434                         for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
4435 
4436                                 /*
4437                                  * If we have reached the end of frame
4438                                  * and we have more SGE's to fill in
4439                                  * we have to fill the final entry
4440                                  * with a chain element and then
4441                                  * continue to the next frame
4442                                  */
4443                                 if ((l == (sgemax + 1)) && (k != frames)) {
4444                                         sgechain = (pMpi2SGEChain64_t)sge;
4445                                         j--;
4446                                         chainflags = (
4447                                             MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4448                                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4449                                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4450                                         ddi_put8(p->m_acc_hdl,
4451                                             &sgechain->Flags, chainflags);
4452                                         /*
4453                                          * k is the frame counter and (k + 1)
4454                                          * is the number of the next frame.
4455                                          * Note that frames are in contiguous
4456                                          * memory space.
4457                                          */
4458                                         ddi_put32(p->m_acc_hdl,
4459                                             &sgechain->Address.Low,
4460                                             (p->m_phys_addr +
4461                                             (mpt->m_req_frame_size * k)));
4462                                         ddi_put32(p->m_acc_hdl,
4463                                             &sgechain->Address.High, 0);
4464 
4465                                         /*
4466                                          * If there are more than 2 frames left
4467                                          * we have to next chain offset to
4468                                          * the location of the chain element
4469                                          * in the next frame and fill in the
4470                                          * length of the next chain
4471                                          */
4472                                         if ((frames - k) >= 2) {
4473                                                 ddi_put8(p->m_acc_hdl,
4474                                                     &sgechain->NextChainOffset,
4475                                                     (sgemax *
4476                                                     sizeof (MPI2_SGE_SIMPLE64))
4477                                                     >> 2);
4478                                                 ddi_put16(p->m_acc_hdl,
4479                                                     &sgechain->Length,
4480                                                     mpt->m_req_frame_size /
4481                                                     sizeof (MPI2_SGE_SIMPLE64) *
4482                                                     sizeof (MPI2_SGE_SIMPLE64));
4483                                         } else {
4484                                                 /*
4485                                                  * This is the last frame. Set
4486                                                  * the NextChainOffset to 0 and
4487                                                  * Length is the total size of
4488                                                  * all remaining simple elements
4489                                                  */
4490                                                 ddi_put8(p->m_acc_hdl,
4491                                                     &sgechain->NextChainOffset,
4492                                                     0);
4493                                                 ddi_put16(p->m_acc_hdl,
4494                                                     &sgechain->Length,
4495                                                     (cookiec - j) *
4496                                                     sizeof (MPI2_SGE_SIMPLE64));
4497                                         }
4498 
4499                                         /* Jump to the next frame */
4500                                         sge = (pMpi2SGESimple64_t)
4501                                             ((char *)p->m_frames_addr +
4502                                             (int)mpt->m_req_frame_size * k);
4503 
4504                                         continue;
4505                                 }
4506 
4507                                 ddi_put32(p->m_acc_hdl,
4508                                     &sge->Address.Low,
4509                                     dmap->addr.address64.Low);
4510                                 ddi_put32(p->m_acc_hdl,
4511                                     &sge->Address.High,
4512                                     dmap->addr.address64.High);
4513                                 ddi_put32(p->m_acc_hdl,
4514                                     &sge->FlagsLength, dmap->count);
4515                                 flags = ddi_get32(p->m_acc_hdl,
4516                                     &sge->FlagsLength);
4517                                 flags |= ((uint32_t)(
4518                                     MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4519                                     MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4520                                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4521                                     MPI2_SGE_FLAGS_SHIFT);
4522 
4523                                 /*
4524                                  * If we are at the end of the frame and
4525                                  * there is another frame to fill in
4526                                  * we set the last simple element as last
4527                                  * element
4528                                  */
4529                                 if ((l == sgemax) && (k != frames)) {
4530                                         flags |= ((uint32_t)
4531                                             (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4532                                             MPI2_SGE_FLAGS_SHIFT);
4533                                 }
4534 
4535                                 /*
4536                                  * If this is the final cookie we
4537                                  * indicate it by setting the flags
4538                                  */
4539                                 if (j == i) {
4540                                         flags |= ((uint32_t)
4541                                             (MPI2_SGE_FLAGS_LAST_ELEMENT |
4542                                             MPI2_SGE_FLAGS_END_OF_BUFFER |
4543                                             MPI2_SGE_FLAGS_END_OF_LIST) <<
4544                                             MPI2_SGE_FLAGS_SHIFT);
4545                                 }
4546                                 if (cmd->cmd_flags & CFLAG_DMASEND) {
4547                                         flags |=
4548                                             (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4549                                             MPI2_SGE_FLAGS_SHIFT);
4550                                 } else {
4551                                         flags |=
4552                                             (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4553                                             MPI2_SGE_FLAGS_SHIFT);
4554                                 }
4555                                 ddi_put32(p->m_acc_hdl,
4556                                     &sge->FlagsLength, flags);
4557                                 dmap++;
4558                                 sge++;
4559                         }
4560                 }
4561 
4562                 /*
4563                  * Sync DMA with the chain buffers that were just created
4564                  */
4565                 (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
4566         }
4567 }
4568 
4569 /*
4570  * Interrupt handling
4571  * Utility routine.  Poll for status of a command sent to HBA
4572  * without interrupts (a FLAG_NOINTR command).
4573  */
4574 int
4575 mptsas_poll(mptsas_t *mpt, mptsas_cmd_t *poll_cmd, int polltime)
4576 {
4577         int     rval = TRUE;
4578 
4579         NDBG5(("mptsas_poll: cmd=0x%p", (void *)poll_cmd));
4580 
4581         if ((poll_cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
4582                 mptsas_restart_hba(mpt);
4583         }
4584 
4585         /*
4586          * Wait, using drv_usecwait(), long enough for the command to
4587          * reasonably return from the target if the target isn't
4588          * "dead".  A polled command may well be sent from scsi_poll, and
4589          * there are retries built in to scsi_poll if the transport
4590          * accepted the packet (TRAN_ACCEPT).  scsi_poll waits 1 second
4591          * and retries the transport up to scsi_poll_busycnt times
4592          * (currently 60) if
4593          * 1. pkt_reason is CMD_INCOMPLETE and pkt_state is 0, or
4594          * 2. pkt_reason is CMD_CMPLT and *pkt_scbp has STATUS_BUSY
4595          *
4596          * limit the waiting to avoid a hang in the event that the
4597          * cmd never gets started but we are still receiving interrupts
4598          */
4599         while (!(poll_cmd->cmd_flags & CFLAG_FINISHED)) {
4600                 if (mptsas_wait_intr(mpt, polltime) == FALSE) {
4601                         NDBG5(("mptsas_poll: command incomplete"));
4602                         rval = FALSE;
4603                         break;
4604                 }
4605         }
4606 
4607         if (rval == FALSE) {
4608 
4609                 /*
4610                  * this isn't supposed to happen, the hba must be wedged
4611                  * Mark this cmd as a timeout.
4612                  */
4613                 mptsas_set_pkt_reason(mpt, poll_cmd, CMD_TIMEOUT,
4614                     (STAT_TIMEOUT|STAT_ABORTED));
4615 
4616                 if (poll_cmd->cmd_queued == FALSE) {
4617 
4618                         NDBG5(("mptsas_poll: not on waitq"));
4619 
4620                         poll_cmd->cmd_pkt->pkt_state |=
4621                             (STATE_GOT_BUS|STATE_GOT_TARGET|STATE_SENT_CMD);
4622                 } else {
4623 
4624                         /* find and remove it from the waitq */
4625                         NDBG5(("mptsas_poll: delete from waitq"));
4626                         mptsas_waitq_delete(mpt, poll_cmd);
4627                 }
4628 
4629         }
4630         mptsas_fma_check(mpt, poll_cmd);
4631         NDBG5(("mptsas_poll: done"));
4632         return (rval);
4633 }
4634 
4635 /*
4636  * Used for polling cmds and TM function
4637  */
4638 static int
4639 mptsas_wait_intr(mptsas_t *mpt, int polltime)
4640 {
4641         int                             cnt;
4642         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
4643         uint32_t                        int_mask;
4644 
4645         NDBG5(("mptsas_wait_intr"));
4646 
4647         mpt->m_polled_intr = 1;
4648 
4649         /*
4650          * Get the current interrupt mask and disable interrupts.  When
4651          * re-enabling ints, set mask to saved value.
4652          */
4653         int_mask = ddi_get32(mpt->m_datap, &mpt->m_reg->HostInterruptMask);
4654         MPTSAS_DISABLE_INTR(mpt);
4655 
4656         /*
4657          * Keep polling for at least (polltime * 1000) seconds
4658          */
4659         for (cnt = 0; cnt < polltime; cnt++) {
4660                 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
4661                     DDI_DMA_SYNC_FORCPU);
4662 
4663                 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
4664                     MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
4665 
4666                 if (ddi_get32(mpt->m_acc_post_queue_hdl,
4667                     &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
4668                     ddi_get32(mpt->m_acc_post_queue_hdl,
4669                     &reply_desc_union->Words.High) == 0xFFFFFFFF) {
4670                         drv_usecwait(1000);
4671                         continue;
4672                 }
4673 
4674                 /*
4675                  * The reply is valid, process it according to its
4676                  * type.
4677                  */
4678                 mptsas_process_intr(mpt, reply_desc_union);
4679 
4680                 if (++mpt->m_post_index == mpt->m_post_queue_depth) {
4681                         mpt->m_post_index = 0;
4682                 }
4683 
4684                 /*
4685                  * Update the global reply index
4686                  */
4687                 ddi_put32(mpt->m_datap,
4688                     &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
4689                 mpt->m_polled_intr = 0;
4690 
4691                 /*
4692                  * Re-enable interrupts and quit.
4693                  */
4694                 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask,
4695                     int_mask);
4696                 return (TRUE);
4697 
4698         }
4699 
4700         /*
4701          * Clear polling flag, re-enable interrupts and quit.
4702          */
4703         mpt->m_polled_intr = 0;
4704         ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask, int_mask);
4705         return (FALSE);
4706 }
4707 
4708 static void
4709 mptsas_handle_scsi_io_success(mptsas_t *mpt,
4710     pMpi2ReplyDescriptorsUnion_t reply_desc)
4711 {
4712         pMpi2SCSIIOSuccessReplyDescriptor_t     scsi_io_success;
4713         uint16_t                                SMID;
4714         mptsas_slots_t                          *slots = mpt->m_active;
4715         mptsas_cmd_t                            *cmd = NULL;
4716         struct scsi_pkt                         *pkt;
4717 
4718         ASSERT(mutex_owned(&mpt->m_mutex));
4719 
4720         scsi_io_success = (pMpi2SCSIIOSuccessReplyDescriptor_t)reply_desc;
4721         SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &scsi_io_success->SMID);
4722 
4723         /*
4724          * This is a success reply so just complete the IO.  First, do a sanity
4725          * check on the SMID.  The final slot is used for TM requests, which
4726          * would not come into this reply handler.
4727          */
4728         if ((SMID == 0) || (SMID > slots->m_n_normal)) {
4729                 mptsas_log(mpt, CE_WARN, "?Received invalid SMID of %d\n",
4730                     SMID);
4731                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4732                 return;
4733         }
4734 
4735         cmd = slots->m_slot[SMID];
4736 
4737         /*
4738          * print warning and return if the slot is empty
4739          */
4740         if (cmd == NULL) {
4741                 mptsas_log(mpt, CE_WARN, "?NULL command for successful SCSI IO "
4742                     "in slot %d", SMID);
4743                 return;
4744         }
4745 
4746         pkt = CMD2PKT(cmd);
4747         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
4748             STATE_GOT_STATUS);
4749         if (cmd->cmd_flags & CFLAG_DMAVALID) {
4750                 pkt->pkt_state |= STATE_XFERRED_DATA;
4751         }
4752         pkt->pkt_resid = 0;
4753 
4754         if (cmd->cmd_flags & CFLAG_PASSTHRU) {
4755                 cmd->cmd_flags |= CFLAG_FINISHED;
4756                 cv_broadcast(&mpt->m_passthru_cv);
4757                 return;
4758         } else {
4759                 mptsas_remove_cmd(mpt, cmd);
4760         }
4761 
4762         if (cmd->cmd_flags & CFLAG_RETRY) {
4763                 /*
4764                  * The target returned QFULL or busy, do not add tihs
4765                  * pkt to the doneq since the hba will retry
4766                  * this cmd.
4767                  *
4768                  * The pkt has already been resubmitted in
4769                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
4770                  * Remove this cmd_flag here.
4771                  */
4772                 cmd->cmd_flags &= ~CFLAG_RETRY;
4773         } else {
4774                 mptsas_doneq_add(mpt, cmd);
4775         }
4776 }
4777 
4778 static void
4779 mptsas_handle_address_reply(mptsas_t *mpt,
4780     pMpi2ReplyDescriptorsUnion_t reply_desc)
4781 {
4782         pMpi2AddressReplyDescriptor_t   address_reply;
4783         pMPI2DefaultReply_t             reply;
4784         mptsas_fw_diagnostic_buffer_t   *pBuffer;
4785         uint32_t                        reply_addr;
4786         uint16_t                        SMID, iocstatus;
4787         mptsas_slots_t                  *slots = mpt->m_active;
4788         mptsas_cmd_t                    *cmd = NULL;
4789         uint8_t                         function, buffer_type;
4790         m_replyh_arg_t                  *args;
4791         int                             reply_frame_no;
4792 
4793         ASSERT(mutex_owned(&mpt->m_mutex));
4794 
4795         address_reply = (pMpi2AddressReplyDescriptor_t)reply_desc;
4796         reply_addr = ddi_get32(mpt->m_acc_post_queue_hdl,
4797             &address_reply->ReplyFrameAddress);
4798         SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &address_reply->SMID);
4799 
4800         /*
4801          * If reply frame is not in the proper range we should ignore this
4802          * message and exit the interrupt handler.
4803          */
4804         if ((reply_addr < mpt->m_reply_frame_dma_addr) ||
4805             (reply_addr >= (mpt->m_reply_frame_dma_addr +
4806             (mpt->m_reply_frame_size * mpt->m_max_replies))) ||
4807             ((reply_addr - mpt->m_reply_frame_dma_addr) %
4808             mpt->m_reply_frame_size != 0)) {
4809                 mptsas_log(mpt, CE_WARN, "?Received invalid reply frame "
4810                     "address 0x%x\n", reply_addr);
4811                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4812                 return;
4813         }
4814 
4815         (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
4816             DDI_DMA_SYNC_FORCPU);
4817         reply = (pMPI2DefaultReply_t)(mpt->m_reply_frame + (reply_addr -
4818             mpt->m_reply_frame_dma_addr));
4819         function = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->Function);
4820 
4821         /*
4822          * don't get slot information and command for events since these values
4823          * don't exist
4824          */
4825         if ((function != MPI2_FUNCTION_EVENT_NOTIFICATION) &&
4826             (function != MPI2_FUNCTION_DIAG_BUFFER_POST)) {
4827                 /*
4828                  * This could be a TM reply, which use the last allocated SMID,
4829                  * so allow for that.
4830                  */
4831                 if ((SMID == 0) || (SMID > (slots->m_n_normal + 1))) {
4832                         mptsas_log(mpt, CE_WARN, "?Received invalid SMID of "
4833                             "%d\n", SMID);
4834                         ddi_fm_service_impact(mpt->m_dip,
4835                             DDI_SERVICE_UNAFFECTED);
4836                         return;
4837                 }
4838 
4839                 cmd = slots->m_slot[SMID];
4840 
4841                 /*
4842                  * print warning and return if the slot is empty
4843                  */
4844                 if (cmd == NULL) {
4845                         mptsas_log(mpt, CE_WARN, "?NULL command for address "
4846                             "reply in slot %d", SMID);
4847                         return;
4848                 }
4849                 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
4850                     (cmd->cmd_flags & CFLAG_CONFIG) ||
4851                     (cmd->cmd_flags & CFLAG_FW_DIAG)) {
4852                         cmd->cmd_rfm = reply_addr;
4853                         cmd->cmd_flags |= CFLAG_FINISHED;
4854                         cv_broadcast(&mpt->m_passthru_cv);
4855                         cv_broadcast(&mpt->m_config_cv);
4856                         cv_broadcast(&mpt->m_fw_diag_cv);
4857                         return;
4858                 } else if (!(cmd->cmd_flags & CFLAG_FW_CMD)) {
4859                         mptsas_remove_cmd(mpt, cmd);
4860                 }
4861                 NDBG31(("\t\tmptsas_process_intr: slot=%d", SMID));
4862         }
4863         /*
4864          * Depending on the function, we need to handle
4865          * the reply frame (and cmd) differently.
4866          */
4867         switch (function) {
4868         case MPI2_FUNCTION_SCSI_IO_REQUEST:
4869                 mptsas_check_scsi_io_error(mpt, (pMpi2SCSIIOReply_t)reply, cmd);
4870                 break;
4871         case MPI2_FUNCTION_SCSI_TASK_MGMT:
4872                 cmd->cmd_rfm = reply_addr;
4873                 mptsas_check_task_mgt(mpt, (pMpi2SCSIManagementReply_t)reply,
4874                     cmd);
4875                 break;
4876         case MPI2_FUNCTION_FW_DOWNLOAD:
4877                 cmd->cmd_flags |= CFLAG_FINISHED;
4878                 cv_signal(&mpt->m_fw_cv);
4879                 break;
4880         case MPI2_FUNCTION_EVENT_NOTIFICATION:
4881                 reply_frame_no = (reply_addr - mpt->m_reply_frame_dma_addr) /
4882                     mpt->m_reply_frame_size;
4883                 args = &mpt->m_replyh_args[reply_frame_no];
4884                 args->mpt = (void *)mpt;
4885                 args->rfm = reply_addr;
4886 
4887                 /*
4888                  * Record the event if its type is enabled in
4889                  * this mpt instance by ioctl.
4890                  */
4891                 mptsas_record_event(args);
4892 
4893                 /*
4894                  * Handle time critical events
4895                  * NOT_RESPONDING/ADDED only now
4896                  */
4897                 if (mptsas_handle_event_sync(args) == DDI_SUCCESS) {
4898                         /*
4899                          * Would not return main process,
4900                          * just let taskq resolve ack action
4901                          * and ack would be sent in taskq thread
4902                          */
4903                         NDBG20(("send mptsas_handle_event_sync success"));
4904                 }
4905 
4906                 if (mpt->m_in_reset) {
4907                         NDBG20(("dropping event received during reset"));
4908                         return;
4909                 }
4910 
4911                 if ((ddi_taskq_dispatch(mpt->m_event_taskq, mptsas_handle_event,
4912                     (void *)args, DDI_NOSLEEP)) != DDI_SUCCESS) {
4913                         mptsas_log(mpt, CE_WARN, "No memory available"
4914                         "for dispatch taskq");
4915                         /*
4916                          * Return the reply frame to the free queue.
4917                          */
4918                         ddi_put32(mpt->m_acc_free_queue_hdl,
4919                             &((uint32_t *)(void *)
4920                             mpt->m_free_queue)[mpt->m_free_index], reply_addr);
4921                         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
4922                             DDI_DMA_SYNC_FORDEV);
4923                         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
4924                                 mpt->m_free_index = 0;
4925                         }
4926 
4927                         ddi_put32(mpt->m_datap,
4928                             &mpt->m_reg->ReplyFreeHostIndex, mpt->m_free_index);
4929                 }
4930                 return;
4931         case MPI2_FUNCTION_DIAG_BUFFER_POST:
4932                 /*
4933                  * If SMID is 0, this implies that the reply is due to a
4934                  * release function with a status that the buffer has been
4935                  * released.  Set the buffer flags accordingly.
4936                  */
4937                 if (SMID == 0) {
4938                         iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
4939                             &reply->IOCStatus);
4940                         buffer_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
4941                             &(((pMpi2DiagBufferPostReply_t)reply)->BufferType));
4942                         if (iocstatus == MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED) {
4943                                 pBuffer =
4944                                     &mpt->m_fw_diag_buffer_list[buffer_type];
4945                                 pBuffer->valid_data = TRUE;
4946                                 pBuffer->owned_by_firmware = FALSE;
4947                                 pBuffer->immediate = FALSE;
4948                         }
4949                 } else {
4950                         /*
4951                          * Normal handling of diag post reply with SMID.
4952                          */
4953                         cmd = slots->m_slot[SMID];
4954 
4955                         /*
4956                          * print warning and return if the slot is empty
4957                          */
4958                         if (cmd == NULL) {
4959                                 mptsas_log(mpt, CE_WARN, "?NULL command for "
4960                                     "address reply in slot %d", SMID);
4961                                 return;
4962                         }
4963                         cmd->cmd_rfm = reply_addr;
4964                         cmd->cmd_flags |= CFLAG_FINISHED;
4965                         cv_broadcast(&mpt->m_fw_diag_cv);
4966                 }
4967                 return;
4968         default:
4969                 mptsas_log(mpt, CE_WARN, "Unknown function 0x%x ", function);
4970                 break;
4971         }
4972 
4973         /*
4974          * Return the reply frame to the free queue.
4975          */
4976         ddi_put32(mpt->m_acc_free_queue_hdl,
4977             &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
4978             reply_addr);
4979         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
4980             DDI_DMA_SYNC_FORDEV);
4981         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
4982                 mpt->m_free_index = 0;
4983         }
4984         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
4985             mpt->m_free_index);
4986 
4987         if (cmd->cmd_flags & CFLAG_FW_CMD)
4988                 return;
4989 
4990         if (cmd->cmd_flags & CFLAG_RETRY) {
4991                 /*
4992                  * The target returned QFULL or busy, do not add tihs
4993                  * pkt to the doneq since the hba will retry
4994                  * this cmd.
4995                  *
4996                  * The pkt has already been resubmitted in
4997                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
4998                  * Remove this cmd_flag here.
4999                  */
5000                 cmd->cmd_flags &= ~CFLAG_RETRY;
5001         } else {
5002                 mptsas_doneq_add(mpt, cmd);
5003         }
5004 }
5005 
5006 static void
5007 mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
5008     mptsas_cmd_t *cmd)
5009 {
5010         uint8_t                 scsi_status, scsi_state;
5011         uint16_t                ioc_status;
5012         uint32_t                xferred, sensecount, responsedata, loginfo = 0;
5013         struct scsi_pkt         *pkt;
5014         struct scsi_arq_status  *arqstat;
5015         struct buf              *bp;
5016         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
5017         uint8_t                 *sensedata = NULL;
5018 
5019         if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
5020             (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
5021                 bp = cmd->cmd_ext_arq_buf;
5022         } else {
5023                 bp = cmd->cmd_arq_buf;
5024         }
5025 
5026         scsi_status = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIStatus);
5027         ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5028         scsi_state = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIState);
5029         xferred = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->TransferCount);
5030         sensecount = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->SenseCount);
5031         responsedata = ddi_get32(mpt->m_acc_reply_frame_hdl,
5032             &reply->ResponseInfo);
5033 
5034         if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
5035                 loginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
5036                     &reply->IOCLogInfo);
5037                 mptsas_log(mpt, CE_NOTE,
5038                     "?Log info 0x%x received for target %d.\n"
5039                     "\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5040                     loginfo, Tgt(cmd), scsi_status, ioc_status,
5041                     scsi_state);
5042         }
5043 
5044         NDBG31(("\t\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5045             scsi_status, ioc_status, scsi_state));
5046 
5047         pkt = CMD2PKT(cmd);
5048         *(pkt->pkt_scbp) = scsi_status;
5049 
5050         if (loginfo == 0x31170000) {
5051                 /*
5052                  * if loginfo PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY
5053                  * 0x31170000 comes, that means the device missing delay
5054                  * is in progressing, the command need retry later.
5055                  */
5056                 *(pkt->pkt_scbp) = STATUS_BUSY;
5057                 return;
5058         }
5059 
5060         if ((scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) &&
5061             ((ioc_status & MPI2_IOCSTATUS_MASK) ==
5062             MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE)) {
5063                 pkt->pkt_reason = CMD_INCOMPLETE;
5064                 pkt->pkt_state |= STATE_GOT_BUS;
5065                 if (ptgt->m_reset_delay == 0) {
5066                         mptsas_set_throttle(mpt, ptgt,
5067                             DRAIN_THROTTLE);
5068                 }
5069                 return;
5070         }
5071 
5072         if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
5073                 responsedata &= 0x000000FF;
5074                 if (responsedata & MPTSAS_SCSI_RESPONSE_CODE_TLR_OFF) {
5075                         mptsas_log(mpt, CE_NOTE, "Do not support the TLR\n");
5076                         pkt->pkt_reason = CMD_TLR_OFF;
5077                         return;
5078                 }
5079         }
5080 
5081 
5082         switch (scsi_status) {
5083         case MPI2_SCSI_STATUS_CHECK_CONDITION:
5084                 pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5085                 arqstat = (void*)(pkt->pkt_scbp);
5086                 arqstat->sts_rqpkt_status = *((struct scsi_status *)
5087                     (pkt->pkt_scbp));
5088                 pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
5089                     STATE_SENT_CMD | STATE_GOT_STATUS | STATE_ARQ_DONE);
5090                 if (cmd->cmd_flags & CFLAG_XARQ) {
5091                         pkt->pkt_state |= STATE_XARQ_DONE;
5092                 }
5093                 if (pkt->pkt_resid != cmd->cmd_dmacount) {
5094                         pkt->pkt_state |= STATE_XFERRED_DATA;
5095                 }
5096                 arqstat->sts_rqpkt_reason = pkt->pkt_reason;
5097                 arqstat->sts_rqpkt_state  = pkt->pkt_state;
5098                 arqstat->sts_rqpkt_state |= STATE_XFERRED_DATA;
5099                 arqstat->sts_rqpkt_statistics = pkt->pkt_statistics;
5100                 sensedata = (uint8_t *)&arqstat->sts_sensedata;
5101 
5102                 bcopy((uchar_t *)bp->b_un.b_addr, sensedata,
5103                     ((cmd->cmd_rqslen >= sensecount) ? sensecount :
5104                     cmd->cmd_rqslen));
5105                 arqstat->sts_rqpkt_resid = (cmd->cmd_rqslen - sensecount);
5106                 cmd->cmd_flags |= CFLAG_CMDARQ;
5107                 /*
5108                  * Set proper status for pkt if autosense was valid
5109                  */
5110                 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
5111                         struct scsi_status zero_status = { 0 };
5112                         arqstat->sts_rqpkt_status = zero_status;
5113                 }
5114 
5115                 /*
5116                  * ASC=0x47 is parity error
5117                  * ASC=0x48 is initiator detected error received
5118                  */
5119                 if ((scsi_sense_key(sensedata) == KEY_ABORTED_COMMAND) &&
5120                     ((scsi_sense_asc(sensedata) == 0x47) ||
5121                     (scsi_sense_asc(sensedata) == 0x48))) {
5122                         mptsas_log(mpt, CE_NOTE, "Aborted_command!");
5123                 }
5124 
5125                 /*
5126                  * ASC/ASCQ=0x3F/0x0E means report_luns data changed
5127                  * ASC/ASCQ=0x25/0x00 means invalid lun
5128                  */
5129                 if (((scsi_sense_key(sensedata) == KEY_UNIT_ATTENTION) &&
5130                     (scsi_sense_asc(sensedata) == 0x3F) &&
5131                     (scsi_sense_ascq(sensedata) == 0x0E)) ||
5132                     ((scsi_sense_key(sensedata) == KEY_ILLEGAL_REQUEST) &&
5133                     (scsi_sense_asc(sensedata) == 0x25) &&
5134                     (scsi_sense_ascq(sensedata) == 0x00))) {
5135                         mptsas_topo_change_list_t *topo_node = NULL;
5136 
5137                         topo_node = kmem_zalloc(
5138                             sizeof (mptsas_topo_change_list_t),
5139                             KM_NOSLEEP);
5140                         if (topo_node == NULL) {
5141                                 mptsas_log(mpt, CE_NOTE, "No memory"
5142                                     "resource for handle SAS dynamic"
5143                                     "reconfigure.\n");
5144                                 break;
5145                         }
5146                         topo_node->mpt = mpt;
5147                         topo_node->event = MPTSAS_DR_EVENT_RECONFIG_TARGET;
5148                         topo_node->un.phymask = ptgt->m_addr.mta_phymask;
5149                         topo_node->devhdl = ptgt->m_devhdl;
5150                         topo_node->object = (void *)ptgt;
5151                         topo_node->flags = MPTSAS_TOPO_FLAG_LUN_ASSOCIATED;
5152 
5153                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
5154                             mptsas_handle_dr,
5155                             (void *)topo_node,
5156                             DDI_NOSLEEP)) != DDI_SUCCESS) {
5157                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq"
5158                                     "for handle SAS dynamic reconfigure"
5159                                     "failed. \n");
5160                         }
5161                 }
5162                 break;
5163         case MPI2_SCSI_STATUS_GOOD:
5164                 switch (ioc_status & MPI2_IOCSTATUS_MASK) {
5165                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
5166                         pkt->pkt_reason = CMD_DEV_GONE;
5167                         pkt->pkt_state |= STATE_GOT_BUS;
5168                         if (ptgt->m_reset_delay == 0) {
5169                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5170                         }
5171                         NDBG31(("lost disk for target%d, command:%x",
5172                             Tgt(cmd), pkt->pkt_cdbp[0]));
5173                         break;
5174                 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
5175                         NDBG31(("data overrun: xferred=%d", xferred));
5176                         NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5177                         pkt->pkt_reason = CMD_DATA_OVR;
5178                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5179                             | STATE_SENT_CMD | STATE_GOT_STATUS
5180                             | STATE_XFERRED_DATA);
5181                         pkt->pkt_resid = 0;
5182                         break;
5183                 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
5184                 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
5185                         NDBG31(("data underrun: xferred=%d", xferred));
5186                         NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5187                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5188                             | STATE_SENT_CMD | STATE_GOT_STATUS);
5189                         pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5190                         if (pkt->pkt_resid != cmd->cmd_dmacount) {
5191                                 pkt->pkt_state |= STATE_XFERRED_DATA;
5192                         }
5193                         break;
5194                 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
5195                         mptsas_set_pkt_reason(mpt,
5196                             cmd, CMD_RESET, STAT_BUS_RESET);
5197                         break;
5198                 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
5199                 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
5200                         mptsas_set_pkt_reason(mpt,
5201                             cmd, CMD_RESET, STAT_DEV_RESET);
5202                         break;
5203                 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
5204                 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
5205                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET);
5206                         mptsas_set_pkt_reason(mpt,
5207                             cmd, CMD_TERMINATED, STAT_TERMINATED);
5208                         break;
5209                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
5210                 case MPI2_IOCSTATUS_BUSY:
5211                         /*
5212                          * set throttles to drain
5213                          */
5214                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
5215                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
5216                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5217                         }
5218 
5219                         /*
5220                          * retry command
5221                          */
5222                         cmd->cmd_flags |= CFLAG_RETRY;
5223                         cmd->cmd_pkt_flags |= FLAG_HEAD;
5224 
5225                         (void) mptsas_accept_pkt(mpt, cmd);
5226                         break;
5227                 default:
5228                         mptsas_log(mpt, CE_WARN,
5229                             "unknown ioc_status = %x\n", ioc_status);
5230                         mptsas_log(mpt, CE_CONT, "scsi_state = %x, transfer "
5231                             "count = %x, scsi_status = %x", scsi_state,
5232                             xferred, scsi_status);
5233                         break;
5234                 }
5235                 break;
5236         case MPI2_SCSI_STATUS_TASK_SET_FULL:
5237                 mptsas_handle_qfull(mpt, cmd);
5238                 break;
5239         case MPI2_SCSI_STATUS_BUSY:
5240                 NDBG31(("scsi_status busy received"));
5241                 break;
5242         case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
5243                 NDBG31(("scsi_status reservation conflict received"));
5244                 break;
5245         default:
5246                 mptsas_log(mpt, CE_WARN, "scsi_status=%x, ioc_status=%x\n",
5247                     scsi_status, ioc_status);
5248                 mptsas_log(mpt, CE_WARN,
5249                     "mptsas_process_intr: invalid scsi status\n");
5250                 break;
5251         }
5252 }
5253 
5254 static void
5255 mptsas_check_task_mgt(mptsas_t *mpt, pMpi2SCSIManagementReply_t reply,
5256         mptsas_cmd_t *cmd)
5257 {
5258         uint8_t         task_type;
5259         uint16_t        ioc_status;
5260         uint32_t        log_info;
5261         uint16_t        dev_handle;
5262         struct scsi_pkt *pkt = CMD2PKT(cmd);
5263 
5264         task_type = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->TaskType);
5265         ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5266         log_info = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->IOCLogInfo);
5267         dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->DevHandle);
5268 
5269         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5270                 mptsas_log(mpt, CE_WARN, "mptsas_check_task_mgt: Task 0x%x "
5271                     "failed. IOCStatus=0x%x IOCLogInfo=0x%x target=%d\n",
5272                     task_type, ioc_status, log_info, dev_handle);
5273                 pkt->pkt_reason = CMD_INCOMPLETE;
5274                 return;
5275         }
5276 
5277         switch (task_type) {
5278         case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
5279         case MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
5280         case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
5281         case MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA:
5282         case MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET:
5283         case MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION:
5284                 break;
5285         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
5286         case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
5287         case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
5288                 /*
5289                  * Check for invalid DevHandle of 0 in case application
5290                  * sends bad command.  DevHandle of 0 could cause problems.
5291                  */
5292                 if (dev_handle == 0) {
5293                         mptsas_log(mpt, CE_WARN, "!Can't flush target with"
5294                             " DevHandle of 0.");
5295                 } else {
5296                         mptsas_flush_target(mpt, dev_handle, Lun(cmd),
5297                             task_type);
5298                 }
5299                 break;
5300         default:
5301                 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
5302                     task_type);
5303                 mptsas_log(mpt, CE_WARN, "ioc status = %x", ioc_status);
5304                 break;
5305         }
5306 }
5307 
5308 static void
5309 mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg)
5310 {
5311         mptsas_t                        *mpt = arg->mpt;
5312         uint64_t                        t = arg->t;
5313         mptsas_cmd_t                    *cmd;
5314         struct scsi_pkt                 *pkt;
5315         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
5316 
5317         mutex_enter(&item->mutex);
5318         while (item->flag & MPTSAS_DONEQ_THREAD_ACTIVE) {
5319                 if (!item->doneq) {
5320                         cv_wait(&item->cv, &item->mutex);
5321                 }
5322                 pkt = NULL;
5323                 if ((cmd = mptsas_doneq_thread_rm(mpt, t)) != NULL) {
5324                         cmd->cmd_flags |= CFLAG_COMPLETED;
5325                         pkt = CMD2PKT(cmd);
5326                 }
5327                 mutex_exit(&item->mutex);
5328                 if (pkt) {
5329                         mptsas_pkt_comp(pkt, cmd);
5330                 }
5331                 mutex_enter(&item->mutex);
5332         }
5333         mutex_exit(&item->mutex);
5334         mutex_enter(&mpt->m_doneq_mutex);
5335         mpt->m_doneq_thread_n--;
5336         cv_broadcast(&mpt->m_doneq_thread_cv);
5337         mutex_exit(&mpt->m_doneq_mutex);
5338 }
5339 
5340 
5341 /*
5342  * mpt interrupt handler.
5343  */
5344 static uint_t
5345 mptsas_intr(caddr_t arg1, caddr_t arg2)
5346 {
5347         mptsas_t                        *mpt = (void *)arg1;
5348         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
5349         uchar_t                         did_reply = FALSE;
5350 
5351         NDBG1(("mptsas_intr: arg1 0x%p arg2 0x%p", (void *)arg1, (void *)arg2));
5352 
5353         mutex_enter(&mpt->m_mutex);
5354 
5355         /*
5356          * If interrupts are shared by two channels then check whether this
5357          * interrupt is genuinely for this channel by making sure first the
5358          * chip is in high power state.
5359          */
5360         if ((mpt->m_options & MPTSAS_OPT_PM) &&
5361             (mpt->m_power_level != PM_LEVEL_D0)) {
5362                 mutex_exit(&mpt->m_mutex);
5363                 return (DDI_INTR_UNCLAIMED);
5364         }
5365 
5366         /*
5367          * If polling, interrupt was triggered by some shared interrupt because
5368          * IOC interrupts are disabled during polling, so polling routine will
5369          * handle any replies.  Considering this, if polling is happening,
5370          * return with interrupt unclaimed.
5371          */
5372         if (mpt->m_polled_intr) {
5373                 mutex_exit(&mpt->m_mutex);
5374                 mptsas_log(mpt, CE_WARN, "mpt_sas: Unclaimed interrupt");
5375                 return (DDI_INTR_UNCLAIMED);
5376         }
5377 
5378         /*
5379          * Read the istat register.
5380          */
5381         if ((INTPENDING(mpt)) != 0) {
5382                 /*
5383                  * read fifo until empty.
5384                  */
5385 #ifndef __lock_lint
5386                 _NOTE(CONSTCOND)
5387 #endif
5388                 while (TRUE) {
5389                         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5390                             DDI_DMA_SYNC_FORCPU);
5391                         reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
5392                             MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
5393 
5394                         if (ddi_get32(mpt->m_acc_post_queue_hdl,
5395                             &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
5396                             ddi_get32(mpt->m_acc_post_queue_hdl,
5397                             &reply_desc_union->Words.High) == 0xFFFFFFFF) {
5398                                 break;
5399                         }
5400 
5401                         /*
5402                          * The reply is valid, process it according to its
5403                          * type.  Also, set a flag for updating the reply index
5404                          * after they've all been processed.
5405                          */
5406                         did_reply = TRUE;
5407 
5408                         mptsas_process_intr(mpt, reply_desc_union);
5409 
5410                         /*
5411                          * Increment post index and roll over if needed.
5412                          */
5413                         if (++mpt->m_post_index == mpt->m_post_queue_depth) {
5414                                 mpt->m_post_index = 0;
5415                         }
5416                 }
5417 
5418                 /*
5419                  * Update the global reply index if at least one reply was
5420                  * processed.
5421                  */
5422                 if (did_reply) {
5423                         ddi_put32(mpt->m_datap,
5424                             &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
5425                 }
5426         } else {
5427                 mutex_exit(&mpt->m_mutex);
5428                 return (DDI_INTR_UNCLAIMED);
5429         }
5430         NDBG1(("mptsas_intr complete"));
5431 
5432         /*
5433          * If no helper threads are created, process the doneq in ISR. If
5434          * helpers are created, use the doneq length as a metric to measure the
5435          * load on the interrupt CPU. If it is long enough, which indicates the
5436          * load is heavy, then we deliver the IO completions to the helpers.
5437          * This measurement has some limitations, although it is simple and
5438          * straightforward and works well for most of the cases at present.
5439          */
5440         if (!mpt->m_doneq_thread_n ||
5441             (mpt->m_doneq_len <= mpt->m_doneq_length_threshold)) {
5442                 mptsas_doneq_empty(mpt);
5443         } else {
5444                 mptsas_deliver_doneq_thread(mpt);
5445         }
5446 
5447         /*
5448          * If there are queued cmd, start them now.
5449          */
5450         if (mpt->m_waitq != NULL) {
5451                 mptsas_restart_waitq(mpt);
5452         }
5453 
5454         mutex_exit(&mpt->m_mutex);
5455         return (DDI_INTR_CLAIMED);
5456 }
5457 
5458 static void
5459 mptsas_process_intr(mptsas_t *mpt,
5460     pMpi2ReplyDescriptorsUnion_t reply_desc_union)
5461 {
5462         uint8_t reply_type;
5463 
5464         ASSERT(mutex_owned(&mpt->m_mutex));
5465 
5466         /*
5467          * The reply is valid, process it according to its
5468          * type.  Also, set a flag for updated the reply index
5469          * after they've all been processed.
5470          */
5471         reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
5472             &reply_desc_union->Default.ReplyFlags);
5473         reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
5474         if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
5475                 mptsas_handle_scsi_io_success(mpt, reply_desc_union);
5476         } else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
5477                 mptsas_handle_address_reply(mpt, reply_desc_union);
5478         } else {
5479                 mptsas_log(mpt, CE_WARN, "?Bad reply type %x", reply_type);
5480                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5481         }
5482 
5483         /*
5484          * Clear the reply descriptor for re-use and increment
5485          * index.
5486          */
5487         ddi_put64(mpt->m_acc_post_queue_hdl,
5488             &((uint64_t *)(void *)mpt->m_post_queue)[mpt->m_post_index],
5489             0xFFFFFFFFFFFFFFFF);
5490         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5491             DDI_DMA_SYNC_FORDEV);
5492 }
5493 
5494 /*
5495  * handle qfull condition
5496  */
5497 static void
5498 mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd)
5499 {
5500         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
5501 
5502         if ((++cmd->cmd_qfull_retries > ptgt->m_qfull_retries) ||
5503             (ptgt->m_qfull_retries == 0)) {
5504                 /*
5505                  * We have exhausted the retries on QFULL, or,
5506                  * the target driver has indicated that it
5507                  * wants to handle QFULL itself by setting
5508                  * qfull-retries capability to 0. In either case
5509                  * we want the target driver's QFULL handling
5510                  * to kick in. We do this by having pkt_reason
5511                  * as CMD_CMPLT and pkt_scbp as STATUS_QFULL.
5512                  */
5513                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5514         } else {
5515                 if (ptgt->m_reset_delay == 0) {
5516                         ptgt->m_t_throttle =
5517                             max((ptgt->m_t_ncmds - 2), 0);
5518                 }
5519 
5520                 cmd->cmd_pkt_flags |= FLAG_HEAD;
5521                 cmd->cmd_flags &= ~(CFLAG_TRANFLAG);
5522                 cmd->cmd_flags |= CFLAG_RETRY;
5523 
5524                 (void) mptsas_accept_pkt(mpt, cmd);
5525 
5526                 /*
5527                  * when target gives queue full status with no commands
5528                  * outstanding (m_t_ncmds == 0), throttle is set to 0
5529                  * (HOLD_THROTTLE), and the queue full handling start
5530                  * (see psarc/1994/313); if there are commands outstanding,
5531                  * throttle is set to (m_t_ncmds - 2)
5532                  */
5533                 if (ptgt->m_t_throttle == HOLD_THROTTLE) {
5534                         /*
5535                          * By setting throttle to QFULL_THROTTLE, we
5536                          * avoid submitting new commands and in
5537                          * mptsas_restart_cmd find out slots which need
5538                          * their throttles to be cleared.
5539                          */
5540                         mptsas_set_throttle(mpt, ptgt, QFULL_THROTTLE);
5541                         if (mpt->m_restart_cmd_timeid == 0) {
5542                                 mpt->m_restart_cmd_timeid =
5543                                     timeout(mptsas_restart_cmd, mpt,
5544                                     ptgt->m_qfull_retry_interval);
5545                         }
5546                 }
5547         }
5548 }
5549 
5550 mptsas_phymask_t
5551 mptsas_physport_to_phymask(mptsas_t *mpt, uint8_t physport)
5552 {
5553         mptsas_phymask_t        phy_mask = 0;
5554         uint8_t                 i = 0;
5555 
5556         NDBG20(("mptsas%d physport_to_phymask enter", mpt->m_instance));
5557 
5558         ASSERT(mutex_owned(&mpt->m_mutex));
5559 
5560         /*
5561          * If physport is 0xFF, this is a RAID volume.  Use phymask of 0.
5562          */
5563         if (physport == 0xFF) {
5564                 return (0);
5565         }
5566 
5567         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
5568                 if (mpt->m_phy_info[i].attached_devhdl &&
5569                     (mpt->m_phy_info[i].phy_mask != 0) &&
5570                     (mpt->m_phy_info[i].port_num == physport)) {
5571                         phy_mask = mpt->m_phy_info[i].phy_mask;
5572                         break;
5573                 }
5574         }
5575         NDBG20(("mptsas%d physport_to_phymask:physport :%x phymask :%x, ",
5576             mpt->m_instance, physport, phy_mask));
5577         return (phy_mask);
5578 }
5579 
5580 /*
5581  * mpt free device handle after device gone, by use of passthrough
5582  */
5583 static int
5584 mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl)
5585 {
5586         Mpi2SasIoUnitControlRequest_t   req;
5587         Mpi2SasIoUnitControlReply_t     rep;
5588         int                             ret;
5589 
5590         ASSERT(mutex_owned(&mpt->m_mutex));
5591 
5592         /*
5593          * Need to compose a SAS IO Unit Control request message
5594          * and call mptsas_do_passthru() function
5595          */
5596         bzero(&req, sizeof (req));
5597         bzero(&rep, sizeof (rep));
5598 
5599         req.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
5600         req.Operation = MPI2_SAS_OP_REMOVE_DEVICE;
5601         req.DevHandle = LE_16(devhdl);
5602 
5603         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
5604             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
5605         if (ret != 0) {
5606                 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
5607                     "Control error %d", ret);
5608                 return (DDI_FAILURE);
5609         }
5610 
5611         /* do passthrough success, check the ioc status */
5612         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
5613                 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
5614                     "Control IOCStatus %d", LE_16(rep.IOCStatus));
5615                 return (DDI_FAILURE);
5616         }
5617 
5618         return (DDI_SUCCESS);
5619 }
5620 
5621 static void
5622 mptsas_update_phymask(mptsas_t *mpt)
5623 {
5624         mptsas_phymask_t mask = 0, phy_mask;
5625         char            *phy_mask_name;
5626         uint8_t         current_port;
5627         int             i, j;
5628 
5629         NDBG20(("mptsas%d update phymask ", mpt->m_instance));
5630 
5631         ASSERT(mutex_owned(&mpt->m_mutex));
5632 
5633         (void) mptsas_get_sas_io_unit_page(mpt);
5634 
5635         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
5636 
5637         for (i = 0; i < mpt->m_num_phys; i++) {
5638                 phy_mask = 0x00;
5639 
5640                 if (mpt->m_phy_info[i].attached_devhdl == 0)
5641                         continue;
5642 
5643                 bzero(phy_mask_name, sizeof (phy_mask_name));
5644 
5645                 current_port = mpt->m_phy_info[i].port_num;
5646 
5647                 if ((mask & (1 << i)) != 0)
5648                         continue;
5649 
5650                 for (j = 0; j < mpt->m_num_phys; j++) {
5651                         if (mpt->m_phy_info[j].attached_devhdl &&
5652                             (mpt->m_phy_info[j].port_num == current_port)) {
5653                                 phy_mask |= (1 << j);
5654                         }
5655                 }
5656                 mask = mask | phy_mask;
5657 
5658                 for (j = 0; j < mpt->m_num_phys; j++) {
5659                         if ((phy_mask >> j) & 0x01) {
5660                                 mpt->m_phy_info[j].phy_mask = phy_mask;
5661                         }
5662                 }
5663 
5664                 (void) sprintf(phy_mask_name, "%x", phy_mask);
5665 
5666                 mutex_exit(&mpt->m_mutex);
5667                 /*
5668                  * register a iport, if the port has already been existed
5669                  * SCSA will do nothing and just return.
5670                  */
5671                 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
5672                 mutex_enter(&mpt->m_mutex);
5673         }
5674         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
5675         NDBG20(("mptsas%d update phymask return", mpt->m_instance));
5676 }
5677 
5678 /*
5679  * mptsas_handle_dr is a task handler for DR, the DR action includes:
5680  * 1. Directly attched Device Added/Removed.
5681  * 2. Expander Device Added/Removed.
5682  * 3. Indirectly Attached Device Added/Expander.
5683  * 4. LUNs of a existing device status change.
5684  * 5. RAID volume created/deleted.
5685  * 6. Member of RAID volume is released because of RAID deletion.
5686  * 7. Physical disks are removed because of RAID creation.
5687  */
5688 static void
5689 mptsas_handle_dr(void *args) {
5690         mptsas_topo_change_list_t       *topo_node = NULL;
5691         mptsas_topo_change_list_t       *save_node = NULL;
5692         mptsas_t                        *mpt;
5693         dev_info_t                      *parent = NULL;
5694         mptsas_phymask_t                phymask = 0;
5695         char                            *phy_mask_name;
5696         uint8_t                         flags = 0, physport = 0xff;
5697         uint8_t                         port_update = 0;
5698         uint_t                          event;
5699 
5700         topo_node = (mptsas_topo_change_list_t *)args;
5701 
5702         mpt = topo_node->mpt;
5703         event = topo_node->event;
5704         flags = topo_node->flags;
5705 
5706         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
5707 
5708         NDBG20(("mptsas%d handle_dr enter", mpt->m_instance));
5709 
5710         switch (event) {
5711         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
5712                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
5713                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE) ||
5714                     (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
5715                         /*
5716                          * Direct attached or expander attached device added
5717                          * into system or a Phys Disk that is being unhidden.
5718                          */
5719                         port_update = 1;
5720                 }
5721                 break;
5722         case MPTSAS_DR_EVENT_RECONFIG_SMP:
5723                 /*
5724                  * New expander added into system, it must be the head
5725                  * of topo_change_list_t
5726                  */
5727                 port_update = 1;
5728                 break;
5729         default:
5730                 port_update = 0;
5731                 break;
5732         }
5733         /*
5734          * All cases port_update == 1 may cause initiator port form change
5735          */
5736         mutex_enter(&mpt->m_mutex);
5737         if (mpt->m_port_chng && port_update) {
5738                 /*
5739                  * mpt->m_port_chng flag indicates some PHYs of initiator
5740                  * port have changed to online. So when expander added or
5741                  * directly attached device online event come, we force to
5742                  * update port information by issueing SAS IO Unit Page and
5743                  * update PHYMASKs.
5744                  */
5745                 (void) mptsas_update_phymask(mpt);
5746                 mpt->m_port_chng = 0;
5747 
5748         }
5749         mutex_exit(&mpt->m_mutex);
5750         while (topo_node) {
5751                 phymask = 0;
5752                 if (parent == NULL) {
5753                         physport = topo_node->un.physport;
5754                         event = topo_node->event;
5755                         flags = topo_node->flags;
5756                         if (event & (MPTSAS_DR_EVENT_OFFLINE_TARGET |
5757                             MPTSAS_DR_EVENT_OFFLINE_SMP)) {
5758                                 /*
5759                                  * For all offline events, phymask is known
5760                                  */
5761                                 phymask = topo_node->un.phymask;
5762                                 goto find_parent;
5763                         }
5764                         if (event & MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
5765                                 goto handle_topo_change;
5766                         }
5767                         if (flags & MPTSAS_TOPO_FLAG_LUN_ASSOCIATED) {
5768                                 phymask = topo_node->un.phymask;
5769                                 goto find_parent;
5770                         }
5771 
5772                         if ((flags ==
5773                             MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) &&
5774                             (event == MPTSAS_DR_EVENT_RECONFIG_TARGET)) {
5775                                 /*
5776                                  * There is no any field in IR_CONFIG_CHANGE
5777                                  * event indicate physport/phynum, let's get
5778                                  * parent after SAS Device Page0 request.
5779                                  */
5780                                 goto handle_topo_change;
5781                         }
5782 
5783                         mutex_enter(&mpt->m_mutex);
5784                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
5785                                 /*
5786                                  * If the direct attached device added or a
5787                                  * phys disk is being unhidden, argument
5788                                  * physport actually is PHY#, so we have to get
5789                                  * phymask according PHY#.
5790                                  */
5791                                 physport = mpt->m_phy_info[physport].port_num;
5792                         }
5793 
5794                         /*
5795                          * Translate physport to phymask so that we can search
5796                          * parent dip.
5797                          */
5798                         phymask = mptsas_physport_to_phymask(mpt,
5799                             physport);
5800                         mutex_exit(&mpt->m_mutex);
5801 
5802 find_parent:
5803                         bzero(phy_mask_name, MPTSAS_MAX_PHYS);
5804                         /*
5805                          * For RAID topology change node, write the iport name
5806                          * as v0.
5807                          */
5808                         if (flags & MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5809                                 (void) sprintf(phy_mask_name, "v0");
5810                         } else {
5811                                 /*
5812                                  * phymask can bo 0 if the drive has been
5813                                  * pulled by the time an add event is
5814                                  * processed.  If phymask is 0, just skip this
5815                                  * event and continue.
5816                                  */
5817                                 if (phymask == 0) {
5818                                         mutex_enter(&mpt->m_mutex);
5819                                         save_node = topo_node;
5820                                         topo_node = topo_node->next;
5821                                         ASSERT(save_node);
5822                                         kmem_free(save_node,
5823                                             sizeof (mptsas_topo_change_list_t));
5824                                         mutex_exit(&mpt->m_mutex);
5825 
5826                                         parent = NULL;
5827                                         continue;
5828                                 }
5829                                 (void) sprintf(phy_mask_name, "%x", phymask);
5830                         }
5831                         parent = scsi_hba_iport_find(mpt->m_dip,
5832                             phy_mask_name);
5833                         if (parent == NULL) {
5834                                 mptsas_log(mpt, CE_WARN, "Failed to find an "
5835                                     "iport, should not happen!");
5836                                 goto out;
5837                         }
5838 
5839                 }
5840                 ASSERT(parent);
5841 handle_topo_change:
5842 
5843                 mutex_enter(&mpt->m_mutex);
5844                 /*
5845                  * If HBA is being reset, don't perform operations depending
5846                  * on the IOC. We must free the topo list, however.
5847                  */
5848                 if (!mpt->m_in_reset)
5849                         mptsas_handle_topo_change(topo_node, parent);
5850                 else
5851                         NDBG20(("skipping topo change received during reset"));
5852                 save_node = topo_node;
5853                 topo_node = topo_node->next;
5854                 ASSERT(save_node);
5855                 kmem_free(save_node, sizeof (mptsas_topo_change_list_t));
5856                 mutex_exit(&mpt->m_mutex);
5857 
5858                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
5859                     (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) ||
5860                     (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED)) {
5861                         /*
5862                          * If direct attached device associated, make sure
5863                          * reset the parent before start the next one. But
5864                          * all devices associated with expander shares the
5865                          * parent.  Also, reset parent if this is for RAID.
5866                          */
5867                         parent = NULL;
5868                 }
5869         }
5870 out:
5871         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
5872 }
5873 
5874 static void
5875 mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
5876     dev_info_t *parent)
5877 {
5878         mptsas_target_t *ptgt = NULL;
5879         mptsas_smp_t    *psmp = NULL;
5880         mptsas_t        *mpt = (void *)topo_node->mpt;
5881         uint16_t        devhdl;
5882         uint16_t        attached_devhdl;
5883         uint64_t        sas_wwn = 0;
5884         int             rval = 0;
5885         uint32_t        page_address;
5886         uint8_t         phy, flags;
5887         char            *addr = NULL;
5888         dev_info_t      *lundip;
5889         int             circ = 0, circ1 = 0;
5890         char            attached_wwnstr[MPTSAS_WWN_STRLEN];
5891 
5892         NDBG20(("mptsas%d handle_topo_change enter", mpt->m_instance));
5893 
5894         ASSERT(mutex_owned(&mpt->m_mutex));
5895 
5896         switch (topo_node->event) {
5897         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
5898         {
5899                 char *phy_mask_name;
5900                 mptsas_phymask_t phymask = 0;
5901 
5902                 if (topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5903                         /*
5904                          * Get latest RAID info.
5905                          */
5906                         (void) mptsas_get_raid_info(mpt);
5907                         ptgt = refhash_linear_search(mpt->m_targets,
5908                             mptsas_target_eval_devhdl, &topo_node->devhdl);
5909                         if (ptgt == NULL)
5910                                 break;
5911                 } else {
5912                         ptgt = (void *)topo_node->object;
5913                 }
5914 
5915                 if (ptgt == NULL) {
5916                         /*
5917                          * If a Phys Disk was deleted, RAID info needs to be
5918                          * updated to reflect the new topology.
5919                          */
5920                         (void) mptsas_get_raid_info(mpt);
5921 
5922                         /*
5923                          * Get sas device page 0 by DevHandle to make sure if
5924                          * SSP/SATA end device exist.
5925                          */
5926                         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
5927                             MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
5928                             topo_node->devhdl;
5929 
5930                         rval = mptsas_get_target_device_info(mpt, page_address,
5931                             &devhdl, &ptgt);
5932                         if (rval == DEV_INFO_WRONG_DEVICE_TYPE) {
5933                                 mptsas_log(mpt, CE_NOTE,
5934                                     "mptsas_handle_topo_change: target %d is "
5935                                     "not a SAS/SATA device. \n",
5936                                     topo_node->devhdl);
5937                         } else if (rval == DEV_INFO_FAIL_ALLOC) {
5938                                 mptsas_log(mpt, CE_NOTE,
5939                                     "mptsas_handle_topo_change: could not "
5940                                     "allocate memory. \n");
5941                         }
5942                         /*
5943                          * If rval is DEV_INFO_PHYS_DISK than there is nothing
5944                          * else to do, just leave.
5945                          */
5946                         if (rval != DEV_INFO_SUCCESS) {
5947                                 return;
5948                         }
5949                 }
5950 
5951                 ASSERT(ptgt->m_devhdl == topo_node->devhdl);
5952 
5953                 mutex_exit(&mpt->m_mutex);
5954                 flags = topo_node->flags;
5955 
5956                 if (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) {
5957                         phymask = ptgt->m_addr.mta_phymask;
5958                         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
5959                         (void) sprintf(phy_mask_name, "%x", phymask);
5960                         parent = scsi_hba_iport_find(mpt->m_dip,
5961                             phy_mask_name);
5962                         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
5963                         if (parent == NULL) {
5964                                 mptsas_log(mpt, CE_WARN, "Failed to find a "
5965                                     "iport for PD, should not happen!");
5966                                 mutex_enter(&mpt->m_mutex);
5967                                 break;
5968                         }
5969                 }
5970 
5971                 if (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5972                         ndi_devi_enter(parent, &circ1);
5973                         (void) mptsas_config_raid(parent, topo_node->devhdl,
5974                             &lundip);
5975                         ndi_devi_exit(parent, circ1);
5976                 } else {
5977                         /*
5978                          * hold nexus for bus configure
5979                          */
5980                         ndi_devi_enter(scsi_vhci_dip, &circ);
5981                         ndi_devi_enter(parent, &circ1);
5982                         rval = mptsas_config_target(parent, ptgt);
5983                         /*
5984                          * release nexus for bus configure
5985                          */
5986                         ndi_devi_exit(parent, circ1);
5987                         ndi_devi_exit(scsi_vhci_dip, circ);
5988 
5989                         /*
5990                          * Add parent's props for SMHBA support
5991                          */
5992                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
5993                                 bzero(attached_wwnstr,
5994                                     sizeof (attached_wwnstr));
5995                                 (void) sprintf(attached_wwnstr, "w%016"PRIx64,
5996                                     ptgt->m_addr.mta_wwn);
5997                                 if (ddi_prop_update_string(DDI_DEV_T_NONE,
5998                                     parent,
5999                                     SCSI_ADDR_PROP_ATTACHED_PORT,
6000                                     attached_wwnstr)
6001                                     != DDI_PROP_SUCCESS) {
6002                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6003                                             parent,
6004                                             SCSI_ADDR_PROP_ATTACHED_PORT);
6005                                         mptsas_log(mpt, CE_WARN, "Failed to"
6006                                             "attached-port props");
6007                                         return;
6008                                 }
6009                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6010                                     MPTSAS_NUM_PHYS, 1) !=
6011                                     DDI_PROP_SUCCESS) {
6012                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6013                                             parent, MPTSAS_NUM_PHYS);
6014                                         mptsas_log(mpt, CE_WARN, "Failed to"
6015                                             " create num-phys props");
6016                                         return;
6017                                 }
6018 
6019                                 /*
6020                                  * Update PHY info for smhba
6021                                  */
6022                                 mutex_enter(&mpt->m_mutex);
6023                                 if (mptsas_smhba_phy_init(mpt)) {
6024                                         mutex_exit(&mpt->m_mutex);
6025                                         mptsas_log(mpt, CE_WARN, "mptsas phy"
6026                                             " update failed");
6027                                         return;
6028                                 }
6029                                 mutex_exit(&mpt->m_mutex);
6030 
6031                                 /*
6032                                  * topo_node->un.physport is really the PHY#
6033                                  * for direct attached devices
6034                                  */
6035                                 mptsas_smhba_set_one_phy_props(mpt, parent,
6036                                     topo_node->un.physport, &attached_devhdl);
6037 
6038                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6039                                     MPTSAS_VIRTUAL_PORT, 0) !=
6040                                     DDI_PROP_SUCCESS) {
6041                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6042                                             parent, MPTSAS_VIRTUAL_PORT);
6043                                         mptsas_log(mpt, CE_WARN,
6044                                             "mptsas virtual-port"
6045                                             "port prop update failed");
6046                                         return;
6047                                 }
6048                         }
6049                 }
6050                 mutex_enter(&mpt->m_mutex);
6051 
6052                 NDBG20(("mptsas%d handle_topo_change to online devhdl:%x, "
6053                     "phymask:%x.", mpt->m_instance, ptgt->m_devhdl,
6054                     ptgt->m_addr.mta_phymask));
6055                 break;
6056         }
6057         case MPTSAS_DR_EVENT_OFFLINE_TARGET:
6058         {
6059                 devhdl = topo_node->devhdl;
6060                 ptgt = refhash_linear_search(mpt->m_targets,
6061                     mptsas_target_eval_devhdl, &devhdl);
6062                 if (ptgt == NULL)
6063                         break;
6064 
6065                 sas_wwn = ptgt->m_addr.mta_wwn;
6066                 phy = ptgt->m_phynum;
6067 
6068                 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
6069 
6070                 if (sas_wwn) {
6071                         (void) sprintf(addr, "w%016"PRIx64, sas_wwn);
6072                 } else {
6073                         (void) sprintf(addr, "p%x", phy);
6074                 }
6075                 ASSERT(ptgt->m_devhdl == devhdl);
6076 
6077                 if ((topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) ||
6078                     (topo_node->flags ==
6079                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6080                         /*
6081                          * Get latest RAID info if RAID volume status changes
6082                          * or Phys Disk status changes
6083                          */
6084                         (void) mptsas_get_raid_info(mpt);
6085                 }
6086                 /*
6087                  * Abort all outstanding command on the device
6088                  */
6089                 rval = mptsas_do_scsi_reset(mpt, devhdl);
6090                 if (rval) {
6091                         NDBG20(("mptsas%d handle_topo_change to reset target "
6092                             "before offline devhdl:%x, phymask:%x, rval:%x",
6093                             mpt->m_instance, ptgt->m_devhdl,
6094                             ptgt->m_addr.mta_phymask, rval));
6095                 }
6096 
6097                 mutex_exit(&mpt->m_mutex);
6098 
6099                 ndi_devi_enter(scsi_vhci_dip, &circ);
6100                 ndi_devi_enter(parent, &circ1);
6101                 rval = mptsas_offline_target(parent, addr);
6102                 ndi_devi_exit(parent, circ1);
6103                 ndi_devi_exit(scsi_vhci_dip, circ);
6104                 NDBG20(("mptsas%d handle_topo_change to offline devhdl:%x, "
6105                     "phymask:%x, rval:%x", mpt->m_instance,
6106                     ptgt->m_devhdl, ptgt->m_addr.mta_phymask, rval));
6107 
6108                 kmem_free(addr, SCSI_MAXNAMELEN);
6109 
6110                 /*
6111                  * Clear parent's props for SMHBA support
6112                  */
6113                 flags = topo_node->flags;
6114                 if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6115                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6116                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6117                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6118                             DDI_PROP_SUCCESS) {
6119                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6120                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6121                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6122                                     "prop update failed");
6123                                 break;
6124                         }
6125                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6126                             MPTSAS_NUM_PHYS, 0) !=
6127                             DDI_PROP_SUCCESS) {
6128                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6129                                     MPTSAS_NUM_PHYS);
6130                                 mptsas_log(mpt, CE_WARN, "mptsas num phys "
6131                                     "prop update failed");
6132                                 break;
6133                         }
6134                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6135                             MPTSAS_VIRTUAL_PORT, 1) !=
6136                             DDI_PROP_SUCCESS) {
6137                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6138                                     MPTSAS_VIRTUAL_PORT);
6139                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6140                                     "prop update failed");
6141                                 break;
6142                         }
6143                 }
6144 
6145                 mutex_enter(&mpt->m_mutex);
6146                 ptgt->m_led_status = 0;
6147                 (void) mptsas_flush_led_status(mpt, ptgt);
6148                 if (rval == DDI_SUCCESS) {
6149                         refhash_remove(mpt->m_targets, ptgt);
6150                         ptgt = NULL;
6151                 } else {
6152                         /*
6153                          * clean DR_INTRANSITION flag to allow I/O down to
6154                          * PHCI driver since failover finished.
6155                          * Invalidate the devhdl
6156                          */
6157                         ptgt->m_devhdl = MPTSAS_INVALID_DEVHDL;
6158                         ptgt->m_tgt_unconfigured = 0;
6159                         mutex_enter(&mpt->m_tx_waitq_mutex);
6160                         ptgt->m_dr_flag = MPTSAS_DR_INACTIVE;
6161                         mutex_exit(&mpt->m_tx_waitq_mutex);
6162                 }
6163 
6164                 /*
6165                  * Send SAS IO Unit Control to free the dev handle
6166                  */
6167                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6168                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE)) {
6169                         rval = mptsas_free_devhdl(mpt, devhdl);
6170 
6171                         NDBG20(("mptsas%d handle_topo_change to remove "
6172                             "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6173                             rval));
6174                 }
6175 
6176                 break;
6177         }
6178         case MPTSAS_TOPO_FLAG_REMOVE_HANDLE:
6179         {
6180                 devhdl = topo_node->devhdl;
6181                 /*
6182                  * If this is the remove handle event, do a reset first.
6183                  */
6184                 if (topo_node->event == MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
6185                         rval = mptsas_do_scsi_reset(mpt, devhdl);
6186                         if (rval) {
6187                                 NDBG20(("mpt%d reset target before remove "
6188                                     "devhdl:%x, rval:%x", mpt->m_instance,
6189                                     devhdl, rval));
6190                         }
6191                 }
6192 
6193                 /*
6194                  * Send SAS IO Unit Control to free the dev handle
6195                  */
6196                 rval = mptsas_free_devhdl(mpt, devhdl);
6197                 NDBG20(("mptsas%d handle_topo_change to remove "
6198                     "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6199                     rval));
6200                 break;
6201         }
6202         case MPTSAS_DR_EVENT_RECONFIG_SMP:
6203         {
6204                 mptsas_smp_t smp;
6205                 dev_info_t *smpdip;
6206 
6207                 devhdl = topo_node->devhdl;
6208 
6209                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
6210                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)devhdl;
6211                 rval = mptsas_get_sas_expander_page0(mpt, page_address, &smp);
6212                 if (rval != DDI_SUCCESS) {
6213                         mptsas_log(mpt, CE_WARN, "failed to online smp, "
6214                             "handle %x", devhdl);
6215                         return;
6216                 }
6217 
6218                 psmp = mptsas_smp_alloc(mpt, &smp);
6219                 if (psmp == NULL) {
6220                         return;
6221                 }
6222 
6223                 mutex_exit(&mpt->m_mutex);
6224                 ndi_devi_enter(parent, &circ1);
6225                 (void) mptsas_online_smp(parent, psmp, &smpdip);
6226                 ndi_devi_exit(parent, circ1);
6227 
6228                 mutex_enter(&mpt->m_mutex);
6229                 break;
6230         }
6231         case MPTSAS_DR_EVENT_OFFLINE_SMP:
6232         {
6233                 devhdl = topo_node->devhdl;
6234                 uint32_t dev_info;
6235 
6236                 psmp = refhash_linear_search(mpt->m_smp_targets,
6237                     mptsas_smp_eval_devhdl, &devhdl);
6238                 if (psmp == NULL)
6239                         break;
6240                 /*
6241                  * The mptsas_smp_t data is released only if the dip is offlined
6242                  * successfully.
6243                  */
6244                 mutex_exit(&mpt->m_mutex);
6245 
6246                 ndi_devi_enter(parent, &circ1);
6247                 rval = mptsas_offline_smp(parent, psmp, NDI_DEVI_REMOVE);
6248                 ndi_devi_exit(parent, circ1);
6249 
6250                 dev_info = psmp->m_deviceinfo;
6251                 if ((dev_info & DEVINFO_DIRECT_ATTACHED) ==
6252                     DEVINFO_DIRECT_ATTACHED) {
6253                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6254                             MPTSAS_VIRTUAL_PORT, 1) !=
6255                             DDI_PROP_SUCCESS) {
6256                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6257                                     MPTSAS_VIRTUAL_PORT);
6258                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6259                                     "prop update failed");
6260                                 return;
6261                         }
6262                         /*
6263                          * Check whether the smp connected to the iport,
6264                          */
6265                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6266                             MPTSAS_NUM_PHYS, 0) !=
6267                             DDI_PROP_SUCCESS) {
6268                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6269                                     MPTSAS_NUM_PHYS);
6270                                 mptsas_log(mpt, CE_WARN, "mptsas num phys"
6271                                     "prop update failed");
6272                                 return;
6273                         }
6274                         /*
6275                          * Clear parent's attached-port props
6276                          */
6277                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6278                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6279                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6280                             DDI_PROP_SUCCESS) {
6281                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6282                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6283                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6284                                     "prop update failed");
6285                                 return;
6286                         }
6287                 }
6288 
6289                 mutex_enter(&mpt->m_mutex);
6290                 NDBG20(("mptsas%d handle_topo_change to remove devhdl:%x, "
6291                     "rval:%x", mpt->m_instance, psmp->m_devhdl, rval));
6292                 if (rval == DDI_SUCCESS) {
6293                         refhash_remove(mpt->m_smp_targets, psmp);
6294                 } else {
6295                         psmp->m_devhdl = MPTSAS_INVALID_DEVHDL;
6296                 }
6297 
6298                 bzero(attached_wwnstr, sizeof (attached_wwnstr));
6299 
6300                 break;
6301         }
6302         default:
6303                 return;
6304         }
6305 }
6306 
6307 /*
6308  * Record the event if its type is enabled in mpt instance by ioctl.
6309  */
6310 static void
6311 mptsas_record_event(void *args)
6312 {
6313         m_replyh_arg_t                  *replyh_arg;
6314         pMpi2EventNotificationReply_t   eventreply;
6315         uint32_t                        event, rfm;
6316         mptsas_t                        *mpt;
6317         int                             i, j;
6318         uint16_t                        event_data_len;
6319         boolean_t                       sendAEN = FALSE;
6320 
6321         replyh_arg = (m_replyh_arg_t *)args;
6322         rfm = replyh_arg->rfm;
6323         mpt = replyh_arg->mpt;
6324 
6325         eventreply = (pMpi2EventNotificationReply_t)
6326             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
6327         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6328 
6329 
6330         /*
6331          * Generate a system event to let anyone who cares know that a
6332          * LOG_ENTRY_ADDED event has occurred.  This is sent no matter what the
6333          * event mask is set to.
6334          */
6335         if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
6336                 sendAEN = TRUE;
6337         }
6338 
6339         /*
6340          * Record the event only if it is not masked.  Determine which dword
6341          * and bit of event mask to test.
6342          */
6343         i = (uint8_t)(event / 32);
6344         j = (uint8_t)(event % 32);
6345         if ((i < 4) && ((1 << j) & mpt->m_event_mask[i])) {
6346                 i = mpt->m_event_index;
6347                 mpt->m_events[i].Type = event;
6348                 mpt->m_events[i].Number = ++mpt->m_event_number;
6349                 bzero(mpt->m_events[i].Data, MPTSAS_MAX_EVENT_DATA_LENGTH * 4);
6350                 event_data_len = ddi_get16(mpt->m_acc_reply_frame_hdl,
6351                     &eventreply->EventDataLength);
6352 
6353                 if (event_data_len > 0) {
6354                         /*
6355                          * Limit data to size in m_event entry
6356                          */
6357                         if (event_data_len > MPTSAS_MAX_EVENT_DATA_LENGTH) {
6358                                 event_data_len = MPTSAS_MAX_EVENT_DATA_LENGTH;
6359                         }
6360                         for (j = 0; j < event_data_len; j++) {
6361                                 mpt->m_events[i].Data[j] =
6362                                     ddi_get32(mpt->m_acc_reply_frame_hdl,
6363                                     &(eventreply->EventData[j]));
6364                         }
6365 
6366                         /*
6367                          * check for index wrap-around
6368                          */
6369                         if (++i == MPTSAS_EVENT_QUEUE_SIZE) {
6370                                 i = 0;
6371                         }
6372                         mpt->m_event_index = (uint8_t)i;
6373 
6374                         /*
6375                          * Set flag to send the event.
6376                          */
6377                         sendAEN = TRUE;
6378                 }
6379         }
6380 
6381         /*
6382          * Generate a system event if flag is set to let anyone who cares know
6383          * that an event has occurred.
6384          */
6385         if (sendAEN) {
6386                 (void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS",
6387                     "SAS", NULL, NULL, DDI_NOSLEEP);
6388         }
6389 }
6390 
6391 #define SMP_RESET_IN_PROGRESS MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS
6392 /*
6393  * handle sync events from ioc in interrupt
6394  * return value:
6395  * DDI_SUCCESS: The event is handled by this func
6396  * DDI_FAILURE: Event is not handled
6397  */
6398 static int
6399 mptsas_handle_event_sync(void *args)
6400 {
6401         m_replyh_arg_t                  *replyh_arg;
6402         pMpi2EventNotificationReply_t   eventreply;
6403         uint32_t                        event, rfm;
6404         mptsas_t                        *mpt;
6405         uint_t                          iocstatus;
6406 
6407         replyh_arg = (m_replyh_arg_t *)args;
6408         rfm = replyh_arg->rfm;
6409         mpt = replyh_arg->mpt;
6410 
6411         ASSERT(mutex_owned(&mpt->m_mutex));
6412 
6413         eventreply = (pMpi2EventNotificationReply_t)
6414             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
6415         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6416 
6417         if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
6418             &eventreply->IOCStatus)) {
6419                 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
6420                         mptsas_log(mpt, CE_WARN,
6421                             "!mptsas_handle_event_sync: IOCStatus=0x%x, "
6422                             "IOCLogInfo=0x%x", iocstatus,
6423                             ddi_get32(mpt->m_acc_reply_frame_hdl,
6424                             &eventreply->IOCLogInfo));
6425                 } else {
6426                         mptsas_log(mpt, CE_WARN,
6427                             "mptsas_handle_event_sync: IOCStatus=0x%x, "
6428                             "IOCLogInfo=0x%x", iocstatus,
6429                             ddi_get32(mpt->m_acc_reply_frame_hdl,
6430                             &eventreply->IOCLogInfo));
6431                 }
6432         }
6433 
6434         /*
6435          * figure out what kind of event we got and handle accordingly
6436          */
6437         switch (event) {
6438         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
6439         {
6440                 pMpi2EventDataSasTopologyChangeList_t   sas_topo_change_list;
6441                 uint8_t                         num_entries, expstatus, phy;
6442                 uint8_t                         phystatus, physport, state, i;
6443                 uint8_t                         start_phy_num, link_rate;
6444                 uint16_t                        dev_handle, reason_code;
6445                 uint16_t                        enc_handle, expd_handle;
6446                 char                            string[80], curr[80], prev[80];
6447                 mptsas_topo_change_list_t       *topo_head = NULL;
6448                 mptsas_topo_change_list_t       *topo_tail = NULL;
6449                 mptsas_topo_change_list_t       *topo_node = NULL;
6450                 mptsas_target_t                 *ptgt;
6451                 mptsas_smp_t                    *psmp;
6452                 uint8_t                         flags = 0, exp_flag;
6453                 smhba_info_t                    *pSmhba = NULL;
6454 
6455                 NDBG20(("mptsas_handle_event_sync: SAS topology change"));
6456 
6457                 sas_topo_change_list = (pMpi2EventDataSasTopologyChangeList_t)
6458                     eventreply->EventData;
6459 
6460                 enc_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6461                     &sas_topo_change_list->EnclosureHandle);
6462                 expd_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6463                     &sas_topo_change_list->ExpanderDevHandle);
6464                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6465                     &sas_topo_change_list->NumEntries);
6466                 start_phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
6467                     &sas_topo_change_list->StartPhyNum);
6468                 expstatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6469                     &sas_topo_change_list->ExpStatus);
6470                 physport = ddi_get8(mpt->m_acc_reply_frame_hdl,
6471                     &sas_topo_change_list->PhysicalPort);
6472 
6473                 string[0] = 0;
6474                 if (expd_handle) {
6475                         flags = MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED;
6476                         switch (expstatus) {
6477                         case MPI2_EVENT_SAS_TOPO_ES_ADDED:
6478                                 (void) sprintf(string, " added");
6479                                 /*
6480                                  * New expander device added
6481                                  */
6482                                 mpt->m_port_chng = 1;
6483                                 topo_node = kmem_zalloc(
6484                                     sizeof (mptsas_topo_change_list_t),
6485                                     KM_SLEEP);
6486                                 topo_node->mpt = mpt;
6487                                 topo_node->event = MPTSAS_DR_EVENT_RECONFIG_SMP;
6488                                 topo_node->un.physport = physport;
6489                                 topo_node->devhdl = expd_handle;
6490                                 topo_node->flags = flags;
6491                                 topo_node->object = NULL;
6492                                 if (topo_head == NULL) {
6493                                         topo_head = topo_tail = topo_node;
6494                                 } else {
6495                                         topo_tail->next = topo_node;
6496                                         topo_tail = topo_node;
6497                                 }
6498                                 break;
6499                         case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
6500                                 (void) sprintf(string, " not responding, "
6501                                     "removed");
6502                                 psmp = refhash_linear_search(mpt->m_smp_targets,
6503                                     mptsas_smp_eval_devhdl, &expd_handle);
6504                                 if (psmp == NULL)
6505                                         break;
6506 
6507                                 topo_node = kmem_zalloc(
6508                                     sizeof (mptsas_topo_change_list_t),
6509                                     KM_SLEEP);
6510                                 topo_node->mpt = mpt;
6511                                 topo_node->un.phymask =
6512                                     psmp->m_addr.mta_phymask;
6513                                 topo_node->event = MPTSAS_DR_EVENT_OFFLINE_SMP;
6514                                 topo_node->devhdl = expd_handle;
6515                                 topo_node->flags = flags;
6516                                 topo_node->object = NULL;
6517                                 if (topo_head == NULL) {
6518                                         topo_head = topo_tail = topo_node;
6519                                 } else {
6520                                         topo_tail->next = topo_node;
6521                                         topo_tail = topo_node;
6522                                 }
6523                                 break;
6524                         case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
6525                                 break;
6526                         case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
6527                                 (void) sprintf(string, " not responding, "
6528                                     "delaying removal");
6529                                 break;
6530                         default:
6531                                 break;
6532                         }
6533                 } else {
6534                         flags = MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE;
6535                 }
6536 
6537                 NDBG20(("SAS TOPOLOGY CHANGE for enclosure %x expander %x%s\n",
6538                     enc_handle, expd_handle, string));
6539                 for (i = 0; i < num_entries; i++) {
6540                         phy = i + start_phy_num;
6541                         phystatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6542                             &sas_topo_change_list->PHY[i].PhyStatus);
6543                         dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6544                             &sas_topo_change_list->PHY[i].AttachedDevHandle);
6545                         reason_code = phystatus & MPI2_EVENT_SAS_TOPO_RC_MASK;
6546                         /*
6547                          * Filter out processing of Phy Vacant Status unless
6548                          * the reason code is "Not Responding".  Process all
6549                          * other combinations of Phy Status and Reason Codes.
6550                          */
6551                         if ((phystatus &
6552                             MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) &&
6553                             (reason_code !=
6554                             MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) {
6555                                 continue;
6556                         }
6557                         curr[0] = 0;
6558                         prev[0] = 0;
6559                         string[0] = 0;
6560                         switch (reason_code) {
6561                         case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
6562                         {
6563                                 NDBG20(("mptsas%d phy %d physical_port %d "
6564                                     "dev_handle %d added", mpt->m_instance, phy,
6565                                     physport, dev_handle));
6566                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
6567                                     &sas_topo_change_list->PHY[i].LinkRate);
6568                                 state = (link_rate &
6569                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
6570                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
6571                                 switch (state) {
6572                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
6573                                         (void) sprintf(curr, "is disabled");
6574                                         break;
6575                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
6576                                         (void) sprintf(curr, "is offline, "
6577                                             "failed speed negotiation");
6578                                         break;
6579                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
6580                                         (void) sprintf(curr, "SATA OOB "
6581                                             "complete");
6582                                         break;
6583                                 case SMP_RESET_IN_PROGRESS:
6584                                         (void) sprintf(curr, "SMP reset in "
6585                                             "progress");
6586                                         break;
6587                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
6588                                         (void) sprintf(curr, "is online at "
6589                                             "1.5 Gbps");
6590                                         break;
6591                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
6592                                         (void) sprintf(curr, "is online at 3.0 "
6593                                             "Gbps");
6594                                         break;
6595                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
6596                                         (void) sprintf(curr, "is online at 6.0 "
6597                                             "Gbps");
6598                                         break;
6599                                 default:
6600                                         (void) sprintf(curr, "state is "
6601                                             "unknown");
6602                                         break;
6603                                 }
6604                                 /*
6605                                  * New target device added into the system.
6606                                  * Set association flag according to if an
6607                                  * expander is used or not.
6608                                  */
6609                                 exp_flag =
6610                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
6611                                 if (flags ==
6612                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
6613                                         flags = exp_flag;
6614                                 }
6615                                 topo_node = kmem_zalloc(
6616                                     sizeof (mptsas_topo_change_list_t),
6617                                     KM_SLEEP);
6618                                 topo_node->mpt = mpt;
6619                                 topo_node->event =
6620                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
6621                                 if (expd_handle == 0) {
6622                                         /*
6623                                          * Per MPI 2, if expander dev handle
6624                                          * is 0, it's a directly attached
6625                                          * device. So driver use PHY to decide
6626                                          * which iport is associated
6627                                          */
6628                                         physport = phy;
6629                                         mpt->m_port_chng = 1;
6630                                 }
6631                                 topo_node->un.physport = physport;
6632                                 topo_node->devhdl = dev_handle;
6633                                 topo_node->flags = flags;
6634                                 topo_node->object = NULL;
6635                                 if (topo_head == NULL) {
6636                                         topo_head = topo_tail = topo_node;
6637                                 } else {
6638                                         topo_tail->next = topo_node;
6639                                         topo_tail = topo_node;
6640                                 }
6641                                 break;
6642                         }
6643                         case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
6644                         {
6645                                 NDBG20(("mptsas%d phy %d physical_port %d "
6646                                     "dev_handle %d removed", mpt->m_instance,
6647                                     phy, physport, dev_handle));
6648                                 /*
6649                                  * Set association flag according to if an
6650                                  * expander is used or not.
6651                                  */
6652                                 exp_flag =
6653                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
6654                                 if (flags ==
6655                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
6656                                         flags = exp_flag;
6657                                 }
6658                                 /*
6659                                  * Target device is removed from the system
6660                                  * Before the device is really offline from
6661                                  * from system.
6662                                  */
6663                                 ptgt = refhash_linear_search(mpt->m_targets,
6664                                     mptsas_target_eval_devhdl, &dev_handle);
6665                                 /*
6666                                  * If ptgt is NULL here, it means that the
6667                                  * DevHandle is not in the hash table.  This is
6668                                  * reasonable sometimes.  For example, if a
6669                                  * disk was pulled, then added, then pulled
6670                                  * again, the disk will not have been put into
6671                                  * the hash table because the add event will
6672                                  * have an invalid phymask.  BUT, this does not
6673                                  * mean that the DevHandle is invalid.  The
6674                                  * controller will still have a valid DevHandle
6675                                  * that must be removed.  To do this, use the
6676                                  * MPTSAS_TOPO_FLAG_REMOVE_HANDLE event.
6677                                  */
6678                                 if (ptgt == NULL) {
6679                                         topo_node = kmem_zalloc(
6680                                             sizeof (mptsas_topo_change_list_t),
6681                                             KM_SLEEP);
6682                                         topo_node->mpt = mpt;
6683                                         topo_node->un.phymask = 0;
6684                                         topo_node->event =
6685                                             MPTSAS_TOPO_FLAG_REMOVE_HANDLE;
6686                                         topo_node->devhdl = dev_handle;
6687                                         topo_node->flags = flags;
6688                                         topo_node->object = NULL;
6689                                         if (topo_head == NULL) {
6690                                                 topo_head = topo_tail =
6691                                                     topo_node;
6692                                         } else {
6693                                                 topo_tail->next = topo_node;
6694                                                 topo_tail = topo_node;
6695                                         }
6696                                         break;
6697                                 }
6698 
6699                                 /*
6700                                  * Update DR flag immediately avoid I/O failure
6701                                  * before failover finish. Pay attention to the
6702                                  * mutex protect, we need grab m_tx_waitq_mutex
6703                                  * during set m_dr_flag because we won't add
6704                                  * the following command into waitq, instead,
6705                                  * we need return TRAN_BUSY in the tran_start
6706                                  * context.
6707                                  */
6708                                 mutex_enter(&mpt->m_tx_waitq_mutex);
6709                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6710                                 mutex_exit(&mpt->m_tx_waitq_mutex);
6711 
6712                                 topo_node = kmem_zalloc(
6713                                     sizeof (mptsas_topo_change_list_t),
6714                                     KM_SLEEP);
6715                                 topo_node->mpt = mpt;
6716                                 topo_node->un.phymask =
6717                                     ptgt->m_addr.mta_phymask;
6718                                 topo_node->event =
6719                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
6720                                 topo_node->devhdl = dev_handle;
6721                                 topo_node->flags = flags;
6722                                 topo_node->object = NULL;
6723                                 if (topo_head == NULL) {
6724                                         topo_head = topo_tail = topo_node;
6725                                 } else {
6726                                         topo_tail->next = topo_node;
6727                                         topo_tail = topo_node;
6728                                 }
6729                                 break;
6730                         }
6731                         case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
6732                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
6733                                     &sas_topo_change_list->PHY[i].LinkRate);
6734                                 state = (link_rate &
6735                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
6736                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
6737                                 pSmhba = &mpt->m_phy_info[i].smhba_info;
6738                                 pSmhba->negotiated_link_rate = state;
6739                                 switch (state) {
6740                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
6741                                         (void) sprintf(curr, "is disabled");
6742                                         mptsas_smhba_log_sysevent(mpt,
6743                                             ESC_SAS_PHY_EVENT,
6744                                             SAS_PHY_REMOVE,
6745                                             &mpt->m_phy_info[i].smhba_info);
6746                                         mpt->m_phy_info[i].smhba_info.
6747                                             negotiated_link_rate
6748                                             = 0x1;
6749                                         break;
6750                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
6751                                         (void) sprintf(curr, "is offline, "
6752                                             "failed speed negotiation");
6753                                         mptsas_smhba_log_sysevent(mpt,
6754                                             ESC_SAS_PHY_EVENT,
6755                                             SAS_PHY_OFFLINE,
6756                                             &mpt->m_phy_info[i].smhba_info);
6757                                         break;
6758                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
6759                                         (void) sprintf(curr, "SATA OOB "
6760                                             "complete");
6761                                         break;
6762                                 case SMP_RESET_IN_PROGRESS:
6763                                         (void) sprintf(curr, "SMP reset in "
6764                                             "progress");
6765                                         break;
6766                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
6767                                         (void) sprintf(curr, "is online at "
6768                                             "1.5 Gbps");
6769                                         if ((expd_handle == 0) &&
6770                                             (enc_handle == 1)) {
6771                                                 mpt->m_port_chng = 1;
6772                                         }
6773                                         mptsas_smhba_log_sysevent(mpt,
6774                                             ESC_SAS_PHY_EVENT,
6775                                             SAS_PHY_ONLINE,
6776                                             &mpt->m_phy_info[i].smhba_info);
6777                                         break;
6778                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
6779                                         (void) sprintf(curr, "is online at 3.0 "
6780                                             "Gbps");
6781                                         if ((expd_handle == 0) &&
6782                                             (enc_handle == 1)) {
6783                                                 mpt->m_port_chng = 1;
6784                                         }
6785                                         mptsas_smhba_log_sysevent(mpt,
6786                                             ESC_SAS_PHY_EVENT,
6787                                             SAS_PHY_ONLINE,
6788                                             &mpt->m_phy_info[i].smhba_info);
6789                                         break;
6790                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
6791                                         (void) sprintf(curr, "is online at "
6792                                             "6.0 Gbps");
6793                                         if ((expd_handle == 0) &&
6794                                             (enc_handle == 1)) {
6795                                                 mpt->m_port_chng = 1;
6796                                         }
6797                                         mptsas_smhba_log_sysevent(mpt,
6798                                             ESC_SAS_PHY_EVENT,
6799                                             SAS_PHY_ONLINE,
6800                                             &mpt->m_phy_info[i].smhba_info);
6801                                         break;
6802                                 default:
6803                                         (void) sprintf(curr, "state is "
6804                                             "unknown");
6805                                         break;
6806                                 }
6807 
6808                                 state = (link_rate &
6809                                     MPI2_EVENT_SAS_TOPO_LR_PREV_MASK) >>
6810                                     MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT;
6811                                 switch (state) {
6812                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
6813                                         (void) sprintf(prev, ", was disabled");
6814                                         break;
6815                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
6816                                         (void) sprintf(prev, ", was offline, "
6817                                             "failed speed negotiation");
6818                                         break;
6819                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
6820                                         (void) sprintf(prev, ", was SATA OOB "
6821                                             "complete");
6822                                         break;
6823                                 case SMP_RESET_IN_PROGRESS:
6824                                         (void) sprintf(prev, ", was SMP reset "
6825                                             "in progress");
6826                                         break;
6827                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
6828                                         (void) sprintf(prev, ", was online at "
6829                                             "1.5 Gbps");
6830                                         break;
6831                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
6832                                         (void) sprintf(prev, ", was online at "
6833                                             "3.0 Gbps");
6834                                         break;
6835                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
6836                                         (void) sprintf(prev, ", was online at "
6837                                             "6.0 Gbps");
6838                                         break;
6839                                 default:
6840                                 break;
6841                                 }
6842                                 (void) sprintf(&string[strlen(string)], "link "
6843                                     "changed, ");
6844                                 break;
6845                         case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
6846                                 continue;
6847                         case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
6848                                 (void) sprintf(&string[strlen(string)],
6849                                     "target not responding, delaying "
6850                                     "removal");
6851                                 break;
6852                         }
6853                         NDBG20(("mptsas%d phy %d DevHandle %x, %s%s%s\n",
6854                             mpt->m_instance, phy, dev_handle, string, curr,
6855                             prev));
6856                 }
6857                 if (topo_head != NULL) {
6858                         /*
6859                          * Launch DR taskq to handle topology change
6860                          */
6861                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
6862                             mptsas_handle_dr, (void *)topo_head,
6863                             DDI_NOSLEEP)) != DDI_SUCCESS) {
6864                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
6865                                     "for handle SAS DR event failed. \n");
6866                         }
6867                 }
6868                 break;
6869         }
6870         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
6871         {
6872                 Mpi2EventDataIrConfigChangeList_t       *irChangeList;
6873                 mptsas_topo_change_list_t               *topo_head = NULL;
6874                 mptsas_topo_change_list_t               *topo_tail = NULL;
6875                 mptsas_topo_change_list_t               *topo_node = NULL;
6876                 mptsas_target_t                         *ptgt;
6877                 uint8_t                                 num_entries, i, reason;
6878                 uint16_t                                volhandle, diskhandle;
6879 
6880                 irChangeList = (pMpi2EventDataIrConfigChangeList_t)
6881                     eventreply->EventData;
6882                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6883                     &irChangeList->NumElements);
6884 
6885                 NDBG20(("mptsas%d IR_CONFIGURATION_CHANGE_LIST event received",
6886                     mpt->m_instance));
6887 
6888                 for (i = 0; i < num_entries; i++) {
6889                         reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
6890                             &irChangeList->ConfigElement[i].ReasonCode);
6891                         volhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6892                             &irChangeList->ConfigElement[i].VolDevHandle);
6893                         diskhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6894                             &irChangeList->ConfigElement[i].PhysDiskDevHandle);
6895 
6896                         switch (reason) {
6897                         case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6898                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6899                         {
6900                                 NDBG20(("mptsas %d volume added\n",
6901                                     mpt->m_instance));
6902 
6903                                 topo_node = kmem_zalloc(
6904                                     sizeof (mptsas_topo_change_list_t),
6905                                     KM_SLEEP);
6906 
6907                                 topo_node->mpt = mpt;
6908                                 topo_node->event =
6909                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
6910                                 topo_node->un.physport = 0xff;
6911                                 topo_node->devhdl = volhandle;
6912                                 topo_node->flags =
6913                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
6914                                 topo_node->object = NULL;
6915                                 if (topo_head == NULL) {
6916                                         topo_head = topo_tail = topo_node;
6917                                 } else {
6918                                         topo_tail->next = topo_node;
6919                                         topo_tail = topo_node;
6920                                 }
6921                                 break;
6922                         }
6923                         case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6924                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6925                         {
6926                                 NDBG20(("mptsas %d volume deleted\n",
6927                                     mpt->m_instance));
6928                                 ptgt = refhash_linear_search(mpt->m_targets,
6929                                     mptsas_target_eval_devhdl, &volhandle);
6930                                 if (ptgt == NULL)
6931                                         break;
6932 
6933                                 /*
6934                                  * Clear any flags related to volume
6935                                  */
6936                                 (void) mptsas_delete_volume(mpt, volhandle);
6937 
6938                                 /*
6939                                  * Update DR flag immediately avoid I/O failure
6940                                  */
6941                                 mutex_enter(&mpt->m_tx_waitq_mutex);
6942                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6943                                 mutex_exit(&mpt->m_tx_waitq_mutex);
6944 
6945                                 topo_node = kmem_zalloc(
6946                                     sizeof (mptsas_topo_change_list_t),
6947                                     KM_SLEEP);
6948                                 topo_node->mpt = mpt;
6949                                 topo_node->un.phymask =
6950                                     ptgt->m_addr.mta_phymask;
6951                                 topo_node->event =
6952                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
6953                                 topo_node->devhdl = volhandle;
6954                                 topo_node->flags =
6955                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
6956                                 topo_node->object = (void *)ptgt;
6957                                 if (topo_head == NULL) {
6958                                         topo_head = topo_tail = topo_node;
6959                                 } else {
6960                                         topo_tail->next = topo_node;
6961                                         topo_tail = topo_node;
6962                                 }
6963                                 break;
6964                         }
6965                         case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
6966                         case MPI2_EVENT_IR_CHANGE_RC_HIDE:
6967                         {
6968                                 ptgt = refhash_linear_search(mpt->m_targets,
6969                                     mptsas_target_eval_devhdl, &diskhandle);
6970                                 if (ptgt == NULL)
6971                                         break;
6972 
6973                                 /*
6974                                  * Update DR flag immediately avoid I/O failure
6975                                  */
6976                                 mutex_enter(&mpt->m_tx_waitq_mutex);
6977                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6978                                 mutex_exit(&mpt->m_tx_waitq_mutex);
6979 
6980                                 topo_node = kmem_zalloc(
6981                                     sizeof (mptsas_topo_change_list_t),
6982                                     KM_SLEEP);
6983                                 topo_node->mpt = mpt;
6984                                 topo_node->un.phymask =
6985                                     ptgt->m_addr.mta_phymask;
6986                                 topo_node->event =
6987                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
6988                                 topo_node->devhdl = diskhandle;
6989                                 topo_node->flags =
6990                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
6991                                 topo_node->object = (void *)ptgt;
6992                                 if (topo_head == NULL) {
6993                                         topo_head = topo_tail = topo_node;
6994                                 } else {
6995                                         topo_tail->next = topo_node;
6996                                         topo_tail = topo_node;
6997                                 }
6998                                 break;
6999                         }
7000                         case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
7001                         case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
7002                         {
7003                                 /*
7004                                  * The physical drive is released by a IR
7005                                  * volume. But we cannot get the the physport
7006                                  * or phynum from the event data, so we only
7007                                  * can get the physport/phynum after SAS
7008                                  * Device Page0 request for the devhdl.
7009                                  */
7010                                 topo_node = kmem_zalloc(
7011                                     sizeof (mptsas_topo_change_list_t),
7012                                     KM_SLEEP);
7013                                 topo_node->mpt = mpt;
7014                                 topo_node->un.phymask = 0;
7015                                 topo_node->event =
7016                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
7017                                 topo_node->devhdl = diskhandle;
7018                                 topo_node->flags =
7019                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
7020                                 topo_node->object = NULL;
7021                                 mpt->m_port_chng = 1;
7022                                 if (topo_head == NULL) {
7023                                         topo_head = topo_tail = topo_node;
7024                                 } else {
7025                                         topo_tail->next = topo_node;
7026                                         topo_tail = topo_node;
7027                                 }
7028                                 break;
7029                         }
7030                         default:
7031                                 break;
7032                         }
7033                 }
7034 
7035                 if (topo_head != NULL) {
7036                         /*
7037                          * Launch DR taskq to handle topology change
7038                          */
7039                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
7040                             mptsas_handle_dr, (void *)topo_head,
7041                             DDI_NOSLEEP)) != DDI_SUCCESS) {
7042                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
7043                                     "for handle SAS DR event failed. \n");
7044                         }
7045                 }
7046                 break;
7047         }
7048         default:
7049                 return (DDI_FAILURE);
7050         }
7051 
7052         return (DDI_SUCCESS);
7053 }
7054 
7055 /*
7056  * handle events from ioc
7057  */
7058 static void
7059 mptsas_handle_event(void *args)
7060 {
7061         m_replyh_arg_t                  *replyh_arg;
7062         pMpi2EventNotificationReply_t   eventreply;
7063         uint32_t                        event, iocloginfo, rfm;
7064         uint32_t                        status;
7065         uint8_t                         port;
7066         mptsas_t                        *mpt;
7067         uint_t                          iocstatus;
7068 
7069         replyh_arg = (m_replyh_arg_t *)args;
7070         rfm = replyh_arg->rfm;
7071         mpt = replyh_arg->mpt;
7072 
7073         mutex_enter(&mpt->m_mutex);
7074         /*
7075          * If HBA is being reset, drop incoming event.
7076          */
7077         if (mpt->m_in_reset) {
7078                 NDBG20(("dropping event received prior to reset"));
7079                 mutex_exit(&mpt->m_mutex);
7080                 return;
7081         }
7082 
7083         eventreply = (pMpi2EventNotificationReply_t)
7084             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
7085         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
7086 
7087         if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
7088             &eventreply->IOCStatus)) {
7089                 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
7090                         mptsas_log(mpt, CE_WARN,
7091                             "!mptsas_handle_event: IOCStatus=0x%x, "
7092                             "IOCLogInfo=0x%x", iocstatus,
7093                             ddi_get32(mpt->m_acc_reply_frame_hdl,
7094                             &eventreply->IOCLogInfo));
7095                 } else {
7096                         mptsas_log(mpt, CE_WARN,
7097                             "mptsas_handle_event: IOCStatus=0x%x, "
7098                             "IOCLogInfo=0x%x", iocstatus,
7099                             ddi_get32(mpt->m_acc_reply_frame_hdl,
7100                             &eventreply->IOCLogInfo));
7101                 }
7102         }
7103 
7104         /*
7105          * figure out what kind of event we got and handle accordingly
7106          */
7107         switch (event) {
7108         case MPI2_EVENT_LOG_ENTRY_ADDED:
7109                 break;
7110         case MPI2_EVENT_LOG_DATA:
7111                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7112                     &eventreply->IOCLogInfo);
7113                 NDBG20(("mptsas %d log info %x received.\n", mpt->m_instance,
7114                     iocloginfo));
7115                 break;
7116         case MPI2_EVENT_STATE_CHANGE:
7117                 NDBG20(("mptsas%d state change.", mpt->m_instance));
7118                 break;
7119         case MPI2_EVENT_HARD_RESET_RECEIVED:
7120                 NDBG20(("mptsas%d event change.", mpt->m_instance));
7121                 break;
7122         case MPI2_EVENT_SAS_DISCOVERY:
7123         {
7124                 MPI2_EVENT_DATA_SAS_DISCOVERY   *sasdiscovery;
7125                 char                            string[80];
7126                 uint8_t                         rc;
7127 
7128                 sasdiscovery =
7129                     (pMpi2EventDataSasDiscovery_t)eventreply->EventData;
7130 
7131                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7132                     &sasdiscovery->ReasonCode);
7133                 port = ddi_get8(mpt->m_acc_reply_frame_hdl,
7134                     &sasdiscovery->PhysicalPort);
7135                 status = ddi_get32(mpt->m_acc_reply_frame_hdl,
7136                     &sasdiscovery->DiscoveryStatus);
7137 
7138                 string[0] = 0;
7139                 switch (rc) {
7140                 case MPI2_EVENT_SAS_DISC_RC_STARTED:
7141                         (void) sprintf(string, "STARTING");
7142                         break;
7143                 case MPI2_EVENT_SAS_DISC_RC_COMPLETED:
7144                         (void) sprintf(string, "COMPLETED");
7145                         break;
7146                 default:
7147                         (void) sprintf(string, "UNKNOWN");
7148                         break;
7149                 }
7150 
7151                 NDBG20(("SAS DISCOVERY is %s for port %d, status %x", string,
7152                     port, status));
7153 
7154                 break;
7155         }
7156         case MPI2_EVENT_EVENT_CHANGE:
7157                 NDBG20(("mptsas%d event change.", mpt->m_instance));
7158                 break;
7159         case MPI2_EVENT_TASK_SET_FULL:
7160         {
7161                 pMpi2EventDataTaskSetFull_t     taskfull;
7162 
7163                 taskfull = (pMpi2EventDataTaskSetFull_t)eventreply->EventData;
7164 
7165                 NDBG20(("TASK_SET_FULL received for mptsas%d, depth %d\n",
7166                     mpt->m_instance,  ddi_get16(mpt->m_acc_reply_frame_hdl,
7167                     &taskfull->CurrentDepth)));
7168                 break;
7169         }
7170         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7171         {
7172                 /*
7173                  * SAS TOPOLOGY CHANGE LIST Event has already been handled
7174                  * in mptsas_handle_event_sync() of interrupt context
7175                  */
7176                 break;
7177         }
7178         case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7179         {
7180                 pMpi2EventDataSasEnclDevStatusChange_t  encstatus;
7181                 uint8_t                                 rc;
7182                 char                                    string[80];
7183 
7184                 encstatus = (pMpi2EventDataSasEnclDevStatusChange_t)
7185                     eventreply->EventData;
7186 
7187                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7188                     &encstatus->ReasonCode);
7189                 switch (rc) {
7190                 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
7191                         (void) sprintf(string, "added");
7192                         break;
7193                 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
7194                         (void) sprintf(string, ", not responding");
7195                         break;
7196                 default:
7197                 break;
7198                 }
7199                 NDBG20(("mptsas%d ENCLOSURE STATUS CHANGE for enclosure %x%s\n",
7200                     mpt->m_instance, ddi_get16(mpt->m_acc_reply_frame_hdl,
7201                     &encstatus->EnclosureHandle), string));
7202                 break;
7203         }
7204 
7205         /*
7206          * MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE is handled by
7207          * mptsas_handle_event_sync,in here just send ack message.
7208          */
7209         case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7210         {
7211                 pMpi2EventDataSasDeviceStatusChange_t   statuschange;
7212                 uint8_t                                 rc;
7213                 uint16_t                                devhdl;
7214                 uint64_t                                wwn = 0;
7215                 uint32_t                                wwn_lo, wwn_hi;
7216 
7217                 statuschange = (pMpi2EventDataSasDeviceStatusChange_t)
7218                     eventreply->EventData;
7219                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7220                     &statuschange->ReasonCode);
7221                 wwn_lo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7222                     (uint32_t *)(void *)&statuschange->SASAddress);
7223                 wwn_hi = ddi_get32(mpt->m_acc_reply_frame_hdl,
7224                     (uint32_t *)(void *)&statuschange->SASAddress + 1);
7225                 wwn = ((uint64_t)wwn_hi << 32) | wwn_lo;
7226                 devhdl =  ddi_get16(mpt->m_acc_reply_frame_hdl,
7227                     &statuschange->DevHandle);
7228 
7229                 NDBG13(("MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE wwn is %"PRIx64,
7230                     wwn));
7231 
7232                 switch (rc) {
7233                 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
7234                         NDBG20(("SMART data received, ASC/ASCQ = %02x/%02x",
7235                             ddi_get8(mpt->m_acc_reply_frame_hdl,
7236                             &statuschange->ASC),
7237                             ddi_get8(mpt->m_acc_reply_frame_hdl,
7238                             &statuschange->ASCQ)));
7239                         break;
7240 
7241                 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
7242                         NDBG20(("Device not supported"));
7243                         break;
7244 
7245                 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
7246                         NDBG20(("IOC internally generated the Target Reset "
7247                             "for devhdl:%x", devhdl));
7248                         break;
7249 
7250                 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
7251                         NDBG20(("IOC's internally generated Target Reset "
7252                             "completed for devhdl:%x", devhdl));
7253                         break;
7254 
7255                 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
7256                         NDBG20(("IOC internally generated Abort Task"));
7257                         break;
7258 
7259                 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
7260                         NDBG20(("IOC's internally generated Abort Task "
7261                             "completed"));
7262                         break;
7263 
7264                 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
7265                         NDBG20(("IOC internally generated Abort Task Set"));
7266                         break;
7267 
7268                 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
7269                         NDBG20(("IOC internally generated Clear Task Set"));
7270                         break;
7271 
7272                 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
7273                         NDBG20(("IOC internally generated Query Task"));
7274                         break;
7275 
7276                 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
7277                         NDBG20(("Device sent an Asynchronous Notification"));
7278                         break;
7279 
7280                 default:
7281                         break;
7282                 }
7283                 break;
7284         }
7285         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7286         {
7287                 /*
7288                  * IR TOPOLOGY CHANGE LIST Event has already been handled
7289                  * in mpt_handle_event_sync() of interrupt context
7290                  */
7291                 break;
7292         }
7293         case MPI2_EVENT_IR_OPERATION_STATUS:
7294         {
7295                 Mpi2EventDataIrOperationStatus_t        *irOpStatus;
7296                 char                                    reason_str[80];
7297                 uint8_t                                 rc, percent;
7298                 uint16_t                                handle;
7299 
7300                 irOpStatus = (pMpi2EventDataIrOperationStatus_t)
7301                     eventreply->EventData;
7302                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7303                     &irOpStatus->RAIDOperation);
7304                 percent = ddi_get8(mpt->m_acc_reply_frame_hdl,
7305                     &irOpStatus->PercentComplete);
7306                 handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7307                     &irOpStatus->VolDevHandle);
7308 
7309                 switch (rc) {
7310                         case MPI2_EVENT_IR_RAIDOP_RESYNC:
7311                                 (void) sprintf(reason_str, "resync");
7312                                 break;
7313                         case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
7314                                 (void) sprintf(reason_str, "online capacity "
7315                                     "expansion");
7316                                 break;
7317                         case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
7318                                 (void) sprintf(reason_str, "consistency check");
7319                                 break;
7320                         default:
7321                                 (void) sprintf(reason_str, "unknown reason %x",
7322                                     rc);
7323                 }
7324 
7325                 NDBG20(("mptsas%d raid operational status: (%s)"
7326                     "\thandle(0x%04x), percent complete(%d)\n",
7327                     mpt->m_instance, reason_str, handle, percent));
7328                 break;
7329         }
7330         case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7331         {
7332                 pMpi2EventDataSasBroadcastPrimitive_t   sas_broadcast;
7333                 uint8_t                                 phy_num;
7334                 uint8_t                                 primitive;
7335 
7336                 sas_broadcast = (pMpi2EventDataSasBroadcastPrimitive_t)
7337                     eventreply->EventData;
7338 
7339                 phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
7340                     &sas_broadcast->PhyNum);
7341                 primitive = ddi_get8(mpt->m_acc_reply_frame_hdl,
7342                     &sas_broadcast->Primitive);
7343 
7344                 switch (primitive) {
7345                 case MPI2_EVENT_PRIMITIVE_CHANGE:
7346                         mptsas_smhba_log_sysevent(mpt,
7347                             ESC_SAS_HBA_PORT_BROADCAST,
7348                             SAS_PORT_BROADCAST_CHANGE,
7349                             &mpt->m_phy_info[phy_num].smhba_info);
7350                         break;
7351                 case MPI2_EVENT_PRIMITIVE_SES:
7352                         mptsas_smhba_log_sysevent(mpt,
7353                             ESC_SAS_HBA_PORT_BROADCAST,
7354                             SAS_PORT_BROADCAST_SES,
7355                             &mpt->m_phy_info[phy_num].smhba_info);
7356                         break;
7357                 case MPI2_EVENT_PRIMITIVE_EXPANDER:
7358                         mptsas_smhba_log_sysevent(mpt,
7359                             ESC_SAS_HBA_PORT_BROADCAST,
7360                             SAS_PORT_BROADCAST_D01_4,
7361                             &mpt->m_phy_info[phy_num].smhba_info);
7362                         break;
7363                 case MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT:
7364                         mptsas_smhba_log_sysevent(mpt,
7365                             ESC_SAS_HBA_PORT_BROADCAST,
7366                             SAS_PORT_BROADCAST_D04_7,
7367                             &mpt->m_phy_info[phy_num].smhba_info);
7368                         break;
7369                 case MPI2_EVENT_PRIMITIVE_RESERVED3:
7370                         mptsas_smhba_log_sysevent(mpt,
7371                             ESC_SAS_HBA_PORT_BROADCAST,
7372                             SAS_PORT_BROADCAST_D16_7,
7373                             &mpt->m_phy_info[phy_num].smhba_info);
7374                         break;
7375                 case MPI2_EVENT_PRIMITIVE_RESERVED4:
7376                         mptsas_smhba_log_sysevent(mpt,
7377                             ESC_SAS_HBA_PORT_BROADCAST,
7378                             SAS_PORT_BROADCAST_D29_7,
7379                             &mpt->m_phy_info[phy_num].smhba_info);
7380                         break;
7381                 case MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED:
7382                         mptsas_smhba_log_sysevent(mpt,
7383                             ESC_SAS_HBA_PORT_BROADCAST,
7384                             SAS_PORT_BROADCAST_D24_0,
7385                             &mpt->m_phy_info[phy_num].smhba_info);
7386                         break;
7387                 case MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED:
7388                         mptsas_smhba_log_sysevent(mpt,
7389                             ESC_SAS_HBA_PORT_BROADCAST,
7390                             SAS_PORT_BROADCAST_D27_4,
7391                             &mpt->m_phy_info[phy_num].smhba_info);
7392                         break;
7393                 default:
7394                         NDBG20(("mptsas%d: unknown BROADCAST PRIMITIVE"
7395                             " %x received",
7396                             mpt->m_instance, primitive));
7397                         break;
7398                 }
7399                 NDBG20(("mptsas%d sas broadcast primitive: "
7400                     "\tprimitive(0x%04x), phy(%d) complete\n",
7401                     mpt->m_instance, primitive, phy_num));
7402                 break;
7403         }
7404         case MPI2_EVENT_IR_VOLUME:
7405         {
7406                 Mpi2EventDataIrVolume_t         *irVolume;
7407                 uint16_t                        devhandle;
7408                 uint32_t                        state;
7409                 int                             config, vol;
7410                 uint8_t                         found = FALSE;
7411 
7412                 irVolume = (pMpi2EventDataIrVolume_t)eventreply->EventData;
7413                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7414                     &irVolume->NewValue);
7415                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7416                     &irVolume->VolDevHandle);
7417 
7418                 NDBG20(("EVENT_IR_VOLUME event is received"));
7419 
7420                 /*
7421                  * Get latest RAID info and then find the DevHandle for this
7422                  * event in the configuration.  If the DevHandle is not found
7423                  * just exit the event.
7424                  */
7425                 (void) mptsas_get_raid_info(mpt);
7426                 for (config = 0; (config < mpt->m_num_raid_configs) &&
7427                     (!found); config++) {
7428                         for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
7429                                 if (mpt->m_raidconfig[config].m_raidvol[vol].
7430                                     m_raidhandle == devhandle) {
7431                                         found = TRUE;
7432                                         break;
7433                                 }
7434                         }
7435                 }
7436                 if (!found) {
7437                         break;
7438                 }
7439 
7440                 switch (irVolume->ReasonCode) {
7441                 case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
7442                 {
7443                         uint32_t i;
7444                         mpt->m_raidconfig[config].m_raidvol[vol].m_settings =
7445                             state;
7446 
7447                         i = state & MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING;
7448                         mptsas_log(mpt, CE_NOTE, " Volume %d settings changed"
7449                             ", auto-config of hot-swap drives is %s"
7450                             ", write caching is %s"
7451                             ", hot-spare pool mask is %02x\n",
7452                             vol, state &
7453                             MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE
7454                             ? "disabled" : "enabled",
7455                             i == MPI2_RAIDVOL0_SETTING_UNCHANGED
7456                             ? "controlled by member disks" :
7457                             i == MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING
7458                             ? "disabled" :
7459                             i == MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING
7460                             ? "enabled" :
7461                             "incorrectly set",
7462                             (state >> 16) & 0xff);
7463                                 break;
7464                 }
7465                 case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
7466                 {
7467                         mpt->m_raidconfig[config].m_raidvol[vol].m_state =
7468                             (uint8_t)state;
7469 
7470                         mptsas_log(mpt, CE_NOTE,
7471                             "Volume %d is now %s\n", vol,
7472                             state == MPI2_RAID_VOL_STATE_OPTIMAL
7473                             ? "optimal" :
7474                             state == MPI2_RAID_VOL_STATE_DEGRADED
7475                             ? "degraded" :
7476                             state == MPI2_RAID_VOL_STATE_ONLINE
7477                             ? "online" :
7478                             state == MPI2_RAID_VOL_STATE_INITIALIZING
7479                             ? "initializing" :
7480                             state == MPI2_RAID_VOL_STATE_FAILED
7481                             ? "failed" :
7482                             state == MPI2_RAID_VOL_STATE_MISSING
7483                             ? "missing" :
7484                             "state unknown");
7485                         break;
7486                 }
7487                 case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
7488                 {
7489                         mpt->m_raidconfig[config].m_raidvol[vol].
7490                             m_statusflags = state;
7491 
7492                         mptsas_log(mpt, CE_NOTE,
7493                             " Volume %d is now %s%s%s%s%s%s%s%s%s\n",
7494                             vol,
7495                             state & MPI2_RAIDVOL0_STATUS_FLAG_ENABLED
7496                             ? ", enabled" : ", disabled",
7497                             state & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED
7498                             ? ", quiesced" : "",
7499                             state & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE
7500                             ? ", inactive" : ", active",
7501                             state &
7502                             MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL
7503                             ? ", bad block table is full" : "",
7504                             state &
7505                             MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
7506                             ? ", resync in progress" : "",
7507                             state & MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT
7508                             ? ", background initialization in progress" : "",
7509                             state &
7510                             MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION
7511                             ? ", capacity expansion in progress" : "",
7512                             state &
7513                             MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK
7514                             ? ", consistency check in progress" : "",
7515                             state & MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB
7516                             ? ", data scrub in progress" : "");
7517                         break;
7518                 }
7519                 default:
7520                         break;
7521                 }
7522                 break;
7523         }
7524         case MPI2_EVENT_IR_PHYSICAL_DISK:
7525         {
7526                 Mpi2EventDataIrPhysicalDisk_t   *irPhysDisk;
7527                 uint16_t                        devhandle, enchandle, slot;
7528                 uint32_t                        status, state;
7529                 uint8_t                         physdisknum, reason;
7530 
7531                 irPhysDisk = (Mpi2EventDataIrPhysicalDisk_t *)
7532                     eventreply->EventData;
7533                 physdisknum = ddi_get8(mpt->m_acc_reply_frame_hdl,
7534                     &irPhysDisk->PhysDiskNum);
7535                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7536                     &irPhysDisk->PhysDiskDevHandle);
7537                 enchandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7538                     &irPhysDisk->EnclosureHandle);
7539                 slot = ddi_get16(mpt->m_acc_reply_frame_hdl,
7540                     &irPhysDisk->Slot);
7541                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7542                     &irPhysDisk->NewValue);
7543                 reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
7544                     &irPhysDisk->ReasonCode);
7545 
7546                 NDBG20(("EVENT_IR_PHYSICAL_DISK event is received"));
7547 
7548                 switch (reason) {
7549                 case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
7550                         mptsas_log(mpt, CE_NOTE,
7551                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7552                             "for enclosure with handle 0x%x is now in hot "
7553                             "spare pool %d",
7554                             physdisknum, devhandle, slot, enchandle,
7555                             (state >> 16) & 0xff);
7556                         break;
7557 
7558                 case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
7559                         status = state;
7560                         mptsas_log(mpt, CE_NOTE,
7561                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7562                             "for enclosure with handle 0x%x is now "
7563                             "%s%s%s%s%s\n", physdisknum, devhandle, slot,
7564                             enchandle,
7565                             status & MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME
7566                             ? ", inactive" : ", active",
7567                             status & MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
7568                             ? ", out of sync" : "",
7569                             status & MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED
7570                             ? ", quiesced" : "",
7571                             status &
7572                             MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED
7573                             ? ", write cache enabled" : "",
7574                             status & MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET
7575                             ? ", capacity expansion target" : "");
7576                         break;
7577 
7578                 case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
7579                         mptsas_log(mpt, CE_NOTE,
7580                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7581                             "for enclosure with handle 0x%x is now %s\n",
7582                             physdisknum, devhandle, slot, enchandle,
7583                             state == MPI2_RAID_PD_STATE_OPTIMAL
7584                             ? "optimal" :
7585                             state == MPI2_RAID_PD_STATE_REBUILDING
7586                             ? "rebuilding" :
7587                             state == MPI2_RAID_PD_STATE_DEGRADED
7588                             ? "degraded" :
7589                             state == MPI2_RAID_PD_STATE_HOT_SPARE
7590                             ? "a hot spare" :
7591                             state == MPI2_RAID_PD_STATE_ONLINE
7592                             ? "online" :
7593                             state == MPI2_RAID_PD_STATE_OFFLINE
7594                             ? "offline" :
7595                             state == MPI2_RAID_PD_STATE_NOT_COMPATIBLE
7596                             ? "not compatible" :
7597                             state == MPI2_RAID_PD_STATE_NOT_CONFIGURED
7598                             ? "not configured" :
7599                             "state unknown");
7600                         break;
7601                 }
7602                 break;
7603         }
7604         default:
7605                 NDBG20(("mptsas%d: unknown event %x received",
7606                     mpt->m_instance, event));
7607                 break;
7608         }
7609 
7610         /*
7611          * Return the reply frame to the free queue.
7612          */
7613         ddi_put32(mpt->m_acc_free_queue_hdl,
7614             &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index], rfm);
7615         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
7616             DDI_DMA_SYNC_FORDEV);
7617         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
7618                 mpt->m_free_index = 0;
7619         }
7620         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
7621             mpt->m_free_index);
7622         mutex_exit(&mpt->m_mutex);
7623 }
7624 
7625 /*
7626  * invoked from timeout() to restart qfull cmds with throttle == 0
7627  */
7628 static void
7629 mptsas_restart_cmd(void *arg)
7630 {
7631         mptsas_t        *mpt = arg;
7632         mptsas_target_t *ptgt = NULL;
7633 
7634         mutex_enter(&mpt->m_mutex);
7635 
7636         mpt->m_restart_cmd_timeid = 0;
7637 
7638         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
7639             ptgt = refhash_next(mpt->m_targets, ptgt)) {
7640                 if (ptgt->m_reset_delay == 0) {
7641                         if (ptgt->m_t_throttle == QFULL_THROTTLE) {
7642                                 mptsas_set_throttle(mpt, ptgt,
7643                                     MAX_THROTTLE);
7644                         }
7645                 }
7646         }
7647         mptsas_restart_hba(mpt);
7648         mutex_exit(&mpt->m_mutex);
7649 }
7650 
7651 void
7652 mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
7653 {
7654         int             slot;
7655         mptsas_slots_t  *slots = mpt->m_active;
7656         int             t;
7657         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
7658 
7659         ASSERT(cmd != NULL);
7660         ASSERT(cmd->cmd_queued == FALSE);
7661 
7662         /*
7663          * Task Management cmds are removed in their own routines.  Also,
7664          * we don't want to modify timeout based on TM cmds.
7665          */
7666         if (cmd->cmd_flags & CFLAG_TM_CMD) {
7667                 return;
7668         }
7669 
7670         t = Tgt(cmd);
7671         slot = cmd->cmd_slot;
7672 
7673         /*
7674          * remove the cmd.
7675          */
7676         if (cmd == slots->m_slot[slot]) {
7677                 NDBG31(("mptsas_remove_cmd: removing cmd=0x%p", (void *)cmd));
7678                 slots->m_slot[slot] = NULL;
7679                 mpt->m_ncmds--;
7680 
7681                 /*
7682                  * only decrement per target ncmds if command
7683                  * has a target associated with it.
7684                  */
7685                 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
7686                         ptgt->m_t_ncmds--;
7687                         /*
7688                          * reset throttle if we just ran an untagged command
7689                          * to a tagged target
7690                          */
7691                         if ((ptgt->m_t_ncmds == 0) &&
7692                             ((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0)) {
7693                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
7694                         }
7695                 }
7696 
7697         }
7698 
7699         /*
7700          * This is all we need to do for ioc commands.
7701          */
7702         if (cmd->cmd_flags & CFLAG_CMDIOC) {
7703                 mptsas_return_to_pool(mpt, cmd);
7704                 return;
7705         }
7706 
7707         /*
7708          * Figure out what to set tag Q timeout for...
7709          *
7710          * Optimize: If we have duplicate's of same timeout
7711          * we're using, then we'll use it again until we run
7712          * out of duplicates.  This should be the normal case
7713          * for block and raw I/O.
7714          * If no duplicates, we have to scan through tag que and
7715          * find the longest timeout value and use it.  This is
7716          * going to take a while...
7717          * Add 1 to m_n_normal to account for TM request.
7718          */
7719         if (cmd->cmd_pkt->pkt_time == ptgt->m_timebase) {
7720                 if (--(ptgt->m_dups) == 0) {
7721                         if (ptgt->m_t_ncmds) {
7722                                 mptsas_cmd_t *ssp;
7723                                 uint_t n = 0;
7724                                 ushort_t nslots = (slots->m_n_normal + 1);
7725                                 ushort_t i;
7726                                 /*
7727                                  * This crude check assumes we don't do
7728                                  * this too often which seems reasonable
7729                                  * for block and raw I/O.
7730                                  */
7731                                 for (i = 0; i < nslots; i++) {
7732                                         ssp = slots->m_slot[i];
7733                                         if (ssp && (Tgt(ssp) == t) &&
7734                                             (ssp->cmd_pkt->pkt_time > n)) {
7735                                                 n = ssp->cmd_pkt->pkt_time;
7736                                                 ptgt->m_dups = 1;
7737                                         } else if (ssp && (Tgt(ssp) == t) &&
7738                                             (ssp->cmd_pkt->pkt_time == n)) {
7739                                                 ptgt->m_dups++;
7740                                         }
7741                                 }
7742                                 ptgt->m_timebase = n;
7743                         } else {
7744                                 ptgt->m_dups = 0;
7745                                 ptgt->m_timebase = 0;
7746                         }
7747                 }
7748         }
7749         ptgt->m_timeout = ptgt->m_timebase;
7750 
7751         ASSERT(cmd != slots->m_slot[cmd->cmd_slot]);
7752 }
7753 
7754 /*
7755  * accept all cmds on the tx_waitq if any and then
7756  * start a fresh request from the top of the device queue.
7757  *
7758  * since there are always cmds queued on the tx_waitq, and rare cmds on
7759  * the instance waitq, so this function should not be invoked in the ISR,
7760  * the mptsas_restart_waitq() is invoked in the ISR instead. otherwise, the
7761  * burden belongs to the IO dispatch CPUs is moved the interrupt CPU.
7762  */
7763 static void
7764 mptsas_restart_hba(mptsas_t *mpt)
7765 {
7766         ASSERT(mutex_owned(&mpt->m_mutex));
7767 
7768         mutex_enter(&mpt->m_tx_waitq_mutex);
7769         if (mpt->m_tx_waitq) {
7770                 mptsas_accept_tx_waitq(mpt);
7771         }
7772         mutex_exit(&mpt->m_tx_waitq_mutex);
7773         mptsas_restart_waitq(mpt);
7774 }
7775 
7776 /*
7777  * start a fresh request from the top of the device queue
7778  */
7779 static void
7780 mptsas_restart_waitq(mptsas_t *mpt)
7781 {
7782         mptsas_cmd_t    *cmd, *next_cmd;
7783         mptsas_target_t *ptgt = NULL;
7784 
7785         NDBG1(("mptsas_restart_waitq: mpt=0x%p", (void *)mpt));
7786 
7787         ASSERT(mutex_owned(&mpt->m_mutex));
7788 
7789         /*
7790          * If there is a reset delay, don't start any cmds.  Otherwise, start
7791          * as many cmds as possible.
7792          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
7793          * commands is m_max_requests - 2.
7794          */
7795         cmd = mpt->m_waitq;
7796 
7797         while (cmd != NULL) {
7798                 next_cmd = cmd->cmd_linkp;
7799                 if (cmd->cmd_flags & CFLAG_PASSTHRU) {
7800                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
7801                                 /*
7802                                  * passthru command get slot need
7803                                  * set CFLAG_PREPARED.
7804                                  */
7805                                 cmd->cmd_flags |= CFLAG_PREPARED;
7806                                 mptsas_waitq_delete(mpt, cmd);
7807                                 mptsas_start_passthru(mpt, cmd);
7808                         }
7809                         cmd = next_cmd;
7810                         continue;
7811                 }
7812                 if (cmd->cmd_flags & CFLAG_CONFIG) {
7813                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
7814                                 /*
7815                                  * Send the config page request and delete it
7816                                  * from the waitq.
7817                                  */
7818                                 cmd->cmd_flags |= CFLAG_PREPARED;
7819                                 mptsas_waitq_delete(mpt, cmd);
7820                                 mptsas_start_config_page_access(mpt, cmd);
7821                         }
7822                         cmd = next_cmd;
7823                         continue;
7824                 }
7825                 if (cmd->cmd_flags & CFLAG_FW_DIAG) {
7826                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
7827                                 /*
7828                                  * Send the FW Diag request and delete if from
7829                                  * the waitq.
7830                                  */
7831                                 cmd->cmd_flags |= CFLAG_PREPARED;
7832                                 mptsas_waitq_delete(mpt, cmd);
7833                                 mptsas_start_diag(mpt, cmd);
7834                         }
7835                         cmd = next_cmd;
7836                         continue;
7837                 }
7838 
7839                 ptgt = cmd->cmd_tgt_addr;
7840                 if (ptgt && (ptgt->m_t_throttle == DRAIN_THROTTLE) &&
7841                     (ptgt->m_t_ncmds == 0)) {
7842                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
7843                 }
7844                 if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
7845                     (ptgt && (ptgt->m_reset_delay == 0)) &&
7846                     (ptgt && (ptgt->m_t_ncmds <
7847                     ptgt->m_t_throttle))) {
7848                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
7849                                 mptsas_waitq_delete(mpt, cmd);
7850                                 (void) mptsas_start_cmd(mpt, cmd);
7851                         }
7852                 }
7853                 cmd = next_cmd;
7854         }
7855 }
7856 /*
7857  * Cmds are queued if tran_start() doesn't get the m_mutexlock(no wait).
7858  * Accept all those queued cmds before new cmd is accept so that the
7859  * cmds are sent in order.
7860  */
7861 static void
7862 mptsas_accept_tx_waitq(mptsas_t *mpt)
7863 {
7864         mptsas_cmd_t *cmd;
7865 
7866         ASSERT(mutex_owned(&mpt->m_mutex));
7867         ASSERT(mutex_owned(&mpt->m_tx_waitq_mutex));
7868 
7869         /*
7870          * A Bus Reset could occur at any time and flush the tx_waitq,
7871          * so we cannot count on the tx_waitq to contain even one cmd.
7872          * And when the m_tx_waitq_mutex is released and run
7873          * mptsas_accept_pkt(), the tx_waitq may be flushed.
7874          */
7875         cmd = mpt->m_tx_waitq;
7876         for (;;) {
7877                 if ((cmd = mpt->m_tx_waitq) == NULL) {
7878                         mpt->m_tx_draining = 0;
7879                         break;
7880                 }
7881                 if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL) {
7882                         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
7883                 }
7884                 cmd->cmd_linkp = NULL;
7885                 mutex_exit(&mpt->m_tx_waitq_mutex);
7886                 if (mptsas_accept_pkt(mpt, cmd) != TRAN_ACCEPT)
7887                         cmn_err(CE_WARN, "mpt: mptsas_accept_tx_waitq: failed "
7888                             "to accept cmd on queue\n");
7889                 mutex_enter(&mpt->m_tx_waitq_mutex);
7890         }
7891 }
7892 
7893 
7894 /*
7895  * mpt tag type lookup
7896  */
7897 static char mptsas_tag_lookup[] =
7898         {0, MSG_HEAD_QTAG, MSG_ORDERED_QTAG, 0, MSG_SIMPLE_QTAG};
7899 
7900 static int
7901 mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
7902 {
7903         struct scsi_pkt         *pkt = CMD2PKT(cmd);
7904         uint32_t                control = 0;
7905         int                     n;
7906         caddr_t                 mem;
7907         pMpi2SCSIIORequest_t    io_request;
7908         ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
7909         ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
7910         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
7911         uint16_t                SMID, io_flags = 0;
7912         uint32_t                request_desc_low, request_desc_high;
7913 
7914         NDBG1(("mptsas_start_cmd: cmd=0x%p", (void *)cmd));
7915 
7916         /*
7917          * Set SMID and increment index.  Rollover to 1 instead of 0 if index
7918          * is at the max.  0 is an invalid SMID, so we call the first index 1.
7919          */
7920         SMID = cmd->cmd_slot;
7921 
7922         /*
7923          * It is possible for back to back device reset to
7924          * happen before the reset delay has expired.  That's
7925          * ok, just let the device reset go out on the bus.
7926          */
7927         if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
7928                 ASSERT(ptgt->m_reset_delay == 0);
7929         }
7930 
7931         /*
7932          * if a non-tagged cmd is submitted to an active tagged target
7933          * then drain before submitting this cmd; SCSI-2 allows RQSENSE
7934          * to be untagged
7935          */
7936         if (((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0) &&
7937             (ptgt->m_t_ncmds > 1) &&
7938             ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) &&
7939             (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE)) {
7940                 if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
7941                         NDBG23(("target=%d, untagged cmd, start draining\n",
7942                             ptgt->m_devhdl));
7943 
7944                         if (ptgt->m_reset_delay == 0) {
7945                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
7946                         }
7947 
7948                         mptsas_remove_cmd(mpt, cmd);
7949                         cmd->cmd_pkt_flags |= FLAG_HEAD;
7950                         mptsas_waitq_add(mpt, cmd);
7951                 }
7952                 return (DDI_FAILURE);
7953         }
7954 
7955         /*
7956          * Set correct tag bits.
7957          */
7958         if (cmd->cmd_pkt_flags & FLAG_TAGMASK) {
7959                 switch (mptsas_tag_lookup[((cmd->cmd_pkt_flags &
7960                     FLAG_TAGMASK) >> 12)]) {
7961                 case MSG_SIMPLE_QTAG:
7962                         control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
7963                         break;
7964                 case MSG_HEAD_QTAG:
7965                         control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
7966                         break;
7967                 case MSG_ORDERED_QTAG:
7968                         control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
7969                         break;
7970                 default:
7971                         mptsas_log(mpt, CE_WARN, "mpt: Invalid tag type\n");
7972                         break;
7973                 }
7974         } else {
7975                 if (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE) {
7976                                 ptgt->m_t_throttle = 1;
7977                 }
7978                 control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
7979         }
7980 
7981         if (cmd->cmd_pkt_flags & FLAG_TLR) {
7982                 control |= MPI2_SCSIIO_CONTROL_TLR_ON;
7983         }
7984 
7985         mem = mpt->m_req_frame + (mpt->m_req_frame_size * SMID);
7986         io_request = (pMpi2SCSIIORequest_t)mem;
7987 
7988         bzero(io_request, sizeof (Mpi2SCSIIORequest_t));
7989         ddi_put8(acc_hdl, &io_request->SGLOffset0, offsetof
7990             (MPI2_SCSI_IO_REQUEST, SGL) / 4);
7991         mptsas_init_std_hdr(acc_hdl, io_request, ptgt->m_devhdl, Lun(cmd), 0,
7992             MPI2_FUNCTION_SCSI_IO_REQUEST);
7993 
7994         (void) ddi_rep_put8(acc_hdl, (uint8_t *)pkt->pkt_cdbp,
7995             io_request->CDB.CDB32, cmd->cmd_cdblen, DDI_DEV_AUTOINCR);
7996 
7997         io_flags = cmd->cmd_cdblen;
7998         ddi_put16(acc_hdl, &io_request->IoFlags, io_flags);
7999         /*
8000          * setup the Scatter/Gather DMA list for this request
8001          */
8002         if (cmd->cmd_cookiec > 0) {
8003                 mptsas_sge_setup(mpt, cmd, &control, io_request, acc_hdl);
8004         } else {
8005                 ddi_put32(acc_hdl, &io_request->SGL.MpiSimple.FlagsLength,
8006                     ((uint32_t)MPI2_SGE_FLAGS_LAST_ELEMENT |
8007                     MPI2_SGE_FLAGS_END_OF_BUFFER |
8008                     MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
8009                     MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
8010         }
8011 
8012         /*
8013          * save ARQ information
8014          */
8015         ddi_put8(acc_hdl, &io_request->SenseBufferLength, cmd->cmd_rqslen);
8016         if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
8017             (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
8018                 ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
8019                     cmd->cmd_ext_arqcookie.dmac_address);
8020         } else {
8021                 ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
8022                     cmd->cmd_arqcookie.dmac_address);
8023         }
8024 
8025         ddi_put32(acc_hdl, &io_request->Control, control);
8026 
8027         NDBG31(("starting message=0x%p, with cmd=0x%p",
8028             (void *)(uintptr_t)mpt->m_req_frame_dma_addr, (void *)cmd));
8029 
8030         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
8031 
8032         /*
8033          * Build request descriptor and write it to the request desc post reg.
8034          */
8035         request_desc_low = (SMID << 16) + MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
8036         request_desc_high = ptgt->m_devhdl << 16;
8037         MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
8038 
8039         /*
8040          * Start timeout.
8041          */
8042 #ifdef MPTSAS_TEST
8043         /*
8044          * Temporarily set timebase = 0;  needed for
8045          * timeout torture test.
8046          */
8047         if (mptsas_test_timeouts) {
8048                 ptgt->m_timebase = 0;
8049         }
8050 #endif
8051         n = pkt->pkt_time - ptgt->m_timebase;
8052 
8053         if (n == 0) {
8054                 (ptgt->m_dups)++;
8055                 ptgt->m_timeout = ptgt->m_timebase;
8056         } else if (n > 0) {
8057                 ptgt->m_timeout =
8058                     ptgt->m_timebase = pkt->pkt_time;
8059                 ptgt->m_dups = 1;
8060         } else if (n < 0) {
8061                 ptgt->m_timeout = ptgt->m_timebase;
8062         }
8063 #ifdef MPTSAS_TEST
8064         /*
8065          * Set back to a number higher than
8066          * mptsas_scsi_watchdog_tick
8067          * so timeouts will happen in mptsas_watchsubr
8068          */
8069         if (mptsas_test_timeouts) {
8070                 ptgt->m_timebase = 60;
8071         }
8072 #endif
8073 
8074         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
8075             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
8076                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8077                 return (DDI_FAILURE);
8078         }
8079         return (DDI_SUCCESS);
8080 }
8081 
8082 /*
8083  * Select a helper thread to handle current doneq
8084  */
8085 static void
8086 mptsas_deliver_doneq_thread(mptsas_t *mpt)
8087 {
8088         uint64_t                        t, i;
8089         uint32_t                        min = 0xffffffff;
8090         mptsas_doneq_thread_list_t      *item;
8091 
8092         for (i = 0; i < mpt->m_doneq_thread_n; i++) {
8093                 item = &mpt->m_doneq_thread_id[i];
8094                 /*
8095                  * If the completed command on help thread[i] less than
8096                  * doneq_thread_threshold, then pick the thread[i]. Otherwise
8097                  * pick a thread which has least completed command.
8098                  */
8099 
8100                 mutex_enter(&item->mutex);
8101                 if (item->len < mpt->m_doneq_thread_threshold) {
8102                         t = i;
8103                         mutex_exit(&item->mutex);
8104                         break;
8105                 }
8106                 if (item->len < min) {
8107                         min = item->len;
8108                         t = i;
8109                 }
8110                 mutex_exit(&item->mutex);
8111         }
8112         mutex_enter(&mpt->m_doneq_thread_id[t].mutex);
8113         mptsas_doneq_mv(mpt, t);
8114         cv_signal(&mpt->m_doneq_thread_id[t].cv);
8115         mutex_exit(&mpt->m_doneq_thread_id[t].mutex);
8116 }
8117 
8118 /*
8119  * move the current global doneq to the doneq of thead[t]
8120  */
8121 static void
8122 mptsas_doneq_mv(mptsas_t *mpt, uint64_t t)
8123 {
8124         mptsas_cmd_t                    *cmd;
8125         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
8126 
8127         ASSERT(mutex_owned(&item->mutex));
8128         while ((cmd = mpt->m_doneq) != NULL) {
8129                 if ((mpt->m_doneq = cmd->cmd_linkp) == NULL) {
8130                         mpt->m_donetail = &mpt->m_doneq;
8131                 }
8132                 cmd->cmd_linkp = NULL;
8133                 *item->donetail = cmd;
8134                 item->donetail = &cmd->cmd_linkp;
8135                 mpt->m_doneq_len--;
8136                 item->len++;
8137         }
8138 }
8139 
8140 void
8141 mptsas_fma_check(mptsas_t *mpt, mptsas_cmd_t *cmd)
8142 {
8143         struct scsi_pkt *pkt = CMD2PKT(cmd);
8144 
8145         /* Check all acc and dma handles */
8146         if ((mptsas_check_acc_handle(mpt->m_datap) !=
8147             DDI_SUCCESS) ||
8148             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
8149             DDI_SUCCESS) ||
8150             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
8151             DDI_SUCCESS) ||
8152             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
8153             DDI_SUCCESS) ||
8154             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
8155             DDI_SUCCESS) ||
8156             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
8157             DDI_SUCCESS) ||
8158             (mptsas_check_acc_handle(mpt->m_config_handle) !=
8159             DDI_SUCCESS)) {
8160                 ddi_fm_service_impact(mpt->m_dip,
8161                     DDI_SERVICE_UNAFFECTED);
8162                 ddi_fm_acc_err_clear(mpt->m_config_handle,
8163                     DDI_FME_VER0);
8164                 pkt->pkt_reason = CMD_TRAN_ERR;
8165                 pkt->pkt_statistics = 0;
8166         }
8167         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
8168             DDI_SUCCESS) ||
8169             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
8170             DDI_SUCCESS) ||
8171             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
8172             DDI_SUCCESS) ||
8173             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
8174             DDI_SUCCESS) ||
8175             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
8176             DDI_SUCCESS)) {
8177                 ddi_fm_service_impact(mpt->m_dip,
8178                     DDI_SERVICE_UNAFFECTED);
8179                 pkt->pkt_reason = CMD_TRAN_ERR;
8180                 pkt->pkt_statistics = 0;
8181         }
8182         if (cmd->cmd_dmahandle &&
8183             (mptsas_check_dma_handle(cmd->cmd_dmahandle) != DDI_SUCCESS)) {
8184                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8185                 pkt->pkt_reason = CMD_TRAN_ERR;
8186                 pkt->pkt_statistics = 0;
8187         }
8188         if ((cmd->cmd_extra_frames &&
8189             ((mptsas_check_dma_handle(cmd->cmd_extra_frames->m_dma_hdl) !=
8190             DDI_SUCCESS) ||
8191             (mptsas_check_acc_handle(cmd->cmd_extra_frames->m_acc_hdl) !=
8192             DDI_SUCCESS)))) {
8193                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8194                 pkt->pkt_reason = CMD_TRAN_ERR;
8195                 pkt->pkt_statistics = 0;
8196         }
8197         if (cmd->cmd_arqhandle &&
8198             (mptsas_check_dma_handle(cmd->cmd_arqhandle) != DDI_SUCCESS)) {
8199                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8200                 pkt->pkt_reason = CMD_TRAN_ERR;
8201                 pkt->pkt_statistics = 0;
8202         }
8203         if (cmd->cmd_ext_arqhandle &&
8204             (mptsas_check_dma_handle(cmd->cmd_ext_arqhandle) != DDI_SUCCESS)) {
8205                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8206                 pkt->pkt_reason = CMD_TRAN_ERR;
8207                 pkt->pkt_statistics = 0;
8208         }
8209 }
8210 
8211 /*
8212  * These routines manipulate the queue of commands that
8213  * are waiting for their completion routines to be called.
8214  * The queue is usually in FIFO order but on an MP system
8215  * it's possible for the completion routines to get out
8216  * of order. If that's a problem you need to add a global
8217  * mutex around the code that calls the completion routine
8218  * in the interrupt handler.
8219  */
8220 static void
8221 mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8222 {
8223         struct scsi_pkt *pkt = CMD2PKT(cmd);
8224 
8225         NDBG31(("mptsas_doneq_add: cmd=0x%p", (void *)cmd));
8226 
8227         ASSERT((cmd->cmd_flags & CFLAG_COMPLETED) == 0);
8228         cmd->cmd_linkp = NULL;
8229         cmd->cmd_flags |= CFLAG_FINISHED;
8230         cmd->cmd_flags &= ~CFLAG_IN_TRANSPORT;
8231 
8232         mptsas_fma_check(mpt, cmd);
8233 
8234         /*
8235          * only add scsi pkts that have completion routines to
8236          * the doneq.  no intr cmds do not have callbacks.
8237          */
8238         if (pkt && (pkt->pkt_comp)) {
8239                 *mpt->m_donetail = cmd;
8240                 mpt->m_donetail = &cmd->cmd_linkp;
8241                 mpt->m_doneq_len++;
8242         }
8243 }
8244 
8245 static mptsas_cmd_t *
8246 mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t)
8247 {
8248         mptsas_cmd_t                    *cmd;
8249         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
8250 
8251         /* pop one off the done queue */
8252         if ((cmd = item->doneq) != NULL) {
8253                 /* if the queue is now empty fix the tail pointer */
8254                 NDBG31(("mptsas_doneq_thread_rm: cmd=0x%p", (void *)cmd));
8255                 if ((item->doneq = cmd->cmd_linkp) == NULL) {
8256                         item->donetail = &item->doneq;
8257                 }
8258                 cmd->cmd_linkp = NULL;
8259                 item->len--;
8260         }
8261         return (cmd);
8262 }
8263 
8264 static void
8265 mptsas_doneq_empty(mptsas_t *mpt)
8266 {
8267         if (mpt->m_doneq && !mpt->m_in_callback) {
8268                 mptsas_cmd_t    *cmd, *next;
8269                 struct scsi_pkt *pkt;
8270 
8271                 mpt->m_in_callback = 1;
8272                 cmd = mpt->m_doneq;
8273                 mpt->m_doneq = NULL;
8274                 mpt->m_donetail = &mpt->m_doneq;
8275                 mpt->m_doneq_len = 0;
8276 
8277                 mutex_exit(&mpt->m_mutex);
8278                 /*
8279                  * run the completion routines of all the
8280                  * completed commands
8281                  */
8282                 while (cmd != NULL) {
8283                         next = cmd->cmd_linkp;
8284                         cmd->cmd_linkp = NULL;
8285                         /* run this command's completion routine */
8286                         cmd->cmd_flags |= CFLAG_COMPLETED;
8287                         pkt = CMD2PKT(cmd);
8288                         mptsas_pkt_comp(pkt, cmd);
8289                         cmd = next;
8290                 }
8291                 mutex_enter(&mpt->m_mutex);
8292                 mpt->m_in_callback = 0;
8293         }
8294 }
8295 
8296 /*
8297  * These routines manipulate the target's queue of pending requests
8298  */
8299 void
8300 mptsas_waitq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8301 {
8302         NDBG7(("mptsas_waitq_add: cmd=0x%p", (void *)cmd));
8303         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8304         cmd->cmd_queued = TRUE;
8305         if (ptgt)
8306                 ptgt->m_t_nwait++;
8307         if (cmd->cmd_pkt_flags & FLAG_HEAD) {
8308                 if ((cmd->cmd_linkp = mpt->m_waitq) == NULL) {
8309                         mpt->m_waitqtail = &cmd->cmd_linkp;
8310                 }
8311                 mpt->m_waitq = cmd;
8312         } else {
8313                 cmd->cmd_linkp = NULL;
8314                 *(mpt->m_waitqtail) = cmd;
8315                 mpt->m_waitqtail = &cmd->cmd_linkp;
8316         }
8317 }
8318 
8319 static mptsas_cmd_t *
8320 mptsas_waitq_rm(mptsas_t *mpt)
8321 {
8322         mptsas_cmd_t    *cmd;
8323         mptsas_target_t *ptgt;
8324         NDBG7(("mptsas_waitq_rm"));
8325 
8326         MPTSAS_WAITQ_RM(mpt, cmd);
8327 
8328         NDBG7(("mptsas_waitq_rm: cmd=0x%p", (void *)cmd));
8329         if (cmd) {
8330                 ptgt = cmd->cmd_tgt_addr;
8331                 if (ptgt) {
8332                         ptgt->m_t_nwait--;
8333                         ASSERT(ptgt->m_t_nwait >= 0);
8334                 }
8335         }
8336         return (cmd);
8337 }
8338 
8339 /*
8340  * remove specified cmd from the middle of the wait queue.
8341  */
8342 static void
8343 mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8344 {
8345         mptsas_cmd_t    *prevp = mpt->m_waitq;
8346         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8347 
8348         NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8349             (void *)mpt, (void *)cmd));
8350         if (ptgt) {
8351                 ptgt->m_t_nwait--;
8352                 ASSERT(ptgt->m_t_nwait >= 0);
8353         }
8354 
8355         if (prevp == cmd) {
8356                 if ((mpt->m_waitq = cmd->cmd_linkp) == NULL)
8357                         mpt->m_waitqtail = &mpt->m_waitq;
8358 
8359                 cmd->cmd_linkp = NULL;
8360                 cmd->cmd_queued = FALSE;
8361                 NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8362                     (void *)mpt, (void *)cmd));
8363                 return;
8364         }
8365 
8366         while (prevp != NULL) {
8367                 if (prevp->cmd_linkp == cmd) {
8368                         if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8369                                 mpt->m_waitqtail = &prevp->cmd_linkp;
8370 
8371                         cmd->cmd_linkp = NULL;
8372                         cmd->cmd_queued = FALSE;
8373                         NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8374                             (void *)mpt, (void *)cmd));
8375                         return;
8376                 }
8377                 prevp = prevp->cmd_linkp;
8378         }
8379         cmn_err(CE_PANIC, "mpt: mptsas_waitq_delete: queue botch");
8380 }
8381 
8382 static mptsas_cmd_t *
8383 mptsas_tx_waitq_rm(mptsas_t *mpt)
8384 {
8385         mptsas_cmd_t *cmd;
8386         NDBG7(("mptsas_tx_waitq_rm"));
8387 
8388         MPTSAS_TX_WAITQ_RM(mpt, cmd);
8389 
8390         NDBG7(("mptsas_tx_waitq_rm: cmd=0x%p", (void *)cmd));
8391 
8392         return (cmd);
8393 }
8394 
8395 /*
8396  * remove specified cmd from the middle of the tx_waitq.
8397  */
8398 static void
8399 mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8400 {
8401         mptsas_cmd_t *prevp = mpt->m_tx_waitq;
8402 
8403         NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8404             (void *)mpt, (void *)cmd));
8405 
8406         if (prevp == cmd) {
8407                 if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL)
8408                         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
8409 
8410                 cmd->cmd_linkp = NULL;
8411                 cmd->cmd_queued = FALSE;
8412                 NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8413                     (void *)mpt, (void *)cmd));
8414                 return;
8415         }
8416 
8417         while (prevp != NULL) {
8418                 if (prevp->cmd_linkp == cmd) {
8419                         if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8420                                 mpt->m_tx_waitqtail = &prevp->cmd_linkp;
8421 
8422                         cmd->cmd_linkp = NULL;
8423                         cmd->cmd_queued = FALSE;
8424                         NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8425                             (void *)mpt, (void *)cmd));
8426                         return;
8427                 }
8428                 prevp = prevp->cmd_linkp;
8429         }
8430         cmn_err(CE_PANIC, "mpt: mptsas_tx_waitq_delete: queue botch");
8431 }
8432 
8433 /*
8434  * device and bus reset handling
8435  *
8436  * Notes:
8437  *      - RESET_ALL:    reset the controller
8438  *      - RESET_TARGET: reset the target specified in scsi_address
8439  */
8440 static int
8441 mptsas_scsi_reset(struct scsi_address *ap, int level)
8442 {
8443         mptsas_t                *mpt = ADDR2MPT(ap);
8444         int                     rval;
8445         mptsas_tgt_private_t    *tgt_private;
8446         mptsas_target_t         *ptgt = NULL;
8447 
8448         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->tran_tgt_private;
8449         ptgt = tgt_private->t_private;
8450         if (ptgt == NULL) {
8451                 return (FALSE);
8452         }
8453         NDBG22(("mptsas_scsi_reset: target=%d level=%d", ptgt->m_devhdl,
8454             level));
8455 
8456         mutex_enter(&mpt->m_mutex);
8457         /*
8458          * if we are not in panic set up a reset delay for this target
8459          */
8460         if (!ddi_in_panic()) {
8461                 mptsas_setup_bus_reset_delay(mpt);
8462         } else {
8463                 drv_usecwait(mpt->m_scsi_reset_delay * 1000);
8464         }
8465         rval = mptsas_do_scsi_reset(mpt, ptgt->m_devhdl);
8466         mutex_exit(&mpt->m_mutex);
8467 
8468         /*
8469          * The transport layer expect to only see TRUE and
8470          * FALSE. Therefore, we will adjust the return value
8471          * if mptsas_do_scsi_reset returns FAILED.
8472          */
8473         if (rval == FAILED)
8474                 rval = FALSE;
8475         return (rval);
8476 }
8477 
8478 static int
8479 mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl)
8480 {
8481         int             rval = FALSE;
8482         uint8_t         config, disk;
8483 
8484         ASSERT(mutex_owned(&mpt->m_mutex));
8485 
8486         if (mptsas_debug_resets) {
8487                 mptsas_log(mpt, CE_WARN, "mptsas_do_scsi_reset: target=%d",
8488                     devhdl);
8489         }
8490 
8491         /*
8492          * Issue a Target Reset message to the target specified but not to a
8493          * disk making up a raid volume.  Just look through the RAID config
8494          * Phys Disk list of DevHandles.  If the target's DevHandle is in this
8495          * list, then don't reset this target.
8496          */
8497         for (config = 0; config < mpt->m_num_raid_configs; config++) {
8498                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
8499                         if (devhdl == mpt->m_raidconfig[config].
8500                             m_physdisk_devhdl[disk]) {
8501                                 return (TRUE);
8502                         }
8503                 }
8504         }
8505 
8506         rval = mptsas_ioc_task_management(mpt,
8507             MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, devhdl, 0, NULL, 0, 0);
8508 
8509         mptsas_doneq_empty(mpt);
8510         return (rval);
8511 }
8512 
8513 static int
8514 mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
8515         void (*callback)(caddr_t), caddr_t arg)
8516 {
8517         mptsas_t        *mpt = ADDR2MPT(ap);
8518 
8519         NDBG22(("mptsas_scsi_reset_notify: tgt=%d", ap->a_target));
8520 
8521         return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
8522             &mpt->m_mutex, &mpt->m_reset_notify_listf));
8523 }
8524 
8525 static int
8526 mptsas_get_name(struct scsi_device *sd, char *name, int len)
8527 {
8528         dev_info_t      *lun_dip = NULL;
8529 
8530         ASSERT(sd != NULL);
8531         ASSERT(name != NULL);
8532         lun_dip = sd->sd_dev;
8533         ASSERT(lun_dip != NULL);
8534 
8535         if (mptsas_name_child(lun_dip, name, len) == DDI_SUCCESS) {
8536                 return (1);
8537         } else {
8538                 return (0);
8539         }
8540 }
8541 
8542 static int
8543 mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len)
8544 {
8545         return (mptsas_get_name(sd, name, len));
8546 }
8547 
8548 void
8549 mptsas_set_throttle(mptsas_t *mpt, mptsas_target_t *ptgt, int what)
8550 {
8551 
8552         NDBG25(("mptsas_set_throttle: throttle=%x", what));
8553 
8554         /*
8555          * if the bus is draining/quiesced, no changes to the throttles
8556          * are allowed. Not allowing change of throttles during draining
8557          * limits error recovery but will reduce draining time
8558          *
8559          * all throttles should have been set to HOLD_THROTTLE
8560          */
8561         if (mpt->m_softstate & (MPTSAS_SS_QUIESCED | MPTSAS_SS_DRAINING)) {
8562                 return;
8563         }
8564 
8565         if (what == HOLD_THROTTLE) {
8566                 ptgt->m_t_throttle = HOLD_THROTTLE;
8567         } else if (ptgt->m_reset_delay == 0) {
8568                 ptgt->m_t_throttle = what;
8569         }
8570 }
8571 
8572 /*
8573  * Clean up from a device reset.
8574  * For the case of target reset, this function clears the waitq of all
8575  * commands for a particular target.   For the case of abort task set, this
8576  * function clears the waitq of all commonds for a particular target/lun.
8577  */
8578 static void
8579 mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun, uint8_t tasktype)
8580 {
8581         mptsas_slots_t  *slots = mpt->m_active;
8582         mptsas_cmd_t    *cmd, *next_cmd;
8583         int             slot;
8584         uchar_t         reason;
8585         uint_t          stat;
8586 
8587         NDBG25(("mptsas_flush_target: target=%d lun=%d", target, lun));
8588 
8589         /*
8590          * Make sure the I/O Controller has flushed all cmds
8591          * that are associated with this target for a target reset
8592          * and target/lun for abort task set.
8593          * Account for TM requests, which use the last SMID.
8594          */
8595         for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
8596                 if ((cmd = slots->m_slot[slot]) == NULL)
8597                         continue;
8598                 reason = CMD_RESET;
8599                 stat = STAT_DEV_RESET;
8600                 switch (tasktype) {
8601                 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
8602                         if (Tgt(cmd) == target) {
8603                                 NDBG25(("mptsas_flush_target discovered non-"
8604                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
8605                                     tasktype));
8606                                 mptsas_dump_cmd(mpt, cmd);
8607                                 mptsas_remove_cmd(mpt, cmd);
8608                                 mptsas_set_pkt_reason(mpt, cmd, reason, stat);
8609                                 mptsas_doneq_add(mpt, cmd);
8610                         }
8611                         break;
8612                 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
8613                         reason = CMD_ABORTED;
8614                         stat = STAT_ABORTED;
8615                         /*FALLTHROUGH*/
8616                 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
8617                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
8618 
8619                                 NDBG25(("mptsas_flush_target discovered non-"
8620                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
8621                                     tasktype));
8622                                 mptsas_dump_cmd(mpt, cmd);
8623                                 mptsas_remove_cmd(mpt, cmd);
8624                                 mptsas_set_pkt_reason(mpt, cmd, reason,
8625                                     stat);
8626                                 mptsas_doneq_add(mpt, cmd);
8627                         }
8628                         break;
8629                 default:
8630                         break;
8631                 }
8632         }
8633 
8634         /*
8635          * Flush the waitq and tx_waitq of this target's cmds
8636          */
8637         cmd = mpt->m_waitq;
8638 
8639         reason = CMD_RESET;
8640         stat = STAT_DEV_RESET;
8641 
8642         switch (tasktype) {
8643         case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
8644                 while (cmd != NULL) {
8645                         next_cmd = cmd->cmd_linkp;
8646                         if (Tgt(cmd) == target) {
8647                                 mptsas_waitq_delete(mpt, cmd);
8648                                 mptsas_set_pkt_reason(mpt, cmd,
8649                                     reason, stat);
8650                                 mptsas_doneq_add(mpt, cmd);
8651                         }
8652                         cmd = next_cmd;
8653                 }
8654                 mutex_enter(&mpt->m_tx_waitq_mutex);
8655                 cmd = mpt->m_tx_waitq;
8656                 while (cmd != NULL) {
8657                         next_cmd = cmd->cmd_linkp;
8658                         if (Tgt(cmd) == target) {
8659                                 mptsas_tx_waitq_delete(mpt, cmd);
8660                                 mutex_exit(&mpt->m_tx_waitq_mutex);
8661                                 mptsas_set_pkt_reason(mpt, cmd,
8662                                     reason, stat);
8663                                 mptsas_doneq_add(mpt, cmd);
8664                                 mutex_enter(&mpt->m_tx_waitq_mutex);
8665                         }
8666                         cmd = next_cmd;
8667                 }
8668                 mutex_exit(&mpt->m_tx_waitq_mutex);
8669                 break;
8670         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
8671                 reason = CMD_ABORTED;
8672                 stat =  STAT_ABORTED;
8673                 /*FALLTHROUGH*/
8674         case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
8675                 while (cmd != NULL) {
8676                         next_cmd = cmd->cmd_linkp;
8677                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
8678                                 mptsas_waitq_delete(mpt, cmd);
8679                                 mptsas_set_pkt_reason(mpt, cmd,
8680                                     reason, stat);
8681                                 mptsas_doneq_add(mpt, cmd);
8682                         }
8683                         cmd = next_cmd;
8684                 }
8685                 mutex_enter(&mpt->m_tx_waitq_mutex);
8686                 cmd = mpt->m_tx_waitq;
8687                 while (cmd != NULL) {
8688                         next_cmd = cmd->cmd_linkp;
8689                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
8690                                 mptsas_tx_waitq_delete(mpt, cmd);
8691                                 mutex_exit(&mpt->m_tx_waitq_mutex);
8692                                 mptsas_set_pkt_reason(mpt, cmd,
8693                                     reason, stat);
8694                                 mptsas_doneq_add(mpt, cmd);
8695                                 mutex_enter(&mpt->m_tx_waitq_mutex);
8696                         }
8697                         cmd = next_cmd;
8698                 }
8699                 mutex_exit(&mpt->m_tx_waitq_mutex);
8700                 break;
8701         default:
8702                 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
8703                     tasktype);
8704                 break;
8705         }
8706 }
8707 
8708 /*
8709  * Clean up hba state, abort all outstanding command and commands in waitq
8710  * reset timeout of all targets.
8711  */
8712 static void
8713 mptsas_flush_hba(mptsas_t *mpt)
8714 {
8715         mptsas_slots_t  *slots = mpt->m_active;
8716         mptsas_cmd_t    *cmd;
8717         int             slot;
8718 
8719         NDBG25(("mptsas_flush_hba"));
8720 
8721         /*
8722          * The I/O Controller should have already sent back
8723          * all commands via the scsi I/O reply frame.  Make
8724          * sure all commands have been flushed.
8725          * Account for TM request, which use the last SMID.
8726          */
8727         for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
8728                 if ((cmd = slots->m_slot[slot]) == NULL)
8729                         continue;
8730 
8731                 if (cmd->cmd_flags & CFLAG_CMDIOC) {
8732                         /*
8733                          * Need to make sure to tell everyone that might be
8734                          * waiting on this command that it's going to fail.  If
8735                          * we get here, this command will never timeout because
8736                          * the active command table is going to be re-allocated,
8737                          * so there will be nothing to check against a time out.
8738                          * Instead, mark the command as failed due to reset.
8739                          */
8740                         mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
8741                             STAT_BUS_RESET);
8742                         if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
8743                             (cmd->cmd_flags & CFLAG_CONFIG) ||
8744                             (cmd->cmd_flags & CFLAG_FW_DIAG)) {
8745                                 cmd->cmd_flags |= CFLAG_FINISHED;
8746                                 cv_broadcast(&mpt->m_passthru_cv);
8747                                 cv_broadcast(&mpt->m_config_cv);
8748                                 cv_broadcast(&mpt->m_fw_diag_cv);
8749                         }
8750                         continue;
8751                 }
8752 
8753                 NDBG25(("mptsas_flush_hba discovered non-NULL cmd in slot %d",
8754                     slot));
8755                 mptsas_dump_cmd(mpt, cmd);
8756 
8757                 mptsas_remove_cmd(mpt, cmd);
8758                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
8759                 mptsas_doneq_add(mpt, cmd);
8760         }
8761 
8762         /*
8763          * Flush the waitq.
8764          */
8765         while ((cmd = mptsas_waitq_rm(mpt)) != NULL) {
8766                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
8767                 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
8768                     (cmd->cmd_flags & CFLAG_CONFIG) ||
8769                     (cmd->cmd_flags & CFLAG_FW_DIAG)) {
8770                         cmd->cmd_flags |= CFLAG_FINISHED;
8771                         cv_broadcast(&mpt->m_passthru_cv);
8772                         cv_broadcast(&mpt->m_config_cv);
8773                         cv_broadcast(&mpt->m_fw_diag_cv);
8774                 } else {
8775                         mptsas_doneq_add(mpt, cmd);
8776                 }
8777         }
8778 
8779         /*
8780          * Flush the tx_waitq
8781          */
8782         mutex_enter(&mpt->m_tx_waitq_mutex);
8783         while ((cmd = mptsas_tx_waitq_rm(mpt)) != NULL) {
8784                 mutex_exit(&mpt->m_tx_waitq_mutex);
8785                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
8786                 mptsas_doneq_add(mpt, cmd);
8787                 mutex_enter(&mpt->m_tx_waitq_mutex);
8788         }
8789         mutex_exit(&mpt->m_tx_waitq_mutex);
8790 
8791         /*
8792          * Drain the taskqs prior to reallocating resources.
8793          */
8794         mutex_exit(&mpt->m_mutex);
8795         ddi_taskq_wait(mpt->m_event_taskq);
8796         ddi_taskq_wait(mpt->m_dr_taskq);
8797         mutex_enter(&mpt->m_mutex);
8798 }
8799 
8800 /*
8801  * set pkt_reason and OR in pkt_statistics flag
8802  */
8803 static void
8804 mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd, uchar_t reason,
8805     uint_t stat)
8806 {
8807 #ifndef __lock_lint
8808         _NOTE(ARGUNUSED(mpt))
8809 #endif
8810 
8811         NDBG25(("mptsas_set_pkt_reason: cmd=0x%p reason=%x stat=%x",
8812             (void *)cmd, reason, stat));
8813 
8814         if (cmd) {
8815                 if (cmd->cmd_pkt->pkt_reason == CMD_CMPLT) {
8816                         cmd->cmd_pkt->pkt_reason = reason;
8817                 }
8818                 cmd->cmd_pkt->pkt_statistics |= stat;
8819         }
8820 }
8821 
8822 static void
8823 mptsas_start_watch_reset_delay()
8824 {
8825         NDBG22(("mptsas_start_watch_reset_delay"));
8826 
8827         mutex_enter(&mptsas_global_mutex);
8828         if (mptsas_reset_watch == NULL && mptsas_timeouts_enabled) {
8829                 mptsas_reset_watch = timeout(mptsas_watch_reset_delay, NULL,
8830                     drv_usectohz((clock_t)
8831                     MPTSAS_WATCH_RESET_DELAY_TICK * 1000));
8832                 ASSERT(mptsas_reset_watch != NULL);
8833         }
8834         mutex_exit(&mptsas_global_mutex);
8835 }
8836 
8837 static void
8838 mptsas_setup_bus_reset_delay(mptsas_t *mpt)
8839 {
8840         mptsas_target_t *ptgt = NULL;
8841 
8842         ASSERT(MUTEX_HELD(&mpt->m_mutex));
8843 
8844         NDBG22(("mptsas_setup_bus_reset_delay"));
8845         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
8846             ptgt = refhash_next(mpt->m_targets, ptgt)) {
8847                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
8848                 ptgt->m_reset_delay = mpt->m_scsi_reset_delay;
8849         }
8850 
8851         mptsas_start_watch_reset_delay();
8852 }
8853 
8854 /*
8855  * mptsas_watch_reset_delay(_subr) is invoked by timeout() and checks every
8856  * mpt instance for active reset delays
8857  */
8858 static void
8859 mptsas_watch_reset_delay(void *arg)
8860 {
8861 #ifndef __lock_lint
8862         _NOTE(ARGUNUSED(arg))
8863 #endif
8864 
8865         mptsas_t        *mpt;
8866         int             not_done = 0;
8867 
8868         NDBG22(("mptsas_watch_reset_delay"));
8869 
8870         mutex_enter(&mptsas_global_mutex);
8871         mptsas_reset_watch = 0;
8872         mutex_exit(&mptsas_global_mutex);
8873         rw_enter(&mptsas_global_rwlock, RW_READER);
8874         for (mpt = mptsas_head; mpt != NULL; mpt = mpt->m_next) {
8875                 if (mpt->m_tran == 0) {
8876                         continue;
8877                 }
8878                 mutex_enter(&mpt->m_mutex);
8879                 not_done += mptsas_watch_reset_delay_subr(mpt);
8880                 mutex_exit(&mpt->m_mutex);
8881         }
8882         rw_exit(&mptsas_global_rwlock);
8883 
8884         if (not_done) {
8885                 mptsas_start_watch_reset_delay();
8886         }
8887 }
8888 
8889 static int
8890 mptsas_watch_reset_delay_subr(mptsas_t *mpt)
8891 {
8892         int             done = 0;
8893         int             restart = 0;
8894         mptsas_target_t *ptgt = NULL;
8895 
8896         NDBG22(("mptsas_watch_reset_delay_subr: mpt=0x%p", (void *)mpt));
8897 
8898         ASSERT(mutex_owned(&mpt->m_mutex));
8899 
8900         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
8901             ptgt = refhash_next(mpt->m_targets, ptgt)) {
8902                 if (ptgt->m_reset_delay != 0) {
8903                         ptgt->m_reset_delay -=
8904                             MPTSAS_WATCH_RESET_DELAY_TICK;
8905                         if (ptgt->m_reset_delay <= 0) {
8906                                 ptgt->m_reset_delay = 0;
8907                                 mptsas_set_throttle(mpt, ptgt,
8908                                     MAX_THROTTLE);
8909                                 restart++;
8910                         } else {
8911                                 done = -1;
8912                         }
8913                 }
8914         }
8915 
8916         if (restart > 0) {
8917                 mptsas_restart_hba(mpt);
8918         }
8919         return (done);
8920 }
8921 
8922 #ifdef MPTSAS_TEST
8923 static void
8924 mptsas_test_reset(mptsas_t *mpt, int target)
8925 {
8926         mptsas_target_t    *ptgt = NULL;
8927 
8928         if (mptsas_rtest == target) {
8929                 if (mptsas_do_scsi_reset(mpt, target) == TRUE) {
8930                         mptsas_rtest = -1;
8931                 }
8932                 if (mptsas_rtest == -1) {
8933                         NDBG22(("mptsas_test_reset success"));
8934                 }
8935         }
8936 }
8937 #endif
8938 
8939 /*
8940  * abort handling:
8941  *
8942  * Notes:
8943  *      - if pkt is not NULL, abort just that command
8944  *      - if pkt is NULL, abort all outstanding commands for target
8945  */
8946 static int
8947 mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
8948 {
8949         mptsas_t                *mpt = ADDR2MPT(ap);
8950         int                     rval;
8951         mptsas_tgt_private_t    *tgt_private;
8952         int                     target, lun;
8953 
8954         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
8955             tran_tgt_private;
8956         ASSERT(tgt_private != NULL);
8957         target = tgt_private->t_private->m_devhdl;
8958         lun = tgt_private->t_lun;
8959 
8960         NDBG23(("mptsas_scsi_abort: target=%d.%d", target, lun));
8961 
8962         mutex_enter(&mpt->m_mutex);
8963         rval = mptsas_do_scsi_abort(mpt, target, lun, pkt);
8964         mutex_exit(&mpt->m_mutex);
8965         return (rval);
8966 }
8967 
8968 static int
8969 mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun, struct scsi_pkt *pkt)
8970 {
8971         mptsas_cmd_t    *sp = NULL;
8972         mptsas_slots_t  *slots = mpt->m_active;
8973         int             rval = FALSE;
8974 
8975         ASSERT(mutex_owned(&mpt->m_mutex));
8976 
8977         /*
8978          * Abort the command pkt on the target/lun in ap.  If pkt is
8979          * NULL, abort all outstanding commands on that target/lun.
8980          * If you can abort them, return 1, else return 0.
8981          * Each packet that's aborted should be sent back to the target
8982          * driver through the callback routine, with pkt_reason set to
8983          * CMD_ABORTED.
8984          *
8985          * abort cmd pkt on HBA hardware; clean out of outstanding
8986          * command lists, etc.
8987          */
8988         if (pkt != NULL) {
8989                 /* abort the specified packet */
8990                 sp = PKT2CMD(pkt);
8991 
8992                 if (sp->cmd_queued) {
8993                         NDBG23(("mptsas_do_scsi_abort: queued sp=0x%p aborted",
8994                             (void *)sp));
8995                         mptsas_waitq_delete(mpt, sp);
8996                         mptsas_set_pkt_reason(mpt, sp, CMD_ABORTED,
8997                             STAT_ABORTED);
8998                         mptsas_doneq_add(mpt, sp);
8999                         rval = TRUE;
9000                         goto done;
9001                 }
9002 
9003                 /*
9004                  * Have mpt firmware abort this command
9005                  */
9006 
9007                 if (slots->m_slot[sp->cmd_slot] != NULL) {
9008                         rval = mptsas_ioc_task_management(mpt,
9009                             MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, target,
9010                             lun, NULL, 0, 0);
9011 
9012                         /*
9013                          * The transport layer expects only TRUE and FALSE.
9014                          * Therefore, if mptsas_ioc_task_management returns
9015                          * FAILED we will return FALSE.
9016                          */
9017                         if (rval == FAILED)
9018                                 rval = FALSE;
9019                         goto done;
9020                 }
9021         }
9022 
9023         /*
9024          * If pkt is NULL then abort task set
9025          */
9026         rval = mptsas_ioc_task_management(mpt,
9027             MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, target, lun, NULL, 0, 0);
9028 
9029         /*
9030          * The transport layer expects only TRUE and FALSE.
9031          * Therefore, if mptsas_ioc_task_management returns
9032          * FAILED we will return FALSE.
9033          */
9034         if (rval == FAILED)
9035                 rval = FALSE;
9036 
9037 #ifdef MPTSAS_TEST
9038         if (rval && mptsas_test_stop) {
9039                 debug_enter("mptsas_do_scsi_abort");
9040         }
9041 #endif
9042 
9043 done:
9044         mptsas_doneq_empty(mpt);
9045         return (rval);
9046 }
9047 
9048 /*
9049  * capability handling:
9050  * (*tran_getcap).  Get the capability named, and return its value.
9051  */
9052 static int
9053 mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly)
9054 {
9055         mptsas_t        *mpt = ADDR2MPT(ap);
9056         int             ckey;
9057         int             rval = FALSE;
9058 
9059         NDBG24(("mptsas_scsi_getcap: target=%d, cap=%s tgtonly=%x",
9060             ap->a_target, cap, tgtonly));
9061 
9062         mutex_enter(&mpt->m_mutex);
9063 
9064         if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9065                 mutex_exit(&mpt->m_mutex);
9066                 return (UNDEFINED);
9067         }
9068 
9069         switch (ckey) {
9070         case SCSI_CAP_DMA_MAX:
9071                 rval = (int)mpt->m_msg_dma_attr.dma_attr_maxxfer;
9072                 break;
9073         case SCSI_CAP_ARQ:
9074                 rval = TRUE;
9075                 break;
9076         case SCSI_CAP_MSG_OUT:
9077         case SCSI_CAP_PARITY:
9078         case SCSI_CAP_UNTAGGED_QING:
9079                 rval = TRUE;
9080                 break;
9081         case SCSI_CAP_TAGGED_QING:
9082                 rval = TRUE;
9083                 break;
9084         case SCSI_CAP_RESET_NOTIFICATION:
9085                 rval = TRUE;
9086                 break;
9087         case SCSI_CAP_LINKED_CMDS:
9088                 rval = FALSE;
9089                 break;
9090         case SCSI_CAP_QFULL_RETRIES:
9091                 rval = ((mptsas_tgt_private_t *)(ap->a_hba_tran->
9092                     tran_tgt_private))->t_private->m_qfull_retries;
9093                 break;
9094         case SCSI_CAP_QFULL_RETRY_INTERVAL:
9095                 rval = drv_hztousec(((mptsas_tgt_private_t *)
9096                     (ap->a_hba_tran->tran_tgt_private))->
9097                     t_private->m_qfull_retry_interval) / 1000;
9098                 break;
9099         case SCSI_CAP_CDB_LEN:
9100                 rval = CDB_GROUP4;
9101                 break;
9102         case SCSI_CAP_INTERCONNECT_TYPE:
9103                 rval = INTERCONNECT_SAS;
9104                 break;
9105         case SCSI_CAP_TRAN_LAYER_RETRIES:
9106                 if (mpt->m_ioc_capabilities &
9107                     MPI2_IOCFACTS_CAPABILITY_TLR)
9108                         rval = TRUE;
9109                 else
9110                         rval = FALSE;
9111                 break;
9112         default:
9113                 rval = UNDEFINED;
9114                 break;
9115         }
9116 
9117         NDBG24(("mptsas_scsi_getcap: %s, rval=%x", cap, rval));
9118 
9119         mutex_exit(&mpt->m_mutex);
9120         return (rval);
9121 }
9122 
9123 /*
9124  * (*tran_setcap).  Set the capability named to the value given.
9125  */
9126 static int
9127 mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value, int tgtonly)
9128 {
9129         mptsas_t        *mpt = ADDR2MPT(ap);
9130         int             ckey;
9131         int             rval = FALSE;
9132 
9133         NDBG24(("mptsas_scsi_setcap: target=%d, cap=%s value=%x tgtonly=%x",
9134             ap->a_target, cap, value, tgtonly));
9135 
9136         if (!tgtonly) {
9137                 return (rval);
9138         }
9139 
9140         mutex_enter(&mpt->m_mutex);
9141 
9142         if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9143                 mutex_exit(&mpt->m_mutex);
9144                 return (UNDEFINED);
9145         }
9146 
9147         switch (ckey) {
9148         case SCSI_CAP_DMA_MAX:
9149         case SCSI_CAP_MSG_OUT:
9150         case SCSI_CAP_PARITY:
9151         case SCSI_CAP_INITIATOR_ID:
9152         case SCSI_CAP_LINKED_CMDS:
9153         case SCSI_CAP_UNTAGGED_QING:
9154         case SCSI_CAP_RESET_NOTIFICATION:
9155                 /*
9156                  * None of these are settable via
9157                  * the capability interface.
9158                  */
9159                 break;
9160         case SCSI_CAP_ARQ:
9161                 /*
9162                  * We cannot turn off arq so return false if asked to
9163                  */
9164                 if (value) {
9165                         rval = TRUE;
9166                 } else {
9167                         rval = FALSE;
9168                 }
9169                 break;
9170         case SCSI_CAP_TAGGED_QING:
9171                 mptsas_set_throttle(mpt, ((mptsas_tgt_private_t *)
9172                     (ap->a_hba_tran->tran_tgt_private))->t_private,
9173                     MAX_THROTTLE);
9174                 rval = TRUE;
9175                 break;
9176         case SCSI_CAP_QFULL_RETRIES:
9177                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9178                     t_private->m_qfull_retries = (uchar_t)value;
9179                 rval = TRUE;
9180                 break;
9181         case SCSI_CAP_QFULL_RETRY_INTERVAL:
9182                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9183                     t_private->m_qfull_retry_interval =
9184                     drv_usectohz(value * 1000);
9185                 rval = TRUE;
9186                 break;
9187         default:
9188                 rval = UNDEFINED;
9189                 break;
9190         }
9191         mutex_exit(&mpt->m_mutex);
9192         return (rval);
9193 }
9194 
9195 /*
9196  * Utility routine for mptsas_ifsetcap/ifgetcap
9197  */
9198 /*ARGSUSED*/
9199 static int
9200 mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp)
9201 {
9202         NDBG24(("mptsas_scsi_capchk: cap=%s", cap));
9203 
9204         if (!cap)
9205                 return (FALSE);
9206 
9207         *cidxp = scsi_hba_lookup_capstr(cap);
9208         return (TRUE);
9209 }
9210 
9211 static int
9212 mptsas_alloc_active_slots(mptsas_t *mpt, int flag)
9213 {
9214         mptsas_slots_t  *old_active = mpt->m_active;
9215         mptsas_slots_t  *new_active;
9216         size_t          size;
9217 
9218         /*
9219          * if there are active commands, then we cannot
9220          * change size of active slots array.
9221          */
9222         ASSERT(mpt->m_ncmds == 0);
9223 
9224         size = MPTSAS_SLOTS_SIZE(mpt);
9225         new_active = kmem_zalloc(size, flag);
9226         if (new_active == NULL) {
9227                 NDBG1(("new active alloc failed"));
9228                 return (-1);
9229         }
9230         /*
9231          * Since SMID 0 is reserved and the TM slot is reserved, the
9232          * number of slots that can be used at any one time is
9233          * m_max_requests - 2.
9234          */
9235         new_active->m_n_normal = (mpt->m_max_requests - 2);
9236         new_active->m_size = size;
9237         new_active->m_rotor = 1;
9238         if (old_active)
9239                 mptsas_free_active_slots(mpt);
9240         mpt->m_active = new_active;
9241 
9242         return (0);
9243 }
9244 
9245 static void
9246 mptsas_free_active_slots(mptsas_t *mpt)
9247 {
9248         mptsas_slots_t  *active = mpt->m_active;
9249         size_t          size;
9250 
9251         if (active == NULL)
9252                 return;
9253         size = active->m_size;
9254         kmem_free(active, size);
9255         mpt->m_active = NULL;
9256 }
9257 
9258 /*
9259  * Error logging, printing, and debug print routines.
9260  */
9261 static char *mptsas_label = "mpt_sas";
9262 
9263 /*PRINTFLIKE3*/
9264 void
9265 mptsas_log(mptsas_t *mpt, int level, char *fmt, ...)
9266 {
9267         dev_info_t      *dev;
9268         va_list         ap;
9269 
9270         if (mpt) {
9271                 dev = mpt->m_dip;
9272         } else {
9273                 dev = 0;
9274         }
9275 
9276         mutex_enter(&mptsas_log_mutex);
9277 
9278         va_start(ap, fmt);
9279         (void) vsprintf(mptsas_log_buf, fmt, ap);
9280         va_end(ap);
9281 
9282         if (level == CE_CONT) {
9283                 scsi_log(dev, mptsas_label, level, "%s\n", mptsas_log_buf);
9284         } else {
9285                 scsi_log(dev, mptsas_label, level, "%s", mptsas_log_buf);
9286         }
9287 
9288         mutex_exit(&mptsas_log_mutex);
9289 }
9290 
9291 #ifdef MPTSAS_DEBUG
9292 /*PRINTFLIKE1*/
9293 void
9294 mptsas_printf(char *fmt, ...)
9295 {
9296         dev_info_t      *dev = 0;
9297         va_list         ap;
9298 
9299         mutex_enter(&mptsas_log_mutex);
9300 
9301         va_start(ap, fmt);
9302         (void) vsprintf(mptsas_log_buf, fmt, ap);
9303         va_end(ap);
9304 
9305 #ifdef PROM_PRINTF
9306         prom_printf("%s:\t%s\n", mptsas_label, mptsas_log_buf);
9307 #else
9308         scsi_log(dev, mptsas_label, SCSI_DEBUG, "%s\n", mptsas_log_buf);
9309 #endif
9310         mutex_exit(&mptsas_log_mutex);
9311 }
9312 #endif
9313 
9314 /*
9315  * timeout handling
9316  */
9317 static void
9318 mptsas_watch(void *arg)
9319 {
9320 #ifndef __lock_lint
9321         _NOTE(ARGUNUSED(arg))
9322 #endif
9323 
9324         mptsas_t        *mpt;
9325         uint32_t        doorbell;
9326 
9327         NDBG30(("mptsas_watch"));
9328 
9329         rw_enter(&mptsas_global_rwlock, RW_READER);
9330         for (mpt = mptsas_head; mpt != (mptsas_t *)NULL; mpt = mpt->m_next) {
9331 
9332                 mutex_enter(&mpt->m_mutex);
9333 
9334                 /* Skip device if not powered on */
9335                 if (mpt->m_options & MPTSAS_OPT_PM) {
9336                         if (mpt->m_power_level == PM_LEVEL_D0) {
9337                                 (void) pm_busy_component(mpt->m_dip, 0);
9338                                 mpt->m_busy = 1;
9339                         } else {
9340                                 mutex_exit(&mpt->m_mutex);
9341                                 continue;
9342                         }
9343                 }
9344 
9345                 /*
9346                  * Check if controller is in a FAULT state. If so, reset it.
9347                  */
9348                 doorbell = ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell);
9349                 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
9350                         doorbell &= MPI2_DOORBELL_DATA_MASK;
9351                         mptsas_log(mpt, CE_WARN, "MPT Firmware Fault, "
9352                             "code: %04x", doorbell);
9353                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
9354                         if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
9355                                 mptsas_log(mpt, CE_WARN, "Reset failed"
9356                                     "after fault was detected");
9357                         }
9358                 }
9359 
9360                 /*
9361                  * For now, always call mptsas_watchsubr.
9362                  */
9363                 mptsas_watchsubr(mpt);
9364 
9365                 if (mpt->m_options & MPTSAS_OPT_PM) {
9366                         mpt->m_busy = 0;
9367                         (void) pm_idle_component(mpt->m_dip, 0);
9368                 }
9369 
9370                 mutex_exit(&mpt->m_mutex);
9371         }
9372         rw_exit(&mptsas_global_rwlock);
9373 
9374         mutex_enter(&mptsas_global_mutex);
9375         if (mptsas_timeouts_enabled)
9376                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
9377         mutex_exit(&mptsas_global_mutex);
9378 }
9379 
9380 static void
9381 mptsas_watchsubr(mptsas_t *mpt)
9382 {
9383         int             i;
9384         mptsas_cmd_t    *cmd;
9385         mptsas_target_t *ptgt = NULL;
9386 
9387         ASSERT(MUTEX_HELD(&mpt->m_mutex));
9388 
9389         NDBG30(("mptsas_watchsubr: mpt=0x%p", (void *)mpt));
9390 
9391 #ifdef MPTSAS_TEST
9392         if (mptsas_enable_untagged) {
9393                 mptsas_test_untagged++;
9394         }
9395 #endif
9396 
9397         /*
9398          * Check for commands stuck in active slot
9399          * Account for TM requests, which use the last SMID.
9400          */
9401         for (i = 0; i <= mpt->m_active->m_n_normal; i++) {
9402                 if ((cmd = mpt->m_active->m_slot[i]) != NULL) {
9403                         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
9404                                 cmd->cmd_active_timeout -=
9405                                     mptsas_scsi_watchdog_tick;
9406                                 if (cmd->cmd_active_timeout <= 0) {
9407                                         /*
9408                                          * There seems to be a command stuck
9409                                          * in the active slot.  Drain throttle.
9410                                          */
9411                                         mptsas_set_throttle(mpt,
9412                                             cmd->cmd_tgt_addr,
9413                                             DRAIN_THROTTLE);
9414                                 }
9415                         }
9416                         if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
9417                             (cmd->cmd_flags & CFLAG_CONFIG) ||
9418                             (cmd->cmd_flags & CFLAG_FW_DIAG)) {
9419                                 cmd->cmd_active_timeout -=
9420                                     mptsas_scsi_watchdog_tick;
9421                                 if (cmd->cmd_active_timeout <= 0) {
9422                                         /*
9423                                          * passthrough command timeout
9424                                          */
9425                                         cmd->cmd_flags |= (CFLAG_FINISHED |
9426                                             CFLAG_TIMEOUT);
9427                                         cv_broadcast(&mpt->m_passthru_cv);
9428                                         cv_broadcast(&mpt->m_config_cv);
9429                                         cv_broadcast(&mpt->m_fw_diag_cv);
9430                                 }
9431                         }
9432                 }
9433         }
9434 
9435         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9436             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9437                 /*
9438                  * If we were draining due to a qfull condition,
9439                  * go back to full throttle.
9440                  */
9441                 if ((ptgt->m_t_throttle < MAX_THROTTLE) &&
9442                     (ptgt->m_t_throttle > HOLD_THROTTLE) &&
9443                     (ptgt->m_t_ncmds < ptgt->m_t_throttle)) {
9444                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9445                         mptsas_restart_hba(mpt);
9446                 }
9447 
9448                 if ((ptgt->m_t_ncmds > 0) &&
9449                     (ptgt->m_timebase)) {
9450 
9451                         if (ptgt->m_timebase <=
9452                             mptsas_scsi_watchdog_tick) {
9453                                 ptgt->m_timebase +=
9454                                     mptsas_scsi_watchdog_tick;
9455                                 continue;
9456                         }
9457 
9458                         ptgt->m_timeout -= mptsas_scsi_watchdog_tick;
9459 
9460                         if (ptgt->m_timeout < 0) {
9461                                 mptsas_cmd_timeout(mpt, ptgt->m_devhdl);
9462                                 continue;
9463                         }
9464 
9465                         if ((ptgt->m_timeout) <=
9466                             mptsas_scsi_watchdog_tick) {
9467                                 NDBG23(("pending timeout"));
9468                                 mptsas_set_throttle(mpt, ptgt,
9469                                     DRAIN_THROTTLE);
9470                         }
9471                 }
9472         }
9473 }
9474 
9475 /*
9476  * timeout recovery
9477  */
9478 static void
9479 mptsas_cmd_timeout(mptsas_t *mpt, uint16_t devhdl)
9480 {
9481 
9482         NDBG29(("mptsas_cmd_timeout: target=%d", devhdl));
9483         mptsas_log(mpt, CE_WARN, "Disconnected command timeout for "
9484             "Target %d", devhdl);
9485 
9486         /*
9487          * If the current target is not the target passed in,
9488          * try to reset that target.
9489          */
9490         NDBG29(("mptsas_cmd_timeout: device reset"));
9491         if (mptsas_do_scsi_reset(mpt, devhdl) != TRUE) {
9492                 mptsas_log(mpt, CE_WARN, "Target %d reset for command timeout "
9493                     "recovery failed!", devhdl);
9494         }
9495 }
9496 
9497 /*
9498  * Device / Hotplug control
9499  */
9500 static int
9501 mptsas_scsi_quiesce(dev_info_t *dip)
9502 {
9503         mptsas_t        *mpt;
9504         scsi_hba_tran_t *tran;
9505 
9506         tran = ddi_get_driver_private(dip);
9507         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
9508                 return (-1);
9509 
9510         return (mptsas_quiesce_bus(mpt));
9511 }
9512 
9513 static int
9514 mptsas_scsi_unquiesce(dev_info_t *dip)
9515 {
9516         mptsas_t                *mpt;
9517         scsi_hba_tran_t *tran;
9518 
9519         tran = ddi_get_driver_private(dip);
9520         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
9521                 return (-1);
9522 
9523         return (mptsas_unquiesce_bus(mpt));
9524 }
9525 
9526 static int
9527 mptsas_quiesce_bus(mptsas_t *mpt)
9528 {
9529         mptsas_target_t *ptgt = NULL;
9530 
9531         NDBG28(("mptsas_quiesce_bus"));
9532         mutex_enter(&mpt->m_mutex);
9533 
9534         /* Set all the throttles to zero */
9535         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9536             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9537                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9538         }
9539 
9540         /* If there are any outstanding commands in the queue */
9541         if (mpt->m_ncmds) {
9542                 mpt->m_softstate |= MPTSAS_SS_DRAINING;
9543                 mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
9544                     mpt, (MPTSAS_QUIESCE_TIMEOUT * drv_usectohz(1000000)));
9545                 if (cv_wait_sig(&mpt->m_cv, &mpt->m_mutex) == 0) {
9546                         /*
9547                          * Quiesce has been interrupted
9548                          */
9549                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
9550                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9551                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9552                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9553                         }
9554                         mptsas_restart_hba(mpt);
9555                         if (mpt->m_quiesce_timeid != 0) {
9556                                 timeout_id_t tid = mpt->m_quiesce_timeid;
9557                                 mpt->m_quiesce_timeid = 0;
9558                                 mutex_exit(&mpt->m_mutex);
9559                                 (void) untimeout(tid);
9560                                 return (-1);
9561                         }
9562                         mutex_exit(&mpt->m_mutex);
9563                         return (-1);
9564                 } else {
9565                         /* Bus has been quiesced */
9566                         ASSERT(mpt->m_quiesce_timeid == 0);
9567                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
9568                         mpt->m_softstate |= MPTSAS_SS_QUIESCED;
9569                         mutex_exit(&mpt->m_mutex);
9570                         return (0);
9571                 }
9572         }
9573         /* Bus was not busy - QUIESCED */
9574         mutex_exit(&mpt->m_mutex);
9575 
9576         return (0);
9577 }
9578 
9579 static int
9580 mptsas_unquiesce_bus(mptsas_t *mpt)
9581 {
9582         mptsas_target_t *ptgt = NULL;
9583 
9584         NDBG28(("mptsas_unquiesce_bus"));
9585         mutex_enter(&mpt->m_mutex);
9586         mpt->m_softstate &= ~MPTSAS_SS_QUIESCED;
9587         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9588             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9589                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9590         }
9591         mptsas_restart_hba(mpt);
9592         mutex_exit(&mpt->m_mutex);
9593         return (0);
9594 }
9595 
9596 static void
9597 mptsas_ncmds_checkdrain(void *arg)
9598 {
9599         mptsas_t        *mpt = arg;
9600         mptsas_target_t *ptgt = NULL;
9601 
9602         mutex_enter(&mpt->m_mutex);
9603         if (mpt->m_softstate & MPTSAS_SS_DRAINING) {
9604                 mpt->m_quiesce_timeid = 0;
9605                 if (mpt->m_ncmds == 0) {
9606                         /* Command queue has been drained */
9607                         cv_signal(&mpt->m_cv);
9608                 } else {
9609                         /*
9610                          * The throttle may have been reset because
9611                          * of a SCSI bus reset
9612                          */
9613                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9614                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9615                                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9616                         }
9617 
9618                         mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
9619                             mpt, (MPTSAS_QUIESCE_TIMEOUT *
9620                             drv_usectohz(1000000)));
9621                 }
9622         }
9623         mutex_exit(&mpt->m_mutex);
9624 }
9625 
9626 /*ARGSUSED*/
9627 static void
9628 mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
9629 {
9630         int     i;
9631         uint8_t *cp = (uchar_t *)cmd->cmd_pkt->pkt_cdbp;
9632         char    buf[128];
9633 
9634         buf[0] = '\0';
9635         NDBG25(("?Cmd (0x%p) dump for Target %d Lun %d:\n", (void *)cmd,
9636             Tgt(cmd), Lun(cmd)));
9637         (void) sprintf(&buf[0], "\tcdb=[");
9638         for (i = 0; i < (int)cmd->cmd_cdblen; i++) {
9639                 (void) sprintf(&buf[strlen(buf)], " 0x%x", *cp++);
9640         }
9641         (void) sprintf(&buf[strlen(buf)], " ]");
9642         NDBG25(("?%s\n", buf));
9643         NDBG25(("?pkt_flags=0x%x pkt_statistics=0x%x pkt_state=0x%x\n",
9644             cmd->cmd_pkt->pkt_flags, cmd->cmd_pkt->pkt_statistics,
9645             cmd->cmd_pkt->pkt_state));
9646         NDBG25(("?pkt_scbp=0x%x cmd_flags=0x%x\n", cmd->cmd_pkt->pkt_scbp ?
9647             *(cmd->cmd_pkt->pkt_scbp) : 0, cmd->cmd_flags));
9648 }
9649 
9650 static void
9651 mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd)
9652 {
9653         caddr_t                 memp;
9654         pMPI2RequestHeader_t    request_hdrp;
9655         struct scsi_pkt         *pkt = cmd->cmd_pkt;
9656         mptsas_pt_request_t     *pt = pkt->pkt_ha_private;
9657         uint32_t                request_size, data_size, dataout_size;
9658         uint32_t                direction;
9659         ddi_dma_cookie_t        data_cookie;
9660         ddi_dma_cookie_t        dataout_cookie;
9661         uint32_t                request_desc_low, request_desc_high = 0;
9662         uint32_t                i, sense_bufp;
9663         uint8_t                 desc_type;
9664         uint8_t                 *request, function;
9665         ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
9666         ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
9667 
9668         desc_type = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
9669 
9670         request = pt->request;
9671         direction = pt->direction;
9672         request_size = pt->request_size;
9673         data_size = pt->data_size;
9674         dataout_size = pt->dataout_size;
9675         data_cookie = pt->data_cookie;
9676         dataout_cookie = pt->dataout_cookie;
9677 
9678         /*
9679          * Store the passthrough message in memory location
9680          * corresponding to our slot number
9681          */
9682         memp = mpt->m_req_frame + (mpt->m_req_frame_size * cmd->cmd_slot);
9683         request_hdrp = (pMPI2RequestHeader_t)memp;
9684         bzero(memp, mpt->m_req_frame_size);
9685 
9686         for (i = 0; i < request_size; i++) {
9687                 bcopy(request + i, memp + i, 1);
9688         }
9689 
9690         if (data_size || dataout_size) {
9691                 pMpi2SGESimple64_t      sgep;
9692                 uint32_t                sge_flags;
9693 
9694                 sgep = (pMpi2SGESimple64_t)((uint8_t *)request_hdrp +
9695                     request_size);
9696                 if (dataout_size) {
9697 
9698                         sge_flags = dataout_size |
9699                             ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
9700                             MPI2_SGE_FLAGS_END_OF_BUFFER |
9701                             MPI2_SGE_FLAGS_HOST_TO_IOC |
9702                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
9703                             MPI2_SGE_FLAGS_SHIFT);
9704                         ddi_put32(acc_hdl, &sgep->FlagsLength, sge_flags);
9705                         ddi_put32(acc_hdl, &sgep->Address.Low,
9706                             (uint32_t)(dataout_cookie.dmac_laddress &
9707                             0xffffffffull));
9708                         ddi_put32(acc_hdl, &sgep->Address.High,
9709                             (uint32_t)(dataout_cookie.dmac_laddress
9710                             >> 32));
9711                         sgep++;
9712                 }
9713                 sge_flags = data_size;
9714                 sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
9715                     MPI2_SGE_FLAGS_LAST_ELEMENT |
9716                     MPI2_SGE_FLAGS_END_OF_BUFFER |
9717                     MPI2_SGE_FLAGS_END_OF_LIST |
9718                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
9719                     MPI2_SGE_FLAGS_SHIFT);
9720                 if (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
9721                         sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_HOST_TO_IOC) <<
9722                             MPI2_SGE_FLAGS_SHIFT);
9723                 } else {
9724                         sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_IOC_TO_HOST) <<
9725                             MPI2_SGE_FLAGS_SHIFT);
9726                 }
9727                 ddi_put32(acc_hdl, &sgep->FlagsLength,
9728                     sge_flags);
9729                 ddi_put32(acc_hdl, &sgep->Address.Low,
9730                     (uint32_t)(data_cookie.dmac_laddress &
9731                     0xffffffffull));
9732                 ddi_put32(acc_hdl, &sgep->Address.High,
9733                     (uint32_t)(data_cookie.dmac_laddress >> 32));
9734         }
9735 
9736         function = request_hdrp->Function;
9737         if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
9738             (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
9739                 pMpi2SCSIIORequest_t    scsi_io_req;
9740 
9741                 scsi_io_req = (pMpi2SCSIIORequest_t)request_hdrp;
9742                 /*
9743                  * Put SGE for data and data_out buffer at the end of
9744                  * scsi_io_request message header.(64 bytes in total)
9745                  * Following above SGEs, the residual space will be
9746                  * used by sense data.
9747                  */
9748                 ddi_put8(acc_hdl,
9749                     &scsi_io_req->SenseBufferLength,
9750                     (uint8_t)(request_size - 64));
9751 
9752                 sense_bufp = mpt->m_req_frame_dma_addr +
9753                     (mpt->m_req_frame_size * cmd->cmd_slot);
9754                 sense_bufp += 64;
9755                 ddi_put32(acc_hdl,
9756                     &scsi_io_req->SenseBufferLowAddress, sense_bufp);
9757 
9758                 /*
9759                  * Set SGLOffset0 value
9760                  */
9761                 ddi_put8(acc_hdl, &scsi_io_req->SGLOffset0,
9762                     offsetof(MPI2_SCSI_IO_REQUEST, SGL) / 4);
9763 
9764                 /*
9765                  * Setup descriptor info.  RAID passthrough must use the
9766                  * default request descriptor which is already set, so if this
9767                  * is a SCSI IO request, change the descriptor to SCSI IO.
9768                  */
9769                 if (function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
9770                         desc_type = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
9771                         request_desc_high = (ddi_get16(acc_hdl,
9772                             &scsi_io_req->DevHandle) << 16);
9773                 }
9774         }
9775 
9776         /*
9777          * We must wait till the message has been completed before
9778          * beginning the next message so we wait for this one to
9779          * finish.
9780          */
9781         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
9782         request_desc_low = (cmd->cmd_slot << 16) + desc_type;
9783         cmd->cmd_rfm = NULL;
9784         MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
9785         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
9786             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
9787                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
9788         }
9789 }
9790 
9791 
9792 
9793 static int
9794 mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
9795     uint8_t *data, uint32_t request_size, uint32_t reply_size,
9796     uint32_t data_size, uint32_t direction, uint8_t *dataout,
9797     uint32_t dataout_size, short timeout, int mode)
9798 {
9799         mptsas_pt_request_t             pt;
9800         mptsas_dma_alloc_state_t        data_dma_state;
9801         mptsas_dma_alloc_state_t        dataout_dma_state;
9802         caddr_t                         memp;
9803         mptsas_cmd_t                    *cmd = NULL;
9804         struct scsi_pkt                 *pkt;
9805         uint32_t                        reply_len = 0, sense_len = 0;
9806         pMPI2RequestHeader_t            request_hdrp;
9807         pMPI2RequestHeader_t            request_msg;
9808         pMPI2DefaultReply_t             reply_msg;
9809         Mpi2SCSIIOReply_t               rep_msg;
9810         int                             i, status = 0, pt_flags = 0, rv = 0;
9811         int                             rvalue;
9812         uint8_t                         function;
9813 
9814         ASSERT(mutex_owned(&mpt->m_mutex));
9815 
9816         reply_msg = (pMPI2DefaultReply_t)(&rep_msg);
9817         bzero(reply_msg, sizeof (MPI2_DEFAULT_REPLY));
9818         request_msg = kmem_zalloc(request_size, KM_SLEEP);
9819 
9820         mutex_exit(&mpt->m_mutex);
9821         /*
9822          * copy in the request buffer since it could be used by
9823          * another thread when the pt request into waitq
9824          */
9825         if (ddi_copyin(request, request_msg, request_size, mode)) {
9826                 mutex_enter(&mpt->m_mutex);
9827                 status = EFAULT;
9828                 mptsas_log(mpt, CE_WARN, "failed to copy request data");
9829                 goto out;
9830         }
9831         mutex_enter(&mpt->m_mutex);
9832 
9833         function = request_msg->Function;
9834         if (function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
9835                 pMpi2SCSITaskManagementRequest_t        task;
9836                 task = (pMpi2SCSITaskManagementRequest_t)request_msg;
9837                 mptsas_setup_bus_reset_delay(mpt);
9838                 rv = mptsas_ioc_task_management(mpt, task->TaskType,
9839                     task->DevHandle, (int)task->LUN[1], reply, reply_size,
9840                     mode);
9841 
9842                 if (rv != TRUE) {
9843                         status = EIO;
9844                         mptsas_log(mpt, CE_WARN, "task management failed");
9845                 }
9846                 goto out;
9847         }
9848 
9849         if (data_size != 0) {
9850                 data_dma_state.size = data_size;
9851                 if (mptsas_dma_alloc(mpt, &data_dma_state) != DDI_SUCCESS) {
9852                         status = ENOMEM;
9853                         mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
9854                             "resource");
9855                         goto out;
9856                 }
9857                 pt_flags |= MPTSAS_DATA_ALLOCATED;
9858                 if (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
9859                         mutex_exit(&mpt->m_mutex);
9860                         for (i = 0; i < data_size; i++) {
9861                                 if (ddi_copyin(data + i, (uint8_t *)
9862                                     data_dma_state.memp + i, 1, mode)) {
9863                                         mutex_enter(&mpt->m_mutex);
9864                                         status = EFAULT;
9865                                         mptsas_log(mpt, CE_WARN, "failed to "
9866                                             "copy read data");
9867                                         goto out;
9868                                 }
9869                         }
9870                         mutex_enter(&mpt->m_mutex);
9871                 }
9872         }
9873 
9874         if (dataout_size != 0) {
9875                 dataout_dma_state.size = dataout_size;
9876                 if (mptsas_dma_alloc(mpt, &dataout_dma_state) != DDI_SUCCESS) {
9877                         status = ENOMEM;
9878                         mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
9879                             "resource");
9880                         goto out;
9881                 }
9882                 pt_flags |= MPTSAS_DATAOUT_ALLOCATED;
9883                 mutex_exit(&mpt->m_mutex);
9884                 for (i = 0; i < dataout_size; i++) {
9885                         if (ddi_copyin(dataout + i, (uint8_t *)
9886                             dataout_dma_state.memp + i, 1, mode)) {
9887                                 mutex_enter(&mpt->m_mutex);
9888                                 mptsas_log(mpt, CE_WARN, "failed to copy out"
9889                                     " data");
9890                                 status = EFAULT;
9891                                 goto out;
9892                         }
9893                 }
9894                 mutex_enter(&mpt->m_mutex);
9895         }
9896 
9897         if ((rvalue = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
9898                 status = EAGAIN;
9899                 mptsas_log(mpt, CE_NOTE, "event ack command pool is full");
9900                 goto out;
9901         }
9902         pt_flags |= MPTSAS_REQUEST_POOL_CMD;
9903 
9904         bzero((caddr_t)cmd, sizeof (*cmd));
9905         bzero((caddr_t)pkt, scsi_pkt_size());
9906         bzero((caddr_t)&pt, sizeof (pt));
9907 
9908         cmd->ioc_cmd_slot = (uint32_t)(rvalue);
9909 
9910         pt.request = (uint8_t *)request_msg;
9911         pt.direction = direction;
9912         pt.request_size = request_size;
9913         pt.data_size = data_size;
9914         pt.dataout_size = dataout_size;
9915         pt.data_cookie = data_dma_state.cookie;
9916         pt.dataout_cookie = dataout_dma_state.cookie;
9917 
9918         /*
9919          * Form a blank cmd/pkt to store the acknowledgement message
9920          */
9921         pkt->pkt_cdbp                = (opaque_t)&cmd->cmd_cdb[0];
9922         pkt->pkt_scbp                = (opaque_t)&cmd->cmd_scb;
9923         pkt->pkt_ha_private  = (opaque_t)&pt;
9924         pkt->pkt_flags               = FLAG_HEAD;
9925         pkt->pkt_time                = timeout;
9926         cmd->cmd_pkt         = pkt;
9927         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_PASSTHRU;
9928 
9929         /*
9930          * Save the command in a slot
9931          */
9932         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
9933                 /*
9934                  * Once passthru command get slot, set cmd_flags
9935                  * CFLAG_PREPARED.
9936                  */
9937                 cmd->cmd_flags |= CFLAG_PREPARED;
9938                 mptsas_start_passthru(mpt, cmd);
9939         } else {
9940                 mptsas_waitq_add(mpt, cmd);
9941         }
9942 
9943         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
9944                 cv_wait(&mpt->m_passthru_cv, &mpt->m_mutex);
9945         }
9946 
9947         if (cmd->cmd_flags & CFLAG_PREPARED) {
9948                 memp = mpt->m_req_frame + (mpt->m_req_frame_size *
9949                     cmd->cmd_slot);
9950                 request_hdrp = (pMPI2RequestHeader_t)memp;
9951         }
9952 
9953         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
9954                 status = ETIMEDOUT;
9955                 mptsas_log(mpt, CE_WARN, "passthrough command timeout");
9956                 pt_flags |= MPTSAS_CMD_TIMEOUT;
9957                 goto out;
9958         }
9959 
9960         if (cmd->cmd_rfm) {
9961                 /*
9962                  * cmd_rfm is zero means the command reply is a CONTEXT
9963                  * reply and no PCI Write to post the free reply SMFA
9964                  * because no reply message frame is used.
9965                  * cmd_rfm is non-zero means the reply is a ADDRESS
9966                  * reply and reply message frame is used.
9967                  */
9968                 pt_flags |= MPTSAS_ADDRESS_REPLY;
9969                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
9970                     DDI_DMA_SYNC_FORCPU);
9971                 reply_msg = (pMPI2DefaultReply_t)
9972                     (mpt->m_reply_frame + (cmd->cmd_rfm -
9973                     mpt->m_reply_frame_dma_addr));
9974         }
9975 
9976         mptsas_fma_check(mpt, cmd);
9977         if (pkt->pkt_reason == CMD_TRAN_ERR) {
9978                 status = EAGAIN;
9979                 mptsas_log(mpt, CE_WARN, "passthru fma error");
9980                 goto out;
9981         }
9982         if (pkt->pkt_reason == CMD_RESET) {
9983                 status = EAGAIN;
9984                 mptsas_log(mpt, CE_WARN, "ioc reset abort passthru");
9985                 goto out;
9986         }
9987 
9988         if (pkt->pkt_reason == CMD_INCOMPLETE) {
9989                 status = EIO;
9990                 mptsas_log(mpt, CE_WARN, "passthrough command incomplete");
9991                 goto out;
9992         }
9993 
9994         mutex_exit(&mpt->m_mutex);
9995         if (cmd->cmd_flags & CFLAG_PREPARED) {
9996                 function = request_hdrp->Function;
9997                 if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
9998                     (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
9999                         reply_len = sizeof (MPI2_SCSI_IO_REPLY);
10000                         sense_len = reply_size - reply_len;
10001                 } else {
10002                         reply_len = reply_size;
10003                         sense_len = 0;
10004                 }
10005 
10006                 for (i = 0; i < reply_len; i++) {
10007                         if (ddi_copyout((uint8_t *)reply_msg + i, reply + i, 1,
10008                             mode)) {
10009                                 mutex_enter(&mpt->m_mutex);
10010                                 status = EFAULT;
10011                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
10012                                     "reply data");
10013                                 goto out;
10014                         }
10015                 }
10016                 for (i = 0; i < sense_len; i++) {
10017                         if (ddi_copyout((uint8_t *)request_hdrp + 64 + i,
10018                             reply + reply_len + i, 1, mode)) {
10019                                 mutex_enter(&mpt->m_mutex);
10020                                 status = EFAULT;
10021                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
10022                                     "sense data");
10023                                 goto out;
10024                         }
10025                 }
10026         }
10027 
10028         if (data_size) {
10029                 if (direction != MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10030                         (void) ddi_dma_sync(data_dma_state.handle, 0, 0,
10031                             DDI_DMA_SYNC_FORCPU);
10032                         for (i = 0; i < data_size; i++) {
10033                                 if (ddi_copyout((uint8_t *)(
10034                                     data_dma_state.memp + i), data + i,  1,
10035                                     mode)) {
10036                                         mutex_enter(&mpt->m_mutex);
10037                                         status = EFAULT;
10038                                         mptsas_log(mpt, CE_WARN, "failed to "
10039                                             "copy out the reply data");
10040                                         goto out;
10041                                 }
10042                         }
10043                 }
10044         }
10045         mutex_enter(&mpt->m_mutex);
10046 out:
10047         /*
10048          * Put the reply frame back on the free queue, increment the free
10049          * index, and write the new index to the free index register.  But only
10050          * if this reply is an ADDRESS reply.
10051          */
10052         if (pt_flags & MPTSAS_ADDRESS_REPLY) {
10053                 ddi_put32(mpt->m_acc_free_queue_hdl,
10054                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
10055                     cmd->cmd_rfm);
10056                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
10057                     DDI_DMA_SYNC_FORDEV);
10058                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
10059                         mpt->m_free_index = 0;
10060                 }
10061                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
10062                     mpt->m_free_index);
10063         }
10064         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
10065                 mptsas_remove_cmd(mpt, cmd);
10066                 pt_flags &= (~MPTSAS_REQUEST_POOL_CMD);
10067         }
10068         if (pt_flags & MPTSAS_REQUEST_POOL_CMD)
10069                 mptsas_return_to_pool(mpt, cmd);
10070         if (pt_flags & MPTSAS_DATA_ALLOCATED) {
10071                 if (mptsas_check_dma_handle(data_dma_state.handle) !=
10072                     DDI_SUCCESS) {
10073                         ddi_fm_service_impact(mpt->m_dip,
10074                             DDI_SERVICE_UNAFFECTED);
10075                         status = EFAULT;
10076                 }
10077                 mptsas_dma_free(&data_dma_state);
10078         }
10079         if (pt_flags & MPTSAS_DATAOUT_ALLOCATED) {
10080                 if (mptsas_check_dma_handle(dataout_dma_state.handle) !=
10081                     DDI_SUCCESS) {
10082                         ddi_fm_service_impact(mpt->m_dip,
10083                             DDI_SERVICE_UNAFFECTED);
10084                         status = EFAULT;
10085                 }
10086                 mptsas_dma_free(&dataout_dma_state);
10087         }
10088         if (pt_flags & MPTSAS_CMD_TIMEOUT) {
10089                 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
10090                         mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
10091                 }
10092         }
10093         if (request_msg)
10094                 kmem_free(request_msg, request_size);
10095 
10096         return (status);
10097 }
10098 
10099 static int
10100 mptsas_pass_thru(mptsas_t *mpt, mptsas_pass_thru_t *data, int mode)
10101 {
10102         /*
10103          * If timeout is 0, set timeout to default of 60 seconds.
10104          */
10105         if (data->Timeout == 0) {
10106                 data->Timeout = MPTSAS_PASS_THRU_TIME_DEFAULT;
10107         }
10108 
10109         if (((data->DataSize == 0) &&
10110             (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_NONE)) ||
10111             ((data->DataSize != 0) &&
10112             ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_READ) ||
10113             (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_WRITE) ||
10114             ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) &&
10115             (data->DataOutSize != 0))))) {
10116                 if (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) {
10117                         data->DataDirection = MPTSAS_PASS_THRU_DIRECTION_READ;
10118                 } else {
10119                         data->DataOutSize = 0;
10120                 }
10121                 /*
10122                  * Send passthru request messages
10123                  */
10124                 return (mptsas_do_passthru(mpt,
10125                     (uint8_t *)((uintptr_t)data->PtrRequest),
10126                     (uint8_t *)((uintptr_t)data->PtrReply),
10127                     (uint8_t *)((uintptr_t)data->PtrData),
10128                     data->RequestSize, data->ReplySize,
10129                     data->DataSize, data->DataDirection,
10130                     (uint8_t *)((uintptr_t)data->PtrDataOut),
10131                     data->DataOutSize, data->Timeout, mode));
10132         } else {
10133                 return (EINVAL);
10134         }
10135 }
10136 
10137 static uint8_t
10138 mptsas_get_fw_diag_buffer_number(mptsas_t *mpt, uint32_t unique_id)
10139 {
10140         uint8_t index;
10141 
10142         for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
10143                 if (mpt->m_fw_diag_buffer_list[index].unique_id == unique_id) {
10144                         return (index);
10145                 }
10146         }
10147 
10148         return (MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND);
10149 }
10150 
10151 static void
10152 mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd)
10153 {
10154         pMpi2DiagBufferPostRequest_t    pDiag_post_msg;
10155         pMpi2DiagReleaseRequest_t       pDiag_release_msg;
10156         struct scsi_pkt                 *pkt = cmd->cmd_pkt;
10157         mptsas_diag_request_t           *diag = pkt->pkt_ha_private;
10158         uint32_t                        request_desc_low, i;
10159 
10160         ASSERT(mutex_owned(&mpt->m_mutex));
10161 
10162         /*
10163          * Form the diag message depending on the post or release function.
10164          */
10165         if (diag->function == MPI2_FUNCTION_DIAG_BUFFER_POST) {
10166                 pDiag_post_msg = (pMpi2DiagBufferPostRequest_t)
10167                     (mpt->m_req_frame + (mpt->m_req_frame_size *
10168                     cmd->cmd_slot));
10169                 bzero(pDiag_post_msg, mpt->m_req_frame_size);
10170                 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->Function,
10171                     diag->function);
10172                 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->BufferType,
10173                     diag->pBuffer->buffer_type);
10174                 ddi_put8(mpt->m_acc_req_frame_hdl,
10175                     &pDiag_post_msg->ExtendedType,
10176                     diag->pBuffer->extended_type);
10177                 ddi_put32(mpt->m_acc_req_frame_hdl,
10178                     &pDiag_post_msg->BufferLength,
10179                     diag->pBuffer->buffer_data.size);
10180                 for (i = 0; i < (sizeof (pDiag_post_msg->ProductSpecific) / 4);
10181                     i++) {
10182                         ddi_put32(mpt->m_acc_req_frame_hdl,
10183                             &pDiag_post_msg->ProductSpecific[i],
10184                             diag->pBuffer->product_specific[i]);
10185                 }
10186                 ddi_put32(mpt->m_acc_req_frame_hdl,
10187                     &pDiag_post_msg->BufferAddress.Low,
10188                     (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
10189                     & 0xffffffffull));
10190                 ddi_put32(mpt->m_acc_req_frame_hdl,
10191                     &pDiag_post_msg->BufferAddress.High,
10192                     (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
10193                     >> 32));
10194         } else {
10195                 pDiag_release_msg = (pMpi2DiagReleaseRequest_t)
10196                     (mpt->m_req_frame + (mpt->m_req_frame_size *
10197                     cmd->cmd_slot));
10198                 bzero(pDiag_release_msg, mpt->m_req_frame_size);
10199                 ddi_put8(mpt->m_acc_req_frame_hdl,
10200                     &pDiag_release_msg->Function, diag->function);
10201                 ddi_put8(mpt->m_acc_req_frame_hdl,
10202                     &pDiag_release_msg->BufferType,
10203                     diag->pBuffer->buffer_type);
10204         }
10205 
10206         /*
10207          * Send the message
10208          */
10209         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
10210             DDI_DMA_SYNC_FORDEV);
10211         request_desc_low = (cmd->cmd_slot << 16) +
10212             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
10213         cmd->cmd_rfm = NULL;
10214         MPTSAS_START_CMD(mpt, request_desc_low, 0);
10215         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
10216             DDI_SUCCESS) ||
10217             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
10218             DDI_SUCCESS)) {
10219                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
10220         }
10221 }
10222 
10223 static int
10224 mptsas_post_fw_diag_buffer(mptsas_t *mpt,
10225     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
10226 {
10227         mptsas_diag_request_t           diag;
10228         int                             status, slot_num, post_flags = 0;
10229         mptsas_cmd_t                    *cmd = NULL;
10230         struct scsi_pkt                 *pkt;
10231         pMpi2DiagBufferPostReply_t      reply;
10232         uint16_t                        iocstatus;
10233         uint32_t                        iocloginfo, transfer_length;
10234 
10235         /*
10236          * If buffer is not enabled, just leave.
10237          */
10238         *return_code = MPTSAS_FW_DIAG_ERROR_POST_FAILED;
10239         if (!pBuffer->enabled) {
10240                 status = DDI_FAILURE;
10241                 goto out;
10242         }
10243 
10244         /*
10245          * Clear some flags initially.
10246          */
10247         pBuffer->force_release = FALSE;
10248         pBuffer->valid_data = FALSE;
10249         pBuffer->owned_by_firmware = FALSE;
10250 
10251         /*
10252          * Get a cmd buffer from the cmd buffer pool
10253          */
10254         if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
10255                 status = DDI_FAILURE;
10256                 mptsas_log(mpt, CE_NOTE, "command pool is full: Post FW Diag");
10257                 goto out;
10258         }
10259         post_flags |= MPTSAS_REQUEST_POOL_CMD;
10260 
10261         bzero((caddr_t)cmd, sizeof (*cmd));
10262         bzero((caddr_t)pkt, scsi_pkt_size());
10263 
10264         cmd->ioc_cmd_slot = (uint32_t)(slot_num);
10265 
10266         diag.pBuffer = pBuffer;
10267         diag.function = MPI2_FUNCTION_DIAG_BUFFER_POST;
10268 
10269         /*
10270          * Form a blank cmd/pkt to store the acknowledgement message
10271          */
10272         pkt->pkt_ha_private  = (opaque_t)&diag;
10273         pkt->pkt_flags               = FLAG_HEAD;
10274         pkt->pkt_time                = 60;
10275         cmd->cmd_pkt         = pkt;
10276         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_DIAG;
10277 
10278         /*
10279          * Save the command in a slot
10280          */
10281         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
10282                 /*
10283                  * Once passthru command get slot, set cmd_flags
10284                  * CFLAG_PREPARED.
10285                  */
10286                 cmd->cmd_flags |= CFLAG_PREPARED;
10287                 mptsas_start_diag(mpt, cmd);
10288         } else {
10289                 mptsas_waitq_add(mpt, cmd);
10290         }
10291 
10292         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
10293                 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
10294         }
10295 
10296         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
10297                 status = DDI_FAILURE;
10298                 mptsas_log(mpt, CE_WARN, "Post FW Diag command timeout");
10299                 goto out;
10300         }
10301 
10302         /*
10303          * cmd_rfm points to the reply message if a reply was given.  Check the
10304          * IOCStatus to make sure everything went OK with the FW diag request
10305          * and set buffer flags.
10306          */
10307         if (cmd->cmd_rfm) {
10308                 post_flags |= MPTSAS_ADDRESS_REPLY;
10309                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
10310                     DDI_DMA_SYNC_FORCPU);
10311                 reply = (pMpi2DiagBufferPostReply_t)(mpt->m_reply_frame +
10312                     (cmd->cmd_rfm - mpt->m_reply_frame_dma_addr));
10313 
10314                 /*
10315                  * Get the reply message data
10316                  */
10317                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
10318                     &reply->IOCStatus);
10319                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
10320                     &reply->IOCLogInfo);
10321                 transfer_length = ddi_get32(mpt->m_acc_reply_frame_hdl,
10322                     &reply->TransferLength);
10323 
10324                 /*
10325                  * If post failed quit.
10326                  */
10327                 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
10328                         status = DDI_FAILURE;
10329                         NDBG13(("post FW Diag Buffer failed: IOCStatus=0x%x, "
10330                             "IOCLogInfo=0x%x, TransferLength=0x%x", iocstatus,
10331                             iocloginfo, transfer_length));
10332                         goto out;
10333                 }
10334 
10335                 /*
10336                  * Post was successful.
10337                  */
10338                 pBuffer->valid_data = TRUE;
10339                 pBuffer->owned_by_firmware = TRUE;
10340                 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
10341                 status = DDI_SUCCESS;
10342         }
10343 
10344 out:
10345         /*
10346          * Put the reply frame back on the free queue, increment the free
10347          * index, and write the new index to the free index register.  But only
10348          * if this reply is an ADDRESS reply.
10349          */
10350         if (post_flags & MPTSAS_ADDRESS_REPLY) {
10351                 ddi_put32(mpt->m_acc_free_queue_hdl,
10352                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
10353                     cmd->cmd_rfm);
10354                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
10355                     DDI_DMA_SYNC_FORDEV);
10356                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
10357                         mpt->m_free_index = 0;
10358                 }
10359                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
10360                     mpt->m_free_index);
10361         }
10362         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
10363                 mptsas_remove_cmd(mpt, cmd);
10364                 post_flags &= (~MPTSAS_REQUEST_POOL_CMD);
10365         }
10366         if (post_flags & MPTSAS_REQUEST_POOL_CMD) {
10367                 mptsas_return_to_pool(mpt, cmd);
10368         }
10369 
10370         return (status);
10371 }
10372 
10373 static int
10374 mptsas_release_fw_diag_buffer(mptsas_t *mpt,
10375     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
10376     uint32_t diag_type)
10377 {
10378         mptsas_diag_request_t   diag;
10379         int                     status, slot_num, rel_flags = 0;
10380         mptsas_cmd_t            *cmd = NULL;
10381         struct scsi_pkt         *pkt;
10382         pMpi2DiagReleaseReply_t reply;
10383         uint16_t                iocstatus;
10384         uint32_t                iocloginfo;
10385 
10386         /*
10387          * If buffer is not enabled, just leave.
10388          */
10389         *return_code = MPTSAS_FW_DIAG_ERROR_RELEASE_FAILED;
10390         if (!pBuffer->enabled) {
10391                 mptsas_log(mpt, CE_NOTE, "This buffer type is not supported "
10392                     "by the IOC");
10393                 status = DDI_FAILURE;
10394                 goto out;
10395         }
10396 
10397         /*
10398          * Clear some flags initially.
10399          */
10400         pBuffer->force_release = FALSE;
10401         pBuffer->valid_data = FALSE;
10402         pBuffer->owned_by_firmware = FALSE;
10403 
10404         /*
10405          * Get a cmd buffer from the cmd buffer pool
10406          */
10407         if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
10408                 status = DDI_FAILURE;
10409                 mptsas_log(mpt, CE_NOTE, "command pool is full: Release FW "
10410                     "Diag");
10411                 goto out;
10412         }
10413         rel_flags |= MPTSAS_REQUEST_POOL_CMD;
10414 
10415         bzero((caddr_t)cmd, sizeof (*cmd));
10416         bzero((caddr_t)pkt, scsi_pkt_size());
10417 
10418         cmd->ioc_cmd_slot = (uint32_t)(slot_num);
10419 
10420         diag.pBuffer = pBuffer;
10421         diag.function = MPI2_FUNCTION_DIAG_RELEASE;
10422 
10423         /*
10424          * Form a blank cmd/pkt to store the acknowledgement message
10425          */
10426         pkt->pkt_ha_private  = (opaque_t)&diag;
10427         pkt->pkt_flags               = FLAG_HEAD;
10428         pkt->pkt_time                = 60;
10429         cmd->cmd_pkt         = pkt;
10430         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_DIAG;
10431 
10432         /*
10433          * Save the command in a slot
10434          */
10435         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
10436                 /*
10437                  * Once passthru command get slot, set cmd_flags
10438                  * CFLAG_PREPARED.
10439                  */
10440                 cmd->cmd_flags |= CFLAG_PREPARED;
10441                 mptsas_start_diag(mpt, cmd);
10442         } else {
10443                 mptsas_waitq_add(mpt, cmd);
10444         }
10445 
10446         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
10447                 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
10448         }
10449 
10450         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
10451                 status = DDI_FAILURE;
10452                 mptsas_log(mpt, CE_WARN, "Release FW Diag command timeout");
10453                 goto out;
10454         }
10455 
10456         /*
10457          * cmd_rfm points to the reply message if a reply was given.  Check the
10458          * IOCStatus to make sure everything went OK with the FW diag request
10459          * and set buffer flags.
10460          */
10461         if (cmd->cmd_rfm) {
10462                 rel_flags |= MPTSAS_ADDRESS_REPLY;
10463                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
10464                     DDI_DMA_SYNC_FORCPU);
10465                 reply = (pMpi2DiagReleaseReply_t)(mpt->m_reply_frame +
10466                     (cmd->cmd_rfm - mpt->m_reply_frame_dma_addr));
10467 
10468                 /*
10469                  * Get the reply message data
10470                  */
10471                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
10472                     &reply->IOCStatus);
10473                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
10474                     &reply->IOCLogInfo);
10475 
10476                 /*
10477                  * If release failed quit.
10478                  */
10479                 if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) ||
10480                     pBuffer->owned_by_firmware) {
10481                         status = DDI_FAILURE;
10482                         NDBG13(("release FW Diag Buffer failed: "
10483                             "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
10484                             iocloginfo));
10485                         goto out;
10486                 }
10487 
10488                 /*
10489                  * Release was successful.
10490                  */
10491                 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
10492                 status = DDI_SUCCESS;
10493 
10494                 /*
10495                  * If this was for an UNREGISTER diag type command, clear the
10496                  * unique ID.
10497                  */
10498                 if (diag_type == MPTSAS_FW_DIAG_TYPE_UNREGISTER) {
10499                         pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
10500                 }
10501         }
10502 
10503 out:
10504         /*
10505          * Put the reply frame back on the free queue, increment the free
10506          * index, and write the new index to the free index register.  But only
10507          * if this reply is an ADDRESS reply.
10508          */
10509         if (rel_flags & MPTSAS_ADDRESS_REPLY) {
10510                 ddi_put32(mpt->m_acc_free_queue_hdl,
10511                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
10512                     cmd->cmd_rfm);
10513                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
10514                     DDI_DMA_SYNC_FORDEV);
10515                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
10516                         mpt->m_free_index = 0;
10517                 }
10518                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
10519                     mpt->m_free_index);
10520         }
10521         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
10522                 mptsas_remove_cmd(mpt, cmd);
10523                 rel_flags &= (~MPTSAS_REQUEST_POOL_CMD);
10524         }
10525         if (rel_flags & MPTSAS_REQUEST_POOL_CMD) {
10526                 mptsas_return_to_pool(mpt, cmd);
10527         }
10528 
10529         return (status);
10530 }
10531 
10532 static int
10533 mptsas_diag_register(mptsas_t *mpt, mptsas_fw_diag_register_t *diag_register,
10534     uint32_t *return_code)
10535 {
10536         mptsas_fw_diagnostic_buffer_t   *pBuffer;
10537         uint8_t                         extended_type, buffer_type, i;
10538         uint32_t                        buffer_size;
10539         uint32_t                        unique_id;
10540         int                             status;
10541 
10542         ASSERT(mutex_owned(&mpt->m_mutex));
10543 
10544         extended_type = diag_register->ExtendedType;
10545         buffer_type = diag_register->BufferType;
10546         buffer_size = diag_register->RequestedBufferSize;
10547         unique_id = diag_register->UniqueId;
10548 
10549         /*
10550          * Check for valid buffer type
10551          */
10552         if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) {
10553                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10554                 return (DDI_FAILURE);
10555         }
10556 
10557         /*
10558          * Get the current buffer and look up the unique ID.  The unique ID
10559          * should not be found.  If it is, the ID is already in use.
10560          */
10561         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10562         pBuffer = &mpt->m_fw_diag_buffer_list[buffer_type];
10563         if (i != MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10564                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10565                 return (DDI_FAILURE);
10566         }
10567 
10568         /*
10569          * The buffer's unique ID should not be registered yet, and the given
10570          * unique ID cannot be 0.
10571          */
10572         if ((pBuffer->unique_id != MPTSAS_FW_DIAG_INVALID_UID) ||
10573             (unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
10574                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10575                 return (DDI_FAILURE);
10576         }
10577 
10578         /*
10579          * If this buffer is already posted as immediate, just change owner.
10580          */
10581         if (pBuffer->immediate && pBuffer->owned_by_firmware &&
10582             (pBuffer->unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
10583                 pBuffer->immediate = FALSE;
10584                 pBuffer->unique_id = unique_id;
10585                 return (DDI_SUCCESS);
10586         }
10587 
10588         /*
10589          * Post a new buffer after checking if it's enabled.  The DMA buffer
10590          * that is allocated will be contiguous (sgl_len = 1).
10591          */
10592         if (!pBuffer->enabled) {
10593                 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
10594                 return (DDI_FAILURE);
10595         }
10596         bzero(&pBuffer->buffer_data, sizeof (mptsas_dma_alloc_state_t));
10597         pBuffer->buffer_data.size = buffer_size;
10598         if (mptsas_dma_alloc(mpt, &pBuffer->buffer_data) != DDI_SUCCESS) {
10599                 mptsas_log(mpt, CE_WARN, "failed to alloc DMA resource for "
10600                     "diag buffer: size = %d bytes", buffer_size);
10601                 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
10602                 return (DDI_FAILURE);
10603         }
10604 
10605         /*
10606          * Copy the given info to the diag buffer and post the buffer.
10607          */
10608         pBuffer->buffer_type = buffer_type;
10609         pBuffer->immediate = FALSE;
10610         if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) {
10611                 for (i = 0; i < (sizeof (pBuffer->product_specific) / 4);
10612                     i++) {
10613                         pBuffer->product_specific[i] =
10614                             diag_register->ProductSpecific[i];
10615                 }
10616         }
10617         pBuffer->extended_type = extended_type;
10618         pBuffer->unique_id = unique_id;
10619         status = mptsas_post_fw_diag_buffer(mpt, pBuffer, return_code);
10620 
10621         if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
10622             DDI_SUCCESS) {
10623                 mptsas_log(mpt, CE_WARN, "Check of DMA handle failed in "
10624                     "mptsas_diag_register.");
10625                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
10626                         status = DDI_FAILURE;
10627         }
10628 
10629         /*
10630          * In case there was a failure, free the DMA buffer.
10631          */
10632         if (status == DDI_FAILURE) {
10633                 mptsas_dma_free(&pBuffer->buffer_data);
10634         }
10635 
10636         return (status);
10637 }
10638 
10639 static int
10640 mptsas_diag_unregister(mptsas_t *mpt,
10641     mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
10642 {
10643         mptsas_fw_diagnostic_buffer_t   *pBuffer;
10644         uint8_t                         i;
10645         uint32_t                        unique_id;
10646         int                             status;
10647 
10648         ASSERT(mutex_owned(&mpt->m_mutex));
10649 
10650         unique_id = diag_unregister->UniqueId;
10651 
10652         /*
10653          * Get the current buffer and look up the unique ID.  The unique ID
10654          * should be there.
10655          */
10656         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10657         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10658                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10659                 return (DDI_FAILURE);
10660         }
10661 
10662         pBuffer = &mpt->m_fw_diag_buffer_list[i];
10663 
10664         /*
10665          * Try to release the buffer from FW before freeing it.  If release
10666          * fails, don't free the DMA buffer in case FW tries to access it
10667          * later.  If buffer is not owned by firmware, can't release it.
10668          */
10669         if (!pBuffer->owned_by_firmware) {
10670                 status = DDI_SUCCESS;
10671         } else {
10672                 status = mptsas_release_fw_diag_buffer(mpt, pBuffer,
10673                     return_code, MPTSAS_FW_DIAG_TYPE_UNREGISTER);
10674         }
10675 
10676         /*
10677          * At this point, return the current status no matter what happens with
10678          * the DMA buffer.
10679          */
10680         pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
10681         if (status == DDI_SUCCESS) {
10682                 if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
10683                     DDI_SUCCESS) {
10684                         mptsas_log(mpt, CE_WARN, "Check of DMA handle failed "
10685                             "in mptsas_diag_unregister.");
10686                         ddi_fm_service_impact(mpt->m_dip,
10687                             DDI_SERVICE_UNAFFECTED);
10688                 }
10689                 mptsas_dma_free(&pBuffer->buffer_data);
10690         }
10691 
10692         return (status);
10693 }
10694 
10695 static int
10696 mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
10697     uint32_t *return_code)
10698 {
10699         mptsas_fw_diagnostic_buffer_t   *pBuffer;
10700         uint8_t                         i;
10701         uint32_t                        unique_id;
10702 
10703         ASSERT(mutex_owned(&mpt->m_mutex));
10704 
10705         unique_id = diag_query->UniqueId;
10706 
10707         /*
10708          * If ID is valid, query on ID.
10709          * If ID is invalid, query on buffer type.
10710          */
10711         if (unique_id == MPTSAS_FW_DIAG_INVALID_UID) {
10712                 i = diag_query->BufferType;
10713                 if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
10714                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10715                         return (DDI_FAILURE);
10716                 }
10717         } else {
10718                 i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10719                 if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10720                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10721                         return (DDI_FAILURE);
10722                 }
10723         }
10724 
10725         /*
10726          * Fill query structure with the diag buffer info.
10727          */
10728         pBuffer = &mpt->m_fw_diag_buffer_list[i];
10729         diag_query->BufferType = pBuffer->buffer_type;
10730         diag_query->ExtendedType = pBuffer->extended_type;
10731         if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) {
10732                 for (i = 0; i < (sizeof (diag_query->ProductSpecific) / 4);
10733                     i++) {
10734                         diag_query->ProductSpecific[i] =
10735                             pBuffer->product_specific[i];
10736                 }
10737         }
10738         diag_query->TotalBufferSize = pBuffer->buffer_data.size;
10739         diag_query->DriverAddedBufferSize = 0;
10740         diag_query->UniqueId = pBuffer->unique_id;
10741         diag_query->ApplicationFlags = 0;
10742         diag_query->DiagnosticFlags = 0;
10743 
10744         /*
10745          * Set/Clear application flags
10746          */
10747         if (pBuffer->immediate) {
10748                 diag_query->ApplicationFlags &= ~MPTSAS_FW_DIAG_FLAG_APP_OWNED;
10749         } else {
10750                 diag_query->ApplicationFlags |= MPTSAS_FW_DIAG_FLAG_APP_OWNED;
10751         }
10752         if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
10753                 diag_query->ApplicationFlags |=
10754                     MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
10755         } else {
10756                 diag_query->ApplicationFlags &=
10757                     ~MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
10758         }
10759         if (pBuffer->owned_by_firmware) {
10760                 diag_query->ApplicationFlags |=
10761                     MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
10762         } else {
10763                 diag_query->ApplicationFlags &=
10764                     ~MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
10765         }
10766 
10767         return (DDI_SUCCESS);
10768 }
10769 
10770 static int
10771 mptsas_diag_read_buffer(mptsas_t *mpt,
10772     mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
10773     uint32_t *return_code, int ioctl_mode)
10774 {
10775         mptsas_fw_diagnostic_buffer_t   *pBuffer;
10776         uint8_t                         i, *pData;
10777         uint32_t                        unique_id, byte;
10778         int                             status;
10779 
10780         ASSERT(mutex_owned(&mpt->m_mutex));
10781 
10782         unique_id = diag_read_buffer->UniqueId;
10783 
10784         /*
10785          * Get the current buffer and look up the unique ID.  The unique ID
10786          * should be there.
10787          */
10788         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10789         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10790                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10791                 return (DDI_FAILURE);
10792         }
10793 
10794         pBuffer = &mpt->m_fw_diag_buffer_list[i];
10795 
10796         /*
10797          * Make sure requested read is within limits
10798          */
10799         if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
10800             pBuffer->buffer_data.size) {
10801                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10802                 return (DDI_FAILURE);
10803         }
10804 
10805         /*
10806          * Copy the requested data from DMA to the diag_read_buffer.  The DMA
10807          * buffer that was allocated is one contiguous buffer.
10808          */
10809         pData = (uint8_t *)(pBuffer->buffer_data.memp +
10810             diag_read_buffer->StartingOffset);
10811         (void) ddi_dma_sync(pBuffer->buffer_data.handle, 0, 0,
10812             DDI_DMA_SYNC_FORCPU);
10813         for (byte = 0; byte < diag_read_buffer->BytesToRead; byte++) {
10814                 if (ddi_copyout(pData + byte, ioctl_buf + byte, 1, ioctl_mode)
10815                     != 0) {
10816                         return (DDI_FAILURE);
10817                 }
10818         }
10819         diag_read_buffer->Status = 0;
10820 
10821         /*
10822          * Set or clear the Force Release flag.
10823          */
10824         if (pBuffer->force_release) {
10825                 diag_read_buffer->Flags |= MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
10826         } else {
10827                 diag_read_buffer->Flags &= ~MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
10828         }
10829 
10830         /*
10831          * If buffer is to be reregistered, make sure it's not already owned by
10832          * firmware first.
10833          */
10834         status = DDI_SUCCESS;
10835         if (!pBuffer->owned_by_firmware) {
10836                 if (diag_read_buffer->Flags & MPTSAS_FW_DIAG_FLAG_REREGISTER) {
10837                         status = mptsas_post_fw_diag_buffer(mpt, pBuffer,
10838                             return_code);
10839                 }
10840         }
10841 
10842         return (status);
10843 }
10844 
10845 static int
10846 mptsas_diag_release(mptsas_t *mpt, mptsas_fw_diag_release_t *diag_release,
10847     uint32_t *return_code)
10848 {
10849         mptsas_fw_diagnostic_buffer_t   *pBuffer;
10850         uint8_t                         i;
10851         uint32_t                        unique_id;
10852         int                             status;
10853 
10854         ASSERT(mutex_owned(&mpt->m_mutex));
10855 
10856         unique_id = diag_release->UniqueId;
10857 
10858         /*
10859          * Get the current buffer and look up the unique ID.  The unique ID
10860          * should be there.
10861          */
10862         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
10863         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
10864                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
10865                 return (DDI_FAILURE);
10866         }
10867 
10868         pBuffer = &mpt->m_fw_diag_buffer_list[i];
10869 
10870         /*
10871          * If buffer is not owned by firmware, it's already been released.
10872          */
10873         if (!pBuffer->owned_by_firmware) {
10874                 *return_code = MPTSAS_FW_DIAG_ERROR_ALREADY_RELEASED;
10875                 return (DDI_FAILURE);
10876         }
10877 
10878         /*
10879          * Release the buffer.
10880          */
10881         status = mptsas_release_fw_diag_buffer(mpt, pBuffer, return_code,
10882             MPTSAS_FW_DIAG_TYPE_RELEASE);
10883         return (status);
10884 }
10885 
10886 static int
10887 mptsas_do_diag_action(mptsas_t *mpt, uint32_t action, uint8_t *diag_action,
10888     uint32_t length, uint32_t *return_code, int ioctl_mode)
10889 {
10890         mptsas_fw_diag_register_t       diag_register;
10891         mptsas_fw_diag_unregister_t     diag_unregister;
10892         mptsas_fw_diag_query_t          diag_query;
10893         mptsas_diag_read_buffer_t       diag_read_buffer;
10894         mptsas_fw_diag_release_t        diag_release;
10895         int                             status = DDI_SUCCESS;
10896         uint32_t                        original_return_code, read_buf_len;
10897 
10898         ASSERT(mutex_owned(&mpt->m_mutex));
10899 
10900         original_return_code = *return_code;
10901         *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
10902 
10903         switch (action) {
10904                 case MPTSAS_FW_DIAG_TYPE_REGISTER:
10905                         if (!length) {
10906                                 *return_code =
10907                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10908                                 status = DDI_FAILURE;
10909                                 break;
10910                         }
10911                         if (ddi_copyin(diag_action, &diag_register,
10912                             sizeof (diag_register), ioctl_mode) != 0) {
10913                                 return (DDI_FAILURE);
10914                         }
10915                         status = mptsas_diag_register(mpt, &diag_register,
10916                             return_code);
10917                         break;
10918 
10919                 case MPTSAS_FW_DIAG_TYPE_UNREGISTER:
10920                         if (length < sizeof (diag_unregister)) {
10921                                 *return_code =
10922                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10923                                 status = DDI_FAILURE;
10924                                 break;
10925                         }
10926                         if (ddi_copyin(diag_action, &diag_unregister,
10927                             sizeof (diag_unregister), ioctl_mode) != 0) {
10928                                 return (DDI_FAILURE);
10929                         }
10930                         status = mptsas_diag_unregister(mpt, &diag_unregister,
10931                             return_code);
10932                         break;
10933 
10934                 case MPTSAS_FW_DIAG_TYPE_QUERY:
10935                         if (length < sizeof (diag_query)) {
10936                                 *return_code =
10937                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10938                                 status = DDI_FAILURE;
10939                                 break;
10940                         }
10941                         if (ddi_copyin(diag_action, &diag_query,
10942                             sizeof (diag_query), ioctl_mode) != 0) {
10943                                 return (DDI_FAILURE);
10944                         }
10945                         status = mptsas_diag_query(mpt, &diag_query,
10946                             return_code);
10947                         if (status == DDI_SUCCESS) {
10948                                 if (ddi_copyout(&diag_query, diag_action,
10949                                     sizeof (diag_query), ioctl_mode) != 0) {
10950                                         return (DDI_FAILURE);
10951                                 }
10952                         }
10953                         break;
10954 
10955                 case MPTSAS_FW_DIAG_TYPE_READ_BUFFER:
10956                         if (ddi_copyin(diag_action, &diag_read_buffer,
10957                             sizeof (diag_read_buffer) - 4, ioctl_mode) != 0) {
10958                                 return (DDI_FAILURE);
10959                         }
10960                         read_buf_len = sizeof (diag_read_buffer) -
10961                             sizeof (diag_read_buffer.DataBuffer) +
10962                             diag_read_buffer.BytesToRead;
10963                         if (length < read_buf_len) {
10964                                 *return_code =
10965                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10966                                 status = DDI_FAILURE;
10967                                 break;
10968                         }
10969                         status = mptsas_diag_read_buffer(mpt,
10970                             &diag_read_buffer, diag_action +
10971                             sizeof (diag_read_buffer) - 4, return_code,
10972                             ioctl_mode);
10973                         if (status == DDI_SUCCESS) {
10974                                 if (ddi_copyout(&diag_read_buffer, diag_action,
10975                                     sizeof (diag_read_buffer) - 4, ioctl_mode)
10976                                     != 0) {
10977                                         return (DDI_FAILURE);
10978                                 }
10979                         }
10980                         break;
10981 
10982                 case MPTSAS_FW_DIAG_TYPE_RELEASE:
10983                         if (length < sizeof (diag_release)) {
10984                                 *return_code =
10985                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10986                                 status = DDI_FAILURE;
10987                                 break;
10988                         }
10989                         if (ddi_copyin(diag_action, &diag_release,
10990                             sizeof (diag_release), ioctl_mode) != 0) {
10991                                 return (DDI_FAILURE);
10992                         }
10993                         status = mptsas_diag_release(mpt, &diag_release,
10994                             return_code);
10995                         break;
10996 
10997                 default:
10998                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
10999                         status = DDI_FAILURE;
11000                         break;
11001         }
11002 
11003         if ((status == DDI_FAILURE) &&
11004             (original_return_code == MPTSAS_FW_DIAG_NEW) &&
11005             (*return_code != MPTSAS_FW_DIAG_ERROR_SUCCESS)) {
11006                 status = DDI_SUCCESS;
11007         }
11008 
11009         return (status);
11010 }
11011 
11012 static int
11013 mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *user_data, int mode)
11014 {
11015         int                     status;
11016         mptsas_diag_action_t    driver_data;
11017 
11018         ASSERT(mutex_owned(&mpt->m_mutex));
11019 
11020         /*
11021          * Copy the user data to a driver data buffer.
11022          */
11023         if (ddi_copyin(user_data, &driver_data, sizeof (mptsas_diag_action_t),
11024             mode) == 0) {
11025                 /*
11026                  * Send diag action request if Action is valid
11027                  */
11028                 if (driver_data.Action == MPTSAS_FW_DIAG_TYPE_REGISTER ||
11029                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_UNREGISTER ||
11030                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_QUERY ||
11031                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_READ_BUFFER ||
11032                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_RELEASE) {
11033                         status = mptsas_do_diag_action(mpt, driver_data.Action,
11034                             (void *)(uintptr_t)driver_data.PtrDiagAction,
11035                             driver_data.Length, &driver_data.ReturnCode,
11036                             mode);
11037                         if (status == DDI_SUCCESS) {
11038                                 if (ddi_copyout(&driver_data.ReturnCode,
11039                                     &user_data->ReturnCode,
11040                                     sizeof (user_data->ReturnCode), mode)
11041                                     != 0) {
11042                                         status = EFAULT;
11043                                 } else {
11044                                         status = 0;
11045                                 }
11046                         } else {
11047                                 status = EIO;
11048                         }
11049                 } else {
11050                         status = EINVAL;
11051                 }
11052         } else {
11053                 status = EFAULT;
11054         }
11055 
11056         return (status);
11057 }
11058 
11059 /*
11060  * This routine handles the "event query" ioctl.
11061  */
11062 static int
11063 mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data, int mode,
11064     int *rval)
11065 {
11066         int                     status;
11067         mptsas_event_query_t    driverdata;
11068         uint8_t                 i;
11069 
11070         driverdata.Entries = MPTSAS_EVENT_QUEUE_SIZE;
11071 
11072         mutex_enter(&mpt->m_mutex);
11073         for (i = 0; i < 4; i++) {
11074                 driverdata.Types[i] = mpt->m_event_mask[i];
11075         }
11076         mutex_exit(&mpt->m_mutex);
11077 
11078         if (ddi_copyout(&driverdata, data, sizeof (driverdata), mode) != 0) {
11079                 status = EFAULT;
11080         } else {
11081                 *rval = MPTIOCTL_STATUS_GOOD;
11082                 status = 0;
11083         }
11084 
11085         return (status);
11086 }
11087 
11088 /*
11089  * This routine handles the "event enable" ioctl.
11090  */
11091 static int
11092 mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data, int mode,
11093     int *rval)
11094 {
11095         int                     status;
11096         mptsas_event_enable_t   driverdata;
11097         uint8_t                 i;
11098 
11099         if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
11100                 mutex_enter(&mpt->m_mutex);
11101                 for (i = 0; i < 4; i++) {
11102                         mpt->m_event_mask[i] = driverdata.Types[i];
11103                 }
11104                 mutex_exit(&mpt->m_mutex);
11105 
11106                 *rval = MPTIOCTL_STATUS_GOOD;
11107                 status = 0;
11108         } else {
11109                 status = EFAULT;
11110         }
11111         return (status);
11112 }
11113 
11114 /*
11115  * This routine handles the "event report" ioctl.
11116  */
11117 static int
11118 mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data, int mode,
11119     int *rval)
11120 {
11121         int                     status;
11122         mptsas_event_report_t   driverdata;
11123 
11124         mutex_enter(&mpt->m_mutex);
11125 
11126         if (ddi_copyin(&data->Size, &driverdata.Size, sizeof (driverdata.Size),
11127             mode) == 0) {
11128                 if (driverdata.Size >= sizeof (mpt->m_events)) {
11129                         if (ddi_copyout(mpt->m_events, data->Events,
11130                             sizeof (mpt->m_events), mode) != 0) {
11131                                 status = EFAULT;
11132                         } else {
11133                                 if (driverdata.Size > sizeof (mpt->m_events)) {
11134                                         driverdata.Size =
11135                                             sizeof (mpt->m_events);
11136                                         if (ddi_copyout(&driverdata.Size,
11137                                             &data->Size,
11138                                             sizeof (driverdata.Size),
11139                                             mode) != 0) {
11140                                                 status = EFAULT;
11141                                         } else {
11142                                                 *rval = MPTIOCTL_STATUS_GOOD;
11143                                                 status = 0;
11144                                         }
11145                                 } else {
11146                                         *rval = MPTIOCTL_STATUS_GOOD;
11147                                         status = 0;
11148                                 }
11149                         }
11150                 } else {
11151                         *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
11152                         status = 0;
11153                 }
11154         } else {
11155                 status = EFAULT;
11156         }
11157 
11158         mutex_exit(&mpt->m_mutex);
11159         return (status);
11160 }
11161 
11162 static void
11163 mptsas_lookup_pci_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
11164 {
11165         int     *reg_data;
11166         uint_t  reglen;
11167 
11168         /*
11169          * Lookup the 'reg' property and extract the other data
11170          */
11171         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
11172             DDI_PROP_DONTPASS, "reg", &reg_data, &reglen) ==
11173             DDI_PROP_SUCCESS) {
11174                 /*
11175                  * Extract the PCI data from the 'reg' property first DWORD.
11176                  * The entry looks like the following:
11177                  * First DWORD:
11178                  * Bits 0 - 7 8-bit Register number
11179                  * Bits 8 - 10 3-bit Function number
11180                  * Bits 11 - 15 5-bit Device number
11181                  * Bits 16 - 23 8-bit Bus number
11182                  * Bits 24 - 25 2-bit Address Space type identifier
11183                  *
11184                  */
11185                 adapter_data->PciInformation.u.bits.BusNumber =
11186                     (reg_data[0] & 0x00FF0000) >> 16;
11187                 adapter_data->PciInformation.u.bits.DeviceNumber =
11188                     (reg_data[0] & 0x0000F800) >> 11;
11189                 adapter_data->PciInformation.u.bits.FunctionNumber =
11190                     (reg_data[0] & 0x00000700) >> 8;
11191                 ddi_prop_free((void *)reg_data);
11192         } else {
11193                 /*
11194                  * If we can't determine the PCI data then we fill in FF's for
11195                  * the data to indicate this.
11196                  */
11197                 adapter_data->PCIDeviceHwId = 0xFFFFFFFF;
11198                 adapter_data->MpiPortNumber = 0xFFFFFFFF;
11199                 adapter_data->PciInformation.u.AsDWORD = 0xFFFFFFFF;
11200         }
11201 
11202         /*
11203          * Saved in the mpt->m_fwversion
11204          */
11205         adapter_data->MpiFirmwareVersion = mpt->m_fwversion;
11206 }
11207 
11208 static void
11209 mptsas_read_adapter_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
11210 {
11211         char    *driver_verstr = MPTSAS_MOD_STRING;
11212 
11213         mptsas_lookup_pci_data(mpt, adapter_data);
11214         adapter_data->AdapterType = MPTIOCTL_ADAPTER_TYPE_SAS2;
11215         adapter_data->PCIDeviceHwId = (uint32_t)mpt->m_devid;
11216         adapter_data->PCIDeviceHwRev = (uint32_t)mpt->m_revid;
11217         adapter_data->SubSystemId = (uint32_t)mpt->m_ssid;
11218         adapter_data->SubsystemVendorId = (uint32_t)mpt->m_svid;
11219         (void) strcpy((char *)&adapter_data->DriverVersion[0], driver_verstr);
11220         adapter_data->BiosVersion = 0;
11221         (void) mptsas_get_bios_page3(mpt, &adapter_data->BiosVersion);
11222 }
11223 
11224 static void
11225 mptsas_read_pci_info(mptsas_t *mpt, mptsas_pci_info_t *pci_info)
11226 {
11227         int     *reg_data, i;
11228         uint_t  reglen;
11229 
11230         /*
11231          * Lookup the 'reg' property and extract the other data
11232          */
11233         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
11234             DDI_PROP_DONTPASS, "reg", &reg_data, &reglen) ==
11235             DDI_PROP_SUCCESS) {
11236                 /*
11237                  * Extract the PCI data from the 'reg' property first DWORD.
11238                  * The entry looks like the following:
11239                  * First DWORD:
11240                  * Bits 8 - 10 3-bit Function number
11241                  * Bits 11 - 15 5-bit Device number
11242                  * Bits 16 - 23 8-bit Bus number
11243                  */
11244                 pci_info->BusNumber = (reg_data[0] & 0x00FF0000) >> 16;
11245                 pci_info->DeviceNumber = (reg_data[0] & 0x0000F800) >> 11;
11246                 pci_info->FunctionNumber = (reg_data[0] & 0x00000700) >> 8;
11247                 ddi_prop_free((void *)reg_data);
11248         } else {
11249                 /*
11250                  * If we can't determine the PCI info then we fill in FF's for
11251                  * the data to indicate this.
11252                  */
11253                 pci_info->BusNumber = 0xFFFFFFFF;
11254                 pci_info->DeviceNumber = 0xFF;
11255                 pci_info->FunctionNumber = 0xFF;
11256         }
11257 
11258         /*
11259          * Now get the interrupt vector and the pci header.  The vector can
11260          * only be 0 right now.  The header is the first 256 bytes of config
11261          * space.
11262          */
11263         pci_info->InterruptVector = 0;
11264         for (i = 0; i < sizeof (pci_info->PciHeader); i++) {
11265                 pci_info->PciHeader[i] = pci_config_get8(mpt->m_config_handle,
11266                     i);
11267         }
11268 }
11269 
11270 static int
11271 mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data, int mode)
11272 {
11273         int                     status = 0;
11274         mptsas_reg_access_t     driverdata;
11275 
11276         mutex_enter(&mpt->m_mutex);
11277         if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
11278                 switch (driverdata.Command) {
11279                         /*
11280                          * IO access is not supported.
11281                          */
11282                         case REG_IO_READ:
11283                         case REG_IO_WRITE:
11284                                 mptsas_log(mpt, CE_WARN, "IO access is not "
11285                                     "supported.  Use memory access.");
11286                                 status = EINVAL;
11287                                 break;
11288 
11289                         case REG_MEM_READ:
11290                                 driverdata.RegData = ddi_get32(mpt->m_datap,
11291                                     (uint32_t *)(void *)mpt->m_reg +
11292                                     driverdata.RegOffset);
11293                                 if (ddi_copyout(&driverdata.RegData,
11294                                     &data->RegData,
11295                                     sizeof (driverdata.RegData), mode) != 0) {
11296                                         mptsas_log(mpt, CE_WARN, "Register "
11297                                             "Read Failed");
11298                                         status = EFAULT;
11299                                 }
11300                                 break;
11301 
11302                         case REG_MEM_WRITE:
11303                                 ddi_put32(mpt->m_datap,
11304                                     (uint32_t *)(void *)mpt->m_reg +
11305                                     driverdata.RegOffset,
11306                                     driverdata.RegData);
11307                                 break;
11308 
11309                         default:
11310                                 status = EINVAL;
11311                                 break;
11312                 }
11313         } else {
11314                 status = EFAULT;
11315         }
11316 
11317         mutex_exit(&mpt->m_mutex);
11318         return (status);
11319 }
11320 
11321 static int
11322 led_control(mptsas_t *mpt, intptr_t data, int mode)
11323 {
11324         int ret = 0;
11325         mptsas_led_control_t lc;
11326         mptsas_target_t *ptgt;
11327 
11328         if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) {
11329                 return (EFAULT);
11330         }
11331 
11332         if ((lc.Command != MPTSAS_LEDCTL_FLAG_SET &&
11333             lc.Command != MPTSAS_LEDCTL_FLAG_GET) ||
11334             lc.Led < MPTSAS_LEDCTL_LED_MIN ||
11335             lc.Led > MPTSAS_LEDCTL_LED_MAX ||
11336             (lc.Command == MPTSAS_LEDCTL_FLAG_SET && lc.LedStatus != 0 &&
11337             lc.LedStatus != 1)) {
11338                 return (EINVAL);
11339         }
11340 
11341         if ((lc.Command == MPTSAS_LEDCTL_FLAG_SET && (mode & FWRITE) == 0) ||
11342             (lc.Command == MPTSAS_LEDCTL_FLAG_GET && (mode & FREAD) == 0))
11343                 return (EACCES);
11344 
11345         /* Locate the target we're interrogating... */
11346         mutex_enter(&mpt->m_mutex);
11347         ptgt = refhash_linear_search(mpt->m_targets,
11348             mptsas_target_eval_slot, &lc);
11349         if (ptgt == NULL) {
11350                 /* We could not find a target for that enclosure/slot. */
11351                 mutex_exit(&mpt->m_mutex);
11352                 return (ENOENT);
11353         }
11354 
11355         if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) {
11356                 /* Update our internal LED state. */
11357                 ptgt->m_led_status &= ~(1 << (lc.Led - 1));
11358                 ptgt->m_led_status |= lc.LedStatus << (lc.Led - 1);
11359 
11360                 /* Flush it to the controller. */
11361                 ret = mptsas_flush_led_status(mpt, ptgt);
11362                 mutex_exit(&mpt->m_mutex);
11363                 return (ret);
11364         }
11365 
11366         /* Return our internal LED state. */
11367         lc.LedStatus = (ptgt->m_led_status >> (lc.Led - 1)) & 1;
11368         mutex_exit(&mpt->m_mutex);
11369 
11370         if (ddi_copyout(&lc, (void *)data, sizeof (lc), mode) != 0) {
11371                 return (EFAULT);
11372         }
11373 
11374         return (0);
11375 }
11376 
11377 static int
11378 get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
11379 {
11380         uint16_t i = 0;
11381         uint16_t count = 0;
11382         int ret = 0;
11383         mptsas_target_t *ptgt;
11384         mptsas_disk_info_t *di;
11385         STRUCT_DECL(mptsas_get_disk_info, gdi);
11386 
11387         if ((mode & FREAD) == 0)
11388                 return (EACCES);
11389 
11390         STRUCT_INIT(gdi, get_udatamodel());
11391 
11392         if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi),
11393             mode) != 0) {
11394                 return (EFAULT);
11395         }
11396 
11397         /* Find out how many targets there are. */
11398         mutex_enter(&mpt->m_mutex);
11399         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11400             ptgt = refhash_next(mpt->m_targets, ptgt)) {
11401                 count++;
11402         }
11403         mutex_exit(&mpt->m_mutex);
11404 
11405         /*
11406          * If we haven't been asked to copy out information on each target,
11407          * then just return the count.
11408          */
11409         STRUCT_FSET(gdi, DiskCount, count);
11410         if (STRUCT_FGETP(gdi, PtrDiskInfoArray) == NULL)
11411                 goto copy_out;
11412 
11413         /*
11414          * If we haven't been given a large enough buffer to copy out into,
11415          * let the caller know.
11416          */
11417         if (STRUCT_FGET(gdi, DiskInfoArraySize) <
11418             count * sizeof (mptsas_disk_info_t)) {
11419                 ret = ENOSPC;
11420                 goto copy_out;
11421         }
11422 
11423         di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP);
11424 
11425         mutex_enter(&mpt->m_mutex);
11426         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11427             ptgt = refhash_next(mpt->m_targets, ptgt)) {
11428                 if (i >= count) {
11429                         /*
11430                          * The number of targets changed while we weren't
11431                          * looking, so give up.
11432                          */
11433                         refhash_rele(mpt->m_targets, ptgt);
11434                         mutex_exit(&mpt->m_mutex);
11435                         kmem_free(di, count * sizeof (mptsas_disk_info_t));
11436                         return (EAGAIN);
11437                 }
11438                 di[i].Instance = mpt->m_instance;
11439                 di[i].Enclosure = ptgt->m_enclosure;
11440                 di[i].Slot = ptgt->m_slot_num;
11441                 di[i].SasAddress = ptgt->m_addr.mta_wwn;
11442                 i++;
11443         }
11444         mutex_exit(&mpt->m_mutex);
11445         STRUCT_FSET(gdi, DiskCount, i);
11446 
11447         /* Copy out the disk information to the caller. */
11448         if (ddi_copyout((void *)di, STRUCT_FGETP(gdi, PtrDiskInfoArray),
11449             i * sizeof (mptsas_disk_info_t), mode) != 0) {
11450                 ret = EFAULT;
11451         }
11452 
11453         kmem_free(di, count * sizeof (mptsas_disk_info_t));
11454 
11455 copy_out:
11456         if (ddi_copyout(STRUCT_BUF(gdi), (void *)data, STRUCT_SIZE(gdi),
11457             mode) != 0) {
11458                 ret = EFAULT;
11459         }
11460 
11461         return (ret);
11462 }
11463 
11464 static int
11465 mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
11466     int *rval)
11467 {
11468         int                     status = 0;
11469         mptsas_t                *mpt;
11470         mptsas_update_flash_t   flashdata;
11471         mptsas_pass_thru_t      passthru_data;
11472         mptsas_adapter_data_t   adapter_data;
11473         mptsas_pci_info_t       pci_info;
11474         int                     copylen;
11475 
11476         int                     iport_flag = 0;
11477         dev_info_t              *dip = NULL;
11478         mptsas_phymask_t        phymask = 0;
11479         struct devctl_iocdata   *dcp = NULL;
11480         char                    *addr = NULL;
11481         mptsas_target_t         *ptgt = NULL;
11482 
11483         *rval = MPTIOCTL_STATUS_GOOD;
11484         if (secpolicy_sys_config(credp, B_FALSE) != 0) {
11485                 return (EPERM);
11486         }
11487 
11488         mpt = ddi_get_soft_state(mptsas_state, MINOR2INST(getminor(dev)));
11489         if (mpt == NULL) {
11490                 /*
11491                  * Called from iport node, get the states
11492                  */
11493                 iport_flag = 1;
11494                 dip = mptsas_get_dip_from_dev(dev, &phymask);
11495                 if (dip == NULL) {
11496                         return (ENXIO);
11497                 }
11498                 mpt = DIP2MPT(dip);
11499         }
11500         /* Make sure power level is D0 before accessing registers */
11501         mutex_enter(&mpt->m_mutex);
11502         if (mpt->m_options & MPTSAS_OPT_PM) {
11503                 (void) pm_busy_component(mpt->m_dip, 0);
11504                 if (mpt->m_power_level != PM_LEVEL_D0) {
11505                         mutex_exit(&mpt->m_mutex);
11506                         if (pm_raise_power(mpt->m_dip, 0, PM_LEVEL_D0) !=
11507                             DDI_SUCCESS) {
11508                                 mptsas_log(mpt, CE_WARN,
11509                                     "mptsas%d: mptsas_ioctl: Raise power "
11510                                     "request failed.", mpt->m_instance);
11511                                 (void) pm_idle_component(mpt->m_dip, 0);
11512                                 return (ENXIO);
11513                         }
11514                 } else {
11515                         mutex_exit(&mpt->m_mutex);
11516                 }
11517         } else {
11518                 mutex_exit(&mpt->m_mutex);
11519         }
11520 
11521         if (iport_flag) {
11522                 status = scsi_hba_ioctl(dev, cmd, data, mode, credp, rval);
11523                 if (status != 0) {
11524                         goto out;
11525                 }
11526                 /*
11527                  * The following code control the OK2RM LED, it doesn't affect
11528                  * the ioctl return status.
11529                  */
11530                 if ((cmd == DEVCTL_DEVICE_ONLINE) ||
11531                     (cmd == DEVCTL_DEVICE_OFFLINE)) {
11532                         if (ndi_dc_allochdl((void *)data, &dcp) !=
11533                             NDI_SUCCESS) {
11534                                 goto out;
11535                         }
11536                         addr = ndi_dc_getaddr(dcp);
11537                         ptgt = mptsas_addr_to_ptgt(mpt, addr, phymask);
11538                         if (ptgt == NULL) {
11539                                 NDBG14(("mptsas_ioctl led control: tgt %s not "
11540                                     "found", addr));
11541                                 ndi_dc_freehdl(dcp);
11542                                 goto out;
11543                         }
11544                         mutex_enter(&mpt->m_mutex);
11545                         if (cmd == DEVCTL_DEVICE_ONLINE) {
11546                                 ptgt->m_tgt_unconfigured = 0;
11547                         } else if (cmd == DEVCTL_DEVICE_OFFLINE) {
11548                                 ptgt->m_tgt_unconfigured = 1;
11549                         }
11550                         if (cmd == DEVCTL_DEVICE_OFFLINE) {
11551                                 ptgt->m_led_status |=
11552                                     (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
11553                         } else {
11554                                 ptgt->m_led_status &=
11555                                     ~(1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
11556                         }
11557                         (void) mptsas_flush_led_status(mpt, ptgt);
11558                         mutex_exit(&mpt->m_mutex);
11559                         ndi_dc_freehdl(dcp);
11560                 }
11561                 goto out;
11562         }
11563         switch (cmd) {
11564                 case MPTIOCTL_GET_DISK_INFO:
11565                         status = get_disk_info(mpt, data, mode);
11566                         break;
11567                 case MPTIOCTL_LED_CONTROL:
11568                         status = led_control(mpt, data, mode);
11569                         break;
11570                 case MPTIOCTL_UPDATE_FLASH:
11571                         if (ddi_copyin((void *)data, &flashdata,
11572                                 sizeof (struct mptsas_update_flash), mode)) {
11573                                 status = EFAULT;
11574                                 break;
11575                         }
11576 
11577                         mutex_enter(&mpt->m_mutex);
11578                         if (mptsas_update_flash(mpt,
11579                             (caddr_t)(long)flashdata.PtrBuffer,
11580                             flashdata.ImageSize, flashdata.ImageType, mode)) {
11581                                 status = EFAULT;
11582                         }
11583 
11584                         /*
11585                          * Reset the chip to start using the new
11586                          * firmware.  Reset if failed also.
11587                          */
11588                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
11589                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
11590                                 status = EFAULT;
11591                         }
11592                         mutex_exit(&mpt->m_mutex);
11593                         break;
11594                 case MPTIOCTL_PASS_THRU:
11595                         /*
11596                          * The user has requested to pass through a command to
11597                          * be executed by the MPT firmware.  Call our routine
11598                          * which does this.  Only allow one passthru IOCTL at
11599                          * one time. Other threads will block on
11600                          * m_passthru_mutex, which is of adaptive variant.
11601                          */
11602                         if (ddi_copyin((void *)data, &passthru_data,
11603                             sizeof (mptsas_pass_thru_t), mode)) {
11604                                 status = EFAULT;
11605                                 break;
11606                         }
11607                         mutex_enter(&mpt->m_passthru_mutex);
11608                         mutex_enter(&mpt->m_mutex);
11609                         status = mptsas_pass_thru(mpt, &passthru_data, mode);
11610                         mutex_exit(&mpt->m_mutex);
11611                         mutex_exit(&mpt->m_passthru_mutex);
11612 
11613                         break;
11614                 case MPTIOCTL_GET_ADAPTER_DATA:
11615                         /*
11616                          * The user has requested to read adapter data.  Call
11617                          * our routine which does this.
11618                          */
11619                         bzero(&adapter_data, sizeof (mptsas_adapter_data_t));
11620                         if (ddi_copyin((void *)data, (void *)&adapter_data,
11621                             sizeof (mptsas_adapter_data_t), mode)) {
11622                                 status = EFAULT;
11623                                 break;
11624                         }
11625                         if (adapter_data.StructureLength >=
11626                             sizeof (mptsas_adapter_data_t)) {
11627                                 adapter_data.StructureLength = (uint32_t)
11628                                     sizeof (mptsas_adapter_data_t);
11629                                 copylen = sizeof (mptsas_adapter_data_t);
11630                                 mutex_enter(&mpt->m_mutex);
11631                                 mptsas_read_adapter_data(mpt, &adapter_data);
11632                                 mutex_exit(&mpt->m_mutex);
11633                         } else {
11634                                 adapter_data.StructureLength = (uint32_t)
11635                                     sizeof (mptsas_adapter_data_t);
11636                                 copylen = sizeof (adapter_data.StructureLength);
11637                                 *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
11638                         }
11639                         if (ddi_copyout((void *)(&adapter_data), (void *)data,
11640                             copylen, mode) != 0) {
11641                                 status = EFAULT;
11642                         }
11643                         break;
11644                 case MPTIOCTL_GET_PCI_INFO:
11645                         /*
11646                          * The user has requested to read pci info.  Call
11647                          * our routine which does this.
11648                          */
11649                         bzero(&pci_info, sizeof (mptsas_pci_info_t));
11650                         mutex_enter(&mpt->m_mutex);
11651                         mptsas_read_pci_info(mpt, &pci_info);
11652                         mutex_exit(&mpt->m_mutex);
11653                         if (ddi_copyout((void *)(&pci_info), (void *)data,
11654                             sizeof (mptsas_pci_info_t), mode) != 0) {
11655                                 status = EFAULT;
11656                         }
11657                         break;
11658                 case MPTIOCTL_RESET_ADAPTER:
11659                         mutex_enter(&mpt->m_mutex);
11660                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
11661                         if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
11662                                 mptsas_log(mpt, CE_WARN, "reset adapter IOCTL "
11663                                     "failed");
11664                                 status = EFAULT;
11665                         }
11666                         mutex_exit(&mpt->m_mutex);
11667                         break;
11668                 case MPTIOCTL_DIAG_ACTION:
11669                         /*
11670                          * The user has done a diag buffer action.  Call our
11671                          * routine which does this.  Only allow one diag action
11672                          * at one time.
11673                          */
11674                         mutex_enter(&mpt->m_mutex);
11675                         if (mpt->m_diag_action_in_progress) {
11676                                 mutex_exit(&mpt->m_mutex);
11677                                 return (EBUSY);
11678                         }
11679                         mpt->m_diag_action_in_progress = 1;
11680                         status = mptsas_diag_action(mpt,
11681                             (mptsas_diag_action_t *)data, mode);
11682                         mpt->m_diag_action_in_progress = 0;
11683                         mutex_exit(&mpt->m_mutex);
11684                         break;
11685                 case MPTIOCTL_EVENT_QUERY:
11686                         /*
11687                          * The user has done an event query. Call our routine
11688                          * which does this.
11689                          */
11690                         status = mptsas_event_query(mpt,
11691                             (mptsas_event_query_t *)data, mode, rval);
11692                         break;
11693                 case MPTIOCTL_EVENT_ENABLE:
11694                         /*
11695                          * The user has done an event enable. Call our routine
11696                          * which does this.
11697                          */
11698                         status = mptsas_event_enable(mpt,
11699                             (mptsas_event_enable_t *)data, mode, rval);
11700                         break;
11701                 case MPTIOCTL_EVENT_REPORT:
11702                         /*
11703                          * The user has done an event report. Call our routine
11704                          * which does this.
11705                          */
11706                         status = mptsas_event_report(mpt,
11707                             (mptsas_event_report_t *)data, mode, rval);
11708                         break;
11709                 case MPTIOCTL_REG_ACCESS:
11710                         /*
11711                          * The user has requested register access.  Call our
11712                          * routine which does this.
11713                          */
11714                         status = mptsas_reg_access(mpt,
11715                             (mptsas_reg_access_t *)data, mode);
11716                         break;
11717                 default:
11718                         status = scsi_hba_ioctl(dev, cmd, data, mode, credp,
11719                             rval);
11720                         break;
11721         }
11722 
11723 out:
11724         return (status);
11725 }
11726 
11727 int
11728 mptsas_restart_ioc(mptsas_t *mpt)
11729 {
11730         int             rval = DDI_SUCCESS;
11731         mptsas_target_t *ptgt = NULL;
11732 
11733         ASSERT(mutex_owned(&mpt->m_mutex));
11734 
11735         /*
11736          * Set a flag telling I/O path that we're processing a reset.  This is
11737          * needed because after the reset is complete, the hash table still
11738          * needs to be rebuilt.  If I/Os are started before the hash table is
11739          * rebuilt, I/O errors will occur.  This flag allows I/Os to be marked
11740          * so that they can be retried.
11741          */
11742         mpt->m_in_reset = TRUE;
11743 
11744         /*
11745          * Set all throttles to HOLD
11746          */
11747         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11748             ptgt = refhash_next(mpt->m_targets, ptgt)) {
11749                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
11750         }
11751 
11752         /*
11753          * Disable interrupts
11754          */
11755         MPTSAS_DISABLE_INTR(mpt);
11756 
11757         /*
11758          * Abort all commands: outstanding commands, commands in waitq and
11759          * tx_waitq.
11760          */
11761         mptsas_flush_hba(mpt);
11762 
11763         /*
11764          * Reinitialize the chip.
11765          */
11766         if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
11767                 rval = DDI_FAILURE;
11768         }
11769 
11770         /*
11771          * Enable interrupts again
11772          */
11773         MPTSAS_ENABLE_INTR(mpt);
11774 
11775         /*
11776          * If mptsas_init_chip was successful, update the driver data.
11777          */
11778         if (rval == DDI_SUCCESS) {
11779                 mptsas_update_driver_data(mpt);
11780         }
11781 
11782         /*
11783          * Reset the throttles
11784          */
11785         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11786             ptgt = refhash_next(mpt->m_targets, ptgt)) {
11787                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
11788         }
11789 
11790         mptsas_doneq_empty(mpt);
11791         mptsas_restart_hba(mpt);
11792 
11793         if (rval != DDI_SUCCESS) {
11794                 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
11795                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
11796         }
11797 
11798         /*
11799          * Clear the reset flag so that I/Os can continue.
11800          */
11801         mpt->m_in_reset = FALSE;
11802 
11803         return (rval);
11804 }
11805 
11806 static int
11807 mptsas_init_chip(mptsas_t *mpt, int first_time)
11808 {
11809         ddi_dma_cookie_t        cookie;
11810         uint32_t                i;
11811         int                     rval;
11812 
11813         /*
11814          * Check to see if the firmware image is valid
11815          */
11816         if (ddi_get32(mpt->m_datap, &mpt->m_reg->HostDiagnostic) &
11817             MPI2_DIAG_FLASH_BAD_SIG) {
11818                 mptsas_log(mpt, CE_WARN, "mptsas bad flash signature!");
11819                 goto fail;
11820         }
11821 
11822         /*
11823          * Reset the chip
11824          */
11825         rval = mptsas_ioc_reset(mpt, first_time);
11826         if (rval == MPTSAS_RESET_FAIL) {
11827                 mptsas_log(mpt, CE_WARN, "hard reset failed!");
11828                 goto fail;
11829         }
11830 
11831         if ((rval == MPTSAS_SUCCESS_MUR) && (!first_time)) {
11832                 goto mur;
11833         }
11834         /*
11835          * Setup configuration space
11836          */
11837         if (mptsas_config_space_init(mpt) == FALSE) {
11838                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init "
11839                     "failed!");
11840                 goto fail;
11841         }
11842 
11843         /*
11844          * IOC facts can change after a diag reset so all buffers that are
11845          * based on these numbers must be de-allocated and re-allocated.  Get
11846          * new IOC facts each time chip is initialized.
11847          */
11848         if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
11849                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed");
11850                 goto fail;
11851         }
11852 
11853         mpt->m_targets = refhash_create(MPTSAS_TARGET_BUCKET_COUNT,
11854             mptsas_target_addr_hash, mptsas_target_addr_cmp,
11855             mptsas_target_free, sizeof (mptsas_target_t),
11856             offsetof(mptsas_target_t, m_link),
11857             offsetof(mptsas_target_t, m_addr), KM_SLEEP);
11858 
11859         if (mptsas_alloc_active_slots(mpt, KM_SLEEP)) {
11860                 goto fail;
11861         }
11862         /*
11863          * Allocate request message frames, reply free queue, reply descriptor
11864          * post queue, and reply message frames using latest IOC facts.
11865          */
11866         if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) {
11867                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames failed");
11868                 goto fail;
11869         }
11870         if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) {
11871                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue failed!");
11872                 goto fail;
11873         }
11874         if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) {
11875                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue failed!");
11876                 goto fail;
11877         }
11878         if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) {
11879                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_reply_frames failed!");
11880                 goto fail;
11881         }
11882 
11883 mur:
11884         /*
11885          * Re-Initialize ioc to operational state
11886          */
11887         if (mptsas_ioc_init(mpt) == DDI_FAILURE) {
11888                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_init failed");
11889                 goto fail;
11890         }
11891 
11892         mptsas_alloc_reply_args(mpt);
11893 
11894         /*
11895          * Initialize reply post index.  Reply free index is initialized after
11896          * the next loop.
11897          */
11898         mpt->m_post_index = 0;
11899 
11900         /*
11901          * Initialize the Reply Free Queue with the physical addresses of our
11902          * reply frames.
11903          */
11904         cookie.dmac_address = mpt->m_reply_frame_dma_addr;
11905         for (i = 0; i < mpt->m_max_replies; i++) {
11906                 ddi_put32(mpt->m_acc_free_queue_hdl,
11907                     &((uint32_t *)(void *)mpt->m_free_queue)[i],
11908                     cookie.dmac_address);
11909                 cookie.dmac_address += mpt->m_reply_frame_size;
11910         }
11911         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
11912             DDI_DMA_SYNC_FORDEV);
11913 
11914         /*
11915          * Initialize the reply free index to one past the last frame on the
11916          * queue.  This will signify that the queue is empty to start with.
11917          */
11918         mpt->m_free_index = i;
11919         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex, i);
11920 
11921         /*
11922          * Initialize the reply post queue to 0xFFFFFFFF,0xFFFFFFFF's.
11923          */
11924         for (i = 0; i < mpt->m_post_queue_depth; i++) {
11925                 ddi_put64(mpt->m_acc_post_queue_hdl,
11926                     &((uint64_t *)(void *)mpt->m_post_queue)[i],
11927                     0xFFFFFFFFFFFFFFFF);
11928         }
11929         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
11930             DDI_DMA_SYNC_FORDEV);
11931 
11932         /*
11933          * Enable ports
11934          */
11935         if (mptsas_ioc_enable_port(mpt) == DDI_FAILURE) {
11936                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_enable_port failed");
11937                 goto fail;
11938         }
11939 
11940         /*
11941          * enable events
11942          */
11943         if (mptsas_ioc_enable_event_notification(mpt)) {
11944                 goto fail;
11945         }
11946 
11947         /*
11948          * We need checks in attach and these.
11949          * chip_init is called in mult. places
11950          */
11951 
11952         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
11953             DDI_SUCCESS) ||
11954             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
11955             DDI_SUCCESS) ||
11956             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
11957             DDI_SUCCESS) ||
11958             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
11959             DDI_SUCCESS) ||
11960             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
11961             DDI_SUCCESS)) {
11962                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
11963                 goto fail;
11964         }
11965 
11966         /* Check all acc handles */
11967         if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
11968             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
11969             DDI_SUCCESS) ||
11970             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
11971             DDI_SUCCESS) ||
11972             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
11973             DDI_SUCCESS) ||
11974             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
11975             DDI_SUCCESS) ||
11976             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
11977             DDI_SUCCESS) ||
11978             (mptsas_check_acc_handle(mpt->m_config_handle) !=
11979             DDI_SUCCESS)) {
11980                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
11981                 goto fail;
11982         }
11983 
11984         return (DDI_SUCCESS);
11985 
11986 fail:
11987         return (DDI_FAILURE);
11988 }
11989 
11990 static int
11991 mptsas_get_pci_cap(mptsas_t *mpt)
11992 {
11993         ushort_t caps_ptr, cap, cap_count;
11994 
11995         if (mpt->m_config_handle == NULL)
11996                 return (FALSE);
11997         /*
11998          * Check if capabilities list is supported and if so,
11999          * get initial capabilities pointer and clear bits 0,1.
12000          */
12001         if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT)
12002             & PCI_STAT_CAP) {
12003                 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
12004                     PCI_CONF_CAP_PTR), 4);
12005         } else {
12006                 caps_ptr = PCI_CAP_NEXT_PTR_NULL;
12007         }
12008 
12009         /*
12010          * Walk capabilities if supported.
12011          */
12012         for (cap_count = 0; caps_ptr != PCI_CAP_NEXT_PTR_NULL; ) {
12013 
12014                 /*
12015                  * Check that we haven't exceeded the maximum number of
12016                  * capabilities and that the pointer is in a valid range.
12017                  */
12018                 if (++cap_count > 48) {
12019                         mptsas_log(mpt, CE_WARN,
12020                             "too many device capabilities.\n");
12021                         break;
12022                 }
12023                 if (caps_ptr < 64) {
12024                         mptsas_log(mpt, CE_WARN,
12025                             "capabilities pointer 0x%x out of range.\n",
12026                             caps_ptr);
12027                         break;
12028                 }
12029 
12030                 /*
12031                  * Get next capability and check that it is valid.
12032                  * For now, we only support power management.
12033                  */
12034                 cap = pci_config_get8(mpt->m_config_handle, caps_ptr);
12035                 switch (cap) {
12036                         case PCI_CAP_ID_PM:
12037                                 mptsas_log(mpt, CE_NOTE,
12038                                     "?mptsas%d supports power management.\n",
12039                                     mpt->m_instance);
12040                                 mpt->m_options |= MPTSAS_OPT_PM;
12041 
12042                                 /* Save PMCSR offset */
12043                                 mpt->m_pmcsr_offset = caps_ptr + PCI_PMCSR;
12044                                 break;
12045                         /*
12046                          * The following capabilities are valid.  Any others
12047                          * will cause a message to be logged.
12048                          */
12049                         case PCI_CAP_ID_VPD:
12050                         case PCI_CAP_ID_MSI:
12051                         case PCI_CAP_ID_PCIX:
12052                         case PCI_CAP_ID_PCI_E:
12053                         case PCI_CAP_ID_MSI_X:
12054                                 break;
12055                         default:
12056                                 mptsas_log(mpt, CE_NOTE,
12057                                     "?mptsas%d unrecognized capability "
12058                                     "0x%x.\n", mpt->m_instance, cap);
12059                                 break;
12060                 }
12061 
12062                 /*
12063                  * Get next capabilities pointer and clear bits 0,1.
12064                  */
12065                 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
12066                     (caps_ptr + PCI_CAP_NEXT_PTR)), 4);
12067         }
12068         return (TRUE);
12069 }
12070 
12071 static int
12072 mptsas_init_pm(mptsas_t *mpt)
12073 {
12074         char            pmc_name[16];
12075         char            *pmc[] = {
12076                                 NULL,
12077                                 "0=Off (PCI D3 State)",
12078                                 "3=On (PCI D0 State)",
12079                                 NULL
12080                         };
12081         uint16_t        pmcsr_stat;
12082 
12083         if (mptsas_get_pci_cap(mpt) == FALSE) {
12084                 return (DDI_FAILURE);
12085         }
12086         /*
12087          * If PCI's capability does not support PM, then don't need
12088          * to registe the pm-components
12089          */
12090         if (!(mpt->m_options & MPTSAS_OPT_PM))
12091                 return (DDI_SUCCESS);
12092         /*
12093          * If power management is supported by this chip, create
12094          * pm-components property for the power management framework
12095          */
12096         (void) sprintf(pmc_name, "NAME=mptsas%d", mpt->m_instance);
12097         pmc[0] = pmc_name;
12098         if (ddi_prop_update_string_array(DDI_DEV_T_NONE, mpt->m_dip,
12099             "pm-components", pmc, 3) != DDI_PROP_SUCCESS) {
12100                 mpt->m_options &= ~MPTSAS_OPT_PM;
12101                 mptsas_log(mpt, CE_WARN,
12102                     "mptsas%d: pm-component property creation failed.",
12103                     mpt->m_instance);
12104                 return (DDI_FAILURE);
12105         }
12106 
12107         /*
12108          * Power on device.
12109          */
12110         (void) pm_busy_component(mpt->m_dip, 0);
12111         pmcsr_stat = pci_config_get16(mpt->m_config_handle,
12112             mpt->m_pmcsr_offset);
12113         if ((pmcsr_stat & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_D0) {
12114                 mptsas_log(mpt, CE_WARN, "mptsas%d: Power up the device",
12115                     mpt->m_instance);
12116                 pci_config_put16(mpt->m_config_handle, mpt->m_pmcsr_offset,
12117                     PCI_PMCSR_D0);
12118         }
12119         if (pm_power_has_changed(mpt->m_dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) {
12120                 mptsas_log(mpt, CE_WARN, "pm_power_has_changed failed");
12121                 return (DDI_FAILURE);
12122         }
12123         mpt->m_power_level = PM_LEVEL_D0;
12124         /*
12125          * Set pm idle delay.
12126          */
12127         mpt->m_pm_idle_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
12128             mpt->m_dip, 0, "mptsas-pm-idle-delay", MPTSAS_PM_IDLE_TIMEOUT);
12129 
12130         return (DDI_SUCCESS);
12131 }
12132 
12133 static int
12134 mptsas_register_intrs(mptsas_t *mpt)
12135 {
12136         dev_info_t *dip;
12137         int intr_types;
12138 
12139         dip = mpt->m_dip;
12140 
12141         /* Get supported interrupt types */
12142         if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) {
12143                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_supported_types "
12144                     "failed\n");
12145                 return (FALSE);
12146         }
12147 
12148         NDBG6(("ddi_intr_get_supported_types() returned: 0x%x", intr_types));
12149 
12150         /*
12151          * Try MSI, but fall back to FIXED
12152          */
12153         if (mptsas_enable_msi && (intr_types & DDI_INTR_TYPE_MSI)) {
12154                 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_MSI) == DDI_SUCCESS) {
12155                         NDBG0(("Using MSI interrupt type"));
12156                         mpt->m_intr_type = DDI_INTR_TYPE_MSI;
12157                         return (TRUE);
12158                 }
12159         }
12160         if (intr_types & DDI_INTR_TYPE_FIXED) {
12161                 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_FIXED) == DDI_SUCCESS) {
12162                         NDBG0(("Using FIXED interrupt type"));
12163                         mpt->m_intr_type = DDI_INTR_TYPE_FIXED;
12164                         return (TRUE);
12165                 } else {
12166                         NDBG0(("FIXED interrupt registration failed"));
12167                         return (FALSE);
12168                 }
12169         }
12170 
12171         return (FALSE);
12172 }
12173 
12174 static void
12175 mptsas_unregister_intrs(mptsas_t *mpt)
12176 {
12177         mptsas_rem_intrs(mpt);
12178 }
12179 
12180 /*
12181  * mptsas_add_intrs:
12182  *
12183  * Register FIXED or MSI interrupts.
12184  */
12185 static int
12186 mptsas_add_intrs(mptsas_t *mpt, int intr_type)
12187 {
12188         dev_info_t      *dip = mpt->m_dip;
12189         int             avail, actual, count = 0;
12190         int             i, flag, ret;
12191 
12192         NDBG6(("mptsas_add_intrs:interrupt type 0x%x", intr_type));
12193 
12194         /* Get number of interrupts */
12195         ret = ddi_intr_get_nintrs(dip, intr_type, &count);
12196         if ((ret != DDI_SUCCESS) || (count <= 0)) {
12197                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_nintrs() failed, "
12198                     "ret %d count %d\n", ret, count);
12199 
12200                 return (DDI_FAILURE);
12201         }
12202 
12203         /* Get number of available interrupts */
12204         ret = ddi_intr_get_navail(dip, intr_type, &avail);
12205         if ((ret != DDI_SUCCESS) || (avail == 0)) {
12206                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_navail() failed, "
12207                     "ret %d avail %d\n", ret, avail);
12208 
12209                 return (DDI_FAILURE);
12210         }
12211 
12212         if (avail < count) {
12213                 mptsas_log(mpt, CE_NOTE, "ddi_intr_get_nvail returned %d, "
12214                     "navail() returned %d", count, avail);
12215         }
12216 
12217         /* Mpt only have one interrupt routine */
12218         if ((intr_type == DDI_INTR_TYPE_MSI) && (count > 1)) {
12219                 count = 1;
12220         }
12221 
12222         /* Allocate an array of interrupt handles */
12223         mpt->m_intr_size = count * sizeof (ddi_intr_handle_t);
12224         mpt->m_htable = kmem_alloc(mpt->m_intr_size, KM_SLEEP);
12225 
12226         flag = DDI_INTR_ALLOC_NORMAL;
12227 
12228         /* call ddi_intr_alloc() */
12229         ret = ddi_intr_alloc(dip, mpt->m_htable, intr_type, 0,
12230             count, &actual, flag);
12231 
12232         if ((ret != DDI_SUCCESS) || (actual == 0)) {
12233                 mptsas_log(mpt, CE_WARN, "ddi_intr_alloc() failed, ret %d\n",
12234                     ret);
12235                 kmem_free(mpt->m_htable, mpt->m_intr_size);
12236                 return (DDI_FAILURE);
12237         }
12238 
12239         /* use interrupt count returned or abort? */
12240         if (actual < count) {
12241                 mptsas_log(mpt, CE_NOTE, "Requested: %d, Received: %d\n",
12242                     count, actual);
12243         }
12244 
12245         mpt->m_intr_cnt = actual;
12246 
12247         /*
12248          * Get priority for first msi, assume remaining are all the same
12249          */
12250         if ((ret = ddi_intr_get_pri(mpt->m_htable[0],
12251             &mpt->m_intr_pri)) != DDI_SUCCESS) {
12252                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_pri() failed %d\n", ret);
12253 
12254                 /* Free already allocated intr */
12255                 for (i = 0; i < actual; i++) {
12256                         (void) ddi_intr_free(mpt->m_htable[i]);
12257                 }
12258 
12259                 kmem_free(mpt->m_htable, mpt->m_intr_size);
12260                 return (DDI_FAILURE);
12261         }
12262 
12263         /* Test for high level mutex */
12264         if (mpt->m_intr_pri >= ddi_intr_get_hilevel_pri()) {
12265                 mptsas_log(mpt, CE_WARN, "mptsas_add_intrs: "
12266                     "Hi level interrupt not supported\n");
12267 
12268                 /* Free already allocated intr */
12269                 for (i = 0; i < actual; i++) {
12270                         (void) ddi_intr_free(mpt->m_htable[i]);
12271                 }
12272 
12273                 kmem_free(mpt->m_htable, mpt->m_intr_size);
12274                 return (DDI_FAILURE);
12275         }
12276 
12277         /* Call ddi_intr_add_handler() */
12278         for (i = 0; i < actual; i++) {
12279                 if ((ret = ddi_intr_add_handler(mpt->m_htable[i], mptsas_intr,
12280                     (caddr_t)mpt, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
12281                         mptsas_log(mpt, CE_WARN, "ddi_intr_add_handler() "
12282                             "failed %d\n", ret);
12283 
12284                         /* Free already allocated intr */
12285                         for (i = 0; i < actual; i++) {
12286                                 (void) ddi_intr_free(mpt->m_htable[i]);
12287                         }
12288 
12289                         kmem_free(mpt->m_htable, mpt->m_intr_size);
12290                         return (DDI_FAILURE);
12291                 }
12292         }
12293 
12294         if ((ret = ddi_intr_get_cap(mpt->m_htable[0], &mpt->m_intr_cap))
12295             != DDI_SUCCESS) {
12296                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_cap() failed %d\n", ret);
12297 
12298                 /* Free already allocated intr */
12299                 for (i = 0; i < actual; i++) {
12300                         (void) ddi_intr_free(mpt->m_htable[i]);
12301                 }
12302 
12303                 kmem_free(mpt->m_htable, mpt->m_intr_size);
12304                 return (DDI_FAILURE);
12305         }
12306 
12307         /*
12308          * Enable interrupts
12309          */
12310         if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
12311                 /* Call ddi_intr_block_enable() for MSI interrupts */
12312                 (void) ddi_intr_block_enable(mpt->m_htable, mpt->m_intr_cnt);
12313         } else {
12314                 /* Call ddi_intr_enable for MSI or FIXED interrupts */
12315                 for (i = 0; i < mpt->m_intr_cnt; i++) {
12316                         (void) ddi_intr_enable(mpt->m_htable[i]);
12317                 }
12318         }
12319         return (DDI_SUCCESS);
12320 }
12321 
12322 /*
12323  * mptsas_rem_intrs:
12324  *
12325  * Unregister FIXED or MSI interrupts
12326  */
12327 static void
12328 mptsas_rem_intrs(mptsas_t *mpt)
12329 {
12330         int     i;
12331 
12332         NDBG6(("mptsas_rem_intrs"));
12333 
12334         /* Disable all interrupts */
12335         if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
12336                 /* Call ddi_intr_block_disable() */
12337                 (void) ddi_intr_block_disable(mpt->m_htable, mpt->m_intr_cnt);
12338         } else {
12339                 for (i = 0; i < mpt->m_intr_cnt; i++) {
12340                         (void) ddi_intr_disable(mpt->m_htable[i]);
12341                 }
12342         }
12343 
12344         /* Call ddi_intr_remove_handler() */
12345         for (i = 0; i < mpt->m_intr_cnt; i++) {
12346                 (void) ddi_intr_remove_handler(mpt->m_htable[i]);
12347                 (void) ddi_intr_free(mpt->m_htable[i]);
12348         }
12349 
12350         kmem_free(mpt->m_htable, mpt->m_intr_size);
12351 }
12352 
12353 /*
12354  * The IO fault service error handling callback function
12355  */
12356 /*ARGSUSED*/
12357 static int
12358 mptsas_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
12359 {
12360         /*
12361          * as the driver can always deal with an error in any dma or
12362          * access handle, we can just return the fme_status value.
12363          */
12364         pci_ereport_post(dip, err, NULL);
12365         return (err->fme_status);
12366 }
12367 
12368 /*
12369  * mptsas_fm_init - initialize fma capabilities and register with IO
12370  *               fault services.
12371  */
12372 static void
12373 mptsas_fm_init(mptsas_t *mpt)
12374 {
12375         /*
12376          * Need to change iblock to priority for new MSI intr
12377          */
12378         ddi_iblock_cookie_t     fm_ibc;
12379 
12380         /* Only register with IO Fault Services if we have some capability */
12381         if (mpt->m_fm_capabilities) {
12382                 /* Adjust access and dma attributes for FMA */
12383                 mpt->m_reg_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
12384                 mpt->m_msg_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
12385                 mpt->m_io_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
12386 
12387                 /*
12388                  * Register capabilities with IO Fault Services.
12389                  * mpt->m_fm_capabilities will be updated to indicate
12390                  * capabilities actually supported (not requested.)
12391                  */
12392                 ddi_fm_init(mpt->m_dip, &mpt->m_fm_capabilities, &fm_ibc);
12393 
12394                 /*
12395                  * Initialize pci ereport capabilities if ereport
12396                  * capable (should always be.)
12397                  */
12398                 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
12399                     DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
12400                         pci_ereport_setup(mpt->m_dip);
12401                 }
12402 
12403                 /*
12404                  * Register error callback if error callback capable.
12405                  */
12406                 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
12407                         ddi_fm_handler_register(mpt->m_dip,
12408                             mptsas_fm_error_cb, (void *) mpt);
12409                 }
12410         }
12411 }
12412 
12413 /*
12414  * mptsas_fm_fini - Releases fma capabilities and un-registers with IO
12415  *               fault services.
12416  *
12417  */
12418 static void
12419 mptsas_fm_fini(mptsas_t *mpt)
12420 {
12421         /* Only unregister FMA capabilities if registered */
12422         if (mpt->m_fm_capabilities) {
12423 
12424                 /*
12425                  * Un-register error callback if error callback capable.
12426                  */
12427 
12428                 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
12429                         ddi_fm_handler_unregister(mpt->m_dip);
12430                 }
12431 
12432                 /*
12433                  * Release any resources allocated by pci_ereport_setup()
12434                  */
12435 
12436                 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
12437                     DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
12438                         pci_ereport_teardown(mpt->m_dip);
12439                 }
12440 
12441                 /* Unregister from IO Fault Services */
12442                 ddi_fm_fini(mpt->m_dip);
12443 
12444                 /* Adjust access and dma attributes for FMA */
12445                 mpt->m_reg_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
12446                 mpt->m_msg_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12447                 mpt->m_io_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12448 
12449         }
12450 }
12451 
12452 int
12453 mptsas_check_acc_handle(ddi_acc_handle_t handle)
12454 {
12455         ddi_fm_error_t  de;
12456 
12457         if (handle == NULL)
12458                 return (DDI_FAILURE);
12459         ddi_fm_acc_err_get(handle, &de, DDI_FME_VER0);
12460         return (de.fme_status);
12461 }
12462 
12463 int
12464 mptsas_check_dma_handle(ddi_dma_handle_t handle)
12465 {
12466         ddi_fm_error_t  de;
12467 
12468         if (handle == NULL)
12469                 return (DDI_FAILURE);
12470         ddi_fm_dma_err_get(handle, &de, DDI_FME_VER0);
12471         return (de.fme_status);
12472 }
12473 
12474 void
12475 mptsas_fm_ereport(mptsas_t *mpt, char *detail)
12476 {
12477         uint64_t        ena;
12478         char            buf[FM_MAX_CLASS];
12479 
12480         (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
12481         ena = fm_ena_generate(0, FM_ENA_FMT1);
12482         if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities)) {
12483                 ddi_fm_ereport_post(mpt->m_dip, buf, ena, DDI_NOSLEEP,
12484                     FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
12485         }
12486 }
12487 
12488 static int
12489 mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
12490     uint16_t *dev_handle, mptsas_target_t **pptgt)
12491 {
12492         int             rval;
12493         uint32_t        dev_info;
12494         uint64_t        sas_wwn;
12495         mptsas_phymask_t phymask;
12496         uint8_t         physport, phynum, config, disk;
12497         uint64_t        devicename;
12498         uint16_t        pdev_hdl;
12499         mptsas_target_t *tmp_tgt = NULL;
12500         uint16_t        bay_num, enclosure;
12501 
12502         ASSERT(*pptgt == NULL);
12503 
12504         rval = mptsas_get_sas_device_page0(mpt, page_address, dev_handle,
12505             &sas_wwn, &dev_info, &physport, &phynum, &pdev_hdl,
12506             &bay_num, &enclosure);
12507         if (rval != DDI_SUCCESS) {
12508                 rval = DEV_INFO_FAIL_PAGE0;
12509                 return (rval);
12510         }
12511 
12512         if ((dev_info & (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
12513             MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
12514             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) == NULL) {
12515                 rval = DEV_INFO_WRONG_DEVICE_TYPE;
12516                 return (rval);
12517         }
12518 
12519         /*
12520          * Check if the dev handle is for a Phys Disk. If so, set return value
12521          * and exit.  Don't add Phys Disks to hash.
12522          */
12523         for (config = 0; config < mpt->m_num_raid_configs; config++) {
12524                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
12525                         if (*dev_handle == mpt->m_raidconfig[config].
12526                             m_physdisk_devhdl[disk]) {
12527                                 rval = DEV_INFO_PHYS_DISK;
12528                                 return (rval);
12529                         }
12530                 }
12531         }
12532 
12533         /*
12534          * Get SATA Device Name from SAS device page0 for
12535          * sata device, if device name doesn't exist, set mta_wwn to
12536          * 0 for direct attached SATA. For the device behind the expander
12537          * we still can use STP address assigned by expander.
12538          */
12539         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
12540             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
12541                 mutex_exit(&mpt->m_mutex);
12542                 /* alloc a tmp_tgt to send the cmd */
12543                 tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target),
12544                     KM_SLEEP);
12545                 tmp_tgt->m_devhdl = *dev_handle;
12546                 tmp_tgt->m_deviceinfo = dev_info;
12547                 tmp_tgt->m_qfull_retries = QFULL_RETRIES;
12548                 tmp_tgt->m_qfull_retry_interval =
12549                     drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
12550                 tmp_tgt->m_t_throttle = MAX_THROTTLE;
12551                 devicename = mptsas_get_sata_guid(mpt, tmp_tgt, 0);
12552                 kmem_free(tmp_tgt, sizeof (struct mptsas_target));
12553                 mutex_enter(&mpt->m_mutex);
12554                 if (devicename != 0 && (((devicename >> 56) & 0xf0) == 0x50)) {
12555                         sas_wwn = devicename;
12556                 } else if (dev_info & MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH) {
12557                         sas_wwn = 0;
12558                 }
12559         }
12560 
12561         phymask = mptsas_physport_to_phymask(mpt, physport);
12562         *pptgt = mptsas_tgt_alloc(mpt, *dev_handle, sas_wwn,
12563             dev_info, phymask, phynum);
12564         if (*pptgt == NULL) {
12565                 mptsas_log(mpt, CE_WARN, "Failed to allocated target"
12566                     "structure!");
12567                 rval = DEV_INFO_FAIL_ALLOC;
12568                 return (rval);
12569         }
12570         (*pptgt)->m_enclosure = enclosure;
12571         (*pptgt)->m_slot_num = bay_num;
12572         return (DEV_INFO_SUCCESS);
12573 }
12574 
12575 uint64_t
12576 mptsas_get_sata_guid(mptsas_t *mpt, mptsas_target_t *ptgt, int lun)
12577 {
12578         uint64_t        sata_guid = 0, *pwwn = NULL;
12579         int             target = ptgt->m_devhdl;
12580         uchar_t         *inq83 = NULL;
12581         int             inq83_len = 0xFF;
12582         uchar_t         *dblk = NULL;
12583         int             inq83_retry = 3;
12584         int             rval = DDI_FAILURE;
12585 
12586         inq83   = kmem_zalloc(inq83_len, KM_SLEEP);
12587 
12588 inq83_retry:
12589         rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
12590             inq83_len, NULL, 1);
12591         if (rval != DDI_SUCCESS) {
12592                 mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
12593                     "0x83 for target:%x, lun:%x failed!", target, lun);
12594                 goto out;
12595         }
12596         /* According to SAT2, the first descriptor is logic unit name */
12597         dblk = &inq83[4];
12598         if ((dblk[1] & 0x30) != 0) {
12599                 mptsas_log(mpt, CE_WARN, "!Descriptor is not lun associated.");
12600                 goto out;
12601         }
12602         pwwn = (uint64_t *)(void *)(&dblk[4]);
12603         if ((dblk[4] & 0xf0) == 0x50) {
12604                 sata_guid = BE_64(*pwwn);
12605                 goto out;
12606         } else if (dblk[4] == 'A') {
12607                 NDBG20(("SATA drive has no NAA format GUID."));
12608                 goto out;
12609         } else {
12610                 /* The data is not ready, wait and retry */
12611                 inq83_retry--;
12612                 if (inq83_retry <= 0) {
12613                         goto out;
12614                 }
12615                 NDBG20(("The GUID is not ready, retry..."));
12616                 delay(1 * drv_usectohz(1000000));
12617                 goto inq83_retry;
12618         }
12619 out:
12620         kmem_free(inq83, inq83_len);
12621         return (sata_guid);
12622 }
12623 
12624 static int
12625 mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun, uchar_t page,
12626     unsigned char *buf, int len, int *reallen, uchar_t evpd)
12627 {
12628         uchar_t                 cdb[CDB_GROUP0];
12629         struct scsi_address     ap;
12630         struct buf              *data_bp = NULL;
12631         int                     resid = 0;
12632         int                     ret = DDI_FAILURE;
12633 
12634         ASSERT(len <= 0xffff);
12635 
12636         ap.a_target = MPTSAS_INVALID_DEVHDL;
12637         ap.a_lun = (uchar_t)(lun);
12638         ap.a_hba_tran = mpt->m_tran;
12639 
12640         data_bp = scsi_alloc_consistent_buf(&ap,
12641             (struct buf *)NULL, len, B_READ, NULL_FUNC, NULL);
12642         if (data_bp == NULL) {
12643                 return (ret);
12644         }
12645         bzero(cdb, CDB_GROUP0);
12646         cdb[0] = SCMD_INQUIRY;
12647         cdb[1] = evpd;
12648         cdb[2] = page;
12649         cdb[3] = (len & 0xff00) >> 8;
12650         cdb[4] = (len & 0x00ff);
12651         cdb[5] = 0;
12652 
12653         ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP0, data_bp,
12654             &resid);
12655         if (ret == DDI_SUCCESS) {
12656                 if (reallen) {
12657                         *reallen = len - resid;
12658                 }
12659                 bcopy((caddr_t)data_bp->b_un.b_addr, buf, len);
12660         }
12661         if (data_bp) {
12662                 scsi_free_consistent_buf(data_bp);
12663         }
12664         return (ret);
12665 }
12666 
12667 static int
12668 mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
12669     mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
12670     int *resid)
12671 {
12672         struct scsi_pkt         *pktp = NULL;
12673         scsi_hba_tran_t         *tran_clone = NULL;
12674         mptsas_tgt_private_t    *tgt_private = NULL;
12675         int                     ret = DDI_FAILURE;
12676 
12677         /*
12678          * scsi_hba_tran_t->tran_tgt_private is used to pass the address
12679          * information to scsi_init_pkt, allocate a scsi_hba_tran structure
12680          * to simulate the cmds from sd
12681          */
12682         tran_clone = kmem_alloc(
12683             sizeof (scsi_hba_tran_t), KM_SLEEP);
12684         if (tran_clone == NULL) {
12685                 goto out;
12686         }
12687         bcopy((caddr_t)mpt->m_tran,
12688             (caddr_t)tran_clone, sizeof (scsi_hba_tran_t));
12689         tgt_private = kmem_alloc(
12690             sizeof (mptsas_tgt_private_t), KM_SLEEP);
12691         if (tgt_private == NULL) {
12692                 goto out;
12693         }
12694         tgt_private->t_lun = ap->a_lun;
12695         tgt_private->t_private = ptgt;
12696         tran_clone->tran_tgt_private = tgt_private;
12697         ap->a_hba_tran = tran_clone;
12698 
12699         pktp = scsi_init_pkt(ap, (struct scsi_pkt *)NULL,
12700             data_bp, cdblen, sizeof (struct scsi_arq_status),
12701             0, PKT_CONSISTENT, NULL, NULL);
12702         if (pktp == NULL) {
12703                 goto out;
12704         }
12705         bcopy(cdb, pktp->pkt_cdbp, cdblen);
12706         pktp->pkt_flags = FLAG_NOPARITY;
12707         if (scsi_poll(pktp) < 0) {
12708                 goto out;
12709         }
12710         if (((struct scsi_status *)pktp->pkt_scbp)->sts_chk) {
12711                 goto out;
12712         }
12713         if (resid != NULL) {
12714                 *resid = pktp->pkt_resid;
12715         }
12716 
12717         ret = DDI_SUCCESS;
12718 out:
12719         if (pktp) {
12720                 scsi_destroy_pkt(pktp);
12721         }
12722         if (tran_clone) {
12723                 kmem_free(tran_clone, sizeof (scsi_hba_tran_t));
12724         }
12725         if (tgt_private) {
12726                 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
12727         }
12728         return (ret);
12729 }
12730 static int
12731 mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy, int *lun)
12732 {
12733         char    *cp = NULL;
12734         char    *ptr = NULL;
12735         size_t  s = 0;
12736         char    *wwid_str = NULL;
12737         char    *lun_str = NULL;
12738         long    lunnum;
12739         long    phyid = -1;
12740         int     rc = DDI_FAILURE;
12741 
12742         ptr = name;
12743         ASSERT(ptr[0] == 'w' || ptr[0] == 'p');
12744         ptr++;
12745         if ((cp = strchr(ptr, ',')) == NULL) {
12746                 return (DDI_FAILURE);
12747         }
12748 
12749         wwid_str = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
12750         s = (uintptr_t)cp - (uintptr_t)ptr;
12751 
12752         bcopy(ptr, wwid_str, s);
12753         wwid_str[s] = '\0';
12754 
12755         ptr = ++cp;
12756 
12757         if ((cp = strchr(ptr, '\0')) == NULL) {
12758                 goto out;
12759         }
12760         lun_str =  kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
12761         s = (uintptr_t)cp - (uintptr_t)ptr;
12762 
12763         bcopy(ptr, lun_str, s);
12764         lun_str[s] = '\0';
12765 
12766         if (name[0] == 'p') {
12767                 rc = ddi_strtol(wwid_str, NULL, 0x10, &phyid);
12768         } else {
12769                 rc = scsi_wwnstr_to_wwn(wwid_str, wwid);
12770         }
12771         if (rc != DDI_SUCCESS)
12772                 goto out;
12773 
12774         if (phyid != -1) {
12775                 ASSERT(phyid < MPTSAS_MAX_PHYS);
12776                 *phy = (uint8_t)phyid;
12777         }
12778         rc = ddi_strtol(lun_str, NULL, 0x10, &lunnum);
12779         if (rc != 0)
12780                 goto out;
12781 
12782         *lun = (int)lunnum;
12783         rc = DDI_SUCCESS;
12784 out:
12785         if (wwid_str)
12786                 kmem_free(wwid_str, SCSI_MAXNAMELEN);
12787         if (lun_str)
12788                 kmem_free(lun_str, SCSI_MAXNAMELEN);
12789 
12790         return (rc);
12791 }
12792 
12793 /*
12794  * mptsas_parse_smp_name() is to parse sas wwn string
12795  * which format is "wWWN"
12796  */
12797 static int
12798 mptsas_parse_smp_name(char *name, uint64_t *wwn)
12799 {
12800         char    *ptr = name;
12801 
12802         if (*ptr != 'w') {
12803                 return (DDI_FAILURE);
12804         }
12805 
12806         ptr++;
12807         if (scsi_wwnstr_to_wwn(ptr, wwn)) {
12808                 return (DDI_FAILURE);
12809         }
12810         return (DDI_SUCCESS);
12811 }
12812 
12813 static int
12814 mptsas_bus_config(dev_info_t *pdip, uint_t flag,
12815     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
12816 {
12817         int             ret = NDI_FAILURE;
12818         int             circ = 0;
12819         int             circ1 = 0;
12820         mptsas_t        *mpt;
12821         char            *ptr = NULL;
12822         char            *devnm = NULL;
12823         uint64_t        wwid = 0;
12824         uint8_t         phy = 0xFF;
12825         int             lun = 0;
12826         uint_t          mflags = flag;
12827         int             bconfig = TRUE;
12828 
12829         if (scsi_hba_iport_unit_address(pdip) == 0) {
12830                 return (DDI_FAILURE);
12831         }
12832 
12833         mpt = DIP2MPT(pdip);
12834         if (!mpt) {
12835                 return (DDI_FAILURE);
12836         }
12837         /*
12838          * Hold the nexus across the bus_config
12839          */
12840         ndi_devi_enter(scsi_vhci_dip, &circ);
12841         ndi_devi_enter(pdip, &circ1);
12842         switch (op) {
12843         case BUS_CONFIG_ONE:
12844                 /* parse wwid/target name out of name given */
12845                 if ((ptr = strchr((char *)arg, '@')) == NULL) {
12846                         ret = NDI_FAILURE;
12847                         break;
12848                 }
12849                 ptr++;
12850                 if (strncmp((char *)arg, "smp", 3) == 0) {
12851                         /*
12852                          * This is a SMP target device
12853                          */
12854                         ret = mptsas_parse_smp_name(ptr, &wwid);
12855                         if (ret != DDI_SUCCESS) {
12856                                 ret = NDI_FAILURE;
12857                                 break;
12858                         }
12859                         ret = mptsas_config_smp(pdip, wwid, childp);
12860                 } else if ((ptr[0] == 'w') || (ptr[0] == 'p')) {
12861                         /*
12862                          * OBP could pass down a non-canonical form
12863                          * bootpath without LUN part when LUN is 0.
12864                          * So driver need adjust the string.
12865                          */
12866                         if (strchr(ptr, ',') == NULL) {
12867                                 devnm = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
12868                                 (void) sprintf(devnm, "%s,0", (char *)arg);
12869                                 ptr = strchr(devnm, '@');
12870                                 ptr++;
12871                         }
12872 
12873                         /*
12874                          * The device path is wWWID format and the device
12875                          * is not SMP target device.
12876                          */
12877                         ret = mptsas_parse_address(ptr, &wwid, &phy, &lun);
12878                         if (ret != DDI_SUCCESS) {
12879                                 ret = NDI_FAILURE;
12880                                 break;
12881                         }
12882                         *childp = NULL;
12883                         if (ptr[0] == 'w') {
12884                                 ret = mptsas_config_one_addr(pdip, wwid,
12885                                     lun, childp);
12886                         } else if (ptr[0] == 'p') {
12887                                 ret = mptsas_config_one_phy(pdip, phy, lun,
12888                                     childp);
12889                         }
12890 
12891                         /*
12892                          * If this is CD/DVD device in OBP path, the
12893                          * ndi_busop_bus_config can be skipped as config one
12894                          * operation is done above.
12895                          */
12896                         if ((ret == NDI_SUCCESS) && (*childp != NULL) &&
12897                             (strcmp(ddi_node_name(*childp), "cdrom") == 0) &&
12898                             (strncmp((char *)arg, "disk", 4) == 0)) {
12899                                 bconfig = FALSE;
12900                                 ndi_hold_devi(*childp);
12901                         }
12902                 } else {
12903                         ret = NDI_FAILURE;
12904                         break;
12905                 }
12906 
12907                 /*
12908                  * DDI group instructed us to use this flag.
12909                  */
12910                 mflags |= NDI_MDI_FALLBACK;
12911                 break;
12912         case BUS_CONFIG_DRIVER:
12913         case BUS_CONFIG_ALL:
12914                 mptsas_config_all(pdip);
12915                 ret = NDI_SUCCESS;
12916                 break;
12917         }
12918 
12919         if ((ret == NDI_SUCCESS) && bconfig) {
12920                 ret = ndi_busop_bus_config(pdip, mflags, op,
12921                     (devnm == NULL) ? arg : devnm, childp, 0);
12922         }
12923 
12924         ndi_devi_exit(pdip, circ1);
12925         ndi_devi_exit(scsi_vhci_dip, circ);
12926         if (devnm != NULL)
12927                 kmem_free(devnm, SCSI_MAXNAMELEN);
12928         return (ret);
12929 }
12930 
12931 static int
12932 mptsas_probe_lun(dev_info_t *pdip, int lun, dev_info_t **dip,
12933     mptsas_target_t *ptgt)
12934 {
12935         int                     rval = DDI_FAILURE;
12936         struct scsi_inquiry     *sd_inq = NULL;
12937         mptsas_t                *mpt = DIP2MPT(pdip);
12938 
12939         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
12940 
12941         rval = mptsas_inquiry(mpt, ptgt, lun, 0, (uchar_t *)sd_inq,
12942             SUN_INQSIZE, 0, (uchar_t)0);
12943 
12944         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
12945                 rval = mptsas_create_lun(pdip, sd_inq, dip, ptgt, lun);
12946         } else {
12947                 rval = DDI_FAILURE;
12948         }
12949 
12950         kmem_free(sd_inq, SUN_INQSIZE);
12951         return (rval);
12952 }
12953 
12954 static int
12955 mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
12956     dev_info_t **lundip)
12957 {
12958         int             rval;
12959         mptsas_t                *mpt = DIP2MPT(pdip);
12960         int             phymask;
12961         mptsas_target_t *ptgt = NULL;
12962 
12963         /*
12964          * Get the physical port associated to the iport
12965          */
12966         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
12967             "phymask", 0);
12968 
12969         ptgt = mptsas_wwid_to_ptgt(mpt, phymask, sasaddr);
12970         if (ptgt == NULL) {
12971                 /*
12972                  * didn't match any device by searching
12973                  */
12974                 return (DDI_FAILURE);
12975         }
12976         /*
12977          * If the LUN already exists and the status is online,
12978          * we just return the pointer to dev_info_t directly.
12979          * For the mdi_pathinfo node, we'll handle it in
12980          * mptsas_create_virt_lun()
12981          * TODO should be also in mptsas_handle_dr
12982          */
12983 
12984         *lundip = mptsas_find_child_addr(pdip, sasaddr, lun);
12985         if (*lundip != NULL) {
12986                 /*
12987                  * TODO Another senario is, we hotplug the same disk
12988                  * on the same slot, the devhdl changed, is this
12989                  * possible?
12990                  * tgt_private->t_private != ptgt
12991                  */
12992                 if (sasaddr != ptgt->m_addr.mta_wwn) {
12993                         /*
12994                          * The device has changed although the devhdl is the
12995                          * same (Enclosure mapping mode, change drive on the
12996                          * same slot)
12997                          */
12998                         return (DDI_FAILURE);
12999                 }
13000                 return (DDI_SUCCESS);
13001         }
13002 
13003         if (phymask == 0) {
13004                 /*
13005                  * Configure IR volume
13006                  */
13007                 rval =  mptsas_config_raid(pdip, ptgt->m_devhdl, lundip);
13008                 return (rval);
13009         }
13010         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
13011 
13012         return (rval);
13013 }
13014 
13015 static int
13016 mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
13017     dev_info_t **lundip)
13018 {
13019         int             rval;
13020         mptsas_t        *mpt = DIP2MPT(pdip);
13021         mptsas_phymask_t phymask;
13022         mptsas_target_t *ptgt = NULL;
13023 
13024         /*
13025          * Get the physical port associated to the iport
13026          */
13027         phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13028             "phymask", 0);
13029 
13030         ptgt = mptsas_phy_to_tgt(mpt, phymask, phy);
13031         if (ptgt == NULL) {
13032                 /*
13033                  * didn't match any device by searching
13034                  */
13035                 return (DDI_FAILURE);
13036         }
13037 
13038         /*
13039          * If the LUN already exists and the status is online,
13040          * we just return the pointer to dev_info_t directly.
13041          * For the mdi_pathinfo node, we'll handle it in
13042          * mptsas_create_virt_lun().
13043          */
13044 
13045         *lundip = mptsas_find_child_phy(pdip, phy);
13046         if (*lundip != NULL) {
13047                 return (DDI_SUCCESS);
13048         }
13049 
13050         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
13051 
13052         return (rval);
13053 }
13054 
13055 static int
13056 mptsas_retrieve_lundata(int lun_cnt, uint8_t *buf, uint16_t *lun_num,
13057     uint8_t *lun_addr_type)
13058 {
13059         uint32_t        lun_idx = 0;
13060 
13061         ASSERT(lun_num != NULL);
13062         ASSERT(lun_addr_type != NULL);
13063 
13064         lun_idx = (lun_cnt + 1) * MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
13065         /* determine report luns addressing type */
13066         switch (buf[lun_idx] & MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) {
13067                 /*
13068                  * Vendors in the field have been found to be concatenating
13069                  * bus/target/lun to equal the complete lun value instead
13070                  * of switching to flat space addressing
13071                  */
13072                 /* 00b - peripheral device addressing method */
13073         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_PERIPHERAL:
13074                 /* FALLTHRU */
13075                 /* 10b - logical unit addressing method */
13076         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT:
13077                 /* FALLTHRU */
13078                 /* 01b - flat space addressing method */
13079         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE:
13080                 /* byte0 bit0-5=msb lun byte1 bit0-7=lsb lun */
13081                 *lun_addr_type = (buf[lun_idx] &
13082                     MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) >> 6;
13083                 *lun_num = (buf[lun_idx] & 0x3F) << 8;
13084                 *lun_num |= buf[lun_idx + 1];
13085                 return (DDI_SUCCESS);
13086         default:
13087                 return (DDI_FAILURE);
13088         }
13089 }
13090 
13091 static int
13092 mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt)
13093 {
13094         struct buf              *repluns_bp = NULL;
13095         struct scsi_address     ap;
13096         uchar_t                 cdb[CDB_GROUP5];
13097         int                     ret = DDI_FAILURE;
13098         int                     retry = 0;
13099         int                     lun_list_len = 0;
13100         uint16_t                lun_num = 0;
13101         uint8_t                 lun_addr_type = 0;
13102         uint32_t                lun_cnt = 0;
13103         uint32_t                lun_total = 0;
13104         dev_info_t              *cdip = NULL;
13105         uint16_t                *saved_repluns = NULL;
13106         char                    *buffer = NULL;
13107         int                     buf_len = 128;
13108         mptsas_t                *mpt = DIP2MPT(pdip);
13109         uint64_t                sas_wwn = 0;
13110         uint8_t                 phy = 0xFF;
13111         uint32_t                dev_info = 0;
13112 
13113         mutex_enter(&mpt->m_mutex);
13114         sas_wwn = ptgt->m_addr.mta_wwn;
13115         phy = ptgt->m_phynum;
13116         dev_info = ptgt->m_deviceinfo;
13117         mutex_exit(&mpt->m_mutex);
13118 
13119         if (sas_wwn == 0) {
13120                 /*
13121                  * It's a SATA without Device Name
13122                  * So don't try multi-LUNs
13123                  */
13124                 if (mptsas_find_child_phy(pdip, phy)) {
13125                         return (DDI_SUCCESS);
13126                 } else {
13127                         /*
13128                          * need configure and create node
13129                          */
13130                         return (DDI_FAILURE);
13131                 }
13132         }
13133 
13134         /*
13135          * WWN (SAS address or Device Name exist)
13136          */
13137         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
13138             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
13139                 /*
13140                  * SATA device with Device Name
13141                  * So don't try multi-LUNs
13142                  */
13143                 if (mptsas_find_child_addr(pdip, sas_wwn, 0)) {
13144                         return (DDI_SUCCESS);
13145                 } else {
13146                         return (DDI_FAILURE);
13147                 }
13148         }
13149 
13150         do {
13151                 ap.a_target = MPTSAS_INVALID_DEVHDL;
13152                 ap.a_lun = 0;
13153                 ap.a_hba_tran = mpt->m_tran;
13154                 repluns_bp = scsi_alloc_consistent_buf(&ap,
13155                     (struct buf *)NULL, buf_len, B_READ, NULL_FUNC, NULL);
13156                 if (repluns_bp == NULL) {
13157                         retry++;
13158                         continue;
13159                 }
13160                 bzero(cdb, CDB_GROUP5);
13161                 cdb[0] = SCMD_REPORT_LUNS;
13162                 cdb[6] = (buf_len & 0xff000000) >> 24;
13163                 cdb[7] = (buf_len & 0x00ff0000) >> 16;
13164                 cdb[8] = (buf_len & 0x0000ff00) >> 8;
13165                 cdb[9] = (buf_len & 0x000000ff);
13166 
13167                 ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP5,
13168                     repluns_bp, NULL);
13169                 if (ret != DDI_SUCCESS) {
13170                         scsi_free_consistent_buf(repluns_bp);
13171                         retry++;
13172                         continue;
13173                 }
13174                 lun_list_len = BE_32(*(int *)((void *)(
13175                     repluns_bp->b_un.b_addr)));
13176                 if (buf_len >= lun_list_len + 8) {
13177                         ret = DDI_SUCCESS;
13178                         break;
13179                 }
13180                 scsi_free_consistent_buf(repluns_bp);
13181                 buf_len = lun_list_len + 8;
13182 
13183         } while (retry < 3);
13184 
13185         if (ret != DDI_SUCCESS)
13186                 return (ret);
13187         buffer = (char *)repluns_bp->b_un.b_addr;
13188         /*
13189          * find out the number of luns returned by the SCSI ReportLun call
13190          * and allocate buffer space
13191          */
13192         lun_total = lun_list_len / MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
13193         saved_repluns = kmem_zalloc(sizeof (uint16_t) * lun_total, KM_SLEEP);
13194         if (saved_repluns == NULL) {
13195                 scsi_free_consistent_buf(repluns_bp);
13196                 return (DDI_FAILURE);
13197         }
13198         for (lun_cnt = 0; lun_cnt < lun_total; lun_cnt++) {
13199                 if (mptsas_retrieve_lundata(lun_cnt, (uint8_t *)(buffer),
13200                     &lun_num, &lun_addr_type) != DDI_SUCCESS) {
13201                         continue;
13202                 }
13203                 saved_repluns[lun_cnt] = lun_num;
13204                 if (cdip = mptsas_find_child_addr(pdip, sas_wwn, lun_num))
13205                         ret = DDI_SUCCESS;
13206                 else
13207                         ret = mptsas_probe_lun(pdip, lun_num, &cdip,
13208                             ptgt);
13209                 if ((ret == DDI_SUCCESS) && (cdip != NULL)) {
13210                         (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip,
13211                             MPTSAS_DEV_GONE);
13212                 }
13213         }
13214         mptsas_offline_missed_luns(pdip, saved_repluns, lun_total, ptgt);
13215         kmem_free(saved_repluns, sizeof (uint16_t) * lun_total);
13216         scsi_free_consistent_buf(repluns_bp);
13217         return (DDI_SUCCESS);
13218 }
13219 
13220 static int
13221 mptsas_config_raid(dev_info_t *pdip, uint16_t target, dev_info_t **dip)
13222 {
13223         int                     rval = DDI_FAILURE;
13224         struct scsi_inquiry     *sd_inq = NULL;
13225         mptsas_t                *mpt = DIP2MPT(pdip);
13226         mptsas_target_t         *ptgt = NULL;
13227 
13228         mutex_enter(&mpt->m_mutex);
13229         ptgt = refhash_linear_search(mpt->m_targets,
13230             mptsas_target_eval_devhdl, &target);
13231         mutex_exit(&mpt->m_mutex);
13232         if (ptgt == NULL) {
13233                 mptsas_log(mpt, CE_WARN, "Volume with VolDevHandle of 0x%x "
13234                     "not found.", target);
13235                 return (rval);
13236         }
13237 
13238         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
13239         rval = mptsas_inquiry(mpt, ptgt, 0, 0, (uchar_t *)sd_inq,
13240             SUN_INQSIZE, 0, (uchar_t)0);
13241 
13242         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
13243                 rval = mptsas_create_phys_lun(pdip, sd_inq, NULL, dip, ptgt,
13244                     0);
13245         } else {
13246                 rval = DDI_FAILURE;
13247         }
13248 
13249         kmem_free(sd_inq, SUN_INQSIZE);
13250         return (rval);
13251 }
13252 
13253 /*
13254  * configure all RAID volumes for virtual iport
13255  */
13256 static void
13257 mptsas_config_all_viport(dev_info_t *pdip)
13258 {
13259         mptsas_t        *mpt = DIP2MPT(pdip);
13260         int             config, vol;
13261         int             target;
13262         dev_info_t      *lundip = NULL;
13263 
13264         /*
13265          * Get latest RAID info and search for any Volume DevHandles.  If any
13266          * are found, configure the volume.
13267          */
13268         mutex_enter(&mpt->m_mutex);
13269         for (config = 0; config < mpt->m_num_raid_configs; config++) {
13270                 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
13271                         if (mpt->m_raidconfig[config].m_raidvol[vol].m_israid
13272                             == 1) {
13273                                 target = mpt->m_raidconfig[config].
13274                                     m_raidvol[vol].m_raidhandle;
13275                                 mutex_exit(&mpt->m_mutex);
13276                                 (void) mptsas_config_raid(pdip, target,
13277                                     &lundip);
13278                                 mutex_enter(&mpt->m_mutex);
13279                         }
13280                 }
13281         }
13282         mutex_exit(&mpt->m_mutex);
13283 }
13284 
13285 static void
13286 mptsas_offline_missed_luns(dev_info_t *pdip, uint16_t *repluns,
13287     int lun_cnt, mptsas_target_t *ptgt)
13288 {
13289         dev_info_t      *child = NULL, *savechild = NULL;
13290         mdi_pathinfo_t  *pip = NULL, *savepip = NULL;
13291         uint64_t        sas_wwn, wwid;
13292         uint8_t         phy;
13293         int             lun;
13294         int             i;
13295         int             find;
13296         char            *addr;
13297         char            *nodename;
13298         mptsas_t        *mpt = DIP2MPT(pdip);
13299 
13300         mutex_enter(&mpt->m_mutex);
13301         wwid = ptgt->m_addr.mta_wwn;
13302         mutex_exit(&mpt->m_mutex);
13303 
13304         child = ddi_get_child(pdip);
13305         while (child) {
13306                 find = 0;
13307                 savechild = child;
13308                 child = ddi_get_next_sibling(child);
13309 
13310                 nodename = ddi_node_name(savechild);
13311                 if (strcmp(nodename, "smp") == 0) {
13312                         continue;
13313                 }
13314 
13315                 addr = ddi_get_name_addr(savechild);
13316                 if (addr == NULL) {
13317                         continue;
13318                 }
13319 
13320                 if (mptsas_parse_address(addr, &sas_wwn, &phy, &lun) !=
13321                     DDI_SUCCESS) {
13322                         continue;
13323                 }
13324 
13325                 if (wwid == sas_wwn) {
13326                         for (i = 0; i < lun_cnt; i++) {
13327                                 if (repluns[i] == lun) {
13328                                         find = 1;
13329                                         break;
13330                                 }
13331                         }
13332                 } else {
13333                         continue;
13334                 }
13335                 if (find == 0) {
13336                         /*
13337                          * The lun has not been there already
13338                          */
13339                         (void) mptsas_offline_lun(pdip, savechild, NULL,
13340                             NDI_DEVI_REMOVE);
13341                 }
13342         }
13343 
13344         pip = mdi_get_next_client_path(pdip, NULL);
13345         while (pip) {
13346                 find = 0;
13347                 savepip = pip;
13348                 addr = MDI_PI(pip)->pi_addr;
13349 
13350                 pip = mdi_get_next_client_path(pdip, pip);
13351 
13352                 if (addr == NULL) {
13353                         continue;
13354                 }
13355 
13356                 if (mptsas_parse_address(addr, &sas_wwn, &phy,
13357                     &lun) != DDI_SUCCESS) {
13358                         continue;
13359                 }
13360 
13361                 if (sas_wwn == wwid) {
13362                         for (i = 0; i < lun_cnt; i++) {
13363                                 if (repluns[i] == lun) {
13364                                         find = 1;
13365                                         break;
13366                                 }
13367                         }
13368                 } else {
13369                         continue;
13370                 }
13371 
13372                 if (find == 0) {
13373                         /*
13374                          * The lun has not been there already
13375                          */
13376                         (void) mptsas_offline_lun(pdip, NULL, savepip,
13377                             NDI_DEVI_REMOVE);
13378                 }
13379         }
13380 }
13381 
13382 void
13383 mptsas_update_hashtab(struct mptsas *mpt)
13384 {
13385         uint32_t        page_address;
13386         int             rval = 0;
13387         uint16_t        dev_handle;
13388         mptsas_target_t *ptgt = NULL;
13389         mptsas_smp_t    smp_node;
13390 
13391         /*
13392          * Get latest RAID info.
13393          */
13394         (void) mptsas_get_raid_info(mpt);
13395 
13396         dev_handle = mpt->m_smp_devhdl;
13397         for (; mpt->m_done_traverse_smp == 0; ) {
13398                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
13399                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)dev_handle;
13400                 if (mptsas_get_sas_expander_page0(mpt, page_address, &smp_node)
13401                     != DDI_SUCCESS) {
13402                         break;
13403                 }
13404                 mpt->m_smp_devhdl = dev_handle = smp_node.m_devhdl;
13405                 (void) mptsas_smp_alloc(mpt, &smp_node);
13406         }
13407 
13408         /*
13409          * Config target devices
13410          */
13411         dev_handle = mpt->m_dev_handle;
13412 
13413         /*
13414          * Do loop to get sas device page 0 by GetNextHandle till the
13415          * the last handle. If the sas device is a SATA/SSP target,
13416          * we try to config it.
13417          */
13418         for (; mpt->m_done_traverse_dev == 0; ) {
13419                 ptgt = NULL;
13420                 page_address =
13421                     (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
13422                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
13423                     (uint32_t)dev_handle;
13424                 rval = mptsas_get_target_device_info(mpt, page_address,
13425                     &dev_handle, &ptgt);
13426                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
13427                     (rval == DEV_INFO_FAIL_ALLOC)) {
13428                         break;
13429                 }
13430 
13431                 mpt->m_dev_handle = dev_handle;
13432         }
13433 
13434 }
13435 
13436 void
13437 mptsas_update_driver_data(struct mptsas *mpt)
13438 {
13439         mptsas_target_t *tp;
13440         mptsas_smp_t *sp;
13441 
13442         ASSERT(MUTEX_HELD(&mpt->m_mutex));
13443 
13444         /*
13445          * TODO after hard reset, update the driver data structures
13446          * 1. update port/phymask mapping table mpt->m_phy_info
13447          * 2. invalid all the entries in hash table
13448          *    m_devhdl = 0xffff and m_deviceinfo = 0
13449          * 3. call sas_device_page/expander_page to update hash table
13450          */
13451         mptsas_update_phymask(mpt);
13452         /*
13453          * Invalid the existing entries
13454          *
13455          * XXX - It seems like we should just delete everything here.  We are
13456          * holding the lock and are about to refresh all the targets in both
13457          * hashes anyway.  Given the path we're in, what outstanding async
13458          * event could possibly be trying to reference one of these things
13459          * without taking the lock, and how would that be useful anyway?
13460          */
13461         for (tp = refhash_first(mpt->m_targets); tp != NULL;
13462             tp = refhash_next(mpt->m_targets, tp)) {
13463                 tp->m_devhdl = MPTSAS_INVALID_DEVHDL;
13464                 tp->m_deviceinfo = 0;
13465                 tp->m_dr_flag = MPTSAS_DR_INACTIVE;
13466         }
13467         for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
13468             sp = refhash_next(mpt->m_smp_targets, sp)) {
13469                 sp->m_devhdl = MPTSAS_INVALID_DEVHDL;
13470                 sp->m_deviceinfo = 0;
13471         }
13472         mpt->m_done_traverse_dev = 0;
13473         mpt->m_done_traverse_smp = 0;
13474         mpt->m_dev_handle = mpt->m_smp_devhdl = MPTSAS_INVALID_DEVHDL;
13475         mptsas_update_hashtab(mpt);
13476 }
13477 
13478 static void
13479 mptsas_config_all(dev_info_t *pdip)
13480 {
13481         dev_info_t      *smpdip = NULL;
13482         mptsas_t        *mpt = DIP2MPT(pdip);
13483         int             phymask = 0;
13484         mptsas_phymask_t phy_mask;
13485         mptsas_target_t *ptgt = NULL;
13486         mptsas_smp_t    *psmp;
13487 
13488         /*
13489          * Get the phymask associated to the iport
13490          */
13491         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13492             "phymask", 0);
13493 
13494         /*
13495          * Enumerate RAID volumes here (phymask == 0).
13496          */
13497         if (phymask == 0) {
13498                 mptsas_config_all_viport(pdip);
13499                 return;
13500         }
13501 
13502         mutex_enter(&mpt->m_mutex);
13503 
13504         if (!mpt->m_done_traverse_dev || !mpt->m_done_traverse_smp) {
13505                 mptsas_update_hashtab(mpt);
13506         }
13507 
13508         for (psmp = refhash_first(mpt->m_smp_targets); psmp != NULL;
13509             psmp = refhash_next(mpt->m_smp_targets, psmp)) {
13510                 phy_mask = psmp->m_addr.mta_phymask;
13511                 if (phy_mask == phymask) {
13512                         smpdip = NULL;
13513                         mutex_exit(&mpt->m_mutex);
13514                         (void) mptsas_online_smp(pdip, psmp, &smpdip);
13515                         mutex_enter(&mpt->m_mutex);
13516                 }
13517         }
13518 
13519         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
13520             ptgt = refhash_next(mpt->m_targets, ptgt)) {
13521                 phy_mask = ptgt->m_addr.mta_phymask;
13522                 if (phy_mask == phymask) {
13523                         mutex_exit(&mpt->m_mutex);
13524                         (void) mptsas_config_target(pdip, ptgt);
13525                         mutex_enter(&mpt->m_mutex);
13526                 }
13527         }
13528         mutex_exit(&mpt->m_mutex);
13529 }
13530 
13531 static int
13532 mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt)
13533 {
13534         int             rval = DDI_FAILURE;
13535         dev_info_t      *tdip;
13536 
13537         rval = mptsas_config_luns(pdip, ptgt);
13538         if (rval != DDI_SUCCESS) {
13539                 /*
13540                  * The return value means the SCMD_REPORT_LUNS
13541                  * did not execute successfully. The target maybe
13542                  * doesn't support such command.
13543                  */
13544                 rval = mptsas_probe_lun(pdip, 0, &tdip, ptgt);
13545         }
13546         return (rval);
13547 }
13548 
13549 /*
13550  * Return fail if not all the childs/paths are freed.
13551  * if there is any path under the HBA, the return value will be always fail
13552  * because we didn't call mdi_pi_free for path
13553  */
13554 static int
13555 mptsas_offline_target(dev_info_t *pdip, char *name)
13556 {
13557         dev_info_t              *child = NULL, *prechild = NULL;
13558         mdi_pathinfo_t          *pip = NULL, *savepip = NULL;
13559         int                     tmp_rval, rval = DDI_SUCCESS;
13560         char                    *addr, *cp;
13561         size_t                  s;
13562         mptsas_t                *mpt = DIP2MPT(pdip);
13563 
13564         child = ddi_get_child(pdip);
13565         while (child) {
13566                 addr = ddi_get_name_addr(child);
13567                 prechild = child;
13568                 child = ddi_get_next_sibling(child);
13569 
13570                 if (addr == NULL) {
13571                         continue;
13572                 }
13573                 if ((cp = strchr(addr, ',')) == NULL) {
13574                         continue;
13575                 }
13576 
13577                 s = (uintptr_t)cp - (uintptr_t)addr;
13578 
13579                 if (strncmp(addr, name, s) != 0) {
13580                         continue;
13581                 }
13582 
13583                 tmp_rval = mptsas_offline_lun(pdip, prechild, NULL,
13584                     NDI_DEVI_REMOVE);
13585                 if (tmp_rval != DDI_SUCCESS) {
13586                         rval = DDI_FAILURE;
13587                         if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
13588                             prechild, MPTSAS_DEV_GONE) !=
13589                             DDI_PROP_SUCCESS) {
13590                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
13591                                     "unable to create property for "
13592                                     "SAS %s (MPTSAS_DEV_GONE)", addr);
13593                         }
13594                 }
13595         }
13596 
13597         pip = mdi_get_next_client_path(pdip, NULL);
13598         while (pip) {
13599                 addr = MDI_PI(pip)->pi_addr;
13600                 savepip = pip;
13601                 pip = mdi_get_next_client_path(pdip, pip);
13602                 if (addr == NULL) {
13603                         continue;
13604                 }
13605 
13606                 if ((cp = strchr(addr, ',')) == NULL) {
13607                         continue;
13608                 }
13609 
13610                 s = (uintptr_t)cp - (uintptr_t)addr;
13611 
13612                 if (strncmp(addr, name, s) != 0) {
13613                         continue;
13614                 }
13615 
13616                 (void) mptsas_offline_lun(pdip, NULL, savepip,
13617                     NDI_DEVI_REMOVE);
13618                 /*
13619                  * driver will not invoke mdi_pi_free, so path will not
13620                  * be freed forever, return DDI_FAILURE.
13621                  */
13622                 rval = DDI_FAILURE;
13623         }
13624         return (rval);
13625 }
13626 
13627 static int
13628 mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
13629     mdi_pathinfo_t *rpip, uint_t flags)
13630 {
13631         int             rval = DDI_FAILURE;
13632         char            *devname;
13633         dev_info_t      *cdip, *parent;
13634 
13635         if (rpip != NULL) {
13636                 parent = scsi_vhci_dip;
13637                 cdip = mdi_pi_get_client(rpip);
13638         } else if (rdip != NULL) {
13639                 parent = pdip;
13640                 cdip = rdip;
13641         } else {
13642                 return (DDI_FAILURE);
13643         }
13644 
13645         /*
13646          * Make sure node is attached otherwise
13647          * it won't have related cache nodes to
13648          * clean up.  i_ddi_devi_attached is
13649          * similiar to i_ddi_node_state(cdip) >=
13650          * DS_ATTACHED.
13651          */
13652         if (i_ddi_devi_attached(cdip)) {
13653 
13654                 /* Get full devname */
13655                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
13656                 (void) ddi_deviname(cdip, devname);
13657                 /* Clean cache */
13658                 (void) devfs_clean(parent, devname + 1,
13659                     DV_CLEAN_FORCE);
13660                 kmem_free(devname, MAXNAMELEN + 1);
13661         }
13662         if (rpip != NULL) {
13663                 if (MDI_PI_IS_OFFLINE(rpip)) {
13664                         rval = DDI_SUCCESS;
13665                 } else {
13666                         rval = mdi_pi_offline(rpip, 0);
13667                 }
13668         } else {
13669                 rval = ndi_devi_offline(cdip, flags);
13670         }
13671 
13672         return (rval);
13673 }
13674 
13675 static dev_info_t *
13676 mptsas_find_smp_child(dev_info_t *parent, char *str_wwn)
13677 {
13678         dev_info_t      *child = NULL;
13679         char            *smp_wwn = NULL;
13680 
13681         child = ddi_get_child(parent);
13682         while (child) {
13683                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
13684                     DDI_PROP_DONTPASS, SMP_WWN, &smp_wwn)
13685                     != DDI_SUCCESS) {
13686                         child = ddi_get_next_sibling(child);
13687                         continue;
13688                 }
13689 
13690                 if (strcmp(smp_wwn, str_wwn) == 0) {
13691                         ddi_prop_free(smp_wwn);
13692                         break;
13693                 }
13694                 child = ddi_get_next_sibling(child);
13695                 ddi_prop_free(smp_wwn);
13696         }
13697         return (child);
13698 }
13699 
13700 static int
13701 mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, uint_t flags)
13702 {
13703         int             rval = DDI_FAILURE;
13704         char            *devname;
13705         char            wwn_str[MPTSAS_WWN_STRLEN];
13706         dev_info_t      *cdip;
13707 
13708         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
13709 
13710         cdip = mptsas_find_smp_child(pdip, wwn_str);
13711 
13712         if (cdip == NULL)
13713                 return (DDI_SUCCESS);
13714 
13715         /*
13716          * Make sure node is attached otherwise
13717          * it won't have related cache nodes to
13718          * clean up.  i_ddi_devi_attached is
13719          * similiar to i_ddi_node_state(cdip) >=
13720          * DS_ATTACHED.
13721          */
13722         if (i_ddi_devi_attached(cdip)) {
13723 
13724                 /* Get full devname */
13725                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
13726                 (void) ddi_deviname(cdip, devname);
13727                 /* Clean cache */
13728                 (void) devfs_clean(pdip, devname + 1,
13729                     DV_CLEAN_FORCE);
13730                 kmem_free(devname, MAXNAMELEN + 1);
13731         }
13732 
13733         rval = ndi_devi_offline(cdip, flags);
13734 
13735         return (rval);
13736 }
13737 
13738 static dev_info_t *
13739 mptsas_find_child(dev_info_t *pdip, char *name)
13740 {
13741         dev_info_t      *child = NULL;
13742         char            *rname = NULL;
13743         int             rval = DDI_FAILURE;
13744 
13745         rname = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13746 
13747         child = ddi_get_child(pdip);
13748         while (child) {
13749                 rval = mptsas_name_child(child, rname, SCSI_MAXNAMELEN);
13750                 if (rval != DDI_SUCCESS) {
13751                         child = ddi_get_next_sibling(child);
13752                         bzero(rname, SCSI_MAXNAMELEN);
13753                         continue;
13754                 }
13755 
13756                 if (strcmp(rname, name) == 0) {
13757                         break;
13758                 }
13759                 child = ddi_get_next_sibling(child);
13760                 bzero(rname, SCSI_MAXNAMELEN);
13761         }
13762 
13763         kmem_free(rname, SCSI_MAXNAMELEN);
13764 
13765         return (child);
13766 }
13767 
13768 
13769 static dev_info_t *
13770 mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr, int lun)
13771 {
13772         dev_info_t      *child = NULL;
13773         char            *name = NULL;
13774         char            *addr = NULL;
13775 
13776         name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13777         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13778         (void) sprintf(name, "%016"PRIx64, sasaddr);
13779         (void) sprintf(addr, "w%s,%x", name, lun);
13780         child = mptsas_find_child(pdip, addr);
13781         kmem_free(name, SCSI_MAXNAMELEN);
13782         kmem_free(addr, SCSI_MAXNAMELEN);
13783         return (child);
13784 }
13785 
13786 static dev_info_t *
13787 mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy)
13788 {
13789         dev_info_t      *child;
13790         char            *addr;
13791 
13792         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13793         (void) sprintf(addr, "p%x,0", phy);
13794         child = mptsas_find_child(pdip, addr);
13795         kmem_free(addr, SCSI_MAXNAMELEN);
13796         return (child);
13797 }
13798 
13799 static mdi_pathinfo_t *
13800 mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy)
13801 {
13802         mdi_pathinfo_t  *path;
13803         char            *addr = NULL;
13804 
13805         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13806         (void) sprintf(addr, "p%x,0", phy);
13807         path = mdi_pi_find(pdip, NULL, addr);
13808         kmem_free(addr, SCSI_MAXNAMELEN);
13809         return (path);
13810 }
13811 
13812 static mdi_pathinfo_t *
13813 mptsas_find_path_addr(dev_info_t *parent, uint64_t sasaddr, int lun)
13814 {
13815         mdi_pathinfo_t  *path;
13816         char            *name = NULL;
13817         char            *addr = NULL;
13818 
13819         name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13820         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13821         (void) sprintf(name, "%016"PRIx64, sasaddr);
13822         (void) sprintf(addr, "w%s,%x", name, lun);
13823         path = mdi_pi_find(parent, NULL, addr);
13824         kmem_free(name, SCSI_MAXNAMELEN);
13825         kmem_free(addr, SCSI_MAXNAMELEN);
13826 
13827         return (path);
13828 }
13829 
13830 static int
13831 mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
13832     dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
13833 {
13834         int                     i = 0;
13835         uchar_t                 *inq83 = NULL;
13836         int                     inq83_len1 = 0xFF;
13837         int                     inq83_len = 0;
13838         int                     rval = DDI_FAILURE;
13839         ddi_devid_t             devid;
13840         char                    *guid = NULL;
13841         int                     target = ptgt->m_devhdl;
13842         mdi_pathinfo_t          *pip = NULL;
13843         mptsas_t                *mpt = DIP2MPT(pdip);
13844 
13845         /*
13846          * For DVD/CD ROM and tape devices and optical
13847          * devices, we won't try to enumerate them under
13848          * scsi_vhci, so no need to try page83
13849          */
13850         if (sd_inq && (sd_inq->inq_dtype == DTYPE_RODIRECT ||
13851             sd_inq->inq_dtype == DTYPE_OPTICAL ||
13852             sd_inq->inq_dtype == DTYPE_ESI))
13853                 goto create_lun;
13854 
13855         /*
13856          * The LCA returns good SCSI status, but corrupt page 83 data the first
13857          * time it is queried. The solution is to keep trying to request page83
13858          * and verify the GUID is not (DDI_NOT_WELL_FORMED) in
13859          * mptsas_inq83_retry_timeout seconds. If the timeout expires, driver
13860          * give up to get VPD page at this stage and fail the enumeration.
13861          */
13862 
13863         inq83   = kmem_zalloc(inq83_len1, KM_SLEEP);
13864 
13865         for (i = 0; i < mptsas_inq83_retry_timeout; i++) {
13866                 rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
13867                     inq83_len1, &inq83_len, 1);
13868                 if (rval != 0) {
13869                         mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
13870                             "0x83 for target:%x, lun:%x failed!", target, lun);
13871                         if (mptsas_physical_bind_failed_page_83 != B_FALSE)
13872                                 goto create_lun;
13873                         goto out;
13874                 }
13875                 /*
13876                  * create DEVID from inquiry data
13877                  */
13878                 if ((rval = ddi_devid_scsi_encode(
13879                     DEVID_SCSI_ENCODE_VERSION_LATEST, NULL, (uchar_t *)sd_inq,
13880                     sizeof (struct scsi_inquiry), NULL, 0, inq83,
13881                     (size_t)inq83_len, &devid)) == DDI_SUCCESS) {
13882                         /*
13883                          * extract GUID from DEVID
13884                          */
13885                         guid = ddi_devid_to_guid(devid);
13886 
13887                         /*
13888                          * Do not enable MPXIO if the strlen(guid) is greater
13889                          * than MPTSAS_MAX_GUID_LEN, this constrain would be
13890                          * handled by framework later.
13891                          */
13892                         if (guid && (strlen(guid) > MPTSAS_MAX_GUID_LEN)) {
13893                                 ddi_devid_free_guid(guid);
13894                                 guid = NULL;
13895                                 if (mpt->m_mpxio_enable == TRUE) {
13896                                         mptsas_log(mpt, CE_NOTE, "!Target:%x, "
13897                                             "lun:%x doesn't have a valid GUID, "
13898                                             "multipathing for this drive is "
13899                                             "not enabled", target, lun);
13900                                 }
13901                         }
13902 
13903                         /*
13904                          * devid no longer needed
13905                          */
13906                         ddi_devid_free(devid);
13907                         break;
13908                 } else if (rval == DDI_NOT_WELL_FORMED) {
13909                         /*
13910                          * return value of ddi_devid_scsi_encode equal to
13911                          * DDI_NOT_WELL_FORMED means DEVID_RETRY, it worth
13912                          * to retry inquiry page 0x83 and get GUID.
13913                          */
13914                         NDBG20(("Not well formed devid, retry..."));
13915                         delay(1 * drv_usectohz(1000000));
13916                         continue;
13917                 } else {
13918                         mptsas_log(mpt, CE_WARN, "!Encode devid failed for "
13919                             "path target:%x, lun:%x", target, lun);
13920                         rval = DDI_FAILURE;
13921                         goto create_lun;
13922                 }
13923         }
13924 
13925         if (i == mptsas_inq83_retry_timeout) {
13926                 mptsas_log(mpt, CE_WARN, "!Repeated page83 requests timeout "
13927                     "for path target:%x, lun:%x", target, lun);
13928         }
13929 
13930         rval = DDI_FAILURE;
13931 
13932 create_lun:
13933         if ((guid != NULL) && (mpt->m_mpxio_enable == TRUE)) {
13934                 rval = mptsas_create_virt_lun(pdip, sd_inq, guid, lun_dip, &pip,
13935                     ptgt, lun);
13936         }
13937         if (rval != DDI_SUCCESS) {
13938                 rval = mptsas_create_phys_lun(pdip, sd_inq, guid, lun_dip,
13939                     ptgt, lun);
13940 
13941         }
13942 out:
13943         if (guid != NULL) {
13944                 /*
13945                  * guid no longer needed
13946                  */
13947                 ddi_devid_free_guid(guid);
13948         }
13949         if (inq83 != NULL)
13950                 kmem_free(inq83, inq83_len1);
13951         return (rval);
13952 }
13953 
13954 static int
13955 mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *inq, char *guid,
13956     dev_info_t **lun_dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt, int lun)
13957 {
13958         int                     target;
13959         char                    *nodename = NULL;
13960         char                    **compatible = NULL;
13961         int                     ncompatible     = 0;
13962         int                     mdi_rtn = MDI_FAILURE;
13963         int                     rval = DDI_FAILURE;
13964         char                    *old_guid = NULL;
13965         mptsas_t                *mpt = DIP2MPT(pdip);
13966         char                    *lun_addr = NULL;
13967         char                    *wwn_str = NULL;
13968         char                    *attached_wwn_str = NULL;
13969         char                    *component = NULL;
13970         uint8_t                 phy = 0xFF;
13971         uint64_t                sas_wwn;
13972         int64_t                 lun64 = 0;
13973         uint32_t                devinfo;
13974         uint16_t                dev_hdl;
13975         uint16_t                pdev_hdl;
13976         uint64_t                dev_sas_wwn;
13977         uint64_t                pdev_sas_wwn;
13978         uint32_t                pdev_info;
13979         uint8_t                 physport;
13980         uint8_t                 phy_id;
13981         uint32_t                page_address;
13982         uint16_t                bay_num, enclosure;
13983         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
13984         uint32_t                dev_info;
13985 
13986         mutex_enter(&mpt->m_mutex);
13987         target = ptgt->m_devhdl;
13988         sas_wwn = ptgt->m_addr.mta_wwn;
13989         devinfo = ptgt->m_deviceinfo;
13990         phy = ptgt->m_phynum;
13991         mutex_exit(&mpt->m_mutex);
13992 
13993         if (sas_wwn) {
13994                 *pip = mptsas_find_path_addr(pdip, sas_wwn, lun);
13995         } else {
13996                 *pip = mptsas_find_path_phy(pdip, phy);
13997         }
13998 
13999         if (*pip != NULL) {
14000                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14001                 ASSERT(*lun_dip != NULL);
14002                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, *lun_dip,
14003                     (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
14004                     MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
14005                         if (strncmp(guid, old_guid, strlen(guid)) == 0) {
14006                                 /*
14007                                  * Same path back online again.
14008                                  */
14009                                 (void) ddi_prop_free(old_guid);
14010                                 if ((!MDI_PI_IS_ONLINE(*pip)) &&
14011                                     (!MDI_PI_IS_STANDBY(*pip)) &&
14012                                     (ptgt->m_tgt_unconfigured == 0)) {
14013                                         rval = mdi_pi_online(*pip, 0);
14014                                         mutex_enter(&mpt->m_mutex);
14015                                         ptgt->m_led_status = 0;
14016                                         (void) mptsas_flush_led_status(mpt,
14017                                             ptgt);
14018                                         mutex_exit(&mpt->m_mutex);
14019                                 } else {
14020                                         rval = DDI_SUCCESS;
14021                                 }
14022                                 if (rval != DDI_SUCCESS) {
14023                                         mptsas_log(mpt, CE_WARN, "path:target: "
14024                                             "%x, lun:%x online failed!", target,
14025                                             lun);
14026                                         *pip = NULL;
14027                                         *lun_dip = NULL;
14028                                 }
14029                                 return (rval);
14030                         } else {
14031                                 /*
14032                                  * The GUID of the LUN has changed which maybe
14033                                  * because customer mapped another volume to the
14034                                  * same LUN.
14035                                  */
14036                                 mptsas_log(mpt, CE_WARN, "The GUID of the "
14037                                     "target:%x, lun:%x was changed, maybe "
14038                                     "because someone mapped another volume "
14039                                     "to the same LUN", target, lun);
14040                                 (void) ddi_prop_free(old_guid);
14041                                 if (!MDI_PI_IS_OFFLINE(*pip)) {
14042                                         rval = mdi_pi_offline(*pip, 0);
14043                                         if (rval != MDI_SUCCESS) {
14044                                                 mptsas_log(mpt, CE_WARN, "path:"
14045                                                     "target:%x, lun:%x offline "
14046                                                     "failed!", target, lun);
14047                                                 *pip = NULL;
14048                                                 *lun_dip = NULL;
14049                                                 return (DDI_FAILURE);
14050                                         }
14051                                 }
14052                                 if (mdi_pi_free(*pip, 0) != MDI_SUCCESS) {
14053                                         mptsas_log(mpt, CE_WARN, "path:target:"
14054                                             "%x, lun:%x free failed!", target,
14055                                             lun);
14056                                         *pip = NULL;
14057                                         *lun_dip = NULL;
14058                                         return (DDI_FAILURE);
14059                                 }
14060                         }
14061                 } else {
14062                         mptsas_log(mpt, CE_WARN, "Can't get client-guid "
14063                             "property for path:target:%x, lun:%x", target, lun);
14064                         *pip = NULL;
14065                         *lun_dip = NULL;
14066                         return (DDI_FAILURE);
14067                 }
14068         }
14069         scsi_hba_nodename_compatible_get(inq, NULL,
14070             inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
14071 
14072         /*
14073          * if nodename can't be determined then print a message and skip it
14074          */
14075         if (nodename == NULL) {
14076                 mptsas_log(mpt, CE_WARN, "mptsas driver found no compatible "
14077                     "driver for target%d lun %d dtype:0x%02x", target, lun,
14078                     inq->inq_dtype);
14079                 return (DDI_FAILURE);
14080         }
14081 
14082         wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
14083         /* The property is needed by MPAPI */
14084         (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
14085 
14086         lun_addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14087         if (guid) {
14088                 (void) sprintf(lun_addr, "w%s,%x", wwn_str, lun);
14089                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14090         } else {
14091                 (void) sprintf(lun_addr, "p%x,%x", phy, lun);
14092                 (void) sprintf(wwn_str, "p%x", phy);
14093         }
14094 
14095         mdi_rtn = mdi_pi_alloc_compatible(pdip, nodename,
14096             guid, lun_addr, compatible, ncompatible,
14097             0, pip);
14098         if (mdi_rtn == MDI_SUCCESS) {
14099 
14100                 if (mdi_prop_update_string(*pip, MDI_GUID,
14101                     guid) != DDI_SUCCESS) {
14102                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14103                             "create prop for target %d lun %d (MDI_GUID)",
14104                             target, lun);
14105                         mdi_rtn = MDI_FAILURE;
14106                         goto virt_create_done;
14107                 }
14108 
14109                 if (mdi_prop_update_int(*pip, LUN_PROP,
14110                     lun) != DDI_SUCCESS) {
14111                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14112                             "create prop for target %d lun %d (LUN_PROP)",
14113                             target, lun);
14114                         mdi_rtn = MDI_FAILURE;
14115                         goto virt_create_done;
14116                 }
14117                 lun64 = (int64_t)lun;
14118                 if (mdi_prop_update_int64(*pip, LUN64_PROP,
14119                     lun64) != DDI_SUCCESS) {
14120                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14121                             "create prop for target %d (LUN64_PROP)",
14122                             target);
14123                         mdi_rtn = MDI_FAILURE;
14124                         goto virt_create_done;
14125                 }
14126                 if (mdi_prop_update_string_array(*pip, "compatible",
14127                     compatible, ncompatible) !=
14128                     DDI_PROP_SUCCESS) {
14129                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14130                             "create prop for target %d lun %d (COMPATIBLE)",
14131                             target, lun);
14132                         mdi_rtn = MDI_FAILURE;
14133                         goto virt_create_done;
14134                 }
14135                 if (sas_wwn && (mdi_prop_update_string(*pip,
14136                     SCSI_ADDR_PROP_TARGET_PORT, wwn_str) != DDI_PROP_SUCCESS)) {
14137                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14138                             "create prop for target %d lun %d "
14139                             "(target-port)", target, lun);
14140                         mdi_rtn = MDI_FAILURE;
14141                         goto virt_create_done;
14142                 } else if ((sas_wwn == 0) && (mdi_prop_update_int(*pip,
14143                     "sata-phy", phy) != DDI_PROP_SUCCESS)) {
14144                         /*
14145                          * Direct attached SATA device without DeviceName
14146                          */
14147                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14148                             "create prop for SAS target %d lun %d "
14149                             "(sata-phy)", target, lun);
14150                         mdi_rtn = MDI_FAILURE;
14151                         goto virt_create_done;
14152                 }
14153                 mutex_enter(&mpt->m_mutex);
14154 
14155                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14156                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14157                     (uint32_t)ptgt->m_devhdl;
14158                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14159                     &dev_hdl, &dev_sas_wwn, &dev_info, &physport,
14160                     &phy_id, &pdev_hdl, &bay_num, &enclosure);
14161                 if (rval != DDI_SUCCESS) {
14162                         mutex_exit(&mpt->m_mutex);
14163                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
14164                             "parent device for handle %d", page_address);
14165                         mdi_rtn = MDI_FAILURE;
14166                         goto virt_create_done;
14167                 }
14168 
14169                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14170                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
14171                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14172                     &dev_hdl, &pdev_sas_wwn, &pdev_info, &physport,
14173                     &phy_id, &pdev_hdl, &bay_num, &enclosure);
14174                 if (rval != DDI_SUCCESS) {
14175                         mutex_exit(&mpt->m_mutex);
14176                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
14177                             "device info for handle %d", page_address);
14178                         mdi_rtn = MDI_FAILURE;
14179                         goto virt_create_done;
14180                 }
14181 
14182                 mutex_exit(&mpt->m_mutex);
14183 
14184                 /*
14185                  * If this device direct attached to the controller
14186                  * set the attached-port to the base wwid
14187                  */
14188                 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14189                     != DEVINFO_DIRECT_ATTACHED) {
14190                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14191                             pdev_sas_wwn);
14192                 } else {
14193                         /*
14194                          * Update the iport's attached-port to guid
14195                          */
14196                         if (sas_wwn == 0) {
14197                                 (void) sprintf(wwn_str, "p%x", phy);
14198                         } else {
14199                                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14200                         }
14201                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
14202                             pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
14203                             DDI_PROP_SUCCESS) {
14204                                 mptsas_log(mpt, CE_WARN,
14205                                     "mptsas unable to create "
14206                                     "property for iport target-port"
14207                                     " %s (sas_wwn)",
14208                                     wwn_str);
14209                                 mdi_rtn = MDI_FAILURE;
14210                                 goto virt_create_done;
14211                         }
14212 
14213                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14214                             mpt->un.m_base_wwid);
14215                 }
14216 
14217                 if (mdi_prop_update_string(*pip,
14218                     SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
14219                     DDI_PROP_SUCCESS) {
14220                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14221                             "property for iport attached-port %s (sas_wwn)",
14222                             attached_wwn_str);
14223                         mdi_rtn = MDI_FAILURE;
14224                         goto virt_create_done;
14225                 }
14226 
14227 
14228                 if (inq->inq_dtype == 0) {
14229                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
14230                         /*
14231                          * set obp path for pathinfo
14232                          */
14233                         (void) snprintf(component, MAXPATHLEN,
14234                             "disk@%s", lun_addr);
14235 
14236                         if (mdi_pi_pathname_obp_set(*pip, component) !=
14237                             DDI_SUCCESS) {
14238                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
14239                                     "unable to set obp-path for object %s",
14240                                     component);
14241                                 mdi_rtn = MDI_FAILURE;
14242                                 goto virt_create_done;
14243                         }
14244                 }
14245 
14246                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14247                 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
14248                     MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
14249                         if ((ndi_prop_update_int(DDI_DEV_T_NONE, *lun_dip,
14250                             "pm-capable", 1)) !=
14251                             DDI_PROP_SUCCESS) {
14252                                 mptsas_log(mpt, CE_WARN, "mptsas driver"
14253                                     "failed to create pm-capable "
14254                                     "property, target %d", target);
14255                                 mdi_rtn = MDI_FAILURE;
14256                                 goto virt_create_done;
14257                         }
14258                 }
14259                 /*
14260                  * Create the phy-num property
14261                  */
14262                 if (mdi_prop_update_int(*pip, "phy-num",
14263                     ptgt->m_phynum) != DDI_SUCCESS) {
14264                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14265                             "create phy-num property for target %d lun %d",
14266                             target, lun);
14267                         mdi_rtn = MDI_FAILURE;
14268                         goto virt_create_done;
14269                 }
14270                 NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr));
14271                 mdi_rtn = mdi_pi_online(*pip, 0);
14272                 if (mdi_rtn == MDI_SUCCESS) {
14273                         mutex_enter(&mpt->m_mutex);
14274                         ptgt->m_led_status = 0;
14275                         (void) mptsas_flush_led_status(mpt, ptgt);
14276                         mutex_exit(&mpt->m_mutex);
14277                 }
14278                 if (mdi_rtn == MDI_NOT_SUPPORTED) {
14279                         mdi_rtn = MDI_FAILURE;
14280                 }
14281 virt_create_done:
14282                 if (*pip && mdi_rtn != MDI_SUCCESS) {
14283                         (void) mdi_pi_free(*pip, 0);
14284                         *pip = NULL;
14285                         *lun_dip = NULL;
14286                 }
14287         }
14288 
14289         scsi_hba_nodename_compatible_free(nodename, compatible);
14290         if (lun_addr != NULL) {
14291                 kmem_free(lun_addr, SCSI_MAXNAMELEN);
14292         }
14293         if (wwn_str != NULL) {
14294                 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
14295         }
14296         if (component != NULL) {
14297                 kmem_free(component, MAXPATHLEN);
14298         }
14299 
14300         return ((mdi_rtn == MDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
14301 }
14302 
14303 static int
14304 mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *inq,
14305     char *guid, dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
14306 {
14307         int                     target;
14308         int                     rval;
14309         int                     ndi_rtn = NDI_FAILURE;
14310         uint64_t                be_sas_wwn;
14311         char                    *nodename = NULL;
14312         char                    **compatible = NULL;
14313         int                     ncompatible = 0;
14314         int                     instance = 0;
14315         mptsas_t                *mpt = DIP2MPT(pdip);
14316         char                    *wwn_str = NULL;
14317         char                    *component = NULL;
14318         char                    *attached_wwn_str = NULL;
14319         uint8_t                 phy = 0xFF;
14320         uint64_t                sas_wwn;
14321         uint32_t                devinfo;
14322         uint16_t                dev_hdl;
14323         uint16_t                pdev_hdl;
14324         uint64_t                pdev_sas_wwn;
14325         uint64_t                dev_sas_wwn;
14326         uint32_t                pdev_info;
14327         uint8_t                 physport;
14328         uint8_t                 phy_id;
14329         uint32_t                page_address;
14330         uint16_t                bay_num, enclosure;
14331         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
14332         uint32_t                dev_info;
14333         int64_t                 lun64 = 0;
14334 
14335         mutex_enter(&mpt->m_mutex);
14336         target = ptgt->m_devhdl;
14337         sas_wwn = ptgt->m_addr.mta_wwn;
14338         devinfo = ptgt->m_deviceinfo;
14339         phy = ptgt->m_phynum;
14340         mutex_exit(&mpt->m_mutex);
14341 
14342         /*
14343          * generate compatible property with binding-set "mpt"
14344          */
14345         scsi_hba_nodename_compatible_get(inq, NULL, inq->inq_dtype, NULL,
14346             &nodename, &compatible, &ncompatible);
14347 
14348         /*
14349          * if nodename can't be determined then print a message and skip it
14350          */
14351         if (nodename == NULL) {
14352                 mptsas_log(mpt, CE_WARN, "mptsas found no compatible driver "
14353                     "for target %d lun %d", target, lun);
14354                 return (DDI_FAILURE);
14355         }
14356 
14357         ndi_rtn = ndi_devi_alloc(pdip, nodename,
14358             DEVI_SID_NODEID, lun_dip);
14359 
14360         /*
14361          * if lun alloc success, set props
14362          */
14363         if (ndi_rtn == NDI_SUCCESS) {
14364 
14365                 if (ndi_prop_update_int(DDI_DEV_T_NONE,
14366                     *lun_dip, LUN_PROP, lun) !=
14367                     DDI_PROP_SUCCESS) {
14368                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14369                             "property for target %d lun %d (LUN_PROP)",
14370                             target, lun);
14371                         ndi_rtn = NDI_FAILURE;
14372                         goto phys_create_done;
14373                 }
14374 
14375                 lun64 = (int64_t)lun;
14376                 if (ndi_prop_update_int64(DDI_DEV_T_NONE,
14377                     *lun_dip, LUN64_PROP, lun64) !=
14378                     DDI_PROP_SUCCESS) {
14379                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14380                             "property for target %d lun64 %d (LUN64_PROP)",
14381                             target, lun);
14382                         ndi_rtn = NDI_FAILURE;
14383                         goto phys_create_done;
14384                 }
14385                 if (ndi_prop_update_string_array(DDI_DEV_T_NONE,
14386                     *lun_dip, "compatible", compatible, ncompatible)
14387                     != DDI_PROP_SUCCESS) {
14388                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14389                             "property for target %d lun %d (COMPATIBLE)",
14390                             target, lun);
14391                         ndi_rtn = NDI_FAILURE;
14392                         goto phys_create_done;
14393                 }
14394 
14395                 /*
14396                  * We need the SAS WWN for non-multipath devices, so
14397                  * we'll use the same property as that multipathing
14398                  * devices need to present for MPAPI. If we don't have
14399                  * a WWN (e.g. parallel SCSI), don't create the prop.
14400                  */
14401                 wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
14402                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14403                 if (sas_wwn && ndi_prop_update_string(DDI_DEV_T_NONE,
14404                     *lun_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str)
14405                     != DDI_PROP_SUCCESS) {
14406                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
14407                             "create property for SAS target %d lun %d "
14408                             "(target-port)", target, lun);
14409                         ndi_rtn = NDI_FAILURE;
14410                         goto phys_create_done;
14411                 }
14412 
14413                 be_sas_wwn = BE_64(sas_wwn);
14414                 if (sas_wwn && ndi_prop_update_byte_array(
14415                     DDI_DEV_T_NONE, *lun_dip, "port-wwn",
14416                     (uchar_t *)&be_sas_wwn, 8) != DDI_PROP_SUCCESS) {
14417                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
14418                             "create property for SAS target %d lun %d "
14419                             "(port-wwn)", target, lun);
14420                         ndi_rtn = NDI_FAILURE;
14421                         goto phys_create_done;
14422                 } else if ((sas_wwn == 0) && (ndi_prop_update_int(
14423                     DDI_DEV_T_NONE, *lun_dip, "sata-phy", phy) !=
14424                     DDI_PROP_SUCCESS)) {
14425                         /*
14426                          * Direct attached SATA device without DeviceName
14427                          */
14428                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
14429                             "create property for SAS target %d lun %d "
14430                             "(sata-phy)", target, lun);
14431                         ndi_rtn = NDI_FAILURE;
14432                         goto phys_create_done;
14433                 }
14434 
14435                 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
14436                     *lun_dip, SAS_PROP) != DDI_PROP_SUCCESS) {
14437                         mptsas_log(mpt, CE_WARN, "mptsas unable to"
14438                             "create property for SAS target %d lun %d"
14439                             " (SAS_PROP)", target, lun);
14440                         ndi_rtn = NDI_FAILURE;
14441                         goto phys_create_done;
14442                 }
14443                 if (guid && (ndi_prop_update_string(DDI_DEV_T_NONE,
14444                     *lun_dip, NDI_GUID, guid) != DDI_SUCCESS)) {
14445                         mptsas_log(mpt, CE_WARN, "mptsas unable "
14446                             "to create guid property for target %d "
14447                             "lun %d", target, lun);
14448                         ndi_rtn = NDI_FAILURE;
14449                         goto phys_create_done;
14450                 }
14451 
14452                 /*
14453                  * The following code is to set properties for SM-HBA support,
14454                  * it doesn't apply to RAID volumes
14455                  */
14456                 if (ptgt->m_addr.mta_phymask == 0)
14457                         goto phys_raid_lun;
14458 
14459                 mutex_enter(&mpt->m_mutex);
14460 
14461                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14462                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14463                     (uint32_t)ptgt->m_devhdl;
14464                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14465                     &dev_hdl, &dev_sas_wwn, &dev_info,
14466                     &physport, &phy_id, &pdev_hdl,
14467                     &bay_num, &enclosure);
14468                 if (rval != DDI_SUCCESS) {
14469                         mutex_exit(&mpt->m_mutex);
14470                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
14471                             "parent device for handle %d.", page_address);
14472                         ndi_rtn = NDI_FAILURE;
14473                         goto phys_create_done;
14474                 }
14475 
14476                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14477                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
14478                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14479                     &dev_hdl, &pdev_sas_wwn, &pdev_info,
14480                     &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure);
14481                 if (rval != DDI_SUCCESS) {
14482                         mutex_exit(&mpt->m_mutex);
14483                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14484                             "device for handle %d.", page_address);
14485                         ndi_rtn = NDI_FAILURE;
14486                         goto phys_create_done;
14487                 }
14488 
14489                 mutex_exit(&mpt->m_mutex);
14490 
14491                 /*
14492                  * If this device direct attached to the controller
14493                  * set the attached-port to the base wwid
14494                  */
14495                 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14496                     != DEVINFO_DIRECT_ATTACHED) {
14497                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14498                             pdev_sas_wwn);
14499                 } else {
14500                         /*
14501                          * Update the iport's attached-port to guid
14502                          */
14503                         if (sas_wwn == 0) {
14504                                 (void) sprintf(wwn_str, "p%x", phy);
14505                         } else {
14506                                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14507                         }
14508                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
14509                             pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
14510                             DDI_PROP_SUCCESS) {
14511                                 mptsas_log(mpt, CE_WARN,
14512                                     "mptsas unable to create "
14513                                     "property for iport target-port"
14514                                     " %s (sas_wwn)",
14515                                     wwn_str);
14516                                 ndi_rtn = NDI_FAILURE;
14517                                 goto phys_create_done;
14518                         }
14519 
14520                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
14521                             mpt->un.m_base_wwid);
14522                 }
14523 
14524                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14525                     *lun_dip, SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
14526                     DDI_PROP_SUCCESS) {
14527                         mptsas_log(mpt, CE_WARN,
14528                             "mptsas unable to create "
14529                             "property for iport attached-port %s (sas_wwn)",
14530                             attached_wwn_str);
14531                         ndi_rtn = NDI_FAILURE;
14532                         goto phys_create_done;
14533                 }
14534 
14535                 if (IS_SATA_DEVICE(dev_info)) {
14536                         if (ndi_prop_update_string(DDI_DEV_T_NONE,
14537                             *lun_dip, MPTSAS_VARIANT, "sata") !=
14538                             DDI_PROP_SUCCESS) {
14539                                 mptsas_log(mpt, CE_WARN,
14540                                     "mptsas unable to create "
14541                                     "property for device variant ");
14542                                 ndi_rtn = NDI_FAILURE;
14543                                 goto phys_create_done;
14544                         }
14545                 }
14546 
14547                 if (IS_ATAPI_DEVICE(dev_info)) {
14548                         if (ndi_prop_update_string(DDI_DEV_T_NONE,
14549                             *lun_dip, MPTSAS_VARIANT, "atapi") !=
14550                             DDI_PROP_SUCCESS) {
14551                                 mptsas_log(mpt, CE_WARN,
14552                                     "mptsas unable to create "
14553                                     "property for device variant ");
14554                                 ndi_rtn = NDI_FAILURE;
14555                                 goto phys_create_done;
14556                         }
14557                 }
14558 
14559 phys_raid_lun:
14560                 /*
14561                  * if this is a SAS controller, and the target is a SATA
14562                  * drive, set the 'pm-capable' property for sd and if on
14563                  * an OPL platform, also check if this is an ATAPI
14564                  * device.
14565                  */
14566                 instance = ddi_get_instance(mpt->m_dip);
14567                 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
14568                     MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
14569                         NDBG2(("mptsas%d: creating pm-capable property, "
14570                             "target %d", instance, target));
14571 
14572                         if ((ndi_prop_update_int(DDI_DEV_T_NONE,
14573                             *lun_dip, "pm-capable", 1)) !=
14574                             DDI_PROP_SUCCESS) {
14575                                 mptsas_log(mpt, CE_WARN, "mptsas "
14576                                     "failed to create pm-capable "
14577                                     "property, target %d", target);
14578                                 ndi_rtn = NDI_FAILURE;
14579                                 goto phys_create_done;
14580                         }
14581 
14582                 }
14583 
14584                 if ((inq->inq_dtype == 0) || (inq->inq_dtype == 5)) {
14585                         /*
14586                          * add 'obp-path' properties for devinfo
14587                          */
14588                         bzero(wwn_str, sizeof (wwn_str));
14589                         (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
14590                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
14591                         if (guid) {
14592                                 (void) snprintf(component, MAXPATHLEN,
14593                                     "disk@w%s,%x", wwn_str, lun);
14594                         } else {
14595                                 (void) snprintf(component, MAXPATHLEN,
14596                                     "disk@p%x,%x", phy, lun);
14597                         }
14598                         if (ddi_pathname_obp_set(*lun_dip, component)
14599                             != DDI_SUCCESS) {
14600                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
14601                                     "unable to set obp-path for SAS "
14602                                     "object %s", component);
14603                                 ndi_rtn = NDI_FAILURE;
14604                                 goto phys_create_done;
14605                         }
14606                 }
14607                 /*
14608                  * Create the phy-num property for non-raid disk
14609                  */
14610                 if (ptgt->m_addr.mta_phymask != 0) {
14611                         if (ndi_prop_update_int(DDI_DEV_T_NONE,
14612                             *lun_dip, "phy-num", ptgt->m_phynum) !=
14613                             DDI_PROP_SUCCESS) {
14614                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
14615                                     "failed to create phy-num property for "
14616                                     "target %d", target);
14617                                 ndi_rtn = NDI_FAILURE;
14618                                 goto phys_create_done;
14619                         }
14620                 }
14621 phys_create_done:
14622                 /*
14623                  * If props were setup ok, online the lun
14624                  */
14625                 if (ndi_rtn == NDI_SUCCESS) {
14626                         /*
14627                          * Try to online the new node
14628                          */
14629                         ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
14630                 }
14631                 if (ndi_rtn == NDI_SUCCESS) {
14632                         mutex_enter(&mpt->m_mutex);
14633                         ptgt->m_led_status = 0;
14634                         (void) mptsas_flush_led_status(mpt, ptgt);
14635                         mutex_exit(&mpt->m_mutex);
14636                 }
14637 
14638                 /*
14639                  * If success set rtn flag, else unwire alloc'd lun
14640                  */
14641                 if (ndi_rtn != NDI_SUCCESS) {
14642                         NDBG12(("mptsas driver unable to online "
14643                             "target %d lun %d", target, lun));
14644                         ndi_prop_remove_all(*lun_dip);
14645                         (void) ndi_devi_free(*lun_dip);
14646                         *lun_dip = NULL;
14647                 }
14648         }
14649 
14650         scsi_hba_nodename_compatible_free(nodename, compatible);
14651 
14652         if (wwn_str != NULL) {
14653                 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
14654         }
14655         if (component != NULL) {
14656                 kmem_free(component, MAXPATHLEN);
14657         }
14658 
14659 
14660         return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
14661 }
14662 
14663 static int
14664 mptsas_probe_smp(dev_info_t *pdip, uint64_t wwn)
14665 {
14666         mptsas_t        *mpt = DIP2MPT(pdip);
14667         struct smp_device smp_sd;
14668 
14669         /* XXX An HBA driver should not be allocating an smp_device. */
14670         bzero(&smp_sd, sizeof (struct smp_device));
14671         smp_sd.smp_sd_address.smp_a_hba_tran = mpt->m_smptran;
14672         bcopy(&wwn, smp_sd.smp_sd_address.smp_a_wwn, SAS_WWN_BYTE_SIZE);
14673 
14674         if (smp_probe(&smp_sd) != DDI_PROBE_SUCCESS)
14675                 return (NDI_FAILURE);
14676         return (NDI_SUCCESS);
14677 }
14678 
14679 static int
14680 mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn, dev_info_t **smp_dip)
14681 {
14682         mptsas_t        *mpt = DIP2MPT(pdip);
14683         mptsas_smp_t    *psmp = NULL;
14684         int             rval;
14685         int             phymask;
14686 
14687         /*
14688          * Get the physical port associated to the iport
14689          * PHYMASK TODO
14690          */
14691         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
14692             "phymask", 0);
14693         /*
14694          * Find the smp node in hash table with specified sas address and
14695          * physical port
14696          */
14697         psmp = mptsas_wwid_to_psmp(mpt, phymask, sas_wwn);
14698         if (psmp == NULL) {
14699                 return (DDI_FAILURE);
14700         }
14701 
14702         rval = mptsas_online_smp(pdip, psmp, smp_dip);
14703 
14704         return (rval);
14705 }
14706 
14707 static int
14708 mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
14709     dev_info_t **smp_dip)
14710 {
14711         char            wwn_str[MPTSAS_WWN_STRLEN];
14712         char            attached_wwn_str[MPTSAS_WWN_STRLEN];
14713         int             ndi_rtn = NDI_FAILURE;
14714         int             rval = 0;
14715         mptsas_smp_t    dev_info;
14716         uint32_t        page_address;
14717         mptsas_t        *mpt = DIP2MPT(pdip);
14718         uint16_t        dev_hdl;
14719         uint64_t        sas_wwn;
14720         uint64_t        smp_sas_wwn;
14721         uint8_t         physport;
14722         uint8_t         phy_id;
14723         uint16_t        pdev_hdl;
14724         uint8_t         numphys = 0;
14725         uint16_t        i = 0;
14726         char            phymask[MPTSAS_MAX_PHYS];
14727         char            *iport = NULL;
14728         mptsas_phymask_t        phy_mask = 0;
14729         uint16_t        attached_devhdl;
14730         uint16_t        bay_num, enclosure;
14731 
14732         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
14733 
14734         /*
14735          * Probe smp device, prevent the node of removed device from being
14736          * configured succesfully
14737          */
14738         if (mptsas_probe_smp(pdip, smp_node->m_addr.mta_wwn) != NDI_SUCCESS) {
14739                 return (DDI_FAILURE);
14740         }
14741 
14742         if ((*smp_dip = mptsas_find_smp_child(pdip, wwn_str)) != NULL) {
14743                 return (DDI_SUCCESS);
14744         }
14745 
14746         ndi_rtn = ndi_devi_alloc(pdip, "smp", DEVI_SID_NODEID, smp_dip);
14747 
14748         /*
14749          * if lun alloc success, set props
14750          */
14751         if (ndi_rtn == NDI_SUCCESS) {
14752                 /*
14753                  * Set the flavor of the child to be SMP flavored
14754                  */
14755                 ndi_flavor_set(*smp_dip, SCSA_FLAVOR_SMP);
14756 
14757                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14758                     *smp_dip, SMP_WWN, wwn_str) !=
14759                     DDI_PROP_SUCCESS) {
14760                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14761                             "property for smp device %s (sas_wwn)",
14762                             wwn_str);
14763                         ndi_rtn = NDI_FAILURE;
14764                         goto smp_create_done;
14765                 }
14766                 (void) sprintf(wwn_str, "w%"PRIx64, smp_node->m_addr.mta_wwn);
14767                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14768                     *smp_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str) !=
14769                     DDI_PROP_SUCCESS) {
14770                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14771                             "property for iport target-port %s (sas_wwn)",
14772                             wwn_str);
14773                         ndi_rtn = NDI_FAILURE;
14774                         goto smp_create_done;
14775                 }
14776 
14777                 mutex_enter(&mpt->m_mutex);
14778 
14779                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
14780                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | smp_node->m_devhdl;
14781                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
14782                     &dev_info);
14783                 if (rval != DDI_SUCCESS) {
14784                         mutex_exit(&mpt->m_mutex);
14785                         mptsas_log(mpt, CE_WARN,
14786                             "mptsas unable to get expander "
14787                             "parent device info for %x", page_address);
14788                         ndi_rtn = NDI_FAILURE;
14789                         goto smp_create_done;
14790                 }
14791 
14792                 smp_node->m_pdevhdl = dev_info.m_pdevhdl;
14793                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14794                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14795                     (uint32_t)dev_info.m_pdevhdl;
14796                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14797                     &dev_hdl, &sas_wwn, &smp_node->m_pdevinfo,
14798                     &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure);
14799                 if (rval != DDI_SUCCESS) {
14800                         mutex_exit(&mpt->m_mutex);
14801                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
14802                             "device info for %x", page_address);
14803                         ndi_rtn = NDI_FAILURE;
14804                         goto smp_create_done;
14805                 }
14806 
14807                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14808                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14809                     (uint32_t)dev_info.m_devhdl;
14810                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14811                     &dev_hdl, &smp_sas_wwn, &smp_node->m_deviceinfo,
14812                     &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure);
14813                 if (rval != DDI_SUCCESS) {
14814                         mutex_exit(&mpt->m_mutex);
14815                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
14816                             "device info for %x", page_address);
14817                         ndi_rtn = NDI_FAILURE;
14818                         goto smp_create_done;
14819                 }
14820                 mutex_exit(&mpt->m_mutex);
14821 
14822                 /*
14823                  * If this smp direct attached to the controller
14824                  * set the attached-port to the base wwid
14825                  */
14826                 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14827                     != DEVINFO_DIRECT_ATTACHED) {
14828                         (void) sprintf(attached_wwn_str, "w%016"PRIx64,
14829                             sas_wwn);
14830                 } else {
14831                         (void) sprintf(attached_wwn_str, "w%016"PRIx64,
14832                             mpt->un.m_base_wwid);
14833                 }
14834 
14835                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14836                     *smp_dip, SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwn_str) !=
14837                     DDI_PROP_SUCCESS) {
14838                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14839                             "property for smp attached-port %s (sas_wwn)",
14840                             attached_wwn_str);
14841                         ndi_rtn = NDI_FAILURE;
14842                         goto smp_create_done;
14843                 }
14844 
14845                 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
14846                     *smp_dip, SMP_PROP) != DDI_PROP_SUCCESS) {
14847                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
14848                             "create property for SMP %s (SMP_PROP) ",
14849                             wwn_str);
14850                         ndi_rtn = NDI_FAILURE;
14851                         goto smp_create_done;
14852                 }
14853 
14854                 /*
14855                  * check the smp to see whether it direct
14856                  * attached to the controller
14857                  */
14858                 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
14859                     != DEVINFO_DIRECT_ATTACHED) {
14860                         goto smp_create_done;
14861                 }
14862                 numphys = ddi_prop_get_int(DDI_DEV_T_ANY, pdip,
14863                     DDI_PROP_DONTPASS, MPTSAS_NUM_PHYS, -1);
14864                 if (numphys > 0) {
14865                         goto smp_create_done;
14866                 }
14867                 /*
14868                  * this iport is an old iport, we need to
14869                  * reconfig the props for it.
14870                  */
14871                 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
14872                     MPTSAS_VIRTUAL_PORT, 0) !=
14873                     DDI_PROP_SUCCESS) {
14874                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
14875                             MPTSAS_VIRTUAL_PORT);
14876                         mptsas_log(mpt, CE_WARN, "mptsas virtual port "
14877                             "prop update failed");
14878                         goto smp_create_done;
14879                 }
14880 
14881                 mutex_enter(&mpt->m_mutex);
14882                 numphys = 0;
14883                 iport = ddi_get_name_addr(pdip);
14884                 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
14885                         bzero(phymask, sizeof (phymask));
14886                         (void) sprintf(phymask,
14887                             "%x", mpt->m_phy_info[i].phy_mask);
14888                         if (strcmp(phymask, iport) == 0) {
14889                                 phy_mask = mpt->m_phy_info[i].phy_mask;
14890                                 break;
14891                         }
14892                 }
14893 
14894                 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
14895                         if ((phy_mask >> i) & 0x01) {
14896                                 numphys++;
14897                         }
14898                 }
14899                 /*
14900                  * Update PHY info for smhba
14901                  */
14902                 if (mptsas_smhba_phy_init(mpt)) {
14903                         mutex_exit(&mpt->m_mutex);
14904                         mptsas_log(mpt, CE_WARN, "mptsas phy update "
14905                             "failed");
14906                         goto smp_create_done;
14907                 }
14908                 mutex_exit(&mpt->m_mutex);
14909 
14910                 mptsas_smhba_set_all_phy_props(mpt, pdip, numphys, phy_mask,
14911                     &attached_devhdl);
14912 
14913                 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
14914                     MPTSAS_NUM_PHYS, numphys) !=
14915                     DDI_PROP_SUCCESS) {
14916                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
14917                             MPTSAS_NUM_PHYS);
14918                         mptsas_log(mpt, CE_WARN, "mptsas update "
14919                             "num phys props failed");
14920                         goto smp_create_done;
14921                 }
14922                 /*
14923                  * Add parent's props for SMHBA support
14924                  */
14925                 if (ddi_prop_update_string(DDI_DEV_T_NONE, pdip,
14926                     SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
14927                     DDI_PROP_SUCCESS) {
14928                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
14929                             SCSI_ADDR_PROP_ATTACHED_PORT);
14930                         mptsas_log(mpt, CE_WARN, "mptsas update iport"
14931                             "attached-port failed");
14932                         goto smp_create_done;
14933                 }
14934 
14935 smp_create_done:
14936                 /*
14937                  * If props were setup ok, online the lun
14938                  */
14939                 if (ndi_rtn == NDI_SUCCESS) {
14940                         /*
14941                          * Try to online the new node
14942                          */
14943                         ndi_rtn = ndi_devi_online(*smp_dip, NDI_ONLINE_ATTACH);
14944                 }
14945 
14946                 /*
14947                  * If success set rtn flag, else unwire alloc'd lun
14948                  */
14949                 if (ndi_rtn != NDI_SUCCESS) {
14950                         NDBG12(("mptsas unable to online "
14951                             "SMP target %s", wwn_str));
14952                         ndi_prop_remove_all(*smp_dip);
14953                         (void) ndi_devi_free(*smp_dip);
14954                 }
14955         }
14956 
14957         return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
14958 }
14959 
14960 /* smp transport routine */
14961 static int mptsas_smp_start(struct smp_pkt *smp_pkt)
14962 {
14963         uint64_t                        wwn;
14964         Mpi2SmpPassthroughRequest_t     req;
14965         Mpi2SmpPassthroughReply_t       rep;
14966         uint32_t                        direction = 0;
14967         mptsas_t                        *mpt;
14968         int                             ret;
14969         uint64_t                        tmp64;
14970 
14971         mpt = (mptsas_t *)smp_pkt->smp_pkt_address->
14972             smp_a_hba_tran->smp_tran_hba_private;
14973 
14974         bcopy(smp_pkt->smp_pkt_address->smp_a_wwn, &wwn, SAS_WWN_BYTE_SIZE);
14975         /*
14976          * Need to compose a SMP request message
14977          * and call mptsas_do_passthru() function
14978          */
14979         bzero(&req, sizeof (req));
14980         bzero(&rep, sizeof (rep));
14981         req.PassthroughFlags = 0;
14982         req.PhysicalPort = 0xff;
14983         req.ChainOffset = 0;
14984         req.Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
14985 
14986         if ((smp_pkt->smp_pkt_reqsize & 0xffff0000ul) != 0) {
14987                 smp_pkt->smp_pkt_reason = ERANGE;
14988                 return (DDI_FAILURE);
14989         }
14990         req.RequestDataLength = LE_16((uint16_t)(smp_pkt->smp_pkt_reqsize - 4));
14991 
14992         req.MsgFlags = 0;
14993         tmp64 = LE_64(wwn);
14994         bcopy(&tmp64, &req.SASAddress, SAS_WWN_BYTE_SIZE);
14995         if (smp_pkt->smp_pkt_rspsize > 0) {
14996                 direction |= MPTSAS_PASS_THRU_DIRECTION_READ;
14997         }
14998         if (smp_pkt->smp_pkt_reqsize > 0) {
14999                 direction |= MPTSAS_PASS_THRU_DIRECTION_WRITE;
15000         }
15001 
15002         mutex_enter(&mpt->m_mutex);
15003         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep,
15004             (uint8_t *)smp_pkt->smp_pkt_rsp,
15005             offsetof(Mpi2SmpPassthroughRequest_t, SGL), sizeof (rep),
15006             smp_pkt->smp_pkt_rspsize - 4, direction,
15007             (uint8_t *)smp_pkt->smp_pkt_req, smp_pkt->smp_pkt_reqsize - 4,
15008             smp_pkt->smp_pkt_timeout, FKIOCTL);
15009         mutex_exit(&mpt->m_mutex);
15010         if (ret != 0) {
15011                 cmn_err(CE_WARN, "smp_start do passthru error %d", ret);
15012                 smp_pkt->smp_pkt_reason = (uchar_t)(ret);
15013                 return (DDI_FAILURE);
15014         }
15015         /* do passthrough success, check the smp status */
15016         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
15017                 switch (LE_16(rep.IOCStatus)) {
15018                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
15019                         smp_pkt->smp_pkt_reason = ENODEV;
15020                         break;
15021                 case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
15022                         smp_pkt->smp_pkt_reason = EOVERFLOW;
15023                         break;
15024                 case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
15025                         smp_pkt->smp_pkt_reason = EIO;
15026                         break;
15027                 default:
15028                         mptsas_log(mpt, CE_NOTE, "smp_start: get unknown ioc"
15029                             "status:%x", LE_16(rep.IOCStatus));
15030                         smp_pkt->smp_pkt_reason = EIO;
15031                         break;
15032                 }
15033                 return (DDI_FAILURE);
15034         }
15035         if (rep.SASStatus != MPI2_SASSTATUS_SUCCESS) {
15036                 mptsas_log(mpt, CE_NOTE, "smp_start: get error SAS status:%x",
15037                     rep.SASStatus);
15038                 smp_pkt->smp_pkt_reason = EIO;
15039                 return (DDI_FAILURE);
15040         }
15041 
15042         return (DDI_SUCCESS);
15043 }
15044 
15045 /*
15046  * If we didn't get a match, we need to get sas page0 for each device, and
15047  * untill we get a match. If failed, return NULL
15048  */
15049 static mptsas_target_t *
15050 mptsas_phy_to_tgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint8_t phy)
15051 {
15052         int             i, j = 0;
15053         int             rval = 0;
15054         uint16_t        cur_handle;
15055         uint32_t        page_address;
15056         mptsas_target_t *ptgt = NULL;
15057 
15058         /*
15059          * PHY named device must be direct attached and attaches to
15060          * narrow port, if the iport is not parent of the device which
15061          * we are looking for.
15062          */
15063         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15064                 if ((1 << i) & phymask)
15065                         j++;
15066         }
15067 
15068         if (j > 1)
15069                 return (NULL);
15070 
15071         /*
15072          * Must be a narrow port and single device attached to the narrow port
15073          * So the physical port num of device  which is equal to the iport's
15074          * port num is the device what we are looking for.
15075          */
15076 
15077         if (mpt->m_phy_info[phy].phy_mask != phymask)
15078                 return (NULL);
15079 
15080         mutex_enter(&mpt->m_mutex);
15081 
15082         ptgt = refhash_linear_search(mpt->m_targets, mptsas_target_eval_nowwn,
15083             &phy);
15084         if (ptgt != NULL) {
15085                 mutex_exit(&mpt->m_mutex);
15086                 return (ptgt);
15087         }
15088 
15089         if (mpt->m_done_traverse_dev) {
15090                 mutex_exit(&mpt->m_mutex);
15091                 return (NULL);
15092         }
15093 
15094         /* If didn't get a match, come here */
15095         cur_handle = mpt->m_dev_handle;
15096         for (; ; ) {
15097                 ptgt = NULL;
15098                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15099                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15100                 rval = mptsas_get_target_device_info(mpt, page_address,
15101                     &cur_handle, &ptgt);
15102                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15103                     (rval == DEV_INFO_FAIL_ALLOC)) {
15104                         break;
15105                 }
15106                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15107                     (rval == DEV_INFO_PHYS_DISK)) {
15108                         continue;
15109                 }
15110                 mpt->m_dev_handle = cur_handle;
15111 
15112                 if ((ptgt->m_addr.mta_wwn == 0) && (ptgt->m_phynum == phy)) {
15113                         break;
15114                 }
15115         }
15116 
15117         mutex_exit(&mpt->m_mutex);
15118         return (ptgt);
15119 }
15120 
15121 /*
15122  * The ptgt->m_addr.mta_wwn contains the wwid for each disk.
15123  * For Raid volumes, we need to check m_raidvol[x].m_raidwwid
15124  * If we didn't get a match, we need to get sas page0 for each device, and
15125  * untill we get a match
15126  * If failed, return NULL
15127  */
15128 static mptsas_target_t *
15129 mptsas_wwid_to_ptgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
15130 {
15131         int             rval = 0;
15132         uint16_t        cur_handle;
15133         uint32_t        page_address;
15134         mptsas_target_t *tmp_tgt = NULL;
15135         mptsas_target_addr_t addr;
15136 
15137         addr.mta_wwn = wwid;
15138         addr.mta_phymask = phymask;
15139         mutex_enter(&mpt->m_mutex);
15140         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
15141         if (tmp_tgt != NULL) {
15142                 mutex_exit(&mpt->m_mutex);
15143                 return (tmp_tgt);
15144         }
15145 
15146         if (phymask == 0) {
15147                 /*
15148                  * It's IR volume
15149                  */
15150                 rval = mptsas_get_raid_info(mpt);
15151                 if (rval) {
15152                         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
15153                 }
15154                 mutex_exit(&mpt->m_mutex);
15155                 return (tmp_tgt);
15156         }
15157 
15158         if (mpt->m_done_traverse_dev) {
15159                 mutex_exit(&mpt->m_mutex);
15160                 return (NULL);
15161         }
15162 
15163         /* If didn't get a match, come here */
15164         cur_handle = mpt->m_dev_handle;
15165         for (;;) {
15166                 tmp_tgt = NULL;
15167                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15168                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | cur_handle;
15169                 rval = mptsas_get_target_device_info(mpt, page_address,
15170                     &cur_handle, &tmp_tgt);
15171                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15172                     (rval == DEV_INFO_FAIL_ALLOC)) {
15173                         tmp_tgt = NULL;
15174                         break;
15175                 }
15176                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15177                     (rval == DEV_INFO_PHYS_DISK)) {
15178                         continue;
15179                 }
15180                 mpt->m_dev_handle = cur_handle;
15181                 if ((tmp_tgt->m_addr.mta_wwn) &&
15182                     (tmp_tgt->m_addr.mta_wwn == wwid) &&
15183                     (tmp_tgt->m_addr.mta_phymask == phymask)) {
15184                         break;
15185                 }
15186         }
15187 
15188         mutex_exit(&mpt->m_mutex);
15189         return (tmp_tgt);
15190 }
15191 
15192 static mptsas_smp_t *
15193 mptsas_wwid_to_psmp(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
15194 {
15195         int             rval = 0;
15196         uint16_t        cur_handle;
15197         uint32_t        page_address;
15198         mptsas_smp_t    smp_node, *psmp = NULL;
15199         mptsas_target_addr_t addr;
15200 
15201         addr.mta_wwn = wwid;
15202         addr.mta_phymask = phymask;
15203         mutex_enter(&mpt->m_mutex);
15204         psmp = refhash_lookup(mpt->m_smp_targets, &addr);
15205         if (psmp != NULL) {
15206                 mutex_exit(&mpt->m_mutex);
15207                 return (psmp);
15208         }
15209 
15210         if (mpt->m_done_traverse_smp) {
15211                 mutex_exit(&mpt->m_mutex);
15212                 return (NULL);
15213         }
15214 
15215         /* If didn't get a match, come here */
15216         cur_handle = mpt->m_smp_devhdl;
15217         for (;;) {
15218                 psmp = NULL;
15219                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
15220                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15221                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
15222                     &smp_node);
15223                 if (rval != DDI_SUCCESS) {
15224                         break;
15225                 }
15226                 mpt->m_smp_devhdl = cur_handle = smp_node.m_devhdl;
15227                 psmp = mptsas_smp_alloc(mpt, &smp_node);
15228                 ASSERT(psmp);
15229                 if ((psmp->m_addr.mta_wwn) && (psmp->m_addr.mta_wwn == wwid) &&
15230                     (psmp->m_addr.mta_phymask == phymask)) {
15231                         break;
15232                 }
15233         }
15234 
15235         mutex_exit(&mpt->m_mutex);
15236         return (psmp);
15237 }
15238 
15239 mptsas_target_t *
15240 mptsas_tgt_alloc(mptsas_t *mpt, uint16_t devhdl, uint64_t wwid,
15241     uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum)
15242 {
15243         mptsas_target_t *tmp_tgt = NULL;
15244         mptsas_target_addr_t addr;
15245 
15246         addr.mta_wwn = wwid;
15247         addr.mta_phymask = phymask;
15248         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
15249         if (tmp_tgt != NULL) {
15250                 NDBG20(("Hash item already exist"));
15251                 tmp_tgt->m_deviceinfo = devinfo;
15252                 tmp_tgt->m_devhdl = devhdl;  /* XXX - duplicate? */
15253                 return (tmp_tgt);
15254         }
15255         tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target), KM_SLEEP);
15256         if (tmp_tgt == NULL) {
15257                 cmn_err(CE_WARN, "Fatal, allocated tgt failed");
15258                 return (NULL);
15259         }
15260         tmp_tgt->m_devhdl = devhdl;
15261         tmp_tgt->m_addr.mta_wwn = wwid;
15262         tmp_tgt->m_deviceinfo = devinfo;
15263         tmp_tgt->m_addr.mta_phymask = phymask;
15264         tmp_tgt->m_phynum = phynum;
15265         /* Initialized the tgt structure */
15266         tmp_tgt->m_qfull_retries = QFULL_RETRIES;
15267         tmp_tgt->m_qfull_retry_interval =
15268             drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
15269         tmp_tgt->m_t_throttle = MAX_THROTTLE;
15270 
15271         refhash_insert(mpt->m_targets, tmp_tgt);
15272 
15273         return (tmp_tgt);
15274 }
15275 
15276 static mptsas_smp_t *
15277 mptsas_smp_alloc(mptsas_t *mpt, mptsas_smp_t *data)
15278 {
15279         mptsas_target_addr_t addr;
15280         mptsas_smp_t *ret_data;
15281 
15282         addr.mta_wwn = data->m_addr.mta_wwn;
15283         addr.mta_phymask = data->m_addr.mta_phymask;
15284         ret_data = refhash_lookup(mpt->m_smp_targets, &addr);
15285         if (ret_data != NULL) {
15286                 bcopy(data, ret_data, sizeof (mptsas_smp_t)); /* XXX - dupl */
15287                 return (ret_data);
15288         }
15289 
15290         ret_data = kmem_alloc(sizeof (mptsas_smp_t), KM_SLEEP);
15291         bcopy(data, ret_data, sizeof (mptsas_smp_t));
15292         refhash_insert(mpt->m_smp_targets, ret_data);
15293         return (ret_data);
15294 }
15295 
15296 /*
15297  * Functions for SGPIO LED support
15298  */
15299 static dev_info_t *
15300 mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask)
15301 {
15302         dev_info_t      *dip;
15303         int             prop;
15304         dip = e_ddi_hold_devi_by_dev(dev, 0);
15305         if (dip == NULL)
15306                 return (dip);
15307         prop = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
15308             "phymask", 0);
15309         *phymask = (mptsas_phymask_t)prop;
15310         ddi_release_devi(dip);
15311         return (dip);
15312 }
15313 static mptsas_target_t *
15314 mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
15315 {
15316         uint8_t                 phynum;
15317         uint64_t                wwn;
15318         int                     lun;
15319         mptsas_target_t         *ptgt = NULL;
15320 
15321         if (mptsas_parse_address(addr, &wwn, &phynum, &lun) != DDI_SUCCESS) {
15322                 return (NULL);
15323         }
15324         if (addr[0] == 'w') {
15325                 ptgt = mptsas_wwid_to_ptgt(mpt, (int)phymask, wwn);
15326         } else {
15327                 ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum);
15328         }
15329         return (ptgt);
15330 }
15331 
15332 static int
15333 mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt)
15334 {
15335         uint32_t slotstatus = 0;
15336 
15337         /* Build an MPI2 Slot Status based on our view of the world */
15338         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_IDENT - 1)))
15339                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST;
15340         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_FAIL - 1)))
15341                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT;
15342         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1)))
15343                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
15344 
15345         /* Write it to the controller */
15346         NDBG14(("mptsas_ioctl: set LED status %x for slot %x",
15347             slotstatus, ptgt->m_slot_num));
15348         return (mptsas_send_sep(mpt, ptgt, &slotstatus,
15349             MPI2_SEP_REQ_ACTION_WRITE_STATUS));
15350 }
15351 
15352 /*
15353  *  send sep request, use enclosure/slot addressing
15354  */
15355 static int
15356 mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
15357     uint32_t *status, uint8_t act)
15358 {
15359         Mpi2SepRequest_t        req;
15360         Mpi2SepReply_t          rep;
15361         int                     ret;
15362 
15363         ASSERT(mutex_owned(&mpt->m_mutex));
15364 
15365         /*
15366          * We only support SEP control of directly-attached targets, in which
15367          * case the "SEP" we're talking to is a virtual one contained within
15368          * the HBA itself.  This is necessary because DA targets typically have
15369          * no other mechanism for LED control.  Targets for which a separate
15370          * enclosure service processor exists should be controlled via ses(7d)
15371          * or sgen(7d).  Furthermore, since such requests can time out, they
15372          * should be made in user context rather than in response to
15373          * asynchronous fabric changes.
15374          *
15375          * In addition, we do not support this operation for RAID volumes,
15376          * since there is no slot associated with them.
15377          */
15378         if (!(ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED) ||
15379             ptgt->m_addr.mta_phymask == 0) {
15380                 return (ENOTTY);
15381         }
15382 
15383         bzero(&req, sizeof (req));
15384         bzero(&rep, sizeof (rep));
15385 
15386         req.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
15387         req.Action = act;
15388         req.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
15389         req.EnclosureHandle = LE_16(ptgt->m_enclosure);
15390         req.Slot = LE_16(ptgt->m_slot_num);
15391         if (act == MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
15392                 req.SlotStatus = LE_32(*status);
15393         }
15394         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
15395             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
15396         if (ret != 0) {
15397                 mptsas_log(mpt, CE_NOTE, "mptsas_send_sep: passthru SEP "
15398                     "Processor Request message error %d", ret);
15399                 return (ret);
15400         }
15401         /* do passthrough success, check the ioc status */
15402         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
15403                 mptsas_log(mpt, CE_NOTE, "send_sep act %x: ioc "
15404                     "status:%x loginfo %x", act, LE_16(rep.IOCStatus),
15405                     LE_32(rep.IOCLogInfo));
15406                 switch (LE_16(rep.IOCStatus) & MPI2_IOCSTATUS_MASK) {
15407                 case MPI2_IOCSTATUS_INVALID_FUNCTION:
15408                 case MPI2_IOCSTATUS_INVALID_VPID:
15409                 case MPI2_IOCSTATUS_INVALID_FIELD:
15410                 case MPI2_IOCSTATUS_INVALID_STATE:
15411                 case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
15412                 case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
15413                 case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
15414                 case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
15415                 case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
15416                 case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
15417                         return (EINVAL);
15418                 case MPI2_IOCSTATUS_BUSY:
15419                         return (EBUSY);
15420                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
15421                         return (EAGAIN);
15422                 case MPI2_IOCSTATUS_INVALID_SGL:
15423                 case MPI2_IOCSTATUS_INTERNAL_ERROR:
15424                 case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
15425                 default:
15426                         return (EIO);
15427                 }
15428         }
15429         if (act != MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
15430                 *status = LE_32(rep.SlotStatus);
15431         }
15432 
15433         return (0);
15434 }
15435 
15436 int
15437 mptsas_dma_addr_create(mptsas_t *mpt, ddi_dma_attr_t dma_attr,
15438     ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp, caddr_t *dma_memp,
15439     uint32_t alloc_size, ddi_dma_cookie_t *cookiep)
15440 {
15441         ddi_dma_cookie_t        new_cookie;
15442         size_t                  alloc_len;
15443         uint_t                  ncookie;
15444 
15445         if (cookiep == NULL)
15446                 cookiep = &new_cookie;
15447 
15448         if (ddi_dma_alloc_handle(mpt->m_dip, &dma_attr, DDI_DMA_SLEEP,
15449             NULL, dma_hdp) != DDI_SUCCESS) {
15450                 return (FALSE);
15451         }
15452 
15453         if (ddi_dma_mem_alloc(*dma_hdp, alloc_size, &mpt->m_dev_acc_attr,
15454             DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, dma_memp, &alloc_len,
15455             acc_hdp) != DDI_SUCCESS) {
15456                 ddi_dma_free_handle(dma_hdp);
15457                 return (FALSE);
15458         }
15459 
15460         if (ddi_dma_addr_bind_handle(*dma_hdp, NULL, *dma_memp, alloc_len,
15461             (DDI_DMA_RDWR | DDI_DMA_CONSISTENT), DDI_DMA_SLEEP, NULL,
15462             cookiep, &ncookie) != DDI_DMA_MAPPED) {
15463                 (void) ddi_dma_mem_free(acc_hdp);
15464                 ddi_dma_free_handle(dma_hdp);
15465                 return (FALSE);
15466         }
15467 
15468         return (TRUE);
15469 }
15470 
15471 void
15472 mptsas_dma_addr_destroy(ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp)
15473 {
15474         if (*dma_hdp == NULL)
15475                 return;
15476 
15477         (void) ddi_dma_unbind_handle(*dma_hdp);
15478         (void) ddi_dma_mem_free(acc_hdp);
15479         ddi_dma_free_handle(dma_hdp);
15480 }