diff options
author | Sean Young <sean@mess.org> | 2017-09-02 07:42:42 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-09-23 07:21:33 -0400 |
commit | b4756707152700c96acdfe149cb1ca4cec306c7a (patch) | |
tree | d27dcc1471d94d40791492f2ad88f7875ee2d3c4 | |
parent | 1efdf1776e2253b77413c997bed862410e4b6aaf (diff) |
media: dvb: i2c transfers over usb cannot be done from stack
Since commit 29d2fef8be11 ("usb: catch attempts to submit urbs
with a vmalloc'd transfer buffer"), the AverMedia AverTV DVB-T
USB 2.0 (a800) fails to probe.
Cc: stable@vger.kernel.org
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
-rw-r--r-- | drivers/media/dvb-frontends/dib3000mc.c | 50 | ||||
-rw-r--r-- | drivers/media/dvb-frontends/dvb-pll.c | 22 | ||||
-rw-r--r-- | drivers/media/tuners/mt2060.c | 59 |
3 files changed, 103 insertions, 28 deletions
diff --git a/drivers/media/dvb-frontends/dib3000mc.c b/drivers/media/dvb-frontends/dib3000mc.c index 224283fe100a..4d086a7248e9 100644 --- a/drivers/media/dvb-frontends/dib3000mc.c +++ b/drivers/media/dvb-frontends/dib3000mc.c | |||
@@ -55,29 +55,57 @@ struct dib3000mc_state { | |||
55 | 55 | ||
56 | static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg) | 56 | static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg) |
57 | { | 57 | { |
58 | u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; | ||
59 | u8 rb[2]; | ||
60 | struct i2c_msg msg[2] = { | 58 | struct i2c_msg msg[2] = { |
61 | { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, | 59 | { .addr = state->i2c_addr >> 1, .flags = 0, .len = 2 }, |
62 | { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, | 60 | { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .len = 2 }, |
63 | }; | 61 | }; |
62 | u16 word; | ||
63 | u8 *b; | ||
64 | |||
65 | b = kmalloc(4, GFP_KERNEL); | ||
66 | if (!b) | ||
67 | return 0; | ||
68 | |||
69 | b[0] = (reg >> 8) | 0x80; | ||
70 | b[1] = reg; | ||
71 | b[2] = 0; | ||
72 | b[3] = 0; | ||
73 | |||
74 | msg[0].buf = b; | ||
75 | msg[1].buf = b + 2; | ||
64 | 76 | ||
65 | if (i2c_transfer(state->i2c_adap, msg, 2) != 2) | 77 | if (i2c_transfer(state->i2c_adap, msg, 2) != 2) |
66 | dprintk("i2c read error on %d\n",reg); | 78 | dprintk("i2c read error on %d\n",reg); |
67 | 79 | ||
68 | return (rb[0] << 8) | rb[1]; | 80 | word = (b[2] << 8) | b[3]; |
81 | kfree(b); | ||
82 | |||
83 | return word; | ||
69 | } | 84 | } |
70 | 85 | ||
71 | static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val) | 86 | static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val) |
72 | { | 87 | { |
73 | u8 b[4] = { | ||
74 | (reg >> 8) & 0xff, reg & 0xff, | ||
75 | (val >> 8) & 0xff, val & 0xff, | ||
76 | }; | ||
77 | struct i2c_msg msg = { | 88 | struct i2c_msg msg = { |
78 | .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 | 89 | .addr = state->i2c_addr >> 1, .flags = 0, .len = 4 |
79 | }; | 90 | }; |
80 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | 91 | int rc; |
92 | u8 *b; | ||
93 | |||
94 | b = kmalloc(4, GFP_KERNEL); | ||
95 | if (!b) | ||
96 | return -ENOMEM; | ||
97 | |||
98 | b[0] = reg >> 8; | ||
99 | b[1] = reg; | ||
100 | b[2] = val >> 8; | ||
101 | b[3] = val; | ||
102 | |||
103 | msg.buf = b; | ||
104 | |||
105 | rc = i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | ||
106 | kfree(b); | ||
107 | |||
108 | return rc; | ||
81 | } | 109 | } |
82 | 110 | ||
83 | static int dib3000mc_identify(struct dib3000mc_state *state) | 111 | static int dib3000mc_identify(struct dib3000mc_state *state) |
diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c index 7bec3e028bee..5553b89b804e 100644 --- a/drivers/media/dvb-frontends/dvb-pll.c +++ b/drivers/media/dvb-frontends/dvb-pll.c | |||
@@ -753,13 +753,19 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, | |||
753 | struct i2c_adapter *i2c, | 753 | struct i2c_adapter *i2c, |
754 | unsigned int pll_desc_id) | 754 | unsigned int pll_desc_id) |
755 | { | 755 | { |
756 | u8 b1 [] = { 0 }; | 756 | u8 *b1; |
757 | struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, | 757 | struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .len = 1 }; |
758 | .buf = b1, .len = 1 }; | ||
759 | struct dvb_pll_priv *priv = NULL; | 758 | struct dvb_pll_priv *priv = NULL; |
760 | int ret; | 759 | int ret; |
761 | const struct dvb_pll_desc *desc; | 760 | const struct dvb_pll_desc *desc; |
762 | 761 | ||
762 | b1 = kmalloc(1, GFP_KERNEL); | ||
763 | if (!b1) | ||
764 | return NULL; | ||
765 | |||
766 | b1[0] = 0; | ||
767 | msg.buf = b1; | ||
768 | |||
763 | if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) && | 769 | if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) && |
764 | (id[dvb_pll_devcount] < ARRAY_SIZE(pll_list))) | 770 | (id[dvb_pll_devcount] < ARRAY_SIZE(pll_list))) |
765 | pll_desc_id = id[dvb_pll_devcount]; | 771 | pll_desc_id = id[dvb_pll_devcount]; |
@@ -773,15 +779,19 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, | |||
773 | fe->ops.i2c_gate_ctrl(fe, 1); | 779 | fe->ops.i2c_gate_ctrl(fe, 1); |
774 | 780 | ||
775 | ret = i2c_transfer (i2c, &msg, 1); | 781 | ret = i2c_transfer (i2c, &msg, 1); |
776 | if (ret != 1) | 782 | if (ret != 1) { |
783 | kfree(b1); | ||
777 | return NULL; | 784 | return NULL; |
785 | } | ||
778 | if (fe->ops.i2c_gate_ctrl) | 786 | if (fe->ops.i2c_gate_ctrl) |
779 | fe->ops.i2c_gate_ctrl(fe, 0); | 787 | fe->ops.i2c_gate_ctrl(fe, 0); |
780 | } | 788 | } |
781 | 789 | ||
782 | priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL); | 790 | priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL); |
783 | if (priv == NULL) | 791 | if (!priv) { |
792 | kfree(b1); | ||
784 | return NULL; | 793 | return NULL; |
794 | } | ||
785 | 795 | ||
786 | priv->pll_i2c_address = pll_addr; | 796 | priv->pll_i2c_address = pll_addr; |
787 | priv->i2c = i2c; | 797 | priv->i2c = i2c; |
@@ -811,6 +821,8 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, | |||
811 | "insmod option" : "autodetected"); | 821 | "insmod option" : "autodetected"); |
812 | } | 822 | } |
813 | 823 | ||
824 | kfree(b1); | ||
825 | |||
814 | return fe; | 826 | return fe; |
815 | } | 827 | } |
816 | EXPORT_SYMBOL(dvb_pll_attach); | 828 | EXPORT_SYMBOL(dvb_pll_attach); |
diff --git a/drivers/media/tuners/mt2060.c b/drivers/media/tuners/mt2060.c index 2e487f9a2cc3..4983eeb39f36 100644 --- a/drivers/media/tuners/mt2060.c +++ b/drivers/media/tuners/mt2060.c | |||
@@ -38,41 +38,74 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); | |||
38 | static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val) | 38 | static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val) |
39 | { | 39 | { |
40 | struct i2c_msg msg[2] = { | 40 | struct i2c_msg msg[2] = { |
41 | { .addr = priv->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, | 41 | { .addr = priv->cfg->i2c_address, .flags = 0, .len = 1 }, |
42 | { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 }, | 42 | { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .len = 1 }, |
43 | }; | 43 | }; |
44 | int rc = 0; | ||
45 | u8 *b; | ||
46 | |||
47 | b = kmalloc(2, GFP_KERNEL); | ||
48 | if (!b) | ||
49 | return -ENOMEM; | ||
50 | |||
51 | b[0] = reg; | ||
52 | b[1] = 0; | ||
53 | |||
54 | msg[0].buf = b; | ||
55 | msg[1].buf = b + 1; | ||
44 | 56 | ||
45 | if (i2c_transfer(priv->i2c, msg, 2) != 2) { | 57 | if (i2c_transfer(priv->i2c, msg, 2) != 2) { |
46 | printk(KERN_WARNING "mt2060 I2C read failed\n"); | 58 | printk(KERN_WARNING "mt2060 I2C read failed\n"); |
47 | return -EREMOTEIO; | 59 | rc = -EREMOTEIO; |
48 | } | 60 | } |
49 | return 0; | 61 | *val = b[1]; |
62 | kfree(b); | ||
63 | |||
64 | return rc; | ||
50 | } | 65 | } |
51 | 66 | ||
52 | // Writes a single register | 67 | // Writes a single register |
53 | static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val) | 68 | static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val) |
54 | { | 69 | { |
55 | u8 buf[2] = { reg, val }; | ||
56 | struct i2c_msg msg = { | 70 | struct i2c_msg msg = { |
57 | .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2 | 71 | .addr = priv->cfg->i2c_address, .flags = 0, .len = 2 |
58 | }; | 72 | }; |
73 | u8 *buf; | ||
74 | int rc = 0; | ||
75 | |||
76 | buf = kmalloc(2, GFP_KERNEL); | ||
77 | if (!buf) | ||
78 | return -ENOMEM; | ||
79 | |||
80 | buf[0] = reg; | ||
81 | buf[1] = val; | ||
82 | |||
83 | msg.buf = buf; | ||
59 | 84 | ||
60 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | 85 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { |
61 | printk(KERN_WARNING "mt2060 I2C write failed\n"); | 86 | printk(KERN_WARNING "mt2060 I2C write failed\n"); |
62 | return -EREMOTEIO; | 87 | rc = -EREMOTEIO; |
63 | } | 88 | } |
64 | return 0; | 89 | kfree(buf); |
90 | return rc; | ||
65 | } | 91 | } |
66 | 92 | ||
67 | // Writes a set of consecutive registers | 93 | // Writes a set of consecutive registers |
68 | static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len) | 94 | static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len) |
69 | { | 95 | { |
70 | int rem, val_len; | 96 | int rem, val_len; |
71 | u8 xfer_buf[16]; | 97 | u8 *xfer_buf; |
98 | int rc = 0; | ||
72 | struct i2c_msg msg = { | 99 | struct i2c_msg msg = { |
73 | .addr = priv->cfg->i2c_address, .flags = 0, .buf = xfer_buf | 100 | .addr = priv->cfg->i2c_address, .flags = 0 |
74 | }; | 101 | }; |
75 | 102 | ||
103 | xfer_buf = kmalloc(16, GFP_KERNEL); | ||
104 | if (!xfer_buf) | ||
105 | return -ENOMEM; | ||
106 | |||
107 | msg.buf = xfer_buf; | ||
108 | |||
76 | for (rem = len - 1; rem > 0; rem -= priv->i2c_max_regs) { | 109 | for (rem = len - 1; rem > 0; rem -= priv->i2c_max_regs) { |
77 | val_len = min_t(int, rem, priv->i2c_max_regs); | 110 | val_len = min_t(int, rem, priv->i2c_max_regs); |
78 | msg.len = 1 + val_len; | 111 | msg.len = 1 + val_len; |
@@ -81,11 +114,13 @@ static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len) | |||
81 | 114 | ||
82 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { | 115 | if (i2c_transfer(priv->i2c, &msg, 1) != 1) { |
83 | printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n", val_len); | 116 | printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n", val_len); |
84 | return -EREMOTEIO; | 117 | rc = -EREMOTEIO; |
118 | break; | ||
85 | } | 119 | } |
86 | } | 120 | } |
87 | 121 | ||
88 | return 0; | 122 | kfree(xfer_buf); |
123 | return rc; | ||
89 | } | 124 | } |
90 | 125 | ||
91 | // Initialisation sequences | 126 | // Initialisation sequences |