* [PATCH AUTOSEL 5.7 141/388] s390/qdio: consistently restore the IRQ handler
[not found] <20200618010805.600873-1-sashal@kernel.org>
@ 2020-06-18 1:03 ` Sasha Levin
2020-06-18 1:03 ` [PATCH AUTOSEL 5.7 142/388] s390/qdio: tear down thinint indicator after early error Sasha Levin
2020-06-18 1:04 ` [PATCH AUTOSEL 5.7 143/388] s390/qdio: put " Sasha Levin
2 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2020-06-18 1:03 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Julian Wiedmann, Benjamin Block, Vasily Gorbik, Sasha Levin,
linux-s390
From: Julian Wiedmann <jwi@linux.ibm.com>
[ Upstream commit 7b942b4be971d49cb185ce4690d7fbf94636e88a ]
For rolling back after an error, qdio_establish() calls qdio_shutdown().
If the error occurs early enough, then the qdio_irq's state still is
QDIO_IRQ_STATE_INACTIVE and qdio_shutdown() does nothing.
But at _any_ point where qdio_establish() bails out in this way,
qdio_setup_irq() will have already replaced the IRQ handler. This then
won't be restored after an early error, and the device can end up being
returned to the device driver with qdio's IRQ handler still installed.
Slightly reorder qdio_setup_irq() so we can be 100% sure that the IRQ
handler was replaced. Then fix the bug in qdio_establish() by calling a
helper that rolls back only the IRQ handler modification.
Also use the new helper in qdio_shutdown() to keep things in sync, and
slightly clean up the locking while doing so.
This makes minor semantical changes, but holding setup_mutex gives us
sufficient leeway to eg. pull qdio_shutdown_thinint() outside of the
ccwdev lock's scope.
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_main.c | 18 +++++-------------
drivers/s390/cio/qdio_setup.c | 20 ++++++++++++++++----
3 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index b8453b594679..3cf223bc1d5f 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -389,6 +389,7 @@ int qdio_setup_get_ssqd(struct qdio_irq *irq_ptr,
struct subchannel_id *schid,
struct qdio_ssqd_desc *data);
int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data);
+void qdio_shutdown_irq(struct qdio_irq *irq);
void qdio_print_subchannel_info(struct qdio_irq *irq_ptr);
void qdio_release_memory(struct qdio_irq *irq_ptr);
int qdio_setup_init(void);
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index bcc3ab14e72d..da5a11138020 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -1154,35 +1154,27 @@ int qdio_shutdown(struct ccw_device *cdev, int how)
/* cleanup subchannel */
spin_lock_irq(get_ccwdev_lock(cdev));
-
+ qdio_set_state(irq_ptr, QDIO_IRQ_STATE_CLEANUP);
if (how & QDIO_FLAG_CLEANUP_USING_CLEAR)
rc = ccw_device_clear(cdev, QDIO_DOING_CLEANUP);
else
/* default behaviour is halt */
rc = ccw_device_halt(cdev, QDIO_DOING_CLEANUP);
+ spin_unlock_irq(get_ccwdev_lock(cdev));
if (rc) {
DBF_ERROR("%4x SHUTD ERR", irq_ptr->schid.sch_no);
DBF_ERROR("rc:%4d", rc);
goto no_cleanup;
}
- qdio_set_state(irq_ptr, QDIO_IRQ_STATE_CLEANUP);
- spin_unlock_irq(get_ccwdev_lock(cdev));
wait_event_interruptible_timeout(cdev->private->wait_q,
irq_ptr->state == QDIO_IRQ_STATE_INACTIVE ||
irq_ptr->state == QDIO_IRQ_STATE_ERR,
10 * HZ);
- spin_lock_irq(get_ccwdev_lock(cdev));
no_cleanup:
qdio_shutdown_thinint(irq_ptr);
-
- /* restore interrupt handler */
- if ((void *)cdev->handler == (void *)qdio_int_handler) {
- cdev->handler = irq_ptr->orig_handler;
- cdev->private->intparm = 0;
- }
- spin_unlock_irq(get_ccwdev_lock(cdev));
+ qdio_shutdown_irq(irq_ptr);
qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
mutex_unlock(&irq_ptr->setup_mutex);
@@ -1352,8 +1344,8 @@ int qdio_establish(struct ccw_device *cdev,
rc = qdio_establish_thinint(irq_ptr);
if (rc) {
+ qdio_shutdown_irq(irq_ptr);
mutex_unlock(&irq_ptr->setup_mutex);
- qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
return rc;
}
@@ -1371,8 +1363,8 @@ int qdio_establish(struct ccw_device *cdev,
if (rc) {
DBF_ERROR("%4x est IO ERR", irq_ptr->schid.sch_no);
DBF_ERROR("rc:%4x", rc);
+ qdio_shutdown_irq(irq_ptr);
mutex_unlock(&irq_ptr->setup_mutex);
- qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR);
return rc;
}
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index 3083edd61f0c..d12f094db056 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -491,6 +491,12 @@ int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data)
/* qdr, qib, sls, slsbs, slibs, sbales are filled now */
+ /* set our IRQ handler */
+ spin_lock_irq(get_ccwdev_lock(cdev));
+ irq_ptr->orig_handler = cdev->handler;
+ cdev->handler = qdio_int_handler;
+ spin_unlock_irq(get_ccwdev_lock(cdev));
+
/* get qdio commands */
ciw = ccw_device_get_ciw(cdev, CIW_TYPE_EQUEUE);
if (!ciw) {
@@ -506,12 +512,18 @@ int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data)
}
irq_ptr->aqueue = *ciw;
- /* set new interrupt handler */
+ return 0;
+}
+
+void qdio_shutdown_irq(struct qdio_irq *irq)
+{
+ struct ccw_device *cdev = irq->cdev;
+
+ /* restore IRQ handler */
spin_lock_irq(get_ccwdev_lock(cdev));
- irq_ptr->orig_handler = cdev->handler;
- cdev->handler = qdio_int_handler;
+ cdev->handler = irq->orig_handler;
+ cdev->private->intparm = 0;
spin_unlock_irq(get_ccwdev_lock(cdev));
- return 0;
}
void qdio_print_subchannel_info(struct qdio_irq *irq_ptr)
--
2.25.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH AUTOSEL 5.7 142/388] s390/qdio: tear down thinint indicator after early error
[not found] <20200618010805.600873-1-sashal@kernel.org>
2020-06-18 1:03 ` [PATCH AUTOSEL 5.7 141/388] s390/qdio: consistently restore the IRQ handler Sasha Levin
@ 2020-06-18 1:03 ` Sasha Levin
2020-06-18 1:04 ` [PATCH AUTOSEL 5.7 143/388] s390/qdio: put " Sasha Levin
2 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2020-06-18 1:03 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Julian Wiedmann, Benjamin Block, Vasily Gorbik, Sasha Levin,
linux-s390
From: Julian Wiedmann <jwi@linux.ibm.com>
[ Upstream commit 68a381746f20e5435206173e22d0a011ef78790e ]
qdio_establish() calls qdio_establish_thinint(), but later has an error
exit path that doesn't roll this call back. Fix it.
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_main.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index da5a11138020..80cc811bd2e0 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -1363,6 +1363,7 @@ int qdio_establish(struct ccw_device *cdev,
if (rc) {
DBF_ERROR("%4x est IO ERR", irq_ptr->schid.sch_no);
DBF_ERROR("rc:%4x", rc);
+ qdio_shutdown_thinint(irq_ptr);
qdio_shutdown_irq(irq_ptr);
mutex_unlock(&irq_ptr->setup_mutex);
return rc;
--
2.25.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH AUTOSEL 5.7 143/388] s390/qdio: put thinint indicator after early error
[not found] <20200618010805.600873-1-sashal@kernel.org>
2020-06-18 1:03 ` [PATCH AUTOSEL 5.7 141/388] s390/qdio: consistently restore the IRQ handler Sasha Levin
2020-06-18 1:03 ` [PATCH AUTOSEL 5.7 142/388] s390/qdio: tear down thinint indicator after early error Sasha Levin
@ 2020-06-18 1:04 ` Sasha Levin
2 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2020-06-18 1:04 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Julian Wiedmann, Benjamin Block, Vasily Gorbik, Sasha Levin,
linux-s390
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 3cf223bc1d5f..a2afd7bc100b 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -364,7 +364,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_device(struct qdio_irq *irq_ptr);
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index d12f094db056..8edfa0982221 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -480,7 +480,6 @@ int qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *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 ae50373617cd..0faa0ad21732 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -227,17 +227,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
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-06-18 1:11 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20200618010805.600873-1-sashal@kernel.org>
2020-06-18 1:03 ` [PATCH AUTOSEL 5.7 141/388] s390/qdio: consistently restore the IRQ handler Sasha Levin
2020-06-18 1:03 ` [PATCH AUTOSEL 5.7 142/388] s390/qdio: tear down thinint indicator after early error Sasha Levin
2020-06-18 1:04 ` [PATCH AUTOSEL 5.7 143/388] s390/qdio: put " Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox