Loading drivers/usb/misc/diag_ipc_bridge.c +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 Loading @@ -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> Loading Loading @@ -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; Loading Loading @@ -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); Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; } Loading @@ -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; } Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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); Loading Loading @@ -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; } Loading @@ -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); Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } } Loading @@ -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); } Loading Loading @@ -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 Loading
drivers/usb/misc/diag_ipc_bridge.c +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 Loading @@ -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> Loading Loading @@ -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; Loading Loading @@ -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); Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; } Loading @@ -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; } Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading @@ -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); Loading Loading @@ -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; } Loading @@ -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); Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } } Loading @@ -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); } Loading Loading @@ -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