summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-04-20 16:10:27 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-04-20 16:10:27 -0700
commit9d26a7fb148d536594dbd18d7630533413fcc6bf (patch)
treed647734e132a9d20b1ea5eda563a524694048711
parente66fc6f5af6fc31695507a38eadb895d5ecc81fc (diff)
parent81fc1566e23e55669d835755eee1f1c49b995b4c (diff)
Merge "msm: mdss: dp: gracefully handle cable disconnect"
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c80
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h1
2 files changed, 66 insertions, 15 deletions
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index 25ce4a4279da..1e878e9a00cb 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -1055,26 +1055,28 @@ static int mdss_dp_wait4video_ready(struct mdss_dp_drv_pdata *dp_drv)
static void mdss_dp_update_cable_status(struct mdss_dp_drv_pdata *dp,
bool connected)
{
- mutex_lock(&dp->pd_msg_mutex);
+ mutex_lock(&dp->attention_lock);
pr_debug("cable_connected to %d\n", connected);
if (dp->cable_connected != connected)
dp->cable_connected = connected;
else
pr_debug("no change in cable status\n");
- mutex_unlock(&dp->pd_msg_mutex);
+ mutex_unlock(&dp->attention_lock);
}
static int dp_get_cable_status(struct platform_device *pdev, u32 vote)
{
- struct mdss_dp_drv_pdata *dp_ctrl = platform_get_drvdata(pdev);
+ struct mdss_dp_drv_pdata *dp = platform_get_drvdata(pdev);
u32 hpd;
- if (!dp_ctrl) {
+ if (!dp) {
DEV_ERR("%s: invalid input\n", __func__);
return -ENODEV;
}
- hpd = dp_ctrl->cable_connected;
+ mutex_lock(&dp->attention_lock);
+ hpd = dp->cable_connected;
+ mutex_unlock(&dp->attention_lock);
return hpd;
}
@@ -2043,7 +2045,6 @@ static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp,
bool notify = false;
bool connect;
- mutex_lock(&dp->pd_msg_mutex);
pr_debug("beginning notification\n");
if (status == dp->hpd_notification_status) {
pr_debug("No change in status %s --> %s\n",
@@ -2135,7 +2136,6 @@ notify:
end:
dp->hpd_notification_status = status;
- mutex_unlock(&dp->pd_msg_mutex);
return ret;
}
@@ -2423,12 +2423,16 @@ static ssize_t mdss_dp_rda_connected(struct device *dev,
{
ssize_t ret;
struct mdss_dp_drv_pdata *dp = mdss_dp_get_drvdata(dev);
+ bool cable_connected;
if (!dp)
return -EINVAL;
- ret = snprintf(buf, PAGE_SIZE, "%d\n", dp->cable_connected);
- pr_debug("%d\n", dp->cable_connected);
+ mutex_lock(&dp->attention_lock);
+ cable_connected = dp->cable_connected;
+ mutex_unlock(&dp->attention_lock);
+ ret = snprintf(buf, PAGE_SIZE, "%d\n", cable_connected);
+ pr_debug("%d\n", cable_connected);
return ret;
}
@@ -2597,6 +2601,7 @@ static ssize_t mdss_dp_wta_hpd(struct device *dev,
int hpd, rc;
ssize_t ret = strnlen(buf, PAGE_SIZE);
struct mdss_dp_drv_pdata *dp = mdss_dp_get_drvdata(dev);
+ bool cable_connected;
if (!dp) {
pr_err("invalid data\n");
@@ -2612,9 +2617,13 @@ static ssize_t mdss_dp_wta_hpd(struct device *dev,
}
dp->hpd = !!hpd;
- pr_debug("hpd=%d\n", dp->hpd);
+ mutex_lock(&dp->attention_lock);
+ cable_connected = dp->cable_connected;
+ mutex_unlock(&dp->attention_lock);
+ pr_debug("hpd=%d cable_connected=%s\n", dp->hpd,
+ cable_connected ? "true" : "false");
- if (dp->hpd && dp->cable_connected) {
+ if (dp->hpd && cable_connected) {
if (dp->alt_mode.current_state & DP_CONFIGURE_DONE) {
mdss_dp_host_init(&dp->panel_data);
mdss_dp_process_hpd_high(dp);
@@ -3248,10 +3257,21 @@ static int mdss_dp_event_thread(void *data)
ev_data = (struct mdss_dp_event_data *)data;
+ pr_debug("starting\n");
while (!kthread_should_stop()) {
wait_event(ev_data->event_q,
(ev_data->pndx != ev_data->gndx) ||
- kthread_should_stop());
+ kthread_should_stop() ||
+ kthread_should_park());
+ if (kthread_should_stop())
+ return 0;
+
+ if (kthread_should_park()) {
+ pr_debug("parking event thread\n");
+ kthread_parkme();
+ continue;
+ }
+
spin_lock_irqsave(&ev_data->event_lock, flag);
ev = &(ev_data->event_list[ev_data->gndx++]);
todo = ev->id;
@@ -3427,6 +3447,27 @@ static int mdss_dp_event_setup(struct mdss_dp_drv_pdata *dp)
return 0;
}
+static void mdss_dp_reset_event_list(struct mdss_dp_drv_pdata *dp)
+{
+ struct mdss_dp_event_data *ev_data = &dp->dp_event;
+
+ spin_lock(&ev_data->event_lock);
+ ev_data->pndx = ev_data->gndx = 0;
+ spin_unlock(&ev_data->event_lock);
+
+ mutex_lock(&dp->attention_lock);
+ INIT_LIST_HEAD(&dp->attention_head);
+ mutex_unlock(&dp->attention_lock);
+}
+
+static void mdss_dp_reset_sw_state(struct mdss_dp_drv_pdata *dp)
+{
+ pr_debug("enter\n");
+ mdss_dp_reset_event_list(dp);
+ atomic_set(&dp->notification_pending, 0);
+ complete_all(&dp->notification_comp);
+}
+
static void usbpd_connect_callback(struct usbpd_svid_handler *hdlr)
{
struct mdss_dp_drv_pdata *dp_drv;
@@ -3438,6 +3479,8 @@ static void usbpd_connect_callback(struct usbpd_svid_handler *hdlr)
}
mdss_dp_update_cable_status(dp_drv, true);
+ if (dp_drv->ev_thread)
+ kthread_unpark(dp_drv->ev_thread);
if (dp_drv->hpd)
dp_send_events(dp_drv, EV_USBPD_DISCOVER_MODES);
@@ -3457,6 +3500,9 @@ static void usbpd_disconnect_callback(struct usbpd_svid_handler *hdlr)
mdss_dp_update_cable_status(dp_drv, false);
dp_drv->alt_mode.current_state = UNKNOWN_STATE;
+ mdss_dp_reset_sw_state(dp_drv);
+ kthread_park(dp_drv->ev_thread);
+
/**
* Manually turn off the DP controller if we are in PHY
* testing mode.
@@ -3975,7 +4021,8 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
node->vdo = *vdos;
mutex_lock(&dp_drv->attention_lock);
- list_add_tail(&node->list, &dp_drv->attention_head);
+ if (dp_drv->cable_connected)
+ list_add_tail(&node->list, &dp_drv->attention_head);
mutex_unlock(&dp_drv->attention_lock);
dp_send_events(dp_drv, EV_USBPD_ATTENTION);
@@ -4093,6 +4140,11 @@ static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp)
reinit_completion(&dp->notification_comp);
mutex_lock(&dp->attention_lock);
+ if (!dp->cable_connected) {
+ pr_debug("cable disconnected, returning\n");
+ mutex_unlock(&dp->attention_lock);
+ goto exit;
+ }
node = list_first_entry(&dp->attention_head,
struct mdss_dp_attention_node, list);
@@ -4124,6 +4176,7 @@ static void mdss_dp_handle_attention(struct mdss_dp_drv_pdata *dp)
pr_debug("done processing item %d in the list\n", i);
};
+exit:
pr_debug("exit\n");
}
@@ -4199,7 +4252,6 @@ static int mdss_dp_probe(struct platform_device *pdev)
dp_drv->mask1 = EDP_INTR_MASK1;
dp_drv->mask2 = EDP_INTR_MASK2;
mutex_init(&dp_drv->emutex);
- mutex_init(&dp_drv->pd_msg_mutex);
mutex_init(&dp_drv->attention_lock);
mutex_init(&dp_drv->hdcp_mutex);
spin_lock_init(&dp_drv->lock);
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index e9f5a04e2d19..f358aad8a667 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -617,7 +617,6 @@ struct mdss_dp_drv_pdata {
struct completion notification_comp;
struct mutex aux_mutex;
struct mutex train_mutex;
- struct mutex pd_msg_mutex;
struct mutex attention_lock;
struct mutex hdcp_mutex;
bool cable_connected;