linux/drivers/usb/misc/lvstest.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * drivers/usb/misc/lvstest.c
   4 *
   5 * Test pattern generation for Link Layer Validation System Tests
   6 *
   7 * Copyright (C) 2014 ST Microelectronics
   8 * Pratyush Anand <pratyush.anand@st.com>
   9 *
  10 * This file is licensed under the terms of the GNU General Public
  11 * License version 2. This program is licensed "as is" without any
  12 * warranty of any kind, whether express or implied.
  13 */
  14
  15#include <linux/init.h>
  16#include <linux/kernel.h>
  17#include <linux/module.h>
  18#include <linux/platform_device.h>
  19#include <linux/slab.h>
  20#include <linux/usb.h>
  21#include <linux/usb/ch11.h>
  22#include <linux/usb/hcd.h>
  23#include <linux/usb/phy.h>
  24
  25struct lvs_rh {
  26        /* root hub interface */
  27        struct usb_interface *intf;
  28        /* if lvs device connected */
  29        bool present;
  30        /* port no at which lvs device is present */
  31        int portnum;
  32        /* urb buffer */
  33        u8 buffer[8];
  34        /* class descriptor */
  35        struct usb_hub_descriptor descriptor;
  36        /* urb for polling interrupt pipe */
  37        struct urb *urb;
  38        /* LVH RH work */
  39        struct work_struct      rh_work;
  40        /* RH port status */
  41        struct usb_port_status port_status;
  42};
  43
  44static struct usb_device *create_lvs_device(struct usb_interface *intf)
  45{
  46        struct usb_device *udev, *hdev;
  47        struct usb_hcd *hcd;
  48        struct lvs_rh *lvs = usb_get_intfdata(intf);
  49
  50        if (!lvs->present) {
  51                dev_err(&intf->dev, "No LVS device is present\n");
  52                return NULL;
  53        }
  54
  55        hdev = interface_to_usbdev(intf);
  56        hcd = bus_to_hcd(hdev->bus);
  57
  58        udev = usb_alloc_dev(hdev, hdev->bus, lvs->portnum);
  59        if (!udev) {
  60                dev_err(&intf->dev, "Could not allocate lvs udev\n");
  61                return NULL;
  62        }
  63        udev->speed = USB_SPEED_SUPER;
  64        udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
  65        usb_set_device_state(udev, USB_STATE_DEFAULT);
  66
  67        if (hcd->driver->enable_device) {
  68                if (hcd->driver->enable_device(hcd, udev) < 0) {
  69                        dev_err(&intf->dev, "Failed to enable\n");
  70                        usb_put_dev(udev);
  71                        return NULL;
  72                }
  73        }
  74
  75        return udev;
  76}
  77
  78static void destroy_lvs_device(struct usb_device *udev)
  79{
  80        struct usb_device *hdev = udev->parent;
  81        struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
  82
  83        if (hcd->driver->free_dev)
  84                hcd->driver->free_dev(hcd, udev);
  85
  86        usb_put_dev(udev);
  87}
  88
  89static int lvs_rh_clear_port_feature(struct usb_device *hdev,
  90                int port1, int feature)
  91{
  92        return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
  93                USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1,
  94                NULL, 0, 1000);
  95}
  96
  97static int lvs_rh_set_port_feature(struct usb_device *hdev,
  98                int port1, int feature)
  99{
 100        return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
 101                USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port1,
 102                NULL, 0, 1000);
 103}
 104
 105static ssize_t u3_entry_store(struct device *dev,
 106                struct device_attribute *attr, const char *buf, size_t count)
 107{
 108        struct usb_interface *intf = to_usb_interface(dev);
 109        struct usb_device *hdev = interface_to_usbdev(intf);
 110        struct lvs_rh *lvs = usb_get_intfdata(intf);
 111        struct usb_device *udev;
 112        int ret;
 113
 114        udev = create_lvs_device(intf);
 115        if (!udev) {
 116                dev_err(dev, "failed to create lvs device\n");
 117                return -ENOMEM;
 118        }
 119
 120        ret = lvs_rh_set_port_feature(hdev, lvs->portnum,
 121                        USB_PORT_FEAT_SUSPEND);
 122        if (ret < 0)
 123                dev_err(dev, "can't issue U3 entry %d\n", ret);
 124
 125        destroy_lvs_device(udev);
 126
 127        if (ret < 0)
 128                return ret;
 129
 130        return count;
 131}
 132static DEVICE_ATTR_WO(u3_entry);
 133
 134static ssize_t u3_exit_store(struct device *dev,
 135                struct device_attribute *attr, const char *buf, size_t count)
 136{
 137        struct usb_interface *intf = to_usb_interface(dev);
 138        struct usb_device *hdev = interface_to_usbdev(intf);
 139        struct lvs_rh *lvs = usb_get_intfdata(intf);
 140        struct usb_device *udev;
 141        int ret;
 142
 143        udev = create_lvs_device(intf);
 144        if (!udev) {
 145                dev_err(dev, "failed to create lvs device\n");
 146                return -ENOMEM;
 147        }
 148
 149        ret = lvs_rh_clear_port_feature(hdev, lvs->portnum,
 150                        USB_PORT_FEAT_SUSPEND);
 151        if (ret < 0)
 152                dev_err(dev, "can't issue U3 exit %d\n", ret);
 153
 154        destroy_lvs_device(udev);
 155
 156        if (ret < 0)
 157                return ret;
 158
 159        return count;
 160}
 161static DEVICE_ATTR_WO(u3_exit);
 162
 163static ssize_t hot_reset_store(struct device *dev,
 164                struct device_attribute *attr, const char *buf, size_t count)
 165{
 166        struct usb_interface *intf = to_usb_interface(dev);
 167        struct usb_device *hdev = interface_to_usbdev(intf);
 168        struct lvs_rh *lvs = usb_get_intfdata(intf);
 169        int ret;
 170
 171        ret = lvs_rh_set_port_feature(hdev, lvs->portnum,
 172                        USB_PORT_FEAT_RESET);
 173        if (ret < 0) {
 174                dev_err(dev, "can't issue hot reset %d\n", ret);
 175                return ret;
 176        }
 177
 178        return count;
 179}
 180static DEVICE_ATTR_WO(hot_reset);
 181
 182static ssize_t warm_reset_store(struct device *dev,
 183                struct device_attribute *attr, const char *buf, size_t count)
 184{
 185        struct usb_interface *intf = to_usb_interface(dev);
 186        struct usb_device *hdev = interface_to_usbdev(intf);
 187        struct lvs_rh *lvs = usb_get_intfdata(intf);
 188        int ret;
 189
 190        ret = lvs_rh_set_port_feature(hdev, lvs->portnum,
 191                        USB_PORT_FEAT_BH_PORT_RESET);
 192        if (ret < 0) {
 193                dev_err(dev, "can't issue warm reset %d\n", ret);
 194                return ret;
 195        }
 196
 197        return count;
 198}
 199static DEVICE_ATTR_WO(warm_reset);
 200
 201static ssize_t u2_timeout_store(struct device *dev,
 202                struct device_attribute *attr, const char *buf, size_t count)
 203{
 204        struct usb_interface *intf = to_usb_interface(dev);
 205        struct usb_device *hdev = interface_to_usbdev(intf);
 206        struct lvs_rh *lvs = usb_get_intfdata(intf);
 207        unsigned long val;
 208        int ret;
 209
 210        ret = kstrtoul(buf, 10, &val);
 211        if (ret < 0) {
 212                dev_err(dev, "couldn't parse string %d\n", ret);
 213                return ret;
 214        }
 215
 216        if (val > 127)
 217                return -EINVAL;
 218
 219        ret = lvs_rh_set_port_feature(hdev, lvs->portnum | (val << 8),
 220                        USB_PORT_FEAT_U2_TIMEOUT);
 221        if (ret < 0) {
 222                dev_err(dev, "Error %d while setting U2 timeout %ld\n", ret, val);
 223                return ret;
 224        }
 225
 226        return count;
 227}
 228static DEVICE_ATTR_WO(u2_timeout);
 229
 230static ssize_t u1_timeout_store(struct device *dev,
 231                struct device_attribute *attr, const char *buf, size_t count)
 232{
 233        struct usb_interface *intf = to_usb_interface(dev);
 234        struct usb_device *hdev = interface_to_usbdev(intf);
 235        struct lvs_rh *lvs = usb_get_intfdata(intf);
 236        unsigned long val;
 237        int ret;
 238
 239        ret = kstrtoul(buf, 10, &val);
 240        if (ret < 0) {
 241                dev_err(dev, "couldn't parse string %d\n", ret);
 242                return ret;
 243        }
 244
 245        if (val > 127)
 246                return -EINVAL;
 247
 248        ret = lvs_rh_set_port_feature(hdev, lvs->portnum | (val << 8),
 249                        USB_PORT_FEAT_U1_TIMEOUT);
 250        if (ret < 0) {
 251                dev_err(dev, "Error %d while setting U1 timeout %ld\n", ret, val);
 252                return ret;
 253        }
 254
 255        return count;
 256}
 257static DEVICE_ATTR_WO(u1_timeout);
 258
 259static ssize_t get_dev_desc_store(struct device *dev,
 260                struct device_attribute *attr, const char *buf, size_t count)
 261{
 262        struct usb_interface *intf = to_usb_interface(dev);
 263        struct usb_device *udev;
 264        struct usb_device_descriptor *descriptor;
 265        int ret;
 266
 267        descriptor = kmalloc(sizeof(*descriptor), GFP_KERNEL);
 268        if (!descriptor)
 269                return -ENOMEM;
 270
 271        udev = create_lvs_device(intf);
 272        if (!udev) {
 273                dev_err(dev, "failed to create lvs device\n");
 274                ret = -ENOMEM;
 275                goto free_desc;
 276        }
 277
 278        ret = usb_control_msg(udev, (PIPE_CONTROL << 30) | USB_DIR_IN,
 279                        USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, USB_DT_DEVICE << 8,
 280                        0, descriptor, sizeof(*descriptor),
 281                        USB_CTRL_GET_TIMEOUT);
 282        if (ret < 0)
 283                dev_err(dev, "can't read device descriptor %d\n", ret);
 284
 285        destroy_lvs_device(udev);
 286
 287free_desc:
 288        kfree(descriptor);
 289
 290        if (ret < 0)
 291                return ret;
 292
 293        return count;
 294}
 295static DEVICE_ATTR_WO(get_dev_desc);
 296
 297static ssize_t enable_compliance_store(struct device *dev,
 298                struct device_attribute *attr, const char *buf, size_t count)
 299{
 300        struct usb_interface *intf = to_usb_interface(dev);
 301        struct usb_device *hdev = interface_to_usbdev(intf);
 302        struct lvs_rh *lvs = usb_get_intfdata(intf);
 303        int ret;
 304
 305        ret = lvs_rh_set_port_feature(hdev,
 306                        lvs->portnum | USB_SS_PORT_LS_COMP_MOD << 3,
 307                        USB_PORT_FEAT_LINK_STATE);
 308        if (ret < 0) {
 309                dev_err(dev, "can't enable compliance mode %d\n", ret);
 310                return ret;
 311        }
 312
 313        return count;
 314}
 315static DEVICE_ATTR_WO(enable_compliance);
 316
 317static struct attribute *lvs_attributes[] = {
 318        &dev_attr_get_dev_desc.attr,
 319        &dev_attr_u1_timeout.attr,
 320        &dev_attr_u2_timeout.attr,
 321        &dev_attr_hot_reset.attr,
 322        &dev_attr_warm_reset.attr,
 323        &dev_attr_u3_entry.attr,
 324        &dev_attr_u3_exit.attr,
 325        &dev_attr_enable_compliance.attr,
 326        NULL
 327};
 328
 329static const struct attribute_group lvs_attr_group = {
 330        .attrs = lvs_attributes,
 331};
 332
 333static void lvs_rh_work(struct work_struct *work)
 334{
 335        struct lvs_rh *lvs = container_of(work, struct lvs_rh, rh_work);
 336        struct usb_interface *intf = lvs->intf;
 337        struct usb_device *hdev = interface_to_usbdev(intf);
 338        struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
 339        struct usb_hub_descriptor *descriptor = &lvs->descriptor;
 340        struct usb_port_status *port_status = &lvs->port_status;
 341        int i, ret = 0;
 342        u16 portchange;
 343
 344        /* Examine each root port */
 345        for (i = 1; i <= descriptor->bNbrPorts; i++) {
 346                ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
 347                        USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, i,
 348                        port_status, sizeof(*port_status), 1000);
 349                if (ret < 4)
 350                        continue;
 351
 352                portchange = le16_to_cpu(port_status->wPortChange);
 353
 354                if (portchange & USB_PORT_STAT_C_LINK_STATE)
 355                        lvs_rh_clear_port_feature(hdev, i,
 356                                        USB_PORT_FEAT_C_PORT_LINK_STATE);
 357                if (portchange & USB_PORT_STAT_C_ENABLE)
 358                        lvs_rh_clear_port_feature(hdev, i,
 359                                        USB_PORT_FEAT_C_ENABLE);
 360                if (portchange & USB_PORT_STAT_C_RESET)
 361                        lvs_rh_clear_port_feature(hdev, i,
 362                                        USB_PORT_FEAT_C_RESET);
 363                if (portchange & USB_PORT_STAT_C_BH_RESET)
 364                        lvs_rh_clear_port_feature(hdev, i,
 365                                        USB_PORT_FEAT_C_BH_PORT_RESET);
 366                if (portchange & USB_PORT_STAT_C_CONNECTION) {
 367                        lvs_rh_clear_port_feature(hdev, i,
 368                                        USB_PORT_FEAT_C_CONNECTION);
 369
 370                        if (le16_to_cpu(port_status->wPortStatus) &
 371                                        USB_PORT_STAT_CONNECTION) {
 372                                lvs->present = true;
 373                                lvs->portnum = i;
 374                                if (hcd->usb_phy)
 375                                        usb_phy_notify_connect(hcd->usb_phy,
 376                                                        USB_SPEED_SUPER);
 377                        } else {
 378                                lvs->present = false;
 379                                if (hcd->usb_phy)
 380                                        usb_phy_notify_disconnect(hcd->usb_phy,
 381                                                        USB_SPEED_SUPER);
 382                        }
 383                        break;
 384                }
 385        }
 386
 387        ret = usb_submit_urb(lvs->urb, GFP_KERNEL);
 388        if (ret != 0 && ret != -ENODEV && ret != -EPERM)
 389                dev_err(&intf->dev, "urb resubmit error %d\n", ret);
 390}
 391
 392static void lvs_rh_irq(struct urb *urb)
 393{
 394        struct lvs_rh *lvs = urb->context;
 395
 396        schedule_work(&lvs->rh_work);
 397}
 398
 399static int lvs_rh_probe(struct usb_interface *intf,
 400                const struct usb_device_id *id)
 401{
 402        struct usb_device *hdev;
 403        struct usb_host_interface *desc;
 404        struct usb_endpoint_descriptor *endpoint;
 405        struct lvs_rh *lvs;
 406        unsigned int pipe;
 407        int ret, maxp;
 408
 409        hdev = interface_to_usbdev(intf);
 410        desc = intf->cur_altsetting;
 411
 412        ret = usb_find_int_in_endpoint(desc, &endpoint);
 413        if (ret)
 414                return ret;
 415
 416        /* valid only for SS root hub */
 417        if (hdev->descriptor.bDeviceProtocol != USB_HUB_PR_SS || hdev->parent) {
 418                dev_err(&intf->dev, "Bind LVS driver with SS root Hub only\n");
 419                return -EINVAL;
 420        }
 421
 422        lvs = devm_kzalloc(&intf->dev, sizeof(*lvs), GFP_KERNEL);
 423        if (!lvs)
 424                return -ENOMEM;
 425
 426        lvs->intf = intf;
 427        usb_set_intfdata(intf, lvs);
 428
 429        /* how many number of ports this root hub has */
 430        ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
 431                        USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
 432                        USB_DT_SS_HUB << 8, 0, &lvs->descriptor,
 433                        USB_DT_SS_HUB_SIZE, USB_CTRL_GET_TIMEOUT);
 434        if (ret < (USB_DT_HUB_NONVAR_SIZE + 2)) {
 435                dev_err(&hdev->dev, "wrong root hub descriptor read %d\n", ret);
 436                return ret;
 437        }
 438
 439        /* submit urb to poll interrupt endpoint */
 440        lvs->urb = usb_alloc_urb(0, GFP_KERNEL);
 441        if (!lvs->urb)
 442                return -ENOMEM;
 443
 444        INIT_WORK(&lvs->rh_work, lvs_rh_work);
 445
 446        ret = sysfs_create_group(&intf->dev.kobj, &lvs_attr_group);
 447        if (ret < 0) {
 448                dev_err(&intf->dev, "Failed to create sysfs node %d\n", ret);
 449                goto free_urb;
 450        }
 451
 452        pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress);
 453        maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe));
 454        usb_fill_int_urb(lvs->urb, hdev, pipe, &lvs->buffer[0], maxp,
 455                        lvs_rh_irq, lvs, endpoint->bInterval);
 456
 457        ret = usb_submit_urb(lvs->urb, GFP_KERNEL);
 458        if (ret < 0) {
 459                dev_err(&intf->dev, "couldn't submit lvs urb %d\n", ret);
 460                goto sysfs_remove;
 461        }
 462
 463        return ret;
 464
 465sysfs_remove:
 466        sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group);
 467free_urb:
 468        usb_free_urb(lvs->urb);
 469        return ret;
 470}
 471
 472static void lvs_rh_disconnect(struct usb_interface *intf)
 473{
 474        struct lvs_rh *lvs = usb_get_intfdata(intf);
 475
 476        sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group);
 477        usb_poison_urb(lvs->urb); /* used in scheduled work */
 478        flush_work(&lvs->rh_work);
 479        usb_free_urb(lvs->urb);
 480}
 481
 482static struct usb_driver lvs_driver = {
 483        .name =         "lvs",
 484        .probe =        lvs_rh_probe,
 485        .disconnect =   lvs_rh_disconnect,
 486};
 487
 488module_usb_driver(lvs_driver);
 489
 490MODULE_DESCRIPTION("Link Layer Validation System Driver");
 491MODULE_LICENSE("GPL");
 492