aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/hyperv
diff options
context:
space:
mode:
authorKY Srinivasan <kys@microsoft.com>2014-03-08 22:23:15 -0500
committerDavid S. Miller <davem@davemloft.net>2014-03-10 15:51:37 -0400
commit4a0e70ae5e3858052f6d91564bf3484f1eb91dc7 (patch)
treead22a782fadd04320ac9ec061036a4f236d39130 /drivers/net/hyperv
parent8a00251a3682a23649cef36949c8019f8589c021 (diff)
Drivers: net: hyperv: Enable offloads on the host
Prior to enabling guest side offloads, enable the offloads on the host. 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>
Diffstat (limited to 'drivers/net/hyperv')
-rw-r--r--drivers/net/hyperv/hyperv_net.h55
-rw-r--r--drivers/net/hyperv/rndis_filter.c80
2 files changed, 135 insertions, 0 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 694bf7cada90..8bc4e766589b 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -721,6 +721,61 @@ struct ndis_pkt_8021q_info {
721 }; 721 };
722}; 722};
723 723
724struct ndis_oject_header {
725 u8 type;
726 u8 revision;
727 u16 size;
728};
729
730#define NDIS_OBJECT_TYPE_DEFAULT 0x80
731#define NDIS_OFFLOAD_PARAMETERS_REVISION_3 3
732#define NDIS_OFFLOAD_PARAMETERS_NO_CHANGE 0
733#define NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED 1
734#define NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED 2
735#define NDIS_OFFLOAD_PARAMETERS_LSOV1_ENABLED 2
736#define NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED 1
737#define NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED 2
738#define NDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED 1
739#define NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED 2
740#define NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED 3
741#define NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED 4
742
743/*
744 * New offload OIDs for NDIS 6
745 */
746#define OID_TCP_OFFLOAD_CURRENT_CONFIG 0xFC01020B /* query only */
747#define OID_TCP_OFFLOAD_PARAMETERS 0xFC01020C /* set only */
748#define OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020D/* query only */
749#define OID_TCP_CONNECTION_OFFLOAD_CURRENT_CONFIG 0xFC01020E /* query only */
750#define OID_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020F /* query */
751#define OID_OFFLOAD_ENCAPSULATION 0x0101010A /* set/query */
752
753struct ndis_offload_params {
754 struct ndis_oject_header header;
755 u8 ip_v4_csum;
756 u8 tcp_ip_v4_csum;
757 u8 udp_ip_v4_csum;
758 u8 tcp_ip_v6_csum;
759 u8 udp_ip_v6_csum;
760 u8 lso_v1;
761 u8 ip_sec_v1;
762 u8 lso_v2_ipv4;
763 u8 lso_v2_ipv6;
764 u8 tcp_connection_ip_v4;
765 u8 tcp_connection_ip_v6;
766 u32 flags;
767 u8 ip_sec_v2;
768 u8 ip_sec_v2_ip_v4;
769 struct {
770 u8 rsc_ip_v4;
771 u8 rsc_ip_v6;
772 };
773 struct {
774 u8 encapsulated_packet_task_offload;
775 u8 encapsulation_types;
776 };
777};
778
724#define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \ 779#define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \
725 sizeof(struct ndis_pkt_8021q_info)) 780 sizeof(struct ndis_pkt_8021q_info))
726 781
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index eaa149950af7..42bfb3a11efd 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -607,6 +607,61 @@ cleanup:
607 return ret; 607 return ret;
608} 608}
609 609
610int rndis_filter_set_offload_params(struct hv_device *hdev,
611 struct ndis_offload_params *req_offloads)
612{
613 struct netvsc_device *nvdev = hv_get_drvdata(hdev);
614 struct rndis_device *rdev = nvdev->extension;
615 struct net_device *ndev = nvdev->ndev;
616 struct rndis_request *request;
617 struct rndis_set_request *set;
618 struct ndis_offload_params *offload_params;
619 struct rndis_set_complete *set_complete;
620 u32 extlen = sizeof(struct ndis_offload_params);
621 int ret, t;
622
623 request = get_rndis_request(rdev, RNDIS_MSG_SET,
624 RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen);
625 if (!request)
626 return -ENOMEM;
627
628 set = &request->request_msg.msg.set_req;
629 set->oid = OID_TCP_OFFLOAD_PARAMETERS;
630 set->info_buflen = extlen;
631 set->info_buf_offset = sizeof(struct rndis_set_request);
632 set->dev_vc_handle = 0;
633
634 offload_params = (struct ndis_offload_params *)((ulong)set +
635 set->info_buf_offset);
636 *offload_params = *req_offloads;
637 offload_params->header.type = NDIS_OBJECT_TYPE_DEFAULT;
638 offload_params->header.revision = NDIS_OFFLOAD_PARAMETERS_REVISION_3;
639 offload_params->header.size = extlen;
640
641 ret = rndis_filter_send_request(rdev, request);
642 if (ret != 0)
643 goto cleanup;
644
645 t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
646 if (t == 0) {
647 netdev_err(ndev, "timeout before we got aOFFLOAD set response...\n");
648 /* can't put_rndis_request, since we may still receive a
649 * send-completion.
650 */
651 return -EBUSY;
652 } else {
653 set_complete = &request->response_msg.msg.set_complete;
654 if (set_complete->status != RNDIS_STATUS_SUCCESS) {
655 netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
656 set_complete->status);
657 ret = -EINVAL;
658 }
659 }
660
661cleanup:
662 put_rndis_request(rdev, request);
663 return ret;
664}
610 665
611static int rndis_filter_query_device_link_status(struct rndis_device *dev) 666static int rndis_filter_query_device_link_status(struct rndis_device *dev)
612{ 667{
@@ -807,6 +862,7 @@ int rndis_filter_device_add(struct hv_device *dev,
807 struct netvsc_device *net_device; 862 struct netvsc_device *net_device;
808 struct rndis_device *rndis_device; 863 struct rndis_device *rndis_device;
809 struct netvsc_device_info *device_info = additional_info; 864 struct netvsc_device_info *device_info = additional_info;
865 struct ndis_offload_params offloads;
810 866
811 rndis_device = get_rndis_device(); 867 rndis_device = get_rndis_device();
812 if (!rndis_device) 868 if (!rndis_device)
@@ -846,6 +902,26 @@ int rndis_filter_device_add(struct hv_device *dev,
846 902
847 memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN); 903 memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);
848 904
905 /* Turn on the offloads; the host supports all of the relevant
906 * offloads.
907 */
908 memset(&offloads, 0, sizeof(struct ndis_offload_params));
909 /* A value of zero means "no change"; now turn on what we
910 * want.
911 */
912 offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
913 offloads.tcp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
914 offloads.udp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
915 offloads.tcp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
916 offloads.udp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
917 offloads.lso_v2_ipv4 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
918
919
920 ret = rndis_filter_set_offload_params(dev, &offloads);
921 if (ret)
922 goto err_dev_remv;
923
924
849 rndis_filter_query_device_link_status(rndis_device); 925 rndis_filter_query_device_link_status(rndis_device);
850 926
851 device_info->link_state = rndis_device->link_state; 927 device_info->link_state = rndis_device->link_state;
@@ -855,6 +931,10 @@ int rndis_filter_device_add(struct hv_device *dev,
855 device_info->link_state ? "down" : "up"); 931 device_info->link_state ? "down" : "up");
856 932
857 return ret; 933 return ret;
934
935err_dev_remv:
936 rndis_filter_device_remove(dev);
937 return ret;
858} 938}
859 939
860void rndis_filter_device_remove(struct hv_device *dev) 940void rndis_filter_device_remove(struct hv_device *dev)