This adds support for SAS3 (SAS3004, 3008, 3104) chips in mpii(4).
As far as we're concerned, these are the same as the supported SAS2
chips, just with a different sgl layout. I've tested this on a Lenovo N2215:
mpii0 at pci1 dev 0 function 0 "Symbios Logic SAS3008" rev 0x02: msi
mpii0: N2215, firmware 11.125.0.0, MPI 2.5
scsibus1 at mpii0: 1024 targets
..
sd0 at scsibus1 targ 2 lun 0: <ATA, INTEL SSDSCKHB08, EM03> SCSI4 0/direct
fixed naa.55cd2e404b768d50
sd0: 76319MB, 512 bytes/sector, 156301488 sectors, thin
sd1 at scsibus1 targ 3 lun 0: <ATA, INTEL SSDSCKHB08, EM03> SCSI4 0/direct
fixed naa.55cd2e404b768eee
sd1: 76319MB, 512 bytes/sector, 156301488 sectors, thin
sd2 at scsibus1 targ 4 lun 0: <LENOVO-X, ST4000NM0025, LK83> SCSI4 0/direct
fixed naa.5000c5008528a0af
sd2: 3815447MB, 512 bytes/sector, 7814037168 sectors
sd3 at scsibus1 targ 5 lun 0: <LENOVO-X, ST4000NM0025, LK83> SCSI4 0/direct
fixed naa.5000c50085a1199f
sd3: 3815447MB, 512 bytes/sector, 7814037168 sectors
sd4 at scsibus1 targ 6 lun 0: <LENOVO-X, ST4000NM0025, LK83> SCSI4 0/direct
fixed naa.5000c50085a114c3
sd4: 3815447MB, 512 bytes/sector, 7814037168 sectors
sd5 at scsibus1 targ 7 lun 0: <LENOVO-X, ST4000NM0025, LK83> SCSI4 0/direct
fixed naa.5000c5008549c5a7
sd5: 3815447MB, 512 bytes/sector, 7814037168 sectors
where it works well enough to check out src/sys and build a kernel.
also includes a bonus spelling correction in an error message.
ok?
Index: mpii.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/mpii.c,v
retrieving revision 1.104
diff -u -p -u -p -r1.104 mpii.c
--- mpii.c 17 Aug 2016 01:02:31 -0000 1.104
+++ mpii.c 13 Sep 2016 02:54:55 -0000
@@ -163,6 +163,7 @@ struct mpii_softc {
int sc_flags;
#define MPII_F_RAID (1<<1)
+#define MPII_F_SAS3 (1<<2)
struct scsibus_softc *sc_scsibus;
@@ -306,6 +307,7 @@ void mpii_wait_done(struct mpii_ccb *);
void mpii_init_queues(struct mpii_softc *);
int mpii_load_xs(struct mpii_ccb *);
+int mpii_load_xs_sas3(struct mpii_ccb *);
u_int32_t mpii_read(struct mpii_softc *, bus_size_t);
void mpii_write(struct mpii_softc *, bus_size_t, u_int32_t);
@@ -420,7 +422,13 @@ static const struct pci_matchid mpii_dev
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2208_6 },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2308_1 },
{ PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2308_2 },
- { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2308_3 }
+ { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2308_3 },
+ { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3004 },
+ { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3008 },
+ { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3108_1 },
+ { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3108_2 },
+ { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3108_3 },
+ { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3108_4 }
};
int
@@ -729,6 +737,63 @@ mpii_intr(void *arg)
}
int
+mpii_load_xs_sas3(struct mpii_ccb *ccb)
+{
+ struct mpii_softc *sc = ccb->ccb_sc;
+ struct scsi_xfer *xs = ccb->ccb_cookie;
+ struct mpii_msg_scsi_io *io = ccb->ccb_cmd;
+ struct mpii_ieee_sge *csge, *nsge, *sge;
+ bus_dmamap_t dmap = ccb->ccb_dmamap;
+ int i, error;
+
+ /* Request frame structure is described in the mpii_iocfacts */
+ nsge = (struct mpii_ieee_sge *)(io + 1);
+ csge = nsge + sc->sc_chain_sge;
+
+ /* zero length transfer still requires an SGE */
+ if (xs->datalen == 0) {
+ nsge->sg_flags = MPII_IEEE_SGE_END_OF_LIST;
+ return (0);
+ }
+
+ error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL,
+ (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
+ if (error) {
+ printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
+ return (1);
+ }
+
+ for (i = 0; i < dmap->dm_nsegs; i++, nsge++) {
+ if (nsge == csge) {
+ nsge++;
+ /* offset to the chain sge from the beginning */
+ io->chain_offset = ((caddr_t)csge - (caddr_t)io) / 4;
+ csge->sg_flags = MPII_IEEE_SGE_CHAIN_ELEMENT |
+ MPII_IEEE_SGE_ADDR_SYSTEM;
+ /* address of the next sge */
+ csge->sg_addr = htole64(ccb->ccb_cmd_dva +
+ ((caddr_t)nsge - (caddr_t)io));
+ csge->sg_len = htole32((dmap->dm_nsegs - i) *
+ sizeof(*sge));
+ }
+
+ sge = nsge;
+ sge->sg_flags = MPII_IEEE_SGE_ADDR_SYSTEM;
+ sge->sg_len = htole32(dmap->dm_segs[i].ds_len);
+ sge->sg_addr = htole64(dmap->dm_segs[i].ds_addr);
+ }
+
+ /* terminate list */
+ sge->sg_flags |= MPII_IEEE_SGE_END_OF_LIST;
+
+ bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
+ (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
+ BUS_DMASYNC_PREWRITE);
+
+ return (0);
+}
+
+int
mpii_load_xs(struct mpii_ccb *ccb)
{
struct mpii_softc *sc = ccb->ccb_sc;
@@ -1126,6 +1191,7 @@ mpii_iocfacts(struct mpii_softc *sc)
struct mpii_msg_iocfacts_request ifq;
struct mpii_msg_iocfacts_reply ifp;
int irs;
+ int sge_size;
u_int qdepth;
DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts\n", DEVNAME(sc));
@@ -1160,6 +1226,10 @@ mpii_iocfacts(struct mpii_softc *sc)
sc->sc_max_cmds = MIN(lemtoh16(&ifp.request_credit),
MPII_REQUEST_CREDIT);
+ /* SAS3 controllers have different sgl layouts */
+ if (ifp.msg_version_maj == 2 && ifp.msg_version_min == 5)
+ SET(sc->sc_flags, MPII_F_SAS3);
+
/*
* The host driver must ensure that there is at least one
* unused entry in the Reply Free Queue. One way to ensure
@@ -1227,9 +1297,15 @@ mpii_iocfacts(struct mpii_softc *sc)
sc->sc_request_size += 16 - (sc->sc_request_size % 16);
}
+ if (ISSET(sc->sc_flags, MPII_F_SAS3)) {
+ sge_size = sizeof(struct mpii_ieee_sge);
+ } else {
+ sge_size = sizeof(struct mpii_sge);
+ }
+
/* offset to the chain sge */
sc->sc_chain_sge = (irs - sizeof(struct mpii_msg_scsi_io)) /
- sizeof(struct mpii_sge) - 1;
+ sge_size - 1;
/*
* A number of simple scatter-gather elements we can fit into the
@@ -1237,7 +1313,7 @@ mpii_iocfacts(struct mpii_softc *sc)
*/
sc->sc_max_sgl = (sc->sc_request_size -
sizeof(struct mpii_msg_scsi_io) - sizeof(struct scsi_sense_data)) /
- sizeof(struct mpii_sge) - 1;
+ sge_size - 1;
return (0);
}
@@ -2704,11 +2780,12 @@ mpii_scsi_cmd(struct scsi_xfer *xs)
struct mpii_ccb *ccb = xs->io;
struct mpii_msg_scsi_io *io;
struct mpii_device *dev;
+ int ret;
DNPRINTF(MPII_D_CMD, "%s: mpii_scsi_cmd\n", DEVNAME(sc));
if (xs->cmdlen > MPII_CDB_LEN) {
- DNPRINTF(MPII_D_CMD, "%s: CBD too big %d\n",
+ DNPRINTF(MPII_D_CMD, "%s: CDB too big %d\n",
DEVNAME(sc), xs->cmdlen);
memset(&xs->sense, 0, sizeof(xs->sense));
xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
@@ -2766,7 +2843,12 @@ mpii_scsi_cmd(struct scsi_xfer *xs)
htolem32(&io->sense_buffer_low_address, ccb->ccb_cmd_dva +
sc->sc_request_size - sizeof(struct scsi_sense_data));
- if (mpii_load_xs(ccb) != 0) {
+ if (ISSET(sc->sc_flags, MPII_F_SAS3))
+ ret = mpii_load_xs_sas3(ccb);
+ else
+ ret = mpii_load_xs(ccb);
+
+ if (ret != 0) {
xs->error = XS_DRIVER_STUFFUP;
goto done;
}
Index: mpiireg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/mpiireg.h,v
retrieving revision 1.9
diff -u -p -u -p -r1.9 mpiireg.h
--- mpiireg.h 27 Mar 2014 12:19:55 -0000 1.9
+++ mpiireg.h 13 Sep 2016 02:54:55 -0000
@@ -128,6 +128,26 @@ struct mpii_sge {
u_int32_t sg_addr_hi;
} __packed __aligned(4);
+/*
+ * SAS3 (IEEE) Scatter Gather Lists
+ */
+
+#define MPII_IEEE_SGE_ADDR_MASK (0x03)
+#define MPII_IEEE_SGE_ADDR_SYSTEM (0x00)
+#define MPII_IEEE_SGE_ADDR_IOCDDR (0x01)
+#define MPII_IEEE_SGE_ADDR_IOCPLB (0x02)
+#define MPII_IEEE_SGE_ADDR_IOCPLBNTA (0x03)
+#define MPII_IEEE_SGE_END_OF_LIST (0x40)
+#define MPII_IEEE_SGE_CHAIN_ELEMENT (0x80)
+
+struct mpii_ieee_sge {
+ u_int64_t sg_addr;
+ u_int32_t sg_len;
+ u_int16_t _reserved;
+ u_int8_t sg_next_chain_offset;
+ u_int8_t sg_flags;
+} __packed __aligned(4);
+
struct mpii_fw_tce {
u_int8_t reserved1;
u_int8_t context_size;
Index: pcidevs
===================================================================
RCS file: /cvs/src/sys/dev/pci/pcidevs,v
retrieving revision 1.1804
diff -u -p -u -p -r1.1804 pcidevs
--- pcidevs 3 Sep 2016 16:05:22 -0000 1.1804
+++ pcidevs 13 Sep 2016 02:54:55 -0000
@@ -5482,6 +5482,12 @@ product SYMBIOS SAS2208_6 0x0085 SAS2208
product SYMBIOS SAS2308_1 0x0086 SAS2308
product SYMBIOS SAS2308_2 0x0087 SAS2308
product SYMBIOS 875J 0x008f 53c875J
+product SYMBIOS SAS3108_1 0x0090 SAS3108
+product SYMBIOS SAS3108_2 0x0091 SAS3108
+product SYMBIOS SAS3108_3 0x0094 SAS3108
+product SYMBIOS SAS3108_4 0x0095 SAS3108
+product SYMBIOS SAS3004 0x0096 SAS3004
+product SYMBIOS SAS3008 0x0097 SAS3008
product SYMBIOS MEGARAID_320 0x0407 MegaRAID 320
product SYMBIOS MEGARAID_3202E 0x0408 MegaRAID 320-2E
product SYMBIOS MEGARAID_SATA 0x0409 MegaRAID SATA 4x/8x