Commit 2d921c32 authored by Ursula Braun's avatar Ursula Braun Committed by Jeff Garzik

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: default avatarUrsula Braun <braunu@de.ibm.com>
Signed-off-by: default avatarFrank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent cef8c793
...@@ -195,7 +195,7 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = { ...@@ -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_NO_STARTLAN, "Setip no startlan received"},
{IPA_RC_SETIP_ALREADY_RECEIVED, "Setip already received"}, {IPA_RC_SETIP_ALREADY_RECEIVED, "Setip already received"},
{IPA_RC_IP_ADDR_ALREADY_USED, "IP address already in use on LAN"}, {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_SETIP_INVALID_VERSION, "SETIP invalid IP version"},
{IPA_RC_UNSUPPORTED_SUBCMD, "Unsupported assist subcommand"}, {IPA_RC_UNSUPPORTED_SUBCMD, "Unsupported assist subcommand"},
{IPA_RC_ARP_ASSIST_NO_ENABLE, "Only partial success, no enable"}, {IPA_RC_ARP_ASSIST_NO_ENABLE, "Only partial success, no enable"},
......
...@@ -182,7 +182,7 @@ enum qeth_ipa_return_codes { ...@@ -182,7 +182,7 @@ enum qeth_ipa_return_codes {
IPA_RC_SETIP_NO_STARTLAN = 0xe008, IPA_RC_SETIP_NO_STARTLAN = 0xe008,
IPA_RC_SETIP_ALREADY_RECEIVED = 0xe009, IPA_RC_SETIP_ALREADY_RECEIVED = 0xe009,
IPA_RC_IP_ADDR_ALREADY_USED = 0xe00a, 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_SETIP_INVALID_VERSION = 0xe00d,
IPA_RC_UNSUPPORTED_SUBCMD = 0xe00e, IPA_RC_UNSUPPORTED_SUBCMD = 0xe00e,
IPA_RC_ARP_ASSIST_NO_ENABLE = 0xe00f, IPA_RC_ARP_ASSIST_NO_ENABLE = 0xe00f,
......
...@@ -401,8 +401,11 @@ static int __qeth_l3_ref_ip_on_card(struct qeth_card *card, ...@@ -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, static void __qeth_l3_delete_all_mc(struct qeth_card *card,
unsigned long *flags) unsigned long *flags)
{ {
struct list_head fail_list;
struct qeth_ipaddr *addr, *tmp; struct qeth_ipaddr *addr, *tmp;
int rc; int rc;
INIT_LIST_HEAD(&fail_list);
again: again:
list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) { list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) {
if (addr->is_multicast) { if (addr->is_multicast) {
...@@ -410,13 +413,14 @@ static void __qeth_l3_delete_all_mc(struct qeth_card *card, ...@@ -410,13 +413,14 @@ static void __qeth_l3_delete_all_mc(struct qeth_card *card,
spin_unlock_irqrestore(&card->ip_lock, *flags); spin_unlock_irqrestore(&card->ip_lock, *flags);
rc = qeth_l3_deregister_addr_entry(card, addr); rc = qeth_l3_deregister_addr_entry(card, addr);
spin_lock_irqsave(&card->ip_lock, *flags); spin_lock_irqsave(&card->ip_lock, *flags);
if (!rc) { if (!rc || (rc == IPA_RC_MC_ADDR_NOT_FOUND))
kfree(addr); kfree(addr);
goto again; else
} else list_add_tail(&addr->entry, &fail_list);
list_add(&addr->entry, &card->ip_list); goto again;
} }
} }
list_splice(&fail_list, &card->ip_list);
} }
static void qeth_l3_set_ip_addr_list(struct qeth_card *card) 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) ...@@ -467,7 +471,7 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
spin_unlock_irqrestore(&card->ip_lock, flags); spin_unlock_irqrestore(&card->ip_lock, flags);
rc = qeth_l3_deregister_addr_entry(card, addr); rc = qeth_l3_deregister_addr_entry(card, addr);
spin_lock_irqsave(&card->ip_lock, flags); spin_lock_irqsave(&card->ip_lock, flags);
if (!rc) if (!rc || (rc == IPA_RC_PRIMARY_ALREADY_DEFINED))
kfree(addr); kfree(addr);
else else
list_add_tail(&addr->entry, &card->ip_list); list_add_tail(&addr->entry, &card->ip_list);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment