From 4b6cd0347a7ab11b73a76008d64246a1f3579941 Mon Sep 17 00:00:00 2001 From: Shunsuke Akiyama Date: Mon, 31 Jan 2005 13:58:10 +0000 Subject: Use a taskqueue to handle port status changes. Calling ucom layer directly from interrupt context make a panic. MFC after: 1 week --- sys/dev/usb/uvscom.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'sys/dev/usb/uvscom.c') diff --git a/sys/dev/usb/uvscom.c b/sys/dev/usb/uvscom.c index 96f40d93766a..79f8b44dca4d 100644 --- a/sys/dev/usb/uvscom.c +++ b/sys/dev/usb/uvscom.c @@ -1,6 +1,6 @@ /* $NetBSD: usb/uvscom.c,v 1.1 2002/03/19 15:08:42 augustss Exp $ */ /*- - * Copyright (c) 2001-2002, Shunsuke Akiyama . + * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama . * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -174,6 +175,8 @@ struct uvscom_softc { uint16_t sc_lcr; /* Line control */ u_char sc_usr; /* unit status */ + + struct task sc_task; }; /* @@ -206,6 +209,7 @@ Static int uvscom_ioctl(void *, int, u_long, caddr_t, int, usb_proc_ptr); Static int uvscom_param(void *, int, struct termios *); Static int uvscom_open(void *, int); Static void uvscom_close(void *, int); +Static void uvscom_notify(void *, int); struct ucom_callback uvscom_callback = { uvscom_get_status, @@ -437,6 +441,7 @@ USB_ATTACH(uvscom) DPRINTF(("uvscom: in = 0x%x out = 0x%x intr = 0x%x\n", ucom->sc_bulkin_no, ucom->sc_bulkout_no, sc->sc_intr_number)); + TASK_INIT(&sc->sc_task, 0, uvscom_notify, sc); ucom_attach(&sc->sc_ucom); free(devinfo, M_USBDEV); @@ -904,6 +909,18 @@ uvscom_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) if (ISSET(pstatus, UVSCOM_DCD)) SET(sc->sc_msr, SER_DCD); + /* Deferred notifying to the ucom layer */ + taskqueue_enqueue(taskqueue_swi_giant, &sc->sc_task); +} + +Static void +uvscom_notify(void *arg, int count) +{ + struct uvscom_softc *sc; + + sc = (struct uvscom_softc *)arg; + if (sc->sc_ucom.sc_dying) + return; ucom_status_change(&sc->sc_ucom); } -- cgit v1.3