[PATCH 5/6] Drivers: hv: vmbus: Fix rescind handling

2017-04-30 Thread kys
From: K. Y. Srinivasan 

Fix the rescind handling. This patch addresses the following rescind
scenario that is currently not handled correctly:

If a rescind were to be received while the offer is still being
peocessed, we will be blocked indefinitely since the rescind message
is handled on the same work element as the offer message. Fix this
issue.

I would like to thank Dexuan Cui  and
Long Li  for working with me on this patch.

Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel.c  |8 -
 drivers/hv/channel_mgmt.c |   69 ++--
 drivers/hv/connection.c   |7 +++-
 drivers/hv/hyperv_vmbus.h |7 
 drivers/hv/vmbus_drv.c|   29 ++-
 5 files changed, 99 insertions(+), 21 deletions(-)

diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 736ac76..e9bf0bb 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -630,9 +630,13 @@ void vmbus_close(struct vmbus_channel *channel)
 */
list_for_each_safe(cur, tmp, &channel->sc_list) {
cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
-   if (cur_channel->state != CHANNEL_OPENED_STATE)
-   continue;
vmbus_close_internal(cur_channel);
+   if (cur_channel->rescind) {
+   mutex_lock(&vmbus_connection.channel_mutex);
+   hv_process_channel_removal(cur_channel,
+  cur_channel->offermsg.child_relid);
+   mutex_unlock(&vmbus_connection.channel_mutex);
+   }
}
/*
 * Now close the primary.
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index eec616a..06529b3 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -428,7 +428,6 @@ void vmbus_free_channels(void)
 {
struct vmbus_channel *channel, *tmp;
 
-   mutex_lock(&vmbus_connection.channel_mutex);
list_for_each_entry_safe(channel, tmp, &vmbus_connection.chn_list,
listentry) {
/* hv_process_channel_removal() needs this */
@@ -436,7 +435,6 @@ void vmbus_free_channels(void)
 
vmbus_device_unregister(channel->device_obj);
}
-   mutex_unlock(&vmbus_connection.channel_mutex);
 }
 
 /*
@@ -483,8 +481,10 @@ static void vmbus_process_offer(struct vmbus_channel 
*newchannel)
list_add_tail(&newchannel->sc_list, &channel->sc_list);
channel->num_sc++;
spin_unlock_irqrestore(&channel->lock, flags);
-   } else
+   } else {
+   atomic_dec(&vmbus_connection.offer_in_progress);
goto err_free_chan;
+   }
}
 
dev_type = hv_get_dev_type(newchannel);
@@ -511,6 +511,7 @@ static void vmbus_process_offer(struct vmbus_channel 
*newchannel)
if (!fnew) {
if (channel->sc_creation_callback != NULL)
channel->sc_creation_callback(newchannel);
+   atomic_dec(&vmbus_connection.offer_in_progress);
return;
}
 
@@ -532,9 +533,7 @@ static void vmbus_process_offer(struct vmbus_channel 
*newchannel)
 * binding which eventually invokes the device driver's AddDevice()
 * method.
 */
-   mutex_lock(&vmbus_connection.channel_mutex);
ret = vmbus_device_register(newchannel->device_obj);
-   mutex_unlock(&vmbus_connection.channel_mutex);
 
