| From b9830d120cbe155863399f25eaef6aa8353e767f Mon Sep 17 00:00:00 2001 |
| From: "K. Y. Srinivasan" <kys@microsoft.com> |
| Date: Fri, 26 Feb 2016 15:13:19 -0800 |
| Subject: Drivers: hv: util: Pass the channel information during the init call |
| |
| From: K. Y. Srinivasan <kys@microsoft.com> |
| |
| commit b9830d120cbe155863399f25eaef6aa8353e767f upstream. |
| |
| Pass the channel information to the util drivers that need to defer |
| reading the channel while they are processing a request. This would address |
| the following issue reported by Vitaly: |
| |
| Commit 3cace4a61610 ("Drivers: hv: utils: run polling callback always in |
| interrupt context") removed direct *_transaction.state = HVUTIL_READY |
| assignments from *_handle_handshake() functions introducing the following |
| race: if a userspace daemon connects before we get first non-negotiation |
| request from the server hv_poll_channel() won't set transaction state to |
| HVUTIL_READY as (!channel) condition will fail, we set it to non-NULL on |
| the first real request from the server. |
| |
| Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> |
| Reported-by: Vitaly Kuznetsov <vkuznets@redhat.com> |
| Signed-off-by: Dexuan Cui <decui@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/hv/hv_fcopy.c | 2 +- |
| drivers/hv/hv_kvp.c | 2 +- |
| drivers/hv/hv_snapshot.c | 2 +- |
| drivers/hv/hv_util.c | 1 + |
| include/linux/hyperv.h | 1 + |
| 5 files changed, 5 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/hv/hv_fcopy.c |
| +++ b/drivers/hv/hv_fcopy.c |
| @@ -256,7 +256,6 @@ void hv_fcopy_onchannelcallback(void *co |
| */ |
| |
| fcopy_transaction.recv_len = recvlen; |
| - fcopy_transaction.recv_channel = channel; |
| fcopy_transaction.recv_req_id = requestid; |
| fcopy_transaction.fcopy_msg = fcopy_msg; |
| |
| @@ -323,6 +322,7 @@ static void fcopy_on_reset(void) |
| int hv_fcopy_init(struct hv_util_service *srv) |
| { |
| recv_buffer = srv->recv_buffer; |
| + fcopy_transaction.recv_channel = srv->channel; |
| |
| init_completion(&release_event); |
| /* |
| --- a/drivers/hv/hv_kvp.c |
| +++ b/drivers/hv/hv_kvp.c |
| @@ -640,7 +640,6 @@ void hv_kvp_onchannelcallback(void *cont |
| */ |
| |
| kvp_transaction.recv_len = recvlen; |
| - kvp_transaction.recv_channel = channel; |
| kvp_transaction.recv_req_id = requestid; |
| kvp_transaction.kvp_msg = kvp_msg; |
| |
| @@ -690,6 +689,7 @@ int |
| hv_kvp_init(struct hv_util_service *srv) |
| { |
| recv_buffer = srv->recv_buffer; |
| + kvp_transaction.recv_channel = srv->channel; |
| |
| init_completion(&release_event); |
| /* |
| --- a/drivers/hv/hv_snapshot.c |
| +++ b/drivers/hv/hv_snapshot.c |
| @@ -264,7 +264,6 @@ void hv_vss_onchannelcallback(void *cont |
| */ |
| |
| vss_transaction.recv_len = recvlen; |
| - vss_transaction.recv_channel = channel; |
| vss_transaction.recv_req_id = requestid; |
| vss_transaction.msg = (struct hv_vss_msg *)vss_msg; |
| |
| @@ -340,6 +339,7 @@ hv_vss_init(struct hv_util_service *srv) |
| return -ENOTSUPP; |
| } |
| recv_buffer = srv->recv_buffer; |
| + vss_transaction.recv_channel = srv->channel; |
| |
| /* |
| * When this driver loads, the user level daemon that |
| --- a/drivers/hv/hv_util.c |
| +++ b/drivers/hv/hv_util.c |
| @@ -326,6 +326,7 @@ static int util_probe(struct hv_device * |
| srv->recv_buffer = kmalloc(PAGE_SIZE * 4, GFP_KERNEL); |
| if (!srv->recv_buffer) |
| return -ENOMEM; |
| + srv->channel = dev->channel; |
| if (srv->util_init) { |
| ret = srv->util_init(srv); |
| if (ret) { |
| --- a/include/linux/hyperv.h |
| +++ b/include/linux/hyperv.h |
| @@ -1179,6 +1179,7 @@ int vmbus_allocate_mmio(struct resource |
| |
| struct hv_util_service { |
| u8 *recv_buffer; |
| + void *channel; |
| void (*util_cb)(void *); |
| int (*util_init)(struct hv_util_service *); |
| void (*util_deinit)(void); |