aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorroel kluin <roel.kluin@gmail.com>2009-09-20 03:11:28 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-22 17:00:12 -0400
commit5d5baa92664e66f63b75abc51fbcd0b96d81f5d8 (patch)
tree3252e79137a936d4dfaa9b0f97b7389d99288364 /drivers
parent74a61ebf653c6abe459f228eb40e9f24f7ef1fb7 (diff)
atm: dereference of he_dev->rbps_virt in he_init_group()
he_dev->rbps_virt or he_dev->rbpl_virt allocation may fail, s them. Make sure that he_init_group() cleans up after errors. Signed-off-by: Roel Kluin <roel.kluin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/atm/he.c59
1 files changed, 50 insertions, 9 deletions
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 2de64065aa1b..29e66d603d3c 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -790,11 +790,15 @@ he_init_group(struct he_dev *he_dev, int group)
790 he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev, 790 he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev,
791 CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys); 791 CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys);
792 if (he_dev->rbps_base == NULL) { 792 if (he_dev->rbps_base == NULL) {
793 hprintk("failed to alloc rbps\n"); 793 hprintk("failed to alloc rbps_base\n");
794 return -ENOMEM; 794 goto out_destroy_rbps_pool;
795 } 795 }
796 memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp)); 796 memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp));
797 he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL); 797 he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL);
798 if (he_dev->rbps_virt == NULL) {
799 hprintk("failed to alloc rbps_virt\n");
800 goto out_free_rbps_base;
801 }
798 802
799 for (i = 0; i < CONFIG_RBPS_SIZE; ++i) { 803 for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
800 dma_addr_t dma_handle; 804 dma_addr_t dma_handle;
@@ -802,7 +806,7 @@ he_init_group(struct he_dev *he_dev, int group)
802 806
803 cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle); 807 cpuaddr = pci_pool_alloc(he_dev->rbps_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
804 if (cpuaddr == NULL) 808 if (cpuaddr == NULL)
805 return -ENOMEM; 809 goto out_free_rbps_virt;
806 810
807 he_dev->rbps_virt[i].virt = cpuaddr; 811 he_dev->rbps_virt[i].virt = cpuaddr;
808 he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF); 812 he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF);
@@ -827,17 +831,21 @@ he_init_group(struct he_dev *he_dev, int group)
827 CONFIG_RBPL_BUFSIZE, 8, 0); 831 CONFIG_RBPL_BUFSIZE, 8, 0);
828 if (he_dev->rbpl_pool == NULL) { 832 if (he_dev->rbpl_pool == NULL) {
829 hprintk("unable to create rbpl pool\n"); 833 hprintk("unable to create rbpl pool\n");
830 return -ENOMEM; 834 goto out_free_rbps_virt;
831 } 835 }
832 836
833 he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev, 837 he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev,
834 CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys); 838 CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys);
835 if (he_dev->rbpl_base == NULL) { 839 if (he_dev->rbpl_base == NULL) {
836 hprintk("failed to alloc rbpl\n"); 840 hprintk("failed to alloc rbpl_base\n");
837 return -ENOMEM; 841 goto out_destroy_rbpl_pool;
838 } 842 }
839 memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp)); 843 memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp));
840 he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL); 844 he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL);
845 if (he_dev->rbpl_virt == NULL) {
846 hprintk("failed to alloc rbpl_virt\n");
847 goto out_free_rbpl_base;
848 }
841 849
842 for (i = 0; i < CONFIG_RBPL_SIZE; ++i) { 850 for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
843 dma_addr_t dma_handle; 851 dma_addr_t dma_handle;
@@ -845,7 +853,7 @@ he_init_group(struct he_dev *he_dev, int group)
845 853
846 cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle); 854 cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, GFP_KERNEL|GFP_DMA, &dma_handle);
847 if (cpuaddr == NULL) 855 if (cpuaddr == NULL)
848 return -ENOMEM; 856 goto out_free_rbpl_virt;
849 857
850 he_dev->rbpl_virt[i].virt = cpuaddr; 858 he_dev->rbpl_virt[i].virt = cpuaddr;
851 he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF); 859 he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF);
@@ -870,7 +878,7 @@ he_init_group(struct he_dev *he_dev, int group)
870 CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys); 878 CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys);
871 if (he_dev->rbrq_base == NULL) { 879 if (he_dev->rbrq_base == NULL) {
872 hprintk("failed to allocate rbrq\n"); 880 hprintk("failed to allocate rbrq\n");
873 return -ENOMEM; 881 goto out_free_rbpl_virt;
874 } 882 }
875 memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq)); 883 memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq));
876 884
@@ -894,7 +902,7 @@ he_init_group(struct he_dev *he_dev, int group)
894 CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys); 902 CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys);
895 if (he_dev->tbrq_base == NULL) { 903 if (he_dev->tbrq_base == NULL) {
896 hprintk("failed to allocate tbrq\n"); 904 hprintk("failed to allocate tbrq\n");
897 return -ENOMEM; 905 goto out_free_rbpq_base;
898 } 906 }
899 memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq)); 907 memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq));
900 908
@@ -906,6 +914,39 @@ he_init_group(struct he_dev *he_dev, int group)
906 he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16)); 914 he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16));
907 915
908 return 0; 916 return 0;
917
918out_free_rbpq_base:
919 pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE *
920 sizeof(struct he_rbrq), he_dev->rbrq_base,
921 he_dev->rbrq_phys);
922 i = CONFIG_RBPL_SIZE;
923out_free_rbpl_virt:
924 while (--i)
925 pci_pool_free(he_dev->rbps_pool, he_dev->rbpl_virt[i].virt,
926 he_dev->rbps_base[i].phys);
927 kfree(he_dev->rbpl_virt);
928
929out_free_rbpl_base:
930 pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE *
931 sizeof(struct he_rbp), he_dev->rbpl_base,
932 he_dev->rbpl_phys);
933out_destroy_rbpl_pool:
934 pci_pool_destroy(he_dev->rbpl_pool);
935
936 i = CONFIG_RBPL_SIZE;
937out_free_rbps_virt:
938 while (--i)
939 pci_pool_free(he_dev->rbpl_pool, he_dev->rbps_virt[i].virt,
940 he_dev->rbpl_base[i].phys);
941 kfree(he_dev->rbps_virt);
942
943out_free_rbps_base:
944 pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE *
945 sizeof(struct he_rbp), he_dev->rbps_base,
946 he_dev->rbps_phys);
947out_destroy_rbps_pool:
948 pci_pool_destroy(he_dev->rbps_pool);
949 return -ENOMEM;
909} 950}
910 951
911static int __devinit 952static int __devinit