Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4a0e70ae authored by KY Srinivasan's avatar KY Srinivasan Committed by David S. Miller
Browse files

Drivers: net: hyperv: Enable offloads on the host



Prior to enabling guest side offloads, enable the offloads on the host.

Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8a00251a
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
@@ -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))

+80 −0
Original line number Diff line number Diff line
@@ -607,6 +607,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 rndis_filter_query_device_link_status(struct rndis_device *dev)
{
@@ -807,6 +862,7 @@ int rndis_filter_device_add(struct hv_device *dev,
	struct netvsc_device *net_device;
	struct rndis_device *rndis_device;
	struct netvsc_device_info *device_info = additional_info;
	struct ndis_offload_params offloads;

	rndis_device = get_rndis_device();
	if (!rndis_device)
@@ -846,6 +902,26 @@ int rndis_filter_device_add(struct hv_device *dev,

	memcpy(device_info->mac_adr, rndis_device->hw_mac_adr, ETH_ALEN);

	/* Turn on the offloads; the host supports all of the relevant
	 * offloads.
	 */
	memset(&offloads, 0, sizeof(struct ndis_offload_params));
	/* A value of zero means "no change"; now turn on what we
	 * want.
	 */
	offloads.ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
	offloads.tcp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
	offloads.udp_ip_v4_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
	offloads.tcp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
	offloads.udp_ip_v6_csum = NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
	offloads.lso_v2_ipv4 = NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;


	ret = rndis_filter_set_offload_params(dev, &offloads);
	if (ret)
		goto err_dev_remv;


	rndis_filter_query_device_link_status(rndis_device);

	device_info->link_state = rndis_device->link_state;
@@ -855,6 +931,10 @@ int rndis_filter_device_add(struct hv_device *dev,
		 device_info->link_state ? "down" : "up");

	return ret;

err_dev_remv:
	rndis_filter_device_remove(dev);
	return ret;
}

void rndis_filter_device_remove(struct hv_device *dev)