Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Jun 2006 18:00:50 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 99063 for review
Message-ID:  <200606121800.k5CI0olJ096308@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=99063

Change 99063 by hselasky@hselasky_mini_itx on 2006/06/12 18:00:12

	New feature: Abstracted the waiting for the USB memory to get freed. 
	There is a new function, usbd_transfer_drain() that is used for that.
	See the README for more info. Fixed some panics, where the driver,
	ehci, ohci, uhci and ugen, did not destroy the mutex at detach. This 
	evidently caused "freed memory accessed" panics.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/README#4 edit
.. //depot/projects/usb/src/sys/dev/usb/ehci_pci.c#4 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci_pci.c#4 edit
.. //depot/projects/usb/src/sys/dev/usb/ugen.c#4 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci_pci.c#4 edit
.. //depot/projects/usb/src/sys/dev/usb/uhid.c#7 edit
.. //depot/projects/usb/src/sys/dev/usb/ukbd.c#6 edit
.. //depot/projects/usb/src/sys/dev/usb/ulpt.c#9 edit
.. //depot/projects/usb/src/sys/dev/usb/umodem.c#7 edit
.. //depot/projects/usb/src/sys/dev/usb/ums.c#7 edit
.. //depot/projects/usb/src/sys/dev/usb/uplcom.c#6 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#9 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#5 edit
.. //depot/projects/usb/src/sys/dev/usb/uvisor.c#4 edit
.. //depot/projects/usb/src/sys/dev/usb/uvscom.c#7 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/README#4 (text+ko) ====

@@ -113,7 +113,7 @@
 /*------------------------------------------------------------------------*
  * usbd_status 
  * usbd_transfer_setup(udev, iface_index, pxfer, setup_start,
- *                     n_setup, priv_sc, priv_mtx, priv_func)
+ *                     n_setup, priv_sc, priv_mtx, priv_wait)
  *------------------------------------------------------------------------*/
 
 - "udev" is a pointer to "struct usbd_device"
@@ -135,8 +135,9 @@
 - "priv_mtx" is the private mutex protecting the transfer structure and
   the softc. This pointer is used to initialize "xfer->priv_mtx".
 
-- "priv_func" is a pointer to a function that is called back when the USB
-  system is finished using the "priv_mtx" mutex.
+- "priv_wait" is a pointer to a structure of type "struct usbd_memory_wait",
+  that is passed to "usbd_transfer_drain()" after "usbd_transfer_unsetup()"
+  to wait for the USB system to finish using the "priv_mtx" mutex.
 
 /*------------------------------------------------------------------------*
  * void
@@ -171,6 +172,18 @@
       "xfer->error=USBD_CANCELLED", before this function returns
 
 /*------------------------------------------------------------------------*
+ * void
+ * usbd_transfer_drain(priv_wait, priv_mtx)
+ *------------------------------------------------------------------------*/
+
+- "priv_wait" is a pointer to a structure of type "struct usbd_memory_wait"
+
+- "priv_mtx" is a pointer to a mutex protecting the "priv_wait" structure
+
+NOTE: This function returns when the mutex "priv_mtx", is not used by the USB
+system any more.
+
+/*------------------------------------------------------------------------*
  * struct usbd_config {
  *   type, endpoint, direction, interval, timeout, frames, index
  *   flags, bufsize, callback
@@ -218,5 +231,11 @@
 
 - The "callback" field sets the USB callback. This field is mandatory.
 
+MUTEX NOTE:
+===========
+
+When you create a mutex, using "mtx_init()", don't forget to call "mtx_destroy()" at detach,
+else you can get freed memory accessed panics.
+
 --HPS
 

==== //depot/projects/usb/src/sys/dev/usb/ehci_pci.c#4 (text+ko) ====

@@ -365,6 +365,8 @@
 		sc->io_res = NULL;
 	}
 
+	mtx_destroy(&sc->sc_bus.mtx);
+
 	usb_free_mem(sc, sizeof(*sc));
 
 	device_set_softc(self, NULL);

==== //depot/projects/usb/src/sys/dev/usb/ohci_pci.c#4 (text+ko) ====

@@ -342,6 +342,8 @@
 		sc->io_res = NULL;
 	}
 
+	mtx_destroy(&sc->sc_bus.mtx);
+
 	usb_free_mem(sc, sizeof(*sc));
 
 	device_set_softc(self, NULL);

==== //depot/projects/usb/src/sys/dev/usb/ugen.c#4 (text+ko) ====

@@ -117,6 +117,7 @@
   struct ugen_endpoint	  sc_endpoints[USB_MAX_ENDPOINTS];
   struct ugen_endpoint	  sc_endpoints_end[0];
   struct mtx		  sc_mtx;
+  struct usbd_memory_wait sc_mem_wait;
 };
 
 extern cdevsw_t ugen_cdevsw;
@@ -228,6 +229,12 @@
 
 	/* destroy all devices */
 	ugen_destroy_devnodes(sc, 0);
