int smdhsic_reset_resume(struct usb_interface *intf) { unsigned int devid; struct str_intf_priv *intfpriv; struct device *dev = &g_usbdev.usbdev->dev; pr_debug("%s: Called\n", __func__); if (!g_usbdev.suspended) return 0; intfpriv = usb_get_intfdata(intf); devid = GET_DEVID(intfpriv->devid); if (!usb_runtime_pm_ap_initiated_L2 && atomic_read(&dev->power.usage_count) == 1) pm_runtime_get_noresume(dev); smdhsic_resume(intf); if (devid == CMD_DEV_ID) { g_usbdev.hsic->dpm_suspending = false; pr_debug("%s : dpm suspending set to false\n", __func__); } return 0; }
static int smdhsic_resume(struct usb_interface *interface) { int r = 0; unsigned int devid; struct str_smdipc *smdipc; struct str_smdrfs *smdrfs; struct str_smdcmd *smdcmd; struct str_smdraw *smdraw; struct str_intf_priv *intfpriv; intfpriv = usb_get_intfdata(interface); devid = GET_DEVID(intfpriv->devid); switch (devid) { case FMT_DEV_ID: smdipc = intfpriv->data; if (!smdipc->suspended) return 0; wake_lock(&smdipc->wakelock); g_usbdev.suspended--; smdipc->suspended = 0; r = smdipc_resume(smdipc); pr_debug("SMDHSIC RES FMT_DEV(%d)\n", g_usbdev.suspended); break; case RAW_DEV_ID: smdraw = intfpriv->data; if (!smdraw->suspended) return 0; wake_lock(&smdraw->wakelock); smdraw->suspended = 0; g_usbdev.suspended--; r = smdraw_resume(smdraw); pr_debug("SMDHSIC RES RAW_DEV(%d)\n", g_usbdev.suspended); break; case RFS_DEV_ID: smdrfs = intfpriv->data; if (!smdrfs->suspended) return 0; wake_lock(&smdrfs->wakelock); smdrfs->suspended = 0; g_usbdev.suspended--; r = smdrfs_resume(smdrfs); pr_debug("SMDHSIC RES RFS_DEV(%d)\n", g_usbdev.suspended); break; case CMD_DEV_ID: smdcmd = intfpriv->data; if (!smdcmd->suspended) return 0; wake_lock(&smdcmd->wakelock); smdcmd->suspended = 0; g_usbdev.suspended--; r = smdcmd_resume(smdcmd); pr_debug("SMDHSIC RES CMD_DEV(%d)\n", g_usbdev.suspended); smdctl_set_pm_status(PM_STATUS_L0); default: break; } return r; }
static struct usb_interface *get_usb_intf(struct str_intf_priv *intfpriv) { unsigned int devid = intfpriv->devid; struct str_smdipc *smdipc; struct str_smd_down *smddown; struct str_smdrfs *smdrfs; struct str_smdcmd *smdcmd; struct str_smdraw *smdraw; if (devid & ID_PRI) { struct str_hsic *hsic = intfpriv->data; return hsic->intf; } switch (GET_DEVID(devid)) { case FMT_DEV_ID: smdipc = (struct str_smdipc *)intfpriv->data; return smdipc->hsic.intf; case RAW_DEV_ID: smdraw = (struct str_smdraw *)intfpriv->data; return smdraw->hsic.intf; case RFS_DEV_ID: smdrfs = (struct str_smdrfs *)intfpriv->data; return smdrfs->hsic.intf; case CMD_DEV_ID: smdcmd = (struct str_smdcmd *)intfpriv->data; return smdcmd->hsic.intf; case DOWN_DEV_ID: smddown = (struct str_smd_down *)intfpriv->data; return smddown->hsic.intf; default: pr_err("%s:Undefined DEVID: %d\n", __func__, GET_DEVID(devid)); } return NULL; }
static int smdhsic_suspend(struct usb_interface *interface, pm_message_t message) { int r = 0; unsigned int devid; struct str_smdipc *smdipc; struct str_smdrfs *smdrfs; struct str_smdcmd *smdcmd; struct str_smdraw *smdraw; struct str_intf_priv *intfpriv; intfpriv = usb_get_intfdata(interface); devid = GET_DEVID(intfpriv->devid); switch (devid) { case FMT_DEV_ID: smdipc = intfpriv->data; if (smdipc->suspended) return 0; r = smdipc_suspend(smdipc); pr_debug("SMDHSIC SUS FMT_DEV(%d)\n", g_usbdev.suspended); wake_unlock(&smdipc->wakelock); smdipc->suspended = 1; g_usbdev.suspended++; smdctl_set_pm_status(PM_STATUS_L2); break; case RAW_DEV_ID: smdraw = intfpriv->data; if (smdraw->suspended) return 0; r = smdraw_suspend(smdraw); pr_debug("SMDHSIC SUS RAW_DEV(%d)\n", g_usbdev.suspended); wake_unlock(&smdraw->wakelock); smdraw->suspended = 1; g_usbdev.suspended++; break; case RFS_DEV_ID: smdrfs = intfpriv->data; if (smdrfs->suspended) return 0; r = smdrfs_suspend(smdrfs); pr_debug("SMDHSIC SUS RFS_DEV(%d)\n", g_usbdev.suspended); wake_unlock(&smdrfs->wakelock); smdrfs->suspended = 1; g_usbdev.suspended++; break; case CMD_DEV_ID: smdcmd = intfpriv->data; if (smdcmd->suspended) return 0; r = smdcmd_suspend(smdcmd); pr_debug("SMDHSIC SUS CMD_DEV(%d)\n", g_usbdev.suspended); wake_unlock(&smdcmd->wakelock); smdcmd->suspended = 1; g_usbdev.suspended++; default: /* fall through */ break; } return r; }
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; }