static void smdhsic_disconnect(struct usb_interface *intf) { int devid; struct usb_interface *smd_intf; struct str_intf_priv *intfpriv; struct usb_device *device = NULL; pr_info("%s: Called\n", __func__); intfpriv = usb_get_intfdata(intf); if (!intfpriv) { pr_err("%s: intfpriv is NULL\n", __func__); goto err_get_intfdata; } device = get_usb_device(intfpriv); devid = GET_DEVID(intfpriv->devid); pr_debug("%s : devid : %d\n", __func__, devid); smd_intf = get_usb_intf(intfpriv); if (!smd_intf) { pr_err("smd_intf is NULL\n"); goto err_get_usb_intf; } if (smd_intf != intf) { pr_err("smd_intf is not same intf\n"); goto err_mismatched_intf; } usb_driver_release_interface(get_usb_driver(intf), smd_intf); if (!device) usb_put_dev(device); pm_runtime_disable(&device->dev); if (g_usbdev.hsic) cancel_delayed_work(&g_usbdev.hsic->pm_runtime_work); switch (devid) { case FMT_DEV_ID: flush_txurb(&g_usbdev.ipc_urbq); flush_txurb(&g_usbdev.data_urbq); smdctl_request_connection_recover(true); case RAW_DEV_ID: case RFS_DEV_ID: case CMD_DEV_ID: case DOWN_DEV_ID: if (emu_discon_func[devid]) emu_discon_func[devid](g_usbdev.smd_device[devid]); else kfree(intfpriv->data); break; default: pr_warn("%s:Undefined Callback Function\n", __func__); } /* to prevent sleep at connection recover * when, usb suspend and recover routine overlap * it makes huge delay on modem reset */ wake_lock_timeout(&g_usbdev.txwake, 20*HZ); kfree(intfpriv); usb_set_intfdata(intf, NULL); g_usbdev.usbdev = NULL; g_usbdev.suspended = 0; g_usbdev.hsic = NULL; return; err_mismatched_intf: err_get_usb_intf: if (!device) usb_put_dev(device); err_get_intfdata: pr_err("release(2) : %p\n", intf); usb_driver_release_interface(get_usb_driver(intf), intf); return; }
static void smdhsic_disconnect(struct usb_interface *intf) { int devid; struct usb_interface *smd_intf; struct str_intf_priv *intfpriv; struct usb_device *device = NULL; pr_info("%s: Called\n", __func__); intfpriv = usb_get_intfdata(intf); if (!intfpriv) { pr_err("%s: intfpriv is NULL\n", __func__); goto err_get_intfdata; } device = get_usb_device(intfpriv); devid = GET_DEVID(intfpriv->devid); pr_debug("%s : devid : %d\n", __func__, devid); smd_intf = get_usb_intf(intfpriv); if (!smd_intf) { pr_err("smd_intf is NULL\n"); goto err_get_usb_intf; } if (smd_intf != intf) { pr_err("smd_intf is not same intf\n"); goto err_mismatched_intf; } usb_driver_release_interface(get_usb_driver(intf), smd_intf); if (!device) usb_put_dev(device); switch (devid) { case FMT_DEV_ID: pm_runtime_disable(&device->dev); if (g_usbdev.hsic) cancel_delayed_work(&g_usbdev.hsic->pm_runtime_work); smdctl_request_connection_recover(true); case RAW_DEV_ID: case RFS_DEV_ID: case CMD_DEV_ID: case DOWN_DEV_ID: if (emu_discon_func[devid]) emu_discon_func[devid](g_usbdev.smd_device[devid]); else kfree(intfpriv->data); break; default: pr_warn("%s:Undefined Callback Function\n", __func__); } /* Power on/off kernel-panic workaround, * if USB suspend cmd was queued in power.work before disconnect, * reset the runtime PM request value to PM_REQ_NONE */ device->dev.power.request = RPM_REQ_NONE; kfree(intfpriv); usb_set_intfdata(intf, NULL); g_usbdev.usbdev = NULL; g_usbdev.suspended = 0; g_usbdev.hsic = NULL; return; err_mismatched_intf: err_get_usb_intf: if (device) usb_put_dev(device); err_get_intfdata: pr_err("release(2) : %p\n", intf); usb_driver_release_interface(get_usb_driver(intf), intf); return; }