diff options
Diffstat (limited to 'drivers/usb/misc/lvstest.c')
| -rw-r--r-- | drivers/usb/misc/lvstest.c | 69 |
1 files changed, 48 insertions, 21 deletions
diff --git a/drivers/usb/misc/lvstest.c b/drivers/usb/misc/lvstest.c index 2142132a1f82..25ec5666a75e 100644 --- a/drivers/usb/misc/lvstest.c +++ b/drivers/usb/misc/lvstest.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * drivers/usb/misc/lvstest.c * @@ -5,10 +6,6 @@ * * Copyright (C) 2014 ST Microelectronics * Pratyush Anand <pratyush.anand@gmail.com> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. */ #include <linux/init.h> @@ -178,6 +175,25 @@ static ssize_t hot_reset_store(struct device *dev, } static DEVICE_ATTR_WO(hot_reset); +static ssize_t warm_reset_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_device *hdev = interface_to_usbdev(intf); + struct lvs_rh *lvs = usb_get_intfdata(intf); + int ret; + + ret = lvs_rh_set_port_feature(hdev, lvs->portnum, + USB_PORT_FEAT_BH_PORT_RESET); + if (ret < 0) { + dev_err(dev, "can't issue warm reset %d\n", ret); + return ret; + } + + return count; +} +static DEVICE_ATTR_WO(warm_reset); + static ssize_t u2_timeout_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -274,19 +290,38 @@ free_desc: } static DEVICE_ATTR_WO(get_dev_desc); -static struct attribute *lvs_attributes[] = { +static ssize_t enable_compliance_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usb_device *hdev = interface_to_usbdev(intf); + struct lvs_rh *lvs = usb_get_intfdata(intf); + int ret; + + ret = lvs_rh_set_port_feature(hdev, + lvs->portnum | USB_SS_PORT_LS_COMP_MOD << 3, + USB_PORT_FEAT_LINK_STATE); + if (ret < 0) { + dev_err(dev, "can't enable compliance mode %d\n", ret); + return ret; + } + + return count; +} +static DEVICE_ATTR_WO(enable_compliance); + +static struct attribute *lvs_attrs[] = { &dev_attr_get_dev_desc.attr, &dev_attr_u1_timeout.attr, &dev_attr_u2_timeout.attr, &dev_attr_hot_reset.attr, + &dev_attr_warm_reset.attr, &dev_attr_u3_entry.attr, &dev_attr_u3_exit.attr, + &dev_attr_enable_compliance.attr, NULL }; - -static const struct attribute_group lvs_attr_group = { - .attrs = lvs_attributes, -}; +ATTRIBUTE_GROUPS(lvs); static void lvs_rh_work(struct work_struct *work) { @@ -391,7 +426,7 @@ static int lvs_rh_probe(struct usb_interface *intf, USB_DT_SS_HUB_SIZE, USB_CTRL_GET_TIMEOUT); if (ret < (USB_DT_HUB_NONVAR_SIZE + 2)) { dev_err(&hdev->dev, "wrong root hub descriptor read %d\n", ret); - return ret; + return ret < 0 ? ret : -EINVAL; } /* submit urb to poll interrupt endpoint */ @@ -401,27 +436,19 @@ static int lvs_rh_probe(struct usb_interface *intf, INIT_WORK(&lvs->rh_work, lvs_rh_work); - ret = sysfs_create_group(&intf->dev.kobj, &lvs_attr_group); - if (ret < 0) { - dev_err(&intf->dev, "Failed to create sysfs node %d\n", ret); - goto free_urb; - } - pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe)); + maxp = usb_maxpacket(hdev, pipe); usb_fill_int_urb(lvs->urb, hdev, pipe, &lvs->buffer[0], maxp, lvs_rh_irq, lvs, endpoint->bInterval); ret = usb_submit_urb(lvs->urb, GFP_KERNEL); if (ret < 0) { dev_err(&intf->dev, "couldn't submit lvs urb %d\n", ret); - goto sysfs_remove; + goto free_urb; } return ret; -sysfs_remove: - sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group); free_urb: usb_free_urb(lvs->urb); return ret; @@ -431,7 +458,6 @@ static void lvs_rh_disconnect(struct usb_interface *intf) { struct lvs_rh *lvs = usb_get_intfdata(intf); - sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group); usb_poison_urb(lvs->urb); /* used in scheduled work */ flush_work(&lvs->rh_work); usb_free_urb(lvs->urb); @@ -441,6 +467,7 @@ static struct usb_driver lvs_driver = { .name = "lvs", .probe = lvs_rh_probe, .disconnect = lvs_rh_disconnect, + .dev_groups = lvs_groups, }; module_usb_driver(lvs_driver); |
