* [PATCH net v3 1/2] net: mana: Add NULL guards in teardown path to prevent panic on attach failure
From: Dipayaan Roy @ 2026-05-25 8:08 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees,
john.fastabend, hawk, bpf, daniel, ast, sdf, yury.norov,
pavan.chebbi
In-Reply-To: <20260525081129.1230035-1-dipayanroy@linux.microsoft.com>
When queue allocation fails partway through, the error cleanup frees
and NULLs apc->tx_qp and apc->rxqs. Multiple teardown paths such as
mana_remove(), mana_change_mtu() recovery, and internal error handling
in mana_alloc_queues() can subsequently call into functions that
dereference these pointers without NULL checks:
- mana_chn_setxdp() dereferences apc->rxqs[0], causing a NULL pointer
dereference panic (CR2: 0000000000000000 at mana_chn_setxdp+0x26).
- mana_destroy_vport() iterates apc->rxqs without a NULL check.
- mana_fence_rqs() iterates apc->rxqs without a NULL check.
- mana_dealloc_queues() iterates apc->tx_qp without a NULL check.
Add NULL guards for apc->rxqs in mana_fence_rqs(),
mana_destroy_vport(), and before the mana_chn_setxdp() call. Add a
NULL guard for apc->tx_qp in mana_dealloc_queues() to skip TX queue
draining when TX queues were never allocated or already freed.
Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)")
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 70 +++++++++++--------
1 file changed, 41 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 9afc786b297a..0582803907a8 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -1727,6 +1727,9 @@ static void mana_fence_rqs(struct mana_port_context *apc)
struct mana_rxq *rxq;
int err;
+ if (!apc->rxqs)
+ return;
+
for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
rxq = apc->rxqs[rxq_idx];
err = mana_fence_rq(apc, rxq);
@@ -2858,13 +2861,16 @@ static void mana_destroy_vport(struct mana_port_context *apc)
struct mana_rxq *rxq;
u32 rxq_idx;
- for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
- rxq = apc->rxqs[rxq_idx];
- if (!rxq)
- continue;
+ if (apc->rxqs) {
- mana_destroy_rxq(apc, rxq, true);
- apc->rxqs[rxq_idx] = NULL;
+ for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+ rxq = apc->rxqs[rxq_idx];
+ if (!rxq)
+ continue;
+
+ mana_destroy_rxq(apc, rxq, true);
+ apc->rxqs[rxq_idx] = NULL;
+ }
}
mana_destroy_txq(apc);
@@ -3269,7 +3275,8 @@ static int mana_dealloc_queues(struct net_device *ndev)
if (apc->port_is_up)
return -EINVAL;
- mana_chn_setxdp(apc, NULL);
+ if (apc->rxqs)
+ mana_chn_setxdp(apc, NULL);
if (gd->gdma_context->is_pf && !apc->ac->bm_hostmode)
mana_pf_deregister_filter(apc);
@@ -3287,33 +3294,38 @@ static int mana_dealloc_queues(struct net_device *ndev)
* number of queues.
*/
- for (i = 0; i < apc->num_queues; i++) {
- txq = &apc->tx_qp[i].txq;
- tsleep = 1000;
- while (atomic_read(&txq->pending_sends) > 0 &&
- time_before(jiffies, timeout)) {
- usleep_range(tsleep, tsleep + 1000);
- tsleep <<= 1;
- }
- if (atomic_read(&txq->pending_sends)) {
- err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
- if (err) {
- netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
- err, atomic_read(&txq->pending_sends),
- txq->gdma_txq_id);
+ if (apc->tx_qp) {
+ for (i = 0; i < apc->num_queues; i++) {
+ txq = &apc->tx_qp[i].txq;
+ tsleep = 1000;
+ while (atomic_read(&txq->pending_sends) > 0 &&
+ time_before(jiffies, timeout)) {
+ usleep_range(tsleep, tsleep + 1000);
+ tsleep <<= 1;
+ }
+ if (atomic_read(&txq->pending_sends)) {
+ err =
+ pcie_flr(to_pci_dev(gd->gdma_context->dev));
+ if (err) {
+ netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
+ err,
+ atomic_read(&txq->pending_sends),
+ txq->gdma_txq_id);
+ }
+ break;
}
- break;
}
- }
- for (i = 0; i < apc->num_queues; i++) {
- txq = &apc->tx_qp[i].txq;
- while ((skb = skb_dequeue(&txq->pending_skbs))) {
- mana_unmap_skb(skb, apc);
- dev_kfree_skb_any(skb);
+ for (i = 0; i < apc->num_queues; i++) {
+ txq = &apc->tx_qp[i].txq;
+ while ((skb = skb_dequeue(&txq->pending_skbs))) {
+ mana_unmap_skb(skb, apc);
+ dev_kfree_skb_any(skb);
+ }
+ atomic_set(&txq->pending_sends, 0);
}
- atomic_set(&txq->pending_sends, 0);
}
+
/* We're 100% sure the queues can no longer be woken up, because
* we're sure now mana_poll_tx_cq() can't be running.
*/
--
2.43.0
^ permalink raw reply related
* [PATCH net v3 0/2] net: mana: Fix NULL dereferences during teardown after attach failure
From: Dipayaan Roy @ 2026-05-25 8:08 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees,
john.fastabend, hawk, bpf, daniel, ast, sdf, yury.norov,
pavan.chebbi
When mana_attach() fails (e.g. during queue allocation), the error
cleanup frees apc->tx_qp and apc->rxqs and sets them to NULL. Multiple
subsequent teardown paths can then dereference these NULL pointers,
causing kernel panics.
Patch 1 adds NULL guards in the low-level teardown functions
(mana_fence_rqs, mana_destroy_vport, mana_dealloc_queues) so they are
safe to call regardless of queue initialization state. This covers all
callers: mana_remove(), mana_change_mtu() recovery, and internal error
paths in mana_alloc_queues().
Patch 2 adds an early exit in mana_detach() for already-detached ports,
making it safe for non-close callers. This allows the queue reset
handler to safely retry mana_attach() without redundant teardown.
Changes in v3:
- Patch 1: Fixed commit message and fixes tag.
Changes in v2:
- Patch 2: moved netif_device_present() check into mana_detach() as
an early exit instead of using goto in the work handler
Dipayaan Roy (2):
net: mana: Add NULL guards in teardown path to prevent panic on attach
failure
net: mana: Skip redundant detach on already-detached port
drivers/net/ethernet/microsoft/mana/mana_en.c | 76 ++++++++++++-------
1 file changed, 47 insertions(+), 29 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH net v3 2/2] net: mana: Skip redundant detach on already-detached port
From: Dipayaan Roy @ 2026-05-25 8:08 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, andrew+netdev, davem, edumazet,
kuba, pabeni, leon, longli, kotaranov, horms, shradhagupta,
ssengar, ernis, shirazsaleem, linux-hyperv, netdev, linux-kernel,
linux-rdma, stephen, jacob.e.keller, dipayanroy, leitao, kees,
john.fastabend, hawk, bpf, daniel, ast, sdf, yury.norov,
pavan.chebbi
In-Reply-To: <20260525081129.1230035-1-dipayanroy@linux.microsoft.com>
When mana_per_port_queue_reset_work_handler() runs after a previous
detach succeeded but attach failed, the port is left in a detached
state with apc->tx_qp and apc->rxqs already freed. Calling
mana_detach() again unconditionally leads to NULL pointer dereferences
during queue teardown.
Add an early exit in mana_detach() when the port is already in
detached state (!netif_device_present) for non-close callers, making
it safe to call idempotently. This allows the queue reset handler and
other recovery paths to simply retry mana_attach() without redundant
teardown.
Fixes: 3b194343c250 ("net: mana: Implement ndo_tx_timeout and serialize queue resets per port.")
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 0582803907a8..1e1ad2795c3c 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -3350,6 +3350,12 @@ int mana_detach(struct net_device *ndev, bool from_close)
ASSERT_RTNL();
+ /* If already detached (indicates detach succeeded but attach failed
+ * previously). Now skip mana detach and just retry mana_attach.
+ */
+ if (!from_close && !netif_device_present(ndev))
+ return 0;
+
apc->port_st_save = apc->port_is_up;
apc->port_is_up = false;
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v5 0/2] drm/hyperv: harden host message parsing
From: Hamza Mahfooz @ 2026-05-25 11:36 UTC (permalink / raw)
To: Berkant Koc
Cc: Saurabh Sengar, Dexuan Cui, Long Li, linux-hyperv, dri-devel,
linux-kernel, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
Michael Kelley, Thomas Zimmermann, Maarten Lankhorst,
Maxime Ripard, Deepak Rawat
In-Reply-To: <cover.1779542874.git.me@berkoc.com>
On Sat, May 23, 2026 at 03:27:54PM +0200, Berkant Koc wrote:
> Two independent issues in the synthetic video driver that both stem
> from trusting unvalidated host data.
>
> 1/2 bounds resolution_count from SYNTHVID_RESOLUTION_RESPONSE against
> the supported_resolution[] array, and populates WIN8 defaults for
> hv->screen_*_max / hv->preferred_* in both the WIN10-probe-failure
> path and the pre-WIN10 path, so a failed or pre-WIN10 probe yields a
> usable display instead of having drm_internal_framebuffer_create()
> reject every userspace framebuffer with -EINVAL.
>
> 2/2 forwards bytes_recvd from vmbus_recvpacket() into the sub-handler,
> rejects packets that do not cover the synthvid header, and requires
> the type-specific payload size before memcpy/complete or before
> reading the feature-change byte. Rejected packets are logged via
> drm_err_ratelimited() instead of being silently dropped, matching the
> CoCo-hardened pattern in hv_kvp_onchannelcallback().
>
> 1/2 is unchanged from v3/v4 and carries Michael Kelley's Reviewed-by.
>
> Changes since v4 (per review by Michael Kelley):
>
> 2/2: collapsed the leading "if (type == ... ) { ... switch ... }"
> plus the separate "if (type == FEATURE_CHANGE)" into a single
> switch on msg->vid_hdr.type. The three completion-driving cases
> compute their per-type size and break to a shared exit that does
> the size check + memcpy(init_buf) + complete(); FEATURE_CHANGE is
> its own case that validates its payload and returns without
> falling through; unknown types hit default and return. No
> functional change, fewer lines.
>
> 2/2: the vmbus_recvpacket() nonzero-return path (e.g. -ENOBUFS for a
> too-big packet) is itself a malformed-message case. It is now
> logged via drm_err_ratelimited(), consistent with the
> sub-handler's other reject paths, instead of being silently
> skipped. No channel recovery is attempted, as that is not worth
> the added code for this rare host-side condition.
>
> Changes since v3 (per review by Michael Kelley):
>
> 2/2: validate SYNTHVID_RESOLUTION_RESPONSE against its actual
> variable length. The response carries resolution_count entries,
> not the full SYNTHVID_MAX_RESOLUTION_COUNT array, so requiring
> sizeof(struct synthvid_supported_resolution_resp) rejected the
> shorter responses the host legitimately sends and broke
> resolution probing. Require the fixed prefix, read and bound
> resolution_count, then require only the count-sized array.
>
> 2/2: only run hyperv_receive_sub() when vmbus_recvpacket() returned
> success. v3 dropped the bytes_recvd upper bound as redundant,
> which holds only on a successful receive: on -ENOBUFS
> vmbus_recvpacket() reports the required length in bytes_recvd,
> which can exceed the 16 KiB hv->recv_buf, and the subsequent
> memcpy(hv->init_buf, msg, bytes_recvd) would read and write
> past both buffers. Gating on the success return restores the
> invariant that made the bound redundant, so an oversized host
> packet is dropped rather than copied.
>
> Changes since v2 (per review by Michael Kelley):
>
> 1/2: dropped the reinit_completion() change; the stale completion can
> only outlive its request in hyperv_vmbus_resume() after a
> get_supported_resolution() timeout, which is a narrower fix that
> belongs in a separate patch against the resume path. Pre-WIN10
> branch now also populates hv->preferred_*. The else branch is
> gone; a single screen_width_max == 0 check covers both the
> pre-WIN10 case and a failed WIN10 probe.
>
> 2/2: added a per-type switch for the three completion-driving message
> types so the wait-completion path validates payload size before
> memcpy/complete. Every reject path emits drm_err_ratelimited()
> rather than returning silently.
>
> Changes since v1:
>
> 1/2: bound resolution_count check folded into the existing zero check;
> populate WIN8 defaults when hyperv_get_supported_resolution()
> fails.
> 2/2: forward bytes_recvd into hyperv_receive_sub(); enforce the pipe +
> synthvid header minimum; check synthvid_feature_change payload
> size before reading is_dirt_needed.
>
> The shared init_buf reuse (a duplicate or late host response can
> overwrite init_buf between successive request/response cycles) and the
> related completion reinit are real but orthogonal to this size
> validation. As discussed on v2, they are queued as a separate follow-up
> against the resume/expected-type path once this series lands.
>
> This series is verified by static analysis and code inspection against
> the synthvid protocol structures and the vmbus_recvpacket() contract. I
> do not currently have a Hyper-V test environment to exercise the receive
> and resolution-probe paths at runtime, so confirmation from someone who
> can run it in a Hyper-V VM would be welcome.
>
> Both patches carry an Assisted-by: Claude:claude-opus-4-7 berkoc-pipeline
> trailer per the kernel coding-assistants policy. Code, analysis and
> review responses are mine; the model is used as a structured reviewer
> under human verification.
>
> Berkant Koc (2):
> drm/hyperv: validate resolution_count and fix WIN8 fallback
> drm/hyperv: validate VMBus packet size in receive callback
>
> drivers/gpu/drm/hyperv/hyperv_drm_proto.c | 113 +++++++++++++++++++---
> 1 file changed, 97 insertions(+), 16 deletions(-)
>
>
Applied, thanks!
> base-commit: 4bf5d3da79c48e1df4bab82c9680c53adeff7820
> --
> 2.47.3
>
^ permalink raw reply
* Re: [PATCH 1/1] x86/hyperv: Refactor hv_smp_prepare_cpus()
From: kernel test robot @ 2026-05-25 11:42 UTC (permalink / raw)
To: Michael Kelley, kys, haiyangz, wei.liu, decui, longli, tglx,
mingo, bp, dave.hansen, x86, hpa, linux-hyperv, linux-kernel,
linux-arch
Cc: llvm, oe-kbuild-all
In-Reply-To: <20260521192336.99623-1-mhklkml@zohomail.com>
Hi Michael,
kernel test robot noticed the following build errors:
[auto build test ERROR on tip/master]
[also build test ERROR on linus/master v7.1-rc5 next-20260522]
[cannot apply to tip/x86/core arnd-asm-generic/master tip/auto-latest]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Michael-Kelley/x86-hyperv-Refactor-hv_smp_prepare_cpus/20260522-032610
base: tip/master
patch link: https://lore.kernel.org/r/20260521192336.99623-1-mhklkml%40zohomail.com
patch subject: [PATCH 1/1] x86/hyperv: Refactor hv_smp_prepare_cpus()
config: x86_64-randconfig-076-20260524 (https://download.01.org/0day-ci/archive/20260525/202605251945.TesslTvF-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260525/202605251945.TesslTvF-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202605251945.TesslTvF-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/hv/hv_proc.c:303:55: error: call to undeclared function 'cpu_physical_id'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
303 | ret = hv_call_add_logical_proc(numa_cpu_node(i), i, cpu_physical_id(i));
| ^
1 error generated.
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for MFD_STMFX
Depends on [n]: HAS_IOMEM [=y] && I2C [=y] && OF [=n]
Selected by [y]:
- PINCTRL_STMFX [=y] && PINCTRL [=y] && I2C [=y] && HAS_IOMEM [=y]
vim +/cpu_physical_id +303 drivers/hv/hv_proc.c
290
291 void hv_smp_prep_cpus(void)
292 {
293 #ifdef CONFIG_X86_64
294 int i, ret;
295
296 /* If AP LPs exist, we are in a kexec'd kernel and VPs already exist */
297 if (num_present_cpus() == 1 || hv_lp_exists(1))
298 return;
299
300 for_each_present_cpu(i) {
301 if (i == 0)
302 continue;
> 303 ret = hv_call_add_logical_proc(numa_cpu_node(i), i, cpu_physical_id(i));
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH] uio_hv_generic: Bind to FCopy device by default
From: Ben Hutchings @ 2026-05-25 12:04 UTC (permalink / raw)
To: K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li
Cc: Greg Kroah-Hartman, linux-hyperv
[-- Attachment #1: Type: text/plain, Size: 1030 bytes --]
The Hyper-V kernel-mode fcopy driver was removed in 6.10 and the new
fcopy daemon requires this uio driver to function. However, by
default the driver does not bind to any devices, and must be
configured through the sysfs "new_id" file.
Since the FCopy device is now only usable through this driver, add its
ID to the driver's ID table so that the daemon will work "out of the
box".
Signed-off-by: Ben Hutchings <benh@debian.org>
Fixes: ec314f61e4fc ("Drivers: hv: Remove fcopy driver")
---
--- a/drivers/uio/uio_hv_generic.c
+++ b/drivers/uio/uio_hv_generic.c
@@ -395,9 +395,15 @@ hv_uio_remove(struct hv_device *dev)
vmbus_free_ring(dev->channel);
}
+static const struct hv_vmbus_device_id hv_uio_id_table[] = {
+ { HV_FCOPY_GUID },
+ {}
+};
+MODULE_DEVICE_TABLE(vmbus, hv_uio_id_table);
+
static struct hv_driver hv_uio_drv = {
.name = "uio_hv_generic",
- .id_table = NULL, /* only dynamic id's */
+ .id_table = hv_uio_id_table,
.probe = hv_uio_probe,
.remove = hv_uio_remove,
};
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* RE: [PATCH v5 0/2] drm/hyperv: harden host message parsing
From: Michael Kelley @ 2026-05-25 14:57 UTC (permalink / raw)
To: Hamza Mahfooz, Berkant Koc
Cc: Saurabh Sengar, Dexuan Cui, Long Li, linux-hyperv@vger.kernel.org,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Michael Kelley,
Thomas Zimmermann, Maarten Lankhorst, Maxime Ripard, Deepak Rawat
In-Reply-To: <ahQ0NS1jrfU8ms1U@linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net>
From: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com> Sent: Monday, May 25, 2026 4:36 AM
>
> On Sat, May 23, 2026 at 03:27:54PM +0200, Berkant Koc wrote:
> > Two independent issues in the synthetic video driver that both stem
> > from trusting unvalidated host data.
> >
> > 1/2 bounds resolution_count from SYNTHVID_RESOLUTION_RESPONSE against
> > the supported_resolution[] array, and populates WIN8 defaults for
> > hv->screen_*_max / hv->preferred_* in both the WIN10-probe-failure
> > path and the pre-WIN10 path, so a failed or pre-WIN10 probe yields a
> > usable display instead of having drm_internal_framebuffer_create()
> > reject every userspace framebuffer with -EINVAL.
> >
> > 2/2 forwards bytes_recvd from vmbus_recvpacket() into the sub-handler,
> > rejects packets that do not cover the synthvid header, and requires
> > the type-specific payload size before memcpy/complete or before
> > reading the feature-change byte. Rejected packets are logged via
> > drm_err_ratelimited() instead of being silently dropped, matching the
> > CoCo-hardened pattern in hv_kvp_onchannelcallback().
> >
> > 1/2 is unchanged from v3/v4 and carries Michael Kelley's Reviewed-by.
> >
[snip]
> >
> > Berkant Koc (2):
> > drm/hyperv: validate resolution_count and fix WIN8 fallback
> > drm/hyperv: validate VMBus packet size in receive callback
> >
> > drivers/gpu/drm/hyperv/hyperv_drm_proto.c | 113 +++++++++++++++++++---
> > 1 file changed, 97 insertions(+), 16 deletions(-)
> >
> >
>
> Applied, thanks!
Hamza -- which tree was this applied to?
Michael
^ permalink raw reply
* Re: [PATCH v5 0/2] drm/hyperv: harden host message parsing
From: Hamza Mahfooz @ 2026-05-25 15:32 UTC (permalink / raw)
To: Michael Kelley
Cc: Berkant Koc, Saurabh Sengar, Dexuan Cui, Long Li,
linux-hyperv@vger.kernel.org, dri-devel@lists.freedesktop.org,
linux-kernel@vger.kernel.org, K. Y. Srinivasan, Haiyang Zhang,
Wei Liu, Thomas Zimmermann, Maarten Lankhorst, Maxime Ripard,
Deepak Rawat
In-Reply-To: <SN6PR02MB4157F72302D2B4B86ECE553FD40A2@SN6PR02MB4157.namprd02.prod.outlook.com>
On Mon, May 25, 2026 at 02:57:24PM +0000, Michael Kelley wrote:
> From: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com> Sent: Monday, May 25, 2026 4:36 AM
> > Applied, thanks!
>
> Hamza -- which tree was this applied to?
drm-misc-fixes
>
> Michael
^ permalink raw reply
* Re: [EXTERNAL] Re: [PATCH rdma-next v2] RDMA/mana_ib: hardening: Clamp adapter capability values from MANA_IB_GET_ADAPTER_CAP
From: Erni Sri Satya Vennela @ 2026-05-25 18:58 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Long Li, Leon Romanovsky, Konstantin Taranov,
linux-rdma@vger.kernel.org, linux-hyperv@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20260413134602.GL3694781@ziepe.ca>
On Mon, Apr 13, 2026 at 10:46:02AM -0300, Jason Gunthorpe wrote:
> On Fri, Apr 10, 2026 at 10:29:45PM +0000, Long Li wrote:
> > > On Sat, Mar 21, 2026 at 12:56:39AM +0000, Long Li wrote:
> > >
> > > > How we rephrase this in this way: the driver should not corrupt or
> > > > overflow other parts of the kernel if its device is misbehaving (or
> > > > has a bug).
> > >
> > > If we are going to do this CC hardening stuff I think I want to see a more
> > > comphrensive approach, like if we detect an attack then the kernel instantly
> > > crashes or something. Or at least an approach in general agreed to by the CC and
> > > kernel community.
> > >
> > > Igoring the issue and continuing seems just wrong.
> > >
> > > This sprinkling of random checks in this series doesn't feel comprehensive or
> > > cohesive to me.
> > >
> > > Jason
> >
> > Can we follow the virtio BAD_RING()/vq->broken pattern in
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/virtio/virtio_ring.c#n57.
> >
> > Add a broken flag to mana_ib_dev. When any hardware response
> > contains out-of-range values, mark the device broken and fail the
> > operation - during probe this prevents device registration entirely,
> > at runtime all subsequent operations return -EIO.
>
> If that's the plan I would think it should be struct device based, but
> yeah, I'm more comfortable with this sort of direction as a CC
> hardening plan.
>
Hi Jason,
Our team is not aligned with marking the device broken, after multiple
discussions, since both the values that are received from hardware and
stored in mana_ib_gd_query_adapter_caps are u32.
I'm planning to send v3 as a non-hardening patch with only clamping the
values at mana_ib_query_device to INT_MAX when out-of-bound.
Your previous concerns:
> “I'm also not convinced clamping to such a high value has any value
> whatsoever, as it probably still triggers maths overflows elsewhere. I
> think you should clamp to reasonable limits for your device if you want
> to do this.”
We plan to clamp it to INT_MAX since it is the max in props.
> “There is no reason they should be signed, you should just fix the
> type.”
It is not allowed to change sign in props, so clamping is the best bet.
Thanks,
Vennela
^ permalink raw reply
* [PATCH rdma-next v3] RDMA/mana_ib: Clamp adapter capabilities at the ib_device_attr boundary
From: Erni Sri Satya Vennela @ 2026-05-25 19:01 UTC (permalink / raw)
To: longli, kotaranov, Jason Gunthorpe, Leon Romanovsky, linux-rdma,
linux-hyperv, linux-kernel
Cc: Erni Sri Satya Vennela
mana_ib stores its adapter capabilities internally as u32 in
struct mana_ib_adapter_caps. The IB core, however, exposes the
corresponding device attributes through struct ib_device_attr, where
fields such as max_qp, max_qp_wr, max_send_sge, max_recv_sge,
max_sge_rd, max_cq, max_cqe, max_mr, max_pd, max_qp_rd_atom,
max_res_rd_atom and max_qp_init_rd_atom are signed int.
mana_ib_query_device() is the only place that copies the cached u32
caps into these int fields. If a cap exceeds INT_MAX, the implicit
u32-to-int narrowing yields a negative value. Clamp each cap to
INT_MAX at this boundary so the values handed to the IB core are always
non-negative.
While here, fix a related overflow in the computation of
max_res_rd_atom. It is derived as max_qp_rd_atom * max_qp, both of
which are int after the assignment above; the multiplication can
overflow an int even with the new clamps in place. Widen to s64
before multiplying and clamp the result to INT_MAX.
Signed-off-by: Erni Sri Satya Vennela <ernis@linux.microsoft.com>
---
Changes in v3:
* Drop clamping from mana_ib_gd_query_adapter_caps(). The internal u32
caps cache does not need to be clamped.
* Move all clamping exclusively to mana_ib_query_device(), which is the
only place the cached u32 values are narrowed into the signed int
fields of struct ib_device_attr.
* Reframe commit message: this is a u32-to-int type boundary fix, not a
CVM/untrusted-hardware hardening patch.
Changes in v2:
* Update patch title.
---
drivers/infiniband/hw/mana/main.c | 33 ++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/drivers/infiniband/hw/mana/main.c b/drivers/infiniband/hw/mana/main.c
index ac5e75dd3494..ca843083140f 100644
--- a/drivers/infiniband/hw/mana/main.c
+++ b/drivers/infiniband/hw/mana/main.c
@@ -555,19 +555,28 @@ int mana_ib_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
props->vendor_part_id = dev->gdma_dev->dev_id.type;
props->max_mr_size = MANA_IB_MAX_MR_SIZE;
props->page_size_cap = dev->adapter_caps.page_size_cap;
- props->max_qp = dev->adapter_caps.max_qp_count;
- props->max_qp_wr = dev->adapter_caps.max_qp_wr;
+ /*
+ * mana_ib stores adapter capabilities internally as u32, but the
+ * corresponding ib_device_attr fields are signed int. Clamp each
+ * value at this boundary so a cap larger than INT_MAX is never
+ * narrowed into a negative value visible to the IB core or
+ * userspace.
+ */
+ props->max_qp = min_t(u32, dev->adapter_caps.max_qp_count, INT_MAX);
+ props->max_qp_wr = min_t(u32, dev->adapter_caps.max_qp_wr, INT_MAX);
props->device_cap_flags = IB_DEVICE_RC_RNR_NAK_GEN;
- props->max_send_sge = dev->adapter_caps.max_send_sge_count;
- props->max_recv_sge = dev->adapter_caps.max_recv_sge_count;
- props->max_sge_rd = dev->adapter_caps.max_recv_sge_count;
- props->max_cq = dev->adapter_caps.max_cq_count;
- props->max_cqe = dev->adapter_caps.max_qp_wr;
- props->max_mr = dev->adapter_caps.max_mr_count;
- props->max_pd = dev->adapter_caps.max_pd_count;
- props->max_qp_rd_atom = dev->adapter_caps.max_inbound_read_limit;
- props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp;
- props->max_qp_init_rd_atom = dev->adapter_caps.max_outbound_read_limit;
+ props->max_send_sge = min_t(u32, dev->adapter_caps.max_send_sge_count, INT_MAX);
+ props->max_recv_sge = min_t(u32, dev->adapter_caps.max_recv_sge_count, INT_MAX);
+ props->max_sge_rd = min_t(u32, dev->adapter_caps.max_recv_sge_count, INT_MAX);
+ props->max_cq = min_t(u32, dev->adapter_caps.max_cq_count, INT_MAX);
+ props->max_cqe = min_t(u32, dev->adapter_caps.max_qp_wr, INT_MAX);
+ props->max_mr = min_t(u32, dev->adapter_caps.max_mr_count, INT_MAX);
+ props->max_pd = min_t(u32, dev->adapter_caps.max_pd_count, INT_MAX);
+ props->max_qp_rd_atom = min_t(u32, dev->adapter_caps.max_inbound_read_limit, INT_MAX);
+ props->max_res_rd_atom = min_t(s64,
+ (s64)props->max_qp_rd_atom * props->max_qp,
+ INT_MAX);
+ props->max_qp_init_rd_atom = min_t(u32, dev->adapter_caps.max_outbound_read_limit, INT_MAX);
props->atomic_cap = IB_ATOMIC_NONE;
props->masked_atomic_cap = IB_ATOMIC_NONE;
props->max_ah = INT_MAX;
--
2.34.1
^ permalink raw reply related
* Re: [EXTERNAL] Re: [PATCH rdma-next v2] RDMA/mana_ib: hardening: Clamp adapter capability values from MANA_IB_GET_ADAPTER_CAP
From: Jason Gunthorpe @ 2026-05-25 23:01 UTC (permalink / raw)
To: Erni Sri Satya Vennela
Cc: Long Li, Leon Romanovsky, Konstantin Taranov,
linux-rdma@vger.kernel.org, linux-hyperv@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <ahSbyYcq0sgfJnmZ@linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net>
On Mon, May 25, 2026 at 11:58:17AM -0700, Erni Sri Satya Vennela wrote:
> > “There is no reason they should be signed, you should just fix the
> > type.”
>
> It is not allowed to change sign in props, so clamping is the best bet.
Why not? Fix the core code, it is just old junk they are signed, they
should't never have been.
Jason
^ permalink raw reply
* Re: [PATCH] uio_hv_generic: Bind to FCopy device by default
From: Naman Jain @ 2026-05-26 6:45 UTC (permalink / raw)
To: Ben Hutchings, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
Dexuan Cui, Long Li
Cc: Greg Kroah-Hartman, linux-hyperv
In-Reply-To: <ahQ6xuhSReidmN-3@decadent.org.uk>
On 5/25/2026 5:34 PM, Ben Hutchings wrote:
> The Hyper-V kernel-mode fcopy driver was removed in 6.10 and the new
> fcopy daemon requires this uio driver to function. However, by
> default the driver does not bind to any devices, and must be
> configured through the sysfs "new_id" file.
>
> Since the FCopy device is now only usable through this driver, add its
> ID to the driver's ID table so that the daemon will work "out of the
> box".
>
> Signed-off-by: Ben Hutchings <benh@debian.org>
> Fixes: ec314f61e4fc ("Drivers: hv: Remove fcopy driver")
> ---
> --- a/drivers/uio/uio_hv_generic.c
> +++ b/drivers/uio/uio_hv_generic.c
> @@ -395,9 +395,15 @@ hv_uio_remove(struct hv_device *dev)
> vmbus_free_ring(dev->channel);
> }
>
> +static const struct hv_vmbus_device_id hv_uio_id_table[] = {
> + { HV_FCOPY_GUID },
> + {}
> +};
> +MODULE_DEVICE_TABLE(vmbus, hv_uio_id_table);
> +
> static struct hv_driver hv_uio_drv = {
> .name = "uio_hv_generic",
> - .id_table = NULL, /* only dynamic id's */
> + .id_table = hv_uio_id_table,
> .probe = hv_uio_probe,
> .remove = hv_uio_remove,
> };
Two things worth considering before applying:
1. Please add Cc: stable@vger.kernel.org or is it that we do not want
this to be ported to older kernels?
2. Every Hyper-V guest (with UIO_HV_GENERIC enabled) will now have an
additional auto-bound /dev/uio0 node for FCopy. Anything that hardcodes
/dev/uio0 (e.g. ad-hoc DPDK scripts that bind a NetVSC NIC via
uio_hv_generic + new_id) may see its index shift, since FCopy now wins
uio0 at boot. The fix for such consumers is the same thing DPDK and the
in-tree daemon already do: resolve uio via
/sys/bus/vmbus/devices/<guid>/uio/ rather than by number. This is not a
regression in the patch, but it's a behavior change worth calling out.
Regards,
Naman
^ permalink raw reply
* Re: [PATCH] uio_hv_generic: Bind to FCopy device by default
From: Naman Jain @ 2026-05-26 10:10 UTC (permalink / raw)
To: Ben Hutchings
Cc: K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
Greg Kroah-Hartman, linux-hyperv
In-Reply-To: <afdcb1775e7a60b7824b5c540a44f0148abe3e1c.camel@debian.org>
On 5/26/2026 1:59 PM, Ben Hutchings wrote:
> On Tue, 2026-05-26 at 12:15 +0530, Naman Jain wrote:
>>
>> On 5/25/2026 5:34 PM, Ben Hutchings wrote:
>>> The Hyper-V kernel-mode fcopy driver was removed in 6.10 and the new
>>> fcopy daemon requires this uio driver to function. However, by
>>> default the driver does not bind to any devices, and must be
>>> configured through the sysfs "new_id" file.
>>>
>>> Since the FCopy device is now only usable through this driver, add its
>>> ID to the driver's ID table so that the daemon will work "out of the
>>> box".
>>>
>>> Signed-off-by: Ben Hutchings <benh@debian.org>
>>> Fixes: ec314f61e4fc ("Drivers: hv: Remove fcopy driver")
>>> ---
>>> --- a/drivers/uio/uio_hv_generic.c
>>> +++ b/drivers/uio/uio_hv_generic.c
>>> @@ -395,9 +395,15 @@ hv_uio_remove(struct hv_device *dev)
>>> vmbus_free_ring(dev->channel);
>>> }
>>>
>>> +static const struct hv_vmbus_device_id hv_uio_id_table[] = {
>>> + { HV_FCOPY_GUID },
>>> + {}
>>> +};
>>> +MODULE_DEVICE_TABLE(vmbus, hv_uio_id_table);
>>> +
>>> static struct hv_driver hv_uio_drv = {
>>> .name = "uio_hv_generic",
>>> - .id_table = NULL, /* only dynamic id's */
>>> + .id_table = hv_uio_id_table,
>>> .probe = hv_uio_probe,
>>> .remove = hv_uio_remove,
>>> };
>>
++ recipients, assuming you mistakenly clicked reply instead of reply all.
>> Two things worth considering before applying:
>>
>> 1. Please add Cc: stable@vger.kernel.org or is it that we do not want
>> this to be ported to older kernels?
>>
>> 2. Every Hyper-V guest (with UIO_HV_GENERIC enabled) will now have an
>> additional auto-bound /dev/uio0 node for FCopy.
>
> I don't think that's quite true. I tested with a Windows 11 host and
> needed to enable "Guest services" for the VM, which was disabled by
> default. But if that includes other features besides FCopy it might be
> enabled for other reasons.
>
Yes, meaning if these two conditions are satisfied (enabling guest
services is also one time step for a Hyper-V VM), we would see uio0 by
default for fcopy.
>> Anything that hardcodes
>> /dev/uio0 (e.g. ad-hoc DPDK scripts that bind a NetVSC NIC via
>> uio_hv_generic + new_id) may see its index shift, since FCopy now wins
>> uio0 at boot.
>
> OK, so maybe I should implement the new_id dance in the fcopy service
> startup, to avoid that? I did already looked at doing it in a systemd
> unit, but it's hard to do right because adding the same ID twice is an
> error. Maybe the daemon itself ould do it?
Implementing it in uio daemon can introduce race conditions with sysfs
creation. I guess it's OK then to implement it here, in kernel.
>
>> The fix for such consumers is the same thing DPDK and the
>> in-tree daemon already do: resolve uio via
>> /sys/bus/vmbus/devices/<guid>/uio/ rather than by number. This is not a
>> regression in the patch, but it's a behavior change worth calling out.
>
> It would be a good reason *not* to make this change in stable.
>
> Ben.
>
What issues are you fixing with this patch exactly? Is there any
particular sequence of events you are targeting where traditional
approach does not work?
Regards,
Naman
^ permalink raw reply
* Re: [PATCH net v2] net: mana: Optimize irq affinity for low vcpu configs
From: Shradha Gupta @ 2026-05-26 13:05 UTC (permalink / raw)
To: Erni Sri Satya Vennela
Cc: Yury Norov, Dexuan Cui, Wei Liu, Haiyang Zhang, K. Y. Srinivasan,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Konstantin Taranov, Simon Horman, Dipayaan Roy,
Shiraz Saleem, Michael Kelley, Long Li, Yury Norov, linux-hyperv,
linux-kernel, netdev, Paul Rosswurm, Shradha Gupta,
Saurabh Singh Sengar, stable
In-Reply-To: <agq5/8rUFp3ttOFz@linuxonhyperv3.guj3yctzbm1etfxqx2vob5hsef.xx.internal.cloudapp.net>
On Mon, May 18, 2026 at 12:04:31AM -0700, Erni Sri Satya Vennela wrote:
> > > But one observation I had was that " irq_set_affinity_and_hint(*irqs++,
> > > NULL);" is essentially a no-op and we end up relying on the initial
> > > placement from pci_alloc_irq_vectors().
> >
> > Yes you are, assuming you're not binding them before in your call chain.
> >
> > > Even though in these tests we
> > > were not able to reproduce it, but with this distribution there is a
> > > chance we end up clustering the mana queue IRQs, while other vCPUs are
> > > not running any network load.
> >
> > That sounds like an IRQ balancer bug which you're unable to reproduce.
> >
> > > It's because the placement depends on
> > > system-wide IRQ state at allocation time.
> >
> > I don't understand this point. The
> >
> > irq_set_affinity_and_hint(*irqs++, NULL);
> >
> > simply means: I trust system IRQ balancer to pick the best CPU for my
> > IRQ at runtime. It doesn't refer any "IRQ state at allocation time".
> >
> > > The linear approach however gaurantees each queue IRQ lands on a
> > > distinct vCPU regardless of system state. Even after stressing the cpus
> > > using stress-ng, we did not observe any significant throughput drop.
> >
> > If you just do nothing, it would lead to the same numbers, right? What
> > does that "non-significant throughput drop" mean? It sounds like the
> > linear approach is slightly worse.
>
> The numbers are not worse, they almost same in both the cases.
> >
> > --
> >
> > So, as you can't demonstrate solid benefit for the 'linear' IRQ placement,
> > I would just stick to the no-affinity logic.
>
> Thankyou Yury,
> We are investigating on more test scenarios and trying to
> capture numbers with both, your proposed change and the one from this
> patch. We will keep you updated about the results.
>
>
> - Vennela
Hi Yury,
Vennela and I ran a bunch of more tests and were able to reproduce the
clustering of mana IRQs issue we discussed earlier with the suggested
approach(setting the affinity and hint to NULL).
In these tests there were additional IRQs allocated(apart from MANA),
that disturbed the MANA IRQ distribution
ENV details
azure SKU(Standard_L4als_v5) 4 vcpu(2 cores), 5 MANA IRQs (1 HWC + 4
Queue)
"Affinity set to NULL" approach
========================================
MANA IRQ distribution vCPU
========================================
IRQ0 HWC 0
IRQ1 mana_q1 2
IRQ3 mana_q2 3
IRQ4 mana_q3 2
IRQ5 mana_q4 3
"Affinity set linearly" approach
========================================
MANA IRQ distribution vCPU
========================================
IRQ0 HWC 0
IRQ1 mana_q1 1
IRQ3 mana_q2 2
IRQ4 mana_q3 3
IRQ5 mana_q4 0
Throughput(Gbps) with high TCP connection
========================================
connection affinity NULL Linear
20480 5.25 13.49
10240 5.77 13.48
8192 7.16 13.48
6144 9.33 13.53
4096 13.50 13.50
Considering these results, we would like to proceed with the linear
approach that was proposed by this patch.
Regards,
Shradha
^ permalink raw reply
* [RFC] KVM/x86: Killing kvm_get_time_and_clockread() in favour of ktime_get_snapshot()
From: David Woodhouse @ 2026-05-26 13:57 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Thomas Gleixner, John Stultz,
Michael Kelley
Cc: Vitaly Kuznetsov, Marcelo Tosatti, Christopher S. Hall,
Stephen Boyd, Miroslav Lichvar, Ingo Molnar, Borislav Petkov,
Dave Hansen, H. Peter Anvin, K. Y. Srinivasan, Haiyang Zhang,
Wei Liu, Dexuan Cui, Daniel Lezcano, kvm, linux-hyperv, x86,
linux-kernel
[-- Attachment #1: Type: text/plain, Size: 2323 bytes --]
In 2012, as part of implementing the "master clock" mode for kvmclock,
Marcelo added kvm_get_time_and_clockread() in commit d828199e8444
("KVM: x86: implement PVCLOCK_TSC_STABLE_BIT pvclock flag").
In 2016, Christopher Hall added the generic ktime_get_snapshot() in
commit 9da0f49c8767 ("time: Add timekeeping snapshot code capturing
system time and counter"), which provides the same paired read of
{ time, counter } through the core timekeeping code.
Then in 2018, Vitaly Kuznetsov added Hyper-V TSC page support in
commit b0c39dc68e3b ("x86/kvm: Pass stable clocksource to guests when
running nested on Hyper-V"), which extended vgettsc() to handle the
HVCLOCK case.
I'd quite like to kill it all with fire and make KVM use
ktime_get_snapshot() instead.
However, to correlate with the TSC provided to guests, KVM needs the
underlying host TSC counter value, *not* the cycles count from the
hyperv_clocksource_tsc_page clocksource which is scaled to 10MHz.
If we wanted to support master clock mode while nesting under KVM and
bizarrely using the kvmclock for system timing, we'd have the same
problem with the kvmclock clocksource, which similarly scales to 1GHz.
One option is to say "Don't Do That Then™": if you want to provide a
masterclock kvmclock to guests then *don't* use the silly pvclocks for
your own kernel's timekeeping, use the damn TSC. Because if the TSC
*isn't* reliable then you can't do masterclock mode for your guests
anyway.
Perhaps that should have been the response when commit b0c39dc68e3b was
submitted, but I guess we're stuck supporting that mode now. But I
really do want to kill the KVM hacks and use ktime_get_snapshot().
Reverse-engineering the original TSC reading from the clocksource
counter value doesn't look sane, without a loss of precision and/or
128-bit division.
One simple option that occurs to me would be to add a 'cycles_raw'
value to the system_time_snapshot, for PV clocksources like hyperv and
kvmclock to populate with the original TSC reading.
That might actually let us clean up some of the PTP code that currently
has to deal with TSC vs. kvmclock in counter snapshots too. I think I
could kill the use of get_cycles() in vmclock for the kvmclock case,
which might make Thomas happy...
Any better ideas?
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]
^ permalink raw reply
* [PATCH v2 1/1] mshv: Add conditional VMBus dependency
From: Michael Kelley @ 2026-05-26 14:13 UTC (permalink / raw)
To: kys, haiyangz, wei.liu, decui, longli, jloeser, linux-hyperv
Cc: linux-kernel, arnd, hamzamahfooz
From: Michael Kelley <mhklinux@outlook.com>
When the VMBus driver is not part of the kernel (CONFIG_HYPERV_VMBUS=n),
the MSHV root driver fails to link:
ERROR: modpost: "hv_vmbus_exists" [drivers/hv/mshv_root.ko] undefined!
Fix this while meeting these requirements:
* It must be possible to include the MSHV root driver without the
VMBus driver. In such case, the MSHV root driver can be built-in
to the kernel image, or it can be built as a separate module.
* If both the MSHV root driver and the VMBus driver are present, the
MSHV root driver and VMBus driver can both be built-in, or they can
both be separate modules. Or the MSHV root driver can be a module
while the VMBus driver can be built-in, but the reverse is
disallowed. Regardless of the build choices, the VMBus driver must
be loaded before the MSHV driver in order for the SynIC to be
managed properly (see comments in the MSHV SynIC code).
The fix has two parts:
* Add a Kconfig entry for MSHV_ROOT to depend on HYPERV_VMBUS if
HYPERV_VMBUS is present. The entry disallows MSHV_ROOT being
built-in when HYPERV_VMBUS is a module, but without requiring that
HYPERV_VMBUS be built.
* Add a stub implementation of hv_vmbus_exists() for when the
VMBus driver is not present so that the MSHV root driver has
no module dependency on VMBus. When the VMBus driver *is*
present, the module dependency ensures that the VMBus driver
loads first when both are built as modules.
Existing code ensures that the VMBus driver loads first if it is
built-in. The VMBus driver uses subsys_initcall(), which is
initcall level 4. The MSHV root driver uses module_init(), which
becomes device_init() when built-in, and device_init() is
initcall level 6.
Reported-by: Arnd Bergmann <arnd@arndb.de>
Closes: https://lore.kernel.org/all/20260520074044.923728-1-arnd@kernel.org/
Signed-off-by: Michael Kelley <mhklinux@outlook.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Reviewed-by: Jork Loeser <jloeser@linux.microsoft.com>
---
Changes in v2:
* Instead of putting IS_ENABLED(CONFIG_HYPERV_VMBUS) around each of
the two calls to hv_vmbus_exists() in mshv_synic.c, provide a stub
for hv_vmbus_exists() when CONFIG_HYPERV_VMBUS is not set. The
effect is the same as in v1, but the code is cleaner. [Jork Loeser]
Arnd: I've kept your Ack even though I changed how hv_vmbus_exists()
is stubbed out since the effect is the same. Let me know if
you have any concerns.
drivers/hv/Kconfig | 1 +
include/linux/hyperv.h | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 2d0b3fcb0ff8..aa11bcefddf2 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -74,6 +74,7 @@ config MSHV_ROOT
# e.g. When withdrawing memory, the hypervisor gives back 4k pages in
# no particular order, making it impossible to reassemble larger pages
depends on PAGE_SIZE_4KB
+ depends on HYPERV_VMBUS if HYPERV_VMBUS
select EVENTFD
select VIRT_XFER_TO_GUEST_WORK
select HMM_MIRROR
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 41a3d82f0722..734b7ef98f4d 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1304,7 +1304,11 @@ static inline void *hv_get_drvdata(struct hv_device *dev)
struct device *hv_get_vmbus_root_device(void);
+#if IS_ENABLED(CONFIG_HYPERV_VMBUS)
bool hv_vmbus_exists(void);
+#else
+static inline bool hv_vmbus_exists(void) { return false; }
+#endif
struct hv_ring_buffer_debug_info {
u32 current_interrupt_mask;
--
2.25.1
^ permalink raw reply related
* Re: [EXTERNAL] Re: [PATCH rdma-next v2] RDMA/mana_ib: hardening: Clamp adapter capability values from MANA_IB_GET_ADAPTER_CAP
From: Erni Sri Satya Vennela @ 2026-05-26 14:43 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Long Li, Leon Romanovsky, Konstantin Taranov,
linux-rdma@vger.kernel.org, linux-hyperv@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <20260525230155.GB2487554@ziepe.ca>
On Mon, May 25, 2026 at 08:01:55PM -0300, Jason Gunthorpe wrote:
> On Mon, May 25, 2026 at 11:58:17AM -0700, Erni Sri Satya Vennela wrote:
> > > “There is no reason they should be signed, you should just fix the
> > > type.”
> >
> > It is not allowed to change sign in props, so clamping is the best bet.
>
> Why not? Fix the core code, it is just old junk they are signed, they
> should't never have been.
>
> Jason
Thanks for the feedback, Jason.
I sent the v3 before your comments in v2.
I'll be sending a v4 which drops the clamping entirely.
- Vennela
^ permalink raw reply
* RE: [PATCH] uio_hv_generic: Bind to FCopy device by default
From: Michael Kelley @ 2026-05-26 15:15 UTC (permalink / raw)
To: Naman Jain, Ben Hutchings
Cc: K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
Greg Kroah-Hartman, linux-hyperv@vger.kernel.org
In-Reply-To: <aa420dc1-029c-408b-aef0-f02d6bfa002c@linux.microsoft.com>
From: Naman Jain <namjain@linux.microsoft.com> Sent: Tuesday, May 26, 2026 3:10 AM
>
> On 5/26/2026 1:59 PM, Ben Hutchings wrote:
> > On Tue, 2026-05-26 at 12:15 +0530, Naman Jain wrote:
> >>
> >> On 5/25/2026 5:34 PM, Ben Hutchings wrote:
> >>> The Hyper-V kernel-mode fcopy driver was removed in 6.10 and the new
> >>> fcopy daemon requires this uio driver to function. However, by
> >>> default the driver does not bind to any devices, and must be
> >>> configured through the sysfs "new_id" file.
> >>>
> >>> Since the FCopy device is now only usable through this driver, add its
> >>> ID to the driver's ID table so that the daemon will work "out of the
> >>> box".
> >>>
> >>> Signed-off-by: Ben Hutchings <benh@debian.org>
> >>> Fixes: ec314f61e4fc ("Drivers: hv: Remove fcopy driver")
> >>> ---
> >>> --- a/drivers/uio/uio_hv_generic.c
> >>> +++ b/drivers/uio/uio_hv_generic.c
> >>> @@ -395,9 +395,15 @@ hv_uio_remove(struct hv_device *dev)
> >>> vmbus_free_ring(dev->channel);
> >>> }
> >>>
> >>> +static const struct hv_vmbus_device_id hv_uio_id_table[] = {
> >>> + { HV_FCOPY_GUID },
> >>> + {}
> >>> +};
> >>> +MODULE_DEVICE_TABLE(vmbus, hv_uio_id_table);
> >>> +
> >>> static struct hv_driver hv_uio_drv = {
> >>> .name = "uio_hv_generic",
> >>> - .id_table = NULL, /* only dynamic id's */
> >>> + .id_table = hv_uio_id_table,
> >>> .probe = hv_uio_probe,
> >>> .remove = hv_uio_remove,
> >>> };
> >>
>
> ++ recipients, assuming you mistakenly clicked reply instead of reply all.
Ben --
Regarding recipients, please include the full LKML
(linux-kernel@vger.kernel.org) on the original patch posting, even
though it is about a narrow Hyper-V issue. I dabble in areas beyond
just Hyper-V so subscribe to the full LKML instead of the
linux-hyperv mailing list. I miss patches like this one unless I happen
to be looking through the lore.kernel.org archives for linux-hyperv.
Thx,
Michael
>
>
> >> Two things worth considering before applying:
> >>
> >> 1. Please add Cc: stable@vger.kernel.org or is it that we do not want
> >> this to be ported to older kernels?
> >>
> >> 2. Every Hyper-V guest (with UIO_HV_GENERIC enabled) will now have an
> >> additional auto-bound /dev/uio0 node for FCopy.
> >
> > I don't think that's quite true. I tested with a Windows 11 host and
> > needed to enable "Guest services" for the VM, which was disabled by
> > default. But if that includes other features besides FCopy it might be
> > enabled for other reasons.
> >
>
> Yes, meaning if these two conditions are satisfied (enabling guest
> services is also one time step for a Hyper-V VM), we would see uio0 by
> default for fcopy.
>
> >> Anything that hardcodes
> >> /dev/uio0 (e.g. ad-hoc DPDK scripts that bind a NetVSC NIC via
> >> uio_hv_generic + new_id) may see its index shift, since FCopy now wins
> >> uio0 at boot.
> >
> > OK, so maybe I should implement the new_id dance in the fcopy service
> > startup, to avoid that? I did already looked at doing it in a systemd
> > unit, but it's hard to do right because adding the same ID twice is an
> > error. Maybe the daemon itself ould do it?
>
> Implementing it in uio daemon can introduce race conditions with sysfs
> creation. I guess it's OK then to implement it here, in kernel.
>
> >
> >> The fix for such consumers is the same thing DPDK and the
> >> in-tree daemon already do: resolve uio via
> >> /sys/bus/vmbus/devices/<guid>/uio/ rather than by number. This is not a
> >> regression in the patch, but it's a behavior change worth calling out.
> >
> > It would be a good reason *not* to make this change in stable.
> >
> > Ben.
> >
>
> What issues are you fixing with this patch exactly? Is there any
> particular sequence of events you are targeting where traditional
> approach does not work?
>
> Regards,
> Naman
^ permalink raw reply
* Re: [PATCH] uio_hv_generic: Bind to FCopy device by default
From: Naman Jain @ 2026-05-26 15:49 UTC (permalink / raw)
To: Michael Kelley, Ben Hutchings
Cc: K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
Greg Kroah-Hartman, linux-hyperv@vger.kernel.org
In-Reply-To: <SN6PR02MB41574FDA377FF59597181B7BD40B2@SN6PR02MB4157.namprd02.prod.outlook.com>
On 5/26/2026 8:45 PM, Michael Kelley wrote:
> From: Naman Jain <namjain@linux.microsoft.com> Sent: Tuesday, May 26, 2026 3:10 AM
>>
>> On 5/26/2026 1:59 PM, Ben Hutchings wrote:
>>> On Tue, 2026-05-26 at 12:15 +0530, Naman Jain wrote:
>>>>
>>>> On 5/25/2026 5:34 PM, Ben Hutchings wrote:
>>>>> The Hyper-V kernel-mode fcopy driver was removed in 6.10 and the new
>>>>> fcopy daemon requires this uio driver to function. However, by
>>>>> default the driver does not bind to any devices, and must be
>>>>> configured through the sysfs "new_id" file.
>>>>>
>>>>> Since the FCopy device is now only usable through this driver, add its
>>>>> ID to the driver's ID table so that the daemon will work "out of the
>>>>> box".
>>>>>
>>>>> Signed-off-by: Ben Hutchings <benh@debian.org>
>>>>> Fixes: ec314f61e4fc ("Drivers: hv: Remove fcopy driver")
>>>>> ---
>>>>> --- a/drivers/uio/uio_hv_generic.c
>>>>> +++ b/drivers/uio/uio_hv_generic.c
>>>>> @@ -395,9 +395,15 @@ hv_uio_remove(struct hv_device *dev)
>>>>> vmbus_free_ring(dev->channel);
>>>>> }
>>>>>
>>>>> +static const struct hv_vmbus_device_id hv_uio_id_table[] = {
>>>>> + { HV_FCOPY_GUID },
>>>>> + {}
>>>>> +};
>>>>> +MODULE_DEVICE_TABLE(vmbus, hv_uio_id_table);
>>>>> +
>>>>> static struct hv_driver hv_uio_drv = {
>>>>> .name = "uio_hv_generic",
>>>>> - .id_table = NULL, /* only dynamic id's */
>>>>> + .id_table = hv_uio_id_table,
>>>>> .probe = hv_uio_probe,
>>>>> .remove = hv_uio_remove,
>>>>> };
>>>>
>>
>> ++ recipients, assuming you mistakenly clicked reply instead of reply all.
>
> Ben --
>
> Regarding recipients, please include the full LKML
> (linux-kernel@vger.kernel.org) on the original patch posting, even
> though it is about a narrow Hyper-V issue. I dabble in areas beyond
> just Hyper-V so subscribe to the full LKML instead of the
> linux-hyperv mailing list. I miss patches like this one unless I happen
> to be looking through the lore.kernel.org archives for linux-hyperv.
>
> Thx,
>
> Michael
>
Sashiko also misses out on such patches if linux-kernel@vger.kernel.org
is not included. I could not find this in https://sashiko.dev/#/.
Regards,
Naman
^ permalink raw reply
* [PATCH 0/2] Remove stack ib_udata's
From: Jason Gunthorpe @ 2026-05-26 16:15 UTC (permalink / raw)
To: Abhijit Gangurde, Allen Hubbe,
Broadcom internal kernel review list, Bernard Metzler,
Potnuri Bharat Teja, Bryan Tan, Cheng Xu, Dennis Dalessandro,
Junxian Huang, Kai Shen, Kalesh AP, Konstantin Taranov,
Krzysztof Czurylo, Leon Romanovsky, linux-hyperv, linux-rdma,
Long Li, Michal Kalderon, Nelson Escobar, Satish Kharat,
Selvin Xavier, Chengchang Tang, Tatyana Nikolova, Vishnu Dasa,
Yishai Hadas, Zhu Yanjun
Cc: Leon Romanovsky, patches
Sashiko pointed out these are dangerous, and the create_qp() one is in
fact a bug. The query_device is just ugly old code.
Remove the stack ib_udata's from both places.
Jason Gunthorpe (2):
RDMA/core: Don't make a dummy ib_udata on the stack in create_qp
RDMA: Update the query_device() op
drivers/infiniband/core/core_priv.h | 2 +-
drivers/infiniband/core/device.c | 3 +--
drivers/infiniband/core/ib_core_uverbs.c | 12 +++++++++++
drivers/infiniband/core/rdma_core.h | 7 +++++++
drivers/infiniband/core/uverbs_cmd.c | 14 +------------
drivers/infiniband/core/uverbs_std_types_qp.c | 3 +--
drivers/infiniband/core/verbs.c | 20 ++++++++++---------
drivers/infiniband/hw/bnxt_re/ib_verbs.c | 5 ++++-
drivers/infiniband/hw/cxgb4/provider.c | 8 +++++---
drivers/infiniband/hw/erdma/erdma_verbs.c | 9 +++++++--
drivers/infiniband/hw/hns/hns_roce_main.c | 7 ++++++-
drivers/infiniband/hw/ionic/ionic_ibdev.c | 7 ++++++-
drivers/infiniband/hw/irdma/verbs.c | 8 +++++---
drivers/infiniband/hw/mana/main.c | 7 ++++++-
drivers/infiniband/hw/mlx4/main.c | 13 ++++++------
drivers/infiniband/hw/mthca/mthca_provider.c | 13 +++++++-----
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 8 +++++---
drivers/infiniband/hw/qedr/verbs.c | 7 ++++++-
drivers/infiniband/hw/usnic/usnic_ib_verbs.c | 8 +++++---
.../infiniband/hw/vmw_pvrdma/pvrdma_verbs.c | 8 +++++---
drivers/infiniband/sw/rdmavt/vt.c | 9 ++++++---
drivers/infiniband/sw/rxe/rxe_verbs.c | 14 ++++---------
drivers/infiniband/sw/siw/siw_verbs.c | 8 +++++---
23 files changed, 124 insertions(+), 76 deletions(-)
base-commit: fd9482545e37fb6b7e04b588ad2bd80a2779776c
--
2.43.0
^ permalink raw reply
* [PATCH 1/2] RDMA/core: Don't make a dummy ib_udata on the stack in create_qp
From: Jason Gunthorpe @ 2026-05-26 16:15 UTC (permalink / raw)
To: Abhijit Gangurde, Allen Hubbe,
Broadcom internal kernel review list, Bernard Metzler,
Potnuri Bharat Teja, Bryan Tan, Cheng Xu, Dennis Dalessandro,
Junxian Huang, Kai Shen, Kalesh AP, Konstantin Taranov,
Krzysztof Czurylo, Leon Romanovsky, linux-hyperv, linux-rdma,
Long Li, Michal Kalderon, Nelson Escobar, Satish Kharat,
Selvin Xavier, Chengchang Tang, Tatyana Nikolova, Vishnu Dasa,
Yishai Hadas, Zhu Yanjun
Cc: Leon Romanovsky, patches
In-Reply-To: <0-v1-922fa8e828ba+f7-ib_udata_stack_jgg@nvidia.com>
Sashiko points out the udata for destruction has to be created using
uverbs_get_cleared_udata(). Move it to ib_core_uverbs.c so that the core
qp code can call it. Rework the call chain to pass the struct
uverbs_attr_bundle right up to the driver op callback.
Fixes a possible wild stack reference in drivers during error unwinding,
mlx5 can call rdma_udata_to_drv_context() from destroy_qp() when
destroying a QP.
Fixes: 00a79d6b996d ("RDMA/core: Configure selinux QP during creation")
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/infiniband/core/core_priv.h | 2 +-
drivers/infiniband/core/ib_core_uverbs.c | 12 +++++++++++
drivers/infiniband/core/rdma_core.h | 7 +++++++
drivers/infiniband/core/uverbs_cmd.c | 14 +------------
drivers/infiniband/core/uverbs_std_types_qp.c | 3 +--
drivers/infiniband/core/verbs.c | 20 ++++++++++---------
6 files changed, 33 insertions(+), 25 deletions(-)
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index a2c36666e6fcb9..19104c542b270d 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -321,7 +321,7 @@ void nldev_exit(void);
struct ib_qp *ib_create_qp_user(struct ib_device *dev, struct ib_pd *pd,
struct ib_qp_init_attr *attr,
- struct ib_udata *udata,
+ struct uverbs_attr_bundle *uattrs,
struct ib_uqp_object *uobj, const char *caller);
void ib_qp_usecnt_inc(struct ib_qp *qp);
diff --git a/drivers/infiniband/core/ib_core_uverbs.c b/drivers/infiniband/core/ib_core_uverbs.c
index b4fc693a3bd8b7..6c3bc9ca1d58ef 100644
--- a/drivers/infiniband/core/ib_core_uverbs.c
+++ b/drivers/infiniband/core/ib_core_uverbs.c
@@ -532,6 +532,18 @@ int uverbs_destroy_def_handler(struct uverbs_attr_bundle *attrs)
}
EXPORT_SYMBOL(uverbs_destroy_def_handler);
+/*
+ * When calling a destroy function during an error unwind we need to pass in
+ * the udata that is sanitized of all user arguments. Ie from the driver
+ * perspective it looks like no udata was passed.
+ */
+struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs)
+{
+ attrs->driver_udata = (struct ib_udata){};
+ return &attrs->driver_udata;
+}
+EXPORT_SYMBOL_NS_GPL(uverbs_get_cleared_udata, "rdma_core");
+
/**
* _uverbs_alloc() - Quickly allocate memory for use with a bundle
* @bundle: The bundle
diff --git a/drivers/infiniband/core/rdma_core.h b/drivers/infiniband/core/rdma_core.h
index b626d3d24d087d..56121103e9f4f5 100644
--- a/drivers/infiniband/core/rdma_core.h
+++ b/drivers/infiniband/core/rdma_core.h
@@ -71,7 +71,14 @@ int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx);
void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile);
+#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs);
+#else
+static inline struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs)
+{
+ return NULL;
+}
+#endif
/*
* This is the runtime description of the uverbs API, used by the syscall
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 32914007bae66f..41ad11ae1123b7 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -163,17 +163,6 @@ static int uverbs_request_finish(struct uverbs_req_iter *iter)
return 0;
}
-/*
- * When calling a destroy function during an error unwind we need to pass in
- * the udata that is sanitized of all user arguments. Ie from the driver
- * perspective it looks like no udata was passed.
- */
-struct ib_udata *uverbs_get_cleared_udata(struct uverbs_attr_bundle *attrs)
-{
- attrs->driver_udata = (struct ib_udata){};
- return &attrs->driver_udata;
-}
-
static struct ib_uverbs_completion_event_file *
_ib_uverbs_lookup_comp_file(s32 fd, struct uverbs_attr_bundle *attrs)
{
@@ -1462,8 +1451,7 @@ static int create_qp(struct uverbs_attr_bundle *attrs,
attr.source_qpn = cmd->source_qpn;
}
- qp = ib_create_qp_user(device, pd, &attr, &attrs->driver_udata, obj,
- KBUILD_MODNAME);
+ qp = ib_create_qp_user(device, pd, &attr, attrs, obj, KBUILD_MODNAME);
if (IS_ERR(qp)) {
ret = PTR_ERR(qp);
goto err_put;
diff --git a/drivers/infiniband/core/uverbs_std_types_qp.c b/drivers/infiniband/core/uverbs_std_types_qp.c
index be0730e8509ed9..fd617903ffcf49 100644
--- a/drivers/infiniband/core/uverbs_std_types_qp.c
+++ b/drivers/infiniband/core/uverbs_std_types_qp.c
@@ -248,8 +248,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QP_CREATE)(
set_caps(&attr, &cap, true);
mutex_init(&obj->mcast_lock);
- qp = ib_create_qp_user(device, pd, &attr, &attrs->driver_udata, obj,
- KBUILD_MODNAME);
+ qp = ib_create_qp_user(device, pd, &attr, attrs, obj, KBUILD_MODNAME);
if (IS_ERR(qp)) {
ret = PTR_ERR(qp);
goto err_put;
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index bac87de9cc6735..1500bc09bdc915 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -53,6 +53,7 @@
#include <rdma/rw.h>
#include <rdma/lag.h>
+#include "rdma_core.h"
#include "core_priv.h"
#include <trace/events/rdma_core.h>
@@ -1265,10 +1266,9 @@ static struct ib_qp *create_xrc_qp_user(struct ib_qp *qp,
static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
struct ib_qp_init_attr *attr,
- struct ib_udata *udata,
+ struct uverbs_attr_bundle *uattrs,
struct ib_uqp_object *uobj, const char *caller)
{
- struct ib_udata dummy = {};
struct ib_qp *qp;
int ret;
@@ -1301,9 +1301,10 @@ static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
qp->recv_cq = attr->recv_cq;
rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP);
- WARN_ONCE(!udata && !caller, "Missing kernel QP owner");
- rdma_restrack_set_name(&qp->res, udata ? NULL : caller);
- ret = dev->ops.create_qp(qp, attr, udata);
+ WARN_ONCE(!uattrs && !caller, "Missing kernel QP owner");
+ rdma_restrack_set_name(&qp->res, uattrs ? NULL : caller);
+ ret = dev->ops.create_qp(qp, attr,
+ uattrs ? &uattrs->driver_udata : NULL);
if (ret)
goto err_create;
@@ -1322,7 +1323,8 @@ static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
return qp;
err_security:
- qp->device->ops.destroy_qp(qp, udata ? &dummy : NULL);
+ qp->device->ops.destroy_qp(
+ qp, uattrs ? uverbs_get_cleared_udata(uattrs) : NULL);
err_create:
rdma_restrack_put(&qp->res);
kfree(qp);
@@ -1338,13 +1340,13 @@ static struct ib_qp *create_qp(struct ib_device *dev, struct ib_pd *pd,
* @attr: A list of initial attributes required to create the
* QP. If QP creation succeeds, then the attributes are updated to
* the actual capabilities of the created QP.
- * @udata: User data
+ * @uattrs: User ioctl attributes and udata
* @uobj: uverbs obect
* @caller: caller's build-time module name
*/
struct ib_qp *ib_create_qp_user(struct ib_device *dev, struct ib_pd *pd,
struct ib_qp_init_attr *attr,
- struct ib_udata *udata,
+ struct uverbs_attr_bundle *uattrs,
struct ib_uqp_object *uobj, const char *caller)
{
struct ib_qp *qp, *xrc_qp;
@@ -1352,7 +1354,7 @@ struct ib_qp *ib_create_qp_user(struct ib_device *dev, struct ib_pd *pd,
if (attr->qp_type == IB_QPT_XRC_TGT)
qp = create_qp(dev, pd, attr, NULL, NULL, caller);
else
- qp = create_qp(dev, pd, attr, udata, uobj, NULL);
+ qp = create_qp(dev, pd, attr, uattrs, uobj, NULL);
if (attr->qp_type != IB_QPT_XRC_TGT || IS_ERR(qp))
return qp;
--
2.43.0
^ permalink raw reply related
* [PATCH 2/2] RDMA: Update the query_device() op
From: Jason Gunthorpe @ 2026-05-26 16:15 UTC (permalink / raw)
To: Abhijit Gangurde, Allen Hubbe,
Broadcom internal kernel review list, Bernard Metzler,
Potnuri Bharat Teja, Bryan Tan, Cheng Xu, Dennis Dalessandro,
Junxian Huang, Kai Shen, Kalesh AP, Konstantin Taranov,
Krzysztof Czurylo, Leon Romanovsky, linux-hyperv, linux-rdma,
Long Li, Michal Kalderon, Nelson Escobar, Satish Kharat,
Selvin Xavier, Chengchang Tang, Tatyana Nikolova, Vishnu Dasa,
Yishai Hadas, Zhu Yanjun
Cc: Leon Romanovsky, patches
In-Reply-To: <0-v1-922fa8e828ba+f7-ib_udata_stack_jgg@nvidia.com>
This op hasn't followed the normal pattern of passing NULL for udata when
invoked by the kernel. Instead the kernel caller creates a dummy ib_udata
on the stack and passes that in. It does not seem to currently be a bug,
but this flow should be modernized to use the new API flow and in the
process accept NULL as well.
Only mlx4 uses an input request structure, have every other driver call
ib_is_udata_in_empty() to enforce the lack of request structs.
Use ib_respond_empty_udata() in every driver that does not use a response
struct.
Ensure a check for NULL udata before calling ib_respond_udata() in
bnxt_re, efa, and mlx5.
Make mlx4 safe to be called with NULL.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/infiniband/core/device.c | 3 +--
drivers/infiniband/hw/bnxt_re/ib_verbs.c | 5 ++++-
drivers/infiniband/hw/cxgb4/provider.c | 8 +++++---
drivers/infiniband/hw/erdma/erdma_verbs.c | 9 +++++++--
drivers/infiniband/hw/hns/hns_roce_main.c | 7 ++++++-
drivers/infiniband/hw/ionic/ionic_ibdev.c | 7 ++++++-
drivers/infiniband/hw/irdma/verbs.c | 8 +++++---
drivers/infiniband/hw/mana/main.c | 7 ++++++-
drivers/infiniband/hw/mlx4/main.c | 13 +++++++------
drivers/infiniband/hw/mthca/mthca_provider.c | 13 ++++++++-----
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 8 +++++---
drivers/infiniband/hw/qedr/verbs.c | 7 ++++++-
drivers/infiniband/hw/usnic/usnic_ib_verbs.c | 8 +++++---
drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c | 8 +++++---
drivers/infiniband/sw/rdmavt/vt.c | 9 ++++++---
drivers/infiniband/sw/rxe/rxe_verbs.c | 14 ++++----------
drivers/infiniband/sw/siw/siw_verbs.c | 8 +++++---
17 files changed, 91 insertions(+), 51 deletions(-)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index b89efaaa81ec58..9f9662e9228186 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1245,7 +1245,6 @@ static int assign_name(struct ib_device *device, const char *name)
*/
static int setup_device(struct ib_device *device)
{
- struct ib_udata uhw = {.outlen = 0, .inlen = 0};
int ret;
ib_device_check_mandatory(device);
@@ -1257,7 +1256,7 @@ static int setup_device(struct ib_device *device)
}
memset(&device->attrs, 0, sizeof(device->attrs));
- ret = device->ops.query_device(device, &device->attrs, &uhw);
+ ret = device->ops.query_device(device, &device->attrs, NULL);
if (ret) {
dev_warn(&device->dev,
"Couldn't query the device attributes\n");
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 94aa06e3b828ca..98d65c1b102200 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -265,7 +265,10 @@ int bnxt_re_query_device(struct ib_device *ibdev,
resp.packet_pacing_caps.supported_qpts =
1 << IB_QPT_RC;
}
- return ib_respond_udata(udata, resp);
+
+ if (udata)
+ return ib_respond_udata(udata, resp);
+ return 0;
}
int bnxt_re_modify_device(struct ib_device *ibdev,
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index 0e3827022c63da..e1eec37ee8222a 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -259,11 +259,13 @@ static int c4iw_query_device(struct ib_device *ibdev, struct ib_device_attr *pro
{
struct c4iw_dev *dev;
+ int err;
pr_debug("ibdev %p\n", ibdev);
- if (uhw->inlen || uhw->outlen)
- return -EINVAL;
+ err = ib_is_udata_in_empty(uhw);
+ if (err)
+ return err;
dev = to_c4iw_dev(ibdev);
addrconf_addr_eui48((u8 *)&props->sys_image_guid,
@@ -298,7 +300,7 @@ static int c4iw_query_device(struct ib_device *ibdev, struct ib_device_attr *pro
props->max_fast_reg_page_list_len =
t4_max_fr_depth(dev->rdev.lldi.ulptx_memwrite_dsgl && use_dsgl);
- return 0;
+ return ib_respond_empty_udata(uhw);
}
static int c4iw_query_port(struct ib_device *ibdev, u32 port,
diff --git a/drivers/infiniband/hw/erdma/erdma_verbs.c b/drivers/infiniband/hw/erdma/erdma_verbs.c
index b59c2e3a5306d1..d9eb8ae2c56fba 100644
--- a/drivers/infiniband/hw/erdma/erdma_verbs.c
+++ b/drivers/infiniband/hw/erdma/erdma_verbs.c
@@ -315,9 +315,14 @@ erdma_user_mmap_entry_insert(struct erdma_ucontext *uctx, void *address,
}
int erdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
- struct ib_udata *unused)
+ struct ib_udata *udata)
{
struct erdma_dev *dev = to_edev(ibdev);
+ int err;
+
+ err = ib_is_udata_in_empty(udata);
+ if (err)
+ return err;
memset(attr, 0, sizeof(*attr));
@@ -358,7 +363,7 @@ int erdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
addrconf_addr_eui48((u8 *)&attr->sys_image_guid,
dev->netdev->dev_addr);
- return 0;
+ return ib_respond_empty_udata(udata);
}
int erdma_query_gid(struct ib_device *ibdev, u32 port, int idx,
diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c
index 77bad9f5d482bb..c6f633bd5a3402 100644
--- a/drivers/infiniband/hw/hns/hns_roce_main.c
+++ b/drivers/infiniband/hw/hns/hns_roce_main.c
@@ -221,6 +221,11 @@ static int hns_roce_query_device(struct ib_device *ib_dev,
struct ib_udata *uhw)
{
struct hns_roce_dev *hr_dev = to_hr_dev(ib_dev);
+ int ret;
+
+ ret = ib_is_udata_in_empty(uhw);
+ if (ret)
+ return ret;
memset(props, 0, sizeof(*props));
@@ -274,7 +279,7 @@ static int hns_roce_query_device(struct ib_device *ib_dev,
if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_XRC)
props->device_cap_flags |= IB_DEVICE_XRC;
- return 0;
+ return ib_respond_empty_udata(uhw);
}
static int hns_roce_query_port(struct ib_device *ib_dev, u32 port_num,
diff --git a/drivers/infiniband/hw/ionic/ionic_ibdev.c b/drivers/infiniband/hw/ionic/ionic_ibdev.c
index 73a616ae350236..b0449c75f8938f 100644
--- a/drivers/infiniband/hw/ionic/ionic_ibdev.c
+++ b/drivers/infiniband/hw/ionic/ionic_ibdev.c
@@ -25,6 +25,11 @@ static int ionic_query_device(struct ib_device *ibdev,
{
struct ionic_ibdev *dev = to_ionic_ibdev(ibdev);
struct net_device *ndev;
+ int err;
+
+ err = ib_is_udata_in_empty(udata);
+ if (err)
+ return err;
ndev = ib_device_get_netdev(ibdev, 1);
addrconf_ifid_eui48((u8 *)&attr->sys_image_guid, ndev);
@@ -69,7 +74,7 @@ static int ionic_query_device(struct ib_device *ibdev,
attr->max_fast_reg_page_list_len = dev->lif_cfg.npts_per_lif / 2;
attr->max_pkeys = IONIC_PKEY_TBL_LEN;
- return 0;
+ return ib_respond_empty_udata(udata);
}
static int ionic_query_port(struct ib_device *ibdev, u32 port,
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 3f4811bb5514c6..5ba2e63b51036e 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -16,9 +16,11 @@ static int irdma_query_device(struct ib_device *ibdev,
struct irdma_pci_f *rf = iwdev->rf;
struct pci_dev *pcidev = iwdev->rf->pcidev;
struct irdma_hw_attrs *hw_attrs = &rf->sc_dev.hw_attrs;
+ int err;
- if (udata->inlen || udata->outlen)
- return -EINVAL;
+ err = ib_is_udata_in_empty(udata);
+ if (err)
+ return err;
memset(props, 0, sizeof(*props));
addrconf_addr_eui48((u8 *)&props->sys_image_guid,
@@ -74,7 +76,7 @@ static int irdma_query_device(struct ib_device *ibdev,
if (hw_attrs->uk_attrs.hw_rev >= IRDMA_GEN_3)
props->device_cap_flags |= IB_DEVICE_MEM_WINDOW_TYPE_2B;
- return 0;
+ return ib_respond_empty_udata(udata);
}
/**
diff --git a/drivers/infiniband/hw/mana/main.c b/drivers/infiniband/hw/mana/main.c
index 307ae01bf26f34..4dcd048d44b69a 100644
--- a/drivers/infiniband/hw/mana/main.c
+++ b/drivers/infiniband/hw/mana/main.c
@@ -549,6 +549,11 @@ int mana_ib_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
{
struct mana_ib_dev *dev = container_of(ibdev, struct mana_ib_dev, ib_dev);
struct pci_dev *pdev = to_pci_dev(mdev_to_gc(dev)->dev);
+ int err;
+
+ err = ib_is_udata_in_empty(uhw);
+ if (err)
+ return err;
memset(props, 0, sizeof(*props));
props->vendor_id = pdev->vendor;
@@ -576,7 +581,7 @@ int mana_ib_query_device(struct ib_device *ibdev, struct ib_device_attr *props,
if (!mana_ib_is_rnic(dev))
props->raw_packet_caps = IB_RAW_PACKET_CAP_IP_CSUM;
- return 0;
+ return ib_respond_empty_udata(uhw);
}
int mana_ib_query_port(struct ib_device *ibdev, u32 port,
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index d50743f090bf21..17073e8f105aab 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -444,8 +444,9 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
struct mlx4_uverbs_ex_query_device cmd;
struct mlx4_uverbs_ex_query_device_resp resp = {};
struct mlx4_clock_params clock_params;
+ size_t uhw_outlen = uhw ? uhw->outlen : 0;
- if (uhw->inlen) {
+ if (uhw && uhw->inlen) {
err = ib_copy_validate_udata_in_cm(uhw, cmd, reserved, 0);
if (err)
return err;
@@ -572,7 +573,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
props->cq_caps.max_cq_moderation_count = MLX4_MAX_CQ_COUNT;
props->cq_caps.max_cq_moderation_period = MLX4_MAX_CQ_PERIOD;
- if (uhw->outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) {
+ if (uhw_outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) {
resp.response_length += sizeof(resp.hca_core_clock_offset);
if (!mlx4_get_internal_clock_params(dev->dev, &clock_params)) {
resp.comp_mask |= MLX4_IB_QUERY_DEV_RESP_MASK_CORE_CLOCK_OFFSET;
@@ -580,14 +581,14 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
}
}
- if (uhw->outlen >= resp.response_length +
+ if (uhw_outlen >= resp.response_length +
sizeof(resp.max_inl_recv_sz)) {
resp.response_length += sizeof(resp.max_inl_recv_sz);
resp.max_inl_recv_sz = dev->dev->caps.max_rq_sg *
sizeof(struct mlx4_wqe_data_seg);
}
- if (offsetofend(typeof(resp), rss_caps) <= uhw->outlen) {
+ if (offsetofend(typeof(resp), rss_caps) <= uhw_outlen) {
if (props->rss_caps.supported_qpts) {
resp.rss_caps.rx_hash_function =
MLX4_IB_RX_HASH_FUNC_TOEPLITZ;
@@ -611,7 +612,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
sizeof(resp.rss_caps);
}
- if (offsetofend(typeof(resp), tso_caps) <= uhw->outlen) {
+ if (offsetofend(typeof(resp), tso_caps) <= uhw_outlen) {
if (dev->dev->caps.max_gso_sz &&
((mlx4_ib_port_link_layer(ibdev, 1) ==
IB_LINK_LAYER_ETHERNET) ||
@@ -625,7 +626,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
sizeof(resp.tso_caps);
}
- if (uhw->outlen) {
+ if (uhw_outlen) {
err = ib_respond_udata(uhw, resp);
if (err)
goto out;
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index afa97d3801f783..079c51003b24a4 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -55,16 +55,19 @@ static int mthca_query_device(struct ib_device *ibdev, struct ib_device_attr *pr
{
struct ib_smp *in_mad;
struct ib_smp *out_mad;
- int err = -ENOMEM;
+ int err;
struct mthca_dev *mdev = to_mdev(ibdev);
- if (uhw->inlen || uhw->outlen)
- return -EINVAL;
+ err = ib_is_udata_in_empty(uhw);
+ if (err)
+ return err;
in_mad = kzalloc_obj(*in_mad);
out_mad = kmalloc_obj(*out_mad);
- if (!in_mad || !out_mad)
+ if (!in_mad || !out_mad) {
+ err = -ENOMEM;
goto out;
+ }
memset(props, 0, sizeof *props);
@@ -111,7 +114,7 @@ static int mthca_query_device(struct ib_device *ibdev, struct ib_device_attr *pr
props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
props->max_mcast_grp;
- err = 0;
+ err = ib_respond_empty_udata(uhw);
out:
kfree(in_mad);
kfree(out_mad);
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index 383f1d9c15d151..17def9d9ce99ca 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -68,9 +68,11 @@ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
struct ib_udata *uhw)
{
struct ocrdma_dev *dev = get_ocrdma_dev(ibdev);
+ int err;
- if (uhw->inlen || uhw->outlen)
- return -EINVAL;
+ err = ib_is_udata_in_empty(uhw);
+ if (err)
+ return err;
memset(attr, 0, sizeof *attr);
memcpy(&attr->fw_ver, &dev->attr.fw_ver[0],
@@ -110,7 +112,7 @@ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr,
attr->local_ca_ack_delay = dev->attr.local_ca_ack_delay;
attr->max_fast_reg_page_list_len = dev->attr.max_pages_per_frmr;
attr->max_pkeys = 1;
- return 0;
+ return ib_respond_empty_udata(uhw);
}
static inline void get_link_speed_and_width(struct ocrdma_dev *dev,
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index 1af908275ca729..cf01078820d8cb 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -105,6 +105,7 @@ int qedr_query_device(struct ib_device *ibdev,
{
struct qedr_dev *dev = get_qedr_dev(ibdev);
struct qedr_device_attr *qattr = &dev->attr;
+ int rc;
if (!dev->rdma_ctx) {
DP_ERR(dev,
@@ -113,6 +114,10 @@ int qedr_query_device(struct ib_device *ibdev,
return -EINVAL;
}
+ rc = ib_is_udata_in_empty(udata);
+ if (rc)
+ return rc;
+
memset(attr, 0, sizeof(*attr));
attr->fw_ver = qattr->fw_ver;
@@ -155,7 +160,7 @@ int qedr_query_device(struct ib_device *ibdev,
attr->max_pkeys = qattr->max_pkey;
attr->max_ah = qattr->max_ah;
- return 0;
+ return ib_respond_empty_udata(udata);
}
static inline void get_link_speed_and_width(int speed, u16 *ib_speed,
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
index 261f18a8368543..dc355b00f61cec 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
@@ -275,10 +275,12 @@ int usnic_ib_query_device(struct ib_device *ibdev,
union ib_gid gid;
struct ethtool_drvinfo info;
int qp_per_vf;
+ int err;
usnic_dbg("\n");
- if (uhw->inlen || uhw->outlen)
- return -EINVAL;
+ err = ib_is_udata_in_empty(uhw);
+ if (err)
+ return err;
mutex_lock(&us_ibdev->usdev_lock);
us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info);
@@ -322,7 +324,7 @@ int usnic_ib_query_device(struct ib_device *ibdev,
* max_qp_wr, max_sge, max_sge_rd, max_cqe */
mutex_unlock(&us_ibdev->usdev_lock);
- return 0;
+ return ib_respond_empty_udata(uhw);
}
int usnic_ib_query_port(struct ib_device *ibdev, u32 port,
diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
index b9c3202b9545e3..1d29a535f76a8c 100644
--- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
+++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
@@ -67,9 +67,11 @@ int pvrdma_query_device(struct ib_device *ibdev,
struct ib_udata *uhw)
{
struct pvrdma_dev *dev = to_vdev(ibdev);
+ int err;
- if (uhw->inlen || uhw->outlen)
- return -EINVAL;
+ err = ib_is_udata_in_empty(uhw);
+ if (err)
+ return err;
props->fw_ver = dev->dsr->caps.fw_ver;
props->sys_image_guid = dev->dsr->caps.sys_image_guid;
@@ -114,7 +116,7 @@ int pvrdma_query_device(struct ib_device *ibdev,
props->device_cap_flags |= IB_DEVICE_PORT_ACTIVE_EVENT |
IB_DEVICE_RC_RNR_NAK_GEN;
- return 0;
+ return ib_respond_empty_udata(uhw);
}
/**
diff --git a/drivers/infiniband/sw/rdmavt/vt.c b/drivers/infiniband/sw/rdmavt/vt.c
index 40aa6420836470..5fa3a1f3332689 100644
--- a/drivers/infiniband/sw/rdmavt/vt.c
+++ b/drivers/infiniband/sw/rdmavt/vt.c
@@ -6,6 +6,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/dma-mapping.h>
+#include <rdma/uverbs_ioctl.h>
#include "vt.h"
#include "cq.h"
#include "trace.h"
@@ -79,14 +80,16 @@ static int rvt_query_device(struct ib_device *ibdev,
struct ib_udata *uhw)
{
struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
+ int err;
- if (uhw->inlen || uhw->outlen)
- return -EINVAL;
+ err = ib_is_udata_in_empty(uhw);
+ if (err)
+ return err;
/*
* Return rvt_dev_info.dparms.props contents
*/
*props = rdi->dparms.props;
- return 0;
+ return ib_respond_empty_udata(uhw);
}
static int rvt_get_numa_node(struct ib_device *ibdev)
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index 8edd4dd1f031f4..5815ce34d9704c 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -22,19 +22,13 @@ static int rxe_query_device(struct ib_device *ibdev,
struct rxe_dev *rxe = to_rdev(ibdev);
int err;
- if (udata->inlen || udata->outlen) {
- rxe_dbg_dev(rxe, "malformed udata\n");
- err = -EINVAL;
- goto err_out;
- }
+ err = ib_is_udata_in_empty(udata);
+ if (err)
+ return err;
memcpy(attr, &rxe->attr, sizeof(*attr));
- return 0;
-
-err_out:
- rxe_err_dev(rxe, "returned err = %d\n", err);
- return err;
+ return ib_respond_empty_udata(udata);
}
static int rxe_query_port(struct ib_device *ibdev,
diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c
index b34f3d6547ffc7..b74ac85c1b8b8b 100644
--- a/drivers/infiniband/sw/siw/siw_verbs.c
+++ b/drivers/infiniband/sw/siw/siw_verbs.c
@@ -130,9 +130,11 @@ int siw_query_device(struct ib_device *base_dev, struct ib_device_attr *attr,
struct ib_udata *udata)
{
struct siw_device *sdev = to_siw_dev(base_dev);
+ int rv;
- if (udata->inlen || udata->outlen)
- return -EINVAL;
+ rv = ib_is_udata_in_empty(udata);
+ if (rv)
+ return rv;
memset(attr, 0, sizeof(*attr));
@@ -165,7 +167,7 @@ int siw_query_device(struct ib_device *base_dev, struct ib_device_attr *attr,
addrconf_addr_eui48((u8 *)&attr->sys_image_guid,
sdev->raw_gid);
- return 0;
+ return ib_respond_empty_udata(udata);
}
int siw_query_port(struct ib_device *base_dev, u32 port,
--
2.43.0
^ permalink raw reply related
* [PATCH 1/1] drm/hyperv: Replace "hyperv_" with "hvdrm_" as symbol name prefix
From: Michael Kelley @ 2026-05-26 20:52 UTC (permalink / raw)
To: maarten.lankhorst, mripard, tzimmermann, airlied, simona, decui,
longli, ssengar
Cc: dri-devel, linux-kernel, linux-hyperv
From: Michael Kelley <mhklinux@outlook.com>
Function and structure names in the Hyper-V DRM driver currently
use "hyperv_" as the prefix. This conflicts with usage in core Hyper-V
and VMBus code, and incorrectly implies that functions and structures
in this driver apply generically to Hyper-V. A specific conflict arises
for "hyperv_init", which is an initcall for generic Hyper-V
initialization on arm64. The conflict prevents the use of
initcall_blacklist on the kernel boot line to skip loading this driver.
Fix this by substituting "hvdrm_" as the prefix for all functions and
structures in this driver. This prefix marries the existing "hv" prefix
for Hyper-V related code with "drm" to indicate this driver.
The changes are all mechanical text substitution in symbol names.
There are no other code or functional changes.
Signed-off-by: Michael Kelley <mhklinux@outlook.com>
---
This patch is built against linux-next20260526.
drivers/gpu/drm/hyperv/hyperv_drm.h | 20 ++--
drivers/gpu/drm/hyperv/hyperv_drm_drv.c | 88 ++++++++--------
drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 110 ++++++++++----------
drivers/gpu/drm/hyperv/hyperv_drm_proto.c | 70 ++++++-------
4 files changed, 144 insertions(+), 144 deletions(-)
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm.h b/drivers/gpu/drm/hyperv/hyperv_drm.h
index 9e776112c03e..66bd8730aad2 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm.h
+++ b/drivers/gpu/drm/hyperv/hyperv_drm.h
@@ -8,7 +8,7 @@
#define VMBUS_MAX_PACKET_SIZE 0x4000
-struct hyperv_drm_device {
+struct hvdrm_drm_device {
/* drm */
struct drm_device dev;
struct drm_plane plane;
@@ -39,17 +39,17 @@ struct hyperv_drm_device {
struct hv_device *hdev;
};
-#define to_hv(_dev) container_of(_dev, struct hyperv_drm_device, dev)
+#define to_hv(_dev) container_of(_dev, struct hvdrm_drm_device, dev)
-/* hyperv_drm_modeset */
-int hyperv_mode_config_init(struct hyperv_drm_device *hv);
+/* hvdrm_drm_modeset */
+int hvdrm_mode_config_init(struct hvdrm_drm_device *hv);
-/* hyperv_drm_proto */
-int hyperv_update_vram_location(struct hv_device *hdev, phys_addr_t vram_pp);
-int hyperv_update_situation(struct hv_device *hdev, u8 active, u32 bpp,
+/* hvdrm_drm_proto */
+int hvdrm_update_vram_location(struct hv_device *hdev, phys_addr_t vram_pp);
+int hvdrm_update_situation(struct hv_device *hdev, u8 active, u32 bpp,
u32 w, u32 h, u32 pitch);
-int hyperv_hide_hw_ptr(struct hv_device *hdev);
-int hyperv_update_dirt(struct hv_device *hdev, struct drm_rect *rect);
-int hyperv_connect_vsp(struct hv_device *hdev);
+int hvdrm_hide_hw_ptr(struct hv_device *hdev);
+int hvdrm_update_dirt(struct hv_device *hdev, struct drm_rect *rect);
+int hvdrm_connect_vsp(struct hv_device *hdev);
#endif
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
index b6bf6412ae34..a4456ccf340e 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
@@ -26,7 +26,7 @@
DEFINE_DRM_GEM_FOPS(hv_fops);
-static struct drm_driver hyperv_driver = {
+static struct drm_driver hvdrm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
.name = DRIVER_NAME,
@@ -39,17 +39,17 @@ static struct drm_driver hyperv_driver = {
DRM_FBDEV_SHMEM_DRIVER_OPS,
};
-static int hyperv_pci_probe(struct pci_dev *pdev,
+static int hvdrm_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
return 0;
}
-static void hyperv_pci_remove(struct pci_dev *pdev)
+static void hvdrm_pci_remove(struct pci_dev *pdev)
{
}
-static const struct pci_device_id hyperv_pci_tbl[] = {
+static const struct pci_device_id hvdrm_pci_tbl[] = {
{
.vendor = PCI_VENDOR_ID_MICROSOFT,
.device = PCI_DEVICE_ID_HYPERV_VIDEO,
@@ -60,14 +60,14 @@ static const struct pci_device_id hyperv_pci_tbl[] = {
/*
* PCI stub to support gen1 VM.
*/
-static struct pci_driver hyperv_pci_driver = {
+static struct pci_driver hvdrm_pci_driver = {
.name = KBUILD_MODNAME,
- .id_table = hyperv_pci_tbl,
- .probe = hyperv_pci_probe,
- .remove = hyperv_pci_remove,
+ .id_table = hvdrm_pci_tbl,
+ .probe = hvdrm_pci_probe,
+ .remove = hvdrm_pci_remove,
};
-static int hyperv_setup_vram(struct hyperv_drm_device *hv,
+static int hvdrm_setup_vram(struct hvdrm_drm_device *hv,
struct hv_device *hdev)
{
struct drm_device *dev = &hv->dev;
@@ -102,15 +102,15 @@ static int hyperv_setup_vram(struct hyperv_drm_device *hv,
return ret;
}
-static int hyperv_vmbus_probe(struct hv_device *hdev,
+static int hvdrm_vmbus_probe(struct hv_device *hdev,
const struct hv_vmbus_device_id *dev_id)
{
- struct hyperv_drm_device *hv;
+ struct hvdrm_drm_device *hv;
struct drm_device *dev;
int ret;
- hv = devm_drm_dev_alloc(&hdev->device, &hyperv_driver,
- struct hyperv_drm_device, dev);
+ hv = devm_drm_dev_alloc(&hdev->device, &hvdrm_driver,
+ struct hvdrm_drm_device, dev);
if (IS_ERR(hv))
return PTR_ERR(hv);
@@ -119,15 +119,15 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
hv_set_drvdata(hdev, hv);
hv->hdev = hdev;
- ret = hyperv_connect_vsp(hdev);
+ ret = hvdrm_connect_vsp(hdev);
if (ret) {
drm_err(dev, "Failed to connect to vmbus.\n");
goto err_hv_set_drv_data;
}
- aperture_remove_all_conflicting_devices(hyperv_driver.name);
+ aperture_remove_all_conflicting_devices(hvdrm_driver.name);
- ret = hyperv_setup_vram(hv, hdev);
+ ret = hvdrm_setup_vram(hv, hdev);
if (ret)
goto err_vmbus_close;
@@ -136,11 +136,11 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
* vram location is not fatal. Device will update dirty area till
* preferred resolution only.
*/
- ret = hyperv_update_vram_location(hdev, hv->fb_base);
+ ret = hvdrm_update_vram_location(hdev, hv->fb_base);
if (ret)
drm_warn(dev, "Failed to update vram location.\n");
- ret = hyperv_mode_config_init(hv);
+ ret = hvdrm_mode_config_init(hv);
if (ret)
goto err_free_mmio;
@@ -168,10 +168,10 @@ static int hyperv_vmbus_probe(struct hv_device *hdev,
return ret;
}
-static void hyperv_vmbus_remove(struct hv_device *hdev)
+static void hvdrm_vmbus_remove(struct hv_device *hdev)
{
struct drm_device *dev = hv_get_drvdata(hdev);
- struct hyperv_drm_device *hv = to_hv(dev);
+ struct hvdrm_drm_device *hv = to_hv(dev);
vmbus_set_skip_unload(false);
drm_dev_unplug(dev);
@@ -183,12 +183,12 @@ static void hyperv_vmbus_remove(struct hv_device *hdev)
vmbus_free_mmio(hv->mem->start, hv->fb_size);
}
-static void hyperv_vmbus_shutdown(struct hv_device *hdev)
+static void hvdrm_vmbus_shutdown(struct hv_device *hdev)
{
drm_atomic_helper_shutdown(hv_get_drvdata(hdev));
}
-static int hyperv_vmbus_suspend(struct hv_device *hdev)
+static int hvdrm_vmbus_suspend(struct hv_device *hdev)
{
struct drm_device *dev = hv_get_drvdata(hdev);
int ret;
@@ -202,67 +202,67 @@ static int hyperv_vmbus_suspend(struct hv_device *hdev)
return 0;
}
-static int hyperv_vmbus_resume(struct hv_device *hdev)
+static int hvdrm_vmbus_resume(struct hv_device *hdev)
{
struct drm_device *dev = hv_get_drvdata(hdev);
- struct hyperv_drm_device *hv = to_hv(dev);
+ struct hvdrm_drm_device *hv = to_hv(dev);
int ret;
- ret = hyperv_connect_vsp(hdev);
+ ret = hvdrm_connect_vsp(hdev);
if (ret)
return ret;
- ret = hyperv_update_vram_location(hdev, hv->fb_base);
+ ret = hvdrm_update_vram_location(hdev, hv->fb_base);
if (ret)
return ret;
return drm_mode_config_helper_resume(dev);
}
-static const struct hv_vmbus_device_id hyperv_vmbus_tbl[] = {
+static const struct hv_vmbus_device_id hvdrm_vmbus_tbl[] = {
/* Synthetic Video Device GUID */
{HV_SYNTHVID_GUID},
{}
};
-static struct hv_driver hyperv_hv_driver = {
+static struct hv_driver hvdrm_hv_driver = {
.name = KBUILD_MODNAME,
- .id_table = hyperv_vmbus_tbl,
- .probe = hyperv_vmbus_probe,
- .remove = hyperv_vmbus_remove,
- .shutdown = hyperv_vmbus_shutdown,
- .suspend = hyperv_vmbus_suspend,
- .resume = hyperv_vmbus_resume,
+ .id_table = hvdrm_vmbus_tbl,
+ .probe = hvdrm_vmbus_probe,
+ .remove = hvdrm_vmbus_remove,
+ .shutdown = hvdrm_vmbus_shutdown,
+ .suspend = hvdrm_vmbus_suspend,
+ .resume = hvdrm_vmbus_resume,
.driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
};
-static int __init hyperv_init(void)
+static int __init hvdrm_init(void)
{
int ret;
if (drm_firmware_drivers_only())
return -ENODEV;
- ret = pci_register_driver(&hyperv_pci_driver);
+ ret = pci_register_driver(&hvdrm_pci_driver);
if (ret != 0)
return ret;
- return vmbus_driver_register(&hyperv_hv_driver);
+ return vmbus_driver_register(&hvdrm_hv_driver);
}
-static void __exit hyperv_exit(void)
+static void __exit hvdrm_exit(void)
{
- vmbus_driver_unregister(&hyperv_hv_driver);
- pci_unregister_driver(&hyperv_pci_driver);
+ vmbus_driver_unregister(&hvdrm_hv_driver);
+ pci_unregister_driver(&hvdrm_pci_driver);
}
-module_init(hyperv_init);
-module_exit(hyperv_exit);
+module_init(hvdrm_init);
+module_exit(hvdrm_exit);
-MODULE_DEVICE_TABLE(pci, hyperv_pci_tbl);
-MODULE_DEVICE_TABLE(vmbus, hyperv_vmbus_tbl);
+MODULE_DEVICE_TABLE(pci, hvdrm_pci_tbl);
+MODULE_DEVICE_TABLE(vmbus, hvdrm_vmbus_tbl);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Deepak Rawat <drawat.floss@gmail.com>");
MODULE_DESCRIPTION("DRM driver for Hyper-V synthetic video device");
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
index 793dbbf61893..6844d085e709 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
@@ -25,11 +25,11 @@
#include "hyperv_drm.h"
-static int hyperv_blit_to_vram_rect(struct drm_framebuffer *fb,
+static int hvdrm_blit_to_vram_rect(struct drm_framebuffer *fb,
const struct iosys_map *vmap,
struct drm_rect *rect)
{
- struct hyperv_drm_device *hv = to_hv(fb->dev);
+ struct hvdrm_drm_device *hv = to_hv(fb->dev);
struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(hv->vram);
int idx;
@@ -44,9 +44,9 @@ static int hyperv_blit_to_vram_rect(struct drm_framebuffer *fb,
return 0;
}
-static int hyperv_connector_get_modes(struct drm_connector *connector)
+static int hvdrm_connector_get_modes(struct drm_connector *connector)
{
- struct hyperv_drm_device *hv = to_hv(connector->dev);
+ struct hvdrm_drm_device *hv = to_hv(connector->dev);
int count;
count = drm_add_modes_noedid(connector,
@@ -58,11 +58,11 @@ static int hyperv_connector_get_modes(struct drm_connector *connector)
return count;
}
-static const struct drm_connector_helper_funcs hyperv_connector_helper_funcs = {
- .get_modes = hyperv_connector_get_modes,
+static const struct drm_connector_helper_funcs hvdrm_connector_helper_funcs = {
+ .get_modes = hvdrm_connector_get_modes,
};
-static const struct drm_connector_funcs hyperv_connector_funcs = {
+static const struct drm_connector_funcs hvdrm_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = drm_connector_cleanup,
.reset = drm_atomic_helper_connector_reset,
@@ -70,15 +70,15 @@ static const struct drm_connector_funcs hyperv_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
-static inline int hyperv_conn_init(struct hyperv_drm_device *hv)
+static inline int hvdrm_conn_init(struct hvdrm_drm_device *hv)
{
- drm_connector_helper_add(&hv->connector, &hyperv_connector_helper_funcs);
+ drm_connector_helper_add(&hv->connector, &hvdrm_connector_helper_funcs);
return drm_connector_init(&hv->dev, &hv->connector,
- &hyperv_connector_funcs,
+ &hvdrm_connector_funcs,
DRM_MODE_CONNECTOR_VIRTUAL);
}
-static int hyperv_check_size(struct hyperv_drm_device *hv, int w, int h,
+static int hvdrm_check_size(struct hvdrm_drm_device *hv, int w, int h,
struct drm_framebuffer *fb)
{
u32 pitch = w * (hv->screen_depth / 8);
@@ -92,25 +92,25 @@ static int hyperv_check_size(struct hyperv_drm_device *hv, int w, int h,
return 0;
}
-static const uint32_t hyperv_formats[] = {
+static const uint32_t hvdrm_formats[] = {
DRM_FORMAT_XRGB8888,
};
-static const uint64_t hyperv_modifiers[] = {
+static const uint64_t hvdrm_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_INVALID
};
-static void hyperv_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+static void hvdrm_crtc_helper_atomic_enable(struct drm_crtc *crtc,
struct drm_atomic_commit *state)
{
- struct hyperv_drm_device *hv = to_hv(crtc->dev);
+ struct hvdrm_drm_device *hv = to_hv(crtc->dev);
struct drm_plane *plane = &hv->plane;
struct drm_plane_state *plane_state = plane->state;
struct drm_crtc_state *crtc_state = crtc->state;
- hyperv_hide_hw_ptr(hv->hdev);
- hyperv_update_situation(hv->hdev, 1, hv->screen_depth,
+ hvdrm_hide_hw_ptr(hv->hdev);
+ hvdrm_update_situation(hv->hdev, 1, hv->screen_depth,
crtc_state->mode.hdisplay,
crtc_state->mode.vdisplay,
plane_state->fb->pitches[0]);
@@ -118,14 +118,14 @@ static void hyperv_crtc_helper_atomic_enable(struct drm_crtc *crtc,
drm_crtc_vblank_on(crtc);
}
-static const struct drm_crtc_helper_funcs hyperv_crtc_helper_funcs = {
+static const struct drm_crtc_helper_funcs hvdrm_crtc_helper_funcs = {
.atomic_check = drm_crtc_helper_atomic_check,
.atomic_flush = drm_crtc_vblank_atomic_flush,
- .atomic_enable = hyperv_crtc_helper_atomic_enable,
+ .atomic_enable = hvdrm_crtc_helper_atomic_enable,
.atomic_disable = drm_crtc_vblank_atomic_disable,
};
-static const struct drm_crtc_funcs hyperv_crtc_funcs = {
+static const struct drm_crtc_funcs hvdrm_crtc_funcs = {
.reset = drm_atomic_helper_crtc_reset,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
@@ -135,11 +135,11 @@ static const struct drm_crtc_funcs hyperv_crtc_funcs = {
DRM_CRTC_VBLANK_TIMER_FUNCS,
};
-static int hyperv_plane_atomic_check(struct drm_plane *plane,
+static int hvdrm_plane_atomic_check(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
- struct hyperv_drm_device *hv = to_hv(plane->dev);
+ struct hvdrm_drm_device *hv = to_hv(plane->dev);
struct drm_framebuffer *fb = plane_state->fb;
struct drm_crtc *crtc = plane_state->crtc;
struct drm_crtc_state *crtc_state = NULL;
@@ -167,10 +167,10 @@ static int hyperv_plane_atomic_check(struct drm_plane *plane,
return 0;
}
-static void hyperv_plane_atomic_update(struct drm_plane *plane,
+static void hvdrm_plane_atomic_update(struct drm_plane *plane,
struct drm_atomic_commit *state)
{
- struct hyperv_drm_device *hv = to_hv(plane->dev);
+ struct hvdrm_drm_device *hv = to_hv(plane->dev);
struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state);
@@ -185,15 +185,15 @@ static void hyperv_plane_atomic_update(struct drm_plane *plane,
if (!drm_rect_intersect(&dst_clip, &damage))
continue;
- hyperv_blit_to_vram_rect(new_state->fb, &shadow_plane_state->data[0], &damage);
- hyperv_update_dirt(hv->hdev, &damage);
+ hvdrm_blit_to_vram_rect(new_state->fb, &shadow_plane_state->data[0], &damage);
+ hvdrm_update_dirt(hv->hdev, &damage);
}
}
-static int hyperv_plane_get_scanout_buffer(struct drm_plane *plane,
+static int hvdrm_plane_get_scanout_buffer(struct drm_plane *plane,
struct drm_scanout_buffer *sb)
{
- struct hyperv_drm_device *hv = to_hv(plane->dev);
+ struct hvdrm_drm_device *hv = to_hv(plane->dev);
struct iosys_map map = IOSYS_MAP_INIT_VADDR_IOMEM(hv->vram);
if (plane->state && plane->state->fb) {
@@ -207,9 +207,9 @@ static int hyperv_plane_get_scanout_buffer(struct drm_plane *plane,
return -ENODEV;
}
-static void hyperv_plane_panic_flush(struct drm_plane *plane)
+static void hvdrm_plane_panic_flush(struct drm_plane *plane)
{
- struct hyperv_drm_device *hv = to_hv(plane->dev);
+ struct hvdrm_drm_device *hv = to_hv(plane->dev);
struct drm_rect rect;
if (plane->state && plane->state->fb) {
@@ -218,32 +218,32 @@ static void hyperv_plane_panic_flush(struct drm_plane *plane)
rect.x2 = plane->state->fb->width;
rect.y2 = plane->state->fb->height;
- hyperv_update_dirt(hv->hdev, &rect);
+ hvdrm_update_dirt(hv->hdev, &rect);
}
vmbus_initiate_unload(true);
}
-static const struct drm_plane_helper_funcs hyperv_plane_helper_funcs = {
+static const struct drm_plane_helper_funcs hvdrm_plane_helper_funcs = {
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
- .atomic_check = hyperv_plane_atomic_check,
- .atomic_update = hyperv_plane_atomic_update,
- .get_scanout_buffer = hyperv_plane_get_scanout_buffer,
- .panic_flush = hyperv_plane_panic_flush,
+ .atomic_check = hvdrm_plane_atomic_check,
+ .atomic_update = hvdrm_plane_atomic_update,
+ .get_scanout_buffer = hvdrm_plane_get_scanout_buffer,
+ .panic_flush = hvdrm_plane_panic_flush,
};
-static const struct drm_plane_funcs hyperv_plane_funcs = {
+static const struct drm_plane_funcs hvdrm_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = drm_plane_cleanup,
DRM_GEM_SHADOW_PLANE_FUNCS,
};
-static const struct drm_encoder_funcs hyperv_drm_simple_encoder_funcs_cleanup = {
+static const struct drm_encoder_funcs hvdrm_drm_simple_encoder_funcs_cleanup = {
.destroy = drm_encoder_cleanup,
};
-static inline int hyperv_pipe_init(struct hyperv_drm_device *hv)
+static inline int hvdrm_pipe_init(struct hvdrm_drm_device *hv)
{
struct drm_device *dev = &hv->dev;
struct drm_encoder *encoder = &hv->encoder;
@@ -253,29 +253,29 @@ static inline int hyperv_pipe_init(struct hyperv_drm_device *hv)
int ret;
ret = drm_universal_plane_init(dev, plane, 0,
- &hyperv_plane_funcs,
- hyperv_formats, ARRAY_SIZE(hyperv_formats),
- hyperv_modifiers,
+ &hvdrm_plane_funcs,
+ hvdrm_formats, ARRAY_SIZE(hvdrm_formats),
+ hvdrm_modifiers,
DRM_PLANE_TYPE_PRIMARY, NULL);
if (ret)
return ret;
- drm_plane_helper_add(plane, &hyperv_plane_helper_funcs);
+ drm_plane_helper_add(plane, &hvdrm_plane_helper_funcs);
drm_plane_enable_fb_damage_clips(plane);
ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL,
- &hyperv_crtc_funcs, NULL);
+ &hvdrm_crtc_funcs, NULL);
if (ret)
return ret;
- drm_crtc_helper_add(crtc, &hyperv_crtc_helper_funcs);
+ drm_crtc_helper_add(crtc, &hvdrm_crtc_helper_funcs);
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = drm_encoder_init(dev, encoder,
- &hyperv_drm_simple_encoder_funcs_cleanup,
+ &hvdrm_drm_simple_encoder_funcs_cleanup,
DRM_MODE_ENCODER_NONE, NULL);
if (ret)
return ret;
- ret = hyperv_conn_init(hv);
+ ret = hvdrm_conn_init(hv);
if (ret) {
drm_err(dev, "Failed to initialized connector.\n");
return ret;
@@ -285,25 +285,25 @@ static inline int hyperv_pipe_init(struct hyperv_drm_device *hv)
}
static enum drm_mode_status
-hyperv_mode_valid(struct drm_device *dev,
+hvdrm_mode_valid(struct drm_device *dev,
const struct drm_display_mode *mode)
{
- struct hyperv_drm_device *hv = to_hv(dev);
+ struct hvdrm_drm_device *hv = to_hv(dev);
- if (hyperv_check_size(hv, mode->hdisplay, mode->vdisplay, NULL))
+ if (hvdrm_check_size(hv, mode->hdisplay, mode->vdisplay, NULL))
return MODE_BAD;
return MODE_OK;
}
-static const struct drm_mode_config_funcs hyperv_mode_config_funcs = {
+static const struct drm_mode_config_funcs hvdrm_mode_config_funcs = {
.fb_create = drm_gem_fb_create_with_dirty,
- .mode_valid = hyperv_mode_valid,
+ .mode_valid = hvdrm_mode_valid,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
-int hyperv_mode_config_init(struct hyperv_drm_device *hv)
+int hvdrm_mode_config_init(struct hvdrm_drm_device *hv)
{
struct drm_device *dev = &hv->dev;
int ret;
@@ -322,9 +322,9 @@ int hyperv_mode_config_init(struct hyperv_drm_device *hv)
dev->mode_config.preferred_depth = hv->screen_depth;
dev->mode_config.prefer_shadow = 0;
- dev->mode_config.funcs = &hyperv_mode_config_funcs;
+ dev->mode_config.funcs = &hvdrm_mode_config_funcs;
- ret = hyperv_pipe_init(hv);
+ ret = hvdrm_pipe_init(hv);
if (ret) {
drm_err(dev, "Failed to initialized pipe.\n");
return ret;
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_proto.c b/drivers/gpu/drm/hyperv/hyperv_drm_proto.c
index 6e09b0218df4..7c11b20a9124 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_proto.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_proto.c
@@ -181,7 +181,7 @@ struct synthvid_msg {
};
} __packed;
-static inline bool hyperv_version_ge(u32 ver1, u32 ver2)
+static inline bool hvdrm_version_ge(u32 ver1, u32 ver2)
{
if (SYNTHVID_VER_GET_MAJOR(ver1) > SYNTHVID_VER_GET_MAJOR(ver2) ||
(SYNTHVID_VER_GET_MAJOR(ver1) == SYNTHVID_VER_GET_MAJOR(ver2) &&
@@ -191,10 +191,10 @@ static inline bool hyperv_version_ge(u32 ver1, u32 ver2)
return false;
}
-static inline int hyperv_sendpacket(struct hv_device *hdev, struct synthvid_msg *msg)
+static inline int hvdrm_sendpacket(struct hv_device *hdev, struct synthvid_msg *msg)
{
static atomic64_t request_id = ATOMIC64_INIT(0);
- struct hyperv_drm_device *hv = hv_get_drvdata(hdev);
+ struct hvdrm_drm_device *hv = hv_get_drvdata(hdev);
int ret;
msg->pipe_hdr.type = PIPE_MSG_DATA;
@@ -211,9 +211,9 @@ static inline int hyperv_sendpacket(struct hv_device *hdev, struct synthvid_msg
return ret;
}
-static int hyperv_negotiate_version(struct hv_device *hdev, u32 ver)
+static int hvdrm_negotiate_version(struct hv_device *hdev, u32 ver)
{
- struct hyperv_drm_device *hv = hv_get_drvdata(hdev);
+ struct hvdrm_drm_device *hv = hv_get_drvdata(hdev);
struct synthvid_msg *msg = (struct synthvid_msg *)hv->init_buf;
struct drm_device *dev = &hv->dev;
unsigned long t;
@@ -223,7 +223,7 @@ static int hyperv_negotiate_version(struct hv_device *hdev, u32 ver)
msg->vid_hdr.size = sizeof(struct synthvid_msg_hdr) +
sizeof(struct synthvid_version_req);
msg->ver_req.version = ver;
- hyperv_sendpacket(hdev, msg);
+ hvdrm_sendpacket(hdev, msg);
t = wait_for_completion_timeout(&hv->wait, VMBUS_VSP_TIMEOUT);
if (!t) {
@@ -243,9 +243,9 @@ static int hyperv_negotiate_version(struct hv_device *hdev, u32 ver)
return 0;
}
-int hyperv_update_vram_location(struct hv_device *hdev, phys_addr_t vram_pp)
+int hvdrm_update_vram_location(struct hv_device *hdev, phys_addr_t vram_pp)
{
- struct hyperv_drm_device *hv = hv_get_drvdata(hdev);
+ struct hvdrm_drm_device *hv = hv_get_drvdata(hdev);
struct synthvid_msg *msg = (struct synthvid_msg *)hv->init_buf;
struct drm_device *dev = &hv->dev;
unsigned long t;
@@ -257,7 +257,7 @@ int hyperv_update_vram_location(struct hv_device *hdev, phys_addr_t vram_pp)
msg->vram.user_ctx = vram_pp;
msg->vram.vram_gpa = vram_pp;
msg->vram.is_vram_gpa_specified = 1;
- hyperv_sendpacket(hdev, msg);
+ hvdrm_sendpacket(hdev, msg);
t = wait_for_completion_timeout(&hv->wait, VMBUS_VSP_TIMEOUT);
if (!t) {
@@ -272,7 +272,7 @@ int hyperv_update_vram_location(struct hv_device *hdev, phys_addr_t vram_pp)
return 0;
}
-int hyperv_update_situation(struct hv_device *hdev, u8 active, u32 bpp,
+int hvdrm_update_situation(struct hv_device *hdev, u8 active, u32 bpp,
u32 w, u32 h, u32 pitch)
{
struct synthvid_msg msg;
@@ -292,7 +292,7 @@ int hyperv_update_situation(struct hv_device *hdev, u8 active, u32 bpp,
msg.situ.video_output[0].height_pixels = h;
msg.situ.video_output[0].pitch_bytes = pitch;
- hyperv_sendpacket(hdev, &msg);
+ hvdrm_sendpacket(hdev, &msg);
return 0;
}
@@ -306,11 +306,11 @@ int hyperv_update_situation(struct hv_device *hdev, u8 active, u32 bpp,
* the msg.ptr_shape.data. Note: setting msg.ptr_pos.is_visible to 0 doesn't
* work in tests.
*
- * The hyperv_hide_hw_ptr() is also called in the handler of the
+ * The hvdrm_hide_hw_ptr() is also called in the handler of the
* SYNTHVID_FEATURE_CHANGE event, otherwise the host still draws an extra
* unwanted mouse pointer after the VM Connection window is closed and reopened.
*/
-int hyperv_hide_hw_ptr(struct hv_device *hdev)
+int hvdrm_hide_hw_ptr(struct hv_device *hdev)
{
struct synthvid_msg msg;
@@ -322,7 +322,7 @@ int hyperv_hide_hw_ptr(struct hv_device *hdev)
msg.ptr_pos.video_output = 0;
msg.ptr_pos.image_x = 0;
msg.ptr_pos.image_y = 0;
- hyperv_sendpacket(hdev, &msg);
+ hvdrm_sendpacket(hdev, &msg);
memset(&msg, 0, sizeof(struct synthvid_msg));
msg.vid_hdr.type = SYNTHVID_POINTER_SHAPE;
@@ -338,14 +338,14 @@ int hyperv_hide_hw_ptr(struct hv_device *hdev)
msg.ptr_shape.data[1] = 1;
msg.ptr_shape.data[2] = 1;
msg.ptr_shape.data[3] = 1;
- hyperv_sendpacket(hdev, &msg);
+ hvdrm_sendpacket(hdev, &msg);
return 0;
}
-int hyperv_update_dirt(struct hv_device *hdev, struct drm_rect *rect)
+int hvdrm_update_dirt(struct hv_device *hdev, struct drm_rect *rect)
{
- struct hyperv_drm_device *hv = hv_get_drvdata(hdev);
+ struct hvdrm_drm_device *hv = hv_get_drvdata(hdev);
struct synthvid_msg msg;
if (!hv->dirt_needed)
@@ -363,14 +363,14 @@ int hyperv_update_dirt(struct hv_device *hdev, struct drm_rect *rect)
msg.dirt.rect[0].x2 = rect->x2;
msg.dirt.rect[0].y2 = rect->y2;
- hyperv_sendpacket(hdev, &msg);
+ hvdrm_sendpacket(hdev, &msg);
return 0;
}
-static int hyperv_get_supported_resolution(struct hv_device *hdev)
+static int hvdrm_get_supported_resolution(struct hv_device *hdev)
{
- struct hyperv_drm_device *hv = hv_get_drvdata(hdev);
+ struct hvdrm_drm_device *hv = hv_get_drvdata(hdev);
struct synthvid_msg *msg = (struct synthvid_msg *)hv->init_buf;
struct drm_device *dev = &hv->dev;
unsigned long t;
@@ -383,7 +383,7 @@ static int hyperv_get_supported_resolution(struct hv_device *hdev)
sizeof(struct synthvid_supported_resolution_req);
msg->resolution_req.maximum_resolution_count =
SYNTHVID_MAX_RESOLUTION_COUNT;
- hyperv_sendpacket(hdev, msg);
+ hvdrm_sendpacket(hdev, msg);
t = wait_for_completion_timeout(&hv->wait, VMBUS_VSP_TIMEOUT);
if (!t) {
@@ -420,9 +420,9 @@ static int hyperv_get_supported_resolution(struct hv_device *hdev)
return 0;
}
-static void hyperv_receive_sub(struct hv_device *hdev, u32 bytes_recvd)
+static void hvdrm_receive_sub(struct hv_device *hdev, u32 bytes_recvd)
{
- struct hyperv_drm_device *hv = hv_get_drvdata(hdev);
+ struct hvdrm_drm_device *hv = hv_get_drvdata(hdev);
struct synthvid_msg *msg;
size_t hdr_size;
size_t need;
@@ -486,7 +486,7 @@ static void hyperv_receive_sub(struct hv_device *hdev, u32 bytes_recvd)
}
hv->dirt_needed = msg->feature_chg.is_dirt_needed;
if (hv->dirt_needed)
- hyperv_hide_hw_ptr(hv->hdev);
+ hvdrm_hide_hw_ptr(hv->hdev);
return;
default:
return;
@@ -508,10 +508,10 @@ static void hyperv_receive_sub(struct hv_device *hdev, u32 bytes_recvd)
complete(&hv->wait);
}
-static void hyperv_receive(void *ctx)
+static void hvdrm_receive(void *ctx)
{
struct hv_device *hdev = ctx;
- struct hyperv_drm_device *hv = hv_get_drvdata(hdev);
+ struct hvdrm_drm_device *hv = hv_get_drvdata(hdev);
struct synthvid_msg *recv_buf;
u32 bytes_recvd;
u64 req_id;
@@ -539,19 +539,19 @@ static void hyperv_receive(void *ctx)
ret, bytes_recvd);
} else if (bytes_recvd > 0 &&
recv_buf->pipe_hdr.type == PIPE_MSG_DATA) {
- hyperv_receive_sub(hdev, bytes_recvd);
+ hvdrm_receive_sub(hdev, bytes_recvd);
}
} while (bytes_recvd > 0 && ret == 0);
}
-int hyperv_connect_vsp(struct hv_device *hdev)
+int hvdrm_connect_vsp(struct hv_device *hdev)
{
- struct hyperv_drm_device *hv = hv_get_drvdata(hdev);
+ struct hvdrm_drm_device *hv = hv_get_drvdata(hdev);
struct drm_device *dev = &hv->dev;
int ret;
ret = vmbus_open(hdev->channel, VMBUS_RING_BUFSIZE, VMBUS_RING_BUFSIZE,
- NULL, 0, hyperv_receive, hdev);
+ NULL, 0, hvdrm_receive, hdev);
if (ret) {
drm_err(dev, "Unable to open vmbus channel\n");
return ret;
@@ -561,16 +561,16 @@ int hyperv_connect_vsp(struct hv_device *hdev)
switch (vmbus_proto_version) {
case VERSION_WIN10:
case VERSION_WIN10_V5:
- ret = hyperv_negotiate_version(hdev, SYNTHVID_VERSION_WIN10);
+ ret = hvdrm_negotiate_version(hdev, SYNTHVID_VERSION_WIN10);
if (!ret)
break;
fallthrough;
case VERSION_WIN8:
case VERSION_WIN8_1:
- ret = hyperv_negotiate_version(hdev, SYNTHVID_VERSION_WIN8);
+ ret = hvdrm_negotiate_version(hdev, SYNTHVID_VERSION_WIN8);
break;
default:
- ret = hyperv_negotiate_version(hdev, SYNTHVID_VERSION_WIN10);
+ ret = hvdrm_negotiate_version(hdev, SYNTHVID_VERSION_WIN10);
break;
}
@@ -581,8 +581,8 @@ int hyperv_connect_vsp(struct hv_device *hdev)
hv->screen_depth = SYNTHVID_DEPTH_WIN8;
- if (hyperv_version_ge(hv->synthvid_version, SYNTHVID_VERSION_WIN10)) {
- ret = hyperv_get_supported_resolution(hdev);
+ if (hvdrm_version_ge(hv->synthvid_version, SYNTHVID_VERSION_WIN10)) {
+ ret = hvdrm_get_supported_resolution(hdev);
if (ret)
drm_err(dev, "Failed to get supported resolution from host, use default\n");
}
--
2.25.1
^ permalink raw reply related
* Re: [PATCH 1/1] drm/hyperv: Replace "hyperv_" with "hvdrm_" as symbol name prefix
From: sashiko-bot @ 2026-05-26 20:59 UTC (permalink / raw)
To: Michael Kelley; +Cc: linux-hyperv
In-Reply-To: <20260526205239.1509-1-mhklkml@zohomail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Potential NULL pointer dereference in `hvdrm_crtc_helper_atomic_enable` when accessing `plane_state->fb->pitches`.
--
commit 9e40bbf4c669c839b0568d52b603d410d08dde6c
Author: Michael Kelley <mhklinux@outlook.com>
drm/hyperv: Replace "hyperv_" with "hvdrm_" as symbol name prefix
This commit mechanically replaces the "hyperv_" prefix with "hvdrm_" across
functions and structures in the Hyper-V DRM driver. This renaming prevents
namespace collisions with core Hyper-V and VMBus code, and addresses an
initcall conflict that prevents using initcall_blacklist.
> diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
> --- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
> +++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
[ ... ]
> @@ -107,14 +107,14 @@ static const uint64_t hyperv_modifiers[] = {
> -static void hyperv_crtc_helper_atomic_enable(struct drm_crtc *crtc,
> +static void hvdrm_crtc_helper_atomic_enable(struct drm_crtc *crtc,
> struct drm_atomic_commit *state)
> {
> - struct hyperv_drm_device *hv = to_hv(crtc->dev);
> + struct hvdrm_drm_device *hv = to_hv(crtc->dev);
> struct drm_plane *plane = &hv->plane;
> struct drm_plane_state *plane_state = plane->state;
> struct drm_crtc_state *crtc_state = crtc->state;
>
> - hyperv_hide_hw_ptr(hv->hdev);
> - hyperv_update_situation(hv->hdev, 1, hv->screen_depth,
> + hvdrm_hide_hw_ptr(hv->hdev);
> + hvdrm_update_situation(hv->hdev, 1, hv->screen_depth,
> crtc_state->mode.hdisplay,
> crtc_state->mode.vdisplay,
> plane_state->fb->pitches[0]);
[Severity: High]
This is a pre-existing issue, but could this cause a NULL pointer
dereference?
In the DRM atomic API, userspace can configure a CRTC to be active without an
attached framebuffer on its primary plane, which means plane_state->fb can be
NULL.
If the CRTC is enabled while the primary plane lacks a framebuffer, it looks
like dereferencing plane_state->fb->pitches[0] here will crash the kernel.
>
> drm_crtc_vblank_on(crtc);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260526205239.1509-1-mhklkml@zohomail.com?part=1
^ permalink raw reply
* Re: [RFC] KVM/x86: Killing kvm_get_time_and_clockread() in favour of ktime_get_snapshot()
From: David Woodhouse @ 2026-05-26 23:04 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini, Thomas Gleixner, John Stultz,
Michael Kelley
Cc: Vitaly Kuznetsov, Marcelo Tosatti, Christopher S. Hall,
Stephen Boyd, Miroslav Lichvar, Ingo Molnar, Borislav Petkov,
Dave Hansen, H. Peter Anvin, K. Y. Srinivasan, Haiyang Zhang,
Wei Liu, Dexuan Cui, Daniel Lezcano, kvm, linux-hyperv, x86,
linux-kernel
In-Reply-To: <b4895a532344ba6a879d922be8536f9000cd398c.camel@infradead.org>
[-- Attachment #1: Type: text/plain, Size: 2117 bytes --]
On Tue, 2026-05-26 at 14:57 +0100, David Woodhouse wrote:
>
> One simple option that occurs to me would be to add a 'cycles_raw'
> value to the system_time_snapshot, for PV clocksources like hyperv and
> kvmclock to populate with the original TSC reading.
>
> That might actually let us clean up some of the PTP code that currently
> has to deal with TSC vs. kvmclock in counter snapshots too. I think I
> could kill the use of get_cycles() in vmclock for the kvmclock case,
> which might make Thomas happy...
I hacked that up to see what it looks like, and it kind of seems to work...
Based on merging my kvmclock branch and Thomas's ktime_get_snapshot_id():
• https://git.infradead.org/?p=users/dwmw2/linux.git;a=shortlog;h=refs/heads/kvmclock5
• https://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git/log/?h=timers/ptp/timekeeping
I'll probably not post this for real until the above two are merged;
there's no rush but I think it's a worthwhile cleanup. For now it's at
• https://git.infradead.org/?p=users/dwmw2/linux.git;a=shortlog;h=refs/heads/kvm-ktime-snapshot
David Woodhouse (8):
timekeeping: Add clocksource read_raw() method and raw_cycles to snapshot
clocksource/hyperv: Implement read_raw() for TSC page clocksource
x86/kvmclock: Implement read_raw() for kvmclock clocksource
KVM: x86: Use ktime_get_snapshot_id() for master clock
KVM: x86: Compute kvmclock base without pvclock_gtod_data
KVM: x86: Replace pvclock_gtod_data vclock_mode with boolean
KVM: x86: Remove pvclock_gtod_data and private timekeeping code
ptp: vmclock: Use raw_cycles from snapshot for precise TSC pairing
arch/x86/kernel/kvmclock.c | 21 ++++
arch/x86/kvm/x86.c | 239 ++++++++-----------------------------
drivers/clocksource/hyperv_timer.c | 14 +++
drivers/ptp/ptp_vmclock.c | 4 +
include/linux/clocksource.h | 8 ++
include/linux/timekeeping.h | 6 +
kernel/time/timekeeping.c | 30 ++++-
7 files changed, 130 insertions(+), 192 deletions(-)
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 5069 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox