From 4568136620c6482bcd4a6b0cd6ae8e5679615d7e Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 25 Apr 2017 17:56:11 -0700 Subject: usb: core: Check URB setup_packet and transfer_buffer sanity Update usb_hcd_map_urb_for_dma() to check for an URB's setup_packet and transfer_buffer sanity. We first check that urb->setup_packet is neither coming from vmalloc space nor is an on stack buffer, and if that's the case, produce a warning and return an error. For urb->transfer_buffer there is an existing is_vmalloc_addr() check so we just supplement that with an object_is_on_stack() check, produce a warning if that is the case and also return an error. Signed-off-by: Florian Fainelli Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 49550790a3cb..26d710eec7da 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1523,6 +1524,14 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, if (hcd->self.uses_pio_for_control) return ret; if (IS_ENABLED(CONFIG_HAS_DMA) && hcd->self.uses_dma) { + if (is_vmalloc_addr(urb->setup_packet)) { + WARN_ONCE(1, "setup packet is not dma capable\n"); + return -EAGAIN; + } else if (object_is_on_stack(urb->setup_packet)) { + WARN_ONCE(1, "setup packet is on stack\n"); + return -EAGAIN; + } + urb->setup_dma = dma_map_single( hcd->self.sysdev, urb->setup_packet, @@ -1587,6 +1596,9 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, } else if (is_vmalloc_addr(urb->transfer_buffer)) { WARN_ONCE(1, "transfer buffer not dma capable\n"); ret = -EAGAIN; + } else if (object_is_on_stack(urb->transfer_buffer)) { + WARN_ONCE(1, "transfer buffer is on stack\n"); + ret = -EAGAIN; } else { urb->transfer_dma = dma_map_single( hcd->self.sysdev, -- cgit v1.2.3 From ed18c5fa945768a9bec994e786edbbbc7695acf6 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 2 Jun 2017 16:36:26 +0300 Subject: usb: optimize acpi companion search for usb port devices This optimization significantly reduces xhci driver load time. In ACPI tables the acpi companion port devices are children of the hub device. The port devices are identified by their port number returned by the ACPI _ADR method. _ADR 0 is reserved for the root hub device. The current implementation to find a acpi companion port device loops through all acpi port devices under that parent hub, evaluating their _ADR method each time a new port device is added. for a xHC controller with 25 ports under its roothub it will end up invoking ACPI bytecode 625 times before all ports are ready, making it really slow. The _ADR values are already read and cached earler. So instead of running the bytecode again we can check the cached _ADR value first, and then fall back to the old way. As one of the more significant changes, the xhci load time on Intel kabylake reduced by 70%, (28ms) from initcall xhci_pci_init+0x0/0x49 returned 0 after 39537 usecs to initcall xhci_pci_init+0x0/0x49 returned 0 after 11270 usecs Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/usb-acpi.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 2776cfe64c09..ef9cf4a21afe 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -127,6 +127,22 @@ out: */ #define USB_ACPI_LOCATION_VALID (1 << 31) +static struct acpi_device *usb_acpi_find_port(struct acpi_device *parent, + int raw) +{ + struct acpi_device *adev; + + if (!parent) + return NULL; + + list_for_each_entry(adev, &parent->children, node) { + if (acpi_device_adr(adev) == raw) + return adev; + } + + return acpi_find_child_device(parent, raw, false); +} + static struct acpi_device *usb_acpi_find_companion(struct device *dev) { struct usb_device *udev; @@ -174,8 +190,10 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev) int raw; raw = usb_hcd_find_raw_port_number(hcd, port1); - adev = acpi_find_child_device(ACPI_COMPANION(&udev->dev), - raw, false); + + adev = usb_acpi_find_port(ACPI_COMPANION(&udev->dev), + raw); + if (!adev) return NULL; } else { @@ -186,7 +204,9 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev) return NULL; acpi_bus_get_device(parent_handle, &adev); - adev = acpi_find_child_device(adev, port1, false); + + adev = usb_acpi_find_port(adev, port1); + if (!adev) return NULL; } -- cgit v1.2.3 From c01b244ad848ac7f0faa141182db80650a8a761a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 5 Jun 2017 10:28:01 -0400 Subject: USB: add usbfs ioctl to retrieve the connection speed The usbfs interface does not provide any way for the user to learn the speed at which a device is connected. The current API includes a USBDEVFS_CONNECTINFO ioctl, but all it provides is the device's address and a one-bit value indicating whether the connection is low speed. That may have sufficed in the era of USB-1.1, but it isn't good enough today. This patch introduces a new ioctl, USBDEVFS_GET_SPEED, which returns a numeric value indicating the speed of the connection: unknown, low, full, high, wireless, super, or super-plus. Similar information (not exactly the same) is available through sysfs, but it seems reasonable to provide the actual value in usbfs. Signed-off-by: Alan Stern Reported-by: Reinhard Huck Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 3 +++ include/uapi/linux/usbdevice_fs.h | 6 ++++++ 2 files changed, 9 insertions(+) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 8e6ef671be9b..0e7d0e81a7cb 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -2537,6 +2537,9 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, case USBDEVFS_DROP_PRIVILEGES: ret = proc_drop_privileges(ps, p); break; + case USBDEVFS_GET_SPEED: + ret = ps->dev->speed; + break; } done: diff --git a/include/uapi/linux/usbdevice_fs.h b/include/uapi/linux/usbdevice_fs.h index a8653a6f40df..0bbfd4abd2e3 100644 --- a/include/uapi/linux/usbdevice_fs.h +++ b/include/uapi/linux/usbdevice_fs.h @@ -156,6 +156,11 @@ struct usbdevfs_streams { unsigned char eps[0]; }; +/* + * USB_SPEED_* values returned by USBDEVFS_GET_SPEED are defined in + * linux/usb/ch9.h + */ + #define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer) #define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32) #define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer) @@ -190,5 +195,6 @@ struct usbdevfs_streams { #define USBDEVFS_ALLOC_STREAMS _IOR('U', 28, struct usbdevfs_streams) #define USBDEVFS_FREE_STREAMS _IOR('U', 29, struct usbdevfs_streams) #define USBDEVFS_DROP_PRIVILEGES _IOW('U', 30, __u32) +#define USBDEVFS_GET_SPEED _IO('U', 31) #endif /* _UAPI_LINUX_USBDEVICE_FS_H */ -- cgit v1.2.3 From e271b2c909a22a2c13b2d5f77f2ce0091b74540c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 6 Jun 2017 17:58:58 +0200 Subject: USB: core: fix device node leak Make sure to release any OF device-node reference taken when creating the USB device. Note that we currently do not hold a reference to the root hub device-tree node (i.e. the parent controller node). Fixes: 69bec7259853 ("USB: core: let USB device know device node") Cc: stable # v4.6 Acked-by: Peter Chen Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/usb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 28b053cacc90..62e1906bb2f3 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -416,6 +416,8 @@ static void usb_release_dev(struct device *dev) usb_destroy_configuration(udev); usb_release_bos_descriptor(udev); + if (udev->parent) + of_node_put(dev->of_node); usb_put_hcd(hcd); kfree(udev->product); kfree(udev->manufacturer); -- cgit v1.2.3 From 60a93cffcffdc86222c184aafc622b53b8460427 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 6 Jun 2017 17:58:59 +0200 Subject: USB: of: document reference taken by child-lookup helper Document that the child-node lookup helper takes a reference to the device-tree node which needs to be dropped after use. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/of.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/of.c b/drivers/usb/core/of.c index d563cbcf76cf..3863bb1ce8c5 100644 --- a/drivers/usb/core/of.c +++ b/drivers/usb/core/of.c @@ -28,7 +28,8 @@ * * Find the node from device tree according to its port number. * - * Return: On success, a pointer to the device node, %NULL on failure. + * Return: A pointer to the node with incremented refcount if found, or + * %NULL otherwise. */ struct device_node *usb_of_get_child_node(struct device_node *parent, int portnum) -- cgit v1.2.3 From 2bf698671205bb6f898db348b788d16f6976e086 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 6 Jun 2017 17:59:02 +0200 Subject: USB: of: fix root-hub device-tree node handling In an attempt to work around a pinmux over-allocation issue in driver core, commit dc5878abf49c ("usb: core: move root hub's device node assignment after it is added to bus") moved the device-tree node assignment until after the root hub had been registered. This not only makes the device-tree node unavailable to the usb driver during probe, but also prevents the of_node from being linked to in sysfs and causes a race with user-space for the (recently added) devspec attribute. Use the new device_set_of_node_from_dev() helper to reuse the node of the sysdev device, something which now prevents driver core from trying to reclaim any pinctrl pins during probe. Fixes: dc5878abf49c ("usb: core: move root hub's device node assignment after it is added to bus") Fixes: 51fa91475e43 ("usb/core: Added devspec sysfs entry for devices behind the usb hub") Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 2 -- drivers/usb/core/usb.c | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index e72cbc751619..ab1bb3b538ac 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1077,7 +1077,6 @@ static void usb_deregister_bus (struct usb_bus *bus) static int register_root_hub(struct usb_hcd *hcd) { struct device *parent_dev = hcd->self.controller; - struct device *sysdev = hcd->self.sysdev; struct usb_device *usb_dev = hcd->self.root_hub; const int devnum = 1; int retval; @@ -1124,7 +1123,6 @@ static int register_root_hub(struct usb_hcd *hcd) /* Did the HC die before the root hub was registered? */ if (HCD_DEAD(hcd)) usb_hc_died (hcd); /* This time clean up */ - usb_dev->dev.of_node = sysdev->of_node; } mutex_unlock(&usb_bus_idr_lock); diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 62e1906bb2f3..17681d5638ac 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -416,8 +416,7 @@ static void usb_release_dev(struct device *dev) usb_destroy_configuration(udev); usb_release_bos_descriptor(udev); - if (udev->parent) - of_node_put(dev->of_node); + of_node_put(dev->of_node); usb_put_hcd(hcd); kfree(udev->product); kfree(udev->manufacturer); @@ -616,6 +615,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, dev->route = 0; dev->dev.parent = bus->controller; + device_set_of_node_from_dev(&dev->dev, bus->sysdev); dev_set_name(&dev->dev, "usb%d", bus->busnum); root_hub = 1; } else { -- cgit v1.2.3 From d590c23111505635e1beb01006612971e5ede8aa Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 15 Jun 2017 11:55:41 +0300 Subject: usb: Avoid unnecessary LPM enabling and disabling during suspend and resume The original motivation for disabling/enabling Link PM at device suspend/resume was to force link state to go via U0 before suspend sets the link state to U3. Going directly from U2 to U3 is not allowed. Disabling LPM will forced the link state to U0, but will send a lot of Set port feature requests for evert suspend and resume. This is not needed as Hub hardware will take care of going via U0 when a U2 -> U3 transition is requested [1] [1] USB 3.1 specification section 10.16.2.10 Set Port Feature: "If the value is 3, then host software wants to selectively suspend the device connected to this port. The hub shall transition the link to U3 from any of the other U states using allowed link state transitions. If the port is not already in the U0 state, then it shall transition the port to the U0 state and then initiate the transition to U3. While this state is active, the hub does not propagate downstream-directed traffic to this port, but the hub will respond to resume signaling from the port" Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b8bb20d7acdb..59e0418a5ed5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3155,12 +3155,6 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) if (PMSG_IS_AUTO(msg)) goto err_ltm; } - if (usb_unlocked_disable_lpm(udev)) { - dev_err(&udev->dev, "Failed to disable LPM before suspend\n."); - status = -ENOMEM; - if (PMSG_IS_AUTO(msg)) - goto err_lpm3; - } /* see 7.1.7.6 */ if (hub_is_superspeed(hub->hdev)) @@ -3187,9 +3181,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) if (status) { dev_dbg(&port_dev->dev, "can't suspend, status %d\n", status); - /* Try to enable USB3 LPM and LTM again */ - usb_unlocked_enable_lpm(udev); - err_lpm3: + /* Try to enable USB3 LTM again */ usb_enable_ltm(udev); err_ltm: /* Try to enable USB2 hardware LPM again */ @@ -3473,9 +3465,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) if (udev->usb2_hw_lpm_capable == 1) usb_set_usb2_hardware_lpm(udev, 1); - /* Try to enable USB3 LTM and LPM */ + /* Try to enable USB3 LTM */ usb_enable_ltm(udev); - usb_unlocked_enable_lpm(udev); } usb_unlock_port(port_dev); -- cgit v1.2.3 From 4f04c210d031667e503d6538a72345a36f3b5d71 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 8 Jun 2017 18:08:32 +0200 Subject: usb: core: read USB ports from DT in the usbport LED trigger driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This uses DT info to read relation description of LEDs and USB ports. If DT has properly described LEDs, trigger will know when to turn them on. Signed-off-by: Rafał Miłecki Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/ledtrig-usbport.c | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/ledtrig-usbport.c b/drivers/usb/core/ledtrig-usbport.c index 1713248ab15a..16c19a31dad1 100644 --- a/drivers/usb/core/ledtrig-usbport.c +++ b/drivers/usb/core/ledtrig-usbport.c @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include struct usbport_trig_data { struct led_classdev *led_cdev; @@ -123,6 +125,57 @@ static const struct attribute_group ports_group = { * Adding & removing ports ***************************************/ +/** + * usbport_trig_port_observed - Check if port should be observed + */ +static bool usbport_trig_port_observed(struct usbport_trig_data *usbport_data, + struct usb_device *usb_dev, int port1) +{ + struct device *dev = usbport_data->led_cdev->dev; + struct device_node *led_np = dev->of_node; + struct of_phandle_args args; + struct device_node *port_np; + int count, i; + + if (!led_np) + return false; + + /* Get node of port being added */ + port_np = usb_of_get_child_node(usb_dev->dev.of_node, port1); + if (!port_np) + return false; + + /* Amount of trigger sources for this LED */ + count = of_count_phandle_with_args(led_np, "trigger-sources", + "#trigger-source-cells"); + if (count < 0) { + dev_warn(dev, "Failed to get trigger sources for %s\n", + led_np->full_name); + return false; + } + + /* Check list of sources for this specific port */ + for (i = 0; i < count; i++) { + int err; + + err = of_parse_phandle_with_args(led_np, "trigger-sources", + "#trigger-source-cells", i, + &args); + if (err) { + dev_err(dev, "Failed to get trigger source phandle at index %d: %d\n", + i, err); + continue; + } + + of_node_put(args.np); + + if (args.np == port_np) + return true; + } + + return false; +} + static int usbport_trig_add_port(struct usbport_trig_data *usbport_data, struct usb_device *usb_dev, const char *hub_name, int portnum) @@ -141,6 +194,8 @@ static int usbport_trig_add_port(struct usbport_trig_data *usbport_data, port->data = usbport_data; port->hub = usb_dev; port->portnum = portnum; + port->observed = usbport_trig_port_observed(usbport_data, usb_dev, + portnum); len = strlen(hub_name) + 8; port->port_name = kzalloc(len, GFP_KERNEL); @@ -255,6 +310,7 @@ static void usbport_trig_activate(struct led_classdev *led_cdev) if (err) goto err_free; usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports); + usbport_trig_update_count(usbport_data); /* Notifications */ usbport_data->nb.notifier_call = usbport_trig_notify, -- cgit v1.2.3 From c94dc34f771a25b8c3e0955147fdc4f5e3d79908 Mon Sep 17 00:00:00 2001 From: Eugene Korenevsky Date: Sun, 25 Jun 2017 11:08:14 +0300 Subject: USB hub_probe: rework ugly goto-into-compound-statement Rework smelling code (goto inside compound statement). Perhaps this is legacy. Anyway such code is not appropriate for Linux kernel. Signed-off-by: Eugene Korenevsky Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 59e0418a5ed5..6e6797d145dd 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1661,10 +1661,28 @@ static void hub_disconnect(struct usb_interface *intf) kref_put(&hub->kref, hub_release); } +static bool hub_descriptor_is_sane(struct usb_host_interface *desc) +{ + /* Some hubs have a subclass of 1, which AFAICT according to the */ + /* specs is not defined, but it works */ + if (desc->desc.bInterfaceSubClass != 0 && + desc->desc.bInterfaceSubClass != 1) + return false; + + /* Multiple endpoints? What kind of mutant ninja-hub is this? */ + if (desc->desc.bNumEndpoints != 1) + return false; + + /* If the first endpoint is not interrupt IN, we'd better punt! */ + if (!usb_endpoint_is_int_in(&desc->endpoint[0].desc)) + return false; + + return true; +} + static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_host_interface *desc; - struct usb_endpoint_descriptor *endpoint; struct usb_device *hdev; struct usb_hub *hub; @@ -1739,25 +1757,11 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) } #endif - /* Some hubs have a subclass of 1, which AFAICT according to the */ - /* specs is not defined, but it works */ - if ((desc->desc.bInterfaceSubClass != 0) && - (desc->desc.bInterfaceSubClass != 1)) { -descriptor_error: + if (!hub_descriptor_is_sane(desc)) { dev_err(&intf->dev, "bad descriptor, ignoring hub\n"); return -EIO; } - /* Multiple endpoints? What kind of mutant ninja-hub is this? */ - if (desc->desc.bNumEndpoints != 1) - goto descriptor_error; - - endpoint = &desc->endpoint[0].desc; - - /* If it's not an interrupt in endpoint, we'd better punt! */ - if (!usb_endpoint_is_int_in(endpoint)) - goto descriptor_error; - /* We found a hub */ dev_info(&intf->dev, "USB hub found\n"); @@ -1784,7 +1788,7 @@ descriptor_error: if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND) hub->quirk_check_port_auto_suspend = 1; - if (hub_configure(hub, endpoint) >= 0) + if (hub_configure(hub, &desc->endpoint[0].desc) >= 0) return 0; hub_disconnect(intf); -- cgit v1.2.3 From 6836796de4019944f4ba4c99a360e8250fd2e735 Mon Sep 17 00:00:00 2001 From: Devin Heitmueller Date: Tue, 27 Jun 2017 13:08:51 -0400 Subject: Add USB quirk for HVR-950q to avoid intermittent device resets The USB core and sysfs will attempt to enumerate certain parameters which are unsupported by the au0828 - causing inconsistent behavior and sometimes causing the chip to reset. Avoid making these calls. This problem manifested as intermittent cases where the au8522 would be reset on analog video startup, in particular when starting up ALSA audio streaming in parallel - the sysfs entries created by snd-usb-audio on streaming startup would result in unsupported control messages being sent during tuning which would put the chip into an unknown state. Signed-off-by: Devin Heitmueller Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 96b21b0dac1e..3116edfcdc18 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -223,6 +223,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* Blackmagic Design UltraStudio SDI */ { USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM }, + /* Hauppauge HVR-950q */ + { USB_DEVICE(0x2040, 0x7200), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* INTEL VALUE SSD */ { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, -- cgit v1.2.3