Merge "msm: mhi_dev: Add uevent support"
diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c
index c0c5357..47d5292 100644
--- a/drivers/platform/msm/mhi_dev/mhi.c
+++ b/drivers/platform/msm/mhi_dev/mhi.c
@@ -71,11 +71,12 @@
static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event,
unsigned long data);
static void mhi_ring_init_cb(void *user_data);
-static void mhi_update_state_info(uint32_t info);
+static void mhi_update_state_info(uint32_t uevent_idx, enum mhi_ctrl_info 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;
static void mhi_dev_transfer_completion_cb(void *mreq);
+static struct mhi_dev_uevent_info channel_state_info[MHI_MAX_CHANNELS];
/*
* mhi_dev_ring_cache_completion_cb () - Call back function called
@@ -454,7 +455,7 @@
return;
}
- mhi_update_state_info(MHI_STATE_CONNECTED);
+ mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONNECTED);
ep_pcie_mask_irq_event(mhi_ctx->phandle,
EP_PCIE_INT_EVT_MHI_A7, true);
@@ -825,16 +826,14 @@
static void mhi_dev_trigger_cb(void)
{
struct mhi_dev_ready_cb_info *info;
- uint32_t state_data;
+ enum mhi_ctrl_info state_data;
- mutex_lock(&mhi_ctx->mhi_lock);
list_for_each_entry(info, &mhi_ctx->client_cb_list, list)
if (info->cb) {
- mhi_ctrl_state_info(&state_data);
+ mhi_ctrl_state_info(info->cb_data.channel, &state_data);
info->cb_data.ctrl_info = state_data;
info->cb(&info->cb_data);
}
- mutex_unlock(&mhi_ctx->mhi_lock);
}
int mhi_dev_trigger_hw_acc_wakeup(struct mhi_dev *mhi)
@@ -937,6 +936,8 @@
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};
ch_id = el->generic.chid;
mhi_log(MHI_MSG_VERBOSE, "for channel:%d and cmd:%d\n",
@@ -1022,6 +1023,10 @@
/* Trigger callback to clients */
mhi_dev_trigger_cb();
+ mhi_update_state_info(ch_id, MHI_STATE_CONNECTED);
+ if (ch_id == MHI_CLIENT_MBIM_OUT)
+ kobject_uevent_env(&mhi_ctx->dev->kobj,
+ KOBJ_CHANGE, connected);
break;
case MHI_DEV_RING_EL_STOP:
if (ch_id >= HW_CHANNEL_BASE) {
@@ -1074,6 +1079,10 @@
pr_err("stop event send failed\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);
}
break;
case MHI_DEV_RING_EL_RESET:
@@ -1146,6 +1155,10 @@
if (rc)
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);
}
break;
default:
@@ -1327,7 +1340,7 @@
}
/* Update ctrl node */
- mhi_update_state_info(MHI_STATE_DISCONNECTED);
+ mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_DISCONNECTED);
flush_workqueue(mhi->ring_init_wq);
flush_workqueue(mhi->pending_ring_wq);
@@ -1808,7 +1821,7 @@
mhi_dev_write_to_host(mhi, &data_transfer, NULL,
MHI_DEV_DMA_SYNC);
}
- mhi_update_state_info(MHI_STATE_CONNECTED);
+ mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONNECTED);
atomic_set(&mhi->is_suspended, 0);
@@ -2369,7 +2382,7 @@
if (mhi_ctx->config_iatu || mhi_ctx->mhi_int)
enable_irq(mhi_ctx->mhi_irq);
- mhi_update_state_info(MHI_STATE_CONNECTED);
+ mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONFIGURED);
}
static void mhi_ring_init_cb(void *data)
@@ -2429,28 +2442,32 @@
}
EXPORT_SYMBOL(mhi_register_state_cb);
-static void mhi_update_state_info(uint32_t info)
+static void mhi_update_state_info(uint32_t uevent_idx, enum mhi_ctrl_info info)
{
struct mhi_dev_client_cb_reason reason;
- mhi_ctx->ctrl_info = info;
+ if (uevent_idx == MHI_DEV_UEVENT_CTRL)
+ mhi_ctx->ctrl_info = info;
- if (info == MHI_STATE_CONNECTED)
- return;
+ channel_state_info[uevent_idx].ctrl_info = info;
- reason.reason = MHI_DEV_CTRL_UPDATE;
- uci_ctrl_update(&reason);
-}
-
-int mhi_ctrl_state_info(uint32_t *info)
-{
- if (!info) {
- pr_err("Invalid info\n");
- return -EINVAL;
+ if (uevent_idx == MHI_CLIENT_QMI_OUT ||
+ uevent_idx == MHI_CLIENT_QMI_IN) {
+ /* For legacy reasons for QTI client */
+ reason.reason = MHI_DEV_CTRL_UPDATE;
+ uci_ctrl_update(&reason);
}
- *info = mhi_ctx->ctrl_info;
- mhi_log(MHI_MSG_VERBOSE, "ctrl:%d", mhi_ctx->ctrl_info);
+}
+
+int mhi_ctrl_state_info(uint32_t idx, uint32_t *info)
+{
+ if (idx == MHI_DEV_UEVENT_CTRL)
+ *info = mhi_ctx->ctrl_info;
+ else
+ *info = channel_state_info[idx].ctrl_info;
+
+ mhi_log(MHI_MSG_VERBOSE, "idx:%d, ctrl:%d", idx, *info);
return 0;
}
@@ -2945,7 +2962,8 @@
"Failed to create IPC logging context\n");
}
mhi_uci_init();
- mhi_update_state_info(MHI_STATE_CONFIGURED);
+ mhi_update_state_info(MHI_DEV_UEVENT_CTRL,
+ MHI_STATE_CONFIGURED);
}
INIT_WORK(&mhi_ctx->pcie_event, mhi_dev_pcie_handle_event);
diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h
index 38e52e2..b9120fc 100644
--- a/drivers/platform/msm/mhi_dev/mhi.h
+++ b/drivers/platform/msm/mhi_dev/mhi.h
@@ -275,7 +275,7 @@
#define MHI_ENV_VALUE 2
#define MHI_MASK_ROWS_CH_EV_DB 4
#define TRB_MAX_DATA_SIZE 8192
-#define MHI_CTRL_STATE 25
+#define MHI_CTRL_STATE 100
#define IPA_DMA_SYNC 1
#define IPA_DMA_ASYNC 0
@@ -607,6 +607,8 @@
bool mhi_int;
/* Registered client callback list */
struct list_head client_cb_list;
+
+ struct kobj_uevent_env kobj_env;
};
struct mhi_req {
@@ -712,6 +714,14 @@
MHI_MAX_CHANNELS = 102,
};
+/* Use ID 0 for legacy /dev/mhi_ctrl. Channel 0 is used for internal only */
+#define MHI_DEV_UEVENT_CTRL 0
+
+struct mhi_dev_uevent_info {
+ enum mhi_client_channel channel;
+ enum mhi_ctrl_info ctrl_info;
+};
+
struct mhi_dev_iov {
void *addr;
uint32_t buf_size;
@@ -1251,6 +1261,9 @@
/**
* mhi_ctrl_state_info() - Provide MHI state info
+ * @idx: Channel number idx. Look at channel_state_info and
+ * pass the index for the corresponding channel.
+ * @info: Return the control info.
* MHI_STATE=CONFIGURED - MHI device is present but not ready
* for data traffic.
* MHI_STATE=CONNECTED - MHI device is ready for data transfer.
@@ -1258,7 +1271,7 @@
* exposes device nodes for the supported MHI software
* channels.
*/
-int mhi_ctrl_state_info(uint32_t *info);
+int mhi_ctrl_state_info(uint32_t idx, uint32_t *info);
/**
* uci_ctrl_update() - Update UCI once TRE's are available for clients to
diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c
index 244cf04..ed02d0d 100644
--- a/drivers/platform/msm/mhi_dev/mhi_uci.c
+++ b/drivers/platform/msm/mhi_dev/mhi_uci.c
@@ -441,6 +441,61 @@
return rc;
}
+static void mhi_parse_state(char *buf, int *nbytes, uint32_t info)
+{
+ switch (info) {
+ case MHI_STATE_CONNECTED:
+ *nbytes = scnprintf(buf, MHI_CTRL_STATE,
+ "CONNECTED");
+ break;
+ case MHI_STATE_DISCONNECTED:
+ *nbytes = scnprintf(buf, MHI_CTRL_STATE,
+ "DISCONNECTED");
+ break;
+ case MHI_STATE_CONFIGURED:
+ default:
+ *nbytes = scnprintf(buf, MHI_CTRL_STATE,
+ "CONFIGURED");
+ break;
+ }
+}
+
+static int mhi_state_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ int rc, nbytes = 0;
+ uint32_t info = 0;
+ char buf[MHI_CTRL_STATE];
+
+ rc = mhi_ctrl_state_info(MHI_DEV_UEVENT_CTRL, &info);
+ if (rc) {
+ pr_err("Failed to obtain MHI_STATE\n");
+ return -EINVAL;
+ }
+
+ mhi_parse_state(buf, &nbytes, info);
+ add_uevent_var(env, "MHI_STATE=%s", buf);
+
+ rc = mhi_ctrl_state_info(MHI_CLIENT_QMI_OUT, &info);
+ if (rc) {
+ pr_err("Failed to obtain channel 14 state\n");
+ return -EINVAL;
+ }
+ nbytes = 0;
+ mhi_parse_state(buf, &nbytes, info);
+ add_uevent_var(env, "MHI_CHANNEL_STATE_14=%s", buf);
+
+ rc = mhi_ctrl_state_info(MHI_CLIENT_MBIM_OUT, &info);
+ if (rc) {
+ pr_err("Failed to obtain channel 12 state\n");
+ return -EINVAL;
+ }
+ nbytes = 0;
+ mhi_parse_state(buf, &nbytes, info);
+ add_uevent_var(env, "MHI_CHANNEL_STATE_12=%s", buf);
+
+ return 0;
+}
+
static ssize_t mhi_uci_ctrl_client_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *offp)
@@ -455,7 +510,7 @@
return -EINVAL;
uci_ctrl_handle = file->private_data;
- rc = mhi_ctrl_state_info(&info);
+ rc = mhi_ctrl_state_info(MHI_CLIENT_QMI_OUT, &info);
if (rc)
return -EINVAL;
@@ -993,6 +1048,8 @@
uci_ctxt.cdev_ctrl = NULL;
}
+ uci_ctxt.mhi_uci_class->dev_uevent = mhi_state_uevent;
+
return 0;
failed_char_add: