Skip to content

Commit 65d8013

Browse files
Stefan Raspldavem330
authored andcommitted
qeth: fix qeth_wait_for_threads() deadlock for OSN devices
Any recovery thread will deadlock when calling qeth_wait_for_threads(), most notably when triggering a recovery on an OSN device. This patch will store the recovery thread's task pointer on recovery invocation and check in qeth_wait_for_threads() respectively to avoid deadlocks. Signed-off-by: Stefan Raspl <raspl@linux.vnet.ibm.com> Signed-off-by: Frank Blaschka <blaschka@linux.vnet.ibm.com> Reviewed-by: Ursula Braun <ursula.braun@de.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent f9c41a6 commit 65d8013

File tree

4 files changed

+26
-0
lines changed

4 files changed

+26
-0
lines changed

drivers/s390/net/qeth_core.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,7 @@ struct qeth_card {
769769
unsigned long thread_start_mask;
770770
unsigned long thread_allowed_mask;
771771
unsigned long thread_running_mask;
772+
struct task_struct *recovery_task;
772773
spinlock_t ip_lock;
773774
struct list_head ip_list;
774775
struct list_head *ip_tbd_list;
@@ -862,6 +863,8 @@ extern struct qeth_card_list_struct qeth_core_card_list;
862863
extern struct kmem_cache *qeth_core_header_cache;
863864
extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS];
864865

866+
void qeth_set_recovery_task(struct qeth_card *);
867+
void qeth_clear_recovery_task(struct qeth_card *);
865868
void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int);
866869
int qeth_threads_running(struct qeth_card *, unsigned long);
867870
int qeth_wait_for_threads(struct qeth_card *, unsigned long);

drivers/s390/net/qeth_core_main.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,23 @@ const char *qeth_get_cardname_short(struct qeth_card *card)
177177
return "n/a";
178178
}
179179

180+
void qeth_set_recovery_task(struct qeth_card *card)
181+
{
182+
card->recovery_task = current;
183+
}
184+
EXPORT_SYMBOL_GPL(qeth_set_recovery_task);
185+
186+
void qeth_clear_recovery_task(struct qeth_card *card)
187+
{
188+
card->recovery_task = NULL;
189+
}
190+
EXPORT_SYMBOL_GPL(qeth_clear_recovery_task);
191+
192+
static bool qeth_is_recovery_task(const struct qeth_card *card)
193+
{
194+
return card->recovery_task == current;
195+
}
196+
180197
void qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
181198
int clear_start_mask)
182199
{
@@ -205,6 +222,8 @@ EXPORT_SYMBOL_GPL(qeth_threads_running);
205222

206223
int qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
207224
{
225+
if (qeth_is_recovery_task(card))
226+
return 0;
208227
return wait_event_interruptible(card->wait_q,
209228
qeth_threads_running(card, threads) == 0);
210229
}

drivers/s390/net/qeth_l2_main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,7 @@ static int qeth_l2_recover(void *ptr)
11431143
QETH_CARD_TEXT(card, 2, "recover2");
11441144
dev_warn(&card->gdev->dev,
11451145
"A recovery process has been started for the device\n");
1146+
qeth_set_recovery_task(card);
11461147
__qeth_l2_set_offline(card->gdev, 1);
11471148
rc = __qeth_l2_set_online(card->gdev, 1);
11481149
if (!rc)
@@ -1153,6 +1154,7 @@ static int qeth_l2_recover(void *ptr)
11531154
dev_warn(&card->gdev->dev, "The qeth device driver "
11541155
"failed to recover an error on the device\n");
11551156
}
1157+
qeth_clear_recovery_task(card);
11561158
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
11571159
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
11581160
return 0;

drivers/s390/net/qeth_l3_main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3515,6 +3515,7 @@ static int qeth_l3_recover(void *ptr)
35153515
QETH_CARD_TEXT(card, 2, "recover2");
35163516
dev_warn(&card->gdev->dev,
35173517
"A recovery process has been started for the device\n");
3518+
qeth_set_recovery_task(card);
35183519
__qeth_l3_set_offline(card->gdev, 1);
35193520
rc = __qeth_l3_set_online(card->gdev, 1);
35203521
if (!rc)
@@ -3525,6 +3526,7 @@ static int qeth_l3_recover(void *ptr)
35253526
dev_warn(&card->gdev->dev, "The qeth device driver "
35263527
"failed to recover an error on the device\n");
35273528
}
3529+
qeth_clear_recovery_task(card);
35283530
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
35293531
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
35303532
return 0;

0 commit comments

Comments
 (0)