aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndreas Herrmann <aherrman@de.ibm.com>2006-04-27 21:40:09 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-28 11:33:47 -0400
commita3ae39c060be57a4936d2c1d970e4d0c7d320d9c (patch)
treea8b0207d32f660fed21f55d0c4ab1c05f691ac39 /drivers
parent28f223782bca914ae65d08234c57c2175ecd7f5d (diff)
[PATCH] s390: qdio memory allocations
Avoid memory allocation with GFP_KERNEL in qdio_establish/qdio_shutdown. Use memory pool instead. (Otherwise this can lead to an I/O stall where qdio waits for a free page and zfcp waits for end of error recovery in low memory situations.) Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/cio/qdio.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index 814f9258ce00..a5bf272fe775 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -38,6 +38,7 @@
38#include <linux/kernel.h> 38#include <linux/kernel.h>
39#include <linux/proc_fs.h> 39#include <linux/proc_fs.h>
40#include <linux/timer.h> 40#include <linux/timer.h>
41#include <linux/mempool.h>
41 42
42#include <asm/ccwdev.h> 43#include <asm/ccwdev.h>
43#include <asm/io.h> 44#include <asm/io.h>
@@ -80,6 +81,8 @@ static int indicator_used[INDICATORS_PER_CACHELINE];
80static __u32 * volatile indicators; 81static __u32 * volatile indicators;
81static __u32 volatile spare_indicator; 82static __u32 volatile spare_indicator;
82static atomic_t spare_indicator_usecount; 83static atomic_t spare_indicator_usecount;
84#define QDIO_MEMPOOL_SCSSC_ELEMENTS 2
85static mempool_t *qdio_mempool_scssc;
83 86
84static debug_info_t *qdio_dbf_setup; 87static debug_info_t *qdio_dbf_setup;
85static debug_info_t *qdio_dbf_sbal; 88static debug_info_t *qdio_dbf_sbal;
@@ -2304,7 +2307,7 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
2304 2307
2305 QDIO_DBF_TEXT0(0,setup,"getssqd"); 2308 QDIO_DBF_TEXT0(0,setup,"getssqd");
2306 qdioac = 0; 2309 qdioac = 0;
2307 ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); 2310 ssqd_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
2308 if (!ssqd_area) { 2311 if (!ssqd_area) {
2309 QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \ 2312 QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \
2310 "SIGAs for sch x%x.\n", irq_ptr->schid.sch_no); 2313 "SIGAs for sch x%x.\n", irq_ptr->schid.sch_no);
@@ -2364,7 +2367,7 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr)
2364out: 2367out:
2365 qdio_check_subchannel_qebsm(irq_ptr, qdioac, 2368 qdio_check_subchannel_qebsm(irq_ptr, qdioac,
2366 ssqd_area->sch_token); 2369 ssqd_area->sch_token);
2367 free_page ((unsigned long) ssqd_area); 2370 mempool_free(ssqd_area, qdio_mempool_scssc);
2368 irq_ptr->qdioac = qdioac; 2371 irq_ptr->qdioac = qdioac;
2369} 2372}
2370 2373
@@ -2458,7 +2461,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
2458 virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind); 2461 virt_to_phys((volatile void *)irq_ptr->dev_st_chg_ind);
2459 } 2462 }
2460 2463
2461 scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); 2464 scssc_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
2462 if (!scssc_area) { 2465 if (!scssc_area) {
2463 QDIO_PRINT_WARN("No memory for setting indicators on " \ 2466 QDIO_PRINT_WARN("No memory for setting indicators on " \
2464 "subchannel 0.%x.%x.\n", 2467 "subchannel 0.%x.%x.\n",
@@ -2514,7 +2517,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero)
2514 QDIO_DBF_HEX2(0,setup,&real_addr_dev_st_chg_ind,sizeof(unsigned long)); 2517 QDIO_DBF_HEX2(0,setup,&real_addr_dev_st_chg_ind,sizeof(unsigned long));
2515 result = 0; 2518 result = 0;
2516out: 2519out:
2517 free_page ((unsigned long) scssc_area); 2520 mempool_free(scssc_area, qdio_mempool_scssc);
2518 return result; 2521 return result;
2519 2522
2520} 2523}
@@ -2543,7 +2546,7 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
2543 if (!irq_ptr->is_thinint_irq) 2546 if (!irq_ptr->is_thinint_irq)
2544 return -ENODEV; 2547 return -ENODEV;
2545 2548
2546 scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); 2549 scsscf_area = mempool_alloc(qdio_mempool_scssc, GFP_ATOMIC);
2547 if (!scsscf_area) { 2550 if (!scsscf_area) {
2548 QDIO_PRINT_WARN("No memory for setting delay target on " \ 2551 QDIO_PRINT_WARN("No memory for setting delay target on " \
2549 "subchannel 0.%x.%x.\n", 2552 "subchannel 0.%x.%x.\n",
@@ -2581,7 +2584,7 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target)
2581 QDIO_DBF_HEX2(0,trace,&delay_target,sizeof(unsigned long)); 2584 QDIO_DBF_HEX2(0,trace,&delay_target,sizeof(unsigned long));
2582 result = 0; /* not critical */ 2585 result = 0; /* not critical */
2583out: 2586out:
2584 free_page ((unsigned long) scsscf_area); 2587 mempool_free(scsscf_area, qdio_mempool_scssc);
2585 return result; 2588 return result;
2586} 2589}
2587 2590
@@ -3780,6 +3783,16 @@ oom:
3780 return -ENOMEM; 3783 return -ENOMEM;
3781} 3784}
3782 3785
3786static void *qdio_mempool_alloc(gfp_t gfp_mask, void *size)
3787{
3788 return (void *) get_zeroed_page(gfp_mask|GFP_DMA);
3789}
3790
3791static void qdio_mempool_free(void *element, void *size)
3792{
3793 free_page((unsigned long) element);
3794}
3795
3783static int __init 3796static int __init
3784init_QDIO(void) 3797init_QDIO(void)
3785{ 3798{
@@ -3809,6 +3822,10 @@ init_QDIO(void)
3809 3822
3810 qdio_add_procfs_entry(); 3823 qdio_add_procfs_entry();
3811 3824
3825 qdio_mempool_scssc = mempool_create(QDIO_MEMPOOL_SCSSC_ELEMENTS,
3826 qdio_mempool_alloc,
3827 qdio_mempool_free, NULL);
3828
3812 if (tiqdio_check_chsc_availability()) 3829 if (tiqdio_check_chsc_availability())
3813 QDIO_PRINT_ERR("Not all CHSCs supported. Continuing.\n"); 3830 QDIO_PRINT_ERR("Not all CHSCs supported. Continuing.\n");
3814 3831
@@ -3824,6 +3841,7 @@ cleanup_QDIO(void)
3824 qdio_remove_procfs_entry(); 3841 qdio_remove_procfs_entry();
3825 qdio_release_qdio_memory(); 3842 qdio_release_qdio_memory();
3826 qdio_unregister_dbf_views(); 3843 qdio_unregister_dbf_views();
3844 mempool_destroy(qdio_mempool_scssc);
3827 3845
3828 printk("qdio: %s: module removed\n",version); 3846 printk("qdio: %s: module removed\n",version);
3829} 3847}