Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 003fce74 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ep_pcie: add the support of D3 cold before BME is set"

parents 381b858b 08169898
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -340,10 +340,13 @@ struct ep_pcie_dev_t {
	bool                         l23_ready;
	bool                         l1ss_enabled;
	struct ep_pcie_msi_config    msi_cfg;
	bool                         no_notify;
	bool                         client_ready;

	struct ep_pcie_register_event *event_reg;
	struct work_struct	     handle_perst_work;
	struct work_struct           handle_bme_work;
	struct work_struct           handle_d3cold_work;
};

extern struct ep_pcie_dev_t ep_pcie_dev;
+62 −7
Original line number Diff line number Diff line
@@ -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)
{
	unsigned long irqsave_flags;

	spin_lock_irqsave(&dev->isr_lock, irqsave_flags);

	dev->enumerated = true;
	dev->link_status = EP_PCIE_LINK_ENABLED;

@@ -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",
		ep_pcie_dev.rev, hw_drv.device_id);
	ep_pcie_register_drv(&hw_drv);
	if (!dev->no_notify)
		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)
@@ -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",
			dev->rev, dev->d3_counter);
		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);
		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) {
		dev->l23_ready = false;
		dev->d0_counter++;
@@ -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,
					handle_perst_work);

	EP_PCIE_DBG(dev,
		"PCIe V%d: Start enumeration due to PERST deassertion.\n",
		dev->rev);

	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)
{
	struct ep_pcie_dev_t *dev = container_of(work,
@@ -1673,10 +1706,14 @@ static irqreturn_t ep_pcie_handle_perst_irq(int irq, void *data)
		EP_PCIE_DBG(dev,
			"PCIe V%d: PCIe is not enumerated yet; PERST is %sasserted.\n",
			dev->rev, perst ? "de" : "");
		if ((!dev->perst_enum) || !perst)
			goto out;
		if (perst) {
			/* start work for link enumeration with the host side */
			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;
	}
@@ -1694,7 +1731,16 @@ static irqreturn_t ep_pcie_handle_perst_irq(int irq, void *data)
		EP_PCIE_DBG(dev,
			"PCIe V%d: No. %ld PERST assertion.\n",
			dev->rev, dev->perst_ast_counter);

		if (dev->client_ready) {
			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:
@@ -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*/
	INIT_WORK(&dev->handle_perst_work, handle_perst_func);
	INIT_WORK(&dev->handle_bme_work, handle_bme_func);
	INIT_WORK(&dev->handle_d3cold_work, handle_d3cold_func);

	if (dev->aggregated_irq) {
		ret = devm_request_irq(pdev,
@@ -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",
		ep_pcie_dev.rev, reg->events);

	ep_pcie_dev.client_ready = true;

	return 0;
}

@@ -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",
			dev->rev, dev->link_status);
		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 {
		EP_PCIE_DBG(dev,
			"PCIe V%d: PCIe link is up but BME is disabled; current SW link status:%d.\n",