diff options
3 files changed, 132 insertions, 72 deletions
diff --git a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c index f094c9a510..9a74c36c28 100644 --- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c +++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2014, Joyent, Inc. All rights reserved. * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved. * Copyright (c) 2014, Tegile Systems Inc. All rights reserved. @@ -410,7 +410,7 @@ static void mptsas_record_event(void *args); static int mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data, int mode); -mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t, uint64_t, +mptsas_target_t *mptsas_tgt_alloc(refhash_t *, uint16_t, uint64_t, uint32_t, mptsas_phymask_t, uint8_t); static mptsas_smp_t *mptsas_smp_alloc(mptsas_t *, mptsas_smp_t *); static int mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, @@ -782,6 +782,23 @@ mptsas_target_addr_cmp(const void *a, const void *b) return ((int)bap->mta_phymask - (int)aap->mta_phymask); } +static uint64_t +mptsas_tmp_target_hash(const void *tp) +{ + return ((uint64_t)(uintptr_t)tp); +} + +static int +mptsas_tmp_target_cmp(const void *a, const void *b) +{ + if (a > b) + return (1); + if (b < a) + return (-1); + + return (0); +} + static void mptsas_target_free(void *op) { @@ -808,6 +825,7 @@ mptsas_destroy_hashes(mptsas_t *mpt) sp = refhash_next(mpt->m_smp_targets, sp)) { refhash_remove(mpt->m_smp_targets, sp); } + refhash_destroy(mpt->m_tmp_targets); refhash_destroy(mpt->m_targets); refhash_destroy(mpt->m_smp_targets); mpt->m_targets = NULL; @@ -1365,6 +1383,16 @@ mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) offsetof(mptsas_target_t, m_addr), KM_SLEEP); /* + * The refhash for temporary targets uses the address of the target + * struct itself as tag, so the tag offset is 0. See the implementation + * of mptsas_tmp_target_hash() and mptsas_tmp_target_cmp(). + */ + mpt->m_tmp_targets = refhash_create(MPTSAS_TMP_TARGET_BUCKET_COUNT, + mptsas_tmp_target_hash, mptsas_tmp_target_cmp, + mptsas_target_free, sizeof (mptsas_target_t), + offsetof(mptsas_target_t, m_link), 0, KM_SLEEP); + + /* * Fill in the phy_info structure and get the base WWID */ if (mptsas_get_manufacture_page5(mpt) == DDI_FAILURE) { @@ -1550,6 +1578,8 @@ fail: mptsas_hba_teardown(mpt); } + if (mpt->m_tmp_targets) + refhash_destroy(mpt->m_tmp_targets); if (mpt->m_targets) refhash_destroy(mpt->m_targets); if (mpt->m_smp_targets) @@ -6375,10 +6405,15 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node, 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 than there is nothing - * else to do, just leave. + * If rval is DEV_INFO_PHYS_DISK or indicates failure + * then there is nothing else to do, just leave. */ if (rval != DEV_INFO_SUCCESS) { return; @@ -9876,6 +9911,61 @@ mptsas_watch(void *arg) } static void +mptsas_watchsubr_tgt(mptsas_t *mpt, mptsas_target_t *ptgt, hrtime_t timestamp) +{ + mptsas_cmd_t *cmd; + + /* + * If we were draining due to a qfull condition, + * go back to full throttle. + */ + if ((ptgt->m_t_throttle < MAX_THROTTLE) && + (ptgt->m_t_throttle > HOLD_THROTTLE) && + (ptgt->m_t_ncmds < ptgt->m_t_throttle)) { + mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE); + mptsas_restart_hba(mpt); + } + + cmd = TAILQ_LAST(&ptgt->m_active_cmdq, mptsas_active_cmdq); + if (cmd == NULL) + return; + + if (cmd->cmd_active_expiration <= timestamp) { + /* + * Earliest command timeout expired. Drain throttle. + */ + mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE); + + /* + * Check for remaining commands. + */ + cmd = TAILQ_FIRST(&ptgt->m_active_cmdq); + if (cmd->cmd_active_expiration > timestamp) { + /* + * Wait for remaining commands to complete or + * time out. + */ + NDBG23(("command timed out, pending drain")); + return; + } + + /* + * All command timeouts expired. + */ + mptsas_log(mpt, CE_NOTE, "Timeout of %d seconds " + "expired with %d commands on target %d lun %d.", + cmd->cmd_pkt->pkt_time, ptgt->m_t_ncmds, + ptgt->m_devhdl, Lun(cmd)); + + mptsas_cmd_timeout(mpt, ptgt); + } else if (cmd->cmd_active_expiration <= + timestamp + (hrtime_t)mptsas_scsi_watchdog_tick * NANOSEC) { + NDBG23(("pending timeout")); + mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE); + } +} + +static void mptsas_watchsubr(mptsas_t *mpt) { int i; @@ -9926,54 +10016,12 @@ mptsas_watchsubr(mptsas_t *mpt) for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL; ptgt = refhash_next(mpt->m_targets, ptgt)) { - /* - * If we were draining due to a qfull condition, - * go back to full throttle. - */ - if ((ptgt->m_t_throttle < MAX_THROTTLE) && - (ptgt->m_t_throttle > HOLD_THROTTLE) && - (ptgt->m_t_ncmds < ptgt->m_t_throttle)) { - mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE); - mptsas_restart_hba(mpt); - } - - cmd = TAILQ_LAST(&ptgt->m_active_cmdq, mptsas_active_cmdq); - if (cmd == NULL) - continue; - - if (cmd->cmd_active_expiration <= timestamp) { - /* - * Earliest command timeout expired. Drain throttle. - */ - mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE); - - /* - * Check for remaining commands. - */ - cmd = TAILQ_FIRST(&ptgt->m_active_cmdq); - if (cmd->cmd_active_expiration > timestamp) { - /* - * Wait for remaining commands to complete or - * time out. - */ - NDBG23(("command timed out, pending drain")); - continue; - } - - /* - * All command timeouts expired. - */ - mptsas_log(mpt, CE_NOTE, "Timeout of %d seconds " - "expired with %d commands on target %d lun %d.", - cmd->cmd_pkt->pkt_time, ptgt->m_t_ncmds, - ptgt->m_devhdl, Lun(cmd)); + mptsas_watchsubr_tgt(mpt, ptgt, timestamp); + } - mptsas_cmd_timeout(mpt, ptgt); - } else if (cmd->cmd_active_expiration <= - timestamp + (hrtime_t)mptsas_scsi_watchdog_tick * NANOSEC) { - NDBG23(("pending timeout")); - mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE); - } + for (ptgt = refhash_first(mpt->m_tmp_targets); ptgt != NULL; + ptgt = refhash_next(mpt->m_tmp_targets, ptgt)) { + mptsas_watchsubr_tgt(mpt, ptgt, timestamp); } } @@ -13555,28 +13603,32 @@ mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address, */ if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE | MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) { + /* alloc a temporary target to send the cmd to */ + tmp_tgt = mptsas_tgt_alloc(mpt->m_tmp_targets, *dev_handle, + 0, dev_info, 0, 0); mutex_exit(&mpt->m_mutex); - /* alloc a tmp_tgt to send the cmd */ - tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target), - KM_SLEEP); - tmp_tgt->m_devhdl = *dev_handle; - tmp_tgt->m_deviceinfo = dev_info; - tmp_tgt->m_qfull_retries = QFULL_RETRIES; - tmp_tgt->m_qfull_retry_interval = - drv_usectohz(QFULL_RETRY_INTERVAL * 1000); - tmp_tgt->m_t_throttle = MAX_THROTTLE; + devicename = mptsas_get_sata_guid(mpt, tmp_tgt, 0); - kmem_free(tmp_tgt, sizeof (struct mptsas_target)); - mutex_enter(&mpt->m_mutex); + + if (devicename == -1) { + mutex_enter(&mpt->m_mutex); + refhash_remove(mpt->m_tmp_targets, tmp_tgt); + rval = DEV_INFO_FAIL_GUID; + return (rval); + } + if (devicename != 0 && (((devicename >> 56) & 0xf0) == 0x50)) { sas_wwn = devicename; } else if (dev_info & MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH) { sas_wwn = 0; } + + mutex_enter(&mpt->m_mutex); + refhash_remove(mpt->m_tmp_targets, tmp_tgt); } phymask = mptsas_physport_to_phymask(mpt, physport); - *pptgt = mptsas_tgt_alloc(mpt, *dev_handle, sas_wwn, + *pptgt = mptsas_tgt_alloc(mpt->m_targets, *dev_handle, sas_wwn, dev_info, phymask, phynum); if (*pptgt == NULL) { mptsas_log(mpt, CE_WARN, "Failed to allocated target" @@ -13609,6 +13661,7 @@ inq83_retry: 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 */ @@ -14442,7 +14495,8 @@ mptsas_update_hashtab(struct mptsas *mpt) rval = mptsas_get_target_device_info(mpt, page_address, &dev_handle, &ptgt); if ((rval == DEV_INFO_FAIL_PAGE0) || - (rval == DEV_INFO_FAIL_ALLOC)) { + (rval == DEV_INFO_FAIL_ALLOC) || + (rval == DEV_INFO_FAIL_GUID)) { break; } @@ -16119,7 +16173,8 @@ mptsas_phy_to_tgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint8_t phy) rval = mptsas_get_target_device_info(mpt, page_address, &cur_handle, &ptgt); if ((rval == DEV_INFO_FAIL_PAGE0) || - (rval == DEV_INFO_FAIL_ALLOC)) { + (rval == DEV_INFO_FAIL_ALLOC) || + (rval == DEV_INFO_FAIL_GUID)) { break; } if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) || @@ -16188,7 +16243,8 @@ mptsas_wwid_to_ptgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid) rval = mptsas_get_target_device_info(mpt, page_address, &cur_handle, &tmp_tgt); if ((rval == DEV_INFO_FAIL_PAGE0) || - (rval == DEV_INFO_FAIL_ALLOC)) { + (rval == DEV_INFO_FAIL_ALLOC) || + (rval == DEV_INFO_FAIL_GUID)) { tmp_tgt = NULL; break; } @@ -16256,7 +16312,7 @@ mptsas_wwid_to_psmp(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid) } mptsas_target_t * -mptsas_tgt_alloc(mptsas_t *mpt, uint16_t devhdl, uint64_t wwid, +mptsas_tgt_alloc(refhash_t *refhash, uint16_t devhdl, uint64_t wwid, uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum) { mptsas_target_t *tmp_tgt = NULL; @@ -16264,7 +16320,7 @@ mptsas_tgt_alloc(mptsas_t *mpt, uint16_t devhdl, uint64_t wwid, addr.mta_wwn = wwid; addr.mta_phymask = phymask; - tmp_tgt = refhash_lookup(mpt->m_targets, &addr); + tmp_tgt = refhash_lookup(refhash, &addr); if (tmp_tgt != NULL) { NDBG20(("Hash item already exist")); tmp_tgt->m_deviceinfo = devinfo; @@ -16288,7 +16344,7 @@ mptsas_tgt_alloc(mptsas_t *mpt, uint16_t devhdl, uint64_t wwid, tmp_tgt->m_t_throttle = MAX_THROTTLE; TAILQ_INIT(&tmp_tgt->m_active_cmdq); - refhash_insert(mpt->m_targets, tmp_tgt); + refhash_insert(refhash, tmp_tgt); return (tmp_tgt); } diff --git a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_raid.c b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_raid.c index 371db950e5..728730a176 100644 --- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_raid.c +++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_raid.c @@ -23,6 +23,7 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright (c) 2014, Tegile Systems Inc. All rights reserved. + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ /* @@ -92,7 +93,7 @@ static int mptsas_get_raid_wwid(mptsas_t *mpt, mptsas_raidvol_t *raidvol); extern int mptsas_check_dma_handle(ddi_dma_handle_t handle); extern int mptsas_check_acc_handle(ddi_acc_handle_t handle); -extern mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t, +extern mptsas_target_t *mptsas_tgt_alloc(refhash_t *, uint16_t, uint64_t, uint32_t, mptsas_phymask_t, uint8_t); static int @@ -216,7 +217,7 @@ mptsas_raidconf_page_0_cb(mptsas_t *mpt, caddr_t page_memp, /* * RAID uses phymask of 0. */ - ptgt = mptsas_tgt_alloc(mpt, + ptgt = mptsas_tgt_alloc(mpt->m_targets, voldevhandle, raidwwn, 0, 0, 0); raidconfig->m_raidvol[vol].m_raidtgt = diff --git a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h index 836548aa30..3983188fce 100644 --- a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h +++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h @@ -21,7 +21,7 @@ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2013, Joyent, Inc. All rights reserved. * Copyright (c) 2014, Tegile Systems Inc. All rights reserved. */ @@ -100,6 +100,7 @@ typedef uint16_t mptsas_phymask_t; */ #define MPTSAS_SMP_BUCKET_COUNT 23 #define MPTSAS_TARGET_BUCKET_COUNT 97 +#define MPTSAS_TMP_TARGET_BUCKET_COUNT 13 /* * MPT HW defines @@ -557,6 +558,7 @@ _NOTE(DATA_READABLE_WITHOUT_LOCK(mptsas_topo_change_list_t::flags)) #define DEV_INFO_WRONG_DEVICE_TYPE 0x2 #define DEV_INFO_PHYS_DISK 0x3 #define DEV_INFO_FAIL_ALLOC 0x4 +#define DEV_INFO_FAIL_GUID 0x5 /* * mpt hotplug event defines @@ -699,6 +701,7 @@ typedef struct mptsas { refhash_t *m_targets; refhash_t *m_smp_targets; + refhash_t *m_tmp_targets; m_raidconfig_t m_raidconfig[MPTSAS_MAX_RAIDCONFIGS]; uint8_t m_num_raid_configs; |