static void if_usb_force_disconnect(struct work_struct *work) { struct usb_link_device *usb_ld = container_of(work, struct usb_link_device, disconnect_work); struct usb_device *udev = usb_ld->usbdev; if (!udev || !(&udev->dev)) return; pm_runtime_get_sync(&udev->dev); if (udev->state != USB_STATE_NOTATTACHED) { usb_force_disconnect(udev); mif_info("force disconnect by modem not responding!!\n"); } pm_runtime_put_autosuspend(&udev->dev); }
static void if_usb_force_disconnect(struct work_struct *work) { struct usb_link_device *usb_ld = container_of(work, struct usb_link_device, disconnect_work); struct usb_device *udev = usb_ld->usbdev; /* if already disconnected before run this workqueue */ if (!udev || !(&udev->dev) || !usb_ld->if_usb_connected) return; /* disconnect udev's parent if usb hub used */ if (has_hub(usb_ld)) udev = udev->parent; pm_runtime_get_sync(&udev->dev); if (udev->state != USB_STATE_NOTATTACHED) { usb_force_disconnect(udev); mif_info("force disconnect\n"); } pm_runtime_put_autosuspend(&udev->dev); }
static long link_pm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int value, err = 0; struct link_pm_data *pm_data = file->private_data; mif_info("cmd: 0x%08x\n", cmd); switch (cmd) { case IOCTL_LINK_CONTROL_ACTIVE: if (copy_from_user(&value, (const void __user *)arg, sizeof(int))) return -EFAULT; gpio_set_value(pm_data->gpio_link_active, value); break; case IOCTL_LINK_GET_HOSTWAKE: return !gpio_get_value(pm_data->gpio_link_hostwake); case IOCTL_LINK_CONNECTED: return pm_data->usb_ld->if_usb_connected; case IOCTL_LINK_PORT_ON: /* hub only */ /* ignore cp host wakeup irq, set the hub_init_lock when AP try CP off and release hub_init_lock when CP boot done */ pm_data->hub_init_lock = 0; if (pm_data->root_hub) { pm_runtime_resume(pm_data->root_hub); pm_runtime_forbid(pm_data->root_hub->parent); } if (pm_data->port_enable) { err = pm_data->port_enable(2, 1); if (err < 0) { mif_err("hub on fail err=%d\n", err); goto exit; } pm_data->hub_status = HUB_STATE_RESUMMING; } break; case IOCTL_LINK_PORT_OFF: /* hub only */ if (pm_data->usb_ld->if_usb_connected) { struct usb_device *udev = pm_data->usb_ld->usbdev->parent; pm_runtime_get_sync(&udev->dev); if (udev->state != USB_STATE_NOTATTACHED) { usb_force_disconnect(udev); pr_info("force disconnect maybe cp-reset!!\n"); } pm_runtime_put_autosuspend(&udev->dev); } err = link_pm_hub_standby(pm_data); if (err < 0) { mif_err("usb3503 active fail\n"); goto exit; } pm_data->hub_init_lock = 1; pm_data->hub_handshake_done = 0; break; default: break; } exit: return err; }
static long link_pm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int value, err = 0; struct task_struct *task = get_current(); struct link_pm_data *pm_data = file->private_data; struct usb_link_device *usb_ld = pm_data->usb_ld; char taskname[TASK_COMM_LEN]; pr_info("mif: %s: 0x%08x\n", __func__, cmd); switch (cmd) { case IOCTL_LINK_CONTROL_ACTIVE: if (copy_from_user(&value, (const void __user *)arg, sizeof(int))) return -EFAULT; gpio_set_value(pm_data->gpio_link_active, value); break; case IOCTL_LINK_GET_HOSTWAKE: return !gpio_get_value(pm_data->gpio_link_hostwake); case IOCTL_LINK_CONNECTED: return pm_data->usb_ld->if_usb_connected; case IOCTL_LINK_PORT_ON: /* hub only */ /* ignore cp host wakeup irq, set the hub_init_lock when AP try CP off and release hub_init_lock when CP boot done */ pm_data->hub_init_lock = 0; if (pm_data->root_hub) { pm_runtime_resume(pm_data->root_hub); pm_runtime_forbid(pm_data->root_hub->parent); } if (pm_data->port_enable) { err = pm_data->port_enable(2, 1); if (err < 0) { pr_err("mif: %s: hub on fail err=%d\n", __func__, err); goto exit; } pm_data->hub_status = HUB_STATE_RESUMMING; } break; case IOCTL_LINK_PORT_OFF: /* hub only */ if (pm_data->usb_ld->if_usb_connected) { struct usb_device *udev = pm_data->usb_ld->usbdev->parent; pm_runtime_get_sync(&udev->dev); if (udev->state != USB_STATE_NOTATTACHED) { usb_force_disconnect(udev); pr_info("force disconnect maybe cp-reset!!\n"); } pm_runtime_put_autosuspend(&udev->dev); } err = link_pm_hub_standby(pm_data); if (err < 0) { pr_err("mif: %s: usb3503 active fail\n", __func__); goto exit; } pm_data->hub_init_lock = 1; pm_data->hub_handshake_done = 0; break; case IOCTL_LINK_BLOCK_AUTOSUSPEND: /* block autosuspend forever */ mif_info("blocked autosuspend by `%s(%d)'\n", get_task_comm(taskname, task), task->pid); pm_data->block_autosuspend = true; if (usb_ld->usbdev) pm_runtime_forbid(&usb_ld->usbdev->dev); else { mif_err("Block autosuspend failed\n"); err = -ENODEV; } break; case IOCTL_LINK_ENABLE_AUTOSUSPEND: /* Enable autosuspend */ mif_info("autosuspend enabled by `%s(%d)'\n", get_task_comm(taskname, task), task->pid); pm_data->block_autosuspend = false; if (usb_ld->usbdev) pm_runtime_allow(&usb_ld->usbdev->dev); else { mif_err("Enable autosuspend failed\n"); err = -ENODEV; } break; default: break; } exit: return err; }