summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2011-04-27 04:03:12 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2011-04-27 04:03:12 +0000
commit76ee89b420ada585862a7228960e39cacabdb06e (patch)
tree6a5f92227a096a47174a53cc27cb01f2bf7fe40b
parentb9d8e746fc2d42e1df6359d0e417227c03692ead (diff)
rework the scanning of fibre channel ports to match how linux does it.
some fc parts dont like the header requests against missing devices with bus addressing, so now we do the magic iteration over active ports. the original problem was reported by deraadt@ lots of testing and debugging by deraadt@ tested on fc929 and fc949 adapters
-rw-r--r--sys/dev/ic/mpi.c29
-rw-r--r--sys/dev/ic/mpireg.h5
2 files changed, 24 insertions, 10 deletions
diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c
index 63027473fb8..ab3176174fd 100644
--- a/sys/dev/ic/mpi.c
+++ b/sys/dev/ic/mpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpi.c,v 1.167 2011/03/04 15:44:39 mikeb Exp $ */
+/* $OpenBSD: mpi.c,v 1.168 2011/04/27 04:03:11 dlg Exp $ */
/*
* Copyright (c) 2005, 2006, 2009 David Gwynne <dlg@openbsd.org>
@@ -2462,28 +2462,39 @@ mpi_fc_rescan(void *xsc, void *xarg)
struct mpi_cfg_hdr hdr;
struct mpi_cfg_fc_device_pg0 pg;
struct scsi_link *link;
- u_int32_t id;
+ u_int8_t devmap[256 / NBBY];
+ u_int32_t id = 0xffffff;
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;
+ bzero(devmap, sizeof(devmap));
+ do {
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);
+ printf("%s: header get for rescan of 0x%08x failed\n",
+ DEVNAME(sc), id);
return;
}
+ bzero(&pg, sizeof(pg));
+ if (mpi_req_cfg_page(sc, id, 0, &hdr, 1, &pg, sizeof(pg)) != 0)
+ break;
+
+ if (ISSET(pg.flags, MPI_CFG_FC_DEV_0_FLAGS_BUSADDR_VALID) &&
+ pg.current_bus == 0)
+ setbit(devmap, pg.current_target_id);
+
+ id = htole32(pg.port_id);
+ } while (id <= 0xff0000);
+
+ for (i = 0; i < sc->sc_buswidth; i++) {
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 (isset(devmap, i)) {
if (link == NULL)
scsi_probe_target(sc->sc_scsibus, i);
} else {
diff --git a/sys/dev/ic/mpireg.h b/sys/dev/ic/mpireg.h
index acc48d09768..c6d05c8013b 100644
--- a/sys/dev/ic/mpireg.h
+++ b/sys/dev/ic/mpireg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpireg.h,v 1.40 2010/09/13 05:28:29 dlg Exp $ */
+/* $OpenBSD: mpireg.h,v 1.41 2011/04/27 04:03:11 dlg Exp $ */
/*
* Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
@@ -1431,6 +1431,9 @@ struct mpi_cfg_fc_device_pg0 {
u_int8_t protocol;
u_int8_t flags;
+#define MPI_CFG_FC_DEV_0_FLAGS_BUSADDR_VALID (1<<0)
+#define MPI_CFG_FC_DEV_0_FLAGS_PLOGI_INVALID (1<<1)
+#define MPI_CFG_FC_DEV_0_FLAGS_PRLI_INVALID (1<<2)
u_int16_t bb_credit;
u_int16_t max_rx_frame_size;