aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2012-04-02 07:54:08 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-09 14:27:28 -0400
commitfe2fc9ca5d7e5d9144a4039d89a6f1f8967d9263 (patch)
treec1e74648f89313c92e86ac2943dabefc5c4d0e05 /drivers/s390
parent9f8c0b081daff1dbf9ca889560bf25aef0a75207 (diff)
TTY: con3215, centralize allocation
There are two copies of allocations of device information. One of them is totally broken. See: raw->cdev = cdev; raw->inbuf = (char *) raw + sizeof(struct raw3215_info); memset(raw, 0, sizeof(struct raw3215_info)); It suggests that this path was never executed. The code uses both raw->cdev and raw->inbuf all over. And it is NULL due to the memset here, so it would panic immediately. I believe nobody used that driver without being a system console. Either way, let us fix it by moving the allocations (and initializations) to a single place. This will save us some double initializations later too. And while at it, initialize the timer properly -- once, at the allocation. Signed-off-by: Jiri Slaby <jslaby@suse.cz> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/char/con3215.c74
1 files changed, 39 insertions, 35 deletions
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 4f9f1dcc1551..7e30f85ee3a5 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -324,10 +324,7 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
324 } 324 }
325 } else if (!(raw->flags & RAW3215_TIMER_RUNS)) { 325 } else if (!(raw->flags & RAW3215_TIMER_RUNS)) {
326 /* delay small writes */ 326 /* delay small writes */
327 init_timer(&raw->timer);
328 raw->timer.expires = RAW3215_TIMEOUT + jiffies; 327 raw->timer.expires = RAW3215_TIMEOUT + jiffies;
329 raw->timer.data = (unsigned long) raw;
330 raw->timer.function = raw3215_timeout;
331 add_timer(&raw->timer); 328 add_timer(&raw->timer);
332 raw->flags |= RAW3215_TIMER_RUNS; 329 raw->flags |= RAW3215_TIMER_RUNS;
333 } 330 }
@@ -648,6 +645,35 @@ static void raw3215_shutdown(struct raw3215_info *raw)
648 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); 645 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
649} 646}
650 647
648static struct raw3215_info *raw3215_alloc_info(void)
649{
650 struct raw3215_info *info;
651
652 info = kzalloc(sizeof(struct raw3215_info), GFP_KERNEL | GFP_DMA);
653 if (!info)
654 return NULL;
655
656 info->buffer = kzalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
657 info->inbuf = kzalloc(RAW3215_INBUF_SIZE, GFP_KERNEL | GFP_DMA);
658 if (!info->buffer || !info->inbuf) {
659 kfree(info);
660 return NULL;
661 }
662
663 setup_timer(&info->timer, raw3215_timeout, (unsigned long)info);
664 init_waitqueue_head(&info->empty_wait);
665 tasklet_init(&info->tlet, raw3215_wakeup, (unsigned long)info);
666
667 return info;
668}
669
670static void raw3215_free_info(struct raw3215_info *raw)
671{
672 kfree(raw->inbuf);
673 kfree(raw->buffer);
674 kfree(raw);
675}
676
651static int raw3215_probe (struct ccw_device *cdev) 677static int raw3215_probe (struct ccw_device *cdev)
652{ 678{
653 struct raw3215_info *raw; 679 struct raw3215_info *raw;
@@ -656,11 +682,15 @@ static int raw3215_probe (struct ccw_device *cdev)
656 /* Console is special. */ 682 /* Console is special. */
657 if (raw3215[0] && (raw3215[0] == dev_get_drvdata(&cdev->dev))) 683 if (raw3215[0] && (raw3215[0] == dev_get_drvdata(&cdev->dev)))
658 return 0; 684 return 0;
659 raw = kmalloc(sizeof(struct raw3215_info) + 685
660 RAW3215_INBUF_SIZE, GFP_KERNEL|GFP_DMA); 686 raw = raw3215_alloc_info();
661 if (raw == NULL) 687 if (raw == NULL)
662 return -ENOMEM; 688 return -ENOMEM;
663 689
690 raw->cdev = cdev;
691 dev_set_drvdata(&cdev->dev, raw);
692 cdev->handler = raw3215_irq;
693
664 spin_lock(&raw3215_device_lock); 694 spin_lock(&raw3215_device_lock);
665 for (line = 0; line < NR_3215; line++) { 695 for (line = 0; line < NR_3215; line++) {
666 if (!raw3215[line]) { 696 if (!raw3215[line]) {
@@ -670,28 +700,10 @@ static int raw3215_probe (struct ccw_device *cdev)
670 } 700 }
671 spin_unlock(&raw3215_device_lock); 701 spin_unlock(&raw3215_device_lock);
672 if (line == NR_3215) { 702 if (line == NR_3215) {
673 kfree(raw); 703 raw3215_free_info(raw);
674 return -ENODEV; 704 return -ENODEV;
675 } 705 }
676 706
677 raw->cdev = cdev;
678 raw->inbuf = (char *) raw + sizeof(struct raw3215_info);
679 memset(raw, 0, sizeof(struct raw3215_info));
680 raw->buffer = kmalloc(RAW3215_BUFFER_SIZE,
681 GFP_KERNEL|GFP_DMA);
682 if (raw->buffer == NULL) {
683 spin_lock(&raw3215_device_lock);
684 raw3215[line] = NULL;
685 spin_unlock(&raw3215_device_lock);
686 kfree(raw);
687 return -ENOMEM;
688 }
689 init_waitqueue_head(&raw->empty_wait);
690 tasklet_init(&raw->tlet, raw3215_wakeup, (unsigned long) raw);
691
692 dev_set_drvdata(&cdev->dev, raw);
693 cdev->handler = raw3215_irq;
694
695 return 0; 707 return 0;
696} 708}
697 709
@@ -703,8 +715,7 @@ static void raw3215_remove (struct ccw_device *cdev)
703 raw = dev_get_drvdata(&cdev->dev); 715 raw = dev_get_drvdata(&cdev->dev);
704 if (raw) { 716 if (raw) {
705 dev_set_drvdata(&cdev->dev, NULL); 717 dev_set_drvdata(&cdev->dev, NULL);
706 kfree(raw->buffer); 718 raw3215_free_info(raw);
707 kfree(raw);
708 } 719 }
709} 720}
710 721
@@ -897,23 +908,16 @@ static int __init con3215_init(void)
897 if (IS_ERR(cdev)) 908 if (IS_ERR(cdev))
898 return -ENODEV; 909 return -ENODEV;
899 910
900 raw3215[0] = raw = (struct raw3215_info *) 911 raw3215[0] = raw = raw3215_alloc_info();
901 kzalloc(sizeof(struct raw3215_info), GFP_KERNEL | GFP_DMA);
902 raw->buffer = kzalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
903 raw->inbuf = kzalloc(RAW3215_INBUF_SIZE, GFP_KERNEL | GFP_DMA);
904 raw->cdev = cdev; 912 raw->cdev = cdev;
905 dev_set_drvdata(&cdev->dev, raw); 913 dev_set_drvdata(&cdev->dev, raw);
906 cdev->handler = raw3215_irq; 914 cdev->handler = raw3215_irq;
907 915
908 raw->flags |= RAW3215_FIXED; 916 raw->flags |= RAW3215_FIXED;
909 init_waitqueue_head(&raw->empty_wait);
910 tasklet_init(&raw->tlet, raw3215_wakeup, (unsigned long) raw);
911 917
912 /* Request the console irq */ 918 /* Request the console irq */
913 if (raw3215_startup(raw) != 0) { 919 if (raw3215_startup(raw) != 0) {
914 kfree(raw->inbuf); 920 raw3215_free_info(raw);
915 kfree(raw->buffer);
916 kfree(raw);
917 raw3215[0] = NULL; 921 raw3215[0] = NULL;
918 return -ENODEV; 922 return -ENODEV;
919 } 923 }