Print this page
NEX-19691 Unsuccessful mpt_sas IOC reset leads to the panic in no I/O to the pool - days later
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-20282 Add disk target queue depth tunable to mpt_sas
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-19821 All SAS paths down sometimes does not cause panic and trigger automatic HA failover
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
9048 mpt_sas should not require targets to send SEP messages
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Approved by: Gordon Ross <gwr@nexenta.com>
NEX-17446 cleanup of hot unplugged disks fails intermittently
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-17944 HBA drivers don't need the redundant devfs_clean step
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
NEX-17006 backport mpt_sas tri-mode parts support change
9044 Need support for mpt_sas tri-mode parts
9045 Clean up mpt_sas compiler warnings
9046 mptsas_handle_topo_change can return without its locks held
9047 workaround SAS3408 firmware issue
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@joyent.com>
Reviewed by: Albert Lee <trisk@forkgnu.org>
Reviewed by: Yuri Pankov <yuripv@yuripv.net>
Approved by: Richard Lowe <richlowe@richlowe.net>
NEX-16174 scsi error messages should go to system log only
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-2100 vmem_hash_delete(ffffff5b5dee0000, 0, 1): bad free
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Marcel Telka <marcel@telka.sk>
NEX-6064 Son of single bad device causes outage a.k.a one disk fault
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-4418 SATA inquiry property generation doesn't work as advertised
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-3988 Single bad device causes outage a.k.a one disk fault
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-3717 mptsas doesn't handle timeouts in mptsas_get_sata_guid()
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-2103 12G mpt_sas needs additional minor enhancements
Revert OS-73 do not do IO complettions in the ISR
NEX-1889 mpt_sas should support 12G HBAs
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>
backout 4500 mptsas_hash_traverse() is unsafe, leads to missing devices
4403 mpt_sas panic when pulling a drive
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Albert Lee <trisk@nexenta.com>
Reviewed by: Andy Giles <illumos@ang.homedns.org>
Approved by: Robert Mustacchi <rm@joyent.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>
NEX-1052 mptsas_do_passthru() does triggers assertion
OS-126 Creating a LUN for retired device results in sysevent loop
OS-91 mptsas does inquiry without setting pkt_time
OS-73 do not do IO complettions in the ISR
OS-61 Need ability for fault injection in mptsas
OS-87 pkt_reason not set accordingly when mpt_sas times out commands
OS-84 slow-io changes cause assertion failure
OS-62 slow io error detector is needed.
OS-59 remove automated target removal mechanism from mpt_sas.
Fix up some merges where we wanted the upstream version.
re #12927 rb4203 LSI 2008 mpt_sas
re #9517 rb4120 After single disk fault patch installed single disk fault still causes process hangs (fix gcc build)
re #9517 rb4120 After single disk fault patch installed single disk fault still causes process hangs
re #8346 rb2639 KT disk failures (fix lint/cstyle)
re #10443 rb3479 3.1.3 crash: BAD TRAP: type=e (#pf Page fault)
re #8346 rb2639 KT disk failures
re #7364 rb2201 "hddisco" hangs after unplugging both cables from JBOD (and NMS too)
re #8346 rb2639 KT disk failures
re #9636 rb2836 - mpt_sas should attempt an MUR reset at attach time.
--HG--
branch : stable-4.0
re #9636 rb2836 - mpt_sas should attempt an MUR reset at attach time.
re #7550 rb2134 lint-clean nza-kernel
re #6530 mpt_sas crash when more than 1 Initiator involved - ie HA
re #6834 rb1773 less verbosity in nfs4_rnode
re #6833 rb1771 less verbosity in mptsas

