Commit 6c88ad2d authored by Frank Pavlic's avatar Frank Pavlic Committed by Jeff Garzik

[PATCH] s390: qeth multicast address registration fixed

[patch 3/7] s390: qeth multicast address registration fixed

From: Klaus Dieter Wacker <kdwacker@de.ibm.com>
	- when running in Layer2 mode we don't have to register
	  the multicast IP address but only group mac address.
	  Therefore for Layer 2 devices it is enough to go
	  through dev->mc_list list and register these entries.
Signed-off-by: default avatarFrank Pavlic <fpavlic@de.ibm.com>

diffstat:
 qeth_main.c |  106 +++++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 80 insertions(+), 26 deletions(-)
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 508cc2b0
/* /*
* *
* linux/drivers/s390/net/qeth_main.c ($Revision: 1.235 $) * linux/drivers/s390/net/qeth_main.c ($Revision: 1.236 $)
* *
* Linux on zSeries OSA Express and HiperSockets support * Linux on zSeries OSA Express and HiperSockets support
* *
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and * Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com> * Thomas Spatzier <tspat@de.ibm.com>
* *
* $Revision: 1.235 $ $Date: 2005/05/04 20:19:18 $ * $Revision: 1.236 $ $Date: 2005/05/04 20:19:18 $
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
#include "qeth_eddp.h" #include "qeth_eddp.h"
#include "qeth_tso.h" #include "qeth_tso.h"
#define VERSION_QETH_C "$Revision: 1.235 $" #define VERSION_QETH_C "$Revision: 1.236 $"
static const char *version = "qeth S/390 OSA-Express driver"; static const char *version = "qeth S/390 OSA-Express driver";
/** /**
...@@ -602,11 +602,20 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, ...@@ -602,11 +602,20 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
int found = 0; int found = 0;
list_for_each_entry(addr, &card->ip_list, entry) { list_for_each_entry(addr, &card->ip_list, entry) {
if (card->options.layer2) {
if ((addr->type == todo->type) &&
(memcmp(&addr->mac, &todo->mac,
OSA_ADDR_LEN) == 0)) {
found = 1;
break;
}
continue;
}
if ((addr->proto == QETH_PROT_IPV4) && if ((addr->proto == QETH_PROT_IPV4) &&
(todo->proto == QETH_PROT_IPV4) && (todo->proto == QETH_PROT_IPV4) &&
(addr->type == todo->type) && (addr->type == todo->type) &&
(addr->u.a4.addr == todo->u.a4.addr) && (addr->u.a4.addr == todo->u.a4.addr) &&
(addr->u.a4.mask == todo->u.a4.mask) ){ (addr->u.a4.mask == todo->u.a4.mask)) {
found = 1; found = 1;
break; break;
} }
...@@ -620,7 +629,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, ...@@ -620,7 +629,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
break; break;
} }
} }
if (found){ if (found) {
addr->users += todo->users; addr->users += todo->users;
if (addr->users <= 0){ if (addr->users <= 0){
*__addr = addr; *__addr = addr;
...@@ -632,7 +641,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, ...@@ -632,7 +641,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
return 0; return 0;
} }
} }
if (todo->users > 0){ if (todo->users > 0) {
/* for VIPA and RXIP limit refcount to 1 */ /* for VIPA and RXIP limit refcount to 1 */
if (todo->type != QETH_IP_TYPE_NORMAL) if (todo->type != QETH_IP_TYPE_NORMAL)
todo->users = 1; todo->users = 1;
...@@ -682,12 +691,22 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) ...@@ -682,12 +691,22 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) && if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
(tmp->type == QETH_IP_TYPE_DEL_ALL_MC)) (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
return 0; return 0;
if (card->options.layer2) {
if ((tmp->type == addr->type) &&
(tmp->is_multicast == addr->is_multicast) &&
(memcmp(&tmp->mac, &addr->mac,
OSA_ADDR_LEN) == 0)) {
found = 1;
break;
}
continue;
}
if ((tmp->proto == QETH_PROT_IPV4) && if ((tmp->proto == QETH_PROT_IPV4) &&
(addr->proto == QETH_PROT_IPV4) && (addr->proto == QETH_PROT_IPV4) &&
(tmp->type == addr->type) && (tmp->type == addr->type) &&
(tmp->is_multicast == addr->is_multicast) && (tmp->is_multicast == addr->is_multicast) &&
(tmp->u.a4.addr == addr->u.a4.addr) && (tmp->u.a4.addr == addr->u.a4.addr) &&
(tmp->u.a4.mask == addr->u.a4.mask) ){ (tmp->u.a4.mask == addr->u.a4.mask)) {
found = 1; found = 1;
break; break;
} }
...@@ -697,7 +716,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) ...@@ -697,7 +716,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
(tmp->is_multicast == addr->is_multicast) && (tmp->is_multicast == addr->is_multicast) &&
(tmp->u.a6.pfxlen == addr->u.a6.pfxlen) && (tmp->u.a6.pfxlen == addr->u.a6.pfxlen) &&
(memcmp(&tmp->u.a6.addr, &addr->u.a6.addr, (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr,
sizeof(struct in6_addr)) == 0) ){ sizeof(struct in6_addr)) == 0)) {
found = 1; found = 1;
break; break;
} }
...@@ -707,7 +726,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) ...@@ -707,7 +726,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
tmp->users += addr->users; tmp->users += addr->users;
else else
tmp->users += add? 1:-1; tmp->users += add? 1:-1;
if (tmp->users == 0){ if (tmp->users == 0) {
list_del(&tmp->entry); list_del(&tmp->entry);
kfree(tmp); kfree(tmp);
} }
...@@ -738,12 +757,15 @@ qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) ...@@ -738,12 +757,15 @@ qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
unsigned long flags; unsigned long flags;
int rc = 0; int rc = 0;
QETH_DBF_TEXT(trace,4,"delip"); QETH_DBF_TEXT(trace, 4, "delip");
if (addr->proto == QETH_PROT_IPV4)
QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4); if (card->options.layer2)
QETH_DBF_HEX(trace, 4, &addr->mac, 6);
else if (addr->proto == QETH_PROT_IPV4)
QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
else { else {
QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8); QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8); QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
} }
spin_lock_irqsave(&card->ip_lock, flags); spin_lock_irqsave(&card->ip_lock, flags);
rc = __qeth_insert_ip_todo(card, addr, 0); rc = __qeth_insert_ip_todo(card, addr, 0);
...@@ -757,12 +779,14 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) ...@@ -757,12 +779,14 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
unsigned long flags; unsigned long flags;
int rc = 0; int rc = 0;
QETH_DBF_TEXT(trace,4,"addip"); QETH_DBF_TEXT(trace, 4, "addip");
if (addr->proto == QETH_PROT_IPV4) if (card->options.layer2)
QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4); QETH_DBF_HEX(trace, 4, &addr->mac, 6);
else if (addr->proto == QETH_PROT_IPV4)
QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4);
else { else {
QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8); QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8); QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8);
} }
spin_lock_irqsave(&card->ip_lock, flags); spin_lock_irqsave(&card->ip_lock, flags);
rc = __qeth_insert_ip_todo(card, addr, 1); rc = __qeth_insert_ip_todo(card, addr, 1);
...@@ -851,6 +875,7 @@ qeth_set_ip_addr_list(struct qeth_card *card) ...@@ -851,6 +875,7 @@ qeth_set_ip_addr_list(struct qeth_card *card)
static void qeth_delete_mc_addresses(struct qeth_card *); static void qeth_delete_mc_addresses(struct qeth_card *);
static void qeth_add_multicast_ipv4(struct qeth_card *); static void qeth_add_multicast_ipv4(struct qeth_card *);
static void qeth_layer2_add_multicast(struct qeth_card *);
#ifdef CONFIG_QETH_IPV6 #ifdef CONFIG_QETH_IPV6
static void qeth_add_multicast_ipv6(struct qeth_card *); static void qeth_add_multicast_ipv6(struct qeth_card *);
#endif #endif
...@@ -5301,8 +5326,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid) ...@@ -5301,8 +5326,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
struct qeth_ipaddr *addr; struct qeth_ipaddr *addr;
QETH_DBF_TEXT(trace, 4, "frvaddr4"); QETH_DBF_TEXT(trace, 4, "frvaddr4");
if (!card->vlangrp)
return;
rcu_read_lock(); rcu_read_lock();
in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]); in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]);
if (!in_dev) if (!in_dev)
...@@ -5330,8 +5354,7 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) ...@@ -5330,8 +5354,7 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
struct qeth_ipaddr *addr; struct qeth_ipaddr *addr;
QETH_DBF_TEXT(trace, 4, "frvaddr6"); QETH_DBF_TEXT(trace, 4, "frvaddr6");
if (!card->vlangrp)
return;
in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]); in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]);
if (!in6_dev) if (!in6_dev)
return; return;
...@@ -5350,6 +5373,15 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) ...@@ -5350,6 +5373,15 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
#endif /* CONFIG_QETH_IPV6 */ #endif /* CONFIG_QETH_IPV6 */
} }
static void
qeth_free_vlan_addresses(struct qeth_card *card, unsigned short vid)
{
if (card->options.layer2 || !card->vlangrp)
return;
qeth_free_vlan_addresses4(card, vid);
qeth_free_vlan_addresses6(card, vid);
}
static int static int
qeth_layer2_send_setdelvlan_cb(struct qeth_card *card, qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
struct qeth_reply *reply, struct qeth_reply *reply,
...@@ -5432,8 +5464,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) ...@@ -5432,8 +5464,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
qeth_free_vlan_skbs(card, vid); qeth_free_vlan_skbs(card, vid);
spin_lock_irqsave(&card->vlanlock, flags); spin_lock_irqsave(&card->vlanlock, flags);
/* unregister IP addresses of vlan device */ /* unregister IP addresses of vlan device */
qeth_free_vlan_addresses4(card, vid); qeth_free_vlan_addresses(card, vid);
qeth_free_vlan_addresses6(card, vid);
if (card->vlangrp) if (card->vlangrp)
card->vlangrp->vlan_devices[vid] = NULL; card->vlangrp->vlan_devices[vid] = NULL;
spin_unlock_irqrestore(&card->vlanlock, flags); spin_unlock_irqrestore(&card->vlanlock, flags);
...@@ -5456,10 +5487,15 @@ qeth_set_multicast_list(struct net_device *dev) ...@@ -5456,10 +5487,15 @@ qeth_set_multicast_list(struct net_device *dev)
QETH_DBF_TEXT(trace,3,"setmulti"); QETH_DBF_TEXT(trace,3,"setmulti");
qeth_delete_mc_addresses(card); qeth_delete_mc_addresses(card);
if (card->options.layer2) {
qeth_layer2_add_multicast(card);
goto out;
}
qeth_add_multicast_ipv4(card); qeth_add_multicast_ipv4(card);
#ifdef CONFIG_QETH_IPV6 #ifdef CONFIG_QETH_IPV6
qeth_add_multicast_ipv6(card); qeth_add_multicast_ipv6(card);
#endif #endif
out:
if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
schedule_work(&card->kernel_thread_starter); schedule_work(&card->kernel_thread_starter);
} }
...@@ -5669,6 +5705,24 @@ qeth_add_multicast_ipv4(struct qeth_card *card) ...@@ -5669,6 +5705,24 @@ qeth_add_multicast_ipv4(struct qeth_card *card)
in_dev_put(in4_dev); in_dev_put(in4_dev);
} }
static void
qeth_layer2_add_multicast(struct qeth_card *card)
{
struct qeth_ipaddr *ipm;
struct dev_mc_list *dm;
QETH_DBF_TEXT(trace,4,"L2addmc");
for (dm = card->dev->mc_list; dm; dm = dm->next) {
ipm = qeth_get_addr_buffer(QETH_PROT_IPV4);
if (!ipm)
continue;
memcpy(ipm->mac,dm->dmi_addr,MAX_ADDR_LEN);
ipm->is_multicast = 1;
if (!qeth_add_ip(card, ipm))
kfree(ipm);
}
}
#ifdef CONFIG_QETH_IPV6 #ifdef CONFIG_QETH_IPV6
static inline void static inline void
qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev) qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
......
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