[media] DiBxxxx: get rid of DMA buffer on stack

This patch removes the remaining on-stack buffer for USB DMA transfer.
This patch also reduces the stack memory usage.

Cc: stable@kernel.org
Cc: Florian Mickler <florian@mickler.org>
Signed-off-by: Olivier Grenie <olivier.grenie@dibcom.fr>
Signed-off-by: Patrick Boettcher <patrick.boettcher@dibcom.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c
index b25ef2b..a085588 100644
--- a/drivers/media/dvb/frontends/dib9000.c
+++ b/drivers/media/dvb/frontends/dib9000.c
@@ -27,6 +27,8 @@
 struct i2c_device {
 	struct i2c_adapter *i2c_adap;
 	u8 i2c_addr;
+	u8 *i2c_read_buffer;
+	u8 *i2c_write_buffer;
 };
 
 /* lock */
@@ -92,11 +94,16 @@
 
 	struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
 	u16 component_bus_speed;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[255];
+	u8 i2c_read_buffer[255];
 };
 
-u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0
+	0, 0, 0, 0, 0, 0, 0, 0
 };
 
 enum dib9000_power_mode {
@@ -217,25 +224,33 @@
 	u32 chunk_size = 126;
 	u32 l;
 	int ret;
-	u8 wb[2] = { reg >> 8, reg & 0xff };
-	struct i2c_msg msg[2] = {
-		{.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
-		{.addr = state->i2c.i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = len},
-	};
 
 	if (state->platform.risc.fw_is_running && (reg < 1024))
 		return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len);
 
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c.i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 2;
+	state->msg[1].addr = state->i2c.i2c_addr >> 1;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = b;
+	state->msg[1].len = len;
+
+	state->i2c_write_buffer[0] = reg >> 8;
+	state->i2c_write_buffer[1] = reg & 0xff;
+
 	if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
-		wb[0] |= (1 << 5);
+		state->i2c_write_buffer[0] |= (1 << 5);
 	if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
-		wb[0] |= (1 << 4);
+		state->i2c_write_buffer[0] |= (1 << 4);
 
 	do {
 		l = len < chunk_size ? len : chunk_size;
-		msg[1].len = l;
-		msg[1].buf = b;
-		ret = i2c_transfer(state->i2c.i2c_adap, msg, 2) != 2 ? -EREMOTEIO : 0;
+		state->msg[1].len = l;
+		state->msg[1].buf = b;
+		ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0;
 		if (ret != 0) {
 			dprintk("i2c read error on %d", reg);
 			return -EREMOTEIO;
@@ -253,50 +268,47 @@
 
 static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg)
 {
-	u8 b[2];
-	u8 wb[2] = { reg >> 8, reg & 0xff };
 	struct i2c_msg msg[2] = {
-		{.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
-		{.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = 2},
+		{.addr = i2c->i2c_addr >> 1, .flags = 0,
+			.buf = i2c->i2c_write_buffer, .len = 2},
+		{.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD,
+			.buf = i2c->i2c_read_buffer, .len = 2},
 	};
 
+	i2c->i2c_write_buffer[0] = reg >> 8;
+	i2c->i2c_write_buffer[1] = reg & 0xff;
+
 	if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) {
 		dprintk("read register %x error", reg);
 		return 0;
 	}
 
-	return (b[0] << 8) | b[1];
+	return (i2c->i2c_read_buffer[0] << 8) | i2c->i2c_read_buffer[1];
 }
 
 static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg)
 {
-	u8 b[2];
-	if (dib9000_read16_attr(state, reg, b, 2, 0) != 0)
+	if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, 0) != 0)
 		return 0;
-	return (b[0] << 8 | b[1]);
+	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 }
 
 static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute)
 {
-	u8 b[2];
-	if (dib9000_read16_attr(state, reg, b, 2, attribute) != 0)
+	if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2,
+				attribute) != 0)
 		return 0;
