mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
HDMI: fix crash error when insert HDMI with following log:
Unable to handle kernel paging request at virtual address 40ce80f8
pgd = ffffffc001022000
[40ce80f8] *pgd=0000000025b19003, *pmd=000000001cb1f003, *pte=0000000000000000
Internal error: Oops: 96000005 [#1] PREEMPT SMP
Modules linked in: pvrsrvkm(O) drmboot(PO)
CPU: 7 PID: 2558 Comm: kworker/u16:1 Tainted: P W O 3.10.0 #66
Workqueue: hdmi-ff980000.hdmi hdmi_work_queue
task: ffffffc01ca83f00 ti: ffffffc033e00000 task.ti: ffffffc033e00000
PC is at hdmi_wq_insert+0xa4/0x2ac
LR is at hdmi_wq_insert+0x74/0x2ac
pc : [<ffffffc000341014>] lr : [<ffffffc000340fe4>] pstate: 60000145
Use inline fuction hdmi_destroy_modelist replace fb_destroy_modelist.
For unkown reason, variable struct hdmi *hdmi is deferent before and
after calling fb_destroy_modelist.
Signed-off-by: Zheng Yang <zhengyang@rock-chips.com>
This commit is contained in:
@@ -23,7 +23,7 @@ struct delayed_work *hdmi_submit_work(struct hdmi *hdmi,
|
||||
{
|
||||
struct hdmi_delayed_work *work;
|
||||
|
||||
DBG("%s event %04x delay %d", __func__, event, delay);
|
||||
DBG("%s event %04x delay %d\n", __func__, event, delay);
|
||||
|
||||
work = kmalloc(sizeof(*work), GFP_ATOMIC);
|
||||
|
||||
@@ -59,14 +59,14 @@ static void hdmi_send_uevent(struct hdmi *hdmi, int uevent)
|
||||
|
||||
static inline void hdmi_wq_set_output(struct hdmi *hdmi, int mute)
|
||||
{
|
||||
DBG("%s mute %d", __func__, mute);
|
||||
DBG("%s mute %d\n", __func__, mute);
|
||||
if (hdmi->ops->setmute)
|
||||
hdmi->ops->setmute(hdmi, mute);
|
||||
}
|
||||
|
||||
static inline void hdmi_wq_set_audio(struct hdmi *hdmi)
|
||||
{
|
||||
DBG("%s", __func__);
|
||||
DBG("%s\n", __func__);
|
||||
if (hdmi->ops->setaudio)
|
||||
hdmi->ops->setaudio(hdmi, &hdmi->audio);
|
||||
}
|
||||
@@ -75,7 +75,7 @@ static void hdmi_wq_set_video(struct hdmi *hdmi)
|
||||
{
|
||||
struct hdmi_video video;
|
||||
|
||||
DBG("%s", __func__);
|
||||
DBG("%s\n", __func__);
|
||||
|
||||
video.vic = hdmi->vic & HDMI_VIC_MASK;
|
||||
video.sink_hdmi = hdmi->edid.sink_hdmi;
|
||||
@@ -120,6 +120,16 @@ static void hdmi_wq_set_video(struct hdmi *hdmi)
|
||||
hdmi->ops->setvideo(hdmi, &video);
|
||||
}
|
||||
|
||||
static inline void hdmi_destroy_modelist(struct list_head *head)
|
||||
{
|
||||
struct list_head *pos, *n;
|
||||
|
||||
list_for_each_safe(pos, n, head) {
|
||||
list_del(pos);
|
||||
kfree(pos);
|
||||
}
|
||||
}
|
||||
|
||||
static void hdmi_wq_parse_edid(struct hdmi *hdmi)
|
||||
{
|
||||
struct hdmi_edid *pedid;
|
||||
@@ -129,13 +139,12 @@ static void hdmi_wq_parse_edid(struct hdmi *hdmi)
|
||||
if (hdmi == NULL)
|
||||
return;
|
||||
|
||||
DBG("%s", __func__);
|
||||
DBG("%s\n", __func__);
|
||||
|
||||
pedid = &(hdmi->edid);
|
||||
fb_destroy_modelist(&pedid->modelist);
|
||||
hdmi_destroy_modelist(&(pedid->modelist));
|
||||
memset(pedid, 0, sizeof(struct hdmi_edid));
|
||||
INIT_LIST_HEAD(&pedid->modelist);
|
||||
|
||||
buff = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
|
||||
if (buff == NULL) {
|
||||
dev_err(hdmi->dev,
|
||||
@@ -206,7 +215,7 @@ out:
|
||||
|
||||
static void hdmi_wq_insert(struct hdmi *hdmi)
|
||||
{
|
||||
DBG("%s", __func__);
|
||||
DBG("%s\n", __func__);
|
||||
if (hdmi->ops->insert)
|
||||
hdmi->ops->insert(hdmi);
|
||||
hdmi_wq_parse_edid(hdmi);
|
||||
@@ -235,7 +244,7 @@ static void hdmi_wq_remove(struct hdmi *hdmi)
|
||||
struct list_head *pos, *n;
|
||||
struct rk_screen screen;
|
||||
|
||||
DBG("%s", __func__);
|
||||
DBG("%s\n", __func__);
|
||||
if (hdmi->ops->remove)
|
||||
hdmi->ops->remove(hdmi);
|
||||
#ifdef CONFIG_SWITCH
|
||||
@@ -324,7 +333,7 @@ static void hdmi_work_queue(struct work_struct *work)
|
||||
case HDMI_HPD_CHANGE:
|
||||
if (hdmi->ops->getstatus)
|
||||
hpd = hdmi->ops->getstatus(hdmi);
|
||||
DBG("hdmi_work_queue() - hpd is %d hotplug is %d",
|
||||
DBG("hdmi_work_queue() - hpd is %d hotplug is %d\n",
|
||||
hpd, hdmi->hotplug);
|
||||
if (hpd != hdmi->hotplug) {
|
||||
if (hpd == HDMI_HPD_ACTIVED) {
|
||||
@@ -427,7 +436,7 @@ struct hdmi *rockchip_hdmi_register(struct hdmi_property *property,
|
||||
if (i == HDMI_MAX_ID)
|
||||
return NULL;
|
||||
|
||||
DBG("hdmi_register() - video source %d display %d",
|
||||
DBG("hdmi_register() - video source %d display %d\n",
|
||||
property->videosrc, property->display);
|
||||
|
||||
hdmi = kmalloc(sizeof(*hdmi), GFP_KERNEL);
|
||||
@@ -514,7 +523,7 @@ void rockchip_hdmi_unregister(struct hdmi *hdmi)
|
||||
switch_dev_unregister(&(hdmi->switchdev));
|
||||
#endif
|
||||
hdmi_unregister_display_sysfs(hdmi);
|
||||
fb_destroy_modelist(&hdmi->edid.modelist);
|
||||
hdmi_destroy_modelist(&hdmi->edid.modelist);
|
||||
kfree(hdmi->edid.audio);
|
||||
if (hdmi->edid.specs) {
|
||||
kfree(hdmi->edid.specs->modedb);
|
||||
|
||||
Reference in New Issue
Block a user