+
+	/* wait for memory to get freed */
+	usbd_transfer_drain(&(sc->sc_mem_wait), &(sc->sc_mtx));
+
+	mtx_destroy(&sc->sc_mtx);
+
 	return 0;
 }
 
@@ -397,7 +404,7 @@
 	 */
 	error = usbd_transfer_setup(udev, iface_index, &temp[0], 
 				    setup, n_setup, 
-				    sce, &sc->sc_mtx, NULL);
+				    sce, &(sc->sc_mtx), &(sc->sc_mem_wait));
 
 	mtx_lock(&sc->sc_mtx);
 

==== //depot/projects/usb/src/sys/dev/usb/uhci_pci.c#4 (text+ko) ====

@@ -367,6 +367,8 @@
 		sc->io_res = NULL;
 	}
 
+	mtx_destroy(&sc->sc_bus.mtx);
+
 	usb_free_mem(sc, sizeof(*sc));
 
 	device_set_softc(self, NULL);

==== //depot/projects/usb/src/sys/dev/usb/uhid.c#7 (text+ko) ====

@@ -96,8 +96,9 @@
 #define	UHID_FRAME_NUM 	  50 /* bytes, frame number */
 
 struct uhid_softc {
-	struct usb_cdev   sc_cdev;
-	struct mtx        sc_mtx;
+	struct usb_cdev         sc_cdev;
+	struct mtx              sc_mtx;
+	struct usbd_memory_wait sc_mem_wait;
 
 	struct usbd_xfer *      sc_xfer[UHID_N_TRANSFER];
 	void *                  sc_repdesc_ptr;
@@ -113,13 +114,11 @@
 	u_int8_t sc_iid;
 	u_int8_t sc_oid;
 	u_int8_t sc_fid;
-	u_int8_t sc_wakeup_detach;
 	u_int8_t sc_flags;
 #define UHID_FLAG_IMMED        0x01 /* set if read should be immediate */
 #define UHID_FLAG_INTR_STALL   0x02 /* set if interrupt transfer stalled */
 #define UHID_FLAG_STATIC_DESC  0x04 /* set if report descriptors are static */
 #define UHID_FLAG_COMMAND_ERR  0x08 /* set if control transfer had an error */
-#define UHID_FLAG_WAIT_USB     0x10 /* set if should wait for USB */
 };
 
 static u_int8_t uhid_xb360gp_report_descr[] = { UHID_XB360GP_REPORT_DESCR() };
@@ -627,23 +626,6 @@
 	return UMATCH_IFACECLASS_GENERIC;
 }
 
-static void
-uhid_detach_complete(struct usbd_memory_info *info)
-{
-	struct uhid_softc *sc = info->priv_sc;
-
-	mtx_lock(&(sc->sc_mtx));
-
-	if (sc->sc_flags &   UHID_FLAG_WAIT_USB) {
-	    sc->sc_flags &= ~UHID_FLAG_WAIT_USB;
-	    wakeup(&(sc->sc_wakeup_detach));
-	}
-
-	mtx_unlock(&(sc->sc_mtx));
-
-	return;
-}
-
 static int
 uhid_attach(device_t dev)
 {
@@ -670,14 +652,12 @@
 
 	error = usbd_transfer_setup(uaa->device, uaa->iface_index, 
 				    sc->sc_xfer, uhid_config, UHID_N_TRANSFER,
-				    sc, &(sc->sc_mtx), &(uhid_detach_complete));
+				    sc, &(sc->sc_mtx), &(sc->sc_mem_wait));
 	if (error) {
 	    DPRINTF(0, "error=%s\n", usbd_errstr(error)) ;
 	    goto detach;
 	}
 
-	sc->sc_flags |= UHID_FLAG_WAIT_USB;
-
 	if (uaa->vendor == USB_VENDOR_WACOM) {
 
 	    /* the report descriptor for the Wacom Graphire is broken */
@@ -805,7 +785,6 @@
 uhid_detach(device_t dev)
 {
 	struct uhid_softc *sc = device_get_softc(dev);
-	int32_t error;
 
 	usb_cdev_detach(&(sc->sc_cdev));
 
@@ -817,13 +796,7 @@
 	    }
 	}
 
-	mtx_lock(&(sc->sc_mtx));
-	while (sc->sc_flags & UHID_FLAG_WAIT_USB) {
-
-	    error = msleep(&(sc->sc_wakeup_detach), &(sc->sc_mtx), 
-			   PRIBIO, "uhid_sync", 0);
-	}
-	mtx_unlock(&(sc->sc_mtx));
+	usbd_transfer_drain(&(sc->sc_mem_wait), &(sc->sc_mtx));
 
 	mtx_destroy(&(sc->sc_mtx));
 

==== //depot/projects/usb/src/sys/dev/usb/ukbd.c#6 (text+ko) ====

@@ -118,6 +118,7 @@
 	struct __callout   sc_callout;
 	struct ukbd_data   sc_ndata;
 	struct ukbd_data   sc_odata;
