From: Emerson Busson <emersonbusson@gmail.com>
To: mhklinux@outlook.com
Cc: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org,
decui@microsoft.com, andrew+netdev@lunn.ch, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org,
linux-hyperv@vger.kernel.org, netdev@vger.kernel.org
Subject: [PATCH v2 12/14] hv: netvsc: allocate RNDIS request descriptors with kvzalloc_obj()
Date: Wed, 7 Oct 2026 16:07:50 -0300 [thread overview]
Message-ID: <20261007190752.336426-13-emersonbusson@gmail.com> (raw)
In-Reply-To: <20261007190752.336426-1-emersonbusson@gmail.com>
struct rndis_request embeds two RNDIS_EXT_LEN protocol tails.
RNDIS_EXT_LEN is HV_HYP_PAGE_SIZE, so the two tails alone are 8 KiB and
the struct is just over KMALLOC_MAX_CACHE_SIZE. kzalloc_obj() therefore
needs an order-2 compound page for every RNDIS control request, which can
fail under buddy fragmentation.
Use kvzalloc_obj() and kvfree() so allocation can fall back to vmalloc.
RNDIS control payloads are sent as GPA-direct page buffers, however, so a
vmalloc-backed descriptor cannot be described by one virt_to_phys() PFN.
Build one hv_page_buffer per Linux/Hyper-V page and resolve vmalloc backing
with vmalloc_to_page(). Linear allocations use virt_to_page(). This keeps
the GPA list valid and preserves the existing per-range DMA mapping for
isolated guests.
Keep both protocol tails unchanged. The response is copied after
request->response_msg into response_ext, within the existing
sizeof(struct rndis_message) + RNDIS_EXT_LEN bound.
Adds a fifth named RNDIS request KUnit case. It builds GPA descriptors from
a vmalloc buffer that crosses a page boundary and checks every PFN, offset,
and length against the backing pages. The existing cases retain the
allocation-size, response-layout, zeroing, request-id, and cleanup checks.
Rollback trigger: revert if the vmalloc page-buffer KUnit case fails or an
exact-source fragmented rebind shows malformed GPA descriptors from this
path.
Fixes: 5b54dac856cb ("hyperv: Add support for virtual Receive Side Scaling (vRSS)")
Signed-off-by: Emerson Busson <emersonbusson@gmail.com>
---
drivers/net/hyperv/Kconfig | 12 ++
drivers/net/hyperv/Makefile | 1 +
drivers/net/hyperv/hyperv_net.h | 43 ++++-
drivers/net/hyperv/rndis_filter.c | 117 ++++++++-----
drivers/net/hyperv/rndis_request_test.c | 216 ++++++++++++++++++++++++
5 files changed, 349 insertions(+), 40 deletions(-)
create mode 100644 drivers/net/hyperv/rndis_request_test.c
diff --git a/drivers/net/hyperv/Kconfig b/drivers/net/hyperv/Kconfig
index 982964c1a9fb..226728fd77d7 100644
--- a/drivers/net/hyperv/Kconfig
+++ b/drivers/net/hyperv/Kconfig
@@ -6,3 +6,15 @@ config HYPERV_NET
select NLS
help
Select this option to enable the Hyper-V virtual network driver.
+
+config HYPERV_NET_KUNIT_TEST
+ bool "Build Hyper-V netvsc KUnit tests"
+ depends on HYPERV_NET && KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ Build the netvsc KUnit test suites into the hv_netvsc object.
+ Built into the module rather than as a separate one so the
+ cases can reach the internal helpers declared in hyperv_net.h
+ without exporting them.
+
+ If unsure, say N.
diff --git a/drivers/net/hyperv/Makefile b/drivers/net/hyperv/Makefile
index 0db7ccaec4a4..6f1abc756fde 100644
--- a/drivers/net/hyperv/Makefile
+++ b/drivers/net/hyperv/Makefile
@@ -2,3 +2,4 @@
obj-$(CONFIG_HYPERV_NET) += hv_netvsc.o
hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o netvsc_trace.o netvsc_bpf.o
+hv_netvsc-$(CONFIG_HYPERV_NET_KUNIT_TEST) += rndis_request_test.o
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index a15cb2460344..6492e7e93ded 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -210,14 +210,25 @@ struct rndis_device {
u8 rss_key[NETVSC_HASH_KEYLEN];
};
+#define RNDIS_EXT_LEN HV_HYP_PAGE_SIZE
-/* Interface */
+/* Full definitions are below, after the RNDIS message format. */
+struct rndis_request;
struct rndis_message;
+
+/* Interface */
struct ndis_offload_params;
struct netvsc_device;
struct netvsc_channel;
struct net_device_context;
+struct rndis_request *get_rndis_request(struct rndis_device *dev,
+ u32 msg_type, u32 msg_len);
+void put_rndis_request(struct rndis_device *dev, struct rndis_request *req);
+int rndis_build_page_buffers(const void *data, u32 len,
+ struct hv_page_buffer *page_bufs,
+ u32 *page_buf_cnt);
+
extern u32 netvsc_ring_bytes;
int netvsc_workqueue_init(void);
@@ -1779,6 +1790,36 @@ struct rndis_message {
union rndis_message_container msg;
};
+/*
+ * RNDIS request descriptor. Declared here so the KUnit cases can reach
+ * the layout the response-copy bound in rndis_filter_receive_resp()
+ * relies on. The two RNDIS_EXT_LEN tails are what make the object
+ * larger than KMALLOC_MAX_CACHE_SIZE.
+ */
+struct rndis_request {
+ struct list_head list_ent;
+ struct completion wait_event;
+
+ struct rndis_message response_msg;
+ /*
+ * The buffer for extended info after the RNDIS response message. It's
+ * referenced based on the data offset in the RNDIS message. Its size
+ * is enough for current needs, and should be sufficient for the near
+ * future.
+ */
+ u8 response_ext[RNDIS_EXT_LEN];
+
+ /* Simplify allocation by having a netvsc packet inline */
+ struct hv_netvsc_packet pkt;
+
+ struct rndis_message request_msg;
+ /*
+ * The buffer for the extended info after the RNDIS request message.
+ * It is referenced and sized in a similar way as response_ext.
+ */
+ u8 request_ext[RNDIS_EXT_LEN];
+};
+
/* Handy macros */
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 9b6c44979b4e..1ce40baa2d23 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -16,6 +16,7 @@
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/if_vlan.h>
+#include <linux/mm.h>
#include <linux/nls.h>
#include <linux/vmalloc.h>
#include <linux/rtnetlink.h>
@@ -27,31 +28,6 @@
static void rndis_set_multicast(struct work_struct *w);
-#define RNDIS_EXT_LEN HV_HYP_PAGE_SIZE
-struct rndis_request {
- struct list_head list_ent;
- struct completion wait_event;
-
- struct rndis_message response_msg;
- /*
- * The buffer for extended info after the RNDIS response message. It's
- * referenced based on the data offset in the RNDIS message. Its size
- * is enough for current needs, and should be sufficient for the near
- * future.
- */
- u8 response_ext[RNDIS_EXT_LEN];
-
- /* Simplify allocation by having a netvsc packet inline */
- struct hv_netvsc_packet pkt;
-
- struct rndis_message request_msg;
- /*
- * The buffer for the extended info after the RNDIS request message.
- * It is referenced and sized in a similar way as response_ext.
- */
- u8 request_ext[RNDIS_EXT_LEN];
-};
-
static const u8 netvsc_hash_key[NETVSC_HASH_KEYLEN] = {
0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
@@ -78,16 +54,27 @@ static struct rndis_device *get_rndis_device(void)
return device;
}
-static struct rndis_request *get_rndis_request(struct rndis_device *dev,
- u32 msg_type,
- u32 msg_len)
+struct rndis_request *get_rndis_request(struct rndis_device *dev,
+ u32 msg_type,
+ u32 msg_len)
{
struct rndis_request *request;
struct rndis_message *rndis_msg;
struct rndis_set_request *set;
unsigned long flags;
- request = kzalloc_obj(struct rndis_request);
+ /*
+ * struct rndis_request embeds two RNDIS_EXT_LEN (4 KiB) protocol
+ * tails and is larger than KMALLOC_MAX_CACHE_SIZE, so
+ * kzalloc_obj() needs an order-2 compound page. That high-order
+ * allocation can fail under buddy fragmentation. kvzalloc_obj()
+ * keeps the zeroing semantics while allowing vmalloc backing when
+ * a suitable kmalloc allocation is unavailable. The request payload
+ * is sent as GPADL-direct page buffers, so rndis_filter_send_request()
+ * must describe each backing page instead of assuming virt_to_phys()
+ * yields one contiguous physical range.
+ */
+ request = kvzalloc_obj(struct rndis_request);
if (!request)
return NULL;
@@ -115,8 +102,8 @@ static struct rndis_request *get_rndis_request(struct rndis_device *dev,
return request;
}
-static void put_rndis_request(struct rndis_device *dev,
- struct rndis_request *req)
+void put_rndis_request(struct rndis_device *dev,
+ struct rndis_request *req)
{
unsigned long flags;
@@ -124,7 +111,8 @@ static void put_rndis_request(struct rndis_device *dev,
list_del(&req->list_ent);
spin_unlock_irqrestore(&dev->request_lock, flags);
- kfree(req);
+ /* Paired with the kvzalloc_obj() in get_rndis_request(). */
+ kvfree(req);
}
static void dump_rndis_message(struct net_device *netdev,
@@ -221,27 +209,78 @@ static void dump_rndis_message(struct net_device *netdev,
}
}
+int rndis_build_page_buffers(const void *data, u32 len,
+ struct hv_page_buffer *page_bufs,
+ u32 *page_buf_cnt)
+{
+ const u8 *addr = data;
+ u32 count = 0;
+
+ if (!data || !len || !page_bufs || !page_buf_cnt)
+ return -EINVAL;
+
+ *page_buf_cnt = 0;
+
+ while (len) {
+ struct page *page;
+ phys_addr_t phys;
+ u32 offset, chunk;
+ unsigned long page_offset = offset_in_page(addr);
+
+ if (count == MAX_PAGE_BUFFER_COUNT)
+ return -E2BIG;
+
+ if (is_vmalloc_addr(addr))
+ page = vmalloc_to_page(addr);
+ else if (virt_addr_valid(addr))
+ page = virt_to_page(addr);
+ else
+ return -EFAULT;
+
+ if (!page)
+ return -EFAULT;
+
+ phys = page_to_phys(page) + page_offset;
+ offset = offset_in_hvpage(phys);
+ chunk = min_t(u32, len, PAGE_SIZE - page_offset);
+ chunk = min_t(u32, chunk, HV_HYP_PAGE_SIZE - offset);
+
+ page_bufs[count].pfn = phys >> HV_HYP_PAGE_SHIFT;
+ page_bufs[count].offset = offset;
+ page_bufs[count].len = chunk;
+
+ addr += chunk;
+ len -= chunk;
+ count++;
+ }
+
+ *page_buf_cnt = count;
+ return 0;
+}
+
static int rndis_filter_send_request(struct rndis_device *dev,
struct rndis_request *req)
{
struct hv_netvsc_packet *packet;
- struct hv_page_buffer pb;
+ struct hv_page_buffer page_bufs[MAX_PAGE_BUFFER_COUNT];
+ u32 page_buf_cnt;
int ret;
/* Setup the packet to send it */
packet = &req->pkt;
packet->total_data_buflen = req->request_msg.msg_len;
- packet->page_buf_cnt = 1;
-
- pb.pfn = virt_to_phys(&req->request_msg) >> HV_HYP_PAGE_SHIFT;
- pb.len = req->request_msg.msg_len;
- pb.offset = offset_in_hvpage(&req->request_msg);
+ ret = rndis_build_page_buffers(&req->request_msg,
+ req->request_msg.msg_len,
+ page_bufs, &page_buf_cnt);
+ if (ret)
+ return ret;
+ packet->page_buf_cnt = page_buf_cnt;
trace_rndis_send(dev->ndev, 0, &req->request_msg);
rcu_read_lock_bh();
- ret = netvsc_send(dev->ndev, packet, NULL, &pb, NULL, false);
+ ret = netvsc_send(dev->ndev, packet, NULL, page_bufs, NULL, false);
rcu_read_unlock_bh();
return ret;
diff --git a/drivers/net/hyperv/rndis_request_test.c b/drivers/net/hyperv/rndis_request_test.c
new file mode 100644
index 000000000000..6affa916e74e
--- /dev/null
+++ b/drivers/net/hyperv/rndis_request_test.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * KUnit tests for RNDIS request descriptor allocation.
+ *
+ * Built into the hv_netvsc object rather than a separate module so the
+ * cases can reach the internal helpers declared in hyperv_net.h
+ * without exporting them.
+ */
+#include <kunit/test.h>
+#include <linux/hyperv.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/vmalloc.h>
+
+#include "hyperv_net.h"
+
+static int rndis_test_device_init(struct rndis_device *dev)
+{
+ memset(dev, 0, sizeof(*dev));
+ atomic_set(&dev->new_req_id, 0);
+ spin_lock_init(&dev->request_lock);
+ INIT_LIST_HEAD(&dev->req_list);
+ return 0;
+}
+
+/*
+ * The premise of the kvzalloc_obj() conversion: the descriptor embeds
+ * two RNDIS_EXT_LEN protocol tails and sits past
+ * KMALLOC_MAX_CACHE_SIZE, so kzalloc_obj() reached kmalloc_large() and
+ * took an order-2 compound page on the subchannel open path. If the
+ * struct ever drops back inside the cache, the conversion stops being
+ * about high-order allocation and this assertion is the reminder.
+ */
+static void rndis_request_size_premise_test(struct kunit *test)
+{
+ KUNIT_EXPECT_GT(test, sizeof(struct rndis_request),
+ (size_t)KMALLOC_MAX_CACHE_SIZE);
+ /*
+ * The copy bound in rndis_filter_receive_resp() is
+ * sizeof(struct rndis_message) + RNDIS_EXT_LEN. That is exactly
+ * the response_msg + response_ext tail of the object. A reorder
+ * or a resize of either member makes the bound lie.
+ */
+ KUNIT_EXPECT_EQ(test,
+ offsetofend(struct rndis_request, response_ext),
+ offsetof(struct rndis_request, response_msg) +
+ sizeof(struct rndis_message) + RNDIS_EXT_LEN);
+ KUNIT_EXPECT_EQ(test,
+ offsetofend(struct rndis_request, request_ext),
+ offsetof(struct rndis_request, request_msg) +
+ sizeof(struct rndis_message) + RNDIS_EXT_LEN);
+}
+
+/*
+ * kvzalloc_obj() keeps the zeroing kzalloc_obj() provided. The two
+ * protocol tails are the fields a response is copied into; a stale
+ * tail is a stale response.
+ */
+static void rndis_request_alloc_zeroed_test(struct kunit *test)
+{
+ struct rndis_device dev;
+ struct rndis_request *req;
+
+ KUNIT_ASSERT_EQ(test, rndis_test_device_init(&dev), 0);
+ req = get_rndis_request(&dev, RNDIS_MSG_INIT, 0x20);
+ KUNIT_ASSERT_NOT_NULL(test, req);
+
+ KUNIT_EXPECT_EQ(test, req->response_ext[0], 0);
+ KUNIT_EXPECT_EQ(test, req->response_ext[RNDIS_EXT_LEN - 1], 0);
+ KUNIT_EXPECT_EQ(test, req->request_ext[0], 0);
+ KUNIT_EXPECT_EQ(test, req->request_ext[RNDIS_EXT_LEN - 1], 0);
+ KUNIT_EXPECT_EQ(test, req->response_msg.msg_len, 0U);
+
+ put_rndis_request(&dev, req);
+}
+
+/* Request ids come from a per-device counter and the list tracks the live set. */
+static void rndis_request_id_lifecycle_test(struct kunit *test)
+{
+ struct rndis_device dev;
+ struct rndis_request *req0, *req1;
+ struct rndis_request *cursor;
+ unsigned int n = 0;
+
+ KUNIT_ASSERT_EQ(test, rndis_test_device_init(&dev), 0);
+
+ req0 = get_rndis_request(&dev, RNDIS_MSG_INIT, 0x20);
+ KUNIT_ASSERT_NOT_NULL(test, req0);
+ req1 = get_rndis_request(&dev, RNDIS_MSG_QUERY, 0x20);
+ KUNIT_ASSERT_NOT_NULL(test, req1);
+
+ /*
+ * get_rndis_request() stamps the id through the set_req template,
+ * which shares the union slot with every other request body. Read
+ * it back through the same member the producer used.
+ */
+ KUNIT_EXPECT_EQ(test,
+ req0->request_msg.msg.set_req.req_id, 1U);
+ KUNIT_EXPECT_EQ(test,
+ req1->request_msg.msg.set_req.req_id, 2U);
+
+ list_for_each_entry(cursor, &dev.req_list, list_ent)
+ n++;
+ KUNIT_EXPECT_EQ(test, n, 2U);
+
+ /*
+ * put_rndis_request() is the cleanup path every error and
+ * timeout branch takes. It unlinks before it frees.
+ */
+ put_rndis_request(&dev, req0);
+ n = 0;
+ list_for_each_entry(cursor, &dev.req_list, list_ent)
+ n++;
+ KUNIT_EXPECT_EQ(test, n, 1U);
+ KUNIT_EXPECT_TRUE(test,
+ list_first_entry(&dev.req_list, struct rndis_request,
+ list_ent) == req1);
+
+ put_rndis_request(&dev, req1);
+ KUNIT_EXPECT_TRUE(test, list_empty(&dev.req_list));
+}
+
+/*
+ * A request left on the list after a completed exchange is a leak of
+ * the descriptor and of its slot in the outstanding set. Repeated
+ * get/put cycles must return to the empty list every time.
+ */
+static void rndis_request_put_cleanup_test(struct kunit *test)
+{
+ struct rndis_device dev;
+ struct rndis_request *req;
+ int i;
+
+ KUNIT_ASSERT_EQ(test, rndis_test_device_init(&dev), 0);
+
+ for (i = 0; i < 4; i++) {
+ req = get_rndis_request(&dev, RNDIS_MSG_INIT, 0x20);
+ KUNIT_ASSERT_NOT_NULL(test, req);
+ KUNIT_EXPECT_FALSE(test, list_empty(&dev.req_list));
+ put_rndis_request(&dev, req);
+ KUNIT_EXPECT_TRUE(test, list_empty(&dev.req_list));
+ }
+}
+
+/*
+ * kvzalloc_obj() may return a vmalloc address under fragmentation. RNDIS
+ * requests are GPA-direct packets, so each backing page must be represented
+ * explicitly instead of deriving a single PFN with virt_to_phys().
+ */
+static void rndis_request_vmalloc_page_buffers_test(struct kunit *test)
+{
+ struct hv_page_buffer page_bufs[MAX_PAGE_BUFFER_COUNT];
+ const u32 data_len = 16;
+ u8 *allocation = vzalloc(2 * PAGE_SIZE);
+ const u8 *cursor;
+ phys_addr_t phys;
+ u32 count = 0, remaining = data_len, i;
+ int ret;
+
+ if (!allocation) {
+ KUNIT_FAIL(test, "could not allocate vmalloc test buffer");
+ return;
+ }
+
+ cursor = allocation + PAGE_SIZE - 8;
+ ret = rndis_build_page_buffers(cursor, data_len, page_bufs, &count);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ if (ret)
+ goto out;
+
+ KUNIT_EXPECT_EQ(test, count, 2U);
+ for (i = 0; i < count; i++) {
+ struct page *page = vmalloc_to_page(cursor);
+ unsigned long page_offset = offset_in_page(cursor);
+ u32 offset, chunk;
+
+ if (!page) {
+ KUNIT_FAIL(test, "vmalloc test buffer has no backing page");
+ goto out;
+ }
+
+ phys = page_to_phys(page) + page_offset;
+ offset = offset_in_hvpage(phys);
+ chunk = min_t(u32, remaining, PAGE_SIZE - page_offset);
+ chunk = min_t(u32, chunk, HV_HYP_PAGE_SIZE - offset);
+
+ KUNIT_EXPECT_EQ(test, page_bufs[i].pfn,
+ (u64)(phys >> HV_HYP_PAGE_SHIFT));
+ KUNIT_EXPECT_EQ(test, page_bufs[i].offset, offset);
+ KUNIT_EXPECT_EQ(test, page_bufs[i].len, chunk);
+
+ cursor += chunk;
+ remaining -= chunk;
+ }
+ KUNIT_EXPECT_EQ(test, remaining, 0U);
+
+out:
+ vfree(allocation);
+}
+
+static struct kunit_case rndis_request_test_cases[] = {
+ KUNIT_CASE(rndis_request_size_premise_test),
+ KUNIT_CASE(rndis_request_alloc_zeroed_test),
+ KUNIT_CASE(rndis_request_id_lifecycle_test),
+ KUNIT_CASE(rndis_request_put_cleanup_test),
+ KUNIT_CASE(rndis_request_vmalloc_page_buffers_test),
+ {}
+};
+
+static struct kunit_suite rndis_request_test_suite = {
+ .name = "hyperv-rndis-request",
+ .test_cases = rndis_request_test_cases,
+};
+
+kunit_test_suite(rndis_request_test_suite);
--
2.43.0
next prev parent reply other threads:[~2026-10-07 19:09 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-07 19:07 [PATCH v2 0/14] hv: vmbus: make rings and host-visible buffers survive buddy fragmentation Emerson Busson
2026-10-07 19:07 ` [PATCH v2 01/14] hv: vmbus: convert ring backing through the chunk allocator Emerson Busson
2026-10-07 19:07 ` [PATCH v2 02/14] hv: vmbus: validate chunk buffer allocation and cleanup Emerson Busson
2026-10-08 21:17 ` kernel test robot
2026-10-07 19:07 ` [PATCH v2 03/14] uio: hv_generic: describe buffers for owned allocation Emerson Busson
2026-10-07 19:07 ` [PATCH v2 04/14] hv: vmbus: add KUnit tests for GPADL post failure injection Emerson Busson
2026-10-07 19:07 ` [PATCH v2 05/14] hv: vmbus: add KUnit test for order-zero allocation fallback Emerson Busson
2026-10-07 19:07 ` [PATCH v2 06/14] hv: vmbus: cover all shared-page policy combinations Emerson Busson
2026-10-07 19:07 ` [PATCH v2 07/14] hv: vmbus: distinguish host rescind from local channel unload Emerson Busson
2026-10-07 19:07 ` [PATCH v2 08/14] hv: vmbus: retain backing until ownership and references clear Emerson Busson
2026-10-08 19:09 ` sashiko-bot
2026-10-07 19:07 ` [PATCH v2 09/14] hv: use owned VMBus buffers in NetVSC and UIO Emerson Busson
2026-10-08 19:09 ` sashiko-bot
2026-10-07 19:07 ` [PATCH v2 10/14] hv: vmbus: pin buffer pages across UIO mmap to close the reclaim race Emerson Busson
2026-10-08 16:49 ` kernel test robot
2026-10-08 17:51 ` Nathan Chancellor
2026-10-08 17:02 ` kernel test robot
2026-10-08 19:09 ` sashiko-bot
2026-10-07 19:07 ` [PATCH v2 11/14] hv: vmbus: vmalloc requestor metadata Emerson Busson
2026-10-08 19:09 ` sashiko-bot
2026-10-07 19:07 ` Emerson Busson [this message]
2026-10-08 19:09 ` [PATCH v2 12/14] hv: netvsc: allocate RNDIS request descriptors with kvzalloc_obj() sashiko-bot
2026-10-07 19:07 ` [PATCH v2 13/14] hv: netvsc: handle a NULL request address on empty completions Emerson Busson
2026-10-08 19:09 ` sashiko-bot
2026-10-07 19:07 ` [PATCH v2 14/14] hv: netvsc: use kvzalloc for device state Emerson Busson
2026-10-08 19:09 ` sashiko-bot
2026-10-08 16:55 ` [PATCH v2 0/14] hv: vmbus: make rings and host-visible buffers survive buddy fragmentation Easwar Hariharan
2026-10-13 17:52 ` Michael Kelley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261007190752.336426-13-emersonbusson@gmail.com \
--to=emersonbusson@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=decui@microsoft.com \
--cc=edumazet@google.com \
--cc=gregkh@linuxfoundation.org \
--cc=haiyangz@microsoft.com \
--cc=kuba@kernel.org \
--cc=kys@microsoft.com \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mhklinux@outlook.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=wei.liu@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.