Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.15-rc6 487 lines 12 kB view raw
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_attributes[] = { 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}; 324 325static const struct attribute_group lvs_attr_group = { 326 .attrs = lvs_attributes, 327}; 328 329static void lvs_rh_work(struct work_struct *work) 330{ 331 struct lvs_rh *lvs = container_of(work, struct lvs_rh, rh_work); 332 struct usb_interface *intf = lvs->intf; 333 struct usb_device *hdev = interface_to_usbdev(intf); 334 struct usb_hcd *hcd = bus_to_hcd(hdev->bus); 335 struct usb_hub_descriptor *descriptor = &lvs->descriptor; 336 struct usb_port_status *port_status = &lvs->port_status; 337 int i, ret = 0; 338 u16 portchange; 339 340 /* Examine each root port */ 341 for (i = 1; i <= descriptor->bNbrPorts; i++) { 342 ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), 343 USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, i, 344 port_status, sizeof(*port_status), 1000); 345 if (ret < 4) 346 continue; 347 348 portchange = le16_to_cpu(port_status->wPortChange); 349 350 if (portchange & USB_PORT_STAT_C_LINK_STATE) 351 lvs_rh_clear_port_feature(hdev, i, 352 USB_PORT_FEAT_C_PORT_LINK_STATE); 353 if (portchange & USB_PORT_STAT_C_ENABLE) 354 lvs_rh_clear_port_feature(hdev, i, 355 USB_PORT_FEAT_C_ENABLE); 356 if (portchange & USB_PORT_STAT_C_RESET) 357 lvs_rh_clear_port_feature(hdev, i, 358 USB_PORT_FEAT_C_RESET); 359 if (portchange & USB_PORT_STAT_C_BH_RESET) 360 lvs_rh_clear_port_feature(hdev, i, 361 USB_PORT_FEAT_C_BH_PORT_RESET); 362 if (portchange & USB_PORT_STAT_C_CONNECTION) { 363 lvs_rh_clear_port_feature(hdev, i, 364 USB_PORT_FEAT_C_CONNECTION); 365 366 if (le16_to_cpu(port_status->wPortStatus) & 367 USB_PORT_STAT_CONNECTION) { 368 lvs->present = true; 369 lvs->portnum = i; 370 if (hcd->usb_phy) 371 usb_phy_notify_connect(hcd->usb_phy, 372 USB_SPEED_SUPER); 373 } else { 374 lvs->present = false; 375 if (hcd->usb_phy) 376 usb_phy_notify_disconnect(hcd->usb_phy, 377 USB_SPEED_SUPER); 378 } 379 break; 380 } 381 } 382 383 ret = usb_submit_urb(lvs->urb, GFP_KERNEL); 384 if (ret != 0 && ret != -ENODEV && ret != -EPERM) 385 dev_err(&intf->dev, "urb resubmit error %d\n", ret); 386} 387 388static void lvs_rh_irq(struct urb *urb) 389{ 390 struct lvs_rh *lvs = urb->context; 391 392 schedule_work(&lvs->rh_work); 393} 394 395static int lvs_rh_probe(struct usb_interface *intf, 396 const struct usb_device_id *id) 397{ 398 struct usb_device *hdev; 399 struct usb_host_interface *desc; 400 struct usb_endpoint_descriptor *endpoint; 401 struct lvs_rh *lvs; 402 unsigned int pipe; 403 int ret, maxp; 404 405 hdev = interface_to_usbdev(intf); 406 desc = intf->cur_altsetting; 407 408 ret = usb_find_int_in_endpoint(desc, &endpoint); 409 if (ret) 410 return ret; 411 412 /* valid only for SS root hub */ 413 if (hdev->descriptor.bDeviceProtocol != USB_HUB_PR_SS || hdev->parent) { 414 dev_err(&intf->dev, "Bind LVS driver with SS root Hub only\n"); 415 return -EINVAL; 416 } 417 418 lvs = devm_kzalloc(&intf->dev, sizeof(*lvs), GFP_KERNEL); 419 if (!lvs) 420 return -ENOMEM; 421 422 lvs->intf = intf; 423 usb_set_intfdata(intf, lvs); 424 425 /* how many number of ports this root hub has */ 426 ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), 427 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, 428 USB_DT_SS_HUB << 8, 0, &lvs->descriptor, 429 USB_DT_SS_HUB_SIZE, USB_CTRL_GET_TIMEOUT); 430 if (ret < (USB_DT_HUB_NONVAR_SIZE + 2)) { 431 dev_err(&hdev->dev, "wrong root hub descriptor read %d\n", ret); 432 return ret; 433 } 434 435 /* submit urb to poll interrupt endpoint */ 436 lvs->urb = usb_alloc_urb(0, GFP_KERNEL); 437 if (!lvs->urb) 438 return -ENOMEM; 439 440 INIT_WORK(&lvs->rh_work, lvs_rh_work); 441 442 ret = sysfs_create_group(&intf->dev.kobj, &lvs_attr_group); 443 if (ret < 0) { 444 dev_err(&intf->dev, "Failed to create sysfs node %d\n", ret); 445 goto free_urb; 446 } 447 448 pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress); 449 maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe)); 450 usb_fill_int_urb(lvs->urb, hdev, pipe, &lvs->buffer[0], maxp, 451 lvs_rh_irq, lvs, endpoint->bInterval); 452 453 ret = usb_submit_urb(lvs->urb, GFP_KERNEL); 454 if (ret < 0) { 455 dev_err(&intf->dev, "couldn't submit lvs urb %d\n", ret); 456 goto sysfs_remove; 457 } 458 459 return ret; 460 461sysfs_remove: 462 sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group); 463free_urb: 464 usb_free_urb(lvs->urb); 465 return ret; 466} 467 468static void lvs_rh_disconnect(struct usb_interface *intf) 469{ 470 struct lvs_rh *lvs = usb_get_intfdata(intf); 471 472 sysfs_remove_group(&intf->dev.kobj, &lvs_attr_group); 473 usb_poison_urb(lvs->urb); /* used in scheduled work */ 474 flush_work(&lvs->rh_work); 475 usb_free_urb(lvs->urb); 476} 477 478static struct usb_driver lvs_driver = { 479 .name = "lvs", 480 .probe = lvs_rh_probe, 481 .disconnect = lvs_rh_disconnect, 482}; 483 484module_usb_driver(lvs_driver); 485 486MODULE_DESCRIPTION("Link Layer Validation System Driver"); 487MODULE_LICENSE("GPL");