git: 137b004e2b7a - main - Fix the isp(4) driver with 9.x firmware.

From: Kenneth D. Merry <ken_at_FreeBSD.org>
Date: Mon, 24 Jun 2024 20:49:46 UTC
The branch main has been updated by ken:

URL: https://cgit.FreeBSD.org/src/commit/?id=137b004e2b7ab504abf98c4aad9d52607df47b9a

commit 137b004e2b7ab504abf98c4aad9d52607df47b9a
Author:     Kenneth D. Merry <ken@FreeBSD.org>
AuthorDate: 2024-06-21 19:30:59 +0000
Commit:     Kenneth D. Merry <ken@FreeBSD.org>
CommitDate: 2024-06-24 20:47:55 +0000

    Fix the isp(4) driver with 9.x firmware.
    
    The isp(4) driver (and ispfw(4) firmware) previously only included
    firmware for Qlogic controllers up to 8Gb.  It recently gained
    firmware for the 27XX and 28XX series controllers along with
    improved firmware loading capabilities.
    
    The 9.x firmware available for the 27XX and 28XX controllers in
    ispfw(4) adds login state for NVMe devices in the top nibble of
    the login state in the port database (isp_pdb_24xx_t in ispmbox.h).
    
    This breaks the check at the end of isp_getpdb() to make sure the
    device is in the right login state.  As a result, it breaks device
    discovery for many (perhaps all?) FC devices.  In my testing with
    IBM LTO-6 drives attached to a quad port 16Gb Qlogic 2714, they
    don't show up when they are directly connected (and in loop mode)
    or connected via a switch (and in fabric mode).
    
    So, mask off the top bits of of the login state before checking it.
    This shouldn't break anything, because all of the existing login
    states defined in ispmbox.h are in the low nibble.
    
    sys/dev/isp/ispmbox.h:
            Add a FCP login state mask define, and a NVMe login state
            shift.
    
    sys/dev/isp/isp.c:
            In isp_getpdb(), make sure we're only looking at the FCP
            login state bits when we try to determine whether a device
            is in the right login state.
    
    MFC after:      1 week
    Sponsored by:   Spectra Logic
    Reviewed by:    mav
    Differential Revision:  <https://reviews.freebsd.org/D45660>
---
 sys/dev/isp/isp.c     | 10 +++++++++-
 sys/dev/isp/ispmbox.h |  6 ++++++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index b53171add5f5..2ed56c5e40bb 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -1539,7 +1539,15 @@ isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb)
 	    chan, id, pdb->portid, un.bill.pdb_flags,
 	    un.bill.pdb_curstate, un.bill.pdb_laststate);
 
-	if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE || un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) {
+	/*
+	 * XXX KDM this is broken for NVMe.  Need to determine whether this
+	 * is an NVMe target, and if so, check the NVMe status bits. We are
+	 * probably missing more bits for proper NVMe support, though.
+	 */
+	if (((un.bill.pdb_curstate & PDB2400_STATE_FCP_MASK) <
+	      PDB2400_STATE_PLOGI_DONE)
+	 || ((un.bill.pdb_curstate & PDB2400_STATE_FCP_MASK) >
+	      PDB2400_STATE_LOGGED_IN)) {
 		mbs.param[0] = MBOX_NOT_LOGGED_IN;
 		return (mbs.param[0]);
 	}
diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h
index c6ac9d9ce971..978ed4dc1638 100644
--- a/sys/dev/isp/ispmbox.h
+++ b/sys/dev/isp/ispmbox.h
@@ -890,6 +890,10 @@ typedef struct {
 #define	PDB2400_CLASS2		0x0010
 #define	PDB2400_ADDR_VALID	0x0002
 
+/*
+ * For NVMe, the state is the high nibble.  For FCP, the state is the low
+ * nibble.  This appears to have changed with the 9.x firmware.
+ */
 #define	PDB2400_STATE_PLOGI_PEND	0x03
 #define	PDB2400_STATE_PLOGI_DONE	0x04
 #define	PDB2400_STATE_PRLI_PEND		0x05
@@ -897,6 +901,8 @@ typedef struct {
 #define	PDB2400_STATE_PORT_UNAVAIL	0x07
 #define	PDB2400_STATE_PRLO_PEND		0x09
 #define	PDB2400_STATE_LOGO_PEND		0x0B
+#define	PDB2400_STATE_FCP_MASK		0x0f
+#define	PDB2400_STATE_NVME_SHIFT	4
 
 /*
  * Common elements from the above two structures that are actually useful to us.