+	struct usbd_memory_wait sc_mem_wait;
 
 	struct usbd_device * sc_udev;
 	struct usbd_interface * sc_iface;
@@ -136,10 +137,8 @@
 #define UKBD_FLAG_POLLING    0x0002
 #define UKBD_FLAG_SET_LEDS   0x0004
 #define UKBD_FLAG_PIPE_ERROR 0x0008
-#define UKBD_FLAG_WAIT_USB   0x0010
-#define UKBD_FLAG_WAIT_CO    0x0020
-#define UKBD_FLAG_ATTACHED   0x0040
-#define UKBD_FLAG_GONE       0x0080
+#define UKBD_FLAG_ATTACHED   0x0010
+#define UKBD_FLAG_GONE       0x0020
 
 	int32_t            sc_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
 	int32_t		   sc_state;  /* shift/lock key state */
@@ -151,7 +150,6 @@
 
 	u_int8_t           sc_leds;
 	u_int8_t	   sc_iface_index;
-	u_int8_t           sc_wakeup_detach; /* dummy */
 };
 
 #define KEY_ERROR	  0x01
@@ -593,23 +591,6 @@
     },
 };
 
-static void
-ukbd_detach_complete(struct usbd_memory_info *info)
-{
-	struct ukbd_softc *sc = info->priv_sc;
-
-	mtx_lock(&Giant);
-
-	if (sc->sc_flags &   UKBD_FLAG_WAIT_USB) {
-	    sc->sc_flags &= ~UKBD_FLAG_WAIT_USB;
-	    wakeup(&(sc->sc_wakeup_detach));
-	}
-
-	mtx_unlock(&Giant);
-
-	return;
-}
-
 static int
 ukbd_probe(device_t dev)
 {
@@ -669,22 +650,15 @@
 
 	__callout_init_mtx(&(sc->sc_callout), &Giant,
 			   CALLOUT_RETURNUNLOCKED);
-#if 0
-	/* TODO: "__callout_init_mtx()" does not support this: */
 
-	sc->sc_flags |= UKBD_FLAG_WAIT_CO; 
-#endif
-
 	err = usbd_transfer_setup(uaa->device, uaa->iface_index, sc->sc_xfer, 
 				  ukbd_config, UKBD_N_TRANSFER, sc, 
-				  &Giant, &ukbd_detach_complete);
+				  &Giant, &(sc->sc_mem_wait));
 	if (err) {
 	    DPRINTF(0, "error=%s\n", usbd_errstr(err)) ;
 	    goto detach;
 	}
 
-	sc->sc_flags |= UKBD_FLAG_WAIT_USB;
-
 	/* setup default keyboard maps */
 
 	sc->sc_keymap = key_map;
@@ -804,13 +778,7 @@
 
 	usbd_transfer_unsetup(sc->sc_xfer, UKBD_N_TRANSFER);
 
-	/* wait for callbacks to be aborted */
-
-	while (sc->sc_flags & (UKBD_FLAG_WAIT_USB|UKBD_FLAG_WAIT_CO)) {
-
-	    error = msleep(&(sc->sc_wakeup_detach), &Giant, 
-			   PRIBIO, "ukbd_sync_2", 0);
-	}
+	usbd_transfer_drain(&(sc->sc_mem_wait), &Giant);
 
 	DPRINTF(0, "%s: disconnected\n", 
 		device_get_nameunit(dev));

==== //depot/projects/usb/src/sys/dev/usb/ulpt.c#9 (text+ko) ====

@@ -94,6 +94,7 @@
 	struct usb_cdev         sc_cdev;
 	struct __callout	sc_watchdog;
 	struct mtx		sc_mtx;
+	struct usbd_memory_wait sc_mem_wait;
 
 	device_t		sc_dev;
 	struct usbd_xfer *	sc_xfer[ULPT_N_TRANSFER];
@@ -101,15 +102,12 @@
 	u_int8_t		sc_flags;
 #define ULPT_FLAG_NO_READ       0x01 /* device has no read endpoint */
 #define ULPT_FLAG_DUMP_READ     0x02 /* device is not opened for read */
-#define ULPT_FLAG_WAIT_USB      0x04 /* device is waiting for USB callbacks */
-#define ULPT_FLAG_WAIT_CO       0x08 /* device is waiting for callouts */
-#define ULPT_FLAG_READ_STALL    0x10 /* read transfer stalled */
-#define ULPT_FLAG_WRITE_STALL   0x20 /* write transfer stalled */
-#define ULPT_FLAG_RESETTING     0x40 /* device is resetting */
+#define ULPT_FLAG_READ_STALL    0x04 /* read transfer stalled */
+#define ULPT_FLAG_WRITE_STALL   0x08 /* write transfer stalled */
+#define ULPT_FLAG_RESETTING     0x10 /* device is resetting */
 
 	u_int8_t		sc_iface_no;
 	u_int8_t		sc_last_status;