if (ret != 0) {
pr_err("unable to add child device object (relid %d)\n",
@@ -542,6 +541,8 @@ static void vmbus_process_offer(struct vmbus_channel 
*newchannel)
kfree(newchannel->device_obj);
goto err_deq_chan;
}
+
+   atomic_dec(&vmbus_connection.offer_in_progress);
return;
 
 err_deq_chan:
@@ -799,6 +800,7 @@ static void vmbus_onoffer(struct 
vmbus_channel_message_header *hdr)
newchannel = alloc_channel();
if (!newchannel) {
vmbus_release_relid(offer->child_relid);
+   atomic_dec(&vmbus_connection.offer_in_progress);
pr_err("Unable to allocate channel object\n");
return;
}
@@ -845,16 +847,38 @@ static void vmbus_onoffer_rescind(struct 
vmbus_channel_message_header *hdr)
 
rescind = (struct vmbus_channel_rescind_offer *)hdr;
 
+   /*
+* The offer msg and the corresponding rescind msg
+* from the host are guranteed to be ordered -
+* offer comes in first and then the rescind.
+* Since we process these events in work elements,
+* and with preemption, we may end up processing
+* the events out of order. Given that we handle these
+* work elements on the same CPU, this is possible only
+* in the case of preemption. In any case wait here
+* until the offer proces

[PATCH 4/6] Drivers: hv: util: Make hv_poll_channel() a little more efficient

2017-04-30 Thread kys
From: K. Y. Srinivasan 

The current code unconditionally sends an IPI. If we are running on the
correct CPU and are in interrupt level, we don't need an IPI.
Make this adjustment.

Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hyperv_vmbus.h |4 
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 6113e91..fa514be 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -411,6 +411,10 @@ static inline void hv_poll_channel(struct vmbus_channel 
*channel,
if (!channel)
return;
 
+   if (in_interrupt() && (channel->target_cpu == smp_processor_id())) {
+   cb(channel);
+   return;
+   }
smp_call_function_single(channel->target_cpu, cb, channel, true);
 }
 
-- 
1.7.1



[PATCH 3/6] Drivers: hv: vmbus: Fix error code returned by vmbus_post_msg()

2017-04-30 Thread kys
From: K. Y. Srinivasan 

ENOBUFS is a more approrpiate error code to be returned
when the hypervisor cannot post the message because of
insufficient buffers. Make the adjustment.

Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/connection.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index fce27fb..a938fcf 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -370,7 +370,7 @@ int vmbus_post_msg(void *buffer, size_t buflen, bool 
can_sleep)
break;
case HV_STATUS_INSUFFICIENT_MEMORY:
case HV_STATUS_INSUFFICIENT_BUFFERS:
-   ret = -ENOMEM;
+   ret = -ENOBUFS;
break;
case HV_STATUS_SUCCESS:
return ret;
-- 
1.7.1



[PATCH 2/6] tools: hv: properly handle long paths

2017-04-30 Thread kys
From: Vitaly Kuznetsov 

Paths can be up to PATH_MAX long and PATH_MAX is usually greater than 256.
While on it, simplify path reconstruction to a simple snprintf(), define
and reuse KVP_NET_DIR.

Suggested-by: Tomas Hozza 
Signed-off-by: Vitaly Kuznetsov 
Signed-off-by: K. Y. Srinivasan 
---
 tools/hv/hv_kvp_daemon.c |   44 ++--
 1 files changed, 18 insertions(+), 26 deletions(-)

diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index f1758fc..88b20e0 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -39,6 +39,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 /*
@@ -97,6 +98,8 @@ enum {
 #define KVP_SCRIPTS_PATH "/usr/libexec/hypervkvpd/"
 #endif
 
+#define KVP_NET_DIR "/sys/class/net/"
+
 #define MAX_FILE_NAME 100
 #define ENTRIES_PER_BLOCK 50
 
@@ -596,26 +599,21 @@ void kvp_get_os_info(void)
DIR *dir;
struct dirent *entry;
FILE*file;
-   char*p, *q, *x;
+   char*p, *x;
char*if_name = NULL;
charbuf[256];
-   char *kvp_net_dir = "/sys/class/net/";
-   char dev_id[256];
+   char dev_id[PATH_MAX];
 
-   dir = opendir(kvp_net_dir);
+   dir = opendir(KVP_NET_DIR);
if (dir == NULL)
return NULL;
 
-   snprintf(dev_id, sizeof(dev_id), "%s", kvp_net_dir);
-   q = dev_id + strlen(kvp_net_dir);
-
while ((entry = readdir(dir)) != NULL) {
/*
 * Set the state for the next pass.
 */
-   *q = '\0';
-   strcat(dev_id, entry->d_name);
-   strcat(dev_id, "/device/device_id");
+   snprintf(dev_id, sizeof(dev_id), "%s%s/device/device_id",
+KVP_NET_DIR, entry->d_name);
 
file = fopen(dev_id, "r");
if (file == NULL)
@@ -653,12 +651,12 @@ void kvp_get_os_info(void)
FILE*file;
char*p, *x;
charbuf[256];
-   char addr_file[256];
+   char addr_file[PATH_MAX];
unsigned int i;
char *mac_addr = NULL;
 
-   snprintf(addr_file, sizeof(addr_file), "%s%s%s", "/sys/class/net/",
-   if_name, "/address");
+   snprintf(addr_file, sizeof(addr_file), "%s%s%s", KVP_NET_DIR,
+if_name, "/address");
 
file = fopen(addr_file, "r");
if (file == NULL)
@@ -688,28 +686,22 @@ void kvp_get_os_info(void)
DIR *dir;
struct dirent *entry;
FILE*file;
-   char*p, *q, *x;
+   char*p, *x;
char*if_name = NULL;
charbuf[256];
-   char *kvp_net_dir = "/sys/class/net/";
-   char dev_id[256];
+   char dev_id[PATH_MAX];
unsigned int i;
 
-   dir = opendir(kvp_net_dir);
+   dir = opendir(KVP_NET_DIR);
if (dir == NULL)
return NULL;
 
-   snprintf(dev_id, sizeof(dev_id), "%s", kvp_net_dir);
-   q = dev_id + strlen(kvp_net_dir);
-
while ((entry = readdir(dir)) != NULL) {
/*
 * Set the state for the next pass.
 */
-   *q = '\0';
-
-   strcat(dev_id, entry->d_name);
-   strcat(dev_id, "/address");
+   snprintf(dev_id, sizeof(dev_id), "%s%s/address", KVP_NET_DIR,
+entry->d_name);
 
file = fopen(dev_id, "r");
if (file == NULL)
@@ -1218,9 +1210,9 @@ static int process_ip_string(FILE *f, char *ip_string, 
int type)
 static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
 {
int error = 0;
-   char if_file[128];
+   char if_file[PATH_MAX];
FILE *file;
-   char cmd[512];
+   char cmd[PATH_MAX];
char *mac_addr;
 
/*
-- 
1.7.1



[PATCH 6/6] HV: properly delay KVP packets when negotiation is in progress

2017-04-30 Thread kys
From: Long Li 

The host may send multiple negotiation packets
(due to timeout) before the KVP user-mode daemon
is connected. KVP user-mode daemon is connected.
We need to defer processing those packets
until the daemon is negotiated and connected.
It's okay for guest to respond
to all negotiation packets.

In addition, the host may send multiple staged
KVP requests as soon as negotiation is done.
We need to properly process those packets using one
tasklet for exclusive access to ring buffer.

This patch is based on the work of
Nick Meier .

Signed-off-by: Long Li 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c |   14 --
 1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index e99ff2d..9a90b91 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -112,7 +112,7 @@ static void kvp_poll_wrapper(void *channel)
 {
/* Transaction is finished, reset the state here to avoid races. */
kvp_transaction.state = HVUTIL_READY;
-   hv_kvp_onchannelcallback(channel);
+   tasklet_schedule(&((struct vmbus_channel *)channel)->callback_event);
 }
 
 static void kvp_register_done(void)
@@ -159,7 +159,7 @@ static void kvp_timeout_func(struct work_struct *dummy)
 
 static void kvp_host_handshake_func(struct work_struct *dummy)
 {
-   hv_poll_channel(kvp_transaction.recv_channel, hv_kvp_onchannelcallback);
+   tasklet_schedule(&kvp_transaction.recv_channel->callback_event);
 }
 
 static int kvp_handle_handshake(struct hv_kvp_msg *msg)
@@ -625,16 +625,17 @@ void hv_kvp_onchannelcallback(void *context)
 NEGO_IN_PROGRESS,
 NEGO_FINISHED} host_negotiatied = NEGO_NOT_STARTED;
 
-   if (host_negotiatied == NEGO_NOT_STARTED &&
-   kvp_transaction.state < HVUTIL_READY) {
+   if (kvp_transaction.state < HVUTIL_READY) {
/*
 * If userspace daemon is not connected and host is asking
 * us to negotiate we need to delay to not lose messages.
 * This is important for Failover IP setting.
 */
-   host_negotiatied = NEGO_IN_PROGRESS;
-   schedule_delayed_work(&kvp_host_handshake_work,
+   if (host_negotiatied == NEGO_NOT_STARTED) {
+   host_negotiatied = NEGO_IN_PROGRESS;
+   schedule_delayed_work(&kvp_host_handshake_work,
  HV_UTIL_NEGO_TIMEOUT * HZ);
+   }
return;
}
if (kvp_transaction.state > HVUTIL_READY)
@@ -702,6 +703,7 @@ void hv_kvp_onchannelcallback(void *context)
   VM_PKT_DATA_INBAND, 0);
 
host_negotiatied = NEGO_FINISHED;
+   hv_poll_channel(kvp_transaction.recv_channel, kvp_poll_wrapper);
}
 
 }
