Print this page
4682 panic in mptsas refhash
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Approved by: Albert Lee <trisk@nexenta.com>
4500 mptsas_hash_traverse() is unsafe, leads to missing devices
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Approved by: Albert Lee <trisk@nexenta.com>


   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) 2013, Joyent, Inc. All rights reserved.
  26  * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
  27  */
  28 
  29 /*
  30  * Copyright (c) 2000 to 2010, LSI Corporation.
  31  * All rights reserved.
  32  *
  33  * Redistribution and use in source and binary forms of all code within
  34  * this file that is exclusively owned by LSI, with or without
  35  * modification, is permitted provided that, in addition to the CDDL 1.0
  36  * License requirements, the following conditions are met:
  37  *
  38  *    Neither the name of the author nor the names of its contributors may be
  39  *    used to endorse or promote products derived from this software without
  40  *    specific prior written permission.
  41  *
  42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  43  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  45  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE


  80 
  81 #pragma pack(1)
  82 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
  83 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
  84 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
  85 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
  86 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
  87 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
  88 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
  89 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
  90 #pragma pack()
  91 
  92 /*
  93  * private header files.
  94  *
  95  */
  96 #include <sys/scsi/impl/scsi_reset_notify.h>
  97 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
  98 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
  99 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>

 100 #include <sys/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 /*


 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, int phymask,
 340     uint8_t phy);
 341 static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt, int phymask,
 342     uint64_t wwid);
 343 static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt, int phymask,
 344     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  */


 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 static void mptsas_hash_init(mptsas_hash_table_t *hashtab);
 411 static void mptsas_hash_uninit(mptsas_hash_table_t *hashtab, size_t datalen);
 412 static void mptsas_hash_add(mptsas_hash_table_t *hashtab, void *data);
 413 static void * mptsas_hash_rem(mptsas_hash_table_t *hashtab, uint64_t key1,
 414     mptsas_phymask_t key2);
 415 static void * mptsas_hash_search(mptsas_hash_table_t *hashtab, uint64_t key1,
 416     mptsas_phymask_t key2);
 417 static void * mptsas_hash_traverse(mptsas_hash_table_t *hashtab, int pos);
 418 
 419 mptsas_target_t *mptsas_tgt_alloc(mptsas_hash_table_t *, uint16_t, uint64_t,
 420     uint32_t, mptsas_phymask_t, uint8_t);
 421 static mptsas_smp_t *mptsas_smp_alloc(mptsas_hash_table_t *hashtab,
 422     mptsas_smp_t *data);
 423 static void mptsas_smp_free(mptsas_hash_table_t *hashtab, uint64_t wwid,
 424     mptsas_phymask_t phymask);
 425 static void mptsas_tgt_free(mptsas_hash_table_t *, uint64_t, mptsas_phymask_t);
 426 static void * mptsas_search_by_devhdl(mptsas_hash_table_t *, uint16_t);
 427 static int mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 428     dev_info_t **smp_dip);
 429 
 430 /*
 431  * Power management functions
 432  */
 433 static int mptsas_get_pci_cap(mptsas_t *mpt);
 434 static int mptsas_init_pm(mptsas_t *mpt);
 435 
 436 /*
 437  * MPT MSI tunable:
 438  *
 439  * By default MSI is enabled on all supported platforms.
 440  */
 441 boolean_t mptsas_enable_msi = B_TRUE;
 442 boolean_t mptsas_physical_bind_failed_page_83 = B_FALSE;
 443 
 444 static int mptsas_register_intrs(mptsas_t *);
 445 static void mptsas_unregister_intrs(mptsas_t *);
 446 static int mptsas_add_intrs(mptsas_t *, int);


 678                 mutex_destroy(&mptsas_global_mutex);
 679                 rw_destroy(&mptsas_global_rwlock);
 680                 mutex_destroy(&mptsas_log_mutex);
 681         }
 682         return (status);
 683 }
 684 
 685 /*
 686  * The loadable-module _info(9E) entry point
 687  */
 688 int
 689 _info(struct modinfo *modinfop)
 690 {
 691         /* CONSTCOND */
 692         ASSERT(NO_COMPETING_THREADS);
 693         NDBG0(("mptsas _info"));
 694 
 695         return (mod_info(&modlinkage, modinfop));
 696 }
 697 





 698 



 699 static int























































































 700 mptsas_iport_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 701 {
 702         dev_info_t              *pdip;
 703         mptsas_t                *mpt;
 704         scsi_hba_tran_t         *hba_tran;
 705         char                    *iport = NULL;
 706         char                    phymask[MPTSAS_MAX_PHYS];
 707         mptsas_phymask_t        phy_mask = 0;
 708         int                     dynamic_port = 0;
 709         uint32_t                page_address;
 710         char                    initiator_wwnstr[MPTSAS_WWN_STRLEN];
 711         int                     rval = DDI_FAILURE;
 712         int                     i = 0;
 713         uint8_t                 numphys = 0;
 714         uint8_t                 phy_id;
 715         uint8_t                 phy_port = 0;
 716         uint16_t                attached_devhdl = 0;
 717         uint32_t                dev_info;
 718         uint64_t                attached_sas_wwn;
 719         uint16_t                dev_hdl;


1387 
1388                 if (mptsas_timeout_id && (mptsas_head == NULL)) {
1389                         timeout_id_t tid = mptsas_timeout_id;
1390                         mptsas_timeouts_enabled = 0;
1391                         mptsas_timeout_id = 0;
1392                         mutex_exit(&mptsas_global_mutex);
1393                         (void) untimeout(tid);
1394                         mutex_enter(&mptsas_global_mutex);
1395                 }
1396                 mutex_exit(&mptsas_global_mutex);
1397                 /* deallocate in reverse order */
1398                 mptsas_cache_destroy(mpt);
1399 
1400                 if (smp_attach_setup) {
1401                         mptsas_smp_teardown(mpt);
1402                 }
1403                 if (hba_attach_setup) {
1404                         mptsas_hba_teardown(mpt);
1405                 }
1406 





1407                 if (mpt->m_active) {
1408                         mptsas_hash_uninit(&mpt->m_active->m_smptbl,
1409                             sizeof (mptsas_smp_t));
1410                         mptsas_hash_uninit(&mpt->m_active->m_tgttbl,
1411                             sizeof (mptsas_target_t));
1412                         mptsas_free_active_slots(mpt);
1413                 }
1414                 if (intr_added) {
1415                         mptsas_unregister_intrs(mpt);
1416                 }
1417 
1418                 if (doneq_thread_create) {
1419                         mutex_enter(&mpt->m_doneq_mutex);
1420                         doneq_thread_num = mpt->m_doneq_thread_n;
1421                         for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1422                                 mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1423                                 mpt->m_doneq_thread_id[j].flag &=
1424                                     (~MPTSAS_DONEQ_THREAD_ACTIVE);
1425                                 cv_signal(&mpt->m_doneq_thread_id[j].cv);
1426                                 mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1427                         }
1428                         while (mpt->m_doneq_thread_n) {
1429                                 cv_wait(&mpt->m_doneq_thread_cv,
1430                                     &mpt->m_doneq_mutex);
1431                         }


1824                         mptsas_timeout_id = 0;
1825                         mutex_exit(&mptsas_global_mutex);
1826                         (void) untimeout(tid);
1827                         mutex_enter(&mptsas_global_mutex);
1828                 }
1829                 if (mptsas_reset_watch) {
1830                         tid = mptsas_reset_watch;
1831                         mptsas_reset_watch = 0;
1832                         mutex_exit(&mptsas_global_mutex);
1833                         (void) untimeout(tid);
1834                         mutex_enter(&mptsas_global_mutex);
1835                 }
1836         }
1837         mutex_exit(&mptsas_global_mutex);
1838 
1839         /*
1840          * Delete Phy stats
1841          */
1842         mptsas_destroy_phy_stats(mpt);
1843 


1844         /*
1845          * Delete nt_active.
1846          */
1847         mutex_enter(&mpt->m_mutex);
1848         mptsas_hash_uninit(&mpt->m_active->m_tgttbl, sizeof (mptsas_target_t));
1849         mptsas_hash_uninit(&mpt->m_active->m_smptbl, sizeof (mptsas_smp_t));
1850         mptsas_free_active_slots(mpt);
1851         mutex_exit(&mpt->m_mutex);
1852 
1853         /* deallocate everything that was allocated in mptsas_attach */
1854         mptsas_cache_destroy(mpt);
1855 
1856         mptsas_hba_fini(mpt);
1857         mptsas_cfg_fini(mpt);
1858 
1859         /* Lower the power informing PM Framework */
1860         if (mpt->m_options & MPTSAS_OPT_PM) {
1861                 if (pm_lower_power(dip, 0, PM_LEVEL_D3) != DDI_SUCCESS)
1862                         mptsas_log(mpt, CE_WARN,
1863                             "!mptsas%d: Lower power request failed "
1864                             "during detach, ignoring.",
1865                             mpt->m_instance);
1866         }
1867 
1868         mutex_destroy(&mpt->m_tx_waitq_mutex);
1869         mutex_destroy(&mpt->m_passthru_mutex);


2090         (void) scsi_hba_iport_register(mpt->m_dip, "v0");
2091 
2092 }
2093 
2094 static int
2095 mptsas_smp_setup(mptsas_t *mpt)
2096 {
2097         mpt->m_smptran = smp_hba_tran_alloc(mpt->m_dip);
2098         ASSERT(mpt->m_smptran != NULL);
2099         mpt->m_smptran->smp_tran_hba_private = mpt;
2100         mpt->m_smptran->smp_tran_start = mptsas_smp_start;
2101         if (smp_hba_attach_setup(mpt->m_dip, mpt->m_smptran) != DDI_SUCCESS) {
2102                 mptsas_log(mpt, CE_WARN, "smp attach setup failed");
2103                 smp_hba_tran_free(mpt->m_smptran);
2104                 mpt->m_smptran = NULL;
2105                 return (FALSE);
2106         }
2107         /*
2108          * Initialize smp hash table
2109          */
2110         mptsas_hash_init(&mpt->m_active->m_smptbl);




2111         mpt->m_smp_devhdl = 0xFFFF;
2112 
2113         return (TRUE);
2114 }
2115 
2116 static void
2117 mptsas_smp_teardown(mptsas_t *mpt)
2118 {
2119         (void) smp_hba_detach(mpt->m_dip);
2120         if (mpt->m_smptran != NULL) {
2121                 smp_hba_tran_free(mpt->m_smptran);
2122                 mpt->m_smptran = NULL;
2123         }
2124         mpt->m_smp_devhdl = 0;
2125 }
2126 
2127 static int
2128 mptsas_cache_create(mptsas_t *mpt)
2129 {
2130         int instance = mpt->m_instance;


2733 {
2734 #ifndef __lock_lint
2735         _NOTE(ARGUNUSED(hba_tran))
2736 #endif
2737 
2738         /*
2739          * At this point, the scsi_device structure already exists
2740          * and has been initialized.
2741          *
2742          * Use this function to allocate target-private data structures,
2743          * if needed by this HBA.  Add revised flow-control and queue
2744          * properties for child here, if desired and if you can tell they
2745          * support tagged queueing by now.
2746          */
2747         mptsas_t                *mpt;
2748         int                     lun = sd->sd_address.a_lun;
2749         mdi_pathinfo_t          *pip = NULL;
2750         mptsas_tgt_private_t    *tgt_private = NULL;
2751         mptsas_target_t         *ptgt = NULL;
2752         char                    *psas_wwn = NULL;
2753         int                     phymask = 0;
2754         uint64_t                sas_wwn = 0;

2755         mpt = SDEV2MPT(sd);
2756 
2757         ASSERT(scsi_hba_iport_unit_address(hba_dip) != 0);
2758 
2759         NDBG0(("mptsas_scsi_tgt_init: hbadip=0x%p tgtdip=0x%p lun=%d",
2760             (void *)hba_dip, (void *)tgt_dip, lun));
2761 
2762         if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
2763                 (void) ndi_merge_node(tgt_dip, mptsas_name_child);
2764                 ddi_set_name_addr(tgt_dip, NULL);
2765                 return (DDI_FAILURE);
2766         }
2767         /*
2768          * phymask is 0 means the virtual port for RAID
2769          */
2770         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, hba_dip, 0,
2771             "phymask", 0);
2772         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2773                 if ((pip = (void *)(sd->sd_private)) == NULL) {
2774                         /*
2775                          * Very bad news if this occurs. Somehow scsi_vhci has
2776                          * lost the pathinfo node for this target.
2777                          */
2778                         return (DDI_NOT_WELL_FORMED);
2779                 }
2780 
2781                 if (mdi_prop_lookup_int(pip, LUN_PROP, &lun) !=
2782                     DDI_PROP_SUCCESS) {
2783                         mptsas_log(mpt, CE_WARN, "Get lun property failed\n");
2784                         return (DDI_FAILURE);
2785                 }
2786 
2787                 if (mdi_prop_lookup_string(pip, SCSI_ADDR_PROP_TARGET_PORT,
2788                     &psas_wwn) == MDI_SUCCESS) {
2789                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2790                                 sas_wwn = 0;
2791                         }
2792                         (void) mdi_prop_free(psas_wwn);
2793                 }
2794         } else {
2795                 lun = ddi_prop_get_int(DDI_DEV_T_ANY, tgt_dip,
2796                     DDI_PROP_DONTPASS, LUN_PROP, 0);
2797                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip,
2798                     DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &psas_wwn) ==
2799                     DDI_PROP_SUCCESS) {
2800                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2801                                 sas_wwn = 0;
2802                         }
2803                         ddi_prop_free(psas_wwn);
2804                 } else {
2805                         sas_wwn = 0;
2806                 }
2807         }

2808         ASSERT((sas_wwn != 0) || (phymask != 0));


2809         mutex_enter(&mpt->m_mutex);
2810         ptgt = mptsas_hash_search(&mpt->m_active->m_tgttbl, sas_wwn, phymask);
2811         mutex_exit(&mpt->m_mutex);
2812         if (ptgt == NULL) {
2813                 mptsas_log(mpt, CE_WARN, "!tgt_init: target doesn't exist or "
2814                     "gone already! phymask:%x, saswwn %"PRIx64, phymask,
2815                     sas_wwn);
2816                 return (DDI_FAILURE);
2817         }
2818         if (hba_tran->tran_tgt_private == NULL) {
2819                 tgt_private = kmem_zalloc(sizeof (mptsas_tgt_private_t),
2820                     KM_SLEEP);
2821                 tgt_private->t_lun = lun;
2822                 tgt_private->t_private = ptgt;
2823                 hba_tran->tran_tgt_private = tgt_private;
2824         }
2825 
2826         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2827                 return (DDI_SUCCESS);
2828         }
2829         mutex_enter(&mpt->m_mutex);
2830 


3221 
3222                 if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3223                         (void) mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
3224 
3225                         /*
3226                          * Only flush the doneq if this is not a TM
3227                          * cmd.  For TM cmds the flushing of the
3228                          * doneq will be done in those routines.
3229                          */
3230                         if ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
3231                                 mptsas_doneq_empty(mpt);
3232                         }
3233                 }
3234         }
3235         return (rval);
3236 }
3237 
3238 int
3239 mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
3240 {
3241         mptsas_slots_t  *slots;
3242         int             slot;
3243         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3244 
3245         ASSERT(mutex_owned(&mpt->m_mutex));
3246         slots = mpt->m_active;
3247 
3248         /*
3249          * Account for reserved TM request slot and reserved SMID of 0.
3250          */
3251         ASSERT(slots->m_n_slots == (mpt->m_max_requests - 2));
3252 
3253         /*
3254          * m_tags is equivalent to the SMID when sending requests.  Since the
3255          * SMID cannot be 0, start out at one if rolling over past the size
3256          * of the request queue depth.  Also, don't use the last SMID, which is
3257          * reserved for TM requests.


3258          */
3259         slot = (slots->m_tags)++;
3260         if (slots->m_tags > slots->m_n_slots) {
3261                 slots->m_tags = 1;
3262         }

3263 
3264 alloc_tag:
3265         /* Validate tag, should never fail. */
3266         if (slots->m_slot[slot] == NULL) {
3267                 /*
3268                  * Make sure SMID is not using reserved value of 0
3269                  * and the TM request slot.
3270                  */
3271                 ASSERT((slot > 0) && (slot <= slots->m_n_slots));

3272                 cmd->cmd_slot = slot;
3273                 slots->m_slot[slot] = cmd;
3274                 mpt->m_ncmds++;
3275 
3276                 /*
3277                  * only increment per target ncmds if this is not a
3278                  * command that has no target associated with it (i.e. a
3279                  * event acknoledgment)
3280                  */
3281                 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
3282                         ptgt->m_t_ncmds++;
3283                 }
3284                 cmd->cmd_active_timeout = cmd->cmd_pkt->pkt_time;
3285 
3286                 /*
3287                  * If initial timout is less than or equal to one tick, bump
3288                  * the timeout by a tick so that command doesn't timeout before
3289                  * its allotted time.
3290                  */
3291                 if (cmd->cmd_active_timeout <= mptsas_scsi_watchdog_tick) {
3292                         cmd->cmd_active_timeout += mptsas_scsi_watchdog_tick;
3293                 }
3294                 return (TRUE);
3295         } else {
3296                 int i;
3297 
3298                 /*
3299                  * If slot in use, scan until a free one is found. Don't use 0
3300                  * or final slot, which is reserved for TM requests.
3301                  */
3302                 for (i = 0; i < slots->m_n_slots; i++) {
3303                         slot = slots->m_tags;
3304                         if (++(slots->m_tags) > slots->m_n_slots) {
3305                                 slots->m_tags = 1;
3306                         }
3307                         if (slots->m_slot[slot] == NULL) {
3308                                 NDBG22(("found free slot %d", slot));
3309                                 goto alloc_tag;
3310                         }
3311                 }
3312         }
3313         return (FALSE);
3314 }
3315 
3316 /*
3317  * prepare the pkt:
3318  * the pkt may have been resubmitted or just reused so
3319  * initialize some fields and do some checks.
3320  */
3321 static int
3322 mptsas_prepare_pkt(mptsas_cmd_t *cmd)
3323 {
3324         struct scsi_pkt *pkt = CMD2PKT(cmd);
3325 
3326         NDBG1(("mptsas_prepare_pkt: cmd=0x%p", (void *)cmd));
3327 
3328         /*
3329          * Reinitialize some fields that need it; the packet may
3330          * have been resubmitted
3331          */
3332         pkt->pkt_reason = CMD_CMPLT;
3333         pkt->pkt_state = 0;


4634 static void
4635 mptsas_handle_scsi_io_success(mptsas_t *mpt,
4636     pMpi2ReplyDescriptorsUnion_t reply_desc)
4637 {
4638         pMpi2SCSIIOSuccessReplyDescriptor_t     scsi_io_success;
4639         uint16_t                                SMID;
4640         mptsas_slots_t                          *slots = mpt->m_active;
4641         mptsas_cmd_t                            *cmd = NULL;
4642         struct scsi_pkt                         *pkt;
4643 
4644         ASSERT(mutex_owned(&mpt->m_mutex));
4645 
4646         scsi_io_success = (pMpi2SCSIIOSuccessReplyDescriptor_t)reply_desc;
4647         SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &scsi_io_success->SMID);
4648 
4649         /*
4650          * This is a success reply so just complete the IO.  First, do a sanity
4651          * check on the SMID.  The final slot is used for TM requests, which
4652          * would not come into this reply handler.
4653          */
4654         if ((SMID == 0) || (SMID > slots->m_n_slots)) {
4655                 mptsas_log(mpt, CE_WARN, "?Received invalid SMID of %d\n",
4656                     SMID);
4657                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4658                 return;
4659         }
4660 
4661         cmd = slots->m_slot[SMID];
4662 
4663         /*
4664          * print warning and return if the slot is empty
4665          */
4666         if (cmd == NULL) {
4667                 mptsas_log(mpt, CE_WARN, "?NULL command for successful SCSI IO "
4668                     "in slot %d", SMID);
4669                 return;
4670         }
4671 
4672         pkt = CMD2PKT(cmd);
4673         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
4674             STATE_GOT_STATUS);


4737                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4738                 return;
4739         }
4740 
4741         (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
4742             DDI_DMA_SYNC_FORCPU);
4743         reply = (pMPI2DefaultReply_t)(mpt->m_reply_frame + (reply_addr -
4744             mpt->m_reply_frame_dma_addr));
4745         function = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->Function);
4746 
4747         /*
4748          * don't get slot information and command for events since these values
4749          * don't exist
4750          */
4751         if ((function != MPI2_FUNCTION_EVENT_NOTIFICATION) &&
4752             (function != MPI2_FUNCTION_DIAG_BUFFER_POST)) {
4753                 /*
4754                  * This could be a TM reply, which use the last allocated SMID,
4755                  * so allow for that.
4756                  */
4757                 if ((SMID == 0) || (SMID > (slots->m_n_slots + 1))) {
4758                         mptsas_log(mpt, CE_WARN, "?Received invalid SMID of "
4759                             "%d\n", SMID);
4760                         ddi_fm_service_impact(mpt->m_dip,
4761                             DDI_SERVICE_UNAFFECTED);
4762                         return;
4763                 }
4764 
4765                 cmd = slots->m_slot[SMID];
4766 
4767                 /*
4768                  * print warning and return if the slot is empty
4769                  */
4770                 if (cmd == NULL) {
4771                         mptsas_log(mpt, CE_WARN, "?NULL command for address "
4772                             "reply in slot %d", SMID);
4773                         return;
4774                 }
4775                 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
4776                     (cmd->cmd_flags & CFLAG_CONFIG) ||
4777                     (cmd->cmd_flags & CFLAG_FW_DIAG)) {


5054                  */
5055                 if (((scsi_sense_key(sensedata) == KEY_UNIT_ATTENTION) &&
5056                     (scsi_sense_asc(sensedata) == 0x3F) &&
5057                     (scsi_sense_ascq(sensedata) == 0x0E)) ||
5058                     ((scsi_sense_key(sensedata) == KEY_ILLEGAL_REQUEST) &&
5059                     (scsi_sense_asc(sensedata) == 0x25) &&
5060                     (scsi_sense_ascq(sensedata) == 0x00))) {
5061                         mptsas_topo_change_list_t *topo_node = NULL;
5062 
5063                         topo_node = kmem_zalloc(
5064                             sizeof (mptsas_topo_change_list_t),
5065                             KM_NOSLEEP);
5066                         if (topo_node == NULL) {
5067                                 mptsas_log(mpt, CE_NOTE, "No memory"
5068                                     "resource for handle SAS dynamic"
5069                                     "reconfigure.\n");
5070                                 break;
5071                         }
5072                         topo_node->mpt = mpt;
5073                         topo_node->event = MPTSAS_DR_EVENT_RECONFIG_TARGET;
5074                         topo_node->un.phymask = ptgt->m_phymask;
5075                         topo_node->devhdl = ptgt->m_devhdl;
5076                         topo_node->object = (void *)ptgt;
5077                         topo_node->flags = MPTSAS_TOPO_FLAG_LUN_ASSOCIATED;
5078 
5079                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
5080                             mptsas_handle_dr,
5081                             (void *)topo_node,
5082                             DDI_NOSLEEP)) != DDI_SUCCESS) {
5083                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq"
5084                                     "for handle SAS dynamic reconfigure"
5085                                     "failed. \n");
5086                         }
5087                 }
5088                 break;
5089         case MPI2_SCSI_STATUS_GOOD:
5090                 switch (ioc_status & MPI2_IOCSTATUS_MASK) {
5091                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
5092                         pkt->pkt_reason = CMD_DEV_GONE;
5093                         pkt->pkt_state |= STATE_GOT_BUS;
5094                         if (ptgt->m_reset_delay == 0) {


5120                 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
5121                         mptsas_set_pkt_reason(mpt,
5122                             cmd, CMD_RESET, STAT_BUS_RESET);
5123                         break;
5124                 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
5125                 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
5126                         mptsas_set_pkt_reason(mpt,
5127                             cmd, CMD_RESET, STAT_DEV_RESET);
5128                         break;
5129                 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
5130                 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
5131                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET);
5132                         mptsas_set_pkt_reason(mpt,
5133                             cmd, CMD_TERMINATED, STAT_TERMINATED);
5134                         break;
5135                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
5136                 case MPI2_IOCSTATUS_BUSY:
5137                         /*
5138                          * set throttles to drain
5139                          */
5140                         ptgt = (mptsas_target_t *)mptsas_hash_traverse(
5141                             &mpt->m_active->m_tgttbl, MPTSAS_HASH_FIRST);
5142                         while (ptgt != NULL) {
5143                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5144 
5145                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
5146                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
5147                         }
5148 
5149                         /*
5150                          * retry command
5151                          */
5152                         cmd->cmd_flags |= CFLAG_RETRY;
5153                         cmd->cmd_pkt_flags |= FLAG_HEAD;
5154 
5155                         (void) mptsas_accept_pkt(mpt, cmd);
5156                         break;
5157                 default:
5158                         mptsas_log(mpt, CE_WARN,
5159                             "unknown ioc_status = %x\n", ioc_status);
5160                         mptsas_log(mpt, CE_CONT, "scsi_state = %x, transfer "
5161                             "count = %x, scsi_status = %x", scsi_state,
5162                             xferred, scsi_status);
5163                         break;
5164                 }
5165                 break;
5166         case MPI2_SCSI_STATUS_TASK_SET_FULL:


5817         char            *addr = NULL;
5818         dev_info_t      *lundip;
5819         int             circ = 0, circ1 = 0;
5820         char            attached_wwnstr[MPTSAS_WWN_STRLEN];
5821 
5822         NDBG20(("mptsas%d handle_topo_change enter", mpt->m_instance));
5823 
5824         ASSERT(mutex_owned(&mpt->m_mutex));
5825 
5826         switch (topo_node->event) {
5827         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
5828         {
5829                 char *phy_mask_name;
5830                 mptsas_phymask_t phymask = 0;
5831 
5832                 if (topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5833                         /*
5834                          * Get latest RAID info.
5835                          */
5836                         (void) mptsas_get_raid_info(mpt);
5837                         ptgt = mptsas_search_by_devhdl(
5838                             &mpt->m_active->m_tgttbl, topo_node->devhdl);
5839                         if (ptgt == NULL)
5840                                 break;
5841                 } else {
5842                         ptgt = (void *)topo_node->object;
5843                 }
5844 
5845                 if (ptgt == NULL) {
5846                         /*
5847                          * If a Phys Disk was deleted, RAID info needs to be
5848                          * updated to reflect the new topology.
5849                          */
5850                         (void) mptsas_get_raid_info(mpt);
5851 
5852                         /*
5853                          * Get sas device page 0 by DevHandle to make sure if
5854                          * SSP/SATA end device exist.
5855                          */
5856                         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
5857                             MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
5858                             topo_node->devhdl;


5867                         } else if (rval == DEV_INFO_FAIL_ALLOC) {
5868                                 mptsas_log(mpt, CE_NOTE,
5869                                     "mptsas_handle_topo_change: could not "
5870                                     "allocate memory. \n");
5871                         }
5872                         /*
5873                          * If rval is DEV_INFO_PHYS_DISK than there is nothing
5874                          * else to do, just leave.
5875                          */
5876                         if (rval != DEV_INFO_SUCCESS) {
5877                                 return;
5878                         }
5879                 }
5880 
5881                 ASSERT(ptgt->m_devhdl == topo_node->devhdl);
5882 
5883                 mutex_exit(&mpt->m_mutex);
5884                 flags = topo_node->flags;
5885 
5886                 if (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) {
5887                         phymask = ptgt->m_phymask;
5888                         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
5889                         (void) sprintf(phy_mask_name, "%x", phymask);
5890                         parent = scsi_hba_iport_find(mpt->m_dip,
5891                             phy_mask_name);
5892                         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
5893                         if (parent == NULL) {
5894                                 mptsas_log(mpt, CE_WARN, "Failed to find a "
5895                                     "iport for PD, should not happen!");
5896                                 mutex_enter(&mpt->m_mutex);
5897                                 break;
5898                         }
5899                 }
5900 
5901                 if (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5902                         ndi_devi_enter(parent, &circ1);
5903                         (void) mptsas_config_raid(parent, topo_node->devhdl,
5904                             &lundip);
5905                         ndi_devi_exit(parent, circ1);
5906                 } else {
5907                         /*
5908                          * hold nexus for bus configure
5909                          */
5910                         ndi_devi_enter(scsi_vhci_dip, &circ);
5911                         ndi_devi_enter(parent, &circ1);
5912                         rval = mptsas_config_target(parent, ptgt);
5913                         /*
5914                          * release nexus for bus configure
5915                          */
5916                         ndi_devi_exit(parent, circ1);
5917                         ndi_devi_exit(scsi_vhci_dip, circ);
5918 
5919                         /*
5920                          * Add parent's props for SMHBA support
5921                          */
5922                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
5923                                 bzero(attached_wwnstr,
5924                                     sizeof (attached_wwnstr));
5925                                 (void) sprintf(attached_wwnstr, "w%016"PRIx64,
5926                                     ptgt->m_sas_wwn);
5927                                 if (ddi_prop_update_string(DDI_DEV_T_NONE,
5928                                     parent,
5929                                     SCSI_ADDR_PROP_ATTACHED_PORT,
5930                                     attached_wwnstr)
5931                                     != DDI_PROP_SUCCESS) {
5932                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
5933                                             parent,
5934                                             SCSI_ADDR_PROP_ATTACHED_PORT);
5935                                         mptsas_log(mpt, CE_WARN, "Failed to"
5936                                             "attached-port props");
5937                                         return;
5938                                 }
5939                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
5940                                     MPTSAS_NUM_PHYS, 1) !=
5941                                     DDI_PROP_SUCCESS) {
5942                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
5943                                             parent, MPTSAS_NUM_PHYS);
5944                                         mptsas_log(mpt, CE_WARN, "Failed to"
5945                                             " create num-phys props");
5946                                         return;


5964                                  */
5965                                 mptsas_smhba_set_one_phy_props(mpt, parent,
5966                                     topo_node->un.physport, &attached_devhdl);
5967 
5968                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
5969                                     MPTSAS_VIRTUAL_PORT, 0) !=
5970                                     DDI_PROP_SUCCESS) {
5971                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
5972                                             parent, MPTSAS_VIRTUAL_PORT);
5973                                         mptsas_log(mpt, CE_WARN,
5974                                             "mptsas virtual-port"
5975                                             "port prop update failed");
5976                                         return;
5977                                 }
5978                         }
5979                 }
5980                 mutex_enter(&mpt->m_mutex);
5981 
5982                 NDBG20(("mptsas%d handle_topo_change to online devhdl:%x, "
5983                     "phymask:%x.", mpt->m_instance, ptgt->m_devhdl,
5984                     ptgt->m_phymask));
5985                 break;
5986         }
5987         case MPTSAS_DR_EVENT_OFFLINE_TARGET:
5988         {
5989                 mptsas_hash_table_t *tgttbl = &mpt->m_active->m_tgttbl;
5990                 devhdl = topo_node->devhdl;
5991                 ptgt = mptsas_search_by_devhdl(tgttbl, devhdl);

5992                 if (ptgt == NULL)
5993                         break;
5994 
5995                 sas_wwn = ptgt->m_sas_wwn;
5996                 phy = ptgt->m_phynum;
5997 
5998                 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
5999 
6000                 if (sas_wwn) {
6001                         (void) sprintf(addr, "w%016"PRIx64, sas_wwn);
6002                 } else {
6003                         (void) sprintf(addr, "p%x", phy);
6004                 }
6005                 ASSERT(ptgt->m_devhdl == devhdl);
6006 
6007                 if ((topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) ||
6008                     (topo_node->flags ==
6009                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6010                         /*
6011                          * Get latest RAID info if RAID volume status changes
6012                          * or Phys Disk status changes
6013                          */
6014                         (void) mptsas_get_raid_info(mpt);
6015                 }
6016                 /*
6017                  * Abort all outstanding command on the device
6018                  */
6019                 rval = mptsas_do_scsi_reset(mpt, devhdl);
6020                 if (rval) {
6021                         NDBG20(("mptsas%d handle_topo_change to reset target "
6022                             "before offline devhdl:%x, phymask:%x, rval:%x",
6023                             mpt->m_instance, ptgt->m_devhdl, ptgt->m_phymask,
6024                             rval));
6025                 }
6026 
6027                 mutex_exit(&mpt->m_mutex);
6028 
6029                 ndi_devi_enter(scsi_vhci_dip, &circ);
6030                 ndi_devi_enter(parent, &circ1);
6031                 rval = mptsas_offline_target(parent, addr);
6032                 ndi_devi_exit(parent, circ1);
6033                 ndi_devi_exit(scsi_vhci_dip, circ);
6034                 NDBG20(("mptsas%d handle_topo_change to offline devhdl:%x, "
6035                     "phymask:%x, rval:%x", mpt->m_instance,
6036                     ptgt->m_devhdl, ptgt->m_phymask, rval));
6037 
6038                 kmem_free(addr, SCSI_MAXNAMELEN);
6039 
6040                 /*
6041                  * Clear parent's props for SMHBA support
6042                  */
6043                 flags = topo_node->flags;
6044                 if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6045                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6046                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6047                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6048                             DDI_PROP_SUCCESS) {
6049                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6050                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6051                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6052                                     "prop update failed");
6053                                 break;
6054                         }
6055                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6056                             MPTSAS_NUM_PHYS, 0) !=