-	return (b[0] << 8 | b[1]);
+	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 }
 
 #define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
 
 static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute)
 {
-	u8 b[255];
 	u32 chunk_size = 126;
 	u32 l;
 	int ret;
 
-	struct i2c_msg msg = {
-		.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = b, .len = len + 2
-	};
-
 	if (state->platform.risc.fw_is_running && (reg < 1024)) {
 		if (dib9000_risc_apb_access_write
 		    (state, reg, DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute, buf, len) != 0)
@@ -304,20 +316,26 @@
 		return 0;
 	}
 
-	b[0] = (reg >> 8) & 0xff;
-	b[1] = (reg) & 0xff;
+	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c.i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = len + 2;
+
+	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	state->i2c_write_buffer[1] = (reg) & 0xff;
 
 	if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
-		b[0] |= (1 << 5);
+		state->i2c_write_buffer[0] |= (1 << 5);
 	if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
-		b[0] |= (1 << 4);
+		state->i2c_write_buffer[0] |= (1 << 4);
 
 	do {
 		l = len < chunk_size ? len : chunk_size;
-		msg.len = l + 2;
-		memcpy(&b[2], buf, l);
+		state->msg[0].len = l + 2;
+		memcpy(&state->i2c_write_buffer[2], buf, l);
 
-		ret = i2c_transfer(state->i2c.i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+		ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
 
 		buf += l;
 		len -= l;
@@ -331,11 +349,16 @@
 
 static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
 {
-	u8 b[4] = { (reg >> 8) & 0xff, reg & 0xff, (val >> 8) & 0xff, val & 0xff };
 	struct i2c_msg msg = {
-		.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+		.addr = i2c->i2c_addr >> 1, .flags = 0,
+		.buf = i2c->i2c_write_buffer, .len = 4
 	};
 
+	i2c->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	i2c->i2c_write_buffer[1] = reg & 0xff;
+	i2c->i2c_write_buffer[2] = (val >> 8) & 0xff;
+	i2c->i2c_write_buffer[3] = val & 0xff;
+
 	return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
 }
 
@@ -1015,8 +1038,8 @@
 		return 0;
 	dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i);
 	do {
-		dib9000_risc_mem_read(state, FE_MM_RW_SYNC, &i, 1);
-	} while (i && index_loop--);
+		dib9000_risc_mem_read(state, FE_MM_RW_SYNC, state->i2c_read_buffer, 1);
+	} while (state->i2c_read_buffer[0] && index_loop--);
 
 	if (index_loop > 0)
 		return 0;
@@ -1139,7 +1162,7 @@
 
 		s8 intlv_native;
 	};
-	struct dibDVBTChannel ch;
+	struct dibDVBTChannel *ch;
 	int ret = 0;
 
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
@@ -1148,9 +1171,12 @@
 		ret = -EIO;
 	}
 
-	dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION, (u8 *) &ch, sizeof(struct dibDVBTChannel));
+	dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
+			state->i2c_read_buffer, sizeof(struct dibDVBTChannel));
+	ch = (struct dibDVBTChannel *)state->i2c_read_buffer;
 
