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

Commit 5709dc37 authored by Siva Kumar Akkireddi's avatar Siva Kumar Akkireddi Committed by Siddartha Mohanadoss
Browse files

msm: mhi_dev: Generalize uevents to apply for all MHI clients



Channel state updates are sent via uevents to MHI clients. The
channel attribute table specifies which clients need to be
notified.

Change-Id: I80afa8baa0bafab36851dfcaea6c86fd8a1a8e71
Signed-off-by: default avatarSiva Kumar Akkireddi <sivaa@codeaurora.org>
parent 56aa07bd
Loading
Loading
Loading
Loading
+25 −26
Original line number Diff line number Diff line
@@ -1243,8 +1243,6 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi,
	struct mhi_addr host_addr;
	struct mhi_dev_channel *ch;
	struct mhi_dev_ring *ring;
	char *connected[2] = { "MHI_CHANNEL_STATE_12=CONNECTED", NULL};
	char *disconnected[2] = { "MHI_CHANNEL_STATE_12=DISCONNECTED", NULL};
	union mhi_dev_ring_ctx *evt_ctx;

	ch_id = el->generic.chid;
@@ -1349,9 +1347,7 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi,
		mhi_update_state_info(ch_id, MHI_STATE_CONNECTED);
		/* Trigger callback to clients */
		mhi_dev_trigger_cb(ch_id);
		if (ch_id == MHI_CLIENT_MBIM_OUT)
			kobject_uevent_env(&mhi_ctx->dev->kobj,
						KOBJ_CHANGE, connected);
		mhi_uci_chan_state_notify(mhi, ch_id, MHI_STATE_CONNECTED);
		break;
	case MHI_DEV_RING_EL_STOP:
		if (ch_id >= HW_CHANNEL_BASE) {
@@ -1405,9 +1401,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi,

			mutex_unlock(&ch->ch_lock);
			mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED);
			if (ch_id == MHI_CLIENT_MBIM_OUT)
				kobject_uevent_env(&mhi_ctx->dev->kobj,
						KOBJ_CHANGE, disconnected);
			/* Trigger callback to clients */
			mhi_dev_trigger_cb(ch_id);
			mhi_uci_chan_state_notify(mhi, ch_id,
					MHI_STATE_DISCONNECTED);
		}
		break;
	case MHI_DEV_RING_EL_RESET:
@@ -1481,9 +1478,9 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi,
				pr_err("Error sending command completion event\n");
			mutex_unlock(&ch->ch_lock);
			mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED);
			if (ch_id == MHI_CLIENT_MBIM_OUT)
				kobject_uevent_env(&mhi_ctx->dev->kobj,
						KOBJ_CHANGE, disconnected);
			mhi_dev_trigger_cb(ch_id);
			mhi_uci_chan_state_notify(mhi, ch_id,
					MHI_STATE_DISCONNECTED);
		}
		break;
	default:
@@ -1646,13 +1643,25 @@ static void mhi_dev_check_channel_interrupt(struct mhi_dev *mhi)
	}
}

static void mhi_update_state_info_all(enum mhi_ctrl_info info)
{
	int i;
	struct mhi_dev_client_cb_reason reason;

	mhi_ctx->ctrl_info = info;
	for (i = 0; i < MHI_MAX_CHANNELS; ++i)
		channel_state_info[i].ctrl_info = info;

	/* For legacy reasons for QTI client */
	reason.reason = MHI_DEV_CTRL_UPDATE;
	uci_ctrl_update(&reason);
}

static int mhi_dev_abort(struct mhi_dev *mhi)
{
	struct mhi_dev_channel *ch;
	struct mhi_dev_ring *ring;
	int ch_id = 0, rc = 0;
	char *disconnected_12[2] = { "MHI_CHANNEL_STATE_12=DISCONNECTED", NULL};
	char *disconnected_14[2] = { "MHI_CHANNEL_STATE_14=DISCONNECTED", NULL};

	/* Hard stop all the channels */
	for (ch_id = 0; ch_id < mhi->cfg.channels; ch_id++) {
@@ -1666,19 +1675,9 @@ static int mhi_dev_abort(struct mhi_dev *mhi)
		mutex_unlock(&ch->ch_lock);
	}

	/* Update ctrl node */
	mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_DISCONNECTED);
	mhi_update_state_info(MHI_CLIENT_MBIM_OUT, MHI_STATE_DISCONNECTED);
	mhi_update_state_info(MHI_CLIENT_QMI_OUT, MHI_STATE_DISCONNECTED);
	rc = kobject_uevent_env(&mhi_ctx->dev->kobj,
				KOBJ_CHANGE, disconnected_12);
	if (rc)
		pr_err("Error sending uevent:%d\n", rc);

	rc = kobject_uevent_env(&mhi_ctx->dev->kobj,
				KOBJ_CHANGE, disconnected_14);
	if (rc)
		pr_err("Error sending uevent:%d\n", rc);
	/* Update channel state and notify clients */
	mhi_update_state_info_all(MHI_STATE_DISCONNECTED);
	mhi_uci_chan_state_notify_all(mhi, MHI_STATE_DISCONNECTED);

	flush_workqueue(mhi->ring_init_wq);
	flush_workqueue(mhi->pending_ring_wq);
