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

Commit 016427da authored by Siva Kumar Akkireddi's avatar Siva Kumar Akkireddi
Browse files

msm: mhi_dev: Switch to look-up table for UCI channel attributes



Use a look-up table to easily add or remove support for UCI SW channels.
The table includes the channel id, direction, TRB size, number of TRBs
and a boolean flag indicating whether to register a channel state change
notification with the MHI driver.

Change-Id: I8697c24ee559546e279eac51cf9365d7570612e3
Signed-off-by: default avatarSiva Kumar Akkireddi <sivaa@codeaurora.org>
parent c60b52df
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -712,6 +712,7 @@ enum mhi_client_channel {
	MHI_CLIENT_RESERVED_2_LOWER = 102,
	MHI_CLIENT_RESERVED_2_UPPER = 127,
	MHI_MAX_CHANNELS = 102,
	MHI_CLIENT_INVALID = 0xFFFFFFFF
};

/* Use ID 0 for legacy /dev/mhi_ctrl. Channel 0 is used for internal only */
+185 −93
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@
#define MHI_SOFTWARE_CLIENT_LIMIT	(MHI_MAX_SOFTWARE_CHANNELS/2)
#define MHI_UCI_IPC_LOG_PAGES		(100)

#define MAX_NR_TRBS_PER_CHAN		1
#define MAX_NR_TRBS_PER_CHAN		9
#define MHI_QTI_IFACE_ID		4
#define DEVICE_NAME "mhi"

@@ -70,7 +70,131 @@ struct chan_attr {
	u32 nr_trbs;
	/* direction of the channel, see enum mhi_chan_dir */
	enum mhi_chan_dir dir;
	u32 uci_ownership;
	/* need to register mhi channel state change callback */
	bool register_cb;
};

/* UCI channel attributes table */
static const struct chan_attr uci_chan_attr_table[] = {
	{
		MHI_CLIENT_LOOPBACK_OUT,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_OUT,
		false
	},
	{
		MHI_CLIENT_LOOPBACK_IN,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_IN,
		false
	},
	{
		MHI_CLIENT_SAHARA_OUT,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_OUT,
		false
	},
	{
		MHI_CLIENT_SAHARA_IN,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_IN,
		false
	},
	{
		MHI_CLIENT_EFS_OUT,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_OUT,
		false
	},
	{
		MHI_CLIENT_EFS_IN,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_IN,
		false
	},
	{
		MHI_CLIENT_MBIM_OUT,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_OUT,
		false
	},
	{
		MHI_CLIENT_MBIM_IN,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_IN,
		false
	},
	{
		MHI_CLIENT_QMI_OUT,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_OUT,
		false
	},
	{
		MHI_CLIENT_QMI_IN,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_IN,
		false
	},
	{
		MHI_CLIENT_IP_CTRL_0_OUT,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_OUT,
		false
	},
	{
		MHI_CLIENT_IP_CTRL_0_IN,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_IN,
		false
	},
	{
		MHI_CLIENT_IP_CTRL_1_OUT,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_OUT,
		false
	},
	{
		MHI_CLIENT_IP_CTRL_1_IN,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_IN,
		false
	},
	{
		MHI_CLIENT_DUN_OUT,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_OUT,
		false
	},
	{
		MHI_CLIENT_DUN_IN,
		TRB_MAX_DATA_SIZE,
		MAX_NR_TRBS_PER_CHAN,
		MHI_DIR_IN,
		false
	},
	{ /* Must be the last */
		MHI_CLIENT_INVALID,
		0,
		0,
		MHI_DIR_INVALID,
		false
	},
};

