Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+80 −26
Original line number Diff line number Diff line
/*
 *
 * 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
 *
@@ -12,7 +12,7 @@
 *			  Frank Pavlic (pavlic@de.ibm.com) and
 *		 	  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
 * it under the terms of the GNU General Public License as published by
@@ -72,7 +72,7 @@
#include "qeth_eddp.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";

/**
@@ -602,6 +602,15 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
	int found = 0;

	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)  &&
		    (todo->proto     == QETH_PROT_IPV4)  &&
		    (addr->type      == todo->type)      &&
@@ -682,6 +691,16 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add)
		if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) &&
		    (tmp->type == QETH_IP_TYPE_DEL_ALL_MC))
			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)     &&
		    (addr->proto       == QETH_PROT_IPV4)     &&
		    (tmp->type         == addr->type)         &&
@@ -739,7 +758,10 @@ qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
	int rc = 0;

	QETH_DBF_TEXT(trace, 4, "delip");
	if (addr->proto == QETH_PROT_IPV4)

	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 {
		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
@@ -758,7 +780,9 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
	int rc = 0;

	QETH_DBF_TEXT(trace, 4, "addip");
	if (addr->proto == QETH_PROT_IPV4)
	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 {
		QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8);
@@ -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_add_multicast_ipv4(struct qeth_card *);
static void qeth_layer2_add_multicast(struct qeth_card *);
#ifdef CONFIG_QETH_IPV6
static void qeth_add_multicast_ipv6(struct qeth_card *);
#endif
@@ -5301,8 +5326,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid)
	struct qeth_ipaddr *addr;

	QETH_DBF_TEXT(trace, 4, "frvaddr4");
	if (!card->vlangrp)
		return;

	rcu_read_lock();
	in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]);
	if (!in_dev)
@@ -5330,8 +5354,7 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
	struct qeth_ipaddr *addr;

	QETH_DBF_TEXT(trace, 4, "frvaddr6");
	if (!card->vlangrp)
		return;

	in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]);
	if (!in6_dev)
		return;
@@ -5350,6 +5373,15 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid)
#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
qeth_layer2_send_setdelvlan_cb(struct qeth_card *card,
                               struct qeth_reply *reply,
@@ -5432,8 +5464,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
	qeth_free_vlan_skbs(card, vid);
	spin_lock_irqsave(&card->vlanlock, flags);
	/* unregister IP addresses of vlan device */
	qeth_free_vlan_addresses4(card, vid);
	qeth_free_vlan_addresses6(card, vid);
	qeth_free_vlan_addresses(card, vid);
	if (card->vlangrp)
		card->vlangrp->vlan_devices[vid] = NULL;
	spin_unlock_irqrestore(&card->vlanlock, flags);
@@ -5456,10 +5487,15 @@ qeth_set_multicast_list(struct net_device *dev)
	 
	QETH_DBF_TEXT(trace,3,"setmulti");
	qeth_delete_mc_addresses(card);
	if (card->options.layer2) {
		qeth_layer2_add_multicast(card);
		goto out;
	}
	qeth_add_multicast_ipv4(card);
#ifdef CONFIG_QETH_IPV6
	qeth_add_multicast_ipv6(card);
#endif
out:
 	if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0)
		schedule_work(&card->kernel_thread_starter);
}
@@ -5669,6 +5705,24 @@ qeth_add_multicast_ipv4(struct qeth_card *card)
	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
static inline void
qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)