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

Commit f09365d9 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mhi: core: do not assert device wake when processing completion event"

parents 65939c37 e04e3591
Loading
Loading
Loading
Loading
+80 −22
Original line number Diff line number Diff line
@@ -65,26 +65,6 @@ Main node properties:
  Value type: Array of <string>
  Definition: Channel names configured in mhi,chan-cfg.

- mhi,ev-cfg
  Usage: required
  Value type: Array of <u32>
  Definition: Array of tuples describe event configuration.
	1st element: Event ring length in elements
	2nd element: Interrupt moderation time in ms
	3rd element: MSI associated with this event ring
	4th element: Dedicated channel number, if it's a dedicated event ring
	5th element: Event ring priority, set to 1 for now
	6th element: Event doorbell mode configuration as defined by
	enum MHI_BRSTMODE
		2 = burst mode disabled
		3 = burst mode enabled
	7th element: Bitwise configuration settings for the channel
		Bit mask:
		BIT(0) : Event ring associated with hardware channels
		BIT(1) : Client manages the event ring (use by napi_poll)
		BIT(2) : Event ring associated with offload channel
		BIT(3) : Event ring dedicated to control events only

- mhi,timeout
  Usage: optional
  Value type: <u32>
@@ -115,6 +95,67 @@ Main node properties:
  Value type: <u32>
  Definition: Size of each segment to allocate for BHIe vector table

==========================
mhi event node properties:
==========================

- mhi,num-elements
  Usage: required
  Value type: <u32>
  Definition: Number of elements event ring support

- mhi,intmod
  Usage: required
  Value type: <u32>
  Definition: interrupt moderation time in ms

- mhi,msi
  Usage: required
  Value type: <u32>
  Definition: MSI associated with this event ring

- mhi,chan
  Usage: optional
  Value type: <u32>
  Definition: Dedicated channel number, if it's a dedicated event ring

- mhi,priority
  Usage: required
  Value type: <u32>
  Definition: Event ring priority, set to 1 for now

- mhi,brstmode
  Usage: required
  Value type: <u32>
  Definition: Event doorbell mode configuration as defined by
	enum MHI_BRSTMODE
		2 = burst mode disabled
		3 = burst mode enabled

- mhi,data-type
  Usage: optional
  Value type: <u32>
  Definition: Type of data this event ring will process as defined
	by enum mhi_er_data_type
		0 = process data packets (default)
		1 = process mhi control packets

- mhi,hw-ev
  Usage: optional
  Value type: <bool>
  Definition: Event ring associated with hardware channels

- mhi,client-manage
  Usage: optional
  Value type: <bool>
  Definition: Client manages the event ring (use by napi_poll)

- mhi,offload
  Usage: optional
  Value type: <bool>
  Definition: Event ring associated with offload channel


Children node properties:

