From 2780a6859a5af847650e39067a3525e9216c46a8 Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Mon, 26 Nov 2007 15:40:52 +0000 Subject: let scsibus ask the adapter about a device before probing it. also allow the adapter to be notified when a device goes away so it can free any state it maintains about that device. ok deraadt@ marco@ --- sys/scsi/scsiconf.c | 21 ++++++++++++++++++--- sys/scsi/scsiconf.h | 4 +++- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'sys/scsi') diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c index 101228588d6..39d01bdfc97 100644 --- a/sys/scsi/scsiconf.c +++ b/sys/scsi/scsiconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scsiconf.c,v 1.128 2007/11/25 22:28:54 dlg Exp $ */ +/* $OpenBSD: scsiconf.c,v 1.129 2007/11/26 15:40:51 dlg Exp $ */ /* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */ /* @@ -421,14 +421,18 @@ scsi_detach_lun(struct scsibus_softc *sc, int target, int lun, int flags) if (((flags & DETACH_FORCE) == 0) && (link->flags & SDEV_OPEN)) return (EBUSY); - /* detaching a device from scsibus is a two step process... */ + /* detaching a device from scsibus is a three step process... */ /* 1. detach the device */ rv = config_detach(link->device_softc, flags); if (rv != 0) return (rv); - /* 2. free up its state in the midlayer */ + /* 2. free up its state in the adapter */ + if (alink->adapter->dev_free != NULL) + alink->adapter->dev_free(link); + + /* 3. free up its state in the midlayer */ free(link, M_DEVBUF); sc->sc_link[target][lun] = NULL; @@ -716,6 +720,14 @@ scsi_probedev(struct scsibus_softc *scsi, int target, int lun) SC_DEBUG(sc_link, SDEV_DB2, ("scsi_link created.\n")); + /* ask the adapter if this will be a valid device */ + if (scsi->adapter_link->adapter->dev_probe != NULL && + scsi->adapter_link->adapter->dev_probe(sc_link) != 0) { + if (lun == 0) + rslt = EINVAL; + goto free; + } + /* * Tell drivers that are paying attention to avoid sync/wide/tags until * INQUIRY data has been processed and the quirks information is @@ -865,6 +877,9 @@ scsi_probedev(struct scsibus_softc *scsi, int target, int lun) return (0); bad: + if (scsi->adapter_link->adapter->dev_free != NULL) + scsi->adapter_link->adapter->dev_free(sc_link); +free: free(sc_link, M_DEVBUF); return (rslt); } diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h index 6dd5ff63549..301ba634de9 100644 --- a/sys/scsi/scsiconf.h +++ b/sys/scsi/scsiconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: scsiconf.h,v 1.88 2007/11/25 22:28:54 dlg Exp $ */ +/* $OpenBSD: scsiconf.h,v 1.89 2007/11/26 15:40:51 dlg Exp $ */ /* $NetBSD: scsiconf.h,v 1.35 1997/04/02 02:29:38 mycroft Exp $ */ /* @@ -107,6 +107,8 @@ struct scsi_adapter { int (*close_target_lu)(void); int (*ioctl)(struct scsi_link *, u_long, caddr_t, int, struct proc *); + int (*dev_probe)(struct scsi_link *); + void (*dev_free)(struct scsi_link *); }; /* -- cgit v1.2.3