]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Gerald Schaefer <geraldsc@de.ibm.com> |
2 | Subject: qeth: avoid crash after detach of replugged device | |
3 | References: bnc#487755,LTC#52681,LTC#52353 | |
4 | ||
5 | Symptom: kernel panic in qeth_l3_qdio_input_handler | |
6 | Problem: If a qeth device is plugged off, setting the device | |
7 | online stops in state HARDSETUP and a failure is | |
8 | reported to the base cio-layer causing halt/clear to | |
9 | be invoked. Replugging the device again triggers a | |
10 | qeth recovery without notification of the cio-layer. | |
11 | If a device is ungrouped in this state, the qeth | |
12 | set_offline function is not invoked, because the | |
13 | corresponding ccwgroup device is not in state ONLINE. | |
14 | Then incoming traffic is still handled by the qdio | |
15 | layer resulting in a crash in | |
16 | qeth_l<x>_qdio_input_handler, because (part of) the | |
17 | qeth data structures for this device are already | |
18 | removed. | |
19 | Solution: After replugging the device qeth recovery should lead | |
20 | to a working net device. Thus a "LAN offline" result | |
21 | when setting a qeth device online must not report a | |
22 | failure to the base cio-layer. | |
23 | ||
24 | Acked-by: John Jolly <jjolly@suse.de> | |
25 | --- | |
26 | drivers/s390/net/qeth_l2_main.c | 4 +++- | |
27 | drivers/s390/net/qeth_l3_main.c | 4 +++- | |
28 | 2 files changed, 6 insertions(+), 2 deletions(-) | |
29 | ||
30 | Index: linux-sles11/drivers/s390/net/qeth_l2_main.c | |
31 | =================================================================== | |
32 | --- linux-sles11.orig/drivers/s390/net/qeth_l2_main.c | |
33 | +++ linux-sles11/drivers/s390/net/qeth_l2_main.c | |
34 | @@ -873,6 +873,7 @@ static void qeth_l2_remove_device(struct | |
35 | { | |
36 | struct qeth_card *card = dev_get_drvdata(&cgdev->dev); | |
37 | ||
38 | + qeth_set_allowed_threads(card, 0, 1); | |
39 | wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); | |
40 | ||
41 | if (cgdev->state == CCWGROUP_ONLINE) { | |
42 | @@ -1029,8 +1030,9 @@ static int __qeth_l2_set_online(struct c | |
43 | dev_warn(&card->gdev->dev, | |
44 | "The LAN is offline\n"); | |
45 | card->lan_online = 0; | |
46 | + return 0; | |
47 | } | |
48 | - return rc; | |
49 | + goto out_remove; | |
50 | } else | |
51 | card->lan_online = 1; | |
52 | ||
53 | Index: linux-sles11/drivers/s390/net/qeth_l3_main.c | |
54 | =================================================================== | |
55 | --- linux-sles11.orig/drivers/s390/net/qeth_l3_main.c | |
56 | +++ linux-sles11/drivers/s390/net/qeth_l3_main.c | |
57 | @@ -3033,6 +3033,7 @@ static void qeth_l3_remove_device(struct | |
58 | { | |
59 | struct qeth_card *card = dev_get_drvdata(&cgdev->dev); | |
60 | ||
61 | + qeth_set_allowed_threads(card, 0, 1); | |
62 | wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); | |
63 | ||
64 | if (cgdev->state == CCWGROUP_ONLINE) { | |
65 | @@ -3107,8 +3108,9 @@ static int __qeth_l3_set_online(struct c | |
66 | dev_warn(&card->gdev->dev, | |
67 | "The LAN is offline\n"); | |
68 | card->lan_online = 0; | |
69 | + return 0; | |
70 | } | |
71 | - return rc; | |
72 | + goto out_remove; | |
73 | } else | |
74 | card->lan_online = 1; | |
75 | qeth_set_large_send(card, card->options.large_send); |