6059                                     MPTSAS_NUM_PHYS);
6060                                 mptsas_log(mpt, CE_WARN, "mptsas num phys "
6061                                     "prop update failed");
6062                                 break;
6063                         }
6064                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6065                             MPTSAS_VIRTUAL_PORT, 1) !=
6066                             DDI_PROP_SUCCESS) {
6067                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6068                                     MPTSAS_VIRTUAL_PORT);
6069                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6070                                     "prop update failed");
6071                                 break;
6072                         }
6073                 }
6074 
6075                 mutex_enter(&mpt->m_mutex);
6076                 ptgt->m_led_status = 0;
6077                 (void) mptsas_flush_led_status(mpt, ptgt);
6078                 if (rval == DDI_SUCCESS) {
6079                         mptsas_tgt_free(&mpt->m_active->m_tgttbl,
6080                             ptgt->m_sas_wwn, ptgt->m_phymask);
6081                         ptgt = NULL;
6082                 } else {
6083                         /*
6084                          * clean DR_INTRANSITION flag to allow I/O down to
6085                          * PHCI driver since failover finished.
6086                          * Invalidate the devhdl
6087                          */
6088                         ptgt->m_devhdl = MPTSAS_INVALID_DEVHDL;
6089                         ptgt->m_tgt_unconfigured = 0;
6090                         mutex_enter(&mpt->m_tx_waitq_mutex);
6091                         ptgt->m_dr_flag = MPTSAS_DR_INACTIVE;
6092                         mutex_exit(&mpt->m_tx_waitq_mutex);
6093                 }
6094 
6095                 /*
6096                  * Send SAS IO Unit Control to free the dev handle
6097                  */
6098                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6099                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE)) {
6100                         rval = mptsas_free_devhdl(mpt, devhdl);


6117                         if (rval) {
6118                                 NDBG20(("mpt%d reset target before remove "
6119                                     "devhdl:%x, rval:%x", mpt->m_instance,
6120                                     devhdl, rval));
6121                         }
6122                 }
6123 
6124                 /*
6125                  * Send SAS IO Unit Control to free the dev handle
6126                  */
6127                 rval = mptsas_free_devhdl(mpt, devhdl);
6128                 NDBG20(("mptsas%d handle_topo_change to remove "
6129                     "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6130                     rval));
6131                 break;
6132         }
6133         case MPTSAS_DR_EVENT_RECONFIG_SMP:
6134         {
6135                 mptsas_smp_t smp;
6136                 dev_info_t *smpdip;
6137                 mptsas_hash_table_t *smptbl = &mpt->m_active->m_smptbl;
6138 
6139                 devhdl = topo_node->devhdl;
6140 
6141                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
6142                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)devhdl;
6143                 rval = mptsas_get_sas_expander_page0(mpt, page_address, &smp);
6144                 if (rval != DDI_SUCCESS) {
6145                         mptsas_log(mpt, CE_WARN, "failed to online smp, "
6146                             "handle %x", devhdl);
6147                         return;
6148                 }
6149 
6150                 psmp = mptsas_smp_alloc(smptbl, &smp);
6151                 if (psmp == NULL) {
6152                         return;
6153                 }
6154 
6155                 mutex_exit(&mpt->m_mutex);
6156                 ndi_devi_enter(parent, &circ1);
6157                 (void) mptsas_online_smp(parent, psmp, &smpdip);
6158                 ndi_devi_exit(parent, circ1);
6159 
6160                 mutex_enter(&mpt->m_mutex);
6161                 break;
6162         }
6163         case MPTSAS_DR_EVENT_OFFLINE_SMP:
6164         {
6165                 mptsas_hash_table_t *smptbl = &mpt->m_active->m_smptbl;
6166                 devhdl = topo_node->devhdl;
6167                 uint32_t dev_info;
6168 
6169                 psmp = mptsas_search_by_devhdl(smptbl, devhdl);

6170                 if (psmp == NULL)
6171                         break;
6172                 /*
6173                  * The mptsas_smp_t data is released only if the dip is offlined
6174                  * successfully.
6175                  */
6176                 mutex_exit(&mpt->m_mutex);
6177 
6178                 ndi_devi_enter(parent, &circ1);
6179                 rval = mptsas_offline_smp(parent, psmp, NDI_DEVI_REMOVE);
6180                 ndi_devi_exit(parent, circ1);
6181 
6182                 dev_info = psmp->m_deviceinfo;
6183                 if ((dev_info & DEVINFO_DIRECT_ATTACHED) ==
6184                     DEVINFO_DIRECT_ATTACHED) {
6185                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6186                             MPTSAS_VIRTUAL_PORT, 1) !=
6187                             DDI_PROP_SUCCESS) {
6188                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6189                                     MPTSAS_VIRTUAL_PORT);


6205                         }
6206                         /*
6207                          * Clear parent's attached-port props
6208                          */
6209                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6210                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6211                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6212                             DDI_PROP_SUCCESS) {
6213                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6214                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6215                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6216                                     "prop update failed");
6217                                 return;
6218                         }
6219                 }
6220 
6221                 mutex_enter(&mpt->m_mutex);
6222                 NDBG20(("mptsas%d handle_topo_change to remove devhdl:%x, "
6223                     "rval:%x", mpt->m_instance, psmp->m_devhdl, rval));
6224                 if (rval == DDI_SUCCESS) {
6225                         mptsas_smp_free(smptbl, psmp->m_sasaddr,
6226                             psmp->m_phymask);
6227                 } else {
6228                         psmp->m_devhdl = MPTSAS_INVALID_DEVHDL;
6229                 }
6230 
6231                 bzero(attached_wwnstr, sizeof (attached_wwnstr));
6232 
6233                 break;
6234         }
6235         default:
6236                 return;
6237         }
6238 }
6239 
6240 /*
6241  * Record the event if its type is enabled in mpt instance by ioctl.
6242  */
6243 static void
6244 mptsas_record_event(void *args)
6245 {
6246         m_replyh_arg_t                  *replyh_arg;


6365         }
6366 
6367         /*
6368          * figure out what kind of event we got and handle accordingly
6369          */
6370         switch (event) {
6371         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
6372         {
6373                 pMpi2EventDataSasTopologyChangeList_t   sas_topo_change_list;
6374                 uint8_t                         num_entries, expstatus, phy;
6375                 uint8_t                         phystatus, physport, state, i;
6376                 uint8_t                         start_phy_num, link_rate;
6377                 uint16_t                        dev_handle, reason_code;
6378                 uint16_t                        enc_handle, expd_handle;
6379                 char                            string[80], curr[80], prev[80];
6380                 mptsas_topo_change_list_t       *topo_head = NULL;
6381                 mptsas_topo_change_list_t       *topo_tail = NULL;
6382                 mptsas_topo_change_list_t       *topo_node = NULL;
6383                 mptsas_target_t                 *ptgt;
6384                 mptsas_smp_t                    *psmp;
6385                 mptsas_hash_table_t             *tgttbl, *smptbl;
6386                 uint8_t                         flags = 0, exp_flag;
6387                 smhba_info_t                    *pSmhba = NULL;
6388 
6389                 NDBG20(("mptsas_handle_event_sync: SAS topology change"));
6390 
6391                 tgttbl = &mpt->m_active->m_tgttbl;
6392                 smptbl = &mpt->m_active->m_smptbl;
6393 
6394                 sas_topo_change_list = (pMpi2EventDataSasTopologyChangeList_t)
6395                     eventreply->EventData;
6396 
6397                 enc_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6398                     &sas_topo_change_list->EnclosureHandle);
6399                 expd_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6400                     &sas_topo_change_list->ExpanderDevHandle);
6401                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6402                     &sas_topo_change_list->NumEntries);
6403                 start_phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
6404                     &sas_topo_change_list->StartPhyNum);
6405                 expstatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6406                     &sas_topo_change_list->ExpStatus);
6407                 physport = ddi_get8(mpt->m_acc_reply_frame_hdl,
6408                     &sas_topo_change_list->PhysicalPort);
6409 
6410                 string[0] = 0;
6411                 if (expd_handle) {
6412                         flags = MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED;
6413                         switch (expstatus) {


6419                                 mpt->m_port_chng = 1;
6420                                 topo_node = kmem_zalloc(
6421                                     sizeof (mptsas_topo_change_list_t),
6422                                     KM_SLEEP);
6423                                 topo_node->mpt = mpt;
6424                                 topo_node->event = MPTSAS_DR_EVENT_RECONFIG_SMP;
6425                                 topo_node->un.physport = physport;
6426                                 topo_node->devhdl = expd_handle;
6427                                 topo_node->flags = flags;
6428                                 topo_node->object = NULL;
6429                                 if (topo_head == NULL) {
6430                                         topo_head = topo_tail = topo_node;
6431                                 } else {
6432                                         topo_tail->next = topo_node;
6433                                         topo_tail = topo_node;
6434                                 }
6435                                 break;
6436                         case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
6437                                 (void) sprintf(string, " not responding, "
6438                                     "removed");
6439                                 psmp = mptsas_search_by_devhdl(smptbl,
6440                                     expd_handle);
6441                                 if (psmp == NULL)
6442                                         break;
6443 
6444                                 topo_node = kmem_zalloc(
6445                                     sizeof (mptsas_topo_change_list_t),
6446                                     KM_SLEEP);
6447                                 topo_node->mpt = mpt;
6448                                 topo_node->un.phymask = psmp->m_phymask;

6449                                 topo_node->event = MPTSAS_DR_EVENT_OFFLINE_SMP;
6450                                 topo_node->devhdl = expd_handle;
6451                                 topo_node->flags = flags;
6452                                 topo_node->object = NULL;
6453                                 if (topo_head == NULL) {
6454                                         topo_head = topo_tail = topo_node;
6455                                 } else {
6456                                         topo_tail->next = topo_node;
6457                                         topo_tail = topo_node;
6458                                 }
6459                                 break;
6460                         case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
6461                                 break;
6462                         case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
6463                                 (void) sprintf(string, " not responding, "
6464                                     "delaying removal");
6465                                 break;
6466                         default:
6467                                 break;
6468                         }


6579                         case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
6580                         {
6581                                 NDBG20(("mptsas%d phy %d physical_port %d "
6582                                     "dev_handle %d removed", mpt->m_instance,
6583                                     phy, physport, dev_handle));
6584                                 /*
6585                                  * Set association flag according to if an
6586                                  * expander is used or not.
6587                                  */
6588                                 exp_flag =
6589                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
6590                                 if (flags ==
6591                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
6592                                         flags = exp_flag;
6593                                 }
6594                                 /*
6595                                  * Target device is removed from the system
6596                                  * Before the device is really offline from
6597                                  * from system.
6598                                  */
6599                                 ptgt = mptsas_search_by_devhdl(tgttbl,
6600                                     dev_handle);
6601                                 /*
6602                                  * If ptgt is NULL here, it means that the
6603                                  * DevHandle is not in the hash table.  This is
6604                                  * reasonable sometimes.  For example, if a
6605                                  * disk was pulled, then added, then pulled
6606                                  * again, the disk will not have been put into
6607                                  * the hash table because the add event will
6608                                  * have an invalid phymask.  BUT, this does not
6609                                  * mean that the DevHandle is invalid.  The
6610                                  * controller will still have a valid DevHandle
6611                                  * that must be removed.  To do this, use the
6612                                  * MPTSAS_TOPO_FLAG_REMOVE_HANDLE event.
6613                                  */
6614                                 if (ptgt == NULL) {
6615                                         topo_node = kmem_zalloc(
6616                                             sizeof (mptsas_topo_change_list_t),
6617                                             KM_SLEEP);
6618                                         topo_node->mpt = mpt;
6619                                         topo_node->un.phymask = 0;
6620                                         topo_node->event =


6632                                         break;
6633                                 }
6634 
6635                                 /*
6636                                  * Update DR flag immediately avoid I/O failure
6637                                  * before failover finish. Pay attention to the
6638                                  * mutex protect, we need grab m_tx_waitq_mutex
6639                                  * during set m_dr_flag because we won't add
6640                                  * the following command into waitq, instead,
6641                                  * we need return TRAN_BUSY in the tran_start
6642                                  * context.
6643                                  */
6644                                 mutex_enter(&mpt->m_tx_waitq_mutex);
6645                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6646                                 mutex_exit(&mpt->m_tx_waitq_mutex);
6647 
6648                                 topo_node = kmem_zalloc(
6649                                     sizeof (mptsas_topo_change_list_t),
6650                                     KM_SLEEP);
6651                                 topo_node->mpt = mpt;
6652                                 topo_node->un.phymask = ptgt->m_phymask;

6653                                 topo_node->event =
6654                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
6655                                 topo_node->devhdl = dev_handle;
6656                                 topo_node->flags = flags;
6657                                 topo_node->object = NULL;
6658                                 if (topo_head == NULL) {
6659                                         topo_head = topo_tail = topo_node;
6660                                 } else {
6661                                         topo_tail->next = topo_node;
6662                                         topo_tail = topo_node;
6663                                 }
6664                                 break;
6665                         }
6666                         case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
6667                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
6668                                     &sas_topo_change_list->PHY[i].LinkRate);
6669                                 state = (link_rate &
6670                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
6671                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
6672                                 pSmhba = &mpt->m_phy_info[i].smhba_info;


6792                 if (topo_head != NULL) {
6793                         /*
6794                          * Launch DR taskq to handle topology change
6795                          */
6796                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
6797                             mptsas_handle_dr, (void *)topo_head,
6798                             DDI_NOSLEEP)) != DDI_SUCCESS) {
6799                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
6800                                     "for handle SAS DR event failed. \n");
6801                         }
6802                 }
6803                 break;
6804         }
6805         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
6806         {
6807                 Mpi2EventDataIrConfigChangeList_t       *irChangeList;
6808                 mptsas_topo_change_list_t               *topo_head = NULL;
6809                 mptsas_topo_change_list_t               *topo_tail = NULL;
6810                 mptsas_topo_change_list_t               *topo_node = NULL;
6811                 mptsas_target_t                         *ptgt;
6812                 mptsas_hash_table_t                     *tgttbl;
6813                 uint8_t                                 num_entries, i, reason;
6814                 uint16_t                                volhandle, diskhandle;
6815 
6816                 irChangeList = (pMpi2EventDataIrConfigChangeList_t)
6817                     eventreply->EventData;
6818                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6819                     &irChangeList->NumElements);
6820 
6821                 tgttbl = &mpt->m_active->m_tgttbl;
6822 
6823                 NDBG20(("mptsas%d IR_CONFIGURATION_CHANGE_LIST event received",
6824                     mpt->m_instance));
6825 
6826                 for (i = 0; i < num_entries; i++) {
6827                         reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
6828                             &irChangeList->ConfigElement[i].ReasonCode);
6829                         volhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6830                             &irChangeList->ConfigElement[i].VolDevHandle);
6831                         diskhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6832                             &irChangeList->ConfigElement[i].PhysDiskDevHandle);
6833 
6834                         switch (reason) {
6835                         case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6836                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6837                         {
6838                                 NDBG20(("mptsas %d volume added\n",
6839                                     mpt->m_instance));
6840 
6841                                 topo_node = kmem_zalloc(
6842                                     sizeof (mptsas_topo_change_list_t),


6846                                 topo_node->event =
6847                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
6848                                 topo_node->un.physport = 0xff;
6849                                 topo_node->devhdl = volhandle;
6850                                 topo_node->flags =
6851                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
6852                                 topo_node->object = NULL;
6853                                 if (topo_head == NULL) {
6854                                         topo_head = topo_tail = topo_node;
6855                                 } else {
6856                                         topo_tail->next = topo_node;
6857                                         topo_tail = topo_node;
6858                                 }
6859                                 break;
6860                         }
6861                         case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6862                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6863                         {
6864                                 NDBG20(("mptsas %d volume deleted\n",
6865                                     mpt->m_instance));
6866                                 ptgt = mptsas_search_by_devhdl(tgttbl,
6867                                     volhandle);
6868                                 if (ptgt == NULL)
6869                                         break;
6870 
6871                                 /*
6872                                  * Clear any flags related to volume
6873                                  */
6874                                 (void) mptsas_delete_volume(mpt, volhandle);
6875 
6876                                 /*
6877                                  * Update DR flag immediately avoid I/O failure
6878                                  */
6879                                 mutex_enter(&mpt->m_tx_waitq_mutex);
6880                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6881                                 mutex_exit(&mpt->m_tx_waitq_mutex);
6882 
6883                                 topo_node = kmem_zalloc(
6884                                     sizeof (mptsas_topo_change_list_t),
6885                                     KM_SLEEP);
6886                                 topo_node->mpt = mpt;
6887                                 topo_node->un.phymask = ptgt->m_phymask;

6888                                 topo_node->event =
6889                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
6890                                 topo_node->devhdl = volhandle;
6891                                 topo_node->flags =
6892                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
6893                                 topo_node->object = (void *)ptgt;
6894                                 if (topo_head == NULL) {
6895                                         topo_head = topo_tail = topo_node;
6896                                 } else {
6897                                         topo_tail->next = topo_node;
6898                                         topo_tail = topo_node;
6899                                 }
6900                                 break;
6901                         }
6902                         case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
6903                         case MPI2_EVENT_IR_CHANGE_RC_HIDE:
6904                         {
6905                                 ptgt = mptsas_search_by_devhdl(tgttbl,
6906                                     diskhandle);
6907                                 if (ptgt == NULL)
6908                                         break;
6909 
6910                                 /*
6911                                  * Update DR flag immediately avoid I/O failure
6912                                  */
6913                                 mutex_enter(&mpt->m_tx_waitq_mutex);
6914                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6915                                 mutex_exit(&mpt->m_tx_waitq_mutex);
6916 
6917                                 topo_node = kmem_zalloc(
6918                                     sizeof (mptsas_topo_change_list_t),
6919                                     KM_SLEEP);
6920                                 topo_node->mpt = mpt;
6921                                 topo_node->un.phymask = ptgt->m_phymask;

6922                                 topo_node->event =
6923                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
6924                                 topo_node->devhdl = diskhandle;
6925                                 topo_node->flags =
6926                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
6927                                 topo_node->object = (void *)ptgt;
6928                                 if (topo_head == NULL) {
6929                                         topo_head = topo_tail = topo_node;
6930                                 } else {
6931                                         topo_tail->next = topo_node;
6932                                         topo_tail = topo_node;
6933                                 }
6934                                 break;
6935                         }
6936                         case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
6937                         case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
6938                         {
6939                                 /*
6940                                  * The physical drive is released by a IR
6941                                  * volume. But we cannot get the the physport


7326                             SAS_PORT_BROADCAST_D27_4,
7327                             &mpt->m_phy_info[phy_num].smhba_info);
7328                         break;
7329                 default:
7330                         NDBG20(("mptsas%d: unknown BROADCAST PRIMITIVE"
7331                             " %x received",
7332                             mpt->m_instance, primitive));
7333                         break;
7334                 }
7335                 NDBG20(("mptsas%d sas broadcast primitive: "
7336                     "\tprimitive(0x%04x), phy(%d) complete\n",
7337                     mpt->m_instance, primitive, phy_num));
7338                 break;
7339         }
7340         case MPI2_EVENT_IR_VOLUME:
7341         {
7342                 Mpi2EventDataIrVolume_t         *irVolume;
7343                 uint16_t                        devhandle;
7344                 uint32_t                        state;
7345                 int                             config, vol;
7346                 mptsas_slots_t                  *slots = mpt->m_active;
7347                 uint8_t                         found = FALSE;
7348 
7349                 irVolume = (pMpi2EventDataIrVolume_t)eventreply->EventData;
7350                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7351                     &irVolume->NewValue);
7352                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7353                     &irVolume->VolDevHandle);
7354 
7355                 NDBG20(("EVENT_IR_VOLUME event is received"));
7356 
7357                 /*
7358                  * Get latest RAID info and then find the DevHandle for this
7359                  * event in the configuration.  If the DevHandle is not found
7360                  * just exit the event.
7361                  */
7362                 (void) mptsas_get_raid_info(mpt);
7363                 for (config = 0; (config < slots->m_num_raid_configs) &&
7364                     (!found); config++) {
7365                         for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
7366                                 if (slots->m_raidconfig[config].m_raidvol[vol].
7367                                     m_raidhandle == devhandle) {
7368                                         found = TRUE;
7369                                         break;
7370                                 }
7371                         }
7372                 }
7373                 if (!found) {
7374                         break;
7375                 }
7376 
7377                 switch (irVolume->ReasonCode) {
7378                 case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
7379                 {
7380                         uint32_t i;
7381                         slots->m_raidconfig[config].m_raidvol[vol].m_settings =
7382                             state;
7383 
7384                         i = state & MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING;
7385                         mptsas_log(mpt, CE_NOTE, " Volume %d settings changed"
7386                             ", auto-config of hot-swap drives is %s"
7387                             ", write caching is %s"
7388                             ", hot-spare pool mask is %02x\n",
7389                             vol, state &
7390                             MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE
7391                             ? "disabled" : "enabled",
7392                             i == MPI2_RAIDVOL0_SETTING_UNCHANGED
7393                             ? "controlled by member disks" :
7394                             i == MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING
7395                             ? "disabled" :
7396                             i == MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING
7397                             ? "enabled" :
7398                             "incorrectly set",
7399                             (state >> 16) & 0xff);
7400                                 break;
7401                 }
7402                 case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
7403                 {
7404                         slots->m_raidconfig[config].m_raidvol[vol].m_state =
7405                             (uint8_t)state;
7406 
7407                         mptsas_log(mpt, CE_NOTE,
7408                             "Volume %d is now %s\n", vol,
7409                             state == MPI2_RAID_VOL_STATE_OPTIMAL
7410                             ? "optimal" :
7411                             state == MPI2_RAID_VOL_STATE_DEGRADED
7412                             ? "degraded" :
7413                             state == MPI2_RAID_VOL_STATE_ONLINE
7414                             ? "online" :
7415                             state == MPI2_RAID_VOL_STATE_INITIALIZING
7416                             ? "initializing" :
7417                             state == MPI2_RAID_VOL_STATE_FAILED
7418                             ? "failed" :
7419                             state == MPI2_RAID_VOL_STATE_MISSING
7420                             ? "missing" :
7421                             "state unknown");
7422                         break;
7423                 }
7424                 case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
7425                 {
7426                         slots->m_raidconfig[config].m_raidvol[vol].
7427                             m_statusflags = state;
7428 
7429                         mptsas_log(mpt, CE_NOTE,
7430                             " Volume %d is now %s%s%s%s%s%s%s%s%s\n",
7431                             vol,
7432                             state & MPI2_RAIDVOL0_STATUS_FLAG_ENABLED
7433                             ? ", enabled" : ", disabled",
7434                             state & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED
7435                             ? ", quiesced" : "",
7436                             state & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE
7437                             ? ", inactive" : ", active",
7438                             state &
7439                             MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL
7440                             ? ", bad block table is full" : "",
7441                             state &
7442                             MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
7443                             ? ", resync in progress" : "",
7444                             state & MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT
7445                             ? ", background initialization in progress" : "",
7446                             state &


7555                 mpt->m_free_index = 0;
7556         }
7557         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
7558             mpt->m_free_index);
7559         mutex_exit(&mpt->m_mutex);
7560 }
7561 
7562 /*
7563  * invoked from timeout() to restart qfull cmds with throttle == 0
7564  */
7565 static void
7566 mptsas_restart_cmd(void *arg)
7567 {
7568         mptsas_t        *mpt = arg;
7569         mptsas_target_t *ptgt = NULL;
7570 
7571         mutex_enter(&mpt->m_mutex);
7572 
7573         mpt->m_restart_cmd_timeid = 0;
7574 
7575         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
7576             MPTSAS_HASH_FIRST);
7577         while (ptgt != NULL) {
7578                 if (ptgt->m_reset_delay == 0) {
7579                         if (ptgt->m_t_throttle == QFULL_THROTTLE) {
7580                                 mptsas_set_throttle(mpt, ptgt,
7581                                     MAX_THROTTLE);
7582                         }
7583                 }
7584 
7585                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
7586                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
7587         }
7588         mptsas_restart_hba(mpt);
7589         mutex_exit(&mpt->m_mutex);
7590 }
7591 
7592 void
7593 mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
7594 {
7595         int             slot;
7596         mptsas_slots_t  *slots = mpt->m_active;
7597         int             t;
7598         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
7599 
7600         ASSERT(cmd != NULL);
7601         ASSERT(cmd->cmd_queued == FALSE);
7602 
7603         /*
7604          * Task Management cmds are removed in their own routines.  Also,
7605          * we don't want to modify timeout based on TM cmds.
7606          */


7638         }
7639 
7640         /*
7641          * This is all we need to do for ioc commands.
7642          */
7643         if (cmd->cmd_flags & CFLAG_CMDIOC) {
7644                 mptsas_return_to_pool(mpt, cmd);
7645                 return;
7646         }
7647 
7648         /*
7649          * Figure out what to set tag Q timeout for...
7650          *
7651          * Optimize: If we have duplicate's of same timeout
7652          * we're using, then we'll use it again until we run
7653          * out of duplicates.  This should be the normal case
7654          * for block and raw I/O.
7655          * If no duplicates, we have to scan through tag que and
7656          * find the longest timeout value and use it.  This is
7657          * going to take a while...
7658          * Add 1 to m_n_slots to account for TM request.
7659          */
7660         if (cmd->cmd_pkt->pkt_time == ptgt->m_timebase) {
7661                 if (--(ptgt->m_dups) == 0) {
7662                         if (ptgt->m_t_ncmds) {
7663                                 mptsas_cmd_t *ssp;
7664                                 uint_t n = 0;
7665                                 ushort_t nslots = (slots->m_n_slots + 1);
7666                                 ushort_t i;
7667                                 /*
7668                                  * This crude check assumes we don't do
7669                                  * this too often which seems reasonable
7670                                  * for block and raw I/O.
7671                                  */
7672                                 for (i = 0; i < nslots; i++) {
7673                                         ssp = slots->m_slot[i];
7674                                         if (ssp && (Tgt(ssp) == t) &&
7675                                             (ssp->cmd_pkt->pkt_time > n)) {
7676                                                 n = ssp->cmd_pkt->pkt_time;
7677                                                 ptgt->m_dups = 1;
7678                                         } else if (ssp && (Tgt(ssp) == t) &&
7679                                             (ssp->cmd_pkt->pkt_time == n)) {
7680                                                 ptgt->m_dups++;
7681                                         }
7682                                 }
7683                                 ptgt->m_timebase = n;
7684                         } else {
7685                                 ptgt->m_dups = 0;


8404                 drv_usecwait(mpt->m_scsi_reset_delay * 1000);
8405         }
8406         rval = mptsas_do_scsi_reset(mpt, ptgt->m_devhdl);
8407         mutex_exit(&mpt->m_mutex);
8408 
8409         /*
8410          * The transport layer expect to only see TRUE and
8411          * FALSE. Therefore, we will adjust the return value
8412          * if mptsas_do_scsi_reset returns FAILED.
8413          */
8414         if (rval == FAILED)
8415                 rval = FALSE;
8416         return (rval);
8417 }
8418 
8419 static int
8420 mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl)
8421 {
8422         int             rval = FALSE;
8423         uint8_t         config, disk;
8424         mptsas_slots_t  *slots = mpt->m_active;
8425 
8426         ASSERT(mutex_owned(&mpt->m_mutex));
8427 
8428         if (mptsas_debug_resets) {
8429                 mptsas_log(mpt, CE_WARN, "mptsas_do_scsi_reset: target=%d",
8430                     devhdl);
8431         }
8432 
8433         /*
8434          * Issue a Target Reset message to the target specified but not to a
8435          * disk making up a raid volume.  Just look through the RAID config
8436          * Phys Disk list of DevHandles.  If the target's DevHandle is in this
8437          * list, then don't reset this target.
8438          */
8439         for (config = 0; config < slots->m_num_raid_configs; config++) {
8440                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
8441                         if (devhdl == slots->m_raidconfig[config].
8442                             m_physdisk_devhdl[disk]) {
8443                                 return (TRUE);
8444                         }
8445                 }
8446         }
8447 
8448         rval = mptsas_ioc_task_management(mpt,
8449             MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, devhdl, 0, NULL, 0, 0);
8450 
8451         mptsas_doneq_empty(mpt);
8452         return (rval);
8453 }
8454 
8455 static int
8456 mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
8457         void (*callback)(caddr_t), caddr_t arg)
8458 {
8459         mptsas_t        *mpt = ADDR2MPT(ap);
8460 
8461         NDBG22(("mptsas_scsi_reset_notify: tgt=%d", ap->a_target));


8517  * commands for a particular target.   For the case of abort task set, this
8518  * function clears the waitq of all commonds for a particular target/lun.
8519  */
8520 static void
8521 mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun, uint8_t tasktype)
8522 {
8523         mptsas_slots_t  *slots = mpt->m_active;
8524         mptsas_cmd_t    *cmd, *next_cmd;
8525         int             slot;
8526         uchar_t         reason;
8527         uint_t          stat;
8528 
8529         NDBG25(("mptsas_flush_target: target=%d lun=%d", target, lun));
8530 
8531         /*
8532          * Make sure the I/O Controller has flushed all cmds
8533          * that are associated with this target for a target reset
8534          * and target/lun for abort task set.
8535          * Account for TM requests, which use the last SMID.
8536          */
8537         for (slot = 0; slot <= mpt->m_active->m_n_slots; slot++) {
8538                 if ((cmd = slots->m_slot[slot]) == NULL)
8539                         continue;
8540                 reason = CMD_RESET;
8541                 stat = STAT_DEV_RESET;
8542                 switch (tasktype) {
8543                 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
8544                         if (Tgt(cmd) == target) {
8545                                 NDBG25(("mptsas_flush_target discovered non-"
8546                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
8547                                     tasktype));
8548                                 mptsas_dump_cmd(mpt, cmd);
8549                                 mptsas_remove_cmd(mpt, cmd);
8550                                 mptsas_set_pkt_reason(mpt, cmd, reason, stat);
8551                                 mptsas_doneq_add(mpt, cmd);
8552                         }
8553                         break;
8554                 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
8555                         reason = CMD_ABORTED;
8556                         stat = STAT_ABORTED;
8557                         /*FALLTHROUGH*/


8649 
8650 /*
8651  * Clean up hba state, abort all outstanding command and commands in waitq
8652  * reset timeout of all targets.
8653  */
8654 static void
8655 mptsas_flush_hba(mptsas_t *mpt)
8656 {
8657         mptsas_slots_t  *slots = mpt->m_active;
8658         mptsas_cmd_t    *cmd;
8659         int             slot;
8660 
8661         NDBG25(("mptsas_flush_hba"));
8662 
8663         /*
8664          * The I/O Controller should have already sent back
8665          * all commands via the scsi I/O reply frame.  Make
8666          * sure all commands have been flushed.
8667          * Account for TM request, which use the last SMID.
8668          */
8669         for (slot = 0; slot <= mpt->m_active->m_n_slots; slot++) {
8670                 if ((cmd = slots->m_slot[slot]) == NULL)
8671                         continue;
8672 
8673                 if (cmd->cmd_flags & CFLAG_CMDIOC) {
8674                         /*
8675                          * Need to make sure to tell everyone that might be
8676                          * waiting on this command that it's going to fail.  If
8677                          * we get here, this command will never timeout because
8678                          * the active command table is going to be re-allocated,
8679                          * so there will be nothing to check against a time out.
8680                          * Instead, mark the command as failed due to reset.
8681                          */
8682                         mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
8683                             STAT_BUS_RESET);
8684                         if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
8685                             (cmd->cmd_flags & CFLAG_CONFIG) ||
8686                             (cmd->cmd_flags & CFLAG_FW_DIAG)) {
8687                                 cmd->cmd_flags |= CFLAG_FINISHED;
8688                                 cv_broadcast(&mpt->m_passthru_cv);
8689                                 cv_broadcast(&mpt->m_config_cv);


8764 static void
8765 mptsas_start_watch_reset_delay()
8766 {
8767         NDBG22(("mptsas_start_watch_reset_delay"));
8768 
8769         mutex_enter(&mptsas_global_mutex);
8770         if (mptsas_reset_watch == NULL && mptsas_timeouts_enabled) {
8771                 mptsas_reset_watch = timeout(mptsas_watch_reset_delay, NULL,
8772                     drv_usectohz((clock_t)
8773                     MPTSAS_WATCH_RESET_DELAY_TICK * 1000));
8774                 ASSERT(mptsas_reset_watch != NULL);
8775         }
8776         mutex_exit(&mptsas_global_mutex);
8777 }
8778 
8779 static void
8780 mptsas_setup_bus_reset_delay(mptsas_t *mpt)
8781 {
8782         mptsas_target_t *ptgt = NULL;
8783 


8784         NDBG22(("mptsas_setup_bus_reset_delay"));
8785         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
8786             MPTSAS_HASH_FIRST);
8787         while (ptgt != NULL) {
8788                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
8789                 ptgt->m_reset_delay = mpt->m_scsi_reset_delay;
8790 
8791                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
8792                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
8793         }
8794 
8795         mptsas_start_watch_reset_delay();
8796 }
8797 
8798 /*
8799  * mptsas_watch_reset_delay(_subr) is invoked by timeout() and checks every
8800  * mpt instance for active reset delays
8801  */
8802 static void
8803 mptsas_watch_reset_delay(void *arg)
8804 {
8805 #ifndef __lock_lint
8806         _NOTE(ARGUNUSED(arg))
8807 #endif
8808 
8809         mptsas_t        *mpt;
8810         int             not_done = 0;
8811 
8812         NDBG22(("mptsas_watch_reset_delay"));


8824                 mutex_exit(&mpt->m_mutex);
8825         }
8826         rw_exit(&mptsas_global_rwlock);
8827 
8828         if (not_done) {
8829                 mptsas_start_watch_reset_delay();
8830         }
8831 }
8832 
8833 static int
8834 mptsas_watch_reset_delay_subr(mptsas_t *mpt)
8835 {
8836         int             done = 0;
8837         int             restart = 0;
8838         mptsas_target_t *ptgt = NULL;
8839 
8840         NDBG22(("mptsas_watch_reset_delay_subr: mpt=0x%p", (void *)mpt));
8841 
8842         ASSERT(mutex_owned(&mpt->m_mutex));
8843 
8844         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
8845             MPTSAS_HASH_FIRST);
8846         while (ptgt != NULL) {
8847                 if (ptgt->m_reset_delay != 0) {
8848                         ptgt->m_reset_delay -=
8849                             MPTSAS_WATCH_RESET_DELAY_TICK;
8850                         if (ptgt->m_reset_delay <= 0) {
8851                                 ptgt->m_reset_delay = 0;
8852                                 mptsas_set_throttle(mpt, ptgt,
8853                                     MAX_THROTTLE);
8854                                 restart++;
8855                         } else {
8856                                 done = -1;
8857                         }
8858                 }
8859 
8860                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
8861                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
8862         }
8863 
8864         if (restart > 0) {
8865                 mptsas_restart_hba(mpt);
8866         }
8867         return (done);
8868 }
8869 
8870 #ifdef MPTSAS_TEST
8871 static void
8872 mptsas_test_reset(mptsas_t *mpt, int target)
8873 {
8874         mptsas_target_t    *ptgt = NULL;
8875 
8876         if (mptsas_rtest == target) {
8877                 if (mptsas_do_scsi_reset(mpt, target) == TRUE) {
8878                         mptsas_rtest = -1;
8879                 }
8880                 if (mptsas_rtest == -1) {
8881                         NDBG22(("mptsas_test_reset success"));


9145  */
9146 /*ARGSUSED*/
9147 static int
9148 mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp)
9149 {
9150         NDBG24(("mptsas_scsi_capchk: cap=%s", cap));
9151 
9152         if (!cap)
9153                 return (FALSE);
9154 
9155         *cidxp = scsi_hba_lookup_capstr(cap);
9156         return (TRUE);
9157 }
9158 
9159 static int
9160 mptsas_alloc_active_slots(mptsas_t *mpt, int flag)
9161 {
9162         mptsas_slots_t  *old_active = mpt->m_active;
9163         mptsas_slots_t  *new_active;
9164         size_t          size;
9165         int             rval = -1, i;
9166 
9167         /*
9168          * if there are active commands, then we cannot
9169          * change size of active slots array.
9170          */
9171         ASSERT(mpt->m_ncmds == 0);
9172 
9173         size = MPTSAS_SLOTS_SIZE(mpt);
9174         new_active = kmem_zalloc(size, flag);
9175         if (new_active == NULL) {
9176                 NDBG1(("new active alloc failed"));
9177                 return (rval);
9178         }
9179         /*
9180          * Since SMID 0 is reserved and the TM slot is reserved, the
9181          * number of slots that can be used at any one time is
9182          * m_max_requests - 2.
9183          */
9184         new_active->m_n_slots = (mpt->m_max_requests - 2);
9185         new_active->m_size = size;
9186         new_active->m_tags = 1;
9187         if (old_active) {
9188                 new_active->m_tgttbl = old_active->m_tgttbl;
9189                 new_active->m_smptbl = old_active->m_smptbl;
9190                 new_active->m_num_raid_configs =
9191                     old_active->m_num_raid_configs;
9192                 for (i = 0; i < new_active->m_num_raid_configs; i++) {
9193                         new_active->m_raidconfig[i] =
9194                             old_active->m_raidconfig[i];
9195                 }
9196                 mptsas_free_active_slots(mpt);
9197         }
9198         mpt->m_active = new_active;
9199         rval = 0;
9200 
9201         return (rval);
9202 }
9203 
9204 static void
9205 mptsas_free_active_slots(mptsas_t *mpt)
9206 {
9207         mptsas_slots_t  *active = mpt->m_active;
9208         size_t          size;
9209 
9210         if (active == NULL)
9211                 return;
9212         size = active->m_size;
9213         kmem_free(active, size);
9214         mpt->m_active = NULL;
9215 }
9216 
9217 /*
9218  * Error logging, printing, and debug print routines.
9219  */
9220 static char *mptsas_label = "mpt_sas";
9221 


9326                         (void) pm_idle_component(mpt->m_dip, 0);
9327                 }
9328 
9329                 mutex_exit(&mpt->m_mutex);
9330         }
9331         rw_exit(&mptsas_global_rwlock);
9332 
9333         mutex_enter(&mptsas_global_mutex);
9334         if (mptsas_timeouts_enabled)
9335                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
9336         mutex_exit(&mptsas_global_mutex);
9337 }
9338 
9339 static void
9340 mptsas_watchsubr(mptsas_t *mpt)
9341 {
9342         int             i;
9343         mptsas_cmd_t    *cmd;
9344         mptsas_target_t *ptgt = NULL;
9345 


9346         NDBG30(("mptsas_watchsubr: mpt=0x%p", (void *)mpt));
9347 
9348 #ifdef MPTSAS_TEST
9349         if (mptsas_enable_untagged) {
9350                 mptsas_test_untagged++;
9351         }
9352 #endif
9353 
9354         /*
9355          * Check for commands stuck in active slot
9356          * Account for TM requests, which use the last SMID.
9357          */
9358         for (i = 0; i <= mpt->m_active->m_n_slots; i++) {
9359                 if ((cmd = mpt->m_active->m_slot[i]) != NULL) {
9360                         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
9361                                 cmd->cmd_active_timeout -=
9362                                     mptsas_scsi_watchdog_tick;
9363                                 if (cmd->cmd_active_timeout <= 0) {
9364                                         /*
9365                                          * There seems to be a command stuck
9366                                          * in the active slot.  Drain throttle.
9367                                          */
9368                                         mptsas_set_throttle(mpt,
9369                                             cmd->cmd_tgt_addr,
9370                                             DRAIN_THROTTLE);
9371                                 }
9372                         }
9373                         if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
9374                             (cmd->cmd_flags & CFLAG_CONFIG) ||
9375                             (cmd->cmd_flags & CFLAG_FW_DIAG)) {
9376                                 cmd->cmd_active_timeout -=
9377                                     mptsas_scsi_watchdog_tick;
9378                                 if (cmd->cmd_active_timeout <= 0) {
9379                                         /*
9380                                          * passthrough command timeout
9381                                          */
9382                                         cmd->cmd_flags |= (CFLAG_FINISHED |
9383                                             CFLAG_TIMEOUT);
9384                                         cv_broadcast(&mpt->m_passthru_cv);
9385                                         cv_broadcast(&mpt->m_config_cv);
9386                                         cv_broadcast(&mpt->m_fw_diag_cv);
9387                                 }
9388                         }
9389                 }
9390         }
9391 
9392         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
9393             MPTSAS_HASH_FIRST);
9394         while (ptgt != NULL) {
9395                 /*
9396                  * If we were draining due to a qfull condition,
9397                  * go back to full throttle.
9398                  */
9399                 if ((ptgt->m_t_throttle < MAX_THROTTLE) &&
9400                     (ptgt->m_t_throttle > HOLD_THROTTLE) &&
9401                     (ptgt->m_t_ncmds < ptgt->m_t_throttle)) {
9402                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9403                         mptsas_restart_hba(mpt);
9404                 }
9405 
9406                 if ((ptgt->m_t_ncmds > 0) &&
9407                     (ptgt->m_timebase)) {
9408 
9409                         if (ptgt->m_timebase <=
9410                             mptsas_scsi_watchdog_tick) {
9411                                 ptgt->m_timebase +=
9412                                     mptsas_scsi_watchdog_tick;
9413                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
9414                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
9415                                 continue;
9416                         }
9417 
9418                         ptgt->m_timeout -= mptsas_scsi_watchdog_tick;
9419 
9420                         if (ptgt->m_timeout < 0) {
9421                                 mptsas_cmd_timeout(mpt, ptgt->m_devhdl);
9422                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
9423                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
9424                                 continue;
9425                         }
9426 
9427                         if ((ptgt->m_timeout) <=
9428                             mptsas_scsi_watchdog_tick) {
9429                                 NDBG23(("pending timeout"));
9430                                 mptsas_set_throttle(mpt, ptgt,
9431                                     DRAIN_THROTTLE);
9432                         }
9433                 }
9434 
9435                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
9436                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
9437         }
9438 }
9439 
9440 /*
9441  * timeout recovery
9442  */
9443 static void
9444 mptsas_cmd_timeout(mptsas_t *mpt, uint16_t devhdl)
9445 {
9446 
9447         NDBG29(("mptsas_cmd_timeout: target=%d", devhdl));
9448         mptsas_log(mpt, CE_WARN, "Disconnected command timeout for "
9449             "Target %d", devhdl);
9450 
9451         /*
9452          * If the current target is not the target passed in,
9453          * try to reset that target.
9454          */
9455         NDBG29(("mptsas_cmd_timeout: device reset"));
9456         if (mptsas_do_scsi_reset(mpt, devhdl) != TRUE) {


9480 {
9481         mptsas_t                *mpt;
9482         scsi_hba_tran_t *tran;
9483 
9484         tran = ddi_get_driver_private(dip);
9485         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
9486                 return (-1);
9487 
9488         return (mptsas_unquiesce_bus(mpt));
9489 }
9490 
9491 static int
9492 mptsas_quiesce_bus(mptsas_t *mpt)
9493 {
9494         mptsas_target_t *ptgt = NULL;
9495 
9496         NDBG28(("mptsas_quiesce_bus"));
9497         mutex_enter(&mpt->m_mutex);
9498 
9499         /* Set all the throttles to zero */
9500         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
9501             MPTSAS_HASH_FIRST);
9502         while (ptgt != NULL) {
9503                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9504 
9505                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
9506                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
9507         }
9508 
9509         /* If there are any outstanding commands in the queue */
9510         if (mpt->m_ncmds) {
9511                 mpt->m_softstate |= MPTSAS_SS_DRAINING;
9512                 mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
9513                     mpt, (MPTSAS_QUIESCE_TIMEOUT * drv_usectohz(1000000)));
9514                 if (cv_wait_sig(&mpt->m_cv, &mpt->m_mutex) == 0) {
9515                         /*
9516                          * Quiesce has been interrupted
9517                          */
9518                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
9519                         ptgt = (mptsas_target_t *)mptsas_hash_traverse(
9520                             &mpt->m_active->m_tgttbl, MPTSAS_HASH_FIRST);
9521                         while (ptgt != NULL) {
9522                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9523 
9524                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
9525                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
9526                         }
9527                         mptsas_restart_hba(mpt);
9528                         if (mpt->m_quiesce_timeid != 0) {
9529                                 timeout_id_t tid = mpt->m_quiesce_timeid;
9530                                 mpt->m_quiesce_timeid = 0;
9531                                 mutex_exit(&mpt->m_mutex);
9532                                 (void) untimeout(tid);
9533                                 return (-1);
9534                         }
9535                         mutex_exit(&mpt->m_mutex);
9536                         return (-1);
9537                 } else {
9538                         /* Bus has been quiesced */
9539                         ASSERT(mpt->m_quiesce_timeid == 0);
9540                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
9541                         mpt->m_softstate |= MPTSAS_SS_QUIESCED;
9542                         mutex_exit(&mpt->m_mutex);
9543                         return (0);
9544                 }
9545         }
9546         /* Bus was not busy - QUIESCED */
9547         mutex_exit(&mpt->m_mutex);
9548 
9549         return (0);
9550 }
9551 
9552 static int
9553 mptsas_unquiesce_bus(mptsas_t *mpt)
9554 {
9555         mptsas_target_t *ptgt = NULL;
9556 
9557         NDBG28(("mptsas_unquiesce_bus"));
9558         mutex_enter(&mpt->m_mutex);
9559         mpt->m_softstate &= ~MPTSAS_SS_QUIESCED;
9560         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
9561             MPTSAS_HASH_FIRST);
9562         while (ptgt != NULL) {
9563                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9564 
9565                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
9566                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
9567         }
9568         mptsas_restart_hba(mpt);
9569         mutex_exit(&mpt->m_mutex);
9570         return (0);
9571 }
9572 
9573 static void
9574 mptsas_ncmds_checkdrain(void *arg)
9575 {
9576         mptsas_t        *mpt = arg;
9577         mptsas_target_t *ptgt = NULL;
9578 
9579         mutex_enter(&mpt->m_mutex);
9580         if (mpt->m_softstate & MPTSAS_SS_DRAINING) {
9581                 mpt->m_quiesce_timeid = 0;
9582                 if (mpt->m_ncmds == 0) {
9583                         /* Command queue has been drained */
9584                         cv_signal(&mpt->m_cv);
9585                 } else {
9586                         /*
9587                          * The throttle may have been reset because
9588                          * of a SCSI bus reset
9589                          */
9590                         ptgt = (mptsas_target_t *)mptsas_hash_traverse(
9591                             &mpt->m_active->m_tgttbl, MPTSAS_HASH_FIRST);
9592                         while (ptgt != NULL) {
9593                                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9594 
9595                                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
9596                                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
9597                         }
9598 
9599                         mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
9600                             mpt, (MPTSAS_QUIESCE_TIMEOUT *
9601                             drv_usectohz(1000000)));
9602                 }
9603         }
9604         mutex_exit(&mpt->m_mutex);
9605 }
9606 
9607 /*ARGSUSED*/
9608 static void
9609 mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
9610 {
9611         int     i;
9612         uint8_t *cp = (uchar_t *)cmd->cmd_pkt->pkt_cdbp;
9613         char    buf[128];
9614 
9615         buf[0] = '\0';
9616         NDBG25(("?Cmd (0x%p) dump for Target %d Lun %d:\n", (void *)cmd,


11308 
11309         if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) {
11310                 return (EFAULT);
11311         }
11312 
11313         if ((lc.Command != MPTSAS_LEDCTL_FLAG_SET &&
11314             lc.Command != MPTSAS_LEDCTL_FLAG_GET) ||
11315             lc.Led < MPTSAS_LEDCTL_LED_MIN ||
11316             lc.Led > MPTSAS_LEDCTL_LED_MAX ||
11317             (lc.Command == MPTSAS_LEDCTL_FLAG_SET && lc.LedStatus != 0 &&
11318             lc.LedStatus != 1)) {
11319                 return (EINVAL);
11320         }
11321 
11322         if ((lc.Command == MPTSAS_LEDCTL_FLAG_SET && (mode & FWRITE) == 0) ||
11323             (lc.Command == MPTSAS_LEDCTL_FLAG_GET && (mode & FREAD) == 0))
11324                 return (EACCES);
11325 
11326         /* Locate the target we're interrogating... */
11327         mutex_enter(&mpt->m_mutex);
11328         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
11329             MPTSAS_HASH_FIRST);
11330         while (ptgt != NULL) {
11331                 if (ptgt->m_enclosure == lc.Enclosure &&
11332                     ptgt->m_slot_num == lc.Slot) {
11333                         break;
11334                 }
11335                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
11336                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
11337         }
11338         if (ptgt == NULL) {
11339                 /* We could not find a target for that enclosure/slot. */
11340                 mutex_exit(&mpt->m_mutex);
11341                 return (ENOENT);
11342         }
11343 
11344         if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) {
11345                 /* Update our internal LED state. */
11346                 ptgt->m_led_status &= ~(1 << (lc.Led - 1));
11347                 ptgt->m_led_status |= lc.LedStatus << (lc.Led - 1);
11348 
11349                 /* Flush it to the controller. */
11350                 ret = mptsas_flush_led_status(mpt, ptgt);
11351                 mutex_exit(&mpt->m_mutex);
11352                 return (ret);
11353         }
11354 
11355         /* Return our internal LED state. */
11356         lc.LedStatus = (ptgt->m_led_status >> (lc.Led - 1)) & 1;
11357         mutex_exit(&mpt->m_mutex);


