qeth: improve ip_list administration after deregister failures
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>
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 21c4390..1013a2a 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -401,8 +401,11 @@
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 @@
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 @@
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);