mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-05-01 07:50:23 +02:00
linux: Backport Hyper-V network driver
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
From a4ec4f58017b456281ee17c35fb82dfe4eab2193 Mon Sep 17 00:00:00 2001
|
||||
From: KY Srinivasan <kys@microsoft.com>
|
||||
Date: Sat, 8 Mar 2014 19:23:18 -0800
|
||||
Subject: [PATCH 10/25] Drivers: net: hyperv: Enable large send offload
|
||||
|
||||
Enable segmentation offload.
|
||||
|
||||
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
|
||||
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/hyperv/hyperv_net.h | 40 ++++++++++++++++++++++++++++++++++++++++
|
||||
drivers/net/hyperv/netvsc_drv.c | 38 ++++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 74 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
|
||||
index 4cf238234321..7d06b4959383 100644
|
||||
--- a/drivers/net/hyperv/hyperv_net.h
|
||||
+++ b/drivers/net/hyperv/hyperv_net.h
|
||||
@@ -742,6 +742,10 @@ struct ndis_oject_header {
|
||||
#define NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED 3
|
||||
#define NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED 4
|
||||
|
||||
+#define NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE 1
|
||||
+#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4 0
|
||||
+#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6 1
|
||||
+
|
||||
/*
|
||||
* New offload OIDs for NDIS 6
|
||||
*/
|
||||
@@ -804,12 +808,48 @@ struct ndis_tcp_ip_checksum_info {
|
||||
};
|
||||
};
|
||||
|
||||
+struct ndis_tcp_lso_info {
|
||||
+ union {
|
||||
+ struct {
|
||||
+ u32 unused:30;
|
||||
+ u32 type:1;
|
||||
+ u32 reserved2:1;
|
||||
+ } transmit;
|
||||
+ struct {
|
||||
+ u32 mss:20;
|
||||
+ u32 tcp_header_offset:10;
|
||||
+ u32 type:1;
|
||||
+ u32 reserved2:1;
|
||||
+ } lso_v1_transmit;
|
||||
+ struct {
|
||||
+ u32 tcp_payload:30;
|
||||
+ u32 type:1;
|
||||
+ u32 reserved2:1;
|
||||
+ } lso_v1_transmit_complete;
|
||||
+ struct {
|
||||
+ u32 mss:20;
|
||||
+ u32 tcp_header_offset:10;
|
||||
+ u32 type:1;
|
||||
+ u32 ip_version:1;
|
||||
+ } lso_v2_transmit;
|
||||
+ struct {
|
||||
+ u32 reserved:30;
|
||||
+ u32 type:1;
|
||||
+ u32 reserved2:1;
|
||||
+ } lso_v2_transmit_complete;
|
||||
+ u32 value;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
#define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
|
||||
sizeof(struct ndis_pkt_8021q_info))
|
||||
|
||||
#define NDIS_CSUM_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
|
||||
sizeof(struct ndis_tcp_ip_checksum_info))
|
||||
|
||||
+#define NDIS_LSO_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
|
||||
+ sizeof(struct ndis_tcp_lso_info))
|
||||
+
|
||||
/* Format of Information buffer passed in a SetRequest for the OID */
|
||||
/* OID_GEN_RNDIS_CONFIG_PARAMETER. */
|
||||
struct rndis_config_parameter_info {
|
||||
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
||||
index 2fab69ac61ef..5baa1fa7e692 100644
|
||||
--- a/drivers/net/hyperv/netvsc_drv.c
|
||||
+++ b/drivers/net/hyperv/netvsc_drv.c
|
||||
@@ -299,6 +299,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
bool isvlan;
|
||||
struct rndis_per_packet_info *ppi;
|
||||
struct ndis_tcp_ip_checksum_info *csum_info;
|
||||
+ struct ndis_tcp_lso_info *lso_info;
|
||||
int hdr_offset;
|
||||
u32 net_trans_info;
|
||||
|
||||
@@ -378,7 +379,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
* GSO packet.
|
||||
*/
|
||||
if (skb_is_gso(skb))
|
||||
- goto do_send;
|
||||
+ goto do_lso;
|
||||
|
||||
rndis_msg_size += NDIS_CSUM_PPI_SIZE;
|
||||
ppi = init_ppi_data(rndis_msg, NDIS_CSUM_PPI_SIZE,
|
||||
@@ -398,6 +399,35 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
|
||||
} else if (net_trans_info & INFO_UDP) {
|
||||
csum_info->transmit.udp_checksum = 1;
|
||||
}
|
||||
+ goto do_send;
|
||||
+
|
||||
+do_lso:
|
||||
+ rndis_msg_size += NDIS_LSO_PPI_SIZE;
|
||||
+ ppi = init_ppi_data(rndis_msg, NDIS_LSO_PPI_SIZE,
|
||||
+ TCP_LARGESEND_PKTINFO);
|
||||
+
|
||||
+ lso_info = (struct ndis_tcp_lso_info *)((void *)ppi +
|
||||
+ ppi->ppi_offset);
|
||||
+
|
||||
+ lso_info->lso_v2_transmit.type = NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE;
|
||||
+ if (net_trans_info & (INFO_IPV4 << 16)) {
|
||||
+ lso_info->lso_v2_transmit.ip_version =
|
||||
+ NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4;
|
||||
+ ip_hdr(skb)->tot_len = 0;
|
||||
+ ip_hdr(skb)->check = 0;
|
||||
+ tcp_hdr(skb)->check =
|
||||
+ ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
|
||||
+ ip_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
|
||||
+ } else {
|
||||
+ lso_info->lso_v2_transmit.ip_version =
|
||||
+ NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6;
|
||||
+ ipv6_hdr(skb)->payload_len = 0;
|
||||
+ tcp_hdr(skb)->check =
|
||||
+ ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
|
||||
+ &ipv6_hdr(skb)->daddr, 0, IPPROTO_TCP, 0);
|
||||
+ }
|
||||
+ lso_info->lso_v2_transmit.tcp_header_offset = hdr_offset;
|
||||
+ lso_info->lso_v2_transmit.mss = skb_shinfo(skb)->gso_size;
|
||||
|
||||
do_send:
|
||||
/* Start filling in the page buffers with the rndis hdr */
|
||||
@@ -655,10 +685,10 @@ static int netvsc_probe(struct hv_device *dev,
|
||||
|
||||
net->netdev_ops = &device_ops;
|
||||
|
||||
- /* TODO: Add GSO and Checksum offload */
|
||||
- net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM;
|
||||
+ net->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM |
|
||||
+ NETIF_F_TSO;
|
||||
net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_RXCSUM |
|
||||
- NETIF_F_IP_CSUM;
|
||||
+ NETIF_F_IP_CSUM | NETIF_F_TSO;
|
||||
|
||||
SET_ETHTOOL_OPS(net, ðtool_ops);
|
||||
SET_NETDEV_DEV(net, &dev->device);
|
||||
--
|
||||
2.4.3
|
||||
|
||||
Reference in New Issue
Block a user