11368 {
11369         uint16_t i = 0;
11370         uint16_t count = 0;
11371         int ret = 0;
11372         mptsas_target_t *ptgt;
11373         mptsas_disk_info_t *di;
11374         STRUCT_DECL(mptsas_get_disk_info, gdi);
11375 
11376         if ((mode & FREAD) == 0)
11377                 return (EACCES);
11378 
11379         STRUCT_INIT(gdi, get_udatamodel());
11380 
11381         if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi),
11382             mode) != 0) {
11383                 return (EFAULT);
11384         }
11385 
11386         /* Find out how many targets there are. */
11387         mutex_enter(&mpt->m_mutex);
11388         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
11389             MPTSAS_HASH_FIRST);
11390         while (ptgt != NULL) {
11391                 count++;
11392                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
11393                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
11394         }
11395         mutex_exit(&mpt->m_mutex);
11396 
11397         /*
11398          * If we haven't been asked to copy out information on each target,
11399          * then just return the count.
11400          */
11401         STRUCT_FSET(gdi, DiskCount, count);
11402         if (STRUCT_FGETP(gdi, PtrDiskInfoArray) == NULL)
11403                 goto copy_out;
11404 
11405         /*
11406          * If we haven't been given a large enough buffer to copy out into,
11407          * let the caller know.
11408          */
11409         if (STRUCT_FGET(gdi, DiskInfoArraySize) <
11410             count * sizeof (mptsas_disk_info_t)) {
11411                 ret = ENOSPC;
11412                 goto copy_out;
11413         }
11414 
11415         di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP);
11416 
11417         mutex_enter(&mpt->m_mutex);
11418         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
11419             MPTSAS_HASH_FIRST);
11420         while (ptgt != NULL) {
11421                 if (i >= count) {
11422                         /*
11423                          * The number of targets changed while we weren't
11424                          * looking, so give up.
11425                          */

11426                         mutex_exit(&mpt->m_mutex);
11427                         kmem_free(di, count * sizeof (mptsas_disk_info_t));
11428                         return (EAGAIN);
11429                 }
11430                 di[i].Instance = mpt->m_instance;
11431                 di[i].Enclosure = ptgt->m_enclosure;
11432                 di[i].Slot = ptgt->m_slot_num;
11433                 di[i].SasAddress = ptgt->m_sas_wwn;
11434 
11435                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
11436                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
11437                 i++;
11438         }
11439         mutex_exit(&mpt->m_mutex);
11440         STRUCT_FSET(gdi, DiskCount, i);
11441 
11442         /* Copy out the disk information to the caller. */
11443         if (ddi_copyout((void *)di, STRUCT_FGETP(gdi, PtrDiskInfoArray),
11444             i * sizeof (mptsas_disk_info_t), mode) != 0) {
11445                 ret = EFAULT;
11446         }
11447 
11448         kmem_free(di, count * sizeof (mptsas_disk_info_t));
11449 
11450 copy_out:
11451         if (ddi_copyout(STRUCT_BUF(gdi), (void *)data, STRUCT_SIZE(gdi),
11452             mode) != 0) {
11453                 ret = EFAULT;
11454         }
11455 
11456         return (ret);


11722 int
11723 mptsas_restart_ioc(mptsas_t *mpt)
11724 {
11725         int             rval = DDI_SUCCESS;
11726         mptsas_target_t *ptgt = NULL;
11727 
11728         ASSERT(mutex_owned(&mpt->m_mutex));
11729 
11730         /*
11731          * Set a flag telling I/O path that we're processing a reset.  This is
11732          * needed because after the reset is complete, the hash table still
11733          * needs to be rebuilt.  If I/Os are started before the hash table is
11734          * rebuilt, I/O errors will occur.  This flag allows I/Os to be marked
11735          * so that they can be retried.
11736          */
11737         mpt->m_in_reset = TRUE;
11738 
11739         /*
11740          * Set all throttles to HOLD
11741          */
11742         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
11743             MPTSAS_HASH_FIRST);
11744         while (ptgt != NULL) {
11745                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
11746 
11747                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
11748                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
11749         }
11750 
11751         /*
11752          * Disable interrupts
11753          */
11754         MPTSAS_DISABLE_INTR(mpt);
11755 
11756         /*
11757          * Abort all commands: outstanding commands, commands in waitq and
11758          * tx_waitq.
11759          */
11760         mptsas_flush_hba(mpt);
11761 
11762         /*
11763          * Reinitialize the chip.
11764          */
11765         if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
11766                 rval = DDI_FAILURE;
11767         }
11768 
11769         /*
11770          * Enable interrupts again
11771          */
11772         MPTSAS_ENABLE_INTR(mpt);
11773 
11774         /*
11775          * If mptsas_init_chip was successful, update the driver data.
11776          */
11777         if (rval == DDI_SUCCESS) {
11778                 mptsas_update_driver_data(mpt);
11779         }
11780 
11781         /*
11782          * Reset the throttles
11783          */
11784         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
11785             MPTSAS_HASH_FIRST);
11786         while (ptgt != NULL) {
11787                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
11788 
11789                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
11790                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
11791         }
11792 
11793         mptsas_doneq_empty(mpt);
11794         mptsas_restart_hba(mpt);
11795 
11796         if (rval != DDI_SUCCESS) {
11797                 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
11798                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
11799         }
11800 
11801         /*
11802          * Clear the reset flag so that I/Os can continue.
11803          */
11804         mpt->m_in_reset = FALSE;
11805 
11806         return (rval);
11807 }
11808 
11809 static int
11810 mptsas_init_chip(mptsas_t *mpt, int first_time)


11836         }
11837         /*
11838          * Setup configuration space
11839          */
11840         if (mptsas_config_space_init(mpt) == FALSE) {
11841                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init "
11842                     "failed!");
11843                 goto fail;
11844         }
11845 
11846         /*
11847          * IOC facts can change after a diag reset so all buffers that are
11848          * based on these numbers must be de-allocated and re-allocated.  Get
11849          * new IOC facts each time chip is initialized.
11850          */
11851         if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
11852                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed");
11853                 goto fail;
11854         }
11855 