-	u_int8_t		sc_wakeup_detach; /* dummy */
 };
 
 static void
@@ -520,23 +518,6 @@
 	return UMATCH_NONE;
 }
 
-static void
-ulpt_detach_complete(struct usbd_memory_info *info)
-{
-	struct ulpt_softc *sc = info->priv_sc;
-
-	mtx_lock(&(sc->sc_mtx));
-
-	if (sc->sc_flags &   ULPT_FLAG_WAIT_USB) {
-	    sc->sc_flags &= ~ULPT_FLAG_WAIT_USB;
-	    wakeup(&(sc->sc_wakeup_detach));
-	}
-
-	mtx_unlock(&(sc->sc_mtx));
-
-	return;
-}
-
 static int
 ulpt_attach(device_t dev)
 {
@@ -562,11 +543,6 @@
 
 	__callout_init_mtx(&(sc->sc_watchdog),
 			   &(sc->sc_mtx), CALLOUT_RETURNUNLOCKED);
-#if 0
-	/* TODO: "__callout_init_mtx()" does not support this: */
-
-	sc->sc_flags |= ULPT_FLAG_WAIT_CO; 
-#endif
 
 	/* search through all the descriptors looking for bidir mode */
 
@@ -613,15 +589,13 @@
 	sc->sc_iface_no = id->bInterfaceNumber;
 
 	error = usbd_transfer_setup(uaa->device, iface_index, 
-				  sc->sc_xfer, ulpt_config, ULPT_N_TRANSFER, 
-				  sc, &(sc->sc_mtx), &(ulpt_detach_complete));
+				    sc->sc_xfer, ulpt_config, ULPT_N_TRANSFER, 
+				    sc, &(sc->sc_mtx), &(sc->sc_mem_wait));
 	if (error) {
 	    DPRINTF(0, "error=%s\n", usbd_errstr(error)) ;
 	    goto detach;
 	}
 
