diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2006-07-09 13:35:11 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2006-07-09 13:35:11 +0000 |
commit | 8b2e05a9250c7f879022f6ac3916608d8b9f25a3 (patch) | |
tree | 7d7cb8d72aff9612d2829ef74afdba426ff008f4 /sys/dev/ic | |
parent | 3a3a5de63daf83aed90cb73e5d4fd6f7710e187c (diff) |
implement firmware upload. this frees up memory on some controllers so they
can do more io at a time. tested on the onboard controllers of a dell 2850
(which can do it) and a pci controller on my home box (which doesnt). this
was the last feature mpt had that mpi was behind on.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/mpi.c | 84 | ||||
-rw-r--r-- | sys/dev/ic/mpivar.h | 5 |
2 files changed, 87 insertions, 2 deletions
diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c index a2998b01f8d..c0ab6fd82a5 100644 --- a/sys/dev/ic/mpi.c +++ b/sys/dev/ic/mpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpi.c,v 1.58 2006/07/06 09:59:42 dlg Exp $ */ +/* $OpenBSD: mpi.c,v 1.59 2006/07/09 13:35:10 dlg Exp $ */ /* * Copyright (c) 2005, 2006 David Gwynne <dlg@openbsd.org> @@ -113,6 +113,7 @@ int mpi_eventnotify(struct mpi_softc *); void mpi_eventnotify_done(struct mpi_ccb *); int mpi_portenable(struct mpi_softc *); void mpi_get_raid(struct mpi_softc *); +int mpi_fwupload(struct mpi_softc *); int mpi_cfg_header(struct mpi_softc *, u_int8_t, u_int8_t, u_int32_t, struct mpi_cfg_hdr *); @@ -201,6 +202,11 @@ mpi_attach(struct mpi_softc *sc) goto free_replies; } + if (mpi_fwupload(sc) != 0) { + printf("%s: unable to upload firmware\n", DEVNAME(sc)); + goto free_replies; + } + /* we should be good to go now, attach scsibus */ sc->sc_link.device = &mpi_dev; sc->sc_link.adapter = &mpi_switch; @@ -1785,6 +1791,8 @@ mpi_iocfacts(struct mpi_softc *sc) else sc->sc_buswidth = (ifp.max_devices == 0) ? 256 : ifp.max_devices; + if (ifp.flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) + sc->sc_fw_len = letoh32(ifp.fw_image_size); /* * you can fit sg elements on the end of the io cmd if they fit in the @@ -2067,6 +2075,80 @@ mpi_portenable(struct mpi_softc *sc) return (0); } +int +mpi_fwupload(struct mpi_softc *sc) +{ + struct mpi_ccb *ccb; + struct { + struct mpi_msg_fwupload_request req; + struct mpi_sge sge; + } __packed *bundle; + struct mpi_msg_fwupload_reply *upp; + u_int64_t addr; + int s; + int rv = 0; + + if (sc->sc_fw_len == 0) + return (0); + + DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload\n", DEVNAME(sc)); + + sc->sc_fw = mpi_dmamem_alloc(sc, sc->sc_fw_len); + if (sc->sc_fw == NULL) { + DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload unable to allocate %d\n", + DEVNAME(sc), sc->sc_fw_len); + return (1); + } + + s = splbio(); + ccb = mpi_get_ccb(sc); + splx(s); + if (ccb == NULL) { + DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload ccb_get\n", + DEVNAME(sc)); + goto err; + } + + ccb->ccb_done = mpi_empty_done; + bundle = ccb->ccb_cmd; + + bundle->req.function = MPI_FUNCTION_FW_UPLOAD; + bundle->req.msg_context = htole32(ccb->ccb_id); + + bundle->req.image_type = MPI_FWUPLOAD_IMAGETYPE_IOC_FW; + + bundle->req.tce.details_length = 12; + bundle->req.tce.image_size = htole32(sc->sc_fw_len); + + bundle->sge.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | + MPI_SGE_FL_SIZE_64 | MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | + MPI_SGE_FL_EOL | (u_int32_t)sc->sc_fw_len); + addr = MPI_DMA_DVA(sc->sc_fw); + bundle->sge.sg_hi_addr = htole32((u_int32_t)(addr >> 32)); + bundle->sge.sg_lo_addr = htole32((u_int32_t)addr); + + if (mpi_poll(sc, ccb, 50000) != 0) { + DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header poll\n", DEVNAME(sc)); + goto err; + } + + upp = ccb->ccb_reply; + if (upp == NULL) + panic("%s: unable to do fw upload\n", DEVNAME(sc)); + + if (letoh16(upp->ioc_status) != MPI_IOCSTATUS_SUCCESS) + rv = 1; + + mpi_push_reply(sc, ccb->ccb_reply_dva); + mpi_put_ccb(sc, ccb); + + return (rv); + +err: + mpi_dmamem_free(sc, sc->sc_fw); + return (1); +} + void mpi_get_raid(struct mpi_softc *sc) { diff --git a/sys/dev/ic/mpivar.h b/sys/dev/ic/mpivar.h index 98e9bcab17c..b457acd9df7 100644 --- a/sys/dev/ic/mpivar.h +++ b/sys/dev/ic/mpivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mpivar.h,v 1.18 2006/07/06 09:59:43 dlg Exp $ */ +/* $OpenBSD: mpivar.h,v 1.19 2006/07/09 13:35:10 dlg Exp $ */ /* * Copyright (c) 2005 David Gwynne <dlg@openbsd.org> @@ -121,6 +121,9 @@ struct mpi_softc { struct mpi_ccb_list sc_ccb_free; struct mpi_dmamem *sc_replies; + + size_t sc_fw_len; + struct mpi_dmamem *sc_fw; }; int mpi_attach(struct mpi_softc *); |