aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/usb2
diff options
context:
space:
mode:
authorAndrew Thompson <thompsa@FreeBSD.org>2009-01-13 19:03:23 +0000
committerAndrew Thompson <thompsa@FreeBSD.org>2009-01-13 19:03:23 +0000
commitedf1048c85c7075d5a4346b649d9eb75ef23b1bf (patch)
tree3fed8d0a87880180cb9be6db99f655c4f0d9335b /sys/dev/usb2
parent13bd84042e7965cb455b03d55dba5440d3d47154 (diff)
Notes
Diffstat (limited to 'sys/dev/usb2')
-rw-r--r--sys/dev/usb2/controller/usb2_bus.h7
-rw-r--r--sys/dev/usb2/controller/usb2_controller.c18
-rw-r--r--sys/dev/usb2/core/usb2_device.c10
-rw-r--r--sys/dev/usb2/core/usb2_transfer.c27
-rw-r--r--sys/dev/usb2/core/usb2_transfer.h2
5 files changed, 48 insertions, 16 deletions
diff --git a/sys/dev/usb2/controller/usb2_bus.h b/sys/dev/usb2/controller/usb2_bus.h
index 43776fdda7ad..c81a7a5b9174 100644
--- a/sys/dev/usb2/controller/usb2_bus.h
+++ b/sys/dev/usb2/controller/usb2_bus.h
@@ -53,6 +53,13 @@ struct usb2_bus {
struct usb2_bus_stat stats_ok;
struct usb2_process explore_proc;
struct usb2_process roothub_proc;
+ /*
+ * There are two callback processes. One for Giant locked
+ * callbacks. One for non-Giant locked callbacks. This should
+ * avoid congestion and reduce response time in most cases.
+ */
+ struct usb2_process giant_callback_proc;
+ struct usb2_process non_giant_callback_proc;
struct usb2_bus_msg explore_msg[2];
struct usb2_bus_msg detach_msg[2];
struct usb2_bus_msg attach_msg[2];
diff --git a/sys/dev/usb2/controller/usb2_controller.c b/sys/dev/usb2/controller/usb2_controller.c
index 61ce31482d1b..a9596c76d9ac 100644
--- a/sys/dev/usb2/controller/usb2_controller.c
+++ b/sys/dev/usb2/controller/usb2_controller.c
@@ -166,6 +166,11 @@ usb2_detach(device_t dev)
USB_BUS_UNLOCK(bus);
+ /* Get rid of USB callback processes */
+
+ usb2_proc_unsetup(&bus->giant_callback_proc);
+ usb2_proc_unsetup(&bus->non_giant_callback_proc);
+
/* Get rid of USB roothub process */
usb2_proc_unsetup(&bus->roothub_proc);
@@ -391,8 +396,17 @@ usb2_attach_sub(device_t dev, struct usb2_bus *bus)
bus->roothub_msg[1].hdr.pm_callback = &usb2_bus_roothub;
bus->roothub_msg[1].bus = bus;
- /* Create USB explore and roothub processes */
- if (usb2_proc_setup(&bus->roothub_proc,
+ /* Create USB explore, roothub and callback processes */
+
+ if (usb2_proc_setup(&bus->giant_callback_proc,
+ &bus->bus_mtx, USB_PRI_MED)) {
+ printf("WARNING: Creation of USB Giant "
+ "callback process failed.\n");
+ } else if (usb2_proc_setup(&bus->non_giant_callback_proc,
+ &bus->bus_mtx, USB_PRI_HIGH)) {
+ printf("WARNING: Creation of USB non-Giant "
+ "callback process failed.\n");
+ } else if (usb2_proc_setup(&bus->roothub_proc,
&bus->bus_mtx, USB_PRI_HIGH)) {
printf("WARNING: Creation of USB roothub "
"process failed.\n");
diff --git a/sys/dev/usb2/core/usb2_device.c b/sys/dev/usb2/core/usb2_device.c
index b54f8633c50c..dfe5e8abf654 100644
--- a/sys/dev/usb2/core/usb2_device.c
+++ b/sys/dev/usb2/core/usb2_device.c
@@ -1742,8 +1742,18 @@ usb2_free_device(struct usb2_device *udev)
/* unsetup any leftover default USB transfers */
usb2_transfer_unsetup(udev->default_xfer, USB_DEFAULT_XFER_MAX);
+ /* template unsetup, if any */
(usb2_temp_unsetup_p) (udev);
+ /*
+ * Make sure that our clear-stall messages are not queued
+ * anywhere:
+ */
+ USB_BUS_LOCK(udev->bus);
+ usb2_proc_mwait(&udev->bus->non_giant_callback_proc,
+ &udev->cs_msg[0], &udev->cs_msg[1]);
+ USB_BUS_UNLOCK(udev->bus);
+
sx_destroy(udev->default_sx);
sx_destroy(udev->default_sx + 1);
diff --git a/sys/dev/usb2/core/usb2_transfer.c b/sys/dev/usb2/core/usb2_transfer.c
index 2237c7ec286d..a5a3e8b0ec85 100644
--- a/sys/dev/usb2/core/usb2_transfer.c
+++ b/sys/dev/usb2/core/usb2_transfer.c
@@ -819,13 +819,12 @@ usb2_transfer_setup(struct usb2_device *udev,
info->done_m[1].hdr.pm_callback = &usb2_callback_proc;
info->done_m[1].xroot = info;
- /* create a callback thread */
-
- if (usb2_proc_setup(&info->done_p,
- &udev->bus->bus_mtx, USB_PRI_HIGH)) {
- parm.err = USB_ERR_NO_INTR_THREAD;
- goto done;
- }
+ if (xfer_mtx == &Giant)
+ info->done_p =
+ &udev->bus->giant_callback_proc;
+ else
+ info->done_p =
+ &udev->bus->non_giant_callback_proc;
}
/* reset sizes */
@@ -1045,10 +1044,11 @@ usb2_transfer_unsetup_sub(struct usb2_xfer_root *info, uint8_t needs_delay)
temp = usb2_get_dma_delay(info->bus);
usb2_pause_mtx(&info->bus->bus_mtx, temp);
}
- USB_BUS_UNLOCK(info->bus);
- /* wait for interrupt thread to exit */
- usb2_proc_unsetup(&info->done_p);
+ /* make sure that our done messages are not queued anywhere */
+ usb2_proc_mwait(info->done_p, &info->done_m[0], &info->done_m[1]);
+
+ USB_BUS_UNLOCK(info->bus);
/* free DMA'able memory, if any */
pc = info->dma_page_cache_start;
@@ -1811,7 +1811,7 @@ usb2_callback_ss_done_defer(struct usb2_xfer *xfer)
* will have a Lock Order Reversal, LOR, if we try to
* proceed !
*/
- if (usb2_proc_msignal(&info->done_p,
+ if (usb2_proc_msignal(info->done_p,
&info->done_m[0], &info->done_m[1])) {
/* ignore */
}
@@ -1851,7 +1851,7 @@ usb2_callback_wrapper(struct usb2_xfer_queue *pq)
* will have a Lock Order Reversal, LOR, if we try to
* proceed !
*/
- if (usb2_proc_msignal(&info->done_p,
+ if (usb2_proc_msignal(info->done_p,
&info->done_m[0], &info->done_m[1])) {
/* ignore */
}
@@ -2195,7 +2195,8 @@ usb2_pipe_start(struct usb2_xfer_queue *pq)
udev, NULL, pipe);
} else if (udev->default_xfer[1]) {
info = udev->default_xfer[1]->xroot;
- if (usb2_proc_msignal(&info->done_p,
+ if (usb2_proc_msignal(
+ &info->bus->non_giant_callback_proc,
&udev->cs_msg[0], &udev->cs_msg[1])) {
/* ignore */
}
diff --git a/sys/dev/usb2/core/usb2_transfer.h b/sys/dev/usb2/core/usb2_transfer.h
index 7e95be1a83f8..41494993c503 100644
--- a/sys/dev/usb2/core/usb2_transfer.h
+++ b/sys/dev/usb2/core/usb2_transfer.h
@@ -47,8 +47,8 @@ struct usb2_xfer_root {
struct usb2_done_msg done_m[2];
struct cv cv_drain;
struct usb2_dma_parent_tag dma_parent_tag;
- struct usb2_process done_p;
+ struct usb2_process *done_p; /* pointer to callback process */
void *memory_base;
struct mtx *xfer_mtx; /* cannot be changed during operation */
struct usb2_page_cache *dma_page_cache_start;