[PATCH V3 3/6] Drivers: net: hyperv: Enable offloads on the host

2014-03-08 Thread K. Y. Srinivasan
Prior to enabling guest side offloads, enable the offloads on the host.

Signed-off-by: K. Y. Srinivasan 
Reviewed-by: Haiyang Zhang 
---
 drivers/net/hyperv/hyperv_net.h   |   55 +
 drivers/net/hyperv/rndis_filter.c |   80 +
 2 files changed, 135 insertions(+), 0 deletions(-)

diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 694bf7c..8bc4e76 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -721,6 +721,61 @@ struct ndis_pkt_8021q_info {
};
 };
 
+struct ndis_oject_header {
+   u8 type;
+   u8 revision;
+   u16 size;
+};
+
+#define NDIS_OBJECT_TYPE_DEFAULT   0x80
+#define NDIS_OFFLOAD_PARAMETERS_REVISION_3 3
+#define NDIS_OFFLOAD_PARAMETERS_NO_CHANGE 0
+#define NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED 1
+#define NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED  2
+#define NDIS_OFFLOAD_PARAMETERS_LSOV1_ENABLED  2
+#define NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED 1
+#define NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED 2
+#define NDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED 1
+#define NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED 2
+#define NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED 3
+#define NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED 4
+
+/*
+ * New offload OIDs for NDIS 6
+ */
+#define OID_TCP_OFFLOAD_CURRENT_CONFIG 0xFC01020B /* query only */
+#define OID_TCP_OFFLOAD_PARAMETERS 0xFC01020C  /* set only */
+#define OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020D/* query only */
+#define OID_TCP_CONNECTION_OFFLOAD_CURRENT_CONFIG 0xFC01020E /* query only */
+#define OID_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020F /* query */
+#define OID_OFFLOAD_ENCAPSULATION 0x0101010A /* set/query */
+
+struct ndis_offload_params {
+   struct ndis_oject_header header;
+   u8 ip_v4_csum;
+   u8 tcp_ip_v4_csum;
+   u8 udp_ip_v4_csum;
+   u8 tcp_ip_v6_csum;
+   u8 udp_ip_v6_csum;
+   u8 lso_v1;
+   u8 ip_sec_v1;
+   u8 lso_v2_ipv4;
+   u8 lso_v2_ipv6;
+   u8 tcp_connection_ip_v4;
+   u8 tcp_connection_ip_v6;
+   u32 flags;
+   u8 ip_sec_v2;
+   u8 ip_sec_v2_ip_v4;
+   struct {
+   u8 rsc_ip_v4;
+   u8 rsc_ip_v6;
+   };
+   struct {
+   u8 encapsulated_packet_task_offload;
+   u8 encapsulation_types;
+   };
+};
+
 #define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
sizeof(struct ndis_pkt_8021q_info))
 
diff --git a/drivers/net/hyperv/rndis_filter.c 
b/drivers/net/hyperv/rndis_filter.c
index dcbf144e..9b02f21 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -627,6 +627,61 @@ cleanup:
return ret;
 }
 
+int rndis_filter_set_offload_params(struct hv_device *hdev,
+   struct ndis_offload_params *req_offloads)
+{
+   struct netvsc_device *nvdev = hv_get_drvdata(hdev);
+   struct rndis_device *rdev = nvdev->extension;
+   struct net_device *ndev = nvdev->ndev;
+   struct rndis_request *request;
+   struct rndis_set_request *set;
+   struct ndis_offload_params *offload_params;
+   struct rndis_set_complete *set_complete;
+   u32 extlen = sizeof(struct ndis_offload_params);
+   int ret, t;
+
+   request = get_rndis_request(rdev, RNDIS_MSG_SET,
+   RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
+   if (!request)
+   return -ENOMEM;
+
+   set = &request->request_msg.msg.set_req;
+   set->oid = OID_TCP_OFFLOAD_PARAMETERS;
+   set->info_buflen = extlen;
+   set->info_buf_offset = sizeof(struct rndis_set_request);
+   set->dev_vc_handle = 0;
+
+   offload_params = (struct ndis_offload_params *)((ulong)set +
+   set->info_buf_offset);
+   *offload_params = *req_offloads;
+   offload_params->header.type = NDIS_OBJECT_TYPE_DEFAULT;
+   offload_params->header.revision = NDIS_OFFLOAD_PARAMETERS_REVISION_3;
+   offload_params->header.size = extlen;
+
+   ret = rndis_filter_send_request(rdev, request);
+   if (ret != 0)
+   goto cleanup;
+
+   t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+   if (t == 0) {
+   netdev_err(ndev, "timeout before we got aOFFLOAD set 
response...\n");
+   /* can't put_rndis_request, since we may still receive a
+* send-completion.
+*/
+   return -EBUSY;
+   } else {
+   set_complete = &request->response_msg.msg.set_complete;
+   if (set_complete->status != RNDIS_STATUS_SUCCESS) {
+   netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
+  set_complete->status);
+   ret = -EINVAL;
+   }
+   }
+
+cleanup:
+   put_rndis_request(rdev, request);
+   return ret;
+}
 
 static int

[PATCH V3 3/6] Drivers: net: hyperv: Enable offloads on the host

2014-03-06 Thread K. Y. Srinivasan
Prior to enabling guest side offloads, enable the offloads on the host.

Signed-off-by: K. Y. Srinivasan 
Reviewed-by: Haiyang Zhang 
---
 drivers/net/hyperv/hyperv_net.h   |   55 +
 drivers/net/hyperv/rndis_filter.c |   80 +
 2 files changed, 135 insertions(+), 0 deletions(-)

diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 694bf7c..8bc4e76 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -721,6 +721,61 @@ struct ndis_pkt_8021q_info {
};
 };
 