-	switch (ch.spectrum_inversion & 0x7) {
+
+	switch (ch->spectrum_inversion & 0x7) {
 	case 1:
 		state->fe[0]->dtv_property_cache.inversion = INVERSION_ON;
 		break;
@@ -1162,7 +1188,7 @@
 		state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO;
 		break;
 	}
-	switch (ch.nfft) {
+	switch (ch->nfft) {
 	case 0:
 		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
 		break;
@@ -1177,7 +1203,7 @@
 		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
 		break;
 	}
-	switch (ch.guard) {
+	switch (ch->guard) {
 	case 0:
 		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
 		break;
@@ -1195,7 +1221,7 @@
 		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
 		break;
 	}
-	switch (ch.constellation) {
+	switch (ch->constellation) {
 	case 2:
 		state->fe[0]->dtv_property_cache.modulation = QAM_64;
 		break;
@@ -1210,7 +1236,7 @@
 		state->fe[0]->dtv_property_cache.modulation = QAM_AUTO;
 		break;
 	}
-	switch (ch.hrch) {
+	switch (ch->hrch) {
 	case 0:
 		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE;
 		break;
@@ -1222,7 +1248,7 @@
 		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
 		break;
 	}
-	switch (ch.code_rate_hp) {
+	switch (ch->code_rate_hp) {
 	case 1:
 		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2;
 		break;
@@ -1243,7 +1269,7 @@
 		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO;
 		break;
 	}
-	switch (ch.code_rate_lp) {
+	switch (ch->code_rate_lp) {
 	case 1:
 		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2;
 		break;
@@ -1439,9 +1465,10 @@
 		break;
 	case CT_DEMOD_STEP_1:
 		if (search)
-			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, (u8 *) &i, 1);
+			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, state->i2c_read_buffer, 1);
 		else
-			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, (u8 *) &i, 1);
+			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, state->i2c_read_buffer, 1);
+		i = (s8)state->i2c_read_buffer[0];
 		switch (i) {	/* something happened */
 		case 0:
 			break;
@@ -2038,14 +2065,17 @@
 static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
 {
 	struct dib9000_state *state = fe->demodulator_priv;
-	u16 c[16];
+	u16 *c;
 
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
 	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
 		return -EIO;
-	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
+			state->i2c_read_buffer, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
 
+	c = (u16 *)state->i2c_read_buffer;
+
 	*ber = c[10] << 16 | c[11];
 	return 0;
 }
@@ -2054,7 +2084,7 @@
 {
 	struct dib9000_state *state = fe->demodulator_priv;
 	u8 index_frontend;
-	u16 c[16];
+	u16 *c = (u16 *)state->i2c_read_buffer;
 	u16 val;
 
 	*strength = 0;
@@ -2069,7 +2099,7 @@
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
 	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
 		return -EIO;
-	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
 
 	val = 65535 - c[4];
@@ -2083,14 +2113,14 @@
 static u32 dib9000_get_snr(struct dvb_frontend *fe)
 {
 	struct dib9000_state *state = fe->demodulator_priv;
-	u16 c[16];
+	u16 *c = (u16 *)state->i2c_read_buffer;
 	u32 n, s, exp;
 	u16 val;
 
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
 	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
 		return -EIO;
-	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
 
 	val = c[7];
@@ -2137,12 +2167,12 @@
 static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
 {
 	struct dib9000_state *state = fe->demodulator_priv;
-	u16 c[16];
+	u16 *c = (u16 *)state->i2c_read_buffer;
 
 	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
 	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
 		return -EIO;
-	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
 	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
 
 	*unc = c[12];
@@ -2151,10 +2181,22 @@
 
 int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
 {
-	int k = 0;
+	int k = 0, ret = 0;
 	u8 new_addr = 0;
 	struct i2c_device client = {.i2c_adap = i2c };
 
+	client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+	if (!client.i2c_write_buffer) {
+		dprintk("%s: not enough memory", __func__);
+		return -ENOMEM;
+	}
+	client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+	if (!client.i2c_read_buffer) {
+		dprintk("%s: not enough memory", __func__);
+		ret = -ENOMEM;
+		goto error_memory;
+	}
+
 	client.i2c_addr = default_addr + 16;
 	dib9000_i2c_write16(&client, 1796, 0x0);
 
@@ -2178,7 +2220,8 @@
 			client.i2c_addr = default_addr;
 			if (dib9000_identify(&client) == 0) {
 				dprintk("DiB9000 #%d: not identified", k);
-				return -EIO;
+				ret = -EIO;
+				goto error;
 			}
 		}
 
@@ -2196,7 +2239,12 @@
 		dib9000_i2c_write16(&client, 1795, 0);
 	}
 
-	return 0;
+error:
+	kfree(client.i2c_read_buffer);
+error_memory:
+	kfree(client.i2c_write_buffer);
+
+	return ret;
 }
 EXPORT_SYMBOL(dib9000_i2c_enumeration);
 
@@ -2263,6 +2311,8 @@
 	memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config));
 	st->i2c.i2c_adap = i2c_adap;
 	st->i2c.i2c_addr = i2c_addr;
+	st->i2c.i2c_write_buffer = st->i2c_write_buffer;
+	st->i2c.i2c_read_buffer = st->i2c_read_buffer;
 
 	st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS;
 	st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;