diff options
author | Julian Wiedmann <jwi@linux.ibm.com> | 2020-04-02 23:30:41 +0200 |
---|---|---|
committer | Vasily Gorbik <gor@linux.ibm.com> | 2020-04-28 13:49:47 +0200 |
commit | 2a7cf35c4056facd35c952e8000519034376eef7 (patch) | |
tree | e830012ff454a9cf367891b4af164eca072b884d | |
parent | edbf3b2a87db6357fba54520c1baf605e08557b3 (diff) | |
download | lwn-2a7cf35c4056facd35c952e8000519034376eef7.tar.gz lwn-2a7cf35c4056facd35c952e8000519034376eef7.zip |
s390/qdio: roll-back after queue allocation error
When qdio_allocate_qs() fails, have it deal with its previous
allocations.
This way qdio_allocate() doesn't need to clean up afterwards.
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: Steffen Maier <maier@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 1 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_setup.c | 21 |
2 files changed, 20 insertions, 2 deletions
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 579caba8ea93..09bb69028d67 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -1271,7 +1271,6 @@ int qdio_allocate(struct ccw_device *cdev, unsigned int no_input_qs, return 0; err_queues: - qdio_free_queues(irq_ptr); free_page((unsigned long) irq_ptr->qdr); err_qdr: free_page(irq_ptr->chsc_page); diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 51dc9a41555a..ebe61cbed443 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -135,6 +135,18 @@ output: } } +static void __qdio_free_queues(struct qdio_q **queues, unsigned int count) +{ + struct qdio_q *q; + unsigned int i; + + for (i = 0; i < count; i++) { + q = queues[i]; + free_page((unsigned long) q->slib); + kmem_cache_free(qdio_q_cache, q); + } +} + static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues) { struct qdio_q *q; @@ -142,12 +154,15 @@ static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues) for (i = 0; i < nr_queues; i++) { q = kmem_cache_zalloc(qdio_q_cache, GFP_KERNEL); - if (!q) + if (!q) { + __qdio_free_queues(irq_ptr_qs, i); return -ENOMEM; + } q->slib = (struct slib *) __get_free_page(GFP_KERNEL); if (!q->slib) { kmem_cache_free(qdio_q_cache, q); + __qdio_free_queues(irq_ptr_qs, i); return -ENOMEM; } irq_ptr_qs[i] = q; @@ -162,7 +177,11 @@ int qdio_allocate_qs(struct qdio_irq *irq_ptr, int nr_input_qs, int nr_output_qs rc = __qdio_allocate_qs(irq_ptr->input_qs, nr_input_qs); if (rc) return rc; + rc = __qdio_allocate_qs(irq_ptr->output_qs, nr_output_qs); + if (rc) + __qdio_free_queues(irq_ptr->input_qs, nr_input_qs); + return rc; } |