aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Khoroshilov <khoroshilov@ispras.ru>2013-02-06 19:00:34 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-02-08 15:21:19 -0500
commitd34138d057628211b1c835e13a64d0cc2423c969 (patch)
treedf6748f0f35437ceb4e3d0fdd49e8f6db2957cb4
parentb95d788ac72b86515842a4eb92bb58a8da76a975 (diff)
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>
-rw-r--r--drivers/char/pcmcia/synclink_cs.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index b66eaa04f8cb..56e4e940fa19 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -397,7 +397,7 @@ static int adapter_test(MGSLPC_INFO *info);
397 397
398static int claim_resources(MGSLPC_INFO *info); 398static int claim_resources(MGSLPC_INFO *info);
399static void release_resources(MGSLPC_INFO *info); 399static void release_resources(MGSLPC_INFO *info);
400static void mgslpc_add_device(MGSLPC_INFO *info); 400static int mgslpc_add_device(MGSLPC_INFO *info);
401static void mgslpc_remove_device(MGSLPC_INFO *info); 401static void mgslpc_remove_device(MGSLPC_INFO *info);
402 402
403static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty); 403static bool rx_get_frame(MGSLPC_INFO *info, struct tty_struct *tty);
@@ -549,14 +549,21 @@ static int mgslpc_probe(struct pcmcia_device *link)
549 /* Initialize the struct pcmcia_device structure */ 549 /* Initialize the struct pcmcia_device structure */
550 550
551 ret = mgslpc_config(link); 551 ret = mgslpc_config(link);
552 if (ret) { 552 if (ret != 0)
553 tty_port_destroy(&info->port); 553 goto failed;
554 return ret;
555 }
556 554
557 mgslpc_add_device(info); 555 ret = mgslpc_add_device(info);
556 if (ret != 0)
557 goto failed_release;
558 558
559 return 0; 559 return 0;
560
561failed_release:
562 mgslpc_release((u_long)link);
563failed:
564 tty_port_destroy(&info->port);
565 kfree(info);
566 return ret;
560} 567}
561 568
562/* Card has been inserted. 569/* Card has been inserted.
@@ -2706,8 +2713,12 @@ static void release_resources(MGSLPC_INFO *info)
2706 * 2713 *
2707 * Arguments: info pointer to device instance data 2714 * Arguments: info pointer to device instance data
2708 */ 2715 */
2709static void mgslpc_add_device(MGSLPC_INFO *info) 2716static int mgslpc_add_device(MGSLPC_INFO *info)
2710{ 2717{
2718 MGSLPC_INFO *current_dev = NULL;
2719 struct device *tty_dev;
2720 int ret;
2721
2711 info->next_device = NULL; 2722 info->next_device = NULL;
2712 info->line = mgslpc_device_count; 2723 info->line = mgslpc_device_count;
2713 sprintf(info->device_name,"ttySLP%d",info->line); 2724 sprintf(info->device_name,"ttySLP%d",info->line);
@@ -2722,7 +2733,7 @@ static void mgslpc_add_device(MGSLPC_INFO *info)
2722 if (!mgslpc_device_list) 2733 if (!mgslpc_device_list)
2723 mgslpc_device_list = info; 2734 mgslpc_device_list = info;
2724 else { 2735 else {
2725 MGSLPC_INFO *current_dev = mgslpc_device_list; 2736 current_dev = mgslpc_device_list;
2726 while( current_dev->next_device ) 2737 while( current_dev->next_device )
2727 current_dev = current_dev->next_device; 2738 current_dev = current_dev->next_device;
2728 current_dev->next_device = info; 2739 current_dev->next_device = info;
@@ -2737,10 +2748,30 @@ static void mgslpc_add_device(MGSLPC_INFO *info)
2737 info->device_name, info->io_base, info->irq_level); 2748 info->device_name, info->io_base, info->irq_level);
2738 2749
2739#if SYNCLINK_GENERIC_HDLC 2750#if SYNCLINK_GENERIC_HDLC
2740 hdlcdev_init(info); 2751 ret = hdlcdev_init(info);
2752 if (ret != 0)
2753 goto failed;
2741#endif 2754#endif
2742 tty_port_register_device(&info->port, serial_driver, info->line, 2755
2756 tty_dev = tty_port_register_device(&info->port, serial_driver, info->line,
2743 &info->p_dev->dev); 2757 &info->p_dev->dev);
2758 if (IS_ERR(tty_dev)) {
2759 ret = PTR_ERR(tty_dev);
2760#if SYNCLINK_GENERIC_HDLC
2761 hdlcdev_exit(info);
2762#endif
2763 goto failed;
2764 }
2765
2766 return 0;
2767
2768failed:
2769 if (current_dev)
2770 current_dev->next_device = NULL;
2771 else
2772 mgslpc_device_list = NULL;
2773 mgslpc_device_count--;
2774 return ret;
2744} 2775}
2745 2776
2746static void mgslpc_remove_device(MGSLPC_INFO *remove_info) 2777static void mgslpc_remove_device(MGSLPC_INFO *remove_info)