-- 
1.7.1



[PATCH 1/6] Tools: hv: vss: Thaw the filesystem and continue if freeze call has timed out

2017-04-30 Thread kys
From: Alex Ng 

If a FREEZE operation takes too long, the driver may time out and move on
to another  operation. The daemon is unaware of this and attempts to
notify the driver that the FREEZE succeeded. This results in an error from
the driver and the daemon leaves the filesystem in frozen state.

Fix this by thawing the filesystem and continuing.

Signed-off-by: Michael Gissing 
Signed-off-by: Alex Ng 
Signed-off-by: K. Y. Srinivasan 
---
 tools/hv/hv_vss_daemon.c |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index e082980..7ba5419 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -261,7 +261,9 @@ int main(int argc, char *argv[])
if (len != sizeof(struct hv_vss_msg)) {
syslog(LOG_ERR, "write failed; error: %d %s", errno,
   strerror(errno));
-   exit(EXIT_FAILURE);
+
+   if (op == VSS_OP_FREEZE)
+   vss_operate(VSS_OP_THAW);
}
}
 
-- 
1.7.1



[PATCH 0/6] Drivers: hv: Miscellaneous fixes

2017-04-30 Thread kys
From: K. Y. Srinivasan 

Miscellaneous fixes to vmbus and util drivers.

