summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorn_hibma <n_hibma@FreeBSD.org>1999-06-13 20:49:12 +0000
committern_hibma <n_hibma@FreeBSD.org>1999-06-13 20:49:12 +0000
commitad6621b237627767b1be38fa484f011b95c9a5cd (patch)
treeafa303a3fb42a9c7da6b4add7fa7a7a135825f4f
parent05f6a4b862edd1b95e87b9206fccc6108b2940ea (diff)
downloadFreeBSD-src-ad6621b237627767b1be38fa484f011b95c9a5cd.zip
FreeBSD-src-ad6621b237627767b1be38fa484f011b95c9a5cd.tar.gz
1) Add non-blocking I/O on read
2) Add checks to make sure we do not dereference the softc when not found because the device has been removed.
-rw-r--r--sys/dev/usb/ums.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c
index a97adb4..c8ec14e 100644
--- a/sys/dev/usb/ums.c
+++ b/sys/dev/usb/ums.c
@@ -397,6 +397,7 @@ ums_detach(device_t self)
* the time the process gets a chance to notice. *_close and friends
* should be fixed to handle this case.
* Or we should do a delayed detach for this.
+ * Does this delay now force tsleep to exit with an error?
*/
#if 0
@@ -627,7 +628,7 @@ ums_close(dev_t dev, int flag, int fmt, struct proc *p)
{
USB_GET_SC(ums, UMSUNIT(dev), sc);
- if (sc == NULL)
+ if (!sc)
return 0;
if (sc->sc_enabled)
@@ -646,14 +647,18 @@ ums_read(dev_t dev, struct uio *uio, int flag)
int error;
s = splusb();
+ if (!sc) {
+ splx(s);
+ return EIO;
+ }
+
while (sc->qcount == 0 ) {
- /* NWH XXX non blocking I/O ??
- if (non blocking I/O ) {
+ if (flag & IO_NDELAY) { /* non-blocking I/O */
splx(s);
return EWOULDBLOCK;
- } else {
- */
- sc->state |= UMS_ASLEEP;
+ }
+
+ sc->state |= UMS_ASLEEP; /* blocking I/O */
error = tsleep(sc, PZERO | PCATCH, "umsrea", 0);
if (error) {
splx(s);
@@ -662,8 +667,23 @@ ums_read(dev_t dev, struct uio *uio, int flag)
splx(s);
return EINTR;
}
+#if defined(__FreeBSD__)
+ /* check whether the device is still there */
+
+ sc = devclass_get_softc(ums_devclass, UMSUNIT(dev));
+ if (!sc) {
+ splx(s);
+ return EIO;
+ }
+#endif
}
+ /*
+ * XXX we could optimise the use of splx/splusb somewhat. The writer
+ * process only extends qcount and qtail. We could copy them and use the copies
+ * to do the copying out of the queue.
+ */
+
while ((sc->qcount > 0) && (uio->uio_resid > 0)) {
l = (sc->qcount < uio->uio_resid? sc->qcount:uio->uio_resid);
if (l > sizeof(buf))
@@ -694,6 +714,9 @@ ums_poll(dev_t dev, int events, struct proc *p)
int revents = 0;
int s;
+ if (!sc)
+ return 0;
+
s = splusb();
if (events & (POLLIN | POLLRDNORM)) {
if (sc->qcount) {
@@ -716,6 +739,9 @@ ums_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
int s;
mousemode_t mode;
+ if (!sc)
+ return EIO;
+
switch(cmd) {
case MOUSE_GETHWINFO:
*(mousehw_t *)addr = sc->hw;
OpenPOWER on IntegriCloud