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

Commit 1f37f3db authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: misc: diag_ipc_bridge: Move dev cleanup to delete function"

parents 4163adf2 64287585
Loading
Loading
Loading
Loading
+59 −46
Original line number Diff line number Diff line
/* Copyright (c) 2011-2015, 2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2015, 2018-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -10,9 +10,6 @@
 * GNU General Public License for more details.
 */

/* add additional information to our printk's */
#define pr_fmt(fmt) "%s: " fmt "\n", __func__

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
@@ -81,31 +78,32 @@ int diag_bridge_open(int id, struct diag_bridge_ops *ops)
	struct diag_bridge	*dev;

	if (id < 0 || id >= MAX_BRIDGE_DEVS) {
		pr_err("Invalid device ID");
		pr_err("%s: Invalid device ID\n", __func__);
		return -ENODEV;
	}

	dev = __dev[id];
	if (!dev) {
		pr_err("dev is null");
		pr_err("%s: dev is null\n", __func__);
		return -ENODEV;
	}

	if (dev->ops) {
		pr_err("bridge already opened");
		pr_err("%s: bridge already opened\n", __func__);
		return -EALREADY;
	}

	mutex_lock(&dev->ifc_mutex);
	if (dev->opened) {
		mutex_unlock(&dev->ifc_mutex);
		pr_err("Bridge already opened");
		pr_err("%s: Bridge already opened\n", __func__);
		return -EBUSY;
	}

	dev->opened = true;
	mutex_unlock(&dev->ifc_mutex);

	dev_dbg(&dev->ifc->dev, "%s\n", __func__);
	dev->ops = ops;
	dev->err = 0;

@@ -133,8 +131,12 @@ static int ipc_bridge_open(struct platform_device *pdev)
static void diag_bridge_delete(struct kref *kref)
{
	struct diag_bridge *dev = container_of(kref, struct diag_bridge, kref);
	struct usb_interface *ifc = dev->ifc;
	int id = dev->id;

	dev_dbg(&dev->ifc->dev, "%s\n", __func__);
	usb_set_intfdata(ifc, NULL);
	usb_put_intf(ifc);
	usb_put_dev(dev->udev);
	__dev[id] = 0;
	kfree(dev);
@@ -145,32 +147,32 @@ void diag_bridge_close(int id)
	struct diag_bridge	*dev;

	if (id < 0 || id >= MAX_BRIDGE_DEVS) {
		pr_err("Invalid device ID");
		pr_err("%s: Invalid device ID\n", __func__);
		return;
	}

	dev = __dev[id];
	if (!dev) {
		pr_err("dev is null");
		pr_err("%s: dev is null\n", __func__);
		return;
	}

	if (id == DIAG_BRIDGE && !dev->ops) {
		pr_err("can't close bridge that was not open");
		pr_err("%s: can't close bridge that was not open\n", __func__);
		return;
	}

	mutex_lock(&dev->ifc_mutex);
	if (!dev->opened) {
		mutex_unlock(&dev->ifc_mutex);
		pr_err("Bridge not opened");
		pr_err("%s: Bridge not opened\n", __func__);
		return;
	}

	dev->opened = false;
	mutex_unlock(&dev->ifc_mutex);

	dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
	dev_dbg(&dev->ifc->dev, "%s\n", __func__);

	usb_kill_anchored_urbs(&dev->submitted);
	dev->ops = 0;
@@ -230,32 +232,33 @@ int diag_bridge_read(int id, char *data, int size)
	int			ret;

	if (id < 0 || id >= MAX_BRIDGE_DEVS) {
		pr_err("Invalid device ID");
		pr_err("%s: Invalid device ID\n", __func__);
		return -ENODEV;
	}

	pr_debug("reading %d bytes", size);
	pr_debug("%s: reading %d bytes\n", __func__, size);

	dev = __dev[id];
	if (!dev) {
		pr_err("device is disconnected");
		pr_err("%s: device is disconnected\n", __func__);
		return -ENODEV;
	}

	mutex_lock(&dev->read_mutex);
	if (!dev->ifc) {
		pr_err("%s: device is disconnected\n", __func__);
		ret = -ENODEV;
		goto error;
	}

	if (id == DIAG_BRIDGE && !dev->ops) {
		pr_err("bridge is not open");
		pr_err("%s: bridge is not open\n", __func__);
		ret = -ENODEV;
		goto error;
	}

	if (!size) {
		dev_dbg(&dev->ifc->dev, "invalid size:%d\n", size);
		dev_err(&dev->ifc->dev, "invalid size:%d\n", size);
		dev->drop_count++;
		ret = -EINVAL;
		goto error;
@@ -263,6 +266,8 @@ int diag_bridge_read(int id, char *data, int size)

	/* if there was a previous unrecoverable error, just quit */
	if (id == DIAG_BRIDGE && dev->err) {
		pr_err("%s: EPROTO error occurred, or device disconnected\n",
								__func__);
		ret = -ENODEV;
		goto error;
	}
@@ -271,14 +276,15 @@ int diag_bridge_read(int id, char *data, int size)

	urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!urb) {
		dev_dbg(&dev->ifc->dev, "unable to allocate urb\n");
		dev_err(&dev->ifc->dev, "unable to allocate urb\n");
		ret = -ENOMEM;
		goto put_error;
	}

	ret = usb_autopm_get_interface(dev->ifc);
	if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
		pr_err_ratelimited("read: autopm_get failed:%d", ret);
		pr_err_ratelimited("%s: read: autopm_get failed:%d\n",
							__func__, ret);
		goto free_error;
	}

@@ -297,13 +303,16 @@ int diag_bridge_read(int id, char *data, int size)

	ret = usb_submit_urb(urb, GFP_KERNEL);
	if (ret) {
		pr_err_ratelimited("submitting urb failed err:%d", ret);
		pr_err_ratelimited("%s: submitting urb failed err:%d\n",
							__func__, ret);
		dev->pending_reads--;
		usb_unanchor_urb(urb);
		usb_autopm_put_interface(dev->ifc);
		goto free_error;
	}

	usb_autopm_put_interface(dev->ifc);

	if (id == IPC_BRIDGE) {
		wait_for_completion(&dev->read_done);
		ret = dev->read_result;
@@ -344,7 +353,7 @@ static void diag_bridge_write_cb(struct urb *urb)
	struct diag_bridge	*dev = urb->context;
	struct diag_bridge_ops	*cbs = dev->ops;

	dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
	dev_dbg(&dev->ifc->dev, "%s\n", __func__);

	usb_autopm_put_interface_async(dev->ifc);

@@ -381,26 +390,27 @@ int diag_bridge_write(int id, char *data, int size)
	int			ret;

	if (id < 0 || id >= MAX_BRIDGE_DEVS) {
		pr_err("Invalid device ID");
		pr_err("%s: Invalid device ID\n", __func__);
		return -ENODEV;
	}

	pr_debug("writing %d bytes", size);
	pr_debug("%s: writing %d bytes\n", __func__, size);

	dev = __dev[id];
	if (!dev) {
		pr_err("device is disconnected");
		pr_err("%s: device is disconnected\n", __func__);
		return -ENODEV;
	}

	mutex_lock(&dev->write_mutex);
	if (!dev->ifc) {
		pr_err("%s: device is disconnected\n", __func__);
		ret = -ENODEV;
		goto error;
	}

	if (id == DIAG_BRIDGE && !dev->ops) {
		pr_err("bridge is not open");
		pr_err("%s: bridge is not open\n", __func__);
		ret = -ENODEV;
		goto error;
	}
@@ -413,6 +423,8 @@ int diag_bridge_write(int id, char *data, int size)

	/* if there was a previous unrecoverable error, just quit */
	if (id == DIAG_BRIDGE && dev->err) {
		pr_err("%s: EPROTO error occurred, or device disconnected\n",
								__func__);
		ret = -ENODEV;
		goto error;
	}
@@ -428,7 +440,8 @@ int diag_bridge_write(int id, char *data, int size)

	ret = usb_autopm_get_interface(dev->ifc);
	if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
		pr_err_ratelimited("write: autopm_get failed:%d", ret);
		pr_err_ratelimited("%s: write: autopm_get failed:%d\n",
							__func__, ret);
		goto free_error;
	}