*** 19,29 **** * CDDL HEADER END */ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright 2016 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2017, Joyent, Inc. * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved. * Copyright (c) 2014, Tegile Systems Inc. All rights reserved. */ --- 19,29 ---- * CDDL HEADER END */ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright 2019 Nexenta Systems, Inc. * Copyright (c) 2017, Joyent, Inc. * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved. * Copyright (c) 2014, Tegile Systems Inc. All rights reserved. */
*** 77,86 **** --- 77,88 ---- #include <sys/sysevent/dr.h> #include <sys/sata/sata_defs.h> #include <sys/sata/sata_hba.h> #include <sys/scsi/generic/sas.h> #include <sys/scsi/impl/scsi_sas.h> + #include <sys/sdt.h> + #include <sys/mdi_impldefs.h> #pragma pack(1) #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h> #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h> #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
*** 100,111 **** #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h> #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h> #include <sys/scsi/adapters/mpt_sas/mptsas_hash.h> #include <sys/raidioctl.h> - #include <sys/fs/dv_node.h> /* devfs_clean */ - /* * FMA header files */ #include <sys/ddifm.h> #include <sys/fm/protocol.h> --- 102,111 ----
*** 355,371 **** static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address, uint16_t *handle, mptsas_target_t **pptgt); static void mptsas_update_phymask(mptsas_t *mpt); ! static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt, uint32_t *status, uint8_t cmd); static dev_info_t *mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask); static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask); - static int mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt); /* * Enumeration / DR functions */ --- 355,372 ---- static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address, uint16_t *handle, mptsas_target_t **pptgt); static void mptsas_update_phymask(mptsas_t *mpt); ! static int mptsas_flush_led_status(mptsas_t *mpt, mptsas_enclosure_t *mep, ! uint16_t idx); ! static int mptsas_send_sep(mptsas_t *mpt, mptsas_enclosure_t *mep, uint16_t idx, uint32_t *status, uint8_t cmd); static dev_info_t *mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask); static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask); /* * Enumeration / DR functions */
*** 394,410 **** char *guid, dev_info_t **dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt, int lun); static void mptsas_offline_missed_luns(dev_info_t *pdip, uint16_t *repluns, int lun_cnt, mptsas_target_t *ptgt); ! static int mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip, ! mdi_pathinfo_t *rpip, uint_t flags); static int mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn, dev_info_t **smp_dip); ! static int mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, ! uint_t flags); static int mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data, int mode, int *rval); static int mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data, int mode, int *rval); --- 395,409 ---- char *guid, dev_info_t **dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt, int lun); static void mptsas_offline_missed_luns(dev_info_t *pdip, uint16_t *repluns, int lun_cnt, mptsas_target_t *ptgt); ! static int mptsas_offline_lun(dev_info_t *rdip, mdi_pathinfo_t *rpip); static int mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn, dev_info_t **smp_dip); ! static int mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node); static int mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data, int mode, int *rval); static int mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data, int mode, int *rval);
*** 467,476 **** --- 466,482 ---- * By default the value is 30 seconds. */ int mptsas_inq83_retry_timeout = 30; /* + * Tunable for default SCSI pkt timeout. Defaults to 5 seconds, which should + * be plenty for INQUIRY and REPORT_LUNS, which are the only commands currently + * issued by mptsas directly. + */ + int mptsas_scsi_pkt_time = 5; + + /* * This is used to allocate memory for message frame storage, not for * data I/O DMA. All message frames must be stored in the first 4G of * physical memory. */ ddi_dma_attr_t mptsas_dma_attrs = {
*** 730,751 **** return ((int)tp->m_devhdl - (int)dh); } static int - mptsas_target_eval_slot(const void *op, void *arg) - { - mptsas_led_control_t *lcp = arg; - const mptsas_target_t *tp = op; - - if (tp->m_enclosure != lcp->Enclosure) - return ((int)tp->m_enclosure - (int)lcp->Enclosure); - - return ((int)tp->m_slot_num - (int)lcp->Slot); - } - - static int mptsas_target_eval_nowwn(const void *op, void *arg) { uint8_t phy = *(uint8_t *)arg; const mptsas_target_t *tp = op; --- 736,745 ----
*** 1202,1221 **** /* * Allocate softc information. */ if (ddi_soft_state_zalloc(mptsas_state, instance) != DDI_SUCCESS) { ! mptsas_log(NULL, CE_WARN, ! "mptsas%d: cannot allocate soft state", instance); goto fail; } mpt = ddi_get_soft_state(mptsas_state, instance); if (mpt == NULL) { ! mptsas_log(NULL, CE_WARN, ! "mptsas%d: cannot get soft state", instance); goto fail; } /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */ scsi_size_clean(dip); --- 1196,1213 ---- /* * Allocate softc information. */ if (ddi_soft_state_zalloc(mptsas_state, instance) != DDI_SUCCESS) { ! mptsas_log(NULL, CE_WARN, "cannot allocate soft state"); goto fail; } mpt = ddi_get_soft_state(mptsas_state, instance); if (mpt == NULL) { ! mptsas_log(NULL, CE_WARN, "cannot get soft state"); goto fail; } /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */ scsi_size_clean(dip);
*** 1296,1306 **** --- 1288,1310 ---- 0, "mptsas_doneq_thread_threshold_prop", 10); mpt->m_doneq_length_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, "mptsas_doneq_length_threshold_prop", 8); mpt->m_doneq_thread_n = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, "mptsas_doneq_thread_n_prop", 8); + mpt->m_max_tune_throttle = ddi_prop_get_int(DDI_DEV_T_ANY, dip, + 0, "mptsas_max_throttle", MAX_THROTTLE); + /* + * Error check to make sure value is withing range. If nothing + * is set default to original design value. + */ + if (mpt->m_max_tune_throttle < THROTTLE_LO) { + mpt->m_max_tune_throttle = MAX_THROTTLE; + } else if (mpt->m_max_tune_throttle > THROTTLE_HI) { + mpt->m_max_tune_throttle = THROTTLE_HI; + } + if (mpt->m_doneq_thread_n) { cv_init(&mpt->m_doneq_thread_cv, NULL, CV_DRIVER, NULL); mutex_init(&mpt->m_doneq_mutex, NULL, MUTEX_DRIVER, NULL); mutex_enter(&mpt->m_doneq_mutex);
*** 1354,1366 **** cv_init(&mpt->m_cv, NULL, CV_DRIVER, NULL); cv_init(&mpt->m_passthru_cv, NULL, CV_DRIVER, NULL); cv_init(&mpt->m_fw_cv, NULL, CV_DRIVER, NULL); cv_init(&mpt->m_config_cv, NULL, CV_DRIVER, NULL); cv_init(&mpt->m_fw_diag_cv, NULL, CV_DRIVER, NULL); - cv_init(&mpt->m_extreq_sense_refcount_cv, NULL, CV_DRIVER, NULL); mutex_init_done++; mutex_enter(&mpt->m_mutex); /* * Initialize power management component */ if (mpt->m_options & MPTSAS_OPT_PM) { --- 1358,1373 ---- cv_init(&mpt->m_cv, NULL, CV_DRIVER, NULL); cv_init(&mpt->m_passthru_cv, NULL, CV_DRIVER, NULL); cv_init(&mpt->m_fw_cv, NULL, CV_DRIVER, NULL); cv_init(&mpt->m_config_cv, NULL, CV_DRIVER, NULL); cv_init(&mpt->m_fw_diag_cv, NULL, CV_DRIVER, NULL); mutex_init_done++; + #ifdef MPTSAS_FAULTINJECTION + TAILQ_INIT(&mpt->m_fminj_cmdq); + #endif + mutex_enter(&mpt->m_mutex); /* * Initialize power management component */ if (mpt->m_options & MPTSAS_OPT_PM) {
*** 1447,1457 **** mpt->m_scsi_reset_delay = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, "scsi-reset-delay", SCSI_DEFAULT_RESET_DELAY); if (mpt->m_scsi_reset_delay == 0) { mptsas_log(mpt, CE_NOTE, "scsi_reset_delay of 0 is not recommended," ! " resetting to SCSI_DEFAULT_RESET_DELAY\n"); mpt->m_scsi_reset_delay = SCSI_DEFAULT_RESET_DELAY; } /* * Initialize the wait and done FIFO queue --- 1454,1464 ---- mpt->m_scsi_reset_delay = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, "scsi-reset-delay", SCSI_DEFAULT_RESET_DELAY); if (mpt->m_scsi_reset_delay == 0) { mptsas_log(mpt, CE_NOTE, "scsi_reset_delay of 0 is not recommended," ! " resetting to SCSI_DEFAULT_RESET_DELAY"); mpt->m_scsi_reset_delay = SCSI_DEFAULT_RESET_DELAY; } /* * Initialize the wait and done FIFO queue
*** 1647,1657 **** cv_destroy(&mpt->m_cv); cv_destroy(&mpt->m_passthru_cv); cv_destroy(&mpt->m_fw_cv); cv_destroy(&mpt->m_config_cv); cv_destroy(&mpt->m_fw_diag_cv); - cv_destroy(&mpt->m_extreq_sense_refcount_cv); } if (map_setup) { mptsas_cfg_fini(mpt); } --- 1654,1663 ----
*** 1895,1905 **** /* * MPxIO enabled for the iport */ ndi_devi_enter(scsi_vhci_dip, &circ1); ndi_devi_enter(dip, &circ); ! while (pip = mdi_get_next_client_path(dip, NULL)) { if (mdi_pi_free(pip, 0) == MDI_SUCCESS) { continue; } ndi_devi_exit(dip, circ); ndi_devi_exit(scsi_vhci_dip, circ1); --- 1901,1912 ---- /* * MPxIO enabled for the iport */ ndi_devi_enter(scsi_vhci_dip, &circ1); ndi_devi_enter(dip, &circ); ! while ((pip = mdi_get_next_client_path(dip, NULL)) != ! NULL) { if (mdi_pi_free(pip, 0) == MDI_SUCCESS) { continue; } ndi_devi_exit(dip, circ); ndi_devi_exit(scsi_vhci_dip, circ1);
*** 1922,1933 **** (void) pm_busy_component(dip, 0); if (mpt->m_power_level != PM_LEVEL_D0) { if (pm_raise_power(dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) { mptsas_log(mpt, CE_WARN, ! "mptsas%d: Raise power request failed.", ! mpt->m_instance); (void) pm_idle_component(dip, 0); return (DDI_FAILURE); } } } --- 1929,1939 ---- (void) pm_busy_component(dip, 0); if (mpt->m_power_level != PM_LEVEL_D0) { if (pm_raise_power(dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) { mptsas_log(mpt, CE_WARN, ! "raise power request failed"); (void) pm_idle_component(dip, 0); return (DDI_FAILURE); } } }
*** 2049,2061 **** /* Lower the power informing PM Framework */ if (mpt->m_options & MPTSAS_OPT_PM) { if (pm_lower_power(dip, 0, PM_LEVEL_D3) != DDI_SUCCESS) mptsas_log(mpt, CE_WARN, ! "!mptsas%d: Lower power request failed " ! "during detach, ignoring.", ! mpt->m_instance); } mutex_destroy(&mpt->m_tx_waitq_mutex); mutex_destroy(&mpt->m_passthru_mutex); mutex_destroy(&mpt->m_mutex); --- 2055,2066 ---- /* Lower the power informing PM Framework */ if (mpt->m_options & MPTSAS_OPT_PM) { if (pm_lower_power(dip, 0, PM_LEVEL_D3) != DDI_SUCCESS) mptsas_log(mpt, CE_WARN, ! "lower power request failed during detach, " ! "ignoring"); } mutex_destroy(&mpt->m_tx_waitq_mutex); mutex_destroy(&mpt->m_passthru_mutex); mutex_destroy(&mpt->m_mutex);
*** 2065,2076 **** cv_destroy(&mpt->m_cv); cv_destroy(&mpt->m_passthru_cv); cv_destroy(&mpt->m_fw_cv); cv_destroy(&mpt->m_config_cv); cv_destroy(&mpt->m_fw_diag_cv); - cv_destroy(&mpt->m_extreq_sense_refcount_cv); mptsas_smp_teardown(mpt); mptsas_enc_teardown(mpt); mptsas_hba_teardown(mpt); mptsas_config_space_fini(mpt); --- 2070,2084 ---- cv_destroy(&mpt->m_cv); cv_destroy(&mpt->m_passthru_cv); cv_destroy(&mpt->m_fw_cv); cv_destroy(&mpt->m_config_cv); cv_destroy(&mpt->m_fw_diag_cv); + #ifdef MPTSAS_FAULTINJECTION + ASSERT(TAILQ_EMPTY(&mpt->m_fminj_cmdq)); + #endif + mptsas_smp_teardown(mpt); mptsas_enc_teardown(mpt); mptsas_hba_teardown(mpt); mptsas_config_space_fini(mpt);
*** 2327,2342 **** offsetof(mptsas_enclosure_t, me_link)); return (TRUE); } static void mptsas_enc_teardown(mptsas_t *mpt) { mptsas_enclosure_t *mep; while ((mep = list_remove_head(&mpt->m_enclosures)) != NULL) { ! kmem_free(mep, sizeof (mptsas_enclosure_t)); } list_destroy(&mpt->m_enclosures); } static mptsas_enclosure_t * --- 2335,2362 ---- offsetof(mptsas_enclosure_t, me_link)); return (TRUE); } static void + mptsas_enc_free(mptsas_enclosure_t *mep) + { + if (mep == NULL) + return; + if (mep->me_slotleds != NULL) { + VERIFY3U(mep->me_nslots, >, 0); + kmem_free(mep->me_slotleds, sizeof (uint8_t) * mep->me_nslots); + } + kmem_free(mep, sizeof (mptsas_enclosure_t)); + } + + static void mptsas_enc_teardown(mptsas_t *mpt) { mptsas_enclosure_t *mep; while ((mep = list_remove_head(&mpt->m_enclosures)) != NULL) { ! mptsas_enc_free(mep); } list_destroy(&mpt->m_enclosures); } static mptsas_enclosure_t *
*** 2469,2480 **** case PM_LEVEL_D3: NDBG11(("mptsas%d: turning power OFF.", mpt->m_instance)); MPTSAS_POWER_OFF(mpt); break; default: ! mptsas_log(mpt, CE_WARN, "mptsas%d: unknown power level <%x>.", ! mpt->m_instance, level); rval = DDI_FAILURE; break; } mutex_exit(&mpt->m_mutex); return (rval); --- 2489,2499 ---- case PM_LEVEL_D3: NDBG11(("mptsas%d: turning power OFF.", mpt->m_instance)); MPTSAS_POWER_OFF(mpt); break; default: ! mptsas_log(mpt, CE_WARN, "unknown power level <%x>", level); rval = DDI_FAILURE; break; } mutex_exit(&mpt->m_mutex); return (rval);
*** 2699,2710 **** caddr_t memp; ddi_dma_cookie_t cookie; size_t mem_size; int num_extrqsense_bufs; - ASSERT(mpt->m_extreq_sense_refcount == 0); - /* * re-alloc when it has already alloced */ if (mpt->m_dma_req_sense_hdl) { rmfreemap(mpt->m_erqsense_map); --- 2718,2727 ----
*** 3043,3053 **** return (DDI_FAILURE); } ASSERT(reallen < len); if (reallen >= len) { ! mptsas_log(0, CE_WARN, "!mptsas_get_name: name parameter " "length too small, it needs to be %d bytes", reallen + 1); } return (DDI_SUCCESS); } --- 3060,3070 ---- return (DDI_FAILURE); } ASSERT(reallen < len); if (reallen >= len) { ! mptsas_log(0, CE_WARN, "mptsas_get_name: name parameter " "length too small, it needs to be %d bytes", reallen + 1); } return (DDI_SUCCESS); }
*** 3090,3104 **** if (ndi_dev_is_persistent_node(tgt_dip) == 0) { (void) ndi_merge_node(tgt_dip, mptsas_name_child); ddi_set_name_addr(tgt_dip, NULL); return (DDI_FAILURE); } /* ! * phymask is 0 means the virtual port for RAID */ phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, hba_dip, 0, "phymask", 0); if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) { if ((pip = (void *)(sd->sd_private)) == NULL) { /* * Very bad news if this occurs. Somehow scsi_vhci has * lost the pathinfo node for this target. --- 3107,3128 ---- if (ndi_dev_is_persistent_node(tgt_dip) == 0) { (void) ndi_merge_node(tgt_dip, mptsas_name_child); ddi_set_name_addr(tgt_dip, NULL); return (DDI_FAILURE); } + /* ! * The phymask exists if the port is active, otherwise ! * nothing to do. */ + if (ddi_prop_exists(DDI_DEV_T_ANY, hba_dip, + DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "phymask") == 0) + return (DDI_FAILURE); + phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, hba_dip, 0, "phymask", 0); + if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) { if ((pip = (void *)(sd->sd_private)) == NULL) { /* * Very bad news if this occurs. Somehow scsi_vhci has * lost the pathinfo node for this target.
*** 3106,3116 **** return (DDI_NOT_WELL_FORMED); } if (mdi_prop_lookup_int(pip, LUN_PROP, &lun) != DDI_PROP_SUCCESS) { ! mptsas_log(mpt, CE_WARN, "Get lun property failed\n"); return (DDI_FAILURE); } if (mdi_prop_lookup_string(pip, SCSI_ADDR_PROP_TARGET_PORT, &psas_wwn) == MDI_SUCCESS) { --- 3130,3140 ---- return (DDI_NOT_WELL_FORMED); } if (mdi_prop_lookup_int(pip, LUN_PROP, &lun) != DDI_PROP_SUCCESS) { ! mptsas_log(mpt, CE_WARN, "Get lun property failed"); return (DDI_FAILURE); } if (mdi_prop_lookup_string(pip, SCSI_ADDR_PROP_TARGET_PORT, &psas_wwn) == MDI_SUCCESS) {
*** 3139,3149 **** addr.mta_phymask = phymask; mutex_enter(&mpt->m_mutex); ptgt = refhash_lookup(mpt->m_targets, &addr); mutex_exit(&mpt->m_mutex); if (ptgt == NULL) { ! mptsas_log(mpt, CE_WARN, "!tgt_init: target doesn't exist or " "gone already! phymask:%x, saswwn %"PRIx64, phymask, sas_wwn); return (DDI_FAILURE); } if (hba_tran->tran_tgt_private == NULL) { --- 3163,3173 ---- addr.mta_phymask = phymask; mutex_enter(&mpt->m_mutex); ptgt = refhash_lookup(mpt->m_targets, &addr); mutex_exit(&mpt->m_mutex); if (ptgt == NULL) { ! mptsas_log(mpt, CE_WARN, "tgt_init: target doesn't exist or " "gone already! phymask:%x, saswwn %"PRIx64, phymask, sas_wwn); return (DDI_FAILURE); } if (hba_tran->tran_tgt_private == NULL) {
*** 3184,3194 **** if (rval != 0) { if (inq89 != NULL) { kmem_free(inq89, inq89_len); } ! mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page " "0x89 for SATA target:%x failed!", ptgt->m_devhdl); return (DDI_SUCCESS); } sid = (void *)(&inq89[60]); --- 3208,3218 ---- if (rval != 0) { if (inq89 != NULL) { kmem_free(inq89, inq89_len); } ! mptsas_log(mpt, CE_WARN, "mptsas request inquiry page " "0x89 for SATA target:%x failed!", ptgt->m_devhdl); return (DDI_SUCCESS); } sid = (void *)(&inq89[60]);
*** 3437,3447 **** --- 3461,3582 ---- rval = mptsas_accept_pkt(mpt, cmd); return (rval); } + #ifdef MPTSAS_FAULTINJECTION + static void + mptsas_fminj_move_cmd_to_doneq(mptsas_t *mpt, mptsas_cmd_t *cmd, + uchar_t reason, uint_t stat) + { + struct scsi_pkt *pkt = cmd->cmd_pkt; + + TAILQ_REMOVE(&mpt->m_fminj_cmdq, cmd, cmd_active_link); + + /* Setup reason/statistics. */ + pkt->pkt_reason = reason; + pkt->pkt_statistics = stat; + + cmd->cmd_active_expiration = 0; + + /* Move command to doneque. */ + cmd->cmd_linkp = NULL; + cmd->cmd_flags |= CFLAG_FINISHED; + cmd->cmd_flags &= ~CFLAG_IN_TRANSPORT; + + *mpt->m_donetail = cmd; + mpt->m_donetail = &cmd->cmd_linkp; + mpt->m_doneq_len++; + } + + static void + mptsas_fminj_move_tgt_to_doneq(mptsas_t *mpt, ushort_t target, + uchar_t reason, uint_t stat) + { + mptsas_cmd_t *cmd; + + ASSERT(mutex_owned(&mpt->m_mutex)); + + if (!TAILQ_EMPTY(&mpt->m_fminj_cmdq)) { + cmd = TAILQ_FIRST(&mpt->m_fminj_cmdq); + ASSERT(cmd != NULL); + + while (cmd != NULL) { + mptsas_cmd_t *next = TAILQ_NEXT(cmd, cmd_active_link); + + if (Tgt(cmd) == target) { + mptsas_fminj_move_cmd_to_doneq(mpt, cmd, + reason, stat); + } + cmd = next; + } + } + } + + static void + mptsas_fminj_watchsubr(mptsas_t *mpt, + struct mptsas_active_cmdq *expired) + { + mptsas_cmd_t *cmd; + + ASSERT(mutex_owned(&mpt->m_mutex)); + + if (!TAILQ_EMPTY(&mpt->m_fminj_cmdq)) { + hrtime_t timestamp = gethrtime(); + + cmd = TAILQ_FIRST(&mpt->m_fminj_cmdq); + ASSERT(cmd != NULL); + + while (cmd != NULL) { + mptsas_cmd_t *next = TAILQ_NEXT(cmd, cmd_active_link); + + if (cmd->cmd_active_expiration <= timestamp) { + struct scsi_pkt *pkt = cmd->cmd_pkt; + + DTRACE_PROBE1(mptsas__command__timeout, + struct scsi_pkt *, pkt); + + /* Setup proper flags. */ + pkt->pkt_reason = CMD_TIMEOUT; + pkt->pkt_statistics = (STAT_TIMEOUT | + STAT_DEV_RESET); + cmd->cmd_active_expiration = 0; + + TAILQ_REMOVE(&mpt->m_fminj_cmdq, cmd, + cmd_active_link); + TAILQ_INSERT_TAIL(expired, cmd, + cmd_active_link); + } + cmd = next; + } + } + } + static int + mptsas_fminject(mptsas_t *mpt, mptsas_cmd_t *cmd) + { + struct scsi_pkt *pkt = cmd->cmd_pkt; + + ASSERT(mutex_owned(&mpt->m_mutex)); + + if (pkt->pkt_flags & FLAG_PKT_TIMEOUT) { + if (((pkt->pkt_flags & FLAG_NOINTR) == 0) && + (pkt->pkt_comp != NULL)) { + pkt->pkt_state = (STATE_GOT_BUS|STATE_GOT_TARGET| + STATE_SENT_CMD); + cmd->cmd_active_expiration = + gethrtime() + (hrtime_t)pkt->pkt_time * NANOSEC; + TAILQ_INSERT_TAIL(&mpt->m_fminj_cmdq, + cmd, cmd_active_link); + return (0); + } + } + return (-1); + } + #endif /* MPTSAS_FAULTINJECTION */ + + static int mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd) { int rval = TRAN_ACCEPT; mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
*** 3466,3482 **** ASSERT(ptgt->m_reset_delay == 0); mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE); } /* ! * If HBA is being reset, the DevHandles are being re-initialized, ! * which means that they could be invalid even if the target is still ! * attached. Check if being reset and if DevHandle is being ! * re-initialized. If this is the case, return BUSY so the I/O can be ! * retried later. */ if ((ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) && mpt->m_in_reset) { mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET); if (cmd->cmd_flags & CFLAG_TXQ) { mptsas_doneq_add(mpt, cmd); mptsas_doneq_empty(mpt); return (rval); --- 3601,3618 ---- ASSERT(ptgt->m_reset_delay == 0); mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE); } /* ! * If HBA is being reset, the device handles will be invalidated. ! * This is temporary and, if target is still attached, the device ! * handles will be re-assigned when firmware reset completes. ! * Then, if command was already waiting, complete the command ! * otherwise return BUSY and expect transport retry. */ if ((ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) && mpt->m_in_reset) { + NDBG20(("retry command, invalid devhdl, during FW reset.")); mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET); if (cmd->cmd_flags & CFLAG_TXQ) { mptsas_doneq_add(mpt, cmd); mptsas_doneq_empty(mpt); return (rval);
*** 3484,3512 **** return (TRAN_BUSY); } } /* ! * If device handle has already been invalidated, just ! * fail the command. In theory, command from scsi_vhci ! * client is impossible send down command with invalid ! * devhdl since devhdl is set after path offline, target ! * driver is not suppose to select a offlined path. */ if (ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) { ! NDBG3(("rejecting command, it might because invalid devhdl " ! "request.")); mptsas_set_pkt_reason(mpt, cmd, CMD_DEV_GONE, STAT_TERMINATED); if (cmd->cmd_flags & CFLAG_TXQ) { mptsas_doneq_add(mpt, cmd); mptsas_doneq_empty(mpt); return (rval); } else { return (TRAN_FATAL_ERROR); } } /* * The first case is the normal case. mpt gets a command from the * target driver and starts it. * Since SMID 0 is reserved and the TM slot is reserved, the actual max * commands is m_max_requests - 2. */ --- 3620,3658 ---- return (TRAN_BUSY); } } /* ! * If the device handle has been invalidated, set the response ! * reason to indicate the device is gone. Then add the ! * command to the done queue and run the completion routine ! * so the initiator of the command can clean up. */ if (ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) { ! NDBG20(("rejecting command, invalid devhdl because " ! "device gone.")); mptsas_set_pkt_reason(mpt, cmd, CMD_DEV_GONE, STAT_TERMINATED); if (cmd->cmd_flags & CFLAG_TXQ) { mptsas_doneq_add(mpt, cmd); mptsas_doneq_empty(mpt); return (rval); } else { return (TRAN_FATAL_ERROR); } } + /* + * Do fault injecttion before transmitting command. + * FLAG_NOINTR commands are skipped. + */ + #ifdef MPTSAS_FAULTINJECTION + if (!mptsas_fminject(mpt, cmd)) { + return (TRAN_ACCEPT); + } + #endif + + /* * The first case is the normal case. mpt gets a command from the * target driver and starts it. * Since SMID 0 is reserved and the TM slot is reserved, the actual max * commands is m_max_requests - 2. */
*** 3615,3624 **** --- 3761,3777 ---- { struct scsi_pkt *pkt = CMD2PKT(cmd); NDBG1(("mptsas_prepare_pkt: cmd=0x%p", (void *)cmd)); + #ifdef MPTSAS_FAULTINJECTION + /* Check for fault flags prior to perform actual initialization. */ + if (pkt->pkt_flags & FLAG_PKT_BUSY) { + return (TRAN_BUSY); + } + #endif + /* * Reinitialize some fields that need it; the packet may * have been resubmitted */ pkt->pkt_reason = CMD_CMPLT;
*** 3727,3792 **** cmd->cmd_tgt_addr = ptgt; if ((cmdlen > sizeof (cmd->cmd_cdb)) || (tgtlen > PKT_PRIV_LEN) || (statuslen > EXTCMDS_STATUS_SIZE)) { ! int failure; ! /* - * We are going to allocate external packet space which - * might include the sense data buffer for DMA so we - * need to increase the reference counter here. In a - * case the HBA is in reset we just simply free the - * allocated packet and bail out. - */ - mutex_enter(&mpt->m_mutex); - if (mpt->m_in_reset) { - mutex_exit(&mpt->m_mutex); - - cmd->cmd_flags = CFLAG_FREE; - kmem_cache_free(mpt->m_kmem_cache, cmd); - return (NULL); - } - mpt->m_extreq_sense_refcount++; - ASSERT(mpt->m_extreq_sense_refcount > 0); - mutex_exit(&mpt->m_mutex); - - /* - * if extern alloc fails, all will be - * deallocated, including cmd - */ - failure = mptsas_pkt_alloc_extern(mpt, cmd, - cmdlen, tgtlen, statuslen, kf); - - if (failure != 0 || cmd->cmd_extrqslen == 0) { - /* - * If the external packet space allocation - * failed, or we didn't allocate the sense - * data buffer for DMA we need to decrease the - * reference counter. - */ - mutex_enter(&mpt->m_mutex); - ASSERT(mpt->m_extreq_sense_refcount > 0); - mpt->m_extreq_sense_refcount--; - if (mpt->m_extreq_sense_refcount == 0) - cv_broadcast( - &mpt->m_extreq_sense_refcount_cv); - mutex_exit(&mpt->m_mutex); - - if (failure != 0) { - /* * if extern allocation fails, it will * deallocate the new pkt as well */ return (NULL); } } - } new_cmd = cmd; } else { cmd = PKT2CMD(pkt); new_cmd = NULL; } /* grab cmd->cmd_cookiec here as oldcookiec */ --- 3880,3904 ---- cmd->cmd_tgt_addr = ptgt; if ((cmdlen > sizeof (cmd->cmd_cdb)) || (tgtlen > PKT_PRIV_LEN) || (statuslen > EXTCMDS_STATUS_SIZE)) { ! if (mptsas_pkt_alloc_extern(mpt, cmd, ! cmdlen, tgtlen, statuslen, kf)) { /* * if extern allocation fails, it will * deallocate the new pkt as well */ return (NULL); } } new_cmd = cmd; } else { cmd = PKT2CMD(pkt); + pkt->pkt_start = 0; + pkt->pkt_stop = 0; new_cmd = NULL; } /* grab cmd->cmd_cookiec here as oldcookiec */
*** 3901,3911 **** get_dma_cookies: cmd->cmd_flags |= CFLAG_DMAVALID; ASSERT(cmd->cmd_cookiec > 0); if (cmd->cmd_cookiec > MPTSAS_MAX_CMD_SEGS) { ! mptsas_log(mpt, CE_NOTE, "large cookiec received %d\n", cmd->cmd_cookiec); bioerror(bp, EINVAL); if (new_cmd) { mptsas_scsi_destroy_pkt(ap, pkt); } --- 4013,4023 ---- get_dma_cookies: cmd->cmd_flags |= CFLAG_DMAVALID; ASSERT(cmd->cmd_cookiec > 0); if (cmd->cmd_cookiec > MPTSAS_MAX_CMD_SEGS) { ! mptsas_log(mpt, CE_NOTE, "large cookiec received %d", cmd->cmd_cookiec); bioerror(bp, EINVAL); if (new_cmd) { mptsas_scsi_destroy_pkt(ap, pkt); }
*** 4063,4089 **** (CFLAG_FREE | CFLAG_CDBEXTERN | CFLAG_PRIVEXTERN | CFLAG_SCBEXTERN)) == 0) { cmd->cmd_flags = CFLAG_FREE; kmem_cache_free(mpt->m_kmem_cache, (void *)cmd); } else { - boolean_t extrqslen = cmd->cmd_extrqslen != 0; - mptsas_pkt_destroy_extern(mpt, cmd); - - /* - * If the packet had the sense data buffer for DMA allocated we - * need to decrease the reference counter. - */ - if (extrqslen) { - mutex_enter(&mpt->m_mutex); - ASSERT(mpt->m_extreq_sense_refcount > 0); - mpt->m_extreq_sense_refcount--; - if (mpt->m_extreq_sense_refcount == 0) - cv_broadcast(&mpt->m_extreq_sense_refcount_cv); - mutex_exit(&mpt->m_mutex); } - } } /* * kmem cache constructor and destructor: * When constructing, we bzero the cmd and allocate the dma handle --- 4175,4186 ----
*** 5238,5249 **** * This is a success reply so just complete the IO. First, do a sanity * check on the SMID. The final slot is used for TM requests, which * would not come into this reply handler. */ if ((SMID == 0) || (SMID > slots->m_n_normal)) { ! mptsas_log(mpt, CE_WARN, "?Received invalid SMID of %d\n", ! SMID); ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED); return; } cmd = slots->m_slot[SMID]; --- 5335,5345 ---- * This is a success reply so just complete the IO. First, do a sanity * check on the SMID. The final slot is used for TM requests, which * would not come into this reply handler. */ if ((SMID == 0) || (SMID > slots->m_n_normal)) { ! mptsas_log(mpt, CE_WARN, "received invalid SMID of %d", SMID); ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED); return; } cmd = slots->m_slot[SMID];
*** 5250,5265 **** /* * print warning and return if the slot is empty */ if (cmd == NULL) { ! mptsas_log(mpt, CE_WARN, "?NULL command for successful SCSI IO " "in slot %d", SMID); return; } pkt = CMD2PKT(cmd); pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD | STATE_GOT_STATUS); if (cmd->cmd_flags & CFLAG_DMAVALID) { pkt->pkt_state |= STATE_XFERRED_DATA; } --- 5346,5363 ---- /* * print warning and return if the slot is empty */ if (cmd == NULL) { ! mptsas_log(mpt, CE_WARN, "NULL command for successful SCSI IO " "in slot %d", SMID); return; } pkt = CMD2PKT(cmd); + ASSERT(pkt->pkt_start != 0); + pkt->pkt_stop = gethrtime(); pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD | STATE_GOT_STATUS); if (cmd->cmd_flags & CFLAG_DMAVALID) { pkt->pkt_state |= STATE_XFERRED_DATA; }
*** 5319,5330 **** if ((reply_addr < reply_frame_dma_baseaddr) || (reply_addr >= (reply_frame_dma_baseaddr + (mpt->m_reply_frame_size * mpt->m_max_replies))) || ((reply_addr - reply_frame_dma_baseaddr) % mpt->m_reply_frame_size != 0)) { ! mptsas_log(mpt, CE_WARN, "?Received invalid reply frame " ! "address 0x%x\n", reply_addr); ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED); return; } (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0, --- 5417,5428 ---- if ((reply_addr < reply_frame_dma_baseaddr) || (reply_addr >= (reply_frame_dma_baseaddr + (mpt->m_reply_frame_size * mpt->m_max_replies))) || ((reply_addr - reply_frame_dma_baseaddr) % mpt->m_reply_frame_size != 0)) { ! mptsas_log(mpt, CE_WARN, "received invalid reply frame " ! "address 0x%x", reply_addr); ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED); return; } (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
*** 5345,5356 **** /* * This could be a TM reply, which use the last allocated SMID, * so allow for that. */ if ((SMID == 0) || (SMID > (slots->m_n_normal + 1))) { ! mptsas_log(mpt, CE_WARN, "?Received invalid SMID of " ! "%d\n", SMID); ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED); return; } --- 5443,5454 ---- /* * This could be a TM reply, which use the last allocated SMID, * so allow for that. */ if ((SMID == 0) || (SMID > (slots->m_n_normal + 1))) { ! mptsas_log(mpt, CE_WARN, "received invalid SMID of " ! "%d", SMID); ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED); return; }
*** 5358,5368 **** /* * print warning and return if the slot is empty */ if (cmd == NULL) { ! mptsas_log(mpt, CE_WARN, "?NULL command for address " "reply in slot %d", SMID); return; } if ((cmd->cmd_flags & (CFLAG_PASSTHRU | CFLAG_CONFIG | CFLAG_FW_DIAG))) { --- 5456,5466 ---- /* * print warning and return if the slot is empty */ if (cmd == NULL) { ! mptsas_log(mpt, CE_WARN, "NULL command for address " "reply in slot %d", SMID); return; } if ((cmd->cmd_flags & (CFLAG_PASSTHRU | CFLAG_CONFIG | CFLAG_FW_DIAG))) {
*** 5471,5481 **** /* * print warning and return if the slot is empty */ if (cmd == NULL) { ! mptsas_log(mpt, CE_WARN, "?NULL command for " "address reply in slot %d", SMID); return; } cmd->cmd_rfm = reply_addr; cmd->cmd_flags |= CFLAG_FINISHED; --- 5569,5579 ---- /* * print warning and return if the slot is empty */ if (cmd == NULL) { ! mptsas_log(mpt, CE_WARN, "NULL command for " "address reply in slot %d", SMID); return; } cmd->cmd_rfm = reply_addr; cmd->cmd_flags |= CFLAG_FINISHED;
*** 5556,5575 **** (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn); } loginfo = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->IOCLogInfo); mptsas_log(mpt, CE_NOTE, ! "?Log info 0x%x received for target %d %s.\n" ! "\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x", loginfo, Tgt(cmd), wwn_str, scsi_status, ioc_status, scsi_state); } NDBG31(("\t\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x", scsi_status, ioc_status, scsi_state)); pkt = CMD2PKT(cmd); *(pkt->pkt_scbp) = scsi_status; if (loginfo == 0x31170000) { /* * if loginfo PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY --- 5654,5675 ---- (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn); } loginfo = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->IOCLogInfo); mptsas_log(mpt, CE_NOTE, ! "log info 0x%x received for target %d %s, " ! "scsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x", loginfo, Tgt(cmd), wwn_str, scsi_status, ioc_status, scsi_state); } NDBG31(("\t\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x", scsi_status, ioc_status, scsi_state)); pkt = CMD2PKT(cmd); + ASSERT(pkt->pkt_start != 0); + pkt->pkt_stop = gethrtime(); *(pkt->pkt_scbp) = scsi_status; if (loginfo == 0x31170000) { /* * if loginfo PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY
*** 5593,5603 **** } if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { responsedata &= 0x000000FF; if (responsedata & MPTSAS_SCSI_RESPONSE_CODE_TLR_OFF) { ! mptsas_log(mpt, CE_NOTE, "Do not support the TLR\n"); pkt->pkt_reason = CMD_TLR_OFF; return; } } --- 5693,5703 ---- } if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { responsedata &= 0x000000FF; if (responsedata & MPTSAS_SCSI_RESPONSE_CODE_TLR_OFF) { ! mptsas_log(mpt, CE_NOTE, "TLR not supported"); pkt->pkt_reason = CMD_TLR_OFF; return; } }
*** 5669,5679 **** sizeof (mptsas_topo_change_list_t), KM_NOSLEEP); if (topo_node == NULL) { mptsas_log(mpt, CE_NOTE, "No memory" "resource for handle SAS dynamic" ! "reconfigure.\n"); break; } topo_node->mpt = mpt; topo_node->event = MPTSAS_DR_EVENT_RECONFIG_TARGET; topo_node->un.phymask = ptgt->m_addr.mta_phymask; --- 5769,5779 ---- sizeof (mptsas_topo_change_list_t), KM_NOSLEEP); if (topo_node == NULL) { mptsas_log(mpt, CE_NOTE, "No memory" "resource for handle SAS dynamic" ! "reconfigure"); break; } topo_node->mpt = mpt; topo_node->event = MPTSAS_DR_EVENT_RECONFIG_TARGET; topo_node->un.phymask = ptgt->m_addr.mta_phymask;
*** 5687,5697 **** DDI_NOSLEEP)) != DDI_SUCCESS) { kmem_free(topo_node, sizeof (mptsas_topo_change_list_t)); mptsas_log(mpt, CE_NOTE, "mptsas start taskq" "for handle SAS dynamic reconfigure" ! "failed. \n"); } } break; case MPI2_SCSI_STATUS_GOOD: switch (ioc_status & MPI2_IOCSTATUS_MASK) { --- 5787,5797 ---- DDI_NOSLEEP)) != DDI_SUCCESS) { kmem_free(topo_node, sizeof (mptsas_topo_change_list_t)); mptsas_log(mpt, CE_NOTE, "mptsas start taskq" "for handle SAS dynamic reconfigure" ! "failed"); } } break; case MPI2_SCSI_STATUS_GOOD: switch (ioc_status & MPI2_IOCSTATUS_MASK) {
*** 5767,5777 **** (void) mptsas_accept_pkt(mpt, cmd); break; default: mptsas_log(mpt, CE_WARN, ! "unknown ioc_status = %x\n", ioc_status); mptsas_log(mpt, CE_CONT, "scsi_state = %x, transfer " "count = %x, scsi_status = %x", scsi_state, xferred, scsi_status); break; } --- 5867,5877 ---- (void) mptsas_accept_pkt(mpt, cmd); break; default: mptsas_log(mpt, CE_WARN, ! "unknown ioc_status = %x", ioc_status); mptsas_log(mpt, CE_CONT, "scsi_state = %x, transfer " "count = %x, scsi_status = %x", scsi_state, xferred, scsi_status); break; }
*** 5784,5797 **** break; case MPI2_SCSI_STATUS_RESERVATION_CONFLICT: NDBG31(("scsi_status reservation conflict received")); break; default: ! mptsas_log(mpt, CE_WARN, "scsi_status=%x, ioc_status=%x\n", scsi_status, ioc_status); mptsas_log(mpt, CE_WARN, ! "mptsas_process_intr: invalid scsi status\n"); break; } } static void --- 5884,5897 ---- break; case MPI2_SCSI_STATUS_RESERVATION_CONFLICT: NDBG31(("scsi_status reservation conflict received")); break; default: ! mptsas_log(mpt, CE_WARN, "scsi_status=%x, ioc_status=%x", scsi_status, ioc_status); mptsas_log(mpt, CE_WARN, ! "mptsas_process_intr: invalid scsi status"); break; } } static void
*** 5809,5819 **** log_info = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->IOCLogInfo); dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->DevHandle); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { mptsas_log(mpt, CE_WARN, "mptsas_check_task_mgt: Task 0x%x " ! "failed. IOCStatus=0x%x IOCLogInfo=0x%x target=%d\n", task_type, ioc_status, log_info, dev_handle); pkt->pkt_reason = CMD_INCOMPLETE; return; } --- 5909,5919 ---- log_info = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->IOCLogInfo); dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->DevHandle); if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { mptsas_log(mpt, CE_WARN, "mptsas_check_task_mgt: Task 0x%x " ! "failed. IOCStatus=0x%x IOCLogInfo=0x%x target=%d", task_type, ioc_status, log_info, dev_handle); pkt->pkt_reason = CMD_INCOMPLETE; return; }
*** 5831,5841 **** /* * Check for invalid DevHandle of 0 in case application * sends bad command. DevHandle of 0 could cause problems. */ if (dev_handle == 0) { ! mptsas_log(mpt, CE_WARN, "!Can't flush target with" " DevHandle of 0."); } else { mptsas_flush_target(mpt, dev_handle, Lun(cmd), task_type); } --- 5931,5941 ---- /* * Check for invalid DevHandle of 0 in case application * sends bad command. DevHandle of 0 could cause problems. */ if (dev_handle == 0) { ! mptsas_log(mpt, CE_WARN, "Can't flush target with" " DevHandle of 0."); } else { mptsas_flush_target(mpt, dev_handle, Lun(cmd), task_type); }
*** 6018,6028 **** reply_type == MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS) { mptsas_handle_scsi_io_success(mpt, reply_desc_union); } else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { mptsas_handle_address_reply(mpt, reply_desc_union); } else { ! mptsas_log(mpt, CE_WARN, "?Bad reply type %x", reply_type); ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED); } /* * Clear the reply descriptor for re-use and increment --- 6118,6128 ---- reply_type == MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS) { mptsas_handle_scsi_io_success(mpt, reply_desc_union); } else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { mptsas_handle_address_reply(mpt, reply_desc_union); } else { ! mptsas_log(mpt, CE_WARN, "bad reply type %x", reply_type); ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED); } /* * Clear the reply descriptor for re-use and increment
*** 6462,6475 **** mutex_enter(&mpt->m_mutex); /* * If HBA is being reset, don't perform operations depending * on the IOC. We must free the topo list, however. */ ! if (!mpt->m_in_reset) mptsas_handle_topo_change(topo_node, parent); ! else NDBG20(("skipping topo change received during reset")); save_node = topo_node; topo_node = topo_node->next; ASSERT(save_node); kmem_free(save_node, sizeof (mptsas_topo_change_list_t)); mutex_exit(&mpt->m_mutex); --- 6562,6576 ---- mutex_enter(&mpt->m_mutex); /* * If HBA is being reset, don't perform operations depending * on the IOC. We must free the topo list, however. */ ! if (!mpt->m_in_reset) { mptsas_handle_topo_change(topo_node, parent); ! } else { NDBG20(("skipping topo change received during reset")); + } save_node = topo_node; topo_node = topo_node->next; ASSERT(save_node); kmem_free(save_node, sizeof (mptsas_topo_change_list_t)); mutex_exit(&mpt->m_mutex);
*** 6551,6570 **** rval = mptsas_get_target_device_info(mpt, page_address, &devhdl, &ptgt); if (rval == DEV_INFO_WRONG_DEVICE_TYPE) { mptsas_log(mpt, CE_NOTE, "mptsas_handle_topo_change: target %d is " ! "not a SAS/SATA device. \n", topo_node->devhdl); } else if (rval == DEV_INFO_FAIL_ALLOC) { mptsas_log(mpt, CE_NOTE, "mptsas_handle_topo_change: could not " ! "allocate memory. \n"); } else if (rval == DEV_INFO_FAIL_GUID) { mptsas_log(mpt, CE_NOTE, "mptsas_handle_topo_change: could not " ! "get SATA GUID for target %d. \n", topo_node->devhdl); } /* * If rval is DEV_INFO_PHYS_DISK or indicates failure * then there is nothing else to do, just leave. --- 6652,6671 ---- rval = mptsas_get_target_device_info(mpt, page_address, &devhdl, &ptgt); if (rval == DEV_INFO_WRONG_DEVICE_TYPE) { mptsas_log(mpt, CE_NOTE, "mptsas_handle_topo_change: target %d is " ! "not a SAS/SATA device", topo_node->devhdl); } else if (rval == DEV_INFO_FAIL_ALLOC) { mptsas_log(mpt, CE_NOTE, "mptsas_handle_topo_change: could not " ! "allocate memory"); } else if (rval == DEV_INFO_FAIL_GUID) { mptsas_log(mpt, CE_NOTE, "mptsas_handle_topo_change: could not " ! "get SATA GUID for target %d", topo_node->devhdl); } /* * If rval is DEV_INFO_PHYS_DISK or indicates failure * then there is nothing else to do, just leave.
*** 6787,6798 **** break; } } mutex_enter(&mpt->m_mutex); - ptgt->m_led_status = 0; - (void) mptsas_flush_led_status(mpt, ptgt); if (rval == DDI_SUCCESS) { refhash_remove(mpt->m_targets, ptgt); ptgt = NULL; } else { /* --- 6888,6897 ----
*** 6888,6898 **** * successfully. */ mutex_exit(&mpt->m_mutex); ndi_devi_enter(parent, &circ1); ! rval = mptsas_offline_smp(parent, psmp, NDI_DEVI_REMOVE); ndi_devi_exit(parent, circ1); dev_info = psmp->m_deviceinfo; if ((dev_info & DEVINFO_DIRECT_ATTACHED) == DEVINFO_DIRECT_ATTACHED) { --- 6987,6997 ---- * successfully. */ mutex_exit(&mpt->m_mutex); ndi_devi_enter(parent, &circ1); ! rval = mptsas_offline_smp(parent, psmp); ndi_devi_exit(parent, circ1); dev_info = psmp->m_deviceinfo; if ((dev_info & DEVINFO_DIRECT_ATTACHED) == DEVINFO_DIRECT_ATTACHED) {
*** 6901,6910 **** --- 7000,7010 ---- DDI_PROP_SUCCESS) { (void) ddi_prop_remove(DDI_DEV_T_NONE, parent, MPTSAS_VIRTUAL_PORT); mptsas_log(mpt, CE_WARN, "mptsas virtual port " "prop update failed"); + mutex_enter(&mpt->m_mutex); return; } /* * Check whether the smp connected to the iport, */
*** 6913,6922 **** --- 7013,7023 ---- DDI_PROP_SUCCESS) { (void) ddi_prop_remove(DDI_DEV_T_NONE, parent, MPTSAS_NUM_PHYS); mptsas_log(mpt, CE_WARN, "mptsas num phys" "prop update failed"); + mutex_enter(&mpt->m_mutex); return; } /* * Clear parent's attached-port props */
*** 6926,6935 **** --- 7027,7037 ---- DDI_PROP_SUCCESS) { (void) ddi_prop_remove(DDI_DEV_T_NONE, parent, SCSI_ADDR_PROP_ATTACHED_PORT); mptsas_log(mpt, CE_WARN, "mptsas attached port " "prop update failed"); + mutex_enter(&mpt->m_mutex); return; } } mutex_enter(&mpt->m_mutex);
*** 7060,7074 **** eventreply = (pMpi2EventNotificationReply_t) (mpt->m_reply_frame + (rfm - (mpt->m_reply_frame_dma_addr & 0xffffffffu))); event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event); ! if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl, ! &eventreply->IOCStatus)) { if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { mptsas_log(mpt, CE_WARN, ! "!mptsas_handle_event_sync: event 0x%x, " "IOCStatus=0x%x, " "IOCLogInfo=0x%x", event, iocstatus, ddi_get32(mpt->m_acc_reply_frame_hdl, &eventreply->IOCLogInfo)); } else { --- 7162,7176 ---- eventreply = (pMpi2EventNotificationReply_t) (mpt->m_reply_frame + (rfm - (mpt->m_reply_frame_dma_addr & 0xffffffffu))); event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event); ! if ((iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl, ! &eventreply->IOCStatus)) != 0) { if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { mptsas_log(mpt, CE_WARN, ! "mptsas_handle_event_sync: event 0x%x, " "IOCStatus=0x%x, " "IOCLogInfo=0x%x", event, iocstatus, ddi_get32(mpt->m_acc_reply_frame_hdl, &eventreply->IOCLogInfo)); } else {
*** 7536,7546 **** topo_head = topo_head->next; kmem_free(topo_node, sizeof (mptsas_topo_change_list_t)); } mptsas_log(mpt, CE_NOTE, "mptsas start taskq " ! "for handle SAS DR event failed. \n"); } } break; } case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: --- 7638,7648 ---- topo_head = topo_head->next; kmem_free(topo_node, sizeof (mptsas_topo_change_list_t)); } mptsas_log(mpt, CE_NOTE, "mptsas start taskq " ! "for handle SAS DR event failed"); } } break; } case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
*** 7720,7730 **** topo_head = topo_head->next; kmem_free(topo_node, sizeof (mptsas_topo_change_list_t)); } mptsas_log(mpt, CE_NOTE, "mptsas start taskq " ! "for handle SAS DR event failed. \n"); } } break; } default: --- 7822,7832 ---- topo_head = topo_head->next; kmem_free(topo_node, sizeof (mptsas_topo_change_list_t)); } mptsas_log(mpt, CE_NOTE, "mptsas start taskq " ! "for handle SAS DR event failed"); } } break; } default:
*** 7765,7779 **** eventreply = (pMpi2EventNotificationReply_t) (mpt->m_reply_frame + (rfm - (mpt->m_reply_frame_dma_addr & 0xffffffffu))); event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event); ! if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl, ! &eventreply->IOCStatus)) { if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { mptsas_log(mpt, CE_WARN, ! "!mptsas_handle_event: IOCStatus=0x%x, " "IOCLogInfo=0x%x", iocstatus, ddi_get32(mpt->m_acc_reply_frame_hdl, &eventreply->IOCLogInfo)); } else { mptsas_log(mpt, CE_WARN, --- 7867,7881 ---- eventreply = (pMpi2EventNotificationReply_t) (mpt->m_reply_frame + (rfm - (mpt->m_reply_frame_dma_addr & 0xffffffffu))); event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event); ! if ((iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl, ! &eventreply->IOCStatus)) != 0) { if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { mptsas_log(mpt, CE_WARN, ! "mptsas_handle_event: IOCStatus=0x%x, " "IOCLogInfo=0x%x", iocstatus, ddi_get32(mpt->m_acc_reply_frame_hdl, &eventreply->IOCLogInfo)); } else { mptsas_log(mpt, CE_WARN,
*** 7880,7890 **** break; case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING: mep = mptsas_enc_lookup(mpt, enchdl); if (mep != NULL) { list_remove(&mpt->m_enclosures, mep); ! kmem_free(mep, sizeof (*mep)); } (void) sprintf(string, ", not responding"); break; default: break; --- 7982,7993 ---- break; case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING: mep = mptsas_enc_lookup(mpt, enchdl); if (mep != NULL) { list_remove(&mpt->m_enclosures, mep); ! mptsas_enc_free(mep); ! mep = NULL; } (void) sprintf(string, ", not responding"); break; default: break;
*** 8147,8157 **** i = state & MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING; mptsas_log(mpt, CE_NOTE, " Volume %d settings changed" ", auto-config of hot-swap drives is %s" ", write caching is %s" ! ", hot-spare pool mask is %02x\n", vol, state & MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE ? "disabled" : "enabled", i == MPI2_RAIDVOL0_SETTING_UNCHANGED ? "controlled by member disks" : --- 8250,8260 ---- i = state & MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING; mptsas_log(mpt, CE_NOTE, " Volume %d settings changed" ", auto-config of hot-swap drives is %s" ", write caching is %s" ! ", hot-spare pool mask is %02x", vol, state & MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE ? "disabled" : "enabled", i == MPI2_RAIDVOL0_SETTING_UNCHANGED ? "controlled by member disks" :
*** 8167,8177 **** { mpt->m_raidconfig[config].m_raidvol[vol].m_state = (uint8_t)state; mptsas_log(mpt, CE_NOTE, ! "Volume %d is now %s\n", vol, state == MPI2_RAID_VOL_STATE_OPTIMAL ? "optimal" : state == MPI2_RAID_VOL_STATE_DEGRADED ? "degraded" : state == MPI2_RAID_VOL_STATE_ONLINE --- 8270,8280 ---- { mpt->m_raidconfig[config].m_raidvol[vol].m_state = (uint8_t)state; mptsas_log(mpt, CE_NOTE, ! "Volume %d is now %s", vol, state == MPI2_RAID_VOL_STATE_OPTIMAL ? "optimal" : state == MPI2_RAID_VOL_STATE_DEGRADED ? "degraded" : state == MPI2_RAID_VOL_STATE_ONLINE
*** 8189,8199 **** { mpt->m_raidconfig[config].m_raidvol[vol]. m_statusflags = state; mptsas_log(mpt, CE_NOTE, ! " Volume %d is now %s%s%s%s%s%s%s%s%s\n", vol, state & MPI2_RAIDVOL0_STATUS_FLAG_ENABLED ? ", enabled" : ", disabled", state & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED ? ", quiesced" : "", --- 8292,8302 ---- { mpt->m_raidconfig[config].m_raidvol[vol]. m_statusflags = state; mptsas_log(mpt, CE_NOTE, ! " Volume %d is now %s%s%s%s%s%s%s%s%s", vol, state & MPI2_RAIDVOL0_STATUS_FLAG_ENABLED ? ", enabled" : ", disabled", state & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED ? ", quiesced" : "",
*** 8259,8269 **** case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED: status = state; mptsas_log(mpt, CE_NOTE, " PhysDiskNum %d with DevHandle 0x%x in slot %d " "for enclosure with handle 0x%x is now " ! "%s%s%s%s%s\n", physdisknum, devhandle, slot, enchandle, status & MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME ? ", inactive" : ", active", status & MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC ? ", out of sync" : "", --- 8362,8372 ---- case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED: status = state; mptsas_log(mpt, CE_NOTE, " PhysDiskNum %d with DevHandle 0x%x in slot %d " "for enclosure with handle 0x%x is now " ! "%s%s%s%s%s", physdisknum, devhandle, slot, enchandle, status & MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME ? ", inactive" : ", active", status & MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC ? ", out of sync" : "",
*** 8277,8287 **** break; case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED: mptsas_log(mpt, CE_NOTE, " PhysDiskNum %d with DevHandle 0x%x in slot %d " ! "for enclosure with handle 0x%x is now %s\n", physdisknum, devhandle, slot, enchandle, state == MPI2_RAID_PD_STATE_OPTIMAL ? "optimal" : state == MPI2_RAID_PD_STATE_REBUILDING ? "rebuilding" : --- 8380,8390 ---- break; case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED: mptsas_log(mpt, CE_NOTE, " PhysDiskNum %d with DevHandle 0x%x in slot %d " ! "for enclosure with handle 0x%x is now %s", physdisknum, devhandle, slot, enchandle, state == MPI2_RAID_PD_STATE_OPTIMAL ? "optimal" : state == MPI2_RAID_PD_STATE_REBUILDING ? "rebuilding" :
*** 8300,8310 **** --- 8403,8467 ---- "state unknown"); break; } break; } + case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION: + { + pMpi26EventDataActiveCableExcept_t actcable; + uint32_t power; + uint8_t reason, id; + + actcable = (pMpi26EventDataActiveCableExcept_t) + eventreply->EventData; + power = ddi_get32(mpt->m_acc_reply_frame_hdl, + &actcable->ActiveCablePowerRequirement); + reason = ddi_get8(mpt->m_acc_reply_frame_hdl, + &actcable->ReasonCode); + id = ddi_get8(mpt->m_acc_reply_frame_hdl, + &actcable->ReceptacleID); + + /* + * It'd be nice if this weren't just logging to the system but + * were telling FMA about the active cable problem and FMA was + * aware of the cable topology and state. + */ + switch (reason) { + case MPI26_EVENT_ACTIVE_CABLE_PRESENT: + /* Don't log anything if it's fine */ + break; + case MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER: + mptsas_log(mpt, CE_WARN, "An active cable (id %u) does " + "not have sufficient power to be enabled. " + "Devices connected to this cable will not be " + "visible to the system.", id); + if (power == UINT32_MAX) { + mptsas_log(mpt, CE_CONT, "The cable's power " + "requirements are unknown.\n"); + } else { + mptsas_log(mpt, CE_CONT, "The cable requires " + "%u mW of power to function.\n", power); + } + break; + case MPI26_EVENT_ACTIVE_CABLE_DEGRADED: + mptsas_log(mpt, CE_WARN, "An active cable (id %u) is " + "degraded and not running at its full speed. " + "Some devices might not appear.", id); + break; default: + break; + } + break; + } + case MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE: + case MPI2_EVENT_PCIE_ENUMERATION: + case MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: + case MPI2_EVENT_PCIE_LINK_COUNTER: + mptsas_log(mpt, CE_NOTE, "Unhandled mpt_sas PCIe device " + "event received (0x%x)", event); + break; + default: NDBG20(("mptsas%d: unknown event %x received", mpt->m_instance, event)); break; }
*** 8547,8557 **** } cmd->cmd_linkp = NULL; mutex_exit(&mpt->m_tx_waitq_mutex); if (mptsas_accept_pkt(mpt, cmd) != TRAN_ACCEPT) cmn_err(CE_WARN, "mpt: mptsas_accept_tx_waitq: failed " ! "to accept cmd on queue\n"); mutex_enter(&mpt->m_tx_waitq_mutex); } } --- 8704,8714 ---- } cmd->cmd_linkp = NULL; mutex_exit(&mpt->m_tx_waitq_mutex); if (mptsas_accept_pkt(mpt, cmd) != TRAN_ACCEPT) cmn_err(CE_WARN, "mpt: mptsas_accept_tx_waitq: failed " ! "to accept cmd on queue"); mutex_enter(&mpt->m_tx_waitq_mutex); } }
*** 8633,8643 **** break; case MSG_ORDERED_QTAG: control |= MPI2_SCSIIO_CONTROL_ORDEREDQ; break; default: ! mptsas_log(mpt, CE_WARN, "mpt: Invalid tag type\n"); break; } } else { if (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE) { ptgt->m_t_throttle = 1; --- 8790,8800 ---- break; case MSG_ORDERED_QTAG: control |= MPI2_SCSIIO_CONTROL_ORDEREDQ; break; default: ! mptsas_log(mpt, CE_WARN, "invalid tag type"); break; } } else { if (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE) { ptgt->m_t_throttle = 1;
*** 8714,8723 **** --- 8871,8881 ---- SMID, (void *)io_request, (void *)cmd)); (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV); (void) ddi_dma_sync(mpt->m_dma_req_sense_hdl, 0, 0, DDI_DMA_SYNC_FORDEV); + pkt->pkt_start = gethrtime(); /* * Build request descriptor and write it to the request desc post reg. */ request_desc |= (SMID << 16);
*** 8725,8736 **** MPTSAS_START_CMD(mpt, request_desc); /* * Start timeout. */ ! cmd->cmd_active_expiration = ! gethrtime() + (hrtime_t)pkt->pkt_time * NANOSEC; #ifdef MPTSAS_TEST /* * Force timeouts to happen immediately. */ if (mptsas_test_timeouts) --- 8883,8895 ---- MPTSAS_START_CMD(mpt, request_desc); /* * Start timeout. */ ! cmd->cmd_active_expiration = pkt->pkt_start + ! (hrtime_t)pkt->pkt_time * (hrtime_t)NANOSEC; ! #ifdef MPTSAS_TEST /* * Force timeouts to happen immediately. */ if (mptsas_test_timeouts)
*** 9248,9259 **** if (mpt->m_softstate & (MPTSAS_SS_QUIESCED | MPTSAS_SS_DRAINING)) { return; } if (what == HOLD_THROTTLE) { ! ptgt->m_t_throttle = HOLD_THROTTLE; } else if (ptgt->m_reset_delay == 0) { ptgt->m_t_throttle = what; } } /* --- 9407,9421 ---- if (mpt->m_softstate & (MPTSAS_SS_QUIESCED | MPTSAS_SS_DRAINING)) { return; } if (what == HOLD_THROTTLE) { ! ptgt->m_t_throttle = what; } else if (ptgt->m_reset_delay == 0) { + if (what == MAX_THROTTLE) + ptgt->m_t_throttle = mpt->m_max_tune_throttle; + else ptgt->m_t_throttle = what; } } /*
*** 9400,9409 **** --- 9562,9575 ---- default: mptsas_log(mpt, CE_WARN, "Unknown task management type %d.", tasktype); break; } + + #ifdef MPTSAS_FAULTINJECTION + mptsas_fminj_move_tgt_to_doneq(mpt, target, reason, stat); + #endif } /* * Clean up hba state, abort all outstanding command and commands in waitq * reset timeout of all targets.
*** 9691,9700 **** --- 9857,9877 ---- */ if (pkt != NULL) { /* abort the specified packet */ sp = PKT2CMD(pkt); + #ifdef MPTSAS_FAULTINJECTION + /* Command already on the list. */ + if (((pkt->pkt_flags & FLAG_PKT_TIMEOUT) != 0) && + (sp->cmd_active_expiration != 0)) { + mptsas_fminj_move_cmd_to_doneq(mpt, sp, CMD_ABORTED, + STAT_ABORTED); + rval = TRUE; + goto done; + } + #endif + if (sp->cmd_queued) { NDBG23(("mptsas_do_scsi_abort: queued sp=0x%p aborted", (void *)sp)); mptsas_waitq_delete(mpt, sp); mptsas_set_pkt_reason(mpt, sp, CMD_ABORTED,
*** 9981,9994 **** va_start(ap, fmt); (void) vsprintf(mptsas_log_buf, fmt, ap); va_end(ap); ! if (level == CE_CONT) { ! scsi_log(dev, mptsas_label, level, "%s\n", mptsas_log_buf); } else { ! scsi_log(dev, mptsas_label, level, "%s", mptsas_log_buf); } mutex_exit(&mptsas_log_mutex); } --- 10158,10171 ---- va_start(ap, fmt); (void) vsprintf(mptsas_log_buf, fmt, ap); va_end(ap); ! if (level == CE_CONT || level == CE_NOTE) { ! scsi_log(dev, mptsas_label, level, "!%s\n", mptsas_log_buf); } else { ! scsi_log(dev, mptsas_label, level, "!%s", mptsas_log_buf); } mutex_exit(&mptsas_log_mutex); }
*** 10052,10061 **** --- 10229,10244 ---- #endif mptsas_t *mpt; uint32_t doorbell; + #ifdef MPTSAS_FAULTINJECTION + struct mptsas_active_cmdq finj_cmds; + + TAILQ_INIT(&finj_cmds); + #endif + NDBG30(("mptsas_watch")); rw_enter(&mptsas_global_rwlock, RW_READER); for (mpt = mptsas_head; mpt != (mptsas_t *)NULL; mpt = mpt->m_next) {
*** 10095,10112 **** --- 10278,10315 ---- if (mpt->m_options & MPTSAS_OPT_PM) { mpt->m_busy = 0; (void) pm_idle_component(mpt->m_dip, 0); } + #ifdef MPTSAS_FAULTINJECTION + mptsas_fminj_watchsubr(mpt, &finj_cmds); + #endif + mutex_exit(&mpt->m_mutex); } rw_exit(&mptsas_global_rwlock); mutex_enter(&mptsas_global_mutex); if (mptsas_timeouts_enabled) mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick); mutex_exit(&mptsas_global_mutex); + + #ifdef MPTSAS_FAULTINJECTION + /* Complete all completed commands. */ + if (!TAILQ_EMPTY(&finj_cmds)) { + mptsas_cmd_t *cmd; + + while ((cmd = TAILQ_FIRST(&finj_cmds)) != NULL) { + TAILQ_REMOVE(&finj_cmds, cmd, cmd_active_link); + struct scsi_pkt *pkt = cmd->cmd_pkt; + + if (pkt->pkt_comp != NULL) { + (*pkt->pkt_comp)(pkt); + } + } + } + #endif } static void mptsas_watchsubr_tgt(mptsas_t *mpt, mptsas_target_t *ptgt, hrtime_t timestamp) {
*** 10669,10687 **** mptsas_log(mpt, CE_WARN, "FW Download tce invalid!"); } pt->sgl_offset = offsetof(MPI2_FW_DOWNLOAD_REQUEST, SGL) + sizeof (*tcsge); ! if (pt->request_size != pt->sgl_offset) NDBG15(("mpi_pre_fw_download(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", (int)pt->request_size, (int)pt->sgl_offset, (int)pt->dataout_size)); ! if (pt->data_size < sizeof (MPI2_FW_DOWNLOAD_REPLY)) NDBG15(("mpi_pre_fw_download(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_FW_DOWNLOAD_REPLY))); } /* * Prepare the pt for a SAS3 FW_DOWNLOAD request. */ --- 10872,10892 ---- mptsas_log(mpt, CE_WARN, "FW Download tce invalid!"); } pt->sgl_offset = offsetof(MPI2_FW_DOWNLOAD_REQUEST, SGL) + sizeof (*tcsge); ! if (pt->request_size != pt->sgl_offset) { NDBG15(("mpi_pre_fw_download(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", (int)pt->request_size, (int)pt->sgl_offset, (int)pt->dataout_size)); ! } ! if (pt->data_size < sizeof (MPI2_FW_DOWNLOAD_REPLY)) { NDBG15(("mpi_pre_fw_download(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_FW_DOWNLOAD_REPLY))); + } } /* * Prepare the pt for a SAS3 FW_DOWNLOAD request. */
*** 10707,10725 **** } req25->ImageOffset = tcsge->ImageOffset; req25->ImageSize = tcsge->ImageSize; pt->sgl_offset = offsetof(MPI25_FW_DOWNLOAD_REQUEST, SGL); ! if (pt->request_size != pt->sgl_offset) NDBG15(("mpi_pre_fw_25_download(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! if (pt->data_size < sizeof (MPI2_FW_DOWNLOAD_REPLY)) NDBG15(("mpi_pre_fw_25_download(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_FW_UPLOAD_REPLY))); } /* * Prepare the pt for a SAS2 FW_UPLOAD request. */ --- 10912,10932 ---- } req25->ImageOffset = tcsge->ImageOffset; req25->ImageSize = tcsge->ImageSize; pt->sgl_offset = offsetof(MPI25_FW_DOWNLOAD_REQUEST, SGL); ! if (pt->request_size != pt->sgl_offset) { NDBG15(("mpi_pre_fw_25_download(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! } ! if (pt->data_size < sizeof (MPI2_FW_DOWNLOAD_REPLY)) { NDBG15(("mpi_pre_fw_25_download(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_FW_UPLOAD_REPLY))); + } } /* * Prepare the pt for a SAS2 FW_UPLOAD request. */
*** 10751,10769 **** mptsas_log(mpt, CE_WARN, "FW Upload tce invalid!"); } pt->sgl_offset = offsetof(MPI2_FW_UPLOAD_REQUEST, SGL) + sizeof (*tcsge); ! if (pt->request_size != pt->sgl_offset) NDBG15(("mpi_pre_fw_upload(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! if (pt->data_size < sizeof (MPI2_FW_UPLOAD_REPLY)) NDBG15(("mpi_pre_fw_upload(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_FW_UPLOAD_REPLY))); } /* * Prepare the pt a SAS3 FW_UPLOAD request. */ --- 10958,10978 ---- mptsas_log(mpt, CE_WARN, "FW Upload tce invalid!"); } pt->sgl_offset = offsetof(MPI2_FW_UPLOAD_REQUEST, SGL) + sizeof (*tcsge); ! if (pt->request_size != pt->sgl_offset) { NDBG15(("mpi_pre_fw_upload(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! } ! if (pt->data_size < sizeof (MPI2_FW_UPLOAD_REPLY)) { NDBG15(("mpi_pre_fw_upload(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_FW_UPLOAD_REPLY))); + } } /* * Prepare the pt a SAS3 FW_UPLOAD request. */
*** 10789,10807 **** } req25->ImageOffset = tcsge->ImageOffset; req25->ImageSize = tcsge->ImageSize; pt->sgl_offset = offsetof(MPI25_FW_UPLOAD_REQUEST, SGL); ! if (pt->request_size != pt->sgl_offset) NDBG15(("mpi_pre_fw_25_upload(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! if (pt->data_size < sizeof (MPI2_FW_UPLOAD_REPLY)) NDBG15(("mpi_pre_fw_25_upload(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_FW_UPLOAD_REPLY))); } /* * Prepare the pt for an IOC_FACTS request. */ --- 10998,11018 ---- } req25->ImageOffset = tcsge->ImageOffset; req25->ImageSize = tcsge->ImageSize; pt->sgl_offset = offsetof(MPI25_FW_UPLOAD_REQUEST, SGL); ! if (pt->request_size != pt->sgl_offset) { NDBG15(("mpi_pre_fw_25_upload(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! } ! if (pt->data_size < sizeof (MPI2_FW_UPLOAD_REPLY)) { NDBG15(("mpi_pre_fw_25_upload(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_FW_UPLOAD_REPLY))); + } } /* * Prepare the pt for an IOC_FACTS request. */
*** 10809,10828 **** mpi_pre_ioc_facts(mptsas_t *mpt, mptsas_pt_request_t *pt) { #ifndef __lock_lint _NOTE(ARGUNUSED(mpt)) #endif ! if (pt->request_size != sizeof (MPI2_IOC_FACTS_REQUEST)) NDBG15(("mpi_pre_ioc_facts(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, (int)sizeof (MPI2_IOC_FACTS_REQUEST), pt->dataout_size)); ! if (pt->data_size != sizeof (MPI2_IOC_FACTS_REPLY)) NDBG15(("mpi_pre_ioc_facts(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_IOC_FACTS_REPLY))); pt->sgl_offset = (uint16_t)pt->request_size; } /* * Prepare the pt for a PORT_FACTS request. --- 11020,11041 ---- mpi_pre_ioc_facts(mptsas_t *mpt, mptsas_pt_request_t *pt) { #ifndef __lock_lint _NOTE(ARGUNUSED(mpt)) #endif ! if (pt->request_size != sizeof (MPI2_IOC_FACTS_REQUEST)) { NDBG15(("mpi_pre_ioc_facts(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, (int)sizeof (MPI2_IOC_FACTS_REQUEST), pt->dataout_size)); ! } ! if (pt->data_size != sizeof (MPI2_IOC_FACTS_REPLY)) { NDBG15(("mpi_pre_ioc_facts(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_IOC_FACTS_REPLY))); + } pt->sgl_offset = (uint16_t)pt->request_size; } /* * Prepare the pt for a PORT_FACTS request.
*** 10831,10850 **** mpi_pre_port_facts(mptsas_t *mpt, mptsas_pt_request_t *pt) { #ifndef __lock_lint _NOTE(ARGUNUSED(mpt)) #endif ! if (pt->request_size != sizeof (MPI2_PORT_FACTS_REQUEST)) NDBG15(("mpi_pre_port_facts(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, (int)sizeof (MPI2_PORT_FACTS_REQUEST), pt->dataout_size)); ! if (pt->data_size != sizeof (MPI2_PORT_FACTS_REPLY)) NDBG15(("mpi_pre_port_facts(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_PORT_FACTS_REPLY))); pt->sgl_offset = (uint16_t)pt->request_size; } /* * Prepare pt for a SATA_PASSTHROUGH request. --- 11044,11065 ---- mpi_pre_port_facts(mptsas_t *mpt, mptsas_pt_request_t *pt) { #ifndef __lock_lint _NOTE(ARGUNUSED(mpt)) #endif ! if (pt->request_size != sizeof (MPI2_PORT_FACTS_REQUEST)) { NDBG15(("mpi_pre_port_facts(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, (int)sizeof (MPI2_PORT_FACTS_REQUEST), pt->dataout_size)); ! } ! if (pt->data_size != sizeof (MPI2_PORT_FACTS_REPLY)) { NDBG15(("mpi_pre_port_facts(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_PORT_FACTS_REPLY))); + } pt->sgl_offset = (uint16_t)pt->request_size; } /* * Prepare pt for a SATA_PASSTHROUGH request.
*** 10854,10890 **** { #ifndef __lock_lint _NOTE(ARGUNUSED(mpt)) #endif pt->sgl_offset = offsetof(MPI2_SATA_PASSTHROUGH_REQUEST, SGL); ! if (pt->request_size != pt->sgl_offset) NDBG15(("mpi_pre_sata_passthrough(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! if (pt->data_size != sizeof (MPI2_SATA_PASSTHROUGH_REPLY)) NDBG15(("mpi_pre_sata_passthrough(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_SATA_PASSTHROUGH_REPLY))); } static void mpi_pre_smp_passthrough(mptsas_t *mpt, mptsas_pt_request_t *pt) { #ifndef __lock_lint _NOTE(ARGUNUSED(mpt)) #endif pt->sgl_offset = offsetof(MPI2_SMP_PASSTHROUGH_REQUEST, SGL); ! if (pt->request_size != pt->sgl_offset) NDBG15(("mpi_pre_smp_passthrough(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! if (pt->data_size != sizeof (MPI2_SMP_PASSTHROUGH_REPLY)) NDBG15(("mpi_pre_smp_passthrough(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_SMP_PASSTHROUGH_REPLY))); } /* * Prepare pt for a CONFIG request. */ --- 11069,11109 ---- { #ifndef __lock_lint _NOTE(ARGUNUSED(mpt)) #endif pt->sgl_offset = offsetof(MPI2_SATA_PASSTHROUGH_REQUEST, SGL); ! if (pt->request_size != pt->sgl_offset) { NDBG15(("mpi_pre_sata_passthrough(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! } ! if (pt->data_size != sizeof (MPI2_SATA_PASSTHROUGH_REPLY)) { NDBG15(("mpi_pre_sata_passthrough(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_SATA_PASSTHROUGH_REPLY))); + } } static void mpi_pre_smp_passthrough(mptsas_t *mpt, mptsas_pt_request_t *pt) { #ifndef __lock_lint _NOTE(ARGUNUSED(mpt)) #endif pt->sgl_offset = offsetof(MPI2_SMP_PASSTHROUGH_REQUEST, SGL); ! if (pt->request_size != pt->sgl_offset) { NDBG15(("mpi_pre_smp_passthrough(): Incorrect req size, " "0x%x, should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! } ! if (pt->data_size != sizeof (MPI2_SMP_PASSTHROUGH_REPLY)) { NDBG15(("mpi_pre_smp_passthrough(): Incorrect rep size, " "0x%x, should be 0x%x", pt->data_size, (int)sizeof (MPI2_SMP_PASSTHROUGH_REPLY))); + } } /* * Prepare pt for a CONFIG request. */
*** 10893,10910 **** { #ifndef __lock_lint _NOTE(ARGUNUSED(mpt)) #endif pt->sgl_offset = offsetof(MPI2_CONFIG_REQUEST, PageBufferSGE); ! if (pt->request_size != pt->sgl_offset) NDBG15(("mpi_pre_config(): Incorrect req size, 0x%x, " "should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! if (pt->data_size != sizeof (MPI2_CONFIG_REPLY)) NDBG15(("mpi_pre_config(): Incorrect rep size, 0x%x, " "should be 0x%x", pt->data_size, (int)sizeof (MPI2_CONFIG_REPLY))); pt->simple = 1; } /* * Prepare pt for a SCSI_IO_REQ request. --- 11112,11131 ---- { #ifndef __lock_lint _NOTE(ARGUNUSED(mpt)) #endif pt->sgl_offset = offsetof(MPI2_CONFIG_REQUEST, PageBufferSGE); ! if (pt->request_size != pt->sgl_offset) { NDBG15(("mpi_pre_config(): Incorrect req size, 0x%x, " "should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! } ! if (pt->data_size != sizeof (MPI2_CONFIG_REPLY)) { NDBG15(("mpi_pre_config(): Incorrect rep size, 0x%x, " "should be 0x%x", pt->data_size, (int)sizeof (MPI2_CONFIG_REPLY))); + } pt->simple = 1; } /* * Prepare pt for a SCSI_IO_REQ request.
*** 10914,10932 **** { #ifndef __lock_lint _NOTE(ARGUNUSED(mpt)) #endif pt->sgl_offset = offsetof(MPI2_SCSI_IO_REQUEST, SGL); ! if (pt->request_size != pt->sgl_offset) NDBG15(("mpi_pre_config(): Incorrect req size, 0x%x, " "should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! if (pt->data_size != sizeof (MPI2_SCSI_IO_REPLY)) NDBG15(("mpi_pre_config(): Incorrect rep size, 0x%x, " "should be 0x%x", pt->data_size, (int)sizeof (MPI2_SCSI_IO_REPLY))); } /* * Prepare the mptsas_cmd for a SAS_IO_UNIT_CONTROL request. */ --- 11135,11155 ---- { #ifndef __lock_lint _NOTE(ARGUNUSED(mpt)) #endif pt->sgl_offset = offsetof(MPI2_SCSI_IO_REQUEST, SGL); ! if (pt->request_size != pt->sgl_offset) { NDBG15(("mpi_pre_config(): Incorrect req size, 0x%x, " "should be 0x%x, dataoutsz 0x%x", pt->request_size, pt->sgl_offset, pt->dataout_size)); ! } ! if (pt->data_size != sizeof (MPI2_SCSI_IO_REPLY)) { NDBG15(("mpi_pre_config(): Incorrect rep size, 0x%x, " "should be 0x%x", pt->data_size, (int)sizeof (MPI2_SCSI_IO_REPLY))); + } } /* * Prepare the mptsas_cmd for a SAS_IO_UNIT_CONTROL request. */
*** 11127,11136 **** --- 11350,11360 ---- pkt->pkt_cdbp = (opaque_t)&cmd->cmd_cdb[0]; pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb; pkt->pkt_ha_private = (opaque_t)&pt; pkt->pkt_flags = FLAG_HEAD; pkt->pkt_time = timeout; + pkt->pkt_start = gethrtime(); cmd->cmd_pkt = pkt; cmd->cmd_flags = CFLAG_CMDIOC | CFLAG_PASSTHRU; if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) || (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
*** 12579,12589 **** static int led_control(mptsas_t *mpt, intptr_t data, int mode) { int ret = 0; mptsas_led_control_t lc; ! mptsas_target_t *ptgt; if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) { return (EFAULT); } --- 12803,12814 ---- static int led_control(mptsas_t *mpt, intptr_t data, int mode) { int ret = 0; mptsas_led_control_t lc; ! mptsas_enclosure_t *mep; ! uint16_t slotidx; if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) { return (EFAULT); }
*** 12598,12630 **** if ((lc.Command == MPTSAS_LEDCTL_FLAG_SET && (mode & FWRITE) == 0) || (lc.Command == MPTSAS_LEDCTL_FLAG_GET && (mode & FREAD) == 0)) return (EACCES); ! /* Locate the target we're interrogating... */ mutex_enter(&mpt->m_mutex); ! ptgt = refhash_linear_search(mpt->m_targets, ! mptsas_target_eval_slot, &lc); ! if (ptgt == NULL) { ! /* We could not find a target for that enclosure/slot. */ mutex_exit(&mpt->m_mutex); return (ENOENT); } if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) { /* Update our internal LED state. */ ! ptgt->m_led_status &= ~(1 << (lc.Led - 1)); ! ptgt->m_led_status |= lc.LedStatus << (lc.Led - 1); /* Flush it to the controller. */ ! ret = mptsas_flush_led_status(mpt, ptgt); mutex_exit(&mpt->m_mutex); return (ret); } /* Return our internal LED state. */ ! lc.LedStatus = (ptgt->m_led_status >> (lc.Led - 1)) & 1; mutex_exit(&mpt->m_mutex); if (ddi_copyout(&lc, (void *)data, sizeof (lc), mode) != 0) { return (EFAULT); } --- 12823,12868 ---- if ((lc.Command == MPTSAS_LEDCTL_FLAG_SET && (mode & FWRITE) == 0) || (lc.Command == MPTSAS_LEDCTL_FLAG_GET && (mode & FREAD) == 0)) return (EACCES); ! /* Locate the required enclosure */ mutex_enter(&mpt->m_mutex); ! mep = mptsas_enc_lookup(mpt, lc.Enclosure); ! if (mep == NULL) { mutex_exit(&mpt->m_mutex); return (ENOENT); } + if (lc.Slot < mep->me_fslot) { + mutex_exit(&mpt->m_mutex); + return (ENOENT); + } + + /* + * Slots on the enclosure are maintained in array where me_fslot is + * entry zero. We normalize the requested slot. + */ + slotidx = lc.Slot - mep->me_fslot; + if (slotidx >= mep->me_nslots) { + mutex_exit(&mpt->m_mutex); + return (ENOENT); + } + if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) { /* Update our internal LED state. */ ! mep->me_slotleds[slotidx] &= ~(1 << (lc.Led - 1)); ! mep->me_slotleds[slotidx] |= lc.LedStatus << (lc.Led - 1); /* Flush it to the controller. */ ! ret = mptsas_flush_led_status(mpt, mep, slotidx); mutex_exit(&mpt->m_mutex); return (ret); } /* Return our internal LED state. */ ! lc.LedStatus = (mep->me_slotleds[slotidx] >> (lc.Led - 1)) & 1; mutex_exit(&mpt->m_mutex); if (ddi_copyout(&lc, (void *)data, sizeof (lc), mode) != 0) { return (EFAULT); }
*** 12762,12773 **** if (mpt->m_power_level != PM_LEVEL_D0) { mutex_exit(&mpt->m_mutex); if (pm_raise_power(mpt->m_dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) { mptsas_log(mpt, CE_WARN, ! "mptsas%d: mptsas_ioctl: Raise power " ! "request failed.", mpt->m_instance); (void) pm_idle_component(mpt->m_dip, 0); return (ENXIO); } } else { mutex_exit(&mpt->m_mutex); --- 13000,13010 ---- if (mpt->m_power_level != PM_LEVEL_D0) { mutex_exit(&mpt->m_mutex); if (pm_raise_power(mpt->m_dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) { mptsas_log(mpt, CE_WARN, ! "raise power request failed"); (void) pm_idle_component(mpt->m_dip, 0); return (ENXIO); } } else { mutex_exit(&mpt->m_mutex);
*** 12797,12821 **** NDBG14(("mptsas_ioctl led control: tgt %s not " "found", addr)); ndi_dc_freehdl(dcp); goto out; } - mutex_enter(&mpt->m_mutex); - if (cmd == DEVCTL_DEVICE_ONLINE) { - ptgt->m_tgt_unconfigured = 0; - } else if (cmd == DEVCTL_DEVICE_OFFLINE) { - ptgt->m_tgt_unconfigured = 1; - } - if (cmd == DEVCTL_DEVICE_OFFLINE) { - ptgt->m_led_status |= - (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1)); - } else { - ptgt->m_led_status &= - ~(1 << (MPTSAS_LEDCTL_LED_OK2RM - 1)); - } - (void) mptsas_flush_led_status(mpt, ptgt); - mutex_exit(&mpt->m_mutex); ndi_dc_freehdl(dcp); } goto out; } switch (cmd) { --- 13034,13043 ----
*** 12998,13013 **** * so that they can be retried. */ mpt->m_in_reset = TRUE; /* - * Wait until all the allocated sense data buffers for DMA are freed. - */ - while (mpt->m_extreq_sense_refcount > 0) - cv_wait(&mpt->m_extreq_sense_refcount_cv, &mpt->m_mutex); - - /* * Set all throttles to HOLD */ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL; ptgt = refhash_next(mpt->m_targets, ptgt)) { mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE); --- 13220,13229 ----
*** 13112,13149 **** if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) { mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed"); goto fail; } if (mptsas_alloc_active_slots(mpt, KM_SLEEP)) { goto fail; } /* ! * Allocate request message frames, reply free queue, reply descriptor ! * post queue, and reply message frames using latest IOC facts. */ if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) { ! mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames failed"); goto fail; } if (mptsas_alloc_sense_bufs(mpt) == DDI_FAILURE) { ! mptsas_log(mpt, CE_WARN, "mptsas_alloc_sense_bufs failed"); goto fail; } if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) { ! mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue failed!"); goto fail; } if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) { ! mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue failed!"); goto fail; } if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) { ! mptsas_log(mpt, CE_WARN, "mptsas_alloc_reply_frames failed!"); goto fail; } ! mur: /* * Re-Initialize ioc to operational state */ if (mptsas_ioc_init(mpt) == DDI_FAILURE) { --- 13328,13372 ---- if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) { mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed"); goto fail; } + if (first_time) { if (mptsas_alloc_active_slots(mpt, KM_SLEEP)) { goto fail; } /* ! * Allocate request message frames, reply free queue, reply ! * descriptor post queue, and reply message frames using ! * latest IOC facts. */ if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) { ! mptsas_log(mpt, CE_WARN, ! "mptsas_alloc_request_frames failed"); goto fail; } if (mptsas_alloc_sense_bufs(mpt) == DDI_FAILURE) { ! mptsas_log(mpt, CE_WARN, ! "mptsas_alloc_sense_bufs failed"); goto fail; } if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) { ! mptsas_log(mpt, CE_WARN, ! "mptsas_alloc_free_queue failed!"); goto fail; } if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) { ! mptsas_log(mpt, CE_WARN, ! "mptsas_alloc_post_queue failed!"); goto fail; } if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) { ! mptsas_log(mpt, CE_WARN, ! "mptsas_alloc_reply_frames failed!"); goto fail; } ! } mur: /* * Re-Initialize ioc to operational state */ if (mptsas_ioc_init(mpt) == DDI_FAILURE) {
*** 13283,13298 **** * Check that we haven't exceeded the maximum number of * capabilities and that the pointer is in a valid range. */ if (++cap_count > 48) { mptsas_log(mpt, CE_WARN, ! "too many device capabilities.\n"); break; } if (caps_ptr < 64) { mptsas_log(mpt, CE_WARN, ! "capabilities pointer 0x%x out of range.\n", caps_ptr); break; } /* --- 13506,13521 ---- * Check that we haven't exceeded the maximum number of * capabilities and that the pointer is in a valid range. */ if (++cap_count > 48) { mptsas_log(mpt, CE_WARN, ! "too many device capabilities"); break; } if (caps_ptr < 64) { mptsas_log(mpt, CE_WARN, ! "capabilities pointer 0x%x out of range", caps_ptr); break; } /*
*** 13301,13312 **** */ cap = pci_config_get8(mpt->m_config_handle, caps_ptr); switch (cap) { case PCI_CAP_ID_PM: mptsas_log(mpt, CE_NOTE, ! "?mptsas%d supports power management.\n", ! mpt->m_instance); mpt->m_options |= MPTSAS_OPT_PM; /* Save PMCSR offset */ mpt->m_pmcsr_offset = caps_ptr + PCI_PMCSR; break; --- 13524,13534 ---- */ cap = pci_config_get8(mpt->m_config_handle, caps_ptr); switch (cap) { case PCI_CAP_ID_PM: mptsas_log(mpt, CE_NOTE, ! "power management supported"); mpt->m_options |= MPTSAS_OPT_PM; /* Save PMCSR offset */ mpt->m_pmcsr_offset = caps_ptr + PCI_PMCSR; break;
*** 13320,13331 **** case PCI_CAP_ID_PCI_E: case PCI_CAP_ID_MSI_X: break; default: mptsas_log(mpt, CE_NOTE, ! "?mptsas%d unrecognized capability " ! "0x%x.\n", mpt->m_instance, cap); break; } /* * Get next capabilities pointer and clear bits 0,1. --- 13542,13552 ---- case PCI_CAP_ID_PCI_E: case PCI_CAP_ID_MSI_X: break; default: mptsas_log(mpt, CE_NOTE, ! "unrecognized capability 0x%x", cap); break; } /* * Get next capabilities pointer and clear bits 0,1.
*** 13359,13376 **** return (DDI_SUCCESS); /* * If power management is supported by this chip, create * pm-components property for the power management framework */ ! (void) sprintf(pmc_name, "NAME=mptsas%d", mpt->m_instance); pmc[0] = pmc_name; if (ddi_prop_update_string_array(DDI_DEV_T_NONE, mpt->m_dip, "pm-components", pmc, 3) != DDI_PROP_SUCCESS) { mpt->m_options &= ~MPTSAS_OPT_PM; mptsas_log(mpt, CE_WARN, ! "mptsas%d: pm-component property creation failed.", ! mpt->m_instance); return (DDI_FAILURE); } /* * Power on device. --- 13580,13596 ---- return (DDI_SUCCESS); /* * If power management is supported by this chip, create * pm-components property for the power management framework */ ! (void) sprintf(pmc_name, "NAME=mpt_sas%d", mpt->m_instance); pmc[0] = pmc_name; if (ddi_prop_update_string_array(DDI_DEV_T_NONE, mpt->m_dip, "pm-components", pmc, 3) != DDI_PROP_SUCCESS) { mpt->m_options &= ~MPTSAS_OPT_PM; mptsas_log(mpt, CE_WARN, ! "pm-component property creation failed"); return (DDI_FAILURE); } /* * Power on device.
*** 13377,13388 **** */ (void) pm_busy_component(mpt->m_dip, 0); pmcsr_stat = pci_config_get16(mpt->m_config_handle, mpt->m_pmcsr_offset); if ((pmcsr_stat & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_D0) { ! mptsas_log(mpt, CE_WARN, "mptsas%d: Power up the device", ! mpt->m_instance); pci_config_put16(mpt->m_config_handle, mpt->m_pmcsr_offset, PCI_PMCSR_D0); } if (pm_power_has_changed(mpt->m_dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) { mptsas_log(mpt, CE_WARN, "pm_power_has_changed failed"); --- 13597,13607 ---- */ (void) pm_busy_component(mpt->m_dip, 0); pmcsr_stat = pci_config_get16(mpt->m_config_handle, mpt->m_pmcsr_offset); if ((pmcsr_stat & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_D0) { ! mptsas_log(mpt, CE_WARN, "power up the device"); pci_config_put16(mpt->m_config_handle, mpt->m_pmcsr_offset, PCI_PMCSR_D0); } if (pm_power_has_changed(mpt->m_dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) { mptsas_log(mpt, CE_WARN, "pm_power_has_changed failed");
*** 13407,13417 **** dip = mpt->m_dip; /* Get supported interrupt types */ if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) { mptsas_log(mpt, CE_WARN, "ddi_intr_get_supported_types " ! "failed\n"); return (FALSE); } NDBG6(("ddi_intr_get_supported_types() returned: 0x%x", intr_types)); --- 13626,13636 ---- dip = mpt->m_dip; /* Get supported interrupt types */ if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) { mptsas_log(mpt, CE_WARN, "ddi_intr_get_supported_types " ! "failed"); return (FALSE); } NDBG6(("ddi_intr_get_supported_types() returned: 0x%x", intr_types));
*** 13461,13480 **** /* Get number of interrupts */ ret = ddi_intr_get_nintrs(dip, intr_type, &count); if ((ret != DDI_SUCCESS) || (count <= 0)) { mptsas_log(mpt, CE_WARN, "ddi_intr_get_nintrs() failed, " ! "ret %d count %d\n", ret, count); return (DDI_FAILURE); } /* Get number of available interrupts */ ret = ddi_intr_get_navail(dip, intr_type, &avail); if ((ret != DDI_SUCCESS) || (avail == 0)) { mptsas_log(mpt, CE_WARN, "ddi_intr_get_navail() failed, " ! "ret %d avail %d\n", ret, avail); return (DDI_FAILURE); } if (avail < count) { --- 13680,13699 ---- /* Get number of interrupts */ ret = ddi_intr_get_nintrs(dip, intr_type, &count); if ((ret != DDI_SUCCESS) || (count <= 0)) { mptsas_log(mpt, CE_WARN, "ddi_intr_get_nintrs() failed, " ! "ret %d count %d", ret, count); return (DDI_FAILURE); } /* Get number of available interrupts */ ret = ddi_intr_get_navail(dip, intr_type, &avail); if ((ret != DDI_SUCCESS) || (avail == 0)) { mptsas_log(mpt, CE_WARN, "ddi_intr_get_navail() failed, " ! "ret %d avail %d", ret, avail); return (DDI_FAILURE); } if (avail < count) {
*** 13496,13514 **** /* call ddi_intr_alloc() */ ret = ddi_intr_alloc(dip, mpt->m_htable, intr_type, 0, count, &actual, flag); if ((ret != DDI_SUCCESS) || (actual == 0)) { ! mptsas_log(mpt, CE_WARN, "ddi_intr_alloc() failed, ret %d\n", ret); kmem_free(mpt->m_htable, mpt->m_intr_size); return (DDI_FAILURE); } /* use interrupt count returned or abort? */ if (actual < count) { ! mptsas_log(mpt, CE_NOTE, "Requested: %d, Received: %d\n", count, actual); } mpt->m_intr_cnt = actual; --- 13715,13733 ---- /* call ddi_intr_alloc() */ ret = ddi_intr_alloc(dip, mpt->m_htable, intr_type, 0, count, &actual, flag); if ((ret != DDI_SUCCESS) || (actual == 0)) { ! mptsas_log(mpt, CE_WARN, "ddi_intr_alloc() failed, ret %d", ret); kmem_free(mpt->m_htable, mpt->m_intr_size); return (DDI_FAILURE); } /* use interrupt count returned or abort? */ if (actual < count) { ! mptsas_log(mpt, CE_NOTE, "Requested: %d, Received: %d", count, actual); } mpt->m_intr_cnt = actual;
*** 13515,13525 **** /* * Get priority for first msi, assume remaining are all the same */ if ((ret = ddi_intr_get_pri(mpt->m_htable[0], &mpt->m_intr_pri)) != DDI_SUCCESS) { ! mptsas_log(mpt, CE_WARN, "ddi_intr_get_pri() failed %d\n", ret); /* Free already allocated intr */ for (i = 0; i < actual; i++) { (void) ddi_intr_free(mpt->m_htable[i]); } --- 13734,13744 ---- /* * Get priority for first msi, assume remaining are all the same */ if ((ret = ddi_intr_get_pri(mpt->m_htable[0], &mpt->m_intr_pri)) != DDI_SUCCESS) { ! mptsas_log(mpt, CE_WARN, "ddi_intr_get_pri() failed %d", ret); /* Free already allocated intr */ for (i = 0; i < actual; i++) { (void) ddi_intr_free(mpt->m_htable[i]); }
*** 13529,13539 **** } /* Test for high level mutex */ if (mpt->m_intr_pri >= ddi_intr_get_hilevel_pri()) { mptsas_log(mpt, CE_WARN, "mptsas_add_intrs: " ! "Hi level interrupt not supported\n"); /* Free already allocated intr */ for (i = 0; i < actual; i++) { (void) ddi_intr_free(mpt->m_htable[i]); } --- 13748,13758 ---- } /* Test for high level mutex */ if (mpt->m_intr_pri >= ddi_intr_get_hilevel_pri()) { mptsas_log(mpt, CE_WARN, "mptsas_add_intrs: " ! "Hi level interrupt not supported"); /* Free already allocated intr */ for (i = 0; i < actual; i++) { (void) ddi_intr_free(mpt->m_htable[i]); }
*** 13545,13555 **** /* Call ddi_intr_add_handler() */ for (i = 0; i < actual; i++) { if ((ret = ddi_intr_add_handler(mpt->m_htable[i], mptsas_intr, (caddr_t)mpt, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) { mptsas_log(mpt, CE_WARN, "ddi_intr_add_handler() " ! "failed %d\n", ret); /* Free already allocated intr */ for (i = 0; i < actual; i++) { (void) ddi_intr_free(mpt->m_htable[i]); } --- 13764,13774 ---- /* Call ddi_intr_add_handler() */ for (i = 0; i < actual; i++) { if ((ret = ddi_intr_add_handler(mpt->m_htable[i], mptsas_intr, (caddr_t)mpt, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) { mptsas_log(mpt, CE_WARN, "ddi_intr_add_handler() " ! "failed %d", ret); /* Free already allocated intr */ for (i = 0; i < actual; i++) { (void) ddi_intr_free(mpt->m_htable[i]); }
*** 13559,13569 **** } } if ((ret = ddi_intr_get_cap(mpt->m_htable[0], &mpt->m_intr_cap)) != DDI_SUCCESS) { ! mptsas_log(mpt, CE_WARN, "ddi_intr_get_cap() failed %d\n", ret); /* Free already allocated intr */ for (i = 0; i < actual; i++) { (void) ddi_intr_free(mpt->m_htable[i]); } --- 13778,13788 ---- } } if ((ret = ddi_intr_get_cap(mpt->m_htable[0], &mpt->m_intr_cap)) != DDI_SUCCESS) { ! mptsas_log(mpt, CE_WARN, "ddi_intr_get_cap() failed %d", ret); /* Free already allocated intr */ for (i = 0; i < actual; i++) { (void) ddi_intr_free(mpt->m_htable[i]); }
*** 13860,13878 **** inq83_retry: rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83, inq83_len, NULL, 1); if (rval != DDI_SUCCESS) { ! mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page " "0x83 for target:%x, lun:%x failed!", target, lun); sata_guid = -1; goto out; } /* According to SAT2, the first descriptor is logic unit name */ dblk = &inq83[4]; if ((dblk[1] & 0x30) != 0) { ! mptsas_log(mpt, CE_WARN, "!Descriptor is not lun associated."); goto out; } pwwn = (uint64_t *)(void *)(&dblk[4]); if ((dblk[4] & 0xf0) == 0x50) { sata_guid = BE_64(*pwwn); --- 14079,14097 ---- inq83_retry: rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83, inq83_len, NULL, 1); if (rval != DDI_SUCCESS) { ! mptsas_log(mpt, CE_WARN, "mptsas request inquiry page " "0x83 for target:%x, lun:%x failed!", target, lun); sata_guid = -1; goto out; } /* According to SAT2, the first descriptor is logic unit name */ dblk = &inq83[4]; if ((dblk[1] & 0x30) != 0) { ! mptsas_log(mpt, CE_WARN, "Descriptor is not lun associated."); goto out; } pwwn = (uint64_t *)(void *)(&dblk[4]); if ((dblk[4] & 0xf0) == 0x50) { sata_guid = BE_64(*pwwn);
*** 13976,13985 **** --- 14195,14205 ---- if (pktp == NULL) { goto out; } bcopy(cdb, pktp->pkt_cdbp, cdblen); pktp->pkt_flags = FLAG_NOPARITY; + pktp->pkt_time = mptsas_scsi_pkt_time; if (scsi_poll(pktp) < 0) { goto out; } if (((struct scsi_status *)pktp->pkt_scbp)->sts_chk) { goto out;
*** 14186,14195 **** --- 14406,14418 ---- case BUS_CONFIG_DRIVER: case BUS_CONFIG_ALL: mptsas_config_all(pdip); ret = NDI_SUCCESS; break; + default: + ret = NDI_FAILURE; + break; } if ((ret == NDI_SUCCESS) && bconfig) { ret = ndi_busop_bus_config(pdip, mflags, op, (devnm == NULL) ? arg : devnm, childp, 0);
*** 14233,14242 **** --- 14456,14473 ---- mptsas_t *mpt = DIP2MPT(pdip); int phymask; mptsas_target_t *ptgt = NULL; /* + * The phymask exists if the port is active, otherwise + * nothing to do. + */ + if (ddi_prop_exists(DDI_DEV_T_ANY, pdip, + DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "phymask") == 0) + return (DDI_FAILURE); + + /* * Get the physical port associated to the iport */ phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0, "phymask", 0);
*** 14272,14283 **** return (DDI_FAILURE); } return (DDI_SUCCESS); } - if (phymask == 0) { /* * Configure IR volume */ rval = mptsas_config_raid(pdip, ptgt->m_devhdl, lundip); return (rval); } --- 14503,14517 ---- return (DDI_FAILURE); } return (DDI_SUCCESS); } /* + * If this is a RAID, configure the volumes + */ + if (mpt->m_num_raid_configs > 0) { + /* * Configure IR volume */ rval = mptsas_config_raid(pdip, ptgt->m_devhdl, lundip); return (rval); }
*** 14294,14303 **** --- 14528,14544 ---- mptsas_t *mpt = DIP2MPT(pdip); mptsas_phymask_t phymask; mptsas_target_t *ptgt = NULL; /* + * The phymask exists if the port is active, otherwise + * nothing to do. + */ + if (ddi_prop_exists(DDI_DEV_T_ANY, pdip, + DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "phymask") == 0) + return (DDI_FAILURE); + /* * Get the physical port associated to the iport */ phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0, "phymask", 0);
*** 14473,14487 **** if (mptsas_retrieve_lundata(lun_cnt, (uint8_t *)(buffer), &lun_num, &lun_addr_type) != DDI_SUCCESS) { continue; } saved_repluns[lun_cnt] = lun_num; ! if (cdip = mptsas_find_child_addr(pdip, sas_wwn, lun_num)) ret = DDI_SUCCESS; ! else ret = mptsas_probe_lun(pdip, lun_num, &cdip, ptgt); if ((ret == DDI_SUCCESS) && (cdip != NULL)) { (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, MPTSAS_DEV_GONE); } } --- 14714,14730 ---- if (mptsas_retrieve_lundata(lun_cnt, (uint8_t *)(buffer), &lun_num, &lun_addr_type) != DDI_SUCCESS) { continue; } saved_repluns[lun_cnt] = lun_num; ! if ((cdip = mptsas_find_child_addr(pdip, sas_wwn, lun_num)) != ! NULL) { ret = DDI_SUCCESS; ! } else { ret = mptsas_probe_lun(pdip, lun_num, &cdip, ptgt); + } if ((ret == DDI_SUCCESS) && (cdip != NULL)) { (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, MPTSAS_DEV_GONE); } }
*** 14608,14619 **** } if (find == 0) { /* * The lun has not been there already */ ! (void) mptsas_offline_lun(pdip, savechild, NULL, ! NDI_DEVI_REMOVE); } } pip = mdi_get_next_client_path(pdip, NULL); while (pip) { --- 14851,14861 ---- } if (find == 0) { /* * The lun has not been there already */ ! (void) mptsas_offline_lun(savechild, NULL); } } pip = mdi_get_next_client_path(pdip, NULL); while (pip) {
*** 14645,14656 **** if (find == 0) { /* * The lun has not been there already */ ! (void) mptsas_offline_lun(pdip, NULL, savepip, ! NDI_DEVI_REMOVE); } } } /* --- 14887,14897 ---- if (find == 0) { /* * The lun has not been there already */ ! (void) mptsas_offline_lun(NULL, savepip); } } } /*
*** 14663,14679 **** --- 14904,14965 ---- mptsas_enclosure_t *m; ASSERT(MUTEX_HELD(&mpt->m_mutex)); m = mptsas_enc_lookup(mpt, mep->me_enchdl); if (m != NULL) { + uint8_t *ledp; m->me_flags = mep->me_flags; + + + /* + * If the number of slots and the first slot entry in the + * enclosure has not changed, then we don't need to do anything + * here. Otherwise, we need to allocate a new array for the LED + * status of the slot. + */ + if (m->me_fslot == mep->me_fslot && + m->me_nslots == mep->me_nslots) return; + + /* + * If the number of slots or the first slot has changed, it's + * not clear that we're really in a place that we can continue + * to honor the existing flags. + */ + if (mep->me_nslots > 0) { + ledp = kmem_zalloc(sizeof (uint8_t) * mep->me_nslots, + KM_SLEEP); + } else { + ledp = NULL; } + if (m->me_slotleds != NULL) { + kmem_free(m->me_slotleds, sizeof (uint8_t) * + m->me_nslots); + } + m->me_slotleds = ledp; + m->me_fslot = mep->me_fslot; + m->me_nslots = mep->me_nslots; + return; + } + m = kmem_zalloc(sizeof (*m), KM_SLEEP); m->me_enchdl = mep->me_enchdl; m->me_flags = mep->me_flags; + m->me_nslots = mep->me_nslots; + m->me_fslot = mep->me_fslot; + if (m->me_nslots > 0) { + m->me_slotleds = kmem_zalloc(sizeof (uint8_t) * mep->me_nslots, + KM_SLEEP); + /* + * It may make sense to optionally flush all of the slots and/or + * read the slot status flag here to synchronize between + * ourselves and the card. So far, that hasn't been needed + * annecdotally when enumerating something new. If we do, we + * should kick that off in a taskq potentially. + */ + } list_insert_tail(&mpt->m_enclosures, m); } static void mptsas_update_hashtab(struct mptsas *mpt)
*** 14800,14818 **** mptsas_phymask_t phy_mask; mptsas_target_t *ptgt = NULL; mptsas_smp_t *psmp; /* ! * Get the phymask associated to the iport */ phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0, "phymask", 0); /* ! * Enumerate RAID volumes here (phymask == 0). */ ! if (phymask == 0) { mptsas_config_all_viport(pdip); return; } mutex_enter(&mpt->m_mutex); --- 15086,15109 ---- mptsas_phymask_t phy_mask; mptsas_target_t *ptgt = NULL; mptsas_smp_t *psmp; /* ! * The phymask exists if the port is active, otherwise ! * nothing to do. */ + if (ddi_prop_exists(DDI_DEV_T_ANY, pdip, + DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "phymask") == 0) + return; + phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0, "phymask", 0); /* ! * If this is a RAID, enumerate the volumes */ ! if (mpt->m_num_raid_configs > 0) { mptsas_config_all_viport(pdip); return; } mutex_enter(&mpt->m_mutex);
*** 14895,14906 **** if (strncmp(addr, name, s) != 0) { continue; } ! tmp_rval = mptsas_offline_lun(pdip, prechild, NULL, ! NDI_DEVI_REMOVE); if (tmp_rval != DDI_SUCCESS) { rval = DDI_FAILURE; if (ndi_prop_create_boolean(DDI_DEV_T_NONE, prechild, MPTSAS_DEV_GONE) != DDI_PROP_SUCCESS) { --- 15186,15196 ---- if (strncmp(addr, name, s) != 0) { continue; } ! tmp_rval = mptsas_offline_lun(prechild, NULL); if (tmp_rval != DDI_SUCCESS) { rval = DDI_FAILURE; if (ndi_prop_create_boolean(DDI_DEV_T_NONE, prechild, MPTSAS_DEV_GONE) != DDI_PROP_SUCCESS) {
*** 14928,14939 **** if (strncmp(addr, name, s) != 0) { continue; } ! (void) mptsas_offline_lun(pdip, NULL, savepip, ! NDI_DEVI_REMOVE); /* * driver will not invoke mdi_pi_free, so path will not * be freed forever, return DDI_FAILURE. */ rval = DDI_FAILURE; --- 15218,15228 ---- if (strncmp(addr, name, s) != 0) { continue; } ! (void) mptsas_offline_lun(NULL, savepip); /* * driver will not invoke mdi_pi_free, so path will not * be freed forever, return DDI_FAILURE. */ rval = DDI_FAILURE;
*** 14940,14991 **** } return (rval); } static int ! mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip, ! mdi_pathinfo_t *rpip, uint_t flags) { int rval = DDI_FAILURE; - char *devname; - dev_info_t *cdip, *parent; if (rpip != NULL) { - parent = scsi_vhci_dip; - cdip = mdi_pi_get_client(rpip); - } else if (rdip != NULL) { - parent = pdip; - cdip = rdip; - } else { - return (DDI_FAILURE); - } - - /* - * Make sure node is attached otherwise - * it won't have related cache nodes to - * clean up. i_ddi_devi_attached is - * similiar to i_ddi_node_state(cdip) >= - * DS_ATTACHED. - */ - if (i_ddi_devi_attached(cdip)) { - - /* Get full devname */ - devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP); - (void) ddi_deviname(cdip, devname); - /* Clean cache */ - (void) devfs_clean(parent, devname + 1, - DV_CLEAN_FORCE); - kmem_free(devname, MAXNAMELEN + 1); - } - if (rpip != NULL) { if (MDI_PI_IS_OFFLINE(rpip)) { rval = DDI_SUCCESS; } else { rval = mdi_pi_offline(rpip, 0); } ! } else { ! rval = ndi_devi_offline(cdip, flags); } return (rval); } --- 15229,15251 ---- } return (rval); } static int ! mptsas_offline_lun(dev_info_t *rdip, mdi_pathinfo_t *rpip) { int rval = DDI_FAILURE; if (rpip != NULL) { if (MDI_PI_IS_OFFLINE(rpip)) { rval = DDI_SUCCESS; } else { rval = mdi_pi_offline(rpip, 0); } ! } else if (rdip != NULL) { ! rval = ndi_devi_offline(rdip, ! NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE | NDI_DEVI_GONE); } return (rval); }
*** 15013,15056 **** } return (child); } static int ! mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, uint_t flags) { int rval = DDI_FAILURE; - char *devname; char wwn_str[MPTSAS_WWN_STRLEN]; dev_info_t *cdip; (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn); cdip = mptsas_find_smp_child(pdip, wwn_str); - if (cdip == NULL) return (DDI_SUCCESS); ! /* ! * Make sure node is attached otherwise ! * it won't have related cache nodes to ! * clean up. i_ddi_devi_attached is ! * similiar to i_ddi_node_state(cdip) >= ! * DS_ATTACHED. ! */ ! if (i_ddi_devi_attached(cdip)) { - /* Get full devname */ - devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP); - (void) ddi_deviname(cdip, devname); - /* Clean cache */ - (void) devfs_clean(pdip, devname + 1, - DV_CLEAN_FORCE); - kmem_free(devname, MAXNAMELEN + 1); - } - - rval = ndi_devi_offline(cdip, flags); - return (rval); } static dev_info_t * mptsas_find_child(dev_info_t *pdip, char *name) --- 15273,15296 ---- } return (child); } static int ! mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node) { int rval = DDI_FAILURE; char wwn_str[MPTSAS_WWN_STRLEN]; dev_info_t *cdip; (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn); cdip = mptsas_find_smp_child(pdip, wwn_str); if (cdip == NULL) return (DDI_SUCCESS); ! rval = ndi_devi_offline(cdip, NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE); return (rval); } static dev_info_t * mptsas_find_child(dev_info_t *pdip, char *name)
*** 15181,15191 **** for (i = 0; i < mptsas_inq83_retry_timeout; i++) { rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83, inq83_len1, &inq83_len, 1); if (rval != 0) { ! mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page " "0x83 for target:%x, lun:%x failed!", target, lun); if (mptsas_physical_bind_failed_page_83 != B_FALSE) goto create_lun; goto out; } --- 15421,15431 ---- for (i = 0; i < mptsas_inq83_retry_timeout; i++) { rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83, inq83_len1, &inq83_len, 1); if (rval != 0) { ! mptsas_log(mpt, CE_WARN, "mptsas request inquiry page " "0x83 for target:%x, lun:%x failed!", target, lun); if (mptsas_physical_bind_failed_page_83 != B_FALSE) goto create_lun; goto out; }
*** 15208,15218 **** */ if (guid && (strlen(guid) > MPTSAS_MAX_GUID_LEN)) { ddi_devid_free_guid(guid); guid = NULL; if (mpt->m_mpxio_enable == TRUE) { ! mptsas_log(mpt, CE_NOTE, "!Target:%x, " "lun:%x doesn't have a valid GUID, " "multipathing for this drive is " "not enabled", target, lun); } } --- 15448,15458 ---- */ if (guid && (strlen(guid) > MPTSAS_MAX_GUID_LEN)) { ddi_devid_free_guid(guid); guid = NULL; if (mpt->m_mpxio_enable == TRUE) { ! mptsas_log(mpt, CE_NOTE, "Target:%x, " "lun:%x doesn't have a valid GUID, " "multipathing for this drive is " "not enabled", target, lun); } }
*** 15230,15248 **** */ NDBG20(("Not well formed devid, retry...")); delay(1 * drv_usectohz(1000000)); continue; } else { ! mptsas_log(mpt, CE_WARN, "!Encode devid failed for " "path target:%x, lun:%x", target, lun); rval = DDI_FAILURE; goto create_lun; } } if (i == mptsas_inq83_retry_timeout) { ! mptsas_log(mpt, CE_WARN, "!Repeated page83 requests timeout " "for path target:%x, lun:%x", target, lun); } rval = DDI_FAILURE; --- 15470,15488 ---- */ NDBG20(("Not well formed devid, retry...")); delay(1 * drv_usectohz(1000000)); continue; } else { ! mptsas_log(mpt, CE_WARN, "Encode devid failed for " "path target:%x, lun:%x", target, lun); rval = DDI_FAILURE; goto create_lun; } } if (i == mptsas_inq83_retry_timeout) { ! mptsas_log(mpt, CE_WARN, "Repeated page83 requests timeout " "for path target:%x, lun:%x", target, lun); } rval = DDI_FAILURE;
*** 15326,15340 **** (void) ddi_prop_free(old_guid); if ((!MDI_PI_IS_ONLINE(*pip)) && (!MDI_PI_IS_STANDBY(*pip)) && (ptgt->m_tgt_unconfigured == 0)) { rval = mdi_pi_online(*pip, 0); - mutex_enter(&mpt->m_mutex); - ptgt->m_led_status = 0; - (void) mptsas_flush_led_status(mpt, - ptgt); - mutex_exit(&mpt->m_mutex); } else { rval = DDI_SUCCESS; } if (rval != DDI_SUCCESS) { mptsas_log(mpt, CE_WARN, "path:target: " --- 15566,15575 ----
*** 15364,15374 **** *pip = NULL; *lun_dip = NULL; return (DDI_FAILURE); } } ! if (mdi_pi_free(*pip, 0) != MDI_SUCCESS) { mptsas_log(mpt, CE_WARN, "path:target:" "%x, lun:%x free failed!", target, lun); *pip = NULL; *lun_dip = NULL; --- 15599,15610 ---- *pip = NULL; *lun_dip = NULL; return (DDI_FAILURE); } } ! if (mdi_pi_free(*pip, ! MDI_CLIENT_FLAGS_NO_EVENT) != MDI_SUCCESS) { mptsas_log(mpt, CE_WARN, "path:target:" "%x, lun:%x free failed!", target, lun); *pip = NULL; *lun_dip = NULL;
*** 15605,15626 **** mdi_rtn = MDI_FAILURE; goto virt_create_done; } NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr)); mdi_rtn = mdi_pi_online(*pip, 0); - if (mdi_rtn == MDI_SUCCESS) { - mutex_enter(&mpt->m_mutex); - ptgt->m_led_status = 0; - (void) mptsas_flush_led_status(mpt, ptgt); - mutex_exit(&mpt->m_mutex); - } if (mdi_rtn == MDI_NOT_SUPPORTED) { mdi_rtn = MDI_FAILURE; } virt_create_done: if (*pip && mdi_rtn != MDI_SUCCESS) { ! (void) mdi_pi_free(*pip, 0); *pip = NULL; *lun_dip = NULL; } } --- 15841,15856 ---- mdi_rtn = MDI_FAILURE; goto virt_create_done; } NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr)); mdi_rtn = mdi_pi_online(*pip, 0); if (mdi_rtn == MDI_NOT_SUPPORTED) { mdi_rtn = MDI_FAILURE; } virt_create_done: if (*pip && mdi_rtn != MDI_SUCCESS) { ! (void) mdi_pi_free(*pip, MDI_CLIENT_FLAGS_NO_EVENT); *pip = NULL; *lun_dip = NULL; } }
*** 15983,15998 **** /* * Try to online the new node */ ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH); } - if (ndi_rtn == NDI_SUCCESS) { - mutex_enter(&mpt->m_mutex); - ptgt->m_led_status = 0; - (void) mptsas_flush_led_status(mpt, ptgt); - mutex_exit(&mpt->m_mutex); - } /* * If success set rtn flag, else unwire alloc'd lun */ if (ndi_rtn != NDI_SUCCESS) { --- 16213,16222 ----
*** 16040,16052 **** mptsas_smp_t *psmp = NULL; int rval; int phymask; /* ! * Get the physical port associated to the iport ! * PHYMASK TODO */ phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0, "phymask", 0); /* * Find the smp node in hash table with specified sas address and * physical port --- 16264,16280 ---- mptsas_smp_t *psmp = NULL; int rval; int phymask; /* ! * The phymask exists if the port is active, otherwise ! * nothing to do. */ + if (ddi_prop_exists(DDI_DEV_T_ANY, pdip, + DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "phymask") == 0) + return (DDI_FAILURE); + phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0, "phymask", 0); /* * Find the smp node in hash table with specified sas address and * physical port
*** 16675,16689 **** --- 16903,16930 ---- static dev_info_t * mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask) { dev_info_t *dip; int prop; + dip = e_ddi_hold_devi_by_dev(dev, 0); if (dip == NULL) return (dip); + + /* + * The phymask exists if the port is active, otherwise + * nothing to do. + */ + if (ddi_prop_exists(DDI_DEV_T_ANY, dip, + DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "phymask") == 0) { + ddi_release_devi(dip); + return ((dev_info_t *)NULL); + } + prop = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, "phymask", 0); + *phymask = (mptsas_phymask_t)prop; ddi_release_devi(dip); return (dip); } static mptsas_target_t *
*** 16704,16788 **** } return (ptgt); } static int ! mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt) { uint32_t slotstatus = 0; /* Build an MPI2 Slot Status based on our view of the world */ ! if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_IDENT - 1))) slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST; ! if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_FAIL - 1))) slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT; ! if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1))) slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE; /* Write it to the controller */ NDBG14(("mptsas_ioctl: set LED status %x for slot %x", ! slotstatus, ptgt->m_slot_num)); ! return (mptsas_send_sep(mpt, ptgt, &slotstatus, MPI2_SEP_REQ_ACTION_WRITE_STATUS)); } /* * send sep request, use enclosure/slot addressing */ static int ! mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt, uint32_t *status, uint8_t act) { Mpi2SepRequest_t req; Mpi2SepReply_t rep; int ret; - mptsas_enclosure_t *mep; uint16_t enctype; ASSERT(mutex_owned(&mpt->m_mutex)); /* - * We only support SEP control of directly-attached targets, in which - * case the "SEP" we're talking to is a virtual one contained within - * the HBA itself. This is necessary because DA targets typically have - * no other mechanism for LED control. Targets for which a separate - * enclosure service processor exists should be controlled via ses(7d) - * or sgen(7d). Furthermore, since such requests can time out, they - * should be made in user context rather than in response to - * asynchronous fabric changes. - * - * In addition, we do not support this operation for RAID volumes, - * since there is no slot associated with them. - */ - if (!(ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED) || - ptgt->m_addr.mta_phymask == 0) { - return (ENOTTY); - } - - /* * Look through the enclosures and make sure that this enclosure is * something that is directly attached device. If we didn't find an * enclosure for this device, don't send the ioctl. */ - mep = mptsas_enc_lookup(mpt, ptgt->m_enclosure); - if (mep == NULL) - return (ENOTTY); enctype = mep->me_flags & MPI2_SAS_ENCLS0_FLAGS_MNG_MASK; if (enctype != MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES && enctype != MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO && enctype != MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO) { return (ENOTTY); } bzero(&req, sizeof (req)); bzero(&rep, sizeof (rep)); req.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; req.Action = act; req.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS; ! req.EnclosureHandle = LE_16(ptgt->m_enclosure); ! req.Slot = LE_16(ptgt->m_slot_num); if (act == MPI2_SEP_REQ_ACTION_WRITE_STATUS) { req.SlotStatus = LE_32(*status); } ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL, sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL); --- 16945,17011 ---- } return (ptgt); } static int ! mptsas_flush_led_status(mptsas_t *mpt, mptsas_enclosure_t *mep, uint16_t idx) { uint32_t slotstatus = 0; + ASSERT3U(idx, <, mep->me_nslots); + /* Build an MPI2 Slot Status based on our view of the world */ ! if (mep->me_slotleds[idx] & (1 << (MPTSAS_LEDCTL_LED_IDENT - 1))) slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST; ! if (mep->me_slotleds[idx] & (1 << (MPTSAS_LEDCTL_LED_FAIL - 1))) slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT; ! if (mep->me_slotleds[idx] & (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1))) slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE; /* Write it to the controller */ NDBG14(("mptsas_ioctl: set LED status %x for slot %x", ! slotstatus, idx + mep->me_fslot)); ! return (mptsas_send_sep(mpt, mep, idx, &slotstatus, MPI2_SEP_REQ_ACTION_WRITE_STATUS)); } /* * send sep request, use enclosure/slot addressing */ static int ! mptsas_send_sep(mptsas_t *mpt, mptsas_enclosure_t *mep, uint16_t idx, uint32_t *status, uint8_t act) { Mpi2SepRequest_t req; Mpi2SepReply_t rep; int ret; uint16_t enctype; + uint16_t slot; ASSERT(mutex_owned(&mpt->m_mutex)); /* * Look through the enclosures and make sure that this enclosure is * something that is directly attached device. If we didn't find an * enclosure for this device, don't send the ioctl. */ enctype = mep->me_flags & MPI2_SAS_ENCLS0_FLAGS_MNG_MASK; if (enctype != MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES && enctype != MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO && enctype != MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO) { return (ENOTTY); } + slot = idx + mep->me_fslot; bzero(&req, sizeof (req)); bzero(&rep, sizeof (rep)); req.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; req.Action = act; req.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS; ! req.EnclosureHandle = LE_16(mep->me_enchdl); ! req.Slot = LE_16(slot); if (act == MPI2_SEP_REQ_ACTION_WRITE_STATUS) { req.SlotStatus = LE_32(*status); } ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL, sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);