From: Hans-Joachim Picht <hpicht@redhat.com> Date: Fri, 4 Apr 2008 19:51:30 +0200 Subject: [s390] qeth: recovery problems with failing STARTLAN Message-id: 20080404175130.GF9759@redhat.com O-Subject: [RHEL5 U3 PATCH 6/7] s390 - qeth: recovery problems with failing STARTLAN Bugzilla: 440420 RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com> Description ============ Linux does not fully recover an OSA-device interface 1. A STARTLAN command from the adapter may arrive while a qeth recovery is currently running with a failed qeth STARTLAN. Usually qeth schedules a recovery when receiving a STARTLAN command from the adapter. But another recovery scheduled while a recovery is already running never starts. Thus the qeth-administered lan_online flag remains zero in this scenario, even though the adapter-STARTLAN has happened. 2. If setting of an ip-address fails with LAN_OFFLINE, qeth does not save the ip-address in its internal list of set ip-addresses. qeth recovers after a following STARTLAN event, but cannot set the unsaved ip-address. This is how the problem is fixed: 1. Set lan_online flag for a received STARTLAN from the adapter in case scheduled recovery does not start and get rid of the superfluous extra STARTLAN for IPv6. 2. save the ip-address in the qeth-maintained list of ip-addresses after a LAN_OFFLINE failure for SETIP. Bugzilla ========= BZ 440420 https://bugzilla.redhat.com/show_bug.cgi?id=440420 Upstream status of the patch: ============================= This patch has been posted upstream http://marc.info/?l=linux-netdev&m=120716473703177&w=2 http://marc.info/?l=linux-netdev&m=120716473703178&w=2 I'll reply to this message as soon as we have a git commit id Test status: ============ Kernel with patch was built and successfully tested Please ACK. With best regards, Hans diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index ca72fe0..d3f119a 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c @@ -856,7 +856,7 @@ qeth_set_ip_addr_list(struct qeth_card *card) spin_unlock_irqrestore(&card->ip_lock, flags); rc = qeth_register_addr_entry(card, todo); spin_lock_irqsave(&card->ip_lock, flags); - if (!rc) + if (!rc || (rc == 0xe080)) list_add_tail(&todo->entry, &card->ip_list); else kfree(todo); @@ -866,7 +866,7 @@ qeth_set_ip_addr_list(struct qeth_card *card) spin_unlock_irqrestore(&card->ip_lock, flags); rc = qeth_deregister_addr_entry(card, addr); spin_lock_irqsave(&card->ip_lock, flags); - if (!rc) + if (!rc || (rc == 0xe010)) kfree(addr); else list_add_tail(&addr->entry, &card->ip_list); @@ -1661,6 +1661,7 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) QETH_CARD_IFNAME(card), card->info.chpid); netif_carrier_on(card->dev); + card->lan_online = 1; qeth_schedule_recovery(card); return NULL; case IPA_CMD_MODCCID: @@ -7243,12 +7244,6 @@ qeth_softsetup_ipv6(struct qeth_card *card) QETH_DBF_TEXT(trace,3,"softipv6"); - rc = qeth_send_startlan(card, QETH_PROT_IPV6); - if (rc) { - PRINT_ERR("IPv6 startlan failed on %s\n", - QETH_CARD_IFNAME(card)); - return rc; - } rc = qeth_query_ipassists(card,QETH_PROT_IPV6); if (rc) { PRINT_ERR("IPv6 query ipassist failed on %s\n",