diff options
Diffstat (limited to 'drivers/s390/cio/qdio.c')
-rw-r--r-- | drivers/s390/cio/qdio.c | 97 |
1 files changed, 51 insertions, 46 deletions
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index ed026a1dc324..d8d479876ec7 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
@@ -81,6 +81,7 @@ static __u32 volatile spare_indicator; | |||
81 | static atomic_t spare_indicator_usecount; | 81 | static atomic_t spare_indicator_usecount; |
82 | #define QDIO_MEMPOOL_SCSSC_ELEMENTS 2 | 82 | #define QDIO_MEMPOOL_SCSSC_ELEMENTS 2 |
83 | static mempool_t *qdio_mempool_scssc; | 83 | static mempool_t *qdio_mempool_scssc; |
84 | static struct kmem_cache *qdio_q_cache; | ||
84 | 85 | ||
85 | static debug_info_t *qdio_dbf_setup; | 86 | static debug_info_t *qdio_dbf_setup; |
86 | static debug_info_t *qdio_dbf_sbal; | 87 | static debug_info_t *qdio_dbf_sbal; |
@@ -194,6 +195,8 @@ qdio_do_eqbs(struct qdio_q *q, unsigned char *state, | |||
194 | again: | 195 | again: |
195 | ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt); | 196 | ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt); |
196 | rc = qdio_check_ccq(q, ccq); | 197 | rc = qdio_check_ccq(q, ccq); |
198 | if ((ccq == 96) && (tmp_cnt != *cnt)) | ||
199 | rc = 0; | ||
197 | if (rc == 1) { | 200 | if (rc == 1) { |
198 | QDIO_DBF_TEXT5(1,trace,"eqAGAIN"); | 201 | QDIO_DBF_TEXT5(1,trace,"eqAGAIN"); |
199 | goto again; | 202 | goto again; |
@@ -739,7 +742,8 @@ qdio_get_outbound_buffer_frontier(struct qdio_q *q) | |||
739 | first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used), | 742 | first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used), |
740 | (QDIO_MAX_BUFFERS_PER_Q-1)); | 743 | (QDIO_MAX_BUFFERS_PER_Q-1)); |
741 | 744 | ||
742 | if ((!q->is_iqdio_q)&&(!q->hydra_gives_outbound_pcis)) | 745 | if (((!q->is_iqdio_q) && (!q->hydra_gives_outbound_pcis)) || |
746 | (q->queue_type == QDIO_IQDIO_QFMT_ASYNCH)) | ||
743 | SYNC_MEMORY; | 747 | SYNC_MEMORY; |
744 | 748 | ||
745 | check_next: | 749 | check_next: |
@@ -1617,23 +1621,21 @@ static void | |||
1617 | qdio_release_irq_memory(struct qdio_irq *irq_ptr) | 1621 | qdio_release_irq_memory(struct qdio_irq *irq_ptr) |
1618 | { | 1622 | { |
1619 | int i; | 1623 | int i; |
1624 | struct qdio_q *q; | ||
1620 | 1625 | ||
1621 | for (i=0;i<QDIO_MAX_QUEUES_PER_IRQ;i++) { | 1626 | for (i = 0; i < QDIO_MAX_QUEUES_PER_IRQ; i++) { |
1622 | if (!irq_ptr->input_qs[i]) | 1627 | q = irq_ptr->input_qs[i]; |
1623 | goto next; | 1628 | if (q) { |
1624 | 1629 | free_page((unsigned long) q->slib); | |
1625 | kfree(irq_ptr->input_qs[i]->slib); | 1630 | kmem_cache_free(qdio_q_cache, q); |
1626 | kfree(irq_ptr->input_qs[i]); | 1631 | } |
1627 | 1632 | q = irq_ptr->output_qs[i]; | |
1628 | next: | 1633 | if (q) { |
1629 | if (!irq_ptr->output_qs[i]) | 1634 | free_page((unsigned long) q->slib); |
1630 | continue; | 1635 | kmem_cache_free(qdio_q_cache, q); |
1631 | 1636 | } | |
1632 | kfree(irq_ptr->output_qs[i]->slib); | ||
1633 | kfree(irq_ptr->output_qs[i]); | ||
1634 | |||
1635 | } | 1637 | } |
1636 | kfree(irq_ptr->qdr); | 1638 | free_page((unsigned long) irq_ptr->qdr); |
1637 | free_page((unsigned long) irq_ptr); | 1639 | free_page((unsigned long) irq_ptr); |
1638 | } | 1640 | } |
1639 | 1641 | ||
@@ -1680,44 +1682,35 @@ qdio_alloc_qs(struct qdio_irq *irq_ptr, | |||
1680 | { | 1682 | { |
1681 | int i; | 1683 | int i; |
1682 | struct qdio_q *q; | 1684 | 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 | 1685 | ||
1688 | if (!q) { | 1686 | for (i = 0; i < no_input_qs; i++) { |
1689 | QDIO_PRINT_ERR("kmalloc of q failed!\n"); | 1687 | q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL); |
1690 | goto out; | 1688 | if (!q) |
1691 | } | 1689 | return -ENOMEM; |
1690 | memset(q, 0, sizeof(*q)); | ||
1692 | 1691 | ||
1693 | q->slib = kmalloc(PAGE_SIZE, GFP_KERNEL); | 1692 | q->slib = (struct slib *) __get_free_page(GFP_KERNEL); |
1694 | if (!q->slib) { | 1693 | if (!q->slib) { |
1695 | QDIO_PRINT_ERR("kmalloc of slib failed!\n"); | 1694 | kmem_cache_free(qdio_q_cache, q); |
1696 | goto out; | 1695 | return -ENOMEM; |
1697 | } | 1696 | } |
1698 | |||
1699 | irq_ptr->input_qs[i]=q; | 1697 | irq_ptr->input_qs[i]=q; |
1700 | } | 1698 | } |
1701 | 1699 | ||
1702 | for (i=0;i<no_output_qs;i++) { | 1700 | for (i = 0; i < no_output_qs; i++) { |
1703 | q = kzalloc(sizeof(struct qdio_q), GFP_KERNEL); | 1701 | q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL); |
1704 | 1702 | if (!q) | |
1705 | if (!q) { | 1703 | return -ENOMEM; |
1706 | goto out; | 1704 | memset(q, 0, sizeof(*q)); |
1707 | } | ||
1708 | 1705 | ||
1709 | q->slib=kmalloc(PAGE_SIZE,GFP_KERNEL); | 1706 | q->slib = (struct slib *) __get_free_page(GFP_KERNEL); |
1710 | if (!q->slib) { | 1707 | if (!q->slib) { |
1711 | QDIO_PRINT_ERR("kmalloc of slib failed!\n"); | 1708 | kmem_cache_free(qdio_q_cache, q); |
1712 | goto out; | 1709 | return -ENOMEM; |
1713 | } | 1710 | } |
1714 | |||
1715 | irq_ptr->output_qs[i]=q; | 1711 | irq_ptr->output_qs[i]=q; |
1716 | } | 1712 | } |
1717 | 1713 | return 0; | |
1718 | result=0; | ||
1719 | out: | ||
1720 | return result; | ||
1721 | } | 1714 | } |
1722 | 1715 | ||
1723 | static void | 1716 | static void |
@@ -2985,17 +2978,17 @@ qdio_allocate(struct qdio_initialize *init_data) | |||
2985 | QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*)); | 2978 | QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*)); |
2986 | 2979 | ||
2987 | if (!irq_ptr) { | 2980 | if (!irq_ptr) { |
2988 | QDIO_PRINT_ERR("kmalloc of irq_ptr failed!\n"); | 2981 | QDIO_PRINT_ERR("allocation of irq_ptr failed!\n"); |
2989 | return -ENOMEM; | 2982 | return -ENOMEM; |
2990 | } | 2983 | } |
2991 | 2984 | ||
2992 | init_MUTEX(&irq_ptr->setting_up_sema); | 2985 | init_MUTEX(&irq_ptr->setting_up_sema); |
2993 | 2986 | ||
2994 | /* QDR must be in DMA area since CCW data address is only 32 bit */ | 2987 | /* 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); | 2988 | irq_ptr->qdr = (struct qdr *) __get_free_page(GFP_KERNEL | GFP_DMA); |
2996 | if (!(irq_ptr->qdr)) { | 2989 | if (!(irq_ptr->qdr)) { |
2997 | free_page((unsigned long) irq_ptr); | 2990 | free_page((unsigned long) irq_ptr); |
2998 | QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n"); | 2991 | QDIO_PRINT_ERR("allocation of irq_ptr->qdr failed!\n"); |
2999 | return -ENOMEM; | 2992 | return -ENOMEM; |
3000 | } | 2993 | } |
3001 | QDIO_DBF_TEXT0(0,setup,"qdr:"); | 2994 | QDIO_DBF_TEXT0(0,setup,"qdr:"); |
@@ -3004,6 +2997,7 @@ qdio_allocate(struct qdio_initialize *init_data) | |||
3004 | if (qdio_alloc_qs(irq_ptr, | 2997 | if (qdio_alloc_qs(irq_ptr, |
3005 | init_data->no_input_qs, | 2998 | init_data->no_input_qs, |
3006 | init_data->no_output_qs)) { | 2999 | init_data->no_output_qs)) { |
3000 | QDIO_PRINT_ERR("queue allocation failed!\n"); | ||
3007 | qdio_release_irq_memory(irq_ptr); | 3001 | qdio_release_irq_memory(irq_ptr); |
3008 | return -ENOMEM; | 3002 | return -ENOMEM; |
3009 | } | 3003 | } |
@@ -3895,9 +3889,19 @@ init_QDIO(void) | |||
3895 | if (res) | 3889 | if (res) |
3896 | return res; | 3890 | return res; |
3897 | 3891 | ||
3892 | qdio_q_cache = kmem_cache_create("qdio_q", sizeof(struct qdio_q), | ||
3893 | 256, 0, NULL); | ||
3894 | if (!qdio_q_cache) { | ||
3895 | qdio_release_qdio_memory(); | ||
3896 | return -ENOMEM; | ||
3897 | } | ||
3898 | |||
3898 | res = qdio_register_dbf_views(); | 3899 | res = qdio_register_dbf_views(); |
3899 | if (res) | 3900 | if (res) { |
3901 | kmem_cache_destroy(qdio_q_cache); | ||
3902 | qdio_release_qdio_memory(); | ||
3900 | return res; | 3903 | return res; |
3904 | } | ||
3901 | 3905 | ||
3902 | QDIO_DBF_TEXT0(0,setup,"initQDIO"); | 3906 | QDIO_DBF_TEXT0(0,setup,"initQDIO"); |
3903 | res = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats); | 3907 | res = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats); |
@@ -3929,6 +3933,7 @@ cleanup_QDIO(void) | |||
3929 | qdio_release_qdio_memory(); | 3933 | qdio_release_qdio_memory(); |
3930 | qdio_unregister_dbf_views(); | 3934 | qdio_unregister_dbf_views(); |
3931 | mempool_destroy(qdio_mempool_scssc); | 3935 | mempool_destroy(qdio_mempool_scssc); |
3936 | kmem_cache_destroy(qdio_q_cache); | ||
3932 | bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats); | 3937 | bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats); |
3933 | printk("qdio: %s: module removed\n",version); | 3938 | printk("qdio: %s: module removed\n",version); |
3934 | } | 3939 | } |