1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * USB4 port device 4 * 5 * Copyright (C) 2021, Intel Corporation 6 * Author: Mika Westerberg <mika.westerberg@linux.intel.com> 7 */ 8 9 #include <linux/acpi.h> 10 #include <linux/pm_runtime.h> 11 12 #include "tb.h" 13 14 static ssize_t link_show(struct device *dev, struct device_attribute *attr, 15 char *buf) 16 { 17 struct usb4_port *usb4 = tb_to_usb4_port_device(dev); 18 struct tb_port *port = usb4->port; 19 struct tb *tb = port->sw->tb; 20 const char *link; 21 22 if (mutex_lock_interruptible(&tb->lock)) 23 return -ERESTARTSYS; 24 25 if (tb_is_upstream_port(port)) 26 link = port->sw->link_usb4 ? "usb4" : "tbt"; 27 else if (tb_port_has_remote(port)) 28 link = port->remote->sw->link_usb4 ? "usb4" : "tbt"; 29 else 30 link = "none"; 31 32 mutex_unlock(&tb->lock); 33 34 return sysfs_emit(buf, "%s\n", link); 35 } 36 static DEVICE_ATTR_RO(link); 37 38 static struct attribute *common_attrs[] = { 39 &dev_attr_link.attr, 40 NULL 41 }; 42 43 static const struct attribute_group common_group = { 44 .attrs = common_attrs, 45 }; 46 47 static const struct attribute_group *usb4_port_device_groups[] = { 48 &common_group, 49 NULL 50 }; 51 52 static void usb4_port_device_release(struct device *dev) 53 { 54 struct usb4_port *usb4 = container_of(dev, struct usb4_port, dev); 55 56 kfree(usb4); 57 } 58 59 struct device_type usb4_port_device_type = { 60 .name = "usb4_port", 61 .groups = usb4_port_device_groups, 62 .release = usb4_port_device_release, 63 }; 64 65 /** 66 * usb4_port_device_add() - Add USB4 port device 67 * @port: Lane 0 adapter port to add the USB4 port 68 * 69 * Creates and registers a USB4 port device for @port. Returns the new 70 * USB4 port device pointer or ERR_PTR() in case of error. 71 */ 72 struct usb4_port *usb4_port_device_add(struct tb_port *port) 73 { 74 struct usb4_port *usb4; 75 int ret; 76 77 usb4 = kzalloc(sizeof(*usb4), GFP_KERNEL); 78 if (!usb4) 79 return ERR_PTR(-ENOMEM); 80 81 usb4->port = port; 82 usb4->dev.type = &usb4_port_device_type; 83 usb4->dev.parent = &port->sw->dev; 84 dev_set_name(&usb4->dev, "usb4_port%d", port->port); 85 86 ret = device_register(&usb4->dev); 87 if (ret) { 88 put_device(&usb4->dev); 89 return ERR_PTR(ret); 90 } 91 92 pm_runtime_no_callbacks(&usb4->dev); 93 pm_runtime_set_active(&usb4->dev); 94 pm_runtime_enable(&usb4->dev); 95 pm_runtime_set_autosuspend_delay(&usb4->dev, TB_AUTOSUSPEND_DELAY); 96 pm_runtime_mark_last_busy(&usb4->dev); 97 pm_runtime_use_autosuspend(&usb4->dev); 98 99 return usb4; 100 } 101 102 /** 103 * usb4_port_device_remove() - Removes USB4 port device 104 * @usb4: USB4 port device 105 * 106 * Unregisters the USB4 port device from the system. The device will be 107 * released when the last reference is dropped. 108 */ 109 void usb4_port_device_remove(struct usb4_port *usb4) 110 { 111 device_unregister(&usb4->dev); 112 } 113