11856         if (mptsas_alloc_active_slots(mpt, KM_SLEEP)) {
11857                 goto fail;
11858         }
11859         /*
11860          * Allocate request message frames, reply free queue, reply descriptor
11861          * post queue, and reply message frames using latest IOC facts.
11862          */
11863         if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) {
11864                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames failed");
11865                 goto fail;
11866         }
11867         if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) {
11868                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue failed!");
11869                 goto fail;
11870         }
11871         if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) {
11872                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue failed!");
11873                 goto fail;
11874         }
11875         if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) {


12474         uint64_t        ena;
12475         char            buf[FM_MAX_CLASS];
12476 
12477         (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
12478         ena = fm_ena_generate(0, FM_ENA_FMT1);
12479         if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities)) {
12480                 ddi_fm_ereport_post(mpt->m_dip, buf, ena, DDI_NOSLEEP,
12481                     FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
12482         }
12483 }
12484 
12485 static int
12486 mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
12487     uint16_t *dev_handle, mptsas_target_t **pptgt)
12488 {
12489         int             rval;
12490         uint32_t        dev_info;
12491         uint64_t        sas_wwn;
12492         mptsas_phymask_t phymask;
12493         uint8_t         physport, phynum, config, disk;
12494         mptsas_slots_t  *slots = mpt->m_active;
12495         uint64_t        devicename;
12496         uint16_t        pdev_hdl;
12497         mptsas_target_t *tmp_tgt = NULL;
12498         uint16_t        bay_num, enclosure;
12499 
12500         ASSERT(*pptgt == NULL);
12501 
12502         rval = mptsas_get_sas_device_page0(mpt, page_address, dev_handle,
12503             &sas_wwn, &dev_info, &physport, &phynum, &pdev_hdl,
12504             &bay_num, &enclosure);
12505         if (rval != DDI_SUCCESS) {
12506                 rval = DEV_INFO_FAIL_PAGE0;
12507                 return (rval);
12508         }
12509 
12510         if ((dev_info & (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
12511             MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
12512             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) == NULL) {
12513                 rval = DEV_INFO_WRONG_DEVICE_TYPE;
12514                 return (rval);
12515         }
12516 
12517         /*
12518          * Check if the dev handle is for a Phys Disk. If so, set return value
12519          * and exit.  Don't add Phys Disks to hash.
12520          */
12521         for (config = 0; config < slots->m_num_raid_configs; config++) {
12522                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
12523                         if (*dev_handle == slots->m_raidconfig[config].
12524                             m_physdisk_devhdl[disk]) {
12525                                 rval = DEV_INFO_PHYS_DISK;
12526                                 return (rval);
12527                         }
12528                 }
12529         }
12530 
12531         /*
12532          * Get SATA Device Name from SAS device page0 for
12533          * sata device, if device name doesn't exist, set m_sas_wwn to
12534          * 0 for direct attached SATA. For the device behind the expander
12535          * we still can use STP address assigned by expander.
12536          */
12537         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
12538             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
12539                 mutex_exit(&mpt->m_mutex);
12540                 /* alloc a tmp_tgt to send the cmd */
12541                 tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target),
12542                     KM_SLEEP);
12543                 tmp_tgt->m_devhdl = *dev_handle;
12544                 tmp_tgt->m_deviceinfo = dev_info;
12545                 tmp_tgt->m_qfull_retries = QFULL_RETRIES;
12546                 tmp_tgt->m_qfull_retry_interval =
12547                     drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
12548                 tmp_tgt->m_t_throttle = MAX_THROTTLE;
12549                 devicename = mptsas_get_sata_guid(mpt, tmp_tgt, 0);
12550                 kmem_free(tmp_tgt, sizeof (struct mptsas_target));
12551                 mutex_enter(&mpt->m_mutex);
12552                 if (devicename != 0 && (((devicename >> 56) & 0xf0) == 0x50)) {
12553                         sas_wwn = devicename;
12554                 } else if (dev_info & MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH) {
12555                         sas_wwn = 0;
12556                 }
12557         }
12558 
12559         phymask = mptsas_physport_to_phymask(mpt, physport);
12560         *pptgt = mptsas_tgt_alloc(&slots->m_tgttbl, *dev_handle, sas_wwn,
12561             dev_info, phymask, phynum);
12562         if (*pptgt == NULL) {
12563                 mptsas_log(mpt, CE_WARN, "Failed to allocated target"
12564                     "structure!");
12565                 rval = DEV_INFO_FAIL_ALLOC;
12566                 return (rval);
12567         }
12568         (*pptgt)->m_enclosure = enclosure;
12569         (*pptgt)->m_slot_num = bay_num;
12570         return (DEV_INFO_SUCCESS);
12571 }
12572 
12573 uint64_t
12574 mptsas_get_sata_guid(mptsas_t *mpt, mptsas_target_t *ptgt, int lun)
12575 {
12576         uint64_t        sata_guid = 0, *pwwn = NULL;
12577         int             target = ptgt->m_devhdl;
12578         uchar_t         *inq83 = NULL;
12579         int             inq83_len = 0xFF;
12580         uchar_t         *dblk = NULL;


12970                  * didn't match any device by searching
12971                  */
12972                 return (DDI_FAILURE);
12973         }
12974         /*
12975          * If the LUN already exists and the status is online,
12976          * we just return the pointer to dev_info_t directly.
12977          * For the mdi_pathinfo node, we'll handle it in
12978          * mptsas_create_virt_lun()
12979          * TODO should be also in mptsas_handle_dr
12980          */
12981 
12982         *lundip = mptsas_find_child_addr(pdip, sasaddr, lun);
12983         if (*lundip != NULL) {
12984                 /*
12985                  * TODO Another senario is, we hotplug the same disk
12986                  * on the same slot, the devhdl changed, is this
12987                  * possible?
12988                  * tgt_private->t_private != ptgt
12989                  */
12990                 if (sasaddr != ptgt->m_sas_wwn) {
12991                         /*
12992                          * The device has changed although the devhdl is the
12993                          * same (Enclosure mapping mode, change drive on the
12994                          * same slot)
12995                          */
12996                         return (DDI_FAILURE);
12997                 }
12998                 return (DDI_SUCCESS);
12999         }
13000 
13001         if (phymask == 0) {
13002                 /*
13003                  * Configure IR volume
13004                  */
13005                 rval =  mptsas_config_raid(pdip, ptgt->m_devhdl, lundip);
13006                 return (rval);
13007         }
13008         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
13009 
13010         return (rval);
13011 }
13012 
13013 static int
13014 mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
13015     dev_info_t **lundip)
13016 {
13017         int             rval;
13018         mptsas_t        *mpt = DIP2MPT(pdip);
13019         int             phymask;
13020         mptsas_target_t *ptgt = NULL;
13021 
13022         /*
13023          * Get the physical port associated to the iport
13024          */
13025         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13026             "phymask", 0);
13027 
13028         ptgt = mptsas_phy_to_tgt(mpt, phymask, phy);
13029         if (ptgt == NULL) {
13030                 /*
13031                  * didn't match any device by searching
13032                  */
13033                 return (DDI_FAILURE);
13034         }
13035 
13036         /*
13037          * If the LUN already exists and the status is online,
13038          * we just return the pointer to dev_info_t directly.
13039          * For the mdi_pathinfo node, we'll handle it in
13040          * mptsas_create_virt_lun().
13041          */
13042 
13043         *lundip = mptsas_find_child_phy(pdip, phy);
13044         if (*lundip != NULL) {
13045                 return (DDI_SUCCESS);


13092         struct buf              *repluns_bp = NULL;
13093         struct scsi_address     ap;
13094         uchar_t                 cdb[CDB_GROUP5];
13095         int                     ret = DDI_FAILURE;
13096         int                     retry = 0;
13097         int                     lun_list_len = 0;
13098         uint16_t                lun_num = 0;
13099         uint8_t                 lun_addr_type = 0;
13100         uint32_t                lun_cnt = 0;
13101         uint32_t                lun_total = 0;
13102         dev_info_t              *cdip = NULL;
13103         uint16_t                *saved_repluns = NULL;
13104         char                    *buffer = NULL;
13105         int                     buf_len = 128;
13106         mptsas_t                *mpt = DIP2MPT(pdip);
13107         uint64_t                sas_wwn = 0;
13108         uint8_t                 phy = 0xFF;
13109         uint32_t                dev_info = 0;
13110 
13111         mutex_enter(&mpt->m_mutex);
13112         sas_wwn = ptgt->m_sas_wwn;
13113         phy = ptgt->m_phynum;
13114         dev_info = ptgt->m_deviceinfo;
13115         mutex_exit(&mpt->m_mutex);
13116 
13117         if (sas_wwn == 0) {
13118                 /*
13119                  * It's a SATA without Device Name
13120                  * So don't try multi-LUNs
13121                  */
13122                 if (mptsas_find_child_phy(pdip, phy)) {
13123                         return (DDI_SUCCESS);
13124                 } else {
13125                         /*
13126                          * need configure and create node
13127                          */
13128                         return (DDI_FAILURE);
13129                 }
13130         }
13131 
13132         /*


13207                 if ((ret == DDI_SUCCESS) && (cdip != NULL)) {
13208                         (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip,
13209                             MPTSAS_DEV_GONE);
13210                 }
13211         }
13212         mptsas_offline_missed_luns(pdip, saved_repluns, lun_total, ptgt);
13213         kmem_free(saved_repluns, sizeof (uint16_t) * lun_total);
13214         scsi_free_consistent_buf(repluns_bp);
13215         return (DDI_SUCCESS);
13216 }
13217 
13218 static int
13219 mptsas_config_raid(dev_info_t *pdip, uint16_t target, dev_info_t **dip)
13220 {
13221         int                     rval = DDI_FAILURE;
13222         struct scsi_inquiry     *sd_inq = NULL;
13223         mptsas_t                *mpt = DIP2MPT(pdip);
13224         mptsas_target_t         *ptgt = NULL;
13225 
13226         mutex_enter(&mpt->m_mutex);
13227         ptgt = mptsas_search_by_devhdl(&mpt->m_active->m_tgttbl, target);

13228         mutex_exit(&mpt->m_mutex);
13229         if (ptgt == NULL) {
13230                 mptsas_log(mpt, CE_WARN, "Volume with VolDevHandle of 0x%x "
13231                     "not found.", target);
13232                 return (rval);
13233         }
13234 
13235         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
13236         rval = mptsas_inquiry(mpt, ptgt, 0, 0, (uchar_t *)sd_inq,
13237             SUN_INQSIZE, 0, (uchar_t)0);
13238 
13239         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
13240                 rval = mptsas_create_phys_lun(pdip, sd_inq, NULL, dip, ptgt,
13241                     0);
13242         } else {
13243                 rval = DDI_FAILURE;
13244         }
13245 
13246         kmem_free(sd_inq, SUN_INQSIZE);
13247         return (rval);
13248 }
13249 
13250 /*
13251  * configure all RAID volumes for virtual iport
13252  */
13253 static void
13254 mptsas_config_all_viport(dev_info_t *pdip)
13255 {
13256         mptsas_t        *mpt = DIP2MPT(pdip);
13257         int             config, vol;
13258         int             target;
13259         dev_info_t      *lundip = NULL;
13260         mptsas_slots_t  *slots = mpt->m_active;
13261 
13262         /*
13263          * Get latest RAID info and search for any Volume DevHandles.  If any
13264          * are found, configure the volume.
13265          */
13266         mutex_enter(&mpt->m_mutex);
13267         for (config = 0; config < slots->m_num_raid_configs; config++) {
13268                 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
13269                         if (slots->m_raidconfig[config].m_raidvol[vol].m_israid
13270                             == 1) {
13271                                 target = slots->m_raidconfig[config].
13272                                     m_raidvol[vol].m_raidhandle;
13273                                 mutex_exit(&mpt->m_mutex);
13274                                 (void) mptsas_config_raid(pdip, target,
13275                                     &lundip);
13276                                 mutex_enter(&mpt->m_mutex);
13277                         }
13278                 }
13279         }
13280         mutex_exit(&mpt->m_mutex);
13281 }
13282 
13283 static void
13284 mptsas_offline_missed_luns(dev_info_t *pdip, uint16_t *repluns,
13285     int lun_cnt, mptsas_target_t *ptgt)
13286 {
13287         dev_info_t      *child = NULL, *savechild = NULL;
13288         mdi_pathinfo_t  *pip = NULL, *savepip = NULL;
13289         uint64_t        sas_wwn, wwid;
13290         uint8_t         phy;
13291         int             lun;
13292         int             i;
13293         int             find;
13294         char            *addr;
13295         char            *nodename;
13296         mptsas_t        *mpt = DIP2MPT(pdip);
13297 
13298         mutex_enter(&mpt->m_mutex);
13299         wwid = ptgt->m_sas_wwn;
13300         mutex_exit(&mpt->m_mutex);
13301 
13302         child = ddi_get_child(pdip);
13303         while (child) {
13304                 find = 0;
13305                 savechild = child;
13306                 child = ddi_get_next_sibling(child);
13307 
13308                 nodename = ddi_node_name(savechild);
13309                 if (strcmp(nodename, "smp") == 0) {
13310                         continue;
13311                 }
13312 
13313                 addr = ddi_get_name_addr(savechild);
13314                 if (addr == NULL) {
13315                         continue;
13316                 }
13317 
13318                 if (mptsas_parse_address(addr, &sas_wwn, &phy, &lun) !=
13319                     DDI_SUCCESS) {


13383         uint32_t        page_address;
13384         int             rval = 0;
13385         uint16_t        dev_handle;
13386         mptsas_target_t *ptgt = NULL;
13387         mptsas_smp_t    smp_node;
13388 
13389         /*
13390          * Get latest RAID info.
13391          */
13392         (void) mptsas_get_raid_info(mpt);
13393 
13394         dev_handle = mpt->m_smp_devhdl;
13395         for (; mpt->m_done_traverse_smp == 0; ) {
13396                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
13397                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)dev_handle;
13398                 if (mptsas_get_sas_expander_page0(mpt, page_address, &smp_node)
13399                     != DDI_SUCCESS) {
13400                         break;
13401                 }
13402                 mpt->m_smp_devhdl = dev_handle = smp_node.m_devhdl;
13403                 (void) mptsas_smp_alloc(&mpt->m_active->m_smptbl, &smp_node);
13404         }
13405 
13406         /*
13407          * Config target devices
13408          */
13409         dev_handle = mpt->m_dev_handle;
13410 
13411         /*
13412          * Do loop to get sas device page 0 by GetNextHandle till the
13413          * the last handle. If the sas device is a SATA/SSP target,
13414          * we try to config it.
13415          */
13416         for (; mpt->m_done_traverse_dev == 0; ) {
13417                 ptgt = NULL;
13418                 page_address =
13419                     (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
13420                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
13421                     (uint32_t)dev_handle;
13422                 rval = mptsas_get_target_device_info(mpt, page_address,
13423                     &dev_handle, &ptgt);
13424                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
13425                     (rval == DEV_INFO_FAIL_ALLOC)) {
13426                         break;
13427                 }
13428 
13429                 mpt->m_dev_handle = dev_handle;
13430         }
13431 
13432 }
13433 
13434 void
13435 mptsas_invalid_hashtab(mptsas_hash_table_t *hashtab)
13436 {
13437         mptsas_hash_data_t *data;
13438         data = mptsas_hash_traverse(hashtab, MPTSAS_HASH_FIRST);
13439         while (data != NULL) {
13440                 data->devhdl = MPTSAS_INVALID_DEVHDL;
13441                 data->device_info = 0;
13442                 /*
13443                  * For tgttbl, clear dr_flag.
13444                  */
13445                 data->dr_flag = MPTSAS_DR_INACTIVE;
13446                 data = mptsas_hash_traverse(hashtab, MPTSAS_HASH_NEXT);
13447         }
13448 }
13449 
13450 void
13451 mptsas_update_driver_data(struct mptsas *mpt)
13452 {





13453         /*
13454          * TODO after hard reset, update the driver data structures
13455          * 1. update port/phymask mapping table mpt->m_phy_info
13456          * 2. invalid all the entries in hash table
13457          *    m_devhdl = 0xffff and m_deviceinfo = 0
13458          * 3. call sas_device_page/expander_page to update hash table
13459          */
13460         mptsas_update_phymask(mpt);
13461         /*
13462          * Invalid the existing entries






13463          */
13464         mptsas_invalid_hashtab(&mpt->m_active->m_tgttbl);
13465         mptsas_invalid_hashtab(&mpt->m_active->m_smptbl);









13466         mpt->m_done_traverse_dev = 0;
13467         mpt->m_done_traverse_smp = 0;
13468         mpt->m_dev_handle = mpt->m_smp_devhdl = MPTSAS_INVALID_DEVHDL;
13469         mptsas_update_hashtab(mpt);
13470 }
13471 
13472 static void
13473 mptsas_config_all(dev_info_t *pdip)
13474 {
13475         dev_info_t      *smpdip = NULL;
13476         mptsas_t        *mpt = DIP2MPT(pdip);
13477         int             phymask = 0;
13478         mptsas_phymask_t phy_mask;
13479         mptsas_target_t *ptgt = NULL;
13480         mptsas_smp_t    *psmp;
13481 
13482         /*
13483          * Get the phymask associated to the iport
13484          */
13485         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13486             "phymask", 0);
13487 
13488         /*
13489          * Enumerate RAID volumes here (phymask == 0).
13490          */
13491         if (phymask == 0) {
13492                 mptsas_config_all_viport(pdip);
13493                 return;
13494         }
13495 
13496         mutex_enter(&mpt->m_mutex);
13497 
13498         if (!mpt->m_done_traverse_dev || !mpt->m_done_traverse_smp) {
13499                 mptsas_update_hashtab(mpt);
13500         }
13501 
13502         psmp = (mptsas_smp_t *)mptsas_hash_traverse(&mpt->m_active->m_smptbl,
13503             MPTSAS_HASH_FIRST);
13504         while (psmp != NULL) {
13505                 phy_mask = psmp->m_phymask;
13506                 if (phy_mask == phymask) {
13507                         smpdip = NULL;
13508                         mutex_exit(&mpt->m_mutex);
13509                         (void) mptsas_online_smp(pdip, psmp, &smpdip);
13510                         mutex_enter(&mpt->m_mutex);
13511                 }
13512                 psmp = (mptsas_smp_t *)mptsas_hash_traverse(
13513                     &mpt->m_active->m_smptbl, MPTSAS_HASH_NEXT);
13514         }
13515 
13516         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
13517             MPTSAS_HASH_FIRST);
13518         while (ptgt != NULL) {
13519                 phy_mask = ptgt->m_phymask;
13520                 if (phy_mask == phymask) {
13521                         mutex_exit(&mpt->m_mutex);
13522                         (void) mptsas_config_target(pdip, ptgt);
13523                         mutex_enter(&mpt->m_mutex);
13524                 }
13525 
13526                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
13527                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
13528         }
13529         mutex_exit(&mpt->m_mutex);
13530 }
13531 
13532 static int
13533 mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt)
13534 {
13535         int             rval = DDI_FAILURE;
13536         dev_info_t      *tdip;
13537 
13538         rval = mptsas_config_luns(pdip, ptgt);
13539         if (rval != DDI_SUCCESS) {
13540                 /*
13541                  * The return value means the SCMD_REPORT_LUNS
13542                  * did not execute successfully. The target maybe
13543                  * doesn't support such command.
13544                  */
13545                 rval = mptsas_probe_lun(pdip, 0, &tdip, ptgt);
13546         }
13547         return (rval);


13689                 }
13690 
13691                 if (strcmp(smp_wwn, str_wwn) == 0) {
13692                         ddi_prop_free(smp_wwn);
13693                         break;
13694                 }
13695                 child = ddi_get_next_sibling(child);
13696                 ddi_prop_free(smp_wwn);
13697         }
13698         return (child);
13699 }
13700 
13701 static int
13702 mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, uint_t flags)
13703 {
13704         int             rval = DDI_FAILURE;
13705         char            *devname;
13706         char            wwn_str[MPTSAS_WWN_STRLEN];
13707         dev_info_t      *cdip;
13708 
13709         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_sasaddr);
13710 
13711         cdip = mptsas_find_smp_child(pdip, wwn_str);
13712 
13713         if (cdip == NULL)
13714                 return (DDI_SUCCESS);
13715 
13716         /*
13717          * Make sure node is attached otherwise
13718          * it won't have related cache nodes to
13719          * clean up.  i_ddi_devi_attached is
13720          * similiar to i_ddi_node_state(cdip) >=
13721          * DS_ATTACHED.
13722          */
13723         if (i_ddi_devi_attached(cdip)) {
13724 
13725                 /* Get full devname */
13726                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
13727                 (void) ddi_deviname(cdip, devname);
13728                 /* Clean cache */
13729                 (void) devfs_clean(pdip, devname + 1,


13969         char                    *attached_wwn_str = NULL;
13970         char                    *component = NULL;
13971         uint8_t                 phy = 0xFF;
13972         uint64_t                sas_wwn;
13973         int64_t                 lun64 = 0;
13974         uint32_t                devinfo;
13975         uint16_t                dev_hdl;
13976         uint16_t                pdev_hdl;
13977         uint64_t                dev_sas_wwn;
13978         uint64_t                pdev_sas_wwn;
13979         uint32_t                pdev_info;
13980         uint8_t                 physport;
13981         uint8_t                 phy_id;
13982         uint32_t                page_address;
13983         uint16_t                bay_num, enclosure;
13984         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
13985         uint32_t                dev_info;
13986 
13987         mutex_enter(&mpt->m_mutex);
13988         target = ptgt->m_devhdl;
13989         sas_wwn = ptgt->m_sas_wwn;
13990         devinfo = ptgt->m_deviceinfo;
13991         phy = ptgt->m_phynum;
13992         mutex_exit(&mpt->m_mutex);
13993 
13994         if (sas_wwn) {
13995                 *pip = mptsas_find_path_addr(pdip, sas_wwn, lun);
13996         } else {
13997                 *pip = mptsas_find_path_phy(pdip, phy);
13998         }
13999 
14000         if (*pip != NULL) {
14001                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14002                 ASSERT(*lun_dip != NULL);
14003                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, *lun_dip,
14004                     (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
14005                     MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
14006                         if (strncmp(guid, old_guid, strlen(guid)) == 0) {
14007                                 /*
14008                                  * Same path back online again.
14009                                  */


14318         char                    *component = NULL;
14319         char                    *attached_wwn_str = NULL;
14320         uint8_t                 phy = 0xFF;
14321         uint64_t                sas_wwn;
14322         uint32_t                devinfo;
14323         uint16_t                dev_hdl;
14324         uint16_t                pdev_hdl;
14325         uint64_t                pdev_sas_wwn;
14326         uint64_t                dev_sas_wwn;
14327         uint32_t                pdev_info;
14328         uint8_t                 physport;
14329         uint8_t                 phy_id;
14330         uint32_t                page_address;
14331         uint16_t                bay_num, enclosure;
14332         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
14333         uint32_t                dev_info;
14334         int64_t                 lun64 = 0;
14335 
14336         mutex_enter(&mpt->m_mutex);
14337         target = ptgt->m_devhdl;
14338         sas_wwn = ptgt->m_sas_wwn;
14339         devinfo = ptgt->m_deviceinfo;
14340         phy = ptgt->m_phynum;
14341         mutex_exit(&mpt->m_mutex);
14342 
14343         /*
14344          * generate compatible property with binding-set "mpt"
14345          */
14346         scsi_hba_nodename_compatible_get(inq, NULL, inq->inq_dtype, NULL,
14347             &nodename, &compatible, &ncompatible);
14348 
14349         /*
14350          * if nodename can't be determined then print a message and skip it
14351          */
14352         if (nodename == NULL) {
14353                 mptsas_log(mpt, CE_WARN, "mptsas found no compatible driver "
14354                     "for target %d lun %d", target, lun);
14355                 return (DDI_FAILURE);
14356         }
14357 
14358         ndi_rtn = ndi_devi_alloc(pdip, nodename,


14437                     *lun_dip, SAS_PROP) != DDI_PROP_SUCCESS) {
14438                         mptsas_log(mpt, CE_WARN, "mptsas unable to"
14439                             "create property for SAS target %d lun %d"
14440                             " (SAS_PROP)", target, lun);
14441                         ndi_rtn = NDI_FAILURE;
14442                         goto phys_create_done;
14443                 }
14444                 if (guid && (ndi_prop_update_string(DDI_DEV_T_NONE,
14445                     *lun_dip, NDI_GUID, guid) != DDI_SUCCESS)) {
14446                         mptsas_log(mpt, CE_WARN, "mptsas unable "
14447                             "to create guid property for target %d "
14448                             "lun %d", target, lun);
14449                         ndi_rtn = NDI_FAILURE;
14450                         goto phys_create_done;
14451                 }
14452 
14453                 /*
14454                  * The following code is to set properties for SM-HBA support,
14455                  * it doesn't apply to RAID volumes
14456                  */
14457                 if (ptgt->m_phymask == 0)
14458                         goto phys_raid_lun;
14459 
14460                 mutex_enter(&mpt->m_mutex);
14461 
14462                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14463                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14464                     (uint32_t)ptgt->m_devhdl;
14465                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14466                     &dev_hdl, &dev_sas_wwn, &dev_info,
14467                     &physport, &phy_id, &pdev_hdl,
14468                     &bay_num, &enclosure);
14469                 if (rval != DDI_SUCCESS) {
14470                         mutex_exit(&mpt->m_mutex);
14471                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
14472                             "parent device for handle %d.", page_address);
14473                         ndi_rtn = NDI_FAILURE;
14474                         goto phys_create_done;
14475                 }
14476 
14477                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &


14591                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
14592                         if (guid) {
14593                                 (void) snprintf(component, MAXPATHLEN,
14594                                     "disk@w%s,%x", wwn_str, lun);
14595                         } else {
14596                                 (void) snprintf(component, MAXPATHLEN,
14597                                     "disk@p%x,%x", phy, lun);
14598                         }
14599                         if (ddi_pathname_obp_set(*lun_dip, component)
14600                             != DDI_SUCCESS) {
14601                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
14602                                     "unable to set obp-path for SAS "
14603                                     "object %s", component);
14604                                 ndi_rtn = NDI_FAILURE;
14605                                 goto phys_create_done;
14606                         }
14607                 }
14608                 /*
14609                  * Create the phy-num property for non-raid disk
14610                  */
14611                 if (ptgt->m_phymask != 0) {
14612                         if (ndi_prop_update_int(DDI_DEV_T_NONE,
14613                             *lun_dip, "phy-num", ptgt->m_phynum) !=
14614                             DDI_PROP_SUCCESS) {
14615                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
14616                                     "failed to create phy-num property for "
14617                                     "target %d", target);
14618                                 ndi_rtn = NDI_FAILURE;
14619                                 goto phys_create_done;
14620                         }
14621                 }
14622 phys_create_done:
14623                 /*
14624                  * If props were setup ok, online the lun
14625                  */
14626                 if (ndi_rtn == NDI_SUCCESS) {
14627                         /*
14628                          * Try to online the new node
14629                          */
14630                         ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
14631                 }


14713         char            attached_wwn_str[MPTSAS_WWN_STRLEN];
14714         int             ndi_rtn = NDI_FAILURE;
14715         int             rval = 0;
14716         mptsas_smp_t    dev_info;
14717         uint32_t        page_address;
14718         mptsas_t        *mpt = DIP2MPT(pdip);
14719         uint16_t        dev_hdl;
14720         uint64_t        sas_wwn;
14721         uint64_t        smp_sas_wwn;
14722         uint8_t         physport;
14723         uint8_t         phy_id;
14724         uint16_t        pdev_hdl;
14725         uint8_t         numphys = 0;
14726         uint16_t        i = 0;
14727         char            phymask[MPTSAS_MAX_PHYS];
14728         char            *iport = NULL;
14729         mptsas_phymask_t        phy_mask = 0;
14730         uint16_t        attached_devhdl;
14731         uint16_t        bay_num, enclosure;
14732 
14733         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_sasaddr);
14734 
14735         /*
14736          * Probe smp device, prevent the node of removed device from being
14737          * configured succesfully
14738          */
14739         if (mptsas_probe_smp(pdip, smp_node->m_sasaddr) != NDI_SUCCESS) {
14740                 return (DDI_FAILURE);
14741         }
14742 
14743         if ((*smp_dip = mptsas_find_smp_child(pdip, wwn_str)) != NULL) {
14744                 return (DDI_SUCCESS);
14745         }
14746 
14747         ndi_rtn = ndi_devi_alloc(pdip, "smp", DEVI_SID_NODEID, smp_dip);
14748 
14749         /*
14750          * if lun alloc success, set props
14751          */
14752         if (ndi_rtn == NDI_SUCCESS) {
14753                 /*
14754                  * Set the flavor of the child to be SMP flavored
14755                  */
14756                 ndi_flavor_set(*smp_dip, SCSA_FLAVOR_SMP);
14757 
14758                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14759                     *smp_dip, SMP_WWN, wwn_str) !=
14760                     DDI_PROP_SUCCESS) {
14761                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14762                             "property for smp device %s (sas_wwn)",
14763                             wwn_str);
14764                         ndi_rtn = NDI_FAILURE;
14765                         goto smp_create_done;
14766                 }
14767                 (void) sprintf(wwn_str, "w%"PRIx64, smp_node->m_sasaddr);
14768                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14769                     *smp_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str) !=
14770                     DDI_PROP_SUCCESS) {
14771                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14772                             "property for iport target-port %s (sas_wwn)",
14773                             wwn_str);
14774                         ndi_rtn = NDI_FAILURE;
14775                         goto smp_create_done;
14776                 }
14777 
14778                 mutex_enter(&mpt->m_mutex);
14779 
14780                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
14781                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | smp_node->m_devhdl;
14782                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
14783                     &dev_info);
14784                 if (rval != DDI_SUCCESS) {
14785                         mutex_exit(&mpt->m_mutex);
14786                         mptsas_log(mpt, CE_WARN,
14787                             "mptsas unable to get expander "


15031                         smp_pkt->smp_pkt_reason = EIO;
15032                         break;
15033                 }
15034                 return (DDI_FAILURE);
15035         }
15036         if (rep.SASStatus != MPI2_SASSTATUS_SUCCESS) {
15037                 mptsas_log(mpt, CE_NOTE, "smp_start: get error SAS status:%x",
15038                     rep.SASStatus);
15039                 smp_pkt->smp_pkt_reason = EIO;
15040                 return (DDI_FAILURE);
15041         }
15042 
15043         return (DDI_SUCCESS);
15044 }
15045 
15046 /*
15047  * If we didn't get a match, we need to get sas page0 for each device, and
15048  * untill we get a match. If failed, return NULL
15049  */
15050 static mptsas_target_t *
15051 mptsas_phy_to_tgt(mptsas_t *mpt, int phymask, uint8_t phy)
15052 {
15053         int             i, j = 0;
15054         int             rval = 0;
15055         uint16_t        cur_handle;
15056         uint32_t        page_address;
15057         mptsas_target_t *ptgt = NULL;
15058 
15059         /*
15060          * PHY named device must be direct attached and attaches to
15061          * narrow port, if the iport is not parent of the device which
15062          * we are looking for.
15063          */
15064         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15065                 if ((1 << i) & phymask)
15066                         j++;
15067         }
15068 
15069         if (j > 1)
15070                 return (NULL);
15071 
15072         /*
15073          * Must be a narrow port and single device attached to the narrow port
15074          * So the physical port num of device  which is equal to the iport's
15075          * port num is the device what we are looking for.
15076          */
15077 
15078         if (mpt->m_phy_info[phy].phy_mask != phymask)
15079                 return (NULL);
15080 
15081         mutex_enter(&mpt->m_mutex);
15082 
15083         ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
15084             MPTSAS_HASH_FIRST);
15085         while (ptgt != NULL) {
15086                         if ((ptgt->m_sas_wwn == 0) && (ptgt->m_phynum == phy)) {
15087                         mutex_exit(&mpt->m_mutex);
15088                         return (ptgt);
15089                 }
15090 
15091                 ptgt = (mptsas_target_t *)mptsas_hash_traverse(
15092                     &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
15093         }
15094 
15095         if (mpt->m_done_traverse_dev) {
15096                 mutex_exit(&mpt->m_mutex);
15097                 return (NULL);
15098         }
15099 
15100         /* If didn't get a match, come here */
15101         cur_handle = mpt->m_dev_handle;
15102         for (; ; ) {
15103                 ptgt = NULL;
15104                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15105                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15106                 rval = mptsas_get_target_device_info(mpt, page_address,
15107                     &cur_handle, &ptgt);
15108                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15109                     (rval == DEV_INFO_FAIL_ALLOC)) {
15110                         break;
15111                 }
15112                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15113                     (rval == DEV_INFO_PHYS_DISK)) {
15114                         continue;
15115                 }
15116                 mpt->m_dev_handle = cur_handle;
15117 
15118                 if ((ptgt->m_sas_wwn == 0) && (ptgt->m_phynum == phy)) {
15119                         break;
15120                 }
15121         }
15122 
15123         mutex_exit(&mpt->m_mutex);
15124         return (ptgt);
15125 }
15126 
15127 /*
15128  * The ptgt->m_sas_wwn contains the wwid for each disk.
15129  * For Raid volumes, we need to check m_raidvol[x].m_raidwwid
15130  * If we didn't get a match, we need to get sas page0 for each device, and
15131  * untill we get a match
15132  * If failed, return NULL
15133  */
15134 static mptsas_target_t *
15135 mptsas_wwid_to_ptgt(mptsas_t *mpt, int phymask, uint64_t wwid)
15136 {
15137         int             rval = 0;
15138         uint16_t        cur_handle;
15139         uint32_t        page_address;
15140         mptsas_target_t *tmp_tgt = NULL;

15141 


15142         mutex_enter(&mpt->m_mutex);
15143         tmp_tgt = (struct mptsas_target *)mptsas_hash_search(
15144             &mpt->m_active->m_tgttbl, wwid, phymask);
15145         if (tmp_tgt != NULL) {
15146                 mutex_exit(&mpt->m_mutex);
15147                 return (tmp_tgt);
15148         }
15149 
15150         if (phymask == 0) {
15151                 /*
15152                  * It's IR volume
15153                  */
15154                 rval = mptsas_get_raid_info(mpt);
15155                 if (rval) {
15156                         tmp_tgt = (struct mptsas_target *)mptsas_hash_search(
15157                             &mpt->m_active->m_tgttbl, wwid, phymask);
15158                 }
15159                 mutex_exit(&mpt->m_mutex);
15160                 return (tmp_tgt);
15161         }
15162 
15163         if (mpt->m_done_traverse_dev) {
15164                 mutex_exit(&mpt->m_mutex);
15165                 return (NULL);
15166         }
15167 
15168         /* If didn't get a match, come here */
15169         cur_handle = mpt->m_dev_handle;
15170         for (; ; ) {
15171                 tmp_tgt = NULL;
15172                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15173                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | cur_handle;
15174                 rval = mptsas_get_target_device_info(mpt, page_address,
15175                     &cur_handle, &tmp_tgt);
15176                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15177                     (rval == DEV_INFO_FAIL_ALLOC)) {
15178                         tmp_tgt = NULL;
15179                         break;
15180                 }
15181                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15182                     (rval == DEV_INFO_PHYS_DISK)) {
15183                         continue;
15184                 }
15185                 mpt->m_dev_handle = cur_handle;
15186                 if ((tmp_tgt->m_sas_wwn) && (tmp_tgt->m_sas_wwn == wwid) &&
15187                     (tmp_tgt->m_phymask == phymask)) {

15188                         break;
15189                 }
15190         }
15191 
15192         mutex_exit(&mpt->m_mutex);
15193         return (tmp_tgt);
15194 }
15195 
15196 static mptsas_smp_t *
15197 mptsas_wwid_to_psmp(mptsas_t *mpt, int phymask, uint64_t wwid)
15198 {
15199         int             rval = 0;
15200         uint16_t        cur_handle;
15201         uint32_t        page_address;
15202         mptsas_smp_t    smp_node, *psmp = NULL;

15203 


15204         mutex_enter(&mpt->m_mutex);
15205         psmp = (struct mptsas_smp *)mptsas_hash_search(&mpt->m_active->m_smptbl,
15206             wwid, phymask);
15207         if (psmp != NULL) {
15208                 mutex_exit(&mpt->m_mutex);
15209                 return (psmp);
15210         }
15211 
15212         if (mpt->m_done_traverse_smp) {
15213                 mutex_exit(&mpt->m_mutex);
15214                 return (NULL);
15215         }
15216 
15217         /* If didn't get a match, come here */
15218         cur_handle = mpt->m_smp_devhdl;
15219         for (; ; ) {
15220                 psmp = NULL;
15221                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
15222                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15223                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
15224                     &smp_node);
15225                 if (rval != DDI_SUCCESS) {
15226                         break;
15227                 }
15228                 mpt->m_smp_devhdl = cur_handle = smp_node.m_devhdl;
15229                 psmp = mptsas_smp_alloc(&mpt->m_active->m_smptbl, &smp_node);
15230                 ASSERT(psmp);
15231                 if ((psmp->m_sasaddr) && (psmp->m_sasaddr == wwid) &&
15232                     (psmp->m_phymask == phymask)) {
15233                         break;
15234                 }
15235         }
15236 
15237         mutex_exit(&mpt->m_mutex);
15238         return (psmp);
15239 }
15240 
15241 /* helper functions using hash */
15242 
15243 /*
15244  * Can't have duplicate entries for same devhdl,
15245  * if there are invalid entries, the devhdl should be set to 0xffff
15246  */
15247 static void *
15248 mptsas_search_by_devhdl(mptsas_hash_table_t *hashtab, uint16_t devhdl)
15249 {
15250         mptsas_hash_data_t *data;
15251 
15252         data = mptsas_hash_traverse(hashtab, MPTSAS_HASH_FIRST);
15253         while (data != NULL) {
15254                 if (data->devhdl == devhdl) {
15255                         break;
15256                 }
15257                 data = mptsas_hash_traverse(hashtab, MPTSAS_HASH_NEXT);
15258         }
15259         return (data);
15260 }
15261 
15262 mptsas_target_t *
15263 mptsas_tgt_alloc(mptsas_hash_table_t *hashtab, uint16_t devhdl, uint64_t wwid,
15264     uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum)
15265 {
15266         mptsas_target_t *tmp_tgt = NULL;

15267 
15268         tmp_tgt = mptsas_hash_search(hashtab, wwid, phymask);


15269         if (tmp_tgt != NULL) {
15270                 NDBG20(("Hash item already exist"));
15271                 tmp_tgt->m_deviceinfo = devinfo;
15272                 tmp_tgt->m_devhdl = devhdl;
15273                 return (tmp_tgt);
15274         }
15275         tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target), KM_SLEEP);
15276         if (tmp_tgt == NULL) {
15277                 cmn_err(CE_WARN, "Fatal, allocated tgt failed");
15278                 return (NULL);
15279         }
15280         tmp_tgt->m_devhdl = devhdl;
15281         tmp_tgt->m_sas_wwn = wwid;
15282         tmp_tgt->m_deviceinfo = devinfo;
15283         tmp_tgt->m_phymask = phymask;
15284         tmp_tgt->m_phynum = phynum;
15285         /* Initialized the tgt structure */
15286         tmp_tgt->m_qfull_retries = QFULL_RETRIES;
15287         tmp_tgt->m_qfull_retry_interval =
15288             drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
15289         tmp_tgt->m_t_throttle = MAX_THROTTLE;
15290 
15291         mptsas_hash_add(hashtab, tmp_tgt);
15292 
15293         return (tmp_tgt);
15294 }
15295 
15296 static void
15297 mptsas_tgt_free(mptsas_hash_table_t *hashtab, uint64_t wwid,
15298     mptsas_phymask_t phymask)
15299 {
15300         mptsas_target_t *tmp_tgt;
15301         tmp_tgt = mptsas_hash_rem(hashtab, wwid, phymask);
15302         if (tmp_tgt == NULL) {
15303                 cmn_err(CE_WARN, "Tgt not found, nothing to free");
15304         } else {
15305                 kmem_free(tmp_tgt, sizeof (struct mptsas_target));
15306         }
15307 }
15308 
15309 /*
15310  * Return the entry in the hash table
15311  */
15312 static mptsas_smp_t *
15313 mptsas_smp_alloc(mptsas_hash_table_t *hashtab, mptsas_smp_t *data)
15314 {
15315         uint64_t key1 = data->m_sasaddr;
15316         mptsas_phymask_t key2 = data->m_phymask;
15317         mptsas_smp_t *ret_data;
15318 
15319         ret_data = mptsas_hash_search(hashtab, key1, key2);








15320         if (ret_data != NULL) {
15321                 bcopy(data, ret_data, sizeof (mptsas_smp_t));
15322                 return (ret_data);
15323         }
15324 
15325         ret_data = kmem_alloc(sizeof (mptsas_smp_t), KM_SLEEP);
15326         bcopy(data, ret_data, sizeof (mptsas_smp_t));
15327         mptsas_hash_add(hashtab, ret_data);
15328         return (ret_data);
15329 }
15330 
15331 static void
15332 mptsas_smp_free(mptsas_hash_table_t *hashtab, uint64_t wwid,
15333     mptsas_phymask_t phymask)
15334 {
15335         mptsas_smp_t *tmp_smp;
15336         tmp_smp = mptsas_hash_rem(hashtab, wwid, phymask);
15337         if (tmp_smp == NULL) {
15338                 cmn_err(CE_WARN, "Smp element not found, nothing to free");
15339         } else {
15340                 kmem_free(tmp_smp, sizeof (struct mptsas_smp));
15341         }
15342 }
15343 
15344 /*
15345  * Hash operation functions
15346  * key1 is the sas_wwn, key2 is the phymask
15347  */
15348 static void
15349 mptsas_hash_init(mptsas_hash_table_t *hashtab)
15350 {
15351         if (hashtab == NULL) {
15352                 return;
15353         }
15354         bzero(hashtab->head, sizeof (mptsas_hash_node_t) *
15355             MPTSAS_HASH_ARRAY_SIZE);
15356         hashtab->cur = NULL;
15357         hashtab->line = 0;
15358 }
15359 
15360 static void
15361 mptsas_hash_uninit(mptsas_hash_table_t *hashtab, size_t datalen)
15362 {
15363         uint16_t line = 0;
15364         mptsas_hash_node_t *cur = NULL, *last = NULL;
15365 
15366         if (hashtab == NULL) {
15367                 return;
15368         }
15369         for (line = 0; line < MPTSAS_HASH_ARRAY_SIZE; line++) {
15370                 cur = hashtab->head[line];
15371                 while (cur != NULL) {
15372                         last = cur;
15373                         cur = cur->next;
15374                         kmem_free(last->data, datalen);
15375                         kmem_free(last, sizeof (mptsas_hash_node_t));
15376                 }
15377         }
15378 }
15379 
15380 /*
15381  * You must guarantee the element doesn't exist in the hash table
15382  * before you call mptsas_hash_add()
15383  */
15384 static void
15385 mptsas_hash_add(mptsas_hash_table_t *hashtab, void *data)
15386 {
15387         uint64_t key1 = ((mptsas_hash_data_t *)data)->key1;
15388         mptsas_phymask_t key2 = ((mptsas_hash_data_t *)data)->key2;
15389         mptsas_hash_node_t **head = NULL;
15390         mptsas_hash_node_t *node = NULL;
15391 
15392         if (hashtab == NULL) {
15393                 return;
15394         }
15395         ASSERT(mptsas_hash_search(hashtab, key1, key2) == NULL);
15396         node = kmem_zalloc(sizeof (mptsas_hash_node_t), KM_NOSLEEP);
15397         node->data = data;
15398 
15399         head = &(hashtab->head[key1 % MPTSAS_HASH_ARRAY_SIZE]);
15400         if (*head == NULL) {
15401                 *head = node;
15402         } else {
15403                 node->next = *head;
15404                 *head = node;
15405         }
15406 }
15407 
15408 static void *
15409 mptsas_hash_rem(mptsas_hash_table_t *hashtab, uint64_t key1,
15410     mptsas_phymask_t key2)
15411 {
15412         mptsas_hash_node_t **head = NULL;
15413         mptsas_hash_node_t *last = NULL, *cur = NULL;
15414         mptsas_hash_data_t *data;
15415         if (hashtab == NULL) {
15416                 return (NULL);
15417         }
15418         head = &(hashtab->head[key1 % MPTSAS_HASH_ARRAY_SIZE]);
15419         cur = *head;
15420         while (cur != NULL) {
15421                 data = cur->data;
15422                 if ((data->key1 == key1) && (data->key2 == key2)) {
15423                         if (last == NULL) {
15424                                 (*head) = cur->next;
15425                         } else {
15426                                 last->next = cur->next;
15427                         }
15428                         kmem_free(cur, sizeof (mptsas_hash_node_t));
15429                         return (data);
15430                 } else {
15431                         last = cur;
15432                         cur = cur->next;
15433                 }
15434         }
15435         return (NULL);
15436 }
15437 
15438 static void *
15439 mptsas_hash_search(mptsas_hash_table_t *hashtab, uint64_t key1,
15440     mptsas_phymask_t key2)
15441 {
15442         mptsas_hash_node_t *cur = NULL;
15443         mptsas_hash_data_t *data;
15444         if (hashtab == NULL) {
15445                 return (NULL);
15446         }
15447         cur = hashtab->head[key1 % MPTSAS_HASH_ARRAY_SIZE];
15448         while (cur != NULL) {
15449                 data = cur->data;
15450                 if ((data->key1 == key1) && (data->key2 == key2)) {
15451                         return (data);
15452                 } else {
15453                         cur = cur->next;
15454                 }
15455         }
15456         return (NULL);
15457 }
15458 
15459 static void *
15460 mptsas_hash_traverse(mptsas_hash_table_t *hashtab, int pos)
15461 {
15462         mptsas_hash_node_t *this = NULL;
15463 
15464         if (hashtab == NULL) {
15465                 return (NULL);
15466         }
15467 
15468         if (pos == MPTSAS_HASH_FIRST) {
15469                 hashtab->line = 0;
15470                 hashtab->cur = NULL;
15471                 this = hashtab->head[0];
15472         } else {
15473                 if (hashtab->cur == NULL) {
15474                         return (NULL);
15475                 } else {
15476                         this = hashtab->cur->next;
15477                 }
15478         }
15479 
15480         while (this == NULL) {
15481                 hashtab->line++;
15482                 if (hashtab->line >= MPTSAS_HASH_ARRAY_SIZE) {
15483                         /* the traverse reaches the end */
15484                         hashtab->cur = NULL;
15485                         return (NULL);
15486                 } else {
15487                         this = hashtab->head[hashtab->line];
15488                 }
15489         }
15490         hashtab->cur = this;
15491         return (this->data);
15492 }
15493 
15494 /*
15495  * Functions for SGPIO LED support
15496  */
15497 static dev_info_t *
15498 mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask)
15499 {
15500         dev_info_t      *dip;
15501         int             prop;
15502         dip = e_ddi_hold_devi_by_dev(dev, 0);
15503         if (dip == NULL)
15504                 return (dip);
15505         prop = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
15506             "phymask", 0);
15507         *phymask = (mptsas_phymask_t)prop;
15508         ddi_release_devi(dip);
15509         return (dip);
15510 }
15511 static mptsas_target_t *
15512 mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
15513 {
15514         uint8_t                 phynum;


15557         Mpi2SepRequest_t        req;
15558         Mpi2SepReply_t          rep;
15559         int                     ret;
15560 
15561         ASSERT(mutex_owned(&mpt->m_mutex));
15562 
15563         /*
15564          * We only support SEP control of directly-attached targets, in which
15565          * case the "SEP" we're talking to is a virtual one contained within
15566          * the HBA itself.  This is necessary because DA targets typically have
15567          * no other mechanism for LED control.  Targets for which a separate
15568          * enclosure service processor exists should be controlled via ses(7d)
15569          * or sgen(7d).  Furthermore, since such requests can time out, they
15570          * should be made in user context rather than in response to
15571          * asynchronous fabric changes.
15572          *
15573          * In addition, we do not support this operation for RAID volumes,
15574          * since there is no slot associated with them.
15575          */
15576         if (!(ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED) ||
15577             ptgt->m_phymask == 0) {
15578                 return (ENOTTY);
15579         }
15580 
15581         bzero(&req, sizeof (req));
15582         bzero(&rep, sizeof (rep));
15583 
15584         req.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
15585         req.Action = act;
15586         req.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
15587         req.EnclosureHandle = LE_16(ptgt->m_enclosure);
15588         req.Slot = LE_16(ptgt->m_slot_num);
15589         if (act == MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
15590                 req.SlotStatus = LE_32(*status);
15591         }
15592         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
15593             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
15594         if (ret != 0) {
15595                 mptsas_log(mpt, CE_NOTE, "mptsas_send_sep: passthru SEP "
15596                     "Processor Request message error %d", ret);
15597                 return (ret);




   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  * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
  27  */
  28 
  29 /*
  30  * Copyright (c) 2000 to 2010, LSI Corporation.
  31  * All rights reserved.
  32  *
  33  * Redistribution and use in source and binary forms of all code within
  34  * this file that is exclusively owned by LSI, with or without
  35  * modification, is permitted provided that, in addition to the CDDL 1.0
  36  * License requirements, the following conditions are met:
  37  *
  38  *    Neither the name of the author nor the names of its contributors may be
  39  *    used to endorse or promote products derived from this software without
  40  *    specific prior written permission.
  41  *
  42  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  43  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  45  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE


  80 
  81 #pragma pack(1)
  82 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
  83 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
  84 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
  85 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
  86 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
  87 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
  88 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
  89 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
  90 #pragma pack()
  91 
  92 /*
  93  * private header files.
  94  *
  95  */
  96 #include <sys/scsi/impl/scsi_reset_notify.h>
  97 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
  98 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
  99 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
 100 #include <sys/scsi/adapters/mpt_sas/mptsas_hash.h>
 101 #include <sys/raidioctl.h>
 102 
 103 #include <sys/fs/dv_node.h>       /* devfs_clean */
 104 
 105 /*
 106  * FMA header files
 107  */
 108 #include <sys/ddifm.h>
 109 #include <sys/fm/protocol.h>
 110 #include <sys/fm/util.h>
 111 #include <sys/fm/io/ddi.h>
 112 
 113 /*
 114  * autoconfiguration data and routines.
 115  */
 116 static int mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
 117 static int mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
 118 static int mptsas_power(dev_info_t *dip, int component, int level);
 119 
 120 /*


 320 static int mptsas_watch_reset_delay_subr(mptsas_t *mpt);
 321 
 322 /*
 323  * helper functions
 324  */
 325 static void mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 326 
 327 static dev_info_t *mptsas_find_child(dev_info_t *pdip, char *name);
 328 static dev_info_t *mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy);
 329 static dev_info_t *mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr,
 330     int lun);
 331 static mdi_pathinfo_t *mptsas_find_path_addr(dev_info_t *pdip, uint64_t sasaddr,
 332     int lun);
 333 static mdi_pathinfo_t *mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy);
 334 static dev_info_t *mptsas_find_smp_child(dev_info_t *pdip, char *str_wwn);
 335 
 336 static int mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy,
 337     int *lun);
 338 static int mptsas_parse_smp_name(char *name, uint64_t *wwn);
 339 
 340 static mptsas_target_t *mptsas_phy_to_tgt(mptsas_t *mpt,
 341     mptsas_phymask_t phymask, uint8_t phy);
 342 static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt,
 343     mptsas_phymask_t phymask, uint64_t wwid);
 344 static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt,
 345     mptsas_phymask_t phymask, uint64_t wwid);
 346 
 347 static int mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun,
 348     uchar_t page, unsigned char *buf, int len, int *rlen, uchar_t evpd);
 349 
 350 static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
 351     uint16_t *handle, mptsas_target_t **pptgt);
 352 static void mptsas_update_phymask(mptsas_t *mpt);
 353 
 354 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
 355     uint32_t *status, uint8_t cmd);
 356 static dev_info_t *mptsas_get_dip_from_dev(dev_t dev,
 357     mptsas_phymask_t *phymask);
 358 static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr,
 359     mptsas_phymask_t phymask);
 360 static int mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt);
 361 
 362 
 363 /*
 364  * Enumeration / DR functions
 365  */


 391 static void mptsas_offline_missed_luns(dev_info_t *pdip,
 392     uint16_t *repluns, int lun_cnt, mptsas_target_t *ptgt);
 393 static int mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
 394     mdi_pathinfo_t *rpip, uint_t flags);
 395 
 396 static int mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn,
 397     dev_info_t **smp_dip);
 398 static int mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 399     uint_t flags);
 400 
 401 static int mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data,
 402     int mode, int *rval);
 403 static int mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data,
 404     int mode, int *rval);
 405 static int mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data,
 406     int mode, int *rval);
 407 static void mptsas_record_event(void *args);
 408 static int mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data,
 409     int mode);
 410 
 411 mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t, uint64_t,









 412     uint32_t, mptsas_phymask_t, uint8_t);
 413 static mptsas_smp_t *mptsas_smp_alloc(mptsas_t *, mptsas_smp_t *);





 414 static int mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 415     dev_info_t **smp_dip);
 416 
 417 /*
 418  * Power management functions
 419  */
 420 static int mptsas_get_pci_cap(mptsas_t *mpt);
 421 static int mptsas_init_pm(mptsas_t *mpt);
 422 
 423 /*
 424  * MPT MSI tunable:
 425  *
 426  * By default MSI is enabled on all supported platforms.
 427  */
 428 boolean_t mptsas_enable_msi = B_TRUE;
 429 boolean_t mptsas_physical_bind_failed_page_83 = B_FALSE;
 430 
 431 static int mptsas_register_intrs(mptsas_t *);
 432 static void mptsas_unregister_intrs(mptsas_t *);
 433 static int mptsas_add_intrs(mptsas_t *, int);


 665                 mutex_destroy(&mptsas_global_mutex);
 666                 rw_destroy(&mptsas_global_rwlock);
 667                 mutex_destroy(&mptsas_log_mutex);
 668         }
 669         return (status);
 670 }
 671 
 672 /*
 673  * The loadable-module _info(9E) entry point
 674  */
 675 int
 676 _info(struct modinfo *modinfop)
 677 {
 678         /* CONSTCOND */
 679         ASSERT(NO_COMPETING_THREADS);
 680         NDBG0(("mptsas _info"));
 681 
 682         return (mod_info(&modlinkage, modinfop));
 683 }
 684 
 685 static int
 686 mptsas_target_eval_devhdl(const void *op, void *arg)
 687 {
 688         uint16_t dh = *(uint16_t *)arg;
 689         const mptsas_target_t *tp = op;
 690 
 691         return ((int)tp->m_devhdl - (int)dh);
 692 }
 693 
 694 static int
 695 mptsas_target_eval_slot(const void *op, void *arg)
 696 {
 697         mptsas_led_control_t *lcp = arg;
 698         const mptsas_target_t *tp = op;
 699 
 700         if (tp->m_enclosure != lcp->Enclosure)
 701                 return ((int)tp->m_enclosure - (int)lcp->Enclosure);
 702 
 703         return ((int)tp->m_slot_num - (int)lcp->Slot);
 704 }
 705 
 706 static int
 707 mptsas_target_eval_nowwn(const void *op, void *arg)
 708 {
 709         uint8_t phy = *(uint8_t *)arg;
 710         const mptsas_target_t *tp = op;
 711 
 712         if (tp->m_addr.mta_wwn != 0)
 713                 return (-1);
 714 
 715         return ((int)tp->m_phynum - (int)phy);
 716 }
 717 
 718 static int
 719 mptsas_smp_eval_devhdl(const void *op, void *arg)
 720 {
 721         uint16_t dh = *(uint16_t *)arg;
 722         const mptsas_smp_t *sp = op;
 723 
 724         return ((int)sp->m_devhdl - (int)dh);
 725 }
 726 
 727 static uint64_t
 728 mptsas_target_addr_hash(const void *tp)
 729 {
 730         const mptsas_target_addr_t *tap = tp;
 731 
 732         return ((tap->mta_wwn & 0xffffffffffffULL) |
 733             ((uint64_t)tap->mta_phymask << 48));
 734 }
 735 
 736 static int
 737 mptsas_target_addr_cmp(const void *a, const void *b)
 738 {
 739         const mptsas_target_addr_t *aap = a;
 740         const mptsas_target_addr_t *bap = b;
 741 
 742         if (aap->mta_wwn < bap->mta_wwn)
 743                 return (-1);
 744         if (aap->mta_wwn > bap->mta_wwn)
 745                 return (1);
 746         return ((int)bap->mta_phymask - (int)aap->mta_phymask);
 747 }
 748 
 749 static void
 750 mptsas_target_free(void *op)
 751 {
 752         kmem_free(op, sizeof (mptsas_target_t));
 753 }
 754 
 755 static void
 756 mptsas_smp_free(void *op)
 757 {
 758         kmem_free(op, sizeof (mptsas_smp_t));
 759 }
 760 
 761 static void
 762 mptsas_destroy_hashes(mptsas_t *mpt)
 763 {
 764         mptsas_target_t *tp;
 765         mptsas_smp_t *sp;
 766 
 767         for (tp = refhash_first(mpt->m_targets); tp != NULL;
 768             tp = refhash_next(mpt->m_targets, tp)) {
 769                 refhash_remove(mpt->m_targets, tp);
 770         }
 771         for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
 772             sp = refhash_next(mpt->m_smp_targets, sp)) {
 773                 refhash_remove(mpt->m_smp_targets, sp);
 774         }
 775         refhash_destroy(mpt->m_targets);
 776         refhash_destroy(mpt->m_smp_targets);
 777         mpt->m_targets = NULL;
 778         mpt->m_smp_targets = NULL;
 779 }
 780 
 781 static int
 782 mptsas_iport_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 783 {
 784         dev_info_t              *pdip;
 785         mptsas_t                *mpt;
 786         scsi_hba_tran_t         *hba_tran;
 787         char                    *iport = NULL;
 788         char                    phymask[MPTSAS_MAX_PHYS];
 789         mptsas_phymask_t        phy_mask = 0;
 790         int                     dynamic_port = 0;
 791         uint32_t                page_address;
 792         char                    initiator_wwnstr[MPTSAS_WWN_STRLEN];
 793         int                     rval = DDI_FAILURE;
 794         int                     i = 0;
 795         uint8_t                 numphys = 0;
 796         uint8_t                 phy_id;
 797         uint8_t                 phy_port = 0;
 798         uint16_t                attached_devhdl = 0;
 799         uint32_t                dev_info;
 800         uint64_t                attached_sas_wwn;
 801         uint16_t                dev_hdl;


1469 
1470                 if (mptsas_timeout_id && (mptsas_head == NULL)) {
1471                         timeout_id_t tid = mptsas_timeout_id;
1472                         mptsas_timeouts_enabled = 0;
1473                         mptsas_timeout_id = 0;
1474                         mutex_exit(&mptsas_global_mutex);
1475                         (void) untimeout(tid);
1476                         mutex_enter(&mptsas_global_mutex);
1477                 }
1478                 mutex_exit(&mptsas_global_mutex);
1479                 /* deallocate in reverse order */
1480                 mptsas_cache_destroy(mpt);
1481 
1482                 if (smp_attach_setup) {
1483                         mptsas_smp_teardown(mpt);
1484                 }
1485                 if (hba_attach_setup) {
1486                         mptsas_hba_teardown(mpt);
1487                 }
1488 
1489                 if (mpt->m_targets)
1490                         refhash_destroy(mpt->m_targets);
1491                 if (mpt->m_smp_targets)
1492                         refhash_destroy(mpt->m_smp_targets);
1493 
1494                 if (mpt->m_active) {




1495                         mptsas_free_active_slots(mpt);
1496                 }
1497                 if (intr_added) {
1498                         mptsas_unregister_intrs(mpt);
1499                 }
1500 
1501                 if (doneq_thread_create) {
1502                         mutex_enter(&mpt->m_doneq_mutex);
1503                         doneq_thread_num = mpt->m_doneq_thread_n;
1504                         for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1505                                 mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1506                                 mpt->m_doneq_thread_id[j].flag &=
1507                                     (~MPTSAS_DONEQ_THREAD_ACTIVE);
1508                                 cv_signal(&mpt->m_doneq_thread_id[j].cv);
1509                                 mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1510                         }
1511                         while (mpt->m_doneq_thread_n) {
1512                                 cv_wait(&mpt->m_doneq_thread_cv,
1513                                     &mpt->m_doneq_mutex);
1514                         }


1907                         mptsas_timeout_id = 0;
1908                         mutex_exit(&mptsas_global_mutex);
1909                         (void) untimeout(tid);
1910                         mutex_enter(&mptsas_global_mutex);
1911                 }
1912                 if (mptsas_reset_watch) {
1913                         tid = mptsas_reset_watch;
1914                         mptsas_reset_watch = 0;
1915                         mutex_exit(&mptsas_global_mutex);
1916                         (void) untimeout(tid);
1917                         mutex_enter(&mptsas_global_mutex);
1918                 }
1919         }
1920         mutex_exit(&mptsas_global_mutex);
1921 
1922         /*
1923          * Delete Phy stats
1924          */
1925         mptsas_destroy_phy_stats(mpt);
1926 
1927         mptsas_destroy_hashes(mpt);
1928 
1929         /*
1930          * Delete nt_active.
1931          */
1932         mutex_enter(&mpt->m_mutex);


