Commit b8812920 authored by David S. Miller's avatar David S. Miller
Browse files


Sasha Levin says:

====================
Hyper-V hv_netvsc commits for 5.0

Three patches from Haiyang Zhang to fix settings hash key using ethtool,
and Adrian Vladu's first patch fixing a few spelling mistakes.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9620d6f6 52d3b494
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -144,6 +144,8 @@ struct hv_netvsc_packet {
	u32 total_data_buflen;
};

#define NETVSC_HASH_KEYLEN 40

struct netvsc_device_info {
	unsigned char mac_adr[ETH_ALEN];
	u32  num_chn;
@@ -151,6 +153,8 @@ struct netvsc_device_info {
	u32  recv_sections;
	u32  send_section_size;
	u32  recv_section_size;

	u8 rss_key[NETVSC_HASH_KEYLEN];
};

enum rndis_device_state {
@@ -160,8 +164,6 @@ enum rndis_device_state {
	RNDIS_DEV_DATAINITIALIZED,
};

#define NETVSC_HASH_KEYLEN 40

struct rndis_device {
	struct net_device *ndev;

@@ -209,7 +211,9 @@ int netvsc_recv_callback(struct net_device *net,
void netvsc_channel_cb(void *context);
int netvsc_poll(struct napi_struct *napi, int budget);

int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev);
int rndis_set_subchannel(struct net_device *ndev,
			 struct netvsc_device *nvdev,
			 struct netvsc_device_info *dev_info);
int rndis_filter_open(struct netvsc_device *nvdev);
int rndis_filter_close(struct netvsc_device *nvdev);
struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
@@ -1177,7 +1181,7 @@ enum ndis_per_pkt_info_type {

enum rndis_per_pkt_info_interal_type {
	RNDIS_PKTINFO_ID = 1,
	/* Add more memebers here */
	/* Add more members here */

	RNDIS_PKTINFO_MAX
};
+2 −2
Original line number Diff line number Diff line
@@ -84,7 +84,7 @@ static void netvsc_subchan_work(struct work_struct *w)

	rdev = nvdev->extension;
	if (rdev) {
		ret = rndis_set_subchannel(rdev->ndev, nvdev);
		ret = rndis_set_subchannel(rdev->ndev, nvdev, NULL);
		if (ret == 0) {
			netif_device_attach(rdev->ndev);
		} else {
@@ -1331,7 +1331,7 @@ void netvsc_channel_cb(void *context)
	prefetch(hv_get_ring_buffer(rbi) + rbi->priv_read_index);

	if (napi_schedule_prep(&nvchan->napi)) {
		/* disable interupts from host */
		/* disable interrupts from host */
		hv_begin_read(rbi);

		__napi_schedule_irqoff(&nvchan->napi);
+92 −53
Original line number Diff line number Diff line
@@ -370,7 +370,7 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len,
{
	int j = 0;

	/* Deal with compund pages by ignoring unused part
	/* Deal with compound pages by ignoring unused part
	 * of the page.
	 */
	page += (offset >> PAGE_SHIFT);
@@ -858,6 +858,39 @@ static void netvsc_get_channels(struct net_device *net,
	}
}

/* Alloc struct netvsc_device_info, and initialize it from either existing
 * struct netvsc_device, or from default values.
 */
static struct netvsc_device_info *netvsc_devinfo_get
			(struct netvsc_device *nvdev)
{
	struct netvsc_device_info *dev_info;

	dev_info = kzalloc(sizeof(*dev_info), GFP_ATOMIC);

	if (!dev_info)
		return NULL;

	if (nvdev) {
		dev_info->num_chn = nvdev->num_chn;
		dev_info->send_sections = nvdev->send_section_cnt;
		dev_info->send_section_size = nvdev->send_section_size;
		dev_info->recv_sections = nvdev->recv_section_cnt;
		dev_info->recv_section_size = nvdev->recv_section_size;

		memcpy(dev_info->rss_key, nvdev->extension->rss_key,
		       NETVSC_HASH_KEYLEN);
	} else {
		dev_info->num_chn = VRSS_CHANNEL_DEFAULT;
		dev_info->send_sections = NETVSC_DEFAULT_TX;
		dev_info->send_section_size = NETVSC_SEND_SECTION_SIZE;
		dev_info->recv_sections = NETVSC_DEFAULT_RX;
		dev_info->recv_section_size = NETVSC_RECV_SECTION_SIZE;
	}

	return dev_info;
}

static int netvsc_detach(struct net_device *ndev,
			 struct netvsc_device *nvdev)
{
@@ -909,7 +942,7 @@ static int netvsc_attach(struct net_device *ndev,
		return PTR_ERR(nvdev);

	if (nvdev->num_chn > 1) {
		ret = rndis_set_subchannel(ndev, nvdev);
		ret = rndis_set_subchannel(ndev, nvdev, dev_info);

		/* if unavailable, just proceed with one queue */
		if (ret) {
@@ -943,7 +976,7 @@ static int netvsc_set_channels(struct net_device *net,
	struct net_device_context *net_device_ctx = netdev_priv(net);
	struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
	unsigned int orig, count = channels->combined_count;
	struct netvsc_device_info device_info;
	struct netvsc_device_info *device_info;
	int ret;

	/* We do not support separate count for rx, tx, or other */
@@ -962,24 +995,26 @@ static int netvsc_set_channels(struct net_device *net,

	orig = nvdev->num_chn;

	memset(&device_info, 0, sizeof(device_info));
	device_info.num_chn = count;
	device_info.send_sections = nvdev->send_section_cnt;
	device_info.send_section_size = nvdev->send_section_size;
	device_info.recv_sections = nvdev->recv_section_cnt;
	device_info.recv_section_size = nvdev->recv_section_size;
	device_info = netvsc_devinfo_get(nvdev);

	if (!device_info)
		return -ENOMEM;

	device_info->num_chn = count;

	ret = netvsc_detach(net, nvdev);
	if (ret)
		return ret;
		goto out;

	ret = netvsc_attach(net, &device_info);
	ret = netvsc_attach(net, device_info);
	if (ret) {
		device_info.num_chn = orig;
		if (netvsc_attach(net, &device_info))
		device_info->num_chn = orig;
		if (netvsc_attach(net, device_info))
			netdev_err(net, "restoring channel setting failed\n");
	}

out:
	kfree(device_info);
	return ret;
}

@@ -1048,48 +1083,45 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
	struct net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev);
	struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
	int orig_mtu = ndev->mtu;
	struct netvsc_device_info device_info;
	struct netvsc_device_info *device_info;
	int ret = 0;

	if (!nvdev || nvdev->destroy)
		return -ENODEV;

	device_info = netvsc_devinfo_get(nvdev);

	if (!device_info)
		return -ENOMEM;

	/* Change MTU of underlying VF netdev first. */
	if (vf_netdev) {
		ret = dev_set_mtu(vf_netdev, mtu);
		if (ret)
			return ret;
			goto out;
	}

	memset(&device_info, 0, sizeof(device_info));
	device_info.num_chn = nvdev->num_chn;
	device_info.send_sections = nvdev->send_section_cnt;
	device_info.send_section_size = nvdev->send_section_size;
	device_info.recv_sections = nvdev->recv_section_cnt;
	device_info.recv_section_size = nvdev->recv_section_size;

	ret = netvsc_detach(ndev, nvdev);
	if (ret)
		goto rollback_vf;

	ndev->mtu = mtu;

	ret = netvsc_attach(ndev, &device_info);
	if (ret)
		goto rollback;

	return 0;
	ret = netvsc_attach(ndev, device_info);
	if (!ret)
		goto out;

rollback:
	/* Attempt rollback to original MTU */
	ndev->mtu = orig_mtu;

	if (netvsc_attach(ndev, &device_info))
	if (netvsc_attach(ndev, device_info))
		netdev_err(ndev, "restoring mtu failed\n");
rollback_vf:
	if (vf_netdev)
		dev_set_mtu(vf_netdev, orig_mtu);

out:
	kfree(device_info);
	return ret;
}

@@ -1674,7 +1706,7 @@ static int netvsc_set_ringparam(struct net_device *ndev,
{
	struct net_device_context *ndevctx = netdev_priv(ndev);
	struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
	struct netvsc_device_info device_info;
	struct netvsc_device_info *device_info;
	struct ethtool_ringparam orig;
	u32 new_tx, new_rx;
	int ret = 0;
@@ -1694,26 +1726,29 @@ static int netvsc_set_ringparam(struct net_device *ndev,
	    new_rx == orig.rx_pending)
		return 0;	 /* no change */

	memset(&device_info, 0, sizeof(device_info));
	device_info.num_chn = nvdev->num_chn;
	device_info.send_sections = new_tx;
	device_info.send_section_size = nvdev->send_section_size;
	device_info.recv_sections = new_rx;
	device_info.recv_section_size = nvdev->recv_section_size;
	device_info = netvsc_devinfo_get(nvdev);

	if (!device_info)
		return -ENOMEM;

	device_info->send_sections = new_tx;
	device_info->recv_sections = new_rx;

	ret = netvsc_detach(ndev, nvdev);
	if (ret)
		return ret;
		goto out;

	ret = netvsc_attach(ndev, &device_info);
	ret = netvsc_attach(ndev, device_info);
	if (ret) {
		device_info.send_sections = orig.tx_pending;
		device_info.recv_sections = orig.rx_pending;
		device_info->send_sections = orig.tx_pending;
		device_info->recv_sections = orig.rx_pending;

		if (netvsc_attach(ndev, &device_info))
		if (netvsc_attach(ndev, device_info))
			netdev_err(ndev, "restoring ringparam failed");
	}

out:
	kfree(device_info);
	return ret;
}

@@ -2088,7 +2123,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
	if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
		return NOTIFY_DONE;

	/* if syntihetic interface is a different namespace,
	/* if synthetic interface is a different namespace,
	 * then move the VF to that namespace; join will be
	 * done again in that context.
	 */
@@ -2167,7 +2202,7 @@ static int netvsc_probe(struct hv_device *dev,
{
	struct net_device *net = NULL;
	struct net_device_context *net_device_ctx;
	struct netvsc_device_info device_info;
	struct netvsc_device_info *device_info = NULL;
	struct netvsc_device *nvdev;
	int ret = -ENOMEM;

@@ -2214,21 +2249,21 @@ static int netvsc_probe(struct hv_device *dev,
	netif_set_real_num_rx_queues(net, 1);

	/* Notify the netvsc driver of the new device */
	memset(&device_info, 0, sizeof(device_info));
	device_info.num_chn = VRSS_CHANNEL_DEFAULT;
	device_info.send_sections = NETVSC_DEFAULT_TX;
	device_info.send_section_size = NETVSC_SEND_SECTION_SIZE;
	device_info.recv_sections = NETVSC_DEFAULT_RX;
	device_info.recv_section_size = NETVSC_RECV_SECTION_SIZE;

	nvdev = rndis_filter_device_add(dev, &device_info);
	device_info = netvsc_devinfo_get(NULL);

	if (!device_info) {
		ret = -ENOMEM;
		goto devinfo_failed;
	}

	nvdev = rndis_filter_device_add(dev, device_info);
	if (IS_ERR(nvdev)) {
		ret = PTR_ERR(nvdev);
		netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
		goto rndis_failed;
	}

	memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
	memcpy(net->dev_addr, device_info->mac_adr, ETH_ALEN);

	/* We must get rtnl lock before scheduling nvdev->subchan_work,
	 * otherwise netvsc_subchan_work() can get rtnl lock first and wait
@@ -2266,12 +2301,16 @@ static int netvsc_probe(struct hv_device *dev,

	list_add(&net_device_ctx->list, &netvsc_dev_list);
	rtnl_unlock();

	kfree(device_info);
	return 0;

register_failed:
	rtnl_unlock();
	rndis_filter_device_remove(dev, nvdev);
rndis_failed:
	kfree(device_info);
devinfo_failed:
	free_percpu(net_device_ctx->vf_stats);
no_stats:
	hv_set_drvdata(dev, NULL);
+27 −9
Original line number Diff line number Diff line
@@ -774,8 +774,8 @@ rndis_filter_set_offload_params(struct net_device *ndev,
	return ret;
}

int rndis_filter_set_rss_param(struct rndis_device *rdev,
			       const u8 *rss_key)
static int rndis_set_rss_param_msg(struct rndis_device *rdev,
				   const u8 *rss_key, u16 flag)
{
	struct net_device *ndev = rdev->ndev;
	struct rndis_request *request;
@@ -804,7 +804,7 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
	rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
	rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
	rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
	rssp->flag = 0;
	rssp->flag = flag;
	rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
			 NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
			 NDIS_HASH_TCP_IPV6;
@@ -829,9 +829,12 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,

	wait_for_completion(&request->wait_event);
	set_complete = &request->response_msg.msg.set_complete;
	if (set_complete->status == RNDIS_STATUS_SUCCESS)
	if (set_complete->status == RNDIS_STATUS_SUCCESS) {
		if (!(flag & NDIS_RSS_PARAM_FLAG_DISABLE_RSS) &&
		    !(flag & NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED))
			memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN);
	else {

	} else {
		netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
			   set_complete->status);
		ret = -EINVAL;
@@ -842,6 +845,16 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
	return ret;
}

int rndis_filter_set_rss_param(struct rndis_device *rdev,
			       const u8 *rss_key)
{
	/* Disable RSS before change */
	rndis_set_rss_param_msg(rdev, rss_key,
				NDIS_RSS_PARAM_FLAG_DISABLE_RSS);

	return rndis_set_rss_param_msg(rdev, rss_key, 0);
}

static int rndis_filter_query_device_link_status(struct rndis_device *dev,
						 struct netvsc_device *net_device)
{
@@ -1121,7 +1134,9 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
 * This breaks overlap of processing the host message for the
 * new primary channel with the initialization of sub-channels.
 */
int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
int rndis_set_subchannel(struct net_device *ndev,
			 struct netvsc_device *nvdev,
			 struct netvsc_device_info *dev_info)
{
	struct nvsp_message *init_packet = &nvdev->channel_init_pkt;
	struct net_device_context *ndev_ctx = netdev_priv(ndev);
@@ -1161,7 +1176,10 @@ int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
	wait_event(nvdev->subchan_open,
		   atomic_read(&nvdev->open_chn) == nvdev->num_chn);

	/* ignore failues from setting rss parameters, still have channels */
	/* ignore failures from setting rss parameters, still have channels */
	if (dev_info)
		rndis_filter_set_rss_param(rdev, dev_info->rss_key);
	else
		rndis_filter_set_rss_param(rdev, netvsc_hash_key);

	netif_set_real_num_tx_queues(ndev, nvdev->num_chn);