linux/drivers/usb/core/port.c
<<
>>
Prefs
   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
  24static const struct attribute_group *port_dev_group[];
  25
  26static 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}
  49static DEVICE_ATTR(connect_type, S_IRUGO, show_port_connect_type,
  50                NULL);
  51
  52static struct attribute *port_dev_attrs[] = {
  53        &dev_attr_connect_type.attr,
  54        NULL,
  55};
  56
  57static struct attribute_group port_dev_attr_grp = {
  58        .attrs = port_dev_attrs,
  59};
  60
  61static const struct attribute_group *port_dev_group[] = {
  62        &port_dev_attr_grp,
  63        NULL,
  64};
  65
  66static void usb_port_device_release(struct device *dev)
  67{
  68        struct usb_port *port_dev = to_usb_port(dev);
  69
  70        kfree(port_dev);
  71}
  72
  73#ifdef CONFIG_PM_RUNTIME
  74static int usb_port_runtime_resume(struct device *dev)
  75{
  76        struct usb_port *port_dev = to_usb_port(dev);
  77        struct usb_device *hdev = to_usb_device(dev->parent->parent);
  78        struct usb_interface *intf = to_usb_interface(dev->parent);
  79        struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
  80        int port1 = port_dev->portnum;
  81        int retval;
  82
  83        if (!hub)
  84                return -EINVAL;
  85
  86        usb_autopm_get_interface(intf);
  87        set_bit(port1, hub->busy_bits);
  88
  89        retval = usb_hub_set_port_power(hdev, hub, port1, true);
  90        if (port_dev->child && !retval) {
  91                /*
  92                 * Wait for usb hub port to be reconnected in order to make
  93                 * the resume procedure successful.
  94                 */
  95                retval = hub_port_debounce_be_connected(hub, port1);
  96                if (retval < 0) {
  97                        dev_dbg(&port_dev->dev, "can't get reconnection after setting port  power on, status %d\n",
  98                                        retval);
  99                        goto out;
 100                }
 101                usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
 102
 103                /* Set return value to 0 if debounce successful */
 104                retval = 0;
 105        }
 106
 107out:
 108        clear_bit(port1, hub->busy_bits);
 109        usb_autopm_put_interface(intf);
 110        return retval;
 111}
 112
 113static int usb_port_runtime_suspend(struct device *dev)
 114{
 115        struct usb_port *port_dev = to_usb_port(dev);
 116        struct usb_device *hdev = to_usb_device(dev->parent->parent);
 117        struct usb_interface *intf = to_usb_interface(dev->parent);
 118        struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
 119        int port1 = port_dev->portnum;
 120        int retval;
 121
 122        if (!hub)
 123                return -EINVAL;
 124
 125        if (dev_pm_qos_flags(&port_dev->dev, PM_QOS_FLAG_NO_POWER_OFF)
 126                        == PM_QOS_FLAGS_ALL)
 127                return -EAGAIN;
 128
 129        usb_autopm_get_interface(intf);
 130        set_bit(port1, hub->busy_bits);
 131        retval = usb_hub_set_port_power(hdev, hub, port1, false);
 132        usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
 133        usb_clear_port_feature(hdev, port1,     USB_PORT_FEAT_C_ENABLE);
 134        clear_bit(port1, hub->busy_bits);
 135        usb_autopm_put_interface(intf);
 136        return retval;
 137}
 138#endif
 139
 140static const struct dev_pm_ops usb_port_pm_ops = {
 141#ifdef CONFIG_PM_RUNTIME
 142        .runtime_suspend =      usb_port_runtime_suspend,
 143        .runtime_resume =       usb_port_runtime_resume,
 144#endif
 145};
 146
 147struct device_type usb_port_device_type = {
 148        .name =         "usb_port",
 149        .release =      usb_port_device_release,
 150        .pm =           &usb_port_pm_ops,
 151};
 152
 153int usb_hub_create_port_device(struct usb_hub *hub, int port1)
 154{
 155        struct usb_port *port_dev = NULL;
 156        int retval;
 157
 158        port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL);
 159        if (!port_dev) {
 160                retval = -ENOMEM;
 161                goto exit;
 162        }
 163
 164        hub->ports[port1 - 1] = port_dev;
 165        port_dev->portnum = port1;
 166        port_dev->power_is_on = true;
 167        port_dev->dev.parent = hub->intfdev;
 168        port_dev->dev.groups = port_dev_group;
 169        port_dev->dev.type = &usb_port_device_type;
 170        dev_set_name(&port_dev->dev, "port%d", port1);
 171
 172        retval = device_register(&port_dev->dev);
 173        if (retval)
 174                goto error_register;
 175
 176        pm_runtime_set_active(&port_dev->dev);
 177
 178        /* It would be dangerous if user space couldn't
 179         * prevent usb device from being powered off. So don't
 180         * enable port runtime pm if failed to expose port's pm qos.
 181         */
 182        if (!dev_pm_qos_expose_flags(&port_dev->dev,
 183                        PM_QOS_FLAG_NO_POWER_OFF))
 184                pm_runtime_enable(&port_dev->dev);
 185
 186        device_enable_async_suspend(&port_dev->dev);
 187        return 0;
 188
 189error_register:
 190        put_device(&port_dev->dev);
 191exit:
 192        return retval;
 193}
 194
 195void usb_hub_remove_port_device(struct usb_hub *hub,
 196                                       int port1)
 197{
 198        device_unregister(&hub->ports[port1 - 1]->dev);
 199}
 200
 201