1933         mptsas_free_active_slots(mpt);
1934         mutex_exit(&mpt->m_mutex);
1935 
1936         /* deallocate everything that was allocated in mptsas_attach */
1937         mptsas_cache_destroy(mpt);
1938 
1939         mptsas_hba_fini(mpt);
1940         mptsas_cfg_fini(mpt);
1941 
1942         /* Lower the power informing PM Framework */
1943         if (mpt->m_options & MPTSAS_OPT_PM) {
1944                 if (pm_lower_power(dip, 0, PM_LEVEL_D3) != DDI_SUCCESS)
1945                         mptsas_log(mpt, CE_WARN,
1946                             "!mptsas%d: Lower power request failed "
1947                             "during detach, ignoring.",
1948                             mpt->m_instance);
1949         }
1950 
1951         mutex_destroy(&mpt->m_tx_waitq_mutex);
1952         mutex_destroy(&mpt->m_passthru_mutex);


2173         (void) scsi_hba_iport_register(mpt->m_dip, "v0");
2174 
2175 }
2176 
2177 static int
2178 mptsas_smp_setup(mptsas_t *mpt)
2179 {
2180         mpt->m_smptran = smp_hba_tran_alloc(mpt->m_dip);
2181         ASSERT(mpt->m_smptran != NULL);
2182         mpt->m_smptran->smp_tran_hba_private = mpt;
2183         mpt->m_smptran->smp_tran_start = mptsas_smp_start;
2184         if (smp_hba_attach_setup(mpt->m_dip, mpt->m_smptran) != DDI_SUCCESS) {
2185                 mptsas_log(mpt, CE_WARN, "smp attach setup failed");
2186                 smp_hba_tran_free(mpt->m_smptran);
2187                 mpt->m_smptran = NULL;
2188                 return (FALSE);
2189         }
2190         /*
2191          * Initialize smp hash table
2192          */
2193         mpt->m_smp_targets = refhash_create(MPTSAS_SMP_BUCKET_COUNT,
2194             mptsas_target_addr_hash, mptsas_target_addr_cmp,
2195             mptsas_smp_free, sizeof (mptsas_smp_t),
2196             offsetof(mptsas_smp_t, m_link), offsetof(mptsas_smp_t, m_addr),
2197             KM_SLEEP);
2198         mpt->m_smp_devhdl = 0xFFFF;
2199 
2200         return (TRUE);
2201 }
2202 
2203 static void
2204 mptsas_smp_teardown(mptsas_t *mpt)
2205 {
2206         (void) smp_hba_detach(mpt->m_dip);
2207         if (mpt->m_smptran != NULL) {
2208                 smp_hba_tran_free(mpt->m_smptran);
2209                 mpt->m_smptran = NULL;
2210         }
2211         mpt->m_smp_devhdl = 0;
2212 }
2213 
2214 static int
2215 mptsas_cache_create(mptsas_t *mpt)
2216 {
2217         int instance = mpt->m_instance;


2820 {
2821 #ifndef __lock_lint
2822         _NOTE(ARGUNUSED(hba_tran))
2823 #endif
2824 
2825         /*
2826          * At this point, the scsi_device structure already exists
2827          * and has been initialized.
2828          *
2829          * Use this function to allocate target-private data structures,
2830          * if needed by this HBA.  Add revised flow-control and queue
2831          * properties for child here, if desired and if you can tell they
2832          * support tagged queueing by now.
2833          */
2834         mptsas_t                *mpt;
2835         int                     lun = sd->sd_address.a_lun;
2836         mdi_pathinfo_t          *pip = NULL;
2837         mptsas_tgt_private_t    *tgt_private = NULL;
2838         mptsas_target_t         *ptgt = NULL;
2839         char                    *psas_wwn = NULL;
2840         mptsas_phymask_t        phymask = 0;
2841         uint64_t                sas_wwn = 0;
2842         mptsas_target_addr_t    addr;
2843         mpt = SDEV2MPT(sd);
2844 
2845         ASSERT(scsi_hba_iport_unit_address(hba_dip) != 0);
2846 
2847         NDBG0(("mptsas_scsi_tgt_init: hbadip=0x%p tgtdip=0x%p lun=%d",
2848             (void *)hba_dip, (void *)tgt_dip, lun));
2849 
2850         if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
2851                 (void) ndi_merge_node(tgt_dip, mptsas_name_child);
2852                 ddi_set_name_addr(tgt_dip, NULL);
2853                 return (DDI_FAILURE);
2854         }
2855         /*
2856          * phymask is 0 means the virtual port for RAID
2857          */
2858         phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, hba_dip, 0,
2859             "phymask", 0);
2860         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2861                 if ((pip = (void *)(sd->sd_private)) == NULL) {
2862                         /*
2863                          * Very bad news if this occurs. Somehow scsi_vhci has
2864                          * lost the pathinfo node for this target.
2865                          */
2866                         return (DDI_NOT_WELL_FORMED);
2867                 }
2868 
2869                 if (mdi_prop_lookup_int(pip, LUN_PROP, &lun) !=
2870                     DDI_PROP_SUCCESS) {
2871                         mptsas_log(mpt, CE_WARN, "Get lun property failed\n");
2872                         return (DDI_FAILURE);
2873                 }
2874 
2875                 if (mdi_prop_lookup_string(pip, SCSI_ADDR_PROP_TARGET_PORT,
2876                     &psas_wwn) == MDI_SUCCESS) {
2877                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2878                                 sas_wwn = 0;
2879                         }
2880                         (void) mdi_prop_free(psas_wwn);
2881                 }
2882         } else {
2883                 lun = ddi_prop_get_int(DDI_DEV_T_ANY, tgt_dip,
2884                     DDI_PROP_DONTPASS, LUN_PROP, 0);
2885                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip,
2886                     DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &psas_wwn) ==
2887                     DDI_PROP_SUCCESS) {
2888                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2889                                 sas_wwn = 0;
2890                         }
2891                         ddi_prop_free(psas_wwn);
2892                 } else {
2893                         sas_wwn = 0;
2894                 }
2895         }
2896 
2897         ASSERT((sas_wwn != 0) || (phymask != 0));
2898         addr.mta_wwn = sas_wwn;
2899         addr.mta_phymask = phymask;
2900         mutex_enter(&mpt->m_mutex);
2901         ptgt = refhash_lookup(mpt->m_targets, &addr);
2902         mutex_exit(&mpt->m_mutex);
2903         if (ptgt == NULL) {
2904                 mptsas_log(mpt, CE_WARN, "!tgt_init: target doesn't exist or "
2905                     "gone already! phymask:%x, saswwn %"PRIx64, phymask,
2906                     sas_wwn);
2907                 return (DDI_FAILURE);
2908         }
2909         if (hba_tran->tran_tgt_private == NULL) {
2910                 tgt_private = kmem_zalloc(sizeof (mptsas_tgt_private_t),
2911                     KM_SLEEP);
2912                 tgt_private->t_lun = lun;
2913                 tgt_private->t_private = ptgt;
2914                 hba_tran->tran_tgt_private = tgt_private;
2915         }
2916 
2917         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2918                 return (DDI_SUCCESS);
2919         }
2920         mutex_enter(&mpt->m_mutex);
2921 


3312 
3313                 if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3314                         (void) mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
3315 
3316                         /*
3317                          * Only flush the doneq if this is not a TM
3318                          * cmd.  For TM cmds the flushing of the
3319                          * doneq will be done in those routines.
3320                          */
3321                         if ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
3322                                 mptsas_doneq_empty(mpt);
3323                         }
3324                 }
3325         }
3326         return (rval);
3327 }
3328 
3329 int
3330 mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
3331 {
3332         mptsas_slots_t *slots = mpt->m_active;
3333         uint_t slot, start_rotor;
3334         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3335 
3336         ASSERT(MUTEX_HELD(&mpt->m_mutex));

3337 
3338         /*
3339          * Account for reserved TM request slot and reserved SMID of 0.
3340          */
3341         ASSERT(slots->m_n_normal == (mpt->m_max_requests - 2));
3342 
3343         /*
3344          * Find the next available slot, beginning at m_rotor.  If no slot is
3345          * available, we'll return FALSE to indicate that.  This mechanism
3346          * considers only the normal slots, not the reserved slot 0 nor the
3347          * task management slot m_n_normal + 1.  The rotor is left to point to
3348          * the normal slot after the one we select, unless we select the last
3349          * normal slot in which case it returns to slot 1.
3350          */
3351         start_rotor = slots->m_rotor;
3352         do {
3353                 slot = slots->m_rotor++;
3354                 if (slots->m_rotor > slots->m_n_normal)
3355                         slots->m_rotor = 1;
3356 
3357                 if (slots->m_rotor == start_rotor)
3358                         break;
3359         } while (slots->m_slot[slot] != NULL);
3360 
3361         if (slots->m_slot[slot] != NULL)
3362                 return (FALSE);
3363 
3364         ASSERT(slot != 0 && slot <= slots->m_n_normal);
3365 
3366         cmd->cmd_slot = slot;
3367         slots->m_slot[slot] = cmd;
3368         mpt->m_ncmds++;
3369 
3370         /*
3371          * only increment per target ncmds if this is not a
3372          * command that has no target associated with it (i.e. a
3373          * event acknoledgment)
3374          */
3375         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
3376                 ptgt->m_t_ncmds++;
3377         }
3378         cmd->cmd_active_timeout = cmd->cmd_pkt->pkt_time;
3379 
3380         /*
3381          * If initial timout is less than or equal to one tick, bump
3382          * the timeout by a tick so that command doesn't timeout before
3383          * its allotted time.
3384          */
3385         if (cmd->cmd_active_timeout <= mptsas_scsi_watchdog_tick) {
3386                 cmd->cmd_active_timeout += mptsas_scsi_watchdog_tick;
3387         }
3388         return (TRUE);



















3389 }
3390 
3391 /*
3392  * prepare the pkt:
3393  * the pkt may have been resubmitted or just reused so
3394  * initialize some fields and do some checks.
3395  */
3396 static int
3397 mptsas_prepare_pkt(mptsas_cmd_t *cmd)
3398 {
3399         struct scsi_pkt *pkt = CMD2PKT(cmd);
3400 
3401         NDBG1(("mptsas_prepare_pkt: cmd=0x%p", (void *)cmd));
3402 
3403         /*
3404          * Reinitialize some fields that need it; the packet may
3405          * have been resubmitted
3406          */
3407         pkt->pkt_reason = CMD_CMPLT;
3408         pkt->pkt_state = 0;


4709 static void
4710 mptsas_handle_scsi_io_success(mptsas_t *mpt,
4711     pMpi2ReplyDescriptorsUnion_t reply_desc)
4712 {
4713         pMpi2SCSIIOSuccessReplyDescriptor_t     scsi_io_success;
4714         uint16_t                                SMID;
4715         mptsas_slots_t                          *slots = mpt->m_active;
4716         mptsas_cmd_t                            *cmd = NULL;
4717         struct scsi_pkt                         *pkt;
4718 
4719         ASSERT(mutex_owned(&mpt->m_mutex));
4720 
4721         scsi_io_success = (pMpi2SCSIIOSuccessReplyDescriptor_t)reply_desc;
4722         SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &scsi_io_success->SMID);
4723 
4724         /*
4725          * This is a success reply so just complete the IO.  First, do a sanity
4726          * check on the SMID.  The final slot is used for TM requests, which
4727          * would not come into this reply handler.
4728          */
4729         if ((SMID == 0) || (SMID > slots->m_n_normal)) {
4730                 mptsas_log(mpt, CE_WARN, "?Received invalid SMID of %d\n",
4731                     SMID);
4732                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4733                 return;
4734         }
4735 
4736         cmd = slots->m_slot[SMID];
4737 
4738         /*
4739          * print warning and return if the slot is empty
4740          */
4741         if (cmd == NULL) {
4742                 mptsas_log(mpt, CE_WARN, "?NULL command for successful SCSI IO "
4743                     "in slot %d", SMID);
4744                 return;
4745         }
4746 
4747         pkt = CMD2PKT(cmd);
4748         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
4749             STATE_GOT_STATUS);


4812                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
4813                 return;
4814         }
4815 
4816         (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
4817             DDI_DMA_SYNC_FORCPU);
4818         reply = (pMPI2DefaultReply_t)(mpt->m_reply_frame + (reply_addr -
4819             mpt->m_reply_frame_dma_addr));
4820         function = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->Function);
4821 
4822         /*
4823          * don't get slot information and command for events since these values
4824          * don't exist
4825          */
4826         if ((function != MPI2_FUNCTION_EVENT_NOTIFICATION) &&
4827             (function != MPI2_FUNCTION_DIAG_BUFFER_POST)) {
4828                 /*
4829                  * This could be a TM reply, which use the last allocated SMID,
4830                  * so allow for that.
4831                  */
4832                 if ((SMID == 0) || (SMID > (slots->m_n_normal + 1))) {
4833                         mptsas_log(mpt, CE_WARN, "?Received invalid SMID of "
4834                             "%d\n", SMID);
4835                         ddi_fm_service_impact(mpt->m_dip,
4836                             DDI_SERVICE_UNAFFECTED);
4837                         return;
4838                 }
4839 
4840                 cmd = slots->m_slot[SMID];
4841 
4842                 /*
4843                  * print warning and return if the slot is empty
4844                  */
4845                 if (cmd == NULL) {
4846                         mptsas_log(mpt, CE_WARN, "?NULL command for address "
4847                             "reply in slot %d", SMID);
4848                         return;
4849                 }
4850                 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
4851                     (cmd->cmd_flags & CFLAG_CONFIG) ||
4852                     (cmd->cmd_flags & CFLAG_FW_DIAG)) {


5129                  */
5130                 if (((scsi_sense_key(sensedata) == KEY_UNIT_ATTENTION) &&
5131                     (scsi_sense_asc(sensedata) == 0x3F) &&
5132                     (scsi_sense_ascq(sensedata) == 0x0E)) ||
5133                     ((scsi_sense_key(sensedata) == KEY_ILLEGAL_REQUEST) &&
5134                     (scsi_sense_asc(sensedata) == 0x25) &&
5135                     (scsi_sense_ascq(sensedata) == 0x00))) {
5136                         mptsas_topo_change_list_t *topo_node = NULL;
5137 
5138                         topo_node = kmem_zalloc(
5139                             sizeof (mptsas_topo_change_list_t),
5140                             KM_NOSLEEP);
5141                         if (topo_node == NULL) {
5142                                 mptsas_log(mpt, CE_NOTE, "No memory"
5143                                     "resource for handle SAS dynamic"
5144                                     "reconfigure.\n");
5145                                 break;
5146                         }
5147                         topo_node->mpt = mpt;
5148                         topo_node->event = MPTSAS_DR_EVENT_RECONFIG_TARGET;
5149                         topo_node->un.phymask = ptgt->m_addr.mta_phymask;
5150                         topo_node->devhdl = ptgt->m_devhdl;
5151                         topo_node->object = (void *)ptgt;
5152                         topo_node->flags = MPTSAS_TOPO_FLAG_LUN_ASSOCIATED;
5153 
5154                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
5155                             mptsas_handle_dr,
5156                             (void *)topo_node,
5157                             DDI_NOSLEEP)) != DDI_SUCCESS) {
5158                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq"
5159                                     "for handle SAS dynamic reconfigure"
5160                                     "failed. \n");
5161                         }
5162                 }
5163                 break;
5164         case MPI2_SCSI_STATUS_GOOD:
5165                 switch (ioc_status & MPI2_IOCSTATUS_MASK) {
5166                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
5167                         pkt->pkt_reason = CMD_DEV_GONE;
5168                         pkt->pkt_state |= STATE_GOT_BUS;
5169                         if (ptgt->m_reset_delay == 0) {


5195                 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
5196                         mptsas_set_pkt_reason(mpt,
5197                             cmd, CMD_RESET, STAT_BUS_RESET);
5198                         break;
5199                 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
5200                 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
5201                         mptsas_set_pkt_reason(mpt,
5202                             cmd, CMD_RESET, STAT_DEV_RESET);
5203                         break;
5204                 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
5205                 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
5206                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET);
5207                         mptsas_set_pkt_reason(mpt,
5208                             cmd, CMD_TERMINATED, STAT_TERMINATED);
5209                         break;
5210                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
5211                 case MPI2_IOCSTATUS_BUSY:
5212                         /*
5213                          * set throttles to drain
5214                          */
5215                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
5216                             ptgt = refhash_next(mpt->m_targets, ptgt)) {

5217                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);



5218                         }
5219 
5220                         /*
5221                          * retry command
5222                          */
5223                         cmd->cmd_flags |= CFLAG_RETRY;
5224                         cmd->cmd_pkt_flags |= FLAG_HEAD;
5225 
5226                         (void) mptsas_accept_pkt(mpt, cmd);
5227                         break;
5228                 default:
5229                         mptsas_log(mpt, CE_WARN,
5230                             "unknown ioc_status = %x\n", ioc_status);
5231                         mptsas_log(mpt, CE_CONT, "scsi_state = %x, transfer "
5232                             "count = %x, scsi_status = %x", scsi_state,
5233                             xferred, scsi_status);
5234                         break;
5235                 }
5236                 break;
5237         case MPI2_SCSI_STATUS_TASK_SET_FULL:


5888         char            *addr = NULL;
5889         dev_info_t      *lundip;
5890         int             circ = 0, circ1 = 0;
5891         char            attached_wwnstr[MPTSAS_WWN_STRLEN];
5892 
5893         NDBG20(("mptsas%d handle_topo_change enter", mpt->m_instance));
5894 
5895         ASSERT(mutex_owned(&mpt->m_mutex));
5896 
5897         switch (topo_node->event) {
5898         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
5899         {
5900                 char *phy_mask_name;
5901                 mptsas_phymask_t phymask = 0;
5902 
5903                 if (topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5904                         /*
5905                          * Get latest RAID info.
5906                          */
5907                         (void) mptsas_get_raid_info(mpt);
5908                         ptgt = refhash_linear_search(mpt->m_targets,
5909                             mptsas_target_eval_devhdl, &topo_node->devhdl);
5910                         if (ptgt == NULL)
5911                                 break;
5912                 } else {
5913                         ptgt = (void *)topo_node->object;
5914                 }
5915 
5916                 if (ptgt == NULL) {
5917                         /*
5918                          * If a Phys Disk was deleted, RAID info needs to be
5919                          * updated to reflect the new topology.
5920                          */
5921                         (void) mptsas_get_raid_info(mpt);
5922 
5923                         /*
5924                          * Get sas device page 0 by DevHandle to make sure if
5925                          * SSP/SATA end device exist.
5926                          */
5927                         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
5928                             MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
5929                             topo_node->devhdl;


5938                         } else if (rval == DEV_INFO_FAIL_ALLOC) {
5939                                 mptsas_log(mpt, CE_NOTE,
5940                                     "mptsas_handle_topo_change: could not "
5941                                     "allocate memory. \n");
5942                         }
5943                         /*
5944                          * If rval is DEV_INFO_PHYS_DISK than there is nothing
5945                          * else to do, just leave.
5946                          */
5947                         if (rval != DEV_INFO_SUCCESS) {
5948                                 return;
5949                         }
5950                 }
5951 
5952                 ASSERT(ptgt->m_devhdl == topo_node->devhdl);
5953 
5954                 mutex_exit(&mpt->m_mutex);
5955                 flags = topo_node->flags;
5956 
5957                 if (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) {
5958                         phymask = ptgt->m_addr.mta_phymask;
5959                         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
5960                         (void) sprintf(phy_mask_name, "%x", phymask);
5961                         parent = scsi_hba_iport_find(mpt->m_dip,
5962                             phy_mask_name);
5963                         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
5964                         if (parent == NULL) {
5965                                 mptsas_log(mpt, CE_WARN, "Failed to find a "
5966                                     "iport for PD, should not happen!");
5967                                 mutex_enter(&mpt->m_mutex);
5968                                 break;
5969                         }
5970                 }
5971 
5972                 if (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
5973                         ndi_devi_enter(parent, &circ1);
5974                         (void) mptsas_config_raid(parent, topo_node->devhdl,
5975                             &lundip);
5976                         ndi_devi_exit(parent, circ1);
5977                 } else {
5978                         /*
5979                          * hold nexus for bus configure
5980                          */
5981                         ndi_devi_enter(scsi_vhci_dip, &circ);
5982                         ndi_devi_enter(parent, &circ1);
5983                         rval = mptsas_config_target(parent, ptgt);
5984                         /*
5985                          * release nexus for bus configure
5986                          */
5987                         ndi_devi_exit(parent, circ1);
5988                         ndi_devi_exit(scsi_vhci_dip, circ);
5989 
5990                         /*
5991                          * Add parent's props for SMHBA support
5992                          */
5993                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
5994                                 bzero(attached_wwnstr,
5995                                     sizeof (attached_wwnstr));
5996                                 (void) sprintf(attached_wwnstr, "w%016"PRIx64,
5997                                     ptgt->m_addr.mta_wwn);
5998                                 if (ddi_prop_update_string(DDI_DEV_T_NONE,
5999                                     parent,
6000                                     SCSI_ADDR_PROP_ATTACHED_PORT,
6001                                     attached_wwnstr)
6002                                     != DDI_PROP_SUCCESS) {
6003                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6004                                             parent,
6005                                             SCSI_ADDR_PROP_ATTACHED_PORT);
6006                                         mptsas_log(mpt, CE_WARN, "Failed to"
6007                                             "attached-port props");
6008                                         return;
6009                                 }
6010                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6011                                     MPTSAS_NUM_PHYS, 1) !=
6012                                     DDI_PROP_SUCCESS) {
6013                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6014                                             parent, MPTSAS_NUM_PHYS);
6015                                         mptsas_log(mpt, CE_WARN, "Failed to"
6016                                             " create num-phys props");
6017                                         return;


