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

Merge tag 'hyperv-fixes-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux

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
...@@ -144,6 +144,8 @@ struct hv_netvsc_packet { ...@@ -144,6 +144,8 @@ struct hv_netvsc_packet {
u32 total_data_buflen; u32 total_data_buflen;
}; };
#define NETVSC_HASH_KEYLEN 40
struct netvsc_device_info { struct netvsc_device_info {
unsigned char mac_adr[ETH_ALEN]; unsigned char mac_adr[ETH_ALEN];
u32 num_chn; u32 num_chn;
...@@ -151,6 +153,8 @@ struct netvsc_device_info { ...@@ -151,6 +153,8 @@ struct netvsc_device_info {
u32 recv_sections; u32 recv_sections;
u32 send_section_size; u32 send_section_size;
u32 recv_section_size; u32 recv_section_size;
u8 rss_key[NETVSC_HASH_KEYLEN];
}; };
enum rndis_device_state { enum rndis_device_state {
...@@ -160,8 +164,6 @@ enum rndis_device_state { ...@@ -160,8 +164,6 @@ enum rndis_device_state {
RNDIS_DEV_DATAINITIALIZED, RNDIS_DEV_DATAINITIALIZED,
}; };
#define NETVSC_HASH_KEYLEN 40
struct rndis_device { struct rndis_device {
struct net_device *ndev; struct net_device *ndev;
...@@ -209,7 +211,9 @@ int netvsc_recv_callback(struct net_device *net, ...@@ -209,7 +211,9 @@ int netvsc_recv_callback(struct net_device *net,
void netvsc_channel_cb(void *context); void netvsc_channel_cb(void *context);
int netvsc_poll(struct napi_struct *napi, int budget); 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_open(struct netvsc_device *nvdev);
int rndis_filter_close(struct netvsc_device *nvdev); int rndis_filter_close(struct netvsc_device *nvdev);
struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
...@@ -1177,7 +1181,7 @@ enum ndis_per_pkt_info_type { ...@@ -1177,7 +1181,7 @@ enum ndis_per_pkt_info_type {
enum rndis_per_pkt_info_interal_type { enum rndis_per_pkt_info_interal_type {
RNDIS_PKTINFO_ID = 1, RNDIS_PKTINFO_ID = 1,
/* Add more memebers here */ /* Add more members here */
RNDIS_PKTINFO_MAX RNDIS_PKTINFO_MAX
}; };
......
...@@ -84,7 +84,7 @@ static void netvsc_subchan_work(struct work_struct *w) ...@@ -84,7 +84,7 @@ static void netvsc_subchan_work(struct work_struct *w)
rdev = nvdev->extension; rdev = nvdev->extension;
if (rdev) { if (rdev) {
ret = rndis_set_subchannel(rdev->ndev, nvdev); ret = rndis_set_subchannel(rdev->ndev, nvdev, NULL);
if (ret == 0) { if (ret == 0) {
netif_device_attach(rdev->ndev); netif_device_attach(rdev->ndev);
} else { } else {
...@@ -1331,7 +1331,7 @@ void netvsc_channel_cb(void *context) ...@@ -1331,7 +1331,7 @@ void netvsc_channel_cb(void *context)
prefetch(hv_get_ring_buffer(rbi) + rbi->priv_read_index); prefetch(hv_get_ring_buffer(rbi) + rbi->priv_read_index);
if (napi_schedule_prep(&nvchan->napi)) { if (napi_schedule_prep(&nvchan->napi)) {
/* disable interupts from host */ /* disable interrupts from host */
hv_begin_read(rbi); hv_begin_read(rbi);
__napi_schedule_irqoff(&nvchan->napi); __napi_schedule_irqoff(&nvchan->napi);
......
...@@ -370,7 +370,7 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len, ...@@ -370,7 +370,7 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len,
{ {
int j = 0; int j = 0;
/* Deal with compund pages by ignoring unused part /* Deal with compound pages by ignoring unused part
* of the page. * of the page.
*/ */
page += (offset >> PAGE_SHIFT); page += (offset >> PAGE_SHIFT);
...@@ -858,6 +858,39 @@ static void netvsc_get_channels(struct net_device *net, ...@@ -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, static int netvsc_detach(struct net_device *ndev,
struct netvsc_device *nvdev) struct netvsc_device *nvdev)
{ {
...@@ -909,7 +942,7 @@ static int netvsc_attach(struct net_device *ndev, ...@@ -909,7 +942,7 @@ static int netvsc_attach(struct net_device *ndev,
return PTR_ERR(nvdev); return PTR_ERR(nvdev);
if (nvdev->num_chn > 1) { 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 unavailable, just proceed with one queue */
if (ret) { if (ret) {
...@@ -943,7 +976,7 @@ static int netvsc_set_channels(struct net_device *net, ...@@ -943,7 +976,7 @@ static int netvsc_set_channels(struct net_device *net,
struct net_device_context *net_device_ctx = netdev_priv(net); struct net_device_context *net_device_ctx = netdev_priv(net);
struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev); struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
unsigned int orig, count = channels->combined_count; unsigned int orig, count = channels->combined_count;
struct netvsc_device_info device_info; struct netvsc_device_info *device_info;
int ret; int ret;
/* We do not support separate count for rx, tx, or other */ /* We do not support separate count for rx, tx, or other */
...@@ -962,24 +995,26 @@ static int netvsc_set_channels(struct net_device *net, ...@@ -962,24 +995,26 @@ static int netvsc_set_channels(struct net_device *net,
orig = nvdev->num_chn; orig = nvdev->num_chn;
memset(&device_info, 0, sizeof(device_info)); device_info = netvsc_devinfo_get(nvdev);
device_info.num_chn = count;
device_info.send_sections = nvdev->send_section_cnt; if (!device_info)
device_info.send_section_size = nvdev->send_section_size; return -ENOMEM;
device_info.recv_sections = nvdev->recv_section_cnt;
device_info.recv_section_size = nvdev->recv_section_size; device_info->num_chn = count;
ret = netvsc_detach(net, nvdev); ret = netvsc_detach(net, nvdev);
if (ret) if (ret)
return ret; goto out;
ret = netvsc_attach(net, &device_info); ret = netvsc_attach(net, device_info);
if (ret) { if (ret) {
device_info.num_chn = orig; device_info->num_chn = orig;
if (netvsc_attach(net, &device_info)) if (netvsc_attach(net, device_info))
netdev_err(net, "restoring channel setting failed\n"); netdev_err(net, "restoring channel setting failed\n");
} }
out:
kfree(device_info);
return ret; return ret;
} }
...@@ -1048,48 +1083,45 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) ...@@ -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 net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev);
struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev); struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
int orig_mtu = ndev->mtu; int orig_mtu = ndev->mtu;
struct netvsc_device_info device_info; struct netvsc_device_info *device_info;
int ret = 0; int ret = 0;
if (!nvdev || nvdev->destroy) if (!nvdev || nvdev->destroy)
return -ENODEV; return -ENODEV;
device_info = netvsc_devinfo_get(nvdev);
if (!device_info)
return -ENOMEM;
/* Change MTU of underlying VF netdev first. */ /* Change MTU of underlying VF netdev first. */
if (vf_netdev) { if (vf_netdev) {
ret = dev_set_mtu(vf_netdev, mtu); ret = dev_set_mtu(vf_netdev, mtu);
if (ret) 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); ret = netvsc_detach(ndev, nvdev);
if (ret) if (ret)
goto rollback_vf; goto rollback_vf;
ndev->mtu = mtu; ndev->mtu = mtu;
ret = netvsc_attach(ndev, &device_info); ret = netvsc_attach(ndev, device_info);
if (ret) if (!ret)
goto rollback; goto out;
return 0;
rollback:
/* Attempt rollback to original MTU */ /* Attempt rollback to original MTU */
ndev->mtu = orig_mtu; ndev->mtu = orig_mtu;
if (netvsc_attach(ndev, &device_info)) if (netvsc_attach(ndev, device_info))
netdev_err(ndev, "restoring mtu failed\n"); netdev_err(ndev, "restoring mtu failed\n");
rollback_vf: rollback_vf:
if (vf_netdev) if (vf_netdev)
dev_set_mtu(vf_netdev, orig_mtu); dev_set_mtu(vf_netdev, orig_mtu);
out:
kfree(device_info);
return ret; return ret;
} }
...@@ -1674,7 +1706,7 @@ static int netvsc_set_ringparam(struct net_device *ndev, ...@@ -1674,7 +1706,7 @@ static int netvsc_set_ringparam(struct net_device *ndev,
{ {
struct net_device_context *ndevctx = netdev_priv(ndev); struct net_device_context *ndevctx = netdev_priv(ndev);
struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev); struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
struct netvsc_device_info device_info; struct netvsc_device_info *device_info;
struct ethtool_ringparam orig; struct ethtool_ringparam orig;
u32 new_tx, new_rx; u32 new_tx, new_rx;
int ret = 0; int ret = 0;
...@@ -1694,26 +1726,29 @@ static int netvsc_set_ringparam(struct net_device *ndev, ...@@ -1694,26 +1726,29 @@ static int netvsc_set_ringparam(struct net_device *ndev,
new_rx == orig.rx_pending) new_rx == orig.rx_pending)
return 0; /* no change */ return 0; /* no change */
memset(&device_info, 0, sizeof(device_info)); device_info = netvsc_devinfo_get(nvdev);
device_info.num_chn = nvdev->num_chn;
device_info.send_sections = new_tx; if (!device_info)
device_info.send_section_size = nvdev->send_section_size; return -ENOMEM;
device_info.recv_sections = new_rx;
device_info.recv_section_size = nvdev->recv_section_size; device_info->send_sections = new_tx;
device_info->recv_sections = new_rx;
ret = netvsc_detach(ndev, nvdev); ret = netvsc_detach(ndev, nvdev);
if (ret) if (ret)
return ret; goto out;
ret = netvsc_attach(ndev, &device_info); ret = netvsc_attach(ndev, device_info);
if (ret) { if (ret) {
device_info.send_sections = orig.tx_pending; device_info->send_sections = orig.tx_pending;
device_info.recv_sections = orig.rx_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"); netdev_err(ndev, "restoring ringparam failed");
} }
out:
kfree(device_info);
return ret; return ret;
} }
...@@ -2088,7 +2123,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev) ...@@ -2088,7 +2123,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev)) if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
return NOTIFY_DONE; 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 * then move the VF to that namespace; join will be
* done again in that context. * done again in that context.
*/ */
...@@ -2167,7 +2202,7 @@ static int netvsc_probe(struct hv_device *dev, ...@@ -2167,7 +2202,7 @@ static int netvsc_probe(struct hv_device *dev,
{ {
struct net_device *net = NULL; struct net_device *net = NULL;
struct net_device_context *net_device_ctx; struct net_device_context *net_device_ctx;
struct netvsc_device_info device_info; struct netvsc_device_info *device_info = NULL;
struct netvsc_device *nvdev; struct netvsc_device *nvdev;
int ret = -ENOMEM; int ret = -ENOMEM;
...@@ -2214,21 +2249,21 @@ static int netvsc_probe(struct hv_device *dev, ...@@ -2214,21 +2249,21 @@ static int netvsc_probe(struct hv_device *dev,
netif_set_real_num_rx_queues(net, 1); netif_set_real_num_rx_queues(net, 1);
/* Notify the netvsc driver of the new device */ /* Notify the netvsc driver of the new device */
memset(&device_info, 0, sizeof(device_info)); device_info = netvsc_devinfo_get(NULL);
device_info.num_chn = VRSS_CHANNEL_DEFAULT;
device_info.send_sections = NETVSC_DEFAULT_TX; if (!device_info) {
device_info.send_section_size = NETVSC_SEND_SECTION_SIZE; ret = -ENOMEM;
device_info.recv_sections = NETVSC_DEFAULT_RX; goto devinfo_failed;
device_info.recv_section_size = NETVSC_RECV_SECTION_SIZE; }
nvdev = rndis_filter_device_add(dev, &device_info); nvdev = rndis_filter_device_add(dev, device_info);
if (IS_ERR(nvdev)) { if (IS_ERR(nvdev)) {
ret = PTR_ERR(nvdev); ret = PTR_ERR(nvdev);
netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
goto rndis_failed; 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, /* We must get rtnl lock before scheduling nvdev->subchan_work,
* otherwise netvsc_subchan_work() can get rtnl lock first and wait * otherwise netvsc_subchan_work() can get rtnl lock first and wait
...@@ -2236,7 +2271,7 @@ static int netvsc_probe(struct hv_device *dev, ...@@ -2236,7 +2271,7 @@ static int netvsc_probe(struct hv_device *dev,
* netvsc_probe() can't get rtnl lock and as a result vmbus_onoffer() * netvsc_probe() can't get rtnl lock and as a result vmbus_onoffer()
* -> ... -> device_add() -> ... -> __device_attach() can't get * -> ... -> device_add() -> ... -> __device_attach() can't get
* the device lock, so all the subchannels can't be processed -- * the device lock, so all the subchannels can't be processed --
* finally netvsc_subchan_work() hangs for ever. * finally netvsc_subchan_work() hangs forever.
*/ */
rtnl_lock(); rtnl_lock();
...@@ -2266,12 +2301,16 @@ static int netvsc_probe(struct hv_device *dev, ...@@ -2266,12 +2301,16 @@ static int netvsc_probe(struct hv_device *dev,
list_add(&net_device_ctx->list, &netvsc_dev_list); list_add(&net_device_ctx->list, &netvsc_dev_list);
rtnl_unlock(); rtnl_unlock();
kfree(device_info);
return 0; return 0;
register_failed: register_failed:
rtnl_unlock(); rtnl_unlock();
rndis_filter_device_remove(dev, nvdev); rndis_filter_device_remove(dev, nvdev);
rndis_failed: rndis_failed:
kfree(device_info);
devinfo_failed:
free_percpu(net_device_ctx->vf_stats); free_percpu(net_device_ctx->vf_stats);
no_stats: no_stats:
hv_set_drvdata(dev, NULL); hv_set_drvdata(dev, NULL);
......
...@@ -774,8 +774,8 @@ rndis_filter_set_offload_params(struct net_device *ndev, ...@@ -774,8 +774,8 @@ rndis_filter_set_offload_params(struct net_device *ndev,
return ret; return ret;
} }
int rndis_filter_set_rss_param(struct rndis_device *rdev, static int rndis_set_rss_param_msg(struct rndis_device *rdev,
const u8 *rss_key) const u8 *rss_key, u16 flag)
{ {
struct net_device *ndev = rdev->ndev; struct net_device *ndev = rdev->ndev;
struct rndis_request *request; struct rndis_request *request;
...@@ -804,7 +804,7 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev, ...@@ -804,7 +804,7 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS; rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2; rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
rssp->hdr.size = sizeof(struct ndis_recv_scale_param); rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
rssp->flag = 0; rssp->flag = flag;
rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 | rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 | NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
NDIS_HASH_TCP_IPV6; NDIS_HASH_TCP_IPV6;
...@@ -829,9 +829,12 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev, ...@@ -829,9 +829,12 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
wait_for_completion(&request->wait_event); wait_for_completion(&request->wait_event);
set_complete = &request->response_msg.msg.set_complete; set_complete = &request->response_msg.msg.set_complete;
if (set_complete->status == RNDIS_STATUS_SUCCESS) if (set_complete->status == RNDIS_STATUS_SUCCESS) {
memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN); if (!(flag & NDIS_RSS_PARAM_FLAG_DISABLE_RSS) &&
else { !(flag & NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED))
memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN);
} else {
netdev_err(ndev, "Fail to set RSS parameters:0x%x\n", netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
set_complete->status); set_complete->status);
ret = -EINVAL; ret = -EINVAL;
...@@ -842,6 +845,16 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev, ...@@ -842,6 +845,16 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
return ret; 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, static int rndis_filter_query_device_link_status(struct rndis_device *dev,
struct netvsc_device *net_device) struct netvsc_device *net_device)
{ {
...@@ -1121,7 +1134,9 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc) ...@@ -1121,7 +1134,9 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
* This breaks overlap of processing the host message for the * This breaks overlap of processing the host message for the
* new primary channel with the initialization of sub-channels. * 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 nvsp_message *init_packet = &nvdev->channel_init_pkt;
struct net_device_context *ndev_ctx = netdev_priv(ndev); struct net_device_context *ndev_ctx = netdev_priv(ndev);
...@@ -1161,8 +1176,11 @@ int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev) ...@@ -1161,8 +1176,11 @@ int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
wait_event(nvdev->subchan_open, wait_event(nvdev->subchan_open,
atomic_read(&nvdev->open_chn) == nvdev->num_chn); 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 */
rndis_filter_set_rss_param(rdev, netvsc_hash_key); 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); netif_set_real_num_tx_queues(ndev, nvdev->num_chn);
netif_set_real_num_rx_queues(ndev, nvdev->num_chn); netif_set_real_num_rx_queues(ndev, nvdev->num_chn);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment