From 7e8f15c5aa9b8021ee933336f3e055f279482051 Mon Sep 17 00:00:00 2001 From: Andrzej Hajda Date: Thu, 9 Jan 2014 09:55:43 -0300 Subject: [PATCH] [media] s5k5baf: allow to handle arbitrary long i2c sequences Using variable length array in s5k5baf_write_arr_seq caused an implicit assumption that i2c sequences should be short. The patch rewrites the function so it can handle sequences of any length and does not use variable length array. Reported-by: Dan Carpenter Signed-off-by: Andrzej Hajda Signed-off-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/i2c/s5k5baf.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index 4b8381111cbd..77e10e0fd8d6 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -478,25 +478,33 @@ static void s5k5baf_write_arr_seq(struct s5k5baf *state, u16 addr, u16 count, const u16 *seq) { struct i2c_client *c = v4l2_get_subdevdata(&state->sd); - __be16 buf[count + 1]; - int ret, n; + __be16 buf[65]; s5k5baf_i2c_write(state, REG_CMDWR_ADDR, addr); if (state->error) return; + v4l2_dbg(3, debug, c, "i2c_write_seq(count=%d): %*ph\n", count, + min(2 * count, 64), seq); + buf[0] = __constant_cpu_to_be16(REG_CMD_BUF); - for (n = 1; n <= count; ++n) - buf[n] = cpu_to_be16(*seq++); - n *= 2; - ret = i2c_master_send(c, (char *)buf, n); - v4l2_dbg(3, debug, c, "i2c_write_seq(count=%d): %*ph\n", count, - min(2 * count, 64), seq - count); + while (count > 0) { + int n = min_t(int, count, ARRAY_SIZE(buf) - 1); + int ret, i; - if (ret != n) { - v4l2_err(c, "i2c_write_seq: error during transfer (%d)\n", ret); - state->error = ret; + for (i = 1; i <= n; ++i) + buf[i] = cpu_to_be16(*seq++); + + i *= 2; + ret = i2c_master_send(c, (char *)buf, i); + if (ret != i) { + v4l2_err(c, "i2c_write_seq: error during transfer (%d)\n", ret); + state->error = ret; + break; + } + + count -= n; } } -- 2.20.1