summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJonathan Matthew <jmatthew@cvs.openbsd.org>2018-03-16 05:12:38 +0000
committerJonathan Matthew <jmatthew@cvs.openbsd.org>2018-03-16 05:12:38 +0000
commitb338d42a3584964e9ee64cb1e72676ff7683a32d (patch)
tree81f2cf90806cb5ef7320f2e79ef7eac9b0b60ec1 /sys
parentd59027601ae22203988578ba31f9f2abd1e2ee9f (diff)
Improve calculation of the number of commands and sges available.
The maximum number of commands may be specified in outbound scratch register 3, should be limited to 1024, and should further be reduced by one to ensure the reply queue doesn't overflow. The maximum number of sges in a command should be the highest power of two that fits in the space available in the io frame and in a chained sge frame. The maximum size of a chained frame is specified in outbound scratch register 2. part of a diff from Naoki Fukaumi ok dlg@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/mfii.c60
1 files changed, 55 insertions, 5 deletions
diff --git a/sys/dev/pci/mfii.c b/sys/dev/pci/mfii.c
index 0a5266acda2..1f31bacd71f 100644
--- a/sys/dev/pci/mfii.c
+++ b/sys/dev/pci/mfii.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfii.c,v 1.49 2018/03/16 04:30:31 jmatthew Exp $ */
+/* $OpenBSD: mfii.c,v 1.50 2018/03/16 05:12:37 jmatthew Exp $ */
/*
* Copyright (c) 2012 David Gwynne <dlg@openbsd.org>
@@ -44,6 +44,8 @@
#define MFII_OSTS_INTR_VALID 0x00000009
#define MFII_RPI 0x6c /* reply post host index */
+#define MFII_OSP2 0xb4 /* outbound scratch pad 2 */
+#define MFII_OSP3 0xb8 /* outbound scratch pad 3 */
#define MFII_REQ_TYPE_SCSI MPII_REQ_DESCR_SCSI_IO
#define MFII_REQ_TYPE_LDIO (0x7 << 1)
@@ -56,6 +58,15 @@
#define MFII_FUNCTION_PASSTHRU_IO (0xf0)
#define MFII_FUNCTION_LDIO_REQUEST (0xf1)
+#define MFII_MAX_CHAIN_UNIT 0x00400000
+#define MFII_MAX_CHAIN_MASK 0x000003E0
+#define MFII_MAX_CHAIN_SHIFT 5
+
+#define MFII_256K_IO 128
+#define MFII_1MB_IO (MFII_256K_IO * 4)
+
+#define MFII_CHAIN_FRAME_MIN 1024
+
struct mfii_request_descr {
u_int8_t flags;
u_int8_t msix_index;
@@ -254,6 +265,7 @@ struct mfii_softc {
struct mutex sc_ccb_mtx;
struct mutex sc_post_mtx;
+ u_int sc_max_fw_cmds;
u_int sc_max_cmds;
u_int sc_max_sgl;
@@ -522,7 +534,8 @@ mfii_attach(struct device *parent, struct device *self, void *aux)
pcireg_t memtype;
pci_intr_handle_t ih;
struct scsibus_attach_args saa;
- u_int32_t status;
+ u_int32_t status, scpad2, scpad3;
+ int chain_frame_sz, nsge_in_io, nsge_in_chain;
/* init sc */
sc->sc_iop = mfii_find_iop(aux);
@@ -561,9 +574,45 @@ mfii_attach(struct device *parent, struct device *self, void *aux)
if (mfii_transition_firmware(sc))
goto pci_unmap;
+ /* determine max_cmds (refer to the Linux megaraid_sas driver) */
+ scpad3 = mfii_read(sc, MFII_OSP3);
status = mfii_fw_state(sc);
- sc->sc_max_cmds = status & MFI_STATE_MAXCMD_MASK;
- sc->sc_max_sgl = (status & MFI_STATE_MAXSGL_MASK) >> 16;
+ sc->sc_max_fw_cmds = scpad3 & MFI_STATE_MAXCMD_MASK;
+ if (sc->sc_max_fw_cmds == 0)
+ sc->sc_max_fw_cmds = status & MFI_STATE_MAXCMD_MASK;
+ /*
+ * reduce max_cmds by 1 to ensure that the reply queue depth does not
+ * exceed FW supplied max_fw_cmds.
+ */
+ sc->sc_max_cmds = min(sc->sc_max_fw_cmds, 1024) - 1;
+
+ /* determine max_sgl (refer to the Linux megaraid_sas driver) */
+ scpad2 = mfii_read(sc, MFII_OSP2);
+ chain_frame_sz =
+ ((scpad2 & MFII_MAX_CHAIN_MASK) >> MFII_MAX_CHAIN_SHIFT) *
+ ((scpad2 & MFII_MAX_CHAIN_UNIT) ? MFII_1MB_IO : MFII_256K_IO);
+ if (chain_frame_sz < MFII_CHAIN_FRAME_MIN)
+ chain_frame_sz = MFII_CHAIN_FRAME_MIN;
+
+ nsge_in_io = (MFII_REQUEST_SIZE -
+ sizeof(struct mpii_msg_scsi_io) -
+ sizeof(struct mfii_raid_context)) / sizeof(struct mfii_sge);
+ nsge_in_chain = chain_frame_sz / sizeof(struct mfii_sge);
+
+ /* round down to nearest power of two */
+ sc->sc_max_sgl = 1;
+ while ((sc->sc_max_sgl << 1) <= (nsge_in_io + nsge_in_chain))
+ sc->sc_max_sgl <<= 1;
+
+#ifdef MFI_DEBUG
+ printf("%s: OSP 0x%08x, OSP2 0x%08x, OSP3 0x%08x\n",
+ DEVNAME(sc), status, scpad2, scpad3);
+ printf("%s: max_fw_cmds %d, max_cmds %d\n",
+ DEVNAME(sc), sc->sc_max_fw_cmds, sc->sc_max_cmds);
+ printf("%s: nsge_in_io %d, nsge_in_chain %d, "
+ "max_sgl %d\n", DEVNAME(sc), nsge_in_io, nsge_in_chain,
+ sc->sc_max_sgl);
+#endif
/* sense memory */
CTASSERT(sizeof(struct mfi_sense) == MFI_SENSE_SIZE);
@@ -573,7 +622,8 @@ mfii_attach(struct device *parent, struct device *self, void *aux)
goto pci_unmap;
}
- sc->sc_reply_postq_depth = roundup(sc->sc_max_cmds, 16);
+ /* reply post queue */
+ sc->sc_reply_postq_depth = roundup(sc->sc_max_fw_cmds, 16);
sc->sc_reply_postq = mfii_dmamem_alloc(sc,
sc->sc_reply_postq_depth * sizeof(struct mpii_reply_descr));