+12 −0
Original line number Diff line number Diff line
@@ -1069,5 +1069,17 @@ int mhi_dev_net_interface_init(void);
void mhi_dev_notify_a7_event(struct mhi_dev *mhi);

void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason);
/**
 * mhi_uci_chan_state_notify_all - Notifies channel state updates for
 *				all clients who have uevents enabled.
 */
void mhi_uci_chan_state_notify_all(struct mhi_dev *mhi,
		enum mhi_ctrl_info ch_state);
/**
 * mhi_uci_chan_state_notify - Notifies channel state update to the client
 *				if uevents are enabled.
 */
void mhi_uci_chan_state_notify(struct mhi_dev *mhi,
		enum mhi_client_channel ch_id, enum mhi_ctrl_info ch_state);

#endif /* _MHI_H */
+75 −2
Original line number Diff line number Diff line
@@ -83,6 +83,8 @@ struct chan_attr {
	void (*tre_notif_cb)(struct mhi_dev_client_cb_reason *reason);
	/* Write completion - false if not needed */
	bool wr_cmpl;
	/* Uevent broadcast of channel state */
	bool state_bcast;

};

@@ -146,7 +148,10 @@ static const struct chan_attr uci_chan_attr_table[] = {
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_OUT,
		NULL,
		NULL
		NULL,
		NULL,
		false,
		true
	},
	{
		MHI_CLIENT_MBIM_IN,
@@ -162,7 +167,10 @@ static const struct chan_attr uci_chan_attr_table[] = {
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_OUT,
		NULL,
		NULL
		NULL,
		NULL,
		false,
		true
	},
	{
		MHI_CLIENT_QMI_IN,
@@ -1150,6 +1158,71 @@ static ssize_t mhi_uci_client_write(struct file *file,

}

void mhi_uci_chan_state_notify_all(struct mhi_dev *mhi,
		enum mhi_ctrl_info ch_state)
{
	unsigned int i;
	const struct chan_attr *chan_attrib;

	for (i = 0; i < ARRAY_SIZE(uci_chan_attr_table); i++) {
		chan_attrib = &uci_chan_attr_table[i];
		if (chan_attrib->state_bcast) {
			uci_log(UCI_DBG_ERROR, "Calling notify for ch %d\n",
					chan_attrib->chan_id);
			mhi_uci_chan_state_notify(mhi, chan_attrib->chan_id,
					ch_state);
		}
	}
}
EXPORT_SYMBOL(mhi_uci_chan_state_notify_all);

void mhi_uci_chan_state_notify(struct mhi_dev *mhi,
		enum mhi_client_channel ch_id, enum mhi_ctrl_info ch_state)
{
	struct uci_client *uci_handle;
	char *buf[2];
	int rc;

	if (ch_id < 0 || ch_id >= MHI_MAX_SOFTWARE_CHANNELS) {
		uci_log(UCI_DBG_ERROR, "Invalid chan %d\n", ch_id);
		return;
	}

	uci_handle = &uci_ctxt.client_handles[CHAN_TO_CLIENT(ch_id)];
	if (!uci_handle->in_chan_attr ||
		!uci_handle->in_chan_attr->state_bcast) {
		uci_log(UCI_DBG_VERBOSE, "Uevents not enabled for chan %d\n",
				ch_id);
		return;
	}

	if (ch_state == MHI_STATE_CONNECTED) {
		buf[0] = kasprintf(GFP_KERNEL,
				"MHI_CHANNEL_STATE_%d=CONNECTED", ch_id);
		buf[1] = NULL;
	} else if (ch_state == MHI_STATE_DISCONNECTED) {
		buf[0] = kasprintf(GFP_KERNEL,
				"MHI_CHANNEL_STATE_%d=DISCONNECTED", ch_id);
		buf[1] = NULL;
	} else {
		uci_log(UCI_DBG_ERROR, "Unsupported chan state %d\n", ch_state);
		return;
	}

	if (!buf[0]) {
		uci_log(UCI_DBG_ERROR, "kasprintf failed for uevent buf!\n");
		return;
	}

	rc = kobject_uevent_env(&mhi->dev->kobj, KOBJ_CHANGE, buf);
	if (rc)
		uci_log(UCI_DBG_ERROR,
				"Sending uevent failed for chan %d\n", ch_id);

	kfree(buf[0]);
}
EXPORT_SYMBOL(mhi_uci_chan_state_notify);

void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason)
{
	struct uci_ctrl *uci_ctrl_handle = NULL;