From edf1048c85c7075d5a4346b649d9eb75ef23b1bf Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Tue, 13 Jan 2009 19:03:23 +0000 Subject: [PATCH] MFp4: //depot/projects/usb@155842 Reduce the number of callback processes to 4 per USB controller. There are two rough categories: 1) Giant locked USB transfers. 2) Non-Giant locked USB transfers. On a real system with many USB devices plugged in the number of processes reported by "ps auxw | grep USBPROC" was reduced from 40 to 18. Submitted by: Hans Petter Selasky --- sys/dev/usb2/controller/usb2_bus.h | 7 ++++++ sys/dev/usb2/controller/usb2_controller.c | 18 +++++++++++++-- sys/dev/usb2/core/usb2_device.c | 10 +++++++++ sys/dev/usb2/core/usb2_transfer.c | 27 ++++++++++++----------- sys/dev/usb2/core/usb2_transfer.h | 2 +- 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 43776fdda7a..c81a7a5b917 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 61ce31482d1..a9596c76d9a 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 b54f8633c50..dfe5e8abf65 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 2237c7ec286..a5a3e8b0ec8 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 7e95be1a83f..41494993c50 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;