diff options
Diffstat (limited to 'drivers/s390/net/qeth_l3_main.c')
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 92 |
1 files changed, 71 insertions, 21 deletions
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index fafb8c29954..ce735204d31 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <net/ip.h> | 29 | #include <net/ip.h> |
30 | #include <net/arp.h> | 30 | #include <net/arp.h> |
31 | #include <net/ip6_checksum.h> | 31 | #include <net/ip6_checksum.h> |
32 | #include <net/iucv/af_iucv.h> | ||
32 | 33 | ||
33 | #include "qeth_l3.h" | 34 | #include "qeth_l3.h" |
34 | 35 | ||
@@ -267,7 +268,7 @@ static int __qeth_l3_insert_ip_todo(struct qeth_card *card, | |||
267 | } | 268 | } |
268 | } | 269 | } |
269 | 270 | ||
270 | static int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | 271 | int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) |
271 | { | 272 | { |
272 | unsigned long flags; | 273 | unsigned long flags; |
273 | int rc = 0; | 274 | int rc = 0; |
@@ -286,7 +287,7 @@ static int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | |||
286 | return rc; | 287 | return rc; |
287 | } | 288 | } |
288 | 289 | ||
289 | static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | 290 | int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) |
290 | { | 291 | { |
291 | unsigned long flags; | 292 | unsigned long flags; |
292 | int rc = 0; | 293 | int rc = 0; |
@@ -305,7 +306,7 @@ static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | |||
305 | } | 306 | } |
306 | 307 | ||
307 | 308 | ||
308 | static struct qeth_ipaddr *qeth_l3_get_addr_buffer( | 309 | struct qeth_ipaddr *qeth_l3_get_addr_buffer( |
309 | enum qeth_prot_versions prot) | 310 | enum qeth_prot_versions prot) |
310 | { | 311 | { |
311 | struct qeth_ipaddr *addr; | 312 | struct qeth_ipaddr *addr; |
@@ -421,7 +422,7 @@ again: | |||
421 | list_splice(&fail_list, &card->ip_list); | 422 | list_splice(&fail_list, &card->ip_list); |
422 | } | 423 | } |
423 | 424 | ||
424 | static void qeth_l3_set_ip_addr_list(struct qeth_card *card) | 425 | void qeth_l3_set_ip_addr_list(struct qeth_card *card) |
425 | { | 426 | { |
426 | struct list_head *tbd_list; | 427 | struct list_head *tbd_list; |
427 | struct qeth_ipaddr *todo, *addr; | 428 | struct qeth_ipaddr *todo, *addr; |
@@ -438,7 +439,7 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card) | |||
438 | 439 | ||
439 | spin_lock_irqsave(&card->ip_lock, flags); | 440 | spin_lock_irqsave(&card->ip_lock, flags); |
440 | tbd_list = card->ip_tbd_list; | 441 | tbd_list = card->ip_tbd_list; |
441 | card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC); | 442 | card->ip_tbd_list = kzalloc(sizeof(struct list_head), GFP_ATOMIC); |
442 | if (!card->ip_tbd_list) { | 443 | if (!card->ip_tbd_list) { |
443 | QETH_CARD_TEXT(card, 0, "silnomem"); | 444 | QETH_CARD_TEXT(card, 0, "silnomem"); |
444 | card->ip_tbd_list = tbd_list; | 445 | card->ip_tbd_list = tbd_list; |
@@ -1993,12 +1994,13 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, | |||
1993 | __u16 vlan_tag = 0; | 1994 | __u16 vlan_tag = 0; |
1994 | int is_vlan; | 1995 | int is_vlan; |
1995 | unsigned int len; | 1996 | unsigned int len; |
1997 | __u16 magic; | ||
1996 | 1998 | ||
1997 | *done = 0; | 1999 | *done = 0; |
1998 | BUG_ON(!budget); | 2000 | BUG_ON(!budget); |
1999 | while (budget) { | 2001 | while (budget) { |
2000 | skb = qeth_core_get_next_skb(card, | 2002 | skb = qeth_core_get_next_skb(card, |
2001 | card->qdio.in_q->bufs[card->rx.b_index].buffer, | 2003 | &card->qdio.in_q->bufs[card->rx.b_index], |
2002 | &card->rx.b_element, &card->rx.e_offset, &hdr); | 2004 | &card->rx.b_element, &card->rx.e_offset, &hdr); |
2003 | if (!skb) { | 2005 | if (!skb) { |
2004 | *done = 1; | 2006 | *done = 1; |
@@ -2007,12 +2009,26 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, | |||
2007 | skb->dev = card->dev; | 2009 | skb->dev = card->dev; |
2008 | switch (hdr->hdr.l3.id) { | 2010 | switch (hdr->hdr.l3.id) { |
2009 | case QETH_HEADER_TYPE_LAYER3: | 2011 | case QETH_HEADER_TYPE_LAYER3: |
2010 | is_vlan = qeth_l3_rebuild_skb(card, skb, hdr, | 2012 | magic = *(__u16 *)skb->data; |
2013 | if ((card->info.type == QETH_CARD_TYPE_IQD) && | ||
2014 | (magic == ETH_P_AF_IUCV)) { | ||
2015 | skb->protocol = ETH_P_AF_IUCV; | ||
2016 | skb->pkt_type = PACKET_HOST; | ||
2017 | skb->mac_header = NET_SKB_PAD; | ||
2018 | skb->dev = card->dev; | ||
2019 | len = skb->len; | ||
2020 | card->dev->header_ops->create(skb, card->dev, 0, | ||
2021 | card->dev->dev_addr, "FAKELL", | ||
2022 | card->dev->addr_len); | ||
2023 | netif_receive_skb(skb); | ||
2024 | } else { | ||
2025 | is_vlan = qeth_l3_rebuild_skb(card, skb, hdr, | ||
2011 | &vlan_tag); | 2026 | &vlan_tag); |
2012 | len = skb->len; | 2027 | len = skb->len; |
2013 | if (is_vlan && !card->options.sniffer) | 2028 | if (is_vlan && !card->options.sniffer) |
2014 | __vlan_hwaccel_put_tag(skb, vlan_tag); | 2029 | __vlan_hwaccel_put_tag(skb, vlan_tag); |
2015 | napi_gro_receive(&card->napi, skb); | 2030 | napi_gro_receive(&card->napi, skb); |
2031 | } | ||
2016 | break; | 2032 | break; |
2017 | case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ | 2033 | case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ |
2018 | skb->pkt_type = PACKET_HOST; | 2034 | skb->pkt_type = PACKET_HOST; |
@@ -2784,6 +2800,30 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb) | |||
2784 | return cast_type; | 2800 | return cast_type; |
2785 | } | 2801 | } |
2786 | 2802 | ||
2803 | static void qeth_l3_fill_af_iucv_hdr(struct qeth_card *card, | ||
2804 | struct qeth_hdr *hdr, struct sk_buff *skb) | ||
2805 | { | ||
2806 | char daddr[16]; | ||
2807 | struct af_iucv_trans_hdr *iucv_hdr; | ||
2808 | |||
2809 | skb_pull(skb, 14); | ||
2810 | card->dev->header_ops->create(skb, card->dev, 0, | ||
2811 | card->dev->dev_addr, card->dev->dev_addr, | ||
2812 | card->dev->addr_len); | ||
2813 | skb_pull(skb, 14); | ||
2814 | iucv_hdr = (struct af_iucv_trans_hdr *)skb->data; | ||
2815 | memset(hdr, 0, sizeof(struct qeth_hdr)); | ||
2816 | hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3; | ||
2817 | hdr->hdr.l3.ext_flags = 0; | ||
2818 | hdr->hdr.l3.length = skb->len; | ||
2819 | hdr->hdr.l3.flags = QETH_HDR_IPV6 | QETH_CAST_UNICAST; | ||
2820 | memset(daddr, 0, sizeof(daddr)); | ||
2821 | daddr[0] = 0xfe; | ||
2822 | daddr[1] = 0x80; | ||
2823 | memcpy(&daddr[8], iucv_hdr->destUserID, 8); | ||
2824 | memcpy(hdr->hdr.l3.dest_addr, daddr, 16); | ||
2825 | } | ||
2826 | |||
2787 | static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, | 2827 | static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, |
2788 | struct sk_buff *skb, int ipv, int cast_type) | 2828 | struct sk_buff *skb, int ipv, int cast_type) |
2789 | { | 2829 | { |
@@ -2936,8 +2976,11 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2936 | int data_offset = -1; | 2976 | int data_offset = -1; |
2937 | int nr_frags; | 2977 | int nr_frags; |
2938 | 2978 | ||
2939 | if (((card->info.type == QETH_CARD_TYPE_IQD) && (!ipv)) || | 2979 | if (((card->info.type == QETH_CARD_TYPE_IQD) && |
2940 | card->options.sniffer) | 2980 | (((card->options.cq != QETH_CQ_ENABLED) && !ipv) || |
2981 | ((card->options.cq == QETH_CQ_ENABLED) && | ||
2982 | (skb->protocol != ETH_P_AF_IUCV)))) || | ||
2983 | card->options.sniffer) | ||
2941 | goto tx_drop; | 2984 | goto tx_drop; |
2942 | 2985 | ||
2943 | if ((card->state != CARD_STATE_UP) || !card->lan_online) { | 2986 | if ((card->state != CARD_STATE_UP) || !card->lan_online) { |
@@ -2959,7 +3002,10 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2959 | if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) && | 3002 | if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) && |
2960 | (skb_shinfo(skb)->nr_frags == 0)) { | 3003 | (skb_shinfo(skb)->nr_frags == 0)) { |
2961 | new_skb = skb; | 3004 | new_skb = skb; |
2962 | data_offset = ETH_HLEN; | 3005 | if (new_skb->protocol == ETH_P_AF_IUCV) |
3006 | data_offset = 0; | ||
3007 | else | ||
3008 | data_offset = ETH_HLEN; | ||
2963 | hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC); | 3009 | hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC); |
2964 | if (!hdr) | 3010 | if (!hdr) |
2965 | goto tx_drop; | 3011 | goto tx_drop; |
@@ -2993,7 +3039,6 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2993 | tag = (u16 *)(new_skb->data + 12); | 3039 | tag = (u16 *)(new_skb->data + 12); |
2994 | *tag = __constant_htons(ETH_P_8021Q); | 3040 | *tag = __constant_htons(ETH_P_8021Q); |
2995 | *(tag + 1) = htons(vlan_tx_tag_get(new_skb)); | 3041 | *(tag + 1) = htons(vlan_tx_tag_get(new_skb)); |
2996 | new_skb->vlan_tci = 0; | ||
2997 | } | 3042 | } |
2998 | } | 3043 | } |
2999 | 3044 | ||
@@ -3025,9 +3070,13 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3025 | qeth_l3_fill_header(card, hdr, new_skb, ipv, | 3070 | qeth_l3_fill_header(card, hdr, new_skb, ipv, |
3026 | cast_type); | 3071 | cast_type); |
3027 | } else { | 3072 | } else { |
3028 | qeth_l3_fill_header(card, hdr, new_skb, ipv, | 3073 | if (new_skb->protocol == ETH_P_AF_IUCV) |
3029 | cast_type); | 3074 | qeth_l3_fill_af_iucv_hdr(card, hdr, new_skb); |
3030 | hdr->hdr.l3.length = new_skb->len - data_offset; | 3075 | else { |
3076 | qeth_l3_fill_header(card, hdr, new_skb, ipv, | ||
3077 | cast_type); | ||
3078 | hdr->hdr.l3.length = new_skb->len - data_offset; | ||
3079 | } | ||
3031 | } | 3080 | } |
3032 | 3081 | ||
3033 | if (skb->ip_summed == CHECKSUM_PARTIAL) | 3082 | if (skb->ip_summed == CHECKSUM_PARTIAL) |
@@ -3226,7 +3275,7 @@ static const struct net_device_ops qeth_l3_netdev_ops = { | |||
3226 | .ndo_get_stats = qeth_get_stats, | 3275 | .ndo_get_stats = qeth_get_stats, |
3227 | .ndo_start_xmit = qeth_l3_hard_start_xmit, | 3276 | .ndo_start_xmit = qeth_l3_hard_start_xmit, |
3228 | .ndo_validate_addr = eth_validate_addr, | 3277 | .ndo_validate_addr = eth_validate_addr, |
3229 | .ndo_set_multicast_list = qeth_l3_set_multicast_list, | 3278 | .ndo_set_rx_mode = qeth_l3_set_multicast_list, |
3230 | .ndo_do_ioctl = qeth_l3_do_ioctl, | 3279 | .ndo_do_ioctl = qeth_l3_do_ioctl, |
3231 | .ndo_change_mtu = qeth_change_mtu, | 3280 | .ndo_change_mtu = qeth_change_mtu, |
3232 | .ndo_fix_features = qeth_l3_fix_features, | 3281 | .ndo_fix_features = qeth_l3_fix_features, |
@@ -3242,7 +3291,7 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = { | |||
3242 | .ndo_get_stats = qeth_get_stats, | 3291 | .ndo_get_stats = qeth_get_stats, |
3243 | .ndo_start_xmit = qeth_l3_hard_start_xmit, | 3292 | .ndo_start_xmit = qeth_l3_hard_start_xmit, |
3244 | .ndo_validate_addr = eth_validate_addr, | 3293 | .ndo_validate_addr = eth_validate_addr, |
3245 | .ndo_set_multicast_list = qeth_l3_set_multicast_list, | 3294 | .ndo_set_rx_mode = qeth_l3_set_multicast_list, |
3246 | .ndo_do_ioctl = qeth_l3_do_ioctl, | 3295 | .ndo_do_ioctl = qeth_l3_do_ioctl, |
3247 | .ndo_change_mtu = qeth_change_mtu, | 3296 | .ndo_change_mtu = qeth_change_mtu, |
3248 | .ndo_fix_features = qeth_l3_fix_features, | 3297 | .ndo_fix_features = qeth_l3_fix_features, |
@@ -3290,6 +3339,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) | |||
3290 | card->dev->flags |= IFF_NOARP; | 3339 | card->dev->flags |= IFF_NOARP; |
3291 | card->dev->netdev_ops = &qeth_l3_netdev_ops; | 3340 | card->dev->netdev_ops = &qeth_l3_netdev_ops; |
3292 | qeth_l3_iqd_read_initial_mac(card); | 3341 | qeth_l3_iqd_read_initial_mac(card); |
3342 | if (card->options.hsuid[0]) | ||
3343 | memcpy(card->dev->perm_addr, card->options.hsuid, 9); | ||
3293 | } else | 3344 | } else |
3294 | return -ENODEV; | 3345 | return -ENODEV; |
3295 | 3346 | ||
@@ -3660,7 +3711,6 @@ static int qeth_l3_ip6_event(struct notifier_block *this, | |||
3660 | struct qeth_ipaddr *addr; | 3711 | struct qeth_ipaddr *addr; |
3661 | struct qeth_card *card; | 3712 | struct qeth_card *card; |
3662 | 3713 | ||
3663 | |||
3664 | card = qeth_l3_get_card_from_dev(dev); | 3714 | card = qeth_l3_get_card_from_dev(dev); |
3665 | if (!card) | 3715 | if (!card) |
3666 | return NOTIFY_DONE; | 3716 | return NOTIFY_DONE; |