cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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");