From nobody Fri Sep 11 05:32:40 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hh38n0BQMz6rdkM for ; Fri, 11 Sep 2026 05:32:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hh38m5w0cz4P5y for ; Fri, 11 Sep 2026 05:32:40 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789104760; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=bgp1TEoIo7pkLyFW3zVIPAU65TjqqBXuLItIpbwDMMo=; b=IYngguwEvMrRLiS6qjY236WdkAqo02d1Uwe8VaD8HttMNldXLjSeOAb06kxWskBZOgNdhh aJuRKEI0zKIxFhUz00KdK/h68eP0UAcnqTD5wGMY3fTVFySXa/AcKtU9bDGqMfXqEqATvQ UV+qLw0pdgFPCdMtT/vuiKzUMZAcIGNJIlSVvDvKVNH1BVEfz9nPrLR40eCiA+PFBcdS+h Y1129+Ubg/gZaGsPOHu8TFnl6hF1tTTHIjx92sBnSjxF+cmsDZ3OS78v5KUCw68A4xfg4g YGOuGRTi7WV59nwkXes+wkLjujpaiW1Gz0lJvOfLF/CYT5vVz6xKxQvhFjdCsQ== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1789104760; b=CM1/zWz5M6QcguP+U+kLv3qmB7qtS3CEXct8BFv/iTQ15hRBieO5hSJx70gaRFzgiQyN5G Tsp0vvF9yykRKLwYIQakDqh3hduz+A7YYN7shzp55pG5rpRwYPOU+4mZpuixcv0vLEvM2j VZ40g0tgrRZTMTiUseC/QKdwkPbetg2NaKFmHtLCVkwMsDQq02fUzfOnfvEIBFkXEzV5m4 ir73L+gvvJpCClS/zUd28bUtRP34wIIa6zqRWMBga+vCzDKV76FzmOnU3vyQUIpADb9RX0 4HQKGXvBo6j76yRdc1iqPsIbgb6CRUqf75oBdBlKhVJdgXBK0bfQvGI83UR5MA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789104760; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=bgp1TEoIo7pkLyFW3zVIPAU65TjqqBXuLItIpbwDMMo=; b=rNfzBDCWId/FRAAC449Qsjg+kui8BL4pwlhCNmpxObtumAISdYBkRPoAo+rxor/btk13ry 7uHT1xzil/usFCihQ5wmzUi77Q2YvxfbJ7NNKiUOedzdEQ7dELxVg4uuWiG6X9a5XLBxaR COJjgBbTEF74cwohH1Qt3EPz9rCzweMt1Uk9ulKxyTEsN5C8UFmrt1N/CAuUan5AcEVhck +RNf362ewx2sXqL2aVDxCOmebJI5NNn+zAj0nkhW3R5Sc7pEDCtA1LMaBtGDT0sqvF9a/B Uql8vVeGZgLUbLLDtw4antxWOoivYb0ScVBH8NK3m422LSEAkBTChMs2wWTBSQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hh38m4kFxz11Bk for ; Fri, 11 Sep 2026 05:32:40 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3dd68 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 11 Sep 2026 05:32:40 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Warner Losh Subject: git: afb60897a15c - main - mpsutil: Add Show Discovery command List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: imp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: afb60897a15c37cb5dbc45e2cabfac58b681550f Auto-Submitted: auto-generated Date: Fri, 11 Sep 2026 05:32:40 +0000 Message-Id: <6aa39278.3dd68.6faff243@gitrepo.freebsd.org> The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=afb60897a15c37cb5dbc45e2cabfac58b681550f commit afb60897a15c37cb5dbc45e2cabfac58b681550f Author: Warner Losh AuthorDate: 2026-09-11 05:13:14 +0000 Commit: Warner Losh CommitDate: 2026-09-11 05:13:14 +0000 mpsutil: Add Show Discovery command Prints the current discovry tables for the driver. Sponsored by: Netflix Assisted by: Claude (sonet-5) Differential Revision: https://reviews.freebsd.org/D58528 --- usr.sbin/mpsutil/mps_show.c | 205 ++++++++++++++++++++++++++++++++++++++++++++ usr.sbin/mpsutil/mpsutil.8 | 14 +++ 2 files changed, 219 insertions(+) diff --git a/usr.sbin/mpsutil/mps_show.c b/usr.sbin/mpsutil/mps_show.c index 378d5380aa76..cf1ae4f5005b 100644 --- a/usr.sbin/mpsutil/mps_show.c +++ b/usr.sbin/mpsutil/mps_show.c @@ -630,6 +630,211 @@ show_devices(int ac, char **av) } MPS_COMMAND(show, devices, show_devices, "", "Show attached devices"); +static const struct { + uint32_t mask; + const char *name; +} discovery_status_bits[] = { + { MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED, "MaxEnclosuresExceeded" }, + { MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED, "MaxExpandersExceeded" }, + { MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED, "MaxDevicesExceeded" }, + { MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED, "MaxTopoPhysExceeded" }, + { MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR, "DownstreamInitiator" }, + { MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE, "MultiSubtractiveToSubtractive" }, + { MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE, "ExpMultiSubtractive" }, + { MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN, "MultiPortDomain" }, + { MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK, "TableToSubtractiveLink" }, + { MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE, "UnsupportedDevice" }, + { MPI2_SASIOUNIT0_DS_TABLE_LINK, "TableLink" }, + { MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK, "SubtractiveLink" }, + { MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR, "SmpCrcError" }, + { MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED, "SmpFunctionFailed" }, + { MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST, "RouteIndexNotExist" }, + { MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES, "RouteTableFull" }, + { MPI2_SASIOUNIT0_DS_SMP_TIMEOUT, "SmpTimeout" }, + { MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS, "MultiplePortsSameAddress" }, + { MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE, "UnaddressableDevice" }, + { MPI2_SASIOUNIT0_DS_LOOP_DETECTED, "LoopDetected" }, +}; + +static void +snprint_discovery_status(char *buf, size_t buflen, uint32_t ds) +{ + unsigned i; + int first = 1; + + buf[0] = '\0'; + if (ds == 0) { + strlcpy(buf, "-", buflen); + return; + } + for (i = 0; i < nitems(discovery_status_bits); i++) { + if ((ds & discovery_status_bits[i].mask) == 0) + continue; + if (!first) + strlcat(buf, ",", buflen); + strlcat(buf, discovery_status_bits[i].name, buflen); + first = 0; + } +} + +static const char * +get_access_status(uint8_t status) +{ + + switch (status) { + case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS: + return ("Ok"); + case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED: + return ("SATAInitFailed"); + case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED: + return ("SATACapabilityFailed"); + case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT: + return ("SATAAffiliationConflict"); + case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION: + return ("SATANeedsInit"); + case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE: + return ("RouteNotAddressable"); + case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE: + return ("SmpErrorNotAddressable"); + case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED: + return ("DeviceBlocked"); + case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN: + return ("SATAInitFailUnknown"); + case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT: + return ("SATAInitFailAffiliation"); + case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG: + return ("SATAInitFailDiag"); + case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION: + return ("SATAInitFailID"); + case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER: + return ("SATAInitFailPower"); + case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN: + return ("SATAInitFailPIO"); + case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN: + return ("SATAInitFailMDMA"); + case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN: + return ("SATAInitFailUDMA"); + case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION: + return ("SATAInitFailZoning"); + case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE: + return ("SATAInitFailNotAddressable"); + default: + return ("Reserved"); + } +} + +/* + * Dump firmware-maintained DiscoveryStatus (SAS IO Unit Page 0, per PHY) and + * AccessStatus (SAS Device Page 0, per device) fields used by mpr(4)/mps(4) + * during discovery. + */ +static int +show_discovery(int ac, char **av) +{ + MPI2_CONFIG_PAGE_SASIOUNIT_0 *sas0; + MPI2_SAS_IO_UNIT0_PHY_DATA *phy; + MPI2_CONFIG_PAGE_SAS_DEV_0 *device; + uint16_t IOCStatus, handle; + uint32_t ds; + uint16_t flags; + uint8_t astatus; + char dsbuf[256]; + int fd, error, i, nsuspect, in_progress, disabled, suspect; + + fd = mps_open(mps_unit); + if (fd < 0) { + error = errno; + warn("mps_open"); + return (error); + } + + sas0 = mps_read_extended_config_page(fd, + MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT, + MPI2_SASIOUNITPAGE0_PAGEVERSION, 0, 0, &IOCStatus); + if (sas0 == NULL) { + error = errno; + warn("Error retrieving SAS IO Unit page 0: %s", + mps_ioc_status(IOCStatus)); + close(fd); + return (error); + } + + nsuspect = 0; + printf("%-4s%-5s%-11s%-9s%-6s%-10s%-10s%s\n", + "Phy", "Port", "PortStatus", "Disabled", "Rate", "AttHandle", + "CtlHandle", "DiscoveryStatus"); + for (i = 0; i < sas0->NumPhys; i++) { + phy = &sas0->PhyData[i]; + ds = le32toh(phy->DiscoveryStatus); + in_progress = (phy->PortFlags & + MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) != 0; + disabled = (phy->PhyFlags & + MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED) != 0; + + snprint_discovery_status(dsbuf, sizeof(dsbuf), ds); + printf("%-4d%-5u%-11s%-9s%-6s0x%-8x0x%-8x%s%s\n", + i, phy->Port, in_progress ? "InProgress" : "Idle", + disabled ? "Y" : "N", get_device_speed(phy->NegotiatedLinkRate), + le16toh(phy->AttachedDevHandle), + le16toh(phy->ControllerDevHandle), dsbuf, + (ds != 0 || in_progress) ? " <== SUSPECT" : ""); + if (ds != 0 || in_progress) + nsuspect++; + } + printf("\n"); + + printf("%-8s%-10s%-17s%-6s%-6s%-8s%s\n", + "Handle", "Parent", "SAS Address", "Enc", "Slot", "Flags", + "AccessStatus"); + handle = 0xffff; + for (;;) { + device = mps_read_extended_config_page(fd, + MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE, + MPI2_SASDEVICE0_PAGEVERSION, 0, + MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE | handle, + &IOCStatus); + if (device == NULL) { + if (IOCStatus == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) + break; + error = errno; + warn("Error retrieving device page: %s", + mps_ioc_status(IOCStatus)); + free(sas0); + close(fd); + return (error); + } + handle = le16toh(device->DevHandle); + + flags = le16toh(device->Flags); + astatus = device->AccessStatus; + suspect = (astatus != MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS) || + (flags & MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE) || + !(flags & MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT); + + printf("0x%-6x0x%-8x%08x%08x %-6u%-6u0x%-6x%s%s\n", + handle, le16toh(device->ParentDevHandle), + le32toh(device->SASAddress.High), + le32toh(device->SASAddress.Low), + le16toh(device->EnclosureHandle), le16toh(device->Slot), + flags, get_access_status(astatus), + suspect ? " <== SUSPECT" : ""); + + if (suspect) + nsuspect++; + free(device); + } + printf("\n"); + + if (nsuspect != 0) + printf("*** %d suspect PHY/device entries found ***\n", nsuspect); + + free(sas0); + close(fd); + return (0); +} +MPS_COMMAND(show, discovery, show_discovery, "", + "Show firmware DiscoveryStatus/AccessStatus per PHY and device"); + static int show_enclosures(int ac, char **av) { diff --git a/usr.sbin/mpsutil/mpsutil.8 b/usr.sbin/mpsutil/mpsutil.8 index 6bfcdf5f9dd7..402031542f16 100644 --- a/usr.sbin/mpsutil/mpsutil.8 +++ b/usr.sbin/mpsutil/mpsutil.8 @@ -51,6 +51,9 @@ .Cm show devices .Nm .Op Fl u Ar unit +.Cm show discovery +.Nm +.Op Fl u Ar unit .Cm show enclosures .Nm .Op Fl u Ar unit @@ -124,6 +127,17 @@ Displays a summary of all adapters. Displays all devices, expanders and enclosures. .It Cm show devices Displays all devices. +.It Cm show discovery +Displays the firmware DiscoveryStatus field for each PHY +.Po Dq SAS IO Unit Page 0 Pc +and the AccessStatus field for each device +.Po Dq SAS Device Page 0 Pc . +Entries with a nonzero DiscoveryStatus, a non-Ok AccessStatus, or a PHY +still showing discovery in progress are marked +.Dq SUSPECT . +Useful for finding which PHY or device a firmware discovery stall was +attributed to, since these fields aren't otherwise exposed and can remain +set after the boot completes. .It Cm show expanders Displays all expanders. .It Cm show enclosures