mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-28 13:16:41 +00:00
media_build: fix TT-S2-3600
- fixes kernel oops see patch notes
This commit is contained in:
parent
c6c4c1d28c
commit
d70dba550e
@ -1,6 +1,6 @@
|
||||
--- a/backports/backports.txt
|
||||
+++ b/backports/backports.txt
|
||||
@@ -25,6 +25,13 @@
|
||||
@@ -25,6 +25,14 @@
|
||||
add pr_fmt.patch
|
||||
add debug.patch
|
||||
add drx39xxj.patch
|
||||
@ -11,6 +11,7 @@
|
||||
+add linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch
|
||||
+add linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch
|
||||
+add linux-062-imon_pad_ignore_diagonal.patch
|
||||
+add linux-240-pctv452e_kernel_oops_in_4.9.patch
|
||||
|
||||
[4.8.255]
|
||||
add v4.8_user_pages_flag.patch
|
||||
|
@ -0,0 +1,311 @@
|
||||
fixes:
|
||||
dvb-usb: found a 'Technotrend TT Connect S2-3600' in warm state.
|
||||
pctv452e: pctv452e_power_ctrl: 1
|
||||
|
||||
Unable to handle kernel NULL pointer dereference at virtual address 00000000
|
||||
pgd = adb60000
|
||||
[00000000] *pgd=00000000
|
||||
Internal error: Oops: 805 [#1] SMP ARM
|
||||
|
||||
fixed in kernel 4.10
|
||||
|
||||
---
|
||||
From 48775cb73c2e26b7ca9d679875a6e570c8b8e124 Mon Sep 17 00:00:00 2001
|
||||
From: Max Kellermann <max.kellermann@gmail.com>
|
||||
Date: Thu, 15 Dec 2016 19:51:07 -0200
|
||||
Subject: [PATCH] [media] pctv452e: move buffer to heap, no mutex
|
||||
|
||||
commit 73d5c5c864f4 ("[media] pctv452e: don't do DMA on stack") caused
|
||||
a NULL pointer dereference which occurs when dvb_usb_init()
|
||||
calls dvb_usb_device_power_ctrl() for the first time, before the
|
||||
frontend has been attached. It also caused a recursive deadlock because
|
||||
tt3650_ci_msg_locked() has already locked the mutex.
|
||||
|
||||
So, partially revert it, but move the buffer to the heap
|
||||
(DMA capable), not to the stack (may not be DMA capable).
|
||||
Instead of sharing one buffer which needs mutex protection,
|
||||
do a new heap allocation for each call.
|
||||
|
||||
Fixes: commit 73d5c5c864f4 ("[media] pctv452e: don't do DMA on stack")
|
||||
|
||||
---
|
||||
drivers/media/usb/dvb-usb/pctv452e.c | 133 +++++++++++++++++++----------------
|
||||
1 file changed, 72 insertions(+), 61 deletions(-)
|
||||
|
||||
diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c
|
||||
index 07fa08b..d54ebe7 100644
|
||||
--- a/drivers/media/usb/dvb-usb/pctv452e.c
|
||||
+++ b/drivers/media/usb/dvb-usb/pctv452e.c
|
||||
@@ -97,14 +97,13 @@ struct pctv452e_state {
|
||||
u8 c; /* transaction counter, wraps around... */
|
||||
u8 initialized; /* set to 1 if 0x15 has been sent */
|
||||
u16 last_rc_key;
|
||||
-
|
||||
- unsigned char data[80];
|
||||
};
|
||||
|
||||
static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
|
||||
unsigned int write_len, unsigned int read_len)
|
||||
{
|
||||
struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
|
||||
+ u8 *buf;
|
||||
u8 id;
|
||||
unsigned int rlen;
|
||||
int ret;
|
||||
@@ -114,36 +113,39 @@ static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
- mutex_lock(&state->ca_mutex);
|
||||
+ buf = kmalloc(64, GFP_KERNEL);
|
||||
+ if (!buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
id = state->c++;
|
||||
|
||||
- state->data[0] = SYNC_BYTE_OUT;
|
||||
- state->data[1] = id;
|
||||
- state->data[2] = cmd;
|
||||
- state->data[3] = write_len;
|
||||
+ buf[0] = SYNC_BYTE_OUT;
|
||||
+ buf[1] = id;
|
||||
+ buf[2] = cmd;
|
||||
+ buf[3] = write_len;
|
||||
|
||||
- memcpy(state->data + 4, data, write_len);
|
||||
+ memcpy(buf + 4, data, write_len);
|
||||
|
||||
rlen = (read_len > 0) ? 64 : 0;
|
||||
- ret = dvb_usb_generic_rw(d, state->data, 4 + write_len,
|
||||
- state->data, rlen, /* delay_ms */ 0);
|
||||
+ ret = dvb_usb_generic_rw(d, buf, 4 + write_len,
|
||||
+ buf, rlen, /* delay_ms */ 0);
|
||||
if (0 != ret)
|
||||
goto failed;
|
||||
|
||||
ret = -EIO;
|
||||
- if (SYNC_BYTE_IN != state->data[0] || id != state->data[1])
|
||||
+ if (SYNC_BYTE_IN != buf[0] || id != buf[1])
|
||||
goto failed;
|
||||
|
||||
- memcpy(data, state->data + 4, read_len);
|
||||
+ memcpy(data, buf + 4, read_len);
|
||||
|
||||
- mutex_unlock(&state->ca_mutex);
|
||||
+ kfree(buf);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
err("CI error %d; %02X %02X %02X -> %*ph.",
|
||||
- ret, SYNC_BYTE_OUT, id, cmd, 3, state->data);
|
||||
+ ret, SYNC_BYTE_OUT, id, cmd, 3, buf);
|
||||
|
||||
- mutex_unlock(&state->ca_mutex);
|
||||
+ kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -410,53 +412,57 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,
|
||||
u8 *rcv_buf, u8 rcv_len)
|
||||
{
|
||||
struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
|
||||
+ u8 *buf;
|
||||
u8 id;
|
||||
int ret;
|
||||
|
||||
- mutex_lock(&state->ca_mutex);
|
||||
+ buf = kmalloc(64, GFP_KERNEL);
|
||||
+ if (!buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
id = state->c++;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (snd_len > 64 - 7 || rcv_len > 64 - 7)
|
||||
goto failed;
|
||||
|
||||
- state->data[0] = SYNC_BYTE_OUT;
|
||||
- state->data[1] = id;
|
||||
- state->data[2] = PCTV_CMD_I2C;
|
||||
- state->data[3] = snd_len + 3;
|
||||
- state->data[4] = addr << 1;
|
||||
- state->data[5] = snd_len;
|
||||
- state->data[6] = rcv_len;
|
||||
+ buf[0] = SYNC_BYTE_OUT;
|
||||
+ buf[1] = id;
|
||||
+ buf[2] = PCTV_CMD_I2C;
|
||||
+ buf[3] = snd_len + 3;
|
||||
+ buf[4] = addr << 1;
|
||||
+ buf[5] = snd_len;
|
||||
+ buf[6] = rcv_len;
|
||||
|
||||
- memcpy(state->data + 7, snd_buf, snd_len);
|
||||
+ memcpy(buf + 7, snd_buf, snd_len);
|
||||
|
||||
- ret = dvb_usb_generic_rw(d, state->data, 7 + snd_len,
|
||||
- state->data, /* rcv_len */ 64,
|
||||
+ ret = dvb_usb_generic_rw(d, buf, 7 + snd_len,
|
||||
+ buf, /* rcv_len */ 64,
|
||||
/* delay_ms */ 0);
|
||||
if (ret < 0)
|
||||
goto failed;
|
||||
|
||||
/* TT USB protocol error. */
|
||||
ret = -EIO;
|
||||
- if (SYNC_BYTE_IN != state->data[0] || id != state->data[1])
|
||||
+ if (SYNC_BYTE_IN != buf[0] || id != buf[1])
|
||||
goto failed;
|
||||
|
||||
/* I2C device didn't respond as expected. */
|
||||
ret = -EREMOTEIO;
|
||||
- if (state->data[5] < snd_len || state->data[6] < rcv_len)
|
||||
+ if (buf[5] < snd_len || buf[6] < rcv_len)
|
||||
goto failed;
|
||||
|
||||
- memcpy(rcv_buf, state->data + 7, rcv_len);
|
||||
- mutex_unlock(&state->ca_mutex);
|
||||
+ memcpy(rcv_buf, buf + 7, rcv_len);
|
||||
|
||||
+ kfree(buf);
|
||||
return rcv_len;
|
||||
|
||||
failed:
|
||||
err("I2C error %d; %02X %02X %02X %02X %02X -> %*ph",
|
||||
ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len,
|
||||
- 7, state->data);
|
||||
+ 7, buf);
|
||||
|
||||
- mutex_unlock(&state->ca_mutex);
|
||||
+ kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -505,7 +511,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter)
|
||||
static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
|
||||
{
|
||||
struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
|
||||
- u8 *rx;
|
||||
+ u8 *b0, *rx;
|
||||
int ret;
|
||||
|
||||
info("%s: %d\n", __func__, i);
|
||||
@@ -516,11 +522,12 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
|
||||
if (state->initialized)
|
||||
return 0;
|
||||
|
||||
- rx = kmalloc(PCTV_ANSWER_LEN, GFP_KERNEL);
|
||||
- if (!rx)
|
||||
+ b0 = kmalloc(5 + PCTV_ANSWER_LEN, GFP_KERNEL);
|
||||
+ if (!b0)
|
||||
return -ENOMEM;
|
||||
|
||||
- mutex_lock(&state->ca_mutex);
|
||||
+ rx = b0 + 5;
|
||||
+
|
||||
/* hmm where shoud this should go? */
|
||||
ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);
|
||||
if (ret != 0)
|
||||
@@ -528,66 +535,70 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
|
||||
__func__, ret);
|
||||
|
||||
/* this is a one-time initialization, dont know where to put */
|
||||
- state->data[0] = 0xaa;
|
||||
- state->data[1] = state->c++;
|
||||
- state->data[2] = PCTV_CMD_RESET;
|
||||
- state->data[3] = 1;
|
||||
- state->data[4] = 0;
|
||||
+ b0[0] = 0xaa;
|
||||
+ b0[1] = state->c++;
|
||||
+ b0[2] = PCTV_CMD_RESET;
|
||||
+ b0[3] = 1;
|
||||
+ b0[4] = 0;
|
||||
/* reset board */
|
||||
- ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0);
|
||||
+ ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0);
|
||||
if (ret)
|
||||
goto ret;
|
||||
|
||||
- state->data[1] = state->c++;
|
||||
- state->data[4] = 1;
|
||||
+ b0[1] = state->c++;
|
||||
+ b0[4] = 1;
|
||||
/* reset board (again?) */
|
||||
- ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0);
|
||||
+ ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0);
|
||||
if (ret)
|
||||
goto ret;
|
||||
|
||||
state->initialized = 1;
|
||||
|
||||
ret:
|
||||
- mutex_unlock(&state->ca_mutex);
|
||||
- kfree(rx);
|
||||
+ kfree(b0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pctv452e_rc_query(struct dvb_usb_device *d)
|
||||
{
|
||||
struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
|
||||
+ u8 *b, *rx;
|
||||
int ret, i;
|
||||
u8 id;
|
||||
|
||||
- mutex_lock(&state->ca_mutex);
|
||||
+ b = kmalloc(CMD_BUFFER_SIZE + PCTV_ANSWER_LEN, GFP_KERNEL);
|
||||
+ if (!b)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ rx = b + CMD_BUFFER_SIZE;
|
||||
+
|
||||
id = state->c++;
|
||||
|
||||
/* prepare command header */
|
||||
- state->data[0] = SYNC_BYTE_OUT;
|
||||
- state->data[1] = id;
|
||||
- state->data[2] = PCTV_CMD_IR;
|
||||
- state->data[3] = 0;
|
||||
+ b[0] = SYNC_BYTE_OUT;
|
||||
+ b[1] = id;
|
||||
+ b[2] = PCTV_CMD_IR;
|
||||
+ b[3] = 0;
|
||||
|
||||
/* send ir request */
|
||||
- ret = dvb_usb_generic_rw(d, state->data, 4,
|
||||
- state->data, PCTV_ANSWER_LEN, 0);
|
||||
+ ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0);
|
||||
if (ret != 0)
|
||||
goto ret;
|
||||
|
||||
if (debug > 3) {
|
||||
- info("%s: read: %2d: %*ph: ", __func__, ret, 3, state->data);
|
||||
- for (i = 0; (i < state->data[3]) && ((i + 3) < PCTV_ANSWER_LEN); i++)
|
||||
- info(" %02x", state->data[i + 3]);
|
||||
+ info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx);
|
||||
+ for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++)
|
||||
+ info(" %02x", rx[i+3]);
|
||||
|
||||
info("\n");
|
||||
}
|
||||
|
||||
- if ((state->data[3] == 9) && (state->data[12] & 0x01)) {
|
||||
+ if ((rx[3] == 9) && (rx[12] & 0x01)) {
|
||||
/* got a "press" event */
|
||||
- state->last_rc_key = RC_SCANCODE_RC5(state->data[7], state->data[6]);
|
||||
+ state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]);
|
||||
if (debug > 2)
|
||||
info("%s: cmd=0x%02x sys=0x%02x\n",
|
||||
- __func__, state->data[6], state->data[7]);
|
||||
+ __func__, rx[6], rx[7]);
|
||||
|
||||
rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0);
|
||||
} else if (state->last_rc_key) {
|
||||
@@ -595,7 +606,7 @@ static int pctv452e_rc_query(struct dvb_usb_device *d)
|
||||
state->last_rc_key = 0;
|
||||
}
|
||||
ret:
|
||||
- mutex_unlock(&state->ca_mutex);
|
||||
+ kfree(b);
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user