Loading drivers/pci/controller/pci-msm.c +92 −3 Original line number Diff line number Diff line Loading @@ -559,6 +559,8 @@ enum msm_pcie_drv_cmds { MSM_PCIE_DRV_CMD_DISABLE = 0xc0000001, MSM_PCIE_DRV_CMD_ENABLE_L1SS_SLEEP = 0xc0000005, MSM_PCIE_DRV_CMD_DISABLE_L1SS_SLEEP = 0xc0000006, MSM_PCIE_DRV_CMD_DISABLE_PC = 0xc0000007, MSM_PCIE_DRV_CMD_ENABLE_PC = 0xc0000008, }; /* DRV IPC message type */ Loading Loading @@ -596,6 +598,8 @@ struct msm_pcie_drv_info { struct msm_pcie_drv_msg drv_disable; /* payload to request back */ struct msm_pcie_drv_msg drv_enable_l1ss_sleep; /* enable l1ss sleep */ struct msm_pcie_drv_msg drv_disable_l1ss_sleep; /* disable l1ss sleep */ struct msm_pcie_drv_msg drv_enable_pc; /* enable drv pc */ struct msm_pcie_drv_msg drv_disable_pc; /* disable drv pc */ int dev_id; u16 seq; u16 reply_seq; Loading Loading @@ -741,6 +745,12 @@ struct msm_pcie_dev_t { struct msm_pcie_device_info pcidev_table[MAX_DEVICE_NUM]; struct msm_pcie_drv_info *drv_info; struct work_struct drv_enable_pc_work; struct work_struct drv_disable_pc_work; /* cache drv pc req from RC client, by default drv pc is enabled */ int drv_disable_pc_vote; struct mutex drv_pc_lock; void (*rumi_init)(struct msm_pcie_dev_t *pcie_dev); }; Loading @@ -752,6 +762,9 @@ struct msm_root_dev_t { static u32 msm_pcie_keep_resources_on; /* high prio WQ */ static struct workqueue_struct *mpcie_wq; /* debugfs values */ static u32 rc_sel = BIT(0); static u32 base_sel; Loading Loading @@ -938,6 +951,8 @@ static const struct msm_pcie_irq_info_t msm_pcie_irq_info[MSM_PCIE_MAX_IRQ] = { {"int_global_int", 0} }; static int msm_pcie_drv_send_rpmsg(struct msm_pcie_dev_t *pcie_dev, struct msm_pcie_drv_msg *msg); static void msm_pcie_config_sid(struct msm_pcie_dev_t *dev); static void msm_pcie_config_l0s_disable_all(struct msm_pcie_dev_t *dev, struct pci_bus *bus); Loading Loading @@ -5405,6 +5420,12 @@ static int msm_pcie_setup_drv(struct msm_pcie_dev_t *pcie_dev, drv_info->dev_id, MSM_PCIE_DRV_CMD_DISABLE_L1SS_SLEEP); msm_pcie_setup_drv_msg(&drv_info->drv_enable_pc, drv_info->dev_id, MSM_PCIE_DRV_CMD_ENABLE_PC); msm_pcie_setup_drv_msg(&drv_info->drv_disable_pc, drv_info->dev_id, MSM_PCIE_DRV_CMD_DISABLE_PC); init_completion(&drv_info->completion); drv_info->timeout_ms = IPC_TIMEOUT_MS; pcie_dev->drv_info = drv_info; Loading Loading @@ -6125,8 +6146,13 @@ static void msm_pcie_drv_notify_client(struct pcie_drv_sta *pcie_drv, if (drv_info->ep_connected) { msm_pcie_notify_client(pcie_dev, event); if (event & MSM_PCIE_EVENT_DRV_DISCONNECT) if (event & MSM_PCIE_EVENT_DRV_DISCONNECT) { mutex_lock(&pcie_dev->drv_pc_lock); drv_info->ep_connected = false; cancel_work_sync(&pcie_dev->drv_disable_pc_work); cancel_work_sync(&pcie_dev->drv_enable_pc_work); mutex_unlock(&pcie_dev->drv_pc_lock); } } } } Loading Loading @@ -6259,6 +6285,22 @@ static void msm_pcie_early_notifier(void *data) msm_pcie_drv_notify_client(pcie_drv, MSM_PCIE_EVENT_WAKEUP); }; static void msm_pcie_drv_disable_pc(struct work_struct *w) { struct msm_pcie_dev_t *pcie_dev = container_of(w, struct msm_pcie_dev_t, drv_disable_pc_work); msm_pcie_drv_send_rpmsg(pcie_dev, &pcie_dev->drv_info->drv_disable_pc); } static void msm_pcie_drv_enable_pc(struct work_struct *w) { struct msm_pcie_dev_t *pcie_dev = container_of(w, struct msm_pcie_dev_t, drv_enable_pc_work); msm_pcie_drv_send_rpmsg(pcie_dev, &pcie_dev->drv_info->drv_enable_pc); } static void msm_pcie_drv_connect_worker(struct work_struct *work) { struct pcie_drv_sta *pcie_drv = container_of(work, struct pcie_drv_sta, Loading Loading @@ -6289,7 +6331,13 @@ static void msm_pcie_drv_connect_worker(struct work_struct *work) msm_pcie_notify_client(pcie_dev, MSM_PCIE_EVENT_DRV_CONNECT); mutex_lock(&pcie_dev->drv_pc_lock); drv_info->ep_connected = true; if (pcie_dev->drv_disable_pc_vote) queue_work(mpcie_wq, &pcie_dev->drv_disable_pc_work); mutex_unlock(&pcie_dev->drv_pc_lock); } subsys_register_early_notifier("adsp", PCIE_DRV_LAYER_NOTIF, Loading Loading @@ -6344,10 +6392,15 @@ static int __init pcie_init(void) mutex_init(&msm_pcie_dev[i].setup_lock); mutex_init(&msm_pcie_dev[i].recovery_lock); mutex_init(&msm_pcie_dev[i].aspm_lock); mutex_init(&msm_pcie_dev[i].drv_pc_lock); spin_lock_init(&msm_pcie_dev[i].wakeup_lock); spin_lock_init(&msm_pcie_dev[i].irq_lock); msm_pcie_dev[i].drv_ready = false; msm_pcie_dev[i].l23_rdy_poll_timeout = L23_READY_POLL_TIMEOUT; INIT_WORK(&msm_pcie_dev[i].drv_disable_pc_work, msm_pcie_drv_disable_pc); INIT_WORK(&msm_pcie_dev[i].drv_enable_pc_work, msm_pcie_drv_enable_pc); } for (i = 0; i < MAX_RC_NUM * MAX_DEVICE_NUM; i++) { msm_pcie_dev_tbl[i].bdf = 0; Loading @@ -6370,6 +6423,11 @@ static int __init pcie_init(void) if (ret) return ret; mpcie_wq = alloc_ordered_workqueue("mpcie_wq", WQ_MEM_RECLAIM | WQ_HIGHPRI); if (!mpcie_wq) return -ENOMEM; INIT_WORK(&pcie_drv.drv_connect, msm_pcie_drv_connect_worker); pcie_drv.msm_pcie_dev = msm_pcie_dev; Loading @@ -6379,6 +6437,8 @@ static int __init pcie_init(void) ret); ret = platform_driver_register(&msm_pcie_driver); if (ret) destroy_workqueue(mpcie_wq); return ret; } Loading @@ -6389,6 +6449,9 @@ static void __exit pcie_exit(void) pr_info("PCIe: %s\n", __func__); if (mpcie_wq) destroy_workqueue(mpcie_wq); platform_driver_unregister(&msm_pcie_driver); msm_pcie_debugfs_exit(); Loading Loading @@ -6881,8 +6944,6 @@ static int msm_pcie_drv_suspend(struct msm_pcie_dev_t *pcie_dev, /* disable global irq - no more linkdown/aer detection */ disable_irq(pcie_dev->irq[MSM_PCIE_INT_GLOBAL_INT].num); drv_info->drv_enable.pkt.dword[2] = options & MSM_PCIE_CONFIG_NO_DRV_PC; ret = msm_pcie_drv_send_rpmsg(pcie_dev, &drv_info->drv_enable); if (ret) { ret = -EBUSY; Loading Loading @@ -6986,6 +7047,10 @@ int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user, PCIE_DBG(pcie_dev, "PCIe: RC%d: DRV: user requests for DRV suspend\n", rc_idx); /* make sure disable pc is done before enabling drv */ flush_work(&pcie_dev->drv_disable_pc_work); ret = msm_pcie_drv_suspend(pcie_dev, options); break; case MSM_PCIE_SUSPEND: Loading Loading @@ -7099,6 +7164,30 @@ int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user, msm_pcie_handle_linkdown(pcie_dev); spin_unlock_irqrestore(&msm_pcie_dev[rc_idx].irq_lock, flags); break; case MSM_PCIE_DRV_PC_CTRL: PCIE_DBG(&msm_pcie_dev[rc_idx], "User of RC%d requests handling drv pc options %u.\n", rc_idx, options); mutex_lock(&pcie_dev->drv_pc_lock); pcie_dev->drv_disable_pc_vote = options & MSM_PCIE_CONFIG_NO_DRV_PC; if (!pcie_dev->drv_info || !pcie_dev->drv_info->ep_connected) { mutex_unlock(&pcie_dev->drv_pc_lock); break; } if (pcie_dev->drv_disable_pc_vote) { queue_work(mpcie_wq, &pcie_dev->drv_disable_pc_work); } else { queue_work(mpcie_wq, &pcie_dev->drv_enable_pc_work); /* make sure enable pc happens asap */ flush_work(&pcie_dev->drv_enable_pc_work); } mutex_unlock(&pcie_dev->drv_pc_lock); break; default: PCIE_ERR(&msm_pcie_dev[rc_idx], "PCIe: RC%d: unsupported pm operation:%d.\n", Loading include/linux/msm_pcie.h +1 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ enum msm_pcie_pm_opt { MSM_PCIE_DISABLE_PC, MSM_PCIE_ENABLE_PC, MSM_PCIE_HANDLE_LINKDOWN, MSM_PCIE_DRV_PC_CTRL, }; enum msm_pcie_event { Loading Loading
drivers/pci/controller/pci-msm.c +92 −3 Original line number Diff line number Diff line Loading @@ -559,6 +559,8 @@ enum msm_pcie_drv_cmds { MSM_PCIE_DRV_CMD_DISABLE = 0xc0000001, MSM_PCIE_DRV_CMD_ENABLE_L1SS_SLEEP = 0xc0000005, MSM_PCIE_DRV_CMD_DISABLE_L1SS_SLEEP = 0xc0000006, MSM_PCIE_DRV_CMD_DISABLE_PC = 0xc0000007, MSM_PCIE_DRV_CMD_ENABLE_PC = 0xc0000008, }; /* DRV IPC message type */ Loading Loading @@ -596,6 +598,8 @@ struct msm_pcie_drv_info { struct msm_pcie_drv_msg drv_disable; /* payload to request back */ struct msm_pcie_drv_msg drv_enable_l1ss_sleep; /* enable l1ss sleep */ struct msm_pcie_drv_msg drv_disable_l1ss_sleep; /* disable l1ss sleep */ struct msm_pcie_drv_msg drv_enable_pc; /* enable drv pc */ struct msm_pcie_drv_msg drv_disable_pc; /* disable drv pc */ int dev_id; u16 seq; u16 reply_seq; Loading Loading @@ -741,6 +745,12 @@ struct msm_pcie_dev_t { struct msm_pcie_device_info pcidev_table[MAX_DEVICE_NUM]; struct msm_pcie_drv_info *drv_info; struct work_struct drv_enable_pc_work; struct work_struct drv_disable_pc_work; /* cache drv pc req from RC client, by default drv pc is enabled */ int drv_disable_pc_vote; struct mutex drv_pc_lock; void (*rumi_init)(struct msm_pcie_dev_t *pcie_dev); }; Loading @@ -752,6 +762,9 @@ struct msm_root_dev_t { static u32 msm_pcie_keep_resources_on; /* high prio WQ */ static struct workqueue_struct *mpcie_wq; /* debugfs values */ static u32 rc_sel = BIT(0); static u32 base_sel; Loading Loading @@ -938,6 +951,8 @@ static const struct msm_pcie_irq_info_t msm_pcie_irq_info[MSM_PCIE_MAX_IRQ] = { {"int_global_int", 0} }; static int msm_pcie_drv_send_rpmsg(struct msm_pcie_dev_t *pcie_dev, struct msm_pcie_drv_msg *msg); static void msm_pcie_config_sid(struct msm_pcie_dev_t *dev); static void msm_pcie_config_l0s_disable_all(struct msm_pcie_dev_t *dev, struct pci_bus *bus); Loading Loading @@ -5405,6 +5420,12 @@ static int msm_pcie_setup_drv(struct msm_pcie_dev_t *pcie_dev, drv_info->dev_id, MSM_PCIE_DRV_CMD_DISABLE_L1SS_SLEEP); msm_pcie_setup_drv_msg(&drv_info->drv_enable_pc, drv_info->dev_id, MSM_PCIE_DRV_CMD_ENABLE_PC); msm_pcie_setup_drv_msg(&drv_info->drv_disable_pc, drv_info->dev_id, MSM_PCIE_DRV_CMD_DISABLE_PC); init_completion(&drv_info->completion); drv_info->timeout_ms = IPC_TIMEOUT_MS; pcie_dev->drv_info = drv_info; Loading Loading @@ -6125,8 +6146,13 @@ static void msm_pcie_drv_notify_client(struct pcie_drv_sta *pcie_drv, if (drv_info->ep_connected) { msm_pcie_notify_client(pcie_dev, event); if (event & MSM_PCIE_EVENT_DRV_DISCONNECT) if (event & MSM_PCIE_EVENT_DRV_DISCONNECT) { mutex_lock(&pcie_dev->drv_pc_lock); drv_info->ep_connected = false; cancel_work_sync(&pcie_dev->drv_disable_pc_work); cancel_work_sync(&pcie_dev->drv_enable_pc_work); mutex_unlock(&pcie_dev->drv_pc_lock); } } } } Loading Loading @@ -6259,6 +6285,22 @@ static void msm_pcie_early_notifier(void *data) msm_pcie_drv_notify_client(pcie_drv, MSM_PCIE_EVENT_WAKEUP); }; static void msm_pcie_drv_disable_pc(struct work_struct *w) { struct msm_pcie_dev_t *pcie_dev = container_of(w, struct msm_pcie_dev_t, drv_disable_pc_work); msm_pcie_drv_send_rpmsg(pcie_dev, &pcie_dev->drv_info->drv_disable_pc); } static void msm_pcie_drv_enable_pc(struct work_struct *w) { struct msm_pcie_dev_t *pcie_dev = container_of(w, struct msm_pcie_dev_t, drv_enable_pc_work); msm_pcie_drv_send_rpmsg(pcie_dev, &pcie_dev->drv_info->drv_enable_pc); } static void msm_pcie_drv_connect_worker(struct work_struct *work) { struct pcie_drv_sta *pcie_drv = container_of(work, struct pcie_drv_sta, Loading Loading @@ -6289,7 +6331,13 @@ static void msm_pcie_drv_connect_worker(struct work_struct *work) msm_pcie_notify_client(pcie_dev, MSM_PCIE_EVENT_DRV_CONNECT); mutex_lock(&pcie_dev->drv_pc_lock); drv_info->ep_connected = true; if (pcie_dev->drv_disable_pc_vote) queue_work(mpcie_wq, &pcie_dev->drv_disable_pc_work); mutex_unlock(&pcie_dev->drv_pc_lock); } subsys_register_early_notifier("adsp", PCIE_DRV_LAYER_NOTIF, Loading Loading @@ -6344,10 +6392,15 @@ static int __init pcie_init(void) mutex_init(&msm_pcie_dev[i].setup_lock); mutex_init(&msm_pcie_dev[i].recovery_lock); mutex_init(&msm_pcie_dev[i].aspm_lock); mutex_init(&msm_pcie_dev[i].drv_pc_lock); spin_lock_init(&msm_pcie_dev[i].wakeup_lock); spin_lock_init(&msm_pcie_dev[i].irq_lock); msm_pcie_dev[i].drv_ready = false; msm_pcie_dev[i].l23_rdy_poll_timeout = L23_READY_POLL_TIMEOUT; INIT_WORK(&msm_pcie_dev[i].drv_disable_pc_work, msm_pcie_drv_disable_pc); INIT_WORK(&msm_pcie_dev[i].drv_enable_pc_work, msm_pcie_drv_enable_pc); } for (i = 0; i < MAX_RC_NUM * MAX_DEVICE_NUM; i++) { msm_pcie_dev_tbl[i].bdf = 0; Loading @@ -6370,6 +6423,11 @@ static int __init pcie_init(void) if (ret) return ret; mpcie_wq = alloc_ordered_workqueue("mpcie_wq", WQ_MEM_RECLAIM | WQ_HIGHPRI); if (!mpcie_wq) return -ENOMEM; INIT_WORK(&pcie_drv.drv_connect, msm_pcie_drv_connect_worker); pcie_drv.msm_pcie_dev = msm_pcie_dev; Loading @@ -6379,6 +6437,8 @@ static int __init pcie_init(void) ret); ret = platform_driver_register(&msm_pcie_driver); if (ret) destroy_workqueue(mpcie_wq); return ret; } Loading @@ -6389,6 +6449,9 @@ static void __exit pcie_exit(void) pr_info("PCIe: %s\n", __func__); if (mpcie_wq) destroy_workqueue(mpcie_wq); platform_driver_unregister(&msm_pcie_driver); msm_pcie_debugfs_exit(); Loading Loading @@ -6881,8 +6944,6 @@ static int msm_pcie_drv_suspend(struct msm_pcie_dev_t *pcie_dev, /* disable global irq - no more linkdown/aer detection */ disable_irq(pcie_dev->irq[MSM_PCIE_INT_GLOBAL_INT].num); drv_info->drv_enable.pkt.dword[2] = options & MSM_PCIE_CONFIG_NO_DRV_PC; ret = msm_pcie_drv_send_rpmsg(pcie_dev, &drv_info->drv_enable); if (ret) { ret = -EBUSY; Loading Loading @@ -6986,6 +7047,10 @@ int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user, PCIE_DBG(pcie_dev, "PCIe: RC%d: DRV: user requests for DRV suspend\n", rc_idx); /* make sure disable pc is done before enabling drv */ flush_work(&pcie_dev->drv_disable_pc_work); ret = msm_pcie_drv_suspend(pcie_dev, options); break; case MSM_PCIE_SUSPEND: Loading Loading @@ -7099,6 +7164,30 @@ int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user, msm_pcie_handle_linkdown(pcie_dev); spin_unlock_irqrestore(&msm_pcie_dev[rc_idx].irq_lock, flags); break; case MSM_PCIE_DRV_PC_CTRL: PCIE_DBG(&msm_pcie_dev[rc_idx], "User of RC%d requests handling drv pc options %u.\n", rc_idx, options); mutex_lock(&pcie_dev->drv_pc_lock); pcie_dev->drv_disable_pc_vote = options & MSM_PCIE_CONFIG_NO_DRV_PC; if (!pcie_dev->drv_info || !pcie_dev->drv_info->ep_connected) { mutex_unlock(&pcie_dev->drv_pc_lock); break; } if (pcie_dev->drv_disable_pc_vote) { queue_work(mpcie_wq, &pcie_dev->drv_disable_pc_work); } else { queue_work(mpcie_wq, &pcie_dev->drv_enable_pc_work); /* make sure enable pc happens asap */ flush_work(&pcie_dev->drv_enable_pc_work); } mutex_unlock(&pcie_dev->drv_pc_lock); break; default: PCIE_ERR(&msm_pcie_dev[rc_idx], "PCIe: RC%d: unsupported pm operation:%d.\n", Loading
include/linux/msm_pcie.h +1 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ enum msm_pcie_pm_opt { MSM_PCIE_DISABLE_PC, MSM_PCIE_ENABLE_PC, MSM_PCIE_HANDLE_LINKDOWN, MSM_PCIE_DRV_PC_CTRL, }; enum msm_pcie_event { Loading