return ret;
 }
 
-static int hub_port_status(struct usb_hub *hub, int port1,
+int usb_hub_port_status(struct usb_hub *hub, int port1,
                u16 *status, u16 *change)
 {
        return hub_ext_port_status(hub, port1, HUB_PORT_STATUS,
                u16 portstatus, portchange;
 
                portstatus = portchange = 0;
-               status = hub_port_status(hub, port1, &portstatus, &portchange);
+               status = usb_hub_port_status(hub, port1, &portstatus, &portchange);
                if (status)
                        goto abort;
 
                                                  &portstatus, &portchange,
                                                  &ext_portstatus);
                else
-                       ret = hub_port_status(hub, port1, &portstatus,
+                       ret = usb_hub_port_status(hub, port1, &portstatus,
                                              &portchange);
                if (ret < 0)
                        return ret;
                 * If the caller hasn't explicitly requested a warm reset,
                 * double check and see if one is needed.
                 */
-               if (hub_port_status(hub, port1, &portstatus, &portchange) == 0)
+               if (usb_hub_port_status(hub, port1, &portstatus,
+                                       &portchange) == 0)
                        if (hub_port_warm_reset_required(hub, port1,
                                                        portstatus))
                                warm = true;
                         * If a USB 3.0 device migrates from reset to an error
                         * state, re-issue the warm reset.
                         */
-                       if (hub_port_status(hub, port1,
+                       if (usb_hub_port_status(hub, port1,
                                        &portstatus, &portchange) < 0)
                                goto done;
 
 }
 
 /* Check if a port is power on */
-static int port_is_power_on(struct usb_hub *hub, unsigned portstatus)
+int usb_port_is_power_on(struct usb_hub *hub, unsigned int portstatus)
 {
        int ret = 0;
 
        }
        /* Is the device still present? */
        else if (status || port_is_suspended(hub, portstatus) ||
-                       !port_is_power_on(hub, portstatus)) {
+                       !usb_port_is_power_on(hub, portstatus)) {
                if (status >= 0)
                        status = -ENODEV;
        } else if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
                if (retries--) {
                        usleep_range(200, 300);
-                       status = hub_port_status(hub, port1, &portstatus,
+                       status = usb_hub_port_status(hub, port1, &portstatus,
                                                             &portchange);
                        goto retry;
                }
                        u16 portstatus, portchange;
 
                        portstatus = portchange = 0;
-                       ret = hub_port_status(hub, port1, &portstatus,
+                       ret = usb_hub_port_status(hub, port1, &portstatus,
                                        &portchange);
 
                        dev_dbg(&port_dev->dev,
        while (delay_ms < 2000) {
                if (status || *portstatus & USB_PORT_STAT_CONNECTION)
                        break;
-               if (!port_is_power_on(hub, *portstatus)) {
+               if (!usb_port_is_power_on(hub, *portstatus)) {
                        status = -ENODEV;
                        break;
                }
                msleep(20);
                delay_ms += 20;
-               status = hub_port_status(hub, port1, portstatus, portchange);
+               status = usb_hub_port_status(hub, port1, portstatus, portchange);
        }
        dev_dbg(&udev->dev, "Waited %dms for CONNECT\n", delay_ms);
        return status;
        usb_lock_port(port_dev);
 
        /* Skip the initial Clear-Suspend step for a remote wakeup */
-       status = hub_port_status(hub, port1, &portstatus, &portchange);
+       status = usb_hub_port_status(hub, port1, &portstatus, &portchange);
        if (status == 0 && !port_is_suspended(hub, portstatus)) {
                if (portchange & USB_PORT_STAT_C_SUSPEND)
                        pm_wakeup_event(&udev->dev, 0);
                 * stop resume signaling.  Then finish the resume
                 * sequence.
                 */
-               status = hub_port_status(hub, port1, &portstatus, &portchange);
+               status = usb_hub_port_status(hub, port1, &portstatus, &portchange);
        }
 
  SuspendCleared:
                u16 portstatus, portchange;
                int status;
 
-               status = hub_port_status(hub, port1, &portstatus, &portchange);
+               status = usb_hub_port_status(hub, port1, &portstatus, &portchange);
                if (!status && portchange)
                        return 1;
        }
        struct usb_port *port_dev = hub->ports[port1 - 1];
 
        for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
-               ret = hub_port_status(hub, port1, &portstatus, &portchange);
+               ret = usb_hub_port_status(hub, port1, &portstatus, &portchange);
                if (ret < 0)
                        return ret;
 
                 * but only if the port isn't owned by someone else.
                 */
                if (hub_is_port_power_switchable(hub)
-                               && !port_is_power_on(hub, portstatus)
+                               && !usb_port_is_power_on(hub, portstatus)
                                && !port_dev->port_owner)
                        set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
 
        clear_bit(port1, hub->event_bits);
        clear_bit(port1, hub->wakeup_bits);
 
-       if (hub_port_status(hub, port1, &portstatus, &portchange) < 0)
+       if (usb_hub_port_status(hub, port1, &portstatus, &portchange) < 0)
                return;
 
        if (portchange & USB_PORT_STAT_C_CONNECTION) {
                                USB_PORT_FEAT_C_OVER_CURRENT);
                msleep(100);    /* Cool down */
                hub_power_on(hub, true);
-               hub_port_status(hub, port1, &status, &unused);
+               usb_hub_port_status(hub, port1, &status, &unused);
                if (status & USB_PORT_STAT_OVERCURRENT)
                        dev_err(&port_dev->dev, "over-current condition\n");
        }
                        u16 unused;
 
                        msleep(20);
-                       hub_port_status(hub, port1, &portstatus, &unused);
+                       usb_hub_port_status(hub, port1, &portstatus, &unused);
                        dev_dbg(&port_dev->dev, "Wait for inactive link disconnect detect\n");
                        continue;
                } else if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION)
 
 
 static const struct attribute_group *port_dev_group[];
 
+static ssize_t disable_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct usb_port *port_dev = to_usb_port(dev);
+       struct usb_device *hdev = to_usb_device(dev->parent->parent);
+       struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
+       struct usb_interface *intf = to_usb_interface(hub->intfdev);
+       int port1 = port_dev->portnum;
+       u16 portstatus, unused;
+       bool disabled;
+       int rc;
+
+       rc = usb_autopm_get_interface(intf);
+       if (rc < 0)
+               return rc;
+
+       usb_lock_device(hdev);
+       if (hub->disconnected) {
+               rc = -ENODEV;
+               goto out_hdev_lock;
+       }
+
+       usb_hub_port_status(hub, port1, &portstatus, &unused);
+       disabled = !usb_port_is_power_on(hub, portstatus);
+
+out_hdev_lock:
+       usb_unlock_device(hdev);
+       usb_autopm_put_interface(intf);
+
+       if (rc)
+               return rc;
+
+       return sysfs_emit(buf, "%s\n", disabled ? "1" : "0");
+}
+
+static ssize_t disable_store(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       struct usb_port *port_dev = to_usb_port(dev);
+       struct usb_device *hdev = to_usb_device(dev->parent->parent);
+       struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
+       struct usb_interface *intf = to_usb_interface(hub->intfdev);
+       int port1 = port_dev->portnum;
+       bool disabled;
+       int rc;
+
+       rc = strtobool(buf, &disabled);
+       if (rc)
+               return rc;
+
+       rc = usb_autopm_get_interface(intf);
+       if (rc < 0)
+               return rc;
+
+       usb_lock_device(hdev);
+       if (hub->disconnected) {
+               rc = -ENODEV;
+               goto out_hdev_lock;
+       }
+
+       if (disabled && port_dev->child)
+               usb_disconnect(&port_dev->child);
+
+       rc = usb_hub_set_port_power(hdev, hub, port1, !disabled);
+
+       if (disabled) {
+               usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
+               if (!port_dev->is_superspeed)
+                       usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
+       }
+
+       if (!rc)
+               rc = count;
+
+out_hdev_lock:
+       usb_unlock_device(hdev);
+       usb_autopm_put_interface(intf);
+
+       return rc;
+}
+static DEVICE_ATTR_RW(disable);
+
 static ssize_t location_show(struct device *dev,
                             struct device_attribute *attr, char *buf)
 {
        &dev_attr_location.attr,
        &dev_attr_quirks.attr,
        &dev_attr_over_current_count.attr,
+       &dev_attr_disable.attr,
        NULL,
 };