From owner-p4-projects@FreeBSD.ORG Thu Sep 11 08:09:16 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 9F7BD1065676; Thu, 11 Sep 2008 08:09:16 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 633B11065674 for ; Thu, 11 Sep 2008 08:09:16 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 4CC768FC1E for ; Thu, 11 Sep 2008 08:09:16 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id m8B89GEL018541 for ; Thu, 11 Sep 2008 08:09:16 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id m8B89Gvh018539 for perforce@freebsd.org; Thu, 11 Sep 2008 08:09:16 GMT (envelope-from hselasky@FreeBSD.org) Date: Thu, 11 Sep 2008 08:09:16 GMT Message-Id: <200809110809.m8B89Gvh018539@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 149593 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Sep 2008 08:09:16 -0000 http://perforce.freebsd.org/chv.cgi?CH=149593 Change 149593 by hselasky@hselasky_laptop001 on 2008/09/11 08:08:55 1) Make usb2_template variable globally accessable. 2) Cleanup FIFO free handling. Currently there were some bugs there, for example that the interface data was freed before freeing the FIFO which led to some NULL pointer accesses. 3) Add support for ugen attach/detach device notifications through devd. Affected files ... .. //depot/projects/usb/src/sys/dev/usb2/core/usb2_device.c#23 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_device.c#23 (text+ko) ==== @@ -64,6 +64,8 @@ static void usb2_clear_stall_proc(struct usb2_proc_msg *_pm); static void usb2_check_strings(struct usb2_device *udev); static usb2_error_t usb2_fill_iface_data(struct usb2_device *udev, uint8_t iface_index, uint8_t alt_index); +static void usb2_notify_addq(const char *type, struct usb2_device *udev); +static void usb2_fifo_free_wrap(struct usb2_device *udev, uint8_t iface_index, uint8_t free_all); /* static structures */ @@ -77,7 +79,9 @@ [USB_SPEED_LOW][USB_SPEED_LOW] = 1, }; -static int usb2_template = 0; +/* This variable is global to allow easy access to it: */ + +int usb2_template = 0; SYSCTL_INT(_hw_usb2, OID_AUTO, template, CTLFLAG_RW, &usb2_template, 0, "Selected USB device side template"); @@ -337,13 +341,12 @@ uint8_t iface_index, uint8_t alt_index) { struct usb2_interface *iface = usb2_get_iface(udev, iface_index); - struct usb2_pipe *pipe = udev->pipes; - struct usb2_pipe *pipe_end = udev->pipes + USB_EP_MAX; + struct usb2_pipe *pipe; + struct usb2_pipe *pipe_end; struct usb2_interface_descriptor *id; struct usb2_endpoint_descriptor *ed = NULL; struct usb2_descriptor *desc; uint8_t nendpt; - uint8_t i; if (iface == NULL) { return (USB_ERR_INVAL); @@ -353,15 +356,8 @@ sx_assert(udev->default_sx + 1, SA_LOCKED); - /* - * Free any USB FIFO on the interface: - */ - for (i = 2; i != USB_FIFO_MAX; i++) { - if (udev->fifo[i] && - (udev->fifo[i]->iface_index == iface_index)) { - usb2_fifo_free(udev->fifo[i]); - } - } + pipe = udev->pipes; + pipe_end = udev->pipes + USB_EP_MAX; /* * Check if any USB pipes on the given USB interface are in @@ -448,7 +444,6 @@ { struct usb2_interface *iface = udev->ifaces; struct usb2_interface *iface_end = udev->ifaces + USB_IFACE_MAX; - uint8_t n; /* mtx_assert() */ @@ -457,12 +452,6 @@ usb_linux_free_device(udev->linux_dev); udev->linux_dev = NULL; } - /* free all generic USB FIFOs except the control endpoint FIFO */ - for (n = 2; n != USB_FIFO_MAX; n++) { - usb2_fifo_free(udev->fifo[n]); - udev->fifo[n] = NULL; - } - /* free all pipes, if any */ usb2_free_pipe_data(udev, 0, 0); @@ -523,6 +512,9 @@ /* detach all interface drivers */ usb2_detach_device(udev, USB_IFACE_INDEX_ANY, 1); + /* free all FIFOs except control endpoint FIFOs */ + usb2_fifo_free_wrap(udev, USB_IFACE_INDEX_ANY, 0); + /* free all configuration data structures */ usb2_free_iface_data(udev); @@ -679,6 +671,9 @@ if (udev->flags.usb2_mode == USB_MODE_DEVICE) { usb2_detach_device(udev, iface_index, 1); } + /* free all FIFOs for this interface */ + usb2_fifo_free_wrap(udev, iface_index, 0); + err = usb2_fill_iface_data(udev, iface_index, alt_index); if (err) { goto done; @@ -1633,6 +1628,8 @@ device_get_unit(udev->bus->bdev), udev->device_index, udev->manufacturer, device_get_nameunit(udev->bus->bdev)); + + usb2_notify_addq("+", udev); done: if (err) { /* free device */ @@ -1658,6 +1655,8 @@ } DPRINTFN(4, "udev=%p port=%d\n", udev, udev->port_no); + usb2_notify_addq("-", udev); + bus = udev->bus; /* @@ -1688,13 +1687,14 @@ /* stop receiving any control transfers (Device Side Mode) */ usb2_transfer_unsetup(udev->default_xfer, USB_DEFAULT_XFER_MAX); } - /* free all interface related data and FIFOs, if any */ + /* free all FIFOs */ + usb2_fifo_free_wrap(udev, USB_IFACE_INDEX_ANY, 1); + + /* + * Free all interface related data and FIFOs, if any. + */ usb2_free_iface_data(udev); - /* free generic control endpoint FIFOs, if any */ - usb2_fifo_free(udev->fifo[0]); - usb2_fifo_free(udev->fifo[1]); - /* unsetup any leftover default USB transfers */ usb2_transfer_unsetup(udev->default_xfer, USB_DEFAULT_XFER_MAX); @@ -1987,3 +1987,111 @@ { return (udev->device_index); } + +/*------------------------------------------------------------------------* + * usb2_notify_addq + * + * This function will generate events for dev. + *------------------------------------------------------------------------*/ +static void +usb2_notify_addq(const char *type, struct usb2_device *udev) +{ + char *data = NULL; + struct malloc_type *mt; + + mtx_lock(&malloc_mtx); + mt = malloc_desc2type("bus"); /* XXX M_BUS */ + mtx_unlock(&malloc_mtx); + if (mt == NULL) + return; + + data = malloc(512, mt, M_NOWAIT); + if (data == NULL) + return; + + /* String it all together. */ + if (udev->parent_hub) { + snprintf(data, 1024, + "%s" + "ugen%u.%u " + "vendor=0x%04x " + "product=0x%04x " + "devclass=0x%02x " + "devsubclass=0x%02x " + "sernum=\"%s\" " + "at " + "port=%u " + "on " + "ugen%u.%u\n", + type, + device_get_unit(udev->bus->bdev), + udev->device_index, + UGETW(udev->ddesc.idVendor), + UGETW(udev->ddesc.idProduct), + udev->ddesc.bDeviceClass, + udev->ddesc.bDeviceSubClass, + udev->serial, + udev->port_no, + device_get_unit(udev->bus->bdev), + udev->parent_hub->device_index); + } else { + snprintf(data, 1024, + "%s" + "ugen%u.%u " + "vendor=0x%04x " + "product=0x%04x " + "devclass=0x%02x " + "devsubclass=0x%02x " + "sernum=\"%s\" " + "at port=%u " + "on " + "%s\n", + type, + device_get_unit(udev->bus->bdev), + udev->device_index, + UGETW(udev->ddesc.idVendor), + UGETW(udev->ddesc.idProduct), + udev->ddesc.bDeviceClass, + udev->ddesc.bDeviceSubClass, + udev->serial, + udev->port_no, + device_get_nameunit(device_get_parent(udev->bus->bdev))); + } + devctl_queue_data(data); + return; +} + +/*------------------------------------------------------------------------* + * usb2_fifo_free_wrap + * + * The function will free the FIFOs. + *------------------------------------------------------------------------*/ +static void +usb2_fifo_free_wrap(struct usb2_device *udev, + uint8_t iface_index, uint8_t free_all) +{ + struct usb2_fifo *f; + struct usb2_pipe *pipe; + uint16_t i; + + /* + * Free any USB FIFOs on the given interface: + */ + for (i = 0; i != USB_FIFO_MAX; i++) { + f = udev->fifo[i]; + if (f == NULL) { + continue; + } + pipe = f->priv_sc0; + if ((pipe == &udev->default_pipe) && (free_all == 0)) { + /* don't free UGEN control endpoint yet */ + continue; + } + /* Check if the interface index matches */ + if ((iface_index == f->iface_index) || + (iface_index == USB_IFACE_INDEX_ANY)) { + usb2_fifo_free(f); + } + } + return; +}