Esempio n. 1
0
long mdm_modem_ioctl(struct file *filp, unsigned int cmd,
				unsigned long arg)
{
	int status, ret = 0;

	if (_IOC_TYPE(cmd) != CHARM_CODE) {
		pr_err("%s: invalid ioctl code\n", __func__);
		return -EINVAL;
	}

	pr_debug("%s: Entering ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
	switch (cmd) {
	case WAKE_CHARM:
		pr_info("%s: Powering on mdm\n", __func__);
#ifdef CONFIG_MDM_HSIC_PM
		request_boot_lock_set(rmnet_pm_dev);
#endif
		mdm_drv->ops->power_on_mdm_cb(mdm_drv);
		break;
	case CHECK_FOR_BOOT:
		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
			put_user(1, (unsigned long __user *) arg);
		else
			put_user(0, (unsigned long __user *) arg);
		break;
	case NORMAL_BOOT_DONE:
		pr_info("%s: check if mdm is booted up\n", __func__);
		get_user(status, (unsigned long __user *) arg);
		if (status) {
			pr_debug("%s: normal boot failed\n", __func__);
			mdm_drv->mdm_boot_status = -EIO;
		} else {
			pr_info("%s: normal boot done\n", __func__);
			mdm_drv->mdm_boot_status = 0;
		}
		mdm_drv->mdm_ready = 1;

		if (mdm_drv->ops->normal_boot_done_cb != NULL)
			mdm_drv->ops->normal_boot_done_cb(mdm_drv);

		if (!first_boot)
			complete(&mdm_boot);
		else
			first_boot = 0;

		/* If bootup succeeded, start a timer to check that the
		 * mdm2ap_status gpio goes high.
		 */
		if (!status && gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
			schedule_delayed_work(&mdm2ap_status_check_work,
				msecs_to_jiffies(MDM2AP_STATUS_TIMEOUT_MS));
		break;
	case RAM_DUMP_DONE:
		pr_info("%s: mdm done collecting RAM dumps\n", __func__);
		get_user(status, (unsigned long __user *) arg);
		if (status)
			mdm_drv->mdm_ram_dump_status = -EIO;
		else {
			pr_info("%s: ramdump collection completed\n", __func__);
			mdm_drv->mdm_ram_dump_status = 0;
			panic("CP Crash %s", mdm_read_err_report());
		}
		complete(&mdm_ram_dumps);
		break;

	case WAIT_FOR_ERROR:
		pr_debug("%s: wait for mdm error\n", __func__);
		#if 0
		ret = wait_for_completion_interruptible(&mdm_error);
		INIT_COMPLETION(mdm_error);
		#endif
		break;

	case WAIT_FOR_RESTART:
		pr_info("%s: wait for mdm to need images reloaded\n",
				__func__);
		ret = wait_for_completion_interruptible(&mdm_needs_reload);
		if (!ret)
			put_user(mdm_drv->boot_type,
					 (unsigned long __user *) arg);
		INIT_COMPLETION(mdm_needs_reload);
		break;

	case SILENT_RESET_CONTROL:
		pr_info("%s: mdm doing silent reset\n", __func__);
		mdm_drv->mdm_ram_dump_status = 0;
		complete(&mdm_ram_dumps);
		break;

	case AUTOPM_LOCK:
		get_user(status, (unsigned long __user *) arg);
		pr_info("%s: mdm autopm request[%s]\n", __func__,
						status ? "lock" : "release");
		request_autopm_lock(status);
		break;

	case GET_BOOT_PROTOCOL:
		pr_info("%s: mdm get boot protocol %d\n", __func__,
						mdm_drv->proto_is_dload);
		return mdm_drv->proto_is_dload;

	case GET_FORCE_RAMDUMP:
		get_user(status, (unsigned long __user *) arg);
		pr_info("%s: mdm get dump mode = %d\n", __func__, force_dump);
		if (status)
			mdm_force_fatal();
		else
			mdm_silent_reset();
		break;

#ifdef CONFIG_SIM_DETECT
	case GET_SIM_DETECT:
		pr_info("%s: mdm get sim detect = %d\n", __func__,
						mdm_drv->sim_state);
		return mdm_drv->sim_state;
#endif
	default:
		pr_err("%s: invalid ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
		ret = -EINVAL;
		break;
	}

	return ret;
}
static int rmnet_usb_probe(struct usb_interface *iface,
		const struct usb_device_id *prod)
{
	struct usbnet		*unet;
	struct usb_device	*udev;
	struct driver_info	*info;
	unsigned int		iface_num;
	static int		first_rmnet_iface_num = -EINVAL;
	int			status = 0;
	int			ret = 0;

	udev = interface_to_usbdev(iface);
	iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
	if (iface->num_altsetting != 1) {
		dev_err(&udev->dev, "%s invalid num_altsetting %u\n",
			__func__, iface->num_altsetting);
		status = -EINVAL;
		goto out;
	}

	info = (struct driver_info *)prod->driver_info;
	if (!test_bit(iface_num, &info->data))
		return -ENODEV;

	status = usbnet_probe(iface, prod);
	if (status < 0) {
		dev_err(&udev->dev, "usbnet_probe failed %d\n", status);
		goto out;
	}
	unet = usb_get_intfdata(iface);

	/*set rmnet operation mode to eth by default*/
	set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]);

	/*update net device*/
	rmnet_usb_setup(unet->net);

	/*create /sys/class/net/rmnet_usbx/dbg_mask*/
	status = device_create_file(&unet->net->dev, &dev_attr_dbg_mask);
	if (status)
		goto out;

	if (first_rmnet_iface_num == -EINVAL)
		first_rmnet_iface_num = iface_num;

	/*save control device intstance */
	unet->data[1] = (unsigned long)ctrl_dev	\
			[iface_num - first_rmnet_iface_num];

	status = rmnet_usb_ctrl_probe(iface, unet->status,
		(struct rmnet_ctrl_dev *)unet->data[1]);
	if (status) {
		if (status == -EPIPE) {
			ret = set_qmicm_mode(rmnet_pm_dev);
			if (ret < 0)
				goto out;
			return status;
		}
		else
			goto out;
	}

	status = rmnet_usb_data_debugfs_init(unet);
	if (status)
		dev_dbg(&udev->dev, "mode debugfs file is not available\n");

#ifdef CONFIG_MDM_HSIC_PM
	status = register_udev_to_pm_dev(rmnet_pm_dev, udev);
	if (status) {
		dev_err(&udev->dev,
			"%s: fail to register to hsic pm device\n", __func__);
		goto out;
	}
#endif
	/* allow modem to wake up suspended system */
	device_set_wakeup_enable(&udev->dev, 1);
out:
#ifdef CONFIG_MDM_HSIC_PM
	/* make reset or dump at 2nd enumeration fail */
	if (status < 0)
		mdm_force_fatal();
#endif
	return status;
}