diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/mfii.c | 60 |
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)); |