* [PATCH 0/3] Drivers: hv: vmbus: Miscellaneous fixes
@ 2018-08-02 3:07 kys
2018-08-02 3:08 ` [PATCH 1/3] Drivers: hv: vmbus: Reset the channel callback in vmbus_onoffer_rescind() kys
0 siblings, 1 reply; 4+ messages in thread
From: kys @ 2018-08-02 3:07 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, olaf, apw, jasowang, sthemmin,
Michael.H.Kelley, vkuznets
Cc: K. Y. Srinivasan
From: "K. Y. Srinivasan" <kys@microsoft.com>
Miscellaneous fixes.
Dexuan Cui (1):
Drivers: hv: vmbus: Reset the channel callback in
vmbus_onoffer_rescind()
Michael Kelley (2):
Drivers: hv: vmbus: Remove use of slow_virt_to_phys()
Drivers: hv: vmbus: Cleanup synic memory free path
drivers/hv/channel.c | 67 +++++++++++++++++++++++++--------------
drivers/hv/channel_mgmt.c | 6 ++++
drivers/hv/hv.c | 14 ++++----
include/linux/hyperv.h | 2 ++
4 files changed, 60 insertions(+), 29 deletions(-)
--
2.17.1
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 1/3] Drivers: hv: vmbus: Reset the channel callback in vmbus_onoffer_rescind() 2018-08-02 3:07 [PATCH 0/3] Drivers: hv: vmbus: Miscellaneous fixes kys @ 2018-08-02 3:08 ` kys 2018-08-02 3:08 ` [PATCH 2/3] Drivers: hv: vmbus: Remove use of slow_virt_to_phys() kys 2018-08-02 3:08 ` [PATCH 3/3] Drivers: hv: vmbus: Cleanup synic memory free path kys 0 siblings, 2 replies; 4+ messages in thread From: kys @ 2018-08-02 3:08 UTC (permalink / raw) To: gregkh, linux-kernel, devel, olaf, apw, jasowang, sthemmin, Michael.H.Kelley, vkuznets Cc: Dexuan Cui, stable, K . Y . Srinivasan, Michael Kelley From: Dexuan Cui <decui@microsoft.com> Before setting channel->rescind in vmbus_rescind_cleanup(), we should make sure the channel callback won't run any more, otherwise a high-level driver like pci_hyperv, which may be infinitely waiting for the host VSP's response and notices the channel has been rescinded, can't safely give up: e.g., in hv_pci_protocol_negotiation() -> wait_for_response(), it's unsafe to exit from wait_for_response() and proceed with the on-stack variable "comp_pkt" popped. The issue was originally spotted by Michael Kelley <mikelley@microsoft.com>. In vmbus_close_internal(), the patch also minimizes the range protected by disabling/enabling channel->callback_event: we don't really need that for the whole function. Signed-off-by: Dexuan Cui <decui@microsoft.com> Reviewed-by: Michael Kelley <mikelley@microsoft.com> Cc: stable@vger.kernel.org Cc: K. Y. Srinivasan <kys@microsoft.com> Cc: Stephen Hemminger <sthemmin@microsoft.com> Cc: Michael Kelley <mikelley@microsoft.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> --- drivers/hv/channel.c | 40 +++++++++++++++++++++++---------------- drivers/hv/channel_mgmt.c | 6 ++++++ include/linux/hyperv.h | 2 ++ 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index ba0a092ae085..c3949220b770 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -558,11 +558,8 @@ static void reset_channel_cb(void *arg) channel->onchannel_callback = NULL; } -static int vmbus_close_internal(struct vmbus_channel *channel) +void vmbus_reset_channel_cb(struct vmbus_channel *channel) { - struct vmbus_channel_close_channel *msg; - int ret; - /* * vmbus_on_event(), running in the per-channel tasklet, can race * with vmbus_close_internal() in the case of SMP guest, e.g., when @@ -572,6 +569,29 @@ static int vmbus_close_internal(struct vmbus_channel *channel) */ tasklet_disable(&channel->callback_event); + channel->sc_creation_callback = NULL; + + /* Stop the callback asap */ + if (channel->target_cpu != get_cpu()) { + put_cpu(); + smp_call_function_single(channel->target_cpu, reset_channel_cb, + channel, true); + } else { + reset_channel_cb(channel); + put_cpu(); + } + + /* Re-enable tasklet for use on re-open */ + tasklet_enable(&channel->callback_event); +} + +static int vmbus_close_internal(struct vmbus_channel *channel) +{ + struct vmbus_channel_close_channel *msg; + int ret; + + vmbus_reset_channel_cb(channel); + /* * In case a device driver's probe() fails (e.g., * util_probe() -> vmbus_open() returns -ENOMEM) and the device is @@ -585,16 +605,6 @@ static int vmbus_close_internal(struct vmbus_channel *channel) } channel->state = CHANNEL_OPEN_STATE; - channel->sc_creation_callback = NULL; - /* Stop callback and cancel the timer asap */ - if (channel->target_cpu != get_cpu()) { - put_cpu(); - smp_call_function_single(channel->target_cpu, reset_channel_cb, - channel, true); - } else { - reset_channel_cb(channel); - put_cpu(); - } /* Send a closing message */ @@ -639,8 +649,6 @@ static int vmbus_close_internal(struct vmbus_channel *channel) get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); out: - /* re-enable tasklet for use on re-open */ - tasklet_enable(&channel->callback_event); return ret; } diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index f3b551a50653..0f0e091c117c 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -892,6 +892,12 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) return; } + /* + * Before setting channel->rescind in vmbus_rescind_cleanup(), we + * should make sure the channel callback is not running any more. + */ + vmbus_reset_channel_cb(channel); + /* * Now wait for offer handling to complete. */ diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 2330f08062c7..efda23cf32c7 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1061,6 +1061,8 @@ extern int vmbus_establish_gpadl(struct vmbus_channel *channel, extern int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle); +void vmbus_reset_channel_cb(struct vmbus_channel *channel); + extern int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, u32 bufferlen, -- 2.17.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] Drivers: hv: vmbus: Remove use of slow_virt_to_phys() 2018-08-02 3:08 ` [PATCH 1/3] Drivers: hv: vmbus: Reset the channel callback in vmbus_onoffer_rescind() kys @ 2018-08-02 3:08 ` kys 2018-08-02 3:08 ` [PATCH 3/3] Drivers: hv: vmbus: Cleanup synic memory free path kys 1 sibling, 0 replies; 4+ messages in thread From: kys @ 2018-08-02 3:08 UTC (permalink / raw) To: gregkh, linux-kernel, devel, olaf, apw, jasowang, sthemmin, Michael.H.Kelley, vkuznets Cc: Michael Kelley, K . Y . Srinivasan From: Michael Kelley <mikelley@microsoft.com> slow_virt_to_phys() is only implemented for arch/x86. Remove its use in arch independent Hyper-V drivers, and replace with test for vmalloc() address followed by appropriate v-to-p function. This follows the typical pattern of other drivers and avoids the need to implement slow_virt_to_phys() for Hyper-V on ARM64. Signed-off-by: Michael Kelley <mikelley@microsoft.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> --- drivers/hv/channel.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index c3949220b770..741857d80da1 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -29,12 +29,26 @@ #include <linux/hyperv.h> #include <linux/uio.h> #include <linux/interrupt.h> +#include <asm/page.h> #include "hyperv_vmbus.h" #define NUM_PAGES_SPANNED(addr, len) \ ((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT)) +static unsigned long virt_to_hvpfn(void *addr) +{ + unsigned long paddr; + + if (is_vmalloc_addr(addr)) + paddr = page_to_phys(vmalloc_to_page(addr)) + + offset_in_page(addr); + else + paddr = __pa(addr); + + return paddr >> PAGE_SHIFT; +} + /* * vmbus_setevent- Trigger an event notification on the specified * channel. @@ -298,8 +312,8 @@ static int create_gpadl_header(void *kbuffer, u32 size, gpadl_header->range[0].byte_offset = 0; gpadl_header->range[0].byte_count = size; for (i = 0; i < pfncount; i++) - gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys( - kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT; + gpadl_header->range[0].pfn_array[i] = virt_to_hvpfn( + kbuffer + PAGE_SIZE * i); *msginfo = msgheader; pfnsum = pfncount; @@ -350,9 +364,8 @@ static int create_gpadl_header(void *kbuffer, u32 size, * so the hypervisor guarantees that this is ok. */ for (i = 0; i < pfncurr; i++) - gpadl_body->pfn[i] = slow_virt_to_phys( - kbuffer + PAGE_SIZE * (pfnsum + i)) >> - PAGE_SHIFT; + gpadl_body->pfn[i] = virt_to_hvpfn( + kbuffer + PAGE_SIZE * (pfnsum + i)); /* add to msg header */ list_add_tail(&msgbody->msglistentry, @@ -380,8 +393,8 @@ static int create_gpadl_header(void *kbuffer, u32 size, gpadl_header->range[0].byte_offset = 0; gpadl_header->range[0].byte_count = size; for (i = 0; i < pagecount; i++) - gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys( - kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT; + gpadl_header->range[0].pfn_array[i] = virt_to_hvpfn( + kbuffer + PAGE_SIZE * i); *msginfo = msgheader; } -- 2.17.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] Drivers: hv: vmbus: Cleanup synic memory free path 2018-08-02 3:08 ` [PATCH 1/3] Drivers: hv: vmbus: Reset the channel callback in vmbus_onoffer_rescind() kys 2018-08-02 3:08 ` [PATCH 2/3] Drivers: hv: vmbus: Remove use of slow_virt_to_phys() kys @ 2018-08-02 3:08 ` kys 1 sibling, 0 replies; 4+ messages in thread From: kys @ 2018-08-02 3:08 UTC (permalink / raw) To: gregkh, linux-kernel, devel, olaf, apw, jasowang, sthemmin, Michael.H.Kelley, vkuznets Cc: Michael Kelley, K . Y . Srinivasan From: Michael Kelley <mikelley@microsoft.com> clk_evt memory is not being freed when the synic is shutdown or when there is an allocation error. Add the appropriate kfree() call, along with a comment to clarify how the memory gets freed after an allocation error. Make the free path consistent by removing checks for NULL since kfree() and free_page() already do the check. Signed-off-by: Michael Kelley <mikelley@microsoft.com> Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> --- drivers/hv/hv.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 312fe5ed7c40..748a1c4172a6 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c @@ -242,6 +242,10 @@ int hv_synic_alloc(void) return 0; err: + /* + * Any memory allocations that succeeded will be freed when + * the caller cleans up by calling hv_synic_free() + */ return -ENOMEM; } @@ -254,12 +258,10 @@ void hv_synic_free(void) struct hv_per_cpu_context *hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu); - if (hv_cpu->synic_event_page) - free_page((unsigned long)hv_cpu->synic_event_page); - if (hv_cpu->synic_message_page) - free_page((unsigned long)hv_cpu->synic_message_page); - if (hv_cpu->post_msg_page) - free_page((unsigned long)hv_cpu->post_msg_page); + kfree(hv_cpu->clk_evt); + free_page((unsigned long)hv_cpu->synic_event_page); + free_page((unsigned long)hv_cpu->synic_message_page); + free_page((unsigned long)hv_cpu->post_msg_page); } kfree(hv_context.hv_numa_map); -- 2.17.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2018-08-02 3:09 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2018-08-02 3:07 [PATCH 0/3] Drivers: hv: vmbus: Miscellaneous fixes kys 2018-08-02 3:08 ` [PATCH 1/3] Drivers: hv: vmbus: Reset the channel callback in vmbus_onoffer_rescind() kys 2018-08-02 3:08 ` [PATCH 2/3] Drivers: hv: vmbus: Remove use of slow_virt_to_phys() kys 2018-08-02 3:08 ` [PATCH 3/3] Drivers: hv: vmbus: Cleanup synic memory free path kys
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox