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

This commit is contained in:
Linux Build Service Account 2019-01-26 02:20:49 -08:00 committed by Gerrit - the friendly Code Review server
commit 1f37f3db6f

View file

@ -1,4 +1,4 @@
/* 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;
}