Fix the handling of the UCS_RXSTOP flag so that it always tracks

whether or not the receive pipe is stopped. This ensures that we
do not attempt to start the same transfer twice, and it allows
ucomstop() to skip the restarting of the read pipe if it was not
originally running, such as when called indirectly from ucomreadcb().

PR:		kern/79420
MFC after:	1 day
This commit is contained in:
Ian Dowse 2005-04-12 00:26:40 +00:00
parent 308f942ec9
commit f04d2ba47f

View File

@ -297,6 +297,7 @@ ucomopen(struct tty *tp, struct cdev *dev)
goto fail;
}
sc->sc_state |= UCS_RXSTOP;
ucomstartread(sc);
sc->sc_poll = 1;
@ -621,7 +622,7 @@ ucomstop(struct tty *tp, int flag)
DPRINTF(("ucomstop: %d\n", flag));
if (flag & FREAD) {
if ((flag & FREAD) && (sc->sc_state & UCS_RXSTOP) == 0) {
DPRINTF(("ucomstop: read\n"));
ucomstopread(sc);
ucomstartread(sc);
@ -701,10 +702,9 @@ ucomstartread(struct ucom_softc *sc)
DPRINTF(("ucomstartread: start\n"));
sc->sc_state &= ~UCS_RXSTOP;
if (sc->sc_bulkin_pipe == NULL)
if (sc->sc_bulkin_pipe == NULL || (sc->sc_state & UCS_RXSTOP) == 0)
return (USBD_NORMAL_COMPLETION);
sc->sc_state &= ~UCS_RXSTOP;
usbd_setup_xfer(sc->sc_ixfer, sc->sc_bulkin_pipe,
(usbd_private_handle)sc,
@ -713,7 +713,8 @@ ucomstartread(struct ucom_softc *sc)
USBD_NO_TIMEOUT, ucomreadcb);
err = usbd_transfer(sc->sc_ixfer);
if (err != USBD_IN_PROGRESS) {
if (err && err != USBD_IN_PROGRESS) {
sc->sc_state |= UCS_RXSTOP;
DPRINTF(("ucomstartread: err = %s\n", usbd_errstr(err)));
return (err);
}
@ -738,11 +739,13 @@ ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
if (!(sc->sc_state & UCS_RXSTOP))
printf("%s: ucomreadcb: %s\n",
USBDEVNAME(sc->sc_dev), usbd_errstr(status));
sc->sc_state |= UCS_RXSTOP;
if (status == USBD_STALLED)
usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
/* XXX we should restart after some delay. */
return;
}
sc->sc_state |= UCS_RXSTOP;
usbd_get_xfer_status(xfer, NULL, (void **)&cp, &cc, NULL);
DPRINTF(("ucomreadcb: got %d chars, tp = %p\n", cc, tp));