Alex Ng (1):
  Tools: hv: vss: Thaw the filesystem and continue if freeze call has
timed out

K. Y. Srinivasan (3):
  Drivers: hv: vmbus: Fix error code returned by vmbus_post_msg()
  Drivers: hv: util: Make hv_poll_channel() a little more efficient
  Drivers: hv: vmbus: Fix rescind handling

Long Li (1):
  HV: properly delay KVP packets when negotiation is in progress

Vitaly Kuznetsov (1):
  tools: hv: properly handle long paths

 drivers/hv/channel.c  |8 -
 drivers/hv/channel_mgmt.c |   69 ++--
 drivers/hv/connection.c   |9 --
 drivers/hv/hv_kvp.c   |   14 +
 drivers/hv/hyperv_vmbus.h |   11 +++
 drivers/hv/vmbus_drv.c|   29 ++-
 tools/hv/hv_kvp_daemon.c  |   44 -
 tools/hv/hv_vss_daemon.c  |4 ++-
 8 files changed, 133 insertions(+), 55 deletions(-)



[PATCH net-next 1/1] netvsc: Deal with rescinded channels correctly

2017-04-19 Thread kys
From: K. Y. Srinivasan 

We will not be able to send packets over a channel that has been
rescinded. Make necessary adjustments so we can properly cleanup
even when the channel is rescinded. This issue can be trigerred
in the NIC hot-remove path.