6035                                  */
6036                                 mptsas_smhba_set_one_phy_props(mpt, parent,
6037                                     topo_node->un.physport, &attached_devhdl);
6038 
6039                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6040                                     MPTSAS_VIRTUAL_PORT, 0) !=
6041                                     DDI_PROP_SUCCESS) {
6042                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6043                                             parent, MPTSAS_VIRTUAL_PORT);
6044                                         mptsas_log(mpt, CE_WARN,
6045                                             "mptsas virtual-port"
6046                                             "port prop update failed");
6047                                         return;
6048                                 }
6049                         }
6050                 }
6051                 mutex_enter(&mpt->m_mutex);
6052 
6053                 NDBG20(("mptsas%d handle_topo_change to online devhdl:%x, "
6054                     "phymask:%x.", mpt->m_instance, ptgt->m_devhdl,
6055                     ptgt->m_addr.mta_phymask));
6056                 break;
6057         }
6058         case MPTSAS_DR_EVENT_OFFLINE_TARGET:
6059         {

6060                 devhdl = topo_node->devhdl;
6061                 ptgt = refhash_linear_search(mpt->m_targets,
6062                     mptsas_target_eval_devhdl, &devhdl);
6063                 if (ptgt == NULL)
6064                         break;
6065 
6066                 sas_wwn = ptgt->m_addr.mta_wwn;
6067                 phy = ptgt->m_phynum;
6068 
6069                 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
6070 
6071                 if (sas_wwn) {
6072                         (void) sprintf(addr, "w%016"PRIx64, sas_wwn);
6073                 } else {
6074                         (void) sprintf(addr, "p%x", phy);
6075                 }
6076                 ASSERT(ptgt->m_devhdl == devhdl);
6077 
6078                 if ((topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) ||
6079                     (topo_node->flags ==
6080                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6081                         /*
6082                          * Get latest RAID info if RAID volume status changes
6083                          * or Phys Disk status changes
6084                          */
6085                         (void) mptsas_get_raid_info(mpt);
6086                 }
6087                 /*
6088                  * Abort all outstanding command on the device
6089                  */
6090                 rval = mptsas_do_scsi_reset(mpt, devhdl);
6091                 if (rval) {
6092                         NDBG20(("mptsas%d handle_topo_change to reset target "
6093                             "before offline devhdl:%x, phymask:%x, rval:%x",
6094                             mpt->m_instance, ptgt->m_devhdl,
6095                             ptgt->m_addr.mta_phymask, rval));
6096                 }
6097 
6098                 mutex_exit(&mpt->m_mutex);
6099 
6100                 ndi_devi_enter(scsi_vhci_dip, &circ);
6101                 ndi_devi_enter(parent, &circ1);
6102                 rval = mptsas_offline_target(parent, addr);
6103                 ndi_devi_exit(parent, circ1);
6104                 ndi_devi_exit(scsi_vhci_dip, circ);
6105                 NDBG20(("mptsas%d handle_topo_change to offline devhdl:%x, "
6106                     "phymask:%x, rval:%x", mpt->m_instance,
6107                     ptgt->m_devhdl, ptgt->m_addr.mta_phymask, rval));
6108 
6109                 kmem_free(addr, SCSI_MAXNAMELEN);
6110 
6111                 /*
6112                  * Clear parent's props for SMHBA support
6113                  */
6114                 flags = topo_node->flags;
6115                 if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6116                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6117                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6118                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6119                             DDI_PROP_SUCCESS) {
6120                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6121                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6122                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6123                                     "prop update failed");
6124                                 break;
6125                         }
6126                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6127                             MPTSAS_NUM_PHYS, 0) !=


6130                                     MPTSAS_NUM_PHYS);
6131                                 mptsas_log(mpt, CE_WARN, "mptsas num phys "
6132                                     "prop update failed");
6133                                 break;
6134                         }
6135                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6136                             MPTSAS_VIRTUAL_PORT, 1) !=
6137                             DDI_PROP_SUCCESS) {
6138                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6139                                     MPTSAS_VIRTUAL_PORT);
6140                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6141                                     "prop update failed");
6142                                 break;
6143                         }
6144                 }
6145 
6146                 mutex_enter(&mpt->m_mutex);
6147                 ptgt->m_led_status = 0;
6148                 (void) mptsas_flush_led_status(mpt, ptgt);
6149                 if (rval == DDI_SUCCESS) {
6150                         refhash_remove(mpt->m_targets, ptgt);

6151                         ptgt = NULL;
6152                 } else {
6153                         /*
6154                          * clean DR_INTRANSITION flag to allow I/O down to
6155                          * PHCI driver since failover finished.
6156                          * Invalidate the devhdl
6157                          */
6158                         ptgt->m_devhdl = MPTSAS_INVALID_DEVHDL;
6159                         ptgt->m_tgt_unconfigured = 0;
6160                         mutex_enter(&mpt->m_tx_waitq_mutex);
6161                         ptgt->m_dr_flag = MPTSAS_DR_INACTIVE;
6162                         mutex_exit(&mpt->m_tx_waitq_mutex);
6163                 }
6164 
6165                 /*
6166                  * Send SAS IO Unit Control to free the dev handle
6167                  */
6168                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6169                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE)) {
6170                         rval = mptsas_free_devhdl(mpt, devhdl);


6187                         if (rval) {
6188                                 NDBG20(("mpt%d reset target before remove "
6189                                     "devhdl:%x, rval:%x", mpt->m_instance,
6190                                     devhdl, rval));
6191                         }
6192                 }
6193 
6194                 /*
6195                  * Send SAS IO Unit Control to free the dev handle
6196                  */
6197                 rval = mptsas_free_devhdl(mpt, devhdl);
6198                 NDBG20(("mptsas%d handle_topo_change to remove "
6199                     "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6200                     rval));
6201                 break;
6202         }
6203         case MPTSAS_DR_EVENT_RECONFIG_SMP:
6204         {
6205                 mptsas_smp_t smp;
6206                 dev_info_t *smpdip;

6207 
6208                 devhdl = topo_node->devhdl;
6209 
6210                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
6211                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)devhdl;
6212                 rval = mptsas_get_sas_expander_page0(mpt, page_address, &smp);
6213                 if (rval != DDI_SUCCESS) {
6214                         mptsas_log(mpt, CE_WARN, "failed to online smp, "
6215                             "handle %x", devhdl);
6216                         return;
6217                 }
6218 
6219                 psmp = mptsas_smp_alloc(mpt, &smp);
6220                 if (psmp == NULL) {
6221                         return;
6222                 }
6223 
6224                 mutex_exit(&mpt->m_mutex);
6225                 ndi_devi_enter(parent, &circ1);
6226                 (void) mptsas_online_smp(parent, psmp, &smpdip);
6227                 ndi_devi_exit(parent, circ1);
6228 
6229                 mutex_enter(&mpt->m_mutex);
6230                 break;
6231         }
6232         case MPTSAS_DR_EVENT_OFFLINE_SMP:
6233         {

6234                 devhdl = topo_node->devhdl;
6235                 uint32_t dev_info;
6236 
6237                 psmp = refhash_linear_search(mpt->m_smp_targets,
6238                     mptsas_smp_eval_devhdl, &devhdl);
6239                 if (psmp == NULL)
6240                         break;
6241                 /*
6242                  * The mptsas_smp_t data is released only if the dip is offlined
6243                  * successfully.
6244                  */
6245                 mutex_exit(&mpt->m_mutex);
6246 
6247                 ndi_devi_enter(parent, &circ1);
6248                 rval = mptsas_offline_smp(parent, psmp, NDI_DEVI_REMOVE);
6249                 ndi_devi_exit(parent, circ1);
6250 
6251                 dev_info = psmp->m_deviceinfo;
6252                 if ((dev_info & DEVINFO_DIRECT_ATTACHED) ==
6253                     DEVINFO_DIRECT_ATTACHED) {
6254                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6255                             MPTSAS_VIRTUAL_PORT, 1) !=
6256                             DDI_PROP_SUCCESS) {
6257                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6258                                     MPTSAS_VIRTUAL_PORT);


6274                         }
6275                         /*
6276                          * Clear parent's attached-port props
6277                          */
6278                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6279                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6280                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6281                             DDI_PROP_SUCCESS) {
6282                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6283                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6284                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6285                                     "prop update failed");
6286                                 return;
6287                         }
6288                 }
6289 
6290                 mutex_enter(&mpt->m_mutex);
6291                 NDBG20(("mptsas%d handle_topo_change to remove devhdl:%x, "
6292                     "rval:%x", mpt->m_instance, psmp->m_devhdl, rval));
6293                 if (rval == DDI_SUCCESS) {
6294                         refhash_remove(mpt->m_smp_targets, psmp);

6295                 } else {
6296                         psmp->m_devhdl = MPTSAS_INVALID_DEVHDL;
6297                 }
6298 
6299                 bzero(attached_wwnstr, sizeof (attached_wwnstr));
6300 
6301                 break;
6302         }
6303         default:
6304                 return;
6305         }
6306 }
6307 
6308 /*
6309  * Record the event if its type is enabled in mpt instance by ioctl.
6310  */
6311 static void
6312 mptsas_record_event(void *args)
6313 {
6314         m_replyh_arg_t                  *replyh_arg;


6433         }
6434 
6435         /*
6436          * figure out what kind of event we got and handle accordingly
6437          */
6438         switch (event) {
6439         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
6440         {
6441                 pMpi2EventDataSasTopologyChangeList_t   sas_topo_change_list;
6442                 uint8_t                         num_entries, expstatus, phy;
6443                 uint8_t                         phystatus, physport, state, i;
6444                 uint8_t                         start_phy_num, link_rate;
6445                 uint16_t                        dev_handle, reason_code;
6446                 uint16_t                        enc_handle, expd_handle;
6447                 char                            string[80], curr[80], prev[80];
6448                 mptsas_topo_change_list_t       *topo_head = NULL;
6449                 mptsas_topo_change_list_t       *topo_tail = NULL;
6450                 mptsas_topo_change_list_t       *topo_node = NULL;
6451                 mptsas_target_t                 *ptgt;
6452                 mptsas_smp_t                    *psmp;

6453                 uint8_t                         flags = 0, exp_flag;
6454                 smhba_info_t                    *pSmhba = NULL;
6455 
6456                 NDBG20(("mptsas_handle_event_sync: SAS topology change"));
6457 



6458                 sas_topo_change_list = (pMpi2EventDataSasTopologyChangeList_t)
6459                     eventreply->EventData;
6460 
6461                 enc_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6462                     &sas_topo_change_list->EnclosureHandle);
6463                 expd_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6464                     &sas_topo_change_list->ExpanderDevHandle);
6465                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6466                     &sas_topo_change_list->NumEntries);
6467                 start_phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
6468                     &sas_topo_change_list->StartPhyNum);
6469                 expstatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6470                     &sas_topo_change_list->ExpStatus);
6471                 physport = ddi_get8(mpt->m_acc_reply_frame_hdl,
6472                     &sas_topo_change_list->PhysicalPort);
6473 
6474                 string[0] = 0;
6475                 if (expd_handle) {
6476                         flags = MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED;
6477                         switch (expstatus) {


6483                                 mpt->m_port_chng = 1;
6484                                 topo_node = kmem_zalloc(
6485                                     sizeof (mptsas_topo_change_list_t),
6486                                     KM_SLEEP);
6487                                 topo_node->mpt = mpt;
6488                                 topo_node->event = MPTSAS_DR_EVENT_RECONFIG_SMP;
6489                                 topo_node->un.physport = physport;
6490                                 topo_node->devhdl = expd_handle;
6491                                 topo_node->flags = flags;
6492                                 topo_node->object = NULL;
6493                                 if (topo_head == NULL) {
6494                                         topo_head = topo_tail = topo_node;
6495                                 } else {
6496                                         topo_tail->next = topo_node;
6497                                         topo_tail = topo_node;
6498                                 }
6499                                 break;
6500                         case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
6501                                 (void) sprintf(string, " not responding, "
6502                                     "removed");
6503                                 psmp = refhash_linear_search(mpt->m_smp_targets,
6504                                     mptsas_smp_eval_devhdl, &expd_handle);
6505                                 if (psmp == NULL)
6506                                         break;
6507 
6508                                 topo_node = kmem_zalloc(
6509                                     sizeof (mptsas_topo_change_list_t),
6510                                     KM_SLEEP);
6511                                 topo_node->mpt = mpt;
6512                                 topo_node->un.phymask =
6513                                     psmp->m_addr.mta_phymask;
6514                                 topo_node->event = MPTSAS_DR_EVENT_OFFLINE_SMP;
6515                                 topo_node->devhdl = expd_handle;
6516                                 topo_node->flags = flags;
6517                                 topo_node->object = NULL;
6518                                 if (topo_head == NULL) {
6519                                         topo_head = topo_tail = topo_node;
6520                                 } else {
6521                                         topo_tail->next = topo_node;
6522                                         topo_tail = topo_node;
6523                                 }
6524                                 break;
6525                         case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
6526                                 break;
6527                         case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
6528                                 (void) sprintf(string, " not responding, "
6529                                     "delaying removal");
6530                                 break;
6531                         default:
6532                                 break;
6533                         }


6644                         case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
6645                         {
6646                                 NDBG20(("mptsas%d phy %d physical_port %d "
6647                                     "dev_handle %d removed", mpt->m_instance,
6648                                     phy, physport, dev_handle));
6649                                 /*
6650                                  * Set association flag according to if an
6651                                  * expander is used or not.
6652                                  */
6653                                 exp_flag =
6654                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
6655                                 if (flags ==
6656                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
6657                                         flags = exp_flag;
6658                                 }
6659                                 /*
6660                                  * Target device is removed from the system
6661                                  * Before the device is really offline from
6662                                  * from system.
6663                                  */
6664                                 ptgt = refhash_linear_search(mpt->m_targets,
6665                                     mptsas_target_eval_devhdl, &dev_handle);
6666                                 /*
6667                                  * If ptgt is NULL here, it means that the
6668                                  * DevHandle is not in the hash table.  This is
6669                                  * reasonable sometimes.  For example, if a
6670                                  * disk was pulled, then added, then pulled
6671                                  * again, the disk will not have been put into
6672                                  * the hash table because the add event will
6673                                  * have an invalid phymask.  BUT, this does not
6674                                  * mean that the DevHandle is invalid.  The
6675                                  * controller will still have a valid DevHandle
6676                                  * that must be removed.  To do this, use the
6677                                  * MPTSAS_TOPO_FLAG_REMOVE_HANDLE event.
6678                                  */
6679                                 if (ptgt == NULL) {
6680                                         topo_node = kmem_zalloc(
6681                                             sizeof (mptsas_topo_change_list_t),
6682                                             KM_SLEEP);
6683                                         topo_node->mpt = mpt;
6684                                         topo_node->un.phymask = 0;
6685                                         topo_node->event =


6697                                         break;
6698                                 }
6699 
6700                                 /*
6701                                  * Update DR flag immediately avoid I/O failure
6702                                  * before failover finish. Pay attention to the
6703                                  * mutex protect, we need grab m_tx_waitq_mutex
6704                                  * during set m_dr_flag because we won't add
6705                                  * the following command into waitq, instead,
6706                                  * we need return TRAN_BUSY in the tran_start
6707                                  * context.
6708                                  */
6709                                 mutex_enter(&mpt->m_tx_waitq_mutex);
6710                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6711                                 mutex_exit(&mpt->m_tx_waitq_mutex);
6712 
6713                                 topo_node = kmem_zalloc(
6714                                     sizeof (mptsas_topo_change_list_t),
6715                                     KM_SLEEP);
6716                                 topo_node->mpt = mpt;
6717                                 topo_node->un.phymask =
6718                                     ptgt->m_addr.mta_phymask;
6719                                 topo_node->event =
6720                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
6721                                 topo_node->devhdl = dev_handle;
6722                                 topo_node->flags = flags;
6723                                 topo_node->object = NULL;
6724                                 if (topo_head == NULL) {
6725                                         topo_head = topo_tail = topo_node;
6726                                 } else {
6727                                         topo_tail->next = topo_node;
6728                                         topo_tail = topo_node;
6729                                 }
6730                                 break;
6731                         }
6732                         case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
6733                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
6734                                     &sas_topo_change_list->PHY[i].LinkRate);
6735                                 state = (link_rate &
6736                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
6737                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
6738                                 pSmhba = &mpt->m_phy_info[i].smhba_info;


6858                 if (topo_head != NULL) {
6859                         /*
6860                          * Launch DR taskq to handle topology change
6861                          */
6862                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
6863                             mptsas_handle_dr, (void *)topo_head,
6864                             DDI_NOSLEEP)) != DDI_SUCCESS) {
6865                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
6866                                     "for handle SAS DR event failed. \n");
6867                         }
6868                 }
6869                 break;
6870         }
6871         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
6872         {
6873                 Mpi2EventDataIrConfigChangeList_t       *irChangeList;
6874                 mptsas_topo_change_list_t               *topo_head = NULL;
6875                 mptsas_topo_change_list_t               *topo_tail = NULL;
6876                 mptsas_topo_change_list_t               *topo_node = NULL;
6877                 mptsas_target_t                         *ptgt;

6878                 uint8_t                                 num_entries, i, reason;
6879                 uint16_t                                volhandle, diskhandle;
6880 
6881                 irChangeList = (pMpi2EventDataIrConfigChangeList_t)
6882                     eventreply->EventData;
6883                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6884                     &irChangeList->NumElements);
6885 


