diff options
author | Julian Wiedmann <jwi@linux.ibm.com> | 2019-11-14 11:19:21 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-11-15 03:16:51 +0100 |
commit | 611abe5165ca185bb64e0427c7efe2acdc9d5250 (patch) | |
tree | db483113b961ac47c36d990dac30d1c106c5b8b4 /drivers/s390/net | |
parent | s390/qeth: remove gratuitious RX modeset (diff) | |
download | linux-611abe5165ca185bb64e0427c7efe2acdc9d5250.tar.xz linux-611abe5165ca185bb64e0427c7efe2acdc9d5250.zip |
s390/qeth: consolidate L3 mcast registration code
Current code processes each (VLAN) device twice - once to inspect the
IPv4 mcast addresses, and then a second time to walk the IPv6 mcast
addresses. Unify all this into a single helper, thus removing some
checks and a duplicated VLAN lookup.
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/s390/net')
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 120 |
1 files changed, 30 insertions, 90 deletions
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 0497ee46660b..1e060331a8cc 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1113,17 +1113,28 @@ qeth_diags_trace(struct qeth_card *card, enum qeth_diags_trace_cmds diags_cmd) return qeth_send_ipa_cmd(card, iob, qeth_diags_trace_cb, NULL); } -static void -qeth_l3_add_mc_to_hash(struct qeth_card *card, struct in_device *in4_dev) +static void qeth_l3_add_mcast_rcu(struct net_device *dev, + struct qeth_card *card) { + struct qeth_ipaddr *tmp = NULL; + struct inet6_dev *in6_dev; + struct in_device *in4_dev; + struct qeth_ipaddr *ipm; struct ip_mc_list *im4; - struct qeth_ipaddr *tmp, *ipm; + struct ifmcaddr6 *im6; QETH_CARD_TEXT(card, 4, "addmc"); + if (!dev || !(dev->flags & IFF_UP)) + goto out; + tmp = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); if (!tmp) - return; + goto out; + + in4_dev = __in_dev_get_rcu(dev); + if (!in4_dev) + goto walk_ipv6; for (im4 = rcu_dereference(in4_dev->mc_list); im4 != NULL; im4 = rcu_dereference(im4->next_rcu)) { @@ -1147,63 +1158,15 @@ qeth_l3_add_mc_to_hash(struct qeth_card *card, struct in_device *in4_dev) } } - kfree(tmp); -} - -/* called with rcu_read_lock */ -static void qeth_l3_add_vlan_mc(struct qeth_card *card) -{ - struct in_device *in_dev; - u16 vid; - - QETH_CARD_TEXT(card, 4, "addmcvl"); - - if (!qeth_is_supported(card, IPA_FULL_VLAN)) - return; - - for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) { - struct net_device *netdev; - - netdev = __vlan_find_dev_deep_rcu(card->dev, htons(ETH_P_8021Q), - vid); - if (netdev == NULL || - !(netdev->flags & IFF_UP)) - continue; - in_dev = __in_dev_get_rcu(netdev); - if (!in_dev) - continue; - qeth_l3_add_mc_to_hash(card, in_dev); - } -} - -static void qeth_l3_add_multicast_ipv4(struct qeth_card *card) -{ - struct in_device *in4_dev; - - QETH_CARD_TEXT(card, 4, "chkmcv4"); - - rcu_read_lock(); - in4_dev = __in_dev_get_rcu(card->dev); - if (in4_dev == NULL) - goto unlock; - qeth_l3_add_mc_to_hash(card, in4_dev); - qeth_l3_add_vlan_mc(card); -unlock: - rcu_read_unlock(); -} - -static void qeth_l3_add_mc6_to_hash(struct qeth_card *card, - struct inet6_dev *in6_dev) -{ - struct qeth_ipaddr *ipm; - struct ifmcaddr6 *im6; - struct qeth_ipaddr *tmp; +walk_ipv6: + if (!qeth_is_supported(card, IPA_IPV6)) + goto out; - QETH_CARD_TEXT(card, 4, "addmc6"); + in6_dev = __in6_dev_get(dev); + if (!in6_dev) + goto out; - tmp = qeth_l3_get_addr_buffer(QETH_PROT_IPV6); - if (!tmp) - return; + qeth_l3_init_ipaddr(tmp, QETH_IP_TYPE_NORMAL, QETH_PROT_IPV6); read_lock_bh(&in6_dev->lock); for (im6 = in6_dev->mc_list; im6 != NULL; im6 = im6->next) { @@ -1230,13 +1193,13 @@ static void qeth_l3_add_mc6_to_hash(struct qeth_card *card, } read_unlock_bh(&in6_dev->lock); +out: kfree(tmp); } /* called with rcu_read_lock */ -static void qeth_l3_add_vlan_mc6(struct qeth_card *card) +static void qeth_l3_add_vlan_mc(struct qeth_card *card) { - struct inet6_dev *in_dev; u16 vid; QETH_CARD_TEXT(card, 4, "admc6vl"); @@ -1249,36 +1212,10 @@ static void qeth_l3_add_vlan_mc6(struct qeth_card *card) netdev = __vlan_find_dev_deep_rcu(card->dev, htons(ETH_P_8021Q), vid); - if (netdev == NULL || - !(netdev->flags & IFF_UP)) - continue; - in_dev = in6_dev_get(netdev); - if (!in_dev) - continue; - qeth_l3_add_mc6_to_hash(card, in_dev); - in6_dev_put(in_dev); + qeth_l3_add_mcast_rcu(netdev, card); } } -static void qeth_l3_add_multicast_ipv6(struct qeth_card *card) -{ - struct inet6_dev *in6_dev; - - QETH_CARD_TEXT(card, 4, "chkmcv6"); - - if (!qeth_is_supported(card, IPA_IPV6)) - return ; - in6_dev = in6_dev_get(card->dev); - if (!in6_dev) - return; - - rcu_read_lock(); - qeth_l3_add_mc6_to_hash(card, in6_dev); - qeth_l3_add_vlan_mc6(card); - rcu_read_unlock(); - in6_dev_put(in6_dev); -} - static int qeth_l3_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid) { @@ -1450,8 +1387,11 @@ static void qeth_l3_rx_mode_work(struct work_struct *work) QETH_CARD_TEXT(card, 3, "setmulti"); if (!card->options.sniffer) { - qeth_l3_add_multicast_ipv4(card); - qeth_l3_add_multicast_ipv6(card); + rcu_read_lock(); + qeth_l3_add_mcast_rcu(card->dev, card); + if (qeth_is_supported(card, IPA_FULL_VLAN)) + qeth_l3_add_vlan_mc(card); + rcu_read_unlock(); hash_for_each_safe(card->ip_mc_htable, i, tmp, addr, hnode) { switch (addr->disp_flag) { |