summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
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));