MHI drivers that require DT can add driver specific information as a child node.
@@ -133,8 +174,25 @@ mhi_controller {
		       <2 64 1 1 2 1 1 0 0>, <3 64 1 2 2 1 1 0 0>;
	mhi,chan-names = "LOOPBACK", "LOOPBACK",
			 "SAHARA", "SAHARA";
	mhi,ev-cfg = <64 1 1 0 1 2 8>
		     <64 1 2 0 1 2 0>;
	mhi_event@0 {
		mhi,num-elements = <32>;
		mhi,intmod = <1>;
		mhi,msi = <1>;
		mhi,chan = <0>;
		mhi,priority = <1>;
		mhi,bstmode = <2>;
		mhi,data-type = <1>;
	};

	mhi_event@1 {
		mhi,num-elements = <256>;
		mhi,intmod = <1>;
		mhi,msi = <2>;
		mhi,chan = <0>;
		mhi,priority = <1>;
		mhi,bstmode = <2>;
	};

	mhi,fw-name = "sbl1.mbn";
	mhi,timeout = <500>;

+135 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

&soc {
	mhi_0: qcom,mhi {
		/* controller specific configuration */
		compatible = "qcom,mhi";
		qcom,pci-domain = <1>;
		qcom,pci-bus = <1>;
		qcom,pci-slot = <0>;
		qcom,smmu-cfg = <0x3>;
		qcom,msm-bus,name = "mhi";
		qcom,msm-bus,num-cases = <2>;
		qcom,msm-bus,num-paths = <1>;
		qcom,msm-bus,vectors-KBps =
					<100 512 0 0>,
					<100 512 1200000000 650000000>;

		/* mhi bus specific settings */
		mhi,max-channels = <106>;
		mhi,chan-cfg =
			<0 64 2 1 2 0 2 0 0>, <1 64 2 2 2 0 2 0 0>,
			<2 128 1 1 2 0 1 0 0>, <3 128 1 2 2 0 1 0 0>,
			<4 64 1 1 2 0 2 0 0>, <5 64 3 2 2 0 2 0 0>,
			<8 64 1 1 2 0 2 0 0>, <9 64 1 2 2 0 2 0 0>,
			<10 64 1 1 2 0 2 0 0>, <11 64 1 2 2 0 2 0 0>,
			<14 64 1 1 2 0 2 0 0>, <15 64 2 2 2 0 2 0 0>,
			<16 64 3 1 2 0 2 0 0>, <17 64 3 2 2 0 2 0 0>,
			<18 64 1 1 2 0 2 0 0>, <19 64 1 2 2 0 2 0 8>,
			<20 64 2 1 2 0 2 1 16>, <21 64 2 2 2 0 2 0 24>,
			<22 64 2 1 2 0 2 0 0>, <23 64 2 2 2 0 2 0 0>,
			<24 64 2 1 2 0 1 0 0>, <25 64 2 2 2 0 1 0 0>,
			<26 64 3 1 2 0 2 0 0>, <27 64 3 2 2 0 2 0 0>,
			<32 64 3 1 2 0 2 0 0>, <33 64 3 2 2 0 2 0 0>,
			<100 512 4 1 3 1 2 1 4>, <101 512 5 2 3 1 2 1 0>;
		mhi,chan-names = "LOOPBACK", "LOOPBACK",
				 "SAHARA", "SAHARA",
				 "DIAG", "DIAG",
				 "QDSS", "QDSS",
				 "EFS", "EFS",
				 "QMI0", "QMI0",
				 "QMI1", "QMI1",
				 "IP_CTRL", "IP_CTRL",
				 "IPCR", "IPCR",
				 "TF", "TF",
				 "BL", "BL",
				 "DCI", "DCI",
				 "DUN", "DUN",
				 "IP_HW0", "IP_HW0";

		mhi,timeout = <2000>;
		status = "disabled";

		#address-cells = <1>;
		#size-cells = <0>;

		mhi_event@0 {
			mhi,num-elements = <32>;
			mhi,intmod = <1>;
			mhi,msi = <1>;
			mhi,priority = <1>;
			mhi,brstmode = <2>;
			mhi,data-type = <1>;
		};

		mhi_event@1 {
			mhi,num-elements = <256>;
			mhi,intmod = <1>;
			mhi,msi = <2>;
			mhi,priority = <1>;
			mhi,brstmode = <2>;
		};

		mhi_event@2 {
			mhi,num-elements = <256>;
			mhi,intmod = <1>;
			mhi,msi = <3>;
			mhi,priority = <1>;
			mhi,brstmode = <2>;
		};

		mhi_event@3 {
			mhi,num-elements = <256>;
			mhi,intmod = <1>;
			mhi,msi = <4>;
			mhi,priority = <1>;
			mhi,brstmode = <2>;
		};

		mhi_event@4 {
			mhi,num-elements = <1024>;
			mhi,intmod = <5>;
			mhi,msi = <5>;
			mhi,chan = <100>;
			mhi,priority = <1>;
			mhi,brstmode = <3>;
			mhi,hw-ev;
		};

		mhi_event@5 {
			mhi,num-elements = <1024>;
			mhi,intmod = <5>;
			mhi,msi = <6>;
			mhi,chan = <101>;
			mhi,priority = <1>;
			mhi,brstmode = <3>;
			mhi,hw-ev;
			mhi,client-manage;
		};

		mhi_netdev_0: mhi_rmnet@0 {
			reg = <0x0>;
			mhi,chan = "IP_HW0";
			mhi,interface-name = "rmnet_mhi";
			mhi,mru = <0x4000>;
		};

		mhi_netdev_1: mhi_rmnet@1 {
			reg = <0x1>;
			mhi,chan = "IP_HW_ADPL";
			mhi,interface-name = "rmnet_mhi";
			mhi,mru = <0x4000>;
		};
	};
};
+1 −67
Original line number Diff line number Diff line
@@ -3525,73 +3525,6 @@
		qcom,smmu-coherent;
		status = "disabled";
	};

	mhi_0: qcom,mhi@0 {
		/* controller specific configuration */
		compatible = "qcom,mhi";
		qcom,pci-domain = <1>;
		qcom,pci-bus = <1>;
		qcom,pci-slot = <0>;
		qcom,smmu-cfg = <0x3>;
		qcom,msm-bus,name = "mhi";
		qcom,msm-bus,num-cases = <2>;
		qcom,msm-bus,num-paths = <1>;
		qcom,msm-bus,vectors-KBps =
					<100 512 0 0>,
					<100 512 1200000000 650000000>;

		/* mhi bus specific settings */
		mhi,max-channels = <106>;
		mhi,chan-cfg =
			<0 64 2 1 2 0 2 0 0>, <1 64 2 2 2 0 2 0 0>,
			<2 128 1 1 2 0 1 0 0>, <3 128 1 2 2 0 1 0 0>,
			<4 64 1 1 2 0 2 0 0>, <5 64 3 2 2 0 2 0 0>,
			<8 64 1 1 2 0 2 0 0>, <9 64 1 2 2 0 2 0 0>,
			<10 64 1 1 2 0 2 0 0>, <11 64 1 2 2 0 2 0 0>,
			<14 64 1 1 2 0 2 0 0>, <15 64 2 2 2 0 2 0 0>,
			<16 64 3 1 2 0 2 0 0>, <17 64 3 2 2 0 2 0 0>,
			<18 64 1 1 2 0 2 0 0>, <19 64 1 2 2 0 2 0 8>,
			<20 64 2 1 2 0 2 1 16>, <21 64 2 2 2 0 2 0 24>,
			<22 64 2 1 2 0 2 0 0>, <23 64 2 2 2 0 2 0 0>,
			<24 64 2 1 2 0 1 0 0>, <25 64 2 2 2 0 1 0 0>,
			<26 64 3 1 2 0 2 0 0>, <27 64 3 2 2 0 2 0 0>,
			<32 64 3 1 2 0 2 0 0>, <33 64 3 2 2 0 2 0 0>,
			<100 512 4 1 3 1 2 1 0x4>, <101 512 5 2 3 1 2 1 0>;
		mhi,chan-names = "LOOPBACK", "LOOPBACK",
				 "SAHARA", "SAHARA",
				 "DIAG", "DIAG",
				 "QDSS", "QDSS",
				 "EFS", "EFS",
				 "QMI0", "QMI0",
				 "QMI1", "QMI1",
				 "IP_CTRL", "IP_CTRL",
				 "IPCR", "IPCR",
				 "TF", "TF",
				 "BL", "BL",
				 "DCI", "DCI",
				 "DUN", "DUN",
				 "IP_HW0", "IP_HW0";
		mhi,ev-cfg = <32 0 1 0 1 2 0x8>,
			     <256 1 2 0 1 2 0>,
			     <256 1 3 0 1 2 0>,
			     <256 1 4 0 1 2 0>,
			     <1024 5 5 100 1 3 0x1>,
			     <1024 5 6 101 1 3 0x3>;
		mhi,timeout = <2000>;
		status = "disabled";

		mhi_netdev_0: mhi_rmnet@0 {
			     mhi,chan = "IP_HW0";
			     mhi,interface-name = "rmnet_mhi";
			     mhi,mru = <0x4000>;
		};

		mhi_netdev_1: mhi_rmnet@1 {
			     mhi,chan = "IP_HW_ADPL";
			     mhi,interface-name = "rmnet_mhi";
			     mhi,mru = <0x4000>;
		};
	};
};

