Skip to content

Commit f13ade1

Browse files
julianwiedmanndavem330
authored andcommitted
s390/qeth: run non-offload L3 traffic over common xmit path
L3 OSAs can only offload IPv4 traffic, use the common L2 transmit path for all other traffic. In particular there's no support for TX VLAN offload, so any such packet needs to be manually de-accelerated via ndo_features_check(). Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent fc69660 commit f13ade1

File tree

1 file changed

+44
-26
lines changed

1 file changed

+44
-26
lines changed

drivers/s390/net/qeth_l3_main.c

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1983,21 +1983,23 @@ static int qeth_l3_get_cast_type(struct sk_buff *skb)
19831983
rcu_read_unlock();
19841984

19851985
/* no neighbour (eg AF_PACKET), fall back to target's IP address ... */
1986-
if (be16_to_cpu(skb->protocol) == ETH_P_IPV6)
1987-
return ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ?
1988-
RTN_MULTICAST : RTN_UNICAST;
1989-
else if (be16_to_cpu(skb->protocol) == ETH_P_IP)
1986+
switch (qeth_get_ip_version(skb)) {
1987+
case 4:
19901988
return ipv4_is_multicast(ip_hdr(skb)->daddr) ?
19911989
RTN_MULTICAST : RTN_UNICAST;
1992-
1993-
/* ... and MAC address */
1994-
if (ether_addr_equal_64bits(eth_hdr(skb)->h_dest, skb->dev->broadcast))
1995-
return RTN_BROADCAST;
1996-
if (is_multicast_ether_addr(eth_hdr(skb)->h_dest))
1997-
return RTN_MULTICAST;
1998-
1999-
/* default to unicast */
2000-
return RTN_UNICAST;
1990+
case 6:
1991+
return ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) ?
1992+
RTN_MULTICAST : RTN_UNICAST;
1993+
default:
1994+
/* ... and MAC address */
1995+
if (ether_addr_equal_64bits(eth_hdr(skb)->h_dest,
1996+
skb->dev->broadcast))
1997+
return RTN_BROADCAST;
1998+
if (is_multicast_ether_addr(eth_hdr(skb)->h_dest))
1999+
return RTN_MULTICAST;
2000+
/* default to unicast */
2001+
return RTN_UNICAST;
2002+
}
20012003
}
20022004

20032005
static void qeth_l3_fill_af_iucv_hdr(struct qeth_hdr *hdr, struct sk_buff *skb,
@@ -2034,20 +2036,21 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
20342036
struct sk_buff *skb, int ipv, int cast_type,
20352037
unsigned int data_len)
20362038
{
2039+
struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
2040+
20372041
memset(hdr, 0, sizeof(struct qeth_hdr));
20382042
hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
20392043
hdr->hdr.l3.length = data_len;
20402044

2041-
/*
2042-
* before we're going to overwrite this location with next hop ip.
2043-
* v6 uses passthrough, v4 sets the tag in the QDIO header.
2044-
*/
2045-
if (skb_vlan_tag_present(skb)) {
2046-
if ((ipv == 4) || (card->info.type == QETH_CARD_TYPE_IQD))
2047-
hdr->hdr.l3.ext_flags = QETH_HDR_EXT_VLAN_FRAME;
2048-
else
2049-
hdr->hdr.l3.ext_flags = QETH_HDR_EXT_INCLUDE_VLAN_TAG;
2050-
hdr->hdr.l3.vlan_id = skb_vlan_tag_get(skb);
2045+
if (ipv == 4 || IS_IQD(card)) {
2046+
/* NETIF_F_HW_VLAN_CTAG_TX */
2047+
if (skb_vlan_tag_present(skb)) {
2048+
hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_VLAN_FRAME;
2049+
hdr->hdr.l3.vlan_id = skb_vlan_tag_get(skb);
2050+
}
2051+
} else if (veth->h_vlan_proto == htons(ETH_P_8021Q)) {
2052+
hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_INCLUDE_VLAN_TAG;
2053+
hdr->hdr.l3.vlan_id = ntohs(veth->h_vlan_TCI);
20512054
}
20522055

20532056
if (!skb_is_gso(skb) && skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -2373,8 +2376,11 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
23732376

23742377
if (IS_IQD(card) || (!skb_is_gso(skb) && ipv == 4))
23752378
rc = qeth_l3_xmit_offload(card, skb, queue, ipv, cast_type);
2376-
else
2379+
else if (skb_is_gso(skb))
23772380
rc = qeth_l3_xmit(card, skb, queue, ipv, cast_type);
2381+
else
2382+
rc = qeth_xmit(card, skb, queue, ipv, cast_type,
2383+
qeth_l3_fill_header);
23782384

23792385
if (!rc) {
23802386
card->stats.tx_packets++;
@@ -2476,6 +2482,15 @@ qeth_l3_neigh_setup(struct net_device *dev, struct neigh_parms *np)
24762482
return 0;
24772483
}
24782484

2485+
static netdev_features_t qeth_l3_osa_features_check(struct sk_buff *skb,
2486+
struct net_device *dev,
2487+
netdev_features_t features)
2488+
{
2489+
if (qeth_get_ip_version(skb) != 4)
2490+
features &= ~NETIF_F_HW_VLAN_CTAG_TX;
2491+
return qeth_features_check(skb, dev, features);
2492+
}
2493+
24792494
static const struct net_device_ops qeth_l3_netdev_ops = {
24802495
.ndo_open = qeth_l3_open,
24812496
.ndo_stop = qeth_l3_stop,
@@ -2496,7 +2511,7 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = {
24962511
.ndo_stop = qeth_l3_stop,
24972512
.ndo_get_stats = qeth_get_stats,
24982513
.ndo_start_xmit = qeth_l3_hard_start_xmit,
2499-
.ndo_features_check = qeth_features_check,
2514+
.ndo_features_check = qeth_l3_osa_features_check,
25002515
.ndo_validate_addr = eth_validate_addr,
25012516
.ndo_set_rx_mode = qeth_l3_set_rx_mode,
25022517
.ndo_do_ioctl = qeth_do_ioctl,
@@ -2524,6 +2539,9 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
25242539
}
25252540

25262541
card->dev->netdev_ops = &qeth_l3_osa_netdev_ops;
2542+
card->dev->needed_headroom = sizeof(struct qeth_hdr);
2543+
/* allow for de-acceleration of NETIF_F_HW_VLAN_CTAG_TX: */
2544+
card->dev->needed_headroom += VLAN_HLEN;
25272545

25282546
/*IPv6 address autoconfiguration stuff*/
25292547
qeth_l3_get_unique_id(card);
@@ -2545,6 +2563,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
25452563
} else if (card->info.type == QETH_CARD_TYPE_IQD) {
25462564
card->dev->flags |= IFF_NOARP;
25472565
card->dev->netdev_ops = &qeth_l3_netdev_ops;
2566+
card->dev->needed_headroom = sizeof(struct qeth_hdr) - ETH_HLEN;
25482567

25492568
rc = qeth_l3_iqd_read_initial_mac(card);
25502569
if (rc)
@@ -2556,7 +2575,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
25562575
return -ENODEV;
25572576

25582577
card->dev->ethtool_ops = &qeth_l3_ethtool_ops;
2559-
card->dev->needed_headroom = sizeof(struct qeth_hdr) - ETH_HLEN;
25602578
card->dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
25612579
NETIF_F_HW_VLAN_CTAG_RX |
25622580
NETIF_F_HW_VLAN_CTAG_FILTER;

0 commit comments

Comments
 (0)