From: Hans-Joachim Picht <hpicht@redhat.com> Date: Fri, 25 Apr 2008 15:08:06 +0200 Subject: [s390] qeth: avoid inconsistent lock state for inet6_dev Message-id: 20080425130806.GD22728@redhat.com O-Subject: [RHEL5 U3 PATCH 4/5] s390 - qeth: avoid inconsistent lock state for inet6_dev->lock Bugzilla: 444077 RH-Acked-by: John W. Linville <linville@redhat.com> RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com> Description ============ qeth recovery hang was observed, but other problems may have been possible. ipv6_regen_rndid in net/ipv6/addrconf.c makes use of "write_lock_bh" for its inet6_dev->lock. It may run in softirq-context. qeth makes use of "read_lock" for the same inet_dev->lock. This can cause a deadlock. The solution is to use read_lock_bh to get inet6_dev->lock. Bugzilla ========= BZ 444077 https://bugzilla.redhat.com/show_bug.cgi?id=444077 Upstream status of the patch: ============================= Patch is contained in linux-2.6 as git commit add3f2fa7a6cec16d35a95b9078e1ecc80a6f332 Test status: ============ The patch has been tested and fixes the problem. The fix has been verified by the IBM test department. Please ACK. With best regards, Hans drivers/s390/net/qeth_main.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index d3f119a..6d9ec25 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -5922,9 +5922,9 @@ qeth_add_vlan_mc6(struct qeth_card *card) in_dev = in6_dev_get(vg->vlan_devices[i]); if (!in_dev) continue; - read_lock(&in_dev->lock); + read_lock_bh(&in_dev->lock); qeth_add_mc6(card,in_dev); - read_unlock(&in_dev->lock); + read_unlock_bh(&in_dev->lock); in6_dev_put(in_dev); } #endif /* CONFIG_QETH_VLAN */ @@ -5941,10 +5941,10 @@ qeth_add_multicast_ipv6(struct qeth_card *card) in6_dev = in6_dev_get(card->dev); if (in6_dev == NULL) return; - read_lock(&in6_dev->lock); + read_lock_bh(&in6_dev->lock); qeth_add_mc6(card, in6_dev); qeth_add_vlan_mc6(card); - read_unlock(&in6_dev->lock); + read_unlock_bh(&in6_dev->lock); in6_dev_put(in6_dev); } #endif /* CONFIG_QETH_IPV6 */