6886                 NDBG20(("mptsas%d IR_CONFIGURATION_CHANGE_LIST event received",
6887                     mpt->m_instance));
6888 
6889                 for (i = 0; i < num_entries; i++) {
6890                         reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
6891                             &irChangeList->ConfigElement[i].ReasonCode);
6892                         volhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6893                             &irChangeList->ConfigElement[i].VolDevHandle);
6894                         diskhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6895                             &irChangeList->ConfigElement[i].PhysDiskDevHandle);
6896 
6897                         switch (reason) {
6898                         case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6899                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6900                         {
6901                                 NDBG20(("mptsas %d volume added\n",
6902                                     mpt->m_instance));
6903 
6904                                 topo_node = kmem_zalloc(
6905                                     sizeof (mptsas_topo_change_list_t),


6909                                 topo_node->event =
6910                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
6911                                 topo_node->un.physport = 0xff;
6912                                 topo_node->devhdl = volhandle;
6913                                 topo_node->flags =
6914                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
6915                                 topo_node->object = NULL;
6916                                 if (topo_head == NULL) {
6917                                         topo_head = topo_tail = topo_node;
6918                                 } else {
6919                                         topo_tail->next = topo_node;
6920                                         topo_tail = topo_node;
6921                                 }
6922                                 break;
6923                         }
6924                         case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6925                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6926                         {
6927                                 NDBG20(("mptsas %d volume deleted\n",
6928                                     mpt->m_instance));
6929                                 ptgt = refhash_linear_search(mpt->m_targets,
6930                                     mptsas_target_eval_devhdl, &volhandle);
6931                                 if (ptgt == NULL)
6932                                         break;
6933 
6934                                 /*
6935                                  * Clear any flags related to volume
6936                                  */
6937                                 (void) mptsas_delete_volume(mpt, volhandle);
6938 
6939                                 /*
6940                                  * Update DR flag immediately avoid I/O failure
6941                                  */
6942                                 mutex_enter(&mpt->m_tx_waitq_mutex);
6943                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6944                                 mutex_exit(&mpt->m_tx_waitq_mutex);
6945 
6946                                 topo_node = kmem_zalloc(
6947                                     sizeof (mptsas_topo_change_list_t),
6948                                     KM_SLEEP);
6949                                 topo_node->mpt = mpt;
6950                                 topo_node->un.phymask =
6951                                     ptgt->m_addr.mta_phymask;
6952                                 topo_node->event =
6953                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
6954                                 topo_node->devhdl = volhandle;
6955                                 topo_node->flags =
6956                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
6957                                 topo_node->object = (void *)ptgt;
6958                                 if (topo_head == NULL) {
6959                                         topo_head = topo_tail = topo_node;
6960                                 } else {
6961                                         topo_tail->next = topo_node;
6962                                         topo_tail = topo_node;
6963                                 }
6964                                 break;
6965                         }
6966                         case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
6967                         case MPI2_EVENT_IR_CHANGE_RC_HIDE:
6968                         {
6969                                 ptgt = refhash_linear_search(mpt->m_targets,
6970                                     mptsas_target_eval_devhdl, &diskhandle);
6971                                 if (ptgt == NULL)
6972                                         break;
6973 
6974                                 /*
6975                                  * Update DR flag immediately avoid I/O failure
6976                                  */
6977                                 mutex_enter(&mpt->m_tx_waitq_mutex);
6978                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
6979                                 mutex_exit(&mpt->m_tx_waitq_mutex);
6980 
6981                                 topo_node = kmem_zalloc(
6982                                     sizeof (mptsas_topo_change_list_t),
6983                                     KM_SLEEP);
6984                                 topo_node->mpt = mpt;
6985                                 topo_node->un.phymask =
6986                                     ptgt->m_addr.mta_phymask;
6987                                 topo_node->event =
6988                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
6989                                 topo_node->devhdl = diskhandle;
6990                                 topo_node->flags =
6991                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
6992                                 topo_node->object = (void *)ptgt;
6993                                 if (topo_head == NULL) {
6994                                         topo_head = topo_tail = topo_node;
6995                                 } else {
6996                                         topo_tail->next = topo_node;
6997                                         topo_tail = topo_node;
6998                                 }
6999                                 break;
7000                         }
7001                         case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
7002                         case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
7003                         {
7004                                 /*
7005                                  * The physical drive is released by a IR
7006                                  * volume. But we cannot get the the physport


7391                             SAS_PORT_BROADCAST_D27_4,
7392                             &mpt->m_phy_info[phy_num].smhba_info);
7393                         break;
7394                 default:
7395                         NDBG20(("mptsas%d: unknown BROADCAST PRIMITIVE"
7396                             " %x received",
7397                             mpt->m_instance, primitive));
7398                         break;
7399                 }
7400                 NDBG20(("mptsas%d sas broadcast primitive: "
7401                     "\tprimitive(0x%04x), phy(%d) complete\n",
7402                     mpt->m_instance, primitive, phy_num));
7403                 break;
7404         }
7405         case MPI2_EVENT_IR_VOLUME:
7406         {
7407                 Mpi2EventDataIrVolume_t         *irVolume;
7408                 uint16_t                        devhandle;
7409                 uint32_t                        state;
7410                 int                             config, vol;

7411                 uint8_t                         found = FALSE;
7412 
7413                 irVolume = (pMpi2EventDataIrVolume_t)eventreply->EventData;
7414                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7415                     &irVolume->NewValue);
7416                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7417                     &irVolume->VolDevHandle);
7418 
7419                 NDBG20(("EVENT_IR_VOLUME event is received"));
7420 
7421                 /*
7422                  * Get latest RAID info and then find the DevHandle for this
7423                  * event in the configuration.  If the DevHandle is not found
7424                  * just exit the event.
7425                  */
7426                 (void) mptsas_get_raid_info(mpt);
7427                 for (config = 0; (config < mpt->m_num_raid_configs) &&
7428                     (!found); config++) {
7429                         for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
7430                                 if (mpt->m_raidconfig[config].m_raidvol[vol].
7431                                     m_raidhandle == devhandle) {
7432                                         found = TRUE;
7433                                         break;
7434                                 }
7435                         }
7436                 }
7437                 if (!found) {
7438                         break;
7439                 }
7440 
7441                 switch (irVolume->ReasonCode) {
7442                 case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
7443                 {
7444                         uint32_t i;
7445                         mpt->m_raidconfig[config].m_raidvol[vol].m_settings =
7446                             state;
7447 
7448                         i = state & MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING;
7449                         mptsas_log(mpt, CE_NOTE, " Volume %d settings changed"
7450                             ", auto-config of hot-swap drives is %s"
7451                             ", write caching is %s"
7452                             ", hot-spare pool mask is %02x\n",
7453                             vol, state &
7454                             MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE
7455                             ? "disabled" : "enabled",
7456                             i == MPI2_RAIDVOL0_SETTING_UNCHANGED
7457                             ? "controlled by member disks" :
7458                             i == MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING
7459                             ? "disabled" :
7460                             i == MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING
7461                             ? "enabled" :
7462                             "incorrectly set",
7463                             (state >> 16) & 0xff);
7464                                 break;
7465                 }
7466                 case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
7467                 {
7468                         mpt->m_raidconfig[config].m_raidvol[vol].m_state =
7469                             (uint8_t)state;
7470 
7471                         mptsas_log(mpt, CE_NOTE,
7472                             "Volume %d is now %s\n", vol,
7473                             state == MPI2_RAID_VOL_STATE_OPTIMAL
7474                             ? "optimal" :
7475                             state == MPI2_RAID_VOL_STATE_DEGRADED
7476                             ? "degraded" :
7477                             state == MPI2_RAID_VOL_STATE_ONLINE
7478                             ? "online" :
7479                             state == MPI2_RAID_VOL_STATE_INITIALIZING
7480                             ? "initializing" :
7481                             state == MPI2_RAID_VOL_STATE_FAILED
7482                             ? "failed" :
7483                             state == MPI2_RAID_VOL_STATE_MISSING
7484                             ? "missing" :
7485                             "state unknown");
7486                         break;
7487                 }
7488                 case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
7489                 {
7490                         mpt->m_raidconfig[config].m_raidvol[vol].
7491                             m_statusflags = state;
7492 
7493                         mptsas_log(mpt, CE_NOTE,
7494                             " Volume %d is now %s%s%s%s%s%s%s%s%s\n",
7495                             vol,
7496                             state & MPI2_RAIDVOL0_STATUS_FLAG_ENABLED
7497                             ? ", enabled" : ", disabled",
7498                             state & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED
7499                             ? ", quiesced" : "",
7500                             state & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE
7501                             ? ", inactive" : ", active",
7502                             state &
7503                             MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL
7504                             ? ", bad block table is full" : "",
7505                             state &
7506                             MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
7507                             ? ", resync in progress" : "",
7508                             state & MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT
7509                             ? ", background initialization in progress" : "",
7510                             state &


7619                 mpt->m_free_index = 0;
7620         }
7621         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
7622             mpt->m_free_index);
7623         mutex_exit(&mpt->m_mutex);
7624 }
7625 
7626 /*
7627  * invoked from timeout() to restart qfull cmds with throttle == 0
7628  */
7629 static void
7630 mptsas_restart_cmd(void *arg)
7631 {
7632         mptsas_t        *mpt = arg;
7633         mptsas_target_t *ptgt = NULL;
7634 
7635         mutex_enter(&mpt->m_mutex);
7636 
7637         mpt->m_restart_cmd_timeid = 0;
7638 
7639         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
7640             ptgt = refhash_next(mpt->m_targets, ptgt)) {

7641                 if (ptgt->m_reset_delay == 0) {
7642                         if (ptgt->m_t_throttle == QFULL_THROTTLE) {
7643                                 mptsas_set_throttle(mpt, ptgt,
7644                                     MAX_THROTTLE);
7645                         }
7646                 }



7647         }
7648         mptsas_restart_hba(mpt);
7649         mutex_exit(&mpt->m_mutex);
7650 }
7651 
7652 void
7653 mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
7654 {
7655         int             slot;
7656         mptsas_slots_t  *slots = mpt->m_active;
7657         int             t;
7658         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
7659 
7660         ASSERT(cmd != NULL);
7661         ASSERT(cmd->cmd_queued == FALSE);
7662 
7663         /*
7664          * Task Management cmds are removed in their own routines.  Also,
7665          * we don't want to modify timeout based on TM cmds.
7666          */


7698         }
7699 
7700         /*
7701          * This is all we need to do for ioc commands.
7702          */
7703         if (cmd->cmd_flags & CFLAG_CMDIOC) {
7704                 mptsas_return_to_pool(mpt, cmd);
7705                 return;
7706         }
7707 
7708         /*
7709          * Figure out what to set tag Q timeout for...
7710          *
7711          * Optimize: If we have duplicate's of same timeout
7712          * we're using, then we'll use it again until we run
7713          * out of duplicates.  This should be the normal case
7714          * for block and raw I/O.
7715          * If no duplicates, we have to scan through tag que and
7716          * find the longest timeout value and use it.  This is
7717          * going to take a while...
7718          * Add 1 to m_n_normal to account for TM request.
7719          */
7720         if (cmd->cmd_pkt->pkt_time == ptgt->m_timebase) {
7721                 if (--(ptgt->m_dups) == 0) {
7722                         if (ptgt->m_t_ncmds) {
7723                                 mptsas_cmd_t *ssp;
7724                                 uint_t n = 0;
7725                                 ushort_t nslots = (slots->m_n_normal + 1);
7726                                 ushort_t i;
7727                                 /*
7728                                  * This crude check assumes we don't do
7729                                  * this too often which seems reasonable
7730                                  * for block and raw I/O.
7731                                  */
7732                                 for (i = 0; i < nslots; i++) {
7733                                         ssp = slots->m_slot[i];
7734                                         if (ssp && (Tgt(ssp) == t) &&
7735                                             (ssp->cmd_pkt->pkt_time > n)) {
7736                                                 n = ssp->cmd_pkt->pkt_time;
7737                                                 ptgt->m_dups = 1;
7738                                         } else if (ssp && (Tgt(ssp) == t) &&
7739                                             (ssp->cmd_pkt->pkt_time == n)) {
7740                                                 ptgt->m_dups++;
7741                                         }
7742                                 }
7743                                 ptgt->m_timebase = n;
7744                         } else {
7745                                 ptgt->m_dups = 0;


8464                 drv_usecwait(mpt->m_scsi_reset_delay * 1000);
8465         }
8466         rval = mptsas_do_scsi_reset(mpt, ptgt->m_devhdl);
8467         mutex_exit(&mpt->m_mutex);
8468 
8469         /*
8470          * The transport layer expect to only see TRUE and
8471          * FALSE. Therefore, we will adjust the return value
8472          * if mptsas_do_scsi_reset returns FAILED.
8473          */
8474         if (rval == FAILED)
8475                 rval = FALSE;
8476         return (rval);
8477 }
8478 
8479 static int
8480 mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl)
8481 {
8482         int             rval = FALSE;
8483         uint8_t         config, disk;

8484 
8485         ASSERT(mutex_owned(&mpt->m_mutex));
8486 
8487         if (mptsas_debug_resets) {
8488                 mptsas_log(mpt, CE_WARN, "mptsas_do_scsi_reset: target=%d",
8489                     devhdl);
8490         }
8491 
8492         /*
8493          * Issue a Target Reset message to the target specified but not to a
8494          * disk making up a raid volume.  Just look through the RAID config
8495          * Phys Disk list of DevHandles.  If the target's DevHandle is in this
8496          * list, then don't reset this target.
8497          */
8498         for (config = 0; config < mpt->m_num_raid_configs; config++) {
8499                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
8500                         if (devhdl == mpt->m_raidconfig[config].
8501                             m_physdisk_devhdl[disk]) {
8502                                 return (TRUE);
8503                         }
8504                 }
8505         }
8506 
8507         rval = mptsas_ioc_task_management(mpt,
8508             MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, devhdl, 0, NULL, 0, 0);
8509 
8510         mptsas_doneq_empty(mpt);
8511         return (rval);
8512 }
8513 
8514 static int
8515 mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
8516         void (*callback)(caddr_t), caddr_t arg)
8517 {
8518         mptsas_t        *mpt = ADDR2MPT(ap);
8519 
8520         NDBG22(("mptsas_scsi_reset_notify: tgt=%d", ap->a_target));


8576  * commands for a particular target.   For the case of abort task set, this
8577  * function clears the waitq of all commonds for a particular target/lun.
8578  */
8579 static void
8580 mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun, uint8_t tasktype)
8581 {
8582         mptsas_slots_t  *slots = mpt->m_active;
8583         mptsas_cmd_t    *cmd, *next_cmd;
8584         int             slot;
8585         uchar_t         reason;
8586         uint_t          stat;
8587 
8588         NDBG25(("mptsas_flush_target: target=%d lun=%d", target, lun));
8589 
8590         /*
8591          * Make sure the I/O Controller has flushed all cmds
8592          * that are associated with this target for a target reset
8593          * and target/lun for abort task set.
8594          * Account for TM requests, which use the last SMID.
8595          */
8596         for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
8597                 if ((cmd = slots->m_slot[slot]) == NULL)
8598                         continue;
8599                 reason = CMD_RESET;
8600                 stat = STAT_DEV_RESET;
8601                 switch (tasktype) {
8602                 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
8603                         if (Tgt(cmd) == target) {
8604                                 NDBG25(("mptsas_flush_target discovered non-"
8605                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
8606                                     tasktype));
8607                                 mptsas_dump_cmd(mpt, cmd);
8608                                 mptsas_remove_cmd(mpt, cmd);
8609                                 mptsas_set_pkt_reason(mpt, cmd, reason, stat);
8610                                 mptsas_doneq_add(mpt, cmd);
8611                         }
8612                         break;
8613                 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
8614                         reason = CMD_ABORTED;
8615                         stat = STAT_ABORTED;
8616                         /*FALLTHROUGH*/


8708 
8709 /*
8710  * Clean up hba state, abort all outstanding command and commands in waitq
8711  * reset timeout of all targets.
8712  */
8713 static void
8714 mptsas_flush_hba(mptsas_t *mpt)
8715 {
8716         mptsas_slots_t  *slots = mpt->m_active;
8717         mptsas_cmd_t    *cmd;
8718         int             slot;
8719 
8720         NDBG25(("mptsas_flush_hba"));
8721 
8722         /*
8723          * The I/O Controller should have already sent back
8724          * all commands via the scsi I/O reply frame.  Make
8725          * sure all commands have been flushed.
8726          * Account for TM request, which use the last SMID.
8727          */
8728         for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
8729                 if ((cmd = slots->m_slot[slot]) == NULL)
8730                         continue;
8731 
8732                 if (cmd->cmd_flags & CFLAG_CMDIOC) {
8733                         /*
8734                          * Need to make sure to tell everyone that might be
8735                          * waiting on this command that it's going to fail.  If
8736                          * we get here, this command will never timeout because
8737                          * the active command table is going to be re-allocated,
8738                          * so there will be nothing to check against a time out.
8739                          * Instead, mark the command as failed due to reset.
8740                          */
8741                         mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
8742                             STAT_BUS_RESET);
8743                         if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
8744                             (cmd->cmd_flags & CFLAG_CONFIG) ||
8745                             (cmd->cmd_flags & CFLAG_FW_DIAG)) {
8746                                 cmd->cmd_flags |= CFLAG_FINISHED;
8747                                 cv_broadcast(&mpt->m_passthru_cv);
8748                                 cv_broadcast(&mpt->m_config_cv);


8823 static void
8824 mptsas_start_watch_reset_delay()
8825 {
8826         NDBG22(("mptsas_start_watch_reset_delay"));
8827 
8828         mutex_enter(&mptsas_global_mutex);
8829         if (mptsas_reset_watch == NULL && mptsas_timeouts_enabled) {
8830                 mptsas_reset_watch = timeout(mptsas_watch_reset_delay, NULL,
8831                     drv_usectohz((clock_t)
8832                     MPTSAS_WATCH_RESET_DELAY_TICK * 1000));
8833                 ASSERT(mptsas_reset_watch != NULL);
8834         }
8835         mutex_exit(&mptsas_global_mutex);
8836 }
8837 
8838 static void
8839 mptsas_setup_bus_reset_delay(mptsas_t *mpt)
8840 {
8841         mptsas_target_t *ptgt = NULL;
8842 
8843         ASSERT(MUTEX_HELD(&mpt->m_mutex));
8844 
8845         NDBG22(("mptsas_setup_bus_reset_delay"));
8846         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
8847             ptgt = refhash_next(mpt->m_targets, ptgt)) {

8848                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
8849                 ptgt->m_reset_delay = mpt->m_scsi_reset_delay;



8850         }
8851 
8852         mptsas_start_watch_reset_delay();
8853 }
8854 
8855 /*
8856  * mptsas_watch_reset_delay(_subr) is invoked by timeout() and checks every
8857  * mpt instance for active reset delays
8858  */
8859 static void
8860 mptsas_watch_reset_delay(void *arg)
8861 {
8862 #ifndef __lock_lint
8863         _NOTE(ARGUNUSED(arg))
8864 #endif
8865 
8866         mptsas_t        *mpt;
8867         int             not_done = 0;
8868 
8869         NDBG22(("mptsas_watch_reset_delay"));


8881                 mutex_exit(&mpt->m_mutex);
8882         }
8883         rw_exit(&mptsas_global_rwlock);
8884 
8885         if (not_done) {
8886                 mptsas_start_watch_reset_delay();
8887         }
8888 }
8889 
8890 static int
8891 mptsas_watch_reset_delay_subr(mptsas_t *mpt)
8892 {
8893         int             done = 0;
8894         int             restart = 0;
8895         mptsas_target_t *ptgt = NULL;
8896 
8897         NDBG22(("mptsas_watch_reset_delay_subr: mpt=0x%p", (void *)mpt));
8898 
8899         ASSERT(mutex_owned(&mpt->m_mutex));
8900 
8901         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
8902             ptgt = refhash_next(mpt->m_targets, ptgt)) {

8903                 if (ptgt->m_reset_delay != 0) {
8904                         ptgt->m_reset_delay -=
8905                             MPTSAS_WATCH_RESET_DELAY_TICK;
8906                         if (ptgt->m_reset_delay <= 0) {
8907                                 ptgt->m_reset_delay = 0;
8908                                 mptsas_set_throttle(mpt, ptgt,
8909                                     MAX_THROTTLE);
8910                                 restart++;
8911                         } else {
8912                                 done = -1;
8913                         }
8914                 }



8915         }
8916 
8917         if (restart > 0) {
8918                 mptsas_restart_hba(mpt);
8919         }
8920         return (done);
8921 }
8922 
8923 #ifdef MPTSAS_TEST
8924 static void
8925 mptsas_test_reset(mptsas_t *mpt, int target)
8926 {
8927         mptsas_target_t    *ptgt = NULL;
8928 
8929         if (mptsas_rtest == target) {
8930                 if (mptsas_do_scsi_reset(mpt, target) == TRUE) {
8931                         mptsas_rtest = -1;
8932                 }
8933                 if (mptsas_rtest == -1) {
8934                         NDBG22(("mptsas_test_reset success"));


9198  */
9199 /*ARGSUSED*/
9200 static int
9201 mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp)
9202 {
9203         NDBG24(("mptsas_scsi_capchk: cap=%s", cap));
9204 
9205         if (!cap)
9206                 return (FALSE);
9207 
9208         *cidxp = scsi_hba_lookup_capstr(cap);
9209         return (TRUE);
9210 }
9211 
9212 static int
9213 mptsas_alloc_active_slots(mptsas_t *mpt, int flag)
9214 {
9215         mptsas_slots_t  *old_active = mpt->m_active;
9216         mptsas_slots_t  *new_active;
9217         size_t          size;

9218 
9219         /*
9220          * if there are active commands, then we cannot
9221          * change size of active slots array.
9222          */
9223         ASSERT(mpt->m_ncmds == 0);
9224 
9225         size = MPTSAS_SLOTS_SIZE(mpt);
9226         new_active = kmem_zalloc(size, flag);
9227         if (new_active == NULL) {
9228                 NDBG1(("new active alloc failed"));
9229                 return (-1);
9230         }
9231         /*
9232          * Since SMID 0 is reserved and the TM slot is reserved, the
9233          * number of slots that can be used at any one time is
9234          * m_max_requests - 2.
9235          */
9236         new_active->m_n_normal = (mpt->m_max_requests - 2);
9237         new_active->m_size = size;
9238         new_active->m_rotor = 1;
9239         if (old_active)








9240                 mptsas_free_active_slots(mpt);

9241         mpt->m_active = new_active;

9242 
9243         return (0);
9244 }
9245 
9246 static void
9247 mptsas_free_active_slots(mptsas_t *mpt)
9248 {
9249         mptsas_slots_t  *active = mpt->m_active;
9250         size_t          size;
9251 
9252         if (active == NULL)
9253                 return;
9254         size = active->m_size;
9255         kmem_free(active, size);
9256         mpt->m_active = NULL;
9257 }
9258 
9259 /*
9260  * Error logging, printing, and debug print routines.
9261  */
9262 static char *mptsas_label = "mpt_sas";
9263 


9368                         (void) pm_idle_component(mpt->m_dip, 0);
9369                 }
9370 
9371                 mutex_exit(&mpt->m_mutex);
9372         }
9373         rw_exit(&mptsas_global_rwlock);
9374 
9375         mutex_enter(&mptsas_global_mutex);
9376         if (mptsas_timeouts_enabled)
9377                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
9378         mutex_exit(&mptsas_global_mutex);
9379 }
9380 
9381 static void
9382 mptsas_watchsubr(mptsas_t *mpt)
9383 {
9384         int             i;
9385         mptsas_cmd_t    *cmd;
9386         mptsas_target_t *ptgt = NULL;
9387 
9388         ASSERT(MUTEX_HELD(&mpt->m_mutex));
9389 
9390         NDBG30(("mptsas_watchsubr: mpt=0x%p", (void *)mpt));
9391 
9392 #ifdef MPTSAS_TEST
9393         if (mptsas_enable_untagged) {
9394                 mptsas_test_untagged++;
9395         }
9396 #endif
9397 
9398         /*
9399          * Check for commands stuck in active slot
9400          * Account for TM requests, which use the last SMID.
9401          */
9402         for (i = 0; i <= mpt->m_active->m_n_normal; i++) {
9403                 if ((cmd = mpt->m_active->m_slot[i]) != NULL) {
9404                         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
9405                                 cmd->cmd_active_timeout -=
9406                                     mptsas_scsi_watchdog_tick;
9407                                 if (cmd->cmd_active_timeout <= 0) {
9408                                         /*
9409                                          * There seems to be a command stuck
9410                                          * in the active slot.  Drain throttle.
9411                                          */
9412                                         mptsas_set_throttle(mpt,
9413                                             cmd->cmd_tgt_addr,
9414                                             DRAIN_THROTTLE);
9415                                 }
9416                         }
9417                         if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
9418                             (cmd->cmd_flags & CFLAG_CONFIG) ||
9419                             (cmd->cmd_flags & CFLAG_FW_DIAG)) {
9420                                 cmd->cmd_active_timeout -=
9421                                     mptsas_scsi_watchdog_tick;
9422                                 if (cmd->cmd_active_timeout <= 0) {
9423                                         /*
9424                                          * passthrough command timeout
9425                                          */
9426                                         cmd->cmd_flags |= (CFLAG_FINISHED |
9427                                             CFLAG_TIMEOUT);
9428                                         cv_broadcast(&mpt->m_passthru_cv);
9429                                         cv_broadcast(&mpt->m_config_cv);
9430                                         cv_broadcast(&mpt->m_fw_diag_cv);
9431                                 }
9432                         }
9433                 }
9434         }
9435 
9436         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9437             ptgt = refhash_next(mpt->m_targets, ptgt)) {

9438                 /*
9439                  * If we were draining due to a qfull condition,
9440                  * go back to full throttle.
9441                  */
9442                 if ((ptgt->m_t_throttle < MAX_THROTTLE) &&
9443                     (ptgt->m_t_throttle > HOLD_THROTTLE) &&
9444                     (ptgt->m_t_ncmds < ptgt->m_t_throttle)) {
9445                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9446                         mptsas_restart_hba(mpt);
9447                 }
9448 
9449                 if ((ptgt->m_t_ncmds > 0) &&
9450                     (ptgt->m_timebase)) {
9451 
9452                         if (ptgt->m_timebase <=
9453                             mptsas_scsi_watchdog_tick) {
9454                                 ptgt->m_timebase +=
9455                                     mptsas_scsi_watchdog_tick;


9456                                 continue;
9457                         }
9458 
9459                         ptgt->m_timeout -= mptsas_scsi_watchdog_tick;
9460 
9461                         if (ptgt->m_timeout < 0) {
9462                                 mptsas_cmd_timeout(mpt, ptgt->m_devhdl);


9463                                 continue;
9464                         }
9465 
9466                         if ((ptgt->m_timeout) <=
9467                             mptsas_scsi_watchdog_tick) {
9468                                 NDBG23(("pending timeout"));
9469                                 mptsas_set_throttle(mpt, ptgt,
9470                                     DRAIN_THROTTLE);
9471                         }
9472                 }



9473         }
9474 }
9475 
9476 /*
9477  * timeout recovery
9478  */
9479 static void
9480 mptsas_cmd_timeout(mptsas_t *mpt, uint16_t devhdl)
9481 {
9482 
9483         NDBG29(("mptsas_cmd_timeout: target=%d", devhdl));
9484         mptsas_log(mpt, CE_WARN, "Disconnected command timeout for "
9485             "Target %d", devhdl);
9486 
9487         /*
9488          * If the current target is not the target passed in,
9489          * try to reset that target.
9490          */
9491         NDBG29(("mptsas_cmd_timeout: device reset"));
9492         if (mptsas_do_scsi_reset(mpt, devhdl) != TRUE) {


9516 {
9517         mptsas_t                *mpt;
9518         scsi_hba_tran_t *tran;
9519 
9520         tran = ddi_get_driver_private(dip);
9521         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
9522                 return (-1);
9523 
9524         return (mptsas_unquiesce_bus(mpt));
9525 }
9526 
9527 static int
9528 mptsas_quiesce_bus(mptsas_t *mpt)
9529 {
9530         mptsas_target_t *ptgt = NULL;
9531 
9532         NDBG28(("mptsas_quiesce_bus"));
9533         mutex_enter(&mpt->m_mutex);
9534 
9535         /* Set all the throttles to zero */
9536         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9537             ptgt = refhash_next(mpt->m_targets, ptgt)) {

9538                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);



9539         }
9540 
9541         /* If there are any outstanding commands in the queue */
9542         if (mpt->m_ncmds) {
9543                 mpt->m_softstate |= MPTSAS_SS_DRAINING;
9544                 mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
9545                     mpt, (MPTSAS_QUIESCE_TIMEOUT * drv_usectohz(1000000)));
9546                 if (cv_wait_sig(&mpt->m_cv, &mpt->m_mutex) == 0) {
9547                         /*
9548                          * Quiesce has been interrupted
9549                          */
9550                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
9551                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9552                             ptgt = refhash_next(mpt->m_targets, ptgt)) {

9553                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);



9554                         }
9555                         mptsas_restart_hba(mpt);
9556                         if (mpt->m_quiesce_timeid != 0) {
9557                                 timeout_id_t tid = mpt->m_quiesce_timeid;
9558                                 mpt->m_quiesce_timeid = 0;
9559                                 mutex_exit(&mpt->m_mutex);
9560                                 (void) untimeout(tid);
9561                                 return (-1);
9562                         }
9563                         mutex_exit(&mpt->m_mutex);
9564                         return (-1);
9565                 } else {
9566                         /* Bus has been quiesced */
9567                         ASSERT(mpt->m_quiesce_timeid == 0);
9568                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
9569                         mpt->m_softstate |= MPTSAS_SS_QUIESCED;
9570                         mutex_exit(&mpt->m_mutex);
9571                         return (0);
9572                 }
9573         }
9574         /* Bus was not busy - QUIESCED */
9575         mutex_exit(&mpt->m_mutex);
9576 
9577         return (0);
9578 }
9579 
9580 static int
9581 mptsas_unquiesce_bus(mptsas_t *mpt)
9582 {
9583         mptsas_target_t *ptgt = NULL;
9584 
9585         NDBG28(("mptsas_unquiesce_bus"));
9586         mutex_enter(&mpt->m_mutex);
9587         mpt->m_softstate &= ~MPTSAS_SS_QUIESCED;
9588         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9589             ptgt = refhash_next(mpt->m_targets, ptgt)) {

9590                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);



9591         }
9592         mptsas_restart_hba(mpt);
9593         mutex_exit(&mpt->m_mutex);
9594         return (0);
9595 }
9596 
9597 static void
9598 mptsas_ncmds_checkdrain(void *arg)
9599 {
9600         mptsas_t        *mpt = arg;
9601         mptsas_target_t *ptgt = NULL;
9602 
9603         mutex_enter(&mpt->m_mutex);
9604         if (mpt->m_softstate & MPTSAS_SS_DRAINING) {
9605                 mpt->m_quiesce_timeid = 0;
9606                 if (mpt->m_ncmds == 0) {
9607                         /* Command queue has been drained */
9608                         cv_signal(&mpt->m_cv);
9609                 } else {
9610                         /*
9611                          * The throttle may have been reset because
9612                          * of a SCSI bus reset
9613                          */
9614                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9615                             ptgt = refhash_next(mpt->m_targets, ptgt)) {

9616                                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);



9617                         }
9618 
9619                         mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
9620                             mpt, (MPTSAS_QUIESCE_TIMEOUT *
9621                             drv_usectohz(1000000)));
9622                 }
9623         }
9624         mutex_exit(&mpt->m_mutex);
9625 }
9626 
9627 /*ARGSUSED*/
9628 static void
9629 mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
9630 {
9631         int     i;
9632         uint8_t *cp = (uchar_t *)cmd->cmd_pkt->pkt_cdbp;
9633         char    buf[128];
9634 
9635         buf[0] = '\0';
9636         NDBG25(("?Cmd (0x%p) dump for Target %d Lun %d:\n", (void *)cmd,


11328 
11329         if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) {
11330                 return (EFAULT);
11331         }
11332 
11333         if ((lc.Command != MPTSAS_LEDCTL_FLAG_SET &&
11334             lc.Command != MPTSAS_LEDCTL_FLAG_GET) ||
11335             lc.Led < MPTSAS_LEDCTL_LED_MIN ||
11336             lc.Led > MPTSAS_LEDCTL_LED_MAX ||
11337             (lc.Command == MPTSAS_LEDCTL_FLAG_SET && lc.LedStatus != 0 &&
11338             lc.LedStatus != 1)) {
11339                 return (EINVAL);
11340         }
11341 
11342         if ((lc.Command == MPTSAS_LEDCTL_FLAG_SET && (mode & FWRITE) == 0) ||
11343             (lc.Command == MPTSAS_LEDCTL_FLAG_GET && (mode & FREAD) == 0))
11344                 return (EACCES);
11345 
11346         /* Locate the target we're interrogating... */
11347         mutex_enter(&mpt->m_mutex);
11348         ptgt = refhash_linear_search(mpt->m_targets,
11349             mptsas_target_eval_slot, &lc);








11350         if (ptgt == NULL) {
11351                 /* We could not find a target for that enclosure/slot. */
11352                 mutex_exit(&mpt->m_mutex);
11353                 return (ENOENT);
11354         }
11355 
11356         if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) {
11357                 /* Update our internal LED state. */
11358                 ptgt->m_led_status &= ~(1 << (lc.Led - 1));
11359                 ptgt->m_led_status |= lc.LedStatus << (lc.Led - 1);
11360 
11361                 /* Flush it to the controller. */
11362                 ret = mptsas_flush_led_status(mpt, ptgt);
11363                 mutex_exit(&mpt->m_mutex);
11364                 return (ret);
11365         }
11366 
11367         /* Return our internal LED state. */
11368         lc.LedStatus = (ptgt->m_led_status >> (lc.Led - 1)) & 1;
11369         mutex_exit(&mpt->m_mutex);


11380 {
11381         uint16_t i = 0;
11382         uint16_t count = 0;
11383         int ret = 0;
11384         mptsas_target_t *ptgt;
11385         mptsas_disk_info_t *di;
11386         STRUCT_DECL(mptsas_get_disk_info, gdi);
11387 
11388         if ((mode & FREAD) == 0)
11389                 return (EACCES);
11390 
11391         STRUCT_INIT(gdi, get_udatamodel());
11392 
11393         if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi),
11394             mode) != 0) {
11395                 return (EFAULT);
11396         }
11397 
11398         /* Find out how many targets there are. */
11399         mutex_enter(&mpt->m_mutex);
11400         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11401             ptgt = refhash_next(mpt->m_targets, ptgt)) {

11402                 count++;


11403         }
11404         mutex_exit(&mpt->m_mutex);
11405 
11406         /*
11407          * If we haven't been asked to copy out information on each target,
11408          * then just return the count.
11409          */
11410         STRUCT_FSET(gdi, DiskCount, count);
11411         if (STRUCT_FGETP(gdi, PtrDiskInfoArray) == NULL)
11412                 goto copy_out;
11413 
11414         /*
11415          * If we haven't been given a large enough buffer to copy out into,
11416          * let the caller know.
11417          */
11418         if (STRUCT_FGET(gdi, DiskInfoArraySize) <
11419             count * sizeof (mptsas_disk_info_t)) {
11420                 ret = ENOSPC;
11421                 goto copy_out;
11422         }
11423 
11424         di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP);
11425 
11426         mutex_enter(&mpt->m_mutex);
11427         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11428             ptgt = refhash_next(mpt->m_targets, ptgt)) {

11429                 if (i >= count) {
11430                         /*
11431                          * The number of targets changed while we weren't
11432                          * looking, so give up.
11433                          */
11434                         refhash_rele(mpt->m_targets, ptgt);
11435                         mutex_exit(&mpt->m_mutex);
11436                         kmem_free(di, count * sizeof (mptsas_disk_info_t));
11437                         return (EAGAIN);
11438                 }
11439                 di[i].Instance = mpt->m_instance;
11440                 di[i].Enclosure = ptgt->m_enclosure;
11441                 di[i].Slot = ptgt->m_slot_num;
11442                 di[i].SasAddress = ptgt->m_addr.mta_wwn;



11443                 i++;
11444         }
11445         mutex_exit(&mpt->m_mutex);
11446         STRUCT_FSET(gdi, DiskCount, i);
11447 
11448         /* Copy out the disk information to the caller. */
11449         if (ddi_copyout((void *)di, STRUCT_FGETP(gdi, PtrDiskInfoArray),
11450             i * sizeof (mptsas_disk_info_t), mode) != 0) {
11451                 ret = EFAULT;
11452         }
11453 
11454         kmem_free(di, count * sizeof (mptsas_disk_info_t));
11455 
11456 copy_out:
11457         if (ddi_copyout(STRUCT_BUF(gdi), (void *)data, STRUCT_SIZE(gdi),
11458             mode) != 0) {
11459                 ret = EFAULT;
11460         }
11461 
11462         return (ret);


11728 int
11729 mptsas_restart_ioc(mptsas_t *mpt)
11730 {
11731         int             rval = DDI_SUCCESS;
11732         mptsas_target_t *ptgt = NULL;
11733 
11734         ASSERT(mutex_owned(&mpt->m_mutex));
11735 
11736         /*
11737          * Set a flag telling I/O path that we're processing a reset.  This is
11738          * needed because after the reset is complete, the hash table still
11739          * needs to be rebuilt.  If I/Os are started before the hash table is
11740          * rebuilt, I/O errors will occur.  This flag allows I/Os to be marked
11741          * so that they can be retried.
11742          */
11743         mpt->m_in_reset = TRUE;
11744 
11745         /*
11746          * Set all throttles to HOLD
11747          */
11748         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11749             ptgt = refhash_next(mpt->m_targets, ptgt)) {

11750                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);



11751         }
11752 
11753         /*
11754          * Disable interrupts
11755          */
11756         MPTSAS_DISABLE_INTR(mpt);
11757 
11758         /*
11759          * Abort all commands: outstanding commands, commands in waitq and
11760          * tx_waitq.
11761          */
11762         mptsas_flush_hba(mpt);
11763 
11764         /*
11765          * Reinitialize the chip.
11766          */
11767         if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
11768                 rval = DDI_FAILURE;
11769         }
11770 
11771         /*
11772          * Enable interrupts again
11773          */
11774         MPTSAS_ENABLE_INTR(mpt);
11775 
11776         /*
11777          * If mptsas_init_chip was successful, update the driver data.
11778          */
11779         if (rval == DDI_SUCCESS) {
11780                 mptsas_update_driver_data(mpt);
11781         }
11782 
11783         /*
11784          * Reset the throttles
11785          */
11786         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
11787             ptgt = refhash_next(mpt->m_targets, ptgt)) {

11788                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);



11789         }
11790 
11791         mptsas_doneq_empty(mpt);
11792         mptsas_restart_hba(mpt);
11793 
11794         if (rval != DDI_SUCCESS) {
11795                 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
11796                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
11797         }
11798 
11799         /*
11800          * Clear the reset flag so that I/Os can continue.
11801          */
11802         mpt->m_in_reset = FALSE;
11803 
11804         return (rval);
11805 }
11806 
11807 static int
11808 mptsas_init_chip(mptsas_t *mpt, int first_time)


