Commit 136b769e authored by Brad Love's avatar Brad Love Committed by Mauro Carvalho Chehab

media: cx231xx: Switch to using new dvb i2c helpers

Mostly very straight forward replace of blocks with equivalent code.

Cleanup added at end of dvb_init in case of failure.
Signed-off-by: default avatarBrad Love <brad@nextdimension.cc>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 13a257f8
...@@ -617,23 +617,15 @@ static void unregister_dvb(struct cx231xx_dvb *dvb) ...@@ -617,23 +617,15 @@ static void unregister_dvb(struct cx231xx_dvb *dvb)
dvb_frontend_detach(dvb->frontend[1]); dvb_frontend_detach(dvb->frontend[1]);
dvb_frontend_detach(dvb->frontend[0]); dvb_frontend_detach(dvb->frontend[0]);
dvb_unregister_adapter(&dvb->adapter); dvb_unregister_adapter(&dvb->adapter);
/* remove I2C tuner */ /* remove I2C tuner */
client = dvb->i2c_client_tuner; dvb_module_release(dvb->i2c_client_tuner);
if (client) { dvb->i2c_client_tuner = NULL;
module_put(client->dev.driver->owner); /* remove I2C demod(s) */
i2c_unregister_device(client); dvb_module_release(dvb->i2c_client_demod[1]);
} dvb->i2c_client_demod[1] = NULL;
/* remove I2C demod */ dvb_module_release(dvb->i2c_client_demod[0]);
client = dvb->i2c_client_demod[1]; dvb->i2c_client_demod[0] = NULL;
if (client) {
module_put(client->dev.driver->owner);
i2c_unregister_device(client);
}
client = dvb->i2c_client_demod[0];
if (client) {
module_put(client->dev.driver->owner);
i2c_unregister_device(client);
}
} }
static int dvb_init(struct cx231xx *dev) static int dvb_init(struct cx231xx *dev)
...@@ -642,6 +634,8 @@ static int dvb_init(struct cx231xx *dev) ...@@ -642,6 +634,8 @@ static int dvb_init(struct cx231xx *dev)
struct cx231xx_dvb *dvb; struct cx231xx_dvb *dvb;
struct i2c_adapter *tuner_i2c; struct i2c_adapter *tuner_i2c;
struct i2c_adapter *demod_i2c; struct i2c_adapter *demod_i2c;
struct i2c_client *client;
struct i2c_adapter *adapter;
if (!dev->board.has_dvb) { if (!dev->board.has_dvb) {
/* This device does not support the extension */ /* This device does not support the extension */
...@@ -789,8 +783,6 @@ static int dvb_init(struct cx231xx *dev) ...@@ -789,8 +783,6 @@ static int dvb_init(struct cx231xx *dev)
case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
{ {
struct i2c_client *client;
struct i2c_board_info info;
struct si2165_platform_data si2165_pdata = {}; struct si2165_platform_data si2165_pdata = {};
/* attach demod */ /* attach demod */
...@@ -798,25 +790,14 @@ static int dvb_init(struct cx231xx *dev) ...@@ -798,25 +790,14 @@ static int dvb_init(struct cx231xx *dev)
si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL; si2165_pdata.chip_mode = SI2165_MODE_PLL_XTAL;
si2165_pdata.ref_freq_hz = 16000000; si2165_pdata.ref_freq_hz = 16000000;
memset(&info, 0, sizeof(struct i2c_board_info)); /* perform probe/init/attach */
strlcpy(info.type, "si2165", I2C_NAME_SIZE); client = dvb_module_probe("si2165", NULL, demod_i2c,
info.addr = dev->board.demod_addr; dev->board.demod_addr,
info.platform_data = &si2165_pdata; &si2165_pdata);
request_module(info.type); if (!client) {
client = i2c_new_device(demod_i2c, &info);
if (!client || !client->dev.driver || !dev->dvb->frontend[0]) {
dev_err(dev->dev,
"Failed to attach SI2165 front end\n");
result = -EINVAL;
goto out_free;
}
if (!try_module_get(client->dev.driver->owner)) {
i2c_unregister_device(client);
result = -ENODEV; result = -ENODEV;
goto out_free; goto out_free;
} }
dvb->i2c_client_demod[0] = client; dvb->i2c_client_demod[0] = client;
dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL; dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;
...@@ -833,8 +814,6 @@ static int dvb_init(struct cx231xx *dev) ...@@ -833,8 +814,6 @@ static int dvb_init(struct cx231xx *dev)
} }
case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx: case CX231XX_BOARD_HAUPPAUGE_930C_HD_1114xx:
{ {
struct i2c_client *client;
struct i2c_board_info info;
struct si2165_platform_data si2165_pdata = {}; struct si2165_platform_data si2165_pdata = {};
struct si2157_config si2157_config = {}; struct si2157_config si2157_config = {};
...@@ -843,29 +822,16 @@ static int dvb_init(struct cx231xx *dev) ...@@ -843,29 +822,16 @@ static int dvb_init(struct cx231xx *dev)
si2165_pdata.chip_mode = SI2165_MODE_PLL_EXT; si2165_pdata.chip_mode = SI2165_MODE_PLL_EXT;
si2165_pdata.ref_freq_hz = 24000000; si2165_pdata.ref_freq_hz = 24000000;
memset(&info, 0, sizeof(struct i2c_board_info)); /* perform probe/init/attach */
strlcpy(info.type, "si2165", I2C_NAME_SIZE); client = dvb_module_probe("si2165", NULL, demod_i2c,
info.addr = dev->board.demod_addr; dev->board.demod_addr,
info.platform_data = &si2165_pdata; &si2165_pdata);
request_module(info.type); if (!client) {
client = i2c_new_device(demod_i2c, &info);
if (!client || !client->dev.driver || !dev->dvb->frontend[0]) {
dev_err(dev->dev,
"Failed to attach SI2165 front end\n");
result = -EINVAL;
goto out_free;
}
if (!try_module_get(client->dev.driver->owner)) {
i2c_unregister_device(client);
result = -ENODEV; result = -ENODEV;
goto out_free; goto out_free;
} }
dvb->i2c_client_demod[0] = client; dvb->i2c_client_demod[0] = client;
memset(&info, 0, sizeof(struct i2c_board_info));
dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL; dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;
/* define general-purpose callback pointer */ /* define general-purpose callback pointer */
...@@ -878,27 +844,15 @@ static int dvb_init(struct cx231xx *dev) ...@@ -878,27 +844,15 @@ static int dvb_init(struct cx231xx *dev)
#endif #endif
si2157_config.if_port = 1; si2157_config.if_port = 1;
si2157_config.inversion = true; si2157_config.inversion = true;
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = dev->board.tuner_addr;
info.platform_data = &si2157_config;
request_module("si2157");
client = i2c_new_device(
tuner_i2c,
&info);
if (client == NULL || client->dev.driver == NULL) {
dvb_frontend_detach(dev->dvb->frontend[0]);
result = -ENODEV;
goto out_free;
}
if (!try_module_get(client->dev.driver->owner)) { /* perform probe/init/attach */
i2c_unregister_device(client); client = dvb_module_probe("si2157", NULL, tuner_i2c,
dvb_frontend_detach(dev->dvb->frontend[0]); dev->board.tuner_addr,
&si2157_config);
if (!client) {
result = -ENODEV; result = -ENODEV;
goto out_free; goto out_free;
} }
dev->cx231xx_reset_analog_tuner = NULL; dev->cx231xx_reset_analog_tuner = NULL;
dev->dvb->i2c_client_tuner = client; dev->dvb->i2c_client_tuner = client;
...@@ -906,12 +860,8 @@ static int dvb_init(struct cx231xx *dev) ...@@ -906,12 +860,8 @@ static int dvb_init(struct cx231xx *dev)
} }
case CX231XX_BOARD_HAUPPAUGE_955Q: case CX231XX_BOARD_HAUPPAUGE_955Q:
{ {
struct i2c_client *client;
struct i2c_board_info info;
struct si2157_config si2157_config = {}; struct si2157_config si2157_config = {};
memset(&info, 0, sizeof(struct i2c_board_info));
dev->dvb->frontend[0] = dvb_attach(lgdt3306a_attach, dev->dvb->frontend[0] = dvb_attach(lgdt3306a_attach,
&hauppauge_955q_lgdt3306a_config, &hauppauge_955q_lgdt3306a_config,
demod_i2c demod_i2c
...@@ -936,27 +886,15 @@ static int dvb_init(struct cx231xx *dev) ...@@ -936,27 +886,15 @@ static int dvb_init(struct cx231xx *dev)
#endif #endif
si2157_config.if_port = 1; si2157_config.if_port = 1;
si2157_config.inversion = true; si2157_config.inversion = true;
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = dev->board.tuner_addr;
info.platform_data = &si2157_config;
request_module("si2157");
client = i2c_new_device(
tuner_i2c,
&info);
if (client == NULL || client->dev.driver == NULL) {
dvb_frontend_detach(dev->dvb->frontend[0]);
result = -ENODEV;
goto out_free;
}
if (!try_module_get(client->dev.driver->owner)) { /* perform probe/init/attach */
i2c_unregister_device(client); client = dvb_module_probe("si2157", NULL, tuner_i2c,
dvb_frontend_detach(dev->dvb->frontend[0]); dev->board.tuner_addr,
&si2157_config);
if (!client) {
result = -ENODEV; result = -ENODEV;
goto out_free; goto out_free;
} }
dev->cx231xx_reset_analog_tuner = NULL; dev->cx231xx_reset_analog_tuner = NULL;
dev->dvb->i2c_client_tuner = client; dev->dvb->i2c_client_tuner = client;
...@@ -992,9 +930,6 @@ static int dvb_init(struct cx231xx *dev) ...@@ -992,9 +930,6 @@ static int dvb_init(struct cx231xx *dev)
{ {
struct si2157_config si2157_config = {}; struct si2157_config si2157_config = {};
struct si2168_config si2168_config = {}; struct si2168_config si2168_config = {};
struct i2c_board_info info = {};
struct i2c_client *client;
struct i2c_adapter *adapter;
/* attach demodulator chip */ /* attach demodulator chip */
si2168_config.ts_mode = SI2168_TS_SERIAL; /* from *.inf file */ si2168_config.ts_mode = SI2168_TS_SERIAL; /* from *.inf file */
...@@ -1002,24 +937,14 @@ static int dvb_init(struct cx231xx *dev) ...@@ -1002,24 +937,14 @@ static int dvb_init(struct cx231xx *dev)
si2168_config.i2c_adapter = &adapter; si2168_config.i2c_adapter = &adapter;
si2168_config.ts_clock_inv = true; si2168_config.ts_clock_inv = true;
strlcpy(info.type, "si2168", sizeof(info.type)); /* perform probe/init/attach */
info.addr = dev->board.demod_addr; client = dvb_module_probe("si2168", NULL, demod_i2c,
info.platform_data = &si2168_config; dev->board.demod_addr,
&si2168_config);
request_module(info.type); if (!client) {
client = i2c_new_device(demod_i2c, &info);
if (client == NULL || client->dev.driver == NULL) {
result = -ENODEV; result = -ENODEV;
goto out_free; goto out_free;
} }
if (!try_module_get(client->dev.driver->owner)) {
i2c_unregister_device(client);
result = -ENODEV;
goto out_free;
}
dvb->i2c_client_demod[0] = client; dvb->i2c_client_demod[0] = client;
/* attach tuner chip */ /* attach tuner chip */
...@@ -1030,37 +955,20 @@ static int dvb_init(struct cx231xx *dev) ...@@ -1030,37 +955,20 @@ static int dvb_init(struct cx231xx *dev)
si2157_config.if_port = 1; si2157_config.if_port = 1;
si2157_config.inversion = false; si2157_config.inversion = false;
memset(&info, 0, sizeof(info)); /* perform probe/init/attach */
strlcpy(info.type, "si2157", sizeof(info.type)); client = dvb_module_probe("si2157", NULL, tuner_i2c,
info.addr = dev->board.tuner_addr; dev->board.tuner_addr,
info.platform_data = &si2157_config; &si2157_config);
if (!client) {
request_module(info.type);
client = i2c_new_device(tuner_i2c, &info);
if (client == NULL || client->dev.driver == NULL) {
module_put(dvb->i2c_client_demod[0]->dev.driver->owner);
i2c_unregister_device(dvb->i2c_client_demod[0]);
result = -ENODEV;
goto out_free;
}
if (!try_module_get(client->dev.driver->owner)) {
i2c_unregister_device(client);
module_put(dvb->i2c_client_demod[0]->dev.driver->owner);
i2c_unregister_device(dvb->i2c_client_demod[0]);
result = -ENODEV; result = -ENODEV;
goto out_free; goto out_free;
} }
dev->cx231xx_reset_analog_tuner = NULL; dev->cx231xx_reset_analog_tuner = NULL;
dev->dvb->i2c_client_tuner = client; dev->dvb->i2c_client_tuner = client;
break; break;
} }
case CX231XX_BOARD_ASTROMETA_T2HYBRID: case CX231XX_BOARD_ASTROMETA_T2HYBRID:
{ {
struct i2c_client *client;
struct i2c_board_info info = {};
struct mn88473_config mn88473_config = {}; struct mn88473_config mn88473_config = {};
/* attach demodulator chip */ /* attach demodulator chip */
...@@ -1068,24 +976,14 @@ static int dvb_init(struct cx231xx *dev) ...@@ -1068,24 +976,14 @@ static int dvb_init(struct cx231xx *dev)
mn88473_config.xtal = 25000000; mn88473_config.xtal = 25000000;
mn88473_config.fe = &dev->dvb->frontend[0]; mn88473_config.fe = &dev->dvb->frontend[0];
strlcpy(info.type, "mn88473", sizeof(info.type)); /* perform probe/init/attach */
info.addr = dev->board.demod_addr; client = dvb_module_probe("mn88473", NULL, demod_i2c,
info.platform_data = &mn88473_config; dev->board.demod_addr,
&mn88473_config);
request_module(info.type); if (!client) {
client = i2c_new_device(demod_i2c, &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; result = -ENODEV;
goto out_free; goto out_free;
} }
dvb->i2c_client_demod[0] = client; dvb->i2c_client_demod[0] = client;
/* define general-purpose callback pointer */ /* define general-purpose callback pointer */
...@@ -1099,9 +997,6 @@ static int dvb_init(struct cx231xx *dev) ...@@ -1099,9 +997,6 @@ static int dvb_init(struct cx231xx *dev)
} }
case CX231XX_BOARD_HAUPPAUGE_935C: case CX231XX_BOARD_HAUPPAUGE_935C:
{ {
struct i2c_client *client;
struct i2c_adapter *adapter;
struct i2c_board_info info = {};
struct si2157_config si2157_config = {}; struct si2157_config si2157_config = {};
struct si2168_config si2168_config = {}; struct si2168_config si2168_config = {};
...@@ -1111,25 +1006,14 @@ static int dvb_init(struct cx231xx *dev) ...@@ -1111,25 +1006,14 @@ static int dvb_init(struct cx231xx *dev)
si2168_config.i2c_adapter = &adapter; si2168_config.i2c_adapter = &adapter;
si2168_config.ts_clock_inv = true; si2168_config.ts_clock_inv = true;
strlcpy(info.type, "si2168", sizeof(info.type)); /* perform probe/init/attach */
info.addr = dev->board.demod_addr; client = dvb_module_probe("si2168", NULL, demod_i2c,
info.platform_data = &si2168_config; dev->board.demod_addr,
&si2168_config);
request_module(info.type); if (!client) {
client = i2c_new_device(demod_i2c, &info);
if (client == NULL || client->dev.driver == NULL) {
result = -ENODEV; result = -ENODEV;
goto out_free; goto out_free;
} }
if (!try_module_get(client->dev.driver->owner)) {
dev_err(dev->dev,
"Failed to attach %s frontend.\n", info.type);
i2c_unregister_device(client);
result = -ENODEV;
goto out_free;
}
dvb->i2c_client_demod[0] = client; dvb->i2c_client_demod[0] = client;
dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL; dev->dvb->frontend[0]->ops.i2c_gate_ctrl = NULL;
...@@ -1144,40 +1028,21 @@ static int dvb_init(struct cx231xx *dev) ...@@ -1144,40 +1028,21 @@ static int dvb_init(struct cx231xx *dev)
si2157_config.if_port = 1; si2157_config.if_port = 1;
si2157_config.inversion = true; si2157_config.inversion = true;
memset(&info, 0, sizeof(struct i2c_board_info)); /* perform probe/init/attach */
strlcpy(info.type, "si2157", I2C_NAME_SIZE); client = dvb_module_probe("si2157", NULL, tuner_i2c,
info.addr = dev->board.tuner_addr; dev->board.tuner_addr,
info.platform_data = &si2157_config; &si2157_config);
request_module("si2157"); if (!client) {
client = i2c_new_device(tuner_i2c, &info);
if (client == NULL || client->dev.driver == NULL) {
module_put(dvb->i2c_client_demod[0]->dev.driver->owner);
i2c_unregister_device(dvb->i2c_client_demod[0]);
result = -ENODEV;
goto out_free;
}
if (!try_module_get(client->dev.driver->owner)) {
dev_err(dev->dev,
"Failed to obtain %s tuner.\n", info.type);
i2c_unregister_device(client);
module_put(dvb->i2c_client_demod[0]->dev.driver->owner);
i2c_unregister_device(dvb->i2c_client_demod[0]);
result = -ENODEV; result = -ENODEV;
goto out_free; goto out_free;
} }
dev->cx231xx_reset_analog_tuner = NULL; dev->cx231xx_reset_analog_tuner = NULL;
dev->dvb->i2c_client_tuner = client; dev->dvb->i2c_client_tuner = client;
break; break;
} }
case CX231XX_BOARD_HAUPPAUGE_975: case CX231XX_BOARD_HAUPPAUGE_975:
{ {
struct i2c_client *client;
struct i2c_adapter *adapter;
struct i2c_adapter *adapter2; struct i2c_adapter *adapter2;
struct i2c_board_info info = {};
struct si2157_config si2157_config = {}; struct si2157_config si2157_config = {};
struct lgdt3306a_config lgdt3306a_config = {}; struct lgdt3306a_config lgdt3306a_config = {};
struct si2168_config si2168_config = {}; struct si2168_config si2168_config = {};
...@@ -1188,25 +1053,14 @@ static int dvb_init(struct cx231xx *dev) ...@@ -1188,25 +1053,14 @@ static int dvb_init(struct cx231xx *dev)
lgdt3306a_config.i2c_adapter = &adapter; lgdt3306a_config.i2c_adapter = &adapter;
lgdt3306a_config.deny_i2c_rptr = 0; lgdt3306a_config.deny_i2c_rptr = 0;
strlcpy(info.type, "lgdt3306a", sizeof(info.type)); /* perform probe/init/attach */
info.addr = dev->board.demod_addr; client = dvb_module_probe("lgdt3306a", NULL, demod_i2c,
info.platform_data = &lgdt3306a_config; dev->board.demod_addr,
&lgdt3306a_config);
request_module(info.type); if (!client) {
client = i2c_new_device(demod_i2c, &info);
if (client == NULL || client->dev.driver == NULL) {
result = -ENODEV; result = -ENODEV;
goto out_free; goto out_free;
} }
if (!try_module_get(client->dev.driver->owner)) {
dev_err(dev->dev,
"Failed to attach %s frontend.\n", info.type);
i2c_unregister_device(client);
result = -ENODEV;
goto out_free;
}
dvb->i2c_client_demod[0] = client; dvb->i2c_client_demod[0] = client;
/* attach second demodulator chip */ /* attach second demodulator chip */
...@@ -1215,30 +1069,14 @@ static int dvb_init(struct cx231xx *dev) ...@@ -1215,30 +1069,14 @@ static int dvb_init(struct cx231xx *dev)
si2168_config.i2c_adapter = &adapter2; si2168_config.i2c_adapter = &adapter2;
si2168_config.ts_clock_inv = true; si2168_config.ts_clock_inv = true;
memset(&info, 0, sizeof(struct i2c_board_info)); /* perform probe/init/attach */
strlcpy(info.type, "si2168", sizeof(info.type)); client = dvb_module_probe("si2168", NULL, adapter,
info.addr = dev->board.demod_addr2; dev->board.demod_addr2,
info.platform_data = &si2168_config; &si2168_config);
if (!client) {
request_module(info.type);
client = i2c_new_device(adapter, &info);
if (client == NULL || client->dev.driver == NULL) {
dev_err(dev->dev,
"Failed to attach %s frontend.\n", info.type);
module_put(dvb->i2c_client_demod[0]->dev.driver->owner);
i2c_unregister_device(dvb->i2c_client_demod[0]);
result = -ENODEV;
goto out_free;
}
if (!try_module_get(client->dev.driver->owner)) {
i2c_unregister_device(client);
module_put(dvb->i2c_client_demod[0]->dev.driver->owner);
i2c_unregister_device(dvb->i2c_client_demod[0]);
result = -ENODEV; result = -ENODEV;
goto out_free; goto out_free;
} }
dvb->i2c_client_demod[1] = client; dvb->i2c_client_demod[1] = client;
dvb->frontend[1]->id = 1; dvb->frontend[1]->id = 1;
...@@ -1254,34 +1092,14 @@ static int dvb_init(struct cx231xx *dev) ...@@ -1254,34 +1092,14 @@ static int dvb_init(struct cx231xx *dev)
si2157_config.if_port = 1; si2157_config.if_port = 1;
si2157_config.inversion = true; si2157_config.inversion = true;
memset(&info, 0, sizeof(struct i2c_board_info)); /* perform probe/init/attach */
strlcpy(info.type, "si2157", I2C_NAME_SIZE); client = dvb_module_probe("si2157", NULL, adapter,
info.addr = dev->board.tuner_addr; dev->board.tuner_addr,
info.platform_data = &si2157_config; &si2157_config);
request_module("si2157"); if (!client) {
client = i2c_new_device(adapter, &info);
if (client == NULL || client->dev.driver == NULL) {
module_put(dvb->i2c_client_demod[1]->dev.driver->owner);
i2c_unregister_device(dvb->i2c_client_demod[1]);
module_put(dvb->i2c_client_demod[0]->dev.driver->owner);
i2c_unregister_device(dvb->i2c_client_demod[0]);
result = -ENODEV;
goto out_free;
}
if (!try_module_get(client->dev.driver->owner)) {
dev_err(dev->dev,
"Failed to obtain %s tuner.\n", info.type);
i2c_unregister_device(client);
module_put(dvb->i2c_client_demod[1]->dev.driver->owner);
i2c_unregister_device(dvb->i2c_client_demod[1]);
module_put(dvb->i2c_client_demod[0]->dev.driver->owner);
i2c_unregister_device(dvb->i2c_client_demod[0]);
result = -ENODEV; result = -ENODEV;
goto out_free; goto out_free;
} }
dev->cx231xx_reset_analog_tuner = NULL; dev->cx231xx_reset_analog_tuner = NULL;
dvb->i2c_client_tuner = client; dvb->i2c_client_tuner = client;
...@@ -1320,6 +1138,14 @@ static int dvb_init(struct cx231xx *dev) ...@@ -1320,6 +1138,14 @@ static int dvb_init(struct cx231xx *dev)
return result; return result;
out_free: out_free:
/* remove I2C tuner */
dvb_module_release(dvb->i2c_client_tuner);
dvb->i2c_client_tuner = NULL;
/* remove I2C demod(s) */
dvb_module_release(dvb->i2c_client_demod[1]);
dvb->i2c_client_demod[1] = NULL;
dvb_module_release(dvb->i2c_client_demod[0]);
dvb->i2c_client_demod[0] = NULL;
kfree(dvb); kfree(dvb);
dev->dvb = NULL; dev->dvb = NULL;
goto ret; goto ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment