diff --git a/drivers/pci/controller/pci-msm.c b/drivers/pci/controller/pci-msm.c index 5cf831e71439..d4537de21c46 100644 --- a/drivers/pci/controller/pci-msm.c +++ b/drivers/pci/controller/pci-msm.c @@ -575,6 +575,8 @@ struct msm_pcie_device_info { enum msm_pcie_drv_cmds { MSM_PCIE_DRV_CMD_ENABLE = 0xc0000000, MSM_PCIE_DRV_CMD_DISABLE = 0xc0000001, + MSM_PCIE_DRV_CMD_ENABLE_L1SS_SLEEP = 0xc0000005, + MSM_PCIE_DRV_CMD_DISABLE_L1SS_SLEEP = 0xc0000006, }; /* DRV IPC message type */ @@ -610,6 +612,8 @@ struct msm_pcie_drv_info { bool ep_connected; /* drv supports only one endpoint (no switch) */ struct msm_pcie_drv_msg drv_enable; /* hand off payload */ 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 */ int dev_id; u16 seq; u16 reply_seq; @@ -5548,13 +5552,26 @@ static void msm_pcie_check_l1ss_support_all(struct msm_pcie_dev_t *dev) pci_walk_bus(dev->dev->bus, msm_pcie_check_l1ss_support, dev); } +static void msm_pcie_setup_drv_msg(struct msm_pcie_drv_msg *msg, u32 dev_id, + enum msm_pcie_drv_cmds cmd) +{ + struct msm_pcie_drv_tre *pkt = &msg->pkt; + struct msm_pcie_drv_header *hdr = &msg->hdr; + + hdr->major_ver = MSM_PCIE_DRV_MAJOR_VERSION; + hdr->minor_ver = MSM_PCIE_DRV_MINOR_VERSION; + hdr->msg_id = MSM_PCIE_DRV_MSG_ID_CMD; + hdr->payload_size = sizeof(*pkt); + hdr->dev_id = dev_id; + + pkt->dword[0] = cmd; + pkt->dword[1] = hdr->dev_id; +} + static int msm_pcie_setup_drv(struct msm_pcie_dev_t *pcie_dev, struct device_node *of_node) { struct msm_pcie_drv_info *drv_info; - struct msm_pcie_drv_msg *msg; - struct msm_pcie_drv_tre *pkt; - struct msm_pcie_drv_header *hdr; int ret; drv_info = devm_kzalloc(&pcie_dev->pdev->dev, sizeof(*drv_info), @@ -5572,31 +5589,21 @@ static int msm_pcie_setup_drv(struct msm_pcie_dev_t *pcie_dev, drv_info->dev_id = pcie_dev->rc_idx; - /* cache frequent command for communication */ - msg = &drv_info->drv_enable; - pkt = &msg->pkt; - hdr = &msg->hdr; - hdr->major_ver = MSM_PCIE_DRV_MAJOR_VERSION; - hdr->minor_ver = MSM_PCIE_DRV_MINOR_VERSION; - hdr->msg_id = MSM_PCIE_DRV_MSG_ID_CMD; - hdr->payload_size = sizeof(*pkt); - hdr->dev_id = drv_info->dev_id; + msm_pcie_setup_drv_msg(&drv_info->drv_enable, drv_info->dev_id, + MSM_PCIE_DRV_CMD_ENABLE); - pkt->dword[0] = MSM_PCIE_DRV_CMD_ENABLE; - pkt->dword[1] = hdr->dev_id; - pkt->dword[2] = drv_info->l1ss_timeout_us / 1000; + msm_pcie_setup_drv_msg(&drv_info->drv_disable, drv_info->dev_id, + MSM_PCIE_DRV_CMD_DISABLE); - msg = &drv_info->drv_disable; - pkt = &msg->pkt; - hdr = &msg->hdr; - hdr->major_ver = MSM_PCIE_DRV_MAJOR_VERSION; - hdr->minor_ver = MSM_PCIE_DRV_MINOR_VERSION; - hdr->msg_id = MSM_PCIE_DRV_MSG_ID_CMD; - hdr->payload_size = sizeof(*pkt); - hdr->dev_id = drv_info->dev_id; + msm_pcie_setup_drv_msg(&drv_info->drv_enable_l1ss_sleep, + drv_info->dev_id, + MSM_PCIE_DRV_CMD_ENABLE_L1SS_SLEEP); + drv_info->drv_enable_l1ss_sleep.pkt.dword[2] = + drv_info->l1ss_timeout_us / 1000; - pkt->dword[0] = MSM_PCIE_DRV_CMD_DISABLE; - pkt->dword[1] = hdr->dev_id; + msm_pcie_setup_drv_msg(&drv_info->drv_disable_l1ss_sleep, + drv_info->dev_id, + MSM_PCIE_DRV_CMD_DISABLE_L1SS_SLEEP); init_completion(&drv_info->completion); drv_info->timeout_ms = IPC_TIMEOUT_MS; @@ -6825,11 +6832,50 @@ static void msm_pcie_fixup_resume_early(struct pci_dev *dev) DECLARE_PCI_FIXUP_RESUME_EARLY(PCIE_VENDOR_ID_QCOM, PCI_ANY_ID, msm_pcie_fixup_resume_early); +static int msm_pcie_drv_send_rpmsg(struct msm_pcie_dev_t *pcie_dev, + struct rpmsg_device *rpdev, + struct msm_pcie_drv_msg *msg) +{ + struct msm_pcie_drv_info *drv_info = pcie_dev->drv_info; + int ret; + + reinit_completion(&drv_info->completion); + + drv_info->reply_seq = drv_info->seq++; + msg->hdr.seq = drv_info->reply_seq; + + if (unlikely(drv_info->seq == MSM_PCIE_DRV_SEQ_RESV)) + drv_info->seq = 0; + + PCIE_DBG(pcie_dev, "PCIe: RC%d: DRV: sending rpmsg: command: 0x%x\n", + pcie_dev->rc_idx, msg->pkt.dword[0]); + + ret = rpmsg_trysend(rpdev->ept, msg, sizeof(*msg)); + if (ret) { + PCIE_ERR(pcie_dev, "PCIe: RC%d: DRV: failed to send rpmsg\n", + pcie_dev->rc_idx); + return ret; + } + + ret = wait_for_completion_timeout(&drv_info->completion, + msecs_to_jiffies(drv_info->timeout_ms)); + if (!ret) { + PCIE_ERR(pcie_dev, + "PCIe: RC%d: DRV: completion timeout for rpmsg\n", + pcie_dev->rc_idx); + return -ETIMEDOUT; + } + + PCIE_DBG(pcie_dev, "PCIe: RC%d: DRV: rpmsg successfully sent\n", + pcie_dev->rc_idx); + + return 0; +} + static int msm_pcie_drv_resume(struct msm_pcie_dev_t *pcie_dev) { struct rpmsg_device *rpdev = pcie_drv.rpdev; struct msm_pcie_drv_info *drv_info = pcie_dev->drv_info; - struct msm_pcie_drv_msg *drv_disable = &drv_info->drv_disable; struct msm_pcie_clk_info_t *clk_info; u32 current_link_speed; int ret, i; @@ -6837,6 +6883,11 @@ static int msm_pcie_drv_resume(struct msm_pcie_dev_t *pcie_dev) mutex_lock(&pcie_dev->recovery_lock); mutex_lock(&pcie_dev->setup_lock); + /* if rpdev is NULL then DRV subsystem is powered down */ + if (rpdev) + msm_pcie_drv_send_rpmsg(pcie_dev, rpdev, + &drv_info->drv_disable_l1ss_sleep); + msm_pcie_vreg_init(pcie_dev); regulator_enable(pcie_dev->gdsc); @@ -6861,30 +6912,9 @@ static int msm_pcie_drv_resume(struct msm_pcie_dev_t *pcie_dev) clk_prepare_enable(clk_info->hdl); /* if rpdev is NULL then DRV subsystem is powered down */ - if (rpdev) { - reinit_completion(&drv_info->completion); - - drv_info->reply_seq = drv_info->seq++; - drv_disable->hdr.seq = drv_info->reply_seq; - - if (unlikely(drv_info->seq == MSM_PCIE_DRV_SEQ_RESV)) - drv_info->seq = 0; - - ret = rpmsg_trysend(rpdev->ept, drv_disable, - sizeof(*drv_disable)); - if (!ret) { - ret = wait_for_completion_timeout(&drv_info->completion, - msecs_to_jiffies(drv_info->timeout_ms)); - if (!ret) - PCIE_ERR(pcie_dev, - "PCIe: RC%d: DRV: completion timeout for rpmsg\n", - pcie_dev->rc_idx); - } else { - PCIE_ERR(pcie_dev, - "PCIe: RC%d: DRV: failed to send rpmsg\n", - pcie_dev->rc_idx); - } - } + if (rpdev) + msm_pcie_drv_send_rpmsg(pcie_dev, rpdev, + &drv_info->drv_disable); /* scale CX and rate change based on current GEN speed */ current_link_speed = readl_relaxed(pcie_dev->dm_core + @@ -6921,8 +6951,6 @@ static int msm_pcie_drv_suspend(struct msm_pcie_dev_t *pcie_dev, { struct rpmsg_device *rpdev = pcie_drv.rpdev; struct msm_pcie_drv_info *drv_info = pcie_dev->drv_info; - struct msm_pcie_drv_msg *drv_enable = &drv_info->drv_enable; - struct msm_pcie_drv_tre *pkt = &drv_enable->pkt; struct msm_pcie_clk_info_t *clk_info; int ret, i; @@ -6940,36 +6968,12 @@ static int msm_pcie_drv_suspend(struct msm_pcie_dev_t *pcie_dev, } mutex_lock(&pcie_dev->recovery_lock); - reinit_completion(&drv_info->completion); /* disable global irq - no more linkdown/aer detection */ disable_irq(pcie_dev->irq[MSM_PCIE_INT_GLOBAL_INT].num); - if (options & MSM_PCIE_CONFIG_NO_L1SS_TO) - pkt->dword[2] = 0; - else - pkt->dword[2] = drv_info->l1ss_timeout_us / 1000; - - drv_info->reply_seq = drv_info->seq++; - drv_enable->hdr.seq = drv_info->reply_seq; - - if (unlikely(drv_info->seq == MSM_PCIE_DRV_SEQ_RESV)) - drv_info->seq = 0; - - ret = rpmsg_trysend(rpdev->ept, drv_enable, sizeof(*drv_enable)); + ret = msm_pcie_drv_send_rpmsg(pcie_dev, rpdev, &drv_info->drv_enable); if (ret) { - PCIE_ERR(pcie_dev, "PCIe: RC%d: DRV: failed to send rpmsg\n", - pcie_dev->rc_idx); - ret = -EBUSY; - goto out; - } - - ret = wait_for_completion_timeout(&drv_info->completion, - msecs_to_jiffies(drv_info->timeout_ms)); - if (!ret) { - PCIE_ERR(pcie_dev, - "PCIe: RC%d: DRV: completion timeout for rpmsg\n", - pcie_dev->rc_idx); ret = -EBUSY; goto out; } @@ -7007,6 +7011,11 @@ static int msm_pcie_drv_suspend(struct msm_pcie_dev_t *pcie_dev, msm_pcie_vreg_deinit(pcie_dev); + /* enable L1ss sleep if client allows it */ + if (!(options & MSM_PCIE_CONFIG_NO_L1SS_TO)) + msm_pcie_drv_send_rpmsg(pcie_dev, rpdev, + &drv_info->drv_enable_l1ss_sleep); + mutex_unlock(&pcie_dev->setup_lock); mutex_unlock(&pcie_dev->recovery_lock);