d288dfed6ccfee146088b189ae7fd81d5a1ee99e
[deliverable/linux.git] / drivers / usb / core / port.c
1 /*
2 * usb port device code
3 *
4 * Copyright (C) 2012 Intel Corp
5 *
6 * Author: Lan Tianyu <tianyu.lan@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 *
17 */
18
19 #include <linux/slab.h>
20 #include <linux/pm_qos.h>
21
22 #include "hub.h"
23
24 static const struct attribute_group *port_dev_group[];
25
26 static ssize_t show_port_connect_type(struct device *dev,
27 struct device_attribute *attr, char *buf)
28 {
29 struct usb_port *port_dev = to_usb_port(dev);
30 char *result;
31
32 switch (port_dev->connect_type) {
33 case USB_PORT_CONNECT_TYPE_HOT_PLUG:
34 result = "hotplug";
35 break;
36 case USB_PORT_CONNECT_TYPE_HARD_WIRED:
37 result = "hardwired";
38 break;
39 case USB_PORT_NOT_USED:
40 result = "not used";
41 break;
42 default:
43 result = "unknown";
44 break;
45 }
46
47 return sprintf(buf, "%s\n", result);
48 }
49 static DEVICE_ATTR(connect_type, S_IRUGO, show_port_connect_type,
50 NULL);
51
52 static struct attribute *port_dev_attrs[] = {
53 &dev_attr_connect_type.attr,
54 NULL,
55 };
56
57 static struct attribute_group port_dev_attr_grp = {
58 .attrs = port_dev_attrs,
59 };
60
61 static const struct attribute_group *port_dev_group[] = {
62 &port_dev_attr_grp,
63 NULL,
64 };
65
66 static void usb_port_device_release(struct device *dev)
67 {
68 struct usb_port *port_dev = to_usb_port(dev);
69
70 usb_acpi_unregister_power_resources(dev);
71 kfree(port_dev);
72 }
73
74 #ifdef CONFIG_USB_SUSPEND
75 static int usb_port_runtime_resume(struct device *dev)
76 {
77 struct usb_port *port_dev = to_usb_port(dev);
78 struct usb_device *hdev = to_usb_device(dev->parent->parent);
79 struct usb_interface *intf = to_usb_interface(dev->parent);
80 int retval;
81
82 usb_autopm_get_interface(intf);
83 retval = usb_hub_set_port_power(hdev, port_dev->portnum, true);
84 usb_autopm_put_interface(intf);
85 return retval;
86 }
87
88 static int usb_port_runtime_suspend(struct device *dev)
89 {
90 struct usb_port *port_dev = to_usb_port(dev);
91 struct usb_device *hdev = to_usb_device(dev->parent->parent);
92 struct usb_interface *intf = to_usb_interface(dev->parent);
93 int retval;
94
95 if (dev_pm_qos_flags(&port_dev->dev, PM_QOS_FLAG_NO_POWER_OFF)
96 == PM_QOS_FLAGS_ALL)
97 return -EAGAIN;
98
99 usb_autopm_get_interface(intf);
100 retval = usb_hub_set_port_power(hdev, port_dev->portnum, false);
101 usb_autopm_put_interface(intf);
102 return retval;
103 }
104 #endif
105
106 static const struct dev_pm_ops usb_port_pm_ops = {
107 #ifdef CONFIG_USB_SUSPEND
108 .runtime_suspend = usb_port_runtime_suspend,
109 .runtime_resume = usb_port_runtime_resume,
110 .runtime_idle = pm_generic_runtime_idle,
111 #endif
112 };
113
114 struct device_type usb_port_device_type = {
115 .name = "usb_port",
116 .release = usb_port_device_release,
117 .pm = &usb_port_pm_ops,
118 };
119
120 int usb_hub_create_port_device(struct usb_hub *hub, int port1)
121 {
122 struct usb_port *port_dev = NULL;
123 int retval;
124
125 port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL);
126 if (!port_dev) {
127 retval = -ENOMEM;
128 goto exit;
129 }
130
131 hub->ports[port1 - 1] = port_dev;
132 port_dev->portnum = port1;
133 port_dev->dev.parent = hub->intfdev;
134 port_dev->dev.groups = port_dev_group;
135 port_dev->dev.type = &usb_port_device_type;
136 dev_set_name(&port_dev->dev, "port%d", port1);
137
138 retval = device_register(&port_dev->dev);
139 if (retval)
140 goto error_register;
141
142 pm_runtime_set_active(&port_dev->dev);
143 pm_runtime_enable(&port_dev->dev);
144
145 retval = usb_acpi_register_power_resources(&port_dev->dev);
146 if (retval && retval != -ENODEV)
147 dev_warn(&port_dev->dev, "the port can't register its ACPI power resource.\n");
148
149 return 0;
150
151 error_register:
152 put_device(&port_dev->dev);
153 exit:
154 return retval;
155 }
156
157 void usb_hub_remove_port_device(struct usb_hub *hub,
158 int port1)
159 {
160 device_unregister(&hub->ports[port1 - 1]->dev);
161 }
162
This page took 0.034329 seconds and 4 git commands to generate.