@@ -441,7 +454,8 @@ int diag_bridge_write(int id, char *data, int size)

	ret = usb_submit_urb(urb, GFP_KERNEL);
	if (ret) {
		pr_err_ratelimited("submitting urb failed err:%d", ret);
		pr_err_ratelimited("%s: submitting urb failed err:%d\n",
							__func__, ret);
		dev->pending_writes--;
		usb_unanchor_urb(urb);
		usb_autopm_put_interface(dev->ifc);
@@ -584,15 +598,17 @@ diag_bridge_probe(struct usb_interface *ifc, const struct usb_device_id *id)
	struct usb_endpoint_descriptor	*ep_desc;
	int				i, devid, ret = -ENOMEM;

	pr_debug("id:%lu", id->driver_info);
	pr_debug("%s: id:%lu\n", __func__, id->driver_info);

	devid = id->driver_info & 0xFF;
	if (devid < 0 || devid >= MAX_BRIDGE_DEVS)
	if (devid < 0 || devid >= MAX_BRIDGE_DEVS) {
		pr_err("%s: Invalid device ID\n", __func__);
		return -ENODEV;
	}

	/* already probed? */
	if (__dev[devid]) {
		pr_err("Diag device already probed");
		pr_err("%s: Diag device already probed\n", __func__);
		return -ENODEV;
	}

@@ -604,7 +620,7 @@ diag_bridge_probe(struct usb_interface *ifc, const struct usb_device_id *id)
	dev->id = devid;

	dev->udev = usb_get_dev(interface_to_usbdev(ifc));
	dev->ifc = ifc;
	dev->ifc = usb_get_intf(ifc);
	kref_init(&dev->kref);
	mutex_init(&dev->ifc_mutex);
	mutex_init(&dev->read_mutex);
@@ -629,7 +645,8 @@ diag_bridge_probe(struct usb_interface *ifc, const struct usb_device_id *id)
	}

	if (!(dev->in_epAddr && dev->out_epAddr)) {
		pr_err("could not find bulk in and bulk out endpoints");
		pr_err("%s: could not find bulk in and bulk out endpoints\n",
								__func__);
		ret = -ENODEV;
		goto error;
	}
@@ -640,14 +657,16 @@ diag_bridge_probe(struct usb_interface *ifc, const struct usb_device_id *id)
		dev->pdev = platform_device_register_simple("diag_bridge",
								devid, NULL, 0);
		if (IS_ERR(dev->pdev)) {
			pr_err("unable to allocate platform device");
			pr_err("%s: unable to allocate platform device\n",
								__func__);
			ret = PTR_ERR(dev->pdev);
			goto error;
		}
	} else {
		dev->pdev = platform_device_alloc("ipc_bridge", -1);
		if (!dev->pdev) {
			pr_err("unable to allocate platform device");
			pr_err("%s: unable to allocate platform device\n",
								__func__);
			ret = -ENOMEM;
			goto error;
		}
@@ -655,13 +674,13 @@ diag_bridge_probe(struct usb_interface *ifc, const struct usb_device_id *id)
		ret = platform_device_add_data(dev->pdev, &ipc_bridge_pdata,
				sizeof(struct ipc_bridge_platform_data));
		if (ret) {
			pr_err("fail to add pdata");
			pr_err("%s: fail to add pdata\n", __func__);
			goto put_pdev;
		}

		ret = platform_device_add(dev->pdev);
		if (ret) {
			pr_err("fail to add pdev");
			pr_err("%s: fail to add pdev\n", __func__);
			goto put_pdev;
		}
	}
@@ -687,17 +706,11 @@ static void diag_bridge_disconnect(struct usb_interface *ifc)
{
	struct diag_bridge	*dev = usb_get_intfdata(ifc);

	dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
	dev_dbg(&dev->ifc->dev, "%s\n", __func__);

	platform_device_unregister(dev->pdev);
	diag_bridge_debugfs_cleanup();
	mutex_lock(&dev->ifc_mutex);
	dev->ifc = NULL;
	mutex_unlock(&dev->ifc_mutex);
	usb_set_intfdata(ifc, NULL);
	mutex_destroy(&dev->write_mutex);
	mutex_destroy(&dev->read_mutex);
	mutex_destroy(&dev->ifc_mutex);
	dev->err = -ENODEV;
	kref_put(&dev->kref, diag_bridge_delete);
}

@@ -815,7 +828,7 @@ static int __init diag_bridge_init(void)

	ret = usb_register(&diag_bridge_driver);
	if (ret) {
		pr_err("unable to register diag driver");
		pr_err("%s: unable to register diag driver\n", __func__);
		return ret;
	}