Signed-off-by: K. Y. Srinivasan 
---
 drivers/net/hyperv/netvsc.c |   16 
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 7ab06b3..b5b10fc 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -135,6 +135,13 @@ static void netvsc_destroy_buf(struct hv_device *device)
   sizeof(struct nvsp_message),
   (unsigned long)revoke_packet,
   VM_PKT_DATA_INBAND, 0);
+   /* If the failure is because the channel is rescinded;
+* ignore the failure since we cannot send on a rescinded
+* channel. This would allow us to properly cleanup
+* even when the channel is rescinded.
+*/
+   if (device->channel->rescind)
+   ret = 0;
/*
 * If we failed here, we might as well return and
 * have a leak rather than continue and a bugchk
@@ -195,6 +202,15 @@ static void netvsc_destroy_buf(struct hv_device *device)
   sizeof(struct nvsp_message),
   (unsigned long)revoke_packet,
   VM_PKT_DATA_INBAND, 0);
+
+   /* If the failure is because the channel is rescinded;
+* ignore the failure since we cannot send on a rescinded
+* channel. This would allow us to properly cleanup
+* even when the channel is rescinded.
+*/
+   if (device->channel->rescind)
+   ret = 0;
+
/* If we failed here, we might as well return and
 * have a leak rather than continue and a bugchk
 */
-- 
1.7.1



[PATCH 1/1] netvsc: Deal with rescinded channels correctly

2017-04-19 Thread kys
From: K. Y. Srinivasan 

We will not be able to send packets over a channel that has been
rescinded. Make necessary adjustments so we can properly cleanup
even when the channel is rescinded. This issue can be trigerred
in the NIC hot-remove path.

Signed-off-by: K. Y. Srinivasan 
---
 drivers/net/hyperv/netvsc.c |   16 
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 7ab06b3..b5b10fc 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -135,6 +135,13 @@ static void netvsc_destroy_buf(struct hv_device *device)
   sizeof(struct nvsp_message),
   (unsigned long)revoke_packet,
   VM_PKT_DATA_INBAND, 0);
+   /* If the failure is because the channel is rescinded;
+* ignore the failure since we cannot send on a rescinded
+* channel. This would allow us to properly cleanup
+* even when the channel is rescinded.
+*/
+   if (device->channel->rescind)
+   ret = 0;
/*
 * If we failed here, we might as well return and
 * have a leak rather than continue and a bugchk
@@ -195,6 +202,15 @@ static void netvsc_destroy_buf(struct hv_device *device)
   sizeof(struct nvsp_message),
   (unsigned long)revoke_packet,
   VM_PKT_DATA_INBAND, 0);
+
+   /* If the failure is because the channel is rescinded;
+* ignore the failure since we cannot send on a rescinded
+* channel. This would allow us to properly cleanup
+* even when the channel is rescinded.
+*/
+   if (device->channel->rescind)
+   ret = 0;
+
/* If we failed here, we might as well return and
 * have a leak rather than continue and a bugchk
 */
-- 
1.7.1



[PATCH net-next 1/1] netvsc: Initialize all channel related state prior to opening the channel

2017-04-06 Thread kys
From: K. Y. Srinivasan 

