aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Blaschka <frank.blaschka@de.ibm.com>2007-08-29 05:26:55 -0400
committerJeff Garzik <jeff@garzik.org>2007-08-31 06:52:58 -0400
commit5a4b61a95a9b742d8a966950d23f386c34a733f2 (patch)
tree76c60e9e5c30304c6434f2eb7365778989ae9bb7
parentecee51b755335d3ff254199fc1a2775ea451eecf (diff)
qeth: Announce tx checksumming for qeth devices in TSO/EDDP mode
TSO requires tx checksumming. For non GSO frames in TSO/EDDP mode we have to manually calculate the checksum. Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com> Signed-off-by: Ursula Braun <braunu@de.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/s390/net/qeth_main.c82
1 files changed, 68 insertions, 14 deletions
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 610d27cfd28b..443cde10353e 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -4555,6 +4555,53 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr,
4555 return elements_needed; 4555 return elements_needed;
4556} 4556}
4557 4557
4558static void qeth_tx_csum(struct sk_buff *skb)
4559{
4560 int tlen;
4561
4562 if (skb->protocol == htons(ETH_P_IP)) {
4563 tlen = ntohs(ip_hdr(skb)->tot_len) - (ip_hdr(skb)->ihl << 2);
4564 switch (ip_hdr(skb)->protocol) {
4565 case IPPROTO_TCP:
4566 tcp_hdr(skb)->check = 0;
4567 tcp_hdr(skb)->check = csum_tcpudp_magic(
4568 ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
4569 tlen, ip_hdr(skb)->protocol,
4570 skb_checksum(skb, skb_transport_offset(skb),
4571 tlen, 0));
4572 break;
4573 case IPPROTO_UDP:
4574 udp_hdr(skb)->check = 0;
4575 udp_hdr(skb)->check = csum_tcpudp_magic(
4576 ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
4577 tlen, ip_hdr(skb)->protocol,
4578 skb_checksum(skb, skb_transport_offset(skb),
4579 tlen, 0));
4580 break;
4581 }
4582 } else if (skb->protocol == htons(ETH_P_IPV6)) {
4583 switch (ipv6_hdr(skb)->nexthdr) {
4584 case IPPROTO_TCP:
4585 tcp_hdr(skb)->check = 0;
4586 tcp_hdr(skb)->check = csum_ipv6_magic(
4587 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
4588 ipv6_hdr(skb)->payload_len,
4589 ipv6_hdr(skb)->nexthdr,
4590 skb_checksum(skb, skb_transport_offset(skb),
4591 ipv6_hdr(skb)->payload_len, 0));
4592 break;
4593 case IPPROTO_UDP:
4594 udp_hdr(skb)->check = 0;
4595 udp_hdr(skb)->check = csum_ipv6_magic(
4596 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
4597 ipv6_hdr(skb)->payload_len,
4598 ipv6_hdr(skb)->nexthdr,
4599 skb_checksum(skb, skb_transport_offset(skb),
4600 ipv6_hdr(skb)->payload_len, 0));
4601 break;
4602 }
4603 }
4604}
4558 4605
4559static int 4606static int
4560qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) 4607qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
@@ -4640,6 +4687,10 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
4640 elements_needed += elems; 4687 elements_needed += elems;
4641 } 4688 }
4642 4689
4690 if ((large_send == QETH_LARGE_SEND_NO) &&
4691 (skb->ip_summed == CHECKSUM_PARTIAL))
4692 qeth_tx_csum(new_skb);
4693
4643 if (card->info.type != QETH_CARD_TYPE_IQD) 4694 if (card->info.type != QETH_CARD_TYPE_IQD)
4644 rc = qeth_do_send_packet(card, queue, new_skb, hdr, 4695 rc = qeth_do_send_packet(card, queue, new_skb, hdr,
4645 elements_needed, ctx); 4696 elements_needed, ctx);
@@ -6387,20 +6438,18 @@ qeth_deregister_addr_entry(struct qeth_card *card, struct qeth_ipaddr *addr)
6387static u32 6438static u32
6388qeth_ethtool_get_tx_csum(struct net_device *dev) 6439qeth_ethtool_get_tx_csum(struct net_device *dev)
6389{ 6440{
6390 /* We may need to say that we support tx csum offload if 6441 return (dev->features & NETIF_F_HW_CSUM) != 0;
6391 * we do EDDP or TSO. There are discussions going on to
6392 * enforce rules in the stack and in ethtool that make
6393 * SG and TSO depend on HW_CSUM. At the moment there are
6394 * no such rules....
6395 * If we say yes here, we have to checksum outbound packets
6396 * any time. */
6397 return 0;
6398} 6442}
6399 6443
6400static int 6444static int
6401qeth_ethtool_set_tx_csum(struct net_device *dev, u32 data) 6445qeth_ethtool_set_tx_csum(struct net_device *dev, u32 data)
6402{ 6446{
6403 return -EINVAL; 6447 if (data)
6448 dev->features |= NETIF_F_HW_CSUM;
6449 else
6450 dev->features &= ~NETIF_F_HW_CSUM;
6451
6452 return 0;
6404} 6453}
6405 6454
6406static u32 6455static u32
@@ -7414,7 +7463,8 @@ qeth_start_ipa_tso(struct qeth_card *card)
7414 } 7463 }
7415 if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)){ 7464 if (rc && (card->options.large_send == QETH_LARGE_SEND_TSO)){
7416 card->options.large_send = QETH_LARGE_SEND_NO; 7465 card->options.large_send = QETH_LARGE_SEND_NO;
7417 card->dev->features &= ~ (NETIF_F_TSO | NETIF_F_SG); 7466 card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
7467 NETIF_F_HW_CSUM);
7418 } 7468 }
7419 return rc; 7469 return rc;
7420} 7470}
@@ -7554,22 +7604,26 @@ qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
7554 card->options.large_send = type; 7604 card->options.large_send = type;
7555 switch (card->options.large_send) { 7605 switch (card->options.large_send) {
7556 case QETH_LARGE_SEND_EDDP: 7606 case QETH_LARGE_SEND_EDDP:
7557 card->dev->features |= NETIF_F_TSO | NETIF_F_SG; 7607 card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
7608 NETIF_F_HW_CSUM;
7558 break; 7609 break;
7559 case QETH_LARGE_SEND_TSO: 7610 case QETH_LARGE_SEND_TSO:
7560 if (qeth_is_supported(card, IPA_OUTBOUND_TSO)){ 7611 if (qeth_is_supported(card, IPA_OUTBOUND_TSO)){
7561 card->dev->features |= NETIF_F_TSO | NETIF_F_SG; 7612 card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
7613 NETIF_F_HW_CSUM;
7562 } else { 7614 } else {
7563 PRINT_WARN("TSO not supported on %s. " 7615 PRINT_WARN("TSO not supported on %s. "
7564 "large_send set to 'no'.\n", 7616 "large_send set to 'no'.\n",
7565 card->dev->name); 7617 card->dev->name);
7566 card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); 7618 card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
7619 NETIF_F_HW_CSUM);
7567 card->options.large_send = QETH_LARGE_SEND_NO; 7620 card->options.large_send = QETH_LARGE_SEND_NO;
7568 rc = -EOPNOTSUPP; 7621 rc = -EOPNOTSUPP;
7569 } 7622 }
7570 break; 7623 break;
7571 default: /* includes QETH_LARGE_SEND_NO */ 7624 default: /* includes QETH_LARGE_SEND_NO */
7572 card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); 7625 card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
7626 NETIF_F_HW_CSUM);
7573 break; 7627 break;
7574 } 7628 }
7575 if (card->state == CARD_STATE_UP) 7629 if (card->state == CARD_STATE_UP)