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