Prior to opening the channel we should have all the state setup to handle
interrupts. The current code does not do that; fix the bug. This bug
can result in faults in the interrupt path.
 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/net/hyperv/netvsc.c   |   27 +++
 drivers/net/hyperv/rndis_filter.c |5 +++--
 2 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index e998e2f..7ab06b3 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -1289,6 +1289,21 @@ int netvsc_device_add(struct hv_device *device,
 */
set_channel_read_mode(device->channel, HV_CALL_ISR);
 
+   /* If we're reopening the device we may have multiple queues, fill the
+* chn_table with the default channel to use it before subchannels are
+* opened.
+* Initialize the channel state before we open;
+* we can be interrupted as soon as we open the channel.
+*/
+
+   for (i = 0; i < VRSS_CHANNEL_MAX; i++) {
+   struct netvsc_channel *nvchan = &net_device->chan_table[i];
+
+   nvchan->channel = device->channel;
+   netif_napi_add(ndev, &nvchan->napi,
+  netvsc_poll, NAPI_POLL_WEIGHT);
+   }
+
/* Open the channel */
ret = vmbus_open(device->channel, ring_size * PAGE_SIZE,
 ring_size * PAGE_SIZE, NULL, 0,
@@ -1303,18 +1318,6 @@ int netvsc_device_add(struct hv_device *device,
/* Channel is opened */
netdev_dbg(ndev, "hv_netvsc channel opened successfully\n");
 
-   /* If we're reopening the device we may have multiple queues, fill the
-* chn_table with the default channel to use it before subchannels are
-* opened.
-*/
-   for (i = 0; i < VRSS_CHANNEL_MAX; i++) {
-   struct netvsc_channel *nvchan = &net_device->chan_table[i];
-
-   nvchan->channel = device->channel;
-   netif_napi_add(ndev, &nvchan->napi,
-  netvsc_poll, NAPI_POLL_WEIGHT);
-   }
-
/* Enable NAPI handler for init callbacks */
napi_enable(&net_device->chan_table[0].napi);
 
diff --git a/drivers/net/hyperv/rndis_filter.c 
b/drivers/net/hyperv/rndis_filter.c
index 9835825..1e9445b 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1007,12 +1007,13 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
 */
set_channel_read_mode(new_sc, HV_CALL_ISR);
 
+   /* Set the channel before opening.*/
+   nvchan->channel = new_sc;
+
ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
 nvscdev->ring_size * PAGE_SIZE, NULL, 0,
 netvsc_channel_cb, nvchan);
 
-   if (ret == 0)
-   nvchan->channel = new_sc;
 
napi_enable(&nvchan->napi);
 
-- 
1.7.1



[PATCH net-next 1/2] netvsc: Fix a bug in sub-channel handling

2017-03-24 Thread kys
From: K. Y. Srinivasan 

All netvsc channels are handled via NAPI. Setup the "read mode" correctly
for the netvsc sub-channels.

Signed-off-by: K. Y. Srinivasan 
---
 drivers/net/hyperv/rndis_filter.c |5 +
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/net/hyperv/rndis_filter.c 
b/drivers/net/hyperv/rndis_filter.c
index 91b3bcf..9835825 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1002,6 +1002,11 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
if (!nvchan->mrc.buf)
return;
 
+   /* Because the device uses NAPI, all the interrupt batching and
+* control is done via Net softirq, not the channel handling
+*/
+   set_channel_read_mode(new_sc, HV_CALL_ISR);
+
ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
 nvscdev->ring_size * PAGE_SIZE, NULL, 0,
 netvsc_channel_cb, nvchan);
-- 
1.7.1



[PATCH net-next 2/2] netvsc: Properly initialize the return value

2017-03-24 Thread kys
From: K. Y. Srinivasan 

Initialize the return value correctly.

Signed-off-by: K. Y. Srinivasan 
---
 drivers/net/hyperv/netvsc_drv.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index eb7ae79..f830bbb 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -855,7 +855,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int 
mtu)
struct hv_device *hdev = ndevctx->device_ctx;
struct netvsc_device_info device_info;
bool was_running;
-   int ret;
+   int ret = 0;
 
if (!nvdev || nvdev->destroy)
return -ENODEV;
-- 
1.7.1



[PATCH net-next 0/2] netvsc: Fix miscellaneous issues

2017-03-24 Thread kys
From: K. Y. Srinivasan 

Fix miscellaneous issues.

K. Y. Srinivasan (2):
  netvsc: Fix a bug in sub-channel handling
  netvsc: Properly initialize the return value

 drivers/net/hyperv/netvsc_drv.c   |2 +-
 drivers/net/hyperv/rndis_filter.c |5 +
 2 files changed, 6 insertions(+), 1 deletions(-)