+struct ndis_oject_header {
+   u8 type;
+   u8 revision;
+   u16 size;
+};
+
+#define NDIS_OBJECT_TYPE_DEFAULT   0x80
+#define NDIS_OFFLOAD_PARAMETERS_REVISION_3 3
+#define NDIS_OFFLOAD_PARAMETERS_NO_CHANGE 0
+#define NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED 1
+#define NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED  2
+#define NDIS_OFFLOAD_PARAMETERS_LSOV1_ENABLED  2
+#define NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED 1
+#define NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED 2
+#define NDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED 1
+#define NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED 2
+#define NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED 3
+#define NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED 4
+
+/*
+ * New offload OIDs for NDIS 6
+ */
+#define OID_TCP_OFFLOAD_CURRENT_CONFIG 0xFC01020B /* query only */
+#define OID_TCP_OFFLOAD_PARAMETERS 0xFC01020C  /* set only */
+#define OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020D/* query only */
+#define OID_TCP_CONNECTION_OFFLOAD_CURRENT_CONFIG 0xFC01020E /* query only */
+#define OID_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020F /* query */
+#define OID_OFFLOAD_ENCAPSULATION 0x0101010A /* set/query */
+
+struct ndis_offload_params {
+   struct ndis_oject_header header;
+   u8 ip_v4_csum;
+   u8 tcp_ip_v4_csum;
+   u8 udp_ip_v4_csum;
+   u8 tcp_ip_v6_csum;
+   u8 udp_ip_v6_csum;
+   u8 lso_v1;
+   u8 ip_sec_v1;
+   u8 lso_v2_ipv4;
+   u8 lso_v2_ipv6;
+   u8 tcp_connection_ip_v4;
+   u8 tcp_connection_ip_v6;
+   u32 flags;
+   u8 ip_sec_v2;
+   u8 ip_sec_v2_ip_v4;
+   struct {
+   u8 rsc_ip_v4;
+   u8 rsc_ip_v6;
+   };
+   struct {
+   u8 encapsulated_packet_task_offload;
+   u8 encapsulation_types;
+   };
+};
+
 #define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
sizeof(struct ndis_pkt_8021q_info))
 
diff --git a/drivers/net/hyperv/rndis_filter.c 
b/drivers/net/hyperv/rndis_filter.c
index dcbf144e..9b02f21 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -627,6 +627,61 @@ cleanup:
return ret;
 }
 
+int rndis_filter_set_offload_params(struct hv_device *hdev,
+   struct ndis_offload_params *req_offloads)
+{
+   struct netvsc_device *nvdev = hv_get_drvdata(hdev);
+   struct rndis_device *rdev = nvdev->extension;
+   struct net_device *ndev = nvdev->ndev;
+   struct rndis_request *request;
+   struct rndis_set_request *set;
+   struct ndis_offload_params *offload_params;
+   struct rndis_set_complete *set_complete;
+   u32 extlen = sizeof(struct ndis_offload_params);
+   int ret, t;
+
+   request = get_rndis_request(rdev, RNDIS_MSG_SET,
+   RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
+   if (!request)
+   return -ENOMEM;
+
+   set = &request->request_msg.msg.set_req;
+   set->oid = OID_TCP_OFFLOAD_PARAMETERS;
+   set->info_buflen = extlen;
+   set->info_buf_offset = sizeof(struct rndis_set_request);
+   set->dev_vc_handle = 0;
+
+   offload_params = (struct ndis_offload_params *)((ulong)set +
+   set->info_buf_offset);
+   *offload_params = *req_offloads;
+   offload_params->header.type = NDIS_OBJECT_TYPE_DEFAULT;
+   offload_params->header.revision = NDIS_OFFLOAD_PARAMETERS_REVISION_3;
+   offload_params->header.size = extlen;
+
+   ret = rndis_filter_send_request(rdev, request);
+   if (ret != 0)
+   goto cleanup;
+
+   t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
+   if (t == 0) {
+   netdev_err(ndev, "timeout before we got aOFFLOAD set 
response...\n");
+   /* can't put_rndis_request, since we may still receive a
+* send-completion.
+*/
+   return -EBUSY;
+   } else {
+   set_complete = &request->response_msg.msg.set_complete;
+   if (set_complete->status != RNDIS_STATUS_SUCCESS) {
+   netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
+  set_complete->status);
+   ret = -EINVAL;
+   }
+   }
+
+cleanup:
+   put_rndis_request(rdev, request);
+   return ret;
+}
 
 static int