Print this page
4682 panic in mptsas refhash
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Approved by: Albert Lee <trisk@nexenta.com>
4500 mptsas_hash_traverse() is unsafe, leads to missing devices
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
Approved by: Albert Lee <trisk@nexenta.com>
@@ -20,11 +20,11 @@
*/
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
* Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
*/
/*
* Copyright (c) 2000 to 2010, LSI Corporation.
@@ -95,10 +95,11 @@
*/
#include <sys/scsi/impl/scsi_reset_notify.h>
#include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
#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 */
/*
@@ -334,16 +335,16 @@
static int mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy,
int *lun);
static int mptsas_parse_smp_name(char *name, uint64_t *wwn);
-static mptsas_target_t *mptsas_phy_to_tgt(mptsas_t *mpt, int phymask,
- uint8_t phy);
-static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt, int phymask,
- uint64_t wwid);
-static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt, int phymask,
- uint64_t wwid);
+static mptsas_target_t *mptsas_phy_to_tgt(mptsas_t *mpt,
+ mptsas_phymask_t phymask, uint8_t phy);
+static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt,
+ mptsas_phymask_t phymask, uint64_t wwid);
+static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt,
+ mptsas_phymask_t phymask, uint64_t wwid);
static int mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun,
uchar_t page, unsigned char *buf, int len, int *rlen, uchar_t evpd);
static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
@@ -405,27 +406,13 @@
int mode, int *rval);
static void mptsas_record_event(void *args);
static int mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data,
int mode);
-static void mptsas_hash_init(mptsas_hash_table_t *hashtab);
-static void mptsas_hash_uninit(mptsas_hash_table_t *hashtab, size_t datalen);
-static void mptsas_hash_add(mptsas_hash_table_t *hashtab, void *data);
-static void * mptsas_hash_rem(mptsas_hash_table_t *hashtab, uint64_t key1,
- mptsas_phymask_t key2);
-static void * mptsas_hash_search(mptsas_hash_table_t *hashtab, uint64_t key1,
- mptsas_phymask_t key2);
-static void * mptsas_hash_traverse(mptsas_hash_table_t *hashtab, int pos);
-
-mptsas_target_t *mptsas_tgt_alloc(mptsas_hash_table_t *, uint16_t, uint64_t,
+mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t, uint64_t,
uint32_t, mptsas_phymask_t, uint8_t);
-static mptsas_smp_t *mptsas_smp_alloc(mptsas_hash_table_t *hashtab,
- mptsas_smp_t *data);
-static void mptsas_smp_free(mptsas_hash_table_t *hashtab, uint64_t wwid,
- mptsas_phymask_t phymask);
-static void mptsas_tgt_free(mptsas_hash_table_t *, uint64_t, mptsas_phymask_t);
-static void * mptsas_search_by_devhdl(mptsas_hash_table_t *, uint16_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,
dev_info_t **smp_dip);
/*
* Power management functions
@@ -693,12 +680,107 @@
NDBG0(("mptsas _info"));
return (mod_info(&modlinkage, modinfop));
}
+static int
+mptsas_target_eval_devhdl(const void *op, void *arg)
+{
+ uint16_t dh = *(uint16_t *)arg;
+ const mptsas_target_t *tp = op;
+ 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;
+
+ if (tp->m_addr.mta_wwn != 0)
+ return (-1);
+
+ return ((int)tp->m_phynum - (int)phy);
+}
+
+static int
+mptsas_smp_eval_devhdl(const void *op, void *arg)
+{
+ uint16_t dh = *(uint16_t *)arg;
+ const mptsas_smp_t *sp = op;
+
+ return ((int)sp->m_devhdl - (int)dh);
+}
+
+static uint64_t
+mptsas_target_addr_hash(const void *tp)
+{
+ const mptsas_target_addr_t *tap = tp;
+
+ return ((tap->mta_wwn & 0xffffffffffffULL) |
+ ((uint64_t)tap->mta_phymask << 48));
+}
+
+static int
+mptsas_target_addr_cmp(const void *a, const void *b)
+{
+ const mptsas_target_addr_t *aap = a;
+ const mptsas_target_addr_t *bap = b;
+
+ if (aap->mta_wwn < bap->mta_wwn)
+ return (-1);
+ if (aap->mta_wwn > bap->mta_wwn)
+ return (1);
+ return ((int)bap->mta_phymask - (int)aap->mta_phymask);
+}
+
+static void
+mptsas_target_free(void *op)
+{
+ kmem_free(op, sizeof (mptsas_target_t));
+}
+
+static void
+mptsas_smp_free(void *op)
+{
+ kmem_free(op, sizeof (mptsas_smp_t));
+}
+
+static void
+mptsas_destroy_hashes(mptsas_t *mpt)
+{
+ mptsas_target_t *tp;
+ mptsas_smp_t *sp;
+
+ for (tp = refhash_first(mpt->m_targets); tp != NULL;
+ tp = refhash_next(mpt->m_targets, tp)) {
+ refhash_remove(mpt->m_targets, tp);
+ }
+ for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
+ sp = refhash_next(mpt->m_smp_targets, sp)) {
+ refhash_remove(mpt->m_smp_targets, sp);
+ }
+ refhash_destroy(mpt->m_targets);
+ refhash_destroy(mpt->m_smp_targets);
+ mpt->m_targets = NULL;
+ mpt->m_smp_targets = NULL;
+}
+
+static int
mptsas_iport_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
dev_info_t *pdip;
mptsas_t *mpt;
scsi_hba_tran_t *hba_tran;
@@ -1402,15 +1484,16 @@
}
if (hba_attach_setup) {
mptsas_hba_teardown(mpt);
}
+ if (mpt->m_targets)
+ refhash_destroy(mpt->m_targets);
+ if (mpt->m_smp_targets)
+ refhash_destroy(mpt->m_smp_targets);
+
if (mpt->m_active) {
- mptsas_hash_uninit(&mpt->m_active->m_smptbl,
- sizeof (mptsas_smp_t));
- mptsas_hash_uninit(&mpt->m_active->m_tgttbl,
- sizeof (mptsas_target_t));
mptsas_free_active_slots(mpt);
}
if (intr_added) {
mptsas_unregister_intrs(mpt);
}
@@ -1839,16 +1922,16 @@
/*
* Delete Phy stats
*/
mptsas_destroy_phy_stats(mpt);
+ mptsas_destroy_hashes(mpt);
+
/*
* Delete nt_active.
*/
mutex_enter(&mpt->m_mutex);
- mptsas_hash_uninit(&mpt->m_active->m_tgttbl, sizeof (mptsas_target_t));
- mptsas_hash_uninit(&mpt->m_active->m_smptbl, sizeof (mptsas_smp_t));
mptsas_free_active_slots(mpt);
mutex_exit(&mpt->m_mutex);
/* deallocate everything that was allocated in mptsas_attach */
mptsas_cache_destroy(mpt);
@@ -2105,11 +2188,15 @@
return (FALSE);
}
/*
* Initialize smp hash table
*/
- mptsas_hash_init(&mpt->m_active->m_smptbl);
+ mpt->m_smp_targets = refhash_create(MPTSAS_SMP_BUCKET_COUNT,
+ mptsas_target_addr_hash, mptsas_target_addr_cmp,
+ mptsas_smp_free, sizeof (mptsas_smp_t),
+ offsetof(mptsas_smp_t, m_link), offsetof(mptsas_smp_t, m_addr),
+ KM_SLEEP);
mpt->m_smp_devhdl = 0xFFFF;
return (TRUE);
}
@@ -2748,12 +2835,13 @@
int lun = sd->sd_address.a_lun;
mdi_pathinfo_t *pip = NULL;
mptsas_tgt_private_t *tgt_private = NULL;
mptsas_target_t *ptgt = NULL;
char *psas_wwn = NULL;
- int phymask = 0;
+ mptsas_phymask_t phymask = 0;
uint64_t sas_wwn = 0;
+ mptsas_target_addr_t addr;
mpt = SDEV2MPT(sd);
ASSERT(scsi_hba_iport_unit_address(hba_dip) != 0);
NDBG0(("mptsas_scsi_tgt_init: hbadip=0x%p tgtdip=0x%p lun=%d",
@@ -2765,11 +2853,11 @@
return (DDI_FAILURE);
}
/*
* phymask is 0 means the virtual port for RAID
*/
- phymask = ddi_prop_get_int(DDI_DEV_T_ANY, hba_dip, 0,
+ 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
@@ -2803,13 +2891,16 @@
ddi_prop_free(psas_wwn);
} else {
sas_wwn = 0;
}
}
+
ASSERT((sas_wwn != 0) || (phymask != 0));
+ addr.mta_wwn = sas_wwn;
+ addr.mta_phymask = phymask;
mutex_enter(&mpt->m_mutex);
- ptgt = mptsas_hash_search(&mpt->m_active->m_tgttbl, sas_wwn, phymask);
+ 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);
@@ -3236,41 +3327,44 @@
}
int
mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
{
- mptsas_slots_t *slots;
- int slot;
+ mptsas_slots_t *slots = mpt->m_active;
+ uint_t slot, start_rotor;
mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
- ASSERT(mutex_owned(&mpt->m_mutex));
- slots = mpt->m_active;
+ ASSERT(MUTEX_HELD(&mpt->m_mutex));
/*
* Account for reserved TM request slot and reserved SMID of 0.
*/
- ASSERT(slots->m_n_slots == (mpt->m_max_requests - 2));
+ ASSERT(slots->m_n_normal == (mpt->m_max_requests - 2));
/*
- * m_tags is equivalent to the SMID when sending requests. Since the
- * SMID cannot be 0, start out at one if rolling over past the size
- * of the request queue depth. Also, don't use the last SMID, which is
- * reserved for TM requests.
+ * Find the next available slot, beginning at m_rotor. If no slot is
+ * available, we'll return FALSE to indicate that. This mechanism
+ * considers only the normal slots, not the reserved slot 0 nor the
+ * task management slot m_n_normal + 1. The rotor is left to point to
+ * the normal slot after the one we select, unless we select the last
+ * normal slot in which case it returns to slot 1.
*/
- slot = (slots->m_tags)++;
- if (slots->m_tags > slots->m_n_slots) {
- slots->m_tags = 1;
- }
+ start_rotor = slots->m_rotor;
+ do {
+ slot = slots->m_rotor++;
+ if (slots->m_rotor > slots->m_n_normal)
+ slots->m_rotor = 1;
-alloc_tag:
- /* Validate tag, should never fail. */
- if (slots->m_slot[slot] == NULL) {
- /*
- * Make sure SMID is not using reserved value of 0
- * and the TM request slot.
- */
- ASSERT((slot > 0) && (slot <= slots->m_n_slots));
+ if (slots->m_rotor == start_rotor)
+ break;
+ } while (slots->m_slot[slot] != NULL);
+
+ if (slots->m_slot[slot] != NULL)
+ return (FALSE);
+
+ ASSERT(slot != 0 && slot <= slots->m_n_normal);
+
cmd->cmd_slot = slot;
slots->m_slot[slot] = cmd;
mpt->m_ncmds++;
/*
@@ -3290,29 +3384,10 @@
*/
if (cmd->cmd_active_timeout <= mptsas_scsi_watchdog_tick) {
cmd->cmd_active_timeout += mptsas_scsi_watchdog_tick;
}
return (TRUE);
- } else {
- int i;
-
- /*
- * If slot in use, scan until a free one is found. Don't use 0
- * or final slot, which is reserved for TM requests.
- */
- for (i = 0; i < slots->m_n_slots; i++) {
- slot = slots->m_tags;
- if (++(slots->m_tags) > slots->m_n_slots) {
- slots->m_tags = 1;
- }
- if (slots->m_slot[slot] == NULL) {
- NDBG22(("found free slot %d", slot));
- goto alloc_tag;
- }
- }
- }
- return (FALSE);
}
/*
* prepare the pkt:
* the pkt may have been resubmitted or just reused so
@@ -4649,11 +4724,11 @@
/*
* 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_slots)) {
+ 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;
}
@@ -4752,11 +4827,11 @@
(function != MPI2_FUNCTION_DIAG_BUFFER_POST)) {
/*
* This could be a TM reply, which use the last allocated SMID,
* so allow for that.
*/
- if ((SMID == 0) || (SMID > (slots->m_n_slots + 1))) {
+ 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;
@@ -5069,11 +5144,11 @@
"reconfigure.\n");
break;
}
topo_node->mpt = mpt;
topo_node->event = MPTSAS_DR_EVENT_RECONFIG_TARGET;
- topo_node->un.phymask = ptgt->m_phymask;
+ topo_node->un.phymask = ptgt->m_addr.mta_phymask;
topo_node->devhdl = ptgt->m_devhdl;
topo_node->object = (void *)ptgt;
topo_node->flags = MPTSAS_TOPO_FLAG_LUN_ASSOCIATED;
if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
@@ -5135,17 +5210,13 @@
case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
case MPI2_IOCSTATUS_BUSY:
/*
* set throttles to drain
*/
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
/*
* retry command
*/
@@ -5832,12 +5903,12 @@
if (topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
/*
* Get latest RAID info.
*/
(void) mptsas_get_raid_info(mpt);
- ptgt = mptsas_search_by_devhdl(
- &mpt->m_active->m_tgttbl, topo_node->devhdl);
+ ptgt = refhash_linear_search(mpt->m_targets,
+ mptsas_target_eval_devhdl, &topo_node->devhdl);
if (ptgt == NULL)
break;
} else {
ptgt = (void *)topo_node->object;
}
@@ -5882,11 +5953,11 @@
mutex_exit(&mpt->m_mutex);
flags = topo_node->flags;
if (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) {
- phymask = ptgt->m_phymask;
+ phymask = ptgt->m_addr.mta_phymask;
phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
(void) sprintf(phy_mask_name, "%x", phymask);
parent = scsi_hba_iport_find(mpt->m_dip,
phy_mask_name);
kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
@@ -5921,11 +5992,11 @@
*/
if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
bzero(attached_wwnstr,
sizeof (attached_wwnstr));
(void) sprintf(attached_wwnstr, "w%016"PRIx64,
- ptgt->m_sas_wwn);
+ ptgt->m_addr.mta_wwn);
if (ddi_prop_update_string(DDI_DEV_T_NONE,
parent,
SCSI_ADDR_PROP_ATTACHED_PORT,
attached_wwnstr)
!= DDI_PROP_SUCCESS) {
@@ -5979,22 +6050,22 @@
}
mutex_enter(&mpt->m_mutex);
NDBG20(("mptsas%d handle_topo_change to online devhdl:%x, "
"phymask:%x.", mpt->m_instance, ptgt->m_devhdl,
- ptgt->m_phymask));
+ ptgt->m_addr.mta_phymask));
break;
}
case MPTSAS_DR_EVENT_OFFLINE_TARGET:
{
- mptsas_hash_table_t *tgttbl = &mpt->m_active->m_tgttbl;
devhdl = topo_node->devhdl;
- ptgt = mptsas_search_by_devhdl(tgttbl, devhdl);
+ ptgt = refhash_linear_search(mpt->m_targets,
+ mptsas_target_eval_devhdl, &devhdl);
if (ptgt == NULL)
break;
- sas_wwn = ptgt->m_sas_wwn;
+ sas_wwn = ptgt->m_addr.mta_wwn;
phy = ptgt->m_phynum;
addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
if (sas_wwn) {
@@ -6018,12 +6089,12 @@
*/
rval = mptsas_do_scsi_reset(mpt, devhdl);
if (rval) {
NDBG20(("mptsas%d handle_topo_change to reset target "
"before offline devhdl:%x, phymask:%x, rval:%x",
- mpt->m_instance, ptgt->m_devhdl, ptgt->m_phymask,
- rval));
+ mpt->m_instance, ptgt->m_devhdl,
+ ptgt->m_addr.mta_phymask, rval));
}
mutex_exit(&mpt->m_mutex);
ndi_devi_enter(scsi_vhci_dip, &circ);
@@ -6031,11 +6102,11 @@
rval = mptsas_offline_target(parent, addr);
ndi_devi_exit(parent, circ1);
ndi_devi_exit(scsi_vhci_dip, circ);
NDBG20(("mptsas%d handle_topo_change to offline devhdl:%x, "
"phymask:%x, rval:%x", mpt->m_instance,
- ptgt->m_devhdl, ptgt->m_phymask, rval));
+ ptgt->m_devhdl, ptgt->m_addr.mta_phymask, rval));
kmem_free(addr, SCSI_MAXNAMELEN);
/*
* Clear parent's props for SMHBA support
@@ -6074,12 +6145,11 @@
mutex_enter(&mpt->m_mutex);
ptgt->m_led_status = 0;
(void) mptsas_flush_led_status(mpt, ptgt);
if (rval == DDI_SUCCESS) {
- mptsas_tgt_free(&mpt->m_active->m_tgttbl,
- ptgt->m_sas_wwn, ptgt->m_phymask);
+ refhash_remove(mpt->m_targets, ptgt);
ptgt = NULL;
} else {
/*
* clean DR_INTRANSITION flag to allow I/O down to
* PHCI driver since failover finished.
@@ -6132,11 +6202,10 @@
}
case MPTSAS_DR_EVENT_RECONFIG_SMP:
{
mptsas_smp_t smp;
dev_info_t *smpdip;
- mptsas_hash_table_t *smptbl = &mpt->m_active->m_smptbl;
devhdl = topo_node->devhdl;
page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)devhdl;
@@ -6145,11 +6214,11 @@
mptsas_log(mpt, CE_WARN, "failed to online smp, "
"handle %x", devhdl);
return;
}
- psmp = mptsas_smp_alloc(smptbl, &smp);
+ psmp = mptsas_smp_alloc(mpt, &smp);
if (psmp == NULL) {
return;
}
mutex_exit(&mpt->m_mutex);
@@ -6160,15 +6229,15 @@
mutex_enter(&mpt->m_mutex);
break;
}
case MPTSAS_DR_EVENT_OFFLINE_SMP:
{
- mptsas_hash_table_t *smptbl = &mpt->m_active->m_smptbl;
devhdl = topo_node->devhdl;
uint32_t dev_info;
- psmp = mptsas_search_by_devhdl(smptbl, devhdl);
+ psmp = refhash_linear_search(mpt->m_smp_targets,
+ mptsas_smp_eval_devhdl, &devhdl);
if (psmp == NULL)
break;
/*
* The mptsas_smp_t data is released only if the dip is offlined
* successfully.
@@ -6220,12 +6289,11 @@
mutex_enter(&mpt->m_mutex);
NDBG20(("mptsas%d handle_topo_change to remove devhdl:%x, "
"rval:%x", mpt->m_instance, psmp->m_devhdl, rval));
if (rval == DDI_SUCCESS) {
- mptsas_smp_free(smptbl, psmp->m_sasaddr,
- psmp->m_phymask);
+ refhash_remove(mpt->m_smp_targets, psmp);
} else {
psmp->m_devhdl = MPTSAS_INVALID_DEVHDL;
}
bzero(attached_wwnstr, sizeof (attached_wwnstr));
@@ -6380,19 +6448,15 @@
mptsas_topo_change_list_t *topo_head = NULL;
mptsas_topo_change_list_t *topo_tail = NULL;
mptsas_topo_change_list_t *topo_node = NULL;
mptsas_target_t *ptgt;
mptsas_smp_t *psmp;
- mptsas_hash_table_t *tgttbl, *smptbl;
uint8_t flags = 0, exp_flag;
smhba_info_t *pSmhba = NULL;
NDBG20(("mptsas_handle_event_sync: SAS topology change"));
- tgttbl = &mpt->m_active->m_tgttbl;
- smptbl = &mpt->m_active->m_smptbl;
-
sas_topo_change_list = (pMpi2EventDataSasTopologyChangeList_t)
eventreply->EventData;
enc_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
&sas_topo_change_list->EnclosureHandle);
@@ -6434,20 +6498,21 @@
}
break;
case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
(void) sprintf(string, " not responding, "
"removed");
- psmp = mptsas_search_by_devhdl(smptbl,
- expd_handle);
+ psmp = refhash_linear_search(mpt->m_smp_targets,
+ mptsas_smp_eval_devhdl, &expd_handle);
if (psmp == NULL)
break;
topo_node = kmem_zalloc(
sizeof (mptsas_topo_change_list_t),
KM_SLEEP);
topo_node->mpt = mpt;
- topo_node->un.phymask = psmp->m_phymask;
+ topo_node->un.phymask =
+ psmp->m_addr.mta_phymask;
topo_node->event = MPTSAS_DR_EVENT_OFFLINE_SMP;
topo_node->devhdl = expd_handle;
topo_node->flags = flags;
topo_node->object = NULL;
if (topo_head == NULL) {
@@ -6594,12 +6659,12 @@
/*
* Target device is removed from the system
* Before the device is really offline from
* from system.
*/
- ptgt = mptsas_search_by_devhdl(tgttbl,
- dev_handle);
+ ptgt = refhash_linear_search(mpt->m_targets,
+ mptsas_target_eval_devhdl, &dev_handle);
/*
* If ptgt is NULL here, it means that the
* DevHandle is not in the hash table. This is
* reasonable sometimes. For example, if a
* disk was pulled, then added, then pulled
@@ -6647,11 +6712,12 @@
topo_node = kmem_zalloc(
sizeof (mptsas_topo_change_list_t),
KM_SLEEP);
topo_node->mpt = mpt;
- topo_node->un.phymask = ptgt->m_phymask;
+ topo_node->un.phymask =
+ ptgt->m_addr.mta_phymask;
topo_node->event =
MPTSAS_DR_EVENT_OFFLINE_TARGET;
topo_node->devhdl = dev_handle;
topo_node->flags = flags;
topo_node->object = NULL;
@@ -6807,21 +6873,18 @@
Mpi2EventDataIrConfigChangeList_t *irChangeList;
mptsas_topo_change_list_t *topo_head = NULL;
mptsas_topo_change_list_t *topo_tail = NULL;
mptsas_topo_change_list_t *topo_node = NULL;
mptsas_target_t *ptgt;
- mptsas_hash_table_t *tgttbl;
uint8_t num_entries, i, reason;
uint16_t volhandle, diskhandle;
irChangeList = (pMpi2EventDataIrConfigChangeList_t)
eventreply->EventData;
num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
&irChangeList->NumElements);
- tgttbl = &mpt->m_active->m_tgttbl;
-
NDBG20(("mptsas%d IR_CONFIGURATION_CHANGE_LIST event received",
mpt->m_instance));
for (i = 0; i < num_entries; i++) {
reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
@@ -6861,12 +6924,12 @@
case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
{
NDBG20(("mptsas %d volume deleted\n",
mpt->m_instance));
- ptgt = mptsas_search_by_devhdl(tgttbl,
- volhandle);
+ ptgt = refhash_linear_search(mpt->m_targets,
+ mptsas_target_eval_devhdl, &volhandle);
if (ptgt == NULL)
break;
/*
* Clear any flags related to volume
@@ -6882,11 +6945,12 @@
topo_node = kmem_zalloc(
sizeof (mptsas_topo_change_list_t),
KM_SLEEP);
topo_node->mpt = mpt;
- topo_node->un.phymask = ptgt->m_phymask;
+ topo_node->un.phymask =
+ ptgt->m_addr.mta_phymask;
topo_node->event =
MPTSAS_DR_EVENT_OFFLINE_TARGET;
topo_node->devhdl = volhandle;
topo_node->flags =
MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
@@ -6900,12 +6964,12 @@
break;
}
case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
case MPI2_EVENT_IR_CHANGE_RC_HIDE:
{
- ptgt = mptsas_search_by_devhdl(tgttbl,
- diskhandle);
+ ptgt = refhash_linear_search(mpt->m_targets,
+ mptsas_target_eval_devhdl, &diskhandle);
if (ptgt == NULL)
break;
/*
* Update DR flag immediately avoid I/O failure
@@ -6916,11 +6980,12 @@
topo_node = kmem_zalloc(
sizeof (mptsas_topo_change_list_t),
KM_SLEEP);
topo_node->mpt = mpt;
- topo_node->un.phymask = ptgt->m_phymask;
+ topo_node->un.phymask =
+ ptgt->m_addr.mta_phymask;
topo_node->event =
MPTSAS_DR_EVENT_OFFLINE_TARGET;
topo_node->devhdl = diskhandle;
topo_node->flags =
MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
@@ -7341,11 +7406,10 @@
{
Mpi2EventDataIrVolume_t *irVolume;
uint16_t devhandle;
uint32_t state;
int config, vol;
- mptsas_slots_t *slots = mpt->m_active;
uint8_t found = FALSE;
irVolume = (pMpi2EventDataIrVolume_t)eventreply->EventData;
state = ddi_get32(mpt->m_acc_reply_frame_hdl,
&irVolume->NewValue);
@@ -7358,14 +7422,14 @@
* Get latest RAID info and then find the DevHandle for this
* event in the configuration. If the DevHandle is not found
* just exit the event.
*/
(void) mptsas_get_raid_info(mpt);
- for (config = 0; (config < slots->m_num_raid_configs) &&
+ for (config = 0; (config < mpt->m_num_raid_configs) &&
(!found); config++) {
for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
- if (slots->m_raidconfig[config].m_raidvol[vol].
+ if (mpt->m_raidconfig[config].m_raidvol[vol].
m_raidhandle == devhandle) {
found = TRUE;
break;
}
}
@@ -7376,11 +7440,11 @@
switch (irVolume->ReasonCode) {
case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
{
uint32_t i;
- slots->m_raidconfig[config].m_raidvol[vol].m_settings =
+ mpt->m_raidconfig[config].m_raidvol[vol].m_settings =
state;
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"
@@ -7399,11 +7463,11 @@
(state >> 16) & 0xff);
break;
}
case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
{
- slots->m_raidconfig[config].m_raidvol[vol].m_state =
+ 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
@@ -7421,11 +7485,11 @@
"state unknown");
break;
}
case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
{
- slots->m_raidconfig[config].m_raidvol[vol].
+ 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,
@@ -7570,22 +7634,18 @@
mutex_enter(&mpt->m_mutex);
mpt->m_restart_cmd_timeid = 0;
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
if (ptgt->m_reset_delay == 0) {
if (ptgt->m_t_throttle == QFULL_THROTTLE) {
mptsas_set_throttle(mpt, ptgt,
MAX_THROTTLE);
}
}
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
mptsas_restart_hba(mpt);
mutex_exit(&mpt->m_mutex);
}
@@ -7653,18 +7713,18 @@
* out of duplicates. This should be the normal case
* for block and raw I/O.
* If no duplicates, we have to scan through tag que and
* find the longest timeout value and use it. This is
* going to take a while...
- * Add 1 to m_n_slots to account for TM request.
+ * Add 1 to m_n_normal to account for TM request.
*/
if (cmd->cmd_pkt->pkt_time == ptgt->m_timebase) {
if (--(ptgt->m_dups) == 0) {
if (ptgt->m_t_ncmds) {
mptsas_cmd_t *ssp;
uint_t n = 0;
- ushort_t nslots = (slots->m_n_slots + 1);
+ ushort_t nslots = (slots->m_n_normal + 1);
ushort_t i;
/*
* This crude check assumes we don't do
* this too often which seems reasonable
* for block and raw I/O.
@@ -8419,11 +8479,10 @@
static int
mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl)
{
int rval = FALSE;
uint8_t config, disk;
- mptsas_slots_t *slots = mpt->m_active;
ASSERT(mutex_owned(&mpt->m_mutex));
if (mptsas_debug_resets) {
mptsas_log(mpt, CE_WARN, "mptsas_do_scsi_reset: target=%d",
@@ -8434,13 +8493,13 @@
* Issue a Target Reset message to the target specified but not to a
* disk making up a raid volume. Just look through the RAID config
* Phys Disk list of DevHandles. If the target's DevHandle is in this
* list, then don't reset this target.
*/
- for (config = 0; config < slots->m_num_raid_configs; config++) {
+ for (config = 0; config < mpt->m_num_raid_configs; config++) {
for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
- if (devhdl == slots->m_raidconfig[config].
+ if (devhdl == mpt->m_raidconfig[config].
m_physdisk_devhdl[disk]) {
return (TRUE);
}
}
}
@@ -8532,11 +8591,11 @@
* Make sure the I/O Controller has flushed all cmds
* that are associated with this target for a target reset
* and target/lun for abort task set.
* Account for TM requests, which use the last SMID.
*/
- for (slot = 0; slot <= mpt->m_active->m_n_slots; slot++) {
+ for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
if ((cmd = slots->m_slot[slot]) == NULL)
continue;
reason = CMD_RESET;
stat = STAT_DEV_RESET;
switch (tasktype) {
@@ -8664,11 +8723,11 @@
* The I/O Controller should have already sent back
* all commands via the scsi I/O reply frame. Make
* sure all commands have been flushed.
* Account for TM request, which use the last SMID.
*/
- for (slot = 0; slot <= mpt->m_active->m_n_slots; slot++) {
+ for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
if ((cmd = slots->m_slot[slot]) == NULL)
continue;
if (cmd->cmd_flags & CFLAG_CMDIOC) {
/*
@@ -8779,19 +8838,17 @@
static void
mptsas_setup_bus_reset_delay(mptsas_t *mpt)
{
mptsas_target_t *ptgt = NULL;
+ ASSERT(MUTEX_HELD(&mpt->m_mutex));
+
NDBG22(("mptsas_setup_bus_reset_delay"));
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
ptgt->m_reset_delay = mpt->m_scsi_reset_delay;
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
mptsas_start_watch_reset_delay();
}
@@ -8839,13 +8896,12 @@
NDBG22(("mptsas_watch_reset_delay_subr: mpt=0x%p", (void *)mpt));
ASSERT(mutex_owned(&mpt->m_mutex));
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
if (ptgt->m_reset_delay != 0) {
ptgt->m_reset_delay -=
MPTSAS_WATCH_RESET_DELAY_TICK;
if (ptgt->m_reset_delay <= 0) {
ptgt->m_reset_delay = 0;
@@ -8854,13 +8910,10 @@
restart++;
} else {
done = -1;
}
}
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
if (restart > 0) {
mptsas_restart_hba(mpt);
}
@@ -9160,11 +9213,10 @@
mptsas_alloc_active_slots(mptsas_t *mpt, int flag)
{
mptsas_slots_t *old_active = mpt->m_active;
mptsas_slots_t *new_active;
size_t size;
- int rval = -1, i;
/*
* if there are active commands, then we cannot
* change size of active slots array.
*/
@@ -9172,35 +9224,25 @@
size = MPTSAS_SLOTS_SIZE(mpt);
new_active = kmem_zalloc(size, flag);
if (new_active == NULL) {
NDBG1(("new active alloc failed"));
- return (rval);
+ return (-1);
}
/*
* Since SMID 0 is reserved and the TM slot is reserved, the
* number of slots that can be used at any one time is
* m_max_requests - 2.
*/
- new_active->m_n_slots = (mpt->m_max_requests - 2);
+ new_active->m_n_normal = (mpt->m_max_requests - 2);
new_active->m_size = size;
- new_active->m_tags = 1;
- if (old_active) {
- new_active->m_tgttbl = old_active->m_tgttbl;
- new_active->m_smptbl = old_active->m_smptbl;
- new_active->m_num_raid_configs =
- old_active->m_num_raid_configs;
- for (i = 0; i < new_active->m_num_raid_configs; i++) {
- new_active->m_raidconfig[i] =
- old_active->m_raidconfig[i];
- }
+ new_active->m_rotor = 1;
+ if (old_active)
mptsas_free_active_slots(mpt);
- }
mpt->m_active = new_active;
- rval = 0;
- return (rval);
+ return (0);
}
static void
mptsas_free_active_slots(mptsas_t *mpt)
{
@@ -9341,10 +9383,12 @@
{
int i;
mptsas_cmd_t *cmd;
mptsas_target_t *ptgt = NULL;
+ ASSERT(MUTEX_HELD(&mpt->m_mutex));
+
NDBG30(("mptsas_watchsubr: mpt=0x%p", (void *)mpt));
#ifdef MPTSAS_TEST
if (mptsas_enable_untagged) {
mptsas_test_untagged++;
@@ -9353,11 +9397,11 @@
/*
* Check for commands stuck in active slot
* Account for TM requests, which use the last SMID.
*/
- for (i = 0; i <= mpt->m_active->m_n_slots; i++) {
+ for (i = 0; i <= mpt->m_active->m_n_normal; i++) {
if ((cmd = mpt->m_active->m_slot[i]) != NULL) {
if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
cmd->cmd_active_timeout -=
mptsas_scsi_watchdog_tick;
if (cmd->cmd_active_timeout <= 0) {
@@ -9387,13 +9431,12 @@
}
}
}
}
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ 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) &&
@@ -9408,21 +9451,17 @@
if (ptgt->m_timebase <=
mptsas_scsi_watchdog_tick) {
ptgt->m_timebase +=
mptsas_scsi_watchdog_tick;
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
continue;
}
ptgt->m_timeout -= mptsas_scsi_watchdog_tick;
if (ptgt->m_timeout < 0) {
mptsas_cmd_timeout(mpt, ptgt->m_devhdl);
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
continue;
}
if ((ptgt->m_timeout) <=
mptsas_scsi_watchdog_tick) {
@@ -9429,13 +9468,10 @@
NDBG23(("pending timeout"));
mptsas_set_throttle(mpt, ptgt,
DRAIN_THROTTLE);
}
}
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
}
/*
* timeout recovery
@@ -9495,17 +9531,13 @@
NDBG28(("mptsas_quiesce_bus"));
mutex_enter(&mpt->m_mutex);
/* Set all the throttles to zero */
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
/* If there are any outstanding commands in the queue */
if (mpt->m_ncmds) {
mpt->m_softstate |= MPTSAS_SS_DRAINING;
@@ -9514,17 +9546,13 @@
if (cv_wait_sig(&mpt->m_cv, &mpt->m_mutex) == 0) {
/*
* Quiesce has been interrupted
*/
mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
mptsas_restart_hba(mpt);
if (mpt->m_quiesce_timeid != 0) {
timeout_id_t tid = mpt->m_quiesce_timeid;
mpt->m_quiesce_timeid = 0;
@@ -9555,17 +9583,13 @@
mptsas_target_t *ptgt = NULL;
NDBG28(("mptsas_unquiesce_bus"));
mutex_enter(&mpt->m_mutex);
mpt->m_softstate &= ~MPTSAS_SS_QUIESCED;
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
mptsas_restart_hba(mpt);
mutex_exit(&mpt->m_mutex);
return (0);
}
@@ -9585,17 +9609,13 @@
} else {
/*
* The throttle may have been reset because
* of a SCSI bus reset
*/
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
mpt, (MPTSAS_QUIESCE_TIMEOUT *
drv_usectohz(1000000)));
@@ -11323,20 +11343,12 @@
(lc.Command == MPTSAS_LEDCTL_FLAG_GET && (mode & FREAD) == 0))
return (EACCES);
/* Locate the target we're interrogating... */
mutex_enter(&mpt->m_mutex);
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
- if (ptgt->m_enclosure == lc.Enclosure &&
- ptgt->m_slot_num == lc.Slot) {
- break;
- }
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
- }
+ 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);
}
@@ -11383,16 +11395,13 @@
return (EFAULT);
}
/* Find out how many targets there are. */
mutex_enter(&mpt->m_mutex);
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
count++;
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
mutex_exit(&mpt->m_mutex);
/*
* If we haven't been asked to copy out information on each target,
@@ -11413,29 +11422,26 @@
}
di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP);
mutex_enter(&mpt->m_mutex);
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
if (i >= count) {
/*
* The number of targets changed while we weren't
* looking, so give up.
*/
+ refhash_rele(mpt->m_targets, ptgt);
mutex_exit(&mpt->m_mutex);
kmem_free(di, count * sizeof (mptsas_disk_info_t));
return (EAGAIN);
}
di[i].Instance = mpt->m_instance;
di[i].Enclosure = ptgt->m_enclosure;
di[i].Slot = ptgt->m_slot_num;
- di[i].SasAddress = ptgt->m_sas_wwn;
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
+ di[i].SasAddress = ptgt->m_addr.mta_wwn;
i++;
}
mutex_exit(&mpt->m_mutex);
STRUCT_FSET(gdi, DiskCount, i);
@@ -11737,17 +11743,13 @@
mpt->m_in_reset = TRUE;
/*
* Set all throttles to HOLD
*/
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
/*
* Disable interrupts
*/
@@ -11779,17 +11781,13 @@
}
/*
* Reset the throttles
*/
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
mptsas_doneq_empty(mpt);
mptsas_restart_hba(mpt);
@@ -11851,10 +11849,16 @@
if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed");
goto fail;
}
+ mpt->m_targets = refhash_create(MPTSAS_TARGET_BUCKET_COUNT,
+ mptsas_target_addr_hash, mptsas_target_addr_cmp,
+ mptsas_target_free, sizeof (mptsas_target_t),
+ offsetof(mptsas_target_t, m_link),
+ offsetof(mptsas_target_t, m_addr), KM_SLEEP);
+
if (mptsas_alloc_active_slots(mpt, KM_SLEEP)) {
goto fail;
}
/*
* Allocate request message frames, reply free queue, reply descriptor
@@ -12489,11 +12493,10 @@
int rval;
uint32_t dev_info;
uint64_t sas_wwn;
mptsas_phymask_t phymask;
uint8_t physport, phynum, config, disk;
- mptsas_slots_t *slots = mpt->m_active;
uint64_t devicename;
uint16_t pdev_hdl;
mptsas_target_t *tmp_tgt = NULL;
uint16_t bay_num, enclosure;
@@ -12516,23 +12519,23 @@
/*
* Check if the dev handle is for a Phys Disk. If so, set return value
* and exit. Don't add Phys Disks to hash.
*/
- for (config = 0; config < slots->m_num_raid_configs; config++) {
+ for (config = 0; config < mpt->m_num_raid_configs; config++) {
for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
- if (*dev_handle == slots->m_raidconfig[config].
+ if (*dev_handle == mpt->m_raidconfig[config].
m_physdisk_devhdl[disk]) {
rval = DEV_INFO_PHYS_DISK;
return (rval);
}
}
}
/*
* Get SATA Device Name from SAS device page0 for
- * sata device, if device name doesn't exist, set m_sas_wwn to
+ * sata device, if device name doesn't exist, set mta_wwn to
* 0 for direct attached SATA. For the device behind the expander
* we still can use STP address assigned by expander.
*/
if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
@@ -12555,11 +12558,11 @@
sas_wwn = 0;
}
}
phymask = mptsas_physport_to_phymask(mpt, physport);
- *pptgt = mptsas_tgt_alloc(&slots->m_tgttbl, *dev_handle, sas_wwn,
+ *pptgt = mptsas_tgt_alloc(mpt, *dev_handle, sas_wwn,
dev_info, phymask, phynum);
if (*pptgt == NULL) {
mptsas_log(mpt, CE_WARN, "Failed to allocated target"
"structure!");
rval = DEV_INFO_FAIL_ALLOC;
@@ -12985,11 +12988,11 @@
* TODO Another senario is, we hotplug the same disk
* on the same slot, the devhdl changed, is this
* possible?
* tgt_private->t_private != ptgt
*/
- if (sasaddr != ptgt->m_sas_wwn) {
+ if (sasaddr != ptgt->m_addr.mta_wwn) {
/*
* The device has changed although the devhdl is the
* same (Enclosure mapping mode, change drive on the
* same slot)
*/
@@ -13014,17 +13017,17 @@
mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
dev_info_t **lundip)
{
int rval;
mptsas_t *mpt = DIP2MPT(pdip);
- int phymask;
+ mptsas_phymask_t phymask;
mptsas_target_t *ptgt = NULL;
/*
* Get the physical port associated to the iport
*/
- phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
+ phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
"phymask", 0);
ptgt = mptsas_phy_to_tgt(mpt, phymask, phy);
if (ptgt == NULL) {
/*
@@ -13107,11 +13110,11 @@
uint64_t sas_wwn = 0;
uint8_t phy = 0xFF;
uint32_t dev_info = 0;
mutex_enter(&mpt->m_mutex);
- sas_wwn = ptgt->m_sas_wwn;
+ sas_wwn = ptgt->m_addr.mta_wwn;
phy = ptgt->m_phynum;
dev_info = ptgt->m_deviceinfo;
mutex_exit(&mpt->m_mutex);
if (sas_wwn == 0) {
@@ -13222,11 +13225,12 @@
struct scsi_inquiry *sd_inq = NULL;
mptsas_t *mpt = DIP2MPT(pdip);
mptsas_target_t *ptgt = NULL;
mutex_enter(&mpt->m_mutex);
- ptgt = mptsas_search_by_devhdl(&mpt->m_active->m_tgttbl, target);
+ ptgt = refhash_linear_search(mpt->m_targets,
+ mptsas_target_eval_devhdl, &target);
mutex_exit(&mpt->m_mutex);
if (ptgt == NULL) {
mptsas_log(mpt, CE_WARN, "Volume with VolDevHandle of 0x%x "
"not found.", target);
return (rval);
@@ -13255,22 +13259,21 @@
{
mptsas_t *mpt = DIP2MPT(pdip);
int config, vol;
int target;
dev_info_t *lundip = NULL;
- mptsas_slots_t *slots = mpt->m_active;
/*
* Get latest RAID info and search for any Volume DevHandles. If any
* are found, configure the volume.
*/
mutex_enter(&mpt->m_mutex);
- for (config = 0; config < slots->m_num_raid_configs; config++) {
+ for (config = 0; config < mpt->m_num_raid_configs; config++) {
for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
- if (slots->m_raidconfig[config].m_raidvol[vol].m_israid
+ if (mpt->m_raidconfig[config].m_raidvol[vol].m_israid
== 1) {
- target = slots->m_raidconfig[config].
+ target = mpt->m_raidconfig[config].
m_raidvol[vol].m_raidhandle;
mutex_exit(&mpt->m_mutex);
(void) mptsas_config_raid(pdip, target,
&lundip);
mutex_enter(&mpt->m_mutex);
@@ -13294,11 +13297,11 @@
char *addr;
char *nodename;
mptsas_t *mpt = DIP2MPT(pdip);
mutex_enter(&mpt->m_mutex);
- wwid = ptgt->m_sas_wwn;
+ wwid = ptgt->m_addr.mta_wwn;
mutex_exit(&mpt->m_mutex);
child = ddi_get_child(pdip);
while (child) {
find = 0;
@@ -13398,11 +13401,11 @@
if (mptsas_get_sas_expander_page0(mpt, page_address, &smp_node)
!= DDI_SUCCESS) {
break;
}
mpt->m_smp_devhdl = dev_handle = smp_node.m_devhdl;
- (void) mptsas_smp_alloc(&mpt->m_active->m_smptbl, &smp_node);
+ (void) mptsas_smp_alloc(mpt, &smp_node);
}
/*
* Config target devices
*/
@@ -13430,28 +13433,17 @@
}
}
void
-mptsas_invalid_hashtab(mptsas_hash_table_t *hashtab)
-{
- mptsas_hash_data_t *data;
- data = mptsas_hash_traverse(hashtab, MPTSAS_HASH_FIRST);
- while (data != NULL) {
- data->devhdl = MPTSAS_INVALID_DEVHDL;
- data->device_info = 0;
- /*
- * For tgttbl, clear dr_flag.
- */
- data->dr_flag = MPTSAS_DR_INACTIVE;
- data = mptsas_hash_traverse(hashtab, MPTSAS_HASH_NEXT);
- }
-}
-
-void
mptsas_update_driver_data(struct mptsas *mpt)
{
+ mptsas_target_t *tp;
+ mptsas_smp_t *sp;
+
+ ASSERT(MUTEX_HELD(&mpt->m_mutex));
+
/*
* TODO after hard reset, update the driver data structures
* 1. update port/phymask mapping table mpt->m_phy_info
* 2. invalid all the entries in hash table
* m_devhdl = 0xffff and m_deviceinfo = 0
@@ -13458,13 +13450,28 @@
* 3. call sas_device_page/expander_page to update hash table
*/
mptsas_update_phymask(mpt);
/*
* Invalid the existing entries
+ *
+ * XXX - It seems like we should just delete everything here. We are
+ * holding the lock and are about to refresh all the targets in both
+ * hashes anyway. Given the path we're in, what outstanding async
+ * event could possibly be trying to reference one of these things
+ * without taking the lock, and how would that be useful anyway?
*/
- mptsas_invalid_hashtab(&mpt->m_active->m_tgttbl);
- mptsas_invalid_hashtab(&mpt->m_active->m_smptbl);
+ for (tp = refhash_first(mpt->m_targets); tp != NULL;
+ tp = refhash_next(mpt->m_targets, tp)) {
+ tp->m_devhdl = MPTSAS_INVALID_DEVHDL;
+ tp->m_deviceinfo = 0;
+ tp->m_dr_flag = MPTSAS_DR_INACTIVE;
+ }
+ for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
+ sp = refhash_next(mpt->m_smp_targets, sp)) {
+ sp->m_devhdl = MPTSAS_INVALID_DEVHDL;
+ sp->m_deviceinfo = 0;
+ }
mpt->m_done_traverse_dev = 0;
mpt->m_done_traverse_smp = 0;
mpt->m_dev_handle = mpt->m_smp_devhdl = MPTSAS_INVALID_DEVHDL;
mptsas_update_hashtab(mpt);
}
@@ -13497,36 +13504,29 @@
if (!mpt->m_done_traverse_dev || !mpt->m_done_traverse_smp) {
mptsas_update_hashtab(mpt);
}
- psmp = (mptsas_smp_t *)mptsas_hash_traverse(&mpt->m_active->m_smptbl,
- MPTSAS_HASH_FIRST);
- while (psmp != NULL) {
- phy_mask = psmp->m_phymask;
+ for (psmp = refhash_first(mpt->m_smp_targets); psmp != NULL;
+ psmp = refhash_next(mpt->m_smp_targets, psmp)) {
+ phy_mask = psmp->m_addr.mta_phymask;
if (phy_mask == phymask) {
smpdip = NULL;
mutex_exit(&mpt->m_mutex);
(void) mptsas_online_smp(pdip, psmp, &smpdip);
mutex_enter(&mpt->m_mutex);
}
- psmp = (mptsas_smp_t *)mptsas_hash_traverse(
- &mpt->m_active->m_smptbl, MPTSAS_HASH_NEXT);
}
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
- phy_mask = ptgt->m_phymask;
+ for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
+ ptgt = refhash_next(mpt->m_targets, ptgt)) {
+ phy_mask = ptgt->m_addr.mta_phymask;
if (phy_mask == phymask) {
mutex_exit(&mpt->m_mutex);
(void) mptsas_config_target(pdip, ptgt);
mutex_enter(&mpt->m_mutex);
}
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
mutex_exit(&mpt->m_mutex);
}
static int
@@ -13704,11 +13704,11 @@
int rval = DDI_FAILURE;
char *devname;
char wwn_str[MPTSAS_WWN_STRLEN];
dev_info_t *cdip;
- (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_sasaddr);
+ (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);
@@ -13984,11 +13984,11 @@
char pdev_wwn_str[MPTSAS_WWN_STRLEN];
uint32_t dev_info;
mutex_enter(&mpt->m_mutex);
target = ptgt->m_devhdl;
- sas_wwn = ptgt->m_sas_wwn;
+ sas_wwn = ptgt->m_addr.mta_wwn;
devinfo = ptgt->m_deviceinfo;
phy = ptgt->m_phynum;
mutex_exit(&mpt->m_mutex);
if (sas_wwn) {
@@ -14333,11 +14333,11 @@
uint32_t dev_info;
int64_t lun64 = 0;
mutex_enter(&mpt->m_mutex);
target = ptgt->m_devhdl;
- sas_wwn = ptgt->m_sas_wwn;
+ sas_wwn = ptgt->m_addr.mta_wwn;
devinfo = ptgt->m_deviceinfo;
phy = ptgt->m_phynum;
mutex_exit(&mpt->m_mutex);
/*
@@ -14452,11 +14452,11 @@
/*
* The following code is to set properties for SM-HBA support,
* it doesn't apply to RAID volumes
*/
- if (ptgt->m_phymask == 0)
+ if (ptgt->m_addr.mta_phymask == 0)
goto phys_raid_lun;
mutex_enter(&mpt->m_mutex);
page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
@@ -14606,11 +14606,11 @@
}
}
/*
* Create the phy-num property for non-raid disk
*/
- if (ptgt->m_phymask != 0) {
+ if (ptgt->m_addr.mta_phymask != 0) {
if (ndi_prop_update_int(DDI_DEV_T_NONE,
*lun_dip, "phy-num", ptgt->m_phynum) !=
DDI_PROP_SUCCESS) {
mptsas_log(mpt, CE_WARN, "mptsas driver "
"failed to create phy-num property for "
@@ -14728,17 +14728,17 @@
char *iport = NULL;
mptsas_phymask_t phy_mask = 0;
uint16_t attached_devhdl;
uint16_t bay_num, enclosure;
- (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_sasaddr);
+ (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
/*
* Probe smp device, prevent the node of removed device from being
* configured succesfully
*/
- if (mptsas_probe_smp(pdip, smp_node->m_sasaddr) != NDI_SUCCESS) {
+ if (mptsas_probe_smp(pdip, smp_node->m_addr.mta_wwn) != NDI_SUCCESS) {
return (DDI_FAILURE);
}
if ((*smp_dip = mptsas_find_smp_child(pdip, wwn_str)) != NULL) {
return (DDI_SUCCESS);
@@ -14762,11 +14762,11 @@
"property for smp device %s (sas_wwn)",
wwn_str);
ndi_rtn = NDI_FAILURE;
goto smp_create_done;
}
- (void) sprintf(wwn_str, "w%"PRIx64, smp_node->m_sasaddr);
+ (void) sprintf(wwn_str, "w%"PRIx64, smp_node->m_addr.mta_wwn);
if (ndi_prop_update_string(DDI_DEV_T_NONE,
*smp_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str) !=
DDI_PROP_SUCCESS) {
mptsas_log(mpt, CE_WARN, "mptsas unable to create "
"property for iport target-port %s (sas_wwn)",
@@ -15046,11 +15046,11 @@
/*
* If we didn't get a match, we need to get sas page0 for each device, and
* untill we get a match. If failed, return NULL
*/
static mptsas_target_t *
-mptsas_phy_to_tgt(mptsas_t *mpt, int phymask, uint8_t phy)
+mptsas_phy_to_tgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint8_t phy)
{
int i, j = 0;
int rval = 0;
uint16_t cur_handle;
uint32_t page_address;
@@ -15078,22 +15078,17 @@
if (mpt->m_phy_info[phy].phy_mask != phymask)
return (NULL);
mutex_enter(&mpt->m_mutex);
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(&mpt->m_active->m_tgttbl,
- MPTSAS_HASH_FIRST);
- while (ptgt != NULL) {
- if ((ptgt->m_sas_wwn == 0) && (ptgt->m_phynum == phy)) {
+ ptgt = refhash_linear_search(mpt->m_targets, mptsas_target_eval_nowwn,
+ &phy);
+ if (ptgt != NULL) {
mutex_exit(&mpt->m_mutex);
return (ptgt);
}
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
- }
-
if (mpt->m_done_traverse_dev) {
mutex_exit(&mpt->m_mutex);
return (NULL);
}
@@ -15113,37 +15108,39 @@
(rval == DEV_INFO_PHYS_DISK)) {
continue;
}
mpt->m_dev_handle = cur_handle;
- if ((ptgt->m_sas_wwn == 0) && (ptgt->m_phynum == phy)) {
+ if ((ptgt->m_addr.mta_wwn == 0) && (ptgt->m_phynum == phy)) {
break;
}
}
mutex_exit(&mpt->m_mutex);
return (ptgt);
}
/*
- * The ptgt->m_sas_wwn contains the wwid for each disk.
+ * The ptgt->m_addr.mta_wwn contains the wwid for each disk.
* For Raid volumes, we need to check m_raidvol[x].m_raidwwid
* If we didn't get a match, we need to get sas page0 for each device, and
* untill we get a match
* If failed, return NULL
*/
static mptsas_target_t *
-mptsas_wwid_to_ptgt(mptsas_t *mpt, int phymask, uint64_t wwid)
+mptsas_wwid_to_ptgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
{
int rval = 0;
uint16_t cur_handle;
uint32_t page_address;
mptsas_target_t *tmp_tgt = NULL;
+ mptsas_target_addr_t addr;
+ addr.mta_wwn = wwid;
+ addr.mta_phymask = phymask;
mutex_enter(&mpt->m_mutex);
- tmp_tgt = (struct mptsas_target *)mptsas_hash_search(
- &mpt->m_active->m_tgttbl, wwid, phymask);
+ tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
if (tmp_tgt != NULL) {
mutex_exit(&mpt->m_mutex);
return (tmp_tgt);
}
@@ -15151,12 +15148,11 @@
/*
* It's IR volume
*/
rval = mptsas_get_raid_info(mpt);
if (rval) {
- tmp_tgt = (struct mptsas_target *)mptsas_hash_search(
- &mpt->m_active->m_tgttbl, wwid, phymask);
+ tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
}
mutex_exit(&mpt->m_mutex);
return (tmp_tgt);
}
@@ -15165,11 +15161,11 @@
return (NULL);
}
/* If didn't get a match, come here */
cur_handle = mpt->m_dev_handle;
- for (; ; ) {
+ for (;;) {
tmp_tgt = NULL;
page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
MPI2_SAS_DEVICE_PGAD_FORM_MASK) | cur_handle;
rval = mptsas_get_target_device_info(mpt, page_address,
&cur_handle, &tmp_tgt);
@@ -15181,31 +15177,34 @@
if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
(rval == DEV_INFO_PHYS_DISK)) {
continue;
}
mpt->m_dev_handle = cur_handle;
- if ((tmp_tgt->m_sas_wwn) && (tmp_tgt->m_sas_wwn == wwid) &&
- (tmp_tgt->m_phymask == phymask)) {
+ if ((tmp_tgt->m_addr.mta_wwn) &&
+ (tmp_tgt->m_addr.mta_wwn == wwid) &&
+ (tmp_tgt->m_addr.mta_phymask == phymask)) {
break;
}
}
mutex_exit(&mpt->m_mutex);
return (tmp_tgt);
}
static mptsas_smp_t *
-mptsas_wwid_to_psmp(mptsas_t *mpt, int phymask, uint64_t wwid)
+mptsas_wwid_to_psmp(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
{
int rval = 0;
uint16_t cur_handle;
uint32_t page_address;
mptsas_smp_t smp_node, *psmp = NULL;
+ mptsas_target_addr_t addr;
+ addr.mta_wwn = wwid;
+ addr.mta_phymask = phymask;
mutex_enter(&mpt->m_mutex);
- psmp = (struct mptsas_smp *)mptsas_hash_search(&mpt->m_active->m_smptbl,
- wwid, phymask);
+ psmp = refhash_lookup(mpt->m_smp_targets, &addr);
if (psmp != NULL) {
mutex_exit(&mpt->m_mutex);
return (psmp);
}
@@ -15214,286 +15213,105 @@
return (NULL);
}
/* If didn't get a match, come here */
cur_handle = mpt->m_smp_devhdl;
- for (; ; ) {
+ for (;;) {
psmp = NULL;
page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)cur_handle;
rval = mptsas_get_sas_expander_page0(mpt, page_address,
&smp_node);
if (rval != DDI_SUCCESS) {
break;
}
mpt->m_smp_devhdl = cur_handle = smp_node.m_devhdl;
- psmp = mptsas_smp_alloc(&mpt->m_active->m_smptbl, &smp_node);
+ psmp = mptsas_smp_alloc(mpt, &smp_node);
ASSERT(psmp);
- if ((psmp->m_sasaddr) && (psmp->m_sasaddr == wwid) &&
- (psmp->m_phymask == phymask)) {
+ if ((psmp->m_addr.mta_wwn) && (psmp->m_addr.mta_wwn == wwid) &&
+ (psmp->m_addr.mta_phymask == phymask)) {
break;
}
}
mutex_exit(&mpt->m_mutex);
return (psmp);
}
-/* helper functions using hash */
-
-/*
- * Can't have duplicate entries for same devhdl,
- * if there are invalid entries, the devhdl should be set to 0xffff
- */
-static void *
-mptsas_search_by_devhdl(mptsas_hash_table_t *hashtab, uint16_t devhdl)
-{
- mptsas_hash_data_t *data;
-
- data = mptsas_hash_traverse(hashtab, MPTSAS_HASH_FIRST);
- while (data != NULL) {
- if (data->devhdl == devhdl) {
- break;
- }
- data = mptsas_hash_traverse(hashtab, MPTSAS_HASH_NEXT);
- }
- return (data);
-}
-
mptsas_target_t *
-mptsas_tgt_alloc(mptsas_hash_table_t *hashtab, uint16_t devhdl, uint64_t wwid,
+mptsas_tgt_alloc(mptsas_t *mpt, uint16_t devhdl, uint64_t wwid,
uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum)
{
mptsas_target_t *tmp_tgt = NULL;
+ mptsas_target_addr_t addr;
- tmp_tgt = mptsas_hash_search(hashtab, wwid, phymask);
+ addr.mta_wwn = wwid;
+ addr.mta_phymask = phymask;
+ tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
if (tmp_tgt != NULL) {
NDBG20(("Hash item already exist"));
tmp_tgt->m_deviceinfo = devinfo;
- tmp_tgt->m_devhdl = devhdl;
+ tmp_tgt->m_devhdl = devhdl; /* XXX - duplicate? */
return (tmp_tgt);
}
tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target), KM_SLEEP);
if (tmp_tgt == NULL) {
cmn_err(CE_WARN, "Fatal, allocated tgt failed");
return (NULL);
}
tmp_tgt->m_devhdl = devhdl;
- tmp_tgt->m_sas_wwn = wwid;
+ tmp_tgt->m_addr.mta_wwn = wwid;
tmp_tgt->m_deviceinfo = devinfo;
- tmp_tgt->m_phymask = phymask;
+ tmp_tgt->m_addr.mta_phymask = phymask;
tmp_tgt->m_phynum = phynum;
/* Initialized the tgt structure */
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;
- mptsas_hash_add(hashtab, tmp_tgt);
+ refhash_insert(mpt->m_targets, tmp_tgt);
return (tmp_tgt);
}
static void
-mptsas_tgt_free(mptsas_hash_table_t *hashtab, uint64_t wwid,
- mptsas_phymask_t phymask)
+mptsas_smp_target_copy(mptsas_smp_t *src, mptsas_smp_t *dst)
{
- mptsas_target_t *tmp_tgt;
- tmp_tgt = mptsas_hash_rem(hashtab, wwid, phymask);
- if (tmp_tgt == NULL) {
- cmn_err(CE_WARN, "Tgt not found, nothing to free");
- } else {
- kmem_free(tmp_tgt, sizeof (struct mptsas_target));
- }
+ dst->m_devhdl = src->m_devhdl;
+ dst->m_deviceinfo = src->m_deviceinfo;
+ dst->m_pdevhdl = src->m_pdevhdl;
+ dst->m_pdevinfo = src->m_pdevinfo;
}
-/*
- * Return the entry in the hash table
- */
static mptsas_smp_t *
-mptsas_smp_alloc(mptsas_hash_table_t *hashtab, mptsas_smp_t *data)
+mptsas_smp_alloc(mptsas_t *mpt, mptsas_smp_t *data)
{
- uint64_t key1 = data->m_sasaddr;
- mptsas_phymask_t key2 = data->m_phymask;
+ mptsas_target_addr_t addr;
mptsas_smp_t *ret_data;
- ret_data = mptsas_hash_search(hashtab, key1, key2);
+ addr.mta_wwn = data->m_addr.mta_wwn;
+ addr.mta_phymask = data->m_addr.mta_phymask;
+ ret_data = refhash_lookup(mpt->m_smp_targets, &addr);
+ /*
+ * If there's already a matching SMP target, update its fields
+ * in place. Since the address is not changing, it's safe to do
+ * this. We cannot just bcopy() here because the structure we've
+ * been given has invalid hash links.
+ */
if (ret_data != NULL) {
- bcopy(data, ret_data, sizeof (mptsas_smp_t));
+ mptsas_smp_target_copy(data, ret_data);
return (ret_data);
}
ret_data = kmem_alloc(sizeof (mptsas_smp_t), KM_SLEEP);
bcopy(data, ret_data, sizeof (mptsas_smp_t));
- mptsas_hash_add(hashtab, ret_data);
+ refhash_insert(mpt->m_smp_targets, ret_data);
return (ret_data);
}
-static void
-mptsas_smp_free(mptsas_hash_table_t *hashtab, uint64_t wwid,
- mptsas_phymask_t phymask)
-{
- mptsas_smp_t *tmp_smp;
- tmp_smp = mptsas_hash_rem(hashtab, wwid, phymask);
- if (tmp_smp == NULL) {
- cmn_err(CE_WARN, "Smp element not found, nothing to free");
- } else {
- kmem_free(tmp_smp, sizeof (struct mptsas_smp));
- }
-}
-
/*
- * Hash operation functions
- * key1 is the sas_wwn, key2 is the phymask
- */
-static void
-mptsas_hash_init(mptsas_hash_table_t *hashtab)
-{
- if (hashtab == NULL) {
- return;
- }
- bzero(hashtab->head, sizeof (mptsas_hash_node_t) *
- MPTSAS_HASH_ARRAY_SIZE);
- hashtab->cur = NULL;
- hashtab->line = 0;
-}
-
-static void
-mptsas_hash_uninit(mptsas_hash_table_t *hashtab, size_t datalen)
-{
- uint16_t line = 0;
- mptsas_hash_node_t *cur = NULL, *last = NULL;
-
- if (hashtab == NULL) {
- return;
- }
- for (line = 0; line < MPTSAS_HASH_ARRAY_SIZE; line++) {
- cur = hashtab->head[line];
- while (cur != NULL) {
- last = cur;
- cur = cur->next;
- kmem_free(last->data, datalen);
- kmem_free(last, sizeof (mptsas_hash_node_t));
- }
- }
-}
-
-/*
- * You must guarantee the element doesn't exist in the hash table
- * before you call mptsas_hash_add()
- */
-static void
-mptsas_hash_add(mptsas_hash_table_t *hashtab, void *data)
-{
- uint64_t key1 = ((mptsas_hash_data_t *)data)->key1;
- mptsas_phymask_t key2 = ((mptsas_hash_data_t *)data)->key2;
- mptsas_hash_node_t **head = NULL;
- mptsas_hash_node_t *node = NULL;
-
- if (hashtab == NULL) {
- return;
- }
- ASSERT(mptsas_hash_search(hashtab, key1, key2) == NULL);
- node = kmem_zalloc(sizeof (mptsas_hash_node_t), KM_NOSLEEP);
- node->data = data;
-
- head = &(hashtab->head[key1 % MPTSAS_HASH_ARRAY_SIZE]);
- if (*head == NULL) {
- *head = node;
- } else {
- node->next = *head;
- *head = node;
- }
-}
-
-static void *
-mptsas_hash_rem(mptsas_hash_table_t *hashtab, uint64_t key1,
- mptsas_phymask_t key2)
-{
- mptsas_hash_node_t **head = NULL;
- mptsas_hash_node_t *last = NULL, *cur = NULL;
- mptsas_hash_data_t *data;
- if (hashtab == NULL) {
- return (NULL);
- }
- head = &(hashtab->head[key1 % MPTSAS_HASH_ARRAY_SIZE]);
- cur = *head;
- while (cur != NULL) {
- data = cur->data;
- if ((data->key1 == key1) && (data->key2 == key2)) {
- if (last == NULL) {
- (*head) = cur->next;
- } else {
- last->next = cur->next;
- }
- kmem_free(cur, sizeof (mptsas_hash_node_t));
- return (data);
- } else {
- last = cur;
- cur = cur->next;
- }
- }
- return (NULL);
-}
-
-static void *
-mptsas_hash_search(mptsas_hash_table_t *hashtab, uint64_t key1,
- mptsas_phymask_t key2)
-{
- mptsas_hash_node_t *cur = NULL;
- mptsas_hash_data_t *data;
- if (hashtab == NULL) {
- return (NULL);
- }
- cur = hashtab->head[key1 % MPTSAS_HASH_ARRAY_SIZE];
- while (cur != NULL) {
- data = cur->data;
- if ((data->key1 == key1) && (data->key2 == key2)) {
- return (data);
- } else {
- cur = cur->next;
- }
- }
- return (NULL);
-}
-
-static void *
-mptsas_hash_traverse(mptsas_hash_table_t *hashtab, int pos)
-{
- mptsas_hash_node_t *this = NULL;
-
- if (hashtab == NULL) {
- return (NULL);
- }
-
- if (pos == MPTSAS_HASH_FIRST) {
- hashtab->line = 0;
- hashtab->cur = NULL;
- this = hashtab->head[0];
- } else {
- if (hashtab->cur == NULL) {
- return (NULL);
- } else {
- this = hashtab->cur->next;
- }
- }
-
- while (this == NULL) {
- hashtab->line++;
- if (hashtab->line >= MPTSAS_HASH_ARRAY_SIZE) {
- /* the traverse reaches the end */
- hashtab->cur = NULL;
- return (NULL);
- } else {
- this = hashtab->head[hashtab->line];
- }
- }
- hashtab->cur = this;
- return (this->data);
-}
-
-/*
* Functions for SGPIO LED support
*/
static dev_info_t *
mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask)
{
@@ -15572,11 +15390,11 @@
*
* 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_phymask == 0) {
+ ptgt->m_addr.mta_phymask == 0) {
return (ENOTTY);
}
bzero(&req, sizeof (req));
bzero(&rep, sizeof (rep));