diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2009-12-01 01:40:03 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2009-12-01 01:40:03 +0000 |
commit | 56901e51ebf1db9a1c61f31f83c5b6e63d702f20 (patch) | |
tree | e67ac5f8cc1747cdb9604d963d72edfc3d46c789 /sys/scsi/scsiconf.c | |
parent | 92a8e1a40ad01eb3ce5d68d4a5b10308e44cdf34 (diff) |
put the midlayer changes back in.
the two issues affecting it last time are gone. the first, mishandling of
TRY_AGAIN_LATER is not relevant now that krw got rid of TRY_AGAIN_LATER.
the second, the misbehaving IBM disk was found to be a problem with siop
using ordered tags on most ops combined with the speed of the new code.
putting this in so we can move forward.
ok krw@ "commit please" marco@
Diffstat (limited to 'sys/scsi/scsiconf.c')
-rw-r--r-- | sys/scsi/scsiconf.c | 229 |
1 files changed, 196 insertions, 33 deletions
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c index 58d0f609d22..c2dbd8c4cbd 100644 --- a/sys/scsi/scsiconf.c +++ b/sys/scsi/scsiconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scsiconf.c,v 1.151 2009/11/12 06:20:27 dlg Exp $ */ +/* $OpenBSD: scsiconf.c,v 1.152 2009/12/01 01:40:02 dlg Exp $ */ /* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */ /* @@ -113,6 +113,10 @@ int scsi_autoconf = SCSI_AUTOCONF; int scsibusprint(void *, const char *); void scsibus_printlink(struct scsi_link *); +void scsi_activate_bus(struct scsibus_softc *, int); +void scsi_activate_target(struct scsibus_softc *, int, int); +void scsi_activate_lun(struct scsibus_softc *, int, int, int); + const u_int8_t version_to_spc [] = { 0, /* 0x00: The device does not claim conformance to any standard. */ 1, /* 0x01: (Obsolete) SCSI-1 in olden times. */ @@ -199,30 +203,99 @@ scsibusattach(struct device *parent, struct device *self, void *aux) int scsibusactivate(struct device *dev, int act) { - return (config_activate_children(dev, act)); + struct scsibus_softc *sc = (struct scsibus_softc *)dev; + + scsi_activate(sc, -1, -1, act); + + return (0); +} + +void +scsi_activate(struct scsibus_softc *sc, int target, int lun, int act) +{ + if (target == -1 && lun == -1) + scsi_activate_bus(sc, act); + + if (target == -1) + return; + + if (lun == -1) + scsi_activate_target(sc, target, act); + + scsi_activate_lun(sc, target, lun, act); +} + +void +scsi_activate_bus(struct scsibus_softc *sc, int act) +{ + int target; + + for (target = 0; target < sc->sc_buswidth; target++) + scsi_activate_target(sc, target, act); +} + +void +scsi_activate_target(struct scsibus_softc *sc, int target, int act) +{ + int lun; + + for (lun = 0; lun < sc->adapter_link->luns; lun++) + scsi_activate_lun(sc, target, lun, act); +} + +void +scsi_activate_lun(struct scsibus_softc *sc, int target, int lun, int act) +{ + struct scsi_link *link = sc->sc_link[target][lun]; + struct device *dev; + + if (link == NULL) + return; + + dev = link->device_softc; + switch (act) { + case DVACT_ACTIVATE: +#if NMPATH > 0 + if (dev == NULL) + mpath_path_activate(link); + else +#endif /* NMPATH */ + config_activate(dev); + break; + + case DVACT_DEACTIVATE: +#if NMPATH > 0 + if (dev == NULL) + mpath_path_deactivate(link); + else +#endif /* NMPATH */ + config_deactivate(dev); + break; + default: +#ifdef DIAGNOSTIC + printf("%s: unsupported act %d\n", sc->sc_dev.dv_xname, act); +#endif + break; + } } int scsibusdetach(struct device *dev, int type) { struct scsibus_softc *sb = (struct scsibus_softc *)dev; - int i, j, error; + int i, error; #if NBIO > 0 bio_unregister(&sb->sc_dev); #endif - if ((error = config_detach_children(dev, type)) != 0) + error = scsi_detach_bus(sb, type); + if (error != 0) return (error); for (i = 0; i < sb->sc_buswidth; i++) { - if (sb->sc_link[i] != NULL) { - for (j = 0; j < sb->adapter_link->luns; j++) { - if (sb->sc_link[i][j] != NULL) - free(sb->sc_link[i][j], M_DEVBUF); - } + if (sb->sc_link[i] != NULL) free(sb->sc_link[i], M_DEVBUF); - } } free(sb->sc_link, M_DEVBUF); @@ -274,6 +347,9 @@ scsibus_bioctl(struct device *dev, u_long cmd, caddr_t addr) case SBIOCDETACH: sdev = (struct sbioc_device *)addr; + if (sdev->sd_target == -1 && sdev->sd_lun == -1) + return (scsi_detach_bus(sc, 0)); + if (sdev->sd_target == -1) return (EINVAL); @@ -379,19 +455,22 @@ int scsi_detach_bus(struct scsibus_softc *sc, int flags) { struct scsi_link *alink = sc->adapter_link; - int i; + int i, err, rv = 0; - for (i = 0; i < alink->adapter_buswidth; i++) - scsi_detach_target(sc, i, flags); + for (i = 0; i < alink->adapter_buswidth; i++) { + err = scsi_detach_target(sc, i, flags); + if (err != 0 && err != ENXIO) + rv = err; + } - return (0); + return (rv); } int scsi_detach_target(struct scsibus_softc *sc, int target, int flags) { struct scsi_link *alink = sc->adapter_link; - int i, err, rv = 0, detached = 0; + int i, err, rv = 0; if (target < 0 || target >= alink->adapter_buswidth || target == alink->adapter_target) @@ -405,12 +484,11 @@ scsi_detach_target(struct scsibus_softc *sc, int target, int flags) continue; err = scsi_detach_lun(sc, target, i, flags); - if (err != 0) + if (err != 0 && err != ENXIO) rv = err; - detached = 1; } - return (detached ? rv : ENXIO); + return (rv); } int @@ -453,6 +531,8 @@ scsi_detach_lun(struct scsibus_softc *sc, int target, int lun, int flags) alink->adapter->dev_free(link); /* 3. free up its state in the midlayer */ + if (link->id != NULL) + devid_free(link->id); free(link, M_DEVBUF); sc->sc_link[target][lun] = NULL; @@ -685,6 +765,42 @@ scsibus_printlink(struct scsi_link *link) printf("SCSI%d", SCSISPC(inqbuf->version)); printf(" %d/%s %s%s", type, dtype, removable ? "removable" : "fixed", qtype); + +#if NMPATH > 0 + if (link->id != NULL && link->id->d_type != DEVID_NONE) { + u_int8_t *id = (u_int8_t *)(link->id + 1); + int i; + + switch (link->id->d_type) { + case DEVID_NAA: + printf(" naa."); + break; + case DEVID_EUI: + printf(" eui."); + break; + case DEVID_T10: + printf(" t10."); + break; + } + + if (ISSET(link->id->d_flags, DEVID_F_PRINT)) { + for (i = 0; i < link->id->d_len; i++) { + if (id[i] == '\0' || id[i] == ' ') + printf("_"); + else if (id[i] < 0x20 || id[i] >= 0x80) { + /* non-printable characters */ + printf("~"); + } else { + /* normal characters */ + printf("%c", id[i]); + } + } + } else { + for (i = 0; i < link->id->d_len; i++) + printf("%02x", id[i]); + } + } +#endif /* NMPATH > 0 */ } /* @@ -738,6 +854,7 @@ scsi_probedev(struct scsibus_softc *scsi, int target, int lun) sc_link->target = target; sc_link->lun = lun; sc_link->device = &probe_switch; + mtx_init(&sc_link->mtx, IPL_BIO); inqbuf = &sc_link->inqdata; SC_DEBUG(sc_link, SDEV_DB2, ("scsi_link created.\n")); @@ -810,15 +927,15 @@ scsi_probedev(struct scsibus_softc *scsi, int target, int lun) ; else if (sc_link->flags & SDEV_UMASS) ; - else if (sc_link->id.d_type != DEVID_NONE && - !DEVID_CMP(&scsi->sc_link[target][0]->id, &sc_link->id)) + else if (sc_link->id != NULL && + !DEVID_CMP(scsi->sc_link[target][0]->id, sc_link->id)) ; else if (memcmp(inqbuf, &scsi->sc_link[target][0]->inqdata, sizeof(*inqbuf)) == 0) { /* The device doesn't distinguish between LUNs. */ SC_DEBUG(sc_link, SDEV_DB1, ("IDENTIFY not supported.\n")); rslt = EINVAL; - goto bad; + goto free_devid; } #if NMPATH > 0 @@ -872,7 +989,7 @@ scsi_probedev(struct scsibus_softc *scsi, int target, int lun) &sa)) == 0) { scsibusprint(&sa, scsi->sc_dev.dv_xname); printf(" not configured\n"); - goto bad; + goto free_devid; } /* @@ -909,6 +1026,9 @@ scsi_probedev(struct scsibus_softc *scsi, int target, int lun) return (0); +free_devid: + if (sc_link->id) + devid_free(sc_link->id); bad: if (scsi->adapter_link->adapter->dev_free != NULL) scsi->adapter_link->adapter->dev_free(sc_link); @@ -979,6 +1099,9 @@ scsi_devid(struct scsi_link *link) } __packed pg; int pg80 = 0, pg83 = 0, i; + if (link->id != NULL) + return; + if (SCSISPC(link->inqdata.version) >= 2) { if (scsi_inquire_vpd(link, &pg, sizeof(pg), SI_PG_SUPPORTED, scsi_autoconf) != 0) @@ -1008,9 +1131,10 @@ int scsi_devid_pg83(struct scsi_link *link) { struct scsi_vpd_hdr hdr; - struct scsi_vpd_devid_hdr dhdr; + struct scsi_vpd_devid_hdr dhdr, chdr; u_int8_t *pg, *id; - int type, idtype = 0, idlen; + int type, idtype = 0; + u_char idflags; int len, pos; int rv; @@ -1048,7 +1172,8 @@ scsi_devid_pg83(struct scsi_link *link) case VPD_DEVID_TYPE_T10: if (type >= idtype) { idtype = type; - idlen = dhdr.len; + + chdr = dhdr; id = &pg[pos]; } break; @@ -1063,21 +1188,27 @@ scsi_devid_pg83(struct scsi_link *link) } while (idtype != VPD_DEVID_TYPE_NAA && len != pos); if (idtype > 0) { - link->id.d_id = malloc(idlen, M_DEVBUF, M_WAITOK); - - switch (idtype) { + switch (VPD_DEVID_TYPE(chdr.flags)) { case VPD_DEVID_TYPE_NAA: - link->id.d_type = DEVID_NAA; + idtype = DEVID_NAA; break; case VPD_DEVID_TYPE_EUI64: - link->id.d_type = DEVID_EUI; + idtype = DEVID_EUI; break; case VPD_DEVID_TYPE_T10: - link->id.d_type = DEVID_T10; + idtype = DEVID_T10; break; } - link->id.d_len = idlen; - memcpy(link->id.d_id, id, idlen); + switch (VPD_DEVID_CODE(chdr.pi_code)) { + case VPD_DEVID_CODE_ASCII: + case VPD_DEVID_CODE_UTF8: + idflags = DEVID_F_PRINT; + break; + default: + idflags = 0; + break; + } + link->id = devid_alloc(idtype, idflags, chdr.len, id); } else rv = ENODEV; @@ -1095,3 +1226,35 @@ scsi_minphys(struct buf *bp, struct scsi_link *sl) { minphys(bp); } + +struct devid * +devid_alloc(u_int8_t type, u_int8_t flags, u_int8_t len, u_int8_t *id) +{ + struct devid *d; + + d = malloc(sizeof(*d) + len, M_DEVBUF, M_WAITOK|M_CANFAIL); + if (d == NULL) + return (NULL); + + d->d_type = type; + d->d_flags = flags; + d->d_len = len; + d->d_refcount = 1; + memcpy(d + 1, id, len); + + return (d); +} + +struct devid * +devid_copy(struct devid *d) +{ + d->d_refcount++; + return (d); +} + +void +devid_free(struct devid *d) +{ + if (--d->d_refcount == 0) + free(d, M_DEVBUF); +} |