[PATCH 20/26] [media] em28xx: split up em28xx_dvb_init to reduce stack size
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
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)) { +