Skip to content

Commit 571f9dd

Browse files
Kittipon Meesompopdavem330
authored andcommitted
s390/qeth: add IPv6 TX checksum offload support
Check if a qeth device supports IPv6 TX checksum offload, and advertise NETIF_F_IPV6_CSUM accordingly. Add support for setting the relevant bits in IPv6 packet descriptors. Currently this has only limited use (ie. UDP, or Jumbo Frames). For any TCP traffic with a standard MSS, the TCP checksum gets calculated as part of the linear GSO segmentation. Signed-off-by: Kittipon Meesompop <[email protected]> Signed-off-by: Julian Wiedmann <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a8155b0 commit 571f9dd

File tree

5 files changed

+38
-15
lines changed

5 files changed

+38
-15
lines changed

drivers/s390/net/qeth_core.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -878,14 +878,17 @@ static inline void qeth_rx_csum(struct qeth_card *card, struct sk_buff *skb,
878878
}
879879
}
880880

881-
static inline void qeth_tx_csum(struct sk_buff *skb, u8 *flags)
881+
static inline void qeth_tx_csum(struct sk_buff *skb, u8 *flags, int ipv)
882882
{
883883
*flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ;
884-
if (ip_hdr(skb)->protocol == IPPROTO_UDP)
884+
if ((ipv == 4 && ip_hdr(skb)->protocol == IPPROTO_UDP) ||
885+
(ipv == 6 && ipv6_hdr(skb)->nexthdr == IPPROTO_UDP))
885886
*flags |= QETH_HDR_EXT_UDP;
886-
/* some HW requires combined L3+L4 csum offload: */
887-
*flags |= QETH_HDR_EXT_CSUM_HDR_REQ;
888-
ip_hdr(skb)->check = 0;
887+
if (ipv == 4) {
888+
/* some HW requires combined L3+L4 csum offload: */
889+
*flags |= QETH_HDR_EXT_CSUM_HDR_REQ;
890+
ip_hdr(skb)->check = 0;
891+
}
889892
}
890893

