summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2006-07-09 13:35:11 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2006-07-09 13:35:11 +0000
commit8b2e05a9250c7f879022f6ac3916608d8b9f25a3 (patch)
tree7d7cb8d72aff9612d2829ef74afdba426ff008f4 /sys/dev/ic
parent3a3a5de63daf83aed90cb73e5d4fd6f7710e187c (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.c84
-rw-r--r--sys/dev/ic/mpivar.h5
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 *);