11834         }
11835         /*
11836          * Setup configuration space
11837          */
11838         if (mptsas_config_space_init(mpt) == FALSE) {
11839                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init "
11840                     "failed!");
11841                 goto fail;
11842         }
11843 
11844         /*
11845          * IOC facts can change after a diag reset so all buffers that are
11846          * based on these numbers must be de-allocated and re-allocated.  Get
11847          * new IOC facts each time chip is initialized.
11848          */
11849         if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
11850                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed");
11851                 goto fail;
11852         }
11853 
11854         mpt->m_targets = refhash_create(MPTSAS_TARGET_BUCKET_COUNT,
11855             mptsas_target_addr_hash, mptsas_target_addr_cmp,
11856             mptsas_target_free, sizeof (mptsas_target_t),
11857             offsetof(mptsas_target_t, m_link),
11858             offsetof(mptsas_target_t, m_addr), KM_SLEEP);
11859 
11860         if (mptsas_alloc_active_slots(mpt, KM_SLEEP)) {
11861                 goto fail;
11862         }
11863         /*
11864          * Allocate request message frames, reply free queue, reply descriptor
11865          * post queue, and reply message frames using latest IOC facts.
11866          */
11867         if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) {
11868                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames failed");
11869                 goto fail;
11870         }
11871         if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) {
11872                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue failed!");
11873                 goto fail;
11874         }
11875         if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) {
11876                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue failed!");
11877                 goto fail;
11878         }
11879         if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) {


12478         uint64_t        ena;
12479         char            buf[FM_MAX_CLASS];
12480 
12481         (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
12482         ena = fm_ena_generate(0, FM_ENA_FMT1);
12483         if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities)) {
12484                 ddi_fm_ereport_post(mpt->m_dip, buf, ena, DDI_NOSLEEP,
12485                     FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
12486         }
12487 }
12488 
12489 static int
12490 mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
12491     uint16_t *dev_handle, mptsas_target_t **pptgt)
12492 {
12493         int             rval;
12494         uint32_t        dev_info;
12495         uint64_t        sas_wwn;
12496         mptsas_phymask_t phymask;
12497         uint8_t         physport, phynum, config, disk;

12498         uint64_t        devicename;
12499         uint16_t        pdev_hdl;
12500         mptsas_target_t *tmp_tgt = NULL;
12501         uint16_t        bay_num, enclosure;
12502 
12503         ASSERT(*pptgt == NULL);
12504 
12505         rval = mptsas_get_sas_device_page0(mpt, page_address, dev_handle,
12506             &sas_wwn, &dev_info, &physport, &phynum, &pdev_hdl,
12507             &bay_num, &enclosure);
12508         if (rval != DDI_SUCCESS) {
12509                 rval = DEV_INFO_FAIL_PAGE0;
12510                 return (rval);
12511         }
12512 
12513         if ((dev_info & (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
12514             MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
12515             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) == NULL) {
12516                 rval = DEV_INFO_WRONG_DEVICE_TYPE;
12517                 return (rval);
12518         }
12519 
12520         /*
12521          * Check if the dev handle is for a Phys Disk. If so, set return value
12522          * and exit.  Don't add Phys Disks to hash.
12523          */
12524         for (config = 0; config < mpt->m_num_raid_configs; config++) {
12525                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
12526                         if (*dev_handle == mpt->m_raidconfig[config].
12527                             m_physdisk_devhdl[disk]) {
12528                                 rval = DEV_INFO_PHYS_DISK;
12529                                 return (rval);
12530                         }
12531                 }
12532         }
12533 
12534         /*
12535          * Get SATA Device Name from SAS device page0 for
12536          * sata device, if device name doesn't exist, set mta_wwn to
12537          * 0 for direct attached SATA. For the device behind the expander
12538          * we still can use STP address assigned by expander.
12539          */
12540         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
12541             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
12542                 mutex_exit(&mpt->m_mutex);
12543                 /* alloc a tmp_tgt to send the cmd */
12544                 tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target),
12545                     KM_SLEEP);
12546                 tmp_tgt->m_devhdl = *dev_handle;
12547                 tmp_tgt->m_deviceinfo = dev_info;
12548                 tmp_tgt->m_qfull_retries = QFULL_RETRIES;
12549                 tmp_tgt->m_qfull_retry_interval =
12550                     drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
12551                 tmp_tgt->m_t_throttle = MAX_THROTTLE;
12552                 devicename = mptsas_get_sata_guid(mpt, tmp_tgt, 0);
12553                 kmem_free(tmp_tgt, sizeof (struct mptsas_target));
12554                 mutex_enter(&mpt->m_mutex);
12555                 if (devicename != 0 && (((devicename >> 56) & 0xf0) == 0x50)) {
12556                         sas_wwn = devicename;
12557                 } else if (dev_info & MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH) {
12558                         sas_wwn = 0;
12559                 }
12560         }
12561 
12562         phymask = mptsas_physport_to_phymask(mpt, physport);
12563         *pptgt = mptsas_tgt_alloc(mpt, *dev_handle, sas_wwn,
12564             dev_info, phymask, phynum);
12565         if (*pptgt == NULL) {
12566                 mptsas_log(mpt, CE_WARN, "Failed to allocated target"
12567                     "structure!");
12568                 rval = DEV_INFO_FAIL_ALLOC;
12569                 return (rval);
12570         }
12571         (*pptgt)->m_enclosure = enclosure;
12572         (*pptgt)->m_slot_num = bay_num;
12573         return (DEV_INFO_SUCCESS);
12574 }
12575 
12576 uint64_t
12577 mptsas_get_sata_guid(mptsas_t *mpt, mptsas_target_t *ptgt, int lun)
12578 {
12579         uint64_t        sata_guid = 0, *pwwn = NULL;
12580         int             target = ptgt->m_devhdl;
12581         uchar_t         *inq83 = NULL;
12582         int             inq83_len = 0xFF;
12583         uchar_t         *dblk = NULL;


12973                  * didn't match any device by searching
12974                  */
12975                 return (DDI_FAILURE);
12976         }
12977         /*
12978          * If the LUN already exists and the status is online,
12979          * we just return the pointer to dev_info_t directly.
12980          * For the mdi_pathinfo node, we'll handle it in
12981          * mptsas_create_virt_lun()
12982          * TODO should be also in mptsas_handle_dr
12983          */
12984 
12985         *lundip = mptsas_find_child_addr(pdip, sasaddr, lun);
12986         if (*lundip != NULL) {
12987                 /*
12988                  * TODO Another senario is, we hotplug the same disk
12989                  * on the same slot, the devhdl changed, is this
12990                  * possible?
12991                  * tgt_private->t_private != ptgt
12992                  */
12993                 if (sasaddr != ptgt->m_addr.mta_wwn) {
12994                         /*
12995                          * The device has changed although the devhdl is the
12996                          * same (Enclosure mapping mode, change drive on the
12997                          * same slot)
12998                          */
12999                         return (DDI_FAILURE);
13000                 }
13001                 return (DDI_SUCCESS);
13002         }
13003 
13004         if (phymask == 0) {
13005                 /*
13006                  * Configure IR volume
13007                  */
13008                 rval =  mptsas_config_raid(pdip, ptgt->m_devhdl, lundip);
13009                 return (rval);
13010         }
13011         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
13012 
13013         return (rval);
13014 }
13015 
13016 static int
13017 mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
13018     dev_info_t **lundip)
13019 {
13020         int             rval;
13021         mptsas_t        *mpt = DIP2MPT(pdip);
13022         mptsas_phymask_t phymask;
13023         mptsas_target_t *ptgt = NULL;
13024 
13025         /*
13026          * Get the physical port associated to the iport
13027          */
13028         phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13029             "phymask", 0);
13030 
13031         ptgt = mptsas_phy_to_tgt(mpt, phymask, phy);
13032         if (ptgt == NULL) {
13033                 /*
13034                  * didn't match any device by searching
13035                  */
13036                 return (DDI_FAILURE);
13037         }
13038 
13039         /*
13040          * If the LUN already exists and the status is online,
13041          * we just return the pointer to dev_info_t directly.
13042          * For the mdi_pathinfo node, we'll handle it in
13043          * mptsas_create_virt_lun().
13044          */
13045 
13046         *lundip = mptsas_find_child_phy(pdip, phy);
13047         if (*lundip != NULL) {
13048                 return (DDI_SUCCESS);


13095         struct buf              *repluns_bp = NULL;
13096         struct scsi_address     ap;
13097         uchar_t                 cdb[CDB_GROUP5];
13098         int                     ret = DDI_FAILURE;
13099         int                     retry = 0;
13100         int                     lun_list_len = 0;
13101         uint16_t                lun_num = 0;
13102         uint8_t                 lun_addr_type = 0;
13103         uint32_t                lun_cnt = 0;
13104         uint32_t                lun_total = 0;
13105         dev_info_t              *cdip = NULL;
13106         uint16_t                *saved_repluns = NULL;
13107         char                    *buffer = NULL;
13108         int                     buf_len = 128;
13109         mptsas_t                *mpt = DIP2MPT(pdip);
13110         uint64_t                sas_wwn = 0;
13111         uint8_t                 phy = 0xFF;
13112         uint32_t                dev_info = 0;
13113 
13114         mutex_enter(&mpt->m_mutex);
13115         sas_wwn = ptgt->m_addr.mta_wwn;
13116         phy = ptgt->m_phynum;
13117         dev_info = ptgt->m_deviceinfo;
13118         mutex_exit(&mpt->m_mutex);
13119 
13120         if (sas_wwn == 0) {
13121                 /*
13122                  * It's a SATA without Device Name
13123                  * So don't try multi-LUNs
13124                  */
13125                 if (mptsas_find_child_phy(pdip, phy)) {
13126                         return (DDI_SUCCESS);
13127                 } else {
13128                         /*
13129                          * need configure and create node
13130                          */
13131                         return (DDI_FAILURE);
13132                 }
13133         }
13134 
13135         /*


13210                 if ((ret == DDI_SUCCESS) && (cdip != NULL)) {
13211                         (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip,
13212                             MPTSAS_DEV_GONE);
13213                 }
13214         }
13215         mptsas_offline_missed_luns(pdip, saved_repluns, lun_total, ptgt);
13216         kmem_free(saved_repluns, sizeof (uint16_t) * lun_total);
13217         scsi_free_consistent_buf(repluns_bp);
13218         return (DDI_SUCCESS);
13219 }
13220 
13221 static int
13222 mptsas_config_raid(dev_info_t *pdip, uint16_t target, dev_info_t **dip)
13223 {
13224         int                     rval = DDI_FAILURE;
13225         struct scsi_inquiry     *sd_inq = NULL;
13226         mptsas_t                *mpt = DIP2MPT(pdip);
13227         mptsas_target_t         *ptgt = NULL;
13228 
13229         mutex_enter(&mpt->m_mutex);
13230         ptgt = refhash_linear_search(mpt->m_targets,
13231             mptsas_target_eval_devhdl, &target);
13232         mutex_exit(&mpt->m_mutex);
13233         if (ptgt == NULL) {
13234                 mptsas_log(mpt, CE_WARN, "Volume with VolDevHandle of 0x%x "
13235                     "not found.", target);
13236                 return (rval);
13237         }
13238 
13239         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
13240         rval = mptsas_inquiry(mpt, ptgt, 0, 0, (uchar_t *)sd_inq,
13241             SUN_INQSIZE, 0, (uchar_t)0);
13242 
13243         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
13244                 rval = mptsas_create_phys_lun(pdip, sd_inq, NULL, dip, ptgt,
13245                     0);
13246         } else {
13247                 rval = DDI_FAILURE;
13248         }
13249 
13250         kmem_free(sd_inq, SUN_INQSIZE);
13251         return (rval);
13252 }
13253 
13254 /*
13255  * configure all RAID volumes for virtual iport
13256  */
13257 static void
13258 mptsas_config_all_viport(dev_info_t *pdip)
13259 {
13260         mptsas_t        *mpt = DIP2MPT(pdip);
13261         int             config, vol;
13262         int             target;
13263         dev_info_t      *lundip = NULL;

13264 
13265         /*
13266          * Get latest RAID info and search for any Volume DevHandles.  If any
13267          * are found, configure the volume.
13268          */
13269         mutex_enter(&mpt->m_mutex);
13270         for (config = 0; config < mpt->m_num_raid_configs; config++) {
13271                 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
13272                         if (mpt->m_raidconfig[config].m_raidvol[vol].m_israid
13273                             == 1) {
13274                                 target = mpt->m_raidconfig[config].
13275                                     m_raidvol[vol].m_raidhandle;
13276                                 mutex_exit(&mpt->m_mutex);
13277                                 (void) mptsas_config_raid(pdip, target,
13278                                     &lundip);
13279                                 mutex_enter(&mpt->m_mutex);
13280                         }
13281                 }
13282         }
13283         mutex_exit(&mpt->m_mutex);
13284 }
13285 
13286 static void
13287 mptsas_offline_missed_luns(dev_info_t *pdip, uint16_t *repluns,
13288     int lun_cnt, mptsas_target_t *ptgt)
13289 {
13290         dev_info_t      *child = NULL, *savechild = NULL;
13291         mdi_pathinfo_t  *pip = NULL, *savepip = NULL;
13292         uint64_t        sas_wwn, wwid;
13293         uint8_t         phy;
13294         int             lun;
13295         int             i;
13296         int             find;
13297         char            *addr;
13298         char            *nodename;
13299         mptsas_t        *mpt = DIP2MPT(pdip);
13300 
13301         mutex_enter(&mpt->m_mutex);
13302         wwid = ptgt->m_addr.mta_wwn;
13303         mutex_exit(&mpt->m_mutex);
13304 
13305         child = ddi_get_child(pdip);
13306         while (child) {
13307                 find = 0;
13308                 savechild = child;
13309                 child = ddi_get_next_sibling(child);
13310 
13311                 nodename = ddi_node_name(savechild);
13312                 if (strcmp(nodename, "smp") == 0) {
13313                         continue;
13314                 }
13315 
13316                 addr = ddi_get_name_addr(savechild);
13317                 if (addr == NULL) {
13318                         continue;
13319                 }
13320 
13321                 if (mptsas_parse_address(addr, &sas_wwn, &phy, &lun) !=
13322                     DDI_SUCCESS) {


13386         uint32_t        page_address;
13387         int             rval = 0;
13388         uint16_t        dev_handle;
13389         mptsas_target_t *ptgt = NULL;
13390         mptsas_smp_t    smp_node;
13391 
13392         /*
13393          * Get latest RAID info.
13394          */
13395         (void) mptsas_get_raid_info(mpt);
13396 
13397         dev_handle = mpt->m_smp_devhdl;
13398         for (; mpt->m_done_traverse_smp == 0; ) {
13399                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
13400                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)dev_handle;
13401                 if (mptsas_get_sas_expander_page0(mpt, page_address, &smp_node)
13402                     != DDI_SUCCESS) {
13403                         break;
13404                 }
13405                 mpt->m_smp_devhdl = dev_handle = smp_node.m_devhdl;
13406                 (void) mptsas_smp_alloc(mpt, &smp_node);
13407         }
13408 
13409         /*
13410          * Config target devices
13411          */
13412         dev_handle = mpt->m_dev_handle;
13413 
13414         /*
13415          * Do loop to get sas device page 0 by GetNextHandle till the
13416          * the last handle. If the sas device is a SATA/SSP target,
13417          * we try to config it.
13418          */
13419         for (; mpt->m_done_traverse_dev == 0; ) {
13420                 ptgt = NULL;
13421                 page_address =
13422                     (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
13423                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
13424                     (uint32_t)dev_handle;
13425                 rval = mptsas_get_target_device_info(mpt, page_address,
13426                     &dev_handle, &ptgt);
13427                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
13428                     (rval == DEV_INFO_FAIL_ALLOC)) {
13429                         break;
13430                 }
13431 
13432                 mpt->m_dev_handle = dev_handle;
13433         }
13434 
13435 }
13436 
13437 void
















13438 mptsas_update_driver_data(struct mptsas *mpt)
13439 {
13440         mptsas_target_t *tp;
13441         mptsas_smp_t *sp;
13442 
13443         ASSERT(MUTEX_HELD(&mpt->m_mutex));
13444 
13445         /*
13446          * TODO after hard reset, update the driver data structures
13447          * 1. update port/phymask mapping table mpt->m_phy_info
13448          * 2. invalid all the entries in hash table
13449          *    m_devhdl = 0xffff and m_deviceinfo = 0
13450          * 3. call sas_device_page/expander_page to update hash table
13451          */
13452         mptsas_update_phymask(mpt);
13453         /*
13454          * Invalid the existing entries
13455          *
13456          * XXX - It seems like we should just delete everything here.  We are
13457          * holding the lock and are about to refresh all the targets in both
13458          * hashes anyway.  Given the path we're in, what outstanding async
13459          * event could possibly be trying to reference one of these things
13460          * without taking the lock, and how would that be useful anyway?
13461          */
13462         for (tp = refhash_first(mpt->m_targets); tp != NULL;
13463             tp = refhash_next(mpt->m_targets, tp)) {
13464                 tp->m_devhdl = MPTSAS_INVALID_DEVHDL;
13465                 tp->m_deviceinfo = 0;
13466                 tp->m_dr_flag = MPTSAS_DR_INACTIVE;
13467         }
13468         for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
13469             sp = refhash_next(mpt->m_smp_targets, sp)) {
13470                 sp->m_devhdl = MPTSAS_INVALID_DEVHDL;
13471                 sp->m_deviceinfo = 0;
13472         }
13473         mpt->m_done_traverse_dev = 0;
13474         mpt->m_done_traverse_smp = 0;
13475         mpt->m_dev_handle = mpt->m_smp_devhdl = MPTSAS_INVALID_DEVHDL;
13476         mptsas_update_hashtab(mpt);
13477 }
13478 
13479 static void
13480 mptsas_config_all(dev_info_t *pdip)
13481 {
13482         dev_info_t      *smpdip = NULL;
13483         mptsas_t        *mpt = DIP2MPT(pdip);
13484         int             phymask = 0;
13485         mptsas_phymask_t phy_mask;
13486         mptsas_target_t *ptgt = NULL;
13487         mptsas_smp_t    *psmp;
13488 
13489         /*
13490          * Get the phymask associated to the iport
13491          */
13492         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13493             "phymask", 0);
13494 
13495         /*
13496          * Enumerate RAID volumes here (phymask == 0).
13497          */
13498         if (phymask == 0) {
13499                 mptsas_config_all_viport(pdip);
13500                 return;
13501         }
13502 
13503         mutex_enter(&mpt->m_mutex);
13504 
13505         if (!mpt->m_done_traverse_dev || !mpt->m_done_traverse_smp) {
13506                 mptsas_update_hashtab(mpt);
13507         }
13508 
13509         for (psmp = refhash_first(mpt->m_smp_targets); psmp != NULL;
13510             psmp = refhash_next(mpt->m_smp_targets, psmp)) {
13511                 phy_mask = psmp->m_addr.mta_phymask;

13512                 if (phy_mask == phymask) {
13513                         smpdip = NULL;
13514                         mutex_exit(&mpt->m_mutex);
13515                         (void) mptsas_online_smp(pdip, psmp, &smpdip);
13516                         mutex_enter(&mpt->m_mutex);
13517                 }


13518         }
13519 
13520         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
13521             ptgt = refhash_next(mpt->m_targets, ptgt)) {
13522                 phy_mask = ptgt->m_addr.mta_phymask;

13523                 if (phy_mask == phymask) {
13524                         mutex_exit(&mpt->m_mutex);
13525                         (void) mptsas_config_target(pdip, ptgt);
13526                         mutex_enter(&mpt->m_mutex);
13527                 }



13528         }
13529         mutex_exit(&mpt->m_mutex);
13530 }
13531 
13532 static int
13533 mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt)
13534 {
13535         int             rval = DDI_FAILURE;
13536         dev_info_t      *tdip;
13537 
13538         rval = mptsas_config_luns(pdip, ptgt);
13539         if (rval != DDI_SUCCESS) {
13540                 /*
13541                  * The return value means the SCMD_REPORT_LUNS
13542                  * did not execute successfully. The target maybe
13543                  * doesn't support such command.
13544                  */
13545                 rval = mptsas_probe_lun(pdip, 0, &tdip, ptgt);
13546         }
13547         return (rval);


13689                 }
13690 
13691                 if (strcmp(smp_wwn, str_wwn) == 0) {
13692                         ddi_prop_free(smp_wwn);
13693                         break;
13694                 }
13695                 child = ddi_get_next_sibling(child);
13696                 ddi_prop_free(smp_wwn);
13697         }
13698         return (child);
13699 }
13700 
13701 static int
13702 mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, uint_t flags)
13703 {
13704         int             rval = DDI_FAILURE;
13705         char            *devname;
13706         char            wwn_str[MPTSAS_WWN_STRLEN];
13707         dev_info_t      *cdip;
13708 
13709         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
13710 
13711         cdip = mptsas_find_smp_child(pdip, wwn_str);
13712 
13713         if (cdip == NULL)
13714                 return (DDI_SUCCESS);
13715 
13716         /*
13717          * Make sure node is attached otherwise
13718          * it won't have related cache nodes to
13719          * clean up.  i_ddi_devi_attached is
13720          * similiar to i_ddi_node_state(cdip) >=
13721          * DS_ATTACHED.
13722          */
13723         if (i_ddi_devi_attached(cdip)) {
13724 
13725                 /* Get full devname */
13726                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
13727                 (void) ddi_deviname(cdip, devname);
13728                 /* Clean cache */
13729                 (void) devfs_clean(pdip, devname + 1,


13969         char                    *attached_wwn_str = NULL;
13970         char                    *component = NULL;
13971         uint8_t                 phy = 0xFF;
13972         uint64_t                sas_wwn;
13973         int64_t                 lun64 = 0;
13974         uint32_t                devinfo;
13975         uint16_t                dev_hdl;
13976         uint16_t                pdev_hdl;
13977         uint64_t                dev_sas_wwn;
13978         uint64_t                pdev_sas_wwn;
13979         uint32_t                pdev_info;
13980         uint8_t                 physport;
13981         uint8_t                 phy_id;
13982         uint32_t                page_address;
13983         uint16_t                bay_num, enclosure;
13984         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
13985         uint32_t                dev_info;
13986 
13987         mutex_enter(&mpt->m_mutex);
13988         target = ptgt->m_devhdl;
13989         sas_wwn = ptgt->m_addr.mta_wwn;
13990         devinfo = ptgt->m_deviceinfo;
13991         phy = ptgt->m_phynum;
13992         mutex_exit(&mpt->m_mutex);
13993 
13994         if (sas_wwn) {
13995                 *pip = mptsas_find_path_addr(pdip, sas_wwn, lun);
13996         } else {
13997                 *pip = mptsas_find_path_phy(pdip, phy);
13998         }
13999 
14000         if (*pip != NULL) {
14001                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14002                 ASSERT(*lun_dip != NULL);
14003                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, *lun_dip,
14004                     (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
14005                     MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
14006                         if (strncmp(guid, old_guid, strlen(guid)) == 0) {
14007                                 /*
14008                                  * Same path back online again.
14009                                  */


14318         char                    *component = NULL;
14319         char                    *attached_wwn_str = NULL;
14320         uint8_t                 phy = 0xFF;
14321         uint64_t                sas_wwn;
14322         uint32_t                devinfo;
14323         uint16_t                dev_hdl;
14324         uint16_t                pdev_hdl;
14325         uint64_t                pdev_sas_wwn;
14326         uint64_t                dev_sas_wwn;
14327         uint32_t                pdev_info;
14328         uint8_t                 physport;
14329         uint8_t                 phy_id;
14330         uint32_t                page_address;
14331         uint16_t                bay_num, enclosure;
14332         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
14333         uint32_t                dev_info;
14334         int64_t                 lun64 = 0;
14335 
14336         mutex_enter(&mpt->m_mutex);
14337         target = ptgt->m_devhdl;
14338         sas_wwn = ptgt->m_addr.mta_wwn;
14339         devinfo = ptgt->m_deviceinfo;
14340         phy = ptgt->m_phynum;
14341         mutex_exit(&mpt->m_mutex);
14342 
14343         /*
14344          * generate compatible property with binding-set "mpt"
14345          */
14346         scsi_hba_nodename_compatible_get(inq, NULL, inq->inq_dtype, NULL,
14347             &nodename, &compatible, &ncompatible);
14348 
14349         /*
14350          * if nodename can't be determined then print a message and skip it
14351          */
14352         if (nodename == NULL) {
14353                 mptsas_log(mpt, CE_WARN, "mptsas found no compatible driver "
14354                     "for target %d lun %d", target, lun);
14355                 return (DDI_FAILURE);
14356         }
14357 
14358         ndi_rtn = ndi_devi_alloc(pdip, nodename,


14437                     *lun_dip, SAS_PROP) != DDI_PROP_SUCCESS) {
14438                         mptsas_log(mpt, CE_WARN, "mptsas unable to"
14439                             "create property for SAS target %d lun %d"
14440                             " (SAS_PROP)", target, lun);
14441                         ndi_rtn = NDI_FAILURE;
14442                         goto phys_create_done;
14443                 }
14444                 if (guid && (ndi_prop_update_string(DDI_DEV_T_NONE,
14445                     *lun_dip, NDI_GUID, guid) != DDI_SUCCESS)) {
14446                         mptsas_log(mpt, CE_WARN, "mptsas unable "
14447                             "to create guid property for target %d "
14448                             "lun %d", target, lun);
14449                         ndi_rtn = NDI_FAILURE;
14450                         goto phys_create_done;
14451                 }
14452 
14453                 /*
14454                  * The following code is to set properties for SM-HBA support,
14455                  * it doesn't apply to RAID volumes
14456                  */
14457                 if (ptgt->m_addr.mta_phymask == 0)
14458                         goto phys_raid_lun;
14459 
14460                 mutex_enter(&mpt->m_mutex);
14461 
14462                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
14463                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14464                     (uint32_t)ptgt->m_devhdl;
14465                 rval = mptsas_get_sas_device_page0(mpt, page_address,
14466                     &dev_hdl, &dev_sas_wwn, &dev_info,
14467                     &physport, &phy_id, &pdev_hdl,
14468                     &bay_num, &enclosure);
14469                 if (rval != DDI_SUCCESS) {
14470                         mutex_exit(&mpt->m_mutex);
14471                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
14472                             "parent device for handle %d.", page_address);
14473                         ndi_rtn = NDI_FAILURE;
14474                         goto phys_create_done;
14475                 }
14476 
14477                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &


14591                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
14592                         if (guid) {
14593                                 (void) snprintf(component, MAXPATHLEN,
14594                                     "disk@w%s,%x", wwn_str, lun);
14595                         } else {
14596                                 (void) snprintf(component, MAXPATHLEN,
14597                                     "disk@p%x,%x", phy, lun);
14598                         }
14599                         if (ddi_pathname_obp_set(*lun_dip, component)
14600                             != DDI_SUCCESS) {
14601                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
14602                                     "unable to set obp-path for SAS "
14603                                     "object %s", component);
14604                                 ndi_rtn = NDI_FAILURE;
14605                                 goto phys_create_done;
14606                         }
14607                 }
14608                 /*
14609                  * Create the phy-num property for non-raid disk
14610                  */
14611                 if (ptgt->m_addr.mta_phymask != 0) {
14612                         if (ndi_prop_update_int(DDI_DEV_T_NONE,
14613                             *lun_dip, "phy-num", ptgt->m_phynum) !=
14614                             DDI_PROP_SUCCESS) {
14615                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
14616                                     "failed to create phy-num property for "
14617                                     "target %d", target);
14618                                 ndi_rtn = NDI_FAILURE;
14619                                 goto phys_create_done;
14620                         }
14621                 }
14622 phys_create_done:
14623                 /*
14624                  * If props were setup ok, online the lun
14625                  */
14626                 if (ndi_rtn == NDI_SUCCESS) {
14627                         /*
14628                          * Try to online the new node
14629                          */
14630                         ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
14631                 }


14713         char            attached_wwn_str[MPTSAS_WWN_STRLEN];
14714         int             ndi_rtn = NDI_FAILURE;
14715         int             rval = 0;
14716         mptsas_smp_t    dev_info;
14717         uint32_t        page_address;
14718         mptsas_t        *mpt = DIP2MPT(pdip);
14719         uint16_t        dev_hdl;
14720         uint64_t        sas_wwn;
14721         uint64_t        smp_sas_wwn;
14722         uint8_t         physport;
14723         uint8_t         phy_id;
14724         uint16_t        pdev_hdl;
14725         uint8_t         numphys = 0;
14726         uint16_t        i = 0;
14727         char            phymask[MPTSAS_MAX_PHYS];
14728         char            *iport = NULL;
14729         mptsas_phymask_t        phy_mask = 0;
14730         uint16_t        attached_devhdl;
14731         uint16_t        bay_num, enclosure;
14732 
14733         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
14734 
14735         /*
14736          * Probe smp device, prevent the node of removed device from being
14737          * configured succesfully
14738          */
14739         if (mptsas_probe_smp(pdip, smp_node->m_addr.mta_wwn) != NDI_SUCCESS) {
14740                 return (DDI_FAILURE);
14741         }
14742 
14743         if ((*smp_dip = mptsas_find_smp_child(pdip, wwn_str)) != NULL) {
14744                 return (DDI_SUCCESS);
14745         }
14746 
14747         ndi_rtn = ndi_devi_alloc(pdip, "smp", DEVI_SID_NODEID, smp_dip);
14748 
14749         /*
14750          * if lun alloc success, set props
14751          */
14752         if (ndi_rtn == NDI_SUCCESS) {
14753                 /*
14754                  * Set the flavor of the child to be SMP flavored
14755                  */
14756                 ndi_flavor_set(*smp_dip, SCSA_FLAVOR_SMP);
14757 
14758                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14759                     *smp_dip, SMP_WWN, wwn_str) !=
14760                     DDI_PROP_SUCCESS) {
14761                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14762                             "property for smp device %s (sas_wwn)",
14763                             wwn_str);
14764                         ndi_rtn = NDI_FAILURE;
14765                         goto smp_create_done;
14766                 }
14767                 (void) sprintf(wwn_str, "w%"PRIx64, smp_node->m_addr.mta_wwn);
14768                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
14769                     *smp_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str) !=
14770                     DDI_PROP_SUCCESS) {
14771                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
14772                             "property for iport target-port %s (sas_wwn)",
14773                             wwn_str);
14774                         ndi_rtn = NDI_FAILURE;
14775                         goto smp_create_done;
14776                 }
14777 
14778                 mutex_enter(&mpt->m_mutex);
14779 
14780                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
14781                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | smp_node->m_devhdl;
14782                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
14783                     &dev_info);
14784                 if (rval != DDI_SUCCESS) {
14785                         mutex_exit(&mpt->m_mutex);
14786                         mptsas_log(mpt, CE_WARN,
14787                             "mptsas unable to get expander "


15031                         smp_pkt->smp_pkt_reason = EIO;
15032                         break;
15033                 }
15034                 return (DDI_FAILURE);
15035         }
15036         if (rep.SASStatus != MPI2_SASSTATUS_SUCCESS) {
15037                 mptsas_log(mpt, CE_NOTE, "smp_start: get error SAS status:%x",
15038                     rep.SASStatus);
15039                 smp_pkt->smp_pkt_reason = EIO;
15040                 return (DDI_FAILURE);
15041         }
15042 
15043         return (DDI_SUCCESS);
15044 }
15045 
15046 /*
15047  * If we didn't get a match, we need to get sas page0 for each device, and
15048  * untill we get a match. If failed, return NULL
15049  */
15050 static mptsas_target_t *
15051 mptsas_phy_to_tgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint8_t phy)
15052 {
15053         int             i, j = 0;
15054         int             rval = 0;
15055         uint16_t        cur_handle;
15056         uint32_t        page_address;
15057         mptsas_target_t *ptgt = NULL;
15058 
15059         /*
15060          * PHY named device must be direct attached and attaches to
15061          * narrow port, if the iport is not parent of the device which
15062          * we are looking for.
15063          */
15064         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15065                 if ((1 << i) & phymask)
15066                         j++;
15067         }
15068 
15069         if (j > 1)
15070                 return (NULL);
15071 
15072         /*
15073          * Must be a narrow port and single device attached to the narrow port
15074          * So the physical port num of device  which is equal to the iport's
15075          * port num is the device what we are looking for.
15076          */
15077 
15078         if (mpt->m_phy_info[phy].phy_mask != phymask)
15079                 return (NULL);
15080 
15081         mutex_enter(&mpt->m_mutex);
15082 
15083         ptgt = refhash_linear_search(mpt->m_targets, mptsas_target_eval_nowwn,
15084             &phy);
15085         if (ptgt != NULL) {

15086                 mutex_exit(&mpt->m_mutex);
15087                 return (ptgt);
15088         }
15089 




15090         if (mpt->m_done_traverse_dev) {
15091                 mutex_exit(&mpt->m_mutex);
15092                 return (NULL);
15093         }
15094 
15095         /* If didn't get a match, come here */
15096         cur_handle = mpt->m_dev_handle;
15097         for (; ; ) {
15098                 ptgt = NULL;
15099                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15100                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15101                 rval = mptsas_get_target_device_info(mpt, page_address,
15102                     &cur_handle, &ptgt);
15103                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15104                     (rval == DEV_INFO_FAIL_ALLOC)) {
15105                         break;
15106                 }
15107                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15108                     (rval == DEV_INFO_PHYS_DISK)) {
15109                         continue;
15110                 }
15111                 mpt->m_dev_handle = cur_handle;
15112 
15113                 if ((ptgt->m_addr.mta_wwn == 0) && (ptgt->m_phynum == phy)) {
15114                         break;
15115                 }
15116         }
15117 
15118         mutex_exit(&mpt->m_mutex);
15119         return (ptgt);
15120 }
15121 
15122 /*
15123  * The ptgt->m_addr.mta_wwn contains the wwid for each disk.
15124  * For Raid volumes, we need to check m_raidvol[x].m_raidwwid
15125  * If we didn't get a match, we need to get sas page0 for each device, and
15126  * untill we get a match
15127  * If failed, return NULL
15128  */
15129 static mptsas_target_t *
15130 mptsas_wwid_to_ptgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
15131 {
15132         int             rval = 0;
15133         uint16_t        cur_handle;
15134         uint32_t        page_address;
15135         mptsas_target_t *tmp_tgt = NULL;
15136         mptsas_target_addr_t addr;
15137 
15138         addr.mta_wwn = wwid;
15139         addr.mta_phymask = phymask;
15140         mutex_enter(&mpt->m_mutex);
15141         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);

15142         if (tmp_tgt != NULL) {
15143                 mutex_exit(&mpt->m_mutex);
15144                 return (tmp_tgt);
15145         }
15146 
15147         if (phymask == 0) {
15148                 /*
15149                  * It's IR volume
15150                  */
15151                 rval = mptsas_get_raid_info(mpt);
15152                 if (rval) {
15153                         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);

15154                 }
15155                 mutex_exit(&mpt->m_mutex);
15156                 return (tmp_tgt);
15157         }
15158 
15159         if (mpt->m_done_traverse_dev) {
15160                 mutex_exit(&mpt->m_mutex);
15161                 return (NULL);
15162         }
15163 
15164         /* If didn't get a match, come here */
15165         cur_handle = mpt->m_dev_handle;
15166         for (;;) {
15167                 tmp_tgt = NULL;
15168                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15169                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | cur_handle;
15170                 rval = mptsas_get_target_device_info(mpt, page_address,
15171                     &cur_handle, &tmp_tgt);
15172                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15173                     (rval == DEV_INFO_FAIL_ALLOC)) {
15174                         tmp_tgt = NULL;
15175                         break;
15176                 }
15177                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15178                     (rval == DEV_INFO_PHYS_DISK)) {
15179                         continue;
15180                 }
15181                 mpt->m_dev_handle = cur_handle;
15182                 if ((tmp_tgt->m_addr.mta_wwn) &&
15183                     (tmp_tgt->m_addr.mta_wwn == wwid) &&
15184                     (tmp_tgt->m_addr.mta_phymask == phymask)) {
15185                         break;
15186                 }
15187         }
15188 
15189         mutex_exit(&mpt->m_mutex);
15190         return (tmp_tgt);
15191 }
15192 
15193 static mptsas_smp_t *
15194 mptsas_wwid_to_psmp(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
15195 {
15196         int             rval = 0;
15197         uint16_t        cur_handle;
15198         uint32_t        page_address;
15199         mptsas_smp_t    smp_node, *psmp = NULL;
15200         mptsas_target_addr_t addr;
15201 
15202         addr.mta_wwn = wwid;
15203         addr.mta_phymask = phymask;
15204         mutex_enter(&mpt->m_mutex);
15205         psmp = refhash_lookup(mpt->m_smp_targets, &addr);

15206         if (psmp != NULL) {
15207                 mutex_exit(&mpt->m_mutex);
15208                 return (psmp);
15209         }
15210 
15211         if (mpt->m_done_traverse_smp) {
15212                 mutex_exit(&mpt->m_mutex);
15213                 return (NULL);
15214         }
15215 
15216         /* If didn't get a match, come here */
15217         cur_handle = mpt->m_smp_devhdl;
15218         for (;;) {
15219                 psmp = NULL;
15220                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
15221                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15222                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
15223                     &smp_node);
15224                 if (rval != DDI_SUCCESS) {
15225                         break;
15226                 }
15227                 mpt->m_smp_devhdl = cur_handle = smp_node.m_devhdl;
15228                 psmp = mptsas_smp_alloc(mpt, &smp_node);
15229                 ASSERT(psmp);
15230                 if ((psmp->m_addr.mta_wwn) && (psmp->m_addr.mta_wwn == wwid) &&
15231                     (psmp->m_addr.mta_phymask == phymask)) {
15232                         break;
15233                 }
15234         }
15235 
15236         mutex_exit(&mpt->m_mutex);
15237         return (psmp);
15238 }
15239 





















15240 mptsas_target_t *
15241 mptsas_tgt_alloc(mptsas_t *mpt, uint16_t devhdl, uint64_t wwid,
15242     uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum)
15243 {
15244         mptsas_target_t *tmp_tgt = NULL;
15245         mptsas_target_addr_t addr;
15246 
15247         addr.mta_wwn = wwid;
15248         addr.mta_phymask = phymask;
15249         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
15250         if (tmp_tgt != NULL) {
15251                 NDBG20(("Hash item already exist"));
15252                 tmp_tgt->m_deviceinfo = devinfo;
15253                 tmp_tgt->m_devhdl = devhdl;  /* XXX - duplicate? */
15254                 return (tmp_tgt);
15255         }
15256         tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target), KM_SLEEP);
15257         if (tmp_tgt == NULL) {
15258                 cmn_err(CE_WARN, "Fatal, allocated tgt failed");
15259                 return (NULL);
15260         }
15261         tmp_tgt->m_devhdl = devhdl;
15262         tmp_tgt->m_addr.mta_wwn = wwid;
15263         tmp_tgt->m_deviceinfo = devinfo;
15264         tmp_tgt->m_addr.mta_phymask = phymask;
15265         tmp_tgt->m_phynum = phynum;
15266         /* Initialized the tgt structure */
15267         tmp_tgt->m_qfull_retries = QFULL_RETRIES;
15268         tmp_tgt->m_qfull_retry_interval =
15269             drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
15270         tmp_tgt->m_t_throttle = MAX_THROTTLE;
15271 
15272         refhash_insert(mpt->m_targets, tmp_tgt);
15273 
15274         return (tmp_tgt);
15275 }
15276 
15277 static void
15278 mptsas_smp_target_copy(mptsas_smp_t *src, mptsas_smp_t *dst)

15279 {
15280         dst->m_devhdl = src->m_devhdl;
15281         dst->m_deviceinfo = src->m_deviceinfo;
15282         dst->m_pdevhdl = src->m_pdevhdl;
15283         dst->m_pdevinfo = src->m_pdevinfo;



15284 }
15285 



15286 static mptsas_smp_t *
15287 mptsas_smp_alloc(mptsas_t *mpt, mptsas_smp_t *data)
15288 {
15289         mptsas_target_addr_t addr;

15290         mptsas_smp_t *ret_data;
15291 
15292         addr.mta_wwn = data->m_addr.mta_wwn;
15293         addr.mta_phymask = data->m_addr.mta_phymask;
15294         ret_data = refhash_lookup(mpt->m_smp_targets, &addr);
15295         /*
15296          * If there's already a matching SMP target, update its fields
15297          * in place.  Since the address is not changing, it's safe to do
15298          * this.  We cannot just bcopy() here because the structure we've
15299          * been given has invalid hash links.
15300          */
15301         if (ret_data != NULL) {
15302                 mptsas_smp_target_copy(data, ret_data);
15303                 return (ret_data);
15304         }
15305 
15306         ret_data = kmem_alloc(sizeof (mptsas_smp_t), KM_SLEEP);
15307         bcopy(data, ret_data, sizeof (mptsas_smp_t));
15308         refhash_insert(mpt->m_smp_targets, ret_data);
15309         return (ret_data);
15310 }
15311 













15312 /*






















































































































































15313  * Functions for SGPIO LED support
15314  */
15315 static dev_info_t *
15316 mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask)
15317 {
15318         dev_info_t      *dip;
15319         int             prop;
15320         dip = e_ddi_hold_devi_by_dev(dev, 0);
15321         if (dip == NULL)
15322                 return (dip);
15323         prop = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
15324             "phymask", 0);
15325         *phymask = (mptsas_phymask_t)prop;
15326         ddi_release_devi(dip);
15327         return (dip);
15328 }
15329 static mptsas_target_t *
15330 mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
15331 {
15332         uint8_t                 phynum;


15375         Mpi2SepRequest_t        req;
15376         Mpi2SepReply_t          rep;
15377         int                     ret;
15378 
15379         ASSERT(mutex_owned(&mpt->m_mutex));
15380 
15381         /*
15382          * We only support SEP control of directly-attached targets, in which
15383          * case the "SEP" we're talking to is a virtual one contained within
15384          * the HBA itself.  This is necessary because DA targets typically have
15385          * no other mechanism for LED control.  Targets for which a separate
15386          * enclosure service processor exists should be controlled via ses(7d)
15387          * or sgen(7d).  Furthermore, since such requests can time out, they
15388          * should be made in user context rather than in response to
15389          * asynchronous fabric changes.
15390          *
15391          * In addition, we do not support this operation for RAID volumes,
15392          * since there is no slot associated with them.
15393          */
15394         if (!(ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED) ||
15395             ptgt->m_addr.mta_phymask == 0) {
15396                 return (ENOTTY);
15397         }
15398 
15399         bzero(&req, sizeof (req));
15400         bzero(&rep, sizeof (rep));
15401 
15402         req.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
15403         req.Action = act;
15404         req.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
15405         req.EnclosureHandle = LE_16(ptgt->m_enclosure);
15406         req.Slot = LE_16(ptgt->m_slot_num);
15407         if (act == MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
15408                 req.SlotStatus = LE_32(*status);
15409         }
15410         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
15411             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
15412         if (ret != 0) {
15413                 mptsas_log(mpt, CE_NOTE, "mptsas_send_sep: passthru SEP "
15414                     "Processor Request message error %d", ret);
15415                 return (ret);