pcmcia: synclink_cs: fix error handling in mgslpc_probe()
mgslpc_probe() ignores errors in mgslpc_add_device() and does not release all resource if mgslpc_config() failed. The patch adds returned code to mgslpc_add_device() and fixes the both issues. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
b95d788ac7
Коммит
d34138d057
|
@ -397,7 +397,7 @@ static int adapter_test(MGSLPC_INFO *info);
|
||||||
|
|
||||||
static int claim_resources(MGSLPC_INFO *info);
|
static int claim_resources(MGSLPC_INFO *info);
|
||||||
static void release_resources(MGSLPC_INFO *info);
|
static void release_resources(MGSLPC_INFO *info);
|
||||||
static void mgslpc_add_device(MGSLPC_INFO *info);
|
static int mgslpc_add_device(MGSLPC_INFO *info);
|
||||||
static void mgslpc_remove_device(MGSLPC_INFO *info);
|
static void mgslpc_remove_device(MGSLPC_INFO *info);
|
||||||
|
|
||||||
static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty);
|
static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty);
|
||||||
|
@ -549,14 +549,21 @@ static int mgslpc_probe(struct pcmcia_device *link)
|
||||||
/* Initialize the struct pcmcia_device structure */
|
/* Initialize the struct pcmcia_device structure */
|
||||||
|
|
||||||
ret = mgslpc_config(link);
|
ret = mgslpc_config(link);
|
||||||
if (ret) {
|
if (ret != 0)
|
||||||
tty_port_destroy(&info->port);
|
goto failed;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
mgslpc_add_device(info);
|
ret = mgslpc_add_device(info);
|
||||||
|
if (ret != 0)
|
||||||
|
goto failed_release;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
failed_release:
|
||||||
|
mgslpc_release((u_long)link);
|
||||||
|
failed:
|
||||||
|
tty_port_destroy(&info->port);
|
||||||
|
kfree(info);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Card has been inserted.
|
/* Card has been inserted.
|
||||||
|
@ -2706,8 +2713,12 @@ static void release_resources(MGSLPC_INFO *info)
|
||||||
*
|
*
|
||||||
* Arguments: info pointer to device instance data
|
* Arguments: info pointer to device instance data
|
||||||
*/
|
*/
|
||||||
static void mgslpc_add_device(MGSLPC_INFO *info)
|
static int mgslpc_add_device(MGSLPC_INFO *info)
|
||||||
{
|
{
|
||||||
|
MGSLPC_INFO *current_dev = NULL;
|
||||||
|
struct device *tty_dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
info->next_device = NULL;
|
info->next_device = NULL;
|
||||||
info->line = mgslpc_device_count;
|
info->line = mgslpc_device_count;
|
||||||
sprintf(info->device_name,"ttySLP%d",info->line);
|
sprintf(info->device_name,"ttySLP%d",info->line);
|
||||||
|
@ -2722,7 +2733,7 @@ static void mgslpc_add_device(MGSLPC_INFO *info)
|
||||||
if (!mgslpc_device_list)
|
if (!mgslpc_device_list)
|
||||||
mgslpc_device_list = info;
|
mgslpc_device_list = info;
|
||||||
else {
|
else {
|
||||||
MGSLPC_INFO *current_dev = mgslpc_device_list;
|
current_dev = mgslpc_device_list;
|
||||||
while( current_dev->next_device )
|
while( current_dev->next_device )
|
||||||
current_dev = current_dev->next_device;
|
current_dev = current_dev->next_device;
|
||||||
current_dev->next_device = info;
|
current_dev->next_device = info;
|
||||||
|
@ -2737,10 +2748,30 @@ static void mgslpc_add_device(MGSLPC_INFO *info)
|
||||||
info->device_name, info->io_base, info->irq_level);
|
info->device_name, info->io_base, info->irq_level);
|
||||||
|
|
||||||
#if SYNCLINK_GENERIC_HDLC
|
#if SYNCLINK_GENERIC_HDLC
|
||||||
hdlcdev_init(info);
|
ret = hdlcdev_init(info);
|
||||||
|
if (ret != 0)
|
||||||
|
goto failed;
|
||||||
#endif
|
#endif
|
||||||
tty_port_register_device(&info->port, serial_driver, info->line,
|
|
||||||
|
tty_dev = tty_port_register_device(&info->port, serial_driver, info->line,
|
||||||
&info->p_dev->dev);
|
&info->p_dev->dev);
|
||||||
|
if (IS_ERR(tty_dev)) {
|
||||||
|
ret = PTR_ERR(tty_dev);
|
||||||
|
#if SYNCLINK_GENERIC_HDLC
|
||||||
|
hdlcdev_exit(info);
|
||||||
|
#endif
|
||||||
|
goto failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
if (current_dev)
|
||||||
|
current_dev->next_device = NULL;
|
||||||
|
else
|
||||||
|
mgslpc_device_list = NULL;
|
||||||
|
mgslpc_device_count--;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
|
static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче