Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Sean Young and committed by
Mauro Carvalho Chehab
b4756707 1efdf177

+103 -28
+39 -11
drivers/media/dvb-frontends/dib3000mc.c
··· 55 55 56 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 58 struct i2c_msg msg[2] = { 61 - { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, 62 - { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, 59 + { .addr = state->i2c_addr >> 1, .flags = 0, .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 77 if (i2c_transfer(state->i2c_adap, msg, 2) != 2) 66 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 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 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 111 static int dib3000mc_identify(struct dib3000mc_state *state)
+17 -5
drivers/media/dvb-frontends/dvb-pll.c
··· 753 753 struct i2c_adapter *i2c, 754 754 unsigned int pll_desc_id) 755 755 { 756 - u8 b1 [] = { 0 }; 757 - struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, 758 - .buf = b1, .len = 1 }; 756 + u8 *b1; 757 + struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .len = 1 }; 759 758 struct dvb_pll_priv *priv = NULL; 760 759 int ret; 761 760 const struct dvb_pll_desc *desc; 761 + 762 + b1 = kmalloc(1, GFP_KERNEL); 763 + if (!b1) 764 + return NULL; 765 + 766 + b1[0] = 0; 767 + msg.buf = b1; 762 768 763 769 if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) && 764 770 (id[dvb_pll_devcount] < ARRAY_SIZE(pll_list))) ··· 779 773 fe->ops.i2c_gate_ctrl(fe, 1); 780 774 781 775 ret = i2c_transfer (i2c, &msg, 1); 782 - if (ret != 1) 776 + if (ret != 1) { 777 + kfree(b1); 783 778 return NULL; 779 + } 784 780 if (fe->ops.i2c_gate_ctrl) 785 781 fe->ops.i2c_gate_ctrl(fe, 0); 786 782 } 787 783 788 784 priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL); 789 - if (priv == NULL) 785 + if (!priv) { 786 + kfree(b1); 790 787 return NULL; 788 + } 791 789 792 790 priv->pll_i2c_address = pll_addr; 793 791 priv->i2c = i2c; ··· 820 810 id[priv->nr] == pll_desc_id ? 821 811 "insmod option" : "autodetected"); 822 812 } 813 + 814 + kfree(b1); 823 815 824 816 return fe; 825 817 }
+47 -12
drivers/media/tuners/mt2060.c
··· 38 38 static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val) 39 39 { 40 40 struct i2c_msg msg[2] = { 41 - { .addr = priv->cfg->i2c_address, .flags = 0, .buf = &reg, .len = 1 }, 42 - { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 }, 41 + { .addr = priv->cfg->i2c_address, .flags = 0, .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 57 if (i2c_transfer(priv->i2c, msg, 2) != 2) { 46 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 67 // Writes a single register 53 68 static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val) 54 69 { 55 - u8 buf[2] = { reg, val }; 56 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 85 if (i2c_transfer(priv->i2c, &msg, 1) != 1) { 61 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 93 // Writes a set of consecutive registers 68 94 static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len) 69 95 { 70 96 int rem, val_len; 71 - u8 xfer_buf[16]; 97 + u8 *xfer_buf; 98 + int rc = 0; 72 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 }; 102 + 103 + xfer_buf = kmalloc(16, GFP_KERNEL); 104 + if (!xfer_buf) 105 + return -ENOMEM; 106 + 107 + msg.buf = xfer_buf; 75 108 76 109 for (rem = len - 1; rem > 0; rem -= priv->i2c_max_regs) { 77 110 val_len = min_t(int, rem, priv->i2c_max_regs); ··· 114 81 115 82 if (i2c_transfer(priv->i2c, &msg, 1) != 1) { 116 83 printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n", val_len); 117 - return -EREMOTEIO; 84 + rc = -EREMOTEIO; 85 + break; 118 86 } 119 87 } 120 88 121 - return 0; 89 + kfree(xfer_buf); 90 + return rc; 122 91 } 123 92 124 93 // Initialisation sequences