summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2010-09-10 07:00:57 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2010-09-10 07:00:57 +0000
commit2dd934c537b8101da0cb472584f8dedd02ab04ff (patch)
tree830fcad4b7c1a210aa947afe6a46eada8ef7f9f8
parent63a05ea837ed7d3e3b1527603352006f3207e601 (diff)
implement handling of rescan events on fc controllers. allows "hotplug" of
fc devices.
-rw-r--r--sys/dev/ic/mpi.c80
-rw-r--r--sys/dev/ic/mpivar.h6
2 files changed, 81 insertions, 5 deletions
diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c
index 120e677e998..04f837b7656 100644
--- a/sys/dev/ic/mpi.c
+++ b/sys/dev/ic/mpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpi.c,v 1.157 2010/08/27 05:30:59 dlg Exp $ */
+/* $OpenBSD: mpi.c,v 1.158 2010/09/10 07:00:56 dlg Exp $ */
/*
* Copyright (c) 2005, 2006, 2009 David Gwynne <dlg@openbsd.org>
@@ -140,6 +140,8 @@ void mpi_eventnotify_done(struct mpi_ccb *);
void mpi_eventack(void *, void *);
void mpi_eventack_done(struct mpi_ccb *);
void mpi_evt_sas(struct mpi_softc *, struct mpi_rcb *);
+void mpi_evt_fc_rescan(struct mpi_softc *);
+void mpi_fc_rescan(void *, void *);
int mpi_req_cfg_header(struct mpi_softc *, u_int8_t,
u_int8_t, u_int32_t, int, void *);
@@ -204,6 +206,9 @@ mpi_attach(struct mpi_softc *sc)
printf("\n");
+ rw_init(&sc->sc_lock, "mpi_lock");
+ mtx_init(&sc->sc_evt_rescan_mtx, IPL_BIO);
+
/* disable interrupts */
mpi_write(sc, MPI_INTR_MASK,
MPI_INTR_MASK_REPLY | MPI_INTR_MASK_DOORBELL);
@@ -254,11 +259,14 @@ mpi_attach(struct mpi_softc *sc)
goto free_replies;
}
- if (sc->sc_porttype == MPI_PORTFACTS_PORTTYPE_SAS) {
+ switch (sc->sc_porttype) {
+ case MPI_PORTFACTS_PORTTYPE_FC:
+ case MPI_PORTFACTS_PORTTYPE_SAS:
if (mpi_eventnotify(sc) != 0) {
printf("%s: unable to enable events\n", DEVNAME(sc));
goto free_replies;
}
+ break;
}
if (mpi_portenable(sc) != 0) {
@@ -282,8 +290,6 @@ mpi_attach(struct mpi_softc *sc)
break;
}
- rw_init(&sc->sc_lock, "mpi_lock");
-
/* get raid pages */
mpi_get_raid(sc);
#if NBIO > 0
@@ -2232,6 +2238,12 @@ mpi_eventnotify_done(struct mpi_ccb *ccb)
mpi_evt_sas(sc, ccb->ccb_rcb);
break;
+ case MPI_EVENT_RESCAN:
+ if (sc->sc_scsibus != NULL &&
+ sc->sc_porttype == MPI_PORTFACTS_PORTTYPE_FC)
+ mpi_evt_fc_rescan(sc);
+ break;
+
default:
DNPRINTF(MPI_D_EVT, "%s: unhandled event 0x%02x\n",
DEVNAME(sc), letoh32(enp->event));
@@ -2287,6 +2299,66 @@ mpi_evt_sas(struct mpi_softc *sc, struct mpi_rcb *rcb)
}
void
+mpi_evt_fc_rescan(struct mpi_softc *sc)
+{
+ int queue = 1;
+
+ mtx_enter(&sc->sc_evt_rescan_mtx);
+ if (sc->sc_evt_rescan_sem)
+ queue = 0;
+ else
+ sc->sc_evt_rescan_sem = 1;
+ mtx_leave(&sc->sc_evt_rescan_mtx);
+
+ if (queue) {
+ workq_queue_task(NULL, &sc->sc_evt_rescan, 0,
+ mpi_fc_rescan, sc, NULL);
+ }
+}
+
+void
+mpi_fc_rescan(void *xsc, void *xarg)
+{
+ struct mpi_softc *sc = xsc;
+ struct mpi_cfg_hdr hdr;
+ struct mpi_cfg_fc_device_pg0 pg;
+ struct scsi_link *link;
+ u_int32_t id;
+ int i;
+
+ mtx_enter(&sc->sc_evt_rescan_mtx);
+ sc->sc_evt_rescan_sem = 0;
+ mtx_leave(&sc->sc_evt_rescan_mtx);
+
+ for (i = 0; i < sc->sc_buswidth; i++) {
+ id = MPI_PAGE_ADDRESS_FC_BTID | i;
+
+ if (mpi_req_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_FC_DEV, 0,
+ id, 0, &hdr) != 0) {
+ printf("%s: header get for rescan of %d failed\n",
+ DEVNAME(sc), i);
+ return;
+ }
+
+ link = scsi_get_link(sc->sc_scsibus, i, 0);
+
+ memset(&pg, 0, sizeof(pg));
+ if (mpi_req_cfg_page(sc, id, 0, &hdr, 1,
+ &pg, sizeof(pg)) == 0) {
+ if (link == NULL)
+ scsi_probe_target(sc->sc_scsibus, i);
+ } else {
+ if (link != NULL) {
+ scsi_activate(sc->sc_scsibus, i, -1,
+ DVACT_DEACTIVATE);
+ scsi_detach_target(sc->sc_scsibus, i,
+ DETACH_FORCE);
+ }
+ }
+ }
+}
+
+void
mpi_eventack(void *cookie, void *io)
{
struct mpi_softc *sc = cookie;
diff --git a/sys/dev/ic/mpivar.h b/sys/dev/ic/mpivar.h
index eed69bfe6e5..bc9875ff2c4 100644
--- a/sys/dev/ic/mpivar.h
+++ b/sys/dev/ic/mpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpivar.h,v 1.32 2010/07/06 07:18:18 dlg Exp $ */
+/* $OpenBSD: mpivar.h,v 1.33 2010/09/10 07:00:56 dlg Exp $ */
/*
* Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
@@ -136,6 +136,10 @@ struct mpi_softc {
struct mpi_ccb *sc_evt_ccb;
struct scsi_iohandler sc_evt_ack;
+ struct workq_task sc_evt_rescan;
+ struct mutex sc_evt_rescan_mtx;
+ u_int sc_evt_rescan_sem;
+
size_t sc_fw_len;
struct mpi_dmamem *sc_fw;