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:
Alexey Khoroshilov 2013-02-07 01:00:34 +01:00 коммит произвёл Greg Kroah-Hartman
Родитель b95d788ac7
Коммит d34138d057
1 изменённых файлов: 41 добавлений и 10 удалений

Просмотреть файл

@ -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)