Пример #1
0
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);
}
Пример #2
0
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;
}