Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9626c8ce authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "Usb: f_gsi: Add uevent support for connect/disconnect events"

parents c04ce9f5 6851e8cc
Loading
Loading
Loading
Loading
+77 −1
Original line number Original line Diff line number Diff line
@@ -1741,6 +1741,15 @@ static unsigned int gsi_xfer_bitrate(struct usb_gadget *g)
		return 19 * 64 * 1 * 1000 * 8;
		return 19 * 64 * 1 * 1000 * 8;
}
}


static void gsi_uevent_work(struct work_struct *w)
{
	struct gsi_ctrl_port *c_port =
			container_of(w, struct gsi_ctrl_port, uevent_work);

	if (c_port->dev)
		kobject_uevent(&c_port->dev->kobj, KOBJ_CHANGE);
}

static int gsi_function_ctrl_port_init(struct f_gsi *gsi)
static int gsi_function_ctrl_port_init(struct f_gsi *gsi)
{
{
	int ret;
	int ret;
@@ -1760,6 +1769,9 @@ static int gsi_function_ctrl_port_init(struct f_gsi *gsi)
	spin_lock_init(&gsi->c_port.lock);
	spin_lock_init(&gsi->c_port.lock);


	init_waitqueue_head(&gsi->c_port.read_wq);
	init_waitqueue_head(&gsi->c_port.read_wq);
	INIT_WORK(&gsi->c_port.uevent_work, gsi_uevent_work);
	gsi->c_port.dev = NULL;
	gsi->c_port.uevent_wq = NULL;


	if (gsi->prot_id == IPA_USB_RMNET)
	if (gsi->prot_id == IPA_USB_RMNET)
		strlcat(gsi->c_port.name, GSI_RMNET_CTRL_NAME, sz);
		strlcat(gsi->c_port.name, GSI_RMNET_CTRL_NAME, sz);
@@ -1775,6 +1787,10 @@ static int gsi_function_ctrl_port_init(struct f_gsi *gsi)
	if (!ctrl_dev_create)
	if (!ctrl_dev_create)
		return 0;
		return 0;


	gsi->c_port.uevent_wq = alloc_workqueue(gsi->c_port.name,
						WQ_UNBOUND | WQ_MEM_RECLAIM |
						WQ_FREEZABLE, 1);

	minor = ida_simple_get(&gsi_ida, 0, MAX_CDEV_INSTANCES, GFP_KERNEL);
	minor = ida_simple_get(&gsi_ida, 0, MAX_CDEV_INSTANCES, GFP_KERNEL);
	if (minor < 0) {
	if (minor < 0) {
		pr_err("%s: No more minor numbers left! rc:%d\n", __func__,
		pr_err("%s: No more minor numbers left! rc:%d\n", __func__,
@@ -1790,7 +1806,7 @@ static int gsi_function_ctrl_port_init(struct f_gsi *gsi)
		goto err_cdev_add;
		goto err_cdev_add;
	}
	}


	dev = device_create(gsi_class, NULL, MKDEV(major, minor), NULL,
	dev = device_create(gsi_class, NULL, MKDEV(major, minor), &gsi->c_port,
			gsi->c_port.name);
			gsi->c_port.name);
	if (IS_ERR(dev)) {
	if (IS_ERR(dev)) {
		log_event_err("%s: device_create failed for (%s)\n", __func__,
		log_event_err("%s: device_create failed for (%s)\n", __func__,
@@ -1799,6 +1815,8 @@ static int gsi_function_ctrl_port_init(struct f_gsi *gsi)
		goto err_create_dev;
		goto err_create_dev;
	}
	}


	gsi->c_port.dev = dev;

	return 0;
	return 0;


err_create_dev:
err_create_dev:
@@ -2329,6 +2347,10 @@ gsi_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
			gsi->rmnet_dtr_status = line_state;
			gsi->rmnet_dtr_status = line_state;
		log_event_dbg("%s: USB_CDC_REQ_SET_CONTROL_LINE_STATE DTR:%d\n",
		log_event_dbg("%s: USB_CDC_REQ_SET_CONTROL_LINE_STATE DTR:%d\n",
						__func__, line_state);
						__func__, line_state);
		if (gsi->c_port.uevent_wq)
			queue_work(gsi->c_port.uevent_wq,
					&gsi->c_port.uevent_work);

		gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
		gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
		value = 0;
		value = 0;
		break;
		break;
@@ -2563,6 +2585,9 @@ static int gsi_set_alt(struct usb_function *f, unsigned int intf,
			gsi->prot_id == IPA_USB_MBIM)
			gsi->prot_id == IPA_USB_MBIM)
		gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
		gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);


	if (gsi->c_port.uevent_wq)
		queue_work(gsi->c_port.uevent_wq, &gsi->c_port.uevent_work);

	return ret;
	return ret;


notify_ep_disable:
notify_ep_disable:
@@ -2595,6 +2620,10 @@ static void gsi_disable(struct usb_function *f)
	}
	}


	gsi_ctrl_clear_cpkt_queues(gsi, false);
	gsi_ctrl_clear_cpkt_queues(gsi, false);

	if (gsi->c_port.uevent_wq)
		queue_work(gsi->c_port.uevent_wq, &gsi->c_port.uevent_work);

	/* send 0 len pkt to qti/qbi/gps to notify state change */
	/* send 0 len pkt to qti/qbi/gps to notify state change */
	gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
	gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
	gsi->c_port.notify_req_queued = false;
	gsi->c_port.notify_req_queued = false;
@@ -3754,11 +3783,22 @@ static void gsi_inst_clean(struct gsi_opts *opts)
{
{
	if (opts->gsi->c_port.cdev.dev) {
	if (opts->gsi->c_port.cdev.dev) {
		struct cdev *cdev = &opts->gsi->c_port.cdev;
		struct cdev *cdev = &opts->gsi->c_port.cdev;
		struct f_gsi *gsi = opts->gsi;
		int minor = MINOR(cdev->dev);
		int minor = MINOR(cdev->dev);


		if (gsi->c_port.dev)
			dev_set_drvdata(gsi->c_port.dev, NULL);

		if (gsi->c_port.uevent_wq) {
			cancel_work_sync(&gsi->c_port.uevent_work);
			destroy_workqueue(gsi->c_port.uevent_wq);
			gsi->c_port.uevent_wq = NULL;
		}

		device_destroy(gsi_class, cdev->dev);
		device_destroy(gsi_class, cdev->dev);
		cdev_del(cdev);
		cdev_del(cdev);
		cdev->dev = 0;
		cdev->dev = 0;
		gsi->c_port.dev = NULL;
		ida_simple_remove(&gsi_ida, minor);
		ida_simple_remove(&gsi_ida, minor);
	}
	}


@@ -3910,6 +3950,41 @@ DECLARE_USB_FUNCTION(gsi, gsi_alloc_inst, gsi_alloc);
MODULE_LICENSE("GPL v2");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("GSI function driver");
MODULE_DESCRIPTION("GSI function driver");


static int usb_gsi_uevent(struct device *dev, struct kobj_uevent_env *env)
{
	struct gsi_ctrl_port *c_port = dev_get_drvdata(dev);
	struct f_gsi *gsi;
	char *str = "undefined";

	if (!c_port) {
		dev_dbg(dev, "%s: gsi is not initialized\n", __func__);
		add_uevent_var(env, "STATE=%s", str);
		return 0;
	}

	gsi = c_port_to_gsi(c_port);

	switch (gsi->prot_id) {
	case IPA_USB_RMNET:
		str = gsi->rmnet_dtr_status ? "connected" : "disconnected";
		break;
	case IPA_USB_MBIM:
	case IPA_USB_DIAG:
	case IPA_USB_GPS:
		str = atomic_read(&gsi->connected) ?
					"connected" : "disconnected";
		break;
	default:
		return 0;
	}

	add_uevent_var(env, "STATE=%s", str);

	log_event_dbg("%s:STATE=%s\n", c_port->name, str);

	return 0;
}

static int fgsi_init(void)
static int fgsi_init(void)
{
{
	int i;
	int i;
@@ -3933,6 +4008,7 @@ static int fgsi_init(void)
		pr_err("%s: class_create() failed:%d\n", __func__, ret);
		pr_err("%s: class_create() failed:%d\n", __func__, ret);
		return ret;
		return ret;
	}
	}
	gsi_class->dev_uevent = usb_gsi_uevent;


	ret = alloc_chrdev_region(&dev, 0, MAX_CDEV_INSTANCES, "gsi_usb");
	ret = alloc_chrdev_region(&dev, 0, MAX_CDEV_INSTANCES, "gsi_usb");
	if (ret) {
	if (ret) {
+4 −0
Original line number Original line Diff line number Diff line
@@ -240,6 +240,10 @@ struct gsi_ctrl_port {
	unsigned int modem_to_host;
	unsigned int modem_to_host;
	unsigned int cpkt_drop_cnt;
	unsigned int cpkt_drop_cnt;
	unsigned int get_encap_cnt;
	unsigned int get_encap_cnt;

	struct device *dev;
	struct work_struct uevent_work;
	struct workqueue_struct *uevent_wq;
};
};


struct gsi_data_port {
struct gsi_data_port {