-	sc->sc_flags |= ULPT_FLAG_WAIT_USB;
-
 	if (usbd_get_quirks(uaa->device)->uq_flags & UQ_BROKEN_BIDIR) {
 		/* this device doesn't handle reading properly. */
 		sc->sc_flags |= ULPT_FLAG_NO_READ;
@@ -709,7 +683,6 @@
 ulpt_detach(device_t dev)
 {
 	struct ulpt_softc *sc = device_get_softc(dev);
-	int error;
 
 	DPRINTF(0, "sc=%p\n", sc);
 
@@ -721,15 +694,7 @@
 
 	usbd_transfer_unsetup(sc->sc_xfer, ULPT_N_TRANSFER);
 
-	/* wait for callbacks to be aborted */
-
-	mtx_lock(&(sc->sc_mtx));
-	while (sc->sc_flags & (ULPT_FLAG_WAIT_USB|ULPT_FLAG_WAIT_CO)) {
-
-	    error = msleep(&(sc->sc_wakeup_detach), &(sc->sc_mtx), 
-			   PRIBIO, "ulpt_sync", 0);
-	}
-	mtx_unlock(&(sc->sc_mtx));
+	usbd_transfer_drain(&(sc->sc_mem_wait), &(sc->sc_mtx));
 
 	mtx_destroy(&(sc->sc_mtx));
 

==== //depot/projects/usb/src/sys/dev/usb/umodem.c#7 (text+ko) ====

@@ -134,6 +134,7 @@
 struct umodem_softc {
 	struct ucom_softc	sc_ucom;
 	usb_cdc_line_state_t	sc_line_state;	/* current line state */
+	struct usbd_memory_wait sc_mem_wait;
 
 	struct usbd_xfer *	sc_xfer_data[UMODEM_N_DATA_TRANSFER];
 	struct usbd_xfer *	sc_xfer_intr[UMODEM_N_INTR_TRANSFER];
@@ -156,11 +157,7 @@
 #define UMODEM_FLAG_INTR_STALL  0x04
 #define UMODEM_FLAG_SET_LS      0x08
 #define UMODEM_FLAG_SEND_BREAK  0x10
-#define UMODEM_FLAG_WAIT_USB_1  0x20
-#define UMODEM_FLAG_WAIT_USB_2  0x40
-#define UMODEM_FLAG_SET_LC      0x80
-
-	u_int8_t		sc_wakeup_detach; /* dummy */
+#define UMODEM_FLAG_SET_LC      0x20
 };
 
 static device_probe_t umodem_probe;
@@ -239,12 +236,6 @@
 static usbd_status
 umodem_set_comm_feature(struct usbd_device *udev, u_int8_t iface_no, int feature, int state);
 
-static void
-umodem_detach_complete_1(struct usbd_memory_info *info);
-
-static void
-umodem_detach_complete_2(struct usbd_memory_info *info);
-
 static const struct usbd_config umodem_config_data[UMODEM_N_DATA_TRANSFER] = {
 
     [0] = {
@@ -503,22 +494,18 @@
 	error = usbd_transfer_setup(uaa->device, sc->sc_data_iface_index,
 				    sc->sc_xfer_data, umodem_config_data, 
 				    UMODEM_N_DATA_TRANSFER,
-				    sc, &Giant, &(umodem_detach_complete_1));
+				    sc, &Giant, &(sc->sc_mem_wait));
 	if (error) {
 	    goto detach;
 	}
 
-	sc->sc_flag |= UMODEM_FLAG_WAIT_USB_1;
-
 	error = usbd_transfer_setup(uaa->device, sc->sc_ctrl_iface_index,
 				    sc->sc_xfer_intr, umodem_config_intr,
 				    UMODEM_N_INTR_TRANSFER,
-				    sc, &Giant, &(umodem_detach_complete_2));
+				    sc, &Giant, &(sc->sc_mem_wait));
 	if (error) {
 	    /* ignore */
 	    DPRINTF(0, "no interrupt pipe!\n");
-	} else {
-	    sc->sc_flag |= UMODEM_FLAG_WAIT_USB_2;
 	}
 
 	sc->sc_rts = -1;
@@ -1092,45 +1079,10 @@
 	return usbd_do_request(udev, &req, &ast);
 }
 
-static void
-umodem_detach_complete_1(struct usbd_memory_info *info)
-{
-	struct umodem_softc *sc = info->priv_sc;
-
-	mtx_lock(&Giant);
-
-	if (sc->sc_flag &   UMODEM_FLAG_WAIT_USB_1) {
-	    sc->sc_flag &= ~UMODEM_FLAG_WAIT_USB_1;
-	    wakeup(&(sc->sc_wakeup_detach));
-	}
-
-	mtx_unlock(&Giant);
-
-	return;
-}
-
-static void
-umodem_detach_complete_2(struct usbd_memory_info *info)
-{
-	struct umodem_softc *sc = info->priv_sc;
-
-	mtx_lock(&Giant);
-
-	if (sc->sc_flag &   UMODEM_FLAG_WAIT_USB_2) {
-	    sc->sc_flag &= ~UMODEM_FLAG_WAIT_USB_2;
-	    wakeup(&(sc->sc_wakeup_detach));
-	}
-
-	mtx_unlock(&Giant);
-
-	return;
-}
-
 static int
 umodem_detach(device_t dev)
 {
 	struct umodem_softc *sc = device_get_softc(dev);
-	int error;
 
 	DPRINTF(0, "sc=%p\n", sc);
 
@@ -1140,13 +1092,7 @@
 
 	usbd_transfer_unsetup(sc->sc_xfer_data, UMODEM_N_DATA_TRANSFER);
 
-	/* wait for callbacks to finish */
-
-	while (sc->sc_flag & (UMODEM_FLAG_WAIT_USB_1|UMODEM_FLAG_WAIT_USB_2)) {
-
-	    error = msleep(&(sc->sc_wakeup_detach), &Giant, 
-			   PRIBIO, "umodem_sync", 0);
-	}
+	usbd_transfer_drain(&(sc->sc_mem_wait), &Giant);
 
 	return 0;
 }

==== //depot/projects/usb/src/sys/dev/usb/ums.c#7 (text+ko) ====

@@ -88,6 +88,7 @@
   struct usbd_ifqueue sc_rdq_free;
   struct usbd_ifqueue sc_rdq_used;
   struct __callout    sc_callout;
+  struct usbd_memory_wait sc_mem_wait;
   struct selinfo      sc_read_sel;
   struct hid_location sc_loc_x; 
   struct hid_location sc_loc_y;
@@ -110,17 +111,14 @@
 #define UMS_FLAG_SBU        0x0010 /* spurious button up events */
 #define UMS_FLAG_SELECT     0x0020 /* select is waiting */
 #define UMS_FLAG_INTR_STALL 0x0040 /* set if transfer error */
-#define UMS_FLAG_WAIT_USB   0x0080 /* device is waiting for callbacks */
-#define UMS_FLAG_WAIT_CO    0x0100 /* device is waiting for callbacks */
-#define UMS_FLAG_GONE       0x0200 /* device is gone */
-#define UMS_FLAG_RD_WUP     0x0400 /* device is waiting for wakeup */
-#define UMS_FLAG_RD_SLP     0x0800 /* device is sleeping */
-#define UMS_FLAG_CLOSING    0x1000 /* device is closing */
-#define UMS_FLAG_DEV_OPEN   0x2000 /* device is open */
+#define UMS_FLAG_GONE       0x0080 /* device is gone */
+#define UMS_FLAG_RD_WUP     0x0100 /* device is waiting for wakeup */
+#define UMS_FLAG_RD_SLP     0x0200 /* device is sleeping */
+#define UMS_FLAG_CLOSING    0x0400 /* device is closing */
+#define UMS_FLAG_DEV_OPEN   0x0800 /* device is open */
 
   u_int8_t	      sc_buttons;
   u_int8_t	      sc_iid;
-  u_int8_t            sc_wakeup_detach; /* dummy */
   u_int8_t            sc_wakeup_read; /* dummy */
   u_int8_t            sc_wakeup_sync_1; /* dummy */
 };
@@ -323,23 +321,6 @@
     },
 };
 
-static void
-ums_detach_complete(struct usbd_memory_info *info)
-{
-	struct ums_softc *sc = info->priv_sc;
-
-	mtx_lock(&(sc->sc_mtx));
-
-	if (sc->sc_flags &   UMS_FLAG_WAIT_USB) {
-	    sc->sc_flags &= ~UMS_FLAG_WAIT_USB;
-	    wakeup(&(sc->sc_wakeup_detach));
-	}
-
-	mtx_unlock(&(sc->sc_mtx));
-
-	return;
-}
-
 static int
 ums_probe(device_t dev)
 {
@@ -403,12 +384,7 @@
 
 	__callout_init_mtx(&(sc->sc_callout),
 			   &(sc->sc_mtx), CALLOUT_RETURNUNLOCKED);
-#if 0
-	/* TODO: "__callout_init_mtx()" does not support this: */
 
-	sc->sc_flags |= UMS_FLAG_WAIT_CO; 
-#endif
-
  	sc->sc_mem_ptr_1 = 
 	  usbd_alloc_mbufs(M_DEVBUF, &(sc->sc_rdq_free), 
 			   UMS_BUF_SIZE, UMS_IFQ_MAXLEN);
@@ -419,14 +395,12 @@
 
 	err = usbd_transfer_setup(uaa->device, uaa->iface_index, sc->sc_xfer, 
 				  ums_config, UMS_N_TRANSFER, sc, 
-				  &(sc->sc_mtx), &ums_detach_complete);
+				  &(sc->sc_mtx), &(sc->sc_mem_wait));
 	if (err) {
 	    DPRINTF(0, "error=%s\n", usbd_errstr(err)) ;
 	    goto detach;
 	}
 
-	sc->sc_flags |= UMS_FLAG_WAIT_USB;
-
 	err = usbreq_read_report_desc(uaa->device, uaa->iface_index, 
 				      &d_ptr, &d_len, M_TEMP);
 	if (err) {
@@ -570,8 +544,6 @@
 {
 	struct ums_softc *sc = device_get_softc(self);
 
-	int error;
-
 	DPRINTF(0, "sc=%p\n", sc);
 
 	mtx_lock(&(sc->sc_mtx));
@@ -599,15 +571,7 @@
 	    free(sc->sc_mem_ptr_1, M_DEVBUF);
 	}
 
-	/* wait for callbacks to be aborted */
-
-	mtx_lock(&(sc->sc_mtx));
-	while (sc->sc_flags & (UMS_FLAG_WAIT_USB|UMS_FLAG_WAIT_CO)) {
-
-	    error = msleep(&(sc->sc_wakeup_detach), &(sc->sc_mtx), 
-			   PRIBIO, "ums_sync_2", 0);
-	}
-	mtx_unlock(&(sc->sc_mtx));
+	usbd_transfer_drain(&(sc->sc_mem_wait), &(sc->sc_mtx));
 
 	mtx_destroy(&(sc->sc_mtx));
 

==== //depot/projects/usb/src/sys/dev/usb/uplcom.c#6 (text+ko) ====

@@ -148,20 +148,19 @@
 struct	uplcom_softc {
 	struct ucom_softc	sc_ucom;
 	usb_cdc_line_state_t	sc_line_state;	/* current line state */
+	struct usbd_memory_wait sc_mem_wait;
 
 	struct usbd_xfer *	sc_xfer_intr[UPLCOM_N_INTR_TRANSFER];
 	struct usbd_xfer *	sc_xfer_data[UPLCOM_N_DATA_TRANSFER];
 
 	u_int16_t		sc_flag;
-#define UPLCOM_FLAG_WAIT_USB_1  0x0001
-#define UPLCOM_FLAG_WAIT_USB_2  0x0002
-#define UPLCOM_FLAG_SET_LS      0x0004
-#define UPLCOM_FLAG_SET_BREAK   0x0008
-#define UPLCOM_FLAG_SET_LC      0x0010
-#define UPLCOM_FLAG_SET_CRTSCTS 0x0020
-#define UPLCOM_FLAG_INTR_STALL  0x0040
-#define UPLCOM_FLAG_READ_STALL  0x0080
-#define UPLCOM_FLAG_WRITE_STALL 0x0100
+#define UPLCOM_FLAG_SET_LS      0x0001
+#define UPLCOM_FLAG_SET_BREAK   0x0002
+#define UPLCOM_FLAG_SET_LC      0x0004
+#define UPLCOM_FLAG_SET_CRTSCTS 0x0008
+#define UPLCOM_FLAG_INTR_STALL  0x0010
+#define UPLCOM_FLAG_READ_STALL  0x0020
+#define UPLCOM_FLAG_WRITE_STALL 0x0040
 
 	u_int8_t		sc_dtr; /* current DTR state */
 	u_int8_t		sc_rts; /* current RTS state */
@@ -174,19 +173,11 @@
 	u_int8_t		sc_data_iface_no;
 	u_int8_t		sc_data_iface_index;
 	u_int8_t		sc_crtscts;
-
-	u_int8_t		sc_wakeup_detach; /* dummy */
 };
 
 static const struct uplcom_product *
 uplcom_find_up(struct usb_attach_arg *uaa);
 
-static void
-uplcom_detach_complete_1(struct usbd_memory_info *info);
-
-static void
-uplcom_detach_complete_2(struct usbd_memory_info *info);
-
 static usbd_status
 uplcom_reset(struct uplcom_softc *sc, struct usbd_device *udev);
 
@@ -536,27 +527,23 @@
 	error = usbd_transfer_setup(uaa->device, sc->sc_data_iface_index,
 				    sc->sc_xfer_data, uplcom_config_data, 
 				    UPLCOM_N_DATA_TRANSFER,
-				    sc, &Giant, &(uplcom_detach_complete_1));
+				    sc, &Giant, &(sc->sc_mem_wait));
 	if (error) {
 	    DPRINTF(0, "one or more missing data "
 		    "pipes, error=%s\n", usbd_errstr(error));
 	    goto detach;
 	}
 