[PATCH RESEND net-next] netvsc: Use the new in-place consumption APIs in the rx path

2016-07-05 Thread kys
From: K. Y. Srinivasan 

Use the new APIs for eliminating a copy on the receive path. These new APIs also
help in minimizing the number of memory barriers we end up issuing (in the
ringbuffer code) since we can better control when we want to expose the ring
state to the host.

The patch is being resent to address earlier email issues.

Signed-off-by: K. Y. Srinivasan 
---
 drivers/net/hyperv/netvsc.c |   88 +--
 1 files changed, 59 insertions(+), 29 deletions(-)

diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 719cb35..8cd4c19 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -1141,6 +1141,39 @@ static inline void netvsc_receive_inband(struct 
hv_device *hdev,
}
 }
 
+static void netvsc_process_raw_pkt(struct hv_device *device,
+  struct vmbus_channel *channel,
+  struct netvsc_device *net_device,
+  struct net_device *ndev,
+  u64 request_id,
+  struct vmpacket_descriptor *desc)
+{
+   struct nvsp_message *nvmsg;
+
+   nvmsg = (struct nvsp_message *)((unsigned long)
+   desc + (desc->offset8 << 3));
+
+   switch (desc->type) {
+   case VM_PKT_COMP:
+   netvsc_send_completion(net_device, channel, device, desc);
+   break;
+
+   case VM_PKT_DATA_USING_XFER_PAGES:
+   netvsc_receive(net_device, channel, device, desc);
+   break;
+
+   case VM_PKT_DATA_INBAND:
+   netvsc_receive_inband(device, net_device, nvmsg);
+   break;
+
+   default:
+   netdev_err(ndev, "unhandled packet type %d, tid %llx\n",
+  desc->type, request_id);
+   break;
+   }
+}
+
+
 void netvsc_channel_cb(void *context)
 {
int ret;
@@ -1153,7 +1186,7 @@ void netvsc_channel_cb(void *context)
unsigned char *buffer;
int bufferlen = NETVSC_PACKET_SIZE;
struct net_device *ndev;
-   struct nvsp_message *nvmsg;
+   bool need_to_commit = false;
 
if (channel->primary_channel != NULL)
device = channel->primary_channel->device_obj;
@@ -1167,39 +1200,36 @@ void netvsc_channel_cb(void *context)
buffer = get_per_channel_state(channel);
 
do {
+   desc = get_next_pkt_raw(channel);
+   if (desc != NULL) {
+   netvsc_process_raw_pkt(device,
+  channel,
+  net_device,
+  ndev,
+  desc->trans_id,
+  desc);
+
+   put_pkt_raw(channel, desc);
+   need_to_commit = true;
+   continue;
+   }
+   if (need_to_commit) {
+   need_to_commit = false;
+   commit_rd_index(channel);
+   }
+
ret = vmbus_recvpacket_raw(channel, buffer, bufferlen,
   &bytes_recvd, &request_id);
if (ret == 0) {
if (bytes_recvd > 0) {
desc = (struct vmpacket_descriptor *)buffer;
-   nvmsg = (struct nvsp_message *)((unsigned long)
-desc + (desc->offset8 << 3));
-   switch (desc->type) {
-   case VM_PKT_COMP:
-   netvsc_send_completion(net_device,
-   channel,
-   device, desc);
-   break;
-
-   case VM_PKT_DATA_USING_XFER_PAGES:
-   netvsc_receive(net_device, channel,
-  device, desc);
-   break;
-
-   case VM_PKT_DATA_INBAND:
-   netvsc_receive_inband(device,
- net_device,
- nvmsg);
-   break;
-
-   default:
-   netdev_err(ndev,
-  "unhandled packet type %d, "
-  "tid %llx len %d\n",
-  desc->type, request_id,
-  bytes_recvd);
-