Loading drivers/platform/msm/ep_pcie/ep_pcie_com.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -340,10 +340,13 @@ struct ep_pcie_dev_t { bool l23_ready; bool l23_ready; bool l1ss_enabled; bool l1ss_enabled; struct ep_pcie_msi_config msi_cfg; struct ep_pcie_msi_config msi_cfg; bool no_notify; bool client_ready; struct ep_pcie_register_event *event_reg; struct ep_pcie_register_event *event_reg; struct work_struct handle_perst_work; struct work_struct handle_perst_work; struct work_struct handle_bme_work; struct work_struct handle_bme_work; struct work_struct handle_d3cold_work; }; }; extern struct ep_pcie_dev_t ep_pcie_dev; extern struct ep_pcie_dev_t ep_pcie_dev; Loading drivers/platform/msm/ep_pcie/ep_pcie_core.c +62 −7 Original line number Original line Diff line number Diff line Loading @@ -1060,6 +1060,10 @@ static void ep_pcie_release_resources(struct ep_pcie_dev_t *dev) static void ep_pcie_enumeration_complete(struct ep_pcie_dev_t *dev) static void ep_pcie_enumeration_complete(struct ep_pcie_dev_t *dev) { { unsigned long irqsave_flags; spin_lock_irqsave(&dev->isr_lock, irqsave_flags); dev->enumerated = true; dev->enumerated = true; dev->link_status = EP_PCIE_LINK_ENABLED; dev->link_status = EP_PCIE_LINK_ENABLED; Loading @@ -1086,7 +1090,14 @@ static void ep_pcie_enumeration_complete(struct ep_pcie_dev_t *dev) "PCIe V%d: register driver for device 0x%x.\n", "PCIe V%d: register driver for device 0x%x.\n", ep_pcie_dev.rev, hw_drv.device_id); ep_pcie_dev.rev, hw_drv.device_id); ep_pcie_register_drv(&hw_drv); ep_pcie_register_drv(&hw_drv); if (!dev->no_notify) ep_pcie_notify_event(dev, EP_PCIE_EVENT_LINKUP); ep_pcie_notify_event(dev, EP_PCIE_EVENT_LINKUP); else EP_PCIE_DBG(dev, "PCIe V%d: do not notify client about linkup.\n", dev->rev); spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags); } } int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) Loading Loading @@ -1584,7 +1595,13 @@ static irqreturn_t ep_pcie_handle_dstate_change_irq(int irq, void *data) "PCIe V%d: No. %ld change to D3 state.\n", "PCIe V%d: No. %ld change to D3 state.\n", dev->rev, dev->d3_counter); dev->rev, dev->d3_counter); ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, 0, BIT(1)); ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, 0, BIT(1)); if (dev->enumerated) ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_D3_HOT); ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_D3_HOT); else EP_PCIE_DBG(dev, "PCIe V%d: do not notify client about this D3 hot event since enumeration by HLOS is not done yet.\n", dev->rev); } else if (dstate == 0) { } else if (dstate == 0) { dev->l23_ready = false; dev->l23_ready = false; dev->d0_counter++; dev->d0_counter++; Loading Loading @@ -1648,9 +1665,25 @@ static void handle_perst_func(struct work_struct *work) struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t, struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t, handle_perst_work); handle_perst_work); EP_PCIE_DBG(dev, "PCIe V%d: Start enumeration due to PERST deassertion.\n", dev->rev); ep_pcie_enumeration(dev); ep_pcie_enumeration(dev); } } static void handle_d3cold_func(struct work_struct *work) { struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t, handle_d3cold_work); EP_PCIE_DBG(dev, "PCIe V%d: shutdown PCIe link due to PERST assertion before BME is set.\n", dev->rev); ep_pcie_core_disable_endpoint(); dev->no_notify = false; } static void handle_bme_func(struct work_struct *work) static void handle_bme_func(struct work_struct *work) { { struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t *dev = container_of(work, Loading @@ -1673,10 +1706,14 @@ static irqreturn_t ep_pcie_handle_perst_irq(int irq, void *data) EP_PCIE_DBG(dev, EP_PCIE_DBG(dev, "PCIe V%d: PCIe is not enumerated yet; PERST is %sasserted.\n", "PCIe V%d: PCIe is not enumerated yet; PERST is %sasserted.\n", dev->rev, perst ? "de" : ""); dev->rev, perst ? "de" : ""); if ((!dev->perst_enum) || !perst) if (perst) { goto out; /* start work for link enumeration with the host side */ /* start work for link enumeration with the host side */ schedule_work(&dev->handle_perst_work); schedule_work(&dev->handle_perst_work); } else { dev->no_notify = true; /* shutdown the link if the link is already on */ schedule_work(&dev->handle_d3cold_work); } goto out; goto out; } } Loading @@ -1694,7 +1731,16 @@ static irqreturn_t ep_pcie_handle_perst_irq(int irq, void *data) EP_PCIE_DBG(dev, EP_PCIE_DBG(dev, "PCIe V%d: No. %ld PERST assertion.\n", "PCIe V%d: No. %ld PERST assertion.\n", dev->rev, dev->perst_ast_counter); dev->rev, dev->perst_ast_counter); if (dev->client_ready) { ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_D3_COLD); ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_D3_COLD); } else { dev->no_notify = true; EP_PCIE_DBG(dev, "PCIe V%d: Client driver is not ready when this PERST assertion happens; shutdown link now.\n", dev->rev); schedule_work(&dev->handle_d3cold_work); } } } out: out: Loading Loading @@ -1779,6 +1825,7 @@ int32_t ep_pcie_irq_init(struct ep_pcie_dev_t *dev) /* Initialize all works to be performed before registering for IRQs*/ /* Initialize all works to be performed before registering for IRQs*/ INIT_WORK(&dev->handle_perst_work, handle_perst_func); INIT_WORK(&dev->handle_perst_work, handle_perst_func); INIT_WORK(&dev->handle_bme_work, handle_bme_func); INIT_WORK(&dev->handle_bme_work, handle_bme_func); INIT_WORK(&dev->handle_d3cold_work, handle_d3cold_func); if (dev->aggregated_irq) { if (dev->aggregated_irq) { ret = devm_request_irq(pdev, ret = devm_request_irq(pdev, Loading Loading @@ -1932,6 +1979,8 @@ int ep_pcie_core_register_event(struct ep_pcie_register_event *reg) "PCIe V%d: Event 0x%x is registered\n", "PCIe V%d: Event 0x%x is registered\n", ep_pcie_dev.rev, reg->events); ep_pcie_dev.rev, reg->events); ep_pcie_dev.client_ready = true; return 0; return 0; } } Loading Loading @@ -1970,6 +2019,12 @@ enum ep_pcie_link_status ep_pcie_core_get_linkstatus(void) "PCIe V%d: PCIe link is up and BME is enabled; current SW link status:%d.\n", "PCIe V%d: PCIe link is up and BME is enabled; current SW link status:%d.\n", dev->rev, dev->link_status); dev->rev, dev->link_status); dev->link_status = EP_PCIE_LINK_ENABLED; dev->link_status = EP_PCIE_LINK_ENABLED; if (dev->no_notify) { EP_PCIE_DBG(dev, "PCIe V%d: BME is set now, but do not tell client about BME enable.\n", dev->rev); return EP_PCIE_LINK_UP; } } else { } else { EP_PCIE_DBG(dev, EP_PCIE_DBG(dev, "PCIe V%d: PCIe link is up but BME is disabled; current SW link status:%d.\n", "PCIe V%d: PCIe link is up but BME is disabled; current SW link status:%d.\n", Loading Loading
drivers/platform/msm/ep_pcie/ep_pcie_com.h +3 −0 Original line number Original line Diff line number Diff line Loading @@ -340,10 +340,13 @@ struct ep_pcie_dev_t { bool l23_ready; bool l23_ready; bool l1ss_enabled; bool l1ss_enabled; struct ep_pcie_msi_config msi_cfg; struct ep_pcie_msi_config msi_cfg; bool no_notify; bool client_ready; struct ep_pcie_register_event *event_reg; struct ep_pcie_register_event *event_reg; struct work_struct handle_perst_work; struct work_struct handle_perst_work; struct work_struct handle_bme_work; struct work_struct handle_bme_work; struct work_struct handle_d3cold_work; }; }; extern struct ep_pcie_dev_t ep_pcie_dev; extern struct ep_pcie_dev_t ep_pcie_dev; Loading
drivers/platform/msm/ep_pcie/ep_pcie_core.c +62 −7 Original line number Original line Diff line number Diff line Loading @@ -1060,6 +1060,10 @@ static void ep_pcie_release_resources(struct ep_pcie_dev_t *dev) static void ep_pcie_enumeration_complete(struct ep_pcie_dev_t *dev) static void ep_pcie_enumeration_complete(struct ep_pcie_dev_t *dev) { { unsigned long irqsave_flags; spin_lock_irqsave(&dev->isr_lock, irqsave_flags); dev->enumerated = true; dev->enumerated = true; dev->link_status = EP_PCIE_LINK_ENABLED; dev->link_status = EP_PCIE_LINK_ENABLED; Loading @@ -1086,7 +1090,14 @@ static void ep_pcie_enumeration_complete(struct ep_pcie_dev_t *dev) "PCIe V%d: register driver for device 0x%x.\n", "PCIe V%d: register driver for device 0x%x.\n", ep_pcie_dev.rev, hw_drv.device_id); ep_pcie_dev.rev, hw_drv.device_id); ep_pcie_register_drv(&hw_drv); ep_pcie_register_drv(&hw_drv); if (!dev->no_notify) ep_pcie_notify_event(dev, EP_PCIE_EVENT_LINKUP); ep_pcie_notify_event(dev, EP_PCIE_EVENT_LINKUP); else EP_PCIE_DBG(dev, "PCIe V%d: do not notify client about linkup.\n", dev->rev); spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags); } } int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) Loading Loading @@ -1584,7 +1595,13 @@ static irqreturn_t ep_pcie_handle_dstate_change_irq(int irq, void *data) "PCIe V%d: No. %ld change to D3 state.\n", "PCIe V%d: No. %ld change to D3 state.\n", dev->rev, dev->d3_counter); dev->rev, dev->d3_counter); ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, 0, BIT(1)); ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, 0, BIT(1)); if (dev->enumerated) ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_D3_HOT); ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_D3_HOT); else EP_PCIE_DBG(dev, "PCIe V%d: do not notify client about this D3 hot event since enumeration by HLOS is not done yet.\n", dev->rev); } else if (dstate == 0) { } else if (dstate == 0) { dev->l23_ready = false; dev->l23_ready = false; dev->d0_counter++; dev->d0_counter++; Loading Loading @@ -1648,9 +1665,25 @@ static void handle_perst_func(struct work_struct *work) struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t, struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t, handle_perst_work); handle_perst_work); EP_PCIE_DBG(dev, "PCIe V%d: Start enumeration due to PERST deassertion.\n", dev->rev); ep_pcie_enumeration(dev); ep_pcie_enumeration(dev); } } static void handle_d3cold_func(struct work_struct *work) { struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t, handle_d3cold_work); EP_PCIE_DBG(dev, "PCIe V%d: shutdown PCIe link due to PERST assertion before BME is set.\n", dev->rev); ep_pcie_core_disable_endpoint(); dev->no_notify = false; } static void handle_bme_func(struct work_struct *work) static void handle_bme_func(struct work_struct *work) { { struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t *dev = container_of(work, Loading @@ -1673,10 +1706,14 @@ static irqreturn_t ep_pcie_handle_perst_irq(int irq, void *data) EP_PCIE_DBG(dev, EP_PCIE_DBG(dev, "PCIe V%d: PCIe is not enumerated yet; PERST is %sasserted.\n", "PCIe V%d: PCIe is not enumerated yet; PERST is %sasserted.\n", dev->rev, perst ? "de" : ""); dev->rev, perst ? "de" : ""); if ((!dev->perst_enum) || !perst) if (perst) { goto out; /* start work for link enumeration with the host side */ /* start work for link enumeration with the host side */ schedule_work(&dev->handle_perst_work); schedule_work(&dev->handle_perst_work); } else { dev->no_notify = true; /* shutdown the link if the link is already on */ schedule_work(&dev->handle_d3cold_work); } goto out; goto out; } } Loading @@ -1694,7 +1731,16 @@ static irqreturn_t ep_pcie_handle_perst_irq(int irq, void *data) EP_PCIE_DBG(dev, EP_PCIE_DBG(dev, "PCIe V%d: No. %ld PERST assertion.\n", "PCIe V%d: No. %ld PERST assertion.\n", dev->rev, dev->perst_ast_counter); dev->rev, dev->perst_ast_counter); if (dev->client_ready) { ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_D3_COLD); ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_D3_COLD); } else { dev->no_notify = true; EP_PCIE_DBG(dev, "PCIe V%d: Client driver is not ready when this PERST assertion happens; shutdown link now.\n", dev->rev); schedule_work(&dev->handle_d3cold_work); } } } out: out: Loading Loading @@ -1779,6 +1825,7 @@ int32_t ep_pcie_irq_init(struct ep_pcie_dev_t *dev) /* Initialize all works to be performed before registering for IRQs*/ /* Initialize all works to be performed before registering for IRQs*/ INIT_WORK(&dev->handle_perst_work, handle_perst_func); INIT_WORK(&dev->handle_perst_work, handle_perst_func); INIT_WORK(&dev->handle_bme_work, handle_bme_func); INIT_WORK(&dev->handle_bme_work, handle_bme_func); INIT_WORK(&dev->handle_d3cold_work, handle_d3cold_func); if (dev->aggregated_irq) { if (dev->aggregated_irq) { ret = devm_request_irq(pdev, ret = devm_request_irq(pdev, Loading Loading @@ -1932,6 +1979,8 @@ int ep_pcie_core_register_event(struct ep_pcie_register_event *reg) "PCIe V%d: Event 0x%x is registered\n", "PCIe V%d: Event 0x%x is registered\n", ep_pcie_dev.rev, reg->events); ep_pcie_dev.rev, reg->events); ep_pcie_dev.client_ready = true; return 0; return 0; } } Loading Loading @@ -1970,6 +2019,12 @@ enum ep_pcie_link_status ep_pcie_core_get_linkstatus(void) "PCIe V%d: PCIe link is up and BME is enabled; current SW link status:%d.\n", "PCIe V%d: PCIe link is up and BME is enabled; current SW link status:%d.\n", dev->rev, dev->link_status); dev->rev, dev->link_status); dev->link_status = EP_PCIE_LINK_ENABLED; dev->link_status = EP_PCIE_LINK_ENABLED; if (dev->no_notify) { EP_PCIE_DBG(dev, "PCIe V%d: BME is set now, but do not tell client about BME enable.\n", dev->rev); return EP_PCIE_LINK_UP; } } else { } else { EP_PCIE_DBG(dev, EP_PCIE_DBG(dev, "PCIe V%d: PCIe link is up but BME is disabled; current SW link status:%d.\n", "PCIe V%d: PCIe link is up but BME is disabled; current SW link status:%d.\n", Loading