diff options
| author | Frank Pavlic <fpavlic@de.ibm.com> | 2005-11-10 07:49:28 -0500 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-11-11 08:26:21 -0500 |
| commit | 6c88ad2ded1de1fe87e917b4a0a45873939c16e1 (patch) | |
| tree | dd849c8ad285a86ca98813126ab1237526669b95 /drivers | |
| parent | 508cc2b0e078c806bb7cc8bba22fb97a4ca99b91 (diff) | |
[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: Frank Pavlic <fpavlic@de.ibm.com>
diffstat:
qeth_main.c | 106 +++++++++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 80 insertions(+), 26 deletions(-)
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/s390/net/qeth_main.c | 106 |
1 files changed, 80 insertions, 26 deletions
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index ab50e0ea9313..0a5d758b531e 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * | 2 | * |
| 3 | * linux/drivers/s390/net/qeth_main.c ($Revision: 1.235 $) | 3 | * linux/drivers/s390/net/qeth_main.c ($Revision: 1.236 $) |
| 4 | * | 4 | * |
| 5 | * Linux on zSeries OSA Express and HiperSockets support | 5 | * Linux on zSeries OSA Express and HiperSockets support |
| 6 | * | 6 | * |
| @@ -12,7 +12,7 @@ | |||
| 12 | * Frank Pavlic (pavlic@de.ibm.com) and | 12 | * Frank Pavlic (pavlic@de.ibm.com) and |
| 13 | * Thomas Spatzier <tspat@de.ibm.com> | 13 | * Thomas Spatzier <tspat@de.ibm.com> |
| 14 | * | 14 | * |
| 15 | * $Revision: 1.235 $ $Date: 2005/05/04 20:19:18 $ | 15 | * $Revision: 1.236 $ $Date: 2005/05/04 20:19:18 $ |
| 16 | * | 16 | * |
| 17 | * This program is free software; you can redistribute it and/or modify | 17 | * This program is free software; you can redistribute it and/or modify |
| 18 | * it under the terms of the GNU General Public License as published by | 18 | * it under the terms of the GNU General Public License as published by |
| @@ -72,7 +72,7 @@ | |||
| 72 | #include "qeth_eddp.h" | 72 | #include "qeth_eddp.h" |
| 73 | #include "qeth_tso.h" | 73 | #include "qeth_tso.h" |
| 74 | 74 | ||
| 75 | #define VERSION_QETH_C "$Revision: 1.235 $" | 75 | #define VERSION_QETH_C "$Revision: 1.236 $" |
| 76 | static const char *version = "qeth S/390 OSA-Express driver"; | 76 | static const char *version = "qeth S/390 OSA-Express driver"; |
| 77 | 77 | ||
| 78 | /** | 78 | /** |
| @@ -602,11 +602,20 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, | |||
| 602 | int found = 0; | 602 | int found = 0; |
| 603 | 603 | ||
| 604 | list_for_each_entry(addr, &card->ip_list, entry) { | 604 | list_for_each_entry(addr, &card->ip_list, entry) { |
| 605 | if (card->options.layer2) { | ||
| 606 | if ((addr->type == todo->type) && | ||
| 607 | (memcmp(&addr->mac, &todo->mac, | ||
| 608 | OSA_ADDR_LEN) == 0)) { | ||
| 609 | found = 1; | ||
| 610 | break; | ||
| 611 | } | ||
| 612 | continue; | ||
| 613 | } | ||
| 605 | if ((addr->proto == QETH_PROT_IPV4) && | 614 | if ((addr->proto == QETH_PROT_IPV4) && |
| 606 | (todo->proto == QETH_PROT_IPV4) && | 615 | (todo->proto == QETH_PROT_IPV4) && |
| 607 | (addr->type == todo->type) && | 616 | (addr->type == todo->type) && |
| 608 | (addr->u.a4.addr == todo->u.a4.addr) && | 617 | (addr->u.a4.addr == todo->u.a4.addr) && |
| 609 | (addr->u.a4.mask == todo->u.a4.mask) ){ | 618 | (addr->u.a4.mask == todo->u.a4.mask)) { |
| 610 | found = 1; | 619 | found = 1; |
| 611 | break; | 620 | break; |
| 612 | } | 621 | } |
| @@ -615,12 +624,12 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, | |||
| 615 | (addr->type == todo->type) && | 624 | (addr->type == todo->type) && |
| 616 | (addr->u.a6.pfxlen == todo->u.a6.pfxlen) && | 625 | (addr->u.a6.pfxlen == todo->u.a6.pfxlen) && |
| 617 | (memcmp(&addr->u.a6.addr, &todo->u.a6.addr, | 626 | (memcmp(&addr->u.a6.addr, &todo->u.a6.addr, |
| 618 | sizeof(struct in6_addr)) == 0)) { | 627 | sizeof(struct in6_addr)) == 0)) { |
| 619 | found = 1; | 628 | found = 1; |
| 620 | break; | 629 | break; |
| 621 | } | 630 | } |
| 622 | } | 631 | } |
| 623 | if (found){ | 632 | if (found) { |
| 624 | addr->users += todo->users; | 633 | addr->users += todo->users; |
| 625 | if (addr->users <= 0){ | 634 | if (addr->users <= 0){ |
| 626 | *__addr = addr; | 635 | *__addr = addr; |
| @@ -632,7 +641,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, | |||
| 632 | return 0; | 641 | return 0; |
| 633 | } | 642 | } |
| 634 | } | 643 | } |
| 635 | if (todo->users > 0){ | 644 | if (todo->users > 0) { |
| 636 | /* for VIPA and RXIP limit refcount to 1 */ | 645 | /* for VIPA and RXIP limit refcount to 1 */ |
| 637 | if (todo->type != QETH_IP_TYPE_NORMAL) | 646 | if (todo->type != QETH_IP_TYPE_NORMAL) |
| 638 | todo->users = 1; | 647 | todo->users = 1; |
| @@ -682,12 +691,22 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) | |||
| 682 | if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) && | 691 | if ((addr->type == QETH_IP_TYPE_DEL_ALL_MC) && |
| 683 | (tmp->type == QETH_IP_TYPE_DEL_ALL_MC)) | 692 | (tmp->type == QETH_IP_TYPE_DEL_ALL_MC)) |
| 684 | return 0; | 693 | return 0; |
| 694 | if (card->options.layer2) { | ||
| 695 | if ((tmp->type == addr->type) && | ||
| 696 | (tmp->is_multicast == addr->is_multicast) && | ||
| 697 | (memcmp(&tmp->mac, &addr->mac, | ||
| 698 | OSA_ADDR_LEN) == 0)) { | ||
| 699 | found = 1; | ||
| 700 | break; | ||
| 701 | } | ||
| 702 | continue; | ||
| 703 | } | ||
| 685 | if ((tmp->proto == QETH_PROT_IPV4) && | 704 | if ((tmp->proto == QETH_PROT_IPV4) && |
| 686 | (addr->proto == QETH_PROT_IPV4) && | 705 | (addr->proto == QETH_PROT_IPV4) && |
| 687 | (tmp->type == addr->type) && | 706 | (tmp->type == addr->type) && |
| 688 | (tmp->is_multicast == addr->is_multicast) && | 707 | (tmp->is_multicast == addr->is_multicast) && |
| 689 | (tmp->u.a4.addr == addr->u.a4.addr) && | 708 | (tmp->u.a4.addr == addr->u.a4.addr) && |
| 690 | (tmp->u.a4.mask == addr->u.a4.mask) ){ | 709 | (tmp->u.a4.mask == addr->u.a4.mask)) { |
| 691 | found = 1; | 710 | found = 1; |
| 692 | break; | 711 | break; |
| 693 | } | 712 | } |
| @@ -697,7 +716,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) | |||
| 697 | (tmp->is_multicast == addr->is_multicast) && | 716 | (tmp->is_multicast == addr->is_multicast) && |
| 698 | (tmp->u.a6.pfxlen == addr->u.a6.pfxlen) && | 717 | (tmp->u.a6.pfxlen == addr->u.a6.pfxlen) && |
| 699 | (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr, | 718 | (memcmp(&tmp->u.a6.addr, &addr->u.a6.addr, |
| 700 | sizeof(struct in6_addr)) == 0) ){ | 719 | sizeof(struct in6_addr)) == 0)) { |
| 701 | found = 1; | 720 | found = 1; |
| 702 | break; | 721 | break; |
| 703 | } | 722 | } |
| @@ -707,7 +726,7 @@ __qeth_insert_ip_todo(struct qeth_card *card, struct qeth_ipaddr *addr, int add) | |||
| 707 | tmp->users += addr->users; | 726 | tmp->users += addr->users; |
| 708 | else | 727 | else |
| 709 | tmp->users += add? 1:-1; | 728 | tmp->users += add? 1:-1; |
| 710 | if (tmp->users == 0){ | 729 | if (tmp->users == 0) { |
| 711 | list_del(&tmp->entry); | 730 | list_del(&tmp->entry); |
| 712 | kfree(tmp); | 731 | kfree(tmp); |
| 713 | } | 732 | } |
| @@ -738,12 +757,15 @@ qeth_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | |||
| 738 | unsigned long flags; | 757 | unsigned long flags; |
| 739 | int rc = 0; | 758 | int rc = 0; |
| 740 | 759 | ||
| 741 | QETH_DBF_TEXT(trace,4,"delip"); | 760 | QETH_DBF_TEXT(trace, 4, "delip"); |
| 742 | if (addr->proto == QETH_PROT_IPV4) | 761 | |
| 743 | QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4); | 762 | if (card->options.layer2) |
| 763 | QETH_DBF_HEX(trace, 4, &addr->mac, 6); | ||
| 764 | else if (addr->proto == QETH_PROT_IPV4) | ||
| 765 | QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4); | ||
| 744 | else { | 766 | else { |
| 745 | QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8); | 767 | QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8); |
| 746 | QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8); | 768 | QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8); |
| 747 | } | 769 | } |
| 748 | spin_lock_irqsave(&card->ip_lock, flags); | 770 | spin_lock_irqsave(&card->ip_lock, flags); |
| 749 | rc = __qeth_insert_ip_todo(card, addr, 0); | 771 | rc = __qeth_insert_ip_todo(card, addr, 0); |
| @@ -757,12 +779,14 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | |||
| 757 | unsigned long flags; | 779 | unsigned long flags; |
| 758 | int rc = 0; | 780 | int rc = 0; |
| 759 | 781 | ||
| 760 | QETH_DBF_TEXT(trace,4,"addip"); | 782 | QETH_DBF_TEXT(trace, 4, "addip"); |
| 761 | if (addr->proto == QETH_PROT_IPV4) | 783 | if (card->options.layer2) |
| 762 | QETH_DBF_HEX(trace,4,&addr->u.a4.addr,4); | 784 | QETH_DBF_HEX(trace, 4, &addr->mac, 6); |
| 785 | else if (addr->proto == QETH_PROT_IPV4) | ||
| 786 | QETH_DBF_HEX(trace, 4, &addr->u.a4.addr, 4); | ||
| 763 | else { | 787 | else { |
| 764 | QETH_DBF_HEX(trace,4,&addr->u.a6.addr,8); | 788 | QETH_DBF_HEX(trace, 4, &addr->u.a6.addr, 8); |
| 765 | QETH_DBF_HEX(trace,4,((char *)&addr->u.a6.addr)+8,8); | 789 | QETH_DBF_HEX(trace, 4, ((char *)&addr->u.a6.addr) + 8, 8); |
| 766 | } | 790 | } |
| 767 | spin_lock_irqsave(&card->ip_lock, flags); | 791 | spin_lock_irqsave(&card->ip_lock, flags); |
| 768 | rc = __qeth_insert_ip_todo(card, addr, 1); | 792 | rc = __qeth_insert_ip_todo(card, addr, 1); |
| @@ -851,6 +875,7 @@ qeth_set_ip_addr_list(struct qeth_card *card) | |||
| 851 | 875 | ||
| 852 | static void qeth_delete_mc_addresses(struct qeth_card *); | 876 | static void qeth_delete_mc_addresses(struct qeth_card *); |
| 853 | static void qeth_add_multicast_ipv4(struct qeth_card *); | 877 | static void qeth_add_multicast_ipv4(struct qeth_card *); |
| 878 | static void qeth_layer2_add_multicast(struct qeth_card *); | ||
| 854 | #ifdef CONFIG_QETH_IPV6 | 879 | #ifdef CONFIG_QETH_IPV6 |
| 855 | static void qeth_add_multicast_ipv6(struct qeth_card *); | 880 | static void qeth_add_multicast_ipv6(struct qeth_card *); |
| 856 | #endif | 881 | #endif |
| @@ -5301,8 +5326,7 @@ qeth_free_vlan_addresses4(struct qeth_card *card, unsigned short vid) | |||
| 5301 | struct qeth_ipaddr *addr; | 5326 | struct qeth_ipaddr *addr; |
| 5302 | 5327 | ||
| 5303 | QETH_DBF_TEXT(trace, 4, "frvaddr4"); | 5328 | QETH_DBF_TEXT(trace, 4, "frvaddr4"); |
| 5304 | if (!card->vlangrp) | 5329 | |
| 5305 | return; | ||
| 5306 | rcu_read_lock(); | 5330 | rcu_read_lock(); |
| 5307 | in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]); | 5331 | in_dev = __in_dev_get_rcu(card->vlangrp->vlan_devices[vid]); |
| 5308 | if (!in_dev) | 5332 | if (!in_dev) |
| @@ -5330,8 +5354,7 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) | |||
| 5330 | struct qeth_ipaddr *addr; | 5354 | struct qeth_ipaddr *addr; |
| 5331 | 5355 | ||
| 5332 | QETH_DBF_TEXT(trace, 4, "frvaddr6"); | 5356 | QETH_DBF_TEXT(trace, 4, "frvaddr6"); |
| 5333 | if (!card->vlangrp) | 5357 | |
| 5334 | return; | ||
| 5335 | in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]); | 5358 | in6_dev = in6_dev_get(card->vlangrp->vlan_devices[vid]); |
| 5336 | if (!in6_dev) | 5359 | if (!in6_dev) |
| 5337 | return; | 5360 | return; |
| @@ -5350,6 +5373,15 @@ qeth_free_vlan_addresses6(struct qeth_card *card, unsigned short vid) | |||
| 5350 | #endif /* CONFIG_QETH_IPV6 */ | 5373 | #endif /* CONFIG_QETH_IPV6 */ |
| 5351 | } | 5374 | } |
| 5352 | 5375 | ||
| 5376 | static void | ||
| 5377 | qeth_free_vlan_addresses(struct qeth_card *card, unsigned short vid) | ||
| 5378 | { | ||
| 5379 | if (card->options.layer2 || !card->vlangrp) | ||
| 5380 | return; | ||
| 5381 | qeth_free_vlan_addresses4(card, vid); | ||
| 5382 | qeth_free_vlan_addresses6(card, vid); | ||
| 5383 | } | ||
| 5384 | |||
| 5353 | static int | 5385 | static int |
| 5354 | qeth_layer2_send_setdelvlan_cb(struct qeth_card *card, | 5386 | qeth_layer2_send_setdelvlan_cb(struct qeth_card *card, |
| 5355 | struct qeth_reply *reply, | 5387 | struct qeth_reply *reply, |
| @@ -5432,8 +5464,7 @@ qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
| 5432 | qeth_free_vlan_skbs(card, vid); | 5464 | qeth_free_vlan_skbs(card, vid); |
| 5433 | spin_lock_irqsave(&card->vlanlock, flags); | 5465 | spin_lock_irqsave(&card->vlanlock, flags); |
| 5434 | /* unregister IP addresses of vlan device */ | 5466 | /* unregister IP addresses of vlan device */ |
| 5435 | qeth_free_vlan_addresses4(card, vid); | 5467 | qeth_free_vlan_addresses(card, vid); |
| 5436 | qeth_free_vlan_addresses6(card, vid); | ||
| 5437 | if (card->vlangrp) | 5468 | if (card->vlangrp) |
| 5438 | card->vlangrp->vlan_devices[vid] = NULL; | 5469 | card->vlangrp->vlan_devices[vid] = NULL; |
| 5439 | spin_unlock_irqrestore(&card->vlanlock, flags); | 5470 | spin_unlock_irqrestore(&card->vlanlock, flags); |
| @@ -5456,10 +5487,15 @@ qeth_set_multicast_list(struct net_device *dev) | |||
| 5456 | 5487 | ||
| 5457 | QETH_DBF_TEXT(trace,3,"setmulti"); | 5488 | QETH_DBF_TEXT(trace,3,"setmulti"); |
| 5458 | qeth_delete_mc_addresses(card); | 5489 | qeth_delete_mc_addresses(card); |
| 5490 | if (card->options.layer2) { | ||
| 5491 | qeth_layer2_add_multicast(card); | ||
| 5492 | goto out; | ||
| 5493 | } | ||
| 5459 | qeth_add_multicast_ipv4(card); | 5494 | qeth_add_multicast_ipv4(card); |
| 5460 | #ifdef CONFIG_QETH_IPV6 | 5495 | #ifdef CONFIG_QETH_IPV6 |
| 5461 | qeth_add_multicast_ipv6(card); | 5496 | qeth_add_multicast_ipv6(card); |
| 5462 | #endif | 5497 | #endif |
| 5498 | out: | ||
| 5463 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) | 5499 | if (qeth_set_thread_start_bit(card, QETH_SET_IP_THREAD) == 0) |
| 5464 | schedule_work(&card->kernel_thread_starter); | 5500 | schedule_work(&card->kernel_thread_starter); |
| 5465 | } | 5501 | } |
| @@ -5669,6 +5705,24 @@ qeth_add_multicast_ipv4(struct qeth_card *card) | |||
| 5669 | in_dev_put(in4_dev); | 5705 | in_dev_put(in4_dev); |
| 5670 | } | 5706 | } |
| 5671 | 5707 | ||
| 5708 | static void | ||
| 5709 | qeth_layer2_add_multicast(struct qeth_card *card) | ||
| 5710 | { | ||
| 5711 | struct qeth_ipaddr *ipm; | ||
| 5712 | struct dev_mc_list *dm; | ||
| 5713 | |||
| 5714 | QETH_DBF_TEXT(trace,4,"L2addmc"); | ||
| 5715 | for (dm = card->dev->mc_list; dm; dm = dm->next) { | ||
| 5716 | ipm = qeth_get_addr_buffer(QETH_PROT_IPV4); | ||
| 5717 | if (!ipm) | ||
| 5718 | continue; | ||
| 5719 | memcpy(ipm->mac,dm->dmi_addr,MAX_ADDR_LEN); | ||
| 5720 | ipm->is_multicast = 1; | ||
| 5721 | if (!qeth_add_ip(card, ipm)) | ||
| 5722 | kfree(ipm); | ||
| 5723 | } | ||
| 5724 | } | ||
| 5725 | |||
| 5672 | #ifdef CONFIG_QETH_IPV6 | 5726 | #ifdef CONFIG_QETH_IPV6 |
| 5673 | static inline void | 5727 | static inline void |
| 5674 | qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev) | 5728 | qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev) |
