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

Commit 3dcfdeb4 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 2cbfdd54 e56d3e7a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -332,10 +332,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
@@ -1002,6 +1002,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;

@@ -1028,7 +1032,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);

	return;
}
@@ -1528,7 +1539,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++;
@@ -1592,9 +1609,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,
@@ -1617,10 +1650,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;
	}
@@ -1638,7 +1675,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:
@@ -1723,6 +1769,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,
@@ -1876,6 +1923,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;
}

@@ -1912,6 +1961,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",
+23 −9
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ static void mhi_ring_init_cb(void *user_data);
static void mhi_update_state_info(uint32_t info);
static int mhi_deinit(struct mhi_dev *mhi);
static void mhi_dev_resume_init_with_link_up(struct ep_pcie_notify *notify);
static int mhi_dev_pcie_notify_event;

void mhi_dev_read_from_host(struct mhi_dev *mhi, struct mhi_addr *transfer)
{
@@ -2492,26 +2493,31 @@ static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx)

void mhi_dev_resume_init_with_link_up(struct ep_pcie_notify *notify)
{
	int rc = 0;

	if (!notify) {
	if (!notify || !notify->user) {
		pr_err("Null argument for notify\n");
		return;
	}

	mhi_ctx = notify->user;
	if (!mhi_ctx) {
		pr_err("Invalid mhi_ctx\n");
		return;
	mhi_dev_pcie_notify_event = notify->options;
	mhi_log(MHI_MSG_INFO,
			"PCIe event=0x%x\n", notify->options);
	queue_work(mhi_ctx->pcie_event_wq, &mhi_ctx->pcie_event);
}

	if (notify->options == MHI_INIT) {
static void mhi_dev_pcie_handle_event(struct work_struct *work)
{
	struct mhi_dev *mhi_ctx = container_of(work, struct mhi_dev,
								pcie_event);
	int rc = 0;

	if (mhi_dev_pcie_notify_event == MHI_INIT) {
		rc = mhi_dev_resume_mmio_mhi_init(mhi_ctx);
		if (rc) {
			pr_err("Error during MHI device initialization\n");
			return;
		}
	} else if (notify->options == MHI_REINIT) {
	} else if (mhi_dev_pcie_notify_event == MHI_REINIT) {
		rc = mhi_dev_resume_mmio_mhi_reinit(mhi_ctx);
		if (rc) {
			pr_err("Error during MHI device re-initialization\n");
@@ -2540,6 +2546,14 @@ static int mhi_dev_probe(struct platform_device *pdev)
		mhi_update_state_info(MHI_STATE_CONFIGURED);
	}

	INIT_WORK(&mhi_ctx->pcie_event, mhi_dev_pcie_handle_event);
	mhi_ctx->pcie_event_wq = alloc_workqueue("mhi_dev_pcie_event_wq",
							WQ_HIGHPRI, 0);
	if (!mhi_ctx->pcie_event_wq) {
		rc = -ENOMEM;
		return rc;
	}

	mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id);
	if (mhi_ctx->phandle) {
		/* PCIe link is already up */
+2 −0
Original line number Diff line number Diff line
@@ -523,9 +523,11 @@ struct mhi_dev {
	struct work_struct		re_init;

	/* EP PCIe registration */
	struct workqueue_struct		*pcie_event_wq;
	struct ep_pcie_register_event	event_reg;
	u32                             ifc_id;
	struct ep_pcie_hw               *phandle;
	struct work_struct		pcie_event;

	atomic_t			write_active;
	atomic_t			is_suspended;