diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-04-08 15:37:49 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-05-20 09:58:21 +0200 |
commit | 165dd8ea1256d71d6a4f52c0a66dcc2799ef8f99 (patch) | |
tree | c42072a99573d4d7cc03b2263e2c0c6d53f9c691 /freebsd/sys/dev/usb | |
parent | rtems-bsd-chunk: Include missing header file (diff) | |
download | rtems-libbsd-165dd8ea1256d71d6a4f52c0a66dcc2799ef8f99.tar.bz2 |
Update to FreeBSD Stable/9 2015-04-08
Diffstat (limited to 'freebsd/sys/dev/usb')
-rw-r--r-- | freebsd/sys/dev/usb/controller/ehci.c | 4 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/controller/usb_controller.c | 49 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/controller/xhcireg.h | 2 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/quirk/usb_quirk.c | 37 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/quirk/usb_quirk.h | 1 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_bus.h | 7 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_busdma.h | 4 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_core.h | 1 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_dev.c | 33 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_device.c | 117 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_device.h | 1 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_dynamic.c | 2 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_freebsd.h | 2 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_generic.c | 9 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_hub.c | 14 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_msctest.c | 38 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_msctest.h | 1 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_process.c | 4 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_request.c | 2 | ||||
-rw-r--r-- | freebsd/sys/dev/usb/usb_transfer.c | 31 |
20 files changed, 248 insertions, 111 deletions
diff --git a/freebsd/sys/dev/usb/controller/ehci.c b/freebsd/sys/dev/usb/controller/ehci.c index 730fd666..3eb63c60 100644 --- a/freebsd/sys/dev/usb/controller/ehci.c +++ b/freebsd/sys/dev/usb/controller/ehci.c @@ -214,7 +214,7 @@ ehci_reset(ehci_softc_t *sc) return (0); } } - device_printf(sc->sc_bus.bdev, "Reset timeout\n"); + device_printf(sc->sc_bus.bdev, "reset timeout\n"); return (USB_ERR_IOERROR); } @@ -289,7 +289,7 @@ ehci_init_sub(struct ehci_softc *sc) } } if (hcr) { - device_printf(sc->sc_bus.bdev, "Run timeout\n"); + device_printf(sc->sc_bus.bdev, "run timeout\n"); return (USB_ERR_IOERROR); } return (USB_ERR_NORMAL_COMPLETION); diff --git a/freebsd/sys/dev/usb/controller/usb_controller.c b/freebsd/sys/dev/usb/controller/usb_controller.c index c0fda652..90e09bb5 100644 --- a/freebsd/sys/dev/usb/controller/usb_controller.c +++ b/freebsd/sys/dev/usb/controller/usb_controller.c @@ -58,6 +58,7 @@ #include <dev/usb/usb_busdma.h> #include <dev/usb/usb_dynamic.h> #include <dev/usb/usb_device.h> +#include <dev/usb/usb_dev.h> #include <dev/usb/usb_hub.h> #include <dev/usb/usb_controller.h> @@ -130,7 +131,7 @@ DRIVER_MODULE(usbus, xhci, usb_driver, usb_devclass, 0, 0); /* Device Only Drivers */ DRIVER_MODULE(usbus, at91_udp, usb_driver, usb_devclass, 0, 0); DRIVER_MODULE(usbus, musbotg, usb_driver, usb_devclass, 0, 0); -DRIVER_MODULE(usbus, uss820, usb_driver, usb_devclass, 0, 0); +DRIVER_MODULE(usbus, uss820dci, usb_driver, usb_devclass, 0, 0); /*------------------------------------------------------------------------* * usb_probe @@ -213,6 +214,11 @@ usb_detach(device_t dev) usb_proc_mwait(&bus->explore_proc, &bus->detach_msg[0], &bus->detach_msg[1]); +#if USB_HAVE_UGEN + /* Wait for cleanup to complete */ + usb_proc_mwait(&bus->explore_proc, + &bus->cleanup_msg[0], &bus->cleanup_msg[1]); +#endif USB_BUS_UNLOCK(bus); /* Get rid of USB callback processes */ @@ -324,7 +330,7 @@ usb_shutdown(device_t dev) return (0); } - device_printf(bus->bdev, "Controller shutdown\n"); + DPRINTF("%s: Controller shutdown\n", device_get_nameunit(bus->bdev)); USB_BUS_LOCK(bus); #ifndef __rtems__ @@ -338,7 +344,8 @@ usb_shutdown(device_t dev) #endif /* __rtems__ */ USB_BUS_UNLOCK(bus); - device_printf(bus->bdev, "Controller shutdown complete\n"); + DPRINTF("%s: Controller shutdown complete\n", + device_get_nameunit(bus->bdev)); return (0); } @@ -624,6 +631,32 @@ usb_bus_shutdown(struct usb_proc_msg *pm) USB_BUS_LOCK(bus); } +/*------------------------------------------------------------------------* + * usb_bus_cleanup + * + * This function is used to cleanup leftover USB character devices. + *------------------------------------------------------------------------*/ +#if USB_HAVE_UGEN +static void +usb_bus_cleanup(struct usb_proc_msg *pm) +{ + struct usb_bus *bus; + struct usb_fs_privdata *pd; + + bus = ((struct usb_bus_msg *)pm)->bus; + + while ((pd = LIST_FIRST(&bus->pd_cleanup_list)) != NULL) { + + LIST_REMOVE(pd, pd_next); + USB_BUS_UNLOCK(bus); + + usb_destroy_dev_sync(pd); + + USB_BUS_LOCK(bus); + } +} +#endif + static void usb_power_wdog(void *arg) { @@ -804,6 +837,14 @@ usb_attach_sub(device_t dev, struct usb_bus *bus) bus->shutdown_msg[1].hdr.pm_callback = &usb_bus_shutdown; bus->shutdown_msg[1].bus = bus; +#if USB_HAVE_UGEN + LIST_INIT(&bus->pd_cleanup_list); + bus->cleanup_msg[0].hdr.pm_callback = &usb_bus_cleanup; + bus->cleanup_msg[0].bus = bus; + bus->cleanup_msg[1].hdr.pm_callback = &usb_bus_cleanup; + bus->cleanup_msg[1].bus = bus; +#endif + /* Create USB explore and callback processes */ if (usb_proc_create(&bus->giant_callback_proc, @@ -901,7 +942,7 @@ usb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat, #if USB_HAVE_BUSDMA usb_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags, - dmat, &bus->bus_mtx, NULL, 32, USB_BUS_DMA_TAG_MAX); + dmat, &bus->bus_mtx, NULL, bus->dma_bits, USB_BUS_DMA_TAG_MAX); #endif if ((bus->devices_max > USB_MAX_DEVICES) || (bus->devices_max < USB_MIN_DEVICES) || diff --git a/freebsd/sys/dev/usb/controller/xhcireg.h b/freebsd/sys/dev/usb/controller/xhcireg.h index bd1d635c..a0b73971 100644 --- a/freebsd/sys/dev/usb/controller/xhcireg.h +++ b/freebsd/sys/dev/usb/controller/xhcireg.h @@ -35,7 +35,9 @@ #define PCI_XHCI_FLADJ 0x61 /* RW frame length adjust */ #define PCI_XHCI_INTEL_XUSB2PR 0xD0 /* Intel USB2 Port Routing */ +#define PCI_XHCI_INTEL_USB2PRM 0xD4 /* Intel USB2 Port Routing Mask */ #define PCI_XHCI_INTEL_USB3_PSSEN 0xD8 /* Intel USB3 Port SuperSpeed Enable */ +#define PCI_XHCI_INTEL_USB3PRM 0xDC /* Intel USB3 Port Routing Mask */ /* XHCI capability registers */ #define XHCI_CAPLENGTH 0x00 /* RO capability */ diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c index 2f7ea792..7447ea80 100644 --- a/freebsd/sys/dev/usb/quirk/usb_quirk.c +++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c @@ -61,7 +61,7 @@ MODULE_DEPEND(usb_quirk, usb, 1, 1, 1); MODULE_VERSION(usb_quirk, 1); -#define USB_DEV_QUIRKS_MAX 256 +#define USB_DEV_QUIRKS_MAX 384 #define USB_SUB_QUIRKS_MAX 8 struct usb_quirk_entry { @@ -132,6 +132,8 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(MICROSOFT, WLINTELLIMOUSE, 0x0000, 0xffff, UQ_MS_LEADING_BYTE), /* Quirk for Corsair Vengeance K60 keyboard */ USB_QUIRK(CORSAIR, K60, 0x0000, 0xffff, UQ_KBD_BOOTPROTO), + /* Quirk for Corsair Vengeance K70 keyboard */ + USB_QUIRK(CORSAIR, K70, 0x0000, 0xffff, UQ_KBD_BOOTPROTO), /* umodem(4) device quirks */ USB_QUIRK(METRICOM, RICOCHET_GS, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA), USB_QUIRK(SANYO, SCP4900, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA), @@ -252,6 +254,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(LEXAR, CF_READER, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY), USB_QUIRK(LEXAR, JUMPSHOT, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI), + USB_QUIRK(LEXAR, JUMPDRIVE, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY), USB_QUIRK(LOGITEC, LDR_H443SU2, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI), USB_QUIRK(LOGITEC, LDR_H443U2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,), @@ -436,8 +439,28 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { USB_QUIRK(WESTERN, MYBOOK, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY_EVPD, UQ_MSC_NO_SYNC_CACHE), - USB_QUIRK(WESTERN, MYPASSWORD, 0x0000, 0xffff, UQ_MSC_FORCE_SHORT_INQ), - USB_QUIRK(WESTERN, MYPASSPORT, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORT_00, 0x0000, 0xffff, UQ_MSC_FORCE_SHORT_INQ), + USB_QUIRK(WESTERN, MYPASSPORT_01, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORT_02, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORT_03, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORT_04, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORT_05, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORT_06, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORT_07, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORT_08, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORT_09, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORT_10, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORT_11, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORTES_00, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORTES_01, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORTES_02, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORTES_03, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORTES_04, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORTES_05, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORTES_06, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORTES_07, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORTES_08, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(WESTERN, MYPASSPORTES_09, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), USB_QUIRK(WINMAXGROUP, FLASH64MC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY), USB_QUIRK(YANO, FW800HD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, @@ -458,10 +481,11 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { UQ_MSC_FORCE_PROTO_ATAPI), USB_QUIRK(MEIZU, M6_SL, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_SYNC_CACHE), - - USB_QUIRK(TOSHIBA, TRANSMEMORY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), + USB_QUIRK(TOSHIBA, TRANSMEMORY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, + UQ_MSC_NO_PREVENT_ALLOW), USB_QUIRK(VIALABS, USB30SATABRIDGE, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE), - + USB_QUIRK(QUALCOMMINC, ZTE_MF730M, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN, + UQ_MSC_NO_INQUIRY, UQ_CFG_INDEX_0), /* Non-standard USB MIDI devices */ USB_QUIRK(ROLAND, UM1, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), USB_QUIRK(ROLAND, SC8850, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS), @@ -565,6 +589,7 @@ static const char *usb_quirk_str[USB_QUIRK_MAX] = { [UQ_MSC_EJECT_WAIT] = "UQ_MSC_EJECT_WAIT", [UQ_MSC_EJECT_SAEL_M460] = "UQ_MSC_EJECT_SAEL_M460", [UQ_MSC_EJECT_HUAWEISCSI] = "UQ_MSC_EJECT_HUAWEISCSI", + [UQ_MSC_EJECT_HUAWEISCSI2] = "UQ_MSC_EJECT_HUAWEISCSI2", [UQ_MSC_EJECT_TCT] = "UQ_MSC_EJECT_TCT", [UQ_BAD_MIDI] = "UQ_BAD_MIDI", [UQ_AU_VENDOR_CLASS] = "UQ_AU_VENDOR_CLASS", diff --git a/freebsd/sys/dev/usb/quirk/usb_quirk.h b/freebsd/sys/dev/usb/quirk/usb_quirk.h index 32a60a10..bddc2c55 100644 --- a/freebsd/sys/dev/usb/quirk/usb_quirk.h +++ b/freebsd/sys/dev/usb/quirk/usb_quirk.h @@ -103,6 +103,7 @@ enum { UQ_MSC_EJECT_WAIT, /* wait for the device to eject */ UQ_MSC_EJECT_SAEL_M460, /* ejects after Sael USB commands */ UQ_MSC_EJECT_HUAWEISCSI, /* ejects after Huawei SCSI command */ + UQ_MSC_EJECT_HUAWEISCSI2, /* ejects after Huawei SCSI 2 command */ UQ_MSC_EJECT_TCT, /* ejects after TCT SCSI command */ UQ_BAD_MIDI, /* device claims MIDI class, but isn't */ diff --git a/freebsd/sys/dev/usb/usb_bus.h b/freebsd/sys/dev/usb/usb_bus.h index 702f623d..0a7350c9 100644 --- a/freebsd/sys/dev/usb/usb_bus.h +++ b/freebsd/sys/dev/usb/usb_bus.h @@ -27,6 +27,8 @@ #ifndef _USB_BUS_H_ #define _USB_BUS_H_ +struct usb_fs_privdata; + /* * The following structure defines the USB explore message sent to the USB * explore process. @@ -75,6 +77,10 @@ struct usb_bus { struct usb_bus_msg resume_msg[2]; struct usb_bus_msg reset_msg[2]; struct usb_bus_msg shutdown_msg[2]; +#if USB_HAVE_UGEN + struct usb_bus_msg cleanup_msg[2]; + LIST_HEAD(,usb_fs_privdata) pd_cleanup_list; +#endif /* * This mutex protects the USB hardware: */ @@ -106,6 +112,7 @@ struct usb_bus { uint8_t devices_max; /* maximum number of USB devices */ uint8_t do_probe; /* set if USB should be re-probed */ uint8_t no_explore; /* don't explore USB ports */ + uint8_t dma_bits; /* number of DMA address lines */ }; #endif /* _USB_BUS_H_ */ diff --git a/freebsd/sys/dev/usb/usb_busdma.h b/freebsd/sys/dev/usb/usb_busdma.h index 6b6e4039..ee420bc6 100644 --- a/freebsd/sys/dev/usb/usb_busdma.h +++ b/freebsd/sys/dev/usb/usb_busdma.h @@ -60,7 +60,7 @@ typedef void (usb_dma_callback_t)(struct usb_dma_parent_tag *udpt); */ struct usb_page { #if USB_HAVE_BUSDMA - bus_size_t physaddr; + bus_addr_t physaddr; void *buffer; /* non Kernel Virtual Address */ #endif }; @@ -73,7 +73,7 @@ struct usb_page { struct usb_page_search { void *buffer; #if USB_HAVE_BUSDMA - bus_size_t physaddr; + bus_addr_t physaddr; #endif usb_size_t length; }; diff --git a/freebsd/sys/dev/usb/usb_core.h b/freebsd/sys/dev/usb/usb_core.h index 48e5ee83..287e69f2 100644 --- a/freebsd/sys/dev/usb/usb_core.h +++ b/freebsd/sys/dev/usb/usb_core.h @@ -97,6 +97,7 @@ struct usb_xfer_flags_int { * sent */ uint8_t control_act:1; /* set if control transfer is active */ uint8_t control_stall:1; /* set if control transfer should be stalled */ + uint8_t control_did_data:1; /* set if control DATA has been transferred */ uint8_t short_frames_ok:1; /* filtered version */ uint8_t short_xfer_ok:1; /* filtered version */ diff --git a/freebsd/sys/dev/usb/usb_dev.c b/freebsd/sys/dev/usb/usb_dev.c index 3ff064ee..ce107cf3 100644 --- a/freebsd/sys/dev/usb/usb_dev.c +++ b/freebsd/sys/dev/usb/usb_dev.c @@ -292,11 +292,15 @@ error: usbd_enum_unlock(cpd->udev); if (crd->is_uref) { - cpd->udev->refcount--; - cv_broadcast(&cpd->udev->ref_cv); + if (--(cpd->udev->refcount) == 0) + cv_broadcast(&cpd->udev->ref_cv); } mtx_unlock(&usb_ref_lock); DPRINTFN(2, "fail\n"); + + /* clear all refs */ + memset(crd, 0, sizeof(*crd)); + return (USB_ERR_INVAL); } @@ -360,8 +364,8 @@ usb_unref_device(struct usb_cdev_privdata *cpd, } if (crd->is_uref) { crd->is_uref = 0; - cpd->udev->refcount--; - cv_broadcast(&cpd->udev->ref_cv); + if (--(cpd->udev->refcount) == 0) + cv_broadcast(&cpd->udev->ref_cv); } mtx_unlock(&usb_ref_lock); } @@ -587,12 +591,12 @@ usb_fifo_free(struct usb_fifo *f) /* decrease refcount */ f->refcount--; - /* prevent any write flush */ - f->flag_iserror = 1; /* need to wait until all callers have exited */ while (f->refcount != 0) { mtx_unlock(&usb_ref_lock); /* avoid LOR */ mtx_lock(f->priv_mtx); + /* prevent write flush, if any */ + f->flag_iserror = 1; /* get I/O thread out of any sleep state */ if (f->flag_sleeping) { f->flag_sleeping = 0; @@ -1092,8 +1096,8 @@ usb_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread* goto done; if (usb_usb_ref_device(cpd, &refs)) { - err = ENXIO; - goto done; + /* we lost the reference */ + return (ENXIO); } err = (f->methods->f_ioctl_post) (f, cmd, addr, fflags); @@ -1116,9 +1120,8 @@ usb_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread* while (usb_ref_device(cpd, &refs, 1 /* need uref */)) { if (usb_ref_device(cpd, &refs, 0)) { - /* device no longer exits */ - err = ENXIO; - goto done; + /* device no longer exists */ + return (ENXIO); } usb_unref_device(cpd, &refs); usb_pause_mtx(NULL, hz / 128); @@ -1410,9 +1413,9 @@ usb_read(struct cdev *dev, struct uio *uio, int ioflag) return (err); err = usb_ref_device(cpd, &refs, 0 /* no uref */ ); - if (err) { + if (err) return (ENXIO); - } + fflags = cpd->fflags; f = refs.rxfifo; @@ -1536,9 +1539,9 @@ usb_write(struct cdev *dev, struct uio *uio, int ioflag) return (err); err = usb_ref_device(cpd, &refs, 0 /* no uref */ ); - if (err) { + if (err) return (ENXIO); - } + fflags = cpd->fflags; f = refs.txfifo; diff --git a/freebsd/sys/dev/usb/usb_device.c b/freebsd/sys/dev/usb/usb_device.c index e18c32df..8e0144cc 100644 --- a/freebsd/sys/dev/usb/usb_device.c +++ b/freebsd/sys/dev/usb/usb_device.c @@ -437,60 +437,28 @@ usb_endpoint_foreach(struct usb_device *udev, struct usb_endpoint *ep) } /*------------------------------------------------------------------------* - * usb_wait_pending_ref_locked + * usb_wait_pending_refs * * This function will wait for any USB references to go away before - * returning and disable further USB device refcounting on the - * specified USB device. This function is used when detaching a USB - * device. + * returning. This function is used before freeing a USB device. *------------------------------------------------------------------------*/ static void -usb_wait_pending_ref_locked(struct usb_device *udev) +usb_wait_pending_refs(struct usb_device *udev) { #if USB_HAVE_UGEN - const uint16_t refcount = - usb_proc_is_called_from( - &udev->bus->explore_proc) ? 1 : 2; - - DPRINTF("Refcount = %d\n", (int)refcount); + DPRINTF("Refcount = %d\n", (int)udev->refcount); + mtx_lock(&usb_ref_lock); + udev->refcount--; while (1) { /* wait for any pending references to go away */ - mtx_lock(&usb_ref_lock); - if (udev->refcount == refcount) { - /* prevent further refs being taken */ + if (udev->refcount == 0) { + /* prevent further refs being taken, if any */ udev->refcount = USB_DEV_REF_MAX; - mtx_unlock(&usb_ref_lock); break; } - usbd_enum_unlock(udev); cv_wait(&udev->ref_cv, &usb_ref_lock); - mtx_unlock(&usb_ref_lock); - (void) usbd_enum_lock(udev); } -#endif -} - -/*------------------------------------------------------------------------* - * usb_ref_restore_locked - * - * This function will restore the reference count value after a call - * to "usb_wait_pending_ref_locked()". - *------------------------------------------------------------------------*/ -static void -usb_ref_restore_locked(struct usb_device *udev) -{ -#if USB_HAVE_UGEN - const uint16_t refcount = - usb_proc_is_called_from( - &udev->bus->explore_proc) ? 1 : 2; - - DPRINTF("Refcount = %d\n", (int)refcount); - - /* restore reference count and wakeup waiters, if any */ - mtx_lock(&usb_ref_lock); - udev->refcount = refcount; - cv_broadcast(&udev->ref_cv); mtx_unlock(&usb_ref_lock); #endif } @@ -844,9 +812,6 @@ usb_config_parse(struct usb_device *udev, uint8_t iface_index, uint8_t cmd) /* find maximum number of endpoints */ if (ep_max < temp) ep_max = temp; - - /* optimalisation */ - id = (struct usb_interface_descriptor *)ed; } } @@ -1100,10 +1065,12 @@ usb_detach_device_sub(struct usb_device *udev, device_t *ppdev, */ *ppdev = NULL; - device_printf(dev, "at %s, port %d, addr %d " - "(disconnected)\n", - device_get_nameunit(udev->parent_dev), - udev->port_no, udev->address); + if (!rebooting) { + device_printf(dev, "at %s, port %d, addr %d " + "(disconnected)\n", + device_get_nameunit(udev->parent_dev), + udev->port_no, udev->address); + } if (device_is_attached(dev)) { if (udev->flags.peer_suspended) { @@ -1156,9 +1123,6 @@ usb_detach_device(struct usb_device *udev, uint8_t iface_index, sx_assert(&udev->enum_sx, SA_LOCKED); - /* wait for pending refs to go away */ - usb_wait_pending_ref_locked(udev); - /* * First detach the child to give the child's detach routine a * chance to detach the sub-devices in the correct order. @@ -1185,8 +1149,6 @@ usb_detach_device(struct usb_device *udev, uint8_t iface_index, usb_detach_device_sub(udev, &iface->subdev, &iface->pnpinfo, flag); } - - usb_ref_restore_locked(udev); } /*------------------------------------------------------------------------* @@ -1999,14 +1961,46 @@ usb_make_dev(struct usb_device *udev, const char *devname, int ep, } void +usb_destroy_dev_sync(struct usb_fs_privdata *pd) +{ + DPRINTFN(1, "Destroying device at ugen%d.%d\n", + pd->bus_index, pd->dev_index); + + /* + * Destroy character device synchronously. After this + * all system calls are returned. Can block. + */ + destroy_dev(pd->cdev); + + free(pd, M_USBDEV); +} + +void usb_destroy_dev(struct usb_fs_privdata *pd) { + struct usb_bus *bus; + if (pd == NULL) return; - destroy_dev(pd->cdev); + mtx_lock(&usb_ref_lock); + bus = devclass_get_softc(usb_devclass_ptr, pd->bus_index); + mtx_unlock(&usb_ref_lock); - free(pd, M_USBDEV); + if (bus == NULL) { + usb_destroy_dev_sync(pd); + return; + } + + /* make sure we can re-use the device name */ + delist_dev(pd->cdev); + + USB_BUS_LOCK(bus); + LIST_INSERT_HEAD(&bus->pd_cleanup_list, pd, pd_next); + /* get cleanup going */ + usb_proc_msignal(&bus->explore_proc, + &bus->cleanup_msg[0], &bus->cleanup_msg[1]); + USB_BUS_UNLOCK(bus); } static void @@ -2115,8 +2109,10 @@ usb_free_device(struct usb_device *udev, uint8_t flag) #endif #if USB_HAVE_UGEN - printf("%s: <%s> at %s (disconnected)\n", udev->ugen_name, - usb_get_manufacturer(udev), device_get_nameunit(bus->bdev)); + if (!rebooting) { + printf("%s: <%s> at %s (disconnected)\n", udev->ugen_name, + usb_get_manufacturer(udev), device_get_nameunit(bus->bdev)); + } /* Destroy UGEN symlink, if any */ if (udev->ugen_symlink) { @@ -2155,6 +2151,9 @@ usb_free_device(struct usb_device *udev, uint8_t flag) &udev->cs_msg[0], &udev->cs_msg[1]); USB_BUS_UNLOCK(udev->bus); + /* wait for all references to go away */ + usb_wait_pending_refs(udev); + sx_destroy(&udev->enum_sx); sx_destroy(&udev->sr_sx); @@ -2640,14 +2639,8 @@ usb_fifo_free_wrap(struct usb_device *udev, /* no need to free this FIFO */ continue; } - /* wait for pending refs to go away */ - usb_wait_pending_ref_locked(udev); - /* free this FIFO */ usb_fifo_free(f); - - /* restore refcount */ - usb_ref_restore_locked(udev); } } #endif diff --git a/freebsd/sys/dev/usb/usb_device.h b/freebsd/sys/dev/usb/usb_device.h index 361f5c3c..309bd057 100644 --- a/freebsd/sys/dev/usb/usb_device.h +++ b/freebsd/sys/dev/usb/usb_device.h @@ -281,6 +281,7 @@ struct usb_device *usb_alloc_device(device_t parent_dev, struct usb_bus *bus, struct usb_fs_privdata *usb_make_dev(struct usb_device *, const char *, int, int, int, uid_t, gid_t, int); void usb_destroy_dev(struct usb_fs_privdata *); +void usb_destroy_dev_sync(struct usb_fs_privdata *); #endif usb_error_t usb_probe_and_attach(struct usb_device *udev, uint8_t iface_index); diff --git a/freebsd/sys/dev/usb/usb_dynamic.c b/freebsd/sys/dev/usb/usb_dynamic.c index 32ff5e6a..65c9a7d7 100644 --- a/freebsd/sys/dev/usb/usb_dynamic.c +++ b/freebsd/sys/dev/usb/usb_dynamic.c @@ -66,7 +66,7 @@ usb_temp_setup_by_index_t *usb_temp_setup_by_index_p = &usb_temp_setup_by_index_ usb_temp_unsetup_t *usb_temp_unsetup_p = &usb_temp_unsetup_w; usb_test_quirk_t *usb_test_quirk_p = &usb_test_quirk_w; usb_quirk_ioctl_t *usb_quirk_ioctl_p = &usb_quirk_ioctl_w; -devclass_t usb_devclass_ptr = NULL; +devclass_t usb_devclass_ptr; static usb_error_t usb_temp_setup_by_index_w(struct usb_device *udev, uint16_t index) diff --git a/freebsd/sys/dev/usb/usb_freebsd.h b/freebsd/sys/dev/usb/usb_freebsd.h index 4cd1758a..ed2c6bba 100644 --- a/freebsd/sys/dev/usb/usb_freebsd.h +++ b/freebsd/sys/dev/usb/usb_freebsd.h @@ -73,7 +73,7 @@ #define USB_EP0_BUFSIZE 1024 /* bytes */ #define USB_CS_RESET_LIMIT 20 /* failures = 20 * 50 ms = 1sec */ -#define USB_MAX_AUTO_QUIRK 4 /* maximum number of dynamic quirks */ +#define USB_MAX_AUTO_QUIRK 8 /* maximum number of dynamic quirks */ typedef uint32_t usb_timeout_t; /* milliseconds */ typedef uint32_t usb_frlength_t; /* bytes */ diff --git a/freebsd/sys/dev/usb/usb_generic.c b/freebsd/sys/dev/usb/usb_generic.c index e1fc141f..d6172908 100644 --- a/freebsd/sys/dev/usb/usb_generic.c +++ b/freebsd/sys/dev/usb/usb_generic.c @@ -1839,14 +1839,13 @@ ugen_get_port_path(struct usb_fifo *f, struct usb_device_port_path *dpp) if (nlevel > USB_DEVICE_PORT_PATH_MAX) goto error; + /* store total level of ports */ + dpp->udp_port_level = nlevel; + /* store port index array */ next = udev; while (next->parent_hub != NULL) { - nlevel--; - - dpp->udp_port_no[nlevel] = next->port_no; - dpp->udp_port_level = nlevel; - + dpp->udp_port_no[--nlevel] = next->port_no; next = next->parent_hub; } return (0); /* success */ diff --git a/freebsd/sys/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c index 9b3bd076..0c62ee08 100644 --- a/freebsd/sys/dev/usb/usb_hub.c +++ b/freebsd/sys/dev/usb/usb_hub.c @@ -603,7 +603,6 @@ uhub_reattach_port(struct uhub_softc *sc, uint8_t portno) DPRINTF("reattaching port %d\n", portno); - err = 0; timeout = 0; udev = sc->sc_udev; child = usb_bus_port_get_device(udev->bus, @@ -1595,6 +1594,7 @@ uhub_child_location_string(device_t parent, device_t child, struct uhub_softc *sc; struct usb_hub *hub; struct hub_result res; + char *ugen_name; if (!device_is_attached(parent)) { if (buflen) @@ -1614,10 +1614,16 @@ uhub_child_location_string(device_t parent, device_t child, } goto done; } - snprintf(buf, buflen, "bus=%u hubaddr=%u port=%u devaddr=%u interface=%u", +#if USB_HAVE_UGEN + ugen_name = res.udev->ugen_name; +#else + ugen_name = "?"; +#endif + snprintf(buf, buflen, "bus=%u hubaddr=%u port=%u devaddr=%u interface=%u" + " ugen=%s", (res.udev->parent_hub != NULL) ? res.udev->parent_hub->device_index : 0, res.portno, device_get_unit(res.udev->bus->bdev), - res.udev->device_index, res.iface_index); + res.udev->device_index, res.iface_index, ugen_name); done: mtx_unlock(&Giant); @@ -1659,7 +1665,7 @@ uhub_child_pnpinfo_string(device_t parent, device_t child, "release=0x%04x " "mode=%s " "intclass=0x%02x intsubclass=0x%02x " - "intprotocol=0x%02x " "%s%s", + "intprotocol=0x%02x" "%s%s", UGETW(res.udev->ddesc.idVendor), UGETW(res.udev->ddesc.idProduct), res.udev->ddesc.bDeviceClass, diff --git a/freebsd/sys/dev/usb/usb_msctest.c b/freebsd/sys/dev/usb/usb_msctest.c index 4d28346c..19accddf 100644 --- a/freebsd/sys/dev/usb/usb_msctest.c +++ b/freebsd/sys/dev/usb/usb_msctest.c @@ -100,6 +100,9 @@ static uint8_t scsi_cmotech_eject[] = { 0xff, 0x52, 0x44, 0x45, 0x56, 0x43, static uint8_t scsi_huawei_eject[] = { 0x11, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static uint8_t scsi_huawei_eject2[] = { 0x11, 0x06, 0x20, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; static uint8_t scsi_tct_eject[] = { 0x06, 0xf5, 0x04, 0x02, 0x52, 0x70 }; static uint8_t scsi_sync_cache[] = { 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -107,6 +110,8 @@ static uint8_t scsi_request_sense[] = { 0x03, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static uint8_t scsi_read_capacity[] = { 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static uint8_t scsi_prevent_removal[] = { 0x1e, 0, 0, 0, 1, 0 }; +static uint8_t scsi_allow_removal[] = { 0x1e, 0, 0, 0, 0, 0 }; #define BULK_SIZE 64 /* dummy */ #define ERR_CSW_FAILED -1 @@ -479,6 +484,7 @@ bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun, sc->data_rem = data_len; sc->data_timeout = (data_timeout + USB_MS_HZ); sc->actlen = 0; + sc->error = 0; sc->cmd_len = cmd_len; memset(&sc->cbw->CBWCDB, 0, sizeof(sc->cbw->CBWCDB)); memcpy(&sc->cbw->CBWCDB, cmd_ptr, cmd_len); @@ -689,10 +695,28 @@ usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index) USB_MS_HZ); if (err != 0) { + if (err != ERR_CSW_FAILED) + goto error; + DPRINTF("Test unit ready failed\n"); + } + + err = bbb_command_start(sc, DIR_OUT, 0, NULL, 0, + &scsi_prevent_removal, sizeof(scsi_prevent_removal), + USB_MS_HZ); + + if (err == 0) { + err = bbb_command_start(sc, DIR_OUT, 0, NULL, 0, + &scsi_allow_removal, sizeof(scsi_allow_removal), + USB_MS_HZ); + } + if (err != 0) { if (err != ERR_CSW_FAILED) goto error; + DPRINTF("Device doesn't handle prevent and allow removal\n"); + usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW); } + timeout = 1; retry_sync_cache: @@ -708,7 +732,6 @@ retry_sync_cache: DPRINTF("Device doesn't handle synchronize cache\n"); usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE); - } else { /* @@ -782,6 +805,7 @@ error: DPRINTF("Device did not respond, enabling all quirks\n"); usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE); + usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW); usbd_add_dynamic_quirk(udev, UQ_MSC_NO_TEST_UNIT_READY); /* Need to re-enumerate the device */ @@ -800,7 +824,6 @@ usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method) if (sc == NULL) return (USB_ERR_INVAL); - err = 0; switch (method) { case MSC_EJECT_STOPUNIT: err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, @@ -831,6 +854,11 @@ usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method) &scsi_huawei_eject, sizeof(scsi_huawei_eject), USB_MS_HZ); break; + case MSC_EJECT_HUAWEI2: + err = bbb_command_start(sc, DIR_IN, 0, NULL, 0, + &scsi_huawei_eject2, sizeof(scsi_huawei_eject2), + USB_MS_HZ); + break; case MSC_EJECT_TCT: /* * TCTMobile needs DIR_IN flag. To get it, we @@ -841,9 +869,11 @@ usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method) sizeof(scsi_tct_eject), USB_MS_HZ); break; default: - printf("usb_msc_eject: unknown eject method (%d)\n", method); - break; + DPRINTF("Unknown eject method (%d)\n", method); + bbb_detach(sc); + return (USB_ERR_INVAL); } + DPRINTF("Eject CD command status: %s\n", usbd_errstr(err)); bbb_detach(sc); diff --git a/freebsd/sys/dev/usb/usb_msctest.h b/freebsd/sys/dev/usb/usb_msctest.h index e4a717fe..4f64f842 100644 --- a/freebsd/sys/dev/usb/usb_msctest.h +++ b/freebsd/sys/dev/usb/usb_msctest.h @@ -33,6 +33,7 @@ enum { MSC_EJECT_ZTESTOR, MSC_EJECT_CMOTECH, MSC_EJECT_HUAWEI, + MSC_EJECT_HUAWEI2, MSC_EJECT_TCT, }; diff --git a/freebsd/sys/dev/usb/usb_process.c b/freebsd/sys/dev/usb/usb_process.c index d36df36e..a5426e1e 100644 --- a/freebsd/sys/dev/usb/usb_process.c +++ b/freebsd/sys/dev/usb/usb_process.c @@ -26,8 +26,6 @@ * SUCH DAMAGE. */ -#define USB_DEBUG_VAR usb_proc_debug - #include <sys/stdint.h> #include <sys/stddef.h> #include <rtems/bsd/sys/param.h> @@ -51,6 +49,8 @@ #include <dev/usb/usbdi.h> #include <dev/usb/usbdi_util.h> #include <dev/usb/usb_process.h> + +#define USB_DEBUG_VAR usb_proc_debug #include <dev/usb/usb_debug.h> #include <dev/usb/usb_util.h> diff --git a/freebsd/sys/dev/usb/usb_request.c b/freebsd/sys/dev/usb/usb_request.c index e9137bd2..6f9d7b12 100644 --- a/freebsd/sys/dev/usb/usb_request.c +++ b/freebsd/sys/dev/usb/usb_request.c @@ -806,8 +806,6 @@ usbd_req_reset_port(struct usb_device *udev, struct mtx *mtx, uint8_t port) /* check for errors */ if (err) goto done; -#ifdef USB_DEBUG -#endif n = 0; while (1) { /* wait for the device to recover from reset */ diff --git a/freebsd/sys/dev/usb/usb_transfer.c b/freebsd/sys/dev/usb/usb_transfer.c index 205a72f7..ab5558e1 100644 --- a/freebsd/sys/dev/usb/usb_transfer.c +++ b/freebsd/sys/dev/usb/usb_transfer.c @@ -945,7 +945,8 @@ usbd_transfer_setup(struct usb_device *udev, #if USB_HAVE_BUSDMA usb_dma_tag_setup(&info->dma_parent_tag, parm->dma_tag_p, udev->bus->dma_parent_tag[0].tag, - xfer_mtx, &usb_bdma_done_event, 32, parm->dma_tag_max); + xfer_mtx, &usb_bdma_done_event, udev->bus->dma_bits, + parm->dma_tag_max); #endif info->bus = udev->bus; @@ -1374,6 +1375,29 @@ usbd_control_transfer_init(struct usb_xfer *xfer) } /*------------------------------------------------------------------------* + * usbd_control_transfer_did_data + * + * This function returns non-zero if a control endpoint has + * transferred the first DATA packet after the SETUP packet. + * Else it returns zero. + *------------------------------------------------------------------------*/ +static uint8_t +usbd_control_transfer_did_data(struct usb_xfer *xfer) +{ + struct usb_device_request req; + + /* SETUP packet is not yet sent */ + if (xfer->flags_int.control_hdr != 0) + return (0); + + /* copy out the USB request header */ + usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req)); + + /* compare remainder to the initial value */ + return (xfer->flags_int.control_rem != UGETW(req.wLength)); +} + +/*------------------------------------------------------------------------* * usbd_setup_ctrl_transfer * * This function handles initialisation of control transfers. Control @@ -1478,6 +1502,11 @@ usbd_setup_ctrl_transfer(struct usb_xfer *xfer) len = (xfer->sumlen - sizeof(struct usb_device_request)); } + /* update did data flag */ + + xfer->flags_int.control_did_data = + usbd_control_transfer_did_data(xfer); + /* check if there is a length mismatch */ if (len > xfer->flags_int.control_rem) { |