struct uci_ctrl {
@@ -87,6 +211,8 @@ struct uci_client {
	u32 in_chan;
	struct mhi_dev_client *out_handle;
	struct mhi_dev_client *in_handle;
	const struct chan_attr *in_chan_attr;
	const struct chan_attr *out_chan_attr;
	wait_queue_head_t read_wq;
	wait_queue_head_t write_wq;
	atomic_t read_data_ready;
@@ -104,7 +230,6 @@ struct uci_client {
};

struct mhi_uci_ctxt_t {
	struct chan_attr chan_attrib[MHI_MAX_SOFTWARE_CHANNELS];
	struct uci_client client_handles[MHI_SOFTWARE_CLIENT_LIMIT];
	struct uci_ctrl ctrl_handle;
	void (*event_notifier)(struct mhi_dev_client_cb_reason *cb);
@@ -119,6 +244,7 @@ struct mhi_uci_ctxt_t {
};

#define CHAN_TO_CLIENT(_CHAN_NR) (_CHAN_NR / 2)
#define CLIENT_TO_CHAN(_CLIENT_NR) (_CLIENT_NR * 2)

#define uci_log(_msg_lvl, _msg, ...) do { \
	if (_msg_lvl >= mhi_uci_msg_lvl) { \
@@ -156,7 +282,7 @@ static int mhi_init_read_chan(struct uci_client *client_handle,
{
	int rc = 0;
	u32 i, j;
	struct chan_attr *chan_attributes;
	const struct chan_attr *in_chan_attr;
	size_t buf_size;
	void *data_loc;

@@ -169,10 +295,15 @@ static int mhi_init_read_chan(struct uci_client *client_handle,
		return -EINVAL;
	}

	chan_attributes = &uci_ctxt.chan_attrib[chan];
	buf_size = chan_attributes->max_packet_size;
	in_chan_attr = client_handle->in_chan_attr;
	if (!in_chan_attr) {
		uci_log(UCI_DBG_ERROR, "Null channel attributes for chan %d\n",
				client_handle->in_chan);
		return -EINVAL;
	}
	buf_size = in_chan_attr->max_packet_size;

	for (i = 0; i < (chan_attributes->nr_trbs); i++) {
	for (i = 0; i < (in_chan_attr->nr_trbs); i++) {
		data_loc = kmalloc(buf_size, GFP_KERNEL);
		if (!data_loc) {
			rc = -ENOMEM;
@@ -397,20 +528,11 @@ static int mhi_uci_client_release(struct inode *mhi_inode,
		struct file *file_handle)
{
	struct uci_client *uci_handle = file_handle->private_data;
	struct mhi_uci_ctxt_t *uci_ctxt;
	u32 nr_in_bufs = 0;
	int rc = 0;
	int in_chan = 0;
	u32 buf_size = 0;

	if (!uci_handle)
		return -EINVAL;

	uci_ctxt = uci_handle->uci_ctxt;
	in_chan = iminor(mhi_inode) + 1;
	nr_in_bufs = uci_ctxt->chan_attrib[in_chan].nr_trbs;
	buf_size = uci_ctxt->chan_attrib[in_chan].max_packet_size;

	if (atomic_sub_return(1, &uci_handle->ref_count) == 0) {
		uci_log(UCI_DBG_DBG,
				"Last client left, closing channel 0x%x\n",
@@ -750,55 +872,26 @@ static ssize_t mhi_uci_client_write(struct file *file,

static int uci_init_client_attributes(struct mhi_uci_ctxt_t *uci_ctxt)
{
	u32 i = 0;
	u32 data_size = TRB_MAX_DATA_SIZE;
	u32 index = 0;
	u32 i;
	u32 index;
	struct uci_client *client;
	struct chan_attr *chan_attrib = NULL;

	for (i = 0; i < ARRAY_SIZE(uci_ctxt->chan_attrib); i++) {
		chan_attrib = &uci_ctxt->chan_attrib[i];
		switch (i) {
		case MHI_CLIENT_LOOPBACK_OUT:
		case MHI_CLIENT_LOOPBACK_IN:
		case MHI_CLIENT_SAHARA_OUT:
		case MHI_CLIENT_SAHARA_IN:
		case MHI_CLIENT_EFS_OUT:
		case MHI_CLIENT_EFS_IN:
		case MHI_CLIENT_MBIM_OUT:
		case MHI_CLIENT_MBIM_IN:
		case MHI_CLIENT_QMI_OUT:
		case MHI_CLIENT_QMI_IN:
		case MHI_CLIENT_IP_CTRL_0_OUT:
		case MHI_CLIENT_IP_CTRL_0_IN:
		case MHI_CLIENT_IP_CTRL_1_OUT:
		case MHI_CLIENT_IP_CTRL_1_IN:
		case MHI_CLIENT_DUN_OUT:
		case MHI_CLIENT_DUN_IN:
			chan_attrib->uci_ownership = 1;
			break;
		default:
			chan_attrib->uci_ownership = 0;
	const struct chan_attr *chan_attrib;

	for (i = 0; i < ARRAY_SIZE(uci_chan_attr_table); i += 2) {
		chan_attrib = &uci_chan_attr_table[i];
		if (chan_attrib->chan_id == MHI_CLIENT_INVALID)
			break;
		}
		if (chan_attrib->uci_ownership) {
			chan_attrib->chan_id = i;
			chan_attrib->max_packet_size = data_size;
		index = CHAN_TO_CLIENT(i);
		client = &uci_ctxt->client_handles[index];
			chan_attrib->nr_trbs = 9;
		client->out_chan_attr = chan_attrib;
		client->in_chan_attr = ++chan_attrib;
		client->in_buf_list =
			      kmalloc(sizeof(struct mhi_dev_iov) *
					      chan_attrib->nr_trbs,
			kcalloc(chan_attrib->nr_trbs,
					sizeof(struct mhi_dev_iov),
					GFP_KERNEL);
			if (client->in_buf_list == NULL)
		if (!client->in_buf_list)
			return -ENOMEM;
	}
		if (i % 2 == 0)
			chan_attrib->dir = MHI_DIR_OUT;
		else
			chan_attrib->dir = MHI_DIR_IN;
	}
	return 0;
}

@@ -949,18 +1042,16 @@ int mhi_uci_init(void)
	uci_log(UCI_DBG_INFO, "Registering for MHI events.\n");

	for (i = 0; i < MHI_SOFTWARE_CLIENT_LIMIT; i++) {
		if (uci_ctxt.chan_attrib[i * 2].uci_ownership) {
		mhi_client = &uci_ctxt.client_handles[i];

		if (!mhi_client->in_chan_attr)
			continue;
		r = mhi_register_client(mhi_client, i);

		if (r) {
			uci_log(UCI_DBG_CRITICAL,
				"Failed to reg client %d ret %d\n",
				r, i);
		}
	}
	}

	init_waitqueue_head(&uci_ctxt.ctrl_handle.ctrl_wq);
	uci_log(UCI_DBG_INFO, "Allocating char devices.\n");
@@ -992,7 +1083,9 @@ int mhi_uci_init(void)

	uci_log(UCI_DBG_INFO, "Setting up device nodes.\n");
	for (i = 0; i < MHI_SOFTWARE_CLIENT_LIMIT; i++) {
		if (uci_ctxt.chan_attrib[i*2].uci_ownership) {
		mhi_client = &uci_ctxt.client_handles[i];
		if (!mhi_client->in_chan_attr)
			continue;
		cdev_init(&uci_ctxt.cdev[i], &mhi_uci_client_fops);
		uci_ctxt.cdev[i].owner = THIS_MODULE;
		r = cdev_add(&uci_ctxt.cdev[i],
@@ -1016,7 +1109,6 @@ int mhi_uci_init(void)
			goto failed_device_create;
		}
	}
	}

	/* Control node */
	uci_ctxt.cdev_ctrl = cdev_alloc();