aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2007-08-10 08:32:28 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-08-10 08:32:36 -0400
commitc6d0e8014a59b641c0669cf5df151667144f220e (patch)
treeac16722d835e946e05266ed2208c1cba30c3260d /drivers/s390
parentb01af5ba9105094ba4f1af60da8f7be44321a0c7 (diff)
[S390] qdio: make sure data structures are correctly aligned.
The slsb structure contained at the beginning of the qdio_q structure must start on a 256 byte boundary. To make sure this is the case even if slab debugging is turned on create an own slab cache for qdio_q structures. Besides that don't use the slab allocator to allocate whole pages. Use the page allocator instead. Also fix a few memory leaks in error handling code. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/qdio.c92
1 files changed, 47 insertions, 45 deletions
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index ed026a1dc324..03347aed2b3e 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -81,6 +81,7 @@ static __u32 volatile spare_indicator;
81static atomic_t spare_indicator_usecount; 81static atomic_t spare_indicator_usecount;
82#define QDIO_MEMPOOL_SCSSC_ELEMENTS 2 82#define QDIO_MEMPOOL_SCSSC_ELEMENTS 2
83static mempool_t *qdio_mempool_scssc; 83static mempool_t *qdio_mempool_scssc;
84static struct kmem_cache *qdio_q_cache;
84 85
85static debug_info_t *qdio_dbf_setup; 86static debug_info_t *qdio_dbf_setup;
86static debug_info_t *qdio_dbf_sbal; 87static debug_info_t *qdio_dbf_sbal;
@@ -1617,23 +1618,21 @@ static void
1617qdio_release_irq_memory(struct qdio_irq *irq_ptr) 1618qdio_release_irq_memory(struct qdio_irq *irq_ptr)
1618{ 1619{
1619 int i; 1620 int i;
1621 struct qdio_q *q;
1620 1622
1621 for (i=0;i<QDIO_MAX_QUEUES_PER_IRQ;i++) { 1623 for (i = 0; i < QDIO_MAX_QUEUES_PER_IRQ; i++) {
1622 if (!irq_ptr->input_qs[i]) 1624 q = irq_ptr->input_qs[i];
1623 goto next; 1625 if (q) {
1624 1626 free_page((unsigned long) q->slib);
1625 kfree(irq_ptr->input_qs[i]->slib); 1627 kmem_cache_free(qdio_q_cache, q);
1626 kfree(irq_ptr->input_qs[i]); 1628 }
1627 1629 q = irq_ptr->output_qs[i];
1628next: 1630 if (q) {
1629 if (!irq_ptr->output_qs[i]) 1631 free_page((unsigned long) q->slib);
1630 continue; 1632 kmem_cache_free(qdio_q_cache, q);
1631 1633 }
1632 kfree(irq_ptr->output_qs[i]->slib);
1633 kfree(irq_ptr->output_qs[i]);
1634
1635 } 1634 }
1636 kfree(irq_ptr->qdr); 1635 free_page((unsigned long) irq_ptr->qdr);
1637 free_page((unsigned long) irq_ptr); 1636 free_page((unsigned long) irq_ptr);
1638} 1637}
1639 1638
@@ -1680,44 +1679,35 @@ qdio_alloc_qs(struct qdio_irq *irq_ptr,
1680{ 1679{
1681 int i; 1680 int i;
1682 struct qdio_q *q; 1681 struct qdio_q *q;
1683 int result=-ENOMEM;
1684
1685 for (i=0;i<no_input_qs;i++) {
1686 q = kzalloc(sizeof(struct qdio_q), GFP_KERNEL);
1687 1682
1688 if (!q) { 1683 for (i = 0; i < no_input_qs; i++) {
1689 QDIO_PRINT_ERR("kmalloc of q failed!\n"); 1684 q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL);
1690 goto out; 1685 if (!q)
1691 } 1686 return -ENOMEM;
1687 memset(q, 0, sizeof(*q));
1692 1688
1693 q->slib = kmalloc(PAGE_SIZE, GFP_KERNEL); 1689 q->slib = (struct slib *) __get_free_page(GFP_KERNEL);
1694 if (!q->slib) { 1690 if (!q->slib) {
1695 QDIO_PRINT_ERR("kmalloc of slib failed!\n"); 1691 kmem_cache_free(qdio_q_cache, q);
1696 goto out; 1692 return -ENOMEM;
1697 } 1693 }
1698
1699 irq_ptr->input_qs[i]=q; 1694 irq_ptr->input_qs[i]=q;
1700 } 1695 }
1701 1696
1702 for (i=0;i<no_output_qs;i++) { 1697 for (i = 0; i < no_output_qs; i++) {
1703 q = kzalloc(sizeof(struct qdio_q), GFP_KERNEL); 1698 q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL);
1704 1699 if (!q)
1705 if (!q) { 1700 return -ENOMEM;
1706 goto out; 1701 memset(q, 0, sizeof(*q));
1707 }
1708 1702
1709 q->slib=kmalloc(PAGE_SIZE,GFP_KERNEL); 1703 q->slib = (struct slib *) __get_free_page(GFP_KERNEL);
1710 if (!q->slib) { 1704 if (!q->slib) {
1711 QDIO_PRINT_ERR("kmalloc of slib failed!\n"); 1705 kmem_cache_free(qdio_q_cache, q);
1712 goto out; 1706 return -ENOMEM;
1713 } 1707 }
1714
1715 irq_ptr->output_qs[i]=q; 1708 irq_ptr->output_qs[i]=q;
1716 } 1709 }
1717 1710 return 0;
1718 result=0;
1719out:
1720 return result;
1721} 1711}
1722 1712
1723static void 1713static void
@@ -2985,17 +2975,17 @@ qdio_allocate(struct qdio_initialize *init_data)
2985 QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*)); 2975 QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*));
2986 2976
2987 if (!irq_ptr) { 2977 if (!irq_ptr) {
2988 QDIO_PRINT_ERR("kmalloc of irq_ptr failed!\n"); 2978 QDIO_PRINT_ERR("allocation of irq_ptr failed!\n");
2989 return -ENOMEM; 2979 return -ENOMEM;
2990 } 2980 }
2991 2981
2992 init_MUTEX(&irq_ptr->setting_up_sema); 2982 init_MUTEX(&irq_ptr->setting_up_sema);
2993 2983
2994 /* QDR must be in DMA area since CCW data address is only 32 bit */ 2984 /* QDR must be in DMA area since CCW data address is only 32 bit */
2995 irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA); 2985 irq_ptr->qdr = (struct qdr *) __get_free_page(GFP_KERNEL | GFP_DMA);
2996 if (!(irq_ptr->qdr)) { 2986 if (!(irq_ptr->qdr)) {
2997 free_page((unsigned long) irq_ptr); 2987 free_page((unsigned long) irq_ptr);
2998 QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n"); 2988 QDIO_PRINT_ERR("allocation of irq_ptr->qdr failed!\n");
2999 return -ENOMEM; 2989 return -ENOMEM;
3000 } 2990 }
3001 QDIO_DBF_TEXT0(0,setup,"qdr:"); 2991 QDIO_DBF_TEXT0(0,setup,"qdr:");
@@ -3004,6 +2994,7 @@ qdio_allocate(struct qdio_initialize *init_data)
3004 if (qdio_alloc_qs(irq_ptr, 2994 if (qdio_alloc_qs(irq_ptr,
3005 init_data->no_input_qs, 2995 init_data->no_input_qs,
3006 init_data->no_output_qs)) { 2996 init_data->no_output_qs)) {
2997 QDIO_PRINT_ERR("queue allocation failed!\n");
3007 qdio_release_irq_memory(irq_ptr); 2998 qdio_release_irq_memory(irq_ptr);
3008 return -ENOMEM; 2999 return -ENOMEM;
3009 } 3000 }
@@ -3895,9 +3886,19 @@ init_QDIO(void)
3895 if (res) 3886 if (res)
3896 return res; 3887 return res;
3897 3888
3889 qdio_q_cache = kmem_cache_create("qdio_q", sizeof(struct qdio_q),
3890 256, 0, NULL);
3891 if (!qdio_q_cache) {
3892 qdio_release_qdio_memory();
3893 return -ENOMEM;
3894 }
3895
3898 res = qdio_register_dbf_views(); 3896 res = qdio_register_dbf_views();
3899 if (res) 3897 if (res) {
3898 kmem_cache_destroy(qdio_q_cache);
3899 qdio_release_qdio_memory();
3900 return res; 3900 return res;
3901 }
3901 3902
3902 QDIO_DBF_TEXT0(0,setup,"initQDIO"); 3903 QDIO_DBF_TEXT0(0,setup,"initQDIO");
3903 res = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats); 3904 res = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
@@ -3929,6 +3930,7 @@ cleanup_QDIO(void)
3929 qdio_release_qdio_memory(); 3930 qdio_release_qdio_memory();
3930 qdio_unregister_dbf_views(); 3931 qdio_unregister_dbf_views();
3931 mempool_destroy(qdio_mempool_scssc); 3932 mempool_destroy(qdio_mempool_scssc);
3933 kmem_cache_destroy(qdio_q_cache);
3932 bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats); 3934 bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
3933 printk("qdio: %s: module removed\n",version); 3935 printk("qdio: %s: module removed\n",version);
3934} 3936}