891894
static inline void qeth_put_buffer_pool_entry(struct qeth_card *card,

drivers/s390/net/qeth_core_main.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6349,12 +6349,12 @@ static int qeth_ipa_checksum_run_cmd(struct qeth_card *card,
63496349
static int qeth_send_checksum_on(struct qeth_card *card, int cstype,
63506350
enum qeth_prot_versions prot)
63516351
{
6352-
const __u32 required_features = QETH_IPA_CHECKSUM_IP_HDR |
6353-
QETH_IPA_CHECKSUM_UDP |
6354-
QETH_IPA_CHECKSUM_TCP;
6352+
u32 required_features = QETH_IPA_CHECKSUM_UDP | QETH_IPA_CHECKSUM_TCP;
63556353
struct qeth_checksum_cmd chksum_cb;
63566354
int rc;
63576355

6356+
if (prot == QETH_PROT_IPV4)
6357+
required_features |= QETH_IPA_CHECKSUM_IP_HDR;
63586358
rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_START, 0,
63596359
&chksum_cb, prot);
63606360
if (!rc) {
@@ -6430,8 +6430,8 @@ static int qeth_set_ipa_tso(struct qeth_card *card, int on)
64306430
return rc;
64316431
}
64326432

6433-
#define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO)
6434-
6433+
#define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO | \
6434+
NETIF_F_IPV6_CSUM)
64356435
/**
64366436
* qeth_recover_features() - Restore device features after recovery
64376437
* @dev: the recovering net_device
@@ -6471,6 +6471,12 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features)
64716471
if (rc)
64726472
changed ^= NETIF_F_IP_CSUM;
64736473
}
6474+
if (changed & NETIF_F_IPV6_CSUM) {
6475+
rc = qeth_set_ipa_csum(card, features & NETIF_F_IPV6_CSUM,
6476+
IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV6);
6477+
if (rc)
6478+
changed ^= NETIF_F_IPV6_CSUM;
6479+
}
64746480
if ((changed & NETIF_F_RXCSUM)) {
64756481
rc = qeth_set_ipa_csum(card, features & NETIF_F_RXCSUM,
64766482
IPA_INBOUND_CHECKSUM, QETH_PROT_IPV4);
@@ -6500,6 +6506,8 @@ netdev_features_t qeth_fix_features(struct net_device *dev,
65006506
QETH_DBF_TEXT(SETUP, 2, "fixfeat");
65016507
if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
65026508
features &= ~NETIF_F_IP_CSUM;
6509+
if (!qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6))
6510+
features &= ~NETIF_F_IPV6_CSUM;
65036511
if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM))
65046512
features &= ~NETIF_F_RXCSUM;
65056513
if (!qeth_is_supported(card, IPA_OUTBOUND_TSO))

drivers/s390/net/qeth_core_mpc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ enum qeth_ipa_funcs {
246246
IPA_QUERY_ARP_ASSIST = 0x00040000L,
247247
IPA_INBOUND_TSO = 0x00080000L,
248248
IPA_OUTBOUND_TSO = 0x00100000L,
249+
IPA_OUTBOUND_CHECKSUM_V6 = 0x00800000L,
249250
};
250251

251252
/* SETIP/DELIP IPA Command: ***************************************************/

drivers/s390/net/qeth_l2_main.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,8 @@ static int qeth_l2_xmit_iqd(struct qeth_card *card, struct sk_buff *skb,
660660
}
661661

662662
static int qeth_l2_xmit_osa(struct qeth_card *card, struct sk_buff *skb,
663-
struct qeth_qdio_out_q *queue, int cast_type)
663+
struct qeth_qdio_out_q *queue, int cast_type,
664+
int ipv)
664665
{
665666
int push_len = sizeof(struct qeth_hdr);
666667
unsigned int elements, nr_frags;
@@ -699,7 +700,7 @@ static int qeth_l2_xmit_osa(struct qeth_card *card, struct sk_buff *skb,
699700
}
700701
qeth_l2_fill_header(hdr, skb, cast_type, skb->len - push_len);
701702
if (skb->ip_summed == CHECKSUM_PARTIAL) {
702-
qeth_tx_csum(skb, &hdr->hdr.l2.flags[1]);
703+
qeth_tx_csum(skb, &hdr->hdr.l2.flags[1], ipv);
703704
if (card->options.performance_stats)
704705
card->perf_stats.tx_csum++;
705706
}
@@ -754,14 +755,15 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
754755
{
755756
struct qeth_card *card = dev->ml_priv;
756757
int cast_type = qeth_l2_get_cast_type(card, skb);
758+
int ipv = qeth_get_ip_version(skb);
757759
struct qeth_qdio_out_q *queue;
758760
int tx_bytes = skb->len;
759761
int rc;
760762

761763
if (card->qdio.do_prio_queueing || (cast_type &&
762764
card->info.is_multicast_different))
763765
queue = card->qdio.out_qs[qeth_get_priority_queue(card, skb,
764-
qeth_get_ip_version(skb), cast_type)];
766+
ipv, cast_type)];
765767
else
766768
queue = card->qdio.out_qs[card->qdio.default_out_queue];
767769

@@ -784,7 +786,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
784786
rc = qeth_l2_xmit_iqd(card, skb, queue, cast_type);
785787
break;
786788
default:
787-
rc = qeth_l2_xmit_osa(card, skb, queue, cast_type);
789+
rc = qeth_l2_xmit_osa(card, skb, queue, cast_type, ipv);
788790
}
789791

790792
if (!rc) {
@@ -995,6 +997,10 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
995997
card->dev->vlan_features |= NETIF_F_RXCSUM;
996998
}
997999
}
1000+
if (qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) {
1001+
card->dev->hw_features |= NETIF_F_IPV6_CSUM;
1002+
card->dev->vlan_features |= NETIF_F_IPV6_CSUM;
1003+
}
9981004

9991005
card->info.broadcast_capable = 1;
10001006
qeth_l2_request_initial_mac(card);

drivers/s390/net/qeth_l3_main.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2281,7 +2281,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
22812281
}
22822282

22832283
if (new_skb->ip_summed == CHECKSUM_PARTIAL) {
2284-
qeth_tx_csum(new_skb, &hdr->hdr.l3.ext_flags);
2284+
qeth_tx_csum(new_skb, &hdr->hdr.l3.ext_flags, ipv);
22852285
if (card->options.performance_stats)
22862286
card->perf_stats.tx_csum++;
22872287
}
@@ -2507,6 +2507,11 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
25072507
card->dev->vlan_features |= NETIF_F_TSO |
25082508
NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
25092509
}
2510+
2511+
if (qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) {
2512+
card->dev->hw_features |= NETIF_F_IPV6_CSUM;
2513+
card->dev->vlan_features |= NETIF_F_IPV6_CSUM;
2514+
}
25102515
} else if (card->info.type == QETH_CARD_TYPE_IQD) {
25112516
card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN,
25122517
ether_setup);

0 commit comments

Comments
 (0)