summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith M Wesolowski <wesolows@foobazco.org>2013-11-19 01:03:50 +0000
committerKeith M Wesolowski <wesolows@foobazco.org>2014-01-03 00:24:12 +0000
commit53186cb50f3aa35193741112d72db0b7ff68ba71 (patch)
tree12e3e038a2f1177b91247fe028038b17281a8799
parent83a5265e15b06b463170d34d871849bfb5fcc592 (diff)
downloadillumos-joyent-53186cb50f3aa35193741112d72db0b7ff68ba71.tar.gz
OS-2616 mptsas_hash_traverse() is unsafe, leads to missing devices
-rw-r--r--usr/src/cmd/mdb/common/modules/mpt_sas/mpt_sas.c199
-rw-r--r--usr/src/uts/common/Makefile.files3
-rw-r--r--usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c909
-rw-r--r--usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_hash.c215
-rw-r--r--usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c2
-rw-r--r--usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_raid.c31
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_hash.h61
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_var.h77
8 files changed, 805 insertions, 692 deletions
diff --git a/usr/src/cmd/mdb/common/modules/mpt_sas/mpt_sas.c b/usr/src/cmd/mdb/common/modules/mpt_sas/mpt_sas.c
index fa6e1a578c..f2841e0260 100644
--- a/usr/src/cmd/mdb/common/modules/mpt_sas/mpt_sas.c
+++ b/usr/src/cmd/mdb/common/modules/mpt_sas/mpt_sas.c
@@ -23,10 +23,15 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright 2014 Joyent, Inc. All rights reserved.
+ */
+
#include <limits.h>
#include <sys/mdb_modapi.h>
#include <sys/sysinfo.h>
#include <sys/sunmdi.h>
+#include <sys/list.h>
#include <sys/scsi/scsi.h>
#pragma pack(1)
@@ -41,9 +46,9 @@
#pragma pack()
#include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
+#include <sys/scsi/adapters/mpt_sas/mptsas_hash.h>
struct {
-
int value;
char *text;
} devinfo_array[] = {
@@ -61,19 +66,6 @@ struct {
{ MPI2_SAS_DEVICE_INFO_SATA_HOST, "SATA host" }
};
-static int
-atoi(const char *p)
-{
- int n;
- int c = *p++;
-
- for (n = 0; c >= '0' && c <= '9'; c = *p++) {
- n *= 10; /* two steps to avoid unnecessary overflow */
- n += '0' - c; /* accum neg to avoid surprises at MAX */
- }
- return (-n);
-}
-
int
construct_path(uintptr_t addr, char *result)
{
@@ -116,8 +108,8 @@ mdi_info_cb(uintptr_t addr, const void *data, void *cbdata)
return (DCMD_ERR);
}
mdb_readstr(string, sizeof (string), (uintptr_t)pi.pi_addr);
- mdi_target = atoi(string);
- mdi_lun = atoi(strchr(string, ',')+1);
+ mdi_target = (int)mdb_strtoull(string);
+ mdi_lun = (int)mdb_strtoull(strchr(string, ',') + 1);
if (target != mdi_target)
return (0);
@@ -213,100 +205,130 @@ print_cdb(mptsas_cmd_t *m)
void
-display_ports(struct mptsas m)
+display_ports(struct mptsas *mp)
{
int i;
mdb_printf("\n");
mdb_printf("phy number and port mapping table\n");
for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
- if (m.m_phy_info[i].attached_devhdl) {
+ if (mp->m_phy_info[i].attached_devhdl) {
mdb_printf("phy %x --> port %x, phymask %x,"
- "attached_devhdl %x\n", i, m.m_phy_info[i].port_num,
- m.m_phy_info[i].phy_mask,
- m.m_phy_info[i].attached_devhdl);
+ "attached_devhdl %x\n", i, mp->m_phy_info[i].port_num,
+ mp->m_phy_info[i].phy_mask,
+ mp->m_phy_info[i].attached_devhdl);
}
}
mdb_printf("\n");
}
-static void *
-hash_traverse(mptsas_hash_table_t *hashtab, int pos, int alloc_size)
+
+static uintptr_t
+klist_head(list_t *lp, uintptr_t klp)
{
- mptsas_hash_node_t *this = NULL;
- mptsas_hash_node_t h;
- void *ret = NULL;
-
- if (pos == MPTSAS_HASH_FIRST) {
- hashtab->line = 0;
- hashtab->cur = NULL;
- this = hashtab->head[0];
- } else {
- if (hashtab->cur == NULL) {
- return (NULL);
- } else {
- mdb_vread(&h, sizeof (h), (uintptr_t)hashtab->cur);
- this = h.next;
- }
- }
+ if ((uintptr_t)lp->list_head.list_next ==
+ klp + offsetof(struct list, list_head))
+ return (NULL);
- 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 ((uintptr_t)(((char *)lp->list_head.list_next) -
+ lp->list_offset));
+}
+
+static uintptr_t
+klist_next(list_t *lp, uintptr_t klp, void *op)
+{
+ struct list_node *np = (struct list_node *)(((char *)op) +
+ lp->list_offset);
- if (mdb_vread(&h, sizeof (h), (uintptr_t)this) == -1) {
- mdb_warn("couldn't read hashtab");
+ if ((uintptr_t)np->list_next == klp + offsetof(struct list, list_head))
return (NULL);
+
+ return (((uintptr_t)(np->list_next)) - lp->list_offset);
+}
+
+static void *
+krefhash_first(uintptr_t khp)
+{
+ refhash_t mh;
+ uintptr_t klp;
+ uintptr_t kop;
+ void *rp;
+
+ mdb_vread(&mh, sizeof (mh), khp);
+ klp = klist_head(&mh.rh_objs, khp + offsetof(refhash_t, rh_objs));
+ if (klp == 0)
+ return (NULL);
+
+ kop = klp - mh.rh_link_off;
+ rp = mdb_alloc(mh.rh_obj_size, UM_SLEEP);
+ mdb_vread(rp, mh.rh_obj_size, kop);
+
+ return (rp);
+}
+
+static void *
+krefhash_next(uintptr_t khp, void *op)
+{
+ refhash_t mh;
+ void *prev = op;
+ refhash_link_t *lp;
+ uintptr_t klp;
+ uintptr_t kop;
+ refhash_link_t ml;
+ void *rp;
+
+ mdb_vread(&mh, sizeof (mh), khp);
+ lp = (refhash_link_t *)(((char *)(op)) + mh.rh_link_off);
+ ml = *lp;
+ while ((klp = klist_next(&mh.rh_objs,
+ khp + offsetof(refhash_t, rh_objs), &ml)) != NULL) {
+ mdb_vread(&ml, sizeof (ml), klp);
+ if (!(ml.rhl_flags & RHL_F_DEAD))
+ break;
}
- ret = mdb_alloc(alloc_size, UM_SLEEP);
- if (mdb_vread(ret, alloc_size, (uintptr_t)h.data) == -1) {
- mdb_warn("couldn't read hashdata");
+
+ if (klp == 0) {
+ mdb_free(prev, mh.rh_obj_size);
return (NULL);
}
- return (ret);
+
+ kop = klp - mh.rh_link_off;
+ rp = mdb_alloc(mh.rh_obj_size, UM_SLEEP);
+ mdb_vread(rp, mh.rh_obj_size, kop);
+
+ mdb_free(prev, mh.rh_obj_size);
+ return (rp);
}
+
void
-display_targets(struct mptsas_slots *s)
+display_targets(struct mptsas *mp)
{
mptsas_target_t *ptgt;
mptsas_smp_t *psmp;
mdb_printf("\n");
mdb_printf("The SCSI target information\n");
- ptgt = (mptsas_target_t *)hash_traverse(&s->m_tgttbl,
- MPTSAS_HASH_FIRST, sizeof (mptsas_target_t));
- while (ptgt != NULL) {
+ for (ptgt = (mptsas_target_t *)krefhash_first((uintptr_t)mp->m_targets);
+ ptgt != NULL;
+ ptgt = krefhash_next((uintptr_t)mp->m_targets, ptgt)) {
mdb_printf("\n");
mdb_printf("devhdl %x, sasaddress %"PRIx64", phymask %x,"
- "devinfo %x\n", ptgt->m_devhdl, ptgt->m_sas_wwn,
- ptgt->m_phymask, ptgt->m_deviceinfo);
+ "devinfo %x\n", ptgt->m_devhdl, ptgt->m_addr.mta_wwn,
+ ptgt->m_addr.mta_phymask, ptgt->m_deviceinfo);
mdb_printf("throttle %x, dr_flag %x, m_t_ncmds %x, "
"enclosure %x, slot_num %x\n", ptgt->m_t_throttle,
ptgt->m_dr_flag, ptgt->m_t_ncmds, ptgt->m_enclosure,
ptgt->m_slot_num);
-
- mdb_free(ptgt, sizeof (mptsas_target_t));
- ptgt = (mptsas_target_t *)hash_traverse(
- &s->m_tgttbl, MPTSAS_HASH_NEXT, sizeof (mptsas_target_t));
}
+
mdb_printf("\n");
mdb_printf("The smp child information\n");
- psmp = (mptsas_smp_t *)hash_traverse(&s->m_smptbl,
- MPTSAS_HASH_FIRST, sizeof (mptsas_smp_t));
- while (psmp != NULL) {
+ for (psmp = (mptsas_smp_t *)krefhash_first(
+ (uintptr_t)mp->m_smp_targets);
+ psmp != NULL;
+ psmp = krefhash_next((uintptr_t)mp->m_smp_targets, psmp)) {
mdb_printf("\n");
mdb_printf("devhdl %x, sasaddress %"PRIx64", phymask %x \n",
- psmp->m_devhdl, psmp->m_sasaddr, psmp->m_phymask);
-
- mdb_free(psmp, sizeof (mptsas_smp_t));
- psmp = (mptsas_smp_t *)hash_traverse(
- &s->m_smptbl, MPTSAS_HASH_NEXT, sizeof (mptsas_smp_t));
+ psmp->m_devhdl, psmp->m_addr.mta_wwn,
+ psmp->m_addr.mta_phymask);
}
mdb_printf("\n");
#if 0
@@ -315,11 +337,12 @@ display_targets(struct mptsas_slots *s)
mdb_printf("-------------------------------"
"--------------------------------\n");
for (i = 0; i < MPTSAS_MAX_TARGETS; i++) {
- if (s->m_target[i].m_sas_wwn || s->m_target[i].m_deviceinfo) {
+ if (s->m_target[i].m_addr.mta_wwn ||
+ s->m_target[i].m_deviceinfo) {
mdb_printf("%4d ", i);
- if (s->m_target[i].m_sas_wwn)
+ if (s->m_target[i].m_addr.mta_wwn)
mdb_printf("%"PRIx64" ",
- s->m_target[i].m_sas_wwn);
+ s->m_target[i].m_addr.mta_wwn);
mdb_printf("%3d", s->m_target[i].m_t_ncmds);
switch (s->m_target[i].m_t_throttle) {
case QFULL_THROTTLE:
@@ -429,7 +452,7 @@ display_slotinfo()
int ncmds = 0;
ulong_t saved_indent;
- nslots = s->m_n_slots;
+ nslots = s->m_n_normal;
slots = mdb_alloc(sizeof (mptsas_cmd_t) * nslots, UM_SLEEP);
@@ -482,7 +505,7 @@ display_slotinfo()
saved_indent = mdb_dec_indent(0);
mdb_dec_indent(saved_indent);
- for (i = 0; i < s->m_n_slots; i++)
+ for (i = 0; i < s->m_n_normal; i++)
if (s->m_slot[i]) {
if (!header_output) {
mdb_printf("\n");
@@ -604,12 +627,12 @@ exit:
}
void
-display_deviceinfo(struct mptsas m)
+display_deviceinfo(struct mptsas *mp)
{
char device_path[PATH_MAX];
*device_path = 0;
- if (construct_path((uintptr_t)m.m_dip, device_path) != DCMD_OK) {
+ if (construct_path((uintptr_t)mp->m_dip, device_path) != DCMD_OK) {
strcpy(device_path, "couldn't determine device path");
}
@@ -694,7 +717,7 @@ static int
mptsas_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
struct mptsas m;
- struct mptsas_slots *s;
+ struct mptsas_slots *s;
int nslots;
int slot_size = 0;
@@ -745,7 +768,7 @@ mptsas_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (DCMD_ERR);
}
- nslots = s->m_n_slots;
+ nslots = s->m_n_normal;
mdb_free(s, sizeof (mptsas_slots_t));
@@ -798,13 +821,13 @@ mptsas_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_inc_indent(17);
if (target_info)
- display_targets(s);
+ display_targets(&m);
if (port_info)
- display_ports(m);
+ display_ports(&m);
if (device_info)
- display_deviceinfo(m);
+ display_deviceinfo(&m);
if (slot_info)
display_slotinfo();
@@ -815,9 +838,7 @@ mptsas_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
return (rv);
}
-/*
- * Only -t is implemented now, will add more later when the driver is stable
- */
+
void
mptsas_help()
{
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index a706bfca8a..9c19ebf1a5 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -1853,7 +1853,8 @@ ZYD_OBJS += zyd.o zyd_usb.o zyd_hw.o zyd_fw.o
MXFE_OBJS += mxfe.o
-MPTSAS_OBJS += mptsas.o mptsas_impl.o mptsas_init.o mptsas_raid.o mptsas_smhba.o
+MPTSAS_OBJS += mptsas.o mptsas_hash.o mptsas_impl.o mptsas_init.o \
+ mptsas_raid.o mptsas_smhba.o
SFE_OBJS += sfe.o sfe_util.o
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 e5c6c6ee69..9ad7c417a0 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
@@ -22,7 +22,7 @@
/*
* 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.
*/
/*
@@ -96,6 +96,7 @@
#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 */
@@ -335,12 +336,12 @@ 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);
@@ -406,23 +407,9 @@ 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);
@@ -694,6 +681,101 @@ _info(struct modinfo *modinfop)
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)
@@ -1403,11 +1485,12 @@ fail:
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) {
@@ -1840,12 +1923,12 @@ mptsas_do_detach(dev_info_t *dip)
*/
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);
@@ -2103,7 +2186,11 @@ mptsas_smp_setup(mptsas_t *mpt)
/*
* 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);
@@ -2746,8 +2833,9 @@ mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
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);
@@ -2763,7 +2851,7 @@ mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
/*
* 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) {
@@ -2801,9 +2889,12 @@ mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
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 "
@@ -3234,79 +3325,63 @@ mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
int
mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
{
- mptsas_slots_t *slots;
- int slot;
- mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
+ 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));
- cmd->cmd_slot = slot;
- slots->m_slot[slot] = cmd;
- mpt->m_ncmds++;
+ if (slots->m_rotor == start_rotor)
+ break;
+ } while (slots->m_slot[slot] != NULL);
- /*
- * only increment per target ncmds if this is not a
- * command that has no target associated with it (i.e. a
- * event acknoledgment)
- */
- if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
- ptgt->m_t_ncmds++;
- }
- cmd->cmd_active_timeout = cmd->cmd_pkt->pkt_time;
+ if (slots->m_slot[slot] != NULL)
+ return (FALSE);
- /*
- * If initial timout is less than or equal to one tick, bump
- * the timeout by a tick so that command doesn't timeout before
- * its allotted time.
- */
- if (cmd->cmd_active_timeout <= mptsas_scsi_watchdog_tick) {
- cmd->cmd_active_timeout += mptsas_scsi_watchdog_tick;
- }
- return (TRUE);
- } else {
- int i;
+ ASSERT(slot != 0 && slot <= slots->m_n_normal);
- /*
- * 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;
- }
- }
+ cmd->cmd_slot = slot;
+ slots->m_slot[slot] = cmd;
+ mpt->m_ncmds++;
+
+ /*
+ * only increment per target ncmds if this is not a
+ * command that has no target associated with it (i.e. a
+ * event acknoledgment)
+ */
+ if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
+ ptgt->m_t_ncmds++;
}
- return (FALSE);
+ cmd->cmd_active_timeout = cmd->cmd_pkt->pkt_time;
+
+ /*
+ * If initial timout is less than or equal to one tick, bump
+ * the timeout by a tick so that command doesn't timeout before
+ * its allotted time.
+ */
+ if (cmd->cmd_active_timeout <= mptsas_scsi_watchdog_tick) {
+ cmd->cmd_active_timeout += mptsas_scsi_watchdog_tick;
+ }
+ return (TRUE);
}
/*
@@ -4647,7 +4722,7 @@ mptsas_handle_scsi_io_success(mptsas_t *mpt,
* 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);
@@ -4750,7 +4825,7 @@ mptsas_handle_address_reply(mptsas_t *mpt,
* 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,
@@ -5067,7 +5142,7 @@ mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
}
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;
@@ -5133,13 +5208,9 @@ mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
/*
* 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);
}
/*
@@ -5830,8 +5901,8 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
* 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 {
@@ -5880,7 +5951,7 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
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,
@@ -5919,7 +5990,7 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
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,
@@ -5977,18 +6048,18 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
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);
@@ -6016,8 +6087,8 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
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);
@@ -6029,7 +6100,7 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
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);
@@ -6072,8 +6143,7 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
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 {
/*
@@ -6130,7 +6200,6 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
{
mptsas_smp_t smp;
dev_info_t *smpdip;
- mptsas_hash_table_t *smptbl = &mpt->m_active->m_smptbl;
devhdl = topo_node->devhdl;
@@ -6143,7 +6212,7 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
return;
}
- psmp = mptsas_smp_alloc(smptbl, &smp);
+ psmp = mptsas_smp_alloc(mpt, &smp);
if (psmp == NULL) {
return;
}
@@ -6158,11 +6227,11 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
}
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;
/*
@@ -6218,8 +6287,7 @@ mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
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;
}
@@ -6378,15 +6446,11 @@ mptsas_handle_event_sync(void *args)
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;
@@ -6432,8 +6496,8 @@ mptsas_handle_event_sync(void *args)
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;
@@ -6441,7 +6505,8 @@ mptsas_handle_event_sync(void *args)
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;
@@ -6592,8 +6657,8 @@ mptsas_handle_event_sync(void *args)
* 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
@@ -6645,7 +6710,8 @@ mptsas_handle_event_sync(void *args)
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;
@@ -6805,7 +6871,6 @@ mptsas_handle_event_sync(void *args)
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;
@@ -6814,8 +6879,6 @@ mptsas_handle_event_sync(void *args)
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));
@@ -6859,8 +6922,8 @@ mptsas_handle_event_sync(void *args)
{
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;
@@ -6880,7 +6943,8 @@ mptsas_handle_event_sync(void *args)
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;
@@ -6898,8 +6962,8 @@ mptsas_handle_event_sync(void *args)
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;
@@ -6914,7 +6978,8 @@ mptsas_handle_event_sync(void *args)
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;
@@ -7339,7 +7404,6 @@ mptsas_handle_event(void *args)
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;
@@ -7356,10 +7420,10 @@ mptsas_handle_event(void *args)
* 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;
@@ -7374,7 +7438,7 @@ mptsas_handle_event(void *args)
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;
@@ -7397,7 +7461,7 @@ mptsas_handle_event(void *args)
}
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,
@@ -7419,7 +7483,7 @@ mptsas_handle_event(void *args)
}
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,
@@ -7568,18 +7632,14 @@ mptsas_restart_cmd(void *arg)
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);
@@ -7651,14 +7711,14 @@ mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
* 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
@@ -8417,7 +8477,6 @@ 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));
@@ -8432,9 +8491,9 @@ mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl)
* 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);
}
@@ -8530,7 +8589,7 @@ mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun, uint8_t tasktype)
* 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;
@@ -8662,7 +8721,7 @@ mptsas_flush_hba(mptsas_t *mpt)
* 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;
@@ -8777,15 +8836,13 @@ 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();
@@ -8837,9 +8894,8 @@ mptsas_watch_reset_delay_subr(mptsas_t *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;
@@ -8852,9 +8908,6 @@ mptsas_watch_reset_delay_subr(mptsas_t *mpt)
done = -1;
}
}
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
if (restart > 0) {
@@ -9158,7 +9211,6 @@ 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
@@ -9170,31 +9222,21 @@ mptsas_alloc_active_slots(mptsas_t *mpt, int flag)
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
@@ -9339,6 +9381,8 @@ mptsas_watchsubr(mptsas_t *mpt)
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
@@ -9351,7 +9395,7 @@ mptsas_watchsubr(mptsas_t *mpt)
* 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 -=
@@ -9385,9 +9429,8 @@ mptsas_watchsubr(mptsas_t *mpt)
}
}
- 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.
@@ -9406,8 +9449,6 @@ mptsas_watchsubr(mptsas_t *mpt)
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;
}
@@ -9415,8 +9456,6 @@ mptsas_watchsubr(mptsas_t *mpt)
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;
}
@@ -9427,9 +9466,6 @@ mptsas_watchsubr(mptsas_t *mpt)
DRAIN_THROTTLE);
}
}
-
- ptgt = (mptsas_target_t *)mptsas_hash_traverse(
- &mpt->m_active->m_tgttbl, MPTSAS_HASH_NEXT);
}
}
@@ -9493,13 +9529,9 @@ mptsas_quiesce_bus(mptsas_t *mpt)
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 */
@@ -9512,13 +9544,9 @@ mptsas_quiesce_bus(mptsas_t *mpt)
* 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) {
@@ -9553,13 +9581,9 @@ mptsas_unquiesce_bus(mptsas_t *mpt)
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);
@@ -9583,13 +9607,9 @@ mptsas_ncmds_checkdrain(void *arg)
* 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,
@@ -11321,16 +11341,8 @@ led_control(mptsas_t *mpt, intptr_t data, int mode)
/* 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);
@@ -11381,12 +11393,9 @@ get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
/* 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);
@@ -11411,14 +11420,14 @@ get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
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);
@@ -11426,10 +11435,7 @@ get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
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);
@@ -11735,13 +11741,9 @@ mptsas_restart_ioc(mptsas_t *mpt)
/*
* 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);
}
/*
@@ -11777,13 +11779,9 @@ mptsas_restart_ioc(mptsas_t *mpt)
/*
* 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);
@@ -11849,6 +11847,12 @@ mptsas_init_chip(mptsas_t *mpt, int first_time)
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;
}
@@ -12487,7 +12491,6 @@ mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
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;
@@ -12514,9 +12517,9 @@ mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
* 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);
@@ -12526,7 +12529,7 @@ mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
/*
* 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.
*/
@@ -12553,7 +12556,7 @@ mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
}
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"
@@ -12983,7 +12986,7 @@ mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
* 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
@@ -13012,13 +13015,13 @@ mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
{
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);
@@ -13105,7 +13108,7 @@ mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt)
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);
@@ -13220,7 +13223,8 @@ mptsas_config_raid(dev_info_t *pdip, uint16_t target, dev_info_t **dip)
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 "
@@ -13253,18 +13257,17 @@ mptsas_config_all_viport(dev_info_t *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,
@@ -13292,7 +13295,7 @@ mptsas_offline_missed_luns(dev_info_t *pdip, uint16_t *repluns,
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);
@@ -13396,7 +13399,7 @@ mptsas_update_hashtab(struct mptsas *mpt)
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);
}
/*
@@ -13428,24 +13431,13 @@ mptsas_update_hashtab(struct mptsas *mpt)
}
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
@@ -13456,9 +13448,24 @@ mptsas_update_driver_data(struct mptsas *mpt)
mptsas_update_phymask(mpt);
/*
* Invalid the existing entries
- */
- mptsas_invalid_hashtab(&mpt->m_active->m_tgttbl);
- mptsas_invalid_hashtab(&mpt->m_active->m_smptbl);
+ *
+ * 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?
+ */
+ 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;
@@ -13495,32 +13502,25 @@ mptsas_config_all(dev_info_t *pdip)
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);
}
@@ -13702,7 +13702,7 @@ mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, uint_t flags)
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);
@@ -13982,7 +13982,7 @@ mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *inq, char *guid,
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);
@@ -14331,7 +14331,7 @@ mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *inq,
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);
@@ -14450,7 +14450,7 @@ mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *inq,
* 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);
@@ -14604,7 +14604,7 @@ phys_raid_lun:
/*
* 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) {
@@ -14726,13 +14726,13 @@ mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
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);
}
@@ -14760,7 +14760,7 @@ mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
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) {
@@ -15044,7 +15044,7 @@ static int mptsas_smp_start(struct smp_pkt *smp_pkt)
* 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;
@@ -15076,16 +15076,11 @@ mptsas_phy_to_tgt(mptsas_t *mpt, int phymask, uint8_t phy)
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)) {
- mutex_exit(&mpt->m_mutex);
- return (ptgt);
- }
-
- 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_nowwn,
+ &phy);
+ if (ptgt != NULL) {
+ mutex_exit(&mpt->m_mutex);
+ return (ptgt);
}
if (mpt->m_done_traverse_dev) {
@@ -15111,7 +15106,7 @@ mptsas_phy_to_tgt(mptsas_t *mpt, int phymask, uint8_t phy)
}
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;
}
}
@@ -15121,23 +15116,25 @@ mptsas_phy_to_tgt(mptsas_t *mpt, int phymask, uint8_t phy)
}
/*
- * 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);
@@ -15149,8 +15146,7 @@ mptsas_wwid_to_ptgt(mptsas_t *mpt, int phymask, uint64_t wwid)
*/
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);
@@ -15163,7 +15159,7 @@ mptsas_wwid_to_ptgt(mptsas_t *mpt, int phymask, uint64_t wwid)
/* 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;
@@ -15179,8 +15175,9 @@ mptsas_wwid_to_ptgt(mptsas_t *mpt, int phymask, uint64_t wwid)
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;
}
}
@@ -15190,16 +15187,18 @@ 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)
+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);
@@ -15212,7 +15211,7 @@ mptsas_wwid_to_psmp(mptsas_t *mpt, int phymask, uint64_t wwid)
/* 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;
@@ -15222,10 +15221,10 @@ mptsas_wwid_to_psmp(mptsas_t *mpt, int phymask, uint64_t wwid)
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;
}
}
@@ -15234,38 +15233,20 @@ mptsas_wwid_to_psmp(mptsas_t *mpt, int phymask, uint64_t wwid)
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);
@@ -15274,9 +15255,9 @@ mptsas_tgt_alloc(mptsas_hash_table_t *hashtab, uint16_t devhdl, uint64_t wwid,
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;
@@ -15284,209 +15265,31 @@ mptsas_tgt_alloc(mptsas_hash_table_t *hashtab, uint16_t devhdl, uint64_t wwid,
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_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));
- }
-}
-
-/*
- * 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 (ret_data != NULL) {
- bcopy(data, ret_data, sizeof (mptsas_smp_t));
+ bcopy(data, ret_data, sizeof (mptsas_smp_t)); /* XXX - dupl */
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
*/
@@ -15570,7 +15373,7 @@ mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
* 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);
}
diff --git a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_hash.c b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_hash.c
new file mode 100644
index 0000000000..8f96c2d9f1
--- /dev/null
+++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_hash.c
@@ -0,0 +1,215 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Joyent, Inc. All rights reserved.
+ */
+
+#include <sys/scsi/adapters/mpt_sas/mptsas_hash.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <sys/kmem.h>
+#include <sys/list.h>
+#include <sys/ddi.h>
+
+#ifdef lint
+extern refhash_link_t *obj_to_link(refhash_t *, void *);
+extern void *link_to_obj(refhash_t *, refhash_link_t *);
+extern void *obj_to_tag(refhash_t *, void *);
+#else
+#define obj_to_link(_h, _o) \
+ ((refhash_link_t *)(((char *)(_o)) + (_h)->rh_link_off))
+#define link_to_obj(_h, _l) \
+ ((void *)(((char *)(_l)) - (_h)->rh_link_off))
+#define obj_to_tag(_h, _o) \
+ ((void *)(((char *)(_o)) + (_h)->rh_tag_off))
+#endif
+
+refhash_t *
+refhash_create(uint_t bucket_count, refhash_hash_f hash,
+ refhash_cmp_f cmp, refhash_dtor_f dtor, size_t obj_size, size_t link_off,
+ size_t tag_off, int km_flags)
+{
+ refhash_t *hp;
+ uint_t i;
+
+ hp = kmem_alloc(sizeof (refhash_t), km_flags);
+ if (hp == NULL)
+ return (NULL);
+ hp->rh_buckets = kmem_zalloc(bucket_count * sizeof (list_t), km_flags);
+ if (hp->rh_buckets == NULL) {
+ kmem_free(hp, sizeof (refhash_t));
+ return (NULL);
+ }
+ hp->rh_bucket_count = bucket_count;
+
+ for (i = 0; i < bucket_count; i++) {
+ list_create(&hp->rh_buckets[i], sizeof (refhash_link_t),
+ offsetof(refhash_link_t, rhl_chain_link));
+ }
+ list_create(&hp->rh_objs, sizeof (refhash_link_t),
+ offsetof(refhash_link_t, rhl_global_link));
+
+ hp->rh_obj_size = obj_size;
+ hp->rh_link_off = link_off;
+ hp->rh_tag_off = tag_off;
+ hp->rh_hash = hash;
+ hp->rh_cmp = cmp;
+ hp->rh_dtor = dtor;
+
+ return (hp);
+}
+
+void
+refhash_destroy(refhash_t *hp)
+{
+ ASSERT(list_is_empty(&hp->rh_objs));
+
+ kmem_free(hp->rh_buckets, hp->rh_bucket_count * sizeof (list_t));
+ kmem_free(hp, sizeof (refhash_t));
+}
+
+void
+refhash_insert(refhash_t *hp, void *op)
+{
+ uint_t bucket;
+ refhash_link_t *lp = obj_to_link(hp, op);
+
+ bucket = hp->rh_hash(obj_to_tag(hp, op)) % hp->rh_bucket_count;
+ list_link_init(&lp->rhl_chain_link);
+ list_link_init(&lp->rhl_global_link);
+ lp->rhl_flags = 0;
+ lp->rhl_refcnt = 0;
+ list_insert_tail(&hp->rh_buckets[bucket], lp);
+ list_insert_tail(&hp->rh_objs, lp);
+}
+
+static void
+refhash_delete(refhash_t *hp, void *op)
+{
+ refhash_link_t *lp = obj_to_link(hp, op);
+ uint_t bucket;
+
+ bucket = hp->rh_hash(obj_to_tag(hp, op)) % hp->rh_bucket_count;
+ list_remove(&hp->rh_buckets[bucket], lp);
+ list_remove(&hp->rh_objs, lp);
+ hp->rh_dtor(op);
+}
+
+void
+refhash_remove(refhash_t *hp, void *op)
+{
+ refhash_link_t *lp = obj_to_link(hp, op);
+
+ if (lp->rhl_refcnt > 0) {
+ lp->rhl_flags |= RHL_F_DEAD;
+ } else {
+ refhash_delete(hp, op);
+ }
+}
+
+void *
+refhash_lookup(refhash_t *hp, const void *tp)
+{
+ uint_t bucket;
+ refhash_link_t *lp;
+ void *op;
+
+ bucket = hp->rh_hash(tp) % hp->rh_bucket_count;
+ for (lp = list_head(&hp->rh_buckets[bucket]); lp != NULL;
+ lp = list_next(&hp->rh_buckets[bucket], lp)) {
+ op = link_to_obj(hp, lp);
+ if (hp->rh_cmp(obj_to_tag(hp, op), tp) == 0 &&
+ !(lp->rhl_flags & RHL_F_DEAD)) {
+ return (op);
+ }
+ }
+
+ return (NULL);
+}
+
+void *
+refhash_linear_search(refhash_t *hp, refhash_eval_f eval, void *arg)
+{
+ void *op;
+ refhash_link_t *lp;
+
+ for (lp = list_head(&hp->rh_objs); lp != NULL;
+ lp = list_next(&hp->rh_objs, lp)) {
+ op = link_to_obj(hp, lp);
+ if (eval(op, arg) == 0)
+ return (op);
+ }
+
+ return (NULL);
+}
+
+void
+refhash_hold(refhash_t *hp, void *op)
+{
+ refhash_link_t *lp = obj_to_link(hp, op);
+
+ ++lp->rhl_refcnt;
+}
+
+void
+refhash_rele(refhash_t *hp, void *op)
+{
+ refhash_link_t *lp = obj_to_link(hp, op);
+
+ ASSERT(lp->rhl_refcnt > 0);
+
+ if (--lp->rhl_refcnt == 0 && (lp->rhl_flags & RHL_F_DEAD))
+ refhash_remove(hp, op);
+}
+
+void *
+refhash_first(refhash_t *hp)
+{
+ refhash_link_t *lp;
+
+ lp = list_head(&hp->rh_objs);
+ if (lp == NULL)
+ return (NULL);
+
+ ++lp->rhl_refcnt;
+
+ return (link_to_obj(hp, lp));
+}
+
+void *
+refhash_next(refhash_t *hp, void *op)
+{
+ refhash_link_t *lp;
+
+ lp = obj_to_link(hp, op);
+ while ((lp = list_next(&hp->rh_objs, lp)) != NULL) {
+ if (!(lp->rhl_flags & RHL_F_DEAD))
+ break;
+ }
+
+ refhash_rele(hp, op);
+ if (lp == NULL)
+ return (NULL);
+
+ ++lp->rhl_refcnt;
+
+ return (link_to_obj(hp, lp));
+}
+
+boolean_t
+refhash_obj_valid(refhash_t *hp, const void *op)
+{
+ /* LINTED - E_ARG_INCOMPATIBLE_WITH_ARG_L */
+ const refhash_link_t *lp = obj_to_link(hp, op);
+
+ return ((lp->rhl_flags & RHL_F_DEAD) != 0);
+}
diff --git a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c
index 03da007e7c..9f1bf7156b 100644
--- a/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c
+++ b/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_impl.c
@@ -1522,7 +1522,7 @@ mptsas_get_sas_expander_page0(mptsas_t *mpt, uint32_t page_address,
MPI2_CONFIG_ACTION_PAGE_READ_CURRENT,
MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER, 0, page_address,
mptsas_sasexpdpage_0_cb, page_address, &info->m_devhdl,
- &info->m_sasaddr, &info->m_phymask, &info->m_pdevhdl);
+ &info->m_addr.mta_wwn, &info->m_addr.mta_phymask, &info->m_pdevhdl);
return (rval);
}
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 e01fcd95a7..a9e210974d 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
@@ -91,7 +91,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_hash_table_t *, uint16_t,
+extern mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t,
uint64_t, uint32_t, mptsas_phymask_t, uint8_t);
static int
@@ -110,7 +110,6 @@ mptsas_raidconf_page_0_cb(mptsas_t *mpt, caddr_t page_memp,
uint16_t elementtype, voldevhandle;
uint16_t etype_vol, etype_pd, etype_hs;
uint16_t etype_oce;
- mptsas_slots_t *slots = mpt->m_active;
m_raidconfig_t *raidconfig;
uint64_t raidwwn;
uint32_t native;
@@ -148,8 +147,8 @@ mptsas_raidconf_page_0_cb(mptsas_t *mpt, caddr_t page_memp,
* Point to the right config in the structure.
* Increment the number of valid RAID configs.
*/
- raidconfig = &slots->m_raidconfig[configindex];
- slots->m_num_raid_configs++;
+ raidconfig = &mpt->m_raidconfig[configindex];
+ mpt->m_num_raid_configs++;
/*
* Set the native flag if this is not a foreign
@@ -216,7 +215,7 @@ mptsas_raidconf_page_0_cb(mptsas_t *mpt, caddr_t page_memp,
/*
* RAID uses phymask of 0.
*/
- ptgt = mptsas_tgt_alloc(&slots->m_tgttbl,
+ ptgt = mptsas_tgt_alloc(mpt,
voldevhandle, raidwwn, 0, 0, 0);
raidconfig->m_raidvol[vol].m_raidtgt =
@@ -258,15 +257,14 @@ mptsas_get_raid_info(mptsas_t *mpt)
int rval = DDI_SUCCESS;
uint32_t confignum, pageaddress;
uint8_t configindex;
- mptsas_slots_t *slots = mpt->m_active;
ASSERT(mutex_owned(&mpt->m_mutex));
/*
* Clear all RAID info before starting.
*/
- bzero(slots->m_raidconfig, sizeof (slots->m_raidconfig));
- slots->m_num_raid_configs = 0;
+ bzero(mpt->m_raidconfig, sizeof (mpt->m_raidconfig));
+ mpt->m_num_raid_configs = 0;
configindex = 0;
confignum = 0xff;
@@ -586,10 +584,10 @@ mptsas_raid_action_system_shutdown(mptsas_t *mpt)
* supports IR and make sure there is a valid volume for the request.
*/
if (mpt->m_ir_capable) {
- for (config = 0; (config < slots->m_num_raid_configs) &&
+ for (config = 0; (config < mpt->m_num_raid_configs) &&
(!ir_active); 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_israid) {
ir_active = TRUE;
break;
@@ -758,12 +756,11 @@ int
mptsas_delete_volume(mptsas_t *mpt, uint16_t volid)
{
int config, i = 0, vol = (-1);
- mptsas_slots_t *slots = mpt->m_active;
- for (config = 0; (config < slots->m_num_raid_configs) && (vol != i);
+ for (config = 0; (config < mpt->m_num_raid_configs) && (vol != i);
config++) {
for (i = 0; i < MPTSAS_MAX_RAIDVOLS; i++) {
- if (slots->m_raidconfig[config].m_raidvol[i].
+ if (mpt->m_raidconfig[config].m_raidvol[i].
m_raidhandle == volid) {
vol = i;
break;
@@ -777,11 +774,11 @@ mptsas_delete_volume(mptsas_t *mpt, uint16_t volid)
return (-1);
}
- slots->m_raidconfig[config].m_raidvol[vol].m_israid = 0;
- slots->m_raidconfig[config].m_raidvol[vol].m_ndisks = 0;
+ mpt->m_raidconfig[config].m_raidvol[vol].m_israid = 0;
+ mpt->m_raidconfig[config].m_raidvol[vol].m_ndisks = 0;
for (i = 0; i < MPTSAS_MAX_DISKS_IN_VOL; i++) {
- slots->m_raidconfig[config].m_raidvol[vol].m_disknum[i] = 0;
- slots->m_raidconfig[config].m_raidvol[vol].m_devhdl[i] = 0;
+ mpt->m_raidconfig[config].m_raidvol[vol].m_disknum[i] = 0;
+ mpt->m_raidconfig[config].m_raidvol[vol].m_devhdl[i] = 0;
}
return (0);
diff --git a/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_hash.h b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_hash.h
new file mode 100644
index 0000000000..2069e6d3f1
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/mpt_sas/mptsas_hash.h
@@ -0,0 +1,61 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Joyent, Inc. All rights reserved.
+ */
+
+#ifndef _SYS_SCSI_ADAPTERS_MPTHASH_H
+#define _SYS_SCSI_ADAPTERS_MPTHASH_H
+
+#include <sys/types.h>
+#include <sys/list.h>
+
+#define RHL_F_DEAD 0x01
+
+typedef struct refhash_link {
+ list_node_t rhl_chain_link;
+ list_node_t rhl_global_link;
+ uint_t rhl_flags;
+ uint_t rhl_refcnt;
+} refhash_link_t;
+
+typedef uint64_t (*refhash_hash_f)(const void *);
+typedef int (*refhash_cmp_f)(const void *, const void *);
+typedef void (*refhash_dtor_f)(void *);
+typedef int (*refhash_eval_f)(const void *, void *);
+
+typedef struct refhash {
+ list_t *rh_buckets;
+ uint_t rh_bucket_count;
+ list_t rh_objs;
+ size_t rh_obj_size; /* used by mdb */
+ size_t rh_link_off;
+ size_t rh_tag_off;
+ refhash_hash_f rh_hash;
+ refhash_cmp_f rh_cmp;
+ refhash_dtor_f rh_dtor;
+} refhash_t;
+
+extern refhash_t *refhash_create(uint_t, refhash_hash_f, refhash_cmp_f,
+ refhash_dtor_f, size_t, size_t, size_t, int);
+extern void refhash_destroy(refhash_t *);
+extern void refhash_insert(refhash_t *, void *);
+extern void refhash_remove(refhash_t *, void *);
+extern void *refhash_lookup(refhash_t *, const void *);
+extern void *refhash_linear_search(refhash_t *, refhash_eval_f, void *);
+extern void refhash_hold(refhash_t *, void *);
+extern void refhash_rele(refhash_t *, void *);
+extern void *refhash_first(refhash_t *);
+extern void *refhash_next(refhash_t *, void *);
+extern boolean_t refhash_obj_valid(refhash_t *hp, const void *);
+
+#endif /* _SYS_SCSI_ADAPTERS_MPTHASH_H */
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 19975b008c..9768c4ea80 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
@@ -59,6 +59,7 @@
#include <sys/isa_defs.h>
#include <sys/sunmdi.h>
#include <sys/mdi_impldefs.h>
+#include <sys/scsi/adapters/mpt_sas/mptsas_hash.h>
#include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
@@ -90,6 +91,15 @@ typedef uint16_t mptsas_phymask_t;
#define MPTSAS_SATA_GUID "sata-guid"
/*
+ * Hash table sizes for SMP targets (i.e., expanders) and ordinary SSP/STP
+ * targets. There's no need to go overboard here, as the ordinary paths for
+ * I/O do not normally require hashed target lookups. These should be good
+ * enough and then some for any fabric within the hardware's capabilities.
+ */
+#define MPTSAS_SMP_BUCKET_COUNT 23
+#define MPTSAS_TARGET_BUCKET_COUNT 97
+
+/*
* MPT HW defines
*/
#define MPTSAS_MAX_DISKS_IN_CONFIG 14
@@ -185,14 +195,15 @@ typedef struct NcrTableIndirect { /* Table Indirect entries */
#define MPTSAS_RAID_WWID(wwid) \
((wwid & 0x0FFFFFFFFFFFFFFF) | 0x3000000000000000)
+typedef struct mptsas_target_addr {
+ uint64_t mta_wwn;
+ mptsas_phymask_t mta_phymask;
+} mptsas_target_addr_t;
+
typedef struct mptsas_target {
- uint64_t m_sas_wwn; /* hash key1 */
- mptsas_phymask_t m_phymask; /* hash key2 */
- /*
- * m_dr_flag is a flag for DR, make sure the member
- * take the place of dr_flag of mptsas_hash_data.
- */
- uint8_t m_dr_flag; /* dr_flag */
+ mptsas_target_addr_t m_addr;
+ refhash_link_t m_link;
+ uint8_t m_dr_flag;
uint16_t m_devhdl;
uint32_t m_deviceinfo;
uint8_t m_phynum;
@@ -214,23 +225,14 @@ typedef struct mptsas_target {
} mptsas_target_t;
typedef struct mptsas_smp {
- uint64_t m_sasaddr; /* hash key1 */
- mptsas_phymask_t m_phymask; /* hash key2 */
- uint8_t reserved1;
- uint16_t m_devhdl;
- uint32_t m_deviceinfo;
- uint16_t m_pdevhdl;
- uint32_t m_pdevinfo;
+ mptsas_target_addr_t m_addr;
+ refhash_link_t m_link;
+ uint16_t m_devhdl;
+ uint32_t m_deviceinfo;
+ uint16_t m_pdevhdl;
+ uint32_t m_pdevinfo;
} mptsas_smp_t;
-typedef struct mptsas_hash_data {
- uint64_t key1;
- mptsas_phymask_t key2;
- uint8_t dr_flag;
- uint16_t devhdl;
- uint32_t device_info;
-} mptsas_hash_data_t;
-
typedef struct mptsas_cache_frames {
ddi_dma_handle_t m_dma_hdl;
ddi_acc_handle_t m_acc_hdl;
@@ -445,17 +447,24 @@ typedef struct mptsas_raidconfig {
} m_raidconfig_t;
/*
- * Structure to hold active outstanding cmds. Also, keep
- * timeout on a per target basis.
+ * Track outstanding commands. The index into the m_slot array is the SMID
+ * (system message ID) of the outstanding command. SMID 0 is reserved by the
+ * software/firmware protocol and is never used for any command we generate;
+ * as such, the assertion m_slot[0] == NULL is universally true. The last
+ * entry in the array is slot number MPTSAS_TM_SLOT(mpt) and is used ONLY for
+ * task management commands. No normal SCSI or ATA command will ever occupy
+ * that slot. Finally, the relationship m_slot[X]->cmd_slot == X holds at any
+ * time that a consistent view of the target array is obtainable.
+ *
+ * As such, m_n_normal is the maximum number of slots available to ordinary
+ * commands, and the relationship:
+ * mpt->m_active->m_n_normal == mpt->m_max_requests - 2
+ * always holds after initialisation.
*/
typedef struct mptsas_slots {
- mptsas_hash_table_t m_tgttbl;
- mptsas_hash_table_t m_smptbl;
- m_raidconfig_t m_raidconfig[MPTSAS_MAX_RAIDCONFIGS];
- uint8_t m_num_raid_configs;
- uint16_t m_tags;
- size_t m_size;
- uint16_t m_n_slots;
+ size_t m_size; /* size of struct, bytes */
+ uint_t m_n_normal; /* see above */
+ uint_t m_rotor; /* next slot idx to consider */
mptsas_cmd_t *m_slot[1];
} mptsas_slots_t;
@@ -673,6 +682,12 @@ typedef struct mptsas {
*/
uint_t m_softstate;
+ refhash_t *m_targets;
+ refhash_t *m_smp_targets;
+
+ m_raidconfig_t m_raidconfig[MPTSAS_MAX_RAIDCONFIGS];
+ uint8_t m_num_raid_configs;
+
struct mptsas_slots *m_active; /* outstanding cmds */
mptsas_cmd_t *m_waitq; /* cmd queue for active request */