| From 2691108ead240193d4bfeb03a5387ee0edf8eb15 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 9 Apr 2020 09:59:39 +0200 |
| Subject: s390/qdio: put thinint indicator after early error |
| |
| From: Julian Wiedmann <jwi@linux.ibm.com> |
| |
| [ Upstream commit 75e82bec6b2622c6f455b7a543fb5476a5d0eed7 ] |
| |
| qdio_establish() calls qdio_setup_thinint() via qdio_setup_irq(). |
| If the subsequent qdio_establish_thinint() fails, we miss to put the |
| DSCI again. Thus the DSCI isn't available for re-use. Given enough of |
| such errors, we could end up with having only the shared DSCI available. |
| |
| Merge qdio_setup_thinint() into qdio_establish_thinint(), and deal with |
| such an error internally. |
| |
| Fixes: 779e6e1c724d ("[S390] qdio: new qdio driver.") |
| Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> |
| Reviewed-by: Benjamin Block <bblock@linux.ibm.com> |
| Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/s390/cio/qdio.h | 1 - |
| drivers/s390/cio/qdio_setup.c | 1 - |
| drivers/s390/cio/qdio_thinint.c | 14 ++++++++------ |
| 3 files changed, 8 insertions(+), 8 deletions(-) |
| |
| diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h |
| index 29d6b5222f1cd..0f8d13288611e 100644 |
| --- a/drivers/s390/cio/qdio.h |
| +++ b/drivers/s390/cio/qdio.h |
| @@ -377,7 +377,6 @@ static inline int multicast_outbound(struct qdio_q *q) |
| extern u64 last_ai_time; |
| |
| /* prototypes for thin interrupt */ |
| -void qdio_setup_thinint(struct qdio_irq *irq_ptr); |
| int qdio_establish_thinint(struct qdio_irq *irq_ptr); |
| void qdio_shutdown_thinint(struct qdio_irq *irq_ptr); |
| void tiqdio_add_input_queues(struct qdio_irq *irq_ptr); |
| diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c |
| index d0090c5c88e74..a64615a10352b 100644 |
| --- a/drivers/s390/cio/qdio_setup.c |
| +++ b/drivers/s390/cio/qdio_setup.c |
| @@ -479,7 +479,6 @@ int qdio_setup_irq(struct qdio_initialize *init_data) |
| setup_queues(irq_ptr, init_data); |
| |
| setup_qib(irq_ptr, init_data); |
| - qdio_setup_thinint(irq_ptr); |
| set_impl_params(irq_ptr, init_data->qib_param_field_format, |
| init_data->qib_param_field, |
| init_data->input_slib_elements, |
| diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c |
| index 831a3a0a2837b..4dc1108069d4a 100644 |
| --- a/drivers/s390/cio/qdio_thinint.c |
| +++ b/drivers/s390/cio/qdio_thinint.c |
| @@ -270,17 +270,19 @@ int __init tiqdio_register_thinints(void) |
| |
| int qdio_establish_thinint(struct qdio_irq *irq_ptr) |
| { |
| + int rc; |
| + |
| if (!is_thinint_irq(irq_ptr)) |
| return 0; |
| - return set_subchannel_ind(irq_ptr, 0); |
| -} |
| |
| -void qdio_setup_thinint(struct qdio_irq *irq_ptr) |
| -{ |
| - if (!is_thinint_irq(irq_ptr)) |
| - return; |
| irq_ptr->dsci = get_indicator(); |
| DBF_HEX(&irq_ptr->dsci, sizeof(void *)); |
| + |
| + rc = set_subchannel_ind(irq_ptr, 0); |
| + if (rc) |
| + put_indicator(irq_ptr->dsci); |
| + |
| + return rc; |
| } |
| |
| void qdio_shutdown_thinint(struct qdio_irq *irq_ptr) |
| -- |
| 2.25.1 |
| |