[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>hifive-unleashed-5.1
parent
b01af5ba91
commit
c6d0e8014a
|
@ -81,6 +81,7 @@ static __u32 volatile spare_indicator;
|
||||||
static atomic_t spare_indicator_usecount;
|
static atomic_t spare_indicator_usecount;
|
||||||
#define QDIO_MEMPOOL_SCSSC_ELEMENTS 2
|
#define QDIO_MEMPOOL_SCSSC_ELEMENTS 2
|
||||||
static mempool_t *qdio_mempool_scssc;
|
static mempool_t *qdio_mempool_scssc;
|
||||||
|
static struct kmem_cache *qdio_q_cache;
|
||||||
|
|
||||||
static debug_info_t *qdio_dbf_setup;
|
static debug_info_t *qdio_dbf_setup;
|
||||||
static debug_info_t *qdio_dbf_sbal;
|
static debug_info_t *qdio_dbf_sbal;
|
||||||
|
@ -1617,23 +1618,21 @@ static void
|
||||||
qdio_release_irq_memory(struct qdio_irq *irq_ptr)
|
qdio_release_irq_memory(struct qdio_irq *irq_ptr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
struct qdio_q *q;
|
||||||
|
|
||||||
for (i=0;i<QDIO_MAX_QUEUES_PER_IRQ;i++) {
|
for (i = 0; i < QDIO_MAX_QUEUES_PER_IRQ; i++) {
|
||||||
if (!irq_ptr->input_qs[i])
|
q = irq_ptr->input_qs[i];
|
||||||
goto next;
|
if (q) {
|
||||||
|
free_page((unsigned long) q->slib);
|
||||||
kfree(irq_ptr->input_qs[i]->slib);
|
kmem_cache_free(qdio_q_cache, q);
|
||||||
kfree(irq_ptr->input_qs[i]);
|
}
|
||||||
|
q = irq_ptr->output_qs[i];
|
||||||
next:
|
if (q) {
|
||||||
if (!irq_ptr->output_qs[i])
|
free_page((unsigned long) q->slib);
|
||||||
continue;
|
kmem_cache_free(qdio_q_cache, q);
|
||||||
|
}
|
||||||
kfree(irq_ptr->output_qs[i]->slib);
|
|
||||||
kfree(irq_ptr->output_qs[i]);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
kfree(irq_ptr->qdr);
|
free_page((unsigned long) irq_ptr->qdr);
|
||||||
free_page((unsigned long) irq_ptr);
|
free_page((unsigned long) irq_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1680,44 +1679,35 @@ qdio_alloc_qs(struct qdio_irq *irq_ptr,
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct qdio_q *q;
|
struct qdio_q *q;
|
||||||
int result=-ENOMEM;
|
|
||||||
|
|
||||||
for (i=0;i<no_input_qs;i++) {
|
for (i = 0; i < no_input_qs; i++) {
|
||||||
q = kzalloc(sizeof(struct qdio_q), GFP_KERNEL);
|
q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL);
|
||||||
|
if (!q)
|
||||||
|
return -ENOMEM;
|
||||||
|
memset(q, 0, sizeof(*q));
|
||||||
|
|
||||||
if (!q) {
|
q->slib = (struct slib *) __get_free_page(GFP_KERNEL);
|
||||||
QDIO_PRINT_ERR("kmalloc of q failed!\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
q->slib = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
|
||||||
if (!q->slib) {
|
if (!q->slib) {
|
||||||
QDIO_PRINT_ERR("kmalloc of slib failed!\n");
|
kmem_cache_free(qdio_q_cache, q);
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq_ptr->input_qs[i]=q;
|
irq_ptr->input_qs[i]=q;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0;i<no_output_qs;i++) {
|
for (i = 0; i < no_output_qs; i++) {
|
||||||
q = kzalloc(sizeof(struct qdio_q), GFP_KERNEL);
|
q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL);
|
||||||
|
if (!q)
|
||||||
|
return -ENOMEM;
|
||||||
|
memset(q, 0, sizeof(*q));
|
||||||
|
|
||||||
if (!q) {
|
q->slib = (struct slib *) __get_free_page(GFP_KERNEL);
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
q->slib=kmalloc(PAGE_SIZE,GFP_KERNEL);
|
|
||||||
if (!q->slib) {
|
if (!q->slib) {
|
||||||
QDIO_PRINT_ERR("kmalloc of slib failed!\n");
|
kmem_cache_free(qdio_q_cache, q);
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq_ptr->output_qs[i]=q;
|
irq_ptr->output_qs[i]=q;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
result=0;
|
|
||||||
out:
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2985,17 +2975,17 @@ qdio_allocate(struct qdio_initialize *init_data)
|
||||||
QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*));
|
QDIO_DBF_HEX0(0,setup,&irq_ptr,sizeof(void*));
|
||||||
|
|
||||||
if (!irq_ptr) {
|
if (!irq_ptr) {
|
||||||
QDIO_PRINT_ERR("kmalloc of irq_ptr failed!\n");
|
QDIO_PRINT_ERR("allocation of irq_ptr failed!\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_MUTEX(&irq_ptr->setting_up_sema);
|
init_MUTEX(&irq_ptr->setting_up_sema);
|
||||||
|
|
||||||
/* QDR must be in DMA area since CCW data address is only 32 bit */
|
/* QDR must be in DMA area since CCW data address is only 32 bit */
|
||||||
irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA);
|
irq_ptr->qdr = (struct qdr *) __get_free_page(GFP_KERNEL | GFP_DMA);
|
||||||
if (!(irq_ptr->qdr)) {
|
if (!(irq_ptr->qdr)) {
|
||||||
free_page((unsigned long) irq_ptr);
|
free_page((unsigned long) irq_ptr);
|
||||||
QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n");
|
QDIO_PRINT_ERR("allocation of irq_ptr->qdr failed!\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
QDIO_DBF_TEXT0(0,setup,"qdr:");
|
QDIO_DBF_TEXT0(0,setup,"qdr:");
|
||||||
|
@ -3004,6 +2994,7 @@ qdio_allocate(struct qdio_initialize *init_data)
|
||||||
if (qdio_alloc_qs(irq_ptr,
|
if (qdio_alloc_qs(irq_ptr,
|
||||||
init_data->no_input_qs,
|
init_data->no_input_qs,
|
||||||
init_data->no_output_qs)) {
|
init_data->no_output_qs)) {
|
||||||
|
QDIO_PRINT_ERR("queue allocation failed!\n");
|
||||||
qdio_release_irq_memory(irq_ptr);
|
qdio_release_irq_memory(irq_ptr);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -3895,9 +3886,19 @@ init_QDIO(void)
|
||||||
if (res)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
qdio_q_cache = kmem_cache_create("qdio_q", sizeof(struct qdio_q),
|
||||||
|
256, 0, NULL);
|
||||||
|
if (!qdio_q_cache) {
|
||||||
|
qdio_release_qdio_memory();
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
res = qdio_register_dbf_views();
|
res = qdio_register_dbf_views();
|
||||||
if (res)
|
if (res) {
|
||||||
|
kmem_cache_destroy(qdio_q_cache);
|
||||||
|
qdio_release_qdio_memory();
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
QDIO_DBF_TEXT0(0,setup,"initQDIO");
|
QDIO_DBF_TEXT0(0,setup,"initQDIO");
|
||||||
res = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
|
res = bus_create_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
|
||||||
|
@ -3929,6 +3930,7 @@ cleanup_QDIO(void)
|
||||||
qdio_release_qdio_memory();
|
qdio_release_qdio_memory();
|
||||||
qdio_unregister_dbf_views();
|
qdio_unregister_dbf_views();
|
||||||
mempool_destroy(qdio_mempool_scssc);
|
mempool_destroy(qdio_mempool_scssc);
|
||||||
|
kmem_cache_destroy(qdio_q_cache);
|
||||||
bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
|
bus_remove_file(&ccw_bus_type, &bus_attr_qdio_performance_stats);
|
||||||
printk("qdio: %s: module removed\n",version);
|
printk("qdio: %s: module removed\n",version);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue