Merge "usb: misc: diag_ipc_bridge: Move dev cleanup to delete function"
This commit is contained in:
commit
1f37f3db6f
1 changed files with 59 additions and 46 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue