Re: [PATCH 21/28] staging: most: fix retrieval of buffer availability
On Tue, Dec 22, 2015 at 10:53:02AM +0100, Christian Gromm wrote: > This patch fixes the function channel_has_mbo that delivers the false > information in case two AIMs are using the same tx channel. > > Signed-off-by: Christian Gromm> --- > > diff --git a/drivers/staging/most/mostcore/core.c > b/drivers/staging/most/mostcore/core.c > index b085f0a..ff0e0dc 100644 > --- a/drivers/staging/most/mostcore/core.c > +++ b/drivers/staging/most/mostcore/core.c > @@ -1352,7 +1352,7 @@ most_c_obj *get_channel_by_iface(struct most_interface > *iface, int id) > return i->channel[id]; > } > > -int channel_has_mbo(struct most_interface *iface, int id) > +int channel_has_mbo(struct most_interface *iface, int id, struct most_aim > *aim) > { > struct most_c_obj *c = get_channel_by_iface(iface, id); > unsigned long flags; > @@ -1361,6 +1361,11 @@ int channel_has_mbo(struct most_interface *iface, int > id) > if (unlikely(!c)) > return -EINVAL; > > + if (c->aim0.refs && c->aim1.refs && > + ((aim == c->aim0.ptr && c->aim0.num_buffers <= 0) || > + (aim == c->aim1.ptr && c->aim1.num_buffers <= 0))) > + return false; channel_has_mbo() return int. maybe return 0 instead of return false.. regards sudip ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [RFC PATCH 00/15] staging/rdma/hfi1: Initial patches to add rdmavt support in HFI1
On Tue, Dec 22, 2015 at 06:27:57PM -0800, gre...@linuxfoundation.org wrote: > On Tue, Dec 22, 2015 at 02:15:08PM -0500, ira.weiny wrote: > > On Mon, Dec 21, 2015 at 05:01:48PM -0800, gre...@linuxfoundation.org wrote: [snip] > > > > > > No, git is good :) > > > > > > > How do we handle changes which affect both qib and hfi1? > > > > > > I don't know, now this gets messy... > > > > > > > Agreed and this is what we are worried about. > > > > Can we do what Dan and Doug have proposed in the past and have Doug take > > over > > the staging/rdma sub-tree? > > > > http://driverdev.linuxdriverproject.org/pipermail/driverdev-devel/2015-November/081922.html > > > > I think the upcoming merge window is a reasonable time for him to do that. > > Ok, but keeping on top of all of the generic staging patches that come > in is a tough thing to do, that's up to Doug, if he is ready for it... > To help this process, once the change over happens, we will help to monitor driverdev-devel for anything submitted to staging/rdma. If something is submitted which was not to Doug and linux-rdma we can handle alerting the submitter to make sure it gets submitted to Doug as per the current MAINTAINERS file. Hope this helps, Ira ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH] staging: most: replace multiple if..else with table lookup
On Thu, 2015-12-24 at 10:49 +, Gujulan Elango, Hari Prasath (H.) wrote: > From: Hari Prasath Gujulan Elango> > Replace multiple if..else if..statements with simple table lookup in two > functions. > > Signed-off-by: Hari Prasath Gujulan Elango > --- > drivers/staging/most/mostcore/core.c | 39 > > 1 file changed, 22 insertions(+), 17 deletions(-) > > diff --git a/drivers/staging/most/mostcore/core.c > b/drivers/staging/most/mostcore/core.c > index ed1ed25..7b4636b 100644 > --- a/drivers/staging/most/mostcore/core.c > +++ b/drivers/staging/most/mostcore/core.c > @@ -82,6 +82,14 @@ struct most_inst_obj { > struct list_head list; > }; > > +static const struct { > + int most_ch_data_type; > + char *name; > +} ch_data_type[] = { { MOST_CH_CONTROL, "control\n" }, > + { MOST_CH_ASYNC, "async\n" }, > + { MOST_CH_SYNC, "sync\n" }, > + { MOST_CH_ISOC_AVP, "isoc_avp\n"} }; > + > #define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) > > /** > @@ -414,14 +422,12 @@ static ssize_t show_set_datatype(struct most_c_obj *c, > struct most_c_attr *attr, > char *buf) > { > - if (c->cfg.data_type & MOST_CH_CONTROL) > - return snprintf(buf, PAGE_SIZE, "control\n"); > - else if (c->cfg.data_type & MOST_CH_ASYNC) > - return snprintf(buf, PAGE_SIZE, "async\n"); > - else if (c->cfg.data_type & MOST_CH_SYNC) > - return snprintf(buf, PAGE_SIZE, "sync\n"); > - else if (c->cfg.data_type & MOST_CH_ISOC_AVP) > - return snprintf(buf, PAGE_SIZE, "isoc_avp\n"); > + int i; > + > + for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { > + if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) > + return snprintf(buf, PAGE_SIZE, ch_data_type[i].name); > + } > return snprintf(buf, PAGE_SIZE, "unconfigured\n"); > } > > @@ -430,15 +436,14 @@ static ssize_t store_set_datatype(struct most_c_obj *c, > const char *buf, > size_t count) > { > - if (!strcmp(buf, "control\n")) { > - c->cfg.data_type = MOST_CH_CONTROL; > - } else if (!strcmp(buf, "async\n")) { > - c->cfg.data_type = MOST_CH_ASYNC; > - } else if (!strcmp(buf, "sync\n")) { > - c->cfg.data_type = MOST_CH_SYNC; > - } else if (!strcmp(buf, "isoc_avp\n")) { > - c->cfg.data_type = MOST_CH_ISOC_AVP; > - } else { > + int i; > + > + for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { > + if (!strcmp(buf, ch_data_type[i].name)) > + c->cfg.data_type = ch_data_type[i].most_ch_data_type; Missing braces and break; > + } > + > + if (i == ARRAY_SIZE(ch_data_type)) { > pr_info("WARN: invalid attribute settings\n"); > return -EINVAL; > } This seems like a lot of code for a simple test. ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH] staging: most: replace multiple if..else with table lookup
From: Hari Prasath Gujulan ElangoReplace multiple if..else if..statements with simple table lookup in two functions. Signed-off-by: Hari Prasath Gujulan Elango --- drivers/staging/most/mostcore/core.c | 39 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c index ed1ed25..7b4636b 100644 --- a/drivers/staging/most/mostcore/core.c +++ b/drivers/staging/most/mostcore/core.c @@ -82,6 +82,14 @@ struct most_inst_obj { struct list_head list; }; +static const struct { + int most_ch_data_type; + char *name; +} ch_data_type[] = { { MOST_CH_CONTROL, "control\n" }, + { MOST_CH_ASYNC, "async\n" }, + { MOST_CH_SYNC, "sync\n" }, + { MOST_CH_ISOC_AVP, "isoc_avp\n"} }; + #define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj) /** @@ -414,14 +422,12 @@ static ssize_t show_set_datatype(struct most_c_obj *c, struct most_c_attr *attr, char *buf) { - if (c->cfg.data_type & MOST_CH_CONTROL) - return snprintf(buf, PAGE_SIZE, "control\n"); - else if (c->cfg.data_type & MOST_CH_ASYNC) - return snprintf(buf, PAGE_SIZE, "async\n"); - else if (c->cfg.data_type & MOST_CH_SYNC) - return snprintf(buf, PAGE_SIZE, "sync\n"); - else if (c->cfg.data_type & MOST_CH_ISOC_AVP) - return snprintf(buf, PAGE_SIZE, "isoc_avp\n"); + int i; + + for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { + if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) + return snprintf(buf, PAGE_SIZE, ch_data_type[i].name); + } return snprintf(buf, PAGE_SIZE, "unconfigured\n"); } @@ -430,15 +436,14 @@ static ssize_t store_set_datatype(struct most_c_obj *c, const char *buf, size_t count) { - if (!strcmp(buf, "control\n")) { - c->cfg.data_type = MOST_CH_CONTROL; - } else if (!strcmp(buf, "async\n")) { - c->cfg.data_type = MOST_CH_ASYNC; - } else if (!strcmp(buf, "sync\n")) { - c->cfg.data_type = MOST_CH_SYNC; - } else if (!strcmp(buf, "isoc_avp\n")) { - c->cfg.data_type = MOST_CH_ISOC_AVP; - } else { + int i; + + for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) { + if (!strcmp(buf, ch_data_type[i].name)) + c->cfg.data_type = ch_data_type[i].most_ch_data_type; + } + + if (i == ARRAY_SIZE(ch_data_type)) { pr_info("WARN: invalid attribute settings\n"); return -EINVAL; } -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V5 0/9] introduce Hyper-V VM Sockets(hvsock
Merry Christmas, everyone! Changes since v1: - updated "[PATCH 6/7] hvsock: introduce Hyper-V VM Sockets feature" - added __init and __exit for the module init/exit functions - net/hv_sock/Kconfig: "default m" -> "default m if HYPERV" - MODULE_LICENSE: "Dual MIT/GPL" -> "Dual BSD/GPL" Changes since v2: - fixed various coding issue pointed out by David Miller - fixed indentation issues - removed pr_debug in net/hv_sock/af_hvsock.c - used reverse-Chrismas-tree style for local variables. - EXPORT_SYMBOL -> EXPORT_SYMBOL_GPL Changes since v3: - fixed a few coding issue pointed by Vitaly Kuznetsov and Dan Carpenter - fixed the ret value in vmbus_recvpacket_hvsock on error - fixed the style of multi-line comment: vmbus_get_hvsock_rw_status() Changes since v4 (https://lkml.org/lkml/2015/7/28/404): - addressed all the comments about V4. - treat the hvsock offers/channels as special VMBus devices - add a mechanism to pass hvsock events to the hvsock driver - fixed some corner cases with proper locking when a connection is closed - rebased to the latest Greg's tree Hyper-V VM Sockets (hvsock) is a byte-stream based communication mechanism between Windowsd 10 (or later) host and a guest. It's kind of TCP over VMBus, but the transportation layer (VMBus) is much simpler than IP. With Hyper-V VM Sockets, applications between the host and a guest can talk with each other directly by the traditional BSD-style socket APIs. The patchset implements the necessary support in the guest side by adding the necessary new APIs in the vmbus driver, and introducing a new driver hv_sock.ko, which implements_a new socket address family AF_HYPERV. I know the kernel has already had a VM Sockets driver (AF_VSOCK) based on VMware's VMCI (net/vmw_vsock/, drivers/misc/vmw_vmci), and KVM is proposing AF_VSOCK of virtio version: http://thread.gmane.org/gmane.linux.network/365205. However, though Hyper-V VM Sockets may seem conceptually similar to AF_VOSCK, there are differences in the transportation layer, and IMO these make the direct code reusing impractical: 1. In AF_VSOCK, the endpoint type is: , but in AF_HYPERV, the endpoint type is: . Here GUID is 128-bit. 2. AF_VSOCK supports SOCK_DGRAM, while AF_HYPERV doesn't. 3. AF_VSOCK supports some special sock opts, like SO_VM_SOCKETS_BUFFER_SIZE, SO_VM_SOCKETS_BUFFER_MIN/MAX_SIZE and SO_VM_SOCKETS_CONNECT_TIMEOUT. These are meaningless to AF_HYPERV. 4. Some AF_VSOCK's VMCI transportation ops are meanless to AF_HYPERV/VMBus, like.notify_recv_init .notify_recv_pre_block .notify_recv_pre_dequeue .notify_recv_post_dequeue .notify_send_init .notify_send_pre_block .notify_send_pre_enqueue .notify_send_post_enqueue etc. So I think we'd better introduce a new address family: AF_HYPERV. Please review the patchset. Looking forward to your comments! Dexuan Cui (9): Drivers: hv: vmbus: add a helper function to set a channel's pending send size Drivers: hv: vmbus: define the new offer type for Hyper-V socket (hvsock) Drivers: hv: vmbus: define a new VMBus message type for hvsock Drivers: hv: ring_buffer: enhance hv_ringbuffer_read() to support hvsock Drivers: hv: vmbus: add APIs to send/recv hvsock packets Drivers: hv: vmbus: add a hvsock flag in struct hv_driver Drivers: hv: vmbus: add a mechanism to pass hvsock events to the hvsock driver Drivers: hv: vmbus: add an API vmbus_hvsock_device_unregister() hvsock: introduce Hyper-V VM Sockets feature MAINTAINERS |2 + drivers/hv/channel.c| 84 ++- drivers/hv/channel_mgmt.c | 53 +- drivers/hv/connection.c |4 +- drivers/hv/hyperv_vmbus.h | 13 +- drivers/hv/ring_buffer.c| 54 +- drivers/hv/vmbus_drv.c |4 + include/linux/hyperv.h | 88 +++ include/linux/socket.h |4 +- include/net/af_hvsock.h | 44 ++ include/uapi/linux/hyperv.h | 16 + net/Kconfig |1 + net/Makefile|1 + net/hv_sock/Kconfig | 10 + net/hv_sock/Makefile|3 + net/hv_sock/af_hvsock.c | 1473 +++ 16 files changed, 1830 insertions(+), 24 deletions(-) create mode 100644 include/net/af_hvsock.h create mode 100644 net/hv_sock/Kconfig create mode 100644 net/hv_sock/Makefile create mode 100644 net/hv_sock/af_hvsock.c -- 2.1.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V5 1/9] Drivers: hv: vmbus: add a helper function to set a channel's pending send size
This will be used by the coming net/hvsock driver. Signed-off-by: Dexuan Cui--- include/linux/hyperv.h | 6 ++ 1 file changed, 6 insertions(+) diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 753dbad..e4867a7 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -790,6 +790,12 @@ static inline void *get_per_channel_state(struct vmbus_channel *c) return c->per_channel_state; } +static inline void set_channel_pending_send_size(struct vmbus_channel *c, +u32 size) +{ + c->outbound.ring_buffer->pending_send_sz = size; +} + void vmbus_onmessage(void *context); int vmbus_request_offers(void); -- 2.1.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V5 8/9] Drivers: hv: vmbus: add an API vmbus_hvsock_device_unregister()
The hvsock driver needs this API to release all the resources related to the channel. Signed-off-by: Dexuan Cui--- drivers/hv/channel_mgmt.c | 33 - drivers/hv/connection.c | 4 ++-- include/linux/hyperv.h| 2 ++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 87fc7d2..f963645 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -195,6 +195,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) vmbus_release_relid(relid); BUG_ON(!channel->rescind); + BUG_ON(!mutex_is_locked(_connection.channel_mutex)); if (channel->target_cpu != get_cpu()) { put_cpu(); @@ -206,9 +207,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) } if (channel->primary_channel == NULL) { - mutex_lock(_connection.channel_mutex); list_del(>listentry); - mutex_unlock(_connection.channel_mutex); primary_channel = channel; } else { @@ -251,6 +250,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) struct vmbus_channel *channel; bool fnew = true; unsigned long flags; + int ret; /* Make sure this is a new offer */ mutex_lock(_connection.channel_mutex); @@ -330,7 +330,11 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) * binding which eventually invokes the device driver's AddDevice() * method. */ - if (vmbus_device_register(newchannel->device_obj) != 0) { + mutex_lock(_connection.channel_mutex); + ret = vmbus_device_register(newchannel->device_obj); + mutex_unlock(_connection.channel_mutex); + + if (ret != 0) { pr_err("unable to add child device object (relid %d)\n", newchannel->offermsg.child_relid); kfree(newchannel->device_obj); @@ -592,6 +596,8 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) struct device *dev; rescind = (struct vmbus_channel_rescind_offer *)hdr; + + mutex_lock(_connection.channel_mutex); channel = relid2channel(rescind->child_relid); if (channel == NULL) { @@ -600,7 +606,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) * vmbus_process_offer(), we have already invoked * vmbus_release_relid() on error. */ - return; + goto out; } spin_lock_irqsave(>lock, flags); @@ -616,7 +622,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) * We can't invoke vmbus_device_unregister() * until the socket fd is closed. */ - return; + goto out; } /* * We will have to unregister this device from the @@ -631,7 +637,24 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) hv_process_channel_removal(channel, channel->offermsg.child_relid); } + +out: + mutex_unlock(_connection.channel_mutex); +} + + +void vmbus_hvsock_device_unregister(struct vmbus_channel *channel) +{ + mutex_lock(_connection.channel_mutex); + + BUG_ON(!is_hvsock_channel(channel)); + + channel->rescind = true; + vmbus_device_unregister(channel->device_obj); + + mutex_unlock(_connection.channel_mutex); } +EXPORT_SYMBOL_GPL(vmbus_hvsock_device_unregister); /* * vmbus_onoffers_delivered - diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 3dc5a9c..deb48e6 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -288,7 +288,8 @@ struct vmbus_channel *relid2channel(u32 relid) struct list_head *cur, *tmp; struct vmbus_channel *cur_sc; - mutex_lock(_connection.channel_mutex); + BUG_ON(!mutex_is_locked(_connection.channel_mutex)); + list_for_each_entry(channel, _connection.chn_list, listentry) { if (channel->offermsg.child_relid == relid) { found_channel = channel; @@ -307,7 +308,6 @@ struct vmbus_channel *relid2channel(u32 relid) } } } - mutex_unlock(_connection.channel_mutex); return found_channel; } diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 7e507bb..8e59f98 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1055,6 +1055,8 @@ int __must_check __vmbus_driver_register(struct hv_driver *hv_driver, const char *mod_name); void vmbus_driver_unregister(struct hv_driver *hv_driver);
[PATCH] staging: dgnc: convert to wait_event_interruptible_timeout
This patch makes use of wait_event_interruptible_timeout to achieve timeout functionality.This is a TODO mentiond in the comment which is also removed. It also aligns with what the function is supposed to do as in the comments. Signed-off-by: Hari Prasath Gujulan Elango--- drivers/staging/dgnc/dgnc_neo.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/staging/dgnc/dgnc_neo.c b/drivers/staging/dgnc/dgnc_neo.c index 39c76e7..7d9efe0 100644 --- a/drivers/staging/dgnc/dgnc_neo.c +++ b/drivers/staging/dgnc/dgnc_neo.c @@ -1306,10 +1306,8 @@ static int neo_drain(struct tty_struct *tty, uint seconds) /* * Go to sleep waiting for the tty layer to wake me back up when * the empty flag goes away. -* -* NOTE: TODO: Do something with time passed in. */ - rc = wait_event_interruptible(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0)); + rc = wait_event_interruptible_timeout(un->un_flags_wait, ((un->un_flags & UN_EMPTY) == 0), msecs_to_jiffies(seconds * 1000)); /* If ret is non-zero, user ctrl-c'ed us */ return rc; -- 1.9.1 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V5 7/9] Drivers: hv: vmbus: add a mechanism to pass hvsock events to the hvsock driver
For now only 1 event is defined: HVSOCK_RESCIND_CHANNEL. We'll have more events in the future. Signed-off-by: Dexuan Cui--- drivers/hv/channel_mgmt.c | 18 ++ include/linux/hyperv.h| 17 + 2 files changed, 35 insertions(+) diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 4611b50..87fc7d2 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -608,6 +608,16 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) spin_unlock_irqrestore(>lock, flags); if (channel->device_obj) { + if (is_hvsock_channel(channel) && + channel->hvsock_event_callback) { + channel->hvsock_event_callback(channel, + HVSOCK_RESCIND_CHANNEL); + /* +* We can't invoke vmbus_device_unregister() +* until the socket fd is closed. +*/ + return; + } /* * We will have to unregister this device from the * driver core. @@ -977,3 +987,11 @@ bool vmbus_are_subchannels_present(struct vmbus_channel *primary) return ret; } EXPORT_SYMBOL_GPL(vmbus_are_subchannels_present); + +void vmbus_set_hvsock_event_callback(struct vmbus_channel *channel, + void (*hvsock_event_callback)(struct vmbus_channel *, + enum hvsock_event)) +{ + channel->hvsock_event_callback = hvsock_event_callback; +} +EXPORT_SYMBOL_GPL(vmbus_set_hvsock_event_callback); diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index b4cc44c..7e507bb 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -645,6 +645,12 @@ enum hv_signal_policy { HV_SIGNAL_POLICY_EXPLICIT, }; +/* hvsock related definitions */ +enum hvsock_event { + /* The host application is close()-ing the connection */ + HVSOCK_RESCIND_CHANNEL, +}; + struct vmbus_channel { /* Unique channel id */ int id; @@ -740,6 +746,13 @@ struct vmbus_channel { void (*sc_creation_callback)(struct vmbus_channel *new_sc); /* +* hvsock event callback. +* For now only 1 event is defined: HVSOCK_RESCIND_CHANNEL. +*/ + void (*hvsock_event_callback)(struct vmbus_channel *channel, + enum hvsock_event event); + + /* * The spinlock to protect the structure. It is being used to protect * test-and-set access to various attributes of the structure as well * as all sc_list operations. @@ -825,6 +838,10 @@ int vmbus_request_offers(void); void vmbus_set_sc_create_callback(struct vmbus_channel *primary_channel, void (*sc_cr_cb)(struct vmbus_channel *new_sc)); +void vmbus_set_hvsock_event_callback(struct vmbus_channel *channel, + void (*hvsock_event_callback)(struct vmbus_channel *, + enum hvsock_event)); + /* * Retrieve the (sub) channel on which to send an outgoing request. * When a primary channel has multiple sub-channels, we choose a -- 2.1.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V5 4/9] Drivers: hv: ring_buffer: enhance hv_ringbuffer_read() to support hvsock
To get the payload of hvsock, we need raw=0 to skip the level-1 header (i.e., struct vmpacket_descriptor desc) and we also need to skip the level-2 header (i.e., struct vmpipe_proto_header pipe_hdr). NB: if the length of the hvsock payload is not aligned with the 8-byte boundeary, at most 7 padding bytes are appended, so the real hvsock payload's length must be retrieved by the pipe_hdr.data_size field. I 'upgrade' the 'raw' parameter of hv_ringbuffer_read() to a 'read_flags', trying to share the logic of the function. This patch is required by the next patch, which will introduce the hvsock send/recv APIs. Signed-off-by: Dexuan CuiCc: Vitaly Kuznetsov --- drivers/hv/channel.c | 10 + drivers/hv/hyperv_vmbus.h | 13 +++- drivers/hv/ring_buffer.c | 54 --- include/linux/hyperv.h| 12 +++ 4 files changed, 72 insertions(+), 17 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index eaaa066..cc49966 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -940,13 +940,14 @@ EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer); static inline int __vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, u32 bufferlen, u32 *buffer_actual_len, u64 *requestid, - bool raw) + u32 read_flags) { int ret; bool signal = false; ret = hv_ringbuffer_read(>inbound, buffer, bufferlen, -buffer_actual_len, requestid, , raw); +buffer_actual_len, requestid, , +read_flags); if (signal) vmbus_setevent(channel); @@ -959,7 +960,7 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, u64 *requestid) { return __vmbus_recvpacket(channel, buffer, bufferlen, - buffer_actual_len, requestid, false); + buffer_actual_len, requestid, 0); } EXPORT_SYMBOL(vmbus_recvpacket); @@ -971,6 +972,7 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer, u64 *requestid) { return __vmbus_recvpacket(channel, buffer, bufferlen, - buffer_actual_len, requestid, true); + buffer_actual_len, requestid, + HV_RINGBUFFER_READ_FLAG_RAW); } EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw); diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 0411b7b..46206b6 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h @@ -619,9 +619,20 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info, struct kvec *kv_list, u32 kv_count, bool *signal); +/* + * By default, a read_flags of 0 means: the payload offset is + * sizeof(struct vmpacket_descriptor). + * + * If HV_RINGBUFFER_READ_FLAG_RAW is used, the payload offset is 0. + * + * If HV_RINGBUFFER_READ_FLAG_HVSOCK is used, the payload offset is + * sizeof(struct vmpacket_descriptor) + sizeof(struct vmpipe_proto_header). + */ +#define HV_RINGBUFFER_READ_FLAG_RAW(1 << 0) +#define HV_RINGBUFFER_READ_FLAG_HVSOCK (1 << 1) int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer, u32 buflen, u32 *buffer_actual_len, - u64 *requestid, bool *signal, bool raw); + u64 *requestid, bool *signal, u32 read_flags); void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, struct hv_ring_buffer_debug_info *debug_info); diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c index b53702c..03a509c 100644 --- a/drivers/hv/ring_buffer.c +++ b/drivers/hv/ring_buffer.c @@ -382,32 +382,43 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info, int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer, u32 buflen, u32 *buffer_actual_len, - u64 *requestid, bool *signal, bool raw) + u64 *requestid, bool *signal, u32 read_flags) { + bool raw = !!(read_flags & HV_RINGBUFFER_READ_FLAG_RAW); + bool hvsock = !!(read_flags & HV_RINGBUFFER_READ_FLAG_HVSOCK); + u32 bytes_avail_towrite; u32 bytes_avail_toread; u32 next_read_location = 0; u64 prev_indices = 0; unsigned long flags; - struct vmpacket_descriptor desc; + struct vmpipe_proto_header *pipe_hdr; + struct vmpacket_descriptor *desc; u32 offset; - u32 packetlen; + u32 packetlen, tot_hdrlen; int ret = 0; if (buflen <= 0) return -EINVAL; + tot_hdrlen = sizeof(*desc); + if (hvsock) + tot_hdrlen +=
[PATCH V5 9/9] hvsock: introduce Hyper-V VM Sockets feature
Hyper-V VM sockets (hvsock) supplies a byte-stream based communication mechanism between the host and a guest. It's kind of TCP over VMBus, but the transportation layer (VMBus) is much simpler than IP. With Hyper-V VM Sockets, applications between the host and a guest can talk with each other directly by the traditional BSD-style socket APIs. Hyper-V VM Sockets is only available on Windows 10 host and later. The patch implements the necessary support in the guest side by introducing a new socket address family AF_HYPERV. Signed-off-by: Dexuan Cui--- MAINTAINERS |2 + include/linux/hyperv.h |8 + include/linux/socket.h |4 +- include/net/af_hvsock.h | 44 ++ include/uapi/linux/hyperv.h | 16 + net/Kconfig |1 + net/Makefile|1 + net/hv_sock/Kconfig | 10 + net/hv_sock/Makefile|3 + net/hv_sock/af_hvsock.c | 1473 +++ 10 files changed, 1561 insertions(+), 1 deletion(-) create mode 100644 include/net/af_hvsock.h create mode 100644 net/hv_sock/Kconfig create mode 100644 net/hv_sock/Makefile create mode 100644 net/hv_sock/af_hvsock.c diff --git a/MAINTAINERS b/MAINTAINERS index 44666b1..f89a4ba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5156,7 +5156,9 @@ F:drivers/input/serio/hyperv-keyboard.c F: drivers/net/hyperv/ F: drivers/scsi/storvsc_drv.c F: drivers/video/fbdev/hyperv_fb.c +F: net/hv_sock/ F: include/linux/hyperv.h +F: include/net/af_hvsock.h F: tools/hv/ F: Documentation/ABI/stable/sysfs-bus-vmbus diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 8e59f98..3495762 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1322,4 +1322,12 @@ struct vmpipe_proto_header { #define HVSOCK_HEADER_LEN (sizeof(struct vmpacket_descriptor) + \ sizeof(struct vmpipe_proto_header)) +/* See 'prev_indices' in hv_ringbuffer_read(), hv_ringbuffer_write() */ +#define PREV_INDICES_LEN (sizeof(u64)) + +#define HVSOCK_PKT_LEN(payload_len)(HVSOCK_HEADER_LEN + \ + ALIGN((payload_len), 8) + \ + PREV_INDICES_LEN) +#define HVSOCK_MIN_PKT_LEN HVSOCK_PKT_LEN(1) + #endif /* _HYPERV_H */ diff --git a/include/linux/socket.h b/include/linux/socket.h index 5bf59c8..d5ef612 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -200,7 +200,8 @@ struct ucred { #define AF_ALG 38 /* Algorithm sockets*/ #define AF_NFC 39 /* NFC sockets */ #define AF_VSOCK 40 /* vSockets */ -#define AF_MAX 41 /* For now.. */ +#define AF_HYPERV 41 /* Hyper-V virtual sockets */ +#define AF_MAX 42 /* For now.. */ /* Protocol families, same as address families. */ #define PF_UNSPEC AF_UNSPEC @@ -246,6 +247,7 @@ struct ucred { #define PF_ALG AF_ALG #define PF_NFC AF_NFC #define PF_VSOCK AF_VSOCK +#define PF_HYPERV AF_HYPERV #define PF_MAX AF_MAX /* Maximum queue length specifiable by listen. */ diff --git a/include/net/af_hvsock.h b/include/net/af_hvsock.h new file mode 100644 index 000..9951658 --- /dev/null +++ b/include/net/af_hvsock.h @@ -0,0 +1,44 @@ +#ifndef __AF_HVSOCK_H__ +#define __AF_HVSOCK_H__ + +#include +#include +#include + +#define VMBUS_RINGBUFFER_SIZE_HVSOCK_RECV (5 * PAGE_SIZE) +#define VMBUS_RINGBUFFER_SIZE_HVSOCK_SEND (5 * PAGE_SIZE) + +#define HVSOCK_RCV_BUF_SZ VMBUS_RINGBUFFER_SIZE_HVSOCK_RECV +#define HVSOCK_SND_BUF_SZ PAGE_SIZE + +#define sk_to_hvsock(__sk)((struct hvsock_sock *)(__sk)) +#define hvsock_to_sk(__hvsk) ((struct sock *)(__hvsk)) + +struct hvsock_sock { + /* sk must be the first member. */ + struct sock sk; + + struct sockaddr_hv local_addr; + struct sockaddr_hv remote_addr; + + /* protected by the global hvsock_mutex */ + struct list_head bound_list; + struct list_head connected_list; + + struct list_head accept_queue; + /* used by enqueue and dequeue */ + struct mutex accept_queue_mutex; + + struct delayed_work dwork; + + u32 peer_shutdown; + + struct vmbus_channel *channel; + + char send_buf[HVSOCK_SND_BUF_SZ]; + char recv_buf[HVSOCK_RCV_BUF_SZ]; + unsigned int recv_data_len; + unsigned int recv_data_offset; +}; + +#endif /* __AF_HVSOCK_H__ */ diff --git a/include/uapi/linux/hyperv.h b/include/uapi/linux/hyperv.h index e347b24..ded4c13 100644 --- a/include/uapi/linux/hyperv.h +++ b/include/uapi/linux/hyperv.h @@ -26,6 +26,7 @@ #define _UAPI_HYPERV_H #include +#include /* * Framework version for util services. @@ -396,4 +397,19 @@ struct hv_kvp_ip_msg { struct hv_kvp_ipaddr_value kvp_ip_val; }
[PATCH V5 5/9] Drivers: hv: vmbus: add APIs to send/recv hvsock packets
This will be used by the coming net/hvsock driver. Signed-off-by: Dexuan Cui--- drivers/hv/channel.c | 59 ++ include/linux/hyperv.h | 9 2 files changed, 68 insertions(+) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index cc49966..ce1b885 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -924,6 +924,52 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel, } EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer); +/* + * vmbus_sendpacket_hvsock - Send the hvsock payload 'buf' of a length 'len' + */ +int vmbus_sendpacket_hvsock(struct vmbus_channel *channel, void *buf, u32 len) +{ + struct vmpipe_proto_header pipe_hdr; + struct vmpacket_descriptor desc; + struct kvec bufferlist[4]; + u32 packetlen_aligned; + u32 packetlen; + u64 aligned_data = 0; + bool signal = false; + int ret; + + packetlen = HVSOCK_HEADER_LEN + len; + packetlen_aligned = ALIGN(packetlen, sizeof(u64)); + + /* Setup the descriptor */ + desc.type = VM_PKT_DATA_INBAND; + /* in 8-bytes granularity */ + desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3; + desc.len8 = (u16)(packetlen_aligned >> 3); + desc.flags = 0; + desc.trans_id = 0; + + pipe_hdr.pkt_type = 1; + pipe_hdr.data_size = len; + + bufferlist[0].iov_base = + bufferlist[0].iov_len = sizeof(struct vmpacket_descriptor); + bufferlist[1].iov_base = _hdr; + bufferlist[1].iov_len = sizeof(struct vmpipe_proto_header); + bufferlist[2].iov_base = buf; + bufferlist[2].iov_len = len; + bufferlist[3].iov_base = _data; + bufferlist[3].iov_len = packetlen_aligned - packetlen; + + ret = hv_ringbuffer_write(>outbound, bufferlist, 4, ); + + if (ret == 0 && signal) + vmbus_setevent(channel); + + return ret; +} +EXPORT_SYMBOL_GPL(vmbus_sendpacket_hvsock); + /** * vmbus_recvpacket() - Retrieve the user packet on the specified channel * @channel: Pointer to vmbus_channel structure. @@ -976,3 +1022,16 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer, HV_RINGBUFFER_READ_FLAG_RAW); } EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw); + +/* + * vmbus_recvpacket_hvsock - Receive the hvsock payload from the vmbus + * ringbuffer into the 'buffer'. + */ +int vmbus_recvpacket_hvsock(struct vmbus_channel *channel, void *buffer, + u32 bufferlen, u32 *buffer_actual_len) +{ + return __vmbus_recvpacket(channel, buffer, bufferlen, + buffer_actual_len, NULL, + HV_RINGBUFFER_READ_FLAG_HVSOCK); +} +EXPORT_SYMBOL_GPL(vmbus_recvpacket_hvsock); diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index e005223..646c20d 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -908,6 +908,9 @@ extern int vmbus_sendpacket_ctl(struct vmbus_channel *channel, u32 flags, bool kick_q); +extern int vmbus_sendpacket_hvsock(struct vmbus_channel *channel, + void *buf, u32 len); + extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, struct hv_page_buffer pagebuffers[], u32 pagecount, @@ -958,6 +961,9 @@ extern int vmbus_recvpacket_raw(struct vmbus_channel *channel, u64 *requestid); +extern int vmbus_recvpacket_hvsock(struct vmbus_channel *channel, void *buffer, + u32 bufferlen, u32 *buffer_actual_len); + extern void vmbus_ontimer(unsigned long data); /* Base driver object */ @@ -1280,4 +1286,7 @@ struct vmpipe_proto_header { }; } __packed; +#define HVSOCK_HEADER_LEN (sizeof(struct vmpacket_descriptor) + \ +sizeof(struct vmpipe_proto_header)) + #endif /* _HYPERV_H */ -- 2.1.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V5 2/9] Drivers: hv: vmbus: define the new offer type for Hyper-V socket (hvsock)
A helper function is also added. Signed-off-by: Dexuan Cui--- include/linux/hyperv.h | 7 +++ 1 file changed, 7 insertions(+) diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index e4867a7..c0eddd7 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -235,6 +235,7 @@ struct vmbus_channel_offer { #define VMBUS_CHANNEL_LOOPBACK_OFFER 0x100 #define VMBUS_CHANNEL_PARENT_OFFER 0x200 #define VMBUS_CHANNEL_REQUEST_MONITORED_NOTIFICATION 0x400 +#define VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER 0x2000 struct vmpacket_descriptor { u16 type; @@ -769,6 +770,12 @@ struct vmbus_channel { enum hv_signal_policy signal_policy; }; +static inline bool is_hvsock_channel(const struct vmbus_channel *c) +{ + return !!(c->offermsg.offer.chn_flags & + VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER); +} + static inline void set_channel_signal_state(struct vmbus_channel *c, enum hv_signal_policy policy) { -- 2.1.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V5 6/9] Drivers: hv: vmbus: add a hvsock flag in struct hv_driver
Only the coming hv_sock driver has a "true" value for this flag. We treat the hvsock offers/channels as special VMBus devices. Since the hv_sock driver handles all the hvsock offers/channels, we need to tweak vmbus_match() for hv_sock driver, so we introduce this flag. Signed-off-by: Dexuan Cui--- drivers/hv/vmbus_drv.c | 4 include/linux/hyperv.h | 14 ++ 2 files changed, 18 insertions(+) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 328e4c3..c1c9d71 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -562,6 +562,10 @@ static int vmbus_match(struct device *device, struct device_driver *driver) struct hv_driver *drv = drv_to_hv_drv(driver); struct hv_device *hv_dev = device_to_hv_device(device); + /* The hv_sock driver handles all hv_sock offers. */ + if (is_hvsock_channel(hv_dev->channel)) + return drv->hvsock; + if (hv_vmbus_get_id(drv->id_table, _dev->dev_type)) return 1; diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 646c20d..b4cc44c 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -970,6 +970,20 @@ extern void vmbus_ontimer(unsigned long data); struct hv_driver { const char *name; + /* +* A hvsock offer, which has a VMBUS_CHANNEL_TLNPI_PROVIDER_OFFER +* channel flag, actually doesn't mean a synthetic device because the +* offer's if_type/if_instance can change for every new hvsock +* connection. +* +* However, to facilitate the notification of new-offer/rescind-offer +* from vmbus driver to hvsock driver, we can handle hvsock offer as +* a special vmbus device, and hence we need the below flag to +* indicate if the driver is the hvsock driver or not: we need to +* specially treat the hvosck offer & driver in vmbus_match(). +*/ + bool hvsock; + /* the device type supported by this driver */ uuid_le dev_type; const struct hv_vmbus_device_id *id_table; -- 2.1.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
[PATCH V5 3/9] Drivers: hv: vmbus: define a new VMBus message type for hvsock
A function to send the type of message is also added. The coming net/hvsock driver will use this function to proactively request the host to offer a VMBus channel for a new hvsock connection. Signed-off-by: Dexuan Cui--- drivers/hv/channel.c | 15 +++ drivers/hv/channel_mgmt.c | 4 include/linux/hyperv.h| 13 + 3 files changed, 32 insertions(+) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 1161d68..eaaa066 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -219,6 +219,21 @@ error0: } EXPORT_SYMBOL_GPL(vmbus_open); +/* Used for Hyper-V Socket: a guest client's connect() to the host */ +int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id, + const uuid_le *shv_host_servie_id) +{ + struct vmbus_channel_tl_connect_request conn_msg; + + memset(_msg, 0, sizeof(conn_msg)); + conn_msg.header.msgtype = CHANNELMSG_TL_CONNECT_REQUEST; + conn_msg.guest_endpoint_id = *shv_guest_servie_id; + conn_msg.host_service_id = *shv_host_servie_id; + + return vmbus_post_msg(_msg, sizeof(conn_msg)); +} +EXPORT_SYMBOL_GPL(vmbus_send_tl_connect_request); + /* * create_gpadl_header - Creates a gpadl for the specified buffer */ diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 1c1ad47..4611b50 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -825,6 +825,10 @@ struct vmbus_channel_message_table_entry {CHANNELMSG_VERSION_RESPONSE, 1, vmbus_onversion_response}, {CHANNELMSG_UNLOAD, 0, NULL}, {CHANNELMSG_UNLOAD_RESPONSE,1, vmbus_unload_response}, + {CHANNELMSG_18, 0, NULL}, + {CHANNELMSG_19, 0, NULL}, + {CHANNELMSG_20, 0, NULL}, + {CHANNELMSG_TL_CONNECT_REQUEST, 0, NULL}, }; /* diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index c0eddd7..b835d80 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -392,6 +392,10 @@ enum vmbus_channel_message_type { CHANNELMSG_VERSION_RESPONSE = 15, CHANNELMSG_UNLOAD = 16, CHANNELMSG_UNLOAD_RESPONSE = 17, + CHANNELMSG_18 = 18, + CHANNELMSG_19 = 19, + CHANNELMSG_20 = 20, + CHANNELMSG_TL_CONNECT_REQUEST = 21, CHANNELMSG_COUNT }; @@ -562,6 +566,13 @@ struct vmbus_channel_initiate_contact { u64 monitor_page2; } __packed; +/* Hyper-V socket: guest's connect()-ing to host */ +struct vmbus_channel_tl_connect_request { + struct vmbus_channel_message_header header; + uuid_le guest_endpoint_id; + uuid_le host_service_id; +} __packed; + struct vmbus_channel_version_response { struct vmbus_channel_message_header header; u8 version_supported; @@ -1255,4 +1266,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid); extern __u32 vmbus_proto_version; +int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id, + const uuid_le *shv_host_servie_id); #endif /* _HYPERV_H */ -- 2.1.4 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel