qeth: improve ip_list administration after deregister failures
authorUrsula Braun <braunu@de.ibm.com>
Tue, 1 Apr 2008 08:26:53 +0000 (10:26 +0200)
committerJeff Garzik <jgarzik@redhat.com>
Thu, 17 Apr 2008 00:41:38 +0000 (20:41 -0400)
1. ip_list handling after deregister failure of multicast address:
   If error code "MC Address not found" is returned do not re-add
   multicast address to ip_list.
   For other error codes readd multicast address at the end of
   function qeth_delete_all_mc.
2. ip_list handling after deregister failure or normal ip address:
   If error code "IP Address not found" is returned do not re-add
   multicast address to ip list.
   This is especially important in IP address takeover scenarios,
   to enable re-takeover of a taken over IP address.

Signed-off-by: Ursula Braun <braunu@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
drivers/s390/net/qeth_core_mpc.c
drivers/s390/net/qeth_core_mpc.h
drivers/s390/net/qeth_l3_main.c

index 8653b73..441533f 100644 (file)
@@ -195,7 +195,7 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
        {IPA_RC_SETIP_NO_STARTLAN,      "Setip no startlan received"},
        {IPA_RC_SETIP_ALREADY_RECEIVED, "Setip already received"},
        {IPA_RC_IP_ADDR_ALREADY_USED,   "IP address already in use on LAN"},
-       {IPA_RC_MULTICAST_FULL,         "No task available, multicast full"},
+       {IPA_RC_MC_ADDR_NOT_FOUND,      "Multicast address not found"},
        {IPA_RC_SETIP_INVALID_VERSION,  "SETIP invalid IP version"},
        {IPA_RC_UNSUPPORTED_SUBCMD,     "Unsupported assist subcommand"},
        {IPA_RC_ARP_ASSIST_NO_ENABLE,   "Only partial success, no enable"},
index de22193..1854882 100644 (file)
@@ -182,7 +182,7 @@ enum qeth_ipa_return_codes {
        IPA_RC_SETIP_NO_STARTLAN        = 0xe008,
        IPA_RC_SETIP_ALREADY_RECEIVED   = 0xe009,
        IPA_RC_IP_ADDR_ALREADY_USED     = 0xe00a,
-       IPA_RC_MULTICAST_FULL           = 0xe00b,
+       IPA_RC_MC_ADDR_NOT_FOUND        = 0xe00b,
        IPA_RC_SETIP_INVALID_VERSION    = 0xe00d,
        IPA_RC_UNSUPPORTED_SUBCMD       = 0xe00e,
        IPA_RC_ARP_ASSIST_NO_ENABLE     = 0xe00f,
index 21c4390..1013a2a 100644 (file)
@@ -401,8 +401,11 @@ static int __qeth_l3_ref_ip_on_card(struct qeth_card *card,
 static void __qeth_l3_delete_all_mc(struct qeth_card *card,
                                        unsigned long *flags)
 {
+       struct list_head fail_list;
        struct qeth_ipaddr *addr, *tmp;
        int rc;
+
+       INIT_LIST_HEAD(&fail_list);
 again:
        list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
                if (addr->is_multicast) {
@@ -410,13 +413,14 @@ again:
                        spin_unlock_irqrestore(&card->ip_lock, *flags);
                        rc = qeth_l3_deregister_addr_entry(card, addr);
                        spin_lock_irqsave(&card->ip_lock, *flags);
-                       if (!rc) {
+                       if (!rc || (rc == IPA_RC_MC_ADDR_NOT_FOUND))
                                kfree(addr);
-                               goto again;
-                       } else
-                               list_add(&addr->entry, &card->ip_list);
+                       else
+                               list_add_tail(&addr->entry, &fail_list);
+                       goto again;
                }
        }
+       list_splice(&fail_list, &card->ip_list);
 }
 
 static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
@@ -467,7 +471,7 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
                        spin_unlock_irqrestore(&card->ip_lock, flags);
                        rc = qeth_l3_deregister_addr_entry(card, addr);
                        spin_lock_irqsave(&card->ip_lock, flags);
-                       if (!rc)
+                       if (!rc || (rc == IPA_RC_PRIMARY_ALREADY_DEFINED))
                                kfree(addr);
                        else
                                list_add_tail(&addr->entry, &card->ip_list);