diff options
Diffstat (limited to 'drivers/s390/net/qeth_l3_main.c')
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 125 |
1 files changed, 64 insertions, 61 deletions
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index fd69da3fa6b4..fafb8c299540 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -13,6 +13,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/bitops.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/kernel.h> @@ -23,6 +24,7 @@ #include <linux/inetdevice.h> #include <linux/igmp.h> #include <linux/slab.h> +#include <linux/if_vlan.h> #include <net/ip.h> #include <net/arp.h> @@ -1696,16 +1698,18 @@ static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev) static void qeth_l3_add_vlan_mc(struct qeth_card *card) { struct in_device *in_dev; - struct vlan_group *vg; - int i; + u16 vid; QETH_CARD_TEXT(card, 4, "addmcvl"); - if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL)) + if (!qeth_is_supported(card, IPA_FULL_VLAN)) return; - vg = card->vlangrp; - for (i = 0; i < VLAN_N_VID; i++) { - struct net_device *netdev = vlan_group_get_device(vg, i); + for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) { + struct net_device *netdev; + + rcu_read_lock(); + netdev = __vlan_find_dev_deep(card->dev, vid); + rcu_read_unlock(); if (netdev == NULL || !(netdev->flags & IFF_UP)) continue; @@ -1759,16 +1763,16 @@ static void qeth_l3_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev) static void qeth_l3_add_vlan_mc6(struct qeth_card *card) { struct inet6_dev *in_dev; - struct vlan_group *vg; - int i; + u16 vid; QETH_CARD_TEXT(card, 4, "admc6vl"); - if (!qeth_is_supported(card, IPA_FULL_VLAN) || (card->vlangrp == NULL)) + if (!qeth_is_supported(card, IPA_FULL_VLAN)) return; - vg = card->vlangrp; - for (i = 0; i < VLAN_N_VID; i++) { - struct net_device *netdev = vlan_group_get_device(vg, i); + for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) { + struct net_device *netdev; + + netdev = __vlan_find_dev_deep(card->dev, vid); if (netdev == NULL || !(netdev->flags & IFF_UP)) continue; @@ -1806,10 +1810,12 @@ static void qeth_l3_free_vlan_addresses4(struct qeth_card *card, struct in_device *in_dev; struct in_ifaddr *ifa; struct qeth_ipaddr *addr; + struct net_device *netdev; QETH_CARD_TEXT(card, 4, "frvaddr4"); - in_dev = in_dev_get(vlan_group_get_device(card->vlangrp, vid)); + netdev = __vlan_find_dev_deep(card->dev, vid); + in_dev = in_dev_get(netdev); if (!in_dev) return; for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { @@ -1832,10 +1838,12 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card, struct inet6_dev *in6_dev; struct inet6_ifaddr *ifa; struct qeth_ipaddr *addr; + struct net_device *netdev; QETH_CARD_TEXT(card, 4, "frvaddr6"); - in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid)); + netdev = __vlan_find_dev_deep(card->dev, vid); + in6_dev = in6_dev_get(netdev); if (!in6_dev) return; list_for_each_entry(ifa, &in6_dev->addr_list, if_list) { @@ -1856,26 +1864,15 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card, static void qeth_l3_free_vlan_addresses(struct qeth_card *card, unsigned short vid) { - if (!card->vlangrp) - return; qeth_l3_free_vlan_addresses4(card, vid); qeth_l3_free_vlan_addresses6(card, vid); } -static void qeth_l3_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) +static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) { struct qeth_card *card = dev->ml_priv; - unsigned long flags; - - QETH_CARD_TEXT(card, 4, "vlanreg"); - spin_lock_irqsave(&card->vlanlock, flags); - card->vlangrp = grp; - spin_unlock_irqrestore(&card->vlanlock, flags); -} -static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) -{ + set_bit(vid, card->active_vlans); return; } @@ -1892,7 +1889,7 @@ static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) spin_lock_irqsave(&card->vlanlock, flags); /* unregister IP addresses of vlan device */ qeth_l3_free_vlan_addresses(card, vid); - vlan_group_set_device(card->vlangrp, vid, NULL); + clear_bit(vid, card->active_vlans); spin_unlock_irqrestore(&card->vlanlock, flags); qeth_l3_set_multicast_list(card->dev); } @@ -2014,10 +2011,8 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, &vlan_tag); len = skb->len; if (is_vlan && !card->options.sniffer) - vlan_gro_receive(&card->napi, card->vlangrp, - vlan_tag, skb); - else - napi_gro_receive(&card->napi, skb); + __vlan_hwaccel_put_tag(skb, vlan_tag); + napi_gro_receive(&card->napi, skb); break; case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ skb->pkt_type = PACKET_HOST; @@ -2118,15 +2113,15 @@ static int qeth_l3_verify_vlan_dev(struct net_device *dev, struct qeth_card *card) { int rc = 0; - struct vlan_group *vg; - int i; + u16 vid; - vg = card->vlangrp; - if (!vg) - return rc; + for_each_set_bit(vid, card->active_vlans, VLAN_N_VID) { + struct net_device *netdev; - for (i = 0; i < VLAN_N_VID; i++) { - if (vlan_group_get_device(vg, i) == dev) { + rcu_read_lock(); + netdev = __vlan_find_dev_deep(dev, vid); + rcu_read_unlock(); + if (netdev == dev) { rc = QETH_VLAN_CARD; break; } @@ -2742,9 +2737,14 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb) { int cast_type = RTN_UNSPEC; - - if (skb_dst(skb) && skb_dst(skb)->neighbour) { - cast_type = skb_dst(skb)->neighbour->type; + struct neighbour *n = NULL; + struct dst_entry *dst; + + dst = skb_dst(skb); + if (dst) + n = dst_get_neighbour(dst); + if (n) { + cast_type = n->type; if ((cast_type == RTN_BROADCAST) || (cast_type == RTN_MULTICAST) || (cast_type == RTN_ANYCAST)) @@ -2787,6 +2787,9 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb) static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, struct sk_buff *skb, int ipv, int cast_type) { + struct neighbour *n = NULL; + struct dst_entry *dst; + memset(hdr, 0, sizeof(struct qeth_hdr)); hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3; hdr->hdr.l3.ext_flags = 0; @@ -2795,7 +2798,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, * before we're going to overwrite this location with next hop ip. * v6 uses passthrough, v4 sets the tag in the QDIO header. */ - if (card->vlangrp && vlan_tx_tag_present(skb)) { + if (vlan_tx_tag_present(skb)) { if ((ipv == 4) || (card->info.type == QETH_CARD_TYPE_IQD)) hdr->hdr.l3.ext_flags = QETH_HDR_EXT_VLAN_FRAME; else @@ -2804,13 +2807,16 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, } hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr); + dst = skb_dst(skb); + if (dst) + n = dst_get_neighbour(dst); if (ipv == 4) { /* IPv4 */ hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags4(cast_type); memset(hdr->hdr.l3.dest_addr, 0, 12); - if ((skb_dst(skb)) && (skb_dst(skb)->neighbour)) { + if (n) { *((u32 *) (&hdr->hdr.l3.dest_addr[12])) = - *((u32 *) skb_dst(skb)->neighbour->primary_key); + *((u32 *) n->primary_key); } else { /* fill in destination address used in ip header */ *((u32 *) (&hdr->hdr.l3.dest_addr[12])) = @@ -2821,9 +2827,9 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags6(cast_type); if (card->info.type == QETH_CARD_TYPE_IQD) hdr->hdr.l3.flags &= ~QETH_HDR_PASSTHRU; - if ((skb_dst(skb)) && (skb_dst(skb)->neighbour)) { + if (n) { memcpy(hdr->hdr.l3.dest_addr, - skb_dst(skb)->neighbour->primary_key, 16); + n->primary_key, 16); } else { /* fill in destination address used in ip header */ memcpy(hdr->hdr.l3.dest_addr, @@ -2977,8 +2983,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_pull(new_skb, ETH_HLEN); } - if (ipv != 4 && card->vlangrp && - vlan_tx_tag_present(new_skb)) { + if (ipv != 4 && vlan_tx_tag_present(new_skb)) { skb_push(new_skb, VLAN_HLEN); skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4); skb_copy_to_linear_data_offset(new_skb, 4, @@ -3222,14 +3227,13 @@ static const struct net_device_ops qeth_l3_netdev_ops = { .ndo_start_xmit = qeth_l3_hard_start_xmit, .ndo_validate_addr = eth_validate_addr, .ndo_set_multicast_list = qeth_l3_set_multicast_list, - .ndo_do_ioctl = qeth_l3_do_ioctl, - .ndo_change_mtu = qeth_change_mtu, - .ndo_fix_features = qeth_l3_fix_features, - .ndo_set_features = qeth_l3_set_features, - .ndo_vlan_rx_register = qeth_l3_vlan_rx_register, + .ndo_do_ioctl = qeth_l3_do_ioctl, + .ndo_change_mtu = qeth_change_mtu, + .ndo_fix_features = qeth_l3_fix_features, + .ndo_set_features = qeth_l3_set_features, .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid, - .ndo_tx_timeout = qeth_tx_timeout, + .ndo_tx_timeout = qeth_tx_timeout, }; static const struct net_device_ops qeth_l3_osa_netdev_ops = { @@ -3239,14 +3243,13 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = { .ndo_start_xmit = qeth_l3_hard_start_xmit, .ndo_validate_addr = eth_validate_addr, .ndo_set_multicast_list = qeth_l3_set_multicast_list, - .ndo_do_ioctl = qeth_l3_do_ioctl, - .ndo_change_mtu = qeth_change_mtu, - .ndo_fix_features = qeth_l3_fix_features, - .ndo_set_features = qeth_l3_set_features, - .ndo_vlan_rx_register = qeth_l3_vlan_rx_register, + .ndo_do_ioctl = qeth_l3_do_ioctl, + .ndo_change_mtu = qeth_change_mtu, + .ndo_fix_features = qeth_l3_fix_features, + .ndo_set_features = qeth_l3_set_features, .ndo_vlan_rx_add_vid = qeth_l3_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = qeth_l3_vlan_rx_kill_vid, - .ndo_tx_timeout = qeth_tx_timeout, + .ndo_tx_timeout = qeth_tx_timeout, .ndo_neigh_setup = qeth_l3_neigh_setup, }; |