git: 6fdabe9b8df4 - stable/13 - isp(4): Add support for QLogic 28xx devices

From: Alexander Motin <mav_at_FreeBSD.org>
Date: Fri, 19 Jan 2024 16:53:28 UTC
The branch stable/13 has been updated by mav:

URL: https://cgit.FreeBSD.org/src/commit/?id=6fdabe9b8df4493af8242fb2755b69e20d1ef042

commit 6fdabe9b8df4493af8242fb2755b69e20d1ef042
Author:     Joerg Pulz <Joerg.Pulz@frm2.tum.de>
AuthorDate: 2023-07-07 21:43:34 +0000
Commit:     Alexander Motin <mav@FreeBSD.org>
CommitDate: 2024-01-19 16:51:45 +0000

    isp(4): Add support for QLogic 28xx devices
    
    This covers the following HBAs:
      ISP2812-based 64/32G Fibre Channel to PCIe Controller:
        QLE2770 Single Port 32GFC PCIe Gen4 x8 Adapter
        QLE2772 Dual Port 32GFC PCIe Gen4 x8 Adapter
        QLE2870 Single Port 64GFC PCIe Gen4 x8 Adapter
        QLE2872 Dual Port 64GFC PCIe Gen4 x8 Adapter
    
      ISP2814-based 64/32G Fibre Channel to PCIe Controller:
        QLE2774 Quad Port 32GFC PCIe Gen4 x16 Adapter
        QLE2874 Quad Port 64GFC PCIe Gen4 x16 Adapter
    
    While here, add required bits to support 64GB FC.
    
    Default framesize is set to 2048 for ISP28xx based HBAs for now.
    
    PR: 271062
    Reviewed by: imp, mav
    Sponsored by: Technical University of Munich
    Pull Request: https://github.com/freebsd/freebsd-src/pull/726
    
    (cherry picked from commit 407abff6a445c8db335093868e9e7e70438c5901)
---
 sys/dev/isp/isp.c     | 14 +++++++++++++-
 sys/dev/isp/isp_pci.c | 28 ++++++++++++++++++++++++++++
 sys/dev/isp/ispmbox.h |  3 +++
 sys/dev/isp/ispvar.h  |  3 +++
 4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index cd60c99a40ff..6940397d10b4 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -178,6 +178,9 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults)
 	case ISP_HA_FC_2700:
 		btype = "2700";
 		break;
+	case ISP_HA_FC_2800:
+		btype = "2800";
+		break;
 	default:
 		break;
 	}
@@ -709,8 +712,11 @@ isp_init(ispsoftc_t *isp)
 	icbp->icb_version = ICB_VERSION1;
 	icbp->icb_maxfrmlen = DEFAULT_FRAMESIZE(isp);
 	if (icbp->icb_maxfrmlen < ICB_MIN_FRMLEN || icbp->icb_maxfrmlen > ICB_MAX_FRMLEN) {
-		isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM- using %d", DEFAULT_FRAMESIZE(isp), ICB_DFLT_FRMLEN);
 		icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN;
+		if (IS_28XX(isp))
+			icbp->icb_maxfrmlen = ICB_DFLT_FRMLEN_28XX;
+
+		isp_prt(isp, ISP_LOGERR, "bad frame length (%d) from NVRAM - using %d", DEFAULT_FRAMESIZE(isp), icbp->icb_maxfrmlen);
 	}
 
 	if (!IS_26XX(isp))
