[PATCH 20/26] [media] em28xx: split up em28xx_dvb_init to reduce stack size

2017-03-02 Thread Arnd Bergmann
With CONFIG_KASAN, the init function uses a large amount of kernel stack:

drivers/media/usb/em28xx/em28xx-dvb.c: In function 'em28xx_dvb_init':
drivers/media/usb/em28xx/em28xx-dvb.c:2069:1: error: the frame size of 4280 
bytes is larger than 3072 bytes [-Werror=frame-larger-than=]

By splitting out each part of the switch/case statement that has its own local
variables into a separate function, no single one of them uses more than 500 
bytes,
and with a noinline_for_kasan annotation we can ensure that they are not merged
back together.

Signed-off-by: Arnd Bergmann 
---
 drivers/media/usb/em28xx/em28xx-dvb.c | 947 ++
 1 file changed, 508 insertions(+), 439 deletions(-)

diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c 
b/drivers/media/usb/em28xx/em28xx-dvb.c
index 82edd37f0d73..83125a05918a 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -934,7 +934,7 @@ static struct lgdt3306a_config 
hauppauge_01595_lgdt3306a_config = {
 
 /* -- */
 
-static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
+static noinline_for_kasan int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
 {
struct dvb_frontend *fe;
struct xc2028_config cfg;
@@ -1126,6 +1126,492 @@ static void em28xx_unregister_dvb(struct em28xx_dvb 
*dvb)
dvb_unregister_adapter(>adapter);
 }
 
+static noinline_for_kasan int em28174_dvb_init_pctv_460e(struct em28xx *dev)
+{
+   struct em28xx_dvb *dvb = dev->dvb;
+   struct i2c_client *client;
+   struct i2c_board_info board_info;
+   struct tda10071_platform_data tda10071_pdata = {};
+   struct a8293_platform_data a8293_pdata = {};
+   int result;
+
+   /* attach demod + tuner combo */
+   tda10071_pdata.clk = 40444000, /* 40.444 MHz */
+   tda10071_pdata.i2c_wr_max = 64,
+   tda10071_pdata.ts_mode = TDA10071_TS_SERIAL,
+   tda10071_pdata.pll_multiplier = 20,
+   tda10071_pdata.tuner_i2c_addr = 0x14,
+   memset(_info, 0, sizeof(board_info));
+   strlcpy(board_info.type, "tda10071_cx24118", I2C_NAME_SIZE);
+   board_info.addr = 0x55;
+   board_info.platform_data = _pdata;
+   request_module("tda10071");
+   client = i2c_new_device(>i2c_adap[dev->def_i2c_bus], _info);
+   if (client == NULL || client->dev.driver == NULL) {
+   result = -ENODEV;
+   goto out_free;
+   }
+   if (!try_module_get(client->dev.driver->owner)) {
+   i2c_unregister_device(client);
+   result = -ENODEV;
+   goto out_free;
+   }
+   dvb->fe[0] = tda10071_pdata.get_dvb_frontend(client);
+   dvb->i2c_client_demod = client;
+
+   /* attach SEC */
+   a8293_pdata.dvb_frontend = dvb->fe[0];
+   memset(_info, 0, sizeof(board_info));
+   strlcpy(board_info.type, "a8293", I2C_NAME_SIZE);
+   board_info.addr = 0x08;
+   board_info.platform_data = _pdata;
+   request_module("a8293");
+   client = i2c_new_device(>i2c_adap[dev->def_i2c_bus], _info);
+   if (client == NULL || client->dev.driver == NULL) {
+   module_put(dvb->i2c_client_demod->dev.driver->owner);
+   i2c_unregister_device(dvb->i2c_client_demod);
+   result = -ENODEV;
+   goto out_free;
+   }
+   if (!try_module_get(client->dev.driver->owner)) {
+   i2c_unregister_device(client);
+   module_put(dvb->i2c_client_demod->dev.driver->owner);
+   i2c_unregister_device(dvb->i2c_client_demod);
+   result = -ENODEV;
+   goto out_free;
+   }
+   dvb->i2c_client_sec = client;
+   result = 0;
+out_free:
+   return result;
+}
+
+static noinline_for_kasan int em28178_dvb_init_pctv_461e(struct em28xx *dev)
+{
+   struct em28xx_dvb *dvb = dev->dvb;
+   struct i2c_client *client;
+   struct i2c_adapter *i2c_adapter;
+   struct i2c_board_info board_info;
+   struct m88ds3103_platform_data m88ds3103_pdata = {};
+   struct ts2020_config ts2020_config = {};
+   struct a8293_platform_data a8293_pdata = {};
+   int result;
+
+   /* attach demod */
+   m88ds3103_pdata.clk = 2700;
+   m88ds3103_pdata.i2c_wr_max = 33;
+   m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL;
+   m88ds3103_pdata.ts_clk = 16000;
+   m88ds3103_pdata.ts_clk_pol = 1;
+   m88ds3103_pdata.agc = 0x99;
+   memset(_info, 0, sizeof(board_info));
+   strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE);
+   board_info.addr = 0x68;
+   board_info.platform_data = _pdata;
+   request_module("m88ds3103");
+   client = i2c_new_device(>i2c_adap[dev->def_i2c_bus], _info);
+   if (client == NULL || client->dev.driver == NULL) {
+   result = -ENODEV;
+   goto out_free;
+   }
+   if 

[PATCH 20/26] [media] em28xx: split up em28xx_dvb_init to reduce stack size

2017-03-02 Thread Arnd Bergmann
With CONFIG_KASAN, the init function uses a large amount of kernel stack:

drivers/media/usb/em28xx/em28xx-dvb.c: In function 'em28xx_dvb_init':
drivers/media/usb/em28xx/em28xx-dvb.c:2069:1: error: the frame size of 4280 
bytes is larger than 3072 bytes [-Werror=frame-larger-than=]

By splitting out each part of the switch/case statement that has its own local
variables into a separate function, no single one of them uses more than 500 
bytes,
and with a noinline_for_kasan annotation we can ensure that they are not merged
back together.

Signed-off-by: Arnd Bergmann 
---
 drivers/media/usb/em28xx/em28xx-dvb.c | 947 ++
 1 file changed, 508 insertions(+), 439 deletions(-)

diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c 
b/drivers/media/usb/em28xx/em28xx-dvb.c
index 82edd37f0d73..83125a05918a 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -934,7 +934,7 @@ static struct lgdt3306a_config 
hauppauge_01595_lgdt3306a_config = {
 
 /* -- */
 
-static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
+static noinline_for_kasan int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
 {
struct dvb_frontend *fe;
struct xc2028_config cfg;
@@ -1126,6 +1126,492 @@ static void em28xx_unregister_dvb(struct em28xx_dvb 
*dvb)
dvb_unregister_adapter(>adapter);
 }
 
+static noinline_for_kasan int em28174_dvb_init_pctv_460e(struct em28xx *dev)
+{
+   struct em28xx_dvb *dvb = dev->dvb;
+   struct i2c_client *client;
+   struct i2c_board_info board_info;
+   struct tda10071_platform_data tda10071_pdata = {};
+   struct a8293_platform_data a8293_pdata = {};
+   int result;
+
+   /* attach demod + tuner combo */
+   tda10071_pdata.clk = 40444000, /* 40.444 MHz */
+   tda10071_pdata.i2c_wr_max = 64,
+   tda10071_pdata.ts_mode = TDA10071_TS_SERIAL,
+   tda10071_pdata.pll_multiplier = 20,
+   tda10071_pdata.tuner_i2c_addr = 0x14,
+   memset(_info, 0, sizeof(board_info));
+   strlcpy(board_info.type, "tda10071_cx24118", I2C_NAME_SIZE);
+   board_info.addr = 0x55;
+   board_info.platform_data = _pdata;
+   request_module("tda10071");
+   client = i2c_new_device(>i2c_adap[dev->def_i2c_bus], _info);
+   if (client == NULL || client->dev.driver == NULL) {
+   result = -ENODEV;
+   goto out_free;
+   }
+   if (!try_module_get(client->dev.driver->owner)) {
+   i2c_unregister_device(client);
+   result = -ENODEV;
+   goto out_free;
+   }
+   dvb->fe[0] = tda10071_pdata.get_dvb_frontend(client);
+   dvb->i2c_client_demod = client;
+
+   /* attach SEC */
+   a8293_pdata.dvb_frontend = dvb->fe[0];
+   memset(_info, 0, sizeof(board_info));
+   strlcpy(board_info.type, "a8293", I2C_NAME_SIZE);
+   board_info.addr = 0x08;
+   board_info.platform_data = _pdata;
+   request_module("a8293");
+   client = i2c_new_device(>i2c_adap[dev->def_i2c_bus], _info);
+   if (client == NULL || client->dev.driver == NULL) {
+   module_put(dvb->i2c_client_demod->dev.driver->owner);
+   i2c_unregister_device(dvb->i2c_client_demod);
+   result = -ENODEV;
+   goto out_free;
+   }
+   if (!try_module_get(client->dev.driver->owner)) {
+   i2c_unregister_device(client);
+   module_put(dvb->i2c_client_demod->dev.driver->owner);
+   i2c_unregister_device(dvb->i2c_client_demod);
+   result = -ENODEV;
+   goto out_free;
+   }
+   dvb->i2c_client_sec = client;
+   result = 0;
+out_free:
+   return result;
+}
+
+static noinline_for_kasan int em28178_dvb_init_pctv_461e(struct em28xx *dev)
+{
+   struct em28xx_dvb *dvb = dev->dvb;
+   struct i2c_client *client;
+   struct i2c_adapter *i2c_adapter;
+   struct i2c_board_info board_info;
+   struct m88ds3103_platform_data m88ds3103_pdata = {};
+   struct ts2020_config ts2020_config = {};
+   struct a8293_platform_data a8293_pdata = {};
+   int result;
+
+   /* attach demod */
+   m88ds3103_pdata.clk = 2700;
+   m88ds3103_pdata.i2c_wr_max = 33;
+   m88ds3103_pdata.ts_mode = M88DS3103_TS_PARALLEL;
+   m88ds3103_pdata.ts_clk = 16000;
+   m88ds3103_pdata.ts_clk_pol = 1;
+   m88ds3103_pdata.agc = 0x99;
+   memset(_info, 0, sizeof(board_info));
+   strlcpy(board_info.type, "m88ds3103", I2C_NAME_SIZE);
+   board_info.addr = 0x68;
+   board_info.platform_data = _pdata;
+   request_module("m88ds3103");
+   client = i2c_new_device(>i2c_adap[dev->def_i2c_bus], _info);
+   if (client == NULL || client->dev.driver == NULL) {
+   result = -ENODEV;
+   goto out_free;
+   }
+   if (!try_module_get(client->dev.driver->owner)) {
+