&emac_gdsc {
@@ -3827,3 +3760,4 @@
#include "sm8150-thermal.dtsi"
#include "sm8150-usb.dtsi"
#include "sm8150-gpu.dtsi"
#include "sm8150-mhi.dtsi"
+62 −11
Original line number Diff line number Diff line
@@ -34,18 +34,30 @@ struct __packed dtr_ctrl_msg {

#define CTRL_MAGIC (0x4C525443)
#define CTRL_MSG_DTR BIT(0)
#define CTRL_MSG_ID (0x10)
#define CTRL_MSG_RTS BIT(1)
#define CTRL_MSG_DCD BIT(0)
#define CTRL_MSG_DSR BIT(1)
#define CTRL_MSG_RI BIT(2)
#define CTRL_HOST_STATE (0x10)
#define CTRL_DEVICE_STATE (0x11)
#define CTRL_GET_CHID(dtr) (dtr->dest_id & 0xFF)

static int mhi_dtr_tiocmset(struct mhi_controller *mhi_cntrl,
			    struct mhi_chan *mhi_chan,
			    struct mhi_device *mhi_dev,
			    u32 tiocm)
{
	struct dtr_ctrl_msg *dtr_msg = NULL;
	struct mhi_chan *dtr_chan = mhi_cntrl->dtr_dev->ul_chan;
	spinlock_t *res_lock = &mhi_dev->dev.devres_lock;
	u32 cur_tiocm;
	int ret = 0;

	tiocm &= TIOCM_DTR;
	if (mhi_chan->tiocm == tiocm)
	cur_tiocm = mhi_dev->tiocm & ~(TIOCM_CD | TIOCM_DSR | TIOCM_RI);

	tiocm &= (TIOCM_DTR | TIOCM_RTS);

	/* state did not changed */
	if (cur_tiocm == tiocm)
		return 0;

	mutex_lock(&dtr_chan->mutex);
@@ -57,11 +69,13 @@ static int mhi_dtr_tiocmset(struct mhi_controller *mhi_cntrl,
	}

	dtr_msg->preamble = CTRL_MAGIC;
	dtr_msg->msg_id = CTRL_MSG_ID;
	dtr_msg->dest_id = mhi_chan->chan;
	dtr_msg->msg_id = CTRL_HOST_STATE;
	dtr_msg->dest_id = mhi_dev->ul_chan_id;
	dtr_msg->size = sizeof(u32);
	if (tiocm & TIOCM_DTR)
		dtr_msg->msg |= CTRL_MSG_DTR;
	if (tiocm & TIOCM_RTS)
		dtr_msg->msg |= CTRL_MSG_RTS;

	reinit_completion(&dtr_chan->completion);
	ret = mhi_queue_transfer(mhi_cntrl->dtr_dev, DMA_TO_DEVICE, dtr_msg,
@@ -71,7 +85,6 @@ static int mhi_dtr_tiocmset(struct mhi_controller *mhi_cntrl,

	ret = wait_for_completion_timeout(&dtr_chan->completion,
				msecs_to_jiffies(mhi_cntrl->timeout_ms));

	if (!ret) {
		MHI_ERR("Failed to receive transfer callback\n");
		ret = -EIO;
@@ -79,7 +92,10 @@ static int mhi_dtr_tiocmset(struct mhi_controller *mhi_cntrl,
	}

	ret = 0;
	mhi_chan->tiocm = tiocm;
	spin_lock_irq(res_lock);
	mhi_dev->tiocm &= ~(TIOCM_DTR | TIOCM_RTS);
	mhi_dev->tiocm |= tiocm;
	spin_unlock_irq(res_lock);

tiocm_exit:
	kfree(dtr_msg);
@@ -91,7 +107,6 @@ static int mhi_dtr_tiocmset(struct mhi_controller *mhi_cntrl,
long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg)
{
	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
	struct mhi_chan *mhi_chan = mhi_dev->ul_chan;
	int ret;

	/* ioctl not supported by this controller */
@@ -100,7 +115,7 @@ long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg)

	switch (cmd) {
	case TIOCMGET:
		return mhi_chan->tiocm;
		return mhi_dev->tiocm;
	case TIOCMSET:
	{
		u32 tiocm;
@@ -109,7 +124,7 @@ long mhi_ioctl(struct mhi_device *mhi_dev, unsigned int cmd, unsigned long arg)
		if (ret)
			return ret;

		return mhi_dtr_tiocmset(mhi_cntrl, mhi_chan, tiocm);
		return mhi_dtr_tiocmset(mhi_cntrl, mhi_dev, tiocm);
	}
	default:
		break;
@@ -122,6 +137,42 @@ EXPORT_SYMBOL(mhi_ioctl);
static void mhi_dtr_dl_xfer_cb(struct mhi_device *mhi_dev,
			       struct mhi_result *mhi_result)
{
	struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
	struct dtr_ctrl_msg *dtr_msg = mhi_result->buf_addr;
	u32 chan;
	spinlock_t *res_lock;

	if (mhi_result->bytes_xferd != sizeof(*dtr_msg)) {
		MHI_ERR("Unexpected length %zu received\n",
			mhi_result->bytes_xferd);
		return;
	}

	MHI_VERB("preamble:0x%x msg_id:%u dest_id:%u msg:0x%x\n",
		 dtr_msg->preamble, dtr_msg->msg_id, dtr_msg->dest_id,
		 dtr_msg->msg);

	chan = CTRL_GET_CHID(dtr_msg);
	if (chan >= mhi_cntrl->max_chan)
		return;

	mhi_dev = mhi_cntrl->mhi_chan[chan].mhi_dev;
	if (!mhi_dev)
		return;

	res_lock = &mhi_dev->dev.devres_lock;
	spin_lock_irq(res_lock);
	mhi_dev->tiocm &= ~(TIOCM_CD | TIOCM_DSR | TIOCM_RI);

	if (dtr_msg->msg & CTRL_MSG_DCD)
		mhi_dev->tiocm |= TIOCM_CD;

	if (dtr_msg->msg & CTRL_MSG_DSR)
		mhi_dev->tiocm |= TIOCM_DSR;

	if (dtr_msg->msg & CTRL_MSG_RI)
		mhi_dev->tiocm |= TIOCM_RI;
	spin_unlock_irq(res_lock);
}

static void mhi_dtr_ul_xfer_cb(struct mhi_device *mhi_dev,
+71 −47
Original line number Diff line number Diff line
@@ -669,75 +669,99 @@ int mhi_device_configure(struct mhi_device *mhi_dev,
static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl,
			   struct device_node *of_node)
{
	struct {
		u32 ev_cfg[MHI_EV_CFG_MAX];
	} *ev_cfg;
	int num, i, ret;
	int i, ret, num = 0;
	struct mhi_event *mhi_event;
	u32 bit_cfg;
	struct device_node *child;

	num = of_property_count_elems_of_size(of_node, "mhi,ev-cfg",
					      sizeof(*ev_cfg));
	if (num <= 0)
		return -EINVAL;
	for_each_available_child_of_node(of_node, child) {
		if (!strcmp(child->name, "mhi_event"))
			num++;
	}

	ev_cfg = kcalloc(num, sizeof(*ev_cfg), GFP_KERNEL);
	if (!ev_cfg)
		return -ENOMEM;
	if (!num)
		return -EINVAL;

	mhi_cntrl->total_ev_rings = num;
	mhi_cntrl->mhi_event = kcalloc(num, sizeof(*mhi_cntrl->mhi_event),
				       GFP_KERNEL);
	if (!mhi_cntrl->mhi_event) {
		kfree(ev_cfg);
	if (!mhi_cntrl->mhi_event)
		return -ENOMEM;
	}

	ret = of_property_read_u32_array(of_node, "mhi,ev-cfg", (u32 *)ev_cfg,
					 num * sizeof(*ev_cfg) / sizeof(u32));
	/* populate ev ring */
	mhi_event = mhi_cntrl->mhi_event;
	i = 0;
	for_each_available_child_of_node(of_node, child) {
		if (strcmp(child->name, "mhi_event"))
			continue;

		mhi_event->er_index = i++;
		ret = of_property_read_u32(child, "mhi,num-elements",
					   (u32 *)&mhi_event->ring.elements);
		if (ret)
			goto error_ev_cfg;

	/* populate ev ring */
	mhi_event = mhi_cntrl->mhi_event;
	for (i = 0; i < mhi_cntrl->total_ev_rings; i++, mhi_event++) {
		mhi_event->er_index = i;
		mhi_event->ring.elements =
			ev_cfg[i].ev_cfg[MHI_EV_CFG_ELEMENTS];
		mhi_event->intmod = ev_cfg[i].ev_cfg[MHI_EV_CFG_INTMOD];
		mhi_event->msi = ev_cfg[i].ev_cfg[MHI_EV_CFG_MSI];
		mhi_event->chan = ev_cfg[i].ev_cfg[MHI_EV_CFG_CHAN];
		if (mhi_event->chan >= mhi_cntrl->max_chan)
		ret = of_property_read_u32(child, "mhi,intmod",
					   &mhi_event->intmod);
		if (ret)
			goto error_ev_cfg;

		ret = of_property_read_u32(child, "mhi,msi",
					   &mhi_event->msi);
		if (ret)
			goto error_ev_cfg;

		ret = of_property_read_u32(child, "mhi,chan",
					   &mhi_event->chan);
		if (!ret) {
			if (mhi_event->chan >= mhi_cntrl->max_chan)
				goto error_ev_cfg;
			/* this event ring has a dedicated channel */
		if (mhi_event->chan)
			mhi_event->mhi_chan =
				&mhi_cntrl->mhi_chan[mhi_event->chan];
		}

		mhi_event->priority = ev_cfg[i].ev_cfg[MHI_EV_CFG_PRIORITY];
		mhi_event->db_cfg.brstmode =
			ev_cfg[i].ev_cfg[MHI_EV_CFG_BRSTMODE];
		if (MHI_INVALID_BRSTMODE(mhi_event->db_cfg.brstmode))
		ret = of_property_read_u32(child, "mhi,priority",
					   &mhi_event->priority);
		if (ret)
			goto error_ev_cfg;

		ret = of_property_read_u32(child, "mhi,brstmode",
					   &mhi_event->db_cfg.brstmode);
		if (ret || MHI_INVALID_BRSTMODE(mhi_event->db_cfg.brstmode))
			goto error_ev_cfg;

		mhi_event->db_cfg.process_db =
			(mhi_event->db_cfg.brstmode == MHI_BRSTMODE_ENABLE) ?
			mhi_db_brstmode : mhi_db_brstmode_disable;

		bit_cfg = ev_cfg[i].ev_cfg[MHI_EV_CFG_BITCFG];
		if (bit_cfg & MHI_EV_CFG_BIT_HW_EV) {
			mhi_event->hw_ring = true;
			mhi_cntrl->hw_ev_rings++;
		} else
			mhi_cntrl->sw_ev_rings++;
		ret = of_property_read_u32(child, "mhi,data-type",
					   &mhi_event->data_type);
		if (ret)
			mhi_event->data_type = MHI_ER_DATA_ELEMENT_TYPE;

		mhi_event->cl_manage = !!(bit_cfg & MHI_EV_CFG_BIT_CL_MANAGE);
		mhi_event->offload_ev = !!(bit_cfg & MHI_EV_CFG_BIT_OFFLOAD_EV);
		mhi_event->ctrl_ev = !!(bit_cfg & MHI_EV_CFG_BIT_CTRL_EV);
		if (mhi_event->data_type > MHI_ER_DATA_TYPE_MAX)
			goto error_ev_cfg;

		switch (mhi_event->data_type) {
		case MHI_ER_DATA_ELEMENT_TYPE:
			mhi_event->process_event = mhi_process_data_event_ring;
			break;
		case MHI_ER_CTRL_ELEMENT_TYPE:
			mhi_event->process_event = mhi_process_ctrl_ev_ring;
			break;
		}

	kfree(ev_cfg);
		mhi_event->hw_ring = of_property_read_bool(child, "mhi,hw-ev");
		if (mhi_event->hw_ring)
			mhi_cntrl->hw_ev_rings++;
		else
			mhi_cntrl->sw_ev_rings++;
		mhi_event->cl_manage = of_property_read_bool(child,
							"mhi,client-manage");
		mhi_event->offload_ev = of_property_read_bool(child,
							      "mhi,offload");
		mhi_event++;
	}

	/* we need msi for each event ring + additional one for BHI */
	mhi_cntrl->msi_required = mhi_cntrl->total_ev_rings + 1;
@@ -745,7 +769,7 @@ static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl,
	return 0;

error_ev_cfg:
	kfree(ev_cfg);

	kfree(mhi_cntrl->mhi_event);
	return -EINVAL;
}
@@ -977,7 +1001,7 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl)

		mhi_event->mhi_cntrl = mhi_cntrl;
		spin_lock_init(&mhi_event->lock);
		if (mhi_event->ctrl_ev)
		if (mhi_event->data_type == MHI_ER_CTRL_ELEMENT_TYPE)
			tasklet_init(&mhi_event->task, mhi_ctrl_ev_task,
				     (ulong)mhi_event);
		else
Loading