Merge 4.18-rc5 into char-misc-next
We want the char-misc fixes in here as well. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
@@ -210,7 +210,7 @@ int netvsc_recv_callback(struct net_device *net,
|
||||
void netvsc_channel_cb(void *context);
|
||||
int netvsc_poll(struct napi_struct *napi, int budget);
|
||||
|
||||
void rndis_set_subchannel(struct work_struct *w);
|
||||
int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev);
|
||||
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,
|
||||
|
@@ -65,6 +65,41 @@ void netvsc_switch_datapath(struct net_device *ndev, bool vf)
|
||||
VM_PKT_DATA_INBAND, 0);
|
||||
}
|
||||
|
||||
/* Worker to setup sub channels on initial setup
|
||||
* Initial hotplug event occurs in softirq context
|
||||
* and can't wait for channels.
|
||||
*/
|
||||
static void netvsc_subchan_work(struct work_struct *w)
|
||||
{
|
||||
struct netvsc_device *nvdev =
|
||||
container_of(w, struct netvsc_device, subchan_work);
|
||||
struct rndis_device *rdev;
|
||||
int i, ret;
|
||||
|
||||
/* Avoid deadlock with device removal already under RTNL */
|
||||
if (!rtnl_trylock()) {
|
||||
schedule_work(w);
|
||||
return;
|
||||
}
|
||||
|
||||
rdev = nvdev->extension;
|
||||
if (rdev) {
|
||||
ret = rndis_set_subchannel(rdev->ndev, nvdev);
|
||||
if (ret == 0) {
|
||||
netif_device_attach(rdev->ndev);
|
||||
} else {
|
||||
/* fallback to only primary channel */
|
||||
for (i = 1; i < nvdev->num_chn; i++)
|
||||
netif_napi_del(&nvdev->chan_table[i].napi);
|
||||
|
||||
nvdev->max_chn = 1;
|
||||
nvdev->num_chn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static struct netvsc_device *alloc_net_device(void)
|
||||
{
|
||||
struct netvsc_device *net_device;
|
||||
@@ -81,7 +116,7 @@ static struct netvsc_device *alloc_net_device(void)
|
||||
|
||||
init_completion(&net_device->channel_init_wait);
|
||||
init_waitqueue_head(&net_device->subchan_open);
|
||||
INIT_WORK(&net_device->subchan_work, rndis_set_subchannel);
|
||||
INIT_WORK(&net_device->subchan_work, netvsc_subchan_work);
|
||||
|
||||
return net_device;
|
||||
}
|
||||
|
@@ -905,8 +905,20 @@ static int netvsc_attach(struct net_device *ndev,
|
||||
if (IS_ERR(nvdev))
|
||||
return PTR_ERR(nvdev);
|
||||
|
||||
/* Note: enable and attach happen when sub-channels setup */
|
||||
if (nvdev->num_chn > 1) {
|
||||
ret = rndis_set_subchannel(ndev, nvdev);
|
||||
|
||||
/* if unavailable, just proceed with one queue */
|
||||
if (ret) {
|
||||
nvdev->max_chn = 1;
|
||||
nvdev->num_chn = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* In any case device is now ready */
|
||||
netif_device_attach(ndev);
|
||||
|
||||
/* Note: enable and attach happen when sub-channels setup */
|
||||
netif_carrier_off(ndev);
|
||||
|
||||
if (netif_running(ndev)) {
|
||||
@@ -2089,6 +2101,9 @@ static int netvsc_probe(struct hv_device *dev,
|
||||
|
||||
memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
|
||||
|
||||
if (nvdev->num_chn > 1)
|
||||
schedule_work(&nvdev->subchan_work);
|
||||
|
||||
/* hw_features computed in rndis_netdev_set_hwcaps() */
|
||||
net->features = net->hw_features |
|
||||
NETIF_F_HIGHDMA | NETIF_F_SG |
|
||||
|
@@ -1062,29 +1062,15 @@ 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.
|
||||
*/
|
||||
void rndis_set_subchannel(struct work_struct *w)
|
||||
int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
|
||||
{
|
||||
struct netvsc_device *nvdev
|
||||
= container_of(w, struct netvsc_device, subchan_work);
|
||||
struct nvsp_message *init_packet = &nvdev->channel_init_pkt;
|
||||
struct net_device_context *ndev_ctx;
|
||||
struct rndis_device *rdev;
|
||||
struct net_device *ndev;
|
||||
struct hv_device *hv_dev;
|
||||
struct net_device_context *ndev_ctx = netdev_priv(ndev);
|
||||
struct hv_device *hv_dev = ndev_ctx->device_ctx;
|
||||
struct rndis_device *rdev = nvdev->extension;
|
||||
int i, ret;
|
||||
|
||||
if (!rtnl_trylock()) {
|
||||
schedule_work(w);
|
||||
return;
|
||||
}
|
||||
|
||||
rdev = nvdev->extension;
|
||||
if (!rdev)
|
||||
goto unlock; /* device was removed */
|
||||
|
||||
ndev = rdev->ndev;
|
||||
ndev_ctx = netdev_priv(ndev);
|
||||
hv_dev = ndev_ctx->device_ctx;
|
||||
ASSERT_RTNL();
|
||||
|
||||
memset(init_packet, 0, sizeof(struct nvsp_message));
|
||||
init_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL;
|
||||
@@ -1100,13 +1086,13 @@ void rndis_set_subchannel(struct work_struct *w)
|
||||
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
||||
if (ret) {
|
||||
netdev_err(ndev, "sub channel allocate send failed: %d\n", ret);
|
||||
goto failed;
|
||||
return ret;
|
||||
}
|
||||
|
||||
wait_for_completion(&nvdev->channel_init_wait);
|
||||
if (init_packet->msg.v5_msg.subchn_comp.status != NVSP_STAT_SUCCESS) {
|
||||
netdev_err(ndev, "sub channel request failed\n");
|
||||
goto failed;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
nvdev->num_chn = 1 +
|
||||
@@ -1125,21 +1111,7 @@ void rndis_set_subchannel(struct work_struct *w)
|
||||
for (i = 0; i < VRSS_SEND_TAB_SIZE; i++)
|
||||
ndev_ctx->tx_table[i] = i % nvdev->num_chn;
|
||||
|
||||
netif_device_attach(ndev);
|
||||
rtnl_unlock();
|
||||
return;
|
||||
|
||||
failed:
|
||||
/* fallback to only primary channel */
|
||||
for (i = 1; i < nvdev->num_chn; i++)
|
||||
netif_napi_del(&nvdev->chan_table[i].napi);
|
||||
|
||||
nvdev->max_chn = 1;
|
||||
nvdev->num_chn = 1;
|
||||
|
||||
netif_device_attach(ndev);
|
||||
unlock:
|
||||
rtnl_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rndis_netdev_set_hwcaps(struct rndis_device *rndis_device,
|
||||
@@ -1360,21 +1332,12 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
|
||||
netif_napi_add(net, &net_device->chan_table[i].napi,
|
||||
netvsc_poll, NAPI_POLL_WEIGHT);
|
||||
|
||||
if (net_device->num_chn > 1)
|
||||
schedule_work(&net_device->subchan_work);
|
||||
return net_device;
|
||||
|
||||
out:
|
||||
/* if unavailable, just proceed with one queue */
|
||||
if (ret) {
|
||||
net_device->max_chn = 1;
|
||||
net_device->num_chn = 1;
|
||||
}
|
||||
|
||||
/* No sub channels, device is ready */
|
||||
if (net_device->num_chn == 1)
|
||||
netif_device_attach(net);
|
||||
|
||||
return net_device;
|
||||
/* setting up multiple channels failed */
|
||||
net_device->max_chn = 1;
|
||||
net_device->num_chn = 1;
|
||||
|
||||
err_dev_remv:
|
||||
rndis_filter_device_remove(dev, net_device);
|
||||
|
Reference in New Issue
Block a user