Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 19 Dec 2007 21:56:33 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 131257 for review
Message-ID:  <200712192156.lBJLuXt3055062@repoman.freebsd.org>

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

Change 131257 by hselasky@hselasky_laptop001 on 2007/12/19 21:55:33

	
	Switch over to using kthread instead of SWI's.
	
	I caught several panics when using "intr_event_destroy".
	
	Suggested by "John Baldwin".

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#81 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#80 edit

Differences ...

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

@@ -632,8 +632,7 @@
 	LIST_HEAD(, usbd_xfer) dma_head;
 	LIST_HEAD(, usbd_xfer) done_head;
 
-	struct intr_event *done_event;	/* software interrupt event */
-	void   *done_cookie;		/* software interrupt thread cookie */
+	struct proc *done_thread;
 	void   *memory_base;
 	struct mtx *priv_mtx;
 	struct mtx *usb_mtx;
@@ -659,6 +658,7 @@
 					 * called */
 
 	uint8_t	dma_tag_max;
+	uint8_t	done_sleep;		/* set if done thread is sleeping */
 };
 
 struct usbd_mbuf {

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

@@ -43,8 +43,8 @@
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
-#include <sys/bus.h>
-#include <sys/interrupt.h>
+#include <sys/kthread.h>
+#include <sys/unistd.h>
 
 #include <dev/usb/usb_port.h>
 #include <dev/usb/usb.h>
@@ -55,15 +55,16 @@
 
 static void usbd_pipe_enter_wrapper(struct usbd_xfer *xfer);
 static void usbd_compute_max_frame_size(struct usbd_xfer *xfer);
-static void usbd_drop_refcount(struct usbd_memory_info *info, uint8_t dropcount);
 static uint8_t usbd_start_hardware_sub(struct usbd_xfer *xfer);
 static void usbd_premature_callback(struct usbd_xfer *xfer, usbd_status_t error);
 static void usbd_delayed_transfer_start(void *arg);
 static void usbd_bdma_work_loop(struct usbd_memory_info *info);
 static void usbd_bdma_cancel_event(struct usbd_xfer *xfer);
 static usbd_status_t usbd_handle_request(struct usbd_xfer *xfer);
-static driver_intr_t usbd_callback_intr_td;
+static void usbd_callback_intr_td(void *arg);
 static void usbd_transfer_unsetup_sub(struct usbd_memory_info *info);
+static void usbd_callback_intr_sched(struct usbd_memory_info *info);
+
 
 #ifdef USB_DEBUG
 void
@@ -835,12 +836,10 @@
 
 			LIST_INIT(&(info->done_head));
 
-			/* create our interrupt thread */
-			if (swi_add(&(info->done_event), "usbcb",
-			    &usbd_callback_intr_td, info, SWI_CAMBIO,
-			    INTR_MPSAFE, &(info->done_cookie))) {
-				info->done_cookie = NULL;
-				info->done_event = NULL;
+			if (usb_thread_create
+			    (&usbd_callback_intr_td, info,
+			    &(info->done_thread), "USB interrupt thread")) {
+				info->done_thread = NULL;
 				parm.err = USBD_NO_INTR_THREAD;
 				goto done;
 			}
@@ -1018,23 +1017,6 @@
 }
 
 /*------------------------------------------------------------------------*
- *	usbd_drop_refcount
- *
- * This function is called from various places, and its job is to
- * wakeup "usbd_transfer_unsetup", when is safe to free the memory.
- *------------------------------------------------------------------------*/
-static void
-usbd_drop_refcount(struct usbd_memory_info *info, uint8_t dropcount)
-{
-	mtx_assert(info->usb_mtx, MA_OWNED);
-
-	if ((info->memory_refcount -= dropcount) == 0) {
-		wakeup(info);
-	}
-	return;
-}
-
-/*------------------------------------------------------------------------*
  *	usbd_dma_delay
  *
  * The following function is called when we need to
@@ -1075,16 +1057,16 @@
 usbd_transfer_unsetup_sub(struct usbd_memory_info *info)
 {
 	struct usbd_page_cache *pc;
-	int error;
+
+	/* wait for interrupt thread to exit */
+
+	while (info->done_thread) {
 
-	/*
-	 * wait for any USB callbacks to
-	 * return
-	 */
+		usbd_callback_intr_sched(info);
 
-	while (info->memory_refcount > 0) {
-		error = mtx_sleep(info, info->usb_mtx, 0,
-		    "usbdwait", 0);
+		if (mtx_sleep(&(info->done_thread), info->usb_mtx,
+		    0, "usbdwait", 0)) {
+		}
 	}
 
 	mtx_unlock(info->usb_mtx);
@@ -1110,11 +1092,6 @@
 	usbd_dma_tag_unsetup(info->dma_tag_p,
 	    info->dma_tag_max);
 
-	/* teardown the interrupt thread, if any */
-	if (info->done_cookie) {
-		swi_remove(info->done_cookie);
-		intr_event_destroy(info->done_event);
-	}
 	/*
 	 * free the "memory_base" last,
 	 * hence the "info" structure is
@@ -2116,6 +2093,18 @@
 	return;
 }
 
+static void
+usbd_callback_intr_sched(struct usbd_memory_info *info)
+{
+	mtx_assert(info->usb_mtx, MA_OWNED);
+
+	if (info->done_sleep) {
+		info->done_sleep = 0;
+		wakeup(info);
+	}
+	return;
+}
+
 /*------------------------------------------------------------------------*
  *	usbd_callback_intr_td
  *
@@ -2190,12 +2179,23 @@
 		mtx_unlock(info->priv_mtx);
 
 		mtx_lock(info->usb_mtx);
-		usbd_drop_refcount(info, dropcount);
+		info->memory_refcount -= dropcount;
 		goto repeat;
 
 	} else {
-		mtx_unlock(info->usb_mtx);
+		if (info->memory_refcount != 0) {
+			info->done_sleep = 1;
+			if (mtx_sleep(info, info->usb_mtx, 0, "usbdone", 0)) {
+				/* should not happen */
+			}
+			goto repeat;
+		}
 	}
+
+	wakeup(&(info->done_thread));
+	info->done_thread = NULL;
+	mtx_unlock(info->usb_mtx);
+	usb_thread_exit(0);
 	return;
 }
 
@@ -2313,7 +2313,7 @@
 			info->memory_refcount++;
 
 			LIST_INSERT_HEAD(&(info->done_head), xfer, done_list);
-			swi_sched(info->done_cookie, 0);
+			usbd_callback_intr_sched(info);
 		}
 		return;
 	} else {



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