-	sc->sc_flag |= UPLCOM_FLAG_WAIT_USB_1;
-
 	error = usbd_transfer_setup(uaa->device, sc->sc_ctrl_iface_index,
 				    sc->sc_xfer_intr, uplcom_config_intr,
 				    UPLCOM_N_INTR_TRANSFER,
-				    sc, &Giant, &(uplcom_detach_complete_2));
+				    sc, &Giant, &(sc->sc_mem_wait));
 	if (error) {
 	    DPRINTF(0, "no interrupt pipe, error=%s\n",
 		    usbd_errstr(error));
 	    goto detach;
 	}
 
-	sc->sc_flag |= UPLCOM_FLAG_WAIT_USB_2;
-
 	sc->sc_dtr = -1;
 	sc->sc_rts = -1;
 	sc->sc_break = -1;
@@ -596,45 +583,10 @@
 	return ENXIO;
 }
 
-static void
-uplcom_detach_complete_1(struct usbd_memory_info *info)
-{
-	struct uplcom_softc *sc = info->priv_sc;
-
-	mtx_lock(&Giant);
-
-	if (sc->sc_flag &   UPLCOM_FLAG_WAIT_USB_1) {
-	    sc->sc_flag &= ~UPLCOM_FLAG_WAIT_USB_1;
-	    wakeup(&(sc->sc_wakeup_detach));
-	}
-
-	mtx_unlock(&Giant);
-
-	return;
-}
-
-static void
-uplcom_detach_complete_2(struct usbd_memory_info *info)
-{
-	struct uplcom_softc *sc = info->priv_sc;
-
-	mtx_lock(&Giant);
-
-	if (sc->sc_flag &   UPLCOM_FLAG_WAIT_USB_2) {
-	    sc->sc_flag &= ~UPLCOM_FLAG_WAIT_USB_2;
-	    wakeup(&(sc->sc_wakeup_detach));
-	}
-
-	mtx_unlock(&Giant);
-
-	return;
-}
-
 static int
 uplcom_detach(device_t dev)
 {
 	struct uplcom_softc *sc = device_get_softc(dev);
-	int error;
 
 	DPRINTF(0, "sc=%p\n", sc);
 
@@ -644,13 +596,7 @@
 
 	usbd_transfer_unsetup(sc->sc_xfer_data, UPLCOM_N_DATA_TRANSFER);
 
-	/* wait for callbacks to finish */
-
-	while (sc->sc_flag & (UPLCOM_FLAG_WAIT_USB_1|UPLCOM_FLAG_WAIT_USB_2)) {
-
-	    error = msleep(&(sc->sc_wakeup_detach), &Giant, 
-			   PRIBIO, "uplcom_sync", 0);
-	}
+	usbd_transfer_drain(&(sc->sc_mem_wait), &Giant);
 
 	return 0;
 }

==== //depot/projects/usb/src/sys/dev/usb/usb_subr.h#9 (text+ko) ====

@@ -382,16 +382,19 @@
 #endif
 };
 
