]>
Commit | Line | Data |
---|---|---|
a7b0967d MT |
1 | From 6b15b5f37e976a5f3840c7ea59560e10c6251250 Mon Sep 17 00:00:00 2001 |
2 | From: KY Srinivasan <kys@microsoft.com> | |
3 | Date: Sat, 8 Mar 2014 19:23:15 -0800 | |
4 | Subject: [PATCH 07/25] Drivers: net: hyperv: Enable offloads on the host | |
5 | ||
6 | Prior to enabling guest side offloads, enable the offloads on the host. | |
7 | ||
8 | Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> | |
9 | Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com> | |
10 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
11 | --- | |
12 | drivers/net/hyperv/hyperv_net.h | 55 +++++++++++++++++++++++++++ | |
13 | drivers/net/hyperv/rndis_filter.c | 80 +++++++++++++++++++++++++++++++++++++++ | |
14 | 2 files changed, 135 insertions(+) | |
15 | ||
16 | diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h | |
17 | index 694bf7cada90..8bc4e766589b 100644 | |
18 | --- a/drivers/net/hyperv/hyperv_net.h | |
19 | +++ b/drivers/net/hyperv/hyperv_net.h | |
20 | @@ -721,6 +721,61 @@ struct ndis_pkt_8021q_info { | |
21 | }; | |
22 | }; | |
23 | ||
24 | +struct ndis_oject_header { | |
25 | + u8 type; | |
26 | + u8 revision; | |
27 | + u16 size; | |
28 | +}; | |
29 | + | |
30 | +#define NDIS_OBJECT_TYPE_DEFAULT 0x80 | |
31 | +#define NDIS_OFFLOAD_PARAMETERS_REVISION_3 3 | |
32 | +#define NDIS_OFFLOAD_PARAMETERS_NO_CHANGE 0 | |
33 | +#define NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED 1 | |
34 | +#define NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED 2 | |
35 | +#define NDIS_OFFLOAD_PARAMETERS_LSOV1_ENABLED 2 | |
36 | +#define NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED 1 | |
37 | +#define NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED 2 | |
38 | +#define NDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED 1 | |
39 | +#define NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED 2 | |
40 | +#define NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED 3 | |
41 | +#define NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED 4 | |
42 | + | |
43 | +/* | |
44 | + * New offload OIDs for NDIS 6 | |
45 | + */ | |
46 | +#define OID_TCP_OFFLOAD_CURRENT_CONFIG 0xFC01020B /* query only */ | |
47 | +#define OID_TCP_OFFLOAD_PARAMETERS 0xFC01020C /* set only */ | |
48 | +#define OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020D/* query only */ | |
49 | +#define OID_TCP_CONNECTION_OFFLOAD_CURRENT_CONFIG 0xFC01020E /* query only */ | |
50 | +#define OID_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020F /* query */ | |
51 | +#define OID_OFFLOAD_ENCAPSULATION 0x0101010A /* set/query */ | |
52 | + | |
53 | +struct ndis_offload_params { | |
54 | + struct ndis_oject_header header; | |
55 | + u8 ip_v4_csum; | |
56 | + u8 tcp_ip_v4_csum; | |
57 | + u8 udp_ip_v4_csum; | |
58 | + u8 tcp_ip_v6_csum; | |
59 | + u8 udp_ip_v6_csum; | |
60 | + u8 lso_v1; | |
61 | + u8 ip_sec_v1; | |
62 | + u8 lso_v2_ipv4; | |
63 | + u8 lso_v2_ipv6; | |
64 | + u8 tcp_connection_ip_v4; | |
65 | + u8 tcp_connection_ip_v6; | |
66 | + u32 flags; | |
67 | + u8 ip_sec_v2; | |
68 | + u8 ip_sec_v2_ip_v4; | |
69 | + struct { | |
70 | + u8 rsc_ip_v4; | |
71 | + u8 rsc_ip_v6; | |
72 | + }; | |
73 | + struct { | |
74 | + u8 encapsulated_packet_task_offload; | |
75 | + u8 encapsulation_types; | |
76 | + }; | |
77 | +}; | |
78 | + | |
79 | #define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \ | |
80 | sizeof(struct ndis_pkt_8021q_info)) | |
81 | ||
82 | diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c | |
83 | index dcbf144ea7da..9b02f21097a7 100644 | |
84 | --- a/drivers/net/hyperv/rndis_filter.c | |
85 | +++ b/drivers/net/hyperv/rndis_filter.c | |
86 | @@ -627,6 +627,61 @@ cleanup: | |
87 | return ret; | |
88 | } | |
89 | ||
90 | +int rndis_filter_set_offload_params(struct hv_device *hdev, | |
91 | + struct ndis_offload_params *req_offloads) | |
92 | +{ | |
93 | + struct netvsc_device *nvdev = hv_get_drvdata(hdev); | |
94 | + struct rndis_device *rdev = nvdev->extension; | |
95 | + struct net_device *ndev = nvdev->ndev; | |
96 | + struct rndis_request *request; | |
97 | + struct rndis_set_request *set; | |
98 | + struct ndis_offload_params *offload_params; | |
99 | + struct rndis_set_complete *set_complete; | |
100 | + u32 extlen = sizeof(struct ndis_offload_params); | |
101 | + int ret, t; | |
102 | + | |
103 | + request = get_rndis_request(rdev, RNDIS_MSG_SET, | |
104 | + RNDIS_MESSAGE_SIZE(struct rndis_set_request) + extlen); | |
105 | + if (!request) | |
106 | + return -ENOMEM; | |
107 | + | |
108 | + set = &request->request_msg.msg.set_req; | |
109 | + set->oid = OID_TCP_OFFLOAD_PARAMETERS; | |
110 | + set->info_buflen = extlen; | |
111 | + set->info_buf_offset = sizeof(struct rndis_set_request); | |
112 | + set->dev_vc_handle = 0; | |
113 | + | |
114 | + offload_params = (struct ndis_offload_params *)((ulong)set + | |
115 | + set->info_buf_offset); | |
116 | + *offload_params = *req_offloads; | |
117 | + offload_params->header.type = NDIS_OBJECT_TYPE_DEFAULT; | |
118 | + offload_params->header.revision = NDIS_OFFLOAD_PARAMETERS_REVISION_3; | |
119 | + offload_params->header.size = extlen; | |
120 | + | |
121 | + ret = rndis_filter_send_request(rdev, request); | |
122 | + if (ret != 0) | |
123 | + goto cleanup; | |
124 | + | |
125 | + t = wait_for_completion_timeout(&request->wait_event, 5*HZ); | |
126 | + if (t == 0) { | |
127 | + netdev_err(ndev, "timeout before we got aOFFLOAD set response...\n"); | |
128 | + /* can't put_rndis_request, since we may still receive a | |
129 | + * send-completion. | |
130 | + */ | |
131 | + return -EBUSY; | |
132 | + } else { | |
133 | + set_complete = &request->response_msg.msg.set_complete; | |
134 | + if (set_complete->status != RNDIS_STATUS_SUCCESS) { | |
135 | + netdev_err(ndev, "Fail to set MAC on host side:0x%x\n", | |
136 | + set_complete->status); | |
137 | + ret = -EINVAL; | |
138 | + } | |
139 | + } | |
140 | + | |
141 | +cleanup: | |
142 | + put_rndis_request(rdev, request); | |
143 | + return ret; | |
144 | +} | |
145 | ||
146 | static int rndis_filter_query_device_link_status(struct rndis_device *dev) | |
147 | { | |
148 | @@ -826,6 +881,7 @@ int rndis_filter_device_add(struct hv_device *dev, | |
149 | struct netvsc_device *net_device; | |
150 | struct rndis_device *rndis_device; | |
151 | struct netvsc_device_info *device_info = additional_info; | |
152 | + struct ndis_offload_params offloads; | |
153 | ||
154 | rndis_device = get_rndis_device(); | |
155 | if (!rndis_device) | |
156 | @@ -865,6 +921,26 @@ int rndis_filter_device_add(struct hv_device *dev, | |
157 | ||
158 | memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN); | |
159 | ||
160 | + /* Turn on the offloads; the host supports all of the relevant | |
161 | + * offloads. | |
162 | + */ | |
163 | + memset(&offloads, 0, sizeof(struct ndis_offload_params)); | |
164 | + /* A value of zero means "no change"; now turn on what we | |
165 | + * want. | |
166 | + */ | |
167 | + offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED; | |
168 | + offloads.tcp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED; | |
169 | + offloads.udp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED; | |
170 | + offloads.tcp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED; | |
171 | + offloads.udp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED; | |
172 | + offloads.lso_v2_ipv4 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED; | |
173 | + | |
174 | + | |
175 | + ret = rndis_filter_set_offload_params(dev, &offloads); | |
176 | + if (ret) | |
177 | + goto err_dev_remv; | |
178 | + | |
179 | + | |
180 | rndis_filter_query_device_link_status(rndis_device); | |
181 | ||
182 | device_info->link_state = rndis_device->link_state; | |
183 | @@ -874,6 +950,10 @@ int rndis_filter_device_add(struct hv_device *dev, | |
184 | device_info->link_state ? "down" : "up"); | |
185 | ||
186 | return ret; | |
187 | + | |
188 | +err_dev_remv: | |
189 | + rndis_filter_device_remove(dev); | |
190 | + return ret; | |
191 | } | |
192 | ||
193 | void rndis_filter_device_remove(struct hv_device *dev) | |
194 | -- | |
195 | 2.4.3 | |
196 |