@@ -821,12 +827,16 @@ isp_init(ispsoftc_t *isp)
 	} else if (isp->isp_confopts & ISP_CFG_32GB) {
 		icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
 		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_32GB;
+	} else if (isp->isp_confopts & ISP_CFG_64GB) {
+		icbp->icb_fwoptions3 &= ~ICB2400_OPT3_RATE_MASK;
+		icbp->icb_fwoptions3 |= ICB2400_OPT3_RATE_64GB;
 	} else {
 		switch (icbp->icb_fwoptions3 & ICB2400_OPT3_RATE_MASK) {
 		case ICB2400_OPT3_RATE_4GB:
 		case ICB2400_OPT3_RATE_8GB:
 		case ICB2400_OPT3_RATE_16GB:
 		case ICB2400_OPT3_RATE_32GB:
+		case ICB2400_OPT3_RATE_64GB:
 		case ICB2400_OPT3_RATE_AUTO:
 			break;
 		case ICB2400_OPT3_RATE_2GB:
@@ -1536,6 +1546,8 @@ not_on_fabric:
 	if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
 		if (mbs.param[1] == MBGSD_10GB)
 			fcp->isp_gbspeed = 10;
+		else if (mbs.param[1] == MBGSD_64GB)
+			fcp->isp_gbspeed = 64;
 		else if (mbs.param[1] == MBGSD_32GB)
 			fcp->isp_gbspeed = 32;
 		else if (mbs.param[1] == MBGSD_16GB)
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 482b7299b446..b0adaeb663e7 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -97,6 +97,16 @@ static struct ispmdvec mdvec_2700 = {
 	NULL
 };
 
+static struct ispmdvec mdvec_2800 = {
+	isp_pci_run_isr_2400,
+	isp_pci_rd_reg_2600,
+	isp_pci_wr_reg_2600,
+	isp_pci_mbxdma,
+	isp_send_cmd,
+	isp_pci_irqsetup,
+	NULL
+};
+
 #ifndef	PCIM_CMD_INVEN
 #define	PCIM_CMD_INVEN			0x10
 #endif
@@ -141,6 +151,8 @@ static struct ispmdvec mdvec_2700 = {
 #define	PCI_PRODUCT_QLOGIC_ISP2692	0x2b61
 #define	PCI_PRODUCT_QLOGIC_ISP2714	0x2071
 #define	PCI_PRODUCT_QLOGIC_ISP2722	0x2261
+#define	PCI_PRODUCT_QLOGIC_ISP2812	0x2281
+#define	PCI_PRODUCT_QLOGIC_ISP2814	0x2081
 
 #define	PCI_QLOGIC_ISP2422	\
 	((PCI_PRODUCT_QLOGIC_ISP2422 << 16) | PCI_VENDOR_QLOGIC)
@@ -162,6 +174,10 @@ static struct ispmdvec mdvec_2700 = {
 	((PCI_PRODUCT_QLOGIC_ISP2714 << 16) | PCI_VENDOR_QLOGIC)
 #define	PCI_QLOGIC_ISP2722	\
 	((PCI_PRODUCT_QLOGIC_ISP2722 << 16) | PCI_VENDOR_QLOGIC)
+#define	PCI_QLOGIC_ISP2812	\
+	((PCI_PRODUCT_QLOGIC_ISP2812 << 16) | PCI_VENDOR_QLOGIC)
+#define	PCI_QLOGIC_ISP2814	\
+	((PCI_PRODUCT_QLOGIC_ISP2814 << 16) | PCI_VENDOR_QLOGIC)
 
 #define	PCI_DFLT_LTNCY	0x40
 #define	PCI_DFLT_LNSZ	0x10
@@ -243,6 +259,12 @@ isp_pci_probe(device_t dev)
 	case PCI_QLOGIC_ISP2722:
 		device_set_desc(dev, "Qlogic ISP 2722 PCI FC Adapter");
 		break;
+	case PCI_QLOGIC_ISP2812:
+		device_set_desc(dev, "Qlogic ISP 2812 PCI FC Adapter");
+		break;
+	case PCI_QLOGIC_ISP2814:
+		device_set_desc(dev, "Qlogic ISP 2814 PCI FC Adapter");
+		break;
 	default:
 		return (ENXIO);
 	}
@@ -491,6 +513,12 @@ isp_pci_attach(device_t dev)
 		isp->isp_mdvec = &mdvec_2700;
 		isp->isp_type = ISP_HA_FC_2700;
 		break;
+	case PCI_QLOGIC_ISP2812:
+	case PCI_QLOGIC_ISP2814:
+		did = 0x2800;
+		isp->isp_mdvec = &mdvec_2800;
+		isp->isp_type = ISP_HA_FC_2800;
+		break;
 	default:
 		device_printf(dev, "unknown device type\n");
 		goto bad;
diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h
index 6523dc6e6ba8..42a45e9c7ea6 100644
--- a/sys/dev/isp/ispmbox.h
+++ b/sys/dev/isp/ispmbox.h
@@ -178,6 +178,7 @@
 #define		MBGSD_8GB	0x04		/* 25XX only */
 #define		MBGSD_16GB	0x05		/* 26XX only */
 #define		MBGSD_32GB	0x06		/* 27XX only */
+#define		MBGSD_64GB	0x07		/* 28XX only */
 #define		MBGSD_10GB	0x13		/* 26XX only */
 #define	MBOX_SEND_RNFT			0x005e
 #define	MBOX_INIT_FIRMWARE		0x0060
@@ -646,6 +647,7 @@ typedef struct {
 #define	ICB2400_OPT3_RATE_8GB		0x00008000
 #define	ICB2400_OPT3_RATE_16GB		0x0000A000
 #define	ICB2400_OPT3_RATE_32GB		0x0000C000
+#define	ICB2400_OPT3_RATE_64GB		0x0000E000
 #define	ICB2400_OPT3_ENA_OOF_XFRDY	0x00000200
 #define	ICB2400_OPT3_NO_N2N_LOGI	0x00000100
 #define	ICB2400_OPT3_NO_LOCAL_PLOGI	0x00000080
@@ -660,6 +662,7 @@ typedef struct {
 #define	ICB_MIN_FRMLEN		256
 #define	ICB_MAX_FRMLEN		2112
 #define	ICB_DFLT_FRMLEN		1024
+#define	ICB_DFLT_FRMLEN_28XX	2048
 #define	ICB_DFLT_RDELAY		5
 #define	ICB_DFLT_RCOUNT		3
 
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index 8ab25c9913d3..faf26bc7b055 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -538,6 +538,7 @@ struct ispsoftc {
 #define	ISP_CFG_8GB		0x4000	/* force 8Gb connection (25XX only) */
 #define	ISP_CFG_16GB		0x8000	/* force 16Gb connection (26XX only) */
 #define	ISP_CFG_32GB		0x10000	/* force 32Gb connection (27XX only) */
+#define	ISP_CFG_64GB		0x20000	/* force 64Gb connection (28XX only) */
 
 /*
  * For each channel, the outer layers should know what role that channel
@@ -606,10 +607,12 @@ struct ispsoftc {
 #define	ISP_HA_FC_2500		0x05
 #define	ISP_HA_FC_2600		0x06
 #define	ISP_HA_FC_2700		0x07
+#define	ISP_HA_FC_2800		0x08
 
 #define	IS_25XX(isp)	((isp)->isp_type >= ISP_HA_FC_2500)
 #define	IS_26XX(isp)	((isp)->isp_type >= ISP_HA_FC_2600)
 #define	IS_27XX(isp)	((isp)->isp_type >= ISP_HA_FC_2700)
+#define	IS_28XX(isp)	((isp)->isp_type >= ISP_HA_FC_2800)
 
 /*
  * DMA related macros