-typedef void (usbd_unsetup_callback_t)(struct usbd_memory_info *info);
+struct usbd_memory_wait {
+    struct mtx *   priv_mtx;
+    u_int16_t      priv_refcount;
+    u_int16_t      priv_sleeping;
+};
 
 struct usbd_memory_info {
     void *         memory_base;
     u_int32_t      memory_size;
     u_int32_t      memory_refcount;
-    void *         priv_sc;
+    struct usbd_memory_wait * priv_wait;
     struct mtx *   priv_mtx;
     struct mtx *   usb_mtx;
-    usbd_unsetup_callback_t *priv_func;
 };
 
 struct usbd_callback_info {
@@ -662,12 +665,15 @@
 		    u_int16_t n_setup,
 		    void *priv_sc,
 		    struct mtx *priv_mtx,
-		    usbd_unsetup_callback_t *priv_func);
+		    struct usbd_memory_wait *priv_wait);
 
 void
 usbd_transfer_unsetup(struct usbd_xfer **pxfer, u_int16_t n_setup);
 
 void
+usbd_transfer_drain(struct usbd_memory_wait *priv_wait, struct mtx *priv_mtx);
+
+void
 usbd_start_hardware(struct usbd_xfer *xfer);
 
 void

==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#5 (text+ko) ====

@@ -226,7 +226,7 @@
 		    u_int16_t n_setup, 
 		    void *priv_sc,
 		    struct mtx *priv_mtx,
-		    usbd_unsetup_callback_t *priv_func)
+		    struct usbd_memory_wait *priv_wait)
 {
 	const struct usbd_config *setup_end = setup_start + n_setup;
 	const struct usbd_config *setup;
@@ -305,6 +305,7 @@
 		    xfer->priv_sc = priv_sc;
 		    xfer->priv_mtx = priv_mtx;
 		    xfer->udev = udev;
+
 		    if(xfer->pipe)
 		    {
 		        xfer->pipe->refcount++;
@@ -312,9 +313,18 @@
 
 		    info = xfer->usb_root;
 		    info->memory_refcount++;
-		    info->priv_sc = priv_sc;
-		    info->priv_mtx = priv_mtx;
-		    info->priv_func = priv_func;
+
+		    if (info->priv_wait == NULL) {
+
+		        info->priv_wait = priv_wait;
+			info->priv_mtx = priv_mtx;
+
+			if (priv_wait) {
+			    mtx_lock(priv_mtx);
+			    priv_wait->priv_refcount++;
+			    mtx_unlock(priv_mtx);
+			}
+		    }
 		}
 	}
 
@@ -336,11 +346,13 @@
 static void
 usbd_drop_refcount(struct usbd_memory_info *info)
 {
+    struct usbd_memory_wait *priv_wait;
     u_int8_t free_memory;
 
     mtx_lock(info->usb_mtx);
 
-    __KASSERT(info->memory_refcount != 0, ("Invalid memory reference count!\n"));
+    __KASSERT(info->memory_refcount != 0, ("Invalid memory "
+					   "reference count!\n"));
 
     free_memory = ((--(info->memory_refcount)) == 0);
 
@@ -348,10 +360,25 @@
 
     if(free_memory)
     {
-        if(info->priv_func)
-	{
-	    (info->priv_func)(info);
+        priv_wait = info->priv_wait;
+
+	/* check if someone is waiting for 
+	 * the memory to be released:
+	 */
+	if (priv_wait) {
+	    mtx_lock(info->priv_mtx);
+
+	    __KASSERT(priv_wait->priv_refcount != 0, ("Invalid private "
+					       "reference count!\n"));
+	    priv_wait->priv_refcount--;
+
+	    if ((priv_wait->priv_refcount == 0) &&
+		(priv_wait->priv_sleeping != 0)) {
+	        wakeup(priv_wait);
+	    }
+	    mtx_unlock(info->priv_mtx);
 	}
+
 	usb_free_mem(info->memory_base, info->memory_size);
     }
     return;
@@ -367,8 +394,7 @@
  * NOTE: the mutex "xfer->priv_mtx" might be in use by 
  * the USB system after that this function has returned! 
  * Therefore the mutex, "xfer->priv_mtx", should be allocated 
- * in static memory. The function "priv_func" will be called
- * when it is safe to destroy this mutex.
+ * in static memory.
  *---------------------------------------------------------------------------*/
 void
 usbd_transfer_unsetup(struct usbd_xfer **pxfer, u_int16_t n_setup)
@@ -406,6 +432,34 @@
 	return;
 }
 
+/*---------------------------------------------------------------------------*
+ *	usbd_transfer_drain - wait for USB memory to get freed
+ *
+ * This function returns when the mutex "priv_mtx", is not used by the
+ * USB system any more.
+ *---------------------------------------------------------------------------*/
+void
+usbd_transfer_drain(struct usbd_memory_wait *priv_wait, struct mtx *priv_mtx)
+{
+    int error;
+
+    mtx_lock(priv_mtx);
+
+    priv_wait->priv_sleeping = 1;
+
+    while (priv_wait->priv_refcount > 0) {
+
+        error = msleep(priv_wait, priv_mtx, PRIBIO, "usb_drain", 0);
+    }
+
+    priv_wait->priv_sleeping = 0;
+
+    mtx_unlock(priv_mtx);
+
+    return;
+}
+
+
 /* CALLBACK EXAMPLES:
  * ==================
  *

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606121800.k5CI0olJ096308>