diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2011-04-27 04:03:12 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2011-04-27 04:03:12 +0000 |
commit | 76ee89b420ada585862a7228960e39cacabdb06e (patch) | |
tree | 6a5f92227a096a47174a53cc27cb01f2bf7fe40b | |
parent | b9d8e746fc2d42e1df6359d0e417227c03692ead (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.c | 29 | ||||
-rw-r--r-- | sys